PddUnionPlus.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. private bool IsTrackUrl(string sourceUrl)
  44. {
  45. string pattern = @"^https?://mobile\.yangkeduo\.com/goods(\d*)\.html\?ps=.*$";
  46. Regex regex = new Regex(pattern);
  47. return regex.IsMatch(sourceUrl);
  48. }
  49. /// <summary>
  50. /// bool:是否ps链接,string 处理后的链接
  51. /// </summary>
  52. /// <param name="sourceUrl"></param>
  53. /// <param name="cancellationToken"></param>
  54. /// <returns></returns>
  55. public async Task<string> GetRedirectedUrlAsync(string sourceUrl, CancellationToken cancellationToken = default)
  56. {
  57. var isTrackUrl = IsTrackUrl(sourceUrl);
  58. if (!isTrackUrl) return ExtractGoodsIdUrl(sourceUrl);
  59. string redirectedUrl = sourceUrl;
  60. try
  61. {
  62. string useragent = ProviderFakeUserAgent.RandomMobile;
  63. WebClientUtility client = new()
  64. {
  65. AllowAutoRedirect = false,
  66. UserAgent = useragent,
  67. };
  68. client.Proxy = _proxy;
  69. #if DEBUG
  70. client.Proxy = null;
  71. #endif
  72. var response = await client.RequestAsync(sourceUrl, "GET", cancellationToken);
  73. if (!response.Successed) return null;
  74. if (response.ResponseMessage.StatusCode == System.Net.HttpStatusCode.RedirectKeepVerb ||
  75. response.ResponseMessage.StatusCode == System.Net.HttpStatusCode.TemporaryRedirect)
  76. {
  77. redirectedUrl = response.ResponseMessage.Headers.Location.ToString();
  78. redirectedUrl = ExtractGoodsIdUrl(redirectedUrl);
  79. return redirectedUrl;
  80. }
  81. }
  82. catch (Exception ex)
  83. {
  84. }
  85. return sourceUrl;
  86. }
  87. public static PddDataDTO GetFormattedObject(string content, string ip = "", string oaid = "")
  88. {
  89. string shortLinkurl = GetLink(content);
  90. string deeplink_url = GetDeeplink(shortLinkurl);
  91. var link_type = LinkTypeEnum.unknown;
  92. if (!string.IsNullOrEmpty(shortLinkurl) && shortLinkurl.StartsWith("https://p.pinduoduo.com/"))
  93. {
  94. link_type = LinkTypeEnum.other_aff;
  95. }
  96. return new PddDataDTO()
  97. {
  98. message = string.Empty,
  99. link_type = link_type,
  100. channel = TkChannelEnum.pdd,
  101. accountName = string.Empty,
  102. success = false,
  103. content = content,
  104. ip = ip,
  105. oaid = oaid,
  106. elapsedTime = 0,
  107. itemName = "点击打开拼多多APP",
  108. shortLinkurl = string.Empty,
  109. deeplink_url = string.Empty,
  110. create_time = DateTime.Now,
  111. end_point = _end_point,
  112. };
  113. }
  114. public async Task<PddDataDTO> PddParseAsync(string content, PddDataDTO result, CancellationToken cancellationToken = default)
  115. {
  116. string message = "OK";
  117. string url = GetLink(content);
  118. if (string.IsNullOrEmpty(url))
  119. {
  120. result.success = false;
  121. result.link_type = LinkTypeEnum.unknown;
  122. result.channel_type = ChannelTypeEnum.pdd;
  123. result.message = "放弃转链";
  124. result.reason = "无效链接";
  125. result.accountId = 0;
  126. result.accountName = string.Empty;
  127. result.content = content;
  128. return result;
  129. }
  130. string shortLinkurl = url;
  131. if (result.link_type == LinkTypeEnum.other_aff)
  132. {
  133. result.success = false;
  134. result.link_type = LinkTypeEnum.unknown;
  135. result.channel_type = ChannelTypeEnum.pdd;
  136. result.message = "放弃转链";
  137. result.reason = "其他推广链接";
  138. result.accountId = 0;
  139. result.accountName = string.Empty;
  140. result.content = content;
  141. return result;
  142. }
  143. if (!result.ip.StartsWith("127.0.0") && FlowControlIgnoreRequest(_config, out string reason))
  144. {
  145. result.success = false;
  146. result.link_type = LinkTypeEnum.unknown;
  147. result.channel_type = ChannelTypeEnum.pdd;
  148. result.message = "放弃转链";
  149. result.reason = reason;
  150. result.accountId = 0;
  151. result.accountName = string.Empty;
  152. result.content = content;
  153. return result;
  154. }
  155. var isTrackUrl = IsTrackUrl(url);
  156. //不是跟踪链接 ps=*** 就返回
  157. if (!isTrackUrl)
  158. {
  159. result.success = false;
  160. result.link_type = LinkTypeEnum.unknown;
  161. result.channel_type = ChannelTypeEnum.pdd;
  162. result.message = "放弃转链";
  163. result.reason = "数字id链接";
  164. result.accountId = 0;
  165. result.accountName = string.Empty;
  166. result.content = content;
  167. return result;
  168. }
  169. //去追踪
  170. Stopwatch stopwatch = Stopwatch.StartNew();
  171. stopwatch.Start();
  172. var redirectedUrl = await GetRedirectedUrlAsync(url, cancellationToken);
  173. stopwatch.Stop();
  174. if (redirectedUrl != url)
  175. {
  176. result.rawContent2 = redirectedUrl;
  177. url = redirectedUrl;
  178. result.elapsedTime2 = (int)stopwatch.ElapsedMilliseconds;
  179. }
  180. Stopwatch stopwatch2 = Stopwatch.StartNew();
  181. stopwatch2.Start();
  182. switch (_account.work_mode)
  183. {
  184. case PddUnionWorkMode.SiteApi:
  185. result = await UnionGeneratelink(result, url, cancellationToken);
  186. break;
  187. //case PddUnionWorkMode.AffApi:
  188. // result = await GetPromotionByAffAsync(result, url, cancellationToken);
  189. // break;
  190. case PddUnionWorkMode.Crawler:
  191. default:
  192. result = await transferUrl(result, url, cancellationToken);
  193. break;
  194. }
  195. stopwatch2.Stop();
  196. result.elapsedTime3 = (int)stopwatch2.ElapsedMilliseconds;
  197. return result;
  198. }
  199. }
  200. }