------ #### V1.0.2404.1201 - 新增支持手动运行规则。 - 规则播放时间间隔不再针对全局声效,而只针对当前规则声效。 - 修复规则中播放文件夹可能导致无法执行的BUG。 - 修复规则不勾选礼物和点赞,则无法执行的BUG。
448 lines
23 KiB
C#
448 lines
23 KiB
C#
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();
|
||
}
|
||
}
|
||
}
|