+33
-3
@@ -10,6 +10,8 @@
|
|||||||
<add key="listenAny" value="true" />
|
<add key="listenAny" value="true" />
|
||||||
<!--系统代理端口-->
|
<!--系统代理端口-->
|
||||||
<add key="proxyPort" value="8827" />
|
<add key="proxyPort" value="8827" />
|
||||||
|
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
||||||
|
<add key="usedProxy" value="true" />
|
||||||
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
||||||
<add key="upstreamProxy" value="" />
|
<add key="upstreamProxy" value="" />
|
||||||
<!--在控制台输出弹幕-->
|
<!--在控制台输出弹幕-->
|
||||||
@@ -22,8 +24,6 @@
|
|||||||
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
||||||
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
||||||
<add key="webRoomIds" value="" />
|
<add key="webRoomIds" value="" />
|
||||||
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
|
||||||
<add key="usedProxy" value="true" />
|
|
||||||
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
||||||
<add key="filterHostName" value="true" />
|
<add key="filterHostName" value="true" />
|
||||||
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
||||||
@@ -41,11 +41,13 @@
|
|||||||
<!--弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)-->
|
<!--弹幕轮询间隔,当 forcePolling 为 true 时生效 (毫秒,1000毫秒=1秒,不建议小于1000毫秒,太小可能会被封IP,值越小,弹幕流越丝滑,对于观众多的直播间可以改小)-->
|
||||||
<add key="pollingInterval" value="3000" />
|
<add key="pollingInterval" value="3000" />
|
||||||
<!--禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)-->
|
<!--禁用直播页浏览器脚本缓存 (如果需要确保脚本每次能够正常匹配替换,则启用它,可能会损失一定的页面加载速度)-->
|
||||||
<add key="disableLivePageScriptCache" value="true" />
|
<add key="disableLivePageScriptCache" value="false" />
|
||||||
<!--指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空 -->
|
<!--指定要发送的COM串口 格式:'COM1:9600' 代表用COM1发送,波特率9600,若不需要使用串口抄送服务请留空 -->
|
||||||
<add key="comPort" value="" />
|
<add key="comPort" value="" />
|
||||||
<!--启用自定义消息过滤,启用后可去程序根目录 Scripts/engine/comPortFilter.js 调整过滤规则 -->
|
<!--启用自定义消息过滤,启用后可去程序根目录 Scripts/engine/comPortFilter.js 调整过滤规则 -->
|
||||||
<add key="useComPortFilter" value="true" />
|
<add key="useComPortFilter" value="true" />
|
||||||
|
<!--直播伴侣exe文件位置(除非程序找不到,否则请留空)-->
|
||||||
|
<add key="liveCompanPath" value="" />
|
||||||
</appSettings>
|
</appSettings>
|
||||||
<runtime>
|
<runtime>
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
@@ -53,6 +55,34 @@
|
|||||||
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
|
||||||
</dependentAssembly>
|
</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>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
<startup>
|
<startup>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ namespace BarrageGrab
|
|||||||
PollingInterval = int.Parse(AppSettings["pollingInterval"].Trim());
|
PollingInterval = int.Parse(AppSettings["pollingInterval"].Trim());
|
||||||
DisableLivePageScriptCache = bool.Parse(AppSettings["disableLivePageScriptCache"].Trim());
|
DisableLivePageScriptCache = bool.Parse(AppSettings["disableLivePageScriptCache"].Trim());
|
||||||
WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
|
WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).ToArray();
|
||||||
|
LiveCompanPath = AppSettings["liveCompanPath"].Trim();
|
||||||
|
|
||||||
ConfigComPort();
|
ConfigComPort();
|
||||||
ConfigFilter();
|
ConfigFilter();
|
||||||
@@ -243,5 +244,10 @@ namespace BarrageGrab
|
|||||||
/// 是否启用串口过滤器脚本
|
/// 是否启用串口过滤器脚本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseComPortFilter { get; set; }
|
public bool UseComPortFilter { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 直播伴侣文件位置
|
||||||
|
/// </summary>
|
||||||
|
public string LiveCompanPath { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||||
|
<Costura />
|
||||||
|
</Weavers>
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
using HtmlAgilityPack;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using IWshRuntimeLibrary;
|
||||||
|
using File = System.IO.File;
|
||||||
|
|
||||||
|
namespace BarrageGrab
|
||||||
|
{
|
||||||
|
public static class LiveCompanHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取抖音直播伴侣的exe路径
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetExePath()
|
||||||
|
{
|
||||||
|
string exePath = "";
|
||||||
|
//获取exe所在目录
|
||||||
|
//1.先在开始菜单找
|
||||||
|
var shortcutPath = @"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\直播伴侣.lnk";
|
||||||
|
if (File.Exists(shortcutPath))
|
||||||
|
{
|
||||||
|
//获取快捷方式的目标路径
|
||||||
|
exePath = GetInkTargetPath(shortcutPath);
|
||||||
|
if (!File.Exists(exePath))
|
||||||
|
{
|
||||||
|
exePath = "";
|
||||||
|
Logger.LogWarn($"直播伴侣.lnk 所指向的exe文件位置 {exePath} 无效");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.LogInfo("未找到直播伴侣的桌面快捷方式");
|
||||||
|
}
|
||||||
|
|
||||||
|
//再从配置文件读取
|
||||||
|
if (exePath.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
exePath = AppSetting.Current.LiveCompanPath;
|
||||||
|
if(!exePath.IsNullOrWhiteSpace() && !File.Exists(exePath))
|
||||||
|
{
|
||||||
|
Logger.LogWarn($"所配置的 {exePath} 不存在");
|
||||||
|
exePath = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化直播伴侣环境
|
||||||
|
/// </summary>
|
||||||
|
public static void SwitchSetup()
|
||||||
|
{
|
||||||
|
var exePath = GetExePath();
|
||||||
|
if (string.IsNullOrEmpty(exePath))
|
||||||
|
{
|
||||||
|
Logger.LogWarn("未找到直播伴侣.exe文件,跳过环境设置");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置index.js
|
||||||
|
var indexJsPath = Path.Combine(Path.GetDirectoryName(exePath), "resources", "app", "index.js");
|
||||||
|
Logger.LogInfo($"正在配置 " + indexJsPath);
|
||||||
|
|
||||||
|
if (!File.Exists(indexJsPath))
|
||||||
|
{
|
||||||
|
throw new Exception("未找到直播伴侣的index.js文件");
|
||||||
|
}
|
||||||
|
var indexJs = File.ReadAllText(indexJsPath, Encoding.UTF8);
|
||||||
|
|
||||||
|
CheckBackFile(indexJsPath);
|
||||||
|
var newjs = SetIndexJsContent(indexJs);
|
||||||
|
if (newjs != indexJs && !newjs.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
File.WriteAllText(indexJsPath, newjs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.LogInfo("直播伴侣环境初始化完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取Ink快捷方式的目标路径
|
||||||
|
private static string GetInkTargetPath(string shortcutPath)
|
||||||
|
{
|
||||||
|
// 创建 Windows Script Host 对象
|
||||||
|
WshShell shell = new WshShell();
|
||||||
|
|
||||||
|
// 使用 IWshShortcut 接口加载 .ink 文件
|
||||||
|
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutPath);
|
||||||
|
|
||||||
|
// 获取目标路径
|
||||||
|
string targetPath = shortcut.TargetPath;
|
||||||
|
|
||||||
|
return targetPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
//检测备份文件
|
||||||
|
private static void CheckBackFile(string filePath)
|
||||||
|
{
|
||||||
|
if (!File.Exists(filePath)) return;
|
||||||
|
|
||||||
|
var bakPath = filePath + ".bak";
|
||||||
|
if (!File.Exists(bakPath))
|
||||||
|
{
|
||||||
|
//拷贝一份备份
|
||||||
|
File.Copy(filePath, bakPath);
|
||||||
|
Logger.LogInfo($"已备份 {filePath} -> {bakPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置index.js内容
|
||||||
|
private static string SetIndexJsContent(string content)
|
||||||
|
{
|
||||||
|
//检测注入代理
|
||||||
|
var mineProxyHost = $"127.0.0.1:{AppSetting.Current.ProxyPort},direct://";
|
||||||
|
SetSwitch("proxy-server", mineProxyHost, ref content);
|
||||||
|
|
||||||
|
//移除文件损坏检测校验
|
||||||
|
var checkReg = new Regex(@"if\(\(0,\w.integrityCheckReport\)\(\w\),!\w\.ok\)");
|
||||||
|
if (checkReg.IsMatch(content))
|
||||||
|
{
|
||||||
|
content = checkReg.Replace(content, "if(false)");
|
||||||
|
Logger.LogInfo($"直播伴侣文件改动检测已拦截");
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
//添加 electron 启动参数
|
||||||
|
private static void SetSwitch(string name, string value, ref string content)
|
||||||
|
{
|
||||||
|
if (name.IsNullOrWhiteSpace()) return;
|
||||||
|
|
||||||
|
//检测注入
|
||||||
|
var proxyReg = new Regex($@"(?<varname>\w+)\.commandLine\.appendSwitch\(""{name}"",""(?<value>[^""]*)""\)");
|
||||||
|
var proxyMatch = proxyReg.Match(content);
|
||||||
|
//检测到已经存在配置,则更新参数值
|
||||||
|
if (proxyMatch.Success)
|
||||||
|
{
|
||||||
|
var matchValue = proxyMatch.Groups["value"].Value;
|
||||||
|
if (value != matchValue)
|
||||||
|
{
|
||||||
|
content = proxyReg.Replace(content, $@"${{varname}}.commandLine.appendSwitch(""{name}"",""{value}"")");
|
||||||
|
Logger.LogInfo($"直播伴侣成功覆盖启动参数 [{name}] = [{value}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//否则添加新的配置
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var nosandboxReg = new Regex(@"(?<varname>\w+)\.commandLine\.appendSwitch\(""no-sandbox""\)");
|
||||||
|
var match = nosandboxReg.Match(content);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
var newvalue = $@"{match.Groups["varname"].ToString()}.commandLine.appendSwitch(""{name}"",""{value}""),";
|
||||||
|
content = content.Insert(match.Index, newvalue);
|
||||||
|
Logger.LogInfo($"直播伴侣成功添加启动参数 [{name}] = [{value}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetInnerText(HtmlNode node, string text)
|
||||||
|
{
|
||||||
|
node.InnerHtml = "";
|
||||||
|
var textNode = node.OwnerDocument.CreateTextNode(text);
|
||||||
|
node.AppendChild(textNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -91,7 +91,28 @@ namespace BarrageGrab
|
|||||||
foreach (var item in list) func(item, i++);
|
foreach (var item in list) func(item, i++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否包含
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool In<T>(this T obj, params T[] args)
|
||||||
|
{
|
||||||
|
return args.Contains(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否包含
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool LikeIn(this string str, params string[] args)
|
||||||
|
{
|
||||||
|
return args.Any(a => str.Contains(a));
|
||||||
|
}
|
||||||
|
|
||||||
public static CookieCollection ToCookies(this string cookieStr, string domain)
|
public static CookieCollection ToCookies(this string cookieStr, string domain)
|
||||||
{
|
{
|
||||||
var cookies = new CookieCollection();
|
var cookies = new CookieCollection();
|
||||||
@@ -170,6 +191,133 @@ namespace BarrageGrab
|
|||||||
if (cookies == null) return;
|
if (cookies == null) return;
|
||||||
var cookieCollection = dic.ToCookies(domain);
|
var cookieCollection = dic.ToCookies(domain);
|
||||||
cookies.Add(cookieCollection);
|
cookies.Add(cookieCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将字典转为查询参数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dic"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ToQueryParam(this IDictionary<string, string> dic, bool encode = true)
|
||||||
|
{
|
||||||
|
if (dic == null || dic.Count == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var queryParams = dic.Select(kvp => kvp.Key + "=" + (encode ? WebUtility.UrlEncode(kvp.Value) : kvp.Value));
|
||||||
|
return string.Join("&", queryParams);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 赋值字典,没有则添加,有则覆盖
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="dic"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
public static void Set<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key, TValue value)
|
||||||
|
{
|
||||||
|
if (dic.ContainsKey(key))
|
||||||
|
{
|
||||||
|
dic[key] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dic.Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 赋值字典,没有则添加,有则覆盖
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="dic"></param>
|
||||||
|
/// <param name="kv"></param>
|
||||||
|
public static void Set<TKey, TValue>(this IDictionary<TKey, TValue> dic, KeyValuePair<TKey, TValue> kv)
|
||||||
|
{
|
||||||
|
dic.Set(kv.Key, kv.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取Uri查询参数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentNullException"></exception>
|
||||||
|
public static IDictionary<string, string> GetQueryParams(this UriBuilder uri)
|
||||||
|
{
|
||||||
|
if (uri == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParams = uri.Query.TrimStart('?');
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(queryParams))
|
||||||
|
{
|
||||||
|
return new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryParams
|
||||||
|
.Split('&')
|
||||||
|
.Select(param => param.Split('='))
|
||||||
|
.ToDictionary(
|
||||||
|
keyValuePair => Uri.UnescapeDataString(keyValuePair[0]),
|
||||||
|
keyValuePair => Uri.UnescapeDataString(keyValuePair.Length > 1 ? keyValuePair[1] : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri"></param>
|
||||||
|
/// <param name="vals"></param>
|
||||||
|
public static void AddQueryParam(this UriBuilder uri, IEnumerable<KeyValuePair<string, string>> vals)
|
||||||
|
{
|
||||||
|
if (uri == null) return;
|
||||||
|
var dic = uri.GetQueryParams();
|
||||||
|
foreach (var item in vals)
|
||||||
|
{
|
||||||
|
dic.Set(item);
|
||||||
|
}
|
||||||
|
uri.Query = dic.ToQueryParam();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除一个query项
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
public static void RemoveQueryParam(this UriBuilder uri, string key)
|
||||||
|
{
|
||||||
|
if (uri == null) return;
|
||||||
|
var dic = uri.GetQueryParams();
|
||||||
|
dic.Remove(key);
|
||||||
|
if (dic.Count > 0)
|
||||||
|
{
|
||||||
|
uri.Query = "?" + dic.ToQueryParam();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uri.Query = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加参数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static void AddQueryParam(this UriBuilder uri, string key, string value)
|
||||||
|
{
|
||||||
|
if (uri == null) return;
|
||||||
|
uri.AddQueryParam(new[] {
|
||||||
|
new KeyValuePair<string, string>(key,value)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-59
@@ -18,19 +18,16 @@ namespace BarrageGrab
|
|||||||
static bool exited = false;
|
static bool exited = false;
|
||||||
static bool formExited = false;
|
static bool formExited = false;
|
||||||
static WinApi.ControlCtrlDelegate controlCtr = ControlCtrlHandle;
|
static WinApi.ControlCtrlDelegate controlCtr = ControlCtrlHandle;
|
||||||
|
static Mutex mutex = new Mutex(false, "DyBarrageGrab");
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
//JintTest();
|
if (!mutex.WaitOne(TimeSpan.Zero, true))
|
||||||
//Console.WriteLine("结束");
|
|
||||||
//Console.ReadKey();
|
|
||||||
//return;
|
|
||||||
if (CheckAlreadyRunning())
|
|
||||||
{
|
{
|
||||||
Logger.PrintColor("已经有一个监听程序在运行,按任意键退出...");
|
Console.WriteLine("另一个实例已在运行。");
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetTitle("抖音弹幕监听推送");
|
SetTitle("抖音弹幕监听推送");
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -39,7 +36,7 @@ namespace BarrageGrab
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError(ex, "程序初始化错误");
|
Logger.LogError(ex, $"程序初始化错误,{ex.Message}");
|
||||||
MessageBox.Show(ex.Message, "程序初始化错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
MessageBox.Show(ex.Message, "程序初始化错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
exited = true;
|
exited = true;
|
||||||
}
|
}
|
||||||
@@ -56,12 +53,12 @@ namespace BarrageGrab
|
|||||||
|
|
||||||
Logger.PrintColor("服务器已关闭...");
|
Logger.PrintColor("服务器已关闭...");
|
||||||
WinApi.SetConsoleCtrlHandler(controlCtr, false);//反注册捕获控制台关闭
|
WinApi.SetConsoleCtrlHandler(controlCtr, false);//反注册捕获控制台关闭
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Init()
|
private static void Init()
|
||||||
{
|
{
|
||||||
AppRuntime.Init();
|
AppRuntime.Init();
|
||||||
|
LiveCompanHelper.SwitchSetup();
|
||||||
WinApi.SetConsoleCtrlHandler(controlCtr, true);//捕获控制台关闭
|
WinApi.SetConsoleCtrlHandler(controlCtr, true);//捕获控制台关闭
|
||||||
WinApi.DisableQuickEditMode();//禁用控制台快速编辑模式
|
WinApi.DisableQuickEditMode();//禁用控制台快速编辑模式
|
||||||
AppRuntime.DisplayConsole(!AppSetting.Current.HideConsole);//控制控制台可见
|
AppRuntime.DisplayConsole(!AppSetting.Current.HideConsole);//控制控制台可见
|
||||||
@@ -94,8 +91,10 @@ namespace BarrageGrab
|
|||||||
}
|
}
|
||||||
|
|
||||||
AppRuntime.WsServer.StartListen();//启动WS以及代理服务
|
AppRuntime.WsServer.StartListen();//启动WS以及代理服务
|
||||||
Logger.PrintColor($"{AppRuntime.WsServer.ServerLocation} 弹幕服务已启动...",ConsoleColor.Green);
|
Logger.PrintColor($"{AppRuntime.WsServer.ServerLocation} 弹幕服务已启动,其他端可通过此地址获取到弹幕流信息", ConsoleColor.Green);
|
||||||
SetTitle($"抖音弹幕监听推送 [{AppRuntime.WsServer.ServerLocation}]");
|
|
||||||
|
Version version = System.Reflection.Assembly.GetAssembly(typeof(Program)).GetName().Version;
|
||||||
|
SetTitle($"抖音弹幕监听推送 v{version} [{AppRuntime.WsServer.ServerLocation}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
//检测设置控制台标题
|
//检测设置控制台标题
|
||||||
@@ -123,53 +122,5 @@ namespace BarrageGrab
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//检测程序是否多开
|
|
||||||
private static bool CheckAlreadyRunning()
|
|
||||||
{
|
|
||||||
const string mutexName = "DyBarrageGrab";
|
|
||||||
// Try to create a new named mutex.
|
|
||||||
bool createdNew;
|
|
||||||
using (Mutex mutex = new Mutex(true, mutexName, out createdNew))
|
|
||||||
{
|
|
||||||
return !createdNew;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if DEBUG
|
|
||||||
private static void JintTest()
|
|
||||||
{
|
|
||||||
var jsEng = JsEngine.CreateNewEngine();
|
|
||||||
var jsFile = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "Scripts", "engine", "comPortFilter.js"), Encoding.UTF8);
|
|
||||||
//var jsFile = @"D:\develop\Project\dy-barrage-grab\BarrageGrab\Scripts\engine\comPortFilter.js";
|
|
||||||
jsEng.Execute(jsFile);
|
|
||||||
var result = jsEng.Invoke("onPackData", 1, new
|
|
||||||
{
|
|
||||||
Aporp = 142,
|
|
||||||
Bprop = "48777",
|
|
||||||
Cprop = new string[] { "123" },
|
|
||||||
Dprop = new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{ "key1","value1" }
|
|
||||||
}
|
|
||||||
},null);
|
|
||||||
Console.WriteLine($"返回类型:{ result.Type.ToString()},值:{result.ToString()}");
|
|
||||||
if (result.Type == Types.String)
|
|
||||||
{
|
|
||||||
Console.WriteLine("返回String: " + result.ToString());
|
|
||||||
}
|
|
||||||
if (result.Type == Types.Object)
|
|
||||||
{
|
|
||||||
var obj = result.ToObject();
|
|
||||||
if (obj is byte[])
|
|
||||||
{
|
|
||||||
Console.WriteLine("返回byte[]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result.Type == Types.Symbol)
|
|
||||||
{
|
|
||||||
Console.WriteLine("返回Symbol: " + result.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,6 @@ using System.Runtime.InteropServices;
|
|||||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||||
//通过使用 "*",如下所示:
|
//通过使用 "*",如下所示:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("2.7.4.0")]
|
[assembly: AssemblyVersion("2.7.6.0")]
|
||||||
[assembly: AssemblyFileVersion("2.7.4.0")]
|
[assembly: AssemblyFileVersion("2.7.6.0")]
|
||||||
[assembly: NeutralResourcesLanguage("zh-CN")]
|
[assembly: NeutralResourcesLanguage("zh-CN")]
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ using Titanium.Web.Proxy.EventArguments;
|
|||||||
using Titanium.Web.Proxy.Http;
|
using Titanium.Web.Proxy.Http;
|
||||||
using Titanium.Web.Proxy.Models;
|
using Titanium.Web.Proxy.Models;
|
||||||
using Titanium.Web.Proxy.StreamExtended.Network;
|
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;
|
||||||
|
|
||||||
namespace BarrageGrab.Proxy
|
namespace BarrageGrab.Proxy
|
||||||
{
|
{
|
||||||
@@ -65,7 +72,7 @@ namespace BarrageGrab.Proxy
|
|||||||
Logger.LogWarn("代理环境设置失败:" + ex.Message);
|
Logger.LogWarn("代理环境设置失败:" + ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TitaniumProxy()
|
public TitaniumProxy()
|
||||||
{
|
{
|
||||||
//注册系统代理
|
//注册系统代理
|
||||||
@@ -75,9 +82,10 @@ namespace BarrageGrab.Proxy
|
|||||||
proxyServer.ReuseSocket = false;
|
proxyServer.ReuseSocket = false;
|
||||||
proxyServer.EnableConnectionPool = true;
|
proxyServer.EnableConnectionPool = true;
|
||||||
proxyServer.ForwardToUpstreamGateway = true;
|
proxyServer.ForwardToUpstreamGateway = true;
|
||||||
proxyServer.CertificateManager.SaveFakeCertificates = true;
|
|
||||||
|
|
||||||
proxyServer.CertificateManager.RootCertificate = proxyServer.CertificateManager.LoadRootCertificate();
|
proxyServer.CertificateManager.CertificateValidDays = 365 * 10;
|
||||||
|
proxyServer.CertificateManager.SaveFakeCertificates = true;
|
||||||
|
proxyServer.CertificateManager.RootCertificate = GetCert();
|
||||||
if (proxyServer.CertificateManager.RootCertificate == null)
|
if (proxyServer.CertificateManager.RootCertificate == null)
|
||||||
{
|
{
|
||||||
Logger.PrintColor("正在进行证书安装,需要信任该证书才可进行https解密,若有提示请确定");
|
Logger.PrintColor("正在进行证书安装,需要信任该证书才可进行https解密,若有提示请确定");
|
||||||
@@ -97,6 +105,64 @@ namespace BarrageGrab.Proxy
|
|||||||
proxyServer.AddEndPoint(explicitEndPoint);
|
proxyServer.AddEndPoint(explicitEndPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private X509Certificate2 GetCert()
|
||||||
|
{
|
||||||
|
X509Certificate2 result = proxyServer.CertificateManager.LoadRootCertificate();
|
||||||
|
|
||||||
|
if (result != null) return result;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// 打开“受信任的根证书颁发机构”存储区
|
||||||
|
using (X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
|
||||||
|
{
|
||||||
|
store.Open(OpenFlags.ReadOnly);
|
||||||
|
|
||||||
|
// 遍历证书集合
|
||||||
|
foreach (X509Certificate2 cert in store.Certificates)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 尝试使用证书创建 X509Certificate2 实例
|
||||||
|
X509Certificate2 certificate = new X509Certificate2(cert);
|
||||||
|
|
||||||
|
//判断过期
|
||||||
|
if (DateTime.Now > certificate.NotAfter) continue;
|
||||||
|
|
||||||
|
//判断黑名单
|
||||||
|
var black = new string[] { "localhost" };
|
||||||
|
if (certificate.FriendlyName.ToLower().LikeIn(black) ||
|
||||||
|
certificate.Subject.ToLower().LikeIn(black)
|
||||||
|
) continue;
|
||||||
|
|
||||||
|
|
||||||
|
if (certificate.FriendlyName.ToLower().LikeIn("titanium"))
|
||||||
|
{
|
||||||
|
result = certificate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印证书信息
|
||||||
|
//Console.WriteLine("证书: " + certificate.Subject);
|
||||||
|
//Console.WriteLine("颁发者: " + certificate.Issuer);
|
||||||
|
//Console.WriteLine("有效期: " + certificate.NotBefore + " - " + certificate.NotAfter);
|
||||||
|
|
||||||
|
//result = certificate;
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
catch (CryptographicException ex)
|
||||||
|
{
|
||||||
|
//捕获加密异常,如果证书需要密码,这里会抛出异常
|
||||||
|
throw new Exception("证书加载失败: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
store.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetUpstreamProxy(string upstreamProxyAddr)
|
public override void SetUpstreamProxy(string upstreamProxyAddr)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(upstreamProxyAddr)) return;
|
if (string.IsNullOrWhiteSpace(upstreamProxyAddr)) return;
|
||||||
@@ -121,6 +187,11 @@ namespace BarrageGrab.Proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckBrowser(string processName)
|
||||||
|
{
|
||||||
|
return AppSetting.Current.ProcessFilter.Contains(processName) && processName!="直播伴侣" && processName!= "douyin";
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e)
|
private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e)
|
||||||
{
|
{
|
||||||
string uri = e.HttpClient.Request.RequestUri.ToString();
|
string uri = e.HttpClient.Request.RequestUri.ToString();
|
||||||
@@ -208,7 +279,7 @@ namespace BarrageGrab.Proxy
|
|||||||
if (uri.Contains(BARRAGE_POOL_PATH) && contentType.Contains("application/protobuffer"))
|
if (uri.Contains(BARRAGE_POOL_PATH) && contentType.Contains("application/protobuffer"))
|
||||||
{
|
{
|
||||||
var payload = await e.GetResponseBody();
|
var payload = await e.GetResponseBody();
|
||||||
|
|
||||||
base.FireOnFetchResponse(new HttpResponseEventArgs()
|
base.FireOnFetchResponse(new HttpResponseEventArgs()
|
||||||
{
|
{
|
||||||
HttpClient = e.HttpClient,
|
HttpClient = e.HttpClient,
|
||||||
@@ -274,7 +345,7 @@ namespace BarrageGrab.Proxy
|
|||||||
});
|
});
|
||||||
liveRoomInjectScript = scriptContext + liveRoomInjectScript;
|
liveRoomInjectScript = scriptContext + liveRoomInjectScript;
|
||||||
var html = await e.GetResponseBodyAsString();
|
var html = await e.GetResponseBodyAsString();
|
||||||
var doc = new HtmlAgilityPack.HtmlDocument();
|
var doc = new HtmlDocument();
|
||||||
doc.LoadHtml(html);
|
doc.LoadHtml(html);
|
||||||
|
|
||||||
if (!liveRoomInjectScript.IsNullOrWhiteSpace())
|
if (!liveRoomInjectScript.IsNullOrWhiteSpace())
|
||||||
@@ -311,7 +382,6 @@ namespace BarrageGrab.Proxy
|
|||||||
AppRuntime.RoomCaches.AddRoomInfoCache(roominfo);
|
AppRuntime.RoomCaches.AddRoomInfoCache(roominfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -335,27 +405,11 @@ namespace BarrageGrab.Proxy
|
|||||||
//给script标签 src加上时间戳避免缓存
|
//给script标签 src加上时间戳避免缓存
|
||||||
if (AppSetting.Current.DisableLivePageScriptCache)
|
if (AppSetting.Current.DisableLivePageScriptCache)
|
||||||
{
|
{
|
||||||
var scripts = doc.DocumentNode.SelectNodes("//script[@src]");
|
ScriptAddTocks(doc);
|
||||||
if (scripts != null)
|
|
||||||
{
|
|
||||||
var ticks = DateTime.Now.Ticks;
|
|
||||||
foreach (var script in scripts)
|
|
||||||
{
|
|
||||||
var src = script.Attributes["src"].Value;
|
|
||||||
if (src.Contains("?"))
|
|
||||||
{
|
|
||||||
src += "&_t=" + ticks;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
src += "?_t=" + ticks;
|
|
||||||
}
|
|
||||||
script.Attributes["src"].Value = src;
|
|
||||||
}
|
|
||||||
html = doc.DocumentNode.OuterHtml;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html = doc.DocumentNode.OuterHtml;
|
||||||
|
|
||||||
e.SetResponseBodyString(html);
|
e.SetResponseBodyString(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,6 +449,38 @@ namespace BarrageGrab.Proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//给部分脚本加上时间戳避免缓存
|
||||||
|
private void ScriptAddTocks(HtmlDocument doc)
|
||||||
|
{
|
||||||
|
var scripts = doc.DocumentNode.SelectNodes("//script[@src]");
|
||||||
|
if (scripts != null)
|
||||||
|
{
|
||||||
|
var ticks = DateTime.Now.Ticks;
|
||||||
|
foreach (var script in scripts)
|
||||||
|
{
|
||||||
|
var src = script.Attributes["src"].Value;
|
||||||
|
|
||||||
|
var srcUri = new Uri(src);
|
||||||
|
if (!CheckHost(srcUri.Host)) continue;
|
||||||
|
|
||||||
|
var fileName = Path.GetFileName(src.Split('?')[0]);
|
||||||
|
//目前只需要用到相关这些js
|
||||||
|
if (!fileName.StartsWith("island") && !src.Contains(LIVE_SCRIPT_PATH)) continue;
|
||||||
|
|
||||||
|
if (src.Contains("?"))
|
||||||
|
{
|
||||||
|
src += "&_t=" + ticks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src += "?_t=" + ticks;
|
||||||
|
}
|
||||||
|
script.Attributes["src"].Value = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//生成注入上下文
|
//生成注入上下文
|
||||||
private string BuildContext(IDictionary<string, string> constVals)
|
private string BuildContext(IDictionary<string, string> constVals)
|
||||||
{
|
{
|
||||||
@@ -415,6 +501,7 @@ namespace BarrageGrab.Proxy
|
|||||||
var processid = e.HttpClient.ProcessId.Value;
|
var processid = e.HttpClient.ProcessId.Value;
|
||||||
var processName = base.GetProcessName(processid);
|
var processName = base.GetProcessName(processid);
|
||||||
var contentType = e.HttpClient.Response.ContentType ?? "";
|
var contentType = e.HttpClient.Response.ContentType ?? "";
|
||||||
|
var fileName = Path.GetFileName(urlNoQuery);
|
||||||
|
|
||||||
if (contentType == null) return;
|
if (contentType == null) return;
|
||||||
if (!contentType.Trim().ToLower().Contains("application/javascript")) return;
|
if (!contentType.Trim().ToLower().Contains("application/javascript")) return;
|
||||||
@@ -424,19 +511,17 @@ namespace BarrageGrab.Proxy
|
|||||||
if (hostname == SCRIPT_HOST
|
if (hostname == SCRIPT_HOST
|
||||||
//这俩个进程不需要注入
|
//这俩个进程不需要注入
|
||||||
&& processName != "直播伴侣" && processName != "douyin"
|
&& processName != "直播伴侣" && processName != "douyin"
|
||||||
|
&& fileName.StartsWith("island")
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var js = await e.GetResponseBodyAsString();
|
var js = await e.GetResponseBodyAsString();
|
||||||
//var reg2 = new Regex(@"if\(!N.DJ\(\)&&(?<variable>\S).current\)\{"); //版本1,已过时
|
var reg2 = new Regex(@"if\(!\((?<v1>\d,\w{1,2})\.DJ\)\(\)&&");
|
||||||
//if(!(0,k.DJ)()&&_.current){
|
|
||||||
|
|
||||||
var reg2 = new Regex(@"if\s*\(\s*\!\s*(?<v1>[\s\S]+\s*\.\s*DJ\s*\))\s*\(\s*\)\s*&\s*&\s*(?<v2>\S)\s*.\s*current\s*\)\s*\{");
|
|
||||||
var match = reg2.Match(js);
|
var match = reg2.Match(js);
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
js = reg2.Replace(js, "if(!${v1}()&&${v2}.current){return;");
|
js = reg2.Replace(js, "if(false &&");
|
||||||
e.SetResponseBodyString(js);
|
e.SetResponseBodyString(js);
|
||||||
Logger.PrintColor($"已成功绕过JS页面无操作检测 {urlNoQuery}\n", ConsoleColor.Green);
|
Logger.PrintColor($"已成功绕过页面无操作检测\n", ConsoleColor.Green);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,6 +564,12 @@ namespace BarrageGrab.Proxy
|
|||||||
string url = e.HttpClient.Request.RequestUri.ToString();
|
string url = e.HttpClient.Request.RequestUri.ToString();
|
||||||
string hostname = e.HttpClient.Request.RequestUri.Host;
|
string hostname = e.HttpClient.Request.RequestUri.Host;
|
||||||
|
|
||||||
|
e.DecryptSsl = CheckHost(hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
//检测域名白名单
|
||||||
|
protected override bool CheckHost(string hostname)
|
||||||
|
{
|
||||||
//需要解析SSL的域名 放在这里,全开会导致性能问题,应只解析业务需要的域名
|
//需要解析SSL的域名 放在这里,全开会导致性能问题,应只解析业务需要的域名
|
||||||
var decryptSsls = new string[]
|
var decryptSsls = new string[]
|
||||||
{
|
{
|
||||||
@@ -489,24 +580,11 @@ namespace BarrageGrab.Proxy
|
|||||||
|
|
||||||
if (decryptSsls.Contains(hostname))
|
if (decryptSsls.Contains(hostname))
|
||||||
{
|
{
|
||||||
e.DecryptSsl = true;
|
return true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!CheckHost(hostname))
|
|
||||||
{
|
|
||||||
e.DecryptSsl = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//检测域名白名单
|
hostname = hostname.Trim().ToLower();
|
||||||
protected override bool CheckHost(string host)
|
return base.CheckHost(hostname);
|
||||||
{
|
|
||||||
host = host.Trim().ToLower();
|
|
||||||
var succ = base.CheckHost(host);
|
|
||||||
return succ || host == SCRIPT_HOST || host == LIVE_HOST;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//WebSocket 流读取
|
//WebSocket 流读取
|
||||||
@@ -585,14 +663,20 @@ namespace BarrageGrab.Proxy
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
override public void Start()
|
override public void Start()
|
||||||
{
|
{
|
||||||
proxyServer.Start(AppSetting.Current.UsedProxy);
|
proxyServer.Start(false);
|
||||||
|
|
||||||
if (AppSetting.Current.UsedProxy)
|
if (AppSetting.Current.UsedProxy)
|
||||||
{
|
{
|
||||||
base.RegisterSystemProxy();
|
base.RegisterSystemProxy();
|
||||||
|
Logger.LogInfo($"系统代理代理已启动,127.0.0.1:{base.ProxyPort}");
|
||||||
//使用其自带的系统代理设置可能会导致格式问题
|
//使用其自带的系统代理设置可能会导致格式问题
|
||||||
//proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
|
//proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
|
||||||
//proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
|
//proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.LogInfo($"代理已启动(局域代理),127.0.0.1:{base.ProxyPort}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ namespace BarrageGrab
|
|||||||
private void PrintMsg(Msg msg, PackMsgType barType)
|
private void PrintMsg(Msg msg, PackMsgType barType)
|
||||||
{
|
{
|
||||||
var rinfo = AppRuntime.RoomCaches.GetCachedWebRoomInfo(msg.RoomId.ToString());
|
var rinfo = AppRuntime.RoomCaches.GetCachedWebRoomInfo(msg.RoomId.ToString());
|
||||||
var roomName = (rinfo?.Owner?.Nickname ?? ("直播间" + (msg.WebRoomId.IsNullOrWhiteSpace() ? msg.RoomId.ToString() : msg.WebRoomId)));
|
var roomName = (rinfo?.Owner?.Nickname ?? ((msg.WebRoomId.IsNullOrWhiteSpace() ? msg.RoomId.ToString() : msg.WebRoomId)));
|
||||||
var text = $"{DateTime.Now.ToString("HH:mm:ss")} [{roomName}] [{barType}]";
|
var text = $"{DateTime.Now.ToString("HH:mm:ss")} [{roomName}] [{barType}]";
|
||||||
|
|
||||||
if (msg.User != null)
|
if (msg.User != null)
|
||||||
@@ -347,48 +347,41 @@ namespace BarrageGrab
|
|||||||
ogift.Name = findForData.name;
|
ogift.Name = findForData.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//判断礼物重复
|
||||||
|
if (msg.repeatEnd == 1 && giftCountCache.ContainsKey(key))
|
||||||
//Combo 为1时,表示为可连击礼物
|
|
||||||
//if (msg.Gift.Combo) //一堆礼物Combo 和实际可连击情况不匹配,例如亲吻,闪耀星辰 Combo =false,实际上是可连击的,抖音那帮程序员怕是看女主播冲昏头了
|
|
||||||
if (true)
|
|
||||||
{
|
{
|
||||||
//判断礼物重复
|
//清除缓存中的key
|
||||||
if (msg.repeatEnd == 1)
|
if (msg.groupId > 0 )
|
||||||
{
|
{
|
||||||
//清除缓存中的key
|
Tuple<int, DateTime> _;
|
||||||
if (msg.groupId > 0 && giftCountCache.ContainsKey(key))
|
giftCountCache.TryRemove(key, out _);
|
||||||
{
|
|
||||||
Tuple<int, DateTime> _;
|
|
||||||
giftCountCache.TryRemove(key, out _);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var backward = currCount <= lastCount;
|
return;
|
||||||
if (currCount <= 0) currCount = 1;
|
|
||||||
|
|
||||||
if (giftCountCache.ContainsKey(key))
|
|
||||||
{
|
|
||||||
lastCount = giftCountCache[key].Item1;
|
|
||||||
backward = currCount <= lastCount;
|
|
||||||
if (!backward)
|
|
||||||
{
|
|
||||||
lock (giftCountCache)
|
|
||||||
{
|
|
||||||
giftCountCache[key] = Tuple.Create(currCount, DateTime.Now);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (msg.groupId > 0 && !backward)
|
|
||||||
{
|
|
||||||
giftCountCache.TryAdd(key, Tuple.Create(currCount, DateTime.Now));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//比上次小,则说明先后顺序出了问题,直接丢掉,应为比它大的消息已经处理过了
|
|
||||||
if (backward) return;
|
|
||||||
}
|
}
|
||||||
|
var backward = currCount <= lastCount;
|
||||||
|
if (currCount <= 0) currCount = 1;
|
||||||
|
|
||||||
|
if (giftCountCache.ContainsKey(key))
|
||||||
|
{
|
||||||
|
lastCount = giftCountCache[key].Item1;
|
||||||
|
backward = currCount <= lastCount;
|
||||||
|
if (!backward)
|
||||||
|
{
|
||||||
|
lock (giftCountCache)
|
||||||
|
{
|
||||||
|
giftCountCache[key] = Tuple.Create(currCount, DateTime.Now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (msg.groupId > 0 && !backward)
|
||||||
|
{
|
||||||
|
giftCountCache.TryAdd(key, Tuple.Create(currCount, DateTime.Now));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//比上次小,则说明先后顺序出了问题,直接丢掉,应为比它大的消息已经处理过了
|
||||||
|
if (backward) return;
|
||||||
|
|
||||||
var count = currCount - lastCount;
|
var count = currCount - lastCount;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>
|
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>
|
||||||
@@ -29,6 +30,8 @@
|
|||||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
<UseApplicationTrust>false</UseApplicationTrust>
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
<NuGetPackageImportStamp>
|
||||||
|
</NuGetPackageImportStamp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -70,6 +73,9 @@
|
|||||||
<Reference Include="BrotliSharpLib, Version=0.3.2.0, Culture=neutral, PublicKeyToken=3f4e2a1cd615fcb7, processorArchitecture=MSIL">
|
<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>
|
<HintPath>..\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Esprima, Version=3.0.4.0, Culture=neutral, PublicKeyToken=2e92ba9c8d81157f, processorArchitecture=MSIL">
|
<Reference Include="Esprima, Version=3.0.4.0, Culture=neutral, PublicKeyToken=2e92ba9c8d81157f, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Esprima.3.0.4\lib\net462\Esprima.dll</HintPath>
|
<HintPath>..\packages\Esprima.3.0.4\lib\net462\Esprima.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@@ -84,6 +90,9 @@
|
|||||||
<HintPath>..\packages\Jint.3.0.1\lib\net462\Jint.dll</HintPath>
|
<HintPath>..\packages\Jint.3.0.1\lib\net462\Jint.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Microsoft.Win32.Registry, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Win32.Registry, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -100,29 +109,93 @@
|
|||||||
<HintPath>..\packages\protobuf-net.Core.3.1.22\lib\net462\protobuf-net.Core.dll</HintPath>
|
<HintPath>..\packages\protobuf-net.Core.3.1.22\lib\net462\protobuf-net.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll</HintPath>
|
<HintPath>..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.ComponentModel.Composition" />
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
|
<Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Diagnostics.Tracing, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.IO.Compression" />
|
<Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
|
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
|
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Numerics" />
|
<Reference Include="System.Numerics" />
|
||||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Reflection, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Runtime.Extensions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Runtime.Extensions.4.3.0\lib\net462\System.Runtime.Extensions.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Runtime.InteropServices, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Runtime.InteropServices.4.3.0\lib\net462\System.Runtime.InteropServices.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Security.AccessControl, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Security.AccessControl, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll</HintPath>
|
<HintPath>..\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
|
<HintPath>..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -135,8 +208,10 @@
|
|||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
<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>
|
||||||
<Reference Include="Titanium.Web.Proxy, Version=1.0.1.0, Culture=neutral, PublicKeyToken=8e41e1f1c790d7cf, processorArchitecture=MSIL">
|
<Reference Include="Titanium.Web.Proxy, Version=1.0.1.0, Culture=neutral, PublicKeyToken=8e41e1f1c790d7cf, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Titanium.Web.Proxy.3.2.2-beta\lib\net461\Titanium.Web.Proxy.dll</HintPath>
|
<HintPath>..\packages\Titanium.Web.Proxy.3.2.2-beta\lib\net461\Titanium.Web.Proxy.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -160,6 +235,7 @@
|
|||||||
<DependentUpon>RoomDetail.cs</DependentUpon>
|
<DependentUpon>RoomDetail.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="JsEngine.cs" />
|
<Compile Include="JsEngine.cs" />
|
||||||
|
<Compile Include="LiveCompanHelper.cs" />
|
||||||
<Compile Include="Logger.cs" />
|
<Compile Include="Logger.cs" />
|
||||||
<Compile Include="Modles\BusinessExecption.cs" />
|
<Compile Include="Modles\BusinessExecption.cs" />
|
||||||
<Compile Include="Modles\JsonEntity\BarrageMessages.cs" />
|
<Compile Include="Modles\JsonEntity\BarrageMessages.cs" />
|
||||||
@@ -194,6 +270,7 @@
|
|||||||
<None Include="Properties\app.manifest" />
|
<None Include="Properties\app.manifest" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Content Include="FodyWeavers.xml" />
|
||||||
<Content Include="Scripts\engine\comPortFilter.js">
|
<Content Include="Scripts\engine\comPortFilter.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
@@ -221,6 +298,26 @@
|
|||||||
<DependentUpon>RoomDetail.cs</DependentUpon>
|
<DependentUpon>RoomDetail.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<COMReference Include="IWshRuntimeLibrary">
|
||||||
|
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
|
||||||
|
<VersionMajor>1</VersionMajor>
|
||||||
|
<VersionMinor>0</VersionMinor>
|
||||||
|
<Lcid>0</Lcid>
|
||||||
|
<WrapperTool>tlbimp</WrapperTool>
|
||||||
|
<Isolated>False</Isolated>
|
||||||
|
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||||
|
</COMReference>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Fody.6.8.2\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.8.2\build\Fody.targets'))" />
|
||||||
|
</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')" />
|
||||||
</Project>
|
</Project>
|
||||||
@@ -2,23 +2,71 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="BouncyCastle.Cryptography" version="2.0.0" targetFramework="net48" />
|
<package id="BouncyCastle.Cryptography" version="2.0.0" targetFramework="net48" />
|
||||||
<package id="BrotliSharpLib" version="0.3.3" targetFramework="net48" />
|
<package id="BrotliSharpLib" version="0.3.3" targetFramework="net48" />
|
||||||
|
<package id="Costura.Fody" version="5.7.0" targetFramework="net462" developmentDependency="true" />
|
||||||
<package id="Esprima" version="3.0.4" targetFramework="net462" />
|
<package id="Esprima" version="3.0.4" targetFramework="net462" />
|
||||||
<package id="Fleck" version="1.2.0" targetFramework="net48" />
|
<package id="Fleck" version="1.2.0" targetFramework="net48" />
|
||||||
|
<package id="Fody" version="6.8.2" targetFramework="net462" developmentDependency="true" />
|
||||||
<package id="HtmlAgilityPack" version="1.11.51" targetFramework="net48" />
|
<package id="HtmlAgilityPack" version="1.11.51" targetFramework="net48" />
|
||||||
<package id="Jint" version="3.0.1" targetFramework="net462" />
|
<package id="Jint" version="3.0.1" targetFramework="net462" />
|
||||||
|
<package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net462" />
|
||||||
|
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="Microsoft.Win32.Registry" version="5.0.0" targetFramework="net48" />
|
<package id="Microsoft.Win32.Registry" version="5.0.0" targetFramework="net48" />
|
||||||
|
<package id="NETStandard.Library" version="1.6.1" targetFramework="net462" />
|
||||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
|
||||||
<package id="NLog" version="5.2.3" targetFramework="net48" />
|
<package id="NLog" version="5.2.3" targetFramework="net48" />
|
||||||
<package id="Portable.BouncyCastle" version="1.8.8" targetFramework="net48" />
|
<package id="Portable.BouncyCastle" version="1.8.8" targetFramework="net48" />
|
||||||
<package id="protobuf-net" version="3.1.22" targetFramework="net48" />
|
<package id="protobuf-net" version="3.1.22" targetFramework="net48" />
|
||||||
<package id="protobuf-net.Core" version="3.1.22" targetFramework="net48" />
|
<package id="protobuf-net.Core" version="3.1.22" targetFramework="net48" />
|
||||||
|
<package id="System.AppContext" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
|
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
|
||||||
|
<package id="System.Collections" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Collections.Immutable" version="1.7.1" targetFramework="net48" />
|
<package id="System.Collections.Immutable" version="1.7.1" targetFramework="net48" />
|
||||||
|
<package id="System.Console" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Diagnostics.DiagnosticSource" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Globalization" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.IO" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.IO.Compression" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Linq" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
|
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
|
||||||
|
<package id="System.Net.Http" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Net.Primitives" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
|
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
|
||||||
|
<package id="System.ObjectModel" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Reflection" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Runtime" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net48" />
|
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net48" />
|
||||||
|
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Runtime.Handles" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Security.AccessControl" version="5.0.0" targetFramework="net48" />
|
<package id="System.Security.AccessControl" version="5.0.0" targetFramework="net48" />
|
||||||
|
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net48" />
|
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net48" />
|
||||||
|
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Threading" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
|
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
|
||||||
|
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net462" />
|
||||||
|
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net462" />
|
||||||
<package id="Titanium.Web.Proxy" version="3.2.2-beta" targetFramework="net48" />
|
<package id="Titanium.Web.Proxy" version="3.2.2-beta" targetFramework="net48" />
|
||||||
</packages>
|
</packages>
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
# ruff: noqa: F401,F403,F405,E402,F541,E722
|
||||||
|
import asyncio
|
||||||
|
import websockets
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import ctypes
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import winreg
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
import customtkinter
|
||||||
|
import subprocess
|
||||||
|
import random
|
||||||
|
import threading
|
||||||
|
import atexit
|
||||||
|
import psutil
|
||||||
|
import queue
|
||||||
|
|
||||||
|
# 创建一个队列
|
||||||
|
gui_queue = queue.Queue()
|
||||||
|
|
||||||
|
# 创建一个线程安全的标志
|
||||||
|
stop_flag = threading.Event()
|
||||||
|
|
||||||
|
|
||||||
|
def is_admin():
|
||||||
|
try:
|
||||||
|
return ctypes.windll.shell32.IsUserAnAdmin()
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def disable_proxy():
|
||||||
|
internet_settings = winreg.OpenKey(
|
||||||
|
winreg.HKEY_CURRENT_USER,
|
||||||
|
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings",
|
||||||
|
0,
|
||||||
|
winreg.KEY_ALL_ACCESS,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 设置代理使能为0(禁用)
|
||||||
|
winreg.SetValueEx(internet_settings, "ProxyEnable", 0, winreg.REG_DWORD, 0)
|
||||||
|
# 清空代理服务器信息
|
||||||
|
winreg.SetValueEx(internet_settings, "ProxyServer", 0, winreg.REG_SZ, "")
|
||||||
|
|
||||||
|
winreg.CloseKey(internet_settings)
|
||||||
|
print("Proxy disabled.")
|
||||||
|
|
||||||
|
|
||||||
|
def initGame():
|
||||||
|
print("Init game.")
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class App(customtkinter.CTk):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.title("dy-barrage-grab-log-window")
|
||||||
|
self.geometry("800x600")
|
||||||
|
self.grid_columnconfigure((0, 1), weight=1)
|
||||||
|
self.grid_rowconfigure(0, weight=1)
|
||||||
|
self.LogFrame = LogFrame(self)
|
||||||
|
self.LogFrame.grid(row=0, column=0, sticky="nsew")
|
||||||
|
|
||||||
|
|
||||||
|
class LogFrame(customtkinter.CTkFrame):
|
||||||
|
def __init__(self, master):
|
||||||
|
super().__init__(master)
|
||||||
|
|
||||||
|
# 创建一个Frame来包含treeview和滚动条
|
||||||
|
self.tree_frame = ttk.Frame(self)
|
||||||
|
self.tree_frame.grid(row=0, column=0, sticky="nsew", padx=50, pady=50)
|
||||||
|
|
||||||
|
# 创建一个滚动条
|
||||||
|
self.scrollbar = customtkinter.CTkScrollbar(self.tree_frame)
|
||||||
|
self.scrollbar.grid(row=0, column=1, sticky="ns")
|
||||||
|
|
||||||
|
self.treeview = ttk.Treeview(
|
||||||
|
self.tree_frame,
|
||||||
|
columns=("Type", "User ID", "User Nickname", "Content"),
|
||||||
|
show="headings",
|
||||||
|
height=20,
|
||||||
|
yscrollcommand=self.scrollbar.set, # 将滚动条与treeview关联
|
||||||
|
)
|
||||||
|
self.treeview.grid(row=0, column=0, sticky="nsew")
|
||||||
|
|
||||||
|
# 设置滚动条的命令为移动treeview
|
||||||
|
self.scrollbar.configure(command=self.treeview.yview)
|
||||||
|
|
||||||
|
# 设置列宽
|
||||||
|
self.treeview.column("Type", width=50)
|
||||||
|
self.treeview.column("User ID", width=100)
|
||||||
|
self.treeview.column("User Nickname", width=100)
|
||||||
|
self.treeview.column("Content", width=450)
|
||||||
|
|
||||||
|
self.treeview.heading("Type", text="Type")
|
||||||
|
self.treeview.heading("User ID", text="User ID")
|
||||||
|
self.treeview.heading("User Nickname", text="User Nickname")
|
||||||
|
self.treeview.heading("Content", text="Content")
|
||||||
|
|
||||||
|
# 设置不同类型的颜色
|
||||||
|
self.treeview.tag_configure("type1", foreground="black")
|
||||||
|
self.treeview.tag_configure("type2", foreground="cyan")
|
||||||
|
self.treeview.tag_configure("type3", foreground="gold")
|
||||||
|
self.treeview.tag_configure("type4", foreground="blue")
|
||||||
|
self.treeview.tag_configure("type5", foreground="red")
|
||||||
|
self.treeview.tag_configure("type6", foreground="purple")
|
||||||
|
self.treeview.tag_configure("type7", foreground="green")
|
||||||
|
self.treeview.tag_configure("type8", foreground="orange")
|
||||||
|
self.treeview.tag_configure("type9", foreground="gray")
|
||||||
|
# 添加更多类型的颜色配置...
|
||||||
|
|
||||||
|
def display_message(self, message):
|
||||||
|
parsed_message = json.loads(message)
|
||||||
|
message_type = parsed_message.get("Type")
|
||||||
|
|
||||||
|
data_str = parsed_message.get("Data", "{}")
|
||||||
|
try:
|
||||||
|
data = json.loads(data_str)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(f"Cannot parse 'Data' as JSON: {data_str}")
|
||||||
|
return
|
||||||
|
user = data.get("User", {})
|
||||||
|
if user is None:
|
||||||
|
# print(f"'User' is None in 'Data': {data_str}")
|
||||||
|
user = {"Id": "无", "Nickname": "无"}
|
||||||
|
user_id = user.get("Id", "")
|
||||||
|
user_nickname = user.get("Nickname", "")
|
||||||
|
content = data.get("Content", "")
|
||||||
|
# 根据类型设置颜色
|
||||||
|
color_tag = f"type{message_type}"
|
||||||
|
message_type_str = [
|
||||||
|
"无",
|
||||||
|
"弹幕",
|
||||||
|
"点赞",
|
||||||
|
"进房",
|
||||||
|
"关注",
|
||||||
|
"礼物",
|
||||||
|
"统计",
|
||||||
|
"粉团",
|
||||||
|
"分享",
|
||||||
|
"下播",
|
||||||
|
]
|
||||||
|
self.treeview.insert(
|
||||||
|
"",
|
||||||
|
"end",
|
||||||
|
values=(
|
||||||
|
message_type_str[message_type],
|
||||||
|
user_id,
|
||||||
|
user_nickname,
|
||||||
|
content,
|
||||||
|
),
|
||||||
|
tags=(color_tag,),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# async def send_ping(websocket):
|
||||||
|
# while True:
|
||||||
|
# try:
|
||||||
|
# if websocket.open:
|
||||||
|
# await websocket.ping()
|
||||||
|
# await asyncio.sleep(5)
|
||||||
|
# else:
|
||||||
|
# break
|
||||||
|
# except websockets.exceptions.ConnectionClosedOK:
|
||||||
|
# # 连接已关闭,尝试重新连接
|
||||||
|
# websocket = await websockets.connect("ws://127.0.0.1:8888")
|
||||||
|
|
||||||
|
|
||||||
|
async def receive_messages():
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
async with websockets.connect(
|
||||||
|
"ws://127.0.0.1:8888", ping_timeout=None, ping_interval=None
|
||||||
|
) as websocket:
|
||||||
|
while True:
|
||||||
|
message = await websocket.recv()
|
||||||
|
if message is not None:
|
||||||
|
try:
|
||||||
|
json.loads(message)
|
||||||
|
app.LogFrame.display_message(message)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(
|
||||||
|
f"Received a message that could not be parsed as JSON: {message}"
|
||||||
|
)
|
||||||
|
except (
|
||||||
|
websockets.ConnectionClosed,
|
||||||
|
websockets.exceptions.ConnectionClosedError,
|
||||||
|
websockets.exceptions.ConnectionClosedOK,
|
||||||
|
) as e:
|
||||||
|
print(f"Connection closed, retrying...{e}")
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred on ws server: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global listener_process
|
||||||
|
global app
|
||||||
|
# Check if the process is already running
|
||||||
|
for proc in psutil.process_iter():
|
||||||
|
if proc.name() == "WssBarrageServer.exe":
|
||||||
|
print("The process is already running.")
|
||||||
|
proc.kill()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Start a new process
|
||||||
|
# 将WssBarrageServer.exe放至同目录下dy-barrage-grab文件夹
|
||||||
|
# 获取当前脚本的绝对路径
|
||||||
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
# 构建WssBarrageServer.exe的绝对路径
|
||||||
|
exe_path = os.path.join(script_dir, "dy-barrage-grab", "WssBarrageServer.exe")
|
||||||
|
|
||||||
|
# 使用绝对路径启动进程
|
||||||
|
listener_process = subprocess.Popen(exe_path)
|
||||||
|
# 创建一个新的事件循环
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
# 设置这个事件循环为当前线程的事件循环
|
||||||
|
asyncio.set_event_loop(loop)
|
||||||
|
app = App()
|
||||||
|
|
||||||
|
# 点击关闭按钮时调用的函数
|
||||||
|
def on_close():
|
||||||
|
print("Closing...")
|
||||||
|
# 设置停止标志
|
||||||
|
stop_flag.set()
|
||||||
|
# 关闭WssBarrageServer
|
||||||
|
listener_process.terminate()
|
||||||
|
# 关闭代理
|
||||||
|
disable_proxy()
|
||||||
|
# 退出程序
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
|
# 设置关闭按钮的回调函数
|
||||||
|
app.protocol("WM_DELETE_WINDOW", on_close)
|
||||||
|
# 在事件循环中创建新的异步任务
|
||||||
|
loop.create_task(receive_messages())
|
||||||
|
|
||||||
|
def update():
|
||||||
|
# 更新Tkinter的界面
|
||||||
|
app.update()
|
||||||
|
# 在事件循环中定期调用update方法
|
||||||
|
loop.call_soon(update)
|
||||||
|
|
||||||
|
# 检查队列中是否有任务
|
||||||
|
while not gui_queue.empty():
|
||||||
|
# 获取任务并执行
|
||||||
|
task = gui_queue.get()
|
||||||
|
task()
|
||||||
|
|
||||||
|
# 在事件循环中定期调用update方法
|
||||||
|
loop.call_soon(update)
|
||||||
|
try:
|
||||||
|
# 运行事件循环
|
||||||
|
loop.run_forever()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred in loop: {e}")
|
||||||
|
finally:
|
||||||
|
# 关闭事件循环
|
||||||
|
loop.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if is_admin():
|
||||||
|
# 如果已经是管理员权限,那么直接运行你的代码
|
||||||
|
print("Running as administrator.")
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# 如果不是管理员权限,那么以管理员权限重新启动程序
|
||||||
|
print("Running as non-administrator.")
|
||||||
|
ctypes.windll.shell32.ShellExecuteW(
|
||||||
|
None, "runas", sys.executable, " ".join(sys.argv), None, 1
|
||||||
|
)
|
||||||
|
# try:
|
||||||
|
main()
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"An error occurred: {e}")
|
||||||
|
# finally:
|
||||||
|
# # 这里结束进程
|
||||||
|
# listener_process.terminate()
|
||||||
|
|
||||||
|
|
||||||
|
# 注册一个函数,在程序结束时调用
|
||||||
|
def on_exit():
|
||||||
|
listener_process.terminate()
|
||||||
|
|
||||||
|
|
||||||
|
atexit.register(on_exit)
|
||||||
@@ -1,20 +1,30 @@
|
|||||||
# 📺 抖音弹幕监听器
|
<p style="text-align:center;font-size:3rem">📺 抖音弹幕监听器</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<p style="text-align:center">- 小白不圆 -</p>
|
||||||
|
|
||||||
## 🔉前文提要
|
## 🔉前文提要
|
||||||
|
|
||||||
+ Github(受网络影响,更新很可能不及时)大佬请移步 [Gitee](https://gitee.com/haodong108/dy-barrage-grab) ,参与Issues讨论,QQ技术讨论群:<br>
|
+ Github(受网络影响,更新很可能不及时)大佬请移步 [Gitee](https://gitee.com/haodong108/dy-barrage-grab) ,参与Issues讨论,QQ技术讨论群:<br>
|
||||||
+ 群1: 819927029 (已满)
|
+ 群1: 819927029
|
||||||
+ 群2: 789875441 (新建)
|
+ 群2: 789875441 (新建)
|
||||||
+ 注: (进群前请先⭐**Star**,并填入答案,用于排除行外人员,特殊原因请私聊我),之前因满员踢掉的群员可申请群2。
|
+ 注: (进群前请先⭐**Star**,并填入答案,用于排除行外人员,特殊原因请私聊我),之前因满员踢掉的群员可申请群2。
|
||||||
+ <span style="font-size:10px">开不起千人群😅</span>
|
|
||||||
+ 发行版下载地址在[这里](https://gitee.com/haodong108/dy-barrage-grab/releases),别下成源码包了!!,**决定下载使用前请先仔细阅读文档**,不要进群提问已经介绍到的问题
|
+ 发行版下载地址在[这里](https://gitee.com/haodong108/dy-barrage-grab/releases),别下成源码包了!!,**决定下载使用前请先仔细阅读文档**,不要进群提问已经介绍到的问题
|
||||||
+ 💭 需要**多直播间超长稳定连接**、**自动私信**(支持群组,单发,支持多账号切换),**私信监听**、**自动关注**、**关注,粉丝群,作品点赞,评论监听**、**直播间发弹幕**、**获取榜单**、**直播间,用户主页信息**、**采集商品上架,连麦,PK等其他所有消息**、**作品评论(支持图片)**、 等功能的可以找我(QQ 1083092844)提供一些技术支持 (注:主要面向个人直播自动化,不面向恶意j流,不支持匿名直播间,想搞采集匿名的勿扰,加群也不会有人支持)
|
+ 💭 需要抖音日常操作协议化,包括**多直播间超长稳定连接**、**自动私信**(支持群组,单发,支持多账号切换),**私信监听、自动关注、粉丝群、作品点赞评论及监听、直播间发弹幕、获取直播间榜单、直播间更多消息事件、作品评论(支持图片)、发布作品** 等等功能的可以找我(Q1083092844)提供一些技术支持 (注:主要面向个人直播自动化,不面向恶意j流、水jun等,不支持匿名直播间,想搞他人直播间匿名采集的勿扰,加群也不会有人支持)
|
||||||
+ **LiveIdea** 支持dou音Web全自动化的本地WebApi服务。直播、引留解放双手,需要了解详情请加我
|
+ 支持接单、定制等,dy相关优先,其他方面也可以找我帮忙转发定制
|
||||||
+ 支持接单,个人定制,dy相关优先,其他方面也可以找我帮忙转发定制,匿名直播间需求勿扰
|
+ 如果好用,请<a href="#user-content-支持一下">捐赠</a>个仨瓜俩枣,白某谢过各位老板
|
||||||
+ 那年,我与TA不可告人的<a href="#user-content-支持一下">秘密</a>😏
|
|
||||||
|
|
||||||
## ⛳近期更新
|
## ⛳近期更新
|
||||||
|
|
||||||
|
2024-09-28 v2.7.6
|
||||||
|
|
||||||
|
1. **[重要更新]** 支持免系统代理监听直播伴侣,需要在配置文件关闭`useproxy`选项,配置后监听web直播间可参考<a href="#user-content-实践指南">实践指南</a>新部分
|
||||||
|
2. 修复了 挂机检测Js拦截逻辑
|
||||||
|
3. 默认关闭 禁用JS文件缓存 配置项,提高网页加载速度
|
||||||
|
4. 礼物计数相关代码有一小处调整
|
||||||
|
5. 整合了dll为单个exe文件
|
||||||
|
|
||||||
2024-05-16 v2.7.5
|
2024-05-16 v2.7.5
|
||||||
|
|
||||||
1. **[重要修复]** 修复了弹幕轮询响应解析Payload读取报错的问题
|
1. **[重要修复]** 修复了弹幕轮询响应解析Payload读取报错的问题
|
||||||
@@ -55,23 +65,6 @@
|
|||||||
3. 支持了控制台隐藏,推送器弹幕类型过滤,日志弹幕类型过滤,弹幕文件日志 (见<a href="#tag1">配置文件</a>)
|
3. 支持了控制台隐藏,推送器弹幕类型过滤,日志弹幕类型过滤,弹幕文件日志 (见<a href="#tag1">配置文件</a>)
|
||||||
4. 支持了更多的ws命令,见 [Command.cs](./BarrageGrab/Modles/JsonEntity/Command.cs)
|
4. 支持了更多的ws命令,见 [Command.cs](./BarrageGrab/Modles/JsonEntity/Command.cs)
|
||||||
|
|
||||||
2023-11-04 v2.6.9
|
|
||||||
|
|
||||||
1. 修复了因抖音版本升级导致的WebRoomId获取不到的问题,并做了多重处理
|
|
||||||
|
|
||||||
2023-09-24 v2.6.8
|
|
||||||
|
|
||||||
1. 添加了上游代理支持,现在可以将无关的请求转发到其他的代理地址!详见下方配置说明`upstreamProxy`
|
|
||||||
2. 内部添加了webRoomid 的缓存映射,只要打开直播间地址即可缓存WebRoomId和Roomid的映射关系,`WebRoomId`现已添加至ws弹幕流数据中!,需要注意直播伴侣端提取的弹幕当前不会有该字段,除非在开播后打开浏览器访问一次你的直播间
|
|
||||||
3. MsgPack 现在添加了进程名字段`ProcessName`
|
|
||||||
|
|
||||||
2023-08-17 v2.6.7
|
|
||||||
|
|
||||||
1. [重要更新] 支持浏览器/客户端 http 弹幕监听,这也会解决原先版本因网络波动使抖音客户端弹幕获取方式降级,而获取不到弹幕导致必须刷新页面重新连接的问题。
|
|
||||||
2. [重要更新] 原先的web/客户端 页面无操作检测逻辑因官方js变动而失效,本次更新修复且完善了该功能,现在会定时模拟全局按键、绕过js检测逻辑、置空Websocket.close 方法三重手段尽量避免断开连接。你也可以直接修改[直播页脚本](./BarrageGrab/Scripts/inject/livePage.js)而无需重新编译源码。
|
|
||||||
3. ws连接现在默认监听在0.0.0.0地址,可以从其他客户端连接。
|
|
||||||
4. 代理端口现在可选择不占用系统代理,便于某些用户直接使用浏览器代理获取弹幕(启动时携带参数,例如:"chrome.exe --proxy-server=127.0.0.1:8827",也可以在浏览器快捷方式-目标 引号之后附加该参数)
|
|
||||||
|
|
||||||
## 🖼️控制台截图
|
## 🖼️控制台截图
|
||||||
|
|
||||||
[](https://imgse.com/i/z9YYPU)
|
[](https://imgse.com/i/z9YYPU)
|
||||||
@@ -98,6 +91,8 @@
|
|||||||
<add key="listenAny" value="true" />
|
<add key="listenAny" value="true" />
|
||||||
<!--系统代理端口-->
|
<!--系统代理端口-->
|
||||||
<add key="proxyPort" value="8827" />
|
<add key="proxyPort" value="8827" />
|
||||||
|
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
||||||
|
<add key="usedProxy" value="true" />
|
||||||
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
<!--上游代理地址,例如开启了系统代理,但是需要将其他无关请求转发到VPN工具中,例如:127.0.0.1:11223,不要带http://-->
|
||||||
<add key="upstreamProxy" value="" />
|
<add key="upstreamProxy" value="" />
|
||||||
<!--在控制台输出弹幕-->
|
<!--在控制台输出弹幕-->
|
||||||
@@ -110,8 +105,6 @@
|
|||||||
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
<add key="logFilter" value="1,2,4,5,6,7,8" />
|
||||||
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
<!--要进行过滤的Web房间ID,多个使用','分隔,根据缓存来过滤的,直播伴侣不支持 -->
|
||||||
<add key="webRoomIds" value="940152769375" />
|
<add key="webRoomIds" value="940152769375" />
|
||||||
<!--是否启用系统代理,若设置为false 则需要在程序手动指定代理地址 -->
|
|
||||||
<add key="usedProxy" value="true" />
|
|
||||||
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
<!--开启内置的域名过滤,设置为false会解包所有https请求,cpu占用很高,建议在无法获取弹幕数据时调整 -->
|
||||||
<add key="filterHostName" value="true" />
|
<add key="filterHostName" value="true" />
|
||||||
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
<!--已知的弹幕域名列表 ','分隔 用作过滤规则中,凡是webcast开头的域名程序都会自动列入白名单-->
|
||||||
@@ -134,19 +127,20 @@
|
|||||||
<add key="comPort" value="" />
|
<add key="comPort" value="" />
|
||||||
<!--启用自定义消息过滤,启用后可去程序根目录 Scripts/engine/comPortFilter.js 调整过滤规则 -->
|
<!--启用自定义消息过滤,启用后可去程序根目录 Scripts/engine/comPortFilter.js 调整过滤规则 -->
|
||||||
<add key="useComPortFilter" value="true" />
|
<add key="useComPortFilter" value="true" />
|
||||||
|
<!--直播伴侣exe文件位置(除非程序找不到,否则请留空)-->
|
||||||
|
<add key="liveCompanPath" value=""/>
|
||||||
</appSettings>
|
</appSettings>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 推送数据格式
|
|
||||||
|
|
||||||
+ 弹幕数据由WebSocket服务进行分发,使用Json格式进行推送,见项目 [BarrageMessages.cs](./BarrageGrab/Modles/JsonEntity/BarrageMessages.cs),如需调整请克隆项目后参照 [message.proto](./BarrageGrab/proto/message.proto) 进行源码修改调整,文件包含所有弹幕相关数据结构,可前往[ws在线测试](http://wstool.jackxiang.com/)网站,连接 ws://127.0.0.1:8888 进行测试
|
|
||||||
|
|
||||||
### 使用方法
|
### 使用方法
|
||||||
1. 管理员身份启动本程序,第一次启动会提示安装自签名证书,程序启动后挂在后台不要关,不然再打开会监听不到正在进行中的直播弹幕。
|
1. 管理员身份启动本程序,第一次启动会提示安装自签名证书,程序启动后挂在后台不要关,程序无法中途监听已经建立连接的弹幕流
|
||||||
2. 打开浏览器进入任何直播间进行测试,没有问题再启动直播伴侣
|
2. 打开浏览器进入任何直播间,然后观察程序控制台中是否有弹幕滚动
|
||||||
3. 如果需要对接自己的应用程序,请先了解 [WebSocket](https://www.bilibili.com/video/BV1KN411n7WD/?share_source=copy_web&vd_source=39ebf42c923024b9eddeca32c9e46d16) ,然后进行对接,可前往[这里](http://wstool.jackxiang.com/)测试
|
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>
|
## 🔌 串口转发</i>
|
||||||
+ 配置串口:见<a href="#tag1">配置文件</a>`comPort`,配置发送串口以及波特率,不填则不启用
|
+ 配置串口:见<a href="#tag1">配置文件</a>`comPort`,配置发送串口以及波特率,不填则不启用
|
||||||
+ 串口报文自定义:可在根目录`Scripts/engine/comPortFilter.js` 根据自己的需求配置转发报文,提供了一定的Bit转换函数,详见其注释
|
+ 串口报文自定义:可在根目录`Scripts/engine/comPortFilter.js` 根据自己的需求配置转发报文,提供了一定的Bit转换函数,详见其注释
|
||||||
@@ -177,29 +171,59 @@
|
|||||||
|
|
||||||
|
|
||||||
+ **弹幕断连**
|
+ **弹幕断连**
|
||||||
|
|
||||||
+ 如果浏览器总是连接一段时间后,就在在控制台看不到弹幕了,优先使用Chrome 和 Edge 浏览器,其他浏览器(例如360浏览器) 可能会存在该问题
|
+ 如果浏览器总是连接一段时间后,就在在控制台看不到弹幕了,优先使用Chrome 和 Edge 浏览器,其他浏览器(例如360浏览器) 可能会存在该问题
|
||||||
|
|
||||||
+ 尝试打开配置文件 `forcePolling` 选项,情况获取会有所改善
|
+ 尝试打开配置文件 `forcePolling` 选项,情况获取会有所改善
|
||||||
|
|
||||||
+ 其他可能是网络原因,或者直播间断连导致,正在想办法优化解决中。。。需要长时间连接可以找我使用其他方式,支持直连和轮询获取方式
|
+ 其他可能是网络原因,或者直播间断连导致,正在想办法优化解决中。。。需要长时间连接可以找我使用其他方式,支持直连和轮询获取方式
|
||||||
|
|
||||||
+ **程序关闭后无法上网**
|
+ **程序关闭后无法上网**
|
||||||
|
|
||||||
+ 这是因为本程序运行时会占用系统代理,不正确的关闭方式可能会导致系统代理未能正确关闭,请前往找到 系统设置-网络和Internet-代理-使用代理服务器 并关闭它即可,也可管理员运行[关闭代理.bat](./关闭代理.bat)
|
+ 这是因为本程序运行时会占用系统代理,不正确的关闭方式可能会导致系统代理未能正确关闭,请前往找到 系统设置-网络和Internet-代理-使用代理服务器 并关闭它即可,也可管理员运行[关闭代理.bat](./关闭代理.bat)
|
||||||
|
+ **未开系统代理,但是无法监听到直播伴侣弹幕**
|
||||||
|
|
||||||
|
+ 之前可以突然不行,且刚刚升级直播伴侣,请重监听启程序和直播伴侣再次尝试
|
||||||
|
+ 如果一次都没成功,则需要检查启动菜单是否有直播伴侣的快捷方式,换言之则必须确保 `C:\ProgramData\Microsoft\Windows\Start Menu\Programs\直播伴侣.lnk` 文件存在,否则请前往配置文件显式指定`直播伴侣.exe`文件存储路径,见配置项`liveCompanPath`
|
||||||
|
|
||||||
|
|
||||||
|
<a id="user-content-实践指南"></a>
|
||||||
|
|
||||||
## 🎲 实践指南
|
## 🎲 实践指南
|
||||||
|
|
||||||
|
### 日常使用
|
||||||
|
|
||||||
+ **隐藏控制台**:见配置文件 `hideConsole`<br><br>
|
+ **隐藏控制台**:见配置文件 `hideConsole`<br><br>
|
||||||
+ **远程控制程序**:例如远程关闭,隐藏/显示控制台,启用/关闭系统代理,可发送Json数据包 `{"Cmd":xx,"Data":xx}` 到ws推送地址,数据格式详见: [Command.cs](./BarrageGrab/Modles/JsonEntity/Command.cs)<br><br>
|
+ **远程控制程序**:例如远程关闭,隐藏/显示控制台,启用/关闭系统代理,可发送Json数据包 `{"Cmd":xx,"Data":xx}` 到ws推送地址,数据格式详见: [Command.cs](./BarrageGrab/Modles/JsonEntity/Command.cs)<br><br>
|
||||||
+ **启用弹幕文件日志**:见配置文件 `barrageFileLog`,启用后,抓到弹幕会记录在根目录 logs/弹幕日志 文件夹中,支持类型过滤,见`logFilter` 配置项<br><br>
|
+ **启用弹幕文件日志**:见配置文件 `barrageFileLog`,启用后,抓到弹幕会记录在根目录 logs/弹幕日志 文件夹中,支持类型过滤,见`logFilter` 配置项<br><br>
|
||||||
+ **UI界面**: 见配置文件 `showWindow ` (做的仓促,功能简陋)<br><br>
|
+ **UI界面**: 见配置文件 `showWindow ` (做的仓促,功能简陋)<br><br>
|
||||||
+ **上游代理**:一般用于自己有 代理工具/代理服务器,希望在使用本程序时访问外网不受到影响,见配置文件项`upstreamProxy` 将它改为你代理工具的代理地址<br><br>
|
+ **上游代理**:一般用于自己有 代理工具/代理服务器,希望在使用本程序时访问外网不受到影响,见配置文件项`upstreamProxy` 将它改为你代理工具的代理地址<br><br>
|
||||||
+ **局域代理**: 若是只需要监听了浏览器,且不想占用系统代理,可创建一个浏览器快捷方式,打开属性,并在exe文件路径后附加启动参数,`--proxy-server=127.0.0.1:8827`,例如:`"C:\\xxx\chrome.exe" --proxy-server=127.0.0.1:8827`<br><br>
|
+ **局域代理**: (请优先参考下文 **浏览器代理切换扩展**) 可创建一个浏览器快捷方式,打开属性,并在exe文件路径后附加启动参数,`--proxy-server=127.0.0.1:8827`,例如:`"C:\\xxx\chrome.exe" --proxy-server=127.0.0.1:8827`<br><br>
|
||||||
+ **直播间区分**: 推送包含 `Onwer`字段,用户描述主播基本信息,客户端可以优先使用其中的`SecUid`或者`Uid`作为直播间标识,若使用`WebRoomid`则需要注意直播伴侣进程需要特殊处理,因为直播伴侣推送的WebRoomid是用户的抖音号。`RoomId`只能作为场次标识,每次开播都会不一样,不可用作直播间唯一区分<br><br>
|
+ **直播间区分**: 推送包含 `Onwer`字段,用户描述主播基本信息,客户端可以优先使用其中的`SecUid`或者`Uid`作为直播间标识,若使用`WebRoomid`则需要注意直播伴侣进程需要特殊处理,因为直播伴侣推送的WebRoomid是用户的抖音号。`RoomId`只能作为场次标识,每次开播都会不一样,不可用作直播间唯一区分<br><br>
|
||||||
+ **直播间地址**: 冷知识,使用`https://live.douyin.com/<抖音号>` 也可以进入主播直播间
|
+ **直播间地址**: 冷知识,使用`https://live.douyin.com/<抖音号>` 也可以进入主播直播间
|
||||||
|
|
||||||
|
### 浏览器代理切换扩展
|
||||||
|
|
||||||
|
若关闭了`usedProxy`开关,浏览器需要通过显示指定代理地址完成代理指向操作,此时可以通过浏览器扩展很好的完成这项功能,以Edge为例
|
||||||
|
|
||||||
|
1. 前往扩展商店 搜索 `switchyomega` 安装
|
||||||
|
|
||||||
|
[<img src="https://s21.ax1x.com/2024/09/28/pA1SSSg.png" alt="pA1SSSg.png" style="zoom: 50%;" />](https://imgse.com/i/pA1SSSg)
|
||||||
|
|
||||||
|
2. 添加弹幕代理
|
||||||
|
|
||||||
|
[<img src="https://s21.ax1x.com/2024/09/28/pA1SCOs.png" alt="pA1SCOs.png" style="zoom:50%;" />](https://imgse.com/i/pA1SCOs)
|
||||||
|
|
||||||
|
3. 配置代理地址,并保存,不要配置为ws服务端口地址,程序默认代理端口是**8827**
|
||||||
|
|
||||||
|
[<img src="https://s21.ax1x.com/2024/09/28/pA1SLjJ.png" alt="pA1SLjJ.png" style="zoom:50%;" />](https://imgse.com/i/pA1SLjJ)
|
||||||
|
|
||||||
|
4. 进入直播页,应用代理,完成!
|
||||||
|
|
||||||
|
[<img src="https://s21.ax1x.com/2024/09/28/pA1SXu9.png" alt="pA1SXu9.png" style="zoom:50%;" />](https://imgse.com/i/pA1SXu9)
|
||||||
|
|
||||||
|
5. Chrome 用户请自行百度搜索扩展安装方法
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## ⚠️特别注意
|
## ⚠️特别注意
|
||||||
|
|
||||||
@@ -227,8 +251,9 @@
|
|||||||
+ 请详细阅读[免责声明](./免责声明.txt)条款后进行使用
|
+ 请详细阅读[免责声明](./免责声明.txt)条款后进行使用
|
||||||
|
|
||||||
<a id="user-content-支持一下" class="anchor"></a>
|
<a id="user-content-支持一下" class="anchor"></a>
|
||||||
|
|
||||||
## 🍻支持一下?
|
## 🍻支持一下?
|
||||||
开源不易啊老板
|
开源不易,老板
|
||||||
<p>
|
<p>
|
||||||
<img src="./imgs/微信.png" alt="微信支付" style="zoom:70%;border-radius: 5px;" />
|
<img src="./imgs/微信.png" alt="微信支付" style="zoom:70%;border-radius: 5px;" />
|
||||||
</p>
|
</p>
|
||||||
Reference in New Issue
Block a user