* 滚木 * feat: 重构核心架构,增强类型安全与插件管理 本次提交对核心模块进行了深度重构,引入 Pydantic 增强配置管理的类型安全性,并全面优化了插件管理系统。 主要变更详情: 1. 核心架构与配置 - 重构配置加载模块:引入 Pydantic 模型 (`core/config_models.py`),提供严格的配置项类型检查、验证及默认值管理。 - 统一模块结构:规范化模块导入路径,移除冗余的 `__init__.py` 文件,提升项目结构的清晰度。 - 性能优化:集成 Redis 缓存支持 (`RedisManager`),有效降低高频 API 调用开销,提升响应速度。 2. 插件系统升级 - 实现热重载机制:新增插件文件变更监听功能,支持开发过程中自动重载插件,提升开发效率。 - 优化生命周期管理:改进插件加载与卸载逻辑,支持精确卸载指定插件及其关联的命令、事件处理器和定时任务。 3. 功能特性增强 - 新增媒体 API:引入 `MediaAPI` 模块,封装图片、语音等富媒体资源的获取与处理接口。 - 完善权限体系:重构权限管理系统,实现管理员与操作员的分级控制,支持更细粒度的命令权限校验。 4. 代码质量与稳定性 - 全面类型修复:解决 `mypy` 静态类型检查发现的大量类型错误(包括 `CommandManager`、`EventFactory` 及 `Bot` API 签名不匹配问题)。 - 增强错误处理:优化消息处理管道的异常捕获机制,完善关键路径的日志记录,提升系统运行稳定性。 * feat: 添加测试用例并优化代码结构 refactor(permission_manager): 调整初始化顺序和逻辑 fix(admin_manager): 修复初始化逻辑和目录创建问题 feat(ws): 优化Bot实例初始化条件 feat(message): 增强MessageSegment功能并添加测试 feat(events): 支持字符串格式的消息解析 test: 添加核心功能测试用例 refactor(plugin_manager): 改进插件路径处理 style: 清理无用导入和代码 chore: 更新依赖项 * refactor(handler): 移除TYPE_CHECKING并直接导入Bot类 简化类型注解,直接导入Bot类而非使用TYPE_CHECKING条件导入,提高代码可读性和维护性 * fix(command_manager): 修复插件卸载时元信息移除不精确的问题 修复 CommandManager 中 unload_plugin 方法移除插件元信息时使用 startswith 导致可能误删其他插件的问题,改为精确匹配 同时调整相关测试用例验证精确匹配行为 * refactor: 清理未使用的导入和更新文档结构 docs: 添加config_models.py到项目结构文档 docs: 调整数据目录位置到core/data下 docs: 更新权限管理器文档描述 * 文档更新 * 更新thpic插件 支持一次返回多张图 * feat: 添加测试覆盖率并修复相关问题 refactor(redis_manager): 移除冗余的ConnectionError处理 refactor(event_handler): 优化Bot类型注解 refactor(factory): 移除未使用的GroupCardNoticeEvent test: 添加全面的单元测试覆盖 - 添加test_import.py测试模块导入 - 添加test_debug.py测试插件加载调试 - 添加test_plugin_error.py测试错误处理 - 添加test_config_loader.py测试配置加载 - 添加test_redis_manager.py测试Redis管理 - 添加test_bot.py测试Bot功能 - 扩展test_models.py测试消息模型 - 添加test_plugin_manager_coverage.py测试插件管理 - 添加test_executor.py测试代码执行器 - 添加test_ws.py测试WebSocket - 添加test_api.py测试API接口 - 添加test_core_managers.py测试核心管理模块 fix(plugin_manager): 修复插件加载日志变量问题 覆盖率已到达86%(忽略插件) * 更新/help指令,现在会发送图片 * feat(help): 重构帮助系统为图片渲染模式 添加浏览器管理器和图片管理器,用于通过 Playwright 渲染帮助菜单为图片 重构命令管理器以支持图片缓存和同步功能 添加 HTML 模板用于帮助菜单渲染 --------- Co-authored-by: baby20162016 <2185823427@qq.com>
73 lines
2.3 KiB
Python
73 lines
2.3 KiB
Python
"""
|
||
浏览器管理器模块
|
||
|
||
负责管理全局唯一的 Playwright 浏览器实例,避免频繁启动/关闭浏览器的开销。
|
||
"""
|
||
import asyncio
|
||
from typing import Optional
|
||
from playwright.async_api import async_playwright, Browser, Playwright, Page
|
||
from ..utils.logger import logger
|
||
|
||
class BrowserManager:
|
||
"""
|
||
浏览器管理器(异步单例)
|
||
"""
|
||
_instance = None
|
||
_playwright: Optional[Playwright] = None
|
||
_browser: Optional[Browser] = None
|
||
|
||
def __new__(cls):
|
||
if cls._instance is None:
|
||
cls._instance = super().__new__(cls)
|
||
return cls._instance
|
||
|
||
async def initialize(self):
|
||
"""
|
||
初始化 Playwright 和 Browser
|
||
"""
|
||
if self._browser is None:
|
||
try:
|
||
logger.info("正在启动无头浏览器...")
|
||
self._playwright = await async_playwright().start()
|
||
# 启动 Chromium,headless=True 表示无头模式
|
||
self._browser = await self._playwright.chromium.launch(headless=True)
|
||
logger.success("无头浏览器启动成功!")
|
||
except Exception as e:
|
||
logger.exception(f"无头浏览器启动失败: {e}")
|
||
self._browser = None
|
||
|
||
async def get_new_page(self) -> Optional[Page]:
|
||
"""
|
||
获取一个新的页面 (Page)
|
||
|
||
使用完毕后,调用者应该负责关闭该页面 (await page.close())
|
||
"""
|
||
if self._browser is None:
|
||
logger.warning("浏览器尚未初始化,尝试重新初始化...")
|
||
await self.initialize()
|
||
|
||
if self._browser:
|
||
try:
|
||
return await self._browser.new_page()
|
||
except Exception as e:
|
||
logger.error(f"创建新页面失败: {e}")
|
||
return None
|
||
return None
|
||
|
||
async def shutdown(self):
|
||
"""
|
||
关闭浏览器和 Playwright
|
||
"""
|
||
if self._browser:
|
||
await self._browser.close()
|
||
self._browser = None
|
||
logger.info("浏览器已关闭")
|
||
|
||
if self._playwright:
|
||
await self._playwright.stop()
|
||
self._playwright = None
|
||
logger.info("Playwright 已停止")
|
||
|
||
# 全局浏览器管理器实例
|
||
browser_manager = BrowserManager()
|