UnionParseCore.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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. using System.Text.RegularExpressions;
  25. using static dodohold.core.ZTOExpress.CreateOrderArgs;
  26. using System.Security.Cryptography;
  27. using System.Threading.Channels;
  28. using TencentCloud.Tke.V20180525.Models;
  29. namespace molilian.core
  30. {
  31. public partial class UnionParseCore
  32. {
  33. public static async Task<ActionResult> UnionParseAsync(string content, string channel, int commerceType, string ip, string oaid, int accountid = 0, string clickId = "")
  34. {
  35. content = content.Trim();
  36. return channel switch
  37. {
  38. "wemeet" => await WemeetParseAsync(content, ip, oaid),
  39. "bdpan" => PanParse(content, ip, oaid),
  40. "jd" => await JdParseAsync(content, commerceType, ip, oaid, accountid, clickId),
  41. "ks" => await KsParseAsync(content, commerceType, ip, oaid, accountid),
  42. "dy" => await DyParseAsync(content, commerceType, ip, oaid),
  43. "pdd" => await PddParseAsync(content, commerceType, ip, oaid, accountid),
  44. "tb" => await TaobaoParseAsync(content, commerceType, ip, oaid, accountid),
  45. _ => await DeeplinkParseCore.ParseAsync(content, channel, ip, oaid),
  46. };
  47. }
  48. //return await DeeplinkParseCore.ParseAsync(content, channel, ip, oaid);
  49. public static async Task<APIResult> WemeetParseAsync(string content, string ip, string oaid)
  50. {
  51. var result = ToolParsePlus.GetFormattedObject(TkChannelEnum.wemeet, content, ip, oaid);
  52. content = content.UrlDecode();
  53. result.rawContent = content;
  54. try
  55. {
  56. result = await ToolParsePlus.WemeetParseAsync(content, result);
  57. }
  58. catch (Exception ex)
  59. {
  60. _ = new LoggerLibrary("unionParse", "wemeet_error")
  61. .Info(ip, oaid)
  62. .Info(content)
  63. .Info(ex.Message, ex.StackTrace)
  64. .SaveAsync();
  65. NotifyCore.Notify(new NifyMessage
  66. {
  67. message = $"【转链异常Wemeet】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  68. priority = NifyMessagePriority.high,
  69. tags = ["red_circle"]
  70. });
  71. result.success = false;
  72. result.message = "内部错误";
  73. result.reason = "转链接口异常";
  74. }
  75. _ = TkLogCore.ParseLogAsync(result);
  76. return new APIResult(new
  77. {
  78. result.success,
  79. result.message,
  80. channel = result?.channel.ToString(),
  81. result.shortLinkurl,
  82. result.deeplink_url,
  83. result.itemName,
  84. }, result.success ? APIResultCodeEnum.OK : APIResultCodeEnum.NotAcceptable);
  85. }
  86. public static APIResult PanParse(string content, string ip, string oaid)
  87. {
  88. var result = ToolParsePlus.GetFormattedObject(TkChannelEnum.bdpan, content, ip, oaid);
  89. content = content.UrlDecode();
  90. result.rawContent = content;
  91. try
  92. {
  93. ToolParsePlus.PanParse(content, ref result);
  94. }
  95. catch (Exception ex)
  96. {
  97. _ = new LoggerLibrary("unionParse", "pan_error")
  98. .Info(ip, oaid)
  99. .Info(content)
  100. .Info(ex.Message, ex.StackTrace)
  101. .SaveAsync();
  102. NotifyCore.Notify(new NifyMessage
  103. {
  104. message = $"【转链异常Pan】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  105. priority = NifyMessagePriority.high,
  106. tags = ["red_circle"]
  107. });
  108. result.success = false;
  109. result.message = "内部错误";
  110. result.reason = "转链接口异常";
  111. }
  112. _ = TkLogCore.ParseLogAsync(result);
  113. return new APIResult(new
  114. {
  115. result.success,
  116. result.message,
  117. channel = result?.channel.ToString(),
  118. result.shortLinkurl,
  119. result.deeplink_url,
  120. result.itemName,
  121. }, !string.IsNullOrEmpty(result.deeplink_url) ? APIResultCodeEnum.OK : APIResultCodeEnum.NotAcceptable);
  122. }
  123. private static APIResult TaobaoParseOutput(TkDataDTO result, Dictionary<string, long> swData, object info, APIResultCodeEnum code = APIResultCodeEnum.OK)
  124. {
  125. if (result.elapsedTime > 2000)
  126. {
  127. LoggerLibrary log = new("debug", "stopwatch");
  128. foreach ((var key, var value) in swData)
  129. {
  130. log.Info($"{key}\t{value}");
  131. }
  132. log.SaveAsync();
  133. }
  134. return new APIResult(info, code);
  135. }
  136. public static async Task<APIResult> TaobaoParseAsync(string content, int commerceType,
  137. string ip = "", string oaid = "",
  138. int accountid = 0)
  139. {
  140. bool other_aff = false;
  141. AlimamaPlus alimama = null;
  142. //content = content.UrlDecode();
  143. content = content[..Math.Min(1000, content.Length)];
  144. var result = AlimamaPlus.GetFormattedObject(content, ip, oaid);
  145. Dictionary<string, long> swData = new();
  146. swData.Add("StartNew", 0);
  147. Stopwatch stopwatch = Stopwatch.StartNew();
  148. result.rawContent = content;
  149. try
  150. {
  151. string reason = string.Empty;
  152. var config = TkConfigCore.Get();
  153. var arr = config.tk_whitelist_regular.Split('\n')
  154. .Where(line => !string.IsNullOrWhiteSpace(line))
  155. .ToList();
  156. var arr2 = config.tk_blacklist_regular.Split('\n')
  157. .Where(line => !string.IsNullOrWhiteSpace(line))
  158. .ToList();
  159. var arr3 = config.multi_token_regular.Split('\n')
  160. .Where(line => !string.IsNullOrWhiteSpace(line))
  161. .ToList();
  162. bool is_tao_url = !string.IsNullOrEmpty(result.shortLinkurl);
  163. bool is_tao_token = AlimamaPlus.MatchRegexes(content, arr);
  164. bool is_other = AlimamaPlus.MatchOtherInfo(content, arr2);
  165. //============================== 放弃转链-初步筛选1 ==============================
  166. if (!is_tao_url && !is_tao_token || is_other)
  167. {
  168. //没有链接都放弃
  169. result.success = false;
  170. result.message = "放弃转链";
  171. result.reason = "初步筛选1";
  172. result.subCode = TkSubCodeEnum.Prelim1;
  173. result.itemName = "";
  174. result.deeplink_url = "";
  175. _ = TkLogCore.ParseLogAsync(result);
  176. return TaobaoParseOutput(result, swData, new
  177. {
  178. result.success,
  179. result.commercial,
  180. result.message,
  181. result.content,
  182. result.itemName,
  183. other_aff,
  184. result.deeplink_url,
  185. });
  186. }
  187. bool is_multi_token = AlimamaPlus.MatchMultiToken(content, arr3);
  188. //============================== 放弃转链-初步筛选1.5 ==============================
  189. if (is_multi_token)
  190. {
  191. //没有链接都放弃
  192. result.success = false;
  193. result.message = "放弃转链";
  194. result.reason = "初步筛选1.5";
  195. result.subCode = TkSubCodeEnum.Prelim1_5;
  196. result.itemName = "";
  197. result.deeplink_url = "";
  198. _ = TkLogCore.ParseLogAsync(result);
  199. return TaobaoParseOutput(result, swData, new
  200. {
  201. result.success,
  202. result.commercial,
  203. result.message,
  204. result.content,
  205. result.itemName,
  206. other_aff,
  207. result.deeplink_url,
  208. });
  209. }
  210. //============================== 放弃转链-初步筛选2 ==============================
  211. bool is_aff_link = false;
  212. if (!string.IsNullOrEmpty(result.shortLinkurl)) is_aff_link = AlimamaPlus.IsAffLink(result.shortLinkurl);
  213. if (!is_tao_url && is_tao_token)
  214. {
  215. //淘宝口令
  216. result.success = false;
  217. result.message = "放弃转链";
  218. result.reason = "初步筛选2";
  219. result.subCode = TkSubCodeEnum.Prelim2;
  220. result.itemName = "点击打开淘宝APP";
  221. _ = TkLogCore.ParseLogAsync(result);
  222. //20241229 特例
  223. //if ("bj".Equals(EndPointCore.CurrentEndPoint))
  224. //{
  225. // string ruleKey = $"tmp_rules2:tb:{DateTime.Now:yyyyMMdd}";
  226. // var count = RedisHelper.Get<int>(ruleKey);
  227. // var now = DateTime.Now;
  228. // if (now > new DateTime(2024, 12, 19) && now <= new DateTime(2024, 12, 22) && now.Hour >= 7 && count < 1000)
  229. // {
  230. // result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?source=auto&action=ali.open.nav&module=h5&bootImage=0&afc_route=1&bc_fl_src=growth_dhh_2200803434968_100-1930985-1595034112&dpa_Inid=159503411212096&dpa_material_id=530637422585&dpa_material_type=1&dpa_source_code=12096&force_no_smb=true&h5Url=https%3A%2F%2Fs.m.taobao.com%2Fh5%3Ffrom%3Dcustoms%26g_channelSrp%3Ddhhdpa_1232552832%26dpa_material_type%3D1%26ut_sk%3Dsearch%26spm%3Da2141.mb819t211c7%26sLaunch%3D0%26sKeep%3D1%26sModuleName%3Dsearch%26spm_back_up%3Da2141.mb819t211c7%26bc_fl_src%3Dgrowth_dhh_2200803434968_100-1930985-1595034112%26dpa_Inid%3D159503411212096%26dpa_material_id%3D530637422585%26dpa_material_type%3D1%26dpa_source_code%3D12096%26force_no_smb%3Dtrue%26itemIds%3D530637422585%26slk_actid%3D100000000207%26spm%3D2014.ugdhh.2200803434968.100-1930985-1595034112%26wh_biz%3Dtm&itemIds=530637422585&slk_actid=100000000207&spm=2014.ugdhh.2200803434968.100-1930985-1595034112&wh_biz=tm";
  231. // RedisHelper.IncrBy(ruleKey);
  232. // RedisHelper.Expire(ruleKey, 86400 * 1);
  233. // }
  234. //}
  235. other_aff = true;
  236. return TaobaoParseOutput(result, swData, new
  237. {
  238. result.success,
  239. result.commercial,
  240. result.message,
  241. result.content,
  242. result.itemName,
  243. other_aff,
  244. result.deeplink_url,
  245. });
  246. }
  247. if ((!is_tao_url && is_tao_token) || is_aff_link)
  248. {
  249. //没有短链接都放弃
  250. result.success = false;
  251. result.message = "放弃转链";
  252. result.reason = "初步筛选2";
  253. result.subCode = TkSubCodeEnum.Prelim2;
  254. result.itemName = "点击打开淘宝APP";
  255. _ = TkLogCore.ParseLogAsync(result);
  256. //20241229 特例
  257. //if ("bj".Equals(EndPointCore.CurrentEndPoint))
  258. //{
  259. // string ruleKey = $"tmp_rules2:tb:{DateTime.Now:yyyyMMdd}";
  260. // var count = RedisHelper.Get<int>(ruleKey);
  261. // var now = DateTime.Now;
  262. // if (now > new DateTime(2024, 12, 19) && now <= new DateTime(2024, 12, 22) && now.Hour >= 7 && count < 1000)
  263. // {
  264. // result.deeplink_url = "tbopen://m.taobao.com/tbopen/index.html?source=auto&action=ali.open.nav&module=h5&bootImage=0&afc_route=1&bc_fl_src=growth_dhh_2200803434968_100-1930985-1595034112&dpa_Inid=159503411212096&dpa_material_id=530637422585&dpa_material_type=1&dpa_source_code=12096&force_no_smb=true&h5Url=https%3A%2F%2Fs.m.taobao.com%2Fh5%3Ffrom%3Dcustoms%26g_channelSrp%3Ddhhdpa_1232552832%26dpa_material_type%3D1%26ut_sk%3Dsearch%26spm%3Da2141.mb819t211c7%26sLaunch%3D0%26sKeep%3D1%26sModuleName%3Dsearch%26spm_back_up%3Da2141.mb819t211c7%26bc_fl_src%3Dgrowth_dhh_2200803434968_100-1930985-1595034112%26dpa_Inid%3D159503411212096%26dpa_material_id%3D530637422585%26dpa_material_type%3D1%26dpa_source_code%3D12096%26force_no_smb%3Dtrue%26itemIds%3D530637422585%26slk_actid%3D100000000207%26spm%3D2014.ugdhh.2200803434968.100-1930985-1595034112%26wh_biz%3Dtm&itemIds=530637422585&slk_actid=100000000207&spm=2014.ugdhh.2200803434968.100-1930985-1595034112&wh_biz=tm";
  265. // RedisHelper.IncrBy(ruleKey);
  266. // RedisHelper.Expire(ruleKey, 86400 * 1);
  267. // }
  268. //}
  269. other_aff = true;
  270. return TaobaoParseOutput(result, swData, new
  271. {
  272. result.success,
  273. result.commercial,
  274. result.message,
  275. result.content,
  276. result.itemName,
  277. other_aff,
  278. result.deeplink_url,
  279. });
  280. }
  281. //那就初步筛选3 有tb.cn 并且有 or 手淘发现
  282. string pattern = @"^(?!【淘宝】).*https?:\/\/m\.tb\.cn.*(?:手淘发现|手淘搜索)";
  283. bool isMatch = Regex.IsMatch(content, pattern);
  284. if (isMatch)
  285. {
  286. result.success = false;
  287. result.message = "放弃转链";
  288. result.reason = "初步筛选3";
  289. result.subCode = TkSubCodeEnum.Prelim3;
  290. result.itemName = "点击打开淘宝APP";
  291. _ = TkLogCore.ParseLogAsync(result);
  292. return TaobaoParseOutput(result, swData, new
  293. {
  294. result.success,
  295. result.commercial,
  296. result.message,
  297. result.content,
  298. result.itemName,
  299. other_aff,
  300. result.deeplink_url,
  301. });
  302. }
  303. //============================== 放弃转链-地区过滤 ==============================
  304. bool is_ignore2 = AlimamaPlus.ShouldIgnoreRequest(ip, oaid, out reason);
  305. if (is_ignore2)
  306. {
  307. result.success = false;
  308. result.message = "放弃转链";
  309. result.itemName = "点击打开淘宝APP";
  310. result.reason = reason;
  311. result.subCode = TkSubCodeEnum.TrafficCtrl;
  312. _ = TkLogCore.ParseLogAsync(result);
  313. return TaobaoParseOutput(result, swData, new
  314. {
  315. result.success,
  316. result.commercial,
  317. result.message,
  318. result.content,
  319. result.itemName,
  320. other_aff,
  321. result.deeplink_url,
  322. });
  323. }
  324. //============================== 放弃转链-没有匹配账号 ==============================
  325. TkPoolDTO? account = accountid > 0 ?
  326. await TkPoolCore.GetOneAsync(accountid) :
  327. await TkPoolCore.GetOneAsync(TkPoolCore.TkAction.parse);
  328. if (account == null)
  329. {
  330. result.success = false;
  331. result.message = "放弃转链";
  332. result.reason = "没有匹配账号";
  333. result.subCode = TkSubCodeEnum.Other;
  334. result.itemName = "点击打开淘宝APP";
  335. _ = TkLogCore.ParseLogAsync(result);
  336. return TaobaoParseOutput(result, swData, new
  337. {
  338. result.success,
  339. result.commercial,
  340. result.message,
  341. result.content,
  342. result.couponAmount,
  343. result.taoToken,
  344. result.shortLinkurl,
  345. other_aff,
  346. result.deeplink_url,
  347. });
  348. }
  349. result.accountId = account.id;
  350. result.accountName = account.company;
  351. alimama = new AlimamaPlus(account);
  352. int timeout = alimama._config.rt_max;
  353. #if DEBUG
  354. timeout = 10000;
  355. #endif
  356. using var cts = new CancellationTokenSource();
  357. cts.CancelAfter(timeout);
  358. var requestTask = Task.Run(() => alimama.UnionParse2Async(content, commerceType, result, cts.Token, swData), cts.Token);
  359. var delayTask = Task.Delay(timeout, cts.Token);
  360. var completedTask = await Task.WhenAny(requestTask, delayTask);
  361. if (completedTask == requestTask)
  362. {
  363. result = await requestTask;
  364. }
  365. else
  366. {
  367. //============================== 放弃转链-请求超时 ==============================
  368. cts.Cancel();
  369. result.success = false;
  370. result.message = "放弃转链";
  371. result.reason = "请求超时";
  372. result.subCode = TkSubCodeEnum.Other;
  373. result.itemName = "点击打开淘宝APP";
  374. }
  375. result.accountName = account.company;
  376. //result = await alimama.UnionParse2Async(content, result);
  377. }
  378. catch (Exception ex)
  379. {
  380. //============================== 放弃转链-请求超时 ==============================
  381. if (ex.Message.Contains("was canceled"))
  382. {
  383. result.success = false;
  384. result.message = "放弃转链";
  385. result.reason = "请求超时";
  386. result.subCode = TkSubCodeEnum.Other;
  387. result.itemName = "点击打开淘宝APP";
  388. }
  389. else
  390. {
  391. //============================== 转链接口异常 ==============================
  392. _ = new LoggerLibrary("unionParse", "tb_error")
  393. .Info(ip, oaid)
  394. .Info(content)
  395. .Info(ex.Message, ex.StackTrace)
  396. .SaveAsync();
  397. NotifyCore.Notify(new NifyMessage
  398. {
  399. message = $"【转链异常TB】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  400. priority = NifyMessagePriority.high,
  401. tags = ["red_circle"]
  402. });
  403. result.success = false;
  404. result.subCode = TkSubCodeEnum.Other;
  405. result.message = "转链接口异常";
  406. result.itemName = "点击打开淘宝APP";
  407. }
  408. }
  409. _ = TkLogCore.ParseLogAsync(result, alimama);
  410. switch (result.reason)
  411. {
  412. case "其他推广链接":
  413. //case "排除淘口令":
  414. case "纯口令 没链接":
  415. other_aff = true;
  416. break;
  417. }
  418. return TaobaoParseOutput(result, swData, new
  419. {
  420. result.success,
  421. result.commercial,
  422. result.message,
  423. link_type = result.link_type.ToString(),
  424. channel = result?.channel.ToString(),
  425. result.channel_type,
  426. result.itemId,
  427. result.itemName,
  428. result.pic,
  429. result.promotionPrice,
  430. result.couponAmount,
  431. result.couponEffectiveStartTime,
  432. result?.couponEffectiveEndTime,
  433. result.shortLinkurl,
  434. result.deeplink_url,
  435. result.content,
  436. result.taoToken,
  437. other_aff,
  438. });
  439. }
  440. private static APIResult JdParseOutput(JdDataDTO result, APIResultCodeEnum code = APIResultCodeEnum.OK)
  441. {
  442. return new APIResult(new
  443. {
  444. result.success,
  445. result.message,
  446. link_type = result.link_type.ToString(),
  447. channel = result?.channel.ToString(),
  448. result.channel_type,
  449. result.itemId,
  450. result.itemName,
  451. result.shortLinkurl,
  452. result.deeplink_url,
  453. }, code);
  454. }
  455. public static async Task<APIResult> JdParseAsync(string content, int commerceType, string ip, string oaid,
  456. int accountid = 0, string clickId = "", CancellationToken cancellationToken = default)
  457. {
  458. var config = TkConfigCore.Get();
  459. var result = JdUnionPlus.GetFormattedObject(content, ip, oaid, clickId);
  460. content = content.UrlDecode();
  461. result.rawContent = content;
  462. bool IfExceptional = false;
  463. try
  464. {
  465. if (!string.IsNullOrEmpty(config.jd_blacklist_regular))
  466. {
  467. var blacklist = config.jd_blacklist_regular.Split('\n')
  468. .Where(line => !string.IsNullOrWhiteSpace(line))
  469. .ToList();
  470. bool anyMatch = false;
  471. foreach (string pattern in blacklist)
  472. {
  473. if (Regex.IsMatch(content, pattern, RegexOptions.IgnoreCase)) anyMatch = true;
  474. }
  475. if (anyMatch)
  476. {
  477. result.success = false;
  478. result.deeplink_url = string.Empty;
  479. result.message = "放弃转链";
  480. result.reason = "规则排除";
  481. _ = TkLogCore.ParseLogAsync(result);
  482. return JdParseOutput(result);
  483. }
  484. }
  485. //============================== 放弃转链-地区过滤 ==============================
  486. if (!result.ip.StartsWith("127.0.0") && accountid == 0 && JdUnionPlus.ShouldIgnoreRequest(config, ip, oaid, out string reason))
  487. {
  488. result.link_type = JdUnionPlus.GetLinkType(result.shortLinkurl, out string out_url, out string itemId);
  489. result.deeplink_url = result.link_type switch
  490. {
  491. LinkTypeEnum.other_aff or
  492. LinkTypeEnum.live or
  493. LinkTypeEnum.video or
  494. LinkTypeEnum.profile or
  495. LinkTypeEnum.goods => JdUnionPlus.GetDeeplink(result.shortLinkurl, clickId),
  496. _ => JdUnionPlus.GetDeeplink(string.Empty, clickId),
  497. };
  498. //if (result.link_type == LinkTypeEnum.other_aff)
  499. //{
  500. // //20241204 特例
  501. // if ("bj".Equals(EndPointCore.CurrentEndPoint))
  502. // {
  503. // string ruleKey = $"tmp_rules1:jd:{DateTime.Now:yyyyMMdd}";
  504. // var count = RedisHelper.Get<int>(ruleKey);
  505. // if (DateTime.Now < DateTime.Parse("2024-12-07") && count < 500)
  506. // {
  507. // result.deeplink_url = "openapp.jdmobile://virtual?params=%7B%22des%22%3A%22union%22%2C%22category%22%3A%22jump%22%2C%22url%22%3A%22https%3A%2F%2Fu.jd.com%2FugInesd%3Fe%3DCPS-11417-__ZLDEVICE__-CPS-wkfG72%22%7D&backurl=__back_url__";
  508. // RedisHelper.IncrBy(ruleKey);
  509. // RedisHelper.Expire(ruleKey, 86400 * 1);
  510. // }
  511. // }
  512. //}
  513. result.success = false;
  514. result.message = "放弃转链";
  515. result.reason = reason;
  516. _ = TkLogCore.ParseLogAsync(result);
  517. return JdParseOutput(result);
  518. }
  519. // bool is_ignore2 = JdUnionPlus.FlowControlIgnoreRequest(config, out reason);
  520. //#if DEBUG
  521. // is_ignore2 = false;
  522. //#endif
  523. // if (accountid == 0 && is_ignore2)
  524. // {
  525. // result.success = false;
  526. // result.message = "放弃转链";
  527. // result.reason = reason;
  528. // _ = TkLogCore.ParseLogAsync(result);
  529. // return JdParseOutput(result);
  530. // }
  531. var account = accountid > 0 ? await JdPoolCore.GetOneAsync(accountid, JdPoolCore.JdAction.parse) : await JdPoolCore.GetOneAsync(JdPoolCore.JdAction.parse);
  532. if (account == null)
  533. {
  534. result.success = false;
  535. result.message = "放弃转链";
  536. result.reason = "没有匹配账号";
  537. result.deeplink_url = result.link_type switch
  538. {
  539. LinkTypeEnum.other_aff or LinkTypeEnum.goods => JdUnionPlus.GetDeeplink(result.shortLinkurl, clickId),
  540. _ => JdUnionPlus.GetDeeplink(string.Empty, clickId),
  541. };
  542. _ = TkLogCore.ParseLogAsync(result);
  543. return JdParseOutput(result);
  544. }
  545. result.accountId = account.id;
  546. result.accountName = account.name;
  547. var plus = new JdUnionPlus(account);
  548. result = await plus.JdParseAsync(content, commerceType, clickId, result, cancellationToken);
  549. }
  550. catch (Exception ex)
  551. {
  552. if (ex.Message.Contains("was canceled"))
  553. {
  554. result.success = false;
  555. result.message = "放弃转链";
  556. result.reason = "请求超时";
  557. }
  558. else
  559. {
  560. IfExceptional = true;
  561. _ = new LoggerLibrary("unionParse", "jd_error")
  562. .Info(ip, oaid)
  563. .Info(content)
  564. .Info(ex.Message, ex.StackTrace)
  565. .SaveAsync();
  566. NotifyCore.Notify(new NifyMessage
  567. {
  568. message = $"【转链异常JD】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  569. priority = NifyMessagePriority.high,
  570. tags = ["red_circle"]
  571. });
  572. result.success = false;
  573. result.message = "内部错误";
  574. result.reason = "转链接口异常";
  575. }
  576. result.deeplink_url = result.link_type switch
  577. {
  578. LinkTypeEnum.other_aff or LinkTypeEnum.goods => JdUnionPlus.GetDeeplink(result.shortLinkurl, clickId),
  579. _ => JdUnionPlus.GetDeeplink(string.Empty, clickId),
  580. };
  581. }
  582. _ = TkLogCore.ParseLogAsync(result);
  583. return JdParseOutput(result, IfExceptional ? APIResultCodeEnum.NotAcceptable : APIResultCodeEnum.OK);
  584. }
  585. public static async Task<APIResult> DyParseAsync(string content, int commerceType, string ip, string oaid, CancellationToken cancellationToken = default)
  586. {
  587. var result = DyUnionPlus.GetFormattedObject(content, ip, oaid);
  588. content = content.UrlDecode();
  589. result.rawContent = content;
  590. bool IfExceptional = false;
  591. try
  592. {
  593. #if DEBUG
  594. #else
  595. // 2024-06-19 联盟业务下线
  596. result.success = false;
  597. result.message = "放弃转链";
  598. result.reason = "联盟下线";
  599. _ = TkLogCore.ParseLogAsync(result);
  600. return new APIResult(result);
  601. #endif
  602. if (DyUnionPlus.ShouldIgnoreRequest(ip, oaid, out string reason))
  603. {
  604. result.success = false;
  605. result.message = "放弃转链";
  606. result.reason = reason;
  607. _ = TkLogCore.ParseLogAsync(result);
  608. return new APIResult(result);
  609. }
  610. var account = PangolinPoolCore.GetOne();
  611. if (account == null)
  612. {
  613. result.success = false;
  614. result.message = "放弃转链";
  615. result.reason = "没有匹配账号";
  616. _ = TkLogCore.ParseLogAsync(result);
  617. return new APIResult(result);
  618. }
  619. result = await DyUnionPlus.DyParseAsync(account, content, commerceType, result, cancellationToken);
  620. }
  621. catch (Exception ex)
  622. {
  623. if (ex.Message.Contains("was canceled"))
  624. {
  625. result.success = false;
  626. result.message = "放弃转链";
  627. result.reason = "请求超时";
  628. }
  629. else
  630. {
  631. IfExceptional = true;
  632. _ = new LoggerLibrary("unionParse", "dy_error")
  633. .Info(ip, oaid)
  634. .Info(content)
  635. .Info(ex.Message, ex.StackTrace)
  636. .SaveAsync();
  637. NotifyCore.Notify(new NifyMessage
  638. {
  639. message = $"【转链异常DY】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  640. priority = NifyMessagePriority.high,
  641. tags = ["red_circle"]
  642. });
  643. result.success = false;
  644. result.message = "内部错误";
  645. result.reason = "转链接口异常";
  646. }
  647. }
  648. _ = TkLogCore.ParseLogAsync(result);
  649. return new APIResult(new
  650. {
  651. result.success,
  652. result.message,
  653. link_type = result.link_type.ToString(),
  654. channel = result?.channel.ToString(),
  655. content = result?.rawContent.ToString(),
  656. taoToken = result?.taoToken.ToString(),
  657. result.channel_type,
  658. result.itemName,
  659. result.shortLinkurl,
  660. result.deeplink_url,
  661. }, IfExceptional ? APIResultCodeEnum.NotAcceptable : APIResultCodeEnum.OK);
  662. }
  663. public static async Task<APIResult> PddParseAsync(string content, int commerceType, string ip, string oaid,
  664. int accountid = 0, CancellationToken cancellationToken = default)
  665. {
  666. var result = PddUnionPlus.GetFormattedObject(content, ip, oaid);
  667. content = content.UrlDecode();
  668. result.rawContent = content;
  669. bool IfExceptional = false;
  670. try
  671. {
  672. var config = TkConfigCore.Get();
  673. if (!string.IsNullOrEmpty(config.pdd_blacklist_regular))
  674. {
  675. var blacklist = config.pdd_blacklist_regular.Split('\n')
  676. .Where(line => !string.IsNullOrWhiteSpace(line))
  677. .ToList();
  678. bool anyMatch = false;
  679. foreach (string pattern in blacklist)
  680. {
  681. if (Regex.IsMatch(content, pattern, RegexOptions.IgnoreCase)) anyMatch = true;
  682. }
  683. if (anyMatch)
  684. {
  685. result.success = false;
  686. result.deeplink_url = string.Empty;
  687. result.message = "放弃转链";
  688. result.reason = "规则排除";
  689. _ = TkLogCore.ParseLogAsync(result);
  690. return PddParseOutput(result);
  691. }
  692. }
  693. //============================== 放弃转链-地区过滤 ==============================
  694. if (accountid == 0 && PddUnionPlus.ShouldIgnoreRequest(config, ip, oaid, out string reason))
  695. {
  696. result.success = false;
  697. result.message = "放弃转链";
  698. result.reason = reason;
  699. _ = TkLogCore.ParseLogAsync(result);
  700. return PddParseOutput(result);
  701. }
  702. var account = PddPoolCore.GetOne(PddUnionWorkMode.All, accountid);
  703. if (account == null)
  704. {
  705. result.success = false;
  706. result.message = "放弃转链";
  707. result.reason = "没有匹配账号";
  708. _ = TkLogCore.ParseLogAsync(result);
  709. return PddParseOutput(result);
  710. }
  711. result.accountId = account.id;
  712. result.accountName = account.name;
  713. var plus = new PddUnionPlus(account);
  714. result = await plus.PddParseAsync(content, commerceType, result, cancellationToken);
  715. }
  716. catch (Exception ex)
  717. {
  718. if (ex.Message.Contains("was canceled"))
  719. {
  720. result.success = false;
  721. result.message = "放弃转链";
  722. result.reason = "请求超时";
  723. }
  724. else
  725. {
  726. IfExceptional = true;
  727. _ = new LoggerLibrary("unionParse", "pdd_error")
  728. .Info(ip, oaid)
  729. .Info(content)
  730. .Info(ex.Message, ex.StackTrace)
  731. .SaveAsync();
  732. NotifyCore.Notify(new NifyMessage
  733. {
  734. message = $"【转链异常PDD】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  735. priority = NifyMessagePriority.high,
  736. tags = ["red_circle"]
  737. });
  738. result.success = false;
  739. result.message = "内部错误";
  740. result.reason = "转链接口异常";
  741. }
  742. }
  743. _ = TkLogCore.ParseLogAsync(result);
  744. return PddParseOutput(result, IfExceptional ? APIResultCodeEnum.NotAcceptable : APIResultCodeEnum.OK);
  745. }
  746. private static APIResult PddParseOutput(PddDataDTO result, APIResultCodeEnum code = APIResultCodeEnum.OK)
  747. {
  748. return new APIResult(new
  749. {
  750. result.success,
  751. result.message,
  752. link_type = result.link_type.ToString(),
  753. channel = result?.channel.ToString(),
  754. result.itemId,
  755. result.itemName,
  756. result.shortLinkurl,
  757. result.deeplink_url,
  758. }, code);
  759. }
  760. public static async Task<APIResult> KsParseAsync(string content, int commerceType, string ip, string oaid,
  761. int accountid = 0, CancellationToken cancellationToken = default)
  762. {
  763. var result = KsUnionPlus.GetFormattedObject(content, ip, oaid);
  764. content = content.UrlDecode();
  765. result.rawContent = content;
  766. bool IfExceptional = false;
  767. try
  768. {
  769. var config = TkConfigCore.Get();
  770. if (!string.IsNullOrEmpty(config.ks_blacklist_regular))
  771. {
  772. var blacklist = config.ks_blacklist_regular.Split('\n')
  773. .Where(line => !string.IsNullOrWhiteSpace(line))
  774. .ToList();
  775. bool anyMatch = false;
  776. foreach (string pattern in blacklist)
  777. {
  778. if (Regex.IsMatch(content, pattern, RegexOptions.IgnoreCase)) anyMatch = true;
  779. }
  780. if (anyMatch)
  781. {
  782. result.success = false;
  783. result.deeplink_url = string.Empty;
  784. result.message = "放弃转链";
  785. result.reason = "规则排除";
  786. _ = TkLogCore.ParseLogAsync(result);
  787. return KsParseOutput(result);
  788. }
  789. }
  790. //============================== 放弃转链-地区过滤 ==============================
  791. if (accountid == 0 && KsUnionPlus.ShouldIgnoreRequest(config, ip, oaid, out string reason))
  792. {
  793. result.success = false;
  794. result.message = "放弃转链";
  795. result.reason = reason;
  796. result.deeplink_url = KsUnionPlus.GetDeeplink(string.Empty, LinkTypeEnum.baseDomain);
  797. _ = TkLogCore.ParseLogAsync(result);
  798. return KsParseOutput(result);
  799. }
  800. var account = accountid > 0 ? KsPoolCore.GetOne(accountid, KsPoolCore.KsAction.parse) : KsPoolCore.GetOne(KsPoolCore.KsAction.parse);
  801. if (account == null)
  802. {
  803. result.success = false;
  804. result.message = "放弃转链";
  805. result.reason = "没有匹配账号";
  806. result.deeplink_url = KsUnionPlus.GetDeeplink(string.Empty, LinkTypeEnum.baseDomain);
  807. _ = TkLogCore.ParseLogAsync(result);
  808. return KsParseOutput(result);
  809. }
  810. result.accountId = account.id;
  811. result.accountName = account.name;
  812. var plus = new KsUnionPlus(account);
  813. result = await plus.KsParseAsync(content, commerceType, result, cancellationToken);
  814. }
  815. catch (Exception ex)
  816. {
  817. if (ex.Message.Contains("was canceled"))
  818. {
  819. result.success = false;
  820. result.message = "放弃转链";
  821. result.reason = "请求超时";
  822. }
  823. else
  824. {
  825. IfExceptional = true;
  826. _ = new LoggerLibrary("unionParse", "jd_error")
  827. .Info(ip, oaid)
  828. .Info(content)
  829. .Info(ex.Message, ex.StackTrace)
  830. .SaveAsync();
  831. NotifyCore.Notify(new NifyMessage
  832. {
  833. message = $"【转链异常JD】\n{content}\n\n{ex.Message}\n{ex.StackTrace}",
  834. priority = NifyMessagePriority.high,
  835. tags = ["red_circle"]
  836. });
  837. result.success = false;
  838. result.message = "内部错误";
  839. result.reason = "转链接口异常";
  840. }
  841. result.deeplink_url = KsUnionPlus.GetDeeplink(string.Empty, LinkTypeEnum.baseDomain);
  842. }
  843. _ = TkLogCore.ParseLogAsync(result);
  844. return KsParseOutput(result, IfExceptional ? APIResultCodeEnum.NotAcceptable : APIResultCodeEnum.OK);
  845. }
  846. private static APIResult KsParseOutput(KsDataDTO result, APIResultCodeEnum code = APIResultCodeEnum.OK)
  847. {
  848. return new APIResult(new
  849. {
  850. result.success,
  851. result.message,
  852. link_type = result.link_type.ToString(),
  853. channel = result?.channel.ToString(),
  854. result.itemId,
  855. result.itemName,
  856. result.shortLinkurl,
  857. result.deeplink_url,
  858. }, code);
  859. }
  860. }
  861. }