DyUnionPlus.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. string pattern = @"https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]";
  96. Regex regex = new(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. string message = "OK";
  210. string url = GetLink(content);
  211. string? desired_url = url;
  212. if (url.StartsWith("https://v.douyin.com")) desired_url = GetDesiredUrl(url);
  213. result.link_type = GetLinkType(content, desired_url);
  214. result.deeplink_url = GetDeeplink(desired_url, url, result.link_type);
  215. if (result.link_type == LinkTypeEnum.other_aff)
  216. {
  217. result.success = false;
  218. result.link_type = LinkTypeEnum.unknown;
  219. result.channel_type = ChannelTypeEnum.dy;
  220. result.message = "其他推广链接";
  221. result.accountName = string.Empty;
  222. result.content = content;
  223. result.shortLinkurl = url;
  224. }
  225. switch (result.link_type)
  226. {
  227. case LinkTypeEnum.other_aff:
  228. {
  229. result.success = false;
  230. result.channel_type = ChannelTypeEnum.dy;
  231. result.message = "其他推广链接";
  232. result.accountName = string.Empty;
  233. result.content = content;
  234. result.shortLinkurl = url;
  235. return result;
  236. }
  237. case LinkTypeEnum.goods:
  238. case LinkTypeEnum.live:
  239. {
  240. result = await plus.ParseAsync(url, result, cancellationToken);
  241. return result;
  242. }
  243. //case LinkTypeEnum.live:
  244. // {
  245. // string room_id = result.deeplink_url.GetContentPart("room_id=", "");
  246. // result = await plus.LiveParse(room_id, result);
  247. // return result;
  248. // }
  249. default:
  250. //跳转到抖音
  251. result.shortLinkurl = url;
  252. result.success = false;
  253. result.message = "转链失败";
  254. return result;
  255. }
  256. }
  257. }
  258. }