DyUnionPlus.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 Dataoke;
  10. using System.Text.RegularExpressions;
  11. using Org.BouncyCastle.Ocsp;
  12. using System.Diagnostics;
  13. using TencentCloud.Fmu.V20191213.Models;
  14. using Microsoft.VisualBasic;
  15. using System.Text.Json;
  16. using static System.Runtime.InteropServices.JavaScript.JSType;
  17. using System.Security.Cryptography;
  18. using Google.Protobuf.WellKnownTypes;
  19. using System.Net;
  20. using TencentCloud.Apm.V20210622.Models;
  21. using TencentCloud.Dsgc.V20190723.Models;
  22. using TencentCloud.Dts.V20211206.Models;
  23. using TencentCloud.Waf.V20180125.Models;
  24. using System.Data.SqlTypes;
  25. namespace molilian.core
  26. {
  27. public partial class DyUnionPlus
  28. {
  29. private static string _end_point;
  30. static DyUnionPlus()
  31. {
  32. _end_point = Environment.GetEnvironmentVariable("EndPoint");
  33. }
  34. public static DyDataDTO GetFormattedObject(string content, string ip = "", string oaid = "")
  35. {
  36. string shortLinkurl = GetLink(content);
  37. string deeplink_url = GetDeeplink(shortLinkurl, "", LinkTypeEnum.unknown);
  38. return new DyDataDTO()
  39. {
  40. message = string.Empty,
  41. link_type = LinkTypeEnum.unknown,
  42. channel = TkChannelEnum.dy,
  43. channel_type = ChannelTypeEnum.dy,
  44. accountName = string.Empty,
  45. success = false,
  46. content = content,
  47. ip = ip,
  48. oaid = oaid,
  49. elapsedTime = 0,
  50. shortLinkurl = shortLinkurl,
  51. deeplink_url = deeplink_url,
  52. itemName = "点击打开抖音APP",
  53. create_time = DateTime.Now,
  54. end_point = _end_point
  55. };
  56. }
  57. public static bool IsAffToken(string content)
  58. {
  59. if (string.IsNullOrEmpty(content)) return false;
  60. string pattern = "[ďȌƯƔɪƝɖƟɏƖԂȎȗϓɫɧơȲǏđǫƲƳɨǹƊȮǚƴɬɲƿȖȳɳɗʮϔӢǙɦɒɎƥʘưΊƞǪȈʠΌǓϒίȠƠƱƗǸ]{6}(.*?)([◤|◥|☆|商|品|详|情]+)[ˇ|ǚ|➝|Š|※|\\#|^|︽]{2}([A-Za-z0-9]+)[ǚ|ˇ|Ƞ|⇜|ǚ|︽|ˇ|\\#|^|Š|ǚ|^|➝|※]{2}";
  61. Match match = Regex.Match(content, pattern);
  62. return match.Success;
  63. }
  64. public static bool IsDyToken(string content)
  65. {
  66. if (string.IsNullOrEmpty(content)) return false;
  67. string pattern = "([ďȌƯƔɪƝɖƟɏƖԂȎȗϓɫɧơȲǏđǫƲƳɨǹƊȮǚƴɬɲƿȖȳɳɗʮϔӢǙɦɒɎƥʘưΊƞǪȈʠΌǓϒίȠƠƱƗǸĎÕŮÝÌŇ]{6}(?:极速版)?(?:口令|搜索))|##[a-zA-Z0-9]+##\\[抖音(?:极速版)?口令\\]";
  68. Regex regex = new(pattern);
  69. Match match = Regex.Match(content, pattern);
  70. return match.Success;
  71. }
  72. public static string? GetDesiredUrl(string url)
  73. {
  74. try
  75. {
  76. WebClientUtility client = new()
  77. {
  78. AllowAutoRedirect = false
  79. };
  80. var response = client.Request(url);
  81. if (!response.Successed) return null;
  82. var target_url = response.ResponseMessage?.Headers?.Location?.ToString();
  83. return target_url;
  84. }
  85. catch (Exception ex)
  86. {
  87. }
  88. return null;
  89. }
  90. public static string GetLink(string content)
  91. {
  92. if (string.IsNullOrEmpty(content)) return content;
  93. string result = content;
  94. //string pattern = @"https?:\/\/?([\da-z\.-]+)\.([a-z]{2,6})(:\d{1,5})?([\/\w\.-]*)*\/?(#[\S]+)?(\?[\S]+)?";
  95. Regex regex = new(AlimamaPlus._url_pattern);
  96. MatchCollection matches = regex.Matches(content);
  97. foreach (Match m in matches.Cast<Match>())
  98. {
  99. string url = m.Value;
  100. return url;
  101. }
  102. return string.Empty;
  103. }
  104. public static LinkTypeEnum GetLinkType(string content, string? url)
  105. {
  106. if (!string.IsNullOrEmpty(content))
  107. {
  108. if (IsAffToken(content)) return LinkTypeEnum.other_aff;
  109. if (IsDyToken(content)) return LinkTypeEnum.goods;
  110. }
  111. if (string.IsNullOrEmpty(url)) return LinkTypeEnum.unknown;
  112. if (url.Contains("v.buydouke.com"))
  113. {
  114. //推广域名
  115. return LinkTypeEnum.other_aff;
  116. }
  117. if (url.StartsWith("https://www.iesdouyin.com/share/video"))
  118. {
  119. return LinkTypeEnum.video;
  120. }
  121. if (url.StartsWith("https://www.iesdouyin.com/share/user"))
  122. {
  123. return LinkTypeEnum.profile;
  124. }
  125. if (url.StartsWith("https://www.iesdouyin.com/share/note"))
  126. {
  127. return LinkTypeEnum.note;
  128. }
  129. if (url.StartsWith("https://webcast.amemv.com"))
  130. {
  131. return LinkTypeEnum.live;
  132. }
  133. if (url.StartsWith("https://haohuo.jinritemai.com/ecommerce/trade/detail"))
  134. {
  135. return LinkTypeEnum.goods;
  136. }
  137. if (url.Contains("iesdouyin.com") ||
  138. url.Contains("jinritemai.com") ||
  139. url.Contains("amemv.com") ||
  140. url.Contains("douyin.com"))
  141. {
  142. return LinkTypeEnum.baseDomain;
  143. }
  144. return LinkTypeEnum.unknown;
  145. }
  146. static bool ContainsSpecialFormat(string content)
  147. {
  148. // 使用正则表达式匹配内容中是否含有特定格式的字符串
  149. string pattern = @"[!$¥%]+[a-zA-Z0-9]+[!$¥%]]*";
  150. return Regex.IsMatch(content, pattern);
  151. }
  152. public static string GetDeeplink(string url, string shortLinkurl, LinkTypeEnum link_type)
  153. {
  154. string baseDeeplink = "snssdk1128://";
  155. if (string.IsNullOrEmpty(url)) return $"{baseDeeplink}feed?refer=web";
  156. try
  157. {
  158. switch (link_type)
  159. {
  160. case LinkTypeEnum.live:
  161. {
  162. var room_id = url.GetContentPart("webcast/reflow/", "?");
  163. return $"{baseDeeplink}live?room_id={room_id}";
  164. }
  165. case LinkTypeEnum.video:
  166. {
  167. var video_id = url.GetContentPart("/share/video/", "/");
  168. return $"{baseDeeplink}aweme/detail/{video_id}";
  169. }
  170. case LinkTypeEnum.note:
  171. {
  172. var video_id = url.GetContentPart("/share/note/", "/");
  173. return $"{baseDeeplink}aweme/detail/{video_id}";
  174. }
  175. case LinkTypeEnum.goods:
  176. {
  177. return $"{baseDeeplink}webview?url={shortLinkurl.UrlEncode()}";
  178. }
  179. case LinkTypeEnum.profile:
  180. {
  181. var sec_uid = url.GetContentPart("/share/user/", "?");
  182. return $"{baseDeeplink}user/profile?sec_uid={sec_uid}";
  183. }
  184. case LinkTypeEnum.unknown:
  185. case LinkTypeEnum.baseDomain:
  186. return $"{baseDeeplink}webview?url={url.UrlEncode()}&from=webview&hide_nav_bar=1&refer=web";
  187. case LinkTypeEnum.other_aff:
  188. return $"{baseDeeplink}feed?refer=web";
  189. }
  190. //string virtual_params = $"{{\"category\":\"jump\",\"des\":\"m\",\"sourceValue\":\"babel-act\",\"sourceType\":\"babel\",\"url\":\"{url}\",\"M_sourceFrom\":\"h5auto\",\"msf_type\":\"auto\"}}";
  191. //string result = $"openapp.jdmobile://virtual?params={virtual_params.UrlEncode()}";
  192. //return result;
  193. /*
  194. * 短视频跟直播间的 根据url的curl直接取id拼接dp
  195. *
  196. 商品分两种 可转链不可转 走穿山甲api去转,能转的直接用api的dp,不能转的就直接webview拼接原地址做dp
  197. 商品,短视频,直播间,个人主页
  198. */
  199. }
  200. catch
  201. {
  202. }
  203. return baseDeeplink;
  204. }
  205. public static async Task<DyDataDTO> DyParseAsync(PangolinDTO account, string content, DyDataDTO result, CancellationToken cancellationToken = default)
  206. {
  207. var plus = new DyUnionPlus(account.app_key, account.app_secret);
  208. #if DEBUG
  209. string test = await plus.AggregateH5Async("7369141045465973001", cancellationToken);
  210. #endif
  211. string message = "OK";
  212. string url = GetLink(content);
  213. string? desired_url = url;
  214. if (url.StartsWith("https://v.douyin.com")) desired_url = GetDesiredUrl(url);
  215. result.link_type = GetLinkType(content, desired_url);
  216. result.deeplink_url = GetDeeplink(desired_url, url, result.link_type);
  217. if (result.link_type == LinkTypeEnum.other_aff)
  218. {
  219. result.success = false;
  220. result.link_type = LinkTypeEnum.unknown;
  221. result.channel_type = ChannelTypeEnum.dy;
  222. result.message = "其他推广链接";
  223. result.accountName = string.Empty;
  224. result.content = content;
  225. result.shortLinkurl = url;
  226. }
  227. switch (result.link_type)
  228. {
  229. case LinkTypeEnum.other_aff:
  230. {
  231. result.success = false;
  232. result.channel_type = ChannelTypeEnum.dy;
  233. result.message = "其他推广链接";
  234. result.accountName = string.Empty;
  235. result.content = content;
  236. result.shortLinkurl = url;
  237. return result;
  238. }
  239. case LinkTypeEnum.goods:
  240. case LinkTypeEnum.live:
  241. {
  242. result = await plus.ParseAsync(url, result, cancellationToken);
  243. return result;
  244. }
  245. //case LinkTypeEnum.live:
  246. // {
  247. // string room_id = result.deeplink_url.GetContentPart("room_id=", "");
  248. // result = await plus.LiveParse(room_id, result);
  249. // return result;
  250. // }
  251. default:
  252. //跳转到抖音
  253. result.shortLinkurl = url;
  254. result.success = false;
  255. result.message = "转链失败";
  256. return result;
  257. }
  258. }
  259. }
  260. }