refactor(core): 重构核心模块结构并添加开发文档
将核心模块按功能重新组织为更清晰的结构,包括 managers、handlers 和 utils 目录 添加完整的开发文档,涵盖快速开始、项目结构、核心概念和插件开发指南 更新所有相关模块的导入路径以匹配新的结构 将单例模式实现提取到单独的 singleton.py 文件
This commit is contained in:
@@ -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"]
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
3
core/data/admin.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"admins": []
|
||||
}
|
||||
3
core/data/permissions.json
Normal file
3
core/data/permissions.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"users": {}
|
||||
}
|
||||
0
core/handlers/__init__.py
Normal file
0
core/handlers/__init__.py
Normal 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
|
||||
0
core/managers/__init__.py
Normal file
0
core/managers/__init__.py
Normal 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:
|
||||
@@ -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
|
||||
|
||||
|
||||
# 从配置中获取命令前缀
|
||||
@@ -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:
|
||||
@@ -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():
|
||||
@@ -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
0
core/utils/__init__.py
Normal 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
30
core/utils/singleton.py
Normal 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
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user