From ee1bb22e955867a65d83cc9e2fc9e5280eb8591c Mon Sep 17 00:00:00 2001 From: cmn Date: Thu, 27 Nov 2025 16:58:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TelegramService.Bl/CnblogsBl.cs | 241 ++++++ TelegramService.Bl/FundBl.cs | 158 ++++ TelegramService.Bl/SendMessageBl.cs | 55 ++ TelegramService.Bl/TelegramService.Bl.csproj | 14 + TelegramService.Bl/TieBaBl.cs | 174 ++++ TelegramService.Entity/Appsettings.cs | 74 ++ TelegramService.Entity/Db.cs | 28 + TelegramService.Entity/Entity/cnblogsList.cs | 69 ++ TelegramService.Entity/Entity/liYuanList.cs | 76 ++ TelegramService.Entity/Entity/tieba.cs | 55 ++ .../TelegramService.Entity.csproj | 13 + TelegramService.Help/EntrustHelper.cs | 13 + TelegramService.Help/ExtendHelper.cs | 745 ++++++++++++++++++ TelegramService.Help/HtmlTag.cs | 226 ++++++ TelegramService.Help/HttpHelper.cs | 244 ++++++ .../TelegramService.Help.csproj | 9 + TelegramService.slnx | 6 + TelegramService/Program.cs | 16 + .../Properties/launchSettings.json | 12 + TelegramService/TelegramService.csproj | 20 + TelegramService/Worker.cs | 175 ++++ TelegramService/appsettings.Development.json | 8 + TelegramService/appsettings.json | 16 + 23 files changed, 2447 insertions(+) create mode 100644 TelegramService.Bl/CnblogsBl.cs create mode 100644 TelegramService.Bl/FundBl.cs create mode 100644 TelegramService.Bl/SendMessageBl.cs create mode 100644 TelegramService.Bl/TelegramService.Bl.csproj create mode 100644 TelegramService.Bl/TieBaBl.cs create mode 100644 TelegramService.Entity/Appsettings.cs create mode 100644 TelegramService.Entity/Db.cs create mode 100644 TelegramService.Entity/Entity/cnblogsList.cs create mode 100644 TelegramService.Entity/Entity/liYuanList.cs create mode 100644 TelegramService.Entity/Entity/tieba.cs create mode 100644 TelegramService.Entity/TelegramService.Entity.csproj create mode 100644 TelegramService.Help/EntrustHelper.cs create mode 100644 TelegramService.Help/ExtendHelper.cs create mode 100644 TelegramService.Help/HtmlTag.cs create mode 100644 TelegramService.Help/HttpHelper.cs create mode 100644 TelegramService.Help/TelegramService.Help.csproj create mode 100644 TelegramService.slnx create mode 100644 TelegramService/Program.cs create mode 100644 TelegramService/Properties/launchSettings.json create mode 100644 TelegramService/TelegramService.csproj create mode 100644 TelegramService/Worker.cs create mode 100644 TelegramService/appsettings.Development.json create mode 100644 TelegramService/appsettings.json diff --git a/TelegramService.Bl/CnblogsBl.cs b/TelegramService.Bl/CnblogsBl.cs new file mode 100644 index 0000000..1b94099 --- /dev/null +++ b/TelegramService.Bl/CnblogsBl.cs @@ -0,0 +1,241 @@ + + +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Data; +using System.Net; +using System.Threading.Tasks; +using TelegramService.Bl; +using TelegramService.Entity; +using TelegramService.Help; +namespace TelegramServiceV6.Bl +{ + public class CnblogsBl + { + + /// + /// 发送 消息 + /// + private async void SendTextMessage(string title, string author, string authorUrl, string time, string preview, string url) + { + try + { + string sHtml = "\r\n主 题:" + title + "\n"; + sHtml += "作 者:" + author + "\n"; + sHtml += "时 间:" + time + "\n"; + sHtml += "预 览:" + preview + "\n"; + sHtml += "链 接:" + url + "\n"; + JObject oObj = new JObject(); + oObj.Add("chat_id", "-1001341062469"); + oObj.Add("text", sHtml); + oObj.Add("parse_mode", "HTML"); + //是否显示url 预览 + oObj.Add("disable_web_page_preview", "TRUE"); + SendMessageBl.SendWx("https://api.telegram.org/bot1879430057:AAHtwdwHLH0a7cNjTPBQsI92ivoKZI6P-5A/sendMessage", oObj.ToString()); + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[CnblogsBl.SendTextMessage] " + ex.Message); + } + } + + + /// + /// 发送微信 + /// + /// + /// + /// + /// + /// + /// + private void SendWeixin(string title, string author, string authorUrl, string time, string preview, string url) + { + + string sHtml = "主 题:" + title + "\n"; + sHtml += "作 者:" + author + "\n"; + sHtml += "时 间:" + time + "\n"; + sHtml += "预 览:" + preview + "\n"; + sHtml += "链 接:" + url + "\n"; + JObject oObj = new JObject(); + oObj.Add("text", sHtml); + + SendMessageBl.SendWx("https://111.230.99.204/weixin/api/send_text", oObj.ToString()); + + } + + /// + /// 获取博客内容 + /// + public async Task GetCnblogsHtml() + { + try + { + if (DateTime.Now.Hour < 6) + { + EntrustHelper.STCB("show", "[CnblogsBl.GetCnblogsHtml] 晚上0-6点不执行!"); + return; + } + + EntrustHelper.STCB("show", "[CnblogsBl.GetCnblogsHtml] 开始执行!"); + string shtml =await GetHtml(); + + if (shtml.IsNullOrWhiteSpace()) + { + EntrustHelper.STCB("show", "[CnblogsBl.GetCnblogsHtml] 获取不到数据!"); + return; + } + List listHtmlTag = HtmlTag.FindTagByAttr(shtml, "div", "id", "post_list"); + + List listObj = null; + + if (listHtmlTag.Count > 0) + { + listHtmlTag = listHtmlTag[0].FindTag("article"); + } + string stitle = ""; + string sauthor = ""; + string sauthorUrl = ""; + string stime = ""; + string spreview = ""; + string surl = ""; + int iCount = listHtmlTag.Count; + for (int i = 1; i <= listHtmlTag.Count; i++) + { + try + { + listObj = listHtmlTag[iCount - i].FindTagByAttr("a", "class", "post-item-title"); + stitle = listObj[0].InnerText; + surl = listObj[0].GetAttribute("href"); + + listObj = listHtmlTag[iCount - i].FindTagByAttr("p", "class", "post-item-summary"); + spreview = listObj[0].InnerText.Trim(); + + listObj = listHtmlTag[iCount - i].FindTagByAttr("a", "class", "post-item-author"); + sauthor = listObj[0].InnerText.Trim(); + sauthorUrl = listObj[0].GetAttribute("href"); + + listObj = listHtmlTag[iCount - i].FindTagByAttr("span", "class", "post-meta-item"); + stime = listObj[0].FindTag("span")[0].InnerHTML; + + if (!IsExistUrl(surl)) + { + //写入数据库 + SetCnblogsDB(stitle, sauthor, sauthorUrl, stime, spreview, surl); + //发送TG消息 + SendTextMessage(stitle, sauthor, sauthorUrl, stime, spreview, surl); + //发送微信 + SendWeixin(stitle, sauthor, sauthorUrl, stime, spreview, surl); + } + else + { + continue; + } + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[CnblogsBl.GetCnblogsHtml] " + ex.Message); + } + } + + listHtmlTag.Clear(); + listObj.Clear(); + EntrustHelper.STCB("show", "[CnblogsBl.GetCnblogsHtml] 执行结束!"); + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[CnblogsBl.GetCnblogsHtml] " + ex.Message); + } + finally + { + EntrustHelper.STCB("InitTimer", Appsettings.Conf.Interval); + } + + } + + /// + /// 判断是否存在 true=存在 false=不存在 + /// + /// + /// + private bool IsExistUrl(string url) + { + try + { + int iCount = 0; + iCount = Db.dbConnection.Queryable().Where(it => it.url == url).Count(); + if (iCount == 1) + { + return true; + } + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[CnblogsBl.IsExistUrl] " + ex.Message); + } + return false; + } + + /// + /// 写入 数据库 + /// + /// + /// + /// + /// + /// + /// + /// + private int SetCnblogsDB(string title, string author, string authorUrl, string time, string preview, string url) + { + string sSql = ""; + int iCount = 0; + cnblogsList encnblogsList = new cnblogsList(); + encnblogsList.url = url; + encnblogsList.title = title; + encnblogsList.preview = preview; + encnblogsList.author = author; + encnblogsList.authorUrl = authorUrl; + encnblogsList.time = time; + encnblogsList.addTime = DateTime.Now; + iCount = Db.dbConnection.Insertable(encnblogsList).ExecuteCommand(); + return iCount; + } + + /// + /// 获取html + /// + /// + private async Task GetHtml() + { + try + { + HttpResult httpResult = null; + string html = ""; + for (int i = 0; i < 5; i++) + { + httpResult =await HttpHelper.GetAsync("https://www.cnblogs.com/"); + if (httpResult.StatusCode == 200) + { + if (httpResult.Html.IndexOfStr("id=\"post_list\"")) + { + return httpResult.Html; + } + } + } + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[CnblogsBl.GetHtml] " + ex.Message); + } + return null; + } + + + } + + +} + + diff --git a/TelegramService.Bl/FundBl.cs b/TelegramService.Bl/FundBl.cs new file mode 100644 index 0000000..cec1641 --- /dev/null +++ b/TelegramService.Bl/FundBl.cs @@ -0,0 +1,158 @@ +using Newtonsoft.Json.Linq; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using TelegramService.Help; +using TelegramService.Entity; +using TelegramService.Help; +using System.Threading.Tasks; + +namespace TelegramServiceV6.Bl +{ + public class FundBl + { + + /// + /// 发送微信 + /// + /// + /// + /// + /// + /// + /// + public static void SendWeixinFund() + { + SendWeixinFundEastmoney(); + } + + /// + /// 发送微信 http://fund.eastmoney.com/ 天天基金 + /// + /// + /// + /// + /// + /// + /// + public static async Task SendWeixinFundEastmoney() + { + + try + { + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] 开始发送基金"); + string code = string.Join(",", Appsettings.Conf.Fund); + + Dictionary form = new Dictionary(); + form.Add("fcodes", code); + + Dictionary header = new Dictionary(); + header.Add("Origin", "https://favor.fund.eastmoney.com"); + header.Add("Referer", "https://favor.fund.eastmoney.com/"); + + HttpResult httpResult = null; + string html = ""; + for (int i = 0; i < 6; i++) + { + try + { + httpResult = await HttpHelper.PostFormAsync("https://api.fund.eastmoney.com/favor/GetFundsInfo?", form, header); + if (httpResult.StatusCode == 200) + { + html = httpResult.Html; + break; + } + } + catch (Exception) + { + } + } + if (html.IsNull()) + { + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] 开始发送基金,请求失败"); + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] "+html); + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] 开始发送基金,请求失败"); + return; + } + + JObject jsdata = JObject.Parse(html); + if (jsdata["ErrCode"].ToString() != "0") + { + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney1] "+jsdata.ToString()); + return; + } + StringBuilder sb = new StringBuilder(); + StringBuilder sb1 = new StringBuilder(); + sb1.Append("---------------------------------\n"); + int index = 0; + foreach (var data in jsdata["Data"]["KFS"]) + { + if (!code.Contains(data["FCODE"].ToString())) + { + continue; + } + if (data["RZDF"].ToDouble() >= 0) + { + if (sb.Length > 0) sb.Append("---------------------------------\n"); + + sb.Append(data["FSRQ"] + " (" + data["FCODE"].ToString() + ")\n"); + sb.Append(data["SHORTNAME"] + "\n"); + sb.Append(data["RZDF"] + "\n"); + } + else + { + sb1.Append("---------------------------------\n"); + sb1.Append(data["FSRQ"] + " (" + data["FCODE"].ToString() + ")\n"); + sb1.Append(data["SHORTNAME"] + "\n"); + sb1.Append(data["RZDF"] + "\n"); + } + index++; + } + + for (int i = 0; i < 2; i++) + { + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] 请求微信api接口"); + httpResult=await HttpHelper.GetAsync("https://111.230.99.204/weixin/api/msgyq?id=CaiMengNan&text=" + sb.ToString() + sb1.ToString()); + if (httpResult.StatusCode==200 && httpResult.Html.IndexOfStr("\"errmsg\":\"ok\"")) + { + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] 发送基金成功"); + return; + } + } + + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] "+ex.Message); + } + finally + { + try + { + DateTime now = DateTime.Now; + DateTime next22 = new DateTime(now.Year, now.Month, now.Day, 22, 0, 0); + // 如果现在已经过了今天的 22:00,则计算明天的 22:00 + if (now >= next22) + { + next22 = next22.AddDays(1); + } + double millisecondsUntilNext22 = (next22 - now).TotalMilliseconds; + + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] 等待下次执行"); + EntrustHelper.STCB("sendWeixinFund", millisecondsUntilNext22); + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[FundBl.SendWeixinFundEastmoney] " + ex.Message); + + } + } + } + + } +} + + diff --git a/TelegramService.Bl/SendMessageBl.cs b/TelegramService.Bl/SendMessageBl.cs new file mode 100644 index 0000000..2c03921 --- /dev/null +++ b/TelegramService.Bl/SendMessageBl.cs @@ -0,0 +1,55 @@ +using NetTaste; +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using TelegramService.Help; + +namespace TelegramService.Bl +{ + public class SendMessageBl + { + + + + public static async Task SendWx(string url,string msg) + { + HttpResult httpResult; + for (int i = 0; i < 2; i++) + { + httpResult = await HttpHelper.PostJsonAsync(url, msg); + if (httpResult.StatusCode != 200) + { + continue; + } + if (httpResult.Html.IndexOfStr("\"errmsg\":\"ok\"")) + { + return true; + } + } + return false; + } + + + public static async Task SendTg(string url,string msg) + { + HttpResult httpResult = null; + for (int i = 0; i < 2; i++) + { + httpResult = await HttpHelper.PostJsonAsync(url, msg); + if (httpResult.StatusCode != 200) + { + continue; + } + if (httpResult.Html.IndexOfStr("\"ok\":true,")) + { + return true; + } + } + return false; + } + + + + } +} diff --git a/TelegramService.Bl/TelegramService.Bl.csproj b/TelegramService.Bl/TelegramService.Bl.csproj new file mode 100644 index 0000000..7636d41 --- /dev/null +++ b/TelegramService.Bl/TelegramService.Bl.csproj @@ -0,0 +1,14 @@ + + + + net10.0 + enable + enable + + + + + + + + diff --git a/TelegramService.Bl/TieBaBl.cs b/TelegramService.Bl/TieBaBl.cs new file mode 100644 index 0000000..2e8320c --- /dev/null +++ b/TelegramService.Bl/TieBaBl.cs @@ -0,0 +1,174 @@ + +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Net; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web; +using TelegramService.Bl; +using TelegramService.Entity; +using TelegramService.Help; + +namespace TelegramServiceV6.Bl +{ + public class TieBaBl + { + + + /// + /// 发送 消息 + /// + private void SendTextMessage(string title, string sType, string stime, string surl) + { + try + { + + string sHtml = "\r\n标 题:" + title + "\n"; + sHtml += "类 型:" + sType + "\n"; + sHtml += "入库时间:" + stime + "\n"; + sHtml += "链 接:" + surl + "\n"; + JObject oObj = new JObject(); + oObj.Add("chat_id", "-1001523898048"); + oObj.Add("text", sHtml); + oObj.Add("parse_mode", "HTML"); + //是否显示url 预览 + oObj.Add("disable_web_page_preview", "TRUE"); + SendMessageBl.SendTg("https://api.telegram.org/bot1918024418:AAHj_RNtA-XkWbodtzkzaTIxc0XYxBVoQKY/sendMessage", oObj.ToString()); + + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[TieBaBl.SendTextMessage] " + ex.Message); + } + } + + /// + /// 获取贴吧 + /// + public async void GetTieBaHtml() + { + try + { + + EntrustHelper.STCB("show", "[TieBaBl.GetTieBaHtml1] 开始执行!"); + + HttpResult httpResult = null; + + foreach (var tk in Appsettings.Conf.TieBa) + { + string key = tk.ToString(); + string encodedUrl = HttpUtility.UrlEncode(key); + string shtml = null; + string tiebaUrl = "https://tieba.baidu.com/mo/m?kw=" + encodedUrl.ToUpper() + "&lm=&pn=0"; + + for (int i = 0; i < 3; i++) + { + httpResult =await HttpHelper.GetAsync(tiebaUrl); + if (httpResult.StatusCode == 200) + { + shtml = httpResult.Html; + break; + } + } + if (shtml.IsNullOrWhiteSpace()) + { + EntrustHelper.STCB("show", "[TieBaBl.GetTieBaHtml2] 获取不到数据!"); + return; + } + List listHtmlTag = HtmlTag.FindTagByAttr(shtml, "ul", "id", "frslistcontent"); + List lista = null; + if (listHtmlTag.Count == 0) + { + EntrustHelper.STCB("show", "[TieBaBl.GetTieBaHtml3] 贴吧html匹配不到div!"); + return; + } + listHtmlTag = listHtmlTag[0].FindTagByAttr("li", "class", "tl_shadow tl_shadow_new "); + for (int i = 0; i < listHtmlTag.Count; i++) + { + try + { + lista = listHtmlTag[i].FindTag("a"); + if (lista.Count == 0) + { + continue; + } + string url = lista[0].GetAttribute("href"); + string id = Regex.Match(url, @"(?is)/p/(?.*?)s*\?").Groups["value"].Value; + if (id.IsNull()) + { + continue; + } + lista = lista[0].FindTagByAttr("div", "class", "ti_title"); + if (lista.Count <= 0) + { + continue; + } + string title = lista[0].InnerText; + if (title.Contains(" ")) + { + string[] arr = title.SplitRemoveEmptyEntries(" "); + if (arr.Length > 1) + { + title = arr[1]; + } + } + tieba tb = new tieba(); + tb.id = id; + tb.title = title; + if (tb.title.Length > 149) + { + tb.title = tb.title.Substring(0, 149); + } + tb.key = key; + tb.url = "tieba.baidu.com/p/" + tb.id; + tb.sysaddtime = DateTime.Now; + if (SetTieBaDB(tb) > 0) + { + SendTextMessage(tb.title, tb.key, tb.sysaddtime.ToDateStr(), "https://" + tb.url); + } + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[TieBaBl.GetTieBaHtml4] " + ex.Message); + } + } + listHtmlTag.Clear(); + lista.Clear(); + Thread.Sleep(5000); + } + EntrustHelper.STCB("show", "[TieBaBl.GetTieBaHtml5] 执行结束!"); + } + catch (Exception) + { + } + finally + { + EntrustHelper.STCB("InitTimerTieBa", Appsettings.Conf.IntervalTieBa); + } + + } + + + /// + /// 写入 数据库 + /// + /// + private int SetTieBaDB(tieba tb) + { + try + { + var x = Db.dbConnection.Storageable(tb).ToStorage(); + x.AsInsertable.ExecuteCommand();//不存在插入 + return x.InsertList.Count; + } + catch (Exception ex) + { + EntrustHelper.STCB("show", "[TieBaBl.SetTieBaDB] " + ex.Message); + } + return 0; + } + } +} diff --git a/TelegramService.Entity/Appsettings.cs b/TelegramService.Entity/Appsettings.cs new file mode 100644 index 0000000..1b53ae3 --- /dev/null +++ b/TelegramService.Entity/Appsettings.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TelegramService.Entity +{ + public class Appsettings + { + public static AppsettingsRoot Conf = null; + } + + + + public class LogLevel + { + /// + /// + /// + public string Default { get; set; } + /// + /// + /// + public string MicrosoftHostingLifetime { get; set; } + } + + public class Logging + { + /// + /// + /// + public LogLevel LogLevel { get; set; } + } + + public class ConnectionStrings + { + /// + /// + /// + public string DBConnection { get; set; } + } + + public class AppsettingsRoot + { + /// + /// + /// + public Logging Logging { get; set; } + /// + /// + /// + public ConnectionStrings ConnectionStrings { get; set; } + /// + /// + /// + public int Interval { get; set; } + /// + /// + /// + public int IntervalLiYuan { get; set; } + /// + /// + /// + public int IntervalTieBa { get; set; } + /// + /// + /// + public List Fund { get; set; } + /// + /// + /// + public List TieBa { get; set; } + } + +} diff --git a/TelegramService.Entity/Db.cs b/TelegramService.Entity/Db.cs new file mode 100644 index 0000000..8a58179 --- /dev/null +++ b/TelegramService.Entity/Db.cs @@ -0,0 +1,28 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Text; + +namespace TelegramService.Entity +{ + public class Db + { + + /// + /// 数据库连接 + /// + public static SqlSugarClient dbConnection + { + get + { + + return new SqlSugarClient(new ConnectionConfig() + { + ConnectionString = Appsettings.Conf.ConnectionStrings.DBConnection,//连接符字串 + DbType = SqlSugar.DbType.MySql, //数据库类型 + IsAutoCloseConnection = true //不设成true要手动close + }); + } + } + } +} diff --git a/TelegramService.Entity/Entity/cnblogsList.cs b/TelegramService.Entity/Entity/cnblogsList.cs new file mode 100644 index 0000000..42114fd --- /dev/null +++ b/TelegramService.Entity/Entity/cnblogsList.cs @@ -0,0 +1,69 @@ +using System; +using System.Linq; +using System.Text; +using SqlSugar; + +namespace TelegramService.Entity +{ + /// + /// + /// + [SugarTable("cnblogsList")] + public partial class cnblogsList + { + public cnblogsList(){ + + + } + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(IsPrimaryKey=true)] + public string url {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string title {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string preview {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string author {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string authorUrl {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string time {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public DateTime? addTime {get;set;} + + } +} diff --git a/TelegramService.Entity/Entity/liYuanList.cs b/TelegramService.Entity/Entity/liYuanList.cs new file mode 100644 index 0000000..5f28d73 --- /dev/null +++ b/TelegramService.Entity/Entity/liYuanList.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; +using System.Text; +using SqlSugar; + +namespace TelegramService.Entity +{ + /// + /// + /// + [SugarTable("liYuanList")] + public partial class liYuanList + { + public liYuanList(){ + + + } + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(IsPrimaryKey=true)] + public int tid {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string title {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string type {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string author {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public DateTime? time {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string url {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public string slug {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:True + /// + public DateTime? addtime {get;set;} + + } +} diff --git a/TelegramService.Entity/Entity/tieba.cs b/TelegramService.Entity/Entity/tieba.cs new file mode 100644 index 0000000..78bafb1 --- /dev/null +++ b/TelegramService.Entity/Entity/tieba.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using System.Text; +using SqlSugar; + +namespace TelegramService.Entity +{ + /// + ///贴吧 + /// + [SugarTable("tieba")] + public partial class tieba + { + public tieba(){ + + + } + /// + /// Desc:那个贴吧 + /// Default: + /// Nullable:False + /// + public string key {get;set;} + + /// + /// Desc:url的id + /// Default: + /// Nullable:False + /// + [SugarColumn(IsPrimaryKey=true)] + public string id {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + public string url {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + public string title {get;set;} + + /// + /// Desc: + /// Default:CURRENT_TIMESTAMP + /// Nullable:False + /// + public DateTime sysaddtime {get;set;} + + } +} diff --git a/TelegramService.Entity/TelegramService.Entity.csproj b/TelegramService.Entity/TelegramService.Entity.csproj new file mode 100644 index 0000000..08fa9c5 --- /dev/null +++ b/TelegramService.Entity/TelegramService.Entity.csproj @@ -0,0 +1,13 @@ + + + + net10.0 + enable + enable + + + + + + + diff --git a/TelegramService.Help/EntrustHelper.cs b/TelegramService.Help/EntrustHelper.cs new file mode 100644 index 0000000..5d9c4ee --- /dev/null +++ b/TelegramService.Help/EntrustHelper.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TelegramService.Help +{ + public class EntrustHelper + { + public delegate object SetTextcallBack(string action, object obj); + public static SetTextcallBack STCB; + + } +} diff --git a/TelegramService.Help/ExtendHelper.cs b/TelegramService.Help/ExtendHelper.cs new file mode 100644 index 0000000..4e79618 --- /dev/null +++ b/TelegramService.Help/ExtendHelper.cs @@ -0,0 +1,745 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; + +namespace TelegramService.Help +{ + public static class ExtendHelper + { + #region Exception 错误扩展 + + /// + /// 获取 错误信息 + /// + /// + /// + public static string StackTrace(this Exception s, string str = null) + { + StackTrace st = new StackTrace(s, true); + //Get the first stack frame + // StackFrame frame = st.GetFrames().Last(); + StackFrame frame = st.GetFrame(0); + StringBuilder sb = new StringBuilder(); + sb.Append("\n===================================错误文件==========================================================\r\n"); + sb.Append(frame.GetFileName() + "\r\n"); + sb.Append("===================================错误类============================================================\r\n"); + sb.Append("[" + Path.GetFileNameWithoutExtension(frame.GetFileName()) + "][" + frame.GetMethod().Name + "][" + frame.GetFileLineNumber() + "]" + "\r\n"); + sb.Append("===================================错误内容==========================================================\r\n"); + sb.Append(s.ToString() + "\r\n"); + if (str.IsNotNull()) + { + sb.Append("===================================备注==============================================================\r\n"); + sb.Append(str + "\r\n"); + } + sb.Append("=====================================================================================================\r\n"); + return sb.ToString(); + } + + /// + /// 获取 位置信息 + /// + /// + public static string getStackTrace() + { + StackTrace st = new StackTrace(true); + StackFrame frame = st.GetFrame(1); + StringBuilder sb = new StringBuilder(); + if (frame != null) + { + sb.Append("[" + Path.GetFileNameWithoutExtension(frame.GetFileName()) + "][" + frame.GetMethod().Name + "][" + frame.GetFileLineNumber() + "]"); + } + return sb.ToString(); + } + + /// + /// 获取 位置信息 + /// + /// + /// + public static string StackTrace(this string s) + { + StackTrace st = new StackTrace(true); + StackFrame frame = st.GetFrame(1); + StringBuilder sb = new StringBuilder(); + sb.Append(s); + if (frame != null) + { + sb.Append("[" + Path.GetFileNameWithoutExtension(frame.GetFileName()) + "][" + frame.GetMethod().Name + "][" + frame.GetFileLineNumber() + "]"); + } + + return sb.ToString(); + } + + #endregion + + + #region int + + /// + /// 转换指定时间得到对应的时间戳 + /// true 则生成13位的时间戳, + /// false 则生成10位的时间戳,默认为 true + /// + /// + /// 精度(毫秒)设置 true,则生成13位的时间戳;精度(秒)设置为 false,则生成10位的时间戳;默认为 true + /// 返回对应的时间戳 + public static long ToTimeStamp(this DateTime s, bool isLongTime = true) + { + var ts = s.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return isLongTime ? Convert.ToInt64(ts.TotalMilliseconds) : Convert.ToInt64(ts.TotalSeconds); + } + + + /// + /// 取整 有小数进1 + /// + /// + /// + /// + public static int ToInteger(this double d) + { + return Math.Ceiling(d).ToInt32(); + } + /// + /// 转换为int + /// + /// + /// + public static int ToInt32(this string s) + { + return Convert.ToInt32(s); + } + /// + /// 转换为Double + /// + /// + /// + public static double ToDouble(this string s) + { + return Convert.ToDouble(s); + } + /// + /// 转换为int + /// + /// + /// + public static int ToInt32(this object s) + { + return Convert.ToInt32(s); + } + + #endregion + + #region bool + + + /// + /// 判断是否 包含 字符串 true 包含 false 不包含 + /// + /// + /// + public static bool IndexOfStr(this string[] s, string sStr) + { + foreach (var item in s) + { + if (item.IndexOf(sStr) > -1) + { + return true; + } + } + return false; + } + /// + /// 判断是否 存在 字符串 true 存在 false 不存在 + /// + /// + /// + public static bool IndexToStr(this string[] s, string sStr) + { + foreach (var item in s) + { + if (item == sStr) + { + return true; + } + } + return false; + } + + + /// + /// 判断 为空 + /// + /// + /// + public static bool IsNull(this string s) + { + return string.IsNullOrWhiteSpace(s); + } + /// + /// 判断 为空 + /// + /// + /// + public static bool IsNullOrWhiteSpace(this string s) + { + return string.IsNullOrWhiteSpace(s); + } + + /// + /// 判断 不为空 + /// + /// + /// + public static bool IsNotNull(this string s) + { + return !string.IsNullOrWhiteSpace(s); + } + /// + /// 判断 不为空 + /// + /// + /// + public static bool IsNotNullOrNotWhiteSpace(this string s) + { + return !string.IsNullOrWhiteSpace(s); + } + + /// + /// 判断是否 包含 字符串 true 包含 false 不包含 + /// + /// + /// + /// + public static bool IndexOfStr(this string s, string sStr) + { + if (s.IndexOf(sStr) > -1) + { + return true; + } + return false; + } + + /// + /// 判断是否 包含 字符串 true 包含 false 不包含 或关系 + /// + /// + /// + /// + public static bool IndexOfStrOr(this string s, params string[] sArrStr) + { + + for (int i = 0; i < sArrStr.Length; i++) + { + if (s.IndexOf(sArrStr[i]) > -1) + { + return true; + } + } + return false; + } + + + + /// + /// 判断是否 包含 字符串 true 包含 false 不包含 和关系 + /// + /// + /// + /// + public static bool IndexOfStrAnd(this string s, params string[] sArrStr) + { + for (int i = 0; i < sArrStr.Length; i++) + { + if (s.IndexOf(sArrStr[i]) == -1) + { + return false; + } + } + return true; + } + + /// + /// 判断是否 包含 字符串 true 包含 false 不包含 和关系 + /// + /// + /// + /// + public static bool And(this string s, params string[] sArrStr) + { + for (int i = 0; i < sArrStr.Length; i++) + { + if (!s.Contains(sArrStr[i])) + { + return false; + } + } + return true; + } + + + /// + /// 判断是否 包含 字符串 true 包含 false 不包含 和关系 + /// + /// + /// + /// + public static bool Or(this string s, params string[] sArrStr) + { + for (int i = 0; i < sArrStr.Length; i++) + { + if (s.Contains(sArrStr[i])) + { + return true; + } + } + return false; + } + + #endregion + + #region DateTime + + + + + /// + /// 字符串转换为 时间 + /// + /// + /// + public static DateTime ToDateTime(this object s) + { + return Convert.ToDateTime(s); + } + /// + /// 字符串转换为 时间 + /// + /// + /// + public static DateTime ToDateTime(this string s) + { + return Convert.ToDateTime(s); + } + /// + /// 时间戳转为C#格式时间 + /// + /// + /// + public static DateTime ToDateTimeByStamp(this string timeStamp) + { + DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + long lTime; + if (timeStamp.Length.Equals(10))//判断是10位 + { + lTime = long.Parse(timeStamp + "0000000"); + } + else + { + lTime = long.Parse(timeStamp + "0000");//13位 + } + TimeSpan toNow = new TimeSpan(lTime); + DateTime daTime = dtStart.Add(toNow); + return daTime; + + } + #endregion + + #region double + + /// + /// 带小数点数字匹配 + /// + /// + /// + public static double MatchingNumber(this string s) + { + string s1 = Regex.Replace(s, @"[^\d.\d]", ""); + if (s1.IsNotNull()) + { + return s1.ToDouble(); + } + return 0; + } + /// + /// 保留小数点 不四舍五入 + /// + /// + /// + /// + public static double NotRound(this double d, int decimals) + { + if (decimals == 0) + { + return (int)d; + } + string sStr = "1"; + for (int i = 0; i < decimals; i++) + { + sStr += "0"; + } + decimals = Convert.ToInt32(sStr); + return Math.Floor(d * decimals) / decimals; + } + + /// + /// 实现数据的四舍五入法 + /// + /// 要进行处理的数据 + /// 保留的小数位数 + /// 四舍五入后的结果 + public static double Round(this double v, int x) + { + bool isNegative = false; + //如果是负数 + if (v < 0) + { + isNegative = true; + v = -v; + } + int IValue = 1; + for (int i = 1; i <= x; i++) + { + IValue = IValue * 10; + } + double Int = Math.Round(v * IValue + 0.5, 0); + v = Int / IValue; + + if (isNegative) + { + v = -v; + } + return v; + } + + /// + /// 获取百分比 iCount=总数 + /// + /// + /// + /// + public static double getProportion(this double d, double iCount) + { + + try + { + double dc = Math.Round((d / iCount) * 100, 2); + if (double.IsNaN(dc)) + { + return 0; + } + return dc; + } + catch (Exception) + { + } + return 0; + } + + /// + /// 获取百分比 iCount=总数 + /// + /// + /// + /// + public static double getProportion(this int d, double iCount) + { + + try + { + double dc = Math.Round((d / iCount) * 100, 2); + if (double.IsNaN(dc)) + { + return 0; + } + return dc; + } + catch (Exception) + { + } + return 0; + } + + + /// + /// 转换为 double + /// + /// + /// + /// + public static double ToDouble(this object d) + { + return Convert.ToDouble(d); + } + + #endregion + + #region string + /// + /// url 编码 + /// + /// + /// + /// + public static string ToUrlEncode(this object s, Encoding e = null) + { + return ToUrlEncode(s.ToString(), e); + } + + /// + /// url 编码 + /// + /// + /// + /// + public static string ToUrlEncode(this string s, Encoding e = null) + { + if (e == null) e = Encoding.UTF8; + return System.Web.HttpUtility.UrlEncode(s, e); + + } + + + /// + /// 数字 千位分隔符 + /// + /// + /// + public static string ToThousandsSeparator(this double s) + { + return s.ToString("N0"); + } + + /// + /// 数字 千位分隔符 + /// + /// + /// + public static string ToThousandsSeparator(this int s) + { + return s.ToString("N0"); + } + + + /// + /// 将c# DateTime时间格式转换为Unix时间戳格式 13位 + /// + /// 时间 + /// long + public static string ToTimeStamp13(this System.DateTime time) + { + System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0)); + long t = (time.Ticks - startTime.Ticks) / 10000; //除10000调整为13位 + return t.ToString(); + } + /// + /// 将c# DateTime时间格式转换为Unix时间戳格式 10位 + /// + /// 时间 + /// long + public static string ToTimeStamp10(this System.DateTime time) + { + DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0); + int timeStamp = Convert.ToInt32((time - dateStart).TotalSeconds); + return timeStamp.ToString(); ; + } + + + + /// + /// 截取字符串 过滤空格 + /// + /// + /// + public static string[] SplitRemoveEmptyEntries(this string s, params string[] arr) + { + try + { + if (string.IsNullOrWhiteSpace(s)) + { + return new string[] { }; + } + return s.Split(arr, StringSplitOptions.RemoveEmptyEntries); + } + catch (Exception) + { + return new string[] { }; + } + } + + /// + /// 过滤sql 特殊符号 + /// + /// + /// + public static string ReplaceSQLChar(this string str) + { + if (str == String.Empty) + return String.Empty; + str = str.Replace("'", ""); + str = str.Replace("<", ""); + str = str.Replace(">", ""); + str = str.Replace("@", ""); + str = str.Replace("=", ""); + str = str.Replace("+", ""); + str = str.Replace("*", ""); + str = str.Replace("&", ""); + str = str.Replace("#", ""); + str = str.Replace("%", ""); + str = str.Replace("$", ""); + + //删除与数据库相关的词 + str = Regex.Replace(str, "select", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "insert", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "delete from", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "count", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "drop table", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "truncate", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "asc", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "mid", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "char", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "xp_cmdshell", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "exec master", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "net localgroup administrators", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "and", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "net user", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "or", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "net", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "-", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "delete", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "drop", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "script", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "update", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "and", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "chr", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "master", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "truncate", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "declare", "", RegexOptions.IgnoreCase); + str = Regex.Replace(str, "mid", "", RegexOptions.IgnoreCase); + + return str; + } + + + /// + /// 将DateTime 格式转换为 yyyy-MM-dd HH:mm:ss + /// + /// + /// + public static string ToDateStr(this DateTime d) + { + return d.ToString("yyyy-MM-dd HH:mm:ss"); + } + /// + /// 将DateTime 格式转换为 yyyy-MM-dd HH:mm:ss + /// + /// + /// + public static string ToDateStr(this DateTime? d) + { + return Convert.ToDateTime(d).ToString("yyyy-MM-dd HH:mm:ss"); + } + + /// + /// Md5 加密 + /// + /// + /// + public static string GetMD5Hash(this string str) + { + using (MD5 mi = MD5.Create()) + { + byte[] buffer = Encoding.Default.GetBytes(str); + //开始加密 + byte[] newBuffer = mi.ComputeHash(buffer); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < newBuffer.Length; i++) + { + sb.Append(newBuffer[i].ToString("x2")); + } + return sb.ToString(); + } + } + + #endregion + + #region T + /// + /// 对象拷贝 + /// + /// 被复制对象 + /// 新对象 + public static T CopyOjbect(T obj) + { + Object targetDeepCopyObj = null; + if ((T)obj == null) + { + return (T)targetDeepCopyObj; + } + Type targetType = obj.GetType(); + //值类型 + if (targetType.IsValueType == true) + { + targetDeepCopyObj = obj; + } + //引用类型 + else + { + targetDeepCopyObj = System.Activator.CreateInstance(targetType); //创建引用对象 + System.Reflection.MemberInfo[] memberCollection = obj.GetType().GetMembers(); + + foreach (System.Reflection.MemberInfo member in memberCollection) + { + //拷贝字段 + if (member.MemberType == System.Reflection.MemberTypes.Field) + { + System.Reflection.FieldInfo field = (System.Reflection.FieldInfo)member; + Object fieldValue = field.GetValue(obj); + if (fieldValue is ICloneable) + { + field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone()); + } + else + { + field.SetValue(targetDeepCopyObj, CopyOjbect(fieldValue)); + } + + }//拷贝属性 + else if (member.MemberType == System.Reflection.MemberTypes.Property) + { + System.Reflection.PropertyInfo myProperty = (System.Reflection.PropertyInfo)member; + + MethodInfo info = myProperty.GetSetMethod(false); + if (info != null) + { + try + { + object propertyValue = myProperty.GetValue(obj, null); + if (propertyValue is ICloneable) + { + myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null); + } + else + { + myProperty.SetValue(targetDeepCopyObj, CopyOjbect(propertyValue), null); + } + } + catch (System.Exception ex) + { + + } + } + } + } + } + return (T)targetDeepCopyObj; + + } + #endregion + + } +} diff --git a/TelegramService.Help/HtmlTag.cs b/TelegramService.Help/HtmlTag.cs new file mode 100644 index 0000000..7d0921a --- /dev/null +++ b/TelegramService.Help/HtmlTag.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace TelegramService.Help +{ + public class HtmlTag + { + private String m_Name; + private String m_BeginTag; + private String m_InnerHTML; + private Hashtable m_Attributes = new Hashtable(); + + static Regex attrReg = new Regex(@"([a-zA-Z1-9_-]+)\s*=\s*(\x27|\x22)([^\x27\x22]*)(\x27|\x22)", RegexOptions.IgnoreCase); + + private HtmlTag(string name, string beginTag, string innerHTML) + { + m_Name = name; + m_BeginTag = beginTag; + m_InnerHTML = innerHTML; + + MatchCollection matchs = attrReg.Matches(beginTag); + foreach (Match match in matchs) + { + m_Attributes[match.Groups[1].Value.ToUpper()] = match.Groups[3].Value; + } + } + public string GetBeginTag() + { + + return m_BeginTag; + } + public List FindTag(String name) + { + return FindTag(m_InnerHTML, name, String.Format(@"<{0}(\s[^<>]*|)>", name)); + } + public List FindImgTag() + { + return FindTag(m_InnerHTML, "img", @"]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>"); + } + public List FindTag(String name, String format) + { + return FindTag(m_InnerHTML, name, format); + } + + public List FindTagByAttr(String tagName, String attrName, String attrValue) + { + return FindTagByAttr(m_InnerHTML, tagName, attrName, attrValue); + } + + public String TagName + { + get { return m_Name; } + } + + public String InnerHTML + { + get { return m_InnerHTML; } + } + public String InnerText + { + get { return checkStr(m_InnerHTML); } + } + public String GetAttribute(string name) + { + return m_Attributes[name.ToUpper()] as String; + } + public String FindDate + { + get + { + Match m = Regex.Match(InnerText, @"(?((1[6-9]|[2-3]\d)\d{2})-(\d{1,2})-(\d{1,2}))"); + if (m.Groups.Count > 0) + { + return m.Groups["date"].Value; + } + else + { + return null; + } + } + } + public static string checkStr2(string html) + { + html = html.Replace("
", "$br$"); + html = html.Replace("
", "$br/$"); + System.Text.RegularExpressions.Regex regex1 = new System.Text.RegularExpressions.Regex(@"", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex2 = new System.Text.RegularExpressions.Regex(@" href *= *[\s\S]*script *:", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex3 = new System.Text.RegularExpressions.Regex(@" no[\s\S]*=", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex4 = new System.Text.RegularExpressions.Regex(@"", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex5 = new System.Text.RegularExpressions.Regex(@"", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex6 = new System.Text.RegularExpressions.Regex(@"\]+\>", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex7 = new System.Text.RegularExpressions.Regex(@"

", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex8 = new System.Text.RegularExpressions.Regex(@"

", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex9 = new System.Text.RegularExpressions.Regex(@"<[^>]*>", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + html = regex1.Replace(html, ""); //过滤标记 + html = regex2.Replace(html, ""); //过滤href=javascript: () 属性 + html = regex3.Replace(html, " _disibledevent="); //过滤其它控件的on...事件 + html = regex4.Replace(html, ""); //过滤iframe + html = regex5.Replace(html, ""); //过滤frameset + html = regex6.Replace(html, ""); //过滤frameset + // html = regex7.Replace(html, ""); //过滤frameset + // html = regex8.Replace(html, ""); //过滤frameset + html = regex9.Replace(html, ""); + html = html.Replace(" ", ""); + html = html.Replace("", ""); + html = html.Replace("", ""); + html = html.Replace("$br$", "
"); + html = html.Replace("$br/$", "
"); + return html; + } + public static string checkStr(string html) + { + if (string.IsNullOrEmpty(html)) + { + return html; + } + System.Text.RegularExpressions.Regex regex1 = new System.Text.RegularExpressions.Regex(@"", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex2 = new System.Text.RegularExpressions.Regex(@" href *= *[\s\S]*script *:", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex3 = new System.Text.RegularExpressions.Regex(@" no[\s\S]*=", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex4 = new System.Text.RegularExpressions.Regex(@"", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex5 = new System.Text.RegularExpressions.Regex(@"", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex6 = new System.Text.RegularExpressions.Regex(@"\]+\>", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex7 = new System.Text.RegularExpressions.Regex(@"

", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex8 = new System.Text.RegularExpressions.Regex(@"

", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + System.Text.RegularExpressions.Regex regex9 = new System.Text.RegularExpressions.Regex(@"<[^>]*>", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + html = regex1.Replace(html, ""); //过滤标记 + html = regex2.Replace(html, ""); //过滤href=javascript: () 属性 + html = regex3.Replace(html, " _disibledevent="); //过滤其它控件的on...事件 + html = regex4.Replace(html, ""); //过滤iframe + html = regex5.Replace(html, ""); //过滤frameset + html = regex6.Replace(html, ""); //过滤frameset + html = regex7.Replace(html, ""); //过滤frameset + html = regex8.Replace(html, ""); //过滤frameset + html = regex9.Replace(html, ""); + html = html.Replace(" ", ""); + html = html.Replace("", ""); + html = html.Replace("", ""); + html = html.Replace(" ", " "); + return html; + } + public static string HtmlToText(string str) + { + + string m_outstr = str; + m_outstr = new Regex(@"(?m)]*>(\w|\W)*?]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr, ""); + m_outstr = new Regex(@"(?m)]*>(\w|\W)*?]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr, ""); + m_outstr = new Regex(@"(?m)]*>(\w|\W)*?]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr, ""); + + //m_outstr = new Regex(@"(?m)]*>(\w|\W)*?]*>", RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr, ""); + Regex objReg = new System.Text.RegularExpressions.Regex("(<[^>]+?>)| ", RegexOptions.Multiline | RegexOptions.IgnoreCase); + m_outstr = objReg.Replace(m_outstr, ""); + Regex objReg2 = new System.Text.RegularExpressions.Regex("(\\s)+", RegexOptions.Multiline | RegexOptions.IgnoreCase); + m_outstr = objReg2.Replace(m_outstr, " "); + return m_outstr; + + + } + + + ///

