using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Collections.Generic; using System.Linq; using System.Text; using dodohold.core; using Dataoke; using System.Text.RegularExpressions; using Org.BouncyCastle.Ocsp; using System.Diagnostics; using TencentCloud.Fmu.V20191213.Models; using Microsoft.VisualBasic; using System.Text.Json; using static System.Runtime.InteropServices.JavaScript.JSType; using System.Security.Cryptography; using Google.Protobuf.WellKnownTypes; using System.Net; using TencentCloud.Apm.V20210622.Models; using TencentCloud.Dsgc.V20190723.Models; using TencentCloud.Dts.V20211206.Models; using TencentCloud.Waf.V20180125.Models; using System.Data.SqlTypes; using COSXML.Network; namespace molilian.core { public partial class DyUnionPlus { private static string _end_point; static DyUnionPlus() { _end_point = Environment.GetEnvironmentVariable("EndPoint"); } public static DyDataDTO GetFormattedObject(string content, string ip = "", string oaid = "") { string shortLinkurl = GetLink(content); string deeplink_url = GetDeeplink(shortLinkurl, "", LinkTypeEnum.unknown); return new DyDataDTO() { message = string.Empty, link_type = LinkTypeEnum.unknown, channel = TkChannelEnum.dy, channel_type = ChannelTypeEnum.dy, accountName = string.Empty, success = false, content = content, ip = ip, oaid = oaid, elapsedTime = 0, shortLinkurl = shortLinkurl, deeplink_url = deeplink_url, itemName = "点击打开抖音APP", create_time = DateTime.Now, end_point = _end_point }; } public static bool IsAffToken(string content) { if (string.IsNullOrEmpty(content)) return false; string pattern = "[ďȌƯƔɪƝɖƟɏƖԂȎȗϓɫɧơȲǏđǫƲƳɨǹƊȮǚƴɬɲƿȖȳɳɗʮϔӢǙɦɒɎƥʘưΊƞǪȈʠΌǓϒίȠƠƱƗǸ]{6}(.*?)([◤|◥|☆|商|品|详|情]+)[ˇ|ǚ|➝|Š|※|\\#|^|︽]{2}([A-Za-z0-9]+)[ǚ|ˇ|Ƞ|⇜|ǚ|︽|ˇ|\\#|^|Š|ǚ|^|➝|※]{2}"; Match match = Regex.Match(content, pattern); return match.Success; } public static bool IsDyToken(string content) { if (string.IsNullOrEmpty(content)) return false; string pattern = "([ďȌƯƔɪƝɖƟɏƖԂȎȗϓɫɧơȲǏđǫƲƳɨǹƊȮǚƴɬɲƿȖȳɳɗʮϔӢǙɦɒɎƥʘưΊƞǪȈʠΌǓϒίȠƠƱƗǸĎÕŮÝÌŇ]{6}(?:极速版)?(?:口令|搜索))|##[a-zA-Z0-9]+##\\[抖音(?:极速版)?口令\\]"; Regex regex = new(pattern); Match match = Regex.Match(content, pattern); return match.Success; } public static string? GetDesiredUrl(string url) { try { WebClientUtility client = new() { AllowAutoRedirect = false }; var response = client.Request(url); if (!response.Successed) return null; var target_url = response.ResponseMessage?.Headers?.Location?.ToString(); return target_url; } catch (Exception ex) { } return null; } public static string GetLink(string content) { if (string.IsNullOrEmpty(content)) return content; string result = content; //string pattern = @"https?:\/\/?([\da-z\.-]+)\.([a-z]{2,6})(:\d{1,5})?([\/\w\.-]*)*\/?(#[\S]+)?(\?[\S]+)?"; Regex regex = new(AlimamaPlus._url_pattern); MatchCollection matches = regex.Matches(content); foreach (Match m in matches.Cast()) { string url = m.Value; return url; } return string.Empty; } public static LinkTypeEnum GetLinkType(string content, string? url) { if (!string.IsNullOrEmpty(content)) { if (IsAffToken(content)) return LinkTypeEnum.other_aff; if (IsDyToken(content)) return LinkTypeEnum.goods; } if (string.IsNullOrEmpty(url)) return LinkTypeEnum.unknown; if (url.Contains("v.buydouke.com")) { //推广域名 return LinkTypeEnum.other_aff; } if (url.StartsWith("https://www.iesdouyin.com/share/video")) { return LinkTypeEnum.video; } if (url.StartsWith("https://www.iesdouyin.com/share/user")) { return LinkTypeEnum.profile; } if (url.StartsWith("https://www.iesdouyin.com/share/note")) { return LinkTypeEnum.note; } if (url.StartsWith("https://webcast.amemv.com")) { return LinkTypeEnum.live; } if (url.StartsWith("https://haohuo.jinritemai.com/ecommerce/trade/detail")) { return LinkTypeEnum.goods; } if (url.Contains("iesdouyin.com") || url.Contains("jinritemai.com") || url.Contains("amemv.com") || url.Contains("douyin.com")) { return LinkTypeEnum.baseDomain; } return LinkTypeEnum.unknown; } static bool ContainsSpecialFormat(string content) { // 使用正则表达式匹配内容中是否含有特定格式的字符串 string pattern = @"[!$¥%]+[a-zA-Z0-9]+[!$¥%]]*"; return Regex.IsMatch(content, pattern); } public static string GetDeeplink(string url, string shortLinkurl, LinkTypeEnum link_type) { string baseDeeplink = "snssdk1128://"; if (string.IsNullOrEmpty(url)) return $"{baseDeeplink}feed?refer=web"; try { switch (link_type) { case LinkTypeEnum.live: { var room_id = url.GetContentPart("webcast/reflow/", "?"); return $"{baseDeeplink}live?room_id={room_id}"; } case LinkTypeEnum.video: { var video_id = url.GetContentPart("/share/video/", "/"); return $"{baseDeeplink}aweme/detail/{video_id}"; } case LinkTypeEnum.note: { var video_id = url.GetContentPart("/share/note/", "/"); return $"{baseDeeplink}aweme/detail/{video_id}"; } case LinkTypeEnum.goods: { return $"{baseDeeplink}webview?url={shortLinkurl.UrlEncode()}"; } case LinkTypeEnum.profile: { var sec_uid = url.GetContentPart("/share/user/", "?"); return $"{baseDeeplink}user/profile?sec_uid={sec_uid}"; } case LinkTypeEnum.unknown: case LinkTypeEnum.baseDomain: return $"{baseDeeplink}webview?url={url.UrlEncode()}&from=webview&hide_nav_bar=1&refer=web"; case LinkTypeEnum.other_aff: return $"{baseDeeplink}feed?refer=web"; } //string virtual_params = $"{{\"category\":\"jump\",\"des\":\"m\",\"sourceValue\":\"babel-act\",\"sourceType\":\"babel\",\"url\":\"{url}\",\"M_sourceFrom\":\"h5auto\",\"msf_type\":\"auto\"}}"; //string result = $"openapp.jdmobile://virtual?params={virtual_params.UrlEncode()}"; //return result; /* * 短视频跟直播间的 根据url的curl直接取id拼接dp * 商品分两种 可转链不可转 走穿山甲api去转,能转的直接用api的dp,不能转的就直接webview拼接原地址做dp 商品,短视频,直播间,个人主页 */ } catch { } return baseDeeplink; } public static async Task DyParseAsync(PangolinDTO account, string content, DyDataDTO result, CancellationToken cancellationToken = default) { var plus = new DyUnionPlus(account.app_key, account.app_secret); #if DEBUG string test = await plus.AggregateH5Async("7369141045465973001", cancellationToken); #endif string message = "OK"; string url = GetLink(content); string? desired_url = url; if (url.StartsWith("https://v.douyin.com")) desired_url = GetDesiredUrl(url); result.link_type = GetLinkType(content, desired_url); result.deeplink_url = GetDeeplink(desired_url, url, result.link_type); if (result.link_type == LinkTypeEnum.other_aff) { result.success = false; result.link_type = LinkTypeEnum.unknown; result.channel_type = ChannelTypeEnum.dy; result.message = "其他推广链接"; result.accountName = string.Empty; result.content = content; result.shortLinkurl = url; } switch (result.link_type) { case LinkTypeEnum.other_aff: { result.success = false; result.channel_type = ChannelTypeEnum.dy; result.message = "其他推广链接"; result.accountName = string.Empty; result.content = content; result.shortLinkurl = url; return result; } case LinkTypeEnum.goods: case LinkTypeEnum.live: { result = await plus.ParseAsync(url, result, cancellationToken); return result; } //case LinkTypeEnum.live: // { // string room_id = result.deeplink_url.GetContentPart("room_id=", ""); // result = await plus.LiveParse(room_id, result); // return result; // } default: //跳转到抖音 result.shortLinkurl = url; result.success = false; result.message = "转链失败"; return result; } } public static async Task DyParseAsync(ReduPoolDTO account, string content, DyDataDTO result, CancellationToken cancellationToken = default) { try { var plus = new ReduPlus(account.base_url, account.app_key, account.app_secret); if (decimal.TryParse(content, out _)) { var root = await plus.DouyinParse(content, cancellationToken); var data = root.ElementRead("data"); //deeplink_url = deeplink_url.Replace("snssdk1128://", "snssdk561124://"); result.taoToken = data.Read("dy_password", string.Empty); result.deeplink_url = data.Read("dy_deeplink", string.Empty); result.shortLinkurl = data.Read("dy_zlink", string.Empty); } else { result.success = false; result.message = "转链失败"; result.reason = "不是商品ID"; } return result; } catch (Exception ex) { result.success = false; result.message = "转链失败"; return result; } } } }