UnionParseCore.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. using Microsoft.AspNetCore.Http;
  2. using Microsoft.AspNetCore.Mvc.Controllers;
  3. using Microsoft.AspNetCore.Mvc.Filters;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using dodohold.core;
  9. using Spire.Pdf.Exporting.XPS.Schema;
  10. using System.Xml.Linq;
  11. using System.Net;
  12. using TencentCloud.Mrs.V20200910.Models;
  13. using Microsoft.AspNetCore.Mvc;
  14. using Microsoft.AspNetCore.Authentication;
  15. using Spire.Pdf.Graphics;
  16. using Google.Protobuf.WellKnownTypes;
  17. using TencentCloud.Tcm.V20210413.Models;
  18. using System.Diagnostics;
  19. using System.Threading;
  20. using TencentCloud.Soe.V20180724.Models;
  21. using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
  22. using System.Runtime.Intrinsics.Arm;
  23. using ZstdSharp.Unsafe;
  24. namespace molilian.core
  25. {
  26. public partial class UnionParseCore
  27. {
  28. public static async Task<ActionResult> UnionParseAsync(string content, string channel, string ip, string oaid, int accountid = 0)
  29. {
  30. content = content.Trim();
  31. return channel switch
  32. {
  33. "wemeet" => await WemeetParseAsync(content, ip, oaid),
  34. "bdpan" => PanParse(content, ip, oaid),
  35. "jd" => await JdParseAsync(content, ip, oaid, accountid),
  36. "dy" => await DyParseAsync(content, ip, oaid),
  37. _ => await TaobaoParseAsync(content, ip, oaid, accountid),
  38. };
  39. }
  40. public static async Task<APIResult> WemeetParseAsync(string content, string ip, string oaid)
  41. {
  42. var result = ToolParsePlus.GetFormattedObject(TkChannelEnum.wemeet, content, ip, oaid);
  43. content = content.UrlDecode();
  44. result.rawContent = content;
  45. try
  46. {
  47. result = await ToolParsePlus.WemeetParseAsync(content, result);
  48. }
  49. catch (Exception ex)
  50. {
  51. _ = new LoggerLibrary("unionParse", "wemeet_error")
  52. .Info(ip, oaid)
  53. .Info(content)
  54. .Info(ex.Message, ex.StackTrace)
  55. .SaveAsync();
  56. NotifyCore.Notify(new NifyMessage
  57. {
  58. message = $"【转链异常Wemeet】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  59. priority = NifyMessagePriority.high,
  60. tags = ["red_circle"]
  61. });
  62. result.success = false;
  63. result.message = "内部错误";
  64. result.reason = "转链接口异常";
  65. }
  66. _ = TkLogCore.ParseLogAsync(result);
  67. return new APIResult(new
  68. {
  69. result.success,
  70. result.message,
  71. channel = result?.channel.ToString(),
  72. result.shortLinkurl,
  73. result.deeplink_url,
  74. result.itemName,
  75. }, result.success ? APIResultCodeEnum.OK : APIResultCodeEnum.NotAcceptable);
  76. }
  77. public static APIResult PanParse(string content, string ip, string oaid)
  78. {
  79. var result = ToolParsePlus.GetFormattedObject(TkChannelEnum.bdpan, content, ip, oaid);
  80. content = content.UrlDecode();
  81. result.rawContent = content;
  82. try
  83. {
  84. ToolParsePlus.PanParse(content, ref result);
  85. }
  86. catch (Exception ex)
  87. {
  88. _ = new LoggerLibrary("unionParse", "pan_error")
  89. .Info(ip, oaid)
  90. .Info(content)
  91. .Info(ex.Message, ex.StackTrace)
  92. .SaveAsync();
  93. NotifyCore.Notify(new NifyMessage
  94. {
  95. message = $"【转链异常Pan】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  96. priority = NifyMessagePriority.high,
  97. tags = ["red_circle"]
  98. });
  99. result.success = false;
  100. result.message = "内部错误";
  101. result.reason = "转链接口异常";
  102. }
  103. _ = TkLogCore.ParseLogAsync(result);
  104. return new APIResult(new
  105. {
  106. result.success,
  107. result.message,
  108. channel = result?.channel.ToString(),
  109. result.shortLinkurl,
  110. result.deeplink_url,
  111. result.itemName,
  112. }, !string.IsNullOrEmpty(result.deeplink_url) ? APIResultCodeEnum.OK : APIResultCodeEnum.NotAcceptable);
  113. }
  114. private static APIResult TaobaoParseOutput(TkDataDTO result, Dictionary<string, long> swData, object info, APIResultCodeEnum code = APIResultCodeEnum.OK)
  115. {
  116. if (result.elapsedTime > 2000)
  117. {
  118. LoggerLibrary log = new("debug", "stopwatch");
  119. foreach ((var key, var value) in swData)
  120. {
  121. log.Info($"{key}\t{value}");
  122. }
  123. log.SaveAsync();
  124. }
  125. return new APIResult(info, code);
  126. }
  127. public static async Task<APIResult> TaobaoParseAsync(string content,
  128. string ip = "", string oaid = "",
  129. int accountid = 0)
  130. {
  131. AlimamaPlus alimama = null;
  132. //content = content.UrlDecode();
  133. content = content[..Math.Min(1000, content.Length)];
  134. var result = AlimamaPlus.GetFormattedObject(content, ip, oaid);
  135. Dictionary<string, long> swData = new();
  136. swData.Add("StartNew", 0);
  137. Stopwatch stopwatch = Stopwatch.StartNew();
  138. result.rawContent = content;
  139. try
  140. {
  141. string reason = string.Empty;
  142. //============================== 放弃转链-平台错误 ==============================
  143. //bool is_other = await AlimamaPlus.OtherPlatformAsync(content);
  144. //if (is_other)
  145. //{
  146. // result.success = false;
  147. // result.message = "放弃转链";
  148. // result.reason = "初步筛选";
  149. // result.itemName = "";
  150. // result.deeplink_url = "";
  151. // _ = TkLogCore.ParseLogAsync(result);
  152. // return TaobaoParseOutput(result, swData, new
  153. // {
  154. // result.success,
  155. // result.message,
  156. // result.content,
  157. // result.itemName,
  158. // result.deeplink_url,
  159. // });
  160. //}
  161. ////一眼要排除
  162. //if (content.Contains("bmlxkyy.com"))
  163. //{
  164. // result.success = false;
  165. // result.message = "放弃转链";
  166. // result.reason = "初步筛选";
  167. // result.itemName = "";
  168. // result.deeplink_url = "";
  169. // _ = TkLogCore.ParseLogAsync(result);
  170. // return TaobaoParseOutput(result, swData, new
  171. // {
  172. // result.success,
  173. // result.message,
  174. // result.content,
  175. // result.itemName,
  176. // result.deeplink_url,
  177. // });
  178. //}
  179. var config = TkConfigCore.Get();
  180. var arr = config.tk_whitelist_regular.Split('\n')
  181. .Where(line => !string.IsNullOrWhiteSpace(line))
  182. .ToList();
  183. var arr2 = config.tk_blacklist_regular.Split('\n')
  184. .Where(line => !string.IsNullOrWhiteSpace(line))
  185. .ToList();
  186. var arr3 = config.multi_token_regular.Split('\n')
  187. .Where(line => !string.IsNullOrWhiteSpace(line))
  188. .ToList();
  189. bool is_tao_url = !string.IsNullOrEmpty(result.shortLinkurl);
  190. bool is_tao_token = AlimamaPlus.MatchRegexes(content, arr);
  191. bool is_other = AlimamaPlus.MatchOtherInfo(content, arr2);
  192. //============================== 放弃转链-初步筛选1 ==============================
  193. if (!is_tao_url && !is_tao_token || is_other)
  194. {
  195. //没有链接都放弃
  196. result.success = false;
  197. result.message = "放弃转链";
  198. result.reason = "初步筛选1";
  199. result.itemName = "";
  200. result.deeplink_url = "";
  201. _ = TkLogCore.ParseLogAsync(result);
  202. return TaobaoParseOutput(result, swData, new
  203. {
  204. result.success,
  205. result.message,
  206. result.content,
  207. result.itemName,
  208. result.deeplink_url,
  209. });
  210. }
  211. bool is_multi_token = AlimamaPlus.MatchMultiToken(content, arr3);
  212. //============================== 放弃转链-初步筛选1.5 ==============================
  213. if (is_multi_token)
  214. {
  215. //没有链接都放弃
  216. result.success = false;
  217. result.message = "放弃转链";
  218. result.reason = "初步筛选1.5";
  219. result.itemName = "";
  220. result.deeplink_url = "";
  221. _ = TkLogCore.ParseLogAsync(result);
  222. return TaobaoParseOutput(result, swData, new
  223. {
  224. result.success,
  225. result.message,
  226. result.content,
  227. result.itemName,
  228. result.deeplink_url,
  229. });
  230. }
  231. //============================== 放弃转链-初步筛选2 ==============================
  232. bool is_aff_link = false;
  233. if (!string.IsNullOrEmpty(result.shortLinkurl)) is_aff_link = AlimamaPlus.IsAffLink(result.shortLinkurl);
  234. if ((!is_tao_url && is_tao_token) || is_aff_link)
  235. {
  236. //没有短链接都放弃
  237. result.success = false;
  238. result.message = "放弃转链";
  239. result.reason = "初步筛选2";
  240. result.itemName = "点击打开淘宝APP";
  241. _ = TkLogCore.ParseLogAsync(result);
  242. return TaobaoParseOutput(result, swData, new
  243. {
  244. result.success,
  245. result.message,
  246. result.content,
  247. result.itemName,
  248. result.deeplink_url,
  249. });
  250. }
  251. //============================== 放弃转链-地区过滤 ==============================
  252. bool is_ignore2 = AlimamaPlus.ShouldIgnoreRequest(ip, oaid, out reason);
  253. if (is_ignore2)
  254. {
  255. result.success = false;
  256. result.message = "放弃转链";
  257. result.itemName = "点击打开淘宝APP";
  258. result.reason = reason;
  259. _ = TkLogCore.ParseLogAsync(result);
  260. return TaobaoParseOutput(result, swData, new
  261. {
  262. result.success,
  263. result.message,
  264. result.content,
  265. result.itemName,
  266. result.deeplink_url,
  267. });
  268. }
  269. ////============================== 放弃转链-初步筛选 ==============================
  270. //bool is_ignore = AlimamaPlus.FirstFilterIgnoreRequest(content, out reason);
  271. //if (string.IsNullOrEmpty(result.shortLinkurl) && is_ignore)
  272. //{
  273. // //没有短链接都放弃
  274. // result.success = false;
  275. // result.message = "放弃转链";
  276. // result.itemName = "点击打开淘宝APP";
  277. // result.reason = "初步筛选";
  278. // _ = TkLogCore.ParseLogAsync(result);
  279. // return TaobaoParseOutput(result, swData, new
  280. // {
  281. // result.success,
  282. // result.message,
  283. // result.content,
  284. // result.itemName,
  285. // result.deeplink_url,
  286. // });
  287. //}
  288. //============================== 放弃转链-没有匹配账号 ==============================
  289. TkPoolDTO? account = accountid > 0 ?
  290. TkPoolCore.GetOne(accountid) :
  291. TkPoolCore.GetOne(TkPoolCore.TkAction.parse);
  292. if (account == null)
  293. {
  294. result.success = false;
  295. result.message = "放弃转链";
  296. result.reason = "没有匹配账号";
  297. result.itemName = "点击打开淘宝APP";
  298. _ = TkLogCore.ParseLogAsync(result);
  299. return TaobaoParseOutput(result, swData, new
  300. {
  301. result.success,
  302. result.message,
  303. result.content,
  304. result.couponAmount,
  305. result.taoToken,
  306. result.shortLinkurl,
  307. result.deeplink_url,
  308. });
  309. }
  310. result.accountId = account.id;
  311. result.accountName = account.company;
  312. alimama = new AlimamaPlus(account);
  313. int timeout = alimama._config.rt_max;
  314. using var cts = new CancellationTokenSource();
  315. cts.CancelAfter(timeout);
  316. var requestTask = Task.Run(() => alimama.UnionParse2Async(content, result, cts.Token, swData), cts.Token);
  317. var delayTask = Task.Delay(timeout, cts.Token);
  318. var completedTask = await Task.WhenAny(requestTask, delayTask);
  319. if (completedTask == requestTask)
  320. {
  321. result = await requestTask;
  322. }
  323. else
  324. {
  325. //============================== 放弃转链-请求超时 ==============================
  326. cts.Cancel();
  327. result.success = false;
  328. result.message = "放弃转链";
  329. result.reason = "请求超时";
  330. result.itemName = "点击打开淘宝APP";
  331. }
  332. result.accountName = account.company;
  333. //result = await alimama.UnionParse2Async(content, result);
  334. }
  335. catch (Exception ex)
  336. {
  337. //============================== 放弃转链-请求超时 ==============================
  338. if (ex.Message.Contains("was canceled"))
  339. {
  340. result.success = false;
  341. result.message = "放弃转链";
  342. result.reason = "请求超时";
  343. result.itemName = "点击打开淘宝APP";
  344. }
  345. else
  346. {
  347. //============================== 转链接口异常 ==============================
  348. _ = new LoggerLibrary("unionParse", "tb_error")
  349. .Info(ip, oaid)
  350. .Info(content)
  351. .Info(ex.Message, ex.StackTrace)
  352. .SaveAsync();
  353. NotifyCore.Notify(new NifyMessage
  354. {
  355. message = $"【转链异常TB】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  356. priority = NifyMessagePriority.high,
  357. tags = ["red_circle"]
  358. });
  359. result.success = false;
  360. result.message = "转链接口异常";
  361. result.itemName = "点击打开淘宝APP";
  362. }
  363. }
  364. _ = TkLogCore.ParseLogAsync(result, alimama);
  365. return TaobaoParseOutput(result, swData, new
  366. {
  367. result.success,
  368. result.message,
  369. link_type = result.link_type.ToString(),
  370. channel = result?.channel.ToString(),
  371. result.channel_type,
  372. result.itemId,
  373. result.itemName,
  374. result.pic,
  375. result.promotionPrice,
  376. result.couponAmount,
  377. result.couponEffectiveStartTime,
  378. result?.couponEffectiveEndTime,
  379. result.shortLinkurl,
  380. result.deeplink_url,
  381. result.content,
  382. result.taoToken,
  383. });
  384. }
  385. private static APIResult JdParseOutput(JdDataDTO result, APIResultCodeEnum code = APIResultCodeEnum.OK)
  386. {
  387. return new APIResult(new
  388. {
  389. result.success,
  390. result.message,
  391. link_type = result.link_type.ToString(),
  392. channel = result?.channel.ToString(),
  393. result.channel_type,
  394. result.itemId,
  395. result.itemName,
  396. result.shortLinkurl,
  397. result.deeplink_url,
  398. }, code);
  399. }
  400. public static async Task<APIResult> JdParseAsync(string content, string ip, string oaid,
  401. int accountid = 0, CancellationToken cancellationToken = default)
  402. {
  403. var result = JdUnionPlus.GetFormattedObject(content, ip, oaid);
  404. content = content.UrlDecode();
  405. result.rawContent = content;
  406. bool IfExceptional = false;
  407. try
  408. {
  409. var config = TkConfigCore.Get();
  410. //============================== 放弃转链-地区过滤 ==============================
  411. if (accountid == 0 && JdUnionPlus.ShouldIgnoreRequest(config, ip, oaid, out string reason))
  412. {
  413. result.success = false;
  414. result.message = "放弃转链";
  415. result.reason = reason;
  416. _ = TkLogCore.ParseLogAsync(result);
  417. return JdParseOutput(result);
  418. }
  419. // bool is_ignore2 = JdUnionPlus.FlowControlIgnoreRequest(config, out reason);
  420. //#if DEBUG
  421. // is_ignore2 = false;
  422. //#endif
  423. // if (accountid == 0 && is_ignore2)
  424. // {
  425. // result.success = false;
  426. // result.message = "放弃转链";
  427. // result.reason = reason;
  428. // _ = TkLogCore.ParseLogAsync(result);
  429. // return JdParseOutput(result);
  430. // }
  431. var account = accountid > 0 ? JdPoolCore.GetOne(accountid) : JdPoolCore.GetOne(JdPoolCore.JdAction.parse);
  432. if (account == null)
  433. {
  434. result.success = false;
  435. result.message = "放弃转链";
  436. result.reason = "没有匹配账号";
  437. _ = TkLogCore.ParseLogAsync(result);
  438. return JdParseOutput(result);
  439. }
  440. result.accountId = account.id;
  441. result.accountName = account.name;
  442. var plus = new JdUnionPlus(account);
  443. result = await plus.JdParseAsync(content, result, cancellationToken);
  444. }
  445. catch (Exception ex)
  446. {
  447. if (ex.Message.Contains("was canceled"))
  448. {
  449. result.success = false;
  450. result.message = "放弃转链";
  451. result.reason = "请求超时";
  452. }
  453. else
  454. {
  455. IfExceptional = true;
  456. _ = new LoggerLibrary("unionParse", "jd_error")
  457. .Info(ip, oaid)
  458. .Info(content)
  459. .Info(ex.Message, ex.StackTrace)
  460. .SaveAsync();
  461. NotifyCore.Notify(new NifyMessage
  462. {
  463. message = $"【转链异常JD】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  464. priority = NifyMessagePriority.high,
  465. tags = ["red_circle"]
  466. });
  467. result.success = false;
  468. result.message = "内部错误";
  469. result.reason = "转链接口异常";
  470. }
  471. }
  472. _ = TkLogCore.ParseLogAsync(result);
  473. return JdParseOutput(result, IfExceptional ? APIResultCodeEnum.NotAcceptable : APIResultCodeEnum.OK);
  474. }
  475. public static async Task<APIResult> DyParseAsync(string content, string ip, string oaid, CancellationToken cancellationToken = default)
  476. {
  477. var result = DyUnionPlus.GetFormattedObject(content, ip, oaid);
  478. content = content.UrlDecode();
  479. result.rawContent = content;
  480. bool IfExceptional = false;
  481. try
  482. {
  483. // 2024-06-19 联盟业务下线
  484. result.success = false;
  485. result.message = "放弃转链";
  486. result.reason = "联盟下线";
  487. _ = TkLogCore.ParseLogAsync(result);
  488. return new APIResult(result);
  489. if (DyUnionPlus.ShouldIgnoreRequest(ip, oaid, out string reason))
  490. {
  491. result.success = false;
  492. result.message = "放弃转链";
  493. result.reason = reason;
  494. _ = TkLogCore.ParseLogAsync(result);
  495. return new APIResult(result);
  496. }
  497. var account = PangolinPoolCore.GetOne();
  498. if (account == null)
  499. {
  500. result.success = false;
  501. result.message = "放弃转链";
  502. result.reason = "没有匹配账号";
  503. _ = TkLogCore.ParseLogAsync(result);
  504. return new APIResult(result);
  505. }
  506. result = await DyUnionPlus.DyParseAsync(account, content, result, cancellationToken);
  507. }
  508. catch (Exception ex)
  509. {
  510. if (ex.Message.Contains("was canceled"))
  511. {
  512. result.success = false;
  513. result.message = "放弃转链";
  514. result.reason = "请求超时";
  515. }
  516. else
  517. {
  518. IfExceptional = true;
  519. _ = new LoggerLibrary("unionParse", "dy_error")
  520. .Info(ip, oaid)
  521. .Info(content)
  522. .Info(ex.Message, ex.StackTrace)
  523. .SaveAsync();
  524. NotifyCore.Notify(new NifyMessage
  525. {
  526. message = $"【转链异常DY】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  527. priority = NifyMessagePriority.high,
  528. tags = ["red_circle"]
  529. });
  530. result.success = false;
  531. result.message = "内部错误";
  532. result.reason = "转链接口异常";
  533. }
  534. }
  535. _ = TkLogCore.ParseLogAsync(result);
  536. return new APIResult(new
  537. {
  538. result.success,
  539. result.message,
  540. link_type = result.link_type.ToString(),
  541. channel = result?.channel.ToString(),
  542. content = result?.rawContent.ToString(),
  543. taoToken = result?.taoToken.ToString(),
  544. result.channel_type,
  545. result.itemName,
  546. result.shortLinkurl,
  547. result.deeplink_url,
  548. }, IfExceptional ? APIResultCodeEnum.NotAcceptable : APIResultCodeEnum.OK);
  549. }
  550. }
  551. }