DyUnionPlus.cs 12 KB

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