UnionParseCore.cs 40 KB

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