perf(methods): 通过移除不必要的 self 参数优化方法签名

在包括 chat、plugin_system、schedule 和 mais4u 在内的多个模块中,消除冗余的实例引用。此次改动将无需访问实例状态的实用函数转换为静态方法,从而提升了内存效率,并使方法依赖关系更加清晰。
This commit is contained in:
雅诺狐
2025-09-20 10:55:06 +08:00
parent 0cc4f5bb27
commit 898208f425
111 changed files with 643 additions and 467 deletions

View File

@@ -119,10 +119,12 @@ class ContentService:
logger.error(f"生成说说内容时发生异常: {e}")
return ""
async def generate_comment(self, content: str, target_name: str, rt_con: str = "", images: list = []) -> str:
async def generate_comment(self, content: str, target_name: str, rt_con: str = "", images=None) -> str:
"""
针对一条具体的说说内容生成评论。
"""
if images is None:
images = []
for i in range(3): # 重试3次
try:
chat_manager = get_chat_manager()
@@ -180,7 +182,8 @@ class ContentService:
return ""
return ""
async def generate_comment_reply(self, story_content: str, comment_content: str, commenter_name: str) -> str:
@staticmethod
async def generate_comment_reply(story_content: str, comment_content: str, commenter_name: str) -> str:
"""
针对自己说说的评论,生成回复。
"""

View File

@@ -50,7 +50,8 @@ class CookieService:
logger.error(f"无法读取或解析Cookie文件 {cookie_file_path}: {e}")
return None
async def _get_cookies_from_adapter(self, stream_id: Optional[str]) -> Optional[Dict[str, str]]:
@staticmethod
async def _get_cookies_from_adapter(stream_id: Optional[str]) -> Optional[Dict[str, str]]:
"""通过Adapter API获取Cookie"""
try:
params = {"domain": "user.qzone.qq.com"}

View File

@@ -59,7 +59,8 @@ class ImageService:
logger.error(f"处理AI配图时发生异常: {e}")
return False
async def _call_siliconflow_api(self, api_key: str, story: str, image_dir: str, batch_size: int) -> bool:
@staticmethod
async def _call_siliconflow_api(api_key: str, story: str, image_dir: str, batch_size: int) -> bool:
"""
调用硅基流动SiliconFlow的API来生成图片。

View File

@@ -187,7 +187,8 @@ class QZoneService:
# --- Internal Helper Methods ---
async def _get_intercom_context(self, stream_id: str) -> Optional[str]:
@staticmethod
async def _get_intercom_context(stream_id: str) -> Optional[str]:
"""
根据 stream_id 查找其所属的互通组,并构建该组的聊天上下文。
@@ -398,7 +399,8 @@ class QZoneService:
logger.error(f"加载本地图片失败: {e}")
return []
def _generate_gtk(self, skey: str) -> str:
@staticmethod
def _generate_gtk(skey: str) -> str:
hash_val = 5381
for char in skey:
hash_val += (hash_val << 5) + ord(char)
@@ -435,7 +437,8 @@ class QZoneService:
logger.error(f"更新或加载Cookie时发生异常: {e}")
return None
async def _fetch_cookies_http(self, host: str, port: str, napcat_token: str) -> Optional[Dict]:
@staticmethod
async def _fetch_cookies_http(host: str, port: str, napcat_token: str) -> Optional[Dict]:
"""通过HTTP服务器获取Cookie"""
url = f"http://{host}:{port}/get_cookies"
max_retries = 5

View File

@@ -36,7 +36,8 @@ class ReplyTrackerService:
self._load_data()
logger.debug(f"ReplyTrackerService initialized with data file: {self.reply_record_file}")
def _validate_data(self, data: Any) -> bool:
@staticmethod
def _validate_data(data: Any) -> bool:
"""验证加载的数据格式是否正确"""
if not isinstance(data, dict):
logger.error("加载的数据不是字典格式")

View File

@@ -129,7 +129,8 @@ class SchedulerService:
logger.error(f"定时任务循环中发生未知错误: {e}\n{traceback.format_exc()}")
await asyncio.sleep(300) # 发生错误后,等待一段时间再重试
async def _is_processed(self, hour_str: str, activity: str) -> bool:
@staticmethod
async def _is_processed(hour_str: str, activity: str) -> bool:
"""
检查指定的任务(某个小时的某个活动)是否已经被成功处理过。
@@ -152,7 +153,8 @@ class SchedulerService:
logger.error(f"检查日程处理状态时发生数据库错误: {e}")
return False # 数据库异常时,默认为未处理,允许重试
async def _mark_as_processed(self, hour_str: str, activity: str, success: bool, content: str):
@staticmethod
async def _mark_as_processed(hour_str: str, activity: str, success: bool, content: str):
"""
将任务的处理状态和结果写入数据库。

