From 89a66d538968b7296d94efe0c34d5dbac6db2dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=99=BD=E7=8C=BF?= <1083092844@qq.com> Date: Thu, 9 Mar 2023 00:33:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=B9=E5=B9=95=E5=9F=9F=E5=90=8D=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E6=94=BE=E5=AE=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BarrageGrab/Program.cs | 4 +- BarrageGrab/Proxy/ISystemProxy.cs | 6 + BarrageGrab/Proxy/SystemProxy.cs | 48 +++++--- BarrageGrab/Proxy/TitaniumProxy.cs | 22 +--- ...sBarrageService.cs => WsBarrageService.cs} | 109 ++++++++++++------ BarrageGrab/WssBarrageGrab.cs | 28 ++++- BarrageGrab/WssBarrageService.csproj | 2 +- 7 files changed, 149 insertions(+), 70 deletions(-) rename BarrageGrab/{WssBarrageService.cs => WsBarrageService.cs} (71%) diff --git a/BarrageGrab/Program.cs b/BarrageGrab/Program.cs index cb07fc7..e2d19e9 100644 --- a/BarrageGrab/Program.cs +++ b/BarrageGrab/Program.cs @@ -11,12 +11,12 @@ namespace BarrageGrab { private delegate bool ControlCtrlDelegate(int CtrlType); - static WssBarrageService server = null; + static WsBarrageService server = null; static void Main(string[] args) { SetConsoleCtrlHandler(cancelHandler, true);//捕获控制台关闭 Console.Title = "抖音弹幕监听推送"; - server = new WssBarrageService(); + server = new WsBarrageService(); server.StartListen(); while (true) diff --git a/BarrageGrab/Proxy/ISystemProxy.cs b/BarrageGrab/Proxy/ISystemProxy.cs index 9cccac0..01b3385 100644 --- a/BarrageGrab/Proxy/ISystemProxy.cs +++ b/BarrageGrab/Proxy/ISystemProxy.cs @@ -1,6 +1,7 @@ using System; using Fiddler; using System.Reflection; +using System.Collections.Generic; namespace BarrageGrab.Proxy { @@ -8,6 +9,11 @@ namespace BarrageGrab.Proxy { event EventHandler OnWebSocketData; + /// + /// 域名过滤器 + /// + Func HostNameFilter { get; set; } + /// /// 开始监听 /// diff --git a/BarrageGrab/Proxy/SystemProxy.cs b/BarrageGrab/Proxy/SystemProxy.cs index 3261701..e94fedc 100644 --- a/BarrageGrab/Proxy/SystemProxy.cs +++ b/BarrageGrab/Proxy/SystemProxy.cs @@ -13,17 +13,10 @@ namespace BarrageGrab.Proxy { internal abstract class SystemProxy : ISystemProxy { - //弹幕服务域名 - protected string[] barrageWsHostNames = new string[] - { - "webcast3-ws-web-hl.douyin.com", - "webcast3-ws-web-lf.douyin.com", - "frontier-im.douyin.com", - "webcast100-ws-web-lq.amemv.com" - }; - - - //https://live.douyin.com/webcast/gift/list/ + /// + /// 域名过滤器 + /// + public Func HostNameFilter { get; set; } /// /// 接收到websocket消息事件 @@ -33,17 +26,42 @@ namespace BarrageGrab.Proxy /// /// 代理端口 /// - public int ProxyPort { get => Appsetting.Instanse.ProxyPort; } + public int ProxyPort { get => Appsetting.Current.ProxyPort; } public abstract void Dispose(); public abstract void Start(); - protected void SendWebSocketData(WsMessageEventArgs args) + //https://live.douyin.com/webcast/gift/list/ [礼物数据接口] + + /// + /// 检测是否是业务相关链接 + /// + /// + /// + protected bool CheckHost(string host) + { + var result = true; + + if (HostNameFilter != null) return HostNameFilter(host); + + return result; + } + + /// + /// 触发websocket消息事件 + /// + /// + protected void FireWsEvent(WsMessageEventArgs args) { OnWebSocketData?.Invoke(this, args); } + /// + /// 获取进程名称 + /// + /// + /// protected string GetProcessName(int processID) { var process = Process.GetProcessById(processID); @@ -54,7 +72,9 @@ namespace BarrageGrab.Proxy return $"<{processID}>"; } - //注册系统代理 + /// + /// 注册系统代理 + /// protected void RegisterSystemProxy() { RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true); diff --git a/BarrageGrab/Proxy/TitaniumProxy.cs b/BarrageGrab/Proxy/TitaniumProxy.cs index 9d521e6..ce369aa 100644 --- a/BarrageGrab/Proxy/TitaniumProxy.cs +++ b/BarrageGrab/Proxy/TitaniumProxy.cs @@ -44,7 +44,7 @@ namespace BarrageGrab.Proxy proxyServer.ServerCertificateValidationCallback += ProxyServer_ServerCertificateValidationCallback; ; proxyServer.BeforeResponse += ProxyServer_BeforeResponse; - explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any,ProxyPort, true); + explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, ProxyPort, true); explicitEndPoint.BeforeTunnelConnectRequest += ExplicitEndPoint_BeforeTunnelConnectRequest; proxyServer.AddEndPoint(explicitEndPoint); } @@ -57,7 +57,6 @@ namespace BarrageGrab.Proxy { e.IsValid = true; } - return Task.CompletedTask; } @@ -65,20 +64,16 @@ namespace BarrageGrab.Proxy private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e) { string hostname = e.HttpClient.Request.RequestUri.Host; - if (!barrageWsHostNames.Contains(hostname)) return; - if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Websocket) { e.DataReceived += WebSocket_DataReceived; - } + } } - //List hostlist = new List(); - private async Task ExplicitEndPoint_BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { string hostname = e.HttpClient.Request.RequestUri.Host; - if (!barrageWsHostNames.Contains(hostname)) + if (!CheckHost(hostname)) { e.DecryptSsl = false; } @@ -93,12 +88,10 @@ namespace BarrageGrab.Proxy var processid = args.HttpClient.ProcessId.Value; var frames = args.WebSocketDecoderReceive.Decode(e.Buffer, e.Offset, e.Count).ToList(); - //Console.WriteLine(frames.Count); - + foreach (var frame in frames) - { - //Console.WriteLine(frame.GetText()); - base.SendWebSocketData(new WsMessageEventArgs() + { + base.FireWsEvent(new WsMessageEventArgs() { ProcessID = processid, HostName = hostname, @@ -106,9 +99,6 @@ namespace BarrageGrab.Proxy ProcessName = base.GetProcessName(processid) }); } - //Console.WriteLine("获取到弹幕信息:" + hostname); - - } /// diff --git a/BarrageGrab/WssBarrageService.cs b/BarrageGrab/WsBarrageService.cs similarity index 71% rename from BarrageGrab/WssBarrageService.cs rename to BarrageGrab/WsBarrageService.cs index e46a2ec..24beef4 100644 --- a/BarrageGrab/WssBarrageService.cs +++ b/BarrageGrab/WsBarrageService.cs @@ -6,26 +6,33 @@ using System.Text; using System.Threading.Tasks; using System.Timers; using BarrageGrab.JsonEntity; +using BarrageGrab.ProtoEntity; using ColorConsole; using Fleck; using Newtonsoft.Json; +using static BarrageGrab.ProtoEntity.Image; namespace BarrageGrab { + /// /// 弹幕服务 /// - internal class WssBarrageService + internal class WsBarrageService { WebSocketServer socketServer; Dictionary socketList = new Dictionary(); Timer dieout = new Timer(10000); ConsoleWriter console = new ConsoleWriter(); WssBarrageGrab grab = new WssBarrageGrab(); - Appsetting Appsetting = Appsetting.Get(); - - public WssBarrageService() + Appsetting Appsetting = Appsetting.Current; + bool debug = false; + + public WsBarrageService() { +#if DEBUG + debug = true; +#endif var socket = new WebSocketServer($"ws://127.0.0.1:{Appsetting.WsProt}"); socket.RestartAfterListenError = true;//异常重启 @@ -44,36 +51,46 @@ namespace BarrageGrab //dieout.Start(); } - private MsgUser GetUser(dynamic obj) + private bool CheckRoomId(long roomid) + { + return Appsetting.RoomIds.Length == 0 || Appsetting.RoomIds.Contains(roomid); + } + + //解析用户 + private MsgUser GetUser(ProtoEntity.User data) { MsgUser user = new MsgUser() { - DisplayId = obj.User.displayId, - Gender = obj.User.Gender, - Id = obj.User.Id, - Level = obj.User.Level, - Nickname = obj.User.Nickname + DisplayId = data.displayId, + Gender = data.Gender, + Id = data.Id, + Level = data.Level, + Nickname = data.Nickname }; return user; } + //粉丝团 private void Grab_OnFansclubMessage(object sender, ProtoEntity.FansclubMessage e) { + if (!CheckRoomId(e.commonInfo.roomId)) return; var enty = new FansclubMsg() { Content = e.Content, RoomId = e.commonInfo.roomId, Type = e.Type, - User = GetUser(e) + User = GetUser(e.User) }; - Print($"[粉丝团消息] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Blue); - var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.粉丝团信息); + Print(enty.User.GenderToString() + " " + enty.Content, ConsoleColor.Blue, BarrageMsgType.粉丝团消息); + var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.粉丝团消息); var json = JsonConvert.SerializeObject(pack); this.Broadcast(json); } + //统计消息 private void Grab_OnRoomUserSeqMessage(object sender, ProtoEntity.RoomUserSeqMessage e) { + if (!CheckRoomId(e.Common.roomId)) return; var enty = new UserSeqMsg() { OnlineUserCount = e.Total, @@ -84,92 +101,113 @@ namespace BarrageGrab Content = $"当前直播间人数 {e.onlineUserForAnchor},累计直播间人数 {e.totalPvForAnchor}", User = null }; - Print($"[直播间统计] " + enty.Content, ConsoleColor.Magenta); + Print(enty.Content, ConsoleColor.Magenta, BarrageMsgType.直播间统计); var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.直播间统计); var json = JsonConvert.SerializeObject(pack); this.Broadcast(json); } + //礼物 private void Grab_OnGiftMessage(object sender, ProtoEntity.GiftMessage e) { + if (!CheckRoomId(e.Common.roomId)) return; + var enty = new GiftMsg() { RoomId = e.Common.roomId, Content = e.Common.Describe, DiamondCount = e.Gift.diamondCount, GiftCount = e.repeatCount, + GroupCount = e.groupCount, GiftId = e.giftId, GiftName = e.Gift.Name, - User = GetUser(e) + User = GetUser(e.User) }; - Print($"[礼物消息] " + $"{enty.User.GenderToString()} " + enty.Content, ConsoleColor.Red); - var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.送礼); + + Print($"{enty.User.GenderToString()} {enty.Content}", ConsoleColor.Red, BarrageMsgType.礼物消息); + var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.礼物消息); var json = JsonConvert.SerializeObject(pack); this.Broadcast(json); } + //关注 private void Grab_OnSocialMessage(object sender, ProtoEntity.SocialMessage e) { + if (!CheckRoomId(e.Common.roomId)) return; + var enty = new Msg() { Content = $"{e.User.Nickname} 关注了主播", RoomId = e.Common.roomId, - User = GetUser(e) + User = GetUser(e.User) }; - Print($"[关注消息] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Yellow); - var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.关注主播); + Print($"{enty.User.GenderToString()} {enty.Content}", ConsoleColor.Yellow, BarrageMsgType.关注消息); + var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.关注消息); var json = JsonConvert.SerializeObject(pack); this.Broadcast(json); } + //来了 private void Grab_OnMemberMessage(object sender, ProtoEntity.MemberMessage e) { - var enty = new Msg() + if (!CheckRoomId(e.Common.roomId)) return; + + var enty = new JsonEntity.MemberMessage() { - Content = $"{e.User.Nickname} 来了", + Content = $"{e.User.Nickname} 来了 直播间人数:{e.memberCount}", RoomId = e.Common.roomId, - User = GetUser(e) + CurrentCount = e.memberCount, + User = GetUser(e.User) }; - Print($"[进直播间] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Green); - var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.进入直播间); + Print($"{enty.User.GenderToString()} {enty.Content}", ConsoleColor.Green, BarrageMsgType.进直播间); + var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.进直播间); var json = JsonConvert.SerializeObject(pack); this.Broadcast(json); } + //点赞 private void Grab_OnLikeMessage(object sender, ProtoEntity.LikeMessage e) { + if (!CheckRoomId(e.Common.roomId)) return; + var enty = new LikeMsg() { Count = e.Count, - Content = $"{e.User.Nickname} 为主播点了{e.Count}个赞", + Content = $"{e.User.Nickname} 为主播点了{e.Count}个赞,总点赞{e.Total}", RoomId = e.Common.roomId, - User = GetUser(e) + Total = e.Total, + User = GetUser(e.User) }; - Print($"[点赞消息] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Cyan); - var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.点赞); + Print($"{enty.User.GenderToString()} {enty.Content}", ConsoleColor.Cyan, BarrageMsgType.点赞消息); + var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.点赞消息); var json = JsonConvert.SerializeObject(pack); this.Broadcast(json); } + //弹幕 private void Grab_OnChatMessage(object sender, ProtoEntity.ChatMessage e) { + if (!CheckRoomId(e.Common.roomId)) return; + var enty = new Msg() { Content = e.Content, RoomId = e.Common.roomId, - User = GetUser(e) + User = GetUser(e.User) }; - Print($"[弹幕消息] {enty.User.GenderToString()} {enty.User.Nickname}: {enty.Content}", ConsoleColor.White); - var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.消息); + Print($"{enty.User.GenderToString()} {enty.User.Nickname}: {enty.Content}", ConsoleColor.White, BarrageMsgType.弹幕消息); + var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.弹幕消息); var json = JsonConvert.SerializeObject(pack); this.Broadcast(json); } - private void Print(string msg, ConsoleColor color) + private void Print(string msg, ConsoleColor color, BarrageMsgType bartype) { + if (!Appsetting.PrintFilter.Any(a => a == bartype.GetHashCode())) return; + if (Appsetting.PrintBarrage) { - console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")} " + msg + "\n", color); + console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")} [{bartype.ToString()}] " + msg + "\n", color); } } @@ -220,6 +258,9 @@ namespace BarrageGrab } } + /// + /// 开始监听 + /// public void StartListen() { this.grab.Start(); //启动代理 diff --git a/BarrageGrab/WssBarrageGrab.cs b/BarrageGrab/WssBarrageGrab.cs index 33287ea..951436f 100644 --- a/BarrageGrab/WssBarrageGrab.cs +++ b/BarrageGrab/WssBarrageGrab.cs @@ -19,9 +19,18 @@ namespace BarrageGrab { //ISystemProxy proxy = new FiddlerProxy(); ISystemProxy proxy = new TitaniumProxy(); - Appsetting appsetting = Appsetting.Get(); + Appsetting appsetting = Appsetting.Current; ConsoleWriter console = new ConsoleWriter(); + //已知的弹幕域名服务器 + string[] wsHostNames = new string[] + { + "webcast3-ws-web-hl.douyin.com", + "webcast3-ws-web-lf.douyin.com", + "frontier-im.douyin.com", + "webcast100-ws-web-lq.amemv.com" + }; + /// /// 进入直播间 /// @@ -65,6 +74,7 @@ namespace BarrageGrab public WssBarrageGrab() { proxy.OnWebSocketData += Proxy_OnWebSocketData; + proxy.HostNameFilter = HostNameChecker; } public void Start() @@ -77,6 +87,16 @@ namespace BarrageGrab proxy.Dispose(); } + //域名过滤器 + private bool HostNameChecker(string hostName) + { + if (hostName.StartsWith("webcast")) return true; + + if (wsHostNames.Any(a => a.ToLower() == hostName.ToLower())) return true; + + return false; + } + //gzip解压缩 private byte[] Decompress(byte[] zippedData) { @@ -95,7 +115,8 @@ namespace BarrageGrab compressedzipStream.Close(); return outBuffer.ToArray(); } - + + //ws数据处理 private void Proxy_OnWebSocketData(object sender, WsMessageEventArgs e) { if (!appsetting.FilterProcess.Contains(e.ProcessName)) return; @@ -103,7 +124,7 @@ namespace BarrageGrab if (buff.Length == 0) return; if (buff[0] != 0x08) return; - + try { var enty = Serializer.Deserialize(new ReadOnlyMemory(buff)); @@ -123,6 +144,7 @@ namespace BarrageGrab catch (Exception) { } } + //发送事件 private void DoMessage(Message msg) { try diff --git a/BarrageGrab/WssBarrageService.csproj b/BarrageGrab/WssBarrageService.csproj index 32b5ed1..337064f 100644 --- a/BarrageGrab/WssBarrageService.csproj +++ b/BarrageGrab/WssBarrageService.csproj @@ -126,7 +126,7 @@ - +