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 System.Threading.Channels; using YunhuiKit; namespace molilian.core { public partial class RiskControlCore { private static Dictionary _calls = new(); private static Dictionary _incomeAmt = new(); public static void Refresh() { _incomeAmt = []; } public static void ResetCalls() { _calls = []; } internal static async Task CallsIncrByAsync(TkChannelEnum channel, int accountId) { await CallsIncrByAsync(channel, accountId, DateTime.Now.ToString("yyyyMMddHHmm"), 300); await CallsIncrByAsync(channel, accountId, DateTime.Now.ToString("yyyyMMddHH"), 14400); await CallsIncrByAsync(channel, accountId, DateTime.Now.ToString("yyyyMMdd")); } internal static async Task CallsIncrByAsync(TkChannelEnum channel, int accountId, string flag, int expire = 259200) { string key = $"{channel}:{accountId}:{flag}"; if (_calls.TryGetValue(key, out int value)) { _calls[key] = ++value; } else { _calls[key] = 1; } string cache_key = $":RiskControl:calls:{key}"; await RedisKit.IncrByAsync(cache_key); await RedisKit.ExpireAsync(cache_key, expire); } internal static async Task SetCallsAsync(TkChannelEnum channel, int accountId, string flag, int val) { string key = $"{channel}:{accountId}:{flag}"; _calls.TryAdd(key, val); string cache_key = $":RiskControl:calls:{key}"; await RedisHelper.SetAsync(cache_key, val); await RedisHelper.ExpireAsync(cache_key, 3 * 86400); } public static async Task GetAllNodesCallsAsync(TkChannelEnum channel, int accountId, string flag) { var key = $"{channel}:{accountId}:{flag}"; 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 0; var cacheKey = $":RiskControl:calls:{key}"; using var scope = await RedisClientFactory.CreateScopeAsync(redisServer); int count = await scope.Client.GetAsync(cacheKey); return count; } catch (Exception ex) { } return 0; }); var results = await Task.WhenAll(tasks); var totalCalls = results.Sum(); _calls.TryAdd(key, totalCalls); return totalCalls; } catch (Exception) { // TODO: 添加日志 return 0; } } internal static async Task SetTkEndpointCallsAsync(int accountId, int ep_id, string flag, int val) { string key = $"tk_endpoint:{accountId}:{ep_id}:{flag}"; if (_calls.ContainsKey(key)) { _calls[key] = val; } else { _calls[key] = val; } string cache_key = $":RiskControl:calls:{key}"; await RedisHelper.IncrByAsync(cache_key); await RedisHelper.ExpireAsync(cache_key, 3 * 86400); } public static async Task GetAllNodesTkEndpointCallsAsync(int accountId, int ep_id, string flag) { string key = $"tk_endpoint:{accountId}:{ep_id}:{flag}"; 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 0; string cacheKey = $":RiskControl:calls:{key}"; using var scope = await RedisClientFactory.CreateScopeAsync(redisServer); return await scope.Client.GetAsync(cacheKey); } catch (Exception ex) { } return 0; }); var results = await Task.WhenAll(tasks); var totalCalls = results.Sum(); _calls.TryAdd(key, totalCalls); return totalCalls; } catch (Exception) { // TODO: 添加日志 return 0; } } public static int GetCalls(TkChannelEnum channel, int accountId, string flag) { try { string key = $"{channel}:{accountId}:{flag}"; if (_calls.ContainsKey(key)) return _calls[key]; string cache_key = $"RiskControl:calls:{key}"; int num = RedisHelper.Get(cache_key); _calls.TryAdd(key, num); return num; } catch (Exception ex) { return 0; } } internal static async Task SaveIncomeAmtAsync(TkChannelEnum channel, string accountName, decimal income_amt) { string key = $"{channel}:{accountName}:{DateTime.Now:yyyyMMdd}"; lock (_incomeAmt) { if (!_incomeAmt.TryAdd(key, income_amt)) _incomeAmt[key] = income_amt; } string cache_key = $"RiskControl:{key}:income_amt"; 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 false; using var scope = await RedisClientFactory.CreateScopeAsync(redisServer); return await scope.Client.SetAsync(cache_key, income_amt, 3 * 86400); } catch (Exception ex) { return false; } }); await Task.WhenAll(tasks); } catch (Exception) { } } public static decimal GetIncomeAmt(TkChannelEnum channel, string accountName) { try { string key = $"{channel}:{accountName}:{DateTime.Now:yyyyMMdd}"; if (_incomeAmt.ContainsKey(key)) return _incomeAmt[key]; string cache_key = $":RiskControl:{key}:income_amt"; return RedisHelper.Get(cache_key); } catch (Exception ex) { return 0; } } } }