+ /// 在文本html的文本查找标志名为tagName,并且属性attrName的值为attrValue的所有标志 + /// 例如:FindTagByAttr(html, "div", "class", "demo") + /// 返回所有class为demo的div标志 + /// + public static List FindTagByAttr(String html, String tagName, String attrName, String attrValue) + { + String format = String.Format(@"<{0}\s[^<>]*{1}\s*=\s*(\x27|\x22){2}(\x27|\x22)[^<>]*>", tagName, attrName, attrValue); + return FindTag(html, tagName, format); + } + + public static List FindTag(String html, String name, String format) + { + Regex reg = new Regex(format, RegexOptions.IgnoreCase); + Regex tagReg = new Regex(String.Format(@"<(\/|)({0})(\s[^<>]*|)>", name), RegexOptions.IgnoreCase); + + List tags = new List(); + int start = 0; + + while (true) + { + Match match = reg.Match(html, start); + if (match.Success) + { + start = match.Index + match.Length; + Match tagMatch = null; + int beginTagCount = 1; + + while (true) + { + tagMatch = tagReg.Match(html, start); + if (!tagMatch.Success) + { + tagMatch = null; + break; + } + start = tagMatch.Index + tagMatch.Length; + if (tagMatch.Groups[1].Value == "/") beginTagCount--; + else beginTagCount++; + if (beginTagCount == 0) break; + } + + if (tagMatch != null) + { + HtmlTag tag = new HtmlTag(name, match.Value, html.Substring(match.Index + match.Length, tagMatch.Index - match.Index - match.Length)); + tags.Add(tag); + } + else + { + break; + } + } + else + { + break; + } + } + + return tags; + } + + + } +} diff --git a/TelegramService.Help/HttpHelper.cs b/TelegramService.Help/HttpHelper.cs new file mode 100644 index 0000000..c5605b7 --- /dev/null +++ b/TelegramService.Help/HttpHelper.cs @@ -0,0 +1,244 @@ +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; + +public static class HttpHelper +{ + private static readonly HttpClient DefaultClient; + private static readonly HttpResult HttpResult; + + static HttpHelper() + { + var handler = CreateBestHandler(); + TrySetPooledConnectionLifetime(handler, TimeSpan.FromMinutes(2)); + + DefaultClient = new HttpClient(handler, disposeHandler: false) + { + Timeout = Timeout.InfiniteTimeSpan + }; + HttpResult = new HttpResult(); + + } + + private static HttpClient CreateProxyClient(string proxy) + { + var (address, isHttpsProxy) = ParseProxyScheme(proxy); + + var handler = CreateBestHandler(); + TrySetPooledConnectionLifetime(handler, TimeSpan.FromMinutes(2)); + + handler.Proxy = new WebProxy(address) + { + // 关键两行!解决 95% 的 HTTPS 代理报错 + UseDefaultCredentials = false, + BypassProxyOnLocal = false + }; + + // 如果是 https:// 开头的代理(极少数 socks5 也可能用这个格式),强制走 CONNECT + if (isHttpsProxy) + { + // .NET 6+ 推荐方式(安全又快) + handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13; + } + + handler.UseProxy = true; + + return new HttpClient(handler, disposeHandler: true) + { + Timeout = Timeout.InfiniteTimeSpan + }; + } + + private static HttpClientHandler CreateBestHandler() + { + return new HttpClientHandler + { + UseCookies = false, + AutomaticDecompression = DecompressionMethods.All, + AllowAutoRedirect = true, + // 下面这行是终极救命稻草(解决代理返回 407 需要认证的坑) + Proxy = null, // 先留空,后面再设 + UseProxy = false, + // 防止某些代理服务器返回奇怪的证书 + ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => true + }; + } + + // 智能解析代理地址,支持以下所有格式: + // http://1.2.3.4:8888 + // https://1.2.3.4:8888 + // 1.2.3.4:8888 + // user:pass@1.2.3.4:8888 + private static (Uri address, bool isHttpsProxy) ParseProxyScheme(string proxy) + { + proxy = proxy.Trim(); + + var uri = proxy.Contains("://") + ? new Uri(proxy) + : new Uri("http://" + proxy); + + // 带用户名密码的代理 + if (!string.IsNullOrEmpty(uri.UserInfo)) + { + var parts = uri.UserInfo.Split(new[] { ':' }, 2); + var credential = new NetworkCredential(parts[0], parts.Length > 1 ? parts[1] : ""); + // 注意:这里不能直接设 DefaultProxyCredentials,会全局污染 + // 我们改在下面用更安全的方式处理 + } + + bool isHttps = uri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase); + var address = new Uri($"{(isHttps ? "http" : uri.Scheme)}://{uri.Host}:{uri.Port}"); + + return (address, isHttps); + } + + public static async Task SendAsync( + string url, + HttpMethod method, + Dictionary? headers = null, + Dictionary? cookies = null, + HttpContent? content = null, + int timeoutSeconds = 30, + string? proxy = null, + CancellationToken cancellationToken = default) + { + var client = string.IsNullOrWhiteSpace(proxy) + ? DefaultClient + : CreateProxyClient(proxy); + var shouldDispose = !string.IsNullOrWhiteSpace(proxy); + + // 处理带账号密码的代理(终极写法) + if (!string.IsNullOrWhiteSpace(proxy) && proxy.Contains("@")) + { + var uri = new Uri(proxy.Contains("://") ? proxy : "http://" + proxy); + if (!string.IsNullOrEmpty(uri.UserInfo)) + { + var parts = uri.UserInfo.Split(new[] { ':' }, 2); + var credential = new NetworkCredential(parts[0], parts.Length > 1 ? parts[1] : ""); + + // 关键:每个 HttpClientHandler 单独设置凭据,不污染全局 + if (client.DefaultRequestHeaders.ProxyAuthorization == null) + { + var handler = (HttpClientHandler)client.GetType() + .GetProperty("Handler", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) + ?.GetValue(client)!; + + if (handler?.Proxy != null) + { + handler.Proxy.Credentials = credential; + } + } + } + } + + try + { + using var request = new HttpRequestMessage(method, url); + if (content != null) request.Content = content; + + if (headers != null) + { + foreach (var h in headers) + { + if (IsContentHeader(h.Key)) + request.Content?.Headers.TryAddWithoutValidation(h.Key, h.Value); + else + request.Headers.TryAddWithoutValidation(h.Key, h.Value); + } + } + + if (cookies is { Count: > 0 }) + { + request.Headers.TryAddWithoutValidation("Cookie", string.Join("; ", cookies.Select(c => $"{c.Key}={c.Value}"))); + } + + using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + cts.CancelAfter(TimeSpan.FromSeconds(timeoutSeconds)); + + using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cts.Token); + + if (!response.IsSuccessStatusCode) + { + var err = await response.Content.ReadAsStringAsync(cts.Token); + + HttpResult.StatusCode = (int)response.StatusCode; + HttpResult.Html = $"请求失败 {(int)response.StatusCode} {response.ReasonPhrase}\n{err}".Trim(); + return HttpResult; + + } + + var bytes = await response.Content.ReadAsByteArrayAsync(cts.Token); + var charset = response.Content.Headers.ContentType?.CharSet; + + if (!string.IsNullOrEmpty(charset) && !charset.Equals("utf-8", StringComparison.OrdinalIgnoreCase)) + { + try { + + HttpResult.StatusCode = (int)response.StatusCode; + HttpResult.Html = Encoding.GetEncoding(charset).GetString(bytes); + return HttpResult; + } catch { } + } + + HttpResult.StatusCode = (int)response.StatusCode; + HttpResult.Html = Encoding.UTF8.GetString(bytes); + return HttpResult; + } + catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) + { + HttpResult.StatusCode = 500; + HttpResult.Html = $"请求超时({timeoutSeconds}s)"; + return HttpResult; + } + finally + { + if (shouldDispose) client.Dispose(); + } + } + + // 你的三个快捷方法完全不变 + public static Task GetAsync(string url, Dictionary? headers = null, + Dictionary? cookies = null, int timeoutSeconds = 30, string? proxy = null) => + SendAsync(url, HttpMethod.Get, headers, cookies, null, timeoutSeconds, proxy); + + public static Task PostFormAsync(string url, Dictionary form, + Dictionary? headers = null, Dictionary? cookies = null, + int timeoutSeconds = 30, string? proxy = null) + { + var content = new FormUrlEncodedContent(form); + return SendAsync(url, HttpMethod.Post, headers, cookies, content, timeoutSeconds, proxy); + } + + public static Task PostJsonAsync(string url, string json, + Dictionary? headers = null, Dictionary? cookies = null, + int timeoutSeconds = 30, string? proxy = null) + { + var content = new StringContent(json, Encoding.UTF8, "application/json"); + headers ??= new(); + headers["Content-Type"] = "application/json; charset=utf-8"; + return SendAsync(url, HttpMethod.Post, headers, cookies, content, timeoutSeconds, proxy); + } + + private static bool IsContentHeader(string name) => + name.StartsWith("Content-", StringComparison.OrdinalIgnoreCase); + + private static void TrySetPooledConnectionLifetime(HttpClientHandler handler, TimeSpan lifetime) + { + try + { + var prop = handler.GetType().GetProperty("PooledConnectionLifetime"); + prop?.SetValue(handler, lifetime); + } + catch { } + } +} + + +public class HttpResult +{ + public int StatusCode { get; set; } + + public string Html { get; set; } + +} \ No newline at end of file diff --git a/TelegramService.Help/TelegramService.Help.csproj b/TelegramService.Help/TelegramService.Help.csproj new file mode 100644 index 0000000..b760144 --- /dev/null +++ b/TelegramService.Help/TelegramService.Help.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/TelegramService.slnx b/TelegramService.slnx new file mode 100644 index 0000000..3e8785a --- /dev/null +++ b/TelegramService.slnx @@ -0,0 +1,6 @@ + + + + + + diff --git a/TelegramService/Program.cs b/TelegramService/Program.cs new file mode 100644 index 0000000..9ee6a76 --- /dev/null +++ b/TelegramService/Program.cs @@ -0,0 +1,16 @@ +using System.Runtime.InteropServices; + +namespace TelegramService +{ + public class Program + { + public static void Main(string[] args) + { + var builder = Host.CreateApplicationBuilder(args); + builder.Services.AddHostedService(); + + var host = builder.Build(); + host.Run(); + } + } +} diff --git a/TelegramService/Properties/launchSettings.json b/TelegramService/Properties/launchSettings.json new file mode 100644 index 0000000..028ed5b --- /dev/null +++ b/TelegramService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "TelegramService": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/TelegramService/TelegramService.csproj b/TelegramService/TelegramService.csproj new file mode 100644 index 0000000..39ea0ab --- /dev/null +++ b/TelegramService/TelegramService.csproj @@ -0,0 +1,20 @@ + + + + net10.0 + enable + enable + dotnet-TelegramService-a097e3f5-17e6-4c41-b5ba-b8e0e160be6e + + + + + + + + + + + + + diff --git a/TelegramService/Worker.cs b/TelegramService/Worker.cs new file mode 100644 index 0000000..9f0afa6 --- /dev/null +++ b/TelegramService/Worker.cs @@ -0,0 +1,175 @@ +using Newtonsoft.Json; +using System.Net; +using System.Net.Security; +using System.Text; +using TelegramService.Entity; +using TelegramService.Help; +using TelegramServiceV6.Bl; + +namespace TelegramService +{ + public class Worker : BackgroundService + { + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "log")) + { + Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "log"); + } + + // 192.168.1.80 SSL ֤ + ServicePointManager.ServerCertificateValidationCallback = + (sender, certificate, chain, sslPolicyErrors) => + { + // sender HttpWebRequest + if (sender is HttpWebRequest req) + { + if (req.Address.Host == "111.230.99.204") + return true; // IP + } + + // ʹĬ֤߼ + return sslPolicyErrors == SslPolicyErrors.None; + }; + EntrustHelper.STCB = Controller; + Appsettings.Conf = JsonConvert.DeserializeObject(File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "/appsettings.json")); + + await Task.Run(() => + { + InitTimer(10); + InitTimerTieBa(10); + InitFund(10); + }); + + } + + #region + /// + ///ر + /// + /// + private void InitFund(double interval) + { + try + { + System.Timers.Timer timer = new System.Timers.Timer(interval); + //ִһΣfalseһֱִ(true) + timer.AutoReset = false; + //ǷִSystem.Timers.Timer.Elapsed¼ + timer.Enabled = true; + //Elapsed¼ + timer.Elapsed += new System.Timers.ElapsedEventHandler((s, e) => + { + FundBl.SendWeixinFund(); + }); + } + catch (Exception ex) + { + Controller("show", ex.StackTrace); + } + } + #endregion + + #region ԰ + /// + ///ر + /// + /// + private void InitTimer(double interval) + { + try + { + System.Timers.Timer timer = new System.Timers.Timer(interval); + //ִһΣfalseһֱִ(true) + timer.AutoReset = false; + //ǷִSystem.Timers.Timer.Elapsed¼ + timer.Enabled = true; + //Elapsed¼ + timer.Elapsed += new System.Timers.ElapsedEventHandler((s, e) => + { + CnblogsBl cnblogsBl = new CnblogsBl(); + cnblogsBl.GetCnblogsHtml(); + }); + } + catch (Exception ex) + { + Controller("show", ex.StackTrace); + } + } + + #endregion + + + #region + /// + ///԰ + /// + /// + private void InitTimerTieBa(double interval) + { + try + { + System.Timers.Timer timer = new System.Timers.Timer(interval); + //ִһΣfalseһֱִ(true) + timer.AutoReset = false; + //ǷִSystem.Timers.Timer.Elapsed¼ + timer.Enabled = true; + //Elapsed¼ + timer.Elapsed += new System.Timers.ElapsedEventHandler((s, e) => + { + TieBaBl tb = new TieBaBl(); + tb.GetTieBaHtml(); + }); + } + catch (Exception ex) + { + Controller("show", ex.StackTrace); + } + } + + #endregion + + + #region ʵʱ״̬ + private static object _lockObj = new object(); + /// + /// ʵʱ״̬ + /// + /// + delegate object SetController(string type, object errorMessage); + + public object Controller(string type, object errorMessage) + { + + if (type.Equals("show")) + { + try + { + lock (_lockObj) + { + File.AppendAllText(System.AppDomain.CurrentDomain.BaseDirectory + "log/Log_" + DateTime.Now.ToString("yyyyMMdd") + ".txt", "[" + DateTime.Now.ToString() + "]:" + errorMessage + "\r\n", Encoding.UTF8); + } + } + catch (Exception) + { + } + } + else if (type.Equals("InitTimer")) + { + InitTimer(Convert.ToDouble(errorMessage) * 60000); + } + else if (type.Equals("InitTimerTieBa")) + { + InitTimerTieBa(Convert.ToDouble(errorMessage) * 60000); + } + else if (type.Equals("sendWeixinFund")) + { + InitFund(Convert.ToDouble(errorMessage)); + } + + return null; + } + + #endregion + } +} diff --git a/TelegramService/appsettings.Development.json b/TelegramService/appsettings.Development.json new file mode 100644 index 0000000..b2dcdb6 --- /dev/null +++ b/TelegramService/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/TelegramService/appsettings.json b/TelegramService/appsettings.json new file mode 100644 index 0000000..c645f22 --- /dev/null +++ b/TelegramService/appsettings.json @@ -0,0 +1,16 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "ConnectionStrings": { + "DBConnection": "" + }, + "Interval": 3, + "IntervalLiYuan": 3, + "IntervalTieBa": 3, + "Fund": [ "009271", "160213", "018043", "016452" ], + "TieBa": [ "广东联通", "广东移动" ] +}