View File

@@ -49,7 +49,8 @@ class _SimpleQZoneAPI:
if p_skey:
self.gtk2 = self._generate_gtk(p_skey)
def _generate_gtk(self, skey: str) -> str:
@staticmethod
def _generate_gtk(skey: str) -> str:
hash_val = 5381
for char in skey:
hash_val += (hash_val << 5) + ord(char)

View File

@@ -400,9 +400,8 @@ class NapcatAdapterPlugin(BasePlugin):
def get_plugin_components(self):
self.register_events()
components = []
components.append((LauchNapcatAdapterHandler.get_handler_info(), LauchNapcatAdapterHandler))
components.append((StopNapcatAdapterHandler.get_handler_info(), StopNapcatAdapterHandler))
components = [(LauchNapcatAdapterHandler.get_handler_info(), LauchNapcatAdapterHandler),
(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))

View File

@@ -49,7 +49,8 @@ class SimpleMessageBuffer:
"""设置插件配置"""
self.plugin_config = plugin_config
def get_session_id(self, event_data: Dict[str, Any]) -> str:
@staticmethod
def get_session_id(event_data: Dict[str, Any]) -> str:
"""根据事件数据生成会话ID"""
message_type = event_data.get("message_type", "unknown")
user_id = event_data.get("user_id", "unknown")
@@ -62,7 +63,8 @@ class SimpleMessageBuffer:
else:
return f"{message_type}_{user_id}"
def extract_text_from_message(self, message: List[Dict[str, Any]]) -> Optional[str]:
@staticmethod
def extract_text_from_message(message: List[Dict[str, Any]]) -> Optional[str]:
"""从OneBot消息中提取纯文本如果包含非文本内容则返回None"""
text_parts = []
has_non_text = False
@@ -177,7 +179,8 @@ class SimpleMessageBuffer:
logger.debug(f"文本消息已添加到缓冲器 {session_id}: {text[:50]}...")
return True
async def _cancel_session_timers(self, session: BufferedSession):
@staticmethod
async def _cancel_session_timers(session: BufferedSession):
"""取消会话的所有定时器"""
for task_name in ["timer_task", "delay_task"]:
task = getattr(session, task_name)

View File

@@ -112,7 +112,8 @@ class MessageChunker:
else:
return [{"_original_message": message}]
def is_chunk_message(self, message: Union[str, Dict[str, Any]]) -> bool:
@staticmethod
def is_chunk_message(message: Union[str, Dict[str, Any]]) -> bool:
"""判断是否是切片消息"""
try:
if isinstance(message, str):

View File

