Files
DanMuRead/BarrageGrab/WssBarrageGrab.cs
T

275 lines
9.5 KiB
C#
Raw Normal View History

2022-10-06 17:44:08 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ProtoBuf;
using BarrageGrab.Proxy;
using BarrageGrab.Proxy.ProxyEventArgs;
2023-08-17 20:37:22 +08:00
using BarrageGrab.Modles.ProtoEntity;
2022-10-06 17:44:08 +08:00
namespace BarrageGrab
{
/// <summary>
/// 本机Wss弹幕抓取器
/// </summary>
public class WssBarrageGrab : IDisposable
{
//ISystemProxy proxy = new FiddlerProxy();
ISystemProxy proxy = new TitaniumProxy();
2024-03-29 17:46:24 +08:00
AppSetting appsetting = AppSetting.Current;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 进入直播间
/// </summary>
public event EventHandler<RoomMessageEventArgs<MemberMessage>> OnMemberMessage;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 关注
/// </summary>
public event EventHandler<RoomMessageEventArgs<SocialMessage>> OnSocialMessage;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 聊天
/// </summary>
public event EventHandler<RoomMessageEventArgs<ChatMessage>> OnChatMessage;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 点赞
/// </summary>
public event EventHandler<RoomMessageEventArgs<LikeMessage>> OnLikeMessage;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 礼物
/// </summary>
public event EventHandler<RoomMessageEventArgs<GiftMessage>> OnGiftMessage;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 直播间统计
/// </summary>
public event EventHandler<RoomMessageEventArgs<RoomUserSeqMessage>> OnRoomUserSeqMessage;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 直播间状态变更
/// </summary>
public event EventHandler<RoomMessageEventArgs<ControlMessage>> OnControlMessage;
2022-10-06 17:44:08 +08:00
/// <summary>
/// 粉丝团消息
/// </summary>
public event EventHandler<RoomMessageEventArgs<FansclubMessage>> OnFansclubMessage;
2022-10-06 17:44:08 +08:00
2023-11-14 20:29:18 +08:00
/// <summary>
/// 代理
/// </summary>
2023-11-16 09:26:40 +08:00
public ISystemProxy Proxy { get { return proxy; } }
2023-11-14 20:29:18 +08:00
2022-10-06 17:44:08 +08:00
public WssBarrageGrab()
{
proxy.OnWebSocketData += Proxy_OnWebSocketData;
2023-08-17 20:37:22 +08:00
proxy.OnFetchResponse += Proxy_OnFetchResponse;
}
2022-10-06 17:44:08 +08:00
public void Start()
{
proxy.Start();
}
public void Dispose()
{
2023-08-17 20:37:22 +08:00
proxy.Dispose();
2022-10-06 17:44:08 +08:00
}
2023-03-09 00:33:03 +08:00
2022-10-06 17:44:08 +08:00
//gzip解压缩
private byte[] Decompress(byte[] zippedData)
{
MemoryStream ms = new MemoryStream(zippedData);
GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Decompress);
MemoryStream outBuffer = new MemoryStream();
byte[] block = new byte[1024];
while (true)
{
int bytesRead = compressedzipStream.Read(block, 0, block.Length);
if (bytesRead <= 0)
break;
else
outBuffer.Write(block, 0, bytesRead);
}
compressedzipStream.Close();
return outBuffer.ToArray();
}
2023-03-09 01:23:46 +08:00
2023-03-09 00:33:03 +08:00
//ws数据处理
private void Proxy_OnWebSocketData(object sender, WsMessageEventArgs e)
2022-10-06 17:44:08 +08:00
{
2023-03-09 01:23:46 +08:00
if (!appsetting.ProcessFilter.Contains(e.ProcessName)) return;
var buff = e.Payload;
2022-10-06 17:44:08 +08:00
if (buff.Length == 0) return;
2023-08-17 20:37:22 +08:00
//如果需要Gzip解压缩,但是开头字节不符合Gzip特征字节 则不处理
if (e.NeedDecompress && buff[0] != 0x08) return;
2022-10-06 17:44:08 +08:00
try
{
var enty = Serializer.Deserialize<WssResponse>(new ReadOnlyMemory<byte>(buff));
if (enty == null) return;
//检测包格式
if (!enty.Headers.Any(a => a.Key == "compress_type" && a.Value == "gzip")) return;
2023-08-17 20:37:22 +08:00
byte[] allBuff;
2022-10-06 17:44:08 +08:00
//解压gzip
2023-08-17 20:37:22 +08:00
allBuff = e.NeedDecompress ? Decompress(enty.Payload) : enty.Payload;
var response = Serializer.Deserialize<Response>(new ReadOnlyMemory<byte>(allBuff));
2023-03-09 01:23:46 +08:00
2024-03-10 04:03:39 +08:00
response.Messages.ForEach(f => DoMessage(f, e.ProcessName));
2022-10-06 17:44:08 +08:00
}
catch (Exception ex)
2024-04-26 00:47:08 +08:00
{
Logger.LogError(ex, $"处理弹幕数据包时出错:{ex.Message}");
2024-04-26 00:47:08 +08:00
}
2022-10-06 17:44:08 +08:00
}
2023-08-17 20:37:22 +08:00
//http 数据处理
private void Proxy_OnFetchResponse(object sender, HttpResponseEventArgs e)
{
2024-05-16 22:24:45 +08:00
var payload = e.Payload;
if (payload == null || payload.Length == 0) return;
2024-01-09 22:39:08 +08:00
2023-08-17 20:37:22 +08:00
var response = Serializer.Deserialize<Response>(new ReadOnlyMemory<byte>(payload));
response.Messages.ForEach(f =>
{
DoMessage(f, e.ProcessName);
2023-08-17 20:37:22 +08:00
});
}
2023-08-17 20:37:22 +08:00
//用于缓存接收过的消息ID,判断是否重复接收
2023-08-17 20:37:22 +08:00
Dictionary<string, List<long>> msgDic = new Dictionary<string, List<long>>();
2023-03-09 00:33:03 +08:00
//发送事件
private void DoMessage(Message msg, string processName)
2023-08-17 20:37:22 +08:00
{
List<long> msgIdList;
if (msgDic.ContainsKey(msg.Method))
{
2023-08-17 20:37:22 +08:00
msgIdList = msgDic[msg.Method];
}
else
{
2023-04-01 00:22:34 +08:00
msgIdList = new List<long>(320);
msgDic.Add(msg.Method, msgIdList);
}
if (msgIdList.Contains(msg.msgId))
{
return;
}
msgIdList.Add(msg.msgId);
//每种消息类型设置300容量应该足够,不太可能存在一条消息被挤出队列后再次出现
while (msgIdList.Count > 300)
{
msgIdList.RemoveAt(0);
}
2023-08-17 20:37:22 +08:00
2022-10-06 17:44:08 +08:00
try
{
switch (msg.Method)
{
//来了
2022-10-06 17:44:08 +08:00
case "WebcastMemberMessage":
{
var arg = Serializer.Deserialize<MemberMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnMemberMessage?.Invoke(this, new RoomMessageEventArgs<MemberMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
//关注
2022-10-06 17:44:08 +08:00
case "WebcastSocialMessage":
{
var arg = Serializer.Deserialize<SocialMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnSocialMessage?.Invoke(this, new RoomMessageEventArgs<SocialMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
//消息
2022-10-06 17:44:08 +08:00
case "WebcastChatMessage":
{
var arg = Serializer.Deserialize<ChatMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnChatMessage?.Invoke(this, new RoomMessageEventArgs<ChatMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
//点赞
2022-10-06 17:44:08 +08:00
case "WebcastLikeMessage":
{
var arg = Serializer.Deserialize<LikeMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnLikeMessage?.Invoke(this, new RoomMessageEventArgs<LikeMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
//礼物
2022-10-06 17:44:08 +08:00
case "WebcastGiftMessage":
{
var arg = Serializer.Deserialize<GiftMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnGiftMessage?.Invoke(this, new RoomMessageEventArgs<GiftMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
//直播间统计
2022-10-06 17:44:08 +08:00
case "WebcastRoomUserSeqMessage":
{
var arg = Serializer.Deserialize<RoomUserSeqMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnRoomUserSeqMessage?.Invoke(this, new RoomMessageEventArgs<RoomUserSeqMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
//直播间状态变更
2022-10-06 17:44:08 +08:00
case "WebcastControlMessage":
{
var arg = Serializer.Deserialize<ControlMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnControlMessage?.Invoke(this, new RoomMessageEventArgs<ControlMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
//粉丝团消息
2022-10-06 17:44:08 +08:00
case "WebcastFansclubMessage":
{
var arg = Serializer.Deserialize<FansclubMessage>(new ReadOnlyMemory<byte>(msg.Payload));
this.OnFansclubMessage?.Invoke(this, new RoomMessageEventArgs<FansclubMessage>(processName, arg));
2022-10-06 17:44:08 +08:00
break;
}
default:
break;
}
}
2023-11-23 16:43:21 +08:00
catch (Exception ex)
2022-10-06 17:44:08 +08:00
{
return;
}
}
2023-03-09 01:23:46 +08:00
public class RoomMessageEventArgs<T> : EventArgs where T : class
{
/// <summary>
/// 进程名
/// </summary>
public string Process { get; set; }
/// <summary>
/// 消息
/// </summary>
public T Message { get; set; }
public RoomMessageEventArgs()
{
}
public RoomMessageEventArgs(string process, T data)
{
this.Process = process;
this.Message = data;
}
}
2022-10-06 17:44:08 +08:00
}
}