Merge branch 'master' of https://gitee.com/haodong108/dy-barrage-grab
This commit is contained in:
+104
-106
@@ -1,109 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<!--配置更改后重启才能生效-->
|
||||
<appSettings>
|
||||
<!--过滤Websocket数据源进程,可用','进行分隔,程序将会监听以下进程的弹幕信息-->
|
||||
<add key="processFilter" value="直播伴侣,douyin,chrome,msedge,QQBrowser,360se,firefox,2345explorer,iexplore" />
|
||||
<!--Websocket监听端口-->
|
||||
<add key="wsListenPort" value="8888" />
|
||||
<!--true:监听在0.0.0.0,接受任意Ip连接,false:监听在127.0.0.1,仅接受本机连接-->
|
||||
<add key="listenAny" value="true" />
|
||||
<!--系统代理端口-->
|
||||
<add key="proxyPort" value="8827" />
|
||||
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
||||
<add key="usedProxy" value="true" />
|
||||
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
||||
<add key="upstreamProxy" value="" />
|
||||
<!--在控制台输出弹幕-->
|
||||
<add key="printBarrage" value="true" />
|
||||
<!--要在控制台打印的弹幕类型,多个使用','分隔,(空代表不过滤) 1[普通弹幕],2[点赞消息],3[进入直播间],4[关注消息],5[礼物消息],6[统计消息],7[粉丝团消息],8[直播间分享],9[下播]-->
|
||||
<add key="printFilter" value="" />
|
||||
<!--要推送的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="pushFilter" value="" />
|
||||
<!--要日志记录的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
||||
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
||||
<add key="webRoomIds" value="" />
|
||||
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
||||
<add key="filterHostName" value="true" />
|
||||
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
||||
<add key="hostNameFilter" value="" />
|
||||
<!--隐藏控制台-->
|
||||
<add key="hideConsole" value="false" />
|
||||
<!--弹幕文件日志-->
|
||||
<add key="barrageFileLog" value="false" />
|
||||
<!--显示窗体-->
|
||||
<add key="showWindow" value="false" />
|
||||
<!--进入直播间自动暂停播放-->
|
||||
<add key="autoPause" value="true" />
|
||||
<!--强制启用轮询模式获取弹幕 (对于容易断开连接或者更加追求稳定的直播间,可以启用这个开关,虽然响应速度不如WebSocket,但是绝对稳定!)-->
|
||||
<add key="forcePolling" value="false" />
|
||||
<!--弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)-->
|
||||
<add key="pollingInterval" value="3000" />
|
||||
<!--禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)-->
|
||||
<add key="disableLivePageScriptCache" value="false" />
|
||||
<!--指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空 -->
|
||||
<add key="comPort" value="" />
|
||||
<!--启用自定义消息过滤,启用后可去程序根目录 Scripts/engine/comPortFilter.js 调整过滤规则 -->
|
||||
<add key="useComPortFilter" value="true" />
|
||||
<!--直播伴侣exe文件位置(除非程序找不到,否则请留空)-->
|
||||
<add key="liveCompanPath" value="" />
|
||||
<!--直播伴侣进程代理开关-->
|
||||
<add key="liveCompanHookSwitch" value="false" />
|
||||
</appSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.Tracing" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
|
||||
</startup>
|
||||
<system.web>
|
||||
<membership defaultProvider="ClientAuthenticationMembershipProvider">
|
||||
<providers>
|
||||
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
|
||||
</providers>
|
||||
</membership>
|
||||
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
|
||||
<providers>
|
||||
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
|
||||
</providers>
|
||||
</roleManager>
|
||||
</system.web>
|
||||
<!--配置更改后重启才能生效-->
|
||||
<appSettings>
|
||||
<!--过滤Websocket数据源进程,可用','进行分隔,程序将会监听以下进程的弹幕信息-->
|
||||
<add key="processFilter" value="直播伴侣,douyin,chrome,msedge,QQBrowser,360se,firefox,2345explorer,iexplore" />
|
||||
<!--Websocket监听端口-->
|
||||
<add key="wsListenPort" value="8888" />
|
||||
<!--true:监听在0.0.0.0,接受任意Ip连接,false:监听在127.0.0.1,仅接受本机连接-->
|
||||
<add key="listenAny" value="true" />
|
||||
<!--系统代理端口-->
|
||||
<add key="proxyPort" value="8827" />
|
||||
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
||||
<add key="sysProxy" value="true" />
|
||||
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
||||
<add key="upstreamProxy" value="" />
|
||||
<!--在控制台输出弹幕-->
|
||||
<add key="printBarrage" value="true" />
|
||||
<!--要在控制台打印的弹幕类型,多个使用','分隔,(空代表不过滤) 1[普通弹幕],2[点赞消息],3[进入直播间],4[关注消息],5[礼物消息],6[统计消息],7[粉丝团消息],8[直播间分享],9[下播]-->
|
||||
<add key="printFilter" value="" />
|
||||
<!--要推送的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="pushFilter" value="" />
|
||||
<!--要日志记录的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
||||
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
||||
<add key="webRoomIds" value="" />
|
||||
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
||||
<add key="filterHostName" value="true" />
|
||||
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
||||
<add key="hostNameFilter" value="" />
|
||||
<!--隐藏控制台-->
|
||||
<add key="hideConsole" value="false" />
|
||||
<!--弹幕文件日志-->
|
||||
<add key="barrageFileLog" value="false" />
|
||||
<!--显示窗体-->
|
||||
<add key="showWindow" value="false" />
|
||||
<!--进入直播间自动暂停播放-->
|
||||
<add key="autoPause" value="true" />
|
||||
<!--强制启用轮询模式获取弹幕 (对于容易断开连接或者更加追求稳定的直播间,可以启用这个开关,虽然响应速度不如WebSocket,但是绝对稳定!)-->
|
||||
<add key="forcePolling" value="false" />
|
||||
<!--弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)-->
|
||||
<add key="pollingInterval" value="3000" />
|
||||
<!--禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)-->
|
||||
<add key="disableLivePageScriptCache" value="false" />
|
||||
<!-- 指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空,(启用后程序会自动生成过滤器模板文件到 scripts/comPortFilter.js) -->
|
||||
<add key="comPort" value="" />
|
||||
<!--直播伴侣exe文件位置(除非程序找不到,否则请留空)-->
|
||||
<add key="liveCompanPath" value="" />
|
||||
<!--直播伴侣进程代理开关-->
|
||||
<add key="liveCompanHookSwitch" value="false" />
|
||||
</appSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.Tracing" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.InteropServices" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
|
||||
</startup>
|
||||
<system.web>
|
||||
<membership defaultProvider="ClientAuthenticationMembershipProvider">
|
||||
<providers>
|
||||
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
|
||||
</providers>
|
||||
</membership>
|
||||
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
|
||||
<providers>
|
||||
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
|
||||
</providers>
|
||||
</roleManager>
|
||||
</system.web>
|
||||
</configuration>
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
// 配置更改后重启才能生效
|
||||
"app": {
|
||||
"general": {
|
||||
// 是否隐藏控制台
|
||||
"hideConsole": false,
|
||||
// 显示窗体
|
||||
"showWindow": false
|
||||
},
|
||||
"network": {
|
||||
"proxy": {
|
||||
// 系统代理端口
|
||||
"port": 8827,
|
||||
// 是否启用系统代理,若设置为false 则需要在程序手动指定代理地址
|
||||
"enabled": true,
|
||||
// 上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://
|
||||
"upstreamAddress": ""
|
||||
},
|
||||
"websocket": {
|
||||
// Websocket监听端口
|
||||
"listenPort": 8888,
|
||||
// true:监听在0.0.0.0,接受任意Ip连接,false:监听在127.0.0.1,仅接受本机连接
|
||||
"listenAny": true
|
||||
}
|
||||
},
|
||||
"filtering": {
|
||||
// 过滤Websocket数据源进程,可用','进行分隔,程序将会监听以下进程的弹幕信息
|
||||
"processFilter": "直播伴侣,douyin,chrome,msedge,QQBrowser,360se,firefox,2345explorer,iexplore",
|
||||
// 开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整
|
||||
"hostNameEnabled": true,
|
||||
// 已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单
|
||||
"hostNameList": "",
|
||||
// 要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持
|
||||
"webRoomIds": ""
|
||||
},
|
||||
"barrage": {
|
||||
// 在控制台输出弹幕
|
||||
"printEnabled": true,
|
||||
// 要在控制台打印的弹幕类型,多个使用','分隔,(空代表不过滤) 1[普通弹幕],2[点赞消息],3[进入直播间],4[关注消息],5[礼物消息],6[统计消息],7[粉丝团消息],8[直播间分享],9[下播]
|
||||
"printFilter": "",
|
||||
// 要推送的弹幕消息类型,多个使用','分隔,同上
|
||||
"pushFilter": "",
|
||||
// 弹幕文件日志
|
||||
"barrageFileLog": false,
|
||||
// 要日志记录的弹幕消息类型,多个使用','分隔,同上
|
||||
"logFilter": "1,2,4,5,6,7,8",
|
||||
//轮询配置
|
||||
"polling": {
|
||||
// 强制启用轮询模式获取弹幕 (对于容易断开连接或者更加追求稳定的直播间,可以启用这个开关,虽然响应速度不如WebSocket,但是绝对稳定!)
|
||||
"enabled": false,
|
||||
// 弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)
|
||||
"interval": 3000,
|
||||
// 禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)
|
||||
"disableScriptCache": false
|
||||
}
|
||||
},
|
||||
"liveCompanion": {
|
||||
// 直播伴侣exe文件位置(除非程序找不到,否则请留空)
|
||||
"path": "",
|
||||
// 直播伴侣进程代理开关
|
||||
"hookEnabled": false,
|
||||
// 进入直播间自动暂停播放
|
||||
"autoPause": true
|
||||
},
|
||||
|
||||
"comPort": {
|
||||
// 指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空,(启用后程序会自动生成过滤器模板文件到 scripts/comPortFilter.js)
|
||||
"config": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,10 +37,10 @@ namespace BarrageGrab
|
||||
|
||||
static AppRuntime()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
public static void Init()
|
||||
{
|
||||
WsServer = new WsBarrageServer();
|
||||
RoomCaches = new RoomCacheManager();
|
||||
@@ -57,7 +57,7 @@ namespace BarrageGrab
|
||||
var hWnd = WinApi.GetConsoleWindow();
|
||||
if (hWnd != IntPtr.Zero)
|
||||
{
|
||||
WinApi.ShowWindow(hWnd, show? WinApi.CmdShow.SW_SHOW:WinApi.CmdShow.SW_HIDE);
|
||||
WinApi.ShowWindow(hWnd, show ? WinApi.CmdShow.SW_SHOW : WinApi.CmdShow.SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace BarrageGrab
|
||||
WebRoomId = webrid,
|
||||
Title = "房间" + webrid
|
||||
};
|
||||
var succ = RoomInfoCache.TryAdd(roomid,info);
|
||||
var succ = RoomInfoCache.TryAdd(roomid, info);
|
||||
if (succ)
|
||||
{
|
||||
OnCache?.Invoke(this, new RoomCacheEventArgs()
|
||||
@@ -130,7 +130,7 @@ namespace BarrageGrab
|
||||
var succ = RoomInfoCache.TryAdd(roomid, roomInfo);
|
||||
if (succ)
|
||||
{
|
||||
OnCache?.Invoke(this,new RoomCacheEventArgs()
|
||||
OnCache?.Invoke(this, new RoomCacheEventArgs()
|
||||
{
|
||||
Model = 0,
|
||||
RoomInfo = roomInfo
|
||||
@@ -147,7 +147,7 @@ namespace BarrageGrab
|
||||
public string GetCachedWebRoomid(string roomid)
|
||||
{
|
||||
RoomInfo value;
|
||||
if (RoomInfoCache.TryGetValue(roomid,out value)) return value.WebRoomId??"未知";
|
||||
if (RoomInfoCache.TryGetValue(roomid, out value)) return value.WebRoomId ?? "未知";
|
||||
return "未知";
|
||||
}
|
||||
|
||||
@@ -177,13 +177,13 @@ namespace BarrageGrab
|
||||
|
||||
public class RoomCacheEventArgs : EventArgs
|
||||
{
|
||||
public RoomInfo RoomInfo { get; set; }
|
||||
|
||||
public RoomInfo RoomInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 0:添加,1更新,2删除
|
||||
/// </summary>
|
||||
public int Model { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+405
-4
@@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BarrageGrab.Modles.JsonEntity;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static System.Configuration.ConfigurationManager;
|
||||
using System.Drawing;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -29,7 +31,7 @@ namespace BarrageGrab
|
||||
LogFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
|
||||
FilterHostName = bool.Parse(AppSettings["filterHostName"].Trim());
|
||||
HostNameFilter = AppSettings["hostNameFilter"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
|
||||
UsedProxy = bool.Parse(AppSettings["usedProxy"].Trim());
|
||||
UsedProxy = bool.Parse(AppSettings["sysProxy"].Trim());
|
||||
ListenAny = bool.Parse(AppSettings["listenAny"].Trim());
|
||||
UpstreamProxy = AppSettings["upstreamProxy"].Trim();
|
||||
HideConsole = bool.Parse(AppSettings["hideConsole"].Trim());
|
||||
@@ -53,6 +55,405 @@ namespace BarrageGrab
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从JSON文件加载配置
|
||||
/// </summary>
|
||||
/// <param name="jsonFilePath">JSON配置文件路径</param>
|
||||
public void LoadFromJson(string jsonFilePath = null)
|
||||
{
|
||||
if(jsonFilePath==null) jsonFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appConfig.json");
|
||||
try
|
||||
{
|
||||
if(!File.Exists(jsonFilePath))
|
||||
{
|
||||
Logger.LogError($"配置文件不存在: {jsonFilePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 读取JSON文件内容(保留注释)
|
||||
string jsonContent = File.ReadAllText(jsonFilePath);
|
||||
|
||||
// 解析JSON(Newtonsoft.Json支持JSONC格式,会自动忽略注释)
|
||||
JObject config = JObject.Parse(jsonContent);
|
||||
|
||||
// 从JSON读取应用配置
|
||||
var app = config["app"];
|
||||
|
||||
// 常规配置
|
||||
var general = app["general"];
|
||||
HideConsole = general["hideConsole"]?.Value<bool>() ?? false;
|
||||
ShowWindow = general["showWindow"]?.Value<bool>() ?? false;
|
||||
|
||||
// 网络配置
|
||||
var network = app["network"];
|
||||
var proxy = network["proxy"];
|
||||
ProxyPort = proxy["port"]?.Value<int>() ?? 8827;
|
||||
UsedProxy = proxy["enabled"]?.Value<bool>() ?? true;
|
||||
UpstreamProxy = proxy["upstreamAddress"]?.Value<string>() ?? string.Empty;
|
||||
|
||||
var websocket = network["websocket"];
|
||||
WsProt = websocket["listenPort"]?.Value<int>() ?? 8888;
|
||||
ListenAny = websocket["listenAny"]?.Value<bool>() ?? true;
|
||||
|
||||
// 过滤配置
|
||||
var filtering = app["filtering"];
|
||||
string processFilterStr = filtering["processFilter"]?.Value<string>() ?? "直播伴侣,douyin,chrome,msedge,QQBrowser,360se,firefox,2345explorer,iexplore";
|
||||
ProcessFilter = processFilterStr.Split(',');
|
||||
FilterHostName = filtering["hostNameEnabled"]?.Value<bool>() ?? true;
|
||||
string hostNameFilterStr = filtering["hostNameList"]?.Value<string>() ?? string.Empty;
|
||||
HostNameFilter = !string.IsNullOrWhiteSpace(hostNameFilterStr)
|
||||
? hostNameFilterStr.Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray()
|
||||
: new string[0];
|
||||
string webRoomIdsStr = filtering["webRoomIds"]?.Value<string>() ?? string.Empty;
|
||||
WebRoomIds = !string.IsNullOrWhiteSpace(webRoomIdsStr)
|
||||
? webRoomIdsStr.Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray()
|
||||
: new string[0];
|
||||
|
||||
// 弹幕配置
|
||||
var barrage = app["barrage"];
|
||||
PrintBarrage = barrage["printEnabled"]?.Value<bool>() ?? true;
|
||||
BarrageLog = barrage["barrageFileLog"]?.Value<bool>() ?? false;
|
||||
var polling = app["barrage"]["polling"];
|
||||
ForcePolling = polling["enabled"]?.Value<bool>() ?? false;
|
||||
PollingInterval = polling["interval"]?.Value<int>() ?? 3000;
|
||||
DisableLivePageScriptCache = polling["disableScriptCache"]?.Value<bool>() ?? false;
|
||||
|
||||
// 设置默认过滤器
|
||||
PrintFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
|
||||
PushFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
|
||||
LogFilter = Enum.GetValues(typeof(PackMsgType)).Cast<int>().Where(w => w > 0).ToArray();
|
||||
|
||||
string printFilterStr = barrage["printFilter"]?.Value<string>() ?? string.Empty;
|
||||
string pushFilterStr = barrage["pushFilter"]?.Value<string>() ?? string.Empty;
|
||||
string logFilterStr = barrage["logFilter"]?.Value<string>() ?? "1,2,4,5,6,7,8";
|
||||
|
||||
// 解析过滤器
|
||||
if (!string.IsNullOrWhiteSpace(printFilterStr))
|
||||
{
|
||||
PrintFilter = printFilterStr.Split(',').Select(x => int.Parse(x)).ToArray();
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(pushFilterStr))
|
||||
{
|
||||
PushFilter = pushFilterStr.Split(',').Select(x => int.Parse(x)).ToArray();
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(logFilterStr))
|
||||
{
|
||||
LogFilter = logFilterStr.Split(',').Select(x => int.Parse(x)).ToArray();
|
||||
}
|
||||
|
||||
// 直播伴侣配置
|
||||
var liveCompanion = app["liveCompanion"];
|
||||
LiveCompanPath = liveCompanion["path"]?.Value<string>() ?? string.Empty;
|
||||
LiveCompanHookSwitch = liveCompanion["hookEnabled"]?.Value<bool>() ?? false;
|
||||
AutoPause = liveCompanion["autoPause"]?.Value<bool>() ?? true;
|
||||
|
||||
// COM端口配置
|
||||
var comPort = app["comPort"];
|
||||
string comPortStr = comPort["config"]?.Value<string>() ?? string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(comPortStr))
|
||||
{
|
||||
try
|
||||
{
|
||||
var spit = comPortStr.Split(':');
|
||||
ComPort = spit[0].Trim();
|
||||
ComBaudRate = int.Parse(spit[1].Trim());
|
||||
ComPortSwitch = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("串口配置格式错误," + ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
Logger.PrintColor("已从JSON配置文件加载设置");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.PrintColor($"从JSON加载配置失败: {ex.Message},将尝试从App.config加载");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从启动参数加载配置
|
||||
/// </summary>
|
||||
/// <param name="args">命令行参数数组</param>
|
||||
public void LoadFromCommand(string[] args)
|
||||
{
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.PrintColor("正在从命令行参数加载配置...");
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
string arg = args[i].ToLower().Trim();
|
||||
|
||||
// 如果参数以-或--开头,则为命令行开关
|
||||
if (arg.StartsWith("-") || arg.StartsWith("--"))
|
||||
{
|
||||
string paramName = arg.TrimStart('-');
|
||||
string paramValue = string.Empty;
|
||||
bool switchDef = false;
|
||||
|
||||
// 检查下一个参数是否是值(不是以-开头)
|
||||
if (i + 1 < args.Length && !(args[i + 1].StartsWith("-") || args[i + 1].StartsWith("--")))
|
||||
{
|
||||
paramValue = args[i + 1];
|
||||
i++; // 跳过已处理的值参数
|
||||
}
|
||||
else
|
||||
{
|
||||
// 对于布尔开关,没有值意味着true
|
||||
paramValue = "?";
|
||||
switchDef = true;
|
||||
}
|
||||
|
||||
// 根据参数名称设置相应的配置
|
||||
switch (paramName)
|
||||
{
|
||||
// 网络相关配置
|
||||
case "port":
|
||||
case "wsport":
|
||||
case "ws-port":
|
||||
if (int.TryParse(paramValue, out int wsPort))
|
||||
{
|
||||
WsProt = wsPort;
|
||||
Logger.PrintColor($"WebSocket端口设置为: {wsPort}");
|
||||
}
|
||||
break;
|
||||
|
||||
case "proxy-port":
|
||||
case "proxyport":
|
||||
if (int.TryParse(paramValue, out int proxyPort))
|
||||
{
|
||||
ProxyPort = proxyPort;
|
||||
Logger.PrintColor($"代理端口设置为: {proxyPort}");
|
||||
}
|
||||
break;
|
||||
|
||||
case "upstream":
|
||||
case "upstream-proxy":
|
||||
UpstreamProxy = paramValue;
|
||||
Logger.PrintColor($"上游代理设置为: {paramValue}");
|
||||
break;
|
||||
|
||||
case "listen-any":
|
||||
case "listenany":
|
||||
if (switchDef) break;
|
||||
ListenAny = ParseBool(paramValue);
|
||||
Logger.PrintColor($"监听任意IP设置为: {ListenAny}");
|
||||
break;
|
||||
|
||||
case "sysproxy":
|
||||
case "sys-proxy":
|
||||
if (switchDef) break;
|
||||
UsedProxy = ParseBool(paramValue);
|
||||
Logger.PrintColor($"系统代理设置为: {UsedProxy}");
|
||||
break;
|
||||
|
||||
// 过滤相关配置
|
||||
case "process-filter":
|
||||
case "processfilter":
|
||||
ProcessFilter = paramValue.Split(',');
|
||||
Logger.PrintColor($"进程过滤器设置为: {paramValue}");
|
||||
break;
|
||||
|
||||
case "hostname-filter":
|
||||
case "hostnamefilter":
|
||||
HostNameFilter = paramValue.Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
|
||||
Logger.PrintColor($"域名过滤器设置为: {paramValue}");
|
||||
break;
|
||||
|
||||
case "filter-hostname":
|
||||
case "filterhostname":
|
||||
if (switchDef) break;
|
||||
FilterHostName = ParseBool(paramValue);
|
||||
Logger.PrintColor($"是否启用域名过滤设置为: {FilterHostName}");
|
||||
break;
|
||||
|
||||
case "room-ids":
|
||||
case "roomids":
|
||||
WebRoomIds = paramValue.Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
|
||||
Logger.PrintColor($"房间ID过滤器设置为: {paramValue}");
|
||||
break;
|
||||
|
||||
// 弹幕相关配置
|
||||
case "print":
|
||||
case "print-barrage":
|
||||
if (switchDef) break;
|
||||
PrintBarrage = ParseBool(paramValue);
|
||||
Logger.PrintColor($"控制台打印弹幕设置为: {PrintBarrage}");
|
||||
break;
|
||||
|
||||
case "print-filter":
|
||||
case "printfilter":
|
||||
if (!string.IsNullOrWhiteSpace(paramValue))
|
||||
{
|
||||
PrintFilter = paramValue.Split(',').Select(x => int.Parse(x)).ToArray();
|
||||
Logger.PrintColor($"控制台打印过滤器设置为: {paramValue}");
|
||||
}
|
||||
break;
|
||||
|
||||
case "push-filter":
|
||||
case "pushfilter":
|
||||
if (!string.IsNullOrWhiteSpace(paramValue))
|
||||
{
|
||||
PushFilter = paramValue.Split(',').Select(x => int.Parse(x)).ToArray();
|
||||
Logger.PrintColor($"推送过滤器设置为: {paramValue}");
|
||||
}
|
||||
break;
|
||||
|
||||
case "log-filter":
|
||||
case "logfilter":
|
||||
if (!string.IsNullOrWhiteSpace(paramValue))
|
||||
{
|
||||
LogFilter = paramValue.Split(',').Select(x => int.Parse(x)).ToArray();
|
||||
Logger.PrintColor($"日志过滤器设置为: {paramValue}");
|
||||
}
|
||||
break;
|
||||
|
||||
case "barrage-log":
|
||||
case "barragelog":
|
||||
if (switchDef) break;
|
||||
BarrageLog = ParseBool(paramValue);
|
||||
Logger.PrintColor($"弹幕文件日志设置为: {BarrageLog}");
|
||||
break;
|
||||
|
||||
// 显示和控制台相关
|
||||
case "hide-console":
|
||||
case "hideconsole":
|
||||
if (switchDef) break;
|
||||
HideConsole = ParseBool(paramValue);
|
||||
Logger.PrintColor($"隐藏控制台设置为: {HideConsole}");
|
||||
break;
|
||||
|
||||
case "show-window":
|
||||
case "showwindow":
|
||||
if (switchDef) break;
|
||||
ShowWindow = ParseBool(paramValue);
|
||||
Logger.PrintColor($"显示窗体设置为: {ShowWindow}");
|
||||
break;
|
||||
|
||||
// 轮询相关配置
|
||||
case "force-polling":
|
||||
case "forcepolling":
|
||||
if (switchDef) break;
|
||||
ForcePolling = ParseBool(paramValue);
|
||||
Logger.PrintColor($"强制轮询模式设置为: {ForcePolling}");
|
||||
break;
|
||||
|
||||
case "polling-interval":
|
||||
case "pollinginterval":
|
||||
if (int.TryParse(paramValue, out int interval))
|
||||
{
|
||||
PollingInterval = interval;
|
||||
Logger.PrintColor($"轮询间隔设置为: {interval}ms");
|
||||
}
|
||||
break;
|
||||
|
||||
case "disable-cache":
|
||||
case "disablecache":
|
||||
if (switchDef) break;
|
||||
DisableLivePageScriptCache = ParseBool(paramValue);
|
||||
Logger.PrintColor($"禁用脚本缓存设置为: {DisableLivePageScriptCache}");
|
||||
break;
|
||||
|
||||
// 直播伴侣相关
|
||||
case "auto-pause":
|
||||
case "autopause":
|
||||
if (switchDef) break;
|
||||
AutoPause = ParseBool(paramValue);
|
||||
Logger.PrintColor($"自动暂停设置为: {AutoPause}");
|
||||
break;
|
||||
|
||||
case "livecompan-path":
|
||||
case "livecompanpath":
|
||||
LiveCompanPath = paramValue;
|
||||
Logger.PrintColor($"直播伴侣路径设置为: {paramValue}");
|
||||
break;
|
||||
|
||||
case "livecompan-hook":
|
||||
case "livecompanhook":
|
||||
if (switchDef) break;
|
||||
LiveCompanHookSwitch = ParseBool(paramValue);
|
||||
Logger.PrintColor($"直播伴侣Hook开关设置为: {LiveCompanHookSwitch}");
|
||||
break;
|
||||
|
||||
// COM端口相关
|
||||
case "com":
|
||||
case "comport":
|
||||
if (!string.IsNullOrWhiteSpace(paramValue))
|
||||
{
|
||||
try
|
||||
{
|
||||
var parts = paramValue.Split(':');
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
ComPort = parts[0].Trim();
|
||||
ComBaudRate = int.Parse(parts[1].Trim());
|
||||
ComPortSwitch = true;
|
||||
Logger.PrintColor($"COM端口设置为: {ComPort} 波特率: {ComBaudRate}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"COM端口配置格式错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 配置文件相关
|
||||
case "config":
|
||||
case "jsonconfig":
|
||||
try
|
||||
{
|
||||
if (File.Exists(paramValue))
|
||||
{
|
||||
LoadFromJson();
|
||||
Logger.PrintColor($"已从JSON配置文件加载配置: {paramValue}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError($"指定的配置文件不存在: {paramValue}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"加载JSON配置文件失败: {ex.Message}");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Logger.LogWarn($"未知的命令行参数: {arg}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.PrintColor("命令行参数配置加载完成");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"命令行参数解析错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析布尔值字符串
|
||||
/// </summary>
|
||||
private bool ParseBool(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return false;
|
||||
|
||||
value = value.ToLower().Trim();
|
||||
|
||||
return value == "true" || value == "1" || value == "yes" || value == "y" || value == "on";
|
||||
}
|
||||
|
||||
//com串口设置
|
||||
private void ConfigComPort()
|
||||
@@ -65,7 +466,7 @@ namespace BarrageGrab
|
||||
var spit = comPort.Split(':');
|
||||
ComPort = spit[0].Trim();
|
||||
ComBaudRate = int.Parse(spit[1].Trim());
|
||||
UseComPortFilter = bool.Parse(AppSettings["useComPortFilter"]);
|
||||
ComPortSwitch = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -244,7 +645,7 @@ namespace BarrageGrab
|
||||
/// <summary>
|
||||
/// 是否启用串口过滤器脚本
|
||||
/// </summary>
|
||||
public bool UseComPortFilter { get; set; }
|
||||
public bool ComPortSwitch { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 直播伴侣文件位置
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using BarrageGrab.Forms;
|
||||
using BarrageGrab.Forms.Models;
|
||||
using BarrageGrab.Modles.JsonEntity;
|
||||
using BarrageGrab.Proxy;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
@@ -13,6 +9,10 @@ using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using BarrageGrab.Forms;
|
||||
using BarrageGrab.Forms.Models;
|
||||
using BarrageGrab.Modles.JsonEntity;
|
||||
using BarrageGrab.Proxy;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace BarrageGrab
|
||||
InitializeComponent();
|
||||
barServer.OnPrint += WssService_OnPrint;
|
||||
barServer.Grab.Proxy.OnProxyStatus += Proxy_OnProxyStatus;
|
||||
AppRuntime.RoomCaches.OnCache += RoomCaches_OnCache;
|
||||
AppRuntime.RoomCaches.OnCache += RoomCaches_OnCache;
|
||||
}
|
||||
|
||||
private void InitTabPages()
|
||||
@@ -85,8 +85,8 @@ namespace BarrageGrab
|
||||
|
||||
private void Ck_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
CheckBox cbx = sender as CheckBox;
|
||||
if (cbx == null) return;
|
||||
CheckBox cbx = sender as CheckBox;
|
||||
if (cbx == null) return;
|
||||
var selected = GetCheckedBarTypes((FlowLayoutPanel)cbx.Parent);
|
||||
if (cbx.Parent.Parent == this.tabPage_Console)
|
||||
{
|
||||
@@ -96,7 +96,7 @@ namespace BarrageGrab
|
||||
{
|
||||
AppSetting.Current.PushFilter = selected;
|
||||
}
|
||||
if(cbx.Parent.Parent == this.tabPage_Log)
|
||||
if (cbx.Parent.Parent == this.tabPage_Log)
|
||||
{
|
||||
AppSetting.Current.LogFilter = selected;
|
||||
}
|
||||
@@ -113,12 +113,12 @@ namespace BarrageGrab
|
||||
if (cbk.Checked && cbk.Name.StartsWith("cbx_bartype_"))
|
||||
{
|
||||
list.Add((int)cbk.Tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list.OrderBy(o => o).ToArray();
|
||||
}
|
||||
|
||||
private Dictionary<int,string> GetMsgTypes()
|
||||
private Dictionary<int, string> GetMsgTypes()
|
||||
{
|
||||
var dic = new Dictionary<int, string>();
|
||||
Type enumType = typeof(PackMsgType);
|
||||
@@ -127,7 +127,7 @@ namespace BarrageGrab
|
||||
{
|
||||
DescriptionAttribute attribute = (DescriptionAttribute)field.GetCustomAttribute(typeof(DescriptionAttribute), false);
|
||||
int value = (int)field.GetValue(null);
|
||||
if (attribute != null && value>0)
|
||||
if (attribute != null && value > 0)
|
||||
{
|
||||
dic.Add(value, attribute.Description);
|
||||
}
|
||||
@@ -146,7 +146,7 @@ namespace BarrageGrab
|
||||
this.label3.Text = $"房间缓存列表({AppRuntime.RoomCaches.RoomInfoCache.Count})";
|
||||
list_roomCaches.Items.Add(item);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
private void FormView_Load(object sender, EventArgs e)
|
||||
@@ -165,7 +165,7 @@ namespace BarrageGrab
|
||||
this.Invoke(new Action(() =>
|
||||
{
|
||||
this.cbx_enableProxy.Checked = e.Open;
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
private void WssService_OnPrint(object sender, WsBarrageServer.PrintEventArgs e)
|
||||
@@ -187,7 +187,7 @@ namespace BarrageGrab
|
||||
this.rich_output.Clear();
|
||||
printCount = 0;
|
||||
}
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
private void cbx_enableProxy_CheckedChanged(object sender, EventArgs e)
|
||||
@@ -209,7 +209,7 @@ namespace BarrageGrab
|
||||
var selectedItem = list_roomCaches.SelectedItem as RoomCacheItem;
|
||||
if (selectedItem == null) return;
|
||||
|
||||
var form = new RoomDetail(selectedItem.RoomInfo);
|
||||
var form = new RoomDetail(selectedItem.RoomInfo);
|
||||
form.ShowDialog();
|
||||
}
|
||||
|
||||
@@ -225,8 +225,8 @@ namespace BarrageGrab
|
||||
catch (Exception ex)
|
||||
{
|
||||
//弹窗提示错误
|
||||
MessageBox.Show(ex.Message,"设置失败");
|
||||
}
|
||||
MessageBox.Show(ex.Message, "设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
private void cbx_barrageLog_CheckedChanged(object sender, EventArgs e)
|
||||
@@ -235,5 +235,5 @@ namespace BarrageGrab
|
||||
AppSetting.Current.BarrageLog = checker.Checked;
|
||||
AppSetting.Current.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using BarrageGrab.Modles;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BarrageGrab.Modles;
|
||||
|
||||
namespace BarrageGrab.Forms.Models
|
||||
{
|
||||
@@ -21,7 +21,7 @@ namespace BarrageGrab.Forms.Models
|
||||
public override string ToString()
|
||||
{
|
||||
if (RoomInfo == null) return "NULL";
|
||||
return $"({RoomInfo.WebRoomId}){RoomInfo?.Owner?.Nickname??"-1"}";
|
||||
return $"({RoomInfo.WebRoomId}){RoomInfo?.Owner?.Nickname ?? "-1"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using BarrageGrab.Modles;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
@@ -8,6 +7,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using BarrageGrab.Modles;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BarrageGrab.Forms
|
||||
@@ -18,7 +18,7 @@ namespace BarrageGrab.Forms
|
||||
{
|
||||
InitializeComponent();
|
||||
//小驼峰
|
||||
var json = JsonConvert.SerializeObject(info,Formatting.Indented,new JsonSerializerSettings()
|
||||
var json = JsonConvert.SerializeObject(info, Formatting.Indented, new JsonSerializerSettings()
|
||||
{
|
||||
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
|
||||
});
|
||||
|
||||
+46
-16
@@ -1,12 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using Jint;
|
||||
using Newtonsoft.Json;
|
||||
using Jint.Native;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -46,15 +46,45 @@ namespace BarrageGrab
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从engine 目录获取js 文件
|
||||
/// 从scripts 目录获取js 文件
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetJsFile(string fileName)
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "Scripts", "engine", fileName);
|
||||
if (!File.Exists(path)) throw new FileNotFoundException("不存在的文件", path);
|
||||
return File.ReadAllText(path, Encoding.UTF8);
|
||||
var checkDirs = new string[]
|
||||
{
|
||||
Path.Combine(AppContext.BaseDirectory, "Scripts"),
|
||||
Path.Combine(AppContext.BaseDirectory, "scripts"),
|
||||
};
|
||||
|
||||
foreach (var dir in checkDirs)
|
||||
{
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
var path = Path.Combine(dir, fileName);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return File.ReadAllText(path, Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在scripts目录下创建js 文件
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="content"></param>
|
||||
public static void CreateJsFile(string fileName,string content)
|
||||
{
|
||||
var dir = Path.Combine(AppContext.BaseDirectory, "scripts");
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
File.WriteAllText(Path.Combine(dir, fileName), content, Encoding.UTF8);
|
||||
}
|
||||
|
||||
class JsConsole
|
||||
@@ -83,7 +113,7 @@ namespace BarrageGrab
|
||||
Engine eng;
|
||||
public JsEncoder(Engine eng)
|
||||
{
|
||||
this.eng = eng;
|
||||
this.eng = eng;
|
||||
}
|
||||
|
||||
private JsValue ByteConvert(byte[] buff)
|
||||
@@ -165,14 +195,14 @@ namespace BarrageGrab
|
||||
return eng.Invoke("byteToUint8Array", buff);
|
||||
}
|
||||
|
||||
public JsValue toNumber(byte[] buff,int startIndex = 0)
|
||||
public JsValue toNumber(byte[] buff, int startIndex = 0)
|
||||
{
|
||||
return BitConverter.ToDouble(buff, startIndex);
|
||||
}
|
||||
|
||||
|
||||
public bool toBoolean(byte[] buff, int startIndex = 0)
|
||||
{
|
||||
return BitConverter.ToBoolean(buff, startIndex);
|
||||
return BitConverter.ToBoolean(buff, startIndex);
|
||||
}
|
||||
|
||||
public string toString(byte[] buff, int startIndex = 0)
|
||||
@@ -182,7 +212,7 @@ namespace BarrageGrab
|
||||
|
||||
public string toString(byte[] buff, int startIndex, int length)
|
||||
{
|
||||
return BitConverter.ToString(buff, startIndex, length);
|
||||
return BitConverter.ToString(buff, startIndex, length);
|
||||
}
|
||||
|
||||
public JsValue getBytes(JsValue value)
|
||||
@@ -190,21 +220,21 @@ namespace BarrageGrab
|
||||
byte[] buff = new byte[0];
|
||||
switch (value.Type)
|
||||
{
|
||||
case Jint.Runtime.Types.Empty:
|
||||
case Jint.Runtime.Types.Empty:
|
||||
case Jint.Runtime.Types.Undefined:
|
||||
case Jint.Runtime.Types.Null:
|
||||
break;
|
||||
case Jint.Runtime.Types.Boolean:
|
||||
buff = BitConverter.GetBytes(value.AsBoolean());
|
||||
break;
|
||||
break;
|
||||
case Jint.Runtime.Types.Number:
|
||||
buff = BitConverter.GetBytes(value.AsNumber());
|
||||
break;
|
||||
break;
|
||||
case Jint.Runtime.Types.BigInt:
|
||||
buff = BitConverter.GetBytes((long)value.AsNumber());
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
throw new Exception($"不支持该类型转换:" + value.Type);
|
||||
throw new Exception($"不支持该类型转换:" + value.Type);
|
||||
}
|
||||
|
||||
return ByteConvert(buff);
|
||||
|
||||
+48
-7
@@ -1,22 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using BarrageGrab.Modles.JsonEntity;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
public static class Logger
|
||||
{
|
||||
private static NLog.Config.ISetupBuilder builder = LogManager.Setup().LoadConfigurationFromFile("nlog.config");
|
||||
private static NLog.Config.ISetupBuilder builder;
|
||||
|
||||
private static readonly NLog.Logger logger = builder.GetLogger("*");
|
||||
private static NLog.Logger logger;
|
||||
|
||||
static Logger()
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
//读取嵌入式资源文件
|
||||
var resourceName = assembly.GetManifestResourceNames().FirstOrDefault(s => s.EndsWith("nlog.config"));
|
||||
if (resourceName == null)
|
||||
{
|
||||
throw new Exception("nlog.config 嵌入式资源不存在");
|
||||
}
|
||||
|
||||
builder = LogManager.Setup().LoadConfigurationFromAssemblyResource(assembly, resourceName);
|
||||
logger = builder.GetLogger("*");
|
||||
}
|
||||
|
||||
public static void PrintColor(string message, ConsoleColor foreground = ConsoleColor.White)
|
||||
{
|
||||
{
|
||||
var color = Console.ForegroundColor;
|
||||
Console.ForegroundColor = foreground;
|
||||
Console.WriteLine(message);
|
||||
@@ -83,9 +98,10 @@ namespace BarrageGrab
|
||||
{
|
||||
var dir = Path.Combine(AppContext.BaseDirectory, "logs", "弹幕日志");
|
||||
var room = AppRuntime.RoomCaches.GetCachedWebRoomInfo(msg.RoomId.ToString());
|
||||
if(room == null) return;
|
||||
if (room == null) return;
|
||||
var date = DateTime.Now.ToString("yyyy年MM月dd日直播");
|
||||
dir = Path.Combine(dir, $"({room.WebRoomId}){room?.Owner?.Nickname ?? "-1"}", date);
|
||||
var nickName = SafePathString(room?.Owner?.Nickname ?? "-1");
|
||||
dir = Path.Combine(dir, $"({room.WebRoomId}){nickName}", date, "场次" + msg.RoomId.ToString());
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
@@ -107,6 +123,31 @@ namespace BarrageGrab
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字符串中的特殊字符转换为'?',使其安全用于文件路径
|
||||
/// </summary>
|
||||
/// <param name="input">输入字符串</param>
|
||||
/// <returns>处理后的安全字符串</returns>
|
||||
public static string SafePathString(string input)
|
||||
{
|
||||
//在文件系统中,以下字符通常不允许用于文件名:\ / : * ? " < > |
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return input;
|
||||
|
||||
// 文件系统中不允许的字符
|
||||
char[] invalidChars = Path.GetInvalidFileNameChars().Concat(Path.GetInvalidPathChars()).Distinct().ToArray();
|
||||
|
||||
StringBuilder result = new StringBuilder(input.Length);
|
||||
foreach (char c in input)
|
||||
{
|
||||
result.Append(invalidChars.Contains(c) ? '?' : c);
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static string LogText(Msg msg, PackMsgType barType)
|
||||
{
|
||||
var rinfo = AppRuntime.RoomCaches.GetCachedWebRoomInfo(msg.RoomId.ToString());
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace BarrageGrab.Modles
|
||||
this.Code = -1;
|
||||
}
|
||||
|
||||
public BusinessExecption(string msg,object data) : base(msg)
|
||||
public BusinessExecption(string msg, object data) : base(msg)
|
||||
{
|
||||
this.ErrorTarget = data;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ namespace BarrageGrab.Modles.JsonEntity
|
||||
public enum PackMsgType
|
||||
{
|
||||
[Description("无")]
|
||||
无 = 0,
|
||||
[Description("消息")]
|
||||
无 = 0,
|
||||
[Description("消息")]
|
||||
弹幕消息 = 1,
|
||||
[Description("点赞")]
|
||||
点赞消息 = 2,
|
||||
@@ -71,8 +71,8 @@ namespace BarrageGrab.Modles.JsonEntity
|
||||
/// <summary>
|
||||
/// 消息类型
|
||||
/// </summary>
|
||||
public PackMsgType Type { get; set; }
|
||||
|
||||
public PackMsgType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 进程名
|
||||
/// </summary>
|
||||
@@ -88,7 +88,7 @@ namespace BarrageGrab.Modles.JsonEntity
|
||||
|
||||
}
|
||||
|
||||
public BarrageMsgPack(string data, PackMsgType type,string processName)
|
||||
public BarrageMsgPack(string data, PackMsgType type, string processName)
|
||||
{
|
||||
Data = data;
|
||||
Type = type;
|
||||
@@ -304,8 +304,8 @@ namespace BarrageGrab.Modles.JsonEntity
|
||||
/// <summary>
|
||||
/// 抖币价格
|
||||
/// </summary>
|
||||
public int DiamondCount { get; set; }
|
||||
|
||||
public int DiamondCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该礼物是否可连击
|
||||
/// </summary>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace BarrageGrab.Modles.JsonEntity
|
||||
/// <summary>
|
||||
/// 空指令
|
||||
/// </summary>
|
||||
None = 0,
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 安全关闭程序
|
||||
|
||||
@@ -4,8 +4,8 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BarrageGrab.Modles
|
||||
{
|
||||
@@ -659,7 +659,7 @@ namespace BarrageGrab.Modles
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
info = dto;
|
||||
|
||||
return Tuple.Create(0, "succ");
|
||||
@@ -710,7 +710,7 @@ namespace BarrageGrab.Modles
|
||||
SecUid = roomOwner["sec_uid"].ToString(),
|
||||
HeadUrl = roomOwner["avatar_thumb"]["url_list"].Values<string>()?.FirstOrDefault() ?? "",
|
||||
FollowStatus = roomOwner["follow_info"]["follow_status"].Value<int>()
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
info = dto;
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static ProtoBuf.Serializer;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -30,13 +31,13 @@ namespace BarrageGrab
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToJson(this object obj,bool format = false)
|
||||
public static string ToJson(this object obj, bool format = false)
|
||||
{
|
||||
if (obj is string)
|
||||
{
|
||||
return obj.ToString();
|
||||
}
|
||||
return JsonConvert.SerializeObject(obj, format?Formatting.Indented:Formatting.None);
|
||||
return JsonConvert.SerializeObject(obj, format ? Formatting.Indented : Formatting.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -135,7 +136,7 @@ namespace BarrageGrab
|
||||
}
|
||||
return cookies;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 追加另一个字典
|
||||
/// </summary>
|
||||
@@ -158,11 +159,11 @@ namespace BarrageGrab
|
||||
else
|
||||
{
|
||||
res.Add(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 转换为Cookie对象列表
|
||||
@@ -359,4 +360,75 @@ namespace BarrageGrab
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 模式匹配相关扩展方法
|
||||
/// </summary>
|
||||
public static class PatternMatchExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断是否匹配任意一个通配符
|
||||
/// </summary>
|
||||
/// <param name="str">要匹配的字符串</param>
|
||||
/// <param name="patterns">通配符表达式数组</param>
|
||||
/// <returns>是否匹配</returns>
|
||||
public static bool WildcardMatchAny(this string str, params string[] patterns)
|
||||
{
|
||||
return patterns.Any(x => x.WildcardMatch(str));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断是否匹配通配符
|
||||
/// </summary>
|
||||
/// <param name="wildcard">通配符表达式</param>
|
||||
/// <param name="s">要匹配的字符串</param>
|
||||
/// <param name="ignoreCase">是否忽略大小写</param>
|
||||
/// <returns>是否匹配</returns>
|
||||
public static bool WildcardMatch(this string wildcard, string s, bool ignoreCase = false)
|
||||
{
|
||||
return wildcard.WildcardMatch(s, 0, 0, ignoreCase);
|
||||
}
|
||||
|
||||
// 递归匹配通配符
|
||||
private static bool WildcardMatch(this string wildcard, string s, int wildcardIndex, int sIndex, bool ignoreCase)
|
||||
{
|
||||
while (wildcardIndex != wildcard.Length)
|
||||
{
|
||||
char c = wildcard[wildcardIndex];
|
||||
switch (c)
|
||||
{
|
||||
case '*':
|
||||
if (wildcardIndex == wildcard.Length - 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return Enumerable.Range(sIndex, s.Length - sIndex).Any((int i) => wildcard.WildcardMatch(s, wildcardIndex + 1, i, ignoreCase));
|
||||
default:
|
||||
{
|
||||
char c2 = (ignoreCase ? char.ToLower(c) : c);
|
||||
if (s.Length == sIndex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char c3 = (ignoreCase ? char.ToLower(s[sIndex]) : s[sIndex]);
|
||||
if (c2 != c3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case '?':
|
||||
break;
|
||||
}
|
||||
|
||||
wildcardIndex++;
|
||||
sIndex++;
|
||||
}
|
||||
|
||||
return sIndex == s.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using Jint.Runtime;
|
||||
using System.Windows.Forms;
|
||||
using Jint.Runtime;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -19,6 +19,7 @@ namespace BarrageGrab
|
||||
static bool formExited = false;
|
||||
static WinApi.ControlCtrlDelegate controlCtr = ControlCtrlHandle;
|
||||
static Mutex mutex = new Mutex(false, "DyBarrageGrab");
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (!mutex.WaitOne(TimeSpan.Zero, true))
|
||||
@@ -37,18 +38,18 @@ namespace BarrageGrab
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"程序初始化错误,{ex.Message}");
|
||||
MessageBox.Show(ex.Message, "程序初始化错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
MessageBox.Show(ex.Message, "程序初始化错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
exited = true;
|
||||
}
|
||||
|
||||
while (!exited)
|
||||
{
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
if (!AppRuntime.WsServer.IsDisposed)
|
||||
{
|
||||
AppRuntime.WsServer.Dispose();
|
||||
AppRuntime.WsServer.Dispose();
|
||||
}
|
||||
|
||||
Logger.PrintColor("服务器已关闭...");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("小白不圆个人工作室")]
|
||||
[assembly: AssemblyProduct("抖音弹幕监听器")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -33,6 +33,6 @@ using System.Runtime.InteropServices;
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.7.7")]
|
||||
[assembly: AssemblyFileVersion("2.7.7")]
|
||||
[assembly: AssemblyVersion("2.7.9")]
|
||||
[assembly: AssemblyFileVersion("2.7.9")]
|
||||
[assembly: NeutralResourcesLanguage("zh-CN")]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using BarrageGrab.Proxy.ProxyEventArgs;
|
||||
|
||||
namespace BarrageGrab.Proxy
|
||||
@@ -42,5 +42,5 @@ namespace BarrageGrab.Proxy
|
||||
/// 开始监听
|
||||
/// </summary>
|
||||
void Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ namespace BarrageGrab.Proxy.ProxyEventArgs
|
||||
/// <summary>
|
||||
/// 域名
|
||||
/// </summary>
|
||||
public string HostName { get; set; }
|
||||
public string HostName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 有效载荷
|
||||
|
||||
@@ -6,11 +6,11 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BarrageGrab.Proxy.ProxyEventArgs
|
||||
{
|
||||
public class SystemProxyChangeEventArgs:EventArgs
|
||||
public class SystemProxyChangeEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// True 以开启:False: 已关闭
|
||||
/// </summary>
|
||||
public bool Open { get; set; }
|
||||
public bool Open { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
using BarrageGrab.Proxy.ProxyEventArgs;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace BarrageGrab.Proxy
|
||||
{
|
||||
@@ -42,7 +42,7 @@ namespace BarrageGrab.Proxy
|
||||
|
||||
public abstract void Start();
|
||||
|
||||
public abstract void SetUpstreamProxy(string addr);
|
||||
public abstract void SetUpstreamProxy(string addr);
|
||||
|
||||
//https://live.douyin.com/webcast/gift/list/ [礼物数据接口]
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace BarrageGrab.Proxy
|
||||
RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
|
||||
registry.SetValue("ProxyEnable", 1);
|
||||
registry.SetValue("ProxyServer", $"127.0.0.1:{ProxyPort}");
|
||||
|
||||
|
||||
OnProxyStatus?.Invoke(this, new SystemProxyChangeEventArgs()
|
||||
{
|
||||
Open = true
|
||||
@@ -128,7 +128,7 @@ namespace BarrageGrab.Proxy
|
||||
{
|
||||
Open = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ProxyIsOpen()
|
||||
{
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using BarrageGrab.Modles;
|
||||
using BarrageGrab.Modles.JsonEntity;
|
||||
using BarrageGrab.Proxy.ProxyEventArgs;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using BrotliSharpLib;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog.LayoutRenderers;
|
||||
using Titanium.Web.Proxy;
|
||||
using Titanium.Web.Proxy.EventArguments;
|
||||
using Titanium.Web.Proxy.Http;
|
||||
using Titanium.Web.Proxy.Models;
|
||||
using Titanium.Web.Proxy.StreamExtended.Network;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Security.Cryptography;
|
||||
using HtmlDocument = HtmlAgilityPack.HtmlDocument;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using BrotliSharpLib;
|
||||
using System.IO.Compression;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Security.Policy;
|
||||
using NLog.LayoutRenderers;
|
||||
|
||||
namespace BarrageGrab.Proxy
|
||||
{
|
||||
@@ -90,17 +90,18 @@ namespace BarrageGrab.Proxy
|
||||
|
||||
proxyServer.CertificateManager.CertificateValidDays = 365 * 10;
|
||||
proxyServer.CertificateManager.SaveFakeCertificates = true;
|
||||
proxyServer.CertificateManager.CertificateEngine = Titanium.Web.Proxy.Network.CertificateEngine.DefaultWindows;
|
||||
proxyServer.CertificateManager.OverwritePfxFile = false;
|
||||
proxyServer.CertificateManager.RootCertificate = GetCert();
|
||||
if (proxyServer.CertificateManager.RootCertificate == null)
|
||||
{
|
||||
Logger.PrintColor("正在进行证书安装,需要信任该证书才可进行https解密,若有提示请确定");
|
||||
proxyServer.CertificateManager.CreateRootCertificate();
|
||||
}
|
||||
|
||||
//信任证书
|
||||
proxyServer.CertificateManager.CreateRootCertificate();
|
||||
proxyServer.CertificateManager.TrustRootCertificate(true);
|
||||
|
||||
//https://github.com/justcoding121/titanium-web-proxy/issues/828
|
||||
|
||||
proxyServer.ServerCertificateValidationCallback += ProxyServer_ServerCertificateValidationCallback;
|
||||
//proxyServer.BeforeRequest += ProxyServer_BeforeRequest;
|
||||
proxyServer.BeforeResponse += ProxyServer_BeforeResponse;
|
||||
@@ -307,7 +308,7 @@ namespace BarrageGrab.Proxy
|
||||
{
|
||||
lock (rinfoRequestings) rinfoRequestings.Add(webroomid);
|
||||
//查询后会自动缓存
|
||||
DyServer.GetRoomInfoForApi(webroomid, cookie).ContinueWith(t =>
|
||||
DyApiHelper.GetRoomInfoForApi(webroomid, cookie).ContinueWith(t =>
|
||||
{
|
||||
var rinfo = t.Result;
|
||||
//限制只尝试一次
|
||||
@@ -332,22 +333,6 @@ namespace BarrageGrab.Proxy
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置的注入的js
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
private string GetInjectScript(string name)
|
||||
{
|
||||
//获取exe所在目录路径
|
||||
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripts", "inject", name + ".js");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Hook 直播页面
|
||||
private async Task HookPageAsync(SessionEventArgs e)
|
||||
{
|
||||
@@ -376,8 +361,7 @@ namespace BarrageGrab.Proxy
|
||||
{
|
||||
string webrid = liveRoomMactch.Groups[1].Value;
|
||||
//获取直播页注入js
|
||||
string liveRoomInjectScript = GetInjectScript("livePage");
|
||||
|
||||
string liveRoomInjectScript = EmbResource.GetFileContent("livePage.js");
|
||||
//注入上下文变量;
|
||||
var scriptContext = BuildContext(new Dictionary<string, string>()
|
||||
{
|
||||
@@ -434,7 +418,7 @@ namespace BarrageGrab.Proxy
|
||||
script.InnerHtml = liveRoomInjectScript;
|
||||
body.AppendChild(script);
|
||||
html = doc.DocumentNode.OuterHtml;
|
||||
Logger.PrintColor($"直播页{urlNoQuery},用户脚本已成功注入!\n", ConsoleColor.Green);
|
||||
Logger.LogTrace($"直播页{urlNoQuery},用户脚本已成功注入!\n");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -458,7 +442,7 @@ namespace BarrageGrab.Proxy
|
||||
if (liveHomeMatch.Success)
|
||||
{
|
||||
//获取直播页注入js
|
||||
string liveHoomInjectScript = GetInjectScript("livePage");
|
||||
string liveHoomInjectScript = EmbResource.GetFileContent("livePage.js");
|
||||
|
||||
//注入上下文变量;
|
||||
var scriptContext = BuildContext(new Dictionary<string, string>()
|
||||
@@ -548,21 +532,20 @@ namespace BarrageGrab.Proxy
|
||||
if (!contentType.Trim().ToLower().Contains("application/javascript")) return;
|
||||
if (e.HttpClient.Response.StatusCode != 200) return;
|
||||
|
||||
//https://lf-webcast-platform.bytetos.com/obj/webcast-platform-cdn/webcast/douyin_live/chunks/island_a74ce.b55095a0.js
|
||||
//判断响应内容是否为js application/javascript
|
||||
if (hostname == SCRIPT_HOST
|
||||
//这俩个进程不需要注入
|
||||
&& processName != "直播伴侣" && processName != "douyin"
|
||||
if (processName != "直播伴侣" && processName != "douyin"
|
||||
&& fileName.StartsWith("island")
|
||||
)
|
||||
{
|
||||
var js = await e.GetResponseBodyAsString();
|
||||
var reg2 = new Regex(@"if\(!\((?<v1>\d,\w{1,2})\.DJ\)\(\)&&");
|
||||
var match = reg2.Match(js);
|
||||
var reg = new Regex(@"if\(!\(\d{1,},\w{1,}\.DJ\)\(\).+\w{1,}\.includes\(""live""\)\)\)\{");
|
||||
var match = reg.Match(js);
|
||||
if (match.Success)
|
||||
{
|
||||
js = reg2.Replace(js, "if(false &&");
|
||||
js = reg.Replace(js, "if(false){");
|
||||
e.SetResponseBodyString(js);
|
||||
Logger.PrintColor($"已成功绕过页面无操作检测\n", ConsoleColor.Green);
|
||||
Logger.PrintColor($"已成功绕过JS页面无操作检测 {urlNoQuery}\n", ConsoleColor.Green);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,6 +610,8 @@ namespace BarrageGrab.Proxy
|
||||
SCRIPT_HOST,
|
||||
LIVE_HOST,
|
||||
WEBCAST_AMEMV_HOST , //直播伴侣开播请求地址
|
||||
"*-webcast-platform.bytetos.com", //新的脚本地址
|
||||
"*webcast*" //所有带webcast的域名
|
||||
};
|
||||
|
||||
if (decryptSsls.Contains(hostname))
|
||||
@@ -634,6 +619,11 @@ namespace BarrageGrab.Proxy
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hostname.WildcardMatchAny(decryptSsls))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
hostname = hostname.Trim().ToLower();
|
||||
return base.CheckHost(hostname);
|
||||
}
|
||||
@@ -648,7 +638,7 @@ namespace BarrageGrab.Proxy
|
||||
var processid = args.HttpClient.ProcessId.Value;
|
||||
|
||||
List<byte> messageData = new List<byte>();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var frame in args.WebSocketDecoderReceive.Decode(e.Buffer, e.Offset, e.Count))
|
||||
|
||||
@@ -6,35 +6,9 @@
|
||||
* 正则: @".*:\/\/live.douyin\.com\/\d+"
|
||||
**/
|
||||
|
||||
/*注入脚本 定时触发全局keydown,避免直播流被无操作阻断*/
|
||||
|
||||
// 创建一个虚拟的按键事件
|
||||
const simulatedEvent = new KeyboardEvent('keydown', {
|
||||
key: 'Virtual_Alt',
|
||||
keyCode: 18, //alt
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
|
||||
// 获取要分派事件的目标元素,例如文档的根元素
|
||||
const targetElement = document.documentElement;
|
||||
|
||||
// 设置定时器,每隔60秒模拟一次按键事件
|
||||
setInterval(() => {
|
||||
targetElement.dispatchEvent(simulatedEvent);
|
||||
}, 1000 * 60);
|
||||
|
||||
// 订阅 keydown 事件 (Debug)
|
||||
targetElement.addEventListener('keydown', event => {
|
||||
if (event.key == "Virtual_Alt") {
|
||||
console.log('[防挂机处理] 按下了', event.key);
|
||||
}
|
||||
});
|
||||
|
||||
/*禁止关闭 Websocket*/
|
||||
WebSocket.prototype.close = function () { return; }
|
||||
|
||||
|
||||
/*判断是否自动关闭 */
|
||||
//获取路由参数
|
||||
function getQueryString(name) {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO.Ports;
|
||||
using Jint;
|
||||
using Jint.Runtime;
|
||||
using System.Windows.Forms;
|
||||
using Jint;
|
||||
using Jint.Native;
|
||||
using Jint.Runtime;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -22,20 +23,30 @@ namespace BarrageGrab
|
||||
|
||||
static ComPortServer()
|
||||
{
|
||||
if (AppSetting.Current.UseComPortFilter)
|
||||
if (!AppSetting.Current.ComPortSwitch) return;
|
||||
|
||||
jsEngine = JsEngine.CreateNewEngine();
|
||||
|
||||
var jsFile = JsEngine.GetJsFile("comPortFilter.js");
|
||||
|
||||
//生成模板文件
|
||||
if (jsFile == null)
|
||||
{
|
||||
jsEngine = JsEngine.CreateNewEngine();
|
||||
var jsFile = JsEngine.GetJsFile("comPortFilter.js");
|
||||
try
|
||||
{
|
||||
jsEngine.Execute(jsFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"comPortFilter.js 执行错误: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
jsFile = EmbResource.GetFileContent("comPortFilter.js");
|
||||
JsEngine.CreateJsFile("comPortFilter.js", jsFile);
|
||||
Logger.PrintColor($"已生成串口脚本模板文件 scripts/comPortFilter.js,请按个人需求修改", ConsoleColor.Yellow);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
jsEngine.Execute(jsFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"comPortFilter.js 执行错误: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ComPortServer(WsBarrageServer server)
|
||||
@@ -64,7 +75,7 @@ namespace BarrageGrab
|
||||
if (e == null) return;
|
||||
if (e.Message == null) return;
|
||||
|
||||
if (!AppSetting.Current.UseComPortFilter)
|
||||
if (!AppSetting.Current.ComPortSwitch)
|
||||
{
|
||||
var json = e.ToJson() + "\r\n";
|
||||
var jbuff = Encoding.UTF8.GetBytes(json);
|
||||
@@ -81,7 +92,7 @@ namespace BarrageGrab
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, $"串口过滤器 onPackData 执行错误:{ex.Message}");
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (result == null) return;
|
||||
|
||||
@@ -146,7 +157,7 @@ namespace BarrageGrab
|
||||
sendPort.Close();
|
||||
sendPort.Dispose();
|
||||
sendPort = null;
|
||||
throw ex;
|
||||
Logger.LogError(ex, $"串口打开失败, {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Dynamic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using Fleck;
|
||||
using Newtonsoft.Json;
|
||||
using BarrageGrab.Modles;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Net.Http;
|
||||
using System.IO.Compression;
|
||||
using System.IO;
|
||||
using BarrageGrab.Modles.JsonEntity;
|
||||
using BarrageGrab.Modles.ProtoEntity;
|
||||
using System.Drawing;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Dynamic;
|
||||
using Fleck;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static BarrageGrab.Modles.ProtoEntity.Image;
|
||||
using static BarrageGrab.Modles.WebCastGift;
|
||||
|
||||
@@ -176,6 +176,7 @@ namespace BarrageGrab
|
||||
return obj.GetType().GetProperty(propertyName) != null;
|
||||
}
|
||||
|
||||
//创建消息对象
|
||||
private T CreateMsg<T>(dynamic msg) where T : Msg, new()
|
||||
{
|
||||
var roomid = msg.Common.roomId.ToString();
|
||||
@@ -220,10 +221,10 @@ namespace BarrageGrab
|
||||
|
||||
if (isAdmin)
|
||||
{
|
||||
text+= " [管理员]";
|
||||
text += " [管理员]";
|
||||
}
|
||||
|
||||
if(isAnchor)
|
||||
if (isAnchor)
|
||||
{
|
||||
text += " [主播]";
|
||||
}
|
||||
@@ -286,7 +287,7 @@ namespace BarrageGrab
|
||||
{
|
||||
if (msg == null) return;
|
||||
var roomInfo = AppRuntime.RoomCaches.GetCachedWebRoomInfo(msg.RoomId.ToString());
|
||||
if (roomInfo != null && roomInfo.Owner!=null)
|
||||
if (roomInfo != null && roomInfo.Owner != null)
|
||||
{
|
||||
msg.Onwer = new RoomAnchorInfo()
|
||||
{
|
||||
@@ -580,29 +581,7 @@ namespace BarrageGrab
|
||||
try
|
||||
{
|
||||
var cmdPack = JsonConvert.DeserializeObject<Command>(message);
|
||||
if (cmdPack == null) return;
|
||||
|
||||
switch (cmdPack.Cmd)
|
||||
{
|
||||
case CommandCode.Close:
|
||||
this.Dispose();
|
||||
break;
|
||||
case CommandCode.EnableProxy:
|
||||
{
|
||||
var enable = (bool)cmdPack.Data;
|
||||
if (enable)
|
||||
this.grab.Proxy.RegisterSystemProxy();
|
||||
else
|
||||
this.grab.Proxy.CloseSystemProxy();
|
||||
break;
|
||||
}
|
||||
case CommandCode.DisplayConsole:
|
||||
{
|
||||
var display = (bool)cmdPack.Data;
|
||||
AppRuntime.DisplayConsole(display);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmdPack == null) return;
|
||||
}
|
||||
catch (Exception) { }
|
||||
};
|
||||
@@ -5,10 +5,10 @@ using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ProtoBuf;
|
||||
using BarrageGrab.Modles.ProtoEntity;
|
||||
using BarrageGrab.Proxy;
|
||||
using BarrageGrab.Proxy.ProxyEventArgs;
|
||||
using BarrageGrab.Modles.ProtoEntity;
|
||||
using ProtoBuf;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -15,7 +15,7 @@ namespace BarrageGrab
|
||||
/// <summary>
|
||||
/// 抖音服务
|
||||
/// </summary>
|
||||
internal class DyServer
|
||||
internal class DyApiHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取直播礼物列表
|
||||
@@ -55,7 +55,7 @@ namespace BarrageGrab
|
||||
Logger.LogError($"礼物信息从服务器请求失败: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取房间信息,通过原生接口
|
||||
@@ -69,7 +69,7 @@ namespace BarrageGrab
|
||||
string url = "https://live.douyin.com/webcast/room/web/enter/";
|
||||
|
||||
var client = new HttpClient();
|
||||
|
||||
|
||||
|
||||
var uri = new UriBuilder(url);
|
||||
var dict = new Dictionary<string, string>();
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源文件
|
||||
/// </summary>
|
||||
public static class EmbResource
|
||||
{
|
||||
static Dictionary<string,string> cache = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// 获取 嵌入式资源文件内容
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static string GetFileContent(string fileName)
|
||||
{
|
||||
if(cache.ContainsKey(fileName))
|
||||
{
|
||||
return cache[fileName];
|
||||
}
|
||||
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
//读取嵌入式资源文件
|
||||
var resourceName = assembly.GetManifestResourceNames().FirstOrDefault(s => s.EndsWith(fileName));
|
||||
if (resourceName == null)
|
||||
{
|
||||
throw new Exception($"{fileName} 嵌入式资源不存在");
|
||||
}
|
||||
|
||||
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(stream,Encoding.UTF8))
|
||||
{
|
||||
var text = reader.ReadToEnd();
|
||||
cache.Add(fileName, text);
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
using HtmlAgilityPack;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.InteropServices;
|
||||
using HtmlAgilityPack;
|
||||
using IWshRuntimeLibrary;
|
||||
using File = System.IO.File;
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
using Newtonsoft.Json;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace BarrageGrab
|
||||
{
|
||||
@@ -219,7 +219,7 @@ namespace BarrageGrab
|
||||
Logger.LogInfo($"直播伴侣文件改动检测点1已拦截");
|
||||
}
|
||||
|
||||
|
||||
|
||||
checkReg = new Regex(@"if\(\(0,\w.integrityCheckReport\)\(\w\),!\w\.ok\)");
|
||||
if (checkReg.IsMatch(content))
|
||||
{
|
||||
@@ -28,8 +28,6 @@ namespace BarrageGrab
|
||||
internal static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint mode);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint mode);
|
||||
|
||||
///If the function fails, the return value is NULL.</returns>
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Acornima, Version=1.1.0.0, Culture=neutral, PublicKeyToken=496b38436bb9edeb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Acornima.1.1.0\lib\net462\Acornima.dll</HintPath>
|
||||
@@ -70,9 +73,6 @@
|
||||
<Reference Include="BouncyCastle.Crypto, Version=1.8.8.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Portable.BouncyCastle.1.8.8\lib\net40\BouncyCastle.Crypto.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="BouncyCastle.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=072edcf4a5328938, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BouncyCastle.Cryptography.2.0.0\lib\net461\BouncyCastle.Cryptography.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="BrotliSharpLib, Version=0.3.2.0, Culture=neutral, PublicKeyToken=3f4e2a1cd615fcb7, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -206,11 +206,11 @@
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -221,8 +221,9 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="AppRuntime.cs" />
|
||||
<Compile Include="AppSetting.cs" />
|
||||
<Compile Include="ComPortServer.cs" />
|
||||
<Compile Include="DyServer.cs" />
|
||||
<Compile Include="Server\ComPortServer.cs" />
|
||||
<Compile Include="Utility\DyApiHelper.cs" />
|
||||
<Compile Include="Utility\EmbResource.cs" />
|
||||
<Compile Include="Forms\FormView.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@@ -237,7 +238,7 @@
|
||||
<DependentUpon>RoomDetail.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="JsEngine.cs" />
|
||||
<Compile Include="LiveCompanHelper.cs" />
|
||||
<Compile Include="Utility\LiveCompanHelper.cs" />
|
||||
<Compile Include="Logger.cs" />
|
||||
<Compile Include="Modles\BusinessExecption.cs" />
|
||||
<Compile Include="Modles\JsonEntity\BarrageMessages.cs" />
|
||||
@@ -254,27 +255,25 @@
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Proxy\SystemProxy.cs" />
|
||||
<Compile Include="Proxy\TitaniumProxy.cs" />
|
||||
<Compile Include="WinApi.cs" />
|
||||
<Compile Include="WssBarrageGrab.cs" />
|
||||
<Compile Include="Utility\WinApi.cs" />
|
||||
<Compile Include="Server\WssBarrageGrab.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="WsBarrageServer.cs" />
|
||||
<Compile Include="Server\WsBarrageServer.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="nlog.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<EmbeddedResource Include="Configs\nlog.config">
|
||||
<CustomToolNamespace>WssBarrageService</CustomToolNamespace>
|
||||
</EmbeddedResource>
|
||||
<None Include="AppConfig.json" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="FodyWeavers.xml" />
|
||||
<Content Include="Scripts\engine\comPortFilter.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Scripts\inject\livePage.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="logo.ico" />
|
||||
<EmbeddedResource Include="Scripts\engine\comPortFilter.js" />
|
||||
<EmbeddedResource Include="Scripts\inject\livePage.js" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.8">
|
||||
@@ -318,4 +317,12 @@
|
||||
</Target>
|
||||
<Import Project="..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" />
|
||||
<Import Project="..\packages\Fody.6.8.2\build\Fody.targets" Condition="Exists('..\packages\Fody.6.8.2\build\Fody.targets')" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>if "$(ConfigurationName)" == "Release" (
|
||||
del /q "$(TargetDir)*.xml"
|
||||
del /q "$(TargetDir)*.pdb"
|
||||
del /q "$(TargetDir)*.pfx"
|
||||
rmdir /s /q "$(TargetDir)crts"
|
||||
)</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -17,20 +17,23 @@
|
||||
|
||||
## ⛳近期更新
|
||||
|
||||
2025-04-15 v2.7.9(beta)
|
||||
1. 大幅优化了程序的体积大小
|
||||
2. 默认移除了Script目录,以及其他不必要的文件,但如果开启了串口推送开关,则会自动生成过滤器模板文件
|
||||
3. 添加了应用图标
|
||||
|
||||
2025-04-09 v2.7.8
|
||||
1. 修复页面无操作检测拦截失效的问题,因为更新了脚本
|
||||
2. 修复弹幕日志因主播昵称的特殊字符导致无法写入的问题
|
||||
|
||||
2025-02-11 v2.7.7
|
||||
|
||||
1. 添加 `Appid` 字段(疑似用户看直播的APP标识) 和 `EnterTipType` 字段(用于获知用户进入直播间的方式,已知0为普通进入,6为通过分享进入)
|
||||
|
||||
2. User字段新增 `IsAdmin` 和 `IsAnchor` 字段,用于区分是否为管理员或者主播的消息
|
||||
|
||||
3. web在中途监听弹幕,且直播间弹幕链接已降级为轮询的情况下,解决 `webroomid` 以及房间信息丢失问题
|
||||
|
||||
4. 修复直播伴侣更新后,无法定位到exe位置的问题
|
||||
|
||||
5. 优化部分其他已知问题
|
||||
|
||||
|
||||
|
||||
2024-09-28 v2.7.6(beta)
|
||||
|
||||
1. **[重要更新]** 支持免系统代理监听直播伴侣,需要在配置文件关闭`useproxy`选项以及打开`liveCompanHookSwitch`选项,配置后监听web直播间可参考<a href="#user-content-实践指南">实践指南</a>新部分
|
||||
@@ -46,38 +49,6 @@
|
||||
3. 修复了窗体初始化因控件可能导致的句柄出错的问题
|
||||
4. 修复在使用窗体的情况下,因跨线程调用抛出异常导致的弹幕断连问题
|
||||
|
||||
2024-05-14 v2.7.4
|
||||
|
||||
1. 修复通过抖音号进入直播偶见获取不到Owner对象和WebRoomid的问题;
|
||||
2. 修复部分电脑启动提示 ‘字符串格式错误’ 导致无法启动的问题
|
||||
3. 2024.05.16 补丁: 修复在使用窗体的情况下,因跨线程调用抛出异常导致的弹幕断连问题
|
||||
|
||||
2024-04-26 v2.7.3 (需要升级版本,请先仔细阅读)
|
||||
|
||||
1. 支持串口转发,详见下方说明<a href="#user-content-串口转发">**串口转发**</a>
|
||||
2. 推送包字段更新<br/>
|
||||
1. 推送包添加 `Onwer`字段,用户描述主播基本信息,客户端应优先使用其中的`SecUid`或者`Uid`作为直播间标识
|
||||
2. **[破坏性更新]** `WebRoomid` 和 `Roomid` 改为String类型
|
||||
3. 之前直播伴侣开播会导致`WebRoomid`为-1,现会抓取直播伴侣开播响应信息,并填充`WebRoomid`,但直播伴侣的`WebRoomid`设定为主播**抖音号**,需要根据进程名做判断,使用请注意
|
||||
|
||||
2024-03-10 v2.7.2
|
||||
|
||||
1. [**重要更新**] 支持设置为轮询模式监听(见配置项**forcePolling**,直播伴侣尚未支持),比起ws更稳定,适合长时间监听
|
||||
2. 支持进入直播间画面自动暂停
|
||||
3. 优化礼物连击判定规则,可区分出可连击的礼物,进一步避免礼物数量推送不准确的问题,并新增字段:
|
||||
1. Combo 礼物是否可连击
|
||||
2. ImgUrl 礼物图像地址
|
||||
3. ToUser 送礼目标
|
||||
4. roomId过滤改为 WebRoomid 过滤(仅支持已经被缓存的直播间,对直播伴侣可能无效)
|
||||
5. 添加“关闭代理.bat” 批处理脚本,见根目录或者上方文件,便于无法上网时双击执行
|
||||
6. 更多介绍请查看底下新增配置项
|
||||
|
||||
2023-11-23 v2.7.0
|
||||
|
||||
1. 修复了因抖音版本升级导致的WebRoomId获取不到的问题,并更近了正则表达式尽量兼容后续的变更
|
||||
2. 添加了winfrom窗体,功能有限,默认隐藏
|
||||
3. 支持了控制台隐藏,推送器弹幕类型过滤,日志弹幕类型过滤,弹幕文件日志 (见<a href="#tag1">配置文件</a>)
|
||||
4. 支持了更多的ws命令,见 [Command.cs](./BarrageGrab/Modles/JsonEntity/Command.cs)
|
||||
|
||||
## 🖼️控制台截图
|
||||
|
||||
@@ -88,6 +59,7 @@
|
||||
### 介绍
|
||||
|
||||
+ 基于系统代理抓包打造的抖音弹幕服务推送程序,它能够获取电脑上所有抖音弹幕来源数据,主要包括三种来源:**浏览器进程** ,**抖音客户端**,**抖音直播伴侣**。它可以监听**弹幕**,**点赞**,**关注**,**送礼**,**进入直播间**,**直播间统计**,**粉丝团**系列消息,你可使用它做自己的直播间数据分析,以及弹幕互动游戏,语音播报等。
|
||||
+ 程序含WebSocket服务,若需要对接自己的应用,或者扩展功能,可以进行接入
|
||||
|
||||
### <a id="tag1">配置文件</a>
|
||||
|
||||
@@ -95,71 +67,73 @@
|
||||
+ 若下载发行版,则该配置文件在根目录下的 **WssBarrageService.exe.config** 可自主配置,配置后需要重新启动程序
|
||||
|
||||
``` xml
|
||||
<!--配置更改后重启才能生效-->
|
||||
<appSettings>
|
||||
<!--过滤Websocket数据源进程,可用','进行分隔,程序将会监听以下进程的弹幕信息-->
|
||||
<add key="processFilter" value="直播伴侣,douyin,chrome,msedge,QQBrowser,360se,firefox,2345explorer,iexplore" />
|
||||
<!--Websocket监听端口-->
|
||||
<add key="wsListenPort" value="8888" />
|
||||
<!--true:监听在0.0.0.0,接受任意Ip连接,false:监听在127.0.0.1,仅接受本机连接-->
|
||||
<add key="listenAny" value="true" />
|
||||
<!--系统代理端口-->
|
||||
<add key="proxyPort" value="8827" />
|
||||
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
||||
<add key="usedProxy" value="true" />
|
||||
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
||||
<add key="upstreamProxy" value="" />
|
||||
<!--在控制台输出弹幕-->
|
||||
<add key="printBarrage" value="true" />
|
||||
<!--要在控制台打印的弹幕类型,多个使用','分隔,(空代表不过滤) 1[普通弹幕],2[点赞消息],3[进入直播间],4[关注消息],5[礼物消息],6[统计消息],7[粉丝团消息],8[直播间分享],9[下播]-->
|
||||
<add key="printFilter" value="" />
|
||||
<!--要推送的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="pushFilter" value="" />
|
||||
<!--要日志记录的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
||||
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
||||
<add key="webRoomIds" value="940152769375" />
|
||||
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
||||
<add key="filterHostName" value="true" />
|
||||
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
||||
<add key="hostNameFilter" value="" />
|
||||
<!--隐藏控制台-->
|
||||
<add key="hideConsole" value="false" />
|
||||
<!--弹幕文件日志-->
|
||||
<add key="barrageFileLog" value="false" />
|
||||
<!--显示窗体-->
|
||||
<add key="showWindow" value="false" />
|
||||
<!--进入直播间自动暂停播放-->
|
||||
<add key="autoPause" value="true"/>
|
||||
<!--强制启用轮询模式获取弹幕 (对于容易断开连接或者更加追求稳定的直播间,可以启用这个开关,虽然响应速度不如WebSocket,但是绝对稳定!)-->
|
||||
<add key="forcePolling" value="false"/>
|
||||
<!--弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)-->
|
||||
<add key="pollingInterval" value="3000"/>
|
||||
<!--禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)-->
|
||||
<add key="disableLivePageScriptCache" value="true"/>
|
||||
<!--指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空 -->
|
||||
<add key="comPort" value="" />
|
||||
<!--启用自定义消息过滤,启用后可去程序根目录 Scripts/engine/comPortFilter.js 调整过滤规则 -->
|
||||
<add key="useComPortFilter" value="true" />
|
||||
<!--直播伴侣exe文件位置(除非程序找不到,否则请留空)-->
|
||||
<add key="liveCompanPath" value=""/>
|
||||
<!--直播伴侣代理hook开关-->
|
||||
<add key="liveCompanHookSwitch" value="false" />
|
||||
</appSettings>
|
||||
<!--配置更改后重启才能生效-->
|
||||
<appSettings>
|
||||
<!--过滤Websocket数据源进程,可用','进行分隔,程序将会监听以下进程的弹幕信息-->
|
||||
<add key="processFilter" value="直播伴侣,douyin,chrome,msedge,QQBrowser,360se,firefox,2345explorer,iexplore" />
|
||||
<!--Websocket监听端口-->
|
||||
<add key="wsListenPort" value="8888" />
|
||||
<!--true:监听在0.0.0.0,接受任意Ip连接,false:监听在127.0.0.1,仅接受本机连接-->
|
||||
<add key="listenAny" value="true" />
|
||||
<!--系统代理端口-->
|
||||
<add key="proxyPort" value="8827" />
|
||||
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
||||
<add key="sysProxy" value="true" />
|
||||
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
||||
<add key="upstreamProxy" value="" />
|
||||
<!--在控制台输出弹幕-->
|
||||
<add key="printBarrage" value="true" />
|
||||
<!--要在控制台打印的弹幕类型,多个使用','分隔,(空代表不过滤) 1[普通弹幕],2[点赞消息],3[进入直播间],4[关注消息],5[礼物消息],6[统计消息],7[粉丝团消息],8[直播间分享],9[下播]-->
|
||||
<add key="printFilter" value="" />
|
||||
<!--要推送的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="pushFilter" value="" />
|
||||
<!--要日志记录的弹幕消息类型,多个使用','分隔,同上-->
|
||||
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
||||
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
||||
<add key="webRoomIds" value="" />
|
||||
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
||||
<add key="filterHostName" value="true" />
|
||||
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
||||
<add key="hostNameFilter" value="" />
|
||||
<!--隐藏控制台-->
|
||||
<add key="hideConsole" value="false" />
|
||||
<!--弹幕文件日志-->
|
||||
<add key="barrageFileLog" value="false" />
|
||||
<!--显示窗体-->
|
||||
<add key="showWindow" value="false" />
|
||||
<!--进入直播间自动暂停播放-->
|
||||
<add key="autoPause" value="true" />
|
||||
<!--强制启用轮询模式获取弹幕 (对于容易断开连接或者更加追求稳定的直播间,可以启用这个开关,虽然响应速度不如WebSocket,但是绝对稳定!)-->
|
||||
<add key="forcePolling" value="false" />
|
||||
<!--弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)-->
|
||||
<add key="pollingInterval" value="3000" />
|
||||
<!--禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)-->
|
||||
<add key="disableLivePageScriptCache" value="false" />
|
||||
<!-- 指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空,(启用后程序会自动生成过滤器模板文件到 scripts/comPortFilter.js) -->
|
||||
<add key="comPort" value="" />
|
||||
<!--直播伴侣exe文件位置(除非程序找不到,否则请留空)-->
|
||||
<add key="liveCompanPath" value="" />
|
||||
<!--直播伴侣进程代理开关-->
|
||||
<add key="liveCompanHookSwitch" value="false" />
|
||||
</appSettings>
|
||||
```
|
||||
|
||||
### 使用方法
|
||||
1. 管理员身份启动本程序,第一次启动会提示安装自签名证书,程序启动后挂在后台不要关,程序无法中途监听已经建立连接的弹幕流
|
||||
|
||||
2. 打开浏览器进入任何直播间,然后观察程序控制台中是否有弹幕滚动
|
||||
|
||||
3. 如果有请往下看,否则请参考诊断排查
|
||||
|
||||
4. 启动后程序控制台标题会显示 ws连接地址,如果需要对接自己的应用程序,请先了解 [WebSocket](https://www.bilibili.com/video/BV1KN411n7WD/?share_source=copy_web&vd_source=39ebf42c923024b9eddeca32c9e46d16) ,然后使用自己的程序进行对接,可前往[在线测试网站](http://wstool.jackxiang.com/)进行连接测试
|
||||
|
||||
5. 对于字段不理解,请参考 [实体类源码文件](./BarrageGrab/Modles/JsonEntity/BarrageMessages.cs) 的注释,或者加群询问
|
||||
|
||||
<a id="user-content-串口转发"></a>
|
||||
<a id="user-content-串口转发"></a>
|
||||
|
||||
## 🔌 串口转发</i>
|
||||
+ 配置串口:见<a href="#tag1">配置文件</a>`comPort`,配置发送串口以及波特率,不填则不启用
|
||||
+ 串口报文自定义:可在根目录`Scripts/engine/comPortFilter.js` 根据自己的需求配置转发报文,提供了一定的Bit转换函数,详见其注释
|
||||
+ 串口报文自定义:配置串口后,程序会自动生成配置模板文件 `scripts/comPortFilter.js`, 可根据自己的需求配置转发报文,提供了一定的Bit转换函数,详见其注释
|
||||
|
||||
## 👨⚕️ 诊断排查
|
||||
|
||||
@@ -182,9 +156,6 @@
|
||||
+ *尝试执行未经授权的操作*
|
||||
+ 关杀毒
|
||||
|
||||
+ *以上都不行*
|
||||
+ 请前往[这里](https://www.baidu.com/s?word=新款电脑淘宝)瞧瞧
|
||||
|
||||
|
||||
+ **弹幕断连**
|
||||
+ 如果浏览器总是连接一段时间后,就在在控制台看不到弹幕了,优先使用Chrome 和 Edge 浏览器,其他浏览器(例如360浏览器) 可能会存在该问题
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Reference in New Issue
Block a user