✨ 引入缓存机制 (#1889)

* 添加全局cache

* ✨ 构建缓存,hook使用缓存

* ✨ 新增数据库Model方法监控

* ✨ 数据库添加semaphore锁

* 🩹 优化webapi返回数据

* ✨ 添加增量缓存与缓存过期

* 🎨 优化检测代码结构

* ⚡ 优化hook权限检测性能

* 🐛 添加新异常判断跳过权限检测

* ✨ 添加插件limit缓存

* 🎨 代码格式优化

* 🐛  修复代码导入

* 🐛 修复刷新时检查

* 👽 Rename exception for missing database URL in initialization

* ♿ Update default database URL to SQLite in configuration

* 🔧 Update tortoise-orm and aiocache dependencies restrictions; add optional redis and asyncpg support

* 🐛 修复ban检测

* 🐛 修复所有插件关闭时缓存更新

* 🐛 尝试迁移至aiocache

* 🐛 完善aiocache缓存

* ⚡ 代码性能优化

* 🐛 移除获取封禁缓存时的日志记录

* 🐛 修复缓存类型声明,优化封禁用户处理逻辑

* 🐛 优化LevelUser权限更新逻辑及数据库迁移

* ✨ cache支持redis连接

* 🚨 auto fix by pre-commit hooks

* ⚡ :增强获取群组的安全性和准确性。同时,优化了缓存管理中的相关逻辑,确保缓存操作的一致性。

* ✨ feat(auth_limit): 将插件初始化逻辑的启动装饰器更改为优先级管理器

* 🔧 修复日志记录级别

* 🔧 更新数据库连接字符串

* 🔧 更新数据库连接字符串为内存数据库,并优化权限检查逻辑

* ✨ feat(cache): 增加缓存功能配置项,并新增数据访问层以支持缓存逻辑

* ♻️ 重构cache

* ✨ feat(cache): 增强缓存管理,新增缓存字典和缓存列表功能,支持过期时间管理

* 🔧 修复Notebook类中的viewport高度设置,将其从1000调整为10

* ✨ 更新插件管理逻辑,替换缓存服务为CacheRoot并优化缓存失效处理

* ✨ 更新RegisterConfig类中的type字段

* ✨ 修复清理重复记录逻辑,确保检查记录的id属性有效性

* ⚡ 超级无敌大优化,解决延迟与卡死问题

* ✨ 更新封禁功能,增加封禁时长参数和描述,优化插件信息返回结构

* ✨ 更新zhenxun_help.py中的viewport高度,将其从453调整为10,以优化页面显示效果

* ✨ 优化插件分类逻辑,增加插件ID排序,并更新插件信息返回结构

---------

Co-authored-by: BalconyJH <balconyjh@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
HibiKier
2025-07-14 22:35:29 +08:00
committed by GitHub
co-authored by BalconyJH pre-commit-ci[bot]
parent 6283c3d13d
commit 8649aaaa54
57 changed files with 5179 additions and 1479 deletions
@@ -1,10 +1,13 @@
import os
from typing import cast
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.task_info import TaskInfo
from zhenxun.utils.enum import BlockType, PluginType
from zhenxun.services.cache import CacheRoot
from zhenxun.utils.common_utils import CommonUtils
from zhenxun.utils.enum import BlockType, CacheType, PluginType
from zhenxun.utils.exception import GroupInfoNotFound
from zhenxun.utils.image_utils import BuildImage, ImageTemplate, RowStyle
@@ -116,9 +119,7 @@ async def build_task(group_id: str | None) -> BuildImage:
column_name = ["ID", "模块", "名称", "群组状态", "全局状态", "运行时间"]
group = None
if group_id:
group = await GroupConsole.get_or_none(
group_id=group_id, channel_id__isnull=True
)
group = await GroupConsole.get_group(group_id=group_id)
if not group:
raise GroupInfoNotFound()
else:
@@ -200,26 +201,26 @@ class PluginManager:
)
return f"成功将所有功能进群默认状态修改为: {'开启' if status else '关闭'}"
if group_id:
if group := await GroupConsole.get_or_none(
group_id=group_id, channel_id__isnull=True
):
module_list = await PluginInfo.filter(
plugin_type=PluginType.NORMAL
).values_list("module", flat=True)
if group := await GroupConsole.get_group(group_id=group_id):
module_list = cast(
list[str],
await PluginInfo.filter(plugin_type=PluginType.NORMAL).values_list(
"module", flat=True
),
)
if status:
for module in module_list:
group.block_plugin = group.block_plugin.replace(
f"<{module},", ""
)
# 开启所有功能 - 清空禁用列表
group.block_plugin = ""
else:
module_list = [f"<{module}" for module in module_list]
group.block_plugin = ",".join(module_list) + "," # type: ignore
# 关闭所有功能 - 将模块列表转换为禁用格式
group.block_plugin = CommonUtils.convert_module_format(module_list)
await group.save(update_fields=["block_plugin"])
return f"成功将此群组所有功能状态修改为: {'开启' if status else '关闭'}"
return "获取群组失败..."
await PluginInfo.filter(plugin_type=PluginType.NORMAL).update(
status=status, block_type=None if status else BlockType.ALL
)
await CacheRoot.invalidate_cache(CacheType.PLUGINS)
return f"成功将所有功能全局状态修改为: {'开启' if status else '关闭'}"
@classmethod
@@ -232,9 +233,7 @@ class PluginManager:
返回:
bool: 是否醒来
"""
if c := await GroupConsole.get_or_none(
group_id=group_id, channel_id__isnull=True
):
if c := await GroupConsole.get_group(group_id=group_id):
return c.status
return False
@@ -245,9 +244,11 @@ class PluginManager:
参数:
group_id: 群组id
"""
await GroupConsole.filter(group_id=group_id, channel_id__isnull=True).update(
status=False
group, _ = await GroupConsole.get_or_create(
group_id=group_id, channel_id__isnull=True
)
group.status = False
await group.save(update_fields=["status"])
@classmethod
async def wake(cls, group_id: str):
@@ -256,9 +257,11 @@ class PluginManager:
参数:
group_id: 群组id
"""
await GroupConsole.filter(group_id=group_id, channel_id__isnull=True).update(
status=True
group, _ = await GroupConsole.get_or_create(
group_id=group_id, channel_id__isnull=True
)
group.status = True
await group.save(update_fields=["status"])
@classmethod
async def block(cls, module: str):
@@ -267,7 +270,9 @@ class PluginManager:
参数:
module: 模块名
"""
await PluginInfo.filter(module=module).update(status=False)
if plugin := await PluginInfo.get_plugin(module=module):
plugin.status = False
await plugin.save(update_fields=["status"])
@classmethod
async def unblock(cls, module: str):
@@ -276,7 +281,9 @@ class PluginManager:
参数:
module: 模块名
"""
await PluginInfo.filter(module=module).update(status=True)
if plugin := await PluginInfo.get_plugin(module=module):
plugin.status = True
await plugin.save(update_fields=["status"])
@classmethod
async def block_group_plugin(cls, plugin_name: str, group_id: str) -> str:
@@ -437,17 +444,18 @@ class PluginManager:
"""
status_str = "关闭" if status else "开启"
if is_all:
modules = await TaskInfo.annotate().values_list("module", flat=True)
if modules:
module_list = cast(
list[str], await TaskInfo.annotate().values_list("module", flat=True)
)
if module_list:
group, _ = await GroupConsole.get_or_create(
group_id=group_id, channel_id__isnull=True
)
modules = [f"<{module}" for module in modules]
if status:
group.block_task = ",".join(modules) + "," # type: ignore
group.block_task = CommonUtils.convert_module_format(module_list)
else:
for module in modules:
group.block_task = group.block_task.replace(f"{module},", "")
# 开启所有模块 - 清空禁用列表
group.block_task = ""
await group.save(update_fields=["block_task"])
return f"已成功{status_str}全部被动技能!"
elif task := await TaskInfo.get_or_none(name=task_name):