using molilian.core; using dodohold.core; using Dapper; using Microsoft.AspNetCore.Mvc; using Org.BouncyCastle.Ocsp; using System.Text.Json; using System.Runtime.InteropServices; using System.Net; using System.Threading; using System.Data; using Microsoft.AspNetCore.Mvc.RazorPages; using TencentCloud.Soe.V20180724.Models; using static dodohold.core.ZTOExpress.CreateOrderArgs; using static Spire.Xls.Core.Spreadsheet.HTMLOptions; using System.Net.Http.Json; using System.Text.RegularExpressions; using System.Text; using TencentCloud.Oceanus.V20190422.Models; using YunhuiKit; using TencentCloud.Cdn.V20180606.Models; namespace molilian.api.Controllers { [ApiController] [Route("[controller]/[action]")] public class TestController : ControllerBase { protected IHttpContextAccessor _accessor; public TestController(IHttpContextAccessor accessor) { _accessor = accessor; } [HttpGet] public async Task ecs_list_test() { var list = AliyunPoolCore.EcsList(); return new APIResult(new { success = true, msg = "ok", list }); } [HttpGet] public async Task testReconnectionRedis() { string cacheKey = "test"; RedisKit.SetAsync(cacheKey, 1, 3600); string val = await RedisKit.GetAsync(cacheKey); return new APIResult(new { success = "ok", val }); } [HttpGet] public async Task ChangePublicIpByName(string nodeName) { var proxy_node = new DBContext.Table("proxy_nodes").Get("nodeName=@nodeName", new { nodeName }); if (proxy_node == null) return new APIResult(new { success = false, msg = "没有匹配的 proxy_nodes 记录" }); int aliyun_id = proxy_node.aliyun_id; string proxy_server = proxy_node.server; var account = new DBContext.Table("aliyun_pool").Get(aliyun_id); if (account == null) return new APIResult(new { success = false, msg = "没有匹配的 aliyun_pool 记录" }); var uri = new Uri(proxy_server); string privateIp = uri.Host; AliyunCore core = new AliyunCore(account); var success = await core.ChangePublicIpAsync(privateIp); return new APIResult(new { success = "ok" }); } [HttpGet] public async Task ChangePublicIp(int id) { id = id >= 20000 ? id - 20000 : id; var proxy_node = new DBContext.Table("proxy_nodes").Get(id); if (proxy_node == null) return new APIResult(new { success = false, msg = "没有匹配的 proxy_nodes 记录" }); int aliyun_id = proxy_node.aliyun_id; string proxy_server = proxy_node.server; var account = new DBContext.Table("aliyun_pool").Get(aliyun_id); if (account == null) return new APIResult(new { success = false, msg = "没有匹配的 aliyun_pool 记录" }); var uri = new Uri(proxy_server); string privateIp = uri.Host; AliyunCore core = new AliyunCore(account); var success = await core.ChangePublicIpAsync(privateIp); return new APIResult(new { success = "ok" }); } [HttpGet] //第一部 先加一个网卡, public async Task CreateNetworkInterface(int id, string ecsid) { AliyunCore core = new AliyunCore(id); //创建弹性网卡并绑定公网IP var success = core.EcsCreateNetworkInterface("cn-beijing", ecsid); return new APIResult(new { success }); } [HttpGet] //第二部 给网卡绑定很多个辅助ip public async Task EcsAssignPrivateIpAddresses(int id, string ecsid, int count, bool isSecondary = true) { AliyunCore core = new AliyunCore(id); //创建弹性网卡并绑定公网IP var success = core.EcsAssignPrivateIpAddresses("cn-beijing", ecsid, count, !isSecondary); return new APIResult(new { success }); } [HttpGet] public async Task QueryAccountBalance() { AliyunPlus plus = new AliyunPlus("LTAI5tQbkTjtULQcrWGaw2VJ", "UIkkolVVEddooOKOIUByCqymZkK6ZA"); var response = plus.QueryAccountBalance(); var balance = response.Body.Data.AvailableAmount; return new APIResult(new { response }); } //[HttpGet] //public async Task test(string table = "tk_parse_logs_shop", int count = 100) //{ // //table = "tk_parse_logs_shop"; // //table = "tk_parse_logs_live"; // //table = "tk_parse_logs_video"; // string filter = "success=0 AND message='放弃转链' AND reason='非标准链接'"; // for (int i = 0; i < 100; i++) // { // try // { // var list = new DBContext.Table(table) // .Where(filter, new { }) // .Limit(count).Select(); // if (!list.Any()) // { // return new APIResult(new // { // success = false, // message = "所有任务完成" // }); // } // foreach (var item in list) // { // TkPoolDTO? account = TkPoolCore.GetOne(TkPoolCore.TkAction.parse); // if (account == null) // { // return new APIResult(new // { // success = false, // message = "没有工作账号" // }); // } // var result = item.Convert2Json().Convert2Object(); // result.accountId = account.id; // result.accountName = account.company; // var alimama = new AlimamaPlus(account); // int timeout = alimama._config.rt_max; // using var cts = new CancellationTokenSource(); // cts.CancelAfter(timeout); // result = await alimama.UnionParseAsync(item.content, result); // string reason = "非标准链接".Equals(result.reason) ? "非标准链接ok" : result.reason; // new DBContext.Table(table) // .Add("linkType", (int)result.link_type) // .Add("rawContent", result.rawContent) // .Add("success", result.success) // .Add("message", result.message) // .Add("reason", reason) // .Add("content", result.content) // .Add("itemId", result.itemId) // .Add("itemName", result.itemName) // .Add("pic", result.pic) // .Add("couponAmount", result.couponAmount) // .Add("promotionPrice", result.promotionPrice) // .Add("taoToken", result.taoToken) // .Add("shortLinkurl", result.shortLinkurl) // .Add("deeplink_url", result.deeplink_url) // .Add("num_iid", result.num_iid) // .Add("elapsedTime", result.elapsedTime) // .Add("elapsedTime2", result.elapsedTime2) // .Add("elapsedTime3", result.elapsedTime3) // .Add("subCode", result.subCode) // .Where("id=@id", new { item.id }) // .Update(); // } // } // catch // { // } // } // return new APIResult(new // { // success = true, // message = "ok" // }); //} [HttpGet] public async Task redu_douyin(string command) { ReduPlus plus = new ReduPlus("", "", ""); var result = await plus.DouyinParse(command); return Content(result.Convert2Json()); } [HttpGet] public async Task redu_kuaishou(string command) { ReduPlus plus = new ReduPlus("", "", ""); var result = await plus.KuaishouParse(command); return Content(result.Convert2Json()); } [HttpPost] public async Task test2([FromForm] string jsonContent, [FromForm] string testText) { // 用于存储输出结果的StringBuilder StringBuilder outputBuilder = new StringBuilder(); // 解析JSON数据 JsonDocument jsonDoc = JsonDocument.Parse(jsonContent); // 获取根元素 JsonElement root = jsonDoc.RootElement; // 遍历规则 foreach (JsonElement ruleSet in root.EnumerateArray()) { string platformType = ruleSet.Read("platformType", string.Empty); string supplier = ruleSet.Read("supplier", string.Empty); outputBuilder.AppendLine($"平台类型: {platformType}, 供应商: {supplier}"); JsonElement pwdRules = ruleSet.GetProperty("pwdRules"); int idx = 0; foreach (JsonElement patternElement in pwdRules.EnumerateArray()) { string pattern = patternElement.GetString(); try { // 使用Regex类来编译正则表达式 Regex compiledPattern = new Regex(pattern); if (compiledPattern.IsMatch(testText)) { outputBuilder.AppendLine($"规则 {idx + 1}: 匹配\t{pattern}"); } else { outputBuilder.AppendLine($"规则 {idx + 1}: 不匹配"); } } catch (Exception e) { outputBuilder.AppendLine($"规则 {idx + 1}: 正则表达式错误 - {e.Message}\t{pattern}"); } idx++; } } outputBuilder.AppendLine("测试完成"); return Content(outputBuilder.ToString()); } [HttpGet] public async Task ip(string ip) { string result = IP2RegionPlus.Search(ip); return new APIResult(new { success = true, message = result }); } [HttpPost] public async Task testreg([FromBody] JsonElement form) { var content = form.Read("s", string.Empty); string shortLinkurl = AlimamaPlus.GetTaobaoLink(content); bool is_tao_token = AlimamaPlus.MatchRegexes(content, []); bool is_other = AlimamaPlus.MatchOtherInfo(content, []); return new APIResult(new { shortLinkurl, is_tao_token, is_other }); } //[HttpGet] //public async Task comparison_tk([FromQuery] int count = 100) //{ // string cacheKey = ":lock_key:comparison_tk_logs"; // int last_id = RedisHelper.Get(cacheKey); // string filter = "id>@last_id"; // var result = new DBContext.Table("comparison_tk_logs") // .Where(filter, new { last_id }) // .Page(count, 1) // .Order("ID") // .PageList(false); // var ip = "127.0.0.1"; // var oaid = "test-comparison_tk_logs"; // foreach (var item in result.List) // { // await UnionParseCore.TaobaoParseAsync(item.rawContent, ip, oaid); // RedisHelper.Set(cacheKey, item.id, 10 * 86400); // } // if (result.Count < count) // { // cacheKey = ":lock_key:start_comparison_tk"; // RedisHelper.Set(cacheKey, 1, 600); // } // return new APIResult(new // { // success = true, // message = "ok" // }); //} //[HttpGet] //public async Task comparison_tk_raw([FromQuery] int count = 100) //{ // string cacheKey = ":lock_key:comparison_tk_logs_raw"; // int last_id = RedisHelper.Get(cacheKey); // string filter = "id>@last_id"; // var result = new DBContext.Table("comparison_tk_logs") // .Where(filter, new { last_id }) // .Page(count, 1) // .Order("ID") // .PageList(false); // var ip = "127.0.0.1"; // var oaid = "test-comparison_tk_logs_raw"; // foreach (var item in result.List) // { // await UnionParseCore.TaobaoParseAsync(item.rawContent, ip, oaid); // RedisHelper.Set(cacheKey, item.id, 10 * 86400); // } // if (result.Count < count) // { // cacheKey = ":lock_key:start_comparison_tk"; // RedisHelper.Set(cacheKey, 1, 600); // } // return new APIResult(new // { // success = true, // message = "ok" // }); //} [HttpGet] public async Task testTask() { string url = "https://www.taobao.com"; TkDataDTO result = new TkDataDTO(); result.message = "init"; result.success = true; int timeout = 1000; using var cts = new CancellationTokenSource(); cts.CancelAfter(timeout); var requestTask = Task.Run(() => AlimamaPlus.testTaskAsync(result, cts.Token), cts.Token); var delayTask = Task.Delay(timeout, cts.Token); var completedTask = await Task.WhenAny(requestTask, delayTask); if (completedTask == requestTask) { result = await requestTask; } else { cts.Cancel(); result.success = false; result.message = "放弃转链"; result.reason = "请求超时"; result.itemName = "点击打开淘宝APP"; } return new APIResult(new { success = true, message = "ok", result, }); } [HttpGet] public async Task testThread() { // 查看默认的最小和最大线程数 ThreadPool.GetMinThreads(out int defaultMinWorker, out int defaultMinIOC); ThreadPool.GetMaxThreads(out int defaultMaxWorker, out int defaultMaxIOC); string tmp = $"Default Min worker threads: {defaultMinWorker}, Min I/O completion threads: {defaultMinIOC}"; string tmp2 = $"Default Max worker threads: {defaultMaxWorker}, Max I/O completion threads: {defaultMaxIOC}"; // 获取当前线程池中可用的工作线程数和 I/O 完成端口线程数 ThreadPool.GetAvailableThreads(out int availableWorkerThreads, out int availableIOCompletionThreads); string tmp3 = $"Current available worker threads: {availableWorkerThreads}, available I/O completion threads: {availableIOCompletionThreads}"; return new APIResult(new { tmp, tmp2, tmp3, }); } [HttpPost] public async Task test1([FromBody] JsonElement form) { NotifyCore.Notify(new NifyMessage { message = $"【淘宝联盟:test】cookie 掉线", priority = NifyMessagePriority.high, tags = ["red_circle"] }); return new APIResult(new { success = true, message = "ok" }); } [HttpGet] public async Task RepairTkDailyAccountStats( DateTime startDate = default, DateTime endDate = default, string accountIds = "129,140", string extraNames = "搜同款_楚颜_128众杰科技,搜同款_广哲2", bool dryRun = false, bool repairDailyLogs = true, bool repairRedis = true, bool repairRedisNameKeys = true, int commandTimeoutSeconds = 600) { if (startDate == default) startDate = new DateTime(2026, 6, 16); if (endDate == default) endDate = DateTime.Now.Date; commandTimeoutSeconds = Math.Clamp(commandTimeoutSeconds, 30, 3600); startDate = startDate.Date; endDate = endDate.Date; if (endDate < startDate) { return new APIResult(new { success = false, message = "endDate 不能早于 startDate" }); } var ids = (accountIds ?? string.Empty) .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Select(item => int.TryParse(item, out int id) ? id : 0) .Where(id => id > 0) .Distinct() .ToArray(); if (ids.Length == 0) { return new APIResult(new { success = false, message = "accountIds 不能为空" }); } using var conn = CenterHub.GetOpenConnection(); if (conn.State != ConnectionState.Open) conn.Open(); var errors = new List(); var affectedNames = new HashSet(StringComparer.Ordinal); var accounts = SqlMapper.Query( conn, "SELECT id accountId, company accountName FROM tk_pool WHERE id IN @ids", new { ids }, commandTimeout: commandTimeoutSeconds).ToList(); foreach (string name in accounts.Select(item => item.accountName).Where(item => !string.IsNullOrWhiteSpace(item))) { affectedNames.Add(name); } extraNames ??= string.Empty; foreach (string name in extraNames .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Where(item => !string.IsNullOrWhiteSpace(item))) { affectedNames.Add(name); } foreach (string name in SqlMapper.Query( conn, @" SELECT DISTINCT accountName FROM center_daily_logs WHERE channel = 0 AND accountId IN @ids AND log_date BETWEEN @startDate AND @endDate AND COALESCE(accountName,'')<>''", new { ids, startDate, endDate }, commandTimeout: commandTimeoutSeconds)) { affectedNames.Add(name); } var days = EachDay(startDate, endDate).ToList(); var dailyReports = new List(); var endpointCountsByDate = new Dictionary>(); foreach (var date in days) { try { string tableName = $"tk_parse_logs_{date:yyyyMMdd}"; if (!TableExists(conn, tableName, commandTimeoutSeconds)) { dailyReports.Add(new { date = date.ToString("yyyy-MM-dd"), tableName, skipped = true, reason = "table not exists" }); continue; } var endpointCounts = SqlMapper.Query( conn, $@" SELECT l.accountId, COALESCE(p.company, MAX(l.accountName), '') accountName, COALESCE(l.end_point, '') end_point, COUNT(*) total_count, CAST(COALESCE(SUM(l.success = 1), 0) AS SIGNED) success_count, CAST(COALESCE(SUM(l.success = 0), 0) AS SIGNED) fail_count, CAST(COALESCE(SUM(l.message = '放弃转链' OR l.reason = '放弃转链'), 0) AS SIGNED) abandon_count FROM {tableName} l LEFT JOIN tk_pool p ON p.id = l.accountId WHERE l.accountId IN @ids GROUP BY l.accountId, p.company, l.end_point ORDER BY l.accountId, l.end_point", new { ids }, commandTimeout: commandTimeoutSeconds).ToList(); endpointCountsByDate[date.ToString("yyyyMMdd")] = endpointCounts; var accountCounts = endpointCounts .GroupBy(item => item.accountId) .Select(group => new TkDailyRepairCountRow { accountId = group.Key, accountName = accounts.FirstOrDefault(item => item.accountId == group.Key)?.accountName ?? group.FirstOrDefault()?.accountName ?? string.Empty, total_count = group.Sum(item => item.total_count), success_count = group.Sum(item => item.success_count), fail_count = group.Sum(item => item.fail_count), abandon_count = group.Sum(item => item.abandon_count) }) .ToList(); int dailyLogRows = 0; var allAccountCounts = ids .Select(accountId => accountCounts.FirstOrDefault(item => item.accountId == accountId) ?? new TkDailyRepairCountRow { accountId = accountId, accountName = accounts.FirstOrDefault(item => item.accountId == accountId)?.accountName ?? string.Empty }) .ToList(); foreach (var counts in allAccountCounts) { if (!dryRun && repairDailyLogs) { dailyLogRows += UpsertCenterDailyLog(conn, date, counts, commandTimeoutSeconds); } } dailyReports.Add(new { date = date.ToString("yyyy-MM-dd"), tableName, skipped = false, dailyLogRows, source = "mysql:tk_parse_logs_yyyyMMdd", counts = allAccountCounts, endpointCounts }); } catch (Exception ex) { var error = new { scope = "daily_log", date = date.ToString("yyyy-MM-dd"), error = FormatRepairError(ex) }; errors.Add(error); dailyReports.Add(new { date = date.ToString("yyyy-MM-dd"), skipped = true, reason = "error", error }); } } var endpointReports = new List(); if (repairRedis || repairRedisNameKeys) { var endpoints = EndPointCore.List(true) .Where(node => node.status && node.is_public_api && !string.IsNullOrEmpty(EndPointCore.GetRedisServer(node))) .ToList(); foreach (var endpoint in endpoints) { var redisServer = EndPointCore.GetRedisServer(endpoint); var endpointReport = new List(); try { await using var scope = await RedisClientFactory.CreateScopeAsync(redisServer); var redis = scope.Client; foreach (var date in days) { string dateKey = date.ToString("yyyyMMdd"); if (!endpointCountsByDate.TryGetValue(dateKey, out var endpointCounts)) { continue; } foreach (int accountId in ids) { var counts = endpointCounts.FirstOrDefault(item => item.accountId == accountId && string.Equals(item.end_point, endpoint.name, StringComparison.Ordinal)) ?? new TkDailyRepairEndpointCountRow { accountId = accountId, accountName = accounts.FirstOrDefault(item => item.accountId == accountId)?.accountName ?? string.Empty, end_point = endpoint.name }; if (!dryRun && repairRedis) { await WriteParseCountKeysAsync(redis, $"tb_{accountId}", dateKey, counts); } endpointReport.Add(new { date = date.ToString("yyyy-MM-dd"), bucket = $"tb_{accountId}", counts }); } if (repairRedisNameKeys) { foreach (string name in affectedNames) { var before = await ReadParseCountKeysAsync(redis, name, dateKey); if (!dryRun) { await DeleteParseBucketKeysAsync(redis, name, dateKey); } endpointReport.Add(new { date = date.ToString("yyyy-MM-dd"), deletedBucket = name, before }); } } } } catch (Exception ex) { errors.Add(new { scope = "redis_endpoint", endpoint = endpoint.name, error = FormatRepairError(ex) }); } endpointReports.Add(new { endpoint = endpoint.name, endpoint.description, dryRun, deletedBuckets = endpointReport }); } } return new APIResult(new { success = errors.Count == 0, dryRun, accountIds = ids, extraNames, repairDailyLogs, repairRedis, repairRedisNameKeys, commandTimeoutSeconds, startDate = startDate.ToString("yyyy-MM-dd"), endDate = endDate.ToString("yyyy-MM-dd"), affectedNames = affectedNames.OrderBy(item => item).ToList(), mysql = dailyReports, redis = endpointReports, errors }); } private static IEnumerable EachDay(DateTime startDate, DateTime endDate) { for (var date = startDate.Date; date <= endDate.Date; date = date.AddDays(1)) { yield return date; } } private static bool TableExists(IDbConnection conn, string tableName, int commandTimeoutSeconds) { const string sql = @" SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = @tableName"; return SqlMapper.ExecuteScalar( conn, sql, new { tableName }, commandTimeout: commandTimeoutSeconds) > 0; } private static int UpsertCenterDailyLog(IDbConnection conn, DateTime date, TkDailyRepairCountRow counts, int commandTimeoutSeconds) { if (string.IsNullOrWhiteSpace(counts.accountName)) return 0; string successPercentage = counts.total_count > 0 ? $"{counts.success_count / (double)counts.total_count * 100:f2}%" : string.Empty; string abandonPercentage = counts.total_count > 0 ? $"{counts.abandon_count / (double)counts.total_count * 100:f2}%" : string.Empty; var existingIds = SqlMapper.Query( conn, @" SELECT id FROM center_daily_logs WHERE channel = 0 AND log_date = @date AND accountId = @accountId ORDER BY id", new { date, counts.accountId }, commandTimeout: commandTimeoutSeconds).ToList(); if (existingIds.Count > 0) { int affectedRows = SqlMapper.Execute( conn, @" UPDATE center_daily_logs SET accountName = @accountName, parse_total_count = @totalCount, parse_success_count = @successCount, parse_abandon_count = @abandonCount, parse_success_percentage = @successPercentage, parse_abandon_percentage = @abandonPercentage, last_time = NOW() WHERE id = @id", new { id = existingIds[0], counts.accountName, totalCount = counts.total_count, successCount = counts.success_count, abandonCount = counts.abandon_count, successPercentage, abandonPercentage }, commandTimeout: commandTimeoutSeconds); if (existingIds.Count > 1) { affectedRows += SqlMapper.Execute( conn, "DELETE FROM center_daily_logs WHERE id IN @ids", new { ids = existingIds.Skip(1).ToArray() }, commandTimeout: commandTimeoutSeconds); } return affectedRows; } if (counts.total_count <= 0) return 0; return SqlMapper.Execute( conn, @" INSERT INTO center_daily_logs (channel, accountId, accountName, log_date, create_time, last_time, parse_total_count, parse_success_count, parse_abandon_count, parse_success_percentage, parse_abandon_percentage) VALUES (0, @accountId, @accountName, @date, NOW(), NOW(), @totalCount, @successCount, @abandonCount, @successPercentage, @abandonPercentage)", new { date, counts.accountId, counts.accountName, totalCount = counts.total_count, successCount = counts.success_count, abandonCount = counts.abandon_count, successPercentage, abandonPercentage }, commandTimeout: commandTimeoutSeconds); } private static async Task ReadParseCountKeysAsync(YunhuiKit.RedisClient redis, string bucket, string dateKey) { return new TkDailyRepairCountRow { accountName = bucket, total_count = await redis.GetAsync($":parse_total:{bucket}:{dateKey}"), success_count = await redis.GetAsync($":parse_total:{bucket}:success:{dateKey}"), fail_count = await redis.GetAsync($":parse_total:{bucket}:fail:{dateKey}"), abandon_count = await redis.GetAsync($":parse_total:{bucket}:放弃转链:{dateKey}") }; } private static async Task DeleteParseBucketKeysAsync(YunhuiKit.RedisClient redis, string bucket, string dateKey) { var keys = new List { $":parse_total:{bucket}:{dateKey}", $":parse_total:{bucket}:success:{dateKey}", $":parse_total:{bucket}:fail:{dateKey}", $":parse_total:{bucket}:放弃转链:{dateKey}", $":parse_total:{bucket}:message:{dateKey}", $":parse_total:{bucket}:reason:{dateKey}" }; foreach (string dpBucket in new[] { "dp_none", "dp_home", "dp_success", "dp_fail" }) { keys.Add($":parse_total:{dpBucket}:{bucket}:{dateKey}"); keys.Add($":parse_total:{dpBucket}:{bucket}:success:{dateKey}"); keys.Add($":parse_total:{dpBucket}:{bucket}:fail:{dateKey}"); keys.Add($":parse_total:{dpBucket}:{bucket}:放弃转链:{dateKey}"); keys.Add($":parse_total:{dpBucket}:{bucket}:message:{dateKey}"); keys.Add($":parse_total:{dpBucket}:{bucket}:reason:{dateKey}"); } await redis.DelAsync(keys.ToArray()); } private static string FormatRepairError(Exception ex) { return ex.InnerException == null ? ex.Message : $"{ex.Message} | {ex.InnerException.Message}"; } private static async Task WriteParseCountKeysAsync(YunhuiKit.RedisClient redis, string bucket, string dateKey, TkDailyRepairCountRow counts) { var keys = new[] { $":parse_total:{bucket}:{dateKey}", $":parse_total:{bucket}:success:{dateKey}", $":parse_total:{bucket}:fail:{dateKey}", $":parse_total:{bucket}:放弃转链:{dateKey}" }; if (counts.total_count <= 0) { await redis.DelAsync(keys); return; } await redis.SetAsync(keys[0], counts.total_count, 90 * 86400); await redis.SetAsync(keys[1], counts.success_count, 90 * 86400); await redis.SetAsync(keys[2], counts.fail_count, 90 * 86400); await redis.SetAsync(keys[3], counts.abandon_count, 90 * 86400); } private class TkDailyRepairCountRow { public int accountId { get; set; } public string accountName { get; set; } = string.Empty; public long total_count { get; set; } public long success_count { get; set; } public long fail_count { get; set; } public long abandon_count { get; set; } } private sealed class TkDailyRepairEndpointCountRow : TkDailyRepairCountRow { public string end_point { get; set; } = string.Empty; } [HttpGet] public async Task xxx() { var list = await TkPoolCore.ListAsync(); if (list == null) return new APIResult(new { success = false, message = "没有有效账号", }); string message = string.Empty; foreach (var account in list) { try { var alimama = new AlimamaPlus(account); alimama.RenewCookie(); } catch (Exception ex) { message = $"【cookie续期】xxxx\n{ex.Message}\n{ex.StackTrace}"; NotifyCore.Notify(new NifyMessage { message = message, priority = NifyMessagePriority.high, tags = ["red_circle"] }); continue; } } return new APIResult(new { success = true, message = "ok" }); } } }