UnionParseCore.cs 41 KB

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