|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|
|
using System.Data;
|
|
using System.Data;
|
|
|
using System.Security.Cryptography;
|
|
using System.Security.Cryptography;
|
|
|
using System.Text.RegularExpressions;
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
+using System.Web;
|
|
|
using YunhuiKit;
|
|
using YunhuiKit;
|
|
|
|
|
|
|
|
|
|
|
|
@@ -102,32 +103,35 @@ namespace molilian.core
|
|
|
|
|
|
|
|
foreach (var item in list)
|
|
foreach (var item in list)
|
|
|
{
|
|
{
|
|
|
|
|
+ //
|
|
|
if (!request.Channel.Equals(item.platform)) continue;
|
|
if (!request.Channel.Equals(item.platform)) continue;
|
|
|
- if (string.IsNullOrEmpty(item.original_text)) continue;
|
|
|
|
|
if (item.use_special_text == 1 && request.SpecialText != 1) continue;
|
|
if (item.use_special_text == 1 && request.SpecialText != 1) continue;
|
|
|
|
|
|
|
|
|
|
+ string original_text = item.original_text;
|
|
|
|
|
+ if (item.use_special_text == 1) original_text = request.QueryText;
|
|
|
|
|
+ if (string.IsNullOrEmpty(original_text)) continue;
|
|
|
|
|
+
|
|
|
switch (item.rule)
|
|
switch (item.rule)
|
|
|
{
|
|
{
|
|
|
case "regex":
|
|
case "regex":
|
|
|
- Match match = Regex.Match(content, item.original_text);
|
|
|
|
|
|
|
+ Match match = Regex.Match(content, original_text);
|
|
|
if (!match.Success) continue;
|
|
if (!match.Success) continue;
|
|
|
break;
|
|
break;
|
|
|
case "text":
|
|
case "text":
|
|
|
- if (!content.Equals(item.original_text)) continue;
|
|
|
|
|
|
|
+ if (!content.Equals(original_text)) continue;
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
- if (!content.Contains(item.original_text)) continue;
|
|
|
|
|
|
|
+ if (!content.Contains(original_text)) continue;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
+ if (item.use_special_text == 1 && request.SpecialText != 1) continue;
|
|
|
|
|
+
|
|
|
if (item.use_risk_control)
|
|
if (item.use_risk_control)
|
|
|
{
|
|
{
|
|
|
bool is_ignore = AlimamaPlus.ShouldIgnoreRequest(request.Ip, request.Oaid, request.RiskStrategy, request.LaunchScene, out _);
|
|
bool is_ignore = AlimamaPlus.ShouldIgnoreRequest(request.Ip, request.Oaid, request.RiskStrategy, request.LaunchScene, out _);
|
|
|
if (is_ignore) continue;
|
|
if (is_ignore) continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (item.use_special_text == 1 && request.SpecialText != 1) continue;
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
// 每小时调用次数统计(无论是否设置限制都要记录)
|
|
// 每小时调用次数统计(无论是否设置限制都要记录)
|
|
|
string hourlyKey = $":override_rule_calls:{item.id}:{DateTime.Now:yyyyMMddHH}";
|
|
string hourlyKey = $":override_rule_calls:{item.id}:{DateTime.Now:yyyyMMddHH}";
|
|
|
try
|
|
try
|
|
@@ -165,11 +169,69 @@ namespace molilian.core
|
|
|
// Redis错误时记录日志但不阻塞业务
|
|
// Redis错误时记录日志但不阻塞业务
|
|
|
_ = new LoggerLibrary("OverrideRule", "Redis").Info($"Daily limit check failed: {ex.Message}", ex.StackTrace).SaveAsync();
|
|
_ = new LoggerLibrary("OverrideRule", "Redis").Info($"Daily limit check failed: {ex.Message}", ex.StackTrace).SaveAsync();
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 关键词统计 - 长期缓存(6个月)用于历史数据分析
|
|
|
|
|
+ await SaveKeywordStatisticsAsync(item.id, item.platform, original_text);
|
|
|
|
|
+
|
|
|
|
|
+ string output_text = item.output_text;
|
|
|
|
|
+ if (output_text.Contains("{url:query_text}")) output_text = output_text.Replace("{url:query_text}", HttpUtility.UrlEncode(original_text));
|
|
|
|
|
+ if (output_text.Contains("{url2:query_text}")) output_text = output_text.Replace("{url2:query_text}", HttpUtility.UrlEncode(HttpUtility.UrlEncode(original_text)));
|
|
|
|
|
+ if (output_text.Contains("{url3:query_text}")) output_text = output_text.Replace("{url3:query_text}", HttpUtility.UrlEncode(HttpUtility.UrlEncode(HttpUtility.UrlEncode(original_text))));
|
|
|
|
|
+ if (output_text.Contains("{query_text}")) output_text = output_text.Replace("{query_text}", original_text);
|
|
|
|
|
+ item.output_text = output_text;
|
|
|
return item;
|
|
return item;
|
|
|
}
|
|
}
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// 保存关键词统计数据到Redis,用于长期数据分析
|
|
|
|
|
+ /// 缓存周期:6个月
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private static async Task SaveKeywordStatisticsAsync(int ruleId, string platform, string keyword)
|
|
|
|
|
+ {
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ // 6个月的秒数
|
|
|
|
|
+ const int sixMonthsInSeconds = 180 * 86400;
|
|
|
|
|
+
|
|
|
|
|
+ // 关键词总请求次数统计 - 按月份
|
|
|
|
|
+ string monthlyKey = $":keyword_stats:{platform}:{ruleId}:{DateTime.Now:yyyyMM}";
|
|
|
|
|
+ await RedisKit.IncrByAsync(monthlyKey);
|
|
|
|
|
+ await RedisKit.ExpireAsync(monthlyKey, sixMonthsInSeconds);
|
|
|
|
|
+
|
|
|
|
|
+ // 关键词总请求次数统计 - 按日
|
|
|
|
|
+ string dailyKey = $":keyword_stats:{platform}:{ruleId}:{DateTime.Now:yyyyMMdd}";
|
|
|
|
|
+ await RedisKit.IncrByAsync(dailyKey);
|
|
|
|
|
+ await RedisKit.ExpireAsync(dailyKey, sixMonthsInSeconds);
|
|
|
|
|
+
|
|
|
|
|
+ // 关键词总请求次数统计 - 按小时
|
|
|
|
|
+ string hourlyKey = $":keyword_stats:{platform}:{ruleId}:{DateTime.Now:yyyyMMddHH}";
|
|
|
|
|
+ await RedisKit.IncrByAsync(hourlyKey);
|
|
|
|
|
+ await RedisKit.ExpireAsync(hourlyKey, sixMonthsInSeconds);
|
|
|
|
|
+
|
|
|
|
|
+ // 平台维度统计
|
|
|
|
|
+ string platformMonthlyKey = $":keyword_stats:platform:{platform}:{DateTime.Now:yyyyMM}";
|
|
|
|
|
+ await RedisKit.IncrByAsync(platformMonthlyKey);
|
|
|
|
|
+ await RedisKit.ExpireAsync(platformMonthlyKey, sixMonthsInSeconds);
|
|
|
|
|
+
|
|
|
|
|
+ // 全局统计
|
|
|
|
|
+ string globalMonthlyKey = $":keyword_stats:global:{DateTime.Now:yyyyMM}";
|
|
|
|
|
+ await RedisKit.IncrByAsync(globalMonthlyKey);
|
|
|
|
|
+ await RedisKit.ExpireAsync(globalMonthlyKey, sixMonthsInSeconds);
|
|
|
|
|
+
|
|
|
|
|
+ // 记录关键词集合(用于后续查询有哪些关键词)
|
|
|
|
|
+ string keywordSetKey = $":keyword_stats:set:{platform}:{DateTime.Now:yyyyMM}";
|
|
|
|
|
+ await RedisKit.SAddAsync(keywordSetKey, keyword);
|
|
|
|
|
+ await RedisKit.ExpireAsync(keywordSetKey, sixMonthsInSeconds);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (Exception ex)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Redis错误时记录日志但不阻塞业务
|
|
|
|
|
+ _ = new LoggerLibrary("OverrideRule", "KeywordStats").Info($"Keyword statistics save failed: {ex.Message}", ex.StackTrace).SaveAsync();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public static void Refresh()
|
|
public static void Refresh()
|
|
|
{
|
|
{
|
|
|
_cached = null;
|
|
_cached = null;
|