refactor(core): 重构核心模块结构并添加开发文档

将核心模块按功能重新组织为更清晰的结构,包括 managers、handlers 和 utils 目录
添加完整的开发文档,涵盖快速开始、项目结构、核心概念和插件开发指南
更新所有相关模块的导入路径以匹配新的结构
将单例模式实现提取到单独的 singleton.py 文件
This commit is contained in:
2026-01-07 22:51:27 +08:00
parent c708761726
commit 56b1014419
45 changed files with 772 additions and 104 deletions

View File

@@ -1,6 +1,6 @@
from .command_manager import matcher
from .managers.command_manager import matcher
from .config_loader import global_config
from .plugin_manager import PluginDataManager
from .managers.plugin_manager import PluginDataManager
from .ws import WS
__all__ = ["WS", "matcher", "global_config", "PluginDataManager"]

View File

@@ -8,7 +8,7 @@ import json
from typing import Dict, Any
from .base import BaseAPI
from models.objects import LoginInfo, VersionInfo, Status
from core.redis_manager import redis_manager
from ..managers.redis_manager import redis_manager
class AccountAPI(BaseAPI):

View File

@@ -8,7 +8,7 @@ import json
from typing import List, Dict, Any
from .base import BaseAPI
from models.objects import FriendInfo, StrangerInfo
from core.redis_manager import redis_manager
from ..managers.redis_manager import redis_manager
class FriendAPI(BaseAPI):

View File

@@ -6,10 +6,10 @@
"""
from typing import List, Dict, Any
import json
from core.redis_manager import redis_manager
from ..managers.redis_manager import redis_manager
from .base import BaseAPI
from models.objects import GroupInfo, GroupMemberInfo, GroupHonorInfo
from core.logger import logger
from ..utils.logger import logger
class GroupAPI(BaseAPI):

3
core/data/admin.json Normal file
View File

@@ -0,0 +1,3 @@
{
"admins": []
}

View File

@@ -0,0 +1,3 @@
{
"users": {}
}

View File

View File

@@ -8,10 +8,10 @@ import inspect
from abc import ABC, abstractmethod
from typing import Any, Callable, Dict, List, Optional, Tuple
from .bot import Bot
from .permission_manager import Permission, permission_manager
from .exceptions import SyncHandlerError
from .executor import run_in_thread_pool
from ..bot import Bot
from ..config_loader import global_config
from ..managers.permission_manager import Permission, permission_manager
from ..utils.executor import run_in_thread_pool
class BaseHandler(ABC):
@@ -75,8 +75,6 @@ class MessageHandler(BaseHandler):
注册通用消息处理器
"""
def decorator(func: Callable) -> Callable:
if not inspect.iscoroutinefunction(func):
raise SyncHandlerError(f"消息处理器 {func.__name__} 必须是异步函数 (async def).")
self.message_handlers.append(func)
return func
return decorator
@@ -91,8 +89,6 @@ class MessageHandler(BaseHandler):
注册命令处理器
"""
def decorator(func: Callable) -> Callable:
if not inspect.iscoroutinefunction(func):
raise SyncHandlerError(f"命令处理器 {func.__name__} 必须是异步函数 (async def).")
for name in names:
self.commands[name] = {
"func": func,
@@ -139,7 +135,8 @@ class MessageHandler(BaseHandler):
if not permission_granted and not override_check:
permission_name = permission.name if isinstance(permission, Permission) else permission
await bot.send(event, f"权限不足,需要 {permission_name} 权限")
message_template = global_config.bot.get("permission_denied_message", "权限不足,需要 {permission_name} 权限")
await bot.send(event, message_template.format(permission_name=permission_name))
return
await self._run_handler(
@@ -160,8 +157,6 @@ class NoticeHandler(BaseHandler):
注册通知处理器
"""
def decorator(func: Callable) -> Callable:
if not inspect.iscoroutinefunction(func):
raise SyncHandlerError(f"通知处理器 {func.__name__} 必须是异步函数 (async def).")
self.handlers.append({"type": notice_type, "func": func})
return func
return decorator
@@ -184,8 +179,6 @@ class RequestHandler(BaseHandler):
注册请求处理器
"""
def decorator(func: Callable) -> Callable:
if not inspect.iscoroutinefunction(func):
raise SyncHandlerError(f"请求处理器 {func.__name__} 必须是异步函数 (async def).")
self.handlers.append({"type": request_type, "func": func})
return func
return decorator

View File

View File

@@ -9,33 +9,25 @@ import json
import os
from typing import Set
from .logger import logger
from ..utils.logger import logger
from ..utils.singleton import Singleton
from .redis_manager import redis_manager
class AdminManager:
class AdminManager(Singleton):
"""
管理员管理器类
负责加载缓存和管理管理员列表
使用单例模式确保全局只有一个实例
"""
_instance = None
_REDIS_KEY = "neobot:admins" # 用于存储管理员集合的 Redis 键
def __new__(cls):
"""
单例模式实现
"""
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
"""
初始化 AdminManager
"""
if getattr(self, "_initialized", False):
super().__init__()
if not self._initialized:
return
# 管理员数据文件路径
@@ -47,7 +39,6 @@ class AdminManager:
)
self._admins: Set[int] = set()
self._initialized = True
logger.info("管理员管理器初始化完成")
async def initialize(self):
@@ -96,7 +87,7 @@ class AdminManager:
"""
将内存中的管理员集合同步到 Redis
"""
from .redis_manager import redis_manager
from core.managers.redis_manager import redis_manager
try:
# 首先清空旧的集合
await redis_manager.redis.delete(self._REDIS_KEY)
@@ -111,7 +102,7 @@ class AdminManager:
"""
检查用户是否为管理员 Redis 缓存读取
"""
from .redis_manager import redis_manager
try:
return await redis_manager.redis.sismember(self._REDIS_KEY, user_id)
except Exception as e:

View File

@@ -7,8 +7,8 @@
"""
from typing import Any, Callable, Dict, Optional, Tuple
from .config_loader import global_config
from .event_handler import MessageHandler, NoticeHandler, RequestHandler
from ..config_loader import global_config
from ..handlers.event_handler import MessageHandler, NoticeHandler, RequestHandler
# 从配置中获取命令前缀

