CpsPoolCore.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using dodohold.core;
  2. using System.Threading.Channels;
  3. namespace molilian.core
  4. {
  5. public partial class CpsPoolCore
  6. {
  7. private static string _end_point;
  8. private static Dictionary<string, decimal> _incomeAmt = new();
  9. private static Dictionary<string, int> _calls = new();
  10. static CpsPoolCore()
  11. {
  12. _end_point = Environment.GetEnvironmentVariable("EndPoint");
  13. }
  14. private static readonly object _lockObj = new();
  15. private static IEnumerable<CpsLinksDTO> _links_cached;
  16. private static IEnumerable<CpsPoolDTO> _cached;
  17. public static CpsLinksDTO? GetOne(string channel)
  18. {
  19. var list = List();
  20. if (!list.Any()) return null;
  21. var pool = list.Where(e => e.channel_code == channel && e.status).FirstOrDefault();
  22. if (pool == null) return null;
  23. var links = LinksList();
  24. if (!links.Any()) return null;
  25. return links.Where(e => IsEligible(e, channel))
  26. .OrderByDescending(e => e.priority_weight)
  27. .ThenBy(l => Guid.NewGuid())
  28. .FirstOrDefault();
  29. }
  30. private static bool IsEligible(CpsLinksDTO item, string channel)
  31. {
  32. if (item.channel_code != channel) return false;
  33. // 使用初始化参数创建工作时间表
  34. if (!new WorkSchedule(item.time_range).IsWorkHour()) return false;
  35. var now = DateTime.Now;
  36. if (item.start_time > now || now > item.end_time) return false;
  37. if (item.daily_calls_limit > 0)
  38. {
  39. int daily_num = RiskControlCore.GetCalls(TkChannelEnum.cps, item.id, DateTime.Now.ToString("yyyyMMdd"));
  40. if (daily_num >= item.daily_calls_limit) return false;
  41. }
  42. if (item.hourly_calls_limit > 0)
  43. {
  44. int hourly_num = RiskControlCore.GetCalls(TkChannelEnum.cps, item.id, DateTime.Now.ToString("yyyyMMddHH"));
  45. if (hourly_num >= item.hourly_calls_limit) return false;
  46. }
  47. return true;
  48. }
  49. public static IEnumerable<CpsPoolDTO> List(bool force = false)
  50. {
  51. #if DEBUG
  52. return new DBContext.Table("cps_pool")
  53. .Where("status=@status", new { status = 1 })
  54. .Select<CpsPoolDTO>();
  55. #else
  56. if (!force && _cached != null) return _cached;
  57. string cache_key = $"cache:cps_pool";
  58. var list = RedisHelper.Get<IEnumerable<CpsPoolDTO>>(cache_key);
  59. if (force || list == null)
  60. {
  61. lock (_lockObj)
  62. {
  63. list = new DBContext.Table("cps_pool")
  64. .Where("status=@status", new { status = 1 })
  65. .Select<CpsPoolDTO>();
  66. if (list == null) return default;
  67. RedisHelper.Set(cache_key, list, 30 * 86400);
  68. }
  69. }
  70. _cached = list;
  71. return list;
  72. #endif
  73. }
  74. public static IEnumerable<CpsLinksDTO> LinksList(bool force = false)
  75. {
  76. #if DEBUG
  77. var list = new DBContext.Table("cps_links")
  78. .Where("status=@status", new { status = 1 })
  79. .Select<CpsLinksDTO>();
  80. foreach (var item in list)
  81. {
  82. RiskControlCore.SetCalls(TkChannelEnum.cps, item.id, DateTime.Now.ToString("yyyyMMddHH"), item.current_hourly_calls);
  83. RiskControlCore.SetCalls(TkChannelEnum.cps, item.id, DateTime.Now.ToString("yyyyMMdd"), item.current_daily_calls);
  84. }
  85. return list;
  86. #else
  87. if (!force && _links_cached != null) return _links_cached;
  88. string cache_key = $"cache:cps_links";
  89. var list = RedisHelper.Get<IEnumerable<CpsLinksDTO>>(cache_key);
  90. if (force || list == null)
  91. {
  92. lock (_lockObj)
  93. {
  94. list = new DBContext.Table("cps_links")
  95. .Where("status=@status", new { status = 1 })
  96. .Select<CpsLinksDTO>();
  97. if (list == null) return default;
  98. foreach (var item in list)
  99. {
  100. RiskControlCore.SetCalls(TkChannelEnum.cps, item.id, DateTime.Now.ToString("yyyyMMddHH"), item.current_hourly_calls);
  101. RiskControlCore.SetCalls(TkChannelEnum.cps, item.id, DateTime.Now.ToString("yyyyMMdd"), item.current_daily_calls);
  102. }
  103. RedisHelper.Set(cache_key, list, 30 * 86400);
  104. }
  105. }
  106. _links_cached = list;
  107. return list;
  108. #endif
  109. }
  110. public static int Update(CpsLinksDTO account)
  111. {
  112. return new DBContext.Table("cps_links")
  113. .Add("current_hourly_calls", account.current_hourly_calls)
  114. .Add("current_daily_calls", account.current_daily_calls)
  115. .Where("id=@id", new { account.id })
  116. .Update();
  117. }
  118. public static void Refresh()
  119. {
  120. _ = List(true);
  121. _ = LinksList(true);
  122. }
  123. internal static void AccountExhausted()
  124. {
  125. string cache_key = $"cache:tk_pool:account:exhausted";
  126. long count = RedisHelper.IncrBy(cache_key);
  127. if (count > 1) return;
  128. RedisHelper.Expire(cache_key, 3600);
  129. NotifyCore.Notify(new NifyMessage
  130. {
  131. message = $"【CPS优惠券】没有匹配账号",
  132. priority = NifyMessagePriority.high,
  133. tags = ["red_circle"]
  134. });
  135. NotifyCore.AnPushNotify("没账号", $"【CPS优惠券】没有匹配账号");
  136. }
  137. }
  138. }