using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Net.Mime; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Threading; using CefSharp; using CefSharp.Wpf; using CommunityToolkit.Mvvm.Messaging; using HandyControl.Controls; using HtmlAgilityPack; using LiveTools.Data; using Newtonsoft.Json.Linq; using ryCommon; using ryCommonDb; using rySafe; namespace LiveTools { /// /// FrmWeb.xaml 的交互逻辑 /// public partial class FrmWeb : HandyControl.Controls.Window { public FrmWeb() { InitializeComponent(); //2 设置定时器时间间隔 TimeSpan.FromSeconds(1) 以秒单位 timer.Interval = TimeSpan.FromMilliseconds(1000); //3 设置每隔时间要执行的方法 ,绑定方法到定时器上 //tick 是事件名, new System.EventHandler() 参数是方法名 timer.Tick += Timer_Tick; } public DirectInfo DirectInfo { get; set; } = new DirectInfo(); Hashtable hash_data = new System.Collections.Hashtable(); bool isRunning = false; //从图片地址获取图片字节数据 public byte[] GetImageFromResponse(string url, string? cookie = null) { try { System.Net.WebRequest request = System.Net.WebRequest.Create(url); if (!string.IsNullOrWhiteSpace(cookie)) { request.Headers[System.Net.HttpRequestHeader.Cookie] = cookie; } System.Net.WebResponse response = request.GetResponse(); using (Stream stream = response.GetResponseStream()) { using (MemoryStream ms = new MemoryStream()) { Byte[] buffer = new Byte[1024]; int current = 0; do { ms.Write(buffer, 0, current); } while ((current = stream.Read(buffer, 0, buffer.Length)) != 0); return ms.ToArray(); } } } catch (Exception ex) { Console.WriteLine(ex.Message); //throw new Exception(ex.Message); return null; } } private async void Timer_Tick(object? sender, EventArgs e) { if (isRunning) { return; } if(chromeBrowser.IsDisposed) { return; } isRunning = true; try { string source = await chromeBrowser.GetSourceAsync(); var th = new Thread(ScanSource); th.Start(); void ScanSource() { if (source != null) { HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument(); htmlDoc.LoadHtml(source); var list = htmlDoc.DocumentNode.SelectNodes("//div[@id='chatroom']//div[@class='webcast-chatroom___items']//div[contains(@class,'webcast-chatroom___item')]"); if (list != null && list.Count > 0) { for (int i = 0; i < list.Count; i++) { var item = list[i]; //if (item.InnerText.Length == 0) { continue; } if (item.InnerText.IndexOfEx("关注") > 0 && item.InnerText.IndexOfEx("点点关注") < 0) { } if (item.GetAttributeValue("class", "") == "webcast-chatroom__room-message") { continue; } var ContentType = "评论"; var isgift = false;//当前是否刷了礼物 var gift_count = 0; var data_id = item.GetAttributeValue("data-id", ""); if (data_id.Length == 0) { continue; } if (hash_data.ContainsKey(data_id)) { continue; } HtmlAgilityPack.HtmlDocument htmlItem = new HtmlAgilityPack.HtmlDocument(); htmlItem.LoadHtml(item.OuterHtml); var imgs = htmlItem.DocumentNode.SelectNodes("//img"); if (imgs != null && imgs.Count > 0) { for (int m = 0; m < imgs.Count; m++) { if (imgs[m].GetAttributeValue("alt", "").Length > 0) { imgs[m].InnerHtml = imgs[m].GetAttributeValue("alt", ""); } } } var content = htmlItem.GetAttr("//*[contains(@class,'webcast-chatroom___content')]", "", ""); var nickname = ""; var iPos = item.InnerText.IndexOf(":"); if (iPos > 0) { nickname = item.InnerText.Substring(0, iPos); } if (nickname.Length == 0) { nickname = item.GetAttr("//span[@class='webcast-chatroom___nickname']", "", ""); if (nickname.Length > 0 && content.Length == 0) { if (item.InnerText.StartsWith(nickname)) { ContentType = "加分"; content = item.InnerText.Substring(nickname.Length); } } } var action = item.GetAttr("//span[3]", "", ""); if (action == "来了") { continue; } if (action.IndexOfEx("为主播点赞") >= 0) { ContentType = "点赞"; } var gift_url = item.GetAttr("//span[contains(text(),'送出了')]//img", "src", ""); var giftFileName = ""; if (gift_url.Length > 0) { ContentType = "礼物"; var md5 = rySafe.MD5Sha1.GetMD5(gift_url.ToLower()); isgift = true; gift_count = item.GetAttr("//span[contains(text(),'送出了')]//img/following::span", "", "").Replace("×", "").Trim().ToInt(); if (Config.GiftTrigger) { EffectInfo effectInfo = new EffectInfo(); effectInfo.ID = DirectInfo.Id; effectInfo.LoopCount = gift_count; var picPath = ""; Ini ini = new Ini(Config.AllUserDbFolder+"\\Setting.ini"); var filename = ini.ReadIni("gift_md5", md5,""); if (System.IO.File.Exists(Config.AllUserDbFolder + "\\GiftImages\\Auto\\" + filename + ".png")) { picPath = Config.AllUserDbFolder + "\\GiftImages\\Auto\\" + filename + ".png"; } else { try { var bytes = GetImageFromResponse(gift_url); if (bytes != null) { var md5_byte = rySafe.MD5Sha1.GetMD5(bytes); filename = md5_byte; ini.WriteIni("gift_md5",md5, md5_byte); RyFiles.CreateDirectory(Config.AllUserDbFolder + "\\GiftImages\\Auto"); using (Config.GiftLock.Write()) { System.IO.File.WriteAllBytes(Config.AllUserDbFolder + "\\GiftImages\\Auto\\" + md5_byte + ".png", bytes); } picPath = Config.AllUserDbFolder + "\\" + md5_byte + ".png"; } } catch { continue; } } if(picPath.Length>0) { JObject jo = new JObject() { { "Name","Rule_ShowPic"}, { "Mode","ShowPic"}, { "PlaySound", Config.PlaySound}, { "PicPath",API.GetRelativePath(picPath) }, { "PicSize",Config.PicSize }, { "PicCount", Config.PicCount }, { "MultiPlaySound", Config.MultiPlaySound }, }; JArray jarr = new JArray(); jarr.Add(jo); effectInfo.ActionList = jarr; } giftFileName = filename + ".png"; //effectInfo.PicPath= WeakReferenceMessenger.Default.Send(new MsgToken(effectInfo) { ID = MsgTokenId.Effects, From = "Web", Msg = "222" }); } } IDbInterface db_logs = new SQLiteDataProvider(); db_logs.ConnDb(Config.UserDbFolder + "\\DirectLogs\\" + DirectInfo.Id + ".log.data"); if (nickname.Length > 0) { RyQuickSQL mySQL = new("Logs"); mySQL.AddField("DirectId", DirectInfo.DirectId); mySQL.AddField("NickName", nickname); mySQL.AddField("data_id", data_id);//送礼物的ID,防止重复记录 mySQL.AddField("ContentType", ContentType); if (content.Length == 0) { if (ContentType != "评论") { content = ContentType; } } if (isgift) { mySQL.AddField("Content", "送出礼物*"+ gift_count); } else { mySQL.AddField("Content", content); } mySQL.AddField("AddTime", DateTime.Now.ToInt64()); if (db_logs.Update(mySQL, "data_id=@data_id") == 0) { db_logs.Insert(mySQL); } if (giftFileName.Length > 0) { RyQuickSQL mySQL2 = new RyQuickSQL("GiftLogs"); mySQL2.AddField("DirectId", DirectInfo.DirectId); mySQL2.AddField("NickName", nickname); mySQL2.AddField("GiftFileName", giftFileName); mySQL2.AddField("data_id", data_id);//送礼物的ID,防止重复记录 mySQL2.AddField("GiftCount", gift_count);//礼物数量 mySQL2.AddField("AddTime", DateTime.Now.ToInt64()); if (db_logs.Update(mySQL2, "data_id=@data_id") == 0) { db_logs.Insert(mySQL2); } } } else { } db_logs.Free(); hash_data[data_id] = 1; IDbInterface db = new SQLiteDataProvider(); db.ConnDb(LiveTools.Config.DbFullPath); var ds = db.ReadData("select * from Rules order by SortIndex desc"); if (ds.HaveData()) { for (int r = 0; r < ds.Tables[0].Rows.Count; r++) { var row = ds.GetRow(r); JObject jo = JObject.Parse(row["RuleJson"].ToString() ?? ""); JArray jarr = jo.GetJsonValue("Content", new JArray()); var ismatch = false; if (jarr.Count > 0) { if (item.InnerText.Length > 0 || content.Length>0) { for (int j = 0; j < jarr.Count; j++) { if (item.InnerText.IndexOfEx(jarr[j].ToString()) >= 0 || content.IndexOfEx(jarr[j].ToString()) >= 0) { ismatch = true; break; } } } } else { ismatch = true; } if (ismatch) { var GiftTrigger=jo.GetJsonValue("GiftTrigger", false); var DianzanTrigger = jo.GetJsonValue("DianzanTrigger", false); var match2 = false; if((GiftTrigger && isgift)) { var GiftTriggerList = jo.GetJsonValue("GiftTriggerList", ""); if (GiftTriggerList.Length == 0 || ("|" + GiftTriggerList + "|").IndexOfEx("|" + giftFileName + "|") >= 0) { match2 = true; } } else if(DianzanTrigger && ContentType == "点赞") { match2 = true; } else if(!GiftTrigger && !DianzanTrigger)//功能都没开 { match2 = true; } ismatch = match2; } if (ismatch) { EffectInfo effectInfo = new EffectInfo(); effectInfo.ID = DirectInfo.Id; effectInfo.RuleID = row["id"].ToInt(); effectInfo.LoopCount = gift_count == 0 ? 1 : gift_count; effectInfo.ActionList = jo.GetJsonValue("ActionList", new JArray()); //HandyControl.Controls.MessageBox.Show(row["RuleName"].ToString()); WeakReferenceMessenger.Default.Send(new MsgToken(effectInfo) { ID = MsgTokenId.Effects, From = "Web", Msg = "222" }); break; } } } ds?.Dispose(); db.Free(); } } } isRunning = false; } } catch { isRunning = false; } } // 1 创建定时器 DispatcherTimer timer = new DispatcherTimer(); public ChromiumWebBrowser chromeBrowser; public void InitCef() { if (!Config.InitCef) { //参数设置 CefSettings settings = new CefSettings(); //settings.ResourcesDirPath = Config.GetCurrentFolder + "SysDb\\runtimes\\win-x64\\native\\"; settings.CachePath = Config.UserDbFolder + "\\WebCache"; settings.UserDataPath = Config.UserDbFolder + "\\WebUserData"; settings.PersistSessionCookies = true; settings.IgnoreCertificateErrors = true; // settings.Locale = "zh-CN"; // settings.CefCommandLineArgs.Add("disable-gpu", "1");//去掉gpu,否则chrome显示有问题 Cef.Initialize(settings); Config.InitCef = true; } //创建实例 chromeBrowser = new ChromiumWebBrowser("https://live.douyin.com/"+DirectInfo.DirectId+"?is_aweme_tied=1"); chromeBrowser.Initialized += ChromeBrowser_Initialized; // 将浏览器放入容器中 MainGrid.Children.Add(chromeBrowser); } private void ChromeBrowser_Initialized(object? sender, EventArgs e) { timer.Start(); } /// /// 创建数据库 /// public void CreateDb() { IDbInterface db = new SQLiteDataProvider(); if (db.ConnDb(Config.UserDbFolder + "\\DirectLogs\\"+ DirectInfo.Id+".log.data") == 1) { #region 日志表 RyQuickSQL mySQL = new("Logs"); mySQL.AddField("DirectId", ""); mySQL.AddField("NickName", ""); mySQL.AddField("data_id", "");//送礼物的ID,防止重复记录 mySQL.AddField("ContentType", ""); mySQL.AddField("Content", ""); mySQL.AddField("AddTime", 0L); db.CreateDb(mySQL); #endregion #region 礼物日志表 mySQL.Clear(); mySQL.TableName = "GiftLogs"; mySQL.AddField("DirectId", ""); mySQL.AddField("NickName", ""); mySQL.AddField("GiftFileName", ""); mySQL.AddField("data_id", "");//送礼物的ID,防止重复记录 mySQL.AddField("GiftCount", 0);//礼物数量 mySQL.AddField("AddTime", 0L); db.CreateDb(mySQL); #endregion // } db.Free(); } private void Window_Loaded(object sender, RoutedEventArgs e) { Title = DirectInfo.Name + "[" + DirectInfo.Platform + "]网页"; CreateDb(); InitCef(); WeakReferenceMessenger.Default.Register(this, OnReceive); //4 开启定时器 } private bool IsProcUse { get; set; } = false; private void OnReceive(object recipient, MsgToken message) { if (message.Value is EffectInfo) { if (message.Msg == "Close" && message.From == "Effects") { IsProcUse = true; this.Close(); return; } } } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if (!IsProcUse) { if (HandyControl.Controls.MessageBox.Show("关闭Web窗口,将导致当前直播特效功能也同步关闭,是否确定要关闭?", "关闭确认", MessageBoxButton.OKCancel) != MessageBoxResult.OK) { e.Cancel = true; } else { EffectInfo effectInfo = new EffectInfo(); effectInfo.ID = DirectInfo.Id; effectInfo.EffectMode = -1; WeakReferenceMessenger.Default.Send(new MsgToken(effectInfo) { ID = MsgTokenId.Effects, From = "Web", Msg = "Close" }); } } } private void BtnHidden_Click(object sender, RoutedEventArgs e) { this.Hide(); } } }