From 3c310ebffca3e80f98f6642c59dc1d59eae805c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=85=E6=B5=A9=E4=B8=9C?= <1083092844@qq.com> Date: Fri, 29 Mar 2024 17:34:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ComPort=20=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BarrageGrab/App.config | 26 ++-- BarrageGrab/AppRuntime.cs | 16 ++- BarrageGrab/Appsetting.cs | 97 +++++++++---- BarrageGrab/ComPortServer.cs | 136 ++++++++++++++++++ BarrageGrab/Forms/FormView.cs | 34 ++--- BarrageGrab/JsEngine.cs | 148 ++++++++++++++++++++ BarrageGrab/Logger.cs | 6 +- BarrageGrab/Program.cs | 122 +++++++++++----- BarrageGrab/Proxy/SystemProxy.cs | 6 +- BarrageGrab/Proxy/TitaniumProxy.cs | 16 +-- BarrageGrab/Scripts/engine/comPortFilter.js | 28 ++++ BarrageGrab/WsBarrageServer.cs | 57 +++++--- BarrageGrab/WssBarrageGrab.cs | 2 +- BarrageGrab/WssBarrageService.csproj | 17 ++- BarrageGrab/packages.config | 3 +- 15 files changed, 587 insertions(+), 127 deletions(-) create mode 100644 BarrageGrab/ComPortServer.cs create mode 100644 BarrageGrab/JsEngine.cs create mode 100644 BarrageGrab/Scripts/engine/comPortFilter.js diff --git a/BarrageGrab/App.config b/BarrageGrab/App.config index c096faf..a3fe1da 100644 --- a/BarrageGrab/App.config +++ b/BarrageGrab/App.config @@ -1,4 +1,4 @@ - + @@ -20,8 +20,8 @@ - - + + @@ -34,14 +34,18 @@ - - - - - - - - + + + + + + + + + + + + diff --git a/BarrageGrab/AppRuntime.cs b/BarrageGrab/AppRuntime.cs index 2da38fe..b949d2d 100644 --- a/BarrageGrab/AppRuntime.cs +++ b/BarrageGrab/AppRuntime.cs @@ -18,12 +18,17 @@ namespace BarrageGrab /// /// Ws弹幕服务示例 /// - public static WsBarrageService WssService { get; private set; } = new WsBarrageService(); + public static WsBarrageServer WsServer { get; private set; } /// /// 房间缓存信息 /// - public static RoomCacheManager RoomCaches { get; } = new RoomCacheManager(); + public static RoomCacheManager RoomCaches { get; private set; } + + /// + /// 串口服务 + /// + public static ComPortServer ComPortServer { get; private set; } /// /// 程序进程信息 @@ -35,6 +40,13 @@ namespace BarrageGrab } + public static void Init() + { + WsServer = new WsBarrageServer(); + RoomCaches = new RoomCacheManager(); + ComPortServer = new ComPortServer(WsServer); + } + /// /// 隐藏/显示 控制台 /// diff --git a/BarrageGrab/Appsetting.cs b/BarrageGrab/Appsetting.cs index 9890e5c..b5543e6 100644 --- a/BarrageGrab/Appsetting.cs +++ b/BarrageGrab/Appsetting.cs @@ -10,13 +10,13 @@ using System.Drawing; namespace BarrageGrab { - internal class Appsetting + internal class AppSetting { - private static readonly Appsetting ins = new Appsetting(); + private static readonly AppSetting ins = new AppSetting(); - public static Appsetting Current { get { return ins; } } + public static AppSetting Current { get { return ins; } } - public Appsetting() + public AppSetting() { try { @@ -24,7 +24,7 @@ namespace BarrageGrab WsProt = int.Parse(AppSettings["wsListenPort"]); PrintBarrage = AppSettings["printBarrage"].ToLower() == "true"; ProxyPort = int.Parse(AppSettings["proxyPort"]); - PrintFilter = Enum.GetValues(typeof(PackMsgType)).Cast().Where(w=>w>0).ToArray(); + PrintFilter = Enum.GetValues(typeof(PackMsgType)).Cast().Where(w => w > 0).ToArray(); PushFilter = Enum.GetValues(typeof(PackMsgType)).Cast().Where(w => w > 0).ToArray(); LogFilter = Enum.GetValues(typeof(PackMsgType)).Cast().Where(w => w > 0).ToArray(); FilterHostName = bool.Parse(AppSettings["filterHostName"].Trim()); @@ -39,26 +39,10 @@ namespace BarrageGrab ForcePolling = bool.Parse(AppSettings["forcePolling"].Trim()); PollingInterval = int.Parse(AppSettings["pollingInterval"].Trim()); DisableLivePageScriptCache = bool.Parse(AppSettings["disableLivePageScriptCache"].Trim()); - WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w=>!string.IsNullOrWhiteSpace(w)).Select(x => long.Parse(x)).ToArray(); + WebRoomIds = AppSettings["webRoomIds"].Trim().Split(',').Where(w => !string.IsNullOrWhiteSpace(w)).Select(x => long.Parse(x)).ToArray(); - var printFilter = AppSettings["printFilter"].Trim().ToLower(); - var pushFilter = AppSettings["pushFilter"].Trim().ToLower(); - var logFilter = AppSettings["logFilter"].Trim().ToLower(); - if (!string.IsNullOrWhiteSpace(printFilter)) - { - if (string.IsNullOrWhiteSpace(printFilter)) PrintFilter = new int[0]; - else PrintFilter = printFilter.Split(',').Select(x => int.Parse(x)).ToArray(); - } - if (!string.IsNullOrWhiteSpace(pushFilter)) - { - if (string.IsNullOrWhiteSpace(pushFilter)) PushFilter = new int[0]; - else PushFilter = pushFilter.Split(',').Select(x => int.Parse(x)).ToArray(); - } - if (!string.IsNullOrWhiteSpace(logFilter)) - { - if (string.IsNullOrWhiteSpace(logFilter)) LogFilter = new int[0]; - else LogFilter = logFilter.Split(',').Select(x => int.Parse(x)).ToArray(); - } + ConfigComPort(); + ConfigFilter(); } catch (Exception ex) { @@ -67,11 +51,55 @@ namespace BarrageGrab } } + + //com串口设置 + private void ConfigComPort() + { + var comPort = AppSettings["comPort"]; + if (!comPort.IsNullOrWhiteSpace()) + { + try + { + var spit = comPort.Split(':'); + ComPort = spit[0].Trim(); + ComBaudRate = int.Parse(spit[1].Trim()); + UseComPortFilter = bool.Parse(AppSettings["useComPortFilter"]); + } + catch (Exception ex) + { + throw new Exception("串口配置格式错误," + ex.Message, ex); + } + } + } + + //各种过滤器设置 + private void ConfigFilter() + { + var printFilter = AppSettings["printFilter"].Trim().ToLower(); + var pushFilter = AppSettings["pushFilter"].Trim().ToLower(); + var logFilter = AppSettings["logFilter"].Trim().ToLower(); + if (!string.IsNullOrWhiteSpace(printFilter)) + { + if (string.IsNullOrWhiteSpace(printFilter)) PrintFilter = new int[0]; + else PrintFilter = printFilter.Split(',').Select(x => int.Parse(x)).ToArray(); + } + if (!string.IsNullOrWhiteSpace(pushFilter)) + { + if (string.IsNullOrWhiteSpace(pushFilter)) PushFilter = new int[0]; + else PushFilter = pushFilter.Split(',').Select(x => int.Parse(x)).ToArray(); + } + if (!string.IsNullOrWhiteSpace(logFilter)) + { + if (string.IsNullOrWhiteSpace(logFilter)) LogFilter = new int[0]; + else LogFilter = logFilter.Split(',').Select(x => int.Parse(x)).ToArray(); + } + } + public void Save() { Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); - - config.AppSettings.Settings["wsListenPort"].Value = WsProt.ToString(); + + config.AppSettings.Settings["wsListenPort"].Value = WsProt.ToString(); config.AppSettings.Settings["printBarrage"].Value = PrintBarrage.ToString().ToLower(); config.AppSettings.Settings["printFilter"].Value = string.Join("", PrintFilter); config.AppSettings.Settings["pushFilter"].Value = string.Join("", PushFilter); @@ -80,7 +108,7 @@ namespace BarrageGrab config.AppSettings.Settings["listenAny"].Value = ListenAny.ToString().ToLower(); config.AppSettings.Settings["hideConsole"].Value = HideConsole.ToString().ToLower(); config.AppSettings.Settings["barrageFileLog"].Value = HideConsole.ToString().ToLower(); - + config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection(config.AppSettings.SectionInformation.Name); } @@ -200,5 +228,20 @@ namespace BarrageGrab /// 禁用直播页面脚本缓存 /// public bool DisableLivePageScriptCache { get; private set; } = true; + + /// + /// 配置的串口 + /// + public string ComPort { get; set; } = string.Empty; + + /// + /// 波特率 + /// + public int ComBaudRate { get; set; } = 9600; + + /// + /// 是否启用串口过滤器脚本 + /// + public bool UseComPortFilter { get; set; } } } diff --git a/BarrageGrab/ComPortServer.cs b/BarrageGrab/ComPortServer.cs new file mode 100644 index 0000000..bbdda9a --- /dev/null +++ b/BarrageGrab/ComPortServer.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO.Ports; +using Jint; +using Jint.Runtime; +using System.Windows.Forms; + +namespace BarrageGrab +{ + public class ComPortServer : IDisposable + { + WsBarrageServer server; + SerialPort sendPort; + static Engine jsEngine = null; + + static ComPortServer() + { + if (AppSetting.Current.UseComPortFilter) + { + jsEngine = JsEngine.CreateNewEngine(); + var jsFile = JsEngine.GetJsFile("comPortFilter.js"); + jsEngine.Execute(jsFile); + } + } + + public ComPortServer(WsBarrageServer server) + { + string portName = AppSetting.Current.ComPort; + int baudRate = AppSetting.Current.ComBaudRate; + if (portName.IsNullOrWhiteSpace()) + { + return; + //throw new ArgumentNullException(nameof(portName)); + } + this.server = server; + server.OnPackMessage += Server_OnPackMessage; + server.OnClose += Server_OnClose; + sendPort = new SerialPort(portName, baudRate); + } + + private void Server_OnClose(object sender, EventArgs e) + { + this.Dispose(); + } + + private void Server_OnPackMessage(WsBarrageServer sender, WsBarrageServer.PackMsgEventArgs e) + { + if (!sendPort.IsOpen) return; + if (e == null) return; + if (!AppSetting.Current.UseComPortFilter) + { + var json = e.ToJson() + "\r\n"; + var jbuff = Encoding.UTF8.GetBytes(json); + Send(jbuff); + return; + } + var result = jsEngine.Invoke("onPackData", e.MsgType.GetHashCode(), e.Message); + var nocanTypes = new Types[] + { + Types.Null, + Types.Undefined, + Types.Empty, + Types.Symbol + }; + if (nocanTypes.Contains(result.Type)) return; + Func encode = (str) => Encoding.UTF8.GetBytes(str); + + byte[] buff = new byte[0]; + switch (result.Type) + { + case Types.Boolean: + buff = encode(result.AsBoolean().ToString().ToLower()); + break; + case Types.String: + buff = encode(result.AsString()); + break; + case Types.BigInt: + case Types.Number: + buff = BitConverter.GetBytes(result.AsNumber()); + break; + case Types.Object: + if (result.ToObject() is byte[]) + { + buff = result.AsArrayBuffer(); + } + break; + default: + break; + } + + if (buff.Length == 0) return; + Send(buff); + } + + //发送数据包 + private void Send(byte[] buff) + { + lock (this.sendPort) + { + sendPort.Write(buff, 0, buff.Length); + } + } + + /// + /// 打开串口并开始接收写入数据 + /// + public void OpenStart() + { + if (sendPort == null) throw new Exception("未成功初始化串口对象,请检查配置文件"); + try + { + sendPort.Open(); + } + catch (Exception ex) + { + sendPort.Close(); + sendPort.Dispose(); + sendPort = null; + throw ex; + } + } + + + public void Dispose() + { + if (sendPort == null) return; + sendPort.Close(); + sendPort.Dispose(); + sendPort = null; + jsEngine.Dispose(); + } + } +} diff --git a/BarrageGrab/Forms/FormView.cs b/BarrageGrab/Forms/FormView.cs index e743aac..b322e6b 100644 --- a/BarrageGrab/Forms/FormView.cs +++ b/BarrageGrab/Forms/FormView.cs @@ -20,9 +20,9 @@ namespace BarrageGrab { static int printCount = 0; - WsBarrageService barServer = AppRuntime.WssService; - WssBarrageGrab grab = AppRuntime.WssService.Grab; - ISystemProxy proxy = AppRuntime.WssService.Grab.Proxy; + WsBarrageServer barServer = AppRuntime.WsServer; + WssBarrageGrab grab = AppRuntime.WsServer.Grab; + ISystemProxy proxy = AppRuntime.WsServer.Grab.Proxy; public FormView() { @@ -32,7 +32,7 @@ namespace BarrageGrab AppRuntime.RoomCaches.OnCache += RoomCaches_OnCache; this.txb_wsaddr.Text = barServer.ServerLocation; this.txb_upstreamProxy.Text = proxy.HttpUpstreamProxy; - this.cbx_barrageLog.Checked = Appsetting.Current.BarrageLog; + this.cbx_barrageLog.Checked = AppSetting.Current.BarrageLog; InitTabPages(); } @@ -67,17 +67,17 @@ namespace BarrageGrab if (page == this.tabPage_Ws) { type = "ws"; - ck.Checked = Appsetting.Current.PushFilter.Contains(label.Key); + ck.Checked = AppSetting.Current.PushFilter.Contains(label.Key); } if (page == this.tabPage_Console) { type = "console"; - ck.Checked = Appsetting.Current.PrintFilter.Contains(label.Key); + ck.Checked = AppSetting.Current.PrintFilter.Contains(label.Key); } if (page == this.tabPage_Log) { type = "log"; - ck.Checked = Appsetting.Current.LogFilter.Contains(label.Key); + ck.Checked = AppSetting.Current.LogFilter.Contains(label.Key); } ck.Name = $"cbx_bartype_{type}_{label.Key}"; ck.CheckedChanged += Ck_CheckedChanged; @@ -94,17 +94,17 @@ namespace BarrageGrab var selected = GetCheckedBarTypes((FlowLayoutPanel)cbx.Parent); if (cbx.Parent.Parent == this.tabPage_Console) { - Appsetting.Current.PrintFilter = selected; + AppSetting.Current.PrintFilter = selected; } if (cbx.Parent.Parent == this.tabPage_Ws) { - Appsetting.Current.PushFilter = selected; + AppSetting.Current.PushFilter = selected; } if(cbx.Parent.Parent == this.tabPage_Log) { - Appsetting.Current.LogFilter = selected; + AppSetting.Current.LogFilter = selected; } - Appsetting.Current.Save(); + AppSetting.Current.Save(); } private int[] GetCheckedBarTypes(FlowLayoutPanel panel) @@ -167,11 +167,11 @@ namespace BarrageGrab })); } - private void WssService_OnPrint(object sender, WsBarrageService.PrintEventArgs e) + private void WssService_OnPrint(object sender, WsBarrageServer.PrintEventArgs e) { //将弹幕输出到richTextBox //颜色转换 - Color color = Appsetting.Current.ColorMap[e.MsgType].Item2; + Color color = AppSetting.Current.ColorMap[e.MsgType].Item2; string msg = e.Message; this.Invoke(new Action(() => @@ -218,8 +218,8 @@ namespace BarrageGrab try { proxy.SetUpstreamProxy(text); - Appsetting.Current.UpstreamProxy = text; - Appsetting.Current.Save(); + AppSetting.Current.UpstreamProxy = text; + AppSetting.Current.Save(); } catch (Exception ex) { @@ -231,8 +231,8 @@ namespace BarrageGrab private void cbx_barrageLog_CheckedChanged(object sender, EventArgs e) { var checker = (CheckBox)sender; - Appsetting.Current.BarrageLog = checker.Checked; - Appsetting.Current.Save(); + AppSetting.Current.BarrageLog = checker.Checked; + AppSetting.Current.Save(); } } } diff --git a/BarrageGrab/JsEngine.cs b/BarrageGrab/JsEngine.cs new file mode 100644 index 0000000..05ccd97 --- /dev/null +++ b/BarrageGrab/JsEngine.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Jint; +using Newtonsoft.Json; +using Jint.Native; + +namespace BarrageGrab +{ + public static class JsEngine + { + public static Engine CreateNewEngine() + { + var jsonParse = new Func((obj) => + { + try + { + return JsonConvert.SerializeObject(JsonConvert.SerializeObject(obj)); + } + catch (Exception ex) + { + Logger.LogError("JS:" + ex.Message); + return null; + } + }); + + var engine = new Engine(); + engine.SetValue("console", new JsConsole()); + engine.SetValue("encoder", new JsEncoder(engine)); + + return engine; + } + + /// + /// 从engine 目录获取js 文件 + /// + /// + /// + 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); + } + + class JsConsole + { + public void log(object obj) + { + if (obj == null) return; + Logger.PrintColor("JS: " + obj.ToString()); + } + + public void error(object obj) + { + if (obj == null) return; + Logger.LogError("JS: " + obj.ToString()); + } + + public void warn(object obj) + { + if (obj == null) return; + Logger.LogWarn("JS: " + obj.ToString()); + } + } + + class JsEncoder + { + Engine eng; + public JsEncoder(Engine eng) + { + this.eng = eng; + eng.Execute(@" + byteToUint8Array = function(arr){ + return new Uint8Array(arr); + }"); + } + + private JsValue ByteConvert(byte[] buff) + { + return eng.Invoke("byteToUint8Array", buff); + } + + public JsValue utf8ToBytes(string str) + { + byte[] res = new byte[0]; + if (str.IsNullOrWhiteSpace()) + { + res = new byte[0]; + } + else + { + res = Encoding.UTF8.GetBytes(str); + } + return ByteConvert(res); + } + + public JsValue utf32ToBytes(string str) + { + byte[] res = new byte[0]; + if (str.IsNullOrWhiteSpace()) + { + res = new byte[0]; + } + else + { + res = Encoding.UTF32.GetBytes(str); + } + return ByteConvert(res); + } + + public JsValue asciiToBytes(string str) + { + byte[] res = new byte[0]; + if (str.IsNullOrWhiteSpace()) + { + res = new byte[0]; + } + else + { + res = Encoding.ASCII.GetBytes(str); + } + return ByteConvert(res); + } + + public string utf8ToString(byte[] bytes) + { + if (bytes == null) return null; + return Encoding.UTF8.GetString(bytes); + } + + public string utf32ToString(byte[] bytes) + { + if (bytes == null) return null; + return Encoding.UTF32.GetString(bytes); + } + + public string asciiToString(byte[] bytes) + { + if (bytes == null) return null; + return Encoding.ASCII.GetString(bytes); + } + } + } +} diff --git a/BarrageGrab/Logger.cs b/BarrageGrab/Logger.cs index 32cd6bc..507e082 100644 --- a/BarrageGrab/Logger.cs +++ b/BarrageGrab/Logger.cs @@ -94,9 +94,9 @@ namespace BarrageGrab /// 弹幕内容 public static void LogBarrage(PackMsgType type, Msg msg) { - if (!Appsetting.Current.BarrageLog) return; + if (!AppSetting.Current.BarrageLog) return; if (type == PackMsgType.无) return; - if (Appsetting.Current.LogFilter.Any() && !Appsetting.Current.LogFilter.Contains(type.GetHashCode())) return; + if (AppSetting.Current.LogFilter.Any() && !AppSetting.Current.LogFilter.Contains(type.GetHashCode())) return; try { @@ -135,7 +135,7 @@ namespace BarrageGrab text += $" [{msg.User?.GenderToString()}] "; } - ConsoleColor color = Appsetting.Current.ColorMap[barType].Item1; + ConsoleColor color = AppSetting.Current.ColorMap[barType].Item1; var append = msg.Content; switch (barType) { diff --git a/BarrageGrab/Program.cs b/BarrageGrab/Program.cs index 311af8e..2ecb8e0 100644 --- a/BarrageGrab/Program.cs +++ b/BarrageGrab/Program.cs @@ -6,6 +6,9 @@ using System.Net; using System.Runtime.InteropServices; using System.Text; using System.Threading; +using System.IO; +using Jint.Runtime; +using System.Windows.Forms; namespace BarrageGrab { @@ -14,9 +17,14 @@ namespace BarrageGrab static FormView mainForm = null; static bool exited = false; static bool formExited = false; + static WinApi.ControlCtrlDelegate controlCtr = ControlCtrlHandle; static void Main(string[] args) { + //JintTest(); + //Console.WriteLine("结束"); + //Console.ReadKey(); + //return; if (CheckAlreadyRunning()) { Logger.PrintColor("已经有一个监听程序在运行,按任意键退出..."); @@ -25,19 +33,51 @@ namespace BarrageGrab } SetTitle("抖音弹幕监听推送"); - WinApi.SetConsoleCtrlHandler(ControlCtrlDelegate, true);//捕获控制台关闭 + try + { + Init(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "程序初始化错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + exited = true; + } + + while (!exited) + { + Thread.Sleep(500); + } + + if (!AppRuntime.WsServer.IsDisposed) + { + AppRuntime.WsServer.Dispose(); + } + + Logger.PrintColor("服务器已关闭..."); + WinApi.SetConsoleCtrlHandler(controlCtr, false);//反注册捕获控制台关闭 + + } + + private static void Init() + { + AppRuntime.Init(); + WinApi.SetConsoleCtrlHandler(controlCtr, true);//捕获控制台关闭 WinApi.DisableQuickEditMode();//禁用控制台快速编辑模式 - AppRuntime.DisplayConsole(!Appsetting.Current.HideConsole);//控制控制台可见 - AppRuntime.WssService.Grab.Proxy.SetUpstreamProxy(Appsetting.Current.UpstreamProxy);//设置上游代理 - AppRuntime.WssService.StartListen();//启动WS服务 + AppRuntime.DisplayConsole(!AppSetting.Current.HideConsole);//控制控制台可见 + AppRuntime.WsServer.Grab.Proxy.SetUpstreamProxy(AppSetting.Current.UpstreamProxy);//设置上游代理 + AppRuntime.WsServer.OnClose += (s, e) => + { + exited = true; + }; - Logger.LogSucc($"{AppRuntime.WssService.ServerLocation} 弹幕服务已启动..."); - SetTitle($"抖音弹幕监听推送 [{AppRuntime.WssService.ServerLocation}]"); - - AppRuntime.WssService.OnClose += (s, e) => exited = true; + //串口写入服务 + if (!AppSetting.Current.ComPort.IsNullOrWhiteSpace()) + { + AppRuntime.ComPortServer.OpenStart(); + } //显示窗体 - if (Appsetting.Current.ShowWindow) + if (AppSetting.Current.ShowWindow) { var uiThread = new Thread(new ThreadStart(() => { @@ -45,33 +85,16 @@ namespace BarrageGrab //开启消息循环 System.Windows.Forms.Application.Run(mainForm); formExited = true; + AppRuntime.WsServer.Dispose();//Close后自动释放资源 })); uiThread.SetApartmentState(ApartmentState.STA); uiThread.IsBackground = true; uiThread.Start(); } - while (!exited) - { - if (formExited && !exited) - { - AppRuntime.WssService.Close(); - } - Thread.Sleep(500); - } - - Logger.PrintColor("服务器已关闭..."); - - //if (!mainForm.IsDisposed) - //{ - // mainForm.Invoke(new Action(() => - // { - // mainForm.Close(); - // })); - //} - - //退出程序,不显示 按任意键退出 - //Environment.Exit(0); + AppRuntime.WsServer.StartListen();//启动WS以及代理服务 + Logger.LogSucc($"{AppRuntime.WsServer.ServerLocation} 弹幕服务已启动..."); + SetTitle($"抖音弹幕监听推送 [{AppRuntime.WsServer.ServerLocation}]"); } //检测设置控制台标题 @@ -84,7 +107,7 @@ namespace BarrageGrab } //监听控制台消息事件 - private static bool ControlCtrlDelegate(int CtrlType) + private static bool ControlCtrlHandle(int CtrlType) { switch (CtrlType) { @@ -94,7 +117,7 @@ namespace BarrageGrab break; case 2: Logger.PrintColor("2工具被强制关闭");//按控制台关闭按钮关闭 - AppRuntime.WssService.Close(); + AppRuntime.WsServer.Dispose(); break; } return false; @@ -111,5 +134,40 @@ namespace BarrageGrab return !createdNew; } } + + private static void JintTest() + { + var jsEng = JsEngine.CreateNewEngine(); + var jsFile = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "Scripts", "engine", "comPortFilter.js"), Encoding.UTF8); + jsEng.Execute(jsFile); + var result = jsEng.Invoke("onPackData", 1, new + { + Aporp = 142, + Bprop = "48777", + Cprop = new string[] { "123" }, + Dprop = new Dictionary() + { + { "key1","value1" } + } + }); + + Console.WriteLine("返回类型:" + result.Type.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()); + } + } } } diff --git a/BarrageGrab/Proxy/SystemProxy.cs b/BarrageGrab/Proxy/SystemProxy.cs index fdcc8b9..661417c 100644 --- a/BarrageGrab/Proxy/SystemProxy.cs +++ b/BarrageGrab/Proxy/SystemProxy.cs @@ -32,7 +32,7 @@ namespace BarrageGrab.Proxy /// /// 代理端口 /// - public int ProxyPort { get { return Appsetting.Current.ProxyPort; } } + public int ProxyPort { get { return AppSetting.Current.ProxyPort; } } public abstract string HttpUpstreamProxy { get; } @@ -55,11 +55,11 @@ namespace BarrageGrab.Proxy { host = host.Trim().ToLower(); - if (!Appsetting.Current.FilterHostName) return true; + if (!AppSetting.Current.FilterHostName) return true; if (host.StartsWith("webcast")) return true; - if (Appsetting.Current.HostNameFilter.Any(a => a.Trim().ToLower() == host)) return true; + if (AppSetting.Current.HostNameFilter.Any(a => a.Trim().ToLower() == host)) return true; return false; } diff --git a/BarrageGrab/Proxy/TitaniumProxy.cs b/BarrageGrab/Proxy/TitaniumProxy.cs index 1825470..b9e7e05 100644 --- a/BarrageGrab/Proxy/TitaniumProxy.cs +++ b/BarrageGrab/Proxy/TitaniumProxy.cs @@ -212,7 +212,7 @@ namespace BarrageGrab.Proxy var scriptContext = BuildContext(new Dictionary() { {"PROCESS_NAME","'{processName}'"}, - {"AUTOPAUSE",Appsetting.Current.AutoPause.ToString().ToLower()} + {"AUTOPAUSE",AppSetting.Current.AutoPause.ToString().ToLower()} }); liveRoomInjectScript = scriptContext + liveRoomInjectScript; var html = await e.GetResponseBodyAsString(); @@ -275,7 +275,7 @@ namespace BarrageGrab.Proxy } //给script标签 src加上时间戳避免缓存 - if (Appsetting.Current.DisableLivePageScriptCache) + if (AppSetting.Current.DisableLivePageScriptCache) { var scripts = doc.DocumentNode.SelectNodes("//script[@src]"); if (scripts != null) @@ -311,7 +311,7 @@ namespace BarrageGrab.Proxy var scriptContext = BuildContext(new Dictionary() { {"PROCESS_NAME","'{processName}'"}, - {"AUTOPAUSE",Appsetting.Current.AutoPause.ToString().ToLower()} + {"AUTOPAUSE",AppSetting.Current.AutoPause.ToString().ToLower()} }); liveHoomInjectScript = scriptContext + liveHoomInjectScript; @@ -382,7 +382,7 @@ namespace BarrageGrab.Proxy } } - if (url.Contains(LIVE_SCRIPT_PATH) && Appsetting.Current.ForcePolling) + if (url.Contains(LIVE_SCRIPT_PATH) && AppSetting.Current.ForcePolling) { var reg = new Regex(@"if\s*\((?!this\.stopPolling)\)"); var js = await e.GetResponseBodyAsString(); @@ -393,7 +393,7 @@ namespace BarrageGrab.Proxy var pollingIntervalMatch = pollingIntervalReg.Match(js); if (pollingIntervalMatch.Success) { - var myValue = Appsetting.Current.PollingInterval; + var myValue = AppSetting.Current.PollingInterval; js = pollingIntervalReg.Replace(js, $"this.pollingInterval={myValue},"); Logger.PrintColor($"直播间已成功修改轮询间隔为{myValue}ms", ConsoleColor.Green); } @@ -515,7 +515,7 @@ namespace BarrageGrab.Proxy { proxyServer.Stop(); proxyServer.Dispose(); - if (Appsetting.Current.UsedProxy) + if (AppSetting.Current.UsedProxy) { CloseSystemProxy(); } @@ -526,8 +526,8 @@ namespace BarrageGrab.Proxy /// override public void Start() { - proxyServer.Start(Appsetting.Current.UsedProxy); - if (Appsetting.Current.UsedProxy) + proxyServer.Start(AppSetting.Current.UsedProxy); + if (AppSetting.Current.UsedProxy) { proxyServer.SetAsSystemHttpProxy(explicitEndPoint); proxyServer.SetAsSystemHttpsProxy(explicitEndPoint); diff --git a/BarrageGrab/Scripts/engine/comPortFilter.js b/BarrageGrab/Scripts/engine/comPortFilter.js new file mode 100644 index 0000000..7dc0ecb --- /dev/null +++ b/BarrageGrab/Scripts/engine/comPortFilter.js @@ -0,0 +1,28 @@ +/** + * 注解:串口数据过滤脚本,可用于自定义配置串口的发送报文 + * Tip: 该脚本引擎为Jint,支持的语法请参考官方文档:https://github.com/sebastienros/jint + * 工具环境: + * 1.支持 console.log, console.error, console.warn 这些日志将被输出到控制台, 其中error日志将被记录到日志文件 + * 2.编码工具 encoder.utf8ToBytes(str),encoder.utf8ToString 字符串 和 Uint8Array 互转 + * encoder.utf32ToBytes(str),encoder.utf32ToString + * encoder.asciiToBytes(str),encoder.asciiToString + */ + + + +/** + * 这个函数由程序JS引擎调用,不要删除 + * @param {number} msgType 消息类型,如礼物,弹幕消息等,和程序内定义一致 + * @param {Object} msg 被WsBarrageServer简化后的消息对象,具体可参考Json实体文件 + * @returns {Uint8Array|string} 返回一个Uint8Array类型的数据,或者返回一个字符串,如果返回 null 则不发送数据。返回的数据将会被发送到串口 + */ +function onPackData(msgType, msg) { + let excludeMsgType = [3, 6, 0]; // 过滤掉进入直播间和统计信息 + if (excludeMsgType.includes(msgType)) return; + var result = msg.Content + "\r\n"; + return result; + // var buff = encoder.utf8ToBytes(result); + // var newjs = encoder.utf8ToString(buff); + // console.log(newjs); + // return newjs; +} diff --git a/BarrageGrab/WsBarrageServer.cs b/BarrageGrab/WsBarrageServer.cs index 7b2fa1e..9aed910 100644 --- a/BarrageGrab/WsBarrageServer.cs +++ b/BarrageGrab/WsBarrageServer.cs @@ -20,10 +20,15 @@ using System.Collections.Concurrent; namespace BarrageGrab { + /// + /// WsBarrageServer 包装消息事件委托 + /// + public delegate void PackMessageEventHandler(WsBarrageServer sender, WsBarrageServer.PackMsgEventArgs e); + /// /// 弹幕服务 /// - public class WsBarrageServer + public class WsBarrageServer:IDisposable { WebSocketServer socketServer; //Ws服务器对象 Dictionary socketList = new Dictionary(); //客户端列表 @@ -31,25 +36,29 @@ namespace BarrageGrab Timer dieout = new Timer(10000);//离线客户端清理计时器 Timer giftCountTimer = new Timer(10000);//礼物缓存清理计时器 WssBarrageGrab grab = new WssBarrageGrab();//弹幕解析器核心 - Appsetting Appsetting = Appsetting.Current;//全局配置文件实例 + AppSetting Appsetting = AppSetting.Current;//全局配置文件实例 static int printCount = 0; //控制台输出计数,用于判断清理控制台 - /// /// WS服务器启动地址 /// - public string ServerLocation { get { return socketServer.Location; } } + public string ServerLocation => socketServer.Location; /// /// 数据内核 /// - public WssBarrageGrab Grab { get { return grab; } } + public WssBarrageGrab Grab => grab; /// /// 控制台打印事件 /// public event EventHandler OnPrint; + /// + /// 是否已经释放资源 + /// + public bool IsDisposed { get; private set; } = false; + /// /// 服务关闭后触发 /// @@ -58,7 +67,7 @@ namespace BarrageGrab /// /// 消息包装完成后触发 /// - public event EventHandler OnPackMessage; + public event PackMessageEventHandler OnPackMessage; public WsBarrageServer() { @@ -111,12 +120,12 @@ namespace BarrageGrab //判断Rommid是否符合拦截规则 private bool CheckRoomId(long roomid) { - if (!Appsetting.Current.WebRoomIds.Any()) return true; + if (!AppSetting.Current.WebRoomIds.Any()) return true; var webrid = AppRuntime.RoomCaches.GetCachedWebRoomid(roomid.ToString()); if (webrid <= 0) return true; - return Appsetting.Current.WebRoomIds.Contains(webrid); + return AppSetting.Current.WebRoomIds.Contains(webrid); } //解析用户 @@ -165,7 +174,7 @@ namespace BarrageGrab text += $" [{msg.User?.GenderToString()}] "; } - ConsoleColor color = Appsetting.Current.ColorMap[barType].Item1; + ConsoleColor color = AppSetting.Current.ColorMap[barType].Item1; var append = msg.Content; switch (barType) { @@ -176,13 +185,13 @@ namespace BarrageGrab text += append; - if (Appsetting.Current.BarrageLog) + if (AppSetting.Current.BarrageLog) { Logger.LogBarrage(barType, msg); } if (!Appsetting.PrintBarrage) return; - if (Appsetting.Current.PrintFilter.Any() && !Appsetting.Current.PrintFilter.Contains(barType.GetHashCode())) return; + if (AppSetting.Current.PrintFilter.Any() && !AppSetting.Current.PrintFilter.Contains(barType.GetHashCode())) return; OnPrint?.Invoke(this, new PrintEventArgs() { @@ -201,7 +210,7 @@ namespace BarrageGrab } //发送消息包装事件 - private void FirePack(Msg msg, PackMsgType barType) + private async void FirePack(Msg msg, PackMsgType barType) { if (OnPackMessage == null) return; var arg = new PackMsgEventArgs() @@ -210,7 +219,7 @@ namespace BarrageGrab Message = msg }; //异步执行 - Task.Run(() => OnPackMessage(this, arg)); + OnPackMessage(this, arg); } //粉丝团 @@ -524,7 +533,7 @@ namespace BarrageGrab switch (cmdPack.Cmd) { case CommandCode.Close: - this.Close(); + this.Dispose(); break; case CommandCode.EnableProxy: { @@ -566,7 +575,7 @@ namespace BarrageGrab public void Broadcast(BarrageMsgPack pack) { if (pack == null) return; - if (Appsetting.Current.PushFilter.Any() && !Appsetting.Current.PushFilter.Contains(pack.Type.GetHashCode())) return; + if (AppSetting.Current.PushFilter.Any() && !AppSetting.Current.PushFilter.Contains(pack.Type.GetHashCode())) return; var offLines = new List(); foreach (var item in socketList) @@ -590,20 +599,28 @@ namespace BarrageGrab /// public void StartListen() { - this.grab.Start(); //启动代理 - this.socketServer.Start(Listen);//启动监听 + try + { + this.grab.Start(); //启动代理 + this.socketServer.Start(Listen);//启动监听 + } + catch (Exception) + { + this.Dispose(); + throw; + } } /// /// 关闭服务器连接,并关闭系统代理 /// - public void Close() + public void Dispose() { socketList.Values.ToList().ForEach(f => f.Socket.Close()); socketList.Clear(); socketServer.Dispose(); grab.Dispose(); - + this.IsDisposed = true; this.OnClose?.Invoke(this, EventArgs.Empty); } @@ -658,6 +675,6 @@ namespace BarrageGrab /// 消息内容 /// public Msg Message { get; set; } - } + } } } diff --git a/BarrageGrab/WssBarrageGrab.cs b/BarrageGrab/WssBarrageGrab.cs index 4f524d0..4552e1a 100644 --- a/BarrageGrab/WssBarrageGrab.cs +++ b/BarrageGrab/WssBarrageGrab.cs @@ -19,7 +19,7 @@ namespace BarrageGrab { //ISystemProxy proxy = new FiddlerProxy(); ISystemProxy proxy = new TitaniumProxy(); - Appsetting appsetting = Appsetting.Current; + AppSetting appsetting = AppSetting.Current; /// /// 进入直播间 diff --git a/BarrageGrab/WssBarrageService.csproj b/BarrageGrab/WssBarrageService.csproj index 2eceb7c..ca3fd75 100644 --- a/BarrageGrab/WssBarrageService.csproj +++ b/BarrageGrab/WssBarrageService.csproj @@ -70,12 +70,20 @@ ..\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll + + ..\packages\Esprima.3.0.4\lib\net462\Esprima.dll + True + ..\packages\Fleck.1.2.0\lib\net45\Fleck.dll ..\packages\HtmlAgilityPack.1.11.51\lib\Net45\HtmlAgilityPack.dll + + ..\packages\Jint.3.0.1\lib\net462\Jint.dll + True + ..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll @@ -135,7 +143,8 @@ - + + Form @@ -149,6 +158,7 @@ RoomDetail.cs + @@ -167,7 +177,7 @@ - + @@ -178,6 +188,9 @@ + + PreserveNewest + Always diff --git a/BarrageGrab/packages.config b/BarrageGrab/packages.config index 2e56486..e0afd29 100644 --- a/BarrageGrab/packages.config +++ b/BarrageGrab/packages.config @@ -2,9 +2,10 @@ - + +