DyUnionPlus.cs 10 KB

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