弹幕域名校验放宽

This commit is contained in:
小白猿
2023-03-09 00:33:03 +08:00
parent c387094ebe
commit 89a66d5389
7 changed files with 149 additions and 70 deletions
+2 -2
View File
@@ -11,12 +11,12 @@ namespace BarrageGrab
{ {
private delegate bool ControlCtrlDelegate(int CtrlType); private delegate bool ControlCtrlDelegate(int CtrlType);
static WssBarrageService server = null; static WsBarrageService server = null;
static void Main(string[] args) static void Main(string[] args)
{ {
SetConsoleCtrlHandler(cancelHandler, true);//捕获控制台关闭 SetConsoleCtrlHandler(cancelHandler, true);//捕获控制台关闭
Console.Title = "抖音弹幕监听推送"; Console.Title = "抖音弹幕监听推送";
server = new WssBarrageService(); server = new WsBarrageService();
server.StartListen(); server.StartListen();
while (true) while (true)
+6
View File
@@ -1,6 +1,7 @@
using System; using System;
using Fiddler; using Fiddler;
using System.Reflection; using System.Reflection;
using System.Collections.Generic;
namespace BarrageGrab.Proxy namespace BarrageGrab.Proxy
{ {
@@ -8,6 +9,11 @@ namespace BarrageGrab.Proxy
{ {
event EventHandler<WsMessageEventArgs> OnWebSocketData; event EventHandler<WsMessageEventArgs> OnWebSocketData;
/// <summary>
/// 域名过滤器
/// </summary>
Func<string, bool> HostNameFilter { get; set; }
/// <summary> /// <summary>
/// 开始监听 /// 开始监听
/// </summary> /// </summary>
+34 -14
View File
@@ -13,17 +13,10 @@ namespace BarrageGrab.Proxy
{ {
internal abstract class SystemProxy : ISystemProxy internal abstract class SystemProxy : ISystemProxy
{ {
//弹幕服务域名 /// <summary>
protected string[] barrageWsHostNames = new string[] /// 域名过滤器
{ /// </summary>
"webcast3-ws-web-hl.douyin.com", public Func<string, bool> HostNameFilter { get; set; }
"webcast3-ws-web-lf.douyin.com",
"frontier-im.douyin.com",
"webcast100-ws-web-lq.amemv.com"
};
//https://live.douyin.com/webcast/gift/list/
/// <summary> /// <summary>
/// 接收到websocket消息事件 /// 接收到websocket消息事件
@@ -33,17 +26,42 @@ namespace BarrageGrab.Proxy
/// <summary> /// <summary>
/// 代理端口 /// 代理端口
/// </summary> /// </summary>
public int ProxyPort { get => Appsetting.Instanse.ProxyPort; } public int ProxyPort { get => Appsetting.Current.ProxyPort; }
public abstract void Dispose(); public abstract void Dispose();
public abstract void Start(); public abstract void Start();
protected void SendWebSocketData(WsMessageEventArgs args) //https://live.douyin.com/webcast/gift/list/ [礼物数据接口]
/// <summary>
/// 检测是否是业务相关链接
/// </summary>
/// <param name="host"></param>
/// <returns></returns>
protected bool CheckHost(string host)
{
var result = true;
if (HostNameFilter != null) return HostNameFilter(host);
return result;
}
/// <summary>
/// 触发websocket消息事件
/// </summary>
/// <param name="args"></param>
protected void FireWsEvent(WsMessageEventArgs args)
{ {
OnWebSocketData?.Invoke(this, args); OnWebSocketData?.Invoke(this, args);
} }
/// <summary>
/// 获取进程名称
/// </summary>
/// <param name="processID"></param>
/// <returns></returns>
protected string GetProcessName(int processID) protected string GetProcessName(int processID)
{ {
var process = Process.GetProcessById(processID); var process = Process.GetProcessById(processID);
@@ -54,7 +72,9 @@ namespace BarrageGrab.Proxy
return $"<{processID}>"; return $"<{processID}>";
} }
//注册系统代理 /// <summary>
/// 注册系统代理
/// </summary>
protected void RegisterSystemProxy() protected void RegisterSystemProxy()
{ {
RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true); RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
+6 -16
View File
@@ -44,7 +44,7 @@ namespace BarrageGrab.Proxy
proxyServer.ServerCertificateValidationCallback += ProxyServer_ServerCertificateValidationCallback; ; proxyServer.ServerCertificateValidationCallback += ProxyServer_ServerCertificateValidationCallback; ;
proxyServer.BeforeResponse += ProxyServer_BeforeResponse; proxyServer.BeforeResponse += ProxyServer_BeforeResponse;
explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any,ProxyPort, true); explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, ProxyPort, true);
explicitEndPoint.BeforeTunnelConnectRequest += ExplicitEndPoint_BeforeTunnelConnectRequest; explicitEndPoint.BeforeTunnelConnectRequest += ExplicitEndPoint_BeforeTunnelConnectRequest;
proxyServer.AddEndPoint(explicitEndPoint); proxyServer.AddEndPoint(explicitEndPoint);
} }
@@ -57,7 +57,6 @@ namespace BarrageGrab.Proxy
{ {
e.IsValid = true; e.IsValid = true;
} }
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -65,20 +64,16 @@ namespace BarrageGrab.Proxy
private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e) private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e)
{ {
string hostname = e.HttpClient.Request.RequestUri.Host; string hostname = e.HttpClient.Request.RequestUri.Host;
if (!barrageWsHostNames.Contains(hostname)) return;
if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Websocket) if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Websocket)
{ {
e.DataReceived += WebSocket_DataReceived; e.DataReceived += WebSocket_DataReceived;
} }
} }
//List<string> hostlist = new List<string>();
private async Task ExplicitEndPoint_BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) private async Task ExplicitEndPoint_BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{ {
string hostname = e.HttpClient.Request.RequestUri.Host; string hostname = e.HttpClient.Request.RequestUri.Host;
if (!barrageWsHostNames.Contains(hostname)) if (!CheckHost(hostname))
{ {
e.DecryptSsl = false; e.DecryptSsl = false;
} }
@@ -93,12 +88,10 @@ namespace BarrageGrab.Proxy
var processid = args.HttpClient.ProcessId.Value; var processid = args.HttpClient.ProcessId.Value;
var frames = args.WebSocketDecoderReceive.Decode(e.Buffer, e.Offset, e.Count).ToList(); var frames = args.WebSocketDecoderReceive.Decode(e.Buffer, e.Offset, e.Count).ToList();
//Console.WriteLine(frames.Count);
foreach (var frame in frames) foreach (var frame in frames)
{ {
//Console.WriteLine(frame.GetText()); base.FireWsEvent(new WsMessageEventArgs()
base.SendWebSocketData(new WsMessageEventArgs()
{ {
ProcessID = processid, ProcessID = processid,
HostName = hostname, HostName = hostname,
@@ -106,9 +99,6 @@ namespace BarrageGrab.Proxy
ProcessName = base.GetProcessName(processid) ProcessName = base.GetProcessName(processid)
}); });
} }
//Console.WriteLine("获取到弹幕信息:" + hostname);
} }
/// <summary> /// <summary>
@@ -6,26 +6,33 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using BarrageGrab.JsonEntity; using BarrageGrab.JsonEntity;
using BarrageGrab.ProtoEntity;
using ColorConsole; using ColorConsole;
using Fleck; using Fleck;
using Newtonsoft.Json; using Newtonsoft.Json;
using static BarrageGrab.ProtoEntity.Image;
namespace BarrageGrab namespace BarrageGrab
{ {
/// <summary> /// <summary>
/// 弹幕服务 /// 弹幕服务
/// </summary> /// </summary>
internal class WssBarrageService internal class WsBarrageService
{ {
WebSocketServer socketServer; WebSocketServer socketServer;
Dictionary<string, UserState> socketList = new Dictionary<string, UserState>(); Dictionary<string, UserState> socketList = new Dictionary<string, UserState>();
Timer dieout = new Timer(10000); Timer dieout = new Timer(10000);
ConsoleWriter console = new ConsoleWriter(); ConsoleWriter console = new ConsoleWriter();
WssBarrageGrab grab = new WssBarrageGrab(); WssBarrageGrab grab = new WssBarrageGrab();
Appsetting Appsetting = Appsetting.Get(); Appsetting Appsetting = Appsetting.Current;
bool debug = false;
public WssBarrageService()
public WsBarrageService()
{ {
#if DEBUG
debug = true;
#endif
var socket = new WebSocketServer($"ws://127.0.0.1:{Appsetting.WsProt}"); var socket = new WebSocketServer($"ws://127.0.0.1:{Appsetting.WsProt}");
socket.RestartAfterListenError = true;//异常重启 socket.RestartAfterListenError = true;//异常重启
@@ -44,36 +51,46 @@ namespace BarrageGrab
//dieout.Start(); //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() MsgUser user = new MsgUser()
{ {
DisplayId = obj.User.displayId, DisplayId = data.displayId,
Gender = obj.User.Gender, Gender = data.Gender,
Id = obj.User.Id, Id = data.Id,
Level = obj.User.Level, Level = data.Level,
Nickname = obj.User.Nickname Nickname = data.Nickname
}; };
return user; return user;
} }
//粉丝团
private void Grab_OnFansclubMessage(object sender, ProtoEntity.FansclubMessage e) private void Grab_OnFansclubMessage(object sender, ProtoEntity.FansclubMessage e)
{ {
if (!CheckRoomId(e.commonInfo.roomId)) return;
var enty = new FansclubMsg() var enty = new FansclubMsg()
{ {
Content = e.Content, Content = e.Content,
RoomId = e.commonInfo.roomId, RoomId = e.commonInfo.roomId,
Type = e.Type, Type = e.Type,
User = GetUser(e) User = GetUser(e.User)
}; };
Print($"[粉丝团消息] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Blue); Print(enty.User.GenderToString() + " " + enty.Content, ConsoleColor.Blue, BarrageMsgType.粉丝团消息);
var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.粉丝团信息); var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.粉丝团消息);
var json = JsonConvert.SerializeObject(pack); var json = JsonConvert.SerializeObject(pack);
this.Broadcast(json); this.Broadcast(json);
} }
//统计消息
private void Grab_OnRoomUserSeqMessage(object sender, ProtoEntity.RoomUserSeqMessage e) private void Grab_OnRoomUserSeqMessage(object sender, ProtoEntity.RoomUserSeqMessage e)
{ {
if (!CheckRoomId(e.Common.roomId)) return;
var enty = new UserSeqMsg() var enty = new UserSeqMsg()
{ {
OnlineUserCount = e.Total, OnlineUserCount = e.Total,
@@ -84,92 +101,113 @@ namespace BarrageGrab
Content = $"当前直播间人数 {e.onlineUserForAnchor},累计直播间人数 {e.totalPvForAnchor}", Content = $"当前直播间人数 {e.onlineUserForAnchor},累计直播间人数 {e.totalPvForAnchor}",
User = null User = null
}; };
Print($"[直播间统计] " + enty.Content, ConsoleColor.Magenta); Print(enty.Content, ConsoleColor.Magenta, BarrageMsgType.直播间统计);
var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.直播间统计); var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.直播间统计);
var json = JsonConvert.SerializeObject(pack); var json = JsonConvert.SerializeObject(pack);
this.Broadcast(json); this.Broadcast(json);
} }
//礼物
private void Grab_OnGiftMessage(object sender, ProtoEntity.GiftMessage e) private void Grab_OnGiftMessage(object sender, ProtoEntity.GiftMessage e)
{ {
if (!CheckRoomId(e.Common.roomId)) return;
var enty = new GiftMsg() var enty = new GiftMsg()
{ {
RoomId = e.Common.roomId, RoomId = e.Common.roomId,
Content = e.Common.Describe, Content = e.Common.Describe,
DiamondCount = e.Gift.diamondCount, DiamondCount = e.Gift.diamondCount,
GiftCount = e.repeatCount, GiftCount = e.repeatCount,
GroupCount = e.groupCount,
GiftId = e.giftId, GiftId = e.giftId,
GiftName = e.Gift.Name, 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); var json = JsonConvert.SerializeObject(pack);
this.Broadcast(json); this.Broadcast(json);
} }
//关注
private void Grab_OnSocialMessage(object sender, ProtoEntity.SocialMessage e) private void Grab_OnSocialMessage(object sender, ProtoEntity.SocialMessage e)
{ {
if (!CheckRoomId(e.Common.roomId)) return;
var enty = new Msg() var enty = new Msg()
{ {
Content = $"{e.User.Nickname} 关注了主播", Content = $"{e.User.Nickname} 关注了主播",
RoomId = e.Common.roomId, RoomId = e.Common.roomId,
User = GetUser(e) User = GetUser(e.User)
}; };
Print($"[关注消息] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Yellow); Print($"{enty.User.GenderToString()} {enty.Content}", ConsoleColor.Yellow, BarrageMsgType.关注消息);
var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.关注主播); var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.关注消息);
var json = JsonConvert.SerializeObject(pack); var json = JsonConvert.SerializeObject(pack);
this.Broadcast(json); this.Broadcast(json);
} }
//来了
private void Grab_OnMemberMessage(object sender, ProtoEntity.MemberMessage e) 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, RoomId = e.Common.roomId,
User = GetUser(e) CurrentCount = e.memberCount,
User = GetUser(e.User)
}; };
Print($"[进直播间] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Green); Print($"{enty.User.GenderToString()} {enty.Content}", ConsoleColor.Green, BarrageMsgType.进直播间);
var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.进入直播间); var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.进直播间);
var json = JsonConvert.SerializeObject(pack); var json = JsonConvert.SerializeObject(pack);
this.Broadcast(json); this.Broadcast(json);
} }
//点赞
private void Grab_OnLikeMessage(object sender, ProtoEntity.LikeMessage e) private void Grab_OnLikeMessage(object sender, ProtoEntity.LikeMessage e)
{ {
if (!CheckRoomId(e.Common.roomId)) return;
var enty = new LikeMsg() var enty = new LikeMsg()
{ {
Count = e.Count, Count = e.Count,
Content = $"{e.User.Nickname} 为主播点了{e.Count}个赞", Content = $"{e.User.Nickname} 为主播点了{e.Count}个赞,总点赞{e.Total}",
RoomId = e.Common.roomId, RoomId = e.Common.roomId,
User = GetUser(e) Total = e.Total,
User = GetUser(e.User)
}; };
Print($"[点赞消息] {enty.User.GenderToString()} " + enty.Content, ConsoleColor.Cyan); Print($"{enty.User.GenderToString()} {enty.Content}", ConsoleColor.Cyan, BarrageMsgType.点赞消息);
var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.点赞); var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.点赞消息);
var json = JsonConvert.SerializeObject(pack); var json = JsonConvert.SerializeObject(pack);
this.Broadcast(json); this.Broadcast(json);
} }
//弹幕
private void Grab_OnChatMessage(object sender, ProtoEntity.ChatMessage e) private void Grab_OnChatMessage(object sender, ProtoEntity.ChatMessage e)
{ {
if (!CheckRoomId(e.Common.roomId)) return;
var enty = new Msg() var enty = new Msg()
{ {
Content = e.Content, Content = e.Content,
RoomId = e.Common.roomId, RoomId = e.Common.roomId,
User = GetUser(e) User = GetUser(e.User)
}; };
Print($"[弹幕消息] {enty.User.GenderToString()} {enty.User.Nickname}: {enty.Content}", ConsoleColor.White); Print($"{enty.User.GenderToString()} {enty.User.Nickname}: {enty.Content}", ConsoleColor.White, BarrageMsgType.弹幕消息);
var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.消息); var pack = new BarrageMsgPack(JsonConvert.SerializeObject(enty), BarrageMsgType.弹幕消息);
var json = JsonConvert.SerializeObject(pack); var json = JsonConvert.SerializeObject(pack);
this.Broadcast(json); 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) 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
} }
} }
/// <summary>
/// 开始监听
/// </summary>
public void StartListen() public void StartListen()
{ {
this.grab.Start(); //启动代理 this.grab.Start(); //启动代理
+25 -3
View File
@@ -19,9 +19,18 @@ namespace BarrageGrab
{ {
//ISystemProxy proxy = new FiddlerProxy(); //ISystemProxy proxy = new FiddlerProxy();
ISystemProxy proxy = new TitaniumProxy(); ISystemProxy proxy = new TitaniumProxy();
Appsetting appsetting = Appsetting.Get(); Appsetting appsetting = Appsetting.Current;
ConsoleWriter console = new ConsoleWriter(); 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"
};
/// <summary> /// <summary>
/// 进入直播间 /// 进入直播间
/// </summary> /// </summary>
@@ -65,6 +74,7 @@ namespace BarrageGrab
public WssBarrageGrab() public WssBarrageGrab()
{ {
proxy.OnWebSocketData += Proxy_OnWebSocketData; proxy.OnWebSocketData += Proxy_OnWebSocketData;
proxy.HostNameFilter = HostNameChecker;
} }
public void Start() public void Start()
@@ -77,6 +87,16 @@ namespace BarrageGrab
proxy.Dispose(); 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解压缩 //gzip解压缩
private byte[] Decompress(byte[] zippedData) private byte[] Decompress(byte[] zippedData)
{ {
@@ -95,7 +115,8 @@ namespace BarrageGrab
compressedzipStream.Close(); compressedzipStream.Close();
return outBuffer.ToArray(); return outBuffer.ToArray();
} }
//ws数据处理
private void Proxy_OnWebSocketData(object sender, WsMessageEventArgs e) private void Proxy_OnWebSocketData(object sender, WsMessageEventArgs e)
{ {
if (!appsetting.FilterProcess.Contains(e.ProcessName)) return; if (!appsetting.FilterProcess.Contains(e.ProcessName)) return;
@@ -103,7 +124,7 @@ namespace BarrageGrab
if (buff.Length == 0) return; if (buff.Length == 0) return;
if (buff[0] != 0x08) return; if (buff[0] != 0x08) return;
try try
{ {
var enty = Serializer.Deserialize<WssResponse>(new ReadOnlyMemory<byte>(buff)); var enty = Serializer.Deserialize<WssResponse>(new ReadOnlyMemory<byte>(buff));
@@ -123,6 +144,7 @@ namespace BarrageGrab
catch (Exception) { } catch (Exception) { }
} }
//发送事件
private void DoMessage(Message msg) private void DoMessage(Message msg)
{ {
try try
+1 -1
View File
@@ -126,7 +126,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ProtoEntity\Messages.cs" /> <Compile Include="ProtoEntity\Messages.cs" />
<Compile Include="ProtoEntity\Wss.cs" /> <Compile Include="ProtoEntity\Wss.cs" />
<Compile Include="WssBarrageService.cs" /> <Compile Include="WsBarrageService.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />