refactor: 统一类型注解风格并优化代码结构
- 将裸 except 改为显式 Exception 捕获 - 用列表推导式替换冗余 for 循环 - 为类属性添加 ClassVar 注解 - 统一 Union/Optional 写法为 | - 移除未使用的导入 - 修复 SQLAlchemy 空值比较语法 - 优化字符串拼接与字典更新逻辑 - 补充缺失的 noqa 注释与异常链 BREAKING CHANGE: 所有插件基类的类级字段现要求显式 ClassVar 注解,自定义插件需同步更新
This commit is contained in:
@@ -7,7 +7,7 @@ import asyncio
|
||||
import time
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from src.chat.express.expression_learner import expression_learner_manager
|
||||
from src.chat.planner_actions.action_manager import ChatterActionManager
|
||||
@@ -29,7 +29,7 @@ class AffinityChatter(BaseChatter):
|
||||
|
||||
chatter_name: str = "AffinityChatter"
|
||||
chatter_description: str = "基于亲和力模型的智能聊天处理器,支持多种聊天类型"
|
||||
chat_types: list[ChatType] = [ChatType.ALL] # 支持所有聊天类型
|
||||
chat_types: ClassVar[list[ChatType]] = [ChatType.ALL] # 支持所有聊天类型
|
||||
|
||||
def __init__(self, stream_id: str, action_manager: ChatterActionManager):
|
||||
"""
|
||||
@@ -68,7 +68,7 @@ class AffinityChatter(BaseChatter):
|
||||
try:
|
||||
# 触发表达学习
|
||||
learner = await expression_learner_manager.get_expression_learner(self.stream_id)
|
||||
asyncio.create_task(learner.trigger_learning_for_chat())
|
||||
asyncio.create_task(learner.trigger_learning_for_chat()) # noqa: RUF006
|
||||
|
||||
unread_messages = context.get_unread_messages()
|
||||
|
||||
@@ -87,7 +87,7 @@ class AffinityChatter(BaseChatter):
|
||||
self.stats["successful_executions"] += 1
|
||||
self.last_activity_time = time.time()
|
||||
|
||||
result = {
|
||||
result: ClassVar = {
|
||||
"success": True,
|
||||
"stream_id": self.stream_id,
|
||||
"plan_created": True,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"""
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from sqlalchemy import select
|
||||
|
||||
@@ -29,7 +29,7 @@ class ChatStreamImpressionTool(BaseTool):
|
||||
|
||||
name = "update_chat_stream_impression"
|
||||
description = "当你通过观察聊天记录对当前聊天环境(群聊或私聊)产生了整体印象或认识时使用此工具,更新对这个聊天流的看法。包括:环境氛围、聊天风格、常见话题、你的兴趣程度。调用时机:当你发现这个聊天环境有明显的氛围特点(如很活跃、很专业、很闲聊)、群成员经常讨论某类话题、或者你对这个环境的感受发生变化时。注意:这是对整个聊天环境的印象,而非对单个用户。"
|
||||
parameters = [
|
||||
parameters: ClassVar = [
|
||||
(
|
||||
"impression_description",
|
||||
ToolParamType.STRING,
|
||||
@@ -73,7 +73,7 @@ class ChatStreamImpressionTool(BaseTool):
|
||||
)
|
||||
except AttributeError:
|
||||
# 降级处理
|
||||
available_models = [
|
||||
available_models: ClassVar = [
|
||||
attr
|
||||
for attr in dir(model_config.model_task_config)
|
||||
if not attr.startswith("_") and attr != "model_dump"
|
||||
@@ -153,7 +153,7 @@ class ChatStreamImpressionTool(BaseTool):
|
||||
await self._update_stream_impression_in_db(stream_id, final_impression)
|
||||
|
||||
# 构建返回信息
|
||||
updates = []
|
||||
updates: ClassVar = []
|
||||
if final_impression.get("stream_impression_text"):
|
||||
updates.append(f"印象: {final_impression['stream_impression_text'][:50]}...")
|
||||
if final_impression.get("stream_chat_style"):
|
||||
|
||||
@@ -117,9 +117,11 @@ class ChatterPlanFilter:
|
||||
elif isinstance(actions_obj, list):
|
||||
actions_to_process_for_log.extend(actions_obj)
|
||||
|
||||
for single_action in actions_to_process_for_log:
|
||||
if isinstance(single_action, dict):
|
||||
action_types_to_log.append(single_action.get("action_type", "no_action"))
|
||||
action_types_to_log = [
|
||||
single_action.get("action_type", "no_action")
|
||||
for single_action in actions_to_process_for_log
|
||||
if isinstance(single_action, dict)
|
||||
]
|
||||
|
||||
if thinking != "未提供思考过程" and action_types_to_log:
|
||||
await self._add_decision_to_history(plan, thinking, ", ".join(action_types_to_log))
|
||||
|
||||
@@ -118,7 +118,6 @@ class ChatterActionPlanner:
|
||||
# 2. 使用新的兴趣度管理系统进行评分
|
||||
max_message_interest = 0.0
|
||||
reply_not_available = True
|
||||
interest_updates: list[dict[str, Any]] = []
|
||||
aggregate_should_act = False
|
||||
|
||||
if unread_messages:
|
||||
@@ -247,7 +246,7 @@ class ChatterActionPlanner:
|
||||
|
||||
async def _normal_mode_flow(self, context: "StreamContext | None") -> tuple[list[dict[str, Any]], Any | None]:
|
||||
"""Normal模式下的简化plan流程
|
||||
|
||||
|
||||
只计算兴趣值并判断是否达到reply阈值,不执行完整的plan流程。
|
||||
根据focus_energy决定退出normal模式回到focus模式的概率。
|
||||
"""
|
||||
@@ -371,7 +370,7 @@ class ChatterActionPlanner:
|
||||
|
||||
async def _check_exit_normal_mode(self, context: "StreamContext | None") -> None:
|
||||
"""检查并执行退出Normal模式的判定
|
||||
|
||||
|
||||
Args:
|
||||
context: 流上下文
|
||||
"""
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
亲和力聊天处理器插件(包含兴趣计算器功能)
|
||||
"""
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis.plugin_register_api import register_plugin
|
||||
from src.plugin_system.base.base_plugin import BasePlugin
|
||||
@@ -21,12 +23,12 @@ class AffinityChatterPlugin(BasePlugin):
|
||||
|
||||
plugin_name: str = "affinity_chatter"
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = []
|
||||
python_dependencies: list[str] = []
|
||||
dependencies: ClassVar[list[str] ] = []
|
||||
python_dependencies: ClassVar[list[str] ] = []
|
||||
config_file_name: str = ""
|
||||
|
||||
# 简单的 config_schema 占位(如果将来需要配置可扩展)
|
||||
config_schema = {}
|
||||
config_schema: ClassVar = {}
|
||||
|
||||
def get_plugin_components(self) -> list[tuple[ComponentInfo, type]]:
|
||||
"""返回插件包含的组件列表
|
||||
@@ -34,7 +36,7 @@ class AffinityChatterPlugin(BasePlugin):
|
||||
这里采用延迟导入以避免循环依赖和启动顺序问题。
|
||||
如果导入失败则返回空列表以让注册过程继续而不崩溃。
|
||||
"""
|
||||
components = []
|
||||
components: ClassVar = []
|
||||
|
||||
try:
|
||||
# 延迟导入 AffinityChatter
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
监听bot的reply事件,在reply后重置对应聊天流的主动思考定时任务
|
||||
"""
|
||||
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system import BaseEventHandler, EventType
|
||||
from src.plugin_system.base.base_event import HandlerResult
|
||||
@@ -23,7 +26,7 @@ class ProactiveThinkingReplyHandler(BaseEventHandler):
|
||||
|
||||
handler_name: str = "proactive_thinking_reply_handler"
|
||||
handler_description: str = "监听reply事件,重置主动思考定时任务"
|
||||
init_subscribe: list[EventType | str] = [EventType.AFTER_SEND]
|
||||
init_subscribe: ClassVar[list[EventType | str]] = [EventType.AFTER_SEND]
|
||||
|
||||
async def execute(self, kwargs: dict | None) -> HandlerResult:
|
||||
"""处理reply事件
|
||||
@@ -90,7 +93,7 @@ class ProactiveThinkingMessageHandler(BaseEventHandler):
|
||||
|
||||
handler_name: str = "proactive_thinking_message_handler"
|
||||
handler_description: str = "监听消息事件,为新聊天流创建主动思考任务"
|
||||
init_subscribe: list[EventType | str] = [EventType.ON_MESSAGE]
|
||||
init_subscribe: ClassVar[list[EventType | str]] = [EventType.ON_MESSAGE]
|
||||
|
||||
async def execute(self, kwargs: dict | None) -> HandlerResult:
|
||||
"""处理消息事件
|
||||
|
||||
@@ -213,7 +213,7 @@ class ProactiveThinkingPlanner:
|
||||
- 理由: {last_reasoning}"""
|
||||
if last_topic:
|
||||
last_decision_text += f"\n- 话题: {last_topic}"
|
||||
|
||||
|
||||
return f"""你的人设是:
|
||||
{context['bot_personality']}
|
||||
|
||||
@@ -238,7 +238,7 @@ class ProactiveThinkingPlanner:
|
||||
- 适用场景:气氛不适合说话、最近对话很活跃、没什么特别想说的、或者此时说话会显得突兀。
|
||||
- 心情影响:如果心情不好(如生气、难过),可能更倾向于保持沉默。
|
||||
|
||||
**选项2:简单冒个泡 (simple_bubble)**
|
||||
**选项2:简单冒个泡 (simple_bubble)**
|
||||
- 适用场景:对话有些冷清,你想缓和气氛或开启新的互动。
|
||||
- 方式:说一句轻松随意的话,旨在建立或维持连接。
|
||||
- 心情影响:心情会影响你冒泡的方式和内容。
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"""
|
||||
|
||||
import time
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
import orjson
|
||||
from sqlalchemy import select
|
||||
@@ -22,7 +22,7 @@ logger = get_logger("user_profile_tool")
|
||||
|
||||
class UserProfileTool(BaseTool):
|
||||
"""用户画像更新工具
|
||||
|
||||
|
||||
使用二步调用机制:
|
||||
1. LLM决定是否调用工具并传入初步参数
|
||||
2. 工具内部调用LLM,结合现有数据和传入参数,决定最终更新内容
|
||||
@@ -30,7 +30,7 @@ class UserProfileTool(BaseTool):
|
||||
|
||||
name = "update_user_profile"
|
||||
description = "当你通过聊天记录对某个用户产生了新的认识或印象时使用此工具,更新该用户的画像信息。包括:用户别名、你对TA的主观印象、TA的偏好兴趣、你对TA的好感程度。调用时机:当你发现用户透露了新的个人信息、展现了性格特点、表达了兴趣偏好,或者你们的互动让你对TA的看法发生变化时。"
|
||||
parameters = [
|
||||
parameters: ClassVar = [
|
||||
("target_user_id", ToolParamType.STRING, "目标用户的ID(必须)", True, None),
|
||||
("user_aliases", ToolParamType.STRING, "该用户的昵称或别名,如果发现用户自称或被他人称呼的其他名字时填写,多个别名用逗号分隔(可选)", False, None),
|
||||
("impression_description", ToolParamType.STRING, "你对该用户的整体印象和性格感受,例如'这个用户很幽默开朗'、'TA对技术很有热情'等。当你通过对话了解到用户的性格、态度、行为特点时填写(可选)", False, None),
|
||||
@@ -51,7 +51,7 @@ class UserProfileTool(BaseTool):
|
||||
)
|
||||
except AttributeError:
|
||||
# 降级处理
|
||||
available_models = [
|
||||
available_models: ClassVar = [
|
||||
attr for attr in dir(model_config.model_task_config)
|
||||
if not attr.startswith("_") and attr != "model_dump"
|
||||
]
|
||||
@@ -68,10 +68,10 @@ class UserProfileTool(BaseTool):
|
||||
|
||||
async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]:
|
||||
"""执行用户画像更新
|
||||
|
||||
|
||||
Args:
|
||||
function_args: 工具参数
|
||||
|
||||
|
||||
Returns:
|
||||
dict: 执行结果
|
||||
"""
|
||||
@@ -131,7 +131,7 @@ class UserProfileTool(BaseTool):
|
||||
await self._update_user_profile_in_db(target_user_id, final_profile)
|
||||
|
||||
# 构建返回信息
|
||||
updates = []
|
||||
updates: ClassVar = []
|
||||
if final_profile.get("user_aliases"):
|
||||
updates.append(f"别名: {final_profile['user_aliases']}")
|
||||
if final_profile.get("relationship_text"):
|
||||
@@ -160,10 +160,10 @@ class UserProfileTool(BaseTool):
|
||||
|
||||
async def _get_user_profile(self, user_id: str) -> dict[str, Any]:
|
||||
"""从数据库获取用户现有画像
|
||||
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
|
||||
|
||||
Returns:
|
||||
dict: 用户画像数据
|
||||
"""
|
||||
@@ -210,7 +210,7 @@ class UserProfileTool(BaseTool):
|
||||
new_score: float | None
|
||||
) -> dict[str, Any] | None:
|
||||
"""使用LLM决策最终的用户画像内容
|
||||
|
||||
|
||||
Args:
|
||||
target_user_id: 目标用户ID
|
||||
existing_profile: 现有画像数据
|
||||
@@ -218,7 +218,7 @@ class UserProfileTool(BaseTool):
|
||||
new_impression: LLM传入的新印象
|
||||
new_keywords: LLM传入的新关键词
|
||||
new_score: LLM传入的新分数
|
||||
|
||||
|
||||
Returns:
|
||||
dict: 最终决定的画像数据,如果失败返回None
|
||||
"""
|
||||
@@ -296,7 +296,7 @@ class UserProfileTool(BaseTool):
|
||||
|
||||
async def _update_user_profile_in_db(self, user_id: str, profile: dict[str, Any]):
|
||||
"""更新数据库中的用户画像
|
||||
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
profile: 画像数据
|
||||
@@ -338,10 +338,10 @@ class UserProfileTool(BaseTool):
|
||||
|
||||
def _clean_llm_json_response(self, response: str) -> str:
|
||||
"""清理LLM响应,移除可能的JSON格式标记
|
||||
|
||||
|
||||
Args:
|
||||
response: LLM原始响应
|
||||
|
||||
|
||||
Returns:
|
||||
str: 清理后的JSON字符串
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import random
|
||||
import re
|
||||
from typing import ClassVar
|
||||
|
||||
from src.chat.emoji_system.emoji_history import add_emoji_to_history, get_recent_emojis
|
||||
from src.chat.emoji_system.emoji_manager import MaiEmoji, get_emoji_manager
|
||||
@@ -20,14 +21,14 @@ logger = get_logger("emoji")
|
||||
|
||||
class EmojiAction(BaseAction):
|
||||
"""表情动作 - 发送表情包
|
||||
|
||||
|
||||
注意:此 Action 使用旧的激活类型配置方式(已废弃但仍然兼容)。
|
||||
BaseAction.go_activate() 的默认实现会自动处理这些旧配置。
|
||||
|
||||
|
||||
推荐的新写法(迁移示例):
|
||||
----------------------------------------
|
||||
# 移除下面的 activation_type 相关配置,改为重写 go_activate 方法:
|
||||
|
||||
|
||||
async def go_activate(self, chat_content: str = "", llm_judge_model=None) -> bool:
|
||||
# 根据配置选择激活方式
|
||||
if global_config.emoji.emoji_activate_type == "llm":
|
||||
@@ -75,17 +76,17 @@ class EmojiAction(BaseAction):
|
||||
"""
|
||||
|
||||
# 动作参数定义
|
||||
action_parameters = {}
|
||||
action_parameters: ClassVar = {}
|
||||
|
||||
# 动作使用场景
|
||||
action_require = [
|
||||
action_require: ClassVar = [
|
||||
"发送表情包辅助表达情绪",
|
||||
"表达情绪时可以选择使用",
|
||||
"不要连续发送,如果你已经发过[表情包],就不要选择此动作",
|
||||
]
|
||||
|
||||
# 关联类型
|
||||
associated_types = ["emoji"]
|
||||
associated_types: ClassVar[list[str]] = ["emoji"]
|
||||
|
||||
async def execute(self) -> tuple[bool, str]:
|
||||
"""执行表情动作"""
|
||||
@@ -119,8 +120,8 @@ class EmojiAction(BaseAction):
|
||||
logger.error(f"{self.log_prefix} 获取或处理表情发送历史时出错: {e}")
|
||||
|
||||
# 4. 准备情感数据和后备列表
|
||||
emotion_map = {}
|
||||
all_emojis_data = []
|
||||
emotion_map: ClassVar = {}
|
||||
all_emojis_data: ClassVar = []
|
||||
|
||||
for emoji in all_emojis_obj:
|
||||
b64 = image_path_to_base64(emoji.full_path)
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
"""
|
||||
|
||||
# 导入依赖的系统组件
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
|
||||
# 导入新插件系统
|
||||
@@ -34,18 +36,18 @@ class CoreActionsPlugin(BasePlugin):
|
||||
# 插件基本信息
|
||||
plugin_name: str = "core_actions" # 内部标识符
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = [] # 插件依赖列表
|
||||
python_dependencies: list[str] = [] # Python包依赖列表
|
||||
dependencies: ClassVar[list[str]] = [] # 插件依赖列表
|
||||
python_dependencies: ClassVar[list[str]] = [] # Python包依赖列表
|
||||
config_file_name: str = "config.toml"
|
||||
|
||||
# 配置节描述
|
||||
config_section_descriptions = {
|
||||
config_section_descriptions: ClassVar = {
|
||||
"plugin": "插件启用配置",
|
||||
"components": "核心组件启用配置",
|
||||
}
|
||||
|
||||
# 配置Schema定义
|
||||
config_schema: dict = {
|
||||
config_schema: ClassVar[dict] = {
|
||||
"plugin": {
|
||||
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
|
||||
"config_version": ConfigField(type=str, default="0.6.0", description="配置文件版本"),
|
||||
@@ -63,7 +65,7 @@ class CoreActionsPlugin(BasePlugin):
|
||||
"""返回插件包含的组件列表"""
|
||||
|
||||
# --- 根据配置注册组件 ---
|
||||
components = []
|
||||
components: ClassVar = []
|
||||
if self.get_config("components.enable_emoji", True):
|
||||
components.append((EmojiAction.get_action_info(), EmojiAction))
|
||||
if self.get_config("components.enable_anti_injector_manager", True):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from src.chat.knowledge.knowledge_lib import qa_manager
|
||||
from src.common.logger import get_logger
|
||||
@@ -13,7 +13,7 @@ class SearchKnowledgeFromLPMMTool(BaseTool):
|
||||
|
||||
name = "lpmm_search_knowledge"
|
||||
description = "从知识库中搜索相关信息,如果你需要知识,就使用这个工具"
|
||||
parameters = [
|
||||
parameters: ClassVar = [
|
||||
("query", ToolParamType.STRING, "搜索查询关键词", True, None),
|
||||
("threshold", ToolParamType.FLOAT, "相似度阈值,0.0到1.0之间", False, None),
|
||||
]
|
||||
@@ -44,7 +44,7 @@ class SearchKnowledgeFromLPMMTool(BaseTool):
|
||||
logger.debug(f"知识库查询结果: {knowledge_info}")
|
||||
|
||||
if knowledge_info and knowledge_info.get("knowledge_items"):
|
||||
knowledge_parts = []
|
||||
knowledge_parts: ClassVar = []
|
||||
for i, item in enumerate(knowledge_info["knowledge_items"]):
|
||||
knowledge_parts.append(f"- {item.get('content', 'N/A')}")
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
阅读说说动作组件
|
||||
"""
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system import ActionActivationType, BaseAction, ChatMode
|
||||
from src.plugin_system.apis import generator_api
|
||||
@@ -21,9 +23,9 @@ class ReadFeedAction(BaseAction):
|
||||
action_description: str = "读取好友的最新动态并进行评论点赞"
|
||||
activation_type: ActionActivationType = ActionActivationType.KEYWORD
|
||||
mode_enable: ChatMode = ChatMode.ALL
|
||||
activation_keywords: list = ["看说说", "看空间", "看动态", "刷空间"]
|
||||
activation_keywords: ClassVar[list] = ["看说说", "看空间", "看动态", "刷空间"]
|
||||
|
||||
action_parameters = {
|
||||
action_parameters: ClassVar[dict] = {
|
||||
"target_name": "需要阅读动态的好友的昵称",
|
||||
"user_name": "请求你阅读动态的好友的昵称",
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
发送说说动作组件
|
||||
"""
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system import ActionActivationType, BaseAction, ChatMode
|
||||
from src.plugin_system.apis import generator_api
|
||||
@@ -21,9 +23,9 @@ class SendFeedAction(BaseAction):
|
||||
action_description: str = "发送一条关于特定主题的说说"
|
||||
activation_type: ActionActivationType = ActionActivationType.KEYWORD
|
||||
mode_enable: ChatMode = ChatMode.ALL
|
||||
activation_keywords: list = ["发说说", "发空间", "发动态"]
|
||||
activation_keywords: ClassVar[list] = ["发说说", "发空间", "发动态"]
|
||||
|
||||
action_parameters = {
|
||||
action_parameters: ClassVar[dict] = {
|
||||
"topic": "用户想要发送的说说主题",
|
||||
"user_name": "请求你发说说的好友的昵称",
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
发送说说命令 await self.send_text(f"收到!正在为你生成关于"{topic or '随机'}"的说说,请稍候...【热重载测试成功】")件
|
||||
"""
|
||||
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.base.command_args import CommandArgs
|
||||
from src.plugin_system.base.plus_command import PlusCommand
|
||||
@@ -20,7 +23,7 @@ class SendFeedCommand(PlusCommand):
|
||||
|
||||
command_name: str = "send_feed"
|
||||
command_description: str = "发一条QQ空间说说"
|
||||
command_aliases = ["发空间"]
|
||||
command_aliases: ClassVar[list[str]] = ["发空间"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@@ -4,6 +4,7 @@ MaiZone(麦麦空间)- 重构版
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system import BasePlugin, ComponentInfo, register_plugin
|
||||
@@ -33,10 +34,10 @@ class MaiZoneRefactoredPlugin(BasePlugin):
|
||||
plugin_description: str = "重构版的MaiZone插件"
|
||||
config_file_name: str = "config.toml"
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = []
|
||||
python_dependencies: list[str] = []
|
||||
dependencies: ClassVar[list[str] ] = []
|
||||
python_dependencies: ClassVar[list[str] ] = []
|
||||
|
||||
config_schema: dict = {
|
||||
config_schema: ClassVar[dict] = {
|
||||
"plugin": {"enable": ConfigField(type=bool, default=True, description="是否启用插件")},
|
||||
"models": {
|
||||
"text_model": ConfigField(type=str, default="maizone", description="生成文本的模型名称"),
|
||||
@@ -83,7 +84,7 @@ class MaiZoneRefactoredPlugin(BasePlugin):
|
||||
},
|
||||
}
|
||||
|
||||
permission_nodes: list[PermissionNodeField] = [
|
||||
permission_nodes: ClassVar[list[PermissionNodeField]] = [
|
||||
PermissionNodeField(node_name="send_feed", description="是否可以使用机器人发送QQ空间说说"),
|
||||
PermissionNodeField(node_name="read_feed", description="是否可以使用机器人读取QQ空间说说"),
|
||||
]
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system import BaseEventHandler
|
||||
from src.plugin_system.base.base_event import HandlerResult
|
||||
|
||||
from .src.send_handler import send_handler
|
||||
from .event_types import NapcatEvent
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from .src.send_handler import send_handler
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
@@ -14,7 +15,7 @@ class SetProfileHandler(BaseEventHandler):
|
||||
handler_description: str = "设置账号信息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.SET_PROFILE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.SET_PROFILE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -49,7 +50,7 @@ class GetOnlineClientsHandler(BaseEventHandler):
|
||||
handler_description: str = "获取当前账号在线客户端列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_ONLINE_CLIENTS]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_ONLINE_CLIENTS]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -72,7 +73,7 @@ class SetOnlineStatusHandler(BaseEventHandler):
|
||||
handler_description: str = "设置在线状态"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.SET_ONLINE_STATUS]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.SET_ONLINE_STATUS]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -103,7 +104,7 @@ class GetFriendsWithCategoryHandler(BaseEventHandler):
|
||||
handler_description: str = "获取好友分组列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_FRIENDS_WITH_CATEGORY]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_FRIENDS_WITH_CATEGORY]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
payload = {}
|
||||
@@ -120,7 +121,7 @@ class SetAvatarHandler(BaseEventHandler):
|
||||
handler_description: str = "设置头像"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.SET_AVATAR]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.SET_AVATAR]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -147,7 +148,7 @@ class SendLikeHandler(BaseEventHandler):
|
||||
handler_description: str = "点赞"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.SEND_LIKE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.SEND_LIKE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -176,7 +177,7 @@ class SetFriendAddRequestHandler(BaseEventHandler):
|
||||
handler_description: str = "处理好友请求"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.SET_FRIEND_ADD_REQUEST]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.SET_FRIEND_ADD_REQUEST]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -207,7 +208,7 @@ class SetSelfLongnickHandler(BaseEventHandler):
|
||||
handler_description: str = "设置个性签名"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.SET_SELF_LONGNICK]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.SET_SELF_LONGNICK]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -240,7 +241,7 @@ class GetLoginInfoHandler(BaseEventHandler):
|
||||
handler_description: str = "获取登录号信息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_LOGIN_INFO]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_LOGIN_INFO]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
payload = {}
|
||||
@@ -257,7 +258,7 @@ class GetRecentContactHandler(BaseEventHandler):
|
||||
handler_description: str = "最近消息列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_RECENT_CONTACT]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_RECENT_CONTACT]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -280,7 +281,7 @@ class GetStrangerInfoHandler(BaseEventHandler):
|
||||
handler_description: str = "获取(指定)账号信息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_STRANGER_INFO]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_STRANGER_INFO]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -307,7 +308,7 @@ class GetFriendListHandler(BaseEventHandler):
|
||||
handler_description: str = "获取好友列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_FRIEND_LIST]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_FRIEND_LIST]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -330,7 +331,7 @@ class GetProfileLikeHandler(BaseEventHandler):
|
||||
handler_description: str = "获取点赞列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_PROFILE_LIKE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_PROFILE_LIKE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -360,7 +361,7 @@ class DeleteFriendHandler(BaseEventHandler):
|
||||
handler_description: str = "删除好友"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.DELETE_FRIEND]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.DELETE_FRIEND]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -395,7 +396,7 @@ class GetUserStatusHandler(BaseEventHandler):
|
||||
handler_description: str = "获取(指定)用户状态"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_USER_STATUS]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_USER_STATUS]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -422,7 +423,7 @@ class GetStatusHandler(BaseEventHandler):
|
||||
handler_description: str = "获取状态"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_STATUS]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_STATUS]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
payload = {}
|
||||
@@ -439,7 +440,7 @@ class GetMiniAppArkHandler(BaseEventHandler):
|
||||
handler_description: str = "获取小程序卡片"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.GET_MINI_APP_ARK]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.GET_MINI_APP_ARK]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -486,7 +487,7 @@ class SetDiyOnlineStatusHandler(BaseEventHandler):
|
||||
handler_description: str = "设置自定义在线状态"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.ACCOUNT.SET_DIY_ONLINE_STATUS]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.ACCOUNT.SET_DIY_ONLINE_STATUS]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -518,7 +519,7 @@ class SendPrivateMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "发送私聊消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.SEND_PRIVATE_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.SEND_PRIVATE_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -547,7 +548,7 @@ class SendPokeHandler(BaseEventHandler):
|
||||
handler_description: str = "发送戳一戳"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.SEND_POKE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.SEND_POKE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -579,7 +580,7 @@ class DeleteMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "撤回消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.DELETE_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.DELETE_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -606,7 +607,7 @@ class GetGroupMsgHistoryHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群历史消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.GET_GROUP_MSG_HISTORY]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.GET_GROUP_MSG_HISTORY]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -644,7 +645,7 @@ class GetMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "获取消息详情"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.GET_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.GET_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -671,7 +672,7 @@ class GetForwardMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "获取合并转发消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.GET_FORWARD_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.GET_FORWARD_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -698,7 +699,7 @@ class SetMsgEmojiLikeHandler(BaseEventHandler):
|
||||
handler_description: str = "贴表情"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.SET_MSG_EMOJI_LIKE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.SET_MSG_EMOJI_LIKE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -729,7 +730,7 @@ class GetFriendMsgHistoryHandler(BaseEventHandler):
|
||||
handler_description: str = "获取好友历史消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.GET_FRIEND_MSG_HISTORY]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.GET_FRIEND_MSG_HISTORY]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -767,7 +768,7 @@ class FetchEmojiLikeHandler(BaseEventHandler):
|
||||
handler_description: str = "获取贴表情详情"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.FETCH_EMOJI_LIKE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.FETCH_EMOJI_LIKE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -805,7 +806,7 @@ class SendForwardMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "发送合并转发消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.SEND_FORWARD_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.SEND_FORWARD_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -849,7 +850,7 @@ class SendGroupAiRecordHandler(BaseEventHandler):
|
||||
handler_description: str = "发送群AI语音"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.MESSAGE.SEND_GROUP_AI_RECORD]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.MESSAGE.SEND_GROUP_AI_RECORD]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -881,7 +882,7 @@ class GetGroupInfoHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群信息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_INFO]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_INFO]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -908,7 +909,7 @@ class SetGroupAddOptionHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群添加选项"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_ADD_OPTION]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_ADD_OPTION]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -946,7 +947,7 @@ class SetGroupKickMembersHandler(BaseEventHandler):
|
||||
handler_description: str = "批量踢出群成员"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_KICK_MEMBERS]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_KICK_MEMBERS]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -977,7 +978,7 @@ class SetGroupRemarkHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群备注"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_REMARK]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_REMARK]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1006,7 +1007,7 @@ class SetGroupKickHandler(BaseEventHandler):
|
||||
handler_description: str = "群踢人"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_KICK]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_KICK]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1037,7 +1038,7 @@ class GetGroupSystemMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群系统消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_SYSTEM_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_SYSTEM_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1064,7 +1065,7 @@ class SetGroupBanHandler(BaseEventHandler):
|
||||
handler_description: str = "群禁言"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_BAN]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_BAN]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1095,7 +1096,7 @@ class GetEssenceMsgListHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群精华消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_ESSENCE_MSG_LIST]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_ESSENCE_MSG_LIST]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1122,7 +1123,7 @@ class SetGroupWholeBanHandler(BaseEventHandler):
|
||||
handler_description: str = "全体禁言"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_WHOLE_BAN]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_WHOLE_BAN]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1151,7 +1152,7 @@ class SetGroupPortraitHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群头像"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_PORTRAINT]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_PORTRAINT]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1180,7 +1181,7 @@ class SetGroupAdminHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群管理"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_ADMIN]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_ADMIN]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1211,7 +1212,7 @@ class SetGroupCardHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群成员名片"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_CARD]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_CARD]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1245,7 +1246,7 @@ class SetEssenceMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群精华消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_ESSENCE_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_ESSENCE_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1272,7 +1273,7 @@ class SetGroupNameHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群名"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_NAME]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_NAME]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1301,7 +1302,7 @@ class DeleteEssenceMsgHandler(BaseEventHandler):
|
||||
handler_description: str = "删除群精华消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.DELETE_ESSENCE_MSG]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.DELETE_ESSENCE_MSG]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1328,7 +1329,7 @@ class SetGroupLeaveHandler(BaseEventHandler):
|
||||
handler_description: str = "退群"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_LEAVE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_LEAVE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1355,7 +1356,7 @@ class SendGroupNoticeHandler(BaseEventHandler):
|
||||
handler_description: str = "发送群公告"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SEND_GROUP_NOTICE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SEND_GROUP_NOTICE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1389,7 +1390,7 @@ class SetGroupSpecialTitleHandler(BaseEventHandler):
|
||||
handler_description: str = "设置群头衔"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_SPECIAL_TITLE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_SPECIAL_TITLE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1423,7 +1424,7 @@ class GetGroupNoticeHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群公告"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_NOTICE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_NOTICE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1450,7 +1451,7 @@ class SetGroupAddRequestHandler(BaseEventHandler):
|
||||
handler_description: str = "处理加群请求"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_ADD_REQUEST]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_ADD_REQUEST]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1484,7 +1485,7 @@ class GetGroupListHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_LIST]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_LIST]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1507,7 +1508,7 @@ class DeleteGroupNoticeHandler(BaseEventHandler):
|
||||
handler_description: str = "删除群公告"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.DELETE_GROUP_NOTICE]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.DELETE_GROUP_NOTICE]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1536,7 +1537,7 @@ class GetGroupMemberInfoHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群成员信息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_MEMBER_INFO]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_MEMBER_INFO]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1567,7 +1568,7 @@ class GetGroupMemberListHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群成员列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_MEMBER_LIST]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_MEMBER_LIST]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1596,7 +1597,7 @@ class GetGroupHonorInfoHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群荣誉"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_HONOR_INFO]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_HONOR_INFO]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1628,7 +1629,7 @@ class GetGroupInfoExHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群信息ex"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_INFO_EX]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_INFO_EX]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1655,7 +1656,7 @@ class GetGroupAtAllRemainHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群 @全体成员 剩余次数"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_AT_ALL_REMAIN]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_AT_ALL_REMAIN]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1682,7 +1683,7 @@ class GetGroupShutListHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群禁言列表"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_SHUT_LIST]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_SHUT_LIST]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1709,7 +1710,7 @@ class GetGroupIgnoredNotifiesHandler(BaseEventHandler):
|
||||
handler_description: str = "获取群过滤系统消息"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.GET_GROUP_IGNORED_NOTIFIES]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.GET_GROUP_IGNORED_NOTIFIES]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
payload = {}
|
||||
@@ -1726,7 +1727,7 @@ class SetGroupSignHandler(BaseEventHandler):
|
||||
handler_description: str = "群打卡"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.GROUP.SET_GROUP_SIGN]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.GROUP.SET_GROUP_SIGN]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
@@ -1754,7 +1755,7 @@ class SetInputStatusHandler(BaseEventHandler):
|
||||
handler_description: str = "设置输入状态"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [NapcatEvent.PERSONAL.SET_INPUT_STATUS]
|
||||
init_subscribe: ClassVar[list] = [NapcatEvent.PERSONAL.SET_INPUT_STATUS]
|
||||
|
||||
async def execute(self, params: dict):
|
||||
raw = params.get("raw", {})
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
import asyncio
|
||||
import json
|
||||
import inspect
|
||||
import json
|
||||
from typing import ClassVar, List
|
||||
|
||||
import websockets as Server
|
||||
from . import event_types, CONSTS, event_handlers
|
||||
|
||||
from typing import List
|
||||
|
||||
from src.plugin_system import BasePlugin, BaseEventHandler, register_plugin, EventType, ConfigField
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
from src.plugin_system.apis import config_api
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system import BaseEventHandler, BasePlugin, ConfigField, EventType, register_plugin
|
||||
from src.plugin_system.apis import config_api
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
|
||||
from . import CONSTS, event_handlers, event_types
|
||||
from .src.message_chunker import chunker, reassembler
|
||||
from .src.mmc_com_layer import mmc_start_com, mmc_stop_com, router
|
||||
from .src.recv_handler.message_handler import message_handler
|
||||
from .src.recv_handler.message_sending import message_send_instance
|
||||
from .src.recv_handler.meta_event_handler import meta_event_handler
|
||||
from .src.recv_handler.notice_handler import notice_handler
|
||||
from .src.recv_handler.message_sending import message_send_instance
|
||||
from .src.response_pool import check_timeout_response, put_response
|
||||
from .src.send_handler import send_handler
|
||||
from .src.mmc_com_layer import mmc_start_com, router, mmc_stop_com
|
||||
from .src.response_pool import put_response, check_timeout_response
|
||||
from .src.websocket_manager import websocket_manager
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
@@ -219,7 +218,7 @@ class LauchNapcatAdapterHandler(BaseEventHandler):
|
||||
handler_description: str = "自动启动napcat adapter"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [EventType.ON_START]
|
||||
init_subscribe: ClassVar[list] = [EventType.ON_START]
|
||||
|
||||
async def execute(self, kwargs):
|
||||
# 启动消息重组器的清理任务
|
||||
@@ -267,7 +266,7 @@ class StopNapcatAdapterHandler(BaseEventHandler):
|
||||
handler_description: str = "关闭napcat adapter"
|
||||
weight: int = 100
|
||||
intercept_message: bool = False
|
||||
init_subscribe = [EventType.ON_STOP]
|
||||
init_subscribe: ClassVar[list] = [EventType.ON_STOP]
|
||||
|
||||
async def execute(self, kwargs):
|
||||
await graceful_shutdown()
|
||||
@@ -277,8 +276,8 @@ class StopNapcatAdapterHandler(BaseEventHandler):
|
||||
@register_plugin
|
||||
class NapcatAdapterPlugin(BasePlugin):
|
||||
plugin_name = CONSTS.PLUGIN_NAME
|
||||
dependencies: List[str] = [] # 插件依赖列表
|
||||
python_dependencies: List[str] = [] # Python包依赖列表
|
||||
dependencies: ClassVar[List[str]] = [] # 插件依赖列表
|
||||
python_dependencies: ClassVar[List[str]] = [] # Python包依赖列表
|
||||
config_file_name: str = "config.toml" # 配置文件名
|
||||
|
||||
@property
|
||||
@@ -291,10 +290,10 @@ class NapcatAdapterPlugin(BasePlugin):
|
||||
return False
|
||||
|
||||
# 配置节描述
|
||||
config_section_descriptions = {"plugin": "插件基本信息"}
|
||||
config_section_descriptions: ClassVar[dict] = {"plugin": "插件基本信息"}
|
||||
|
||||
# 配置Schema定义
|
||||
config_schema: dict = {
|
||||
config_schema: ClassVar[dict] = {
|
||||
"plugin": {
|
||||
"name": ConfigField(type=str, default="napcat_adapter_plugin", description="插件名称"),
|
||||
"version": ConfigField(type=str, default="1.1.0", description="插件版本"),
|
||||
@@ -389,7 +388,7 @@ class NapcatAdapterPlugin(BasePlugin):
|
||||
}
|
||||
|
||||
# 配置节描述
|
||||
config_section_descriptions = {
|
||||
config_section_descriptions: ClassVar[dict] = {
|
||||
"plugin": "插件基本信息",
|
||||
"inner": "内部配置信息(请勿修改)",
|
||||
"nickname": "昵称配置(目前未使用)",
|
||||
@@ -421,9 +420,11 @@ class NapcatAdapterPlugin(BasePlugin):
|
||||
components = []
|
||||
components.append((LauchNapcatAdapterHandler.get_handler_info(), LauchNapcatAdapterHandler))
|
||||
components.append((StopNapcatAdapterHandler.get_handler_info(), StopNapcatAdapterHandler))
|
||||
for handler in get_classes_in_module(event_handlers):
|
||||
if issubclass(handler, BaseEventHandler):
|
||||
components.append((handler.get_handler_info(), handler))
|
||||
components.extend(
|
||||
(handler.get_handler_info(), handler)
|
||||
for handler in get_classes_in_module(event_handlers)
|
||||
if issubclass(handler, BaseEventHandler)
|
||||
)
|
||||
return components
|
||||
|
||||
async def on_plugin_loaded(self):
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from enum import Enum
|
||||
import tomlkit
|
||||
import os
|
||||
from enum import Enum
|
||||
|
||||
import tomlkit
|
||||
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, List, Sequence
|
||||
from typing import List, Optional, Sequence
|
||||
|
||||
from sqlalchemy import Column, Integer, BigInteger, UniqueConstraint, select, Index
|
||||
from sqlalchemy import BigInteger, Column, Index, Integer, UniqueConstraint, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from src.common.database.sqlalchemy_models import Base, get_db_session
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
仅在 Ada -> MMC 方向进行切片,其他方向(MMC -> Ada,Ada <-> Napcat)不切片
|
||||
"""
|
||||
|
||||
import json
|
||||
import uuid
|
||||
import asyncio
|
||||
import json
|
||||
import time
|
||||
from typing import List, Dict, Any, Optional, Union
|
||||
from src.plugin_system.apis import config_api
|
||||
import uuid
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis import config_api
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from maim_message import Router, RouteConfig, TargetConfig
|
||||
from maim_message import RouteConfig, Router, TargetConfig
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.common.server import get_global_server
|
||||
|
||||
@@ -1,45 +1,43 @@
|
||||
from ...event_types import NapcatEvent
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
import base64
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import websockets as Server
|
||||
from maim_message import (
|
||||
BaseMessageInfo,
|
||||
FormatInfo,
|
||||
GroupInfo,
|
||||
MessageBase,
|
||||
Seg,
|
||||
TemplateInfo,
|
||||
UserInfo,
|
||||
)
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from ...CONSTS import PLUGIN_NAME
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
from src.plugin_system.apis import config_api
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
|
||||
from ...CONSTS import PLUGIN_NAME
|
||||
from ...event_types import NapcatEvent
|
||||
from ..response_pool import get_response
|
||||
from ..utils import (
|
||||
get_group_info,
|
||||
get_member_info,
|
||||
get_image_base64,
|
||||
get_member_info,
|
||||
get_message_detail,
|
||||
get_record_detail,
|
||||
get_self_info,
|
||||
get_message_detail,
|
||||
)
|
||||
from .qq_emoji_list import qq_face
|
||||
from .message_sending import message_send_instance
|
||||
from . import RealMessageType, MessageType, ACCEPT_FORMAT
|
||||
from ..video_handler import get_video_downloader
|
||||
from ..websocket_manager import websocket_manager
|
||||
from . import ACCEPT_FORMAT, MessageType, RealMessageType
|
||||
from .message_sending import message_send_instance
|
||||
from .qq_emoji_list import qq_face
|
||||
|
||||
import time
|
||||
import json
|
||||
import websockets as Server
|
||||
import base64
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple, Optional, Dict, Any
|
||||
import uuid
|
||||
|
||||
from maim_message import (
|
||||
UserInfo,
|
||||
GroupInfo,
|
||||
Seg,
|
||||
BaseMessageInfo,
|
||||
MessageBase,
|
||||
TemplateInfo,
|
||||
FormatInfo,
|
||||
)
|
||||
|
||||
|
||||
from ..response_pool import get_response
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
|
||||
class MessageHandler:
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import asyncio
|
||||
|
||||
from maim_message import MessageBase, Router
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from ..message_chunker import chunker
|
||||
from src.plugin_system.apis import config_api
|
||||
|
||||
from ..message_chunker import chunker
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
from maim_message import MessageBase, Router
|
||||
|
||||
|
||||
class MessageSending:
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
from src.plugin_system.apis import config_api
|
||||
import time
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis import config_api
|
||||
|
||||
from . import MetaEventType
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
|
||||
class MetaEventHandler:
|
||||
"""
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
import time
|
||||
import json
|
||||
import asyncio
|
||||
import json
|
||||
import time
|
||||
from typing import ClassVar, Optional, Tuple
|
||||
|
||||
import websockets as Server
|
||||
from typing import Tuple, Optional
|
||||
from maim_message import BaseMessageInfo, FormatInfo, GroupInfo, MessageBase, Seg, UserInfo
|
||||
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
from src.plugin_system.apis import config_api
|
||||
from ..database import BanUser, napcat_db, is_identical
|
||||
from . import NoticeType, ACCEPT_FORMAT
|
||||
from .message_sending import message_send_instance
|
||||
from .message_handler import message_handler
|
||||
from maim_message import FormatInfo, UserInfo, GroupInfo, Seg, BaseMessageInfo, MessageBase
|
||||
from ..websocket_manager import websocket_manager
|
||||
|
||||
from ...CONSTS import PLUGIN_NAME, QQ_FACE
|
||||
from ..database import BanUser, is_identical, napcat_db
|
||||
from ..utils import (
|
||||
get_group_info,
|
||||
get_member_info,
|
||||
@@ -23,16 +18,20 @@ from ..utils import (
|
||||
get_stranger_info,
|
||||
read_ban_list,
|
||||
)
|
||||
from ..websocket_manager import websocket_manager
|
||||
from . import ACCEPT_FORMAT, NoticeType
|
||||
from .message_handler import message_handler
|
||||
from .message_sending import message_send_instance
|
||||
|
||||
from ...CONSTS import PLUGIN_NAME, QQ_FACE
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
notice_queue: asyncio.Queue[MessageBase] = asyncio.Queue(maxsize=100)
|
||||
unsuccessful_notice_queue: asyncio.Queue[MessageBase] = asyncio.Queue(maxsize=3)
|
||||
|
||||
|
||||
class NoticeHandler:
|
||||
banned_list: list[BanUser] = [] # 当前仍在禁言中的用户列表
|
||||
lifted_list: list[BanUser] = [] # 已经自然解除禁言
|
||||
banned_list: ClassVar[list[BanUser]] = [] # 当前仍在禁言中的用户列表
|
||||
lifted_list: ClassVar[list[BanUser]] = [] # 已经自然解除禁言
|
||||
|
||||
def __init__(self):
|
||||
self.server_connection: Server.ServerConnection | None = None
|
||||
@@ -131,6 +130,7 @@ class NoticeHandler:
|
||||
logger.warning("戳一戳消息被禁用,取消戳一戳处理")
|
||||
case NoticeType.Notify.input_status:
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
|
||||
from ...event_types import NapcatEvent
|
||||
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED.FRIEND_INPUT, permission_group=PLUGIN_NAME)
|
||||
@@ -357,6 +357,7 @@ class NoticeHandler:
|
||||
logger.debug("无法获取表情回复对方的用户昵称")
|
||||
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
|
||||
from ...event_types import NapcatEvent
|
||||
|
||||
target_message = await event_manager.trigger_event(NapcatEvent.MESSAGE.GET_MSG,message_id=raw_message.get("message_id",""))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import time
|
||||
from typing import Dict
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis import config_api
|
||||
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
import websockets as Server
|
||||
import time
|
||||
import uuid
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
import websockets as Server
|
||||
from maim_message import (
|
||||
UserInfo,
|
||||
GroupInfo,
|
||||
Seg,
|
||||
BaseMessageInfo,
|
||||
GroupInfo,
|
||||
MessageBase,
|
||||
Seg,
|
||||
UserInfo,
|
||||
)
|
||||
from typing import Dict, Any, Tuple, Optional
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis import config_api
|
||||
|
||||
from . import CommandType
|
||||
from .recv_handler.message_sending import message_send_instance
|
||||
from .response_pool import get_response
|
||||
from src.common.logger import get_logger
|
||||
from .utils import convert_image_to_gif, get_image_format
|
||||
from .websocket_manager import websocket_manager
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
from .utils import get_image_format, convert_image_to_gif
|
||||
from .recv_handler.message_sending import message_send_instance
|
||||
from .websocket_manager import websocket_manager
|
||||
|
||||
|
||||
class SendHandler:
|
||||
@@ -547,7 +549,7 @@ class SendHandler:
|
||||
set_like = bool(args["set"])
|
||||
except (KeyError, ValueError) as e:
|
||||
logger.error(f"处理表情回应命令时发生错误: {e}, 原始参数: {args}")
|
||||
raise ValueError(f"缺少必需参数或参数类型错误: {e}")
|
||||
raise ValueError(f"缺少必需参数或参数类型错误: {e}") from e
|
||||
|
||||
return (
|
||||
CommandType.SET_EMOJI_LIKE.value,
|
||||
@@ -567,8 +569,8 @@ class SendHandler:
|
||||
try:
|
||||
user_id: int = int(args["qq_id"])
|
||||
times: int = int(args["times"])
|
||||
except (KeyError, ValueError):
|
||||
raise ValueError("缺少必需参数: qq_id 或 times")
|
||||
except (KeyError, ValueError) as e:
|
||||
raise ValueError("缺少必需参数: qq_id 或 times") from e
|
||||
|
||||
return (
|
||||
CommandType.SEND_LIKE.value,
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import websockets as Server
|
||||
import json
|
||||
import base64
|
||||
import uuid
|
||||
import urllib3
|
||||
import ssl
|
||||
import io
|
||||
import json
|
||||
import ssl
|
||||
import uuid
|
||||
from typing import List, Optional, Tuple, Union
|
||||
|
||||
import urllib3
|
||||
import websockets as Server
|
||||
from PIL import Image
|
||||
|
||||
from .database import BanUser, napcat_db
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("napcat_adapter")
|
||||
from .database import BanUser, napcat_db
|
||||
from .response_pool import get_response
|
||||
|
||||
from PIL import Image
|
||||
from typing import Union, List, Tuple, Optional
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
|
||||
class SSLAdapter(urllib3.PoolManager):
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
用于从QQ消息中下载视频并转发给Bot进行分析
|
||||
"""
|
||||
|
||||
import aiohttp
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import aiohttp
|
||||
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("video_handler")
|
||||
@@ -34,20 +36,20 @@ class VideoDownloader:
|
||||
if any(keyword in url_lower for keyword in video_keywords):
|
||||
return True
|
||||
|
||||
# 检查文件扩展名(传统方法)
|
||||
# 检查文件扩展名(传统方法)
|
||||
path = Path(url.split("?")[0]) # 移除查询参数
|
||||
if path.suffix.lower() in self.supported_formats:
|
||||
return True
|
||||
|
||||
# 对于QQ等特殊平台,URL可能没有扩展名
|
||||
# 我们允许这些URL通过,稍后通过HTTP头Content-Type验证
|
||||
# 对于QQ等特殊平台,URL可能没有扩展名
|
||||
# 我们允许这些URL通过,稍后通过HTTP头Content-Type验证
|
||||
qq_domains = ["qpic.cn", "gtimg.cn", "qq.com", "tencent.com"]
|
||||
if any(domain in url_lower for domain in qq_domains):
|
||||
return True
|
||||
|
||||
return False
|
||||
except:
|
||||
# 如果解析失败,默认允许尝试下载(稍后验证)
|
||||
except Exception:
|
||||
# 如果解析失败,默认允许尝试下载(稍后验证)
|
||||
return True
|
||||
|
||||
def check_file_size(self, content_length: Optional[str]) -> bool:
|
||||
@@ -59,7 +61,7 @@ class VideoDownloader:
|
||||
size_bytes = int(content_length)
|
||||
size_mb = size_bytes / (1024 * 1024)
|
||||
return size_mb <= self.max_size_mb
|
||||
except:
|
||||
except Exception:
|
||||
return True
|
||||
|
||||
async def download_video(self, url: str, filename: Optional[str] = None) -> Dict[str, Any]:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import asyncio
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
import websockets as Server
|
||||
from typing import Optional, Callable, Any
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis import config_api
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import ClassVar
|
||||
|
||||
from src.plugin_system.apis.logging_api import get_logger
|
||||
from src.plugin_system.apis.permission_api import permission_api
|
||||
@@ -29,7 +30,7 @@ class PermissionCommand(PlusCommand):
|
||||
|
||||
command_name = "permission"
|
||||
command_description = "权限管理命令,支持授权、撤销、查询等功能"
|
||||
command_aliases = ["perm", "权限"]
|
||||
command_aliases: ClassVar[list[str]] = ["perm", "权限"]
|
||||
priority = 10
|
||||
chat_type_allow = ChatType.ALL
|
||||
intercept_message = True
|
||||
@@ -37,7 +38,7 @@ class PermissionCommand(PlusCommand):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
permission_nodes: list[PermissionNodeField] = [
|
||||
permission_nodes: ClassVar[list[PermissionNodeField]] = [
|
||||
PermissionNodeField(
|
||||
node_name="manage",
|
||||
description="权限管理:可以授权和撤销其他用户的权限",
|
||||
@@ -382,10 +383,10 @@ class PermissionCommand(PlusCommand):
|
||||
class PermissionManagerPlugin(BasePlugin):
|
||||
plugin_name: str = "permission_manager_plugin"
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = []
|
||||
python_dependencies: list[str] = []
|
||||
dependencies: ClassVar[list[str]] = []
|
||||
python_dependencies: ClassVar[list[str]] = []
|
||||
config_file_name: str = "config.toml"
|
||||
config_schema: dict = {
|
||||
config_schema: ClassVar[dict] = {
|
||||
"plugin": {
|
||||
"enabled": ConfigField(bool, default=True, description="是否启用插件"),
|
||||
"config_version": ConfigField(type=str, default="1.1.0", description="配置文件版本"),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
from typing import ClassVar
|
||||
|
||||
from src.plugin_system import (
|
||||
BasePlugin,
|
||||
@@ -21,7 +22,7 @@ class ManagementCommand(PlusCommand):
|
||||
|
||||
command_name = "pm"
|
||||
command_description = "插件管理命令,支持插件和组件的管理操作"
|
||||
command_aliases = ["pluginmanage", "插件管理"]
|
||||
command_aliases: ClassVar[list[str]] = ["pluginmanage", "插件管理"]
|
||||
priority = 10
|
||||
chat_type_allow = ChatType.ALL
|
||||
intercept_message = True
|
||||
@@ -273,6 +274,7 @@ class ManagementCommand(PlusCommand):
|
||||
def _fetch_all_registered_components() -> list[ComponentInfo]:
|
||||
all_plugin_info = component_manage_api.get_all_plugin_info()
|
||||
if not all_plugin_info:
|
||||
|
||||
return []
|
||||
|
||||
components_info: list[ComponentInfo] = []
|
||||
@@ -486,10 +488,10 @@ class ManagementCommand(PlusCommand):
|
||||
class PluginManagementPlugin(BasePlugin):
|
||||
plugin_name: str = "plugin_management_plugin"
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = []
|
||||
python_dependencies: list[str] = []
|
||||
dependencies: ClassVar[list[str]] = []
|
||||
python_dependencies: ClassVar[list[str]] = []
|
||||
config_file_name: str = "config.toml"
|
||||
config_schema: dict = {
|
||||
config_schema: ClassVar[dict] = {
|
||||
"plugin": {
|
||||
"enabled": ConfigField(bool, default=False, description="是否启用插件"),
|
||||
"config_version": ConfigField(type=str, default="1.1.0", description="配置文件版本"),
|
||||
|
||||
@@ -152,12 +152,12 @@ class PokeAction(BaseAction):
|
||||
parallel_action = True
|
||||
|
||||
# === 功能描述(必须填写)===
|
||||
action_parameters = {
|
||||
action_parameters: ClassVar[dict] = {
|
||||
"user_name": "需要戳一戳的用户的名字 (可选)",
|
||||
"user_id": "需要戳一戳的用户的ID (可选,优先级更高)",
|
||||
"times": "需要戳一戳的次数 (默认为 1)",
|
||||
}
|
||||
action_require = ["当需要戳某个用户时使用", "当你想提醒特定用户时使用"]
|
||||
action_require: ClassVar[list] = ["当需要戳某个用户时使用", "当你想提醒特定用户时使用"]
|
||||
llm_judge_prompt = """
|
||||
判定是否需要使用戳一戳动作的条件:
|
||||
1. **互动时机**: 这是一个有趣的互动方式,可以在想提醒某人,或者单纯想开个玩笑时使用。
|
||||
@@ -167,7 +167,7 @@ class PokeAction(BaseAction):
|
||||
|
||||
请根据上述规则,回答“是”或“否”。
|
||||
"""
|
||||
associated_types = ["text"]
|
||||
associated_types: ClassVar[list[str]] = ["text"]
|
||||
|
||||
async def execute(self) -> tuple[bool, str]:
|
||||
"""执行戳一戳的动作"""
|
||||
@@ -225,10 +225,10 @@ class SetEmojiLikeAction(BaseAction):
|
||||
parallel_action = True
|
||||
|
||||
# === 功能描述(必须填写)===
|
||||
action_parameters = {
|
||||
action_parameters: ClassVar[dict] = {
|
||||
"set": "是否设置回应 (True/False)",
|
||||
}
|
||||
action_require = [
|
||||
action_require: ClassVar[list] = [
|
||||
"当需要对一个已存在消息进行‘贴表情’回应时使用",
|
||||
"这是一个对旧消息的操作,而不是发送新消息",
|
||||
]
|
||||
@@ -240,10 +240,10 @@ class SetEmojiLikeAction(BaseAction):
|
||||
|
||||
请回答"是"或"否"。
|
||||
"""
|
||||
associated_types = ["text"]
|
||||
associated_types: ClassVar[list[str]] = ["text"]
|
||||
|
||||
# 重新启用完整的表情库
|
||||
emoji_options = []
|
||||
emoji_options: ClassVar[list] = []
|
||||
for name in qq_face.values():
|
||||
match = re.search(r"\[表情:(.+?)\]", name)
|
||||
if match:
|
||||
@@ -359,14 +359,14 @@ class RemindAction(BaseAction):
|
||||
action_name = "set_reminder"
|
||||
action_description = "根据用户的对话内容,智能地设置一个未来的提醒事项。"
|
||||
activation_type = ActionActivationType.KEYWORD
|
||||
activation_keywords = ["提醒", "叫我", "记得", "别忘了"]
|
||||
activation_keywords: ClassVar[list[str]] = ["提醒", "叫我", "记得", "别忘了"]
|
||||
chat_type_allow = ChatType.ALL
|
||||
parallel_action = True
|
||||
|
||||
# === LLM 判断与参数提取 ===
|
||||
llm_judge_prompt = ""
|
||||
action_parameters = {}
|
||||
action_require = [
|
||||
action_parameters: ClassVar[dict] = {}
|
||||
action_require: ClassVar[list] = [
|
||||
"当用户请求在未来的某个时间点提醒他/她或别人某件事时使用",
|
||||
"适用于包含明确时间信息和事件描述的对话",
|
||||
"例如:'10分钟后提醒我收快递'、'明天早上九点喊一下李四参加晨会'",
|
||||
@@ -545,12 +545,12 @@ class SetEmojiLikePlugin(BasePlugin):
|
||||
# 插件基本信息
|
||||
plugin_name: str = "social_toolkit_plugin" # 内部标识符
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = [] # 插件依赖列表
|
||||
python_dependencies: list[str] = [] # Python包依赖列表,现在使用内置API
|
||||
dependencies: ClassVar[list[str]] = [] # 插件依赖列表
|
||||
python_dependencies: ClassVar[list[str]] = [] # Python包依赖列表,现在使用内置API
|
||||
config_file_name: str = "config.toml" # 配置文件名
|
||||
|
||||
# 配置节描述
|
||||
config_section_descriptions = {"plugin": "插件基本信息", "components": "插件组件"}
|
||||
config_section_descriptions: ClassVar[dict] = {"plugin": "插件基本信息", "components": "插件组件"}
|
||||
|
||||
# 配置Schema定义
|
||||
config_schema: ClassVar[dict] = {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
from typing import ClassVar
|
||||
|
||||
import whisper
|
||||
|
||||
@@ -19,7 +20,7 @@ class LocalASRTool(BaseTool):
|
||||
"""
|
||||
tool_name = "local_asr"
|
||||
tool_description = "将本地音频文件路径转换为文字。"
|
||||
tool_parameters = [
|
||||
tool_parameters: ClassVar[list] = [
|
||||
{"name": "audio_path", "type": "string", "description": "需要识别的音频文件路径", "required": True}
|
||||
]
|
||||
|
||||
@@ -50,6 +51,7 @@ class LocalASRTool(BaseTool):
|
||||
async def execute(self, function_args: dict) -> str:
|
||||
audio_path = function_args.get("audio_path")
|
||||
if not audio_path:
|
||||
|
||||
return "错误:缺少 audio_path 参数。"
|
||||
|
||||
global _whisper_model
|
||||
@@ -78,7 +80,7 @@ class LocalASRTool(BaseTool):
|
||||
class STTWhisperPlugin(BasePlugin):
|
||||
plugin_name = "stt_whisper_plugin"
|
||||
config_file_name = "config.toml"
|
||||
python_dependencies = ["openai-whisper"]
|
||||
python_dependencies: ClassVar[list[str]] = ["openai-whisper"]
|
||||
|
||||
async def on_plugin_loaded(self):
|
||||
"""
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.apis.plugin_register_api import register_plugin
|
||||
from src.plugin_system.base.base_action import ActionActivationType, BaseAction, ChatMode
|
||||
@@ -22,16 +24,16 @@ class TTSAction(BaseAction):
|
||||
action_description = "将文本转换为语音进行播放,适用于需要语音输出的场景"
|
||||
|
||||
# 关键词配置 - Normal模式下使用关键词触发
|
||||
activation_keywords = ["语音", "tts", "播报", "读出来", "语音播放", "听", "朗读"]
|
||||
activation_keywords: ClassVar[list[str]] = ["语音", "tts", "播报", "读出来", "语音播放", "听", "朗读"]
|
||||
keyword_case_sensitive = False
|
||||
|
||||
# 动作参数定义
|
||||
action_parameters = {
|
||||
action_parameters: ClassVar[dict] = {
|
||||
"text": "需要转换为语音的文本内容,必填,内容应当适合语音播报,语句流畅、清晰",
|
||||
}
|
||||
|
||||
# 动作使用场景
|
||||
action_require = [
|
||||
action_require: ClassVar[list] = [
|
||||
"当需要发送语音信息时使用",
|
||||
"当用户要求你说话时使用",
|
||||
"当用户要求听你声音时使用",
|
||||
@@ -41,7 +43,7 @@ class TTSAction(BaseAction):
|
||||
]
|
||||
|
||||
# 关联类型
|
||||
associated_types = ["tts_text"]
|
||||
associated_types: ClassVar[list[str]] = ["tts_text"]
|
||||
|
||||
async def execute(self) -> tuple[bool, str]:
|
||||
"""处理TTS文本转语音动作"""
|
||||
@@ -111,19 +113,19 @@ class TTSPlugin(BasePlugin):
|
||||
# 插件基本信息
|
||||
plugin_name: str = "tts_plugin" # 内部标识符
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = [] # 插件依赖列表
|
||||
python_dependencies: list[str] = [] # Python包依赖列表
|
||||
dependencies: ClassVar[list[str]] = [] # 插件依赖列表
|
||||
python_dependencies: ClassVar[list[str]] = [] # Python包依赖列表
|
||||
config_file_name: str = "config.toml"
|
||||
|
||||
# 配置节描述
|
||||
config_section_descriptions = {
|
||||
config_section_descriptions: ClassVar[dict] = {
|
||||
"plugin": "插件基本信息配置",
|
||||
"components": "组件启用控制",
|
||||
"logging": "日志记录相关配置",
|
||||
}
|
||||
|
||||
# 配置Schema定义
|
||||
config_schema: dict = {
|
||||
config_schema: ClassVar[dict] = {
|
||||
"plugin": {
|
||||
"name": ConfigField(type=str, default="tts_plugin", description="插件名称", required=True),
|
||||
"version": ConfigField(type=str, default="0.1.0", description="插件版本号"),
|
||||
|
||||
@@ -3,6 +3,7 @@ TTS 语音合成 Action
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import ClassVar
|
||||
|
||||
import toml
|
||||
|
||||
@@ -32,6 +33,7 @@ def _get_available_styles() -> list[str]:
|
||||
|
||||
styles_config = config.get("tts_styles", [])
|
||||
if not isinstance(styles_config, list):
|
||||
|
||||
return ["default"]
|
||||
|
||||
# 使用显式循环和类型检查来提取 style_name,以确保 Pylance 类型检查通过
|
||||
@@ -65,7 +67,7 @@ class TTSVoiceAction(BaseAction):
|
||||
mode_enable = ChatMode.ALL
|
||||
parallel_action = False
|
||||
|
||||
action_parameters = {
|
||||
action_parameters: ClassVar[dict] = {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "需要转换为语音并发送的完整、自然、适合口语的文本内容。",
|
||||
@@ -97,7 +99,7 @@ class TTSVoiceAction(BaseAction):
|
||||
}
|
||||
}
|
||||
|
||||
action_require = [
|
||||
action_require: ClassVar[list] = [
|
||||
"在调用此动作时,你必须在 'text' 参数中提供要合成语音的完整回复内容。这是强制性的。",
|
||||
"当用户明确请求使用语音进行回复时,例如‘发个语音听听’、‘用语音说’等。",
|
||||
"当对话内容适合用语音表达,例如讲故事、念诗、撒嬌或进行角色扮演时。",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""
|
||||
TTS 语音合成命令
|
||||
"""
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.base.command_args import CommandArgs
|
||||
from src.plugin_system.base.plus_command import PlusCommand
|
||||
@@ -18,7 +20,7 @@ class TTSVoiceCommand(PlusCommand):
|
||||
|
||||
command_name: str = "tts"
|
||||
command_description: str = "使用GPT-SoVITS将文本转换为语音并发送"
|
||||
command_aliases = ["语音合成", "说"]
|
||||
command_aliases: ClassVar[list[str]] = ["语音合成", "说"]
|
||||
command_usage = "/tts <要说的文本> [风格]"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
TTS Voice 插件 - 重构版
|
||||
"""
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
import toml
|
||||
|
||||
@@ -29,15 +29,15 @@ class TTSVoicePlugin(BasePlugin):
|
||||
plugin_version = "3.1.2"
|
||||
plugin_author = "Kilo Code & 靚仔"
|
||||
config_file_name = "config.toml"
|
||||
dependencies = []
|
||||
dependencies: ClassVar[list[str]] = []
|
||||
|
||||
permission_nodes: list[PermissionNodeField] = [
|
||||
permission_nodes: ClassVar[list[PermissionNodeField]] = [
|
||||
PermissionNodeField(node_name="command.use", description="是否可以使用 /tts 命令"),
|
||||
]
|
||||
|
||||
config_schema = {}
|
||||
config_schema: ClassVar[dict] = {}
|
||||
|
||||
config_section_descriptions = {
|
||||
config_section_descriptions: ClassVar[dict] = {
|
||||
"plugin": "插件基本配置",
|
||||
"components": "组件启用控制",
|
||||
"tts": "TTS语音合成基础配置",
|
||||
|
||||
@@ -67,10 +67,14 @@ class TTSService:
|
||||
logger.warning("TTS 'default' style is missing 'refer_wav_path'.")
|
||||
|
||||
for style_cfg in tts_styles_config:
|
||||
if not isinstance(style_cfg, dict): continue
|
||||
if not isinstance(style_cfg, dict):
|
||||
|
||||
continue
|
||||
|
||||
style_name = style_cfg.get("style_name")
|
||||
if not style_name: continue
|
||||
if not style_name:
|
||||
|
||||
continue
|
||||
|
||||
styles[style_name] = {
|
||||
"url": global_server,
|
||||
@@ -158,7 +162,9 @@ class TTSService:
|
||||
|
||||
# --- 步骤一:像稳定版一样,先切换模型 ---
|
||||
async def switch_model_weights(weights_path: str | None, weight_type: str):
|
||||
if not weights_path: return
|
||||
if not weights_path:
|
||||
|
||||
return
|
||||
api_endpoint = f"/set_{weight_type}_weights"
|
||||
switch_url = f"{base_url}{api_endpoint}"
|
||||
try:
|
||||
@@ -220,6 +226,7 @@ class TTSService:
|
||||
try:
|
||||
effects_config = self.get_config("spatial_effects", {})
|
||||
if not effects_config.get("enabled", False):
|
||||
|
||||
return audio_data
|
||||
|
||||
# 获取插件目录和IR文件路径
|
||||
@@ -251,6 +258,8 @@ class TTSService:
|
||||
logger.warning(f"卷积混响已启用,但IR文件不存在 ({ir_path}),跳过该效果。")
|
||||
|
||||
if not effects:
|
||||
|
||||
|
||||
return audio_data
|
||||
|
||||
# 将原始音频数据加载到内存中的 AudioFile 对象
|
||||
@@ -293,7 +302,9 @@ class TTSService:
|
||||
|
||||
server_config = self.tts_styles[style]
|
||||
clean_text = self._clean_text_for_tts(text)
|
||||
if not clean_text: return None
|
||||
if not clean_text:
|
||||
|
||||
return None
|
||||
|
||||
# 语言决策流程:
|
||||
# 1. 优先使用决策模型直接指定的 language_hint (最高优先级)
|
||||
|
||||
@@ -42,6 +42,7 @@ class TavilySearchEngine(BaseSearchEngine):
|
||||
async def search(self, args: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
"""执行Tavily搜索"""
|
||||
if not self.is_available():
|
||||
|
||||
return []
|
||||
|
||||
query = args["query"]
|
||||
@@ -76,15 +77,15 @@ class TavilySearchEngine(BaseSearchEngine):
|
||||
|
||||
results = []
|
||||
if search_response and "results" in search_response:
|
||||
for res in search_response["results"]:
|
||||
results.append(
|
||||
{
|
||||
"title": res.get("title", "无标题"),
|
||||
"url": res.get("url", ""),
|
||||
"snippet": res.get("content", "")[:300] + "..." if res.get("content") else "无摘要",
|
||||
"provider": "Tavily",
|
||||
}
|
||||
)
|
||||
results.extend(
|
||||
{
|
||||
"title": res.get("title", "无标题"),
|
||||
"url": res.get("url", ""),
|
||||
"snippet": res.get("content", "")[:300] + "..." if res.get("content") else "无摘要",
|
||||
"provider": "Tavily",
|
||||
}
|
||||
for res in search_response["results"]
|
||||
)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ Web Search Tool Plugin
|
||||
一个功能强大的网络搜索和URL解析插件,支持多种搜索引擎和解析策略。
|
||||
"""
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system import BasePlugin, ComponentInfo, ConfigField, register_plugin
|
||||
from src.plugin_system.apis import config_api
|
||||
@@ -30,7 +32,7 @@ class WEBSEARCHPLUGIN(BasePlugin):
|
||||
# 插件基本信息
|
||||
plugin_name: str = "web_search_tool" # 内部标识符
|
||||
enable_plugin: bool = True
|
||||
dependencies: list[str] = [] # 插件依赖列表
|
||||
dependencies: ClassVar[list[str]] = [] # 插件依赖列表
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""初始化插件,立即加载所有搜索引擎"""
|
||||
@@ -77,11 +79,11 @@ class WEBSEARCHPLUGIN(BasePlugin):
|
||||
config_file_name: str = "config.toml" # 配置文件名
|
||||
|
||||
# 配置节描述
|
||||
config_section_descriptions = {"plugin": "插件基本信息", "proxy": "链接本地解析代理配置"}
|
||||
config_section_descriptions: ClassVar[dict] = {"plugin": "插件基本信息", "proxy": "链接本地解析代理配置"}
|
||||
|
||||
# 配置Schema定义
|
||||
# 注意:EXA配置和组件设置已迁移到主配置文件(bot_config.toml)的[exa]和[web_search]部分
|
||||
config_schema: dict = {
|
||||
config_schema: ClassVar[dict] = {
|
||||
"plugin": {
|
||||
"name": ConfigField(type=str, default="WEB_SEARCH_PLUGIN", description="插件名称"),
|
||||
"version": ConfigField(type=str, default="1.0.0", description="插件版本"),
|
||||
|
||||
@@ -4,7 +4,7 @@ URL parser tool implementation
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
import httpx
|
||||
from bs4 import BeautifulSoup
|
||||
@@ -30,7 +30,7 @@ class URLParserTool(BaseTool):
|
||||
name: str = "parse_url"
|
||||
description: str = "当需要理解一个或多个特定网页链接的内容时,使用此工具。例如:'这些网页讲了什么?[https://example.com, https://example2.com]' 或 '帮我总结一下这些文章'"
|
||||
available_for_llm: bool = True
|
||||
parameters = [
|
||||
parameters: ClassVar[list] = [
|
||||
("urls", ToolParamType.STRING, "要理解的网站", True, None),
|
||||
]
|
||||
|
||||
@@ -93,6 +93,8 @@ class URLParserTool(BaseTool):
|
||||
text = soup.get_text(strip=True)
|
||||
|
||||
if not text:
|
||||
|
||||
|
||||
return {"error": "无法从页面提取有效文本内容。"}
|
||||
|
||||
summary_prompt = f"请根据以下网页内容,生成一段不超过300字的中文摘要,保留核心信息和关键点:\n\n---\n\n标题: {title}\n\n内容:\n{text[:4000]}\n\n---\n\n摘要:"
|
||||
@@ -144,16 +146,19 @@ class URLParserTool(BaseTool):
|
||||
|
||||
urls_input = function_args.get("urls")
|
||||
if not urls_input:
|
||||
|
||||
return {"error": "URL列表不能为空。"}
|
||||
|
||||
# 处理URL输入,确保是列表格式
|
||||
urls = parse_urls_from_input(urls_input)
|
||||
if not urls:
|
||||
|
||||
return {"error": "提供的字符串中未找到有效的URL。"}
|
||||
|
||||
# 验证URL格式
|
||||
valid_urls = validate_urls(urls)
|
||||
if not valid_urls:
|
||||
|
||||
return {"error": "未找到有效的URL。"}
|
||||
|
||||
urls = valid_urls
|
||||
@@ -226,6 +231,8 @@ class URLParserTool(BaseTool):
|
||||
successful_results.append(res)
|
||||
|
||||
if not successful_results:
|
||||
|
||||
|
||||
return {"error": "无法从所有给定的URL获取内容。", "details": error_messages}
|
||||
|
||||
formatted_content = format_url_parse_results(successful_results)
|
||||
|
||||
@@ -3,7 +3,7 @@ Web search tool implementation
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from src.common.cache_manager import tool_cache
|
||||
from src.common.logger import get_logger
|
||||
@@ -31,7 +31,7 @@ class WebSurfingTool(BaseTool):
|
||||
"用于执行网络搜索。当用户明确要求搜索,或者需要获取关于公司、产品、事件的最新信息、新闻或动态时,必须使用此工具"
|
||||
)
|
||||
available_for_llm: bool = True
|
||||
parameters = [
|
||||
parameters: ClassVar[list] = [
|
||||
("query", ToolParamType.STRING, "要搜索的关键词或问题。", True, None),
|
||||
("num_results", ToolParamType.INTEGER, "期望每个搜索引擎返回的搜索结果数量,默认为5。", False, None),
|
||||
(
|
||||
@@ -58,6 +58,7 @@ class WebSurfingTool(BaseTool):
|
||||
async def execute(self, function_args: dict[str, Any]) -> dict[str, Any]:
|
||||
query = function_args.get("query")
|
||||
if not query:
|
||||
|
||||
return {"error": "搜索查询不能为空。"}
|
||||
|
||||
# 获取当前文件路径用于缓存键
|
||||
@@ -105,6 +106,8 @@ class WebSurfingTool(BaseTool):
|
||||
search_tasks.append(engine.search(custom_args))
|
||||
|
||||
if not search_tasks:
|
||||
|
||||
|
||||
return {"error": "没有可用的搜索引擎。"}
|
||||
|
||||
try:
|
||||
@@ -137,6 +140,7 @@ class WebSurfingTool(BaseTool):
|
||||
for engine_name in enabled_engines:
|
||||
engine = self.engines.get(engine_name)
|
||||
if not engine or not engine.is_available():
|
||||
|
||||
continue
|
||||
|
||||
try:
|
||||
@@ -163,6 +167,7 @@ class WebSurfingTool(BaseTool):
|
||||
for engine_name in enabled_engines:
|
||||
engine = self.engines.get(engine_name)
|
||||
if not engine or not engine.is_available():
|
||||
|
||||
continue
|
||||
|
||||
try:
|
||||
|
||||
@@ -33,10 +33,10 @@ class APIKeyManager(Generic[T]):
|
||||
|
||||
if api_keys:
|
||||
# 过滤有效的API密钥,排除None、空字符串、"None"字符串等
|
||||
valid_keys = []
|
||||
for key in api_keys:
|
||||
if isinstance(key, str) and key.strip() and key.strip().lower() not in ("none", "null", ""):
|
||||
valid_keys.append(key.strip())
|
||||
valid_keys = [
|
||||
key.strip() for key in api_keys
|
||||
if isinstance(key, str) and key.strip() and key.strip().lower() not in ("none", "null", "")
|
||||
]
|
||||
|
||||
if valid_keys:
|
||||
try:
|
||||
@@ -59,6 +59,7 @@ class APIKeyManager(Generic[T]):
|
||||
def get_next_client(self) -> T | None:
|
||||
"""获取下一个客户端(轮询)"""
|
||||
if not self.is_available():
|
||||
|
||||
return None
|
||||
return next(self.client_cycle)
|
||||
|
||||
|
||||
@@ -32,8 +32,4 @@ def validate_urls(urls: list[str]) -> list[str]:
|
||||
"""
|
||||
验证URL格式,返回有效的URL列表
|
||||
"""
|
||||
valid_urls = []
|
||||
for url in urls:
|
||||
if url.startswith(("http://", "https://")):
|
||||
valid_urls.append(url)
|
||||
return valid_urls
|
||||
return [url for url in urls if url.startswith(("http://", "https://"))]
|
||||
|
||||
Reference in New Issue
Block a user