RyLiveTools/Source/FrmWeb.xaml.cs
如果当时 0ec1400de9 ### 2024-04-12更新
------
####  V1.0.2404.1201
- 新增支持手动运行规则。
- 规则播放时间间隔不再针对全局声效,而只针对当前规则声效。
- 修复规则中播放文件夹可能导致无法执行的BUG。
- 修复规则不勾选礼物和点赞,则无法执行的BUG。
2024-04-13 10:13:30 +08:00

448 lines
23 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
/// <summary>
/// FrmWeb.xaml 的交互逻辑
/// </summary>
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<MsgToken>(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<MsgToken>(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();
}
/// <summary>
/// 创建数据库
/// </summary>
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<MsgToken>(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<MsgToken>(new MsgToken(effectInfo) { ID = MsgTokenId.Effects, From = "Web", Msg = "Close" });
}
}
}
private void BtnHidden_Click(object sender, RoutedEventArgs e)
{
this.Hide();
}
}
}