PddUnionPlus.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using dodohold.core;
  2. using Sayaka.Common;
  3. using System.Diagnostics;
  4. using System.Text.RegularExpressions;
  5. using System.Web;
  6. namespace molilian.core
  7. {
  8. public partial class PddUnionPlus
  9. {
  10. public static string _url_pattern = @"https?://(?:[\w-]+\.)*(?:yangkeduo\.com|pinduoduo\.com)(?:/[^\s]*)?";
  11. public static string GetLink(string content)
  12. {
  13. if (string.IsNullOrEmpty(content)) return content;
  14. string result = content;
  15. //
  16. Regex regex = new(_url_pattern);
  17. MatchCollection matches = regex.Matches(content);
  18. foreach (Match m in matches.Cast<Match>())
  19. {
  20. string url = m.Value;
  21. return url;
  22. }
  23. return string.Empty;
  24. }
  25. public static string GetDeeplink(string url)
  26. {
  27. string result = $"pinduoduo://com.xunmeng.pinduoduo/{url}";
  28. return result;
  29. }
  30. private string ExtractGoodsIdUrl(string url)
  31. {
  32. var uri = new Uri(url);
  33. var queryParams = HttpUtility.ParseQueryString(uri.Query);
  34. string goodsId = queryParams["goods_id"];
  35. if (!string.IsNullOrEmpty(goodsId)&& uri.AbsolutePath.StartsWith("/goods"))
  36. {
  37. // 保持域名和路径不变,仅保留 goods_id 参数
  38. var baseUrl = $"{uri.Scheme}://{uri.Host}{uri.AbsolutePath}";
  39. return $"{baseUrl}?goods_id={goodsId}";
  40. }
  41. return url; // 如果没有找到 goods_id 参数,则返回原始 URL
  42. }
  43. public async Task<string> GetRedirectedUrlAsync(string sourceUrl, CancellationToken cancellationToken = default)
  44. {
  45. string pattern = @"^https?://mobile\.yangkeduo\.com/goods(\d*)\.html\?ps=.*$";
  46. Regex regex = new Regex(pattern);
  47. if (!regex.IsMatch(sourceUrl)) return ExtractGoodsIdUrl(sourceUrl);
  48. string redirectedUrl = sourceUrl;
  49. try
  50. {
  51. string useragent = ProviderFakeUserAgent.RandomMobile;
  52. WebClientUtility client = new()
  53. {
  54. AllowAutoRedirect = false,
  55. UserAgent = useragent,
  56. };
  57. client.Proxy = _proxy;
  58. #if DEBUG
  59. client.Proxy = null;
  60. #endif
  61. var response = await client.RequestAsync(sourceUrl, "GET", cancellationToken);
  62. if (!response.Successed) return null;
  63. if (response.ResponseMessage.StatusCode == System.Net.HttpStatusCode.RedirectKeepVerb ||
  64. response.ResponseMessage.StatusCode == System.Net.HttpStatusCode.TemporaryRedirect)
  65. {
  66. redirectedUrl = response.ResponseMessage.Headers.Location.ToString();
  67. redirectedUrl = ExtractGoodsIdUrl(redirectedUrl);
  68. return redirectedUrl;
  69. }
  70. }
  71. catch (Exception ex)
  72. {
  73. }
  74. return sourceUrl;
  75. }
  76. public static PddDataDTO GetFormattedObject(string content, string ip = "", string oaid = "")
  77. {
  78. string shortLinkurl = GetLink(content);
  79. string deeplink_url = GetDeeplink(shortLinkurl);
  80. var link_type = LinkTypeEnum.unknown;
  81. if (!string.IsNullOrEmpty(shortLinkurl) && shortLinkurl.StartsWith("https://p.pinduoduo.com/"))
  82. {
  83. link_type = LinkTypeEnum.other_aff;
  84. }
  85. return new PddDataDTO()
  86. {
  87. message = string.Empty,
  88. link_type = link_type,
  89. channel = TkChannelEnum.pdd,
  90. accountName = string.Empty,
  91. success = false,
  92. content = content,
  93. ip = ip,
  94. oaid = oaid,
  95. elapsedTime = 0,
  96. itemName = "点击打开拼多多APP",
  97. shortLinkurl = string.Empty,
  98. deeplink_url = string.Empty,
  99. create_time = DateTime.Now,
  100. end_point = _end_point,
  101. };
  102. }
  103. public async Task<PddDataDTO> PddParseAsync(string content, PddDataDTO result, CancellationToken cancellationToken = default)
  104. {
  105. string message = "OK";
  106. string url = GetLink(content);
  107. if (string.IsNullOrEmpty(url))
  108. {
  109. result.success = false;
  110. result.link_type = LinkTypeEnum.unknown;
  111. result.channel_type = ChannelTypeEnum.pdd;
  112. result.message = "放弃转链";
  113. result.reason = "无效链接";
  114. result.accountId = 0;
  115. result.accountName = string.Empty;
  116. result.content = content;
  117. return result;
  118. }
  119. string shortLinkurl = url;
  120. if (result.link_type == LinkTypeEnum.other_aff)
  121. {
  122. result.success = false;
  123. result.link_type = LinkTypeEnum.unknown;
  124. result.channel_type = ChannelTypeEnum.pdd;
  125. result.message = "放弃转链";
  126. result.reason = "其他推广链接";
  127. result.accountId = 0;
  128. result.accountName = string.Empty;
  129. result.content = content;
  130. return result;
  131. }
  132. if (!result.ip.StartsWith("127.0.0") && FlowControlIgnoreRequest(_config, out string reason))
  133. {
  134. result.success = false;
  135. result.link_type = LinkTypeEnum.unknown;
  136. result.channel_type = ChannelTypeEnum.pdd;
  137. result.message = "放弃转链";
  138. result.reason = reason;
  139. result.accountId = 0;
  140. result.accountName = string.Empty;
  141. result.content = content;
  142. return result;
  143. }
  144. //去追踪
  145. Stopwatch stopwatch = Stopwatch.StartNew();
  146. stopwatch.Start();
  147. var redirectedUrl = await GetRedirectedUrlAsync(url, cancellationToken);
  148. stopwatch.Stop();
  149. if (redirectedUrl != url)
  150. {
  151. result.rawContent2 = redirectedUrl;
  152. url = redirectedUrl;
  153. result.elapsedTime2 = (int)stopwatch.ElapsedMilliseconds;
  154. }
  155. Stopwatch stopwatch2 = Stopwatch.StartNew();
  156. stopwatch2.Start();
  157. switch (_account.work_mode)
  158. {
  159. case PddUnionWorkMode.SiteApi:
  160. result = await UnionGeneratelink(result, url, cancellationToken);
  161. break;
  162. //case PddUnionWorkMode.AffApi:
  163. // result = await GetPromotionByAffAsync(result, url, cancellationToken);
  164. // break;
  165. case PddUnionWorkMode.Crawler:
  166. default:
  167. result = await transferUrl(result, url, cancellationToken);
  168. break;
  169. }
  170. stopwatch2.Stop();
  171. result.elapsedTime3 = (int)stopwatch2.ElapsedMilliseconds;
  172. return result;
  173. }
  174. }
  175. }