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 Google.Protobuf.WellKnownTypes; using System.Diagnostics; using System.Text.Json; using TencentCloud.Tcm.V20210413.Models; using System.Security.Cryptography; using System.Data; using System.Threading.Channels; using YunhuiKit; using System.IO; namespace molilian.core { public partial class TkOrderTrackingCore { public static void SaveLinkSummary(TkDataDTO item) { //清洗数据 item.content = null; item.rawContent = null; item.rawContent2 = null; TkDataDTO newData = new() { channel = item.channel, ip = item.ip, oaid = item.oaid, mktId = item.mktId, itemId = item.itemId, itemName = item.itemName, taoToken = item.taoToken, shortLinkurl = item.shortLinkurl, deeplink_url = item.deeplink_url, create_time = item.create_time, }; var config = TkConfigCore.Get(); var ttl = config.fake_click_ttl * 3600; string cacheKey = $":cache:order_summary:{item.accountId}:{item.itemId}"; RedisHelper.Set(cacheKey, newData, ttl); string mktId = item.mktId; if (!string.IsNullOrEmpty(mktId) && mktId.Contains('-')) { mktId = mktId.Split('-')[^1]; cacheKey = $":cache:order_summary:{item.accountId}:mktId:{mktId}"; RedisHelper.Set(cacheKey, newData, ttl); } cacheKey = $":cache:order_summary:{item.accountId}:{item.itemName}"; RedisHelper.Set(cacheKey, newData, ttl); } public static async Task<(int, TkDataDTO)> GetLinkSummaryAsync(TkPoolDTO account, string itemId, string mktId, string itemTitle) { try { int accountId = account.id; mktId = !string.IsNullOrEmpty(mktId) && mktId.Contains('-') ? mktId.Split('-')[^1] : mktId; // 获取所有关联账户ID(包括当前账户) var relatedAccountIds = new List { accountId }; if (!string.IsNullOrEmpty(account.related_account_ids)) { relatedAccountIds.AddRange(account.related_account_ids .Split(',') .Where(id => !string.IsNullOrWhiteSpace(id)) .Select(int.Parse)); } var tasks = EndPointCore.List() .Where(node => node.is_public_api && !string.IsNullOrEmpty(node.redis_server)) .Select(async node => { try { var redisServer = EndPointCore.GetRedisServer(node); if (string.IsNullOrEmpty(redisServer)) return (0, null); using var scope = await RedisClientFactory.CreateScopeAsync(redisServer); var redis = scope.Client; // 按优先级依次查询不同的缓存key TkDataDTO result = null; // 遍历所有关联账户ID foreach (var relatedId in relatedAccountIds) { if (!string.IsNullOrEmpty(mktId)) { result = await redis.GetAsync($":cache:order_summary:{relatedId}:mktId:{mktId}"); if (result != null) return (1, result); } if (!string.IsNullOrEmpty(itemId)) { result = await redis.GetAsync($":cache:order_summary:{relatedId}:{itemId}"); if (result != null) return (2, result); if (!string.IsNullOrEmpty(itemTitle)) { result = await redis.GetAsync($":cache:order_summary:{relatedId}:{itemTitle}"); if (result != null) return (3, result); } } } } catch (Exception ex) { } return (0, null); }); var results = await Task.WhenAll(tasks); return results.FirstOrDefault(r => r != (0, null)); } catch (Exception) { // TODO: 添加日志记录 return (0, null); } } public static async Task RemoveLinkSummaryAsync(int accountId, string itemId, string mktId, string itemTitle) { try { var tasks = EndPointCore.List() .Where(node => node.is_public_api && !string.IsNullOrEmpty(node.redis_server)) .Select(async node => { try { var redisServer = EndPointCore.GetRedisServer(node); if (string.IsNullOrEmpty(redisServer)) return; using var scope = await RedisClientFactory.CreateScopeAsync(redisServer); var redis = scope.Client; var keys = new[] { $":cache:order_summary:{accountId}:{itemId}", $":cache:order_summary:{accountId}:mktId:{mktId}", $":cache:order_summary:{accountId}:{itemTitle}" }.Where(k => !string.IsNullOrEmpty(k)); // 批量删除所有相关缓存 await redis.DelAsync(keys.ToArray()); } catch (Exception ex) { } }); await Task.WhenAll(tasks); } catch (Exception) { // TODO: 添加日志记录 } } //public static async void RemoveLinkSummary(int accountId, string itemId, string mktId, string itemTitle) //{ // await EndPointCore.ProcessEndPointNodesAsync(node => // { // if (!node.is_public_api) return Task.CompletedTask; // if (string.IsNullOrEmpty(node.redis_server)) return Task.CompletedTask; // var redis = RedisClientManager.GetRedisClient(node.redis_server); // string cacheKey = $":cache:order_summary:{accountId}:{itemId}"; // redis.Del(cacheKey); // cacheKey = $":cache:order_summary:{accountId}:mktId:{mktId}"; // redis.Del(cacheKey); // cacheKey = $":cache:order_summary:{accountId}:{itemTitle}"; // redis.Del(cacheKey); // return Task.CompletedTask; // }); //} public static async Task MatchOrder(TkPoolDTO account, TkOrderDetailDTO item) { DateTime now = DateTime.Now; if (item.tbPaidTime < now.AddDays(-24)) return false; (int match_type, var summary) = await GetLinkSummaryAsync(account, item.itemId, item.mktId, item.itemTitle); if (summary == null) return false; var config = TkConfigCore.Get(); Random rand = new(); int click_num = rand.Next(config.fake_click_min, config.fake_click_max + 1); if (account.fake_click_min != 0 && account.fake_click_max != 0) click_num = rand.Next(account.fake_click_min, account.fake_click_max + 1); DateTime paidTime = item.tbPaidTime; if (paidTime < summary.create_time) return false; if (paidTime < now.AddDays(-24)) return false; int minutes = now.Minute / 10 * 10; DateTime rounded = new(now.Year, now.Month, now.Day, now.Hour, minutes, 0); string batchId = rounded.ToString("yyyyMMddHHmm"); string accountName = item.accountName; string shortLinkUrl = !string.IsNullOrEmpty(summary.item_url) ? summary.item_url : summary.shortLinkurl; string deeplinkUrl = !string.IsNullOrEmpty(summary.item_deeplink_url) ? summary.item_deeplink_url : summary.deeplink_url; switch (account.fake_click_link_type) { case FakeClickLinkType.Deeplink: shortLinkUrl = string.Empty; break; case FakeClickLinkType.H5: deeplinkUrl = string.Empty; break; } var exist = new DBContext.Table("tk_order_tracking").Fields("id").Get("tradeId=@tradeId", new { item.tradeId }); DateTime expTime = now.Hour >= 21 ? now.AddHours(3) : now.Date.AddDays(1); var data = new TkOrderTrackingDTO() { match_type = match_type, channel = summary.channel, accountId = item.accountId, accountName = accountName, batchId = batchId, ip = summary.ip, oaid = summary.oaid, mktId = summary.mktId, itemId = summary.itemId, itemName = summary.itemName, taoToken = summary.taoToken, shortLinkUrl = shortLinkUrl, deeplinkUrl = deeplinkUrl, tradeId = item.tradeId, tradeParentId = item.tradeParentId, create_time = summary.create_time, click_time = item.clickTime, paid_time = item.tbPaidTime, exp_time = expTime, click_num = click_num, }; if (exist == null) { using var conn = DBContext.GetOpenConnection(); conn.Insert(data); } //RemoveLinkSummary(item.accountId, item.itemId, item.mktId, item.itemTitle); await RemoveLinkSummaryAsync(item.accountId, item.itemId, item.mktId, item.itemTitle); return true; } } }