@@ -26,7 +26,7 @@ import json
import websockets as Server
import base64
from pathlib import Path
from typing import List, Tuple, Optional, Dict, Any
from typing import List, Tuple, Optional, Dict, Any, Coroutine
import uuid
from maim_message import (
@@ -351,6 +351,7 @@ class MessageHandler:
logger.debug("发送到Maibot处理信息")
await message_send_instance.message_send(message_base)
return None
async def handle_real_message(self, raw_message: dict, in_reply: bool = False) -> List[Seg] | None:
# sourcery skip: low-code-quality
@@ -518,7 +519,8 @@ class MessageHandler:
logger.debug(f"handle_real_message完成处理了{len(real_message)}个消息段,生成了{len(seg_message)}个seg")
return seg_message
async def handle_text_message(self, raw_message: dict) -> Seg:
@staticmethod
async def handle_text_message(raw_message: dict) -> Seg:
"""
处理纯文本信息
Parameters:
@@ -530,7 +532,8 @@ class MessageHandler:
plain_text: str = message_data.get("text")
return Seg(type="text", data=plain_text)
async def handle_face_message(self, raw_message: dict) -> Seg | None:
@staticmethod
async def handle_face_message(raw_message: dict) -> Seg | None:
"""
处理表情消息
Parameters:
@@ -547,7 +550,8 @@ class MessageHandler:
logger.warning(f"不支持的表情:{face_raw_id}")
return None
async def handle_image_message(self, raw_message: dict) -> Seg | None:
@staticmethod
async def handle_image_message(raw_message: dict) -> Seg | None:
"""
处理图片消息与表情包消息
Parameters:
@@ -603,6 +607,7 @@ class MessageHandler:
return Seg(type="at", data=f"{member_info.get('nickname')}:{member_info.get('user_id')}")
else:
return None
return None
async def handle_record_message(self, raw_message: dict) -> Seg | None:
"""
@@ -631,7 +636,8 @@ class MessageHandler:
return None
return Seg(type="voice", data=audio_base64)
async def handle_video_message(self, raw_message: dict) -> Seg | None:
@staticmethod
async def handle_video_message(raw_message: dict) -> Seg | None:
"""
处理视频消息
Parameters:
@@ -762,7 +768,7 @@ class MessageHandler:
return None
processed_message: Seg
if image_count < 5 and image_count > 0:
if 5 > image_count > 0:
# 处理图片数量小于5的情况此时解析图片为base64
logger.debug("图片数量小于5开始解析图片为base64")
processed_message = await self._recursive_parse_image_seg(handled_message, True)
@@ -779,15 +785,18 @@ class MessageHandler:
forward_hint = Seg(type="text", data="这是一条转发消息:\n")
return Seg(type="seglist", data=[forward_hint, processed_message])
async def handle_dice_message(self, raw_message: dict) -> Seg:
@staticmethod
async def handle_dice_message(raw_message: dict) -> Seg:
message_data: dict = raw_message.get("data", {})
res = message_data.get("result", "")
return Seg(type="text", data=f"[扔了一个骰子,点数是{res}]")
async def handle_shake_message(self, raw_message: dict) -> Seg:
@staticmethod
async def handle_shake_message(raw_message: dict) -> Seg:
return Seg(type="text", data="[向你发送了窗口抖动,现在你的屏幕猛烈地震了一下!]")
async def handle_json_message(self, raw_message: dict) -> Seg:
@staticmethod
async def handle_json_message(raw_message: dict) -> Seg | None:
"""
处理JSON消息
Parameters:
@@ -906,7 +915,8 @@ class MessageHandler:
logger.error(f"处理JSON消息时出错: {e}")
return None
async def handle_rps_message(self, raw_message: dict) -> Seg:
@staticmethod
async def handle_rps_message(raw_message: dict) -> Seg:
message_data: dict = raw_message.get("data", {})
res = message_data.get("result", "")
if res == "1":
@@ -1089,7 +1099,8 @@ class MessageHandler:
return None
return response_data.get("messages")
async def _send_buffered_message(self, session_id: str, merged_text: str, original_event: Dict[str, Any]):
@staticmethod
async def _send_buffered_message(session_id: str, merged_text: str, original_event: Dict[str, Any]):
"""发送缓冲的合并消息"""
try:
# 从原始事件数据中提取信息

View File

@@ -14,6 +14,7 @@ class MetaEventHandler:
"""
def __init__(self):
self.last_heart_beat = time.time()
self.interval = 5.0 # 默认值稍后通过set_plugin_config设置
self._interval_checking = False
self.plugin_config = None
@@ -37,7 +38,6 @@ class MetaEventHandler:
if message["status"].get("online") and message["status"].get("good"):
if not self._interval_checking:
asyncio.create_task(self.check_heartbeat())
self.last_heart_beat = time.time()
self.interval = message.get("interval") / 1000
else:
self_id = message.get("self_id")

View File

@@ -197,9 +197,11 @@ class NoticeHandler:
if system_notice:
await self.put_notice(message_base)
return None
else:
logger.debug("发送到Maibot处理通知信息")
await message_send_instance.message_send(message_base)
return None
async def handle_poke_notify(
self, raw_message: dict, group_id: int, user_id: int
@@ -464,7 +466,8 @@ class NoticeHandler:
)
return seg_data, operator_info
async def put_notice(self, message_base: MessageBase) -> None:
@staticmethod
async def put_notice(message_base: MessageBase) -> None:
"""
将处理后的通知消息放入通知队列
"""
@@ -577,7 +580,8 @@ class NoticeHandler:
self.banned_list.remove(ban_record)
await asyncio.sleep(5)
async def send_notice(self) -> None:
@staticmethod
async def send_notice() -> None:
"""
发送通知消息到Napcat
"""

View File

@@ -76,7 +76,7 @@ class SendHandler:
processed_message = await self.handle_seg_recursive(message_segment, user_info)
except Exception as e:
logger.error(f"处理消息时发生错误: {e}")
return
return None
if not processed_message:
logger.critical("现在暂时不支持解析此回复!")
@@ -94,7 +94,7 @@ class SendHandler:
id_name = "user_id"
else:
logger.error("无法识别的消息类型")
return
return None
logger.info("尝试发送到napcat")
response = await self.send_message_to_napcat(
action,
@@ -107,8 +107,10 @@ class SendHandler:
logger.info("消息发送成功")
qq_message_id = response.get("data", {}).get("message_id")
await self.message_sent_back(raw_message_base, qq_message_id)
return None
else:
logger.warning(f"消息发送失败napcat返回{str(response)}")
return None
async def send_command(self, raw_message_base: MessageBase) -> None:
"""
@@ -146,7 +148,7 @@ class SendHandler:
command, args_dict = self.handle_send_like_command(args)
case _:
logger.error(f"未知命令: {command_name}")
return
return None
except Exception as e:
logger.error(f"处理命令时发生错误: {e}")
return None
@@ -158,8 +160,10 @@ class SendHandler:
response = await self.send_message_to_napcat(command, args_dict)
if response.get("status") == "ok":
logger.info(f"命令 {command_name} 执行成功")
return None
else:
logger.warning(f"命令 {command_name} 执行失败napcat返回{str(response)}")
return None
async def handle_adapter_command(self, raw_message_base: MessageBase) -> None:
"""
@@ -265,7 +269,8 @@ class SendHandler:
new_payload = self.build_payload(payload, self.handle_file_message(file_path), False)
return new_payload
def build_payload(self, payload: list, addon: dict | list, is_reply: bool = False) -> list:
@staticmethod
def build_payload(payload: list, addon: dict | list, is_reply: bool = False) -> list:
# sourcery skip: for-append-to-extend, merge-list-append, simplify-generator
"""构建发送的消息体"""
if is_reply:
@@ -324,11 +329,13 @@ class SendHandler:
return reply_seg
def handle_text_message(self, message: str) -> dict:
@staticmethod
def handle_text_message(message: str) -> dict:
"""处理文本消息"""
return {"type": "text", "data": {"text": message}}
def handle_image_message(self, encoded_image: str) -> dict:
@staticmethod
def handle_image_message(encoded_image: str) -> dict:
"""处理图片消息"""
return {
"type": "image",
@@ -338,7 +345,8 @@ class SendHandler:
},
} # base64 编码的图片
def handle_emoji_message(self, encoded_emoji: str) -> dict:
@staticmethod
def handle_emoji_message(encoded_emoji: str) -> dict:
"""处理表情消息"""
encoded_image = encoded_emoji
image_format = get_image_format(encoded_emoji)
@@ -369,39 +377,45 @@ class SendHandler:
"data": {"file": f"base64://{encoded_voice}"},
}
def handle_voiceurl_message(self, voice_url: str) -> dict:
@staticmethod
def handle_voiceurl_message(voice_url: str) -> dict:
"""处理语音链接消息"""
return {
"type": "record",
"data": {"file": voice_url},
}
def handle_music_message(self, song_id: str) -> dict:
@staticmethod
def handle_music_message(song_id: str) -> dict:
"""处理音乐消息"""
return {
"type": "music",
"data": {"type": "163", "id": song_id},
}
def handle_videourl_message(self, video_url: str) -> dict:
@staticmethod
def handle_videourl_message(video_url: str) -> dict:
"""处理视频链接消息"""
return {
"type": "video",
"data": {"file": video_url},
}
def handle_file_message(self, file_path: str) -> dict:
@staticmethod
def handle_file_message(file_path: str) -> dict:
"""处理文件消息"""
return {
"type": "file",
"data": {"file": f"file://{file_path}"},
}
def delete_msg_command(self, args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def delete_msg_command(args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
"""处理删除消息命令"""
return "delete_msg", {"message_id": args["message_id"]}
def handle_ban_command(self, args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_ban_command(args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
"""处理封禁命令
Args:
@@ -429,7 +443,8 @@ class SendHandler:
},
)
def handle_whole_ban_command(self, args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_whole_ban_command(args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
"""处理全体禁言命令
Args:
@@ -452,7 +467,8 @@ class SendHandler:
},
)
def handle_kick_command(self, args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_kick_command(args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
"""处理群成员踢出命令
Args:
@@ -477,7 +493,8 @@ class SendHandler:
},
)
def handle_poke_command(self, args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_poke_command(args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
"""处理戳一戳命令
Args:
@@ -504,7 +521,8 @@ class SendHandler:
},
)
def handle_set_emoji_like_command(self, args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_set_emoji_like_command(args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
"""处理设置表情回应命令
Args:
@@ -526,7 +544,8 @@ class SendHandler:
{"message_id": message_id, "emoji_id": emoji_id, "set": set_like},
)
def handle_send_like_command(self, args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_send_like_command(args: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
"""
处理发送点赞命令的逻辑。
@@ -547,7 +566,8 @@ class SendHandler:
{"user_id": user_id, "times": times},
)
def handle_ai_voice_send_command(self, args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_ai_voice_send_command(args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
"""
处理AI语音发送命令的逻辑。
并返回 NapCat 兼容的 (action, params) 元组。
@@ -594,7 +614,8 @@ class SendHandler:
return {"status": "error", "message": str(e)}
return response
async def message_sent_back(self, message_base: MessageBase, qq_message_id: str) -> None:
@staticmethod
async def message_sent_back(message_base: MessageBase, qq_message_id: str) -> None:
# 修改 additional_config添加 echo 字段
if message_base.message_info.additional_config is None:
message_base.message_info.additional_config = {}
@@ -612,8 +633,9 @@ class SendHandler:
logger.debug("已回送消息ID")
return
@staticmethod
async def send_adapter_command_response(
self, original_message: MessageBase, response_data: dict, request_id: str
original_message: MessageBase, response_data: dict, request_id: str
) -> None:
"""
发送适配器命令响应回MaiBot
@@ -642,7 +664,8 @@ class SendHandler:
except Exception as e:
logger.error(f"发送适配器命令响应时出错: {e}")
def handle_at_message_command(self, args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
@staticmethod
def handle_at_message_command(args: Dict[str, Any], group_info: GroupInfo) -> Tuple[str, Dict[str, Any]]:
"""处理艾特并发送消息命令
Args:

View File

@@ -111,7 +111,8 @@ class PermissionCommand(PlusCommand):
await self.send_text(help_text)
def _parse_user_mention(self, mention: str) -> Optional[str]:
@staticmethod
def _parse_user_mention(mention: str) -> Optional[str]:
"""解析用户提及提取QQ号
支持的格式:

View File

@@ -34,11 +34,11 @@ class ManagementCommand(PlusCommand):
@require_permission("plugin.management.admin", "❌ 你没有插件管理的权限")
async def execute(self, args: CommandArgs) -> Tuple[bool, str, bool]:
"""执行插件管理命令"""
if args.is_empty():
if args.is_empty:
await self._show_help("all")
return True, "显示帮助信息", True
subcommand = args.get_first().lower()
subcommand = args.get_first.lower()
remaining_args = args.get_args()[1:] # 获取除第一个参数外的所有参数
if subcommand in ["plugin", "插件"]:
@@ -318,7 +318,8 @@ class ManagementCommand(PlusCommand):
else:
await self.send_text(f"❌ 插件目录添加失败: `{dir_path}`")
def _fetch_all_registered_components(self) -> List[ComponentInfo]:
@staticmethod
def _fetch_all_registered_components() -> List[ComponentInfo]:
all_plugin_info = component_manage_api.get_all_plugin_info()
if not all_plugin_info:
return []

View File

@@ -1,6 +1,7 @@
import asyncio
from datetime import datetime
from typing import List, Tuple, Type, Optional
from dateutil.parser import parse as parse_datetime
from src.common.logger import get_logger
@@ -14,7 +15,7 @@ from src.plugin_system import (
ActionActivationType,
)
from src.plugin_system.apis import send_api, llm_api, generator_api
from src.plugin_system.base.component_types import ChatType, ComponentType
from src.plugin_system.base.component_types import ComponentType
logger = get_logger(__name__)

View File

@@ -74,7 +74,8 @@ class TTSAction(BaseAction):
logger.error(f"{self.log_prefix} 执行TTS动作时出错: {e}")
return False, f"执行TTS动作时出错: {e}"
def _process_text_for_tts(self, text: str) -> str:
@staticmethod
def _process_text_for_tts(text: str) -> str:
"""
处理文本使其更适合TTS使用
- 移除不必要的特殊字符和表情符号

View File

@@ -111,7 +111,8 @@ class BingSearchEngine(BaseSearchEngine):
logger.debug(f"Bing搜索 [{keyword}] 完成,总共 {len(list_result)} 个结果")
return list_result[:num_results] if len(list_result) > num_results else list_result
def _parse_html(self, url: str) -> List[Dict[str, Any]]:
@staticmethod
def _parse_html(url: str) -> List[Dict[str, Any]]:
"""解析处理结果"""
try:
logger.debug(f"访问Bing搜索URL: {url}")

View File

@@ -89,7 +89,7 @@ class URLParserTool(BaseTool):
title = soup.title.string if soup.title else "无标题"
for script in soup(["script", "style"]):
script.extract()
text = soup.get_text(separator="\n", strip=True)
text = soup.get_text(strip=True)
if not text:
return {"error": "无法从页面提取有效文本内容。"}