DyUnionPlus.cs 10 KB

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