创建新工程

This commit is contained in:
moyin
2025-12-05 19:00:14 +08:00
commit ff4fa5fffd
227 changed files with 32804 additions and 0 deletions

448
scripts/DialogueFilter.gd Normal file
View File

@@ -0,0 +1,448 @@
extends Node
class_name DialogueFilter
## 对话过滤器
## 提供内容审核、过滤和安全检查功能
# 过滤规则配置
var enable_profanity_filter: bool = true
var enable_spam_detection: bool = true
var enable_length_limit: bool = true
var enable_rate_limiting: bool = true
# 长度限制
var max_message_length: int = 500
var min_message_length: int = 1
# 垃圾信息检测
var spam_detection_window: float = 10.0 # 10秒窗口
var max_messages_per_window: int = 5
var max_duplicate_messages: int = 3
# 违禁词列表(示例,实际使用时应该从配置文件加载)
var profanity_words: Array[String] = [
# 基础违禁词(示例)
"垃圾", "废物", "白痴", "蠢货", "混蛋",
# 可以根据需要添加更多
]
# 敏感词替换
var profanity_replacement: String = "***"
# 消息历史(用于垃圾信息检测)
var message_history: Dictionary = {} # user_id -> Array[Dictionary]
# 过滤统计
var filter_stats: Dictionary = {
"total_messages": 0,
"filtered_messages": 0,
"profanity_blocked": 0,
"spam_blocked": 0,
"length_violations": 0,
"rate_limit_violations": 0
}
# 信号
signal message_filtered(user_id: String, original_message: String, filtered_message: String, reason: String)
signal message_blocked(user_id: String, message: String, reason: String)
func _ready():
"""初始化对话过滤器"""
load_filter_config()
print("DialogueFilter initialized")
## 过滤消息
func filter_message(user_id: String, message: String) -> Dictionary:
"""
过滤和验证消息
@param user_id: 用户ID
@param message: 原始消息
@return: 过滤结果 {allowed: bool, filtered_message: String, reason: String}
"""
filter_stats.total_messages += 1
var result = {
"allowed": true,
"filtered_message": message,
"reason": ""
}
# 1. 长度检查
if enable_length_limit:
var length_check = _check_message_length(message)
if not length_check.valid:
result.allowed = false
result.reason = length_check.reason
filter_stats.length_violations += 1
message_blocked.emit(user_id, message, result.reason)
return result
# 2. 速率限制检查
if enable_rate_limiting:
var rate_check = _check_rate_limit(user_id, message)
if not rate_check.valid:
result.allowed = false
result.reason = rate_check.reason
filter_stats.rate_limit_violations += 1
message_blocked.emit(user_id, message, result.reason)
return result
# 3. 垃圾信息检测
if enable_spam_detection:
var spam_check = _check_spam(user_id, message)
if not spam_check.valid:
result.allowed = false
result.reason = spam_check.reason
filter_stats.spam_blocked += 1
message_blocked.emit(user_id, message, result.reason)
return result
# 4. 违禁词过滤
if enable_profanity_filter:
var profanity_result = _filter_profanity(message)
if profanity_result.has_profanity:
result.filtered_message = profanity_result.filtered_message
filter_stats.profanity_blocked += 1
message_filtered.emit(user_id, message, result.filtered_message, "违禁词过滤")
# 5. 记录消息历史(用于垃圾信息检测)
_record_message(user_id, result.filtered_message)
if result.filtered_message != message:
filter_stats.filtered_messages += 1
return result
## 检查消息长度
func _check_message_length(message: String) -> Dictionary:
"""
检查消息长度是否符合要求
@param message: 消息内容
@return: 验证结果
"""
var trimmed = message.strip_edges()
if trimmed.length() < min_message_length:
return {
"valid": false,
"reason": "消息不能为空"
}
if trimmed.length() > max_message_length:
return {
"valid": false,
"reason": "消息长度超过限制(最多%d个字符)" % max_message_length
}
return {"valid": true, "reason": ""}
## 检查速率限制
func _check_rate_limit(user_id: String, _message: String) -> Dictionary:
"""
检查用户是否超过消息发送速率限制
@param user_id: 用户ID
@param _message: 消息内容(暂未使用)
@return: 验证结果
"""
var current_time = Time.get_unix_time_from_system()
if not message_history.has(user_id):
return {"valid": true, "reason": ""}
var user_messages = message_history[user_id]
var recent_messages = []
# 统计时间窗口内的消息
for msg_record in user_messages:
if current_time - msg_record.timestamp <= spam_detection_window:
recent_messages.append(msg_record)
if recent_messages.size() >= max_messages_per_window:
return {
"valid": false,
"reason": "发送消息过于频繁,请稍后再试"
}
return {"valid": true, "reason": ""}
## 检查垃圾信息
func _check_spam(user_id: String, message: String) -> Dictionary:
"""
检查是否为垃圾信息
@param user_id: 用户ID
@param message: 消息内容
@return: 验证结果
"""
if not message_history.has(user_id):
return {"valid": true, "reason": ""}
var user_messages = message_history[user_id]
var duplicate_count = 0
var current_time = Time.get_unix_time_from_system()
# 检查重复消息
for msg_record in user_messages:
# 只检查最近的消息
if current_time - msg_record.timestamp <= spam_detection_window:
if msg_record.message.to_lower() == message.to_lower():
duplicate_count += 1
if duplicate_count >= max_duplicate_messages:
return {
"valid": false,
"reason": "请不要重复发送相同的消息"
}
# 检查是否全是重复字符
if _is_repetitive_text(message):
return {
"valid": false,
"reason": "请发送有意义的消息内容"
}
# 检查是否全是大写字母(可能是刷屏)
if message.length() > 10 and message == message.to_upper():
return {
"valid": false,
"reason": "请不要使用全大写字母"
}
return {"valid": true, "reason": ""}
## 过滤违禁词
func _filter_profanity(message: String) -> Dictionary:
"""
过滤消息中的违禁词
@param message: 原始消息
@return: 过滤结果
"""
var filtered_message = message
var has_profanity = false
for word in profanity_words:
if filtered_message.to_lower().contains(word.to_lower()):
# 替换违禁词
var regex = RegEx.new()
regex.compile("(?i)" + word) # 不区分大小写
filtered_message = regex.sub(filtered_message, profanity_replacement, true)
has_profanity = true
return {
"has_profanity": has_profanity,
"filtered_message": filtered_message
}
## 检查是否为重复字符文本
func _is_repetitive_text(text: String) -> bool:
"""
检查文本是否主要由重复字符组成
@param text: 输入文本
@return: 是否为重复字符文本
"""
if text.length() < 5:
return false
var char_counts = {}
for character in text:
char_counts[character] = char_counts.get(character, 0) + 1
# 如果任何字符占比超过70%,认为是重复文本
var threshold = text.length() * 0.7
for count in char_counts.values():
if count > threshold:
return true
return false
## 记录消息历史
func _record_message(user_id: String, message: String) -> void:
"""
记录用户消息历史(用于垃圾信息检测)
@param user_id: 用户ID
@param message: 消息内容
"""
if not message_history.has(user_id):
message_history[user_id] = []
var user_messages = message_history[user_id]
var current_time = Time.get_unix_time_from_system()
# 添加新消息
user_messages.append({
"message": message,
"timestamp": current_time
})
# 清理过期消息保留最近1小时的消息
var one_hour_ago = current_time - 3600
var filtered_messages = []
for msg_record in user_messages:
if msg_record.timestamp > one_hour_ago:
filtered_messages.append(msg_record)
message_history[user_id] = filtered_messages
## 添加违禁词
func add_profanity_word(word: String) -> void:
"""
添加违禁词到过滤列表
@param word: 违禁词
"""
var clean_word = word.strip_edges().to_lower()
if not clean_word.is_empty() and not clean_word in profanity_words:
profanity_words.append(clean_word)
save_filter_config()
## 移除违禁词
func remove_profanity_word(word: String) -> void:
"""
从过滤列表中移除违禁词
@param word: 违禁词
"""
var clean_word = word.strip_edges().to_lower()
if clean_word in profanity_words:
profanity_words.erase(clean_word)
save_filter_config()
## 设置过滤配置
func set_filter_config(config: Dictionary) -> void:
"""
设置过滤器配置
@param config: 配置字典
"""
if config.has("enable_profanity_filter"):
enable_profanity_filter = config.enable_profanity_filter
if config.has("enable_spam_detection"):
enable_spam_detection = config.enable_spam_detection
if config.has("enable_length_limit"):
enable_length_limit = config.enable_length_limit
if config.has("enable_rate_limiting"):
enable_rate_limiting = config.enable_rate_limiting
if config.has("max_message_length"):
max_message_length = config.max_message_length
if config.has("max_messages_per_window"):
max_messages_per_window = config.max_messages_per_window
save_filter_config()
## 获取过滤配置
func get_filter_config() -> Dictionary:
"""
获取当前过滤器配置
@return: 配置字典
"""
return {
"enable_profanity_filter": enable_profanity_filter,
"enable_spam_detection": enable_spam_detection,
"enable_length_limit": enable_length_limit,
"enable_rate_limiting": enable_rate_limiting,
"max_message_length": max_message_length,
"min_message_length": min_message_length,
"max_messages_per_window": max_messages_per_window,
"spam_detection_window": spam_detection_window,
"profanity_words_count": profanity_words.size()
}
## 获取过滤统计
func get_filter_statistics() -> Dictionary:
"""
获取过滤统计信息
@return: 统计信息字典
"""
var stats = filter_stats.duplicate()
if stats.total_messages > 0:
stats["filter_rate"] = float(stats.filtered_messages) / float(stats.total_messages)
stats["block_rate"] = float(stats.profanity_blocked + stats.spam_blocked + stats.length_violations + stats.rate_limit_violations) / float(stats.total_messages)
else:
stats["filter_rate"] = 0.0
stats["block_rate"] = 0.0
return stats
## 重置统计信息
func reset_statistics() -> void:
"""重置过滤统计信息"""
filter_stats = {
"total_messages": 0,
"filtered_messages": 0,
"profanity_blocked": 0,
"spam_blocked": 0,
"length_violations": 0,
"rate_limit_violations": 0
}
## 清理用户历史
func clear_user_history(user_id: String) -> void:
"""
清理指定用户的消息历史
@param user_id: 用户ID
"""
if message_history.has(user_id):
message_history.erase(user_id)
## 保存过滤器配置
func save_filter_config() -> void:
"""保存过滤器配置到本地文件"""
var config = {
"filter_settings": get_filter_config(),
"profanity_words": profanity_words
}
var file = FileAccess.open("user://dialogue_filter_config.json", FileAccess.WRITE)
if file:
var json_string = JSON.stringify(config)
file.store_string(json_string)
file.close()
print("Filter config saved")
## 加载过滤器配置
func load_filter_config() -> void:
"""从本地文件加载过滤器配置"""
if not FileAccess.file_exists("user://dialogue_filter_config.json"):
print("No filter config found, using defaults")
return
var file = FileAccess.open("user://dialogue_filter_config.json", FileAccess.READ)
if file:
var json_string = file.get_as_text()
file.close()
var json = JSON.new()
var parse_result = json.parse(json_string)
if parse_result == OK:
var config = json.data
if config.has("filter_settings"):
set_filter_config(config.filter_settings)
if config.has("profanity_words") and config.profanity_words is Array:
profanity_words = config.profanity_words
print("Filter config loaded")
else:
print("Failed to parse filter config")
## 定期清理过期数据
func _on_cleanup_timer():
"""定期清理过期的消息历史数据"""
var current_time = Time.get_unix_time_from_system()
var one_hour_ago = current_time - 3600
for user_id in message_history.keys():
var user_messages = message_history[user_id]
var filtered_messages = []
for msg_record in user_messages:
if msg_record.timestamp > one_hour_ago:
filtered_messages.append(msg_record)
if filtered_messages.is_empty():
message_history.erase(user_id)
else:
message_history[user_id] = filtered_messages