feat:给动作添加了选择器,并添加了新api

This commit is contained in:
SengokuCola
2025-06-09 12:55:23 +08:00
parent 5ef3139654
commit 2ce5114b8c
19 changed files with 1660 additions and 103 deletions

View File

@@ -1,5 +1,5 @@
from src.common.logger_manager import get_logger
from src.chat.focus_chat.planners.actions.plugin_action import PluginAction, register_action
from src.chat.focus_chat.planners.actions.plugin_action import PluginAction, register_action, ActionActivationType
from typing import Tuple
logger = get_logger("mute_action")
@@ -22,9 +22,102 @@ class MuteAction(PluginAction):
"当有人发了擦边,或者色情内容时使用",
"当有人要求禁言自己时使用",
]
default = False # 默认动作,是否手动添加到使用集
default = True # 默认动作,是否手动添加到使用集
associated_types = ["command", "text"]
# associated_types = ["text"]
action_config_file_name = "mute_action_config.toml"
# 激活类型设置 - 使用LLM判定因为禁言是严肃的管理动作需要谨慎判断
action_activation_type = ActionActivationType.LLM_JUDGE
llm_judge_prompt = """
判定是否需要使用禁言动作的严格条件:
必须使用禁言的情况:
1. 用户发送明显违规内容(色情、暴力、政治敏感等)
2. 恶意刷屏或垃圾信息轰炸
3. 用户主动明确要求被禁言("禁言我"等)
4. 严重违反群规的行为
5. 恶意攻击他人或群组管理
绝对不要使用的情况:
1. 正常聊天和讨论,即使话题敏感
2. 情绪化表达但无恶意
3. 开玩笑或调侃,除非过分
4. 单纯的意见分歧或争论
5. 轻微的不当言论(应优先提醒)
6. 用户只是提到"禁言"词汇但非要求
注意:禁言是严厉措施,只在明确违规或用户主动要求时使用。
宁可保守也不要误判,保护用户的发言权利。
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 生成配置文件(如果不存在)
self._generate_config_if_needed()
def _generate_config_if_needed(self):
"""生成配置文件(如果不存在)"""
import os
# 获取动作文件所在目录
current_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(current_dir, "mute_action_config.toml")
if not os.path.exists(config_path):
config_content = """\
# 禁言动作配置文件
# 默认禁言时长限制(秒)
min_duration = 60 # 最短禁言时长
max_duration = 2592000 # 最长禁言时长30天
default_duration = 300 # 默认禁言时长5分钟
# 禁言消息模板
templates = [
"好的,禁言 {target} {duration},理由:{reason}",
"收到,对 {target} 执行禁言 {duration},因为{reason}",
"明白了,禁言 {target} {duration},原因是{reason}"
]
# 错误消息模板
error_messages = [
"没有指定禁言对象呢~",
"没有指定禁言时长呢~",
"禁言时长必须是正数哦~",
"禁言时长必须是数字哦~",
"找不到 {target} 这个人呢~",
"查找用户信息时出现问题~"
]
# 是否启用时长美化显示
enable_duration_formatting = true
# 是否记录禁言历史
log_mute_history = true
"""
try:
with open(config_path, "w", encoding="utf-8") as f:
f.write(config_content)
logger.info(f"已生成禁言动作配置文件: {config_path}")
except Exception as e:
logger.error(f"生成配置文件失败: {e}")
def _get_duration_limits(self) -> tuple[int, int, int]:
"""获取时长限制配置"""
min_dur = self.config.get("min_duration", 60)
max_dur = self.config.get("max_duration", 2592000)
default_dur = self.config.get("default_duration", 300)
return min_dur, max_dur, default_dur
def _get_template_message(self, target: str, duration_str: str, reason: str) -> str:
"""获取模板化的禁言消息"""
templates = self.config.get("templates", [
"好的,禁言 {target} {duration},理由:{reason}"
])
import random
template = random.choice(templates)
return template.format(target=target, duration=duration_str, reason=reason)
async def process(self) -> Tuple[bool, str]:
"""处理群聊禁言动作"""
@@ -35,47 +128,115 @@ class MuteAction(PluginAction):
duration = self.action_data.get("duration")
reason = self.action_data.get("reason", "违反群规")
if not target or not duration:
error_msg = "禁言参数不完整需要target和duration"
# 参数验证
if not target:
error_msg = "禁言目标不能为空"
logger.error(f"{self.log_prefix} {error_msg}")
await self.send_message_by_expressor("没有指定禁言对象呢~")
return False, error_msg
if not duration:
error_msg = "禁言时长不能为空"
logger.error(f"{self.log_prefix} {error_msg}")
await self.send_message_by_expressor("没有指定禁言时长呢~")
return False, error_msg
# 获取时长限制配置
min_duration, max_duration, default_duration = self._get_duration_limits()
# 验证时长格式并转换
try:
duration_int = int(duration)
if duration_int <= 0:
error_msg = "禁言时长必须大于0"
logger.error(f"{self.log_prefix} {error_msg}")
error_templates = self.config.get("error_messages", ["禁言时长必须是正数哦~"])
await self.send_message_by_expressor(error_templates[2] if len(error_templates) > 2 else "禁言时长必须是正数哦~")
return False, error_msg
# 限制禁言时长范围
if duration_int < min_duration:
duration_int = min_duration
logger.info(f"{self.log_prefix} 禁言时长过短,调整为{min_duration}")
elif duration_int > max_duration:
duration_int = max_duration
logger.info(f"{self.log_prefix} 禁言时长过长,调整为{max_duration}")
except (ValueError, TypeError) as e:
error_msg = f"禁言时长格式无效: {duration}"
logger.error(f"{self.log_prefix} {error_msg}")
error_templates = self.config.get("error_messages", ["禁言时长必须是数字哦~"])
await self.send_message_by_expressor(error_templates[3] if len(error_templates) > 3 else "禁言时长必须是数字哦~")
return False, error_msg
# 获取用户ID
platform, user_id = await self.get_user_id_by_person_name(target)
try:
platform, user_id = await self.get_user_id_by_person_name(target)
except Exception as e:
error_msg = f"查找用户ID时出错: {e}"
logger.error(f"{self.log_prefix} {error_msg}")
await self.send_message_by_expressor("查找用户信息时出现问题~")
return False, error_msg
if not user_id:
error_msg = f"未找到用户 {target} 的ID"
await self.send_message_by_expressor(f"压根没 {target} 这个人")
await self.send_message_by_expressor(f"找不到 {target} 这个人呢~")
logger.error(f"{self.log_prefix} {error_msg}")
return False, error_msg
# 发送表达情绪的消息
await self.send_message_by_expressor(f"禁言{target} {duration}秒,因为{reason}")
enable_formatting = self.config.get("enable_duration_formatting", True)
time_str = self._format_duration(duration_int) if enable_formatting else f"{duration_int}"
# 使用模板化消息
message = self._get_template_message(target, time_str, reason)
await self.send_message_by_expressor(message)
try:
# 确保duration是字符串类型
if int(duration) < 60:
duration = 60
if int(duration) > 3600 * 24 * 30:
duration = 3600 * 24 * 30
duration_str = str(int(duration))
duration_str = str(duration_int)
# 发送群聊禁言命令,按照新格式
await self.send_message(
type="command",
data={"name": "GROUP_BAN", "args": {"qq_id": str(user_id), "duration": duration_str}},
display_message=f"尝试禁言了 {target} {duration_str}",
display_message=f"尝试禁言了 {target} {time_str}",
)
await self.store_action_info(
action_build_into_prompt=False,
action_prompt_display=f"你尝试禁言了 {target} {duration_str}",
action_prompt_display=f"你尝试禁言了 {target} {time_str},理由:{reason}",
)
logger.info(f"{self.log_prefix} 成功发送禁言命令,用户 {target}({user_id}),时长 {duration}")
return True, f"成功禁言 {target},时长 {duration}"
logger.info(f"{self.log_prefix} 成功发送禁言命令,用户 {target}({user_id}),时长 {duration_int}")
return True, f"成功禁言 {target},时长 {time_str}"
except Exception as e:
logger.error(f"{self.log_prefix} 执行禁言动作时出错: {e}")
await self.send_message_by_expressor(f"执行禁言动作时出错: {e}")
return False, f"执行禁言动作时出错: {e}"
def _format_duration(self, seconds: int) -> str:
"""将秒数格式化为可读的时间字符串"""
if seconds < 60:
return f"{seconds}"
elif seconds < 3600:
minutes = seconds // 60
remaining_seconds = seconds % 60
if remaining_seconds > 0:
return f"{minutes}{remaining_seconds}"
else:
return f"{minutes}分钟"
elif seconds < 86400:
hours = seconds // 3600
remaining_minutes = (seconds % 3600) // 60
if remaining_minutes > 0:
return f"{hours}小时{remaining_minutes}分钟"
else:
return f"{hours}小时"
else:
days = seconds // 86400
remaining_hours = (seconds % 86400) // 3600
if remaining_hours > 0:
return f"{days}{remaining_hours}小时"
else:
return f"{days}"