View File

@@ -16,8 +16,9 @@ import os
from functools import total_ordering
from typing import Dict
from .logger import logger
from .admin_manager import admin_manager # 导入 AdminManager
from ..utils.logger import logger
from ..utils.singleton import Singleton
from .admin_manager import admin_manager
@total_ordering
@@ -73,7 +74,7 @@ _PERMISSIONS: Dict[str, Permission] = {
}
class PermissionManager:
class PermissionManager(Singleton):
"""
权限管理器类
@@ -81,27 +82,14 @@ class PermissionManager:
使用单例模式确保全局只有一个权限管理器实例
"""
_instance = None
def __new__(cls):
"""
单例模式实现
Returns:
PermissionManager: 全局唯一的权限管理器实例
"""
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
"""
初始化权限管理器
如果已经初始化过则直接返回
"""
if getattr(self, "_initialized", False):
super().__init__()
if not self._initialized:
return
# 权限数据文件路径
@@ -122,7 +110,6 @@ class PermissionManager:
# 加载现有数据
self.load()
self._initialized = True
logger.info("权限管理器初始化完成")
def load(self) -> None:

View File

@@ -10,10 +10,10 @@ import os
import pkgutil
import sys
from core.command_manager import matcher
from core.exceptions import SyncHandlerError
from .logger import logger
from .executor import run_in_thread_pool
from .command_manager import matcher
from ..utils.exceptions import SyncHandlerError
from ..utils.logger import logger
from ..utils.executor import run_in_thread_pool
def load_all_plugins():

View File

@@ -1,6 +1,6 @@
import redis.asyncio as redis
from .config_loader import global_config as config
from .logger import logger
from ..config_loader import global_config as config
from ..utils.logger import logger
class RedisManager:
"""

0
core/utils/__init__.py Normal file
View File

View File

@@ -4,7 +4,7 @@ import docker
from docker.tls import TLSConfig
from typing import Dict, Any, Callable
from core.logger import logger
from core.utils.logger import logger
class CodeExecutor:
"""

30
core/utils/singleton.py Normal file
View File

@@ -0,0 +1,30 @@
"""
通用单例模式基类
"""
class Singleton:
"""
一个通用的单例基类
任何继承自该类的子类都将自动成为单例。
它通过重写 __new__ 方法来确保每个类只有一个实例。
同时,它处理了重复初始化的问题,确保 __init__ 方法只在第一次实例化时被调用。
"""
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
"""
创建或返回现有的实例
"""
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
"""
确保初始化逻辑只执行一次
"""
if self._initialized:
return
self._initialized = True

View File

@@ -22,9 +22,9 @@ import websockets
from models import EventFactory
from .bot import Bot
from .command_manager import matcher
from .config_loader import global_config
from .logger import logger
from .managers.command_manager import matcher
from .utils.logger import logger
class WS: