适配新版本webui (#1905)

Co-authored-by: molanp <104612722+molanp@users.noreply.github.com>
Co-authored-by: BalconyJH <73932916+BalconyJH@users.noreply.github.com>
This commit is contained in:
HibiKier 2025-05-15 23:52:20 +08:00 committed by GitHub
parent 6546eb990b
commit 9cda0e5d8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 101 additions and 18 deletions

View File

@ -40,7 +40,9 @@ async def create_help_img(
match help_type:
case "html":
result = BuildImage.open(await build_html_image(group_id, is_detail))
result = BuildImage.open(
await build_html_image(session, group_id, is_detail)
)
case "zhenxun":
result = BuildImage.open(
await build_zhenxun_image(session, group_id, is_detail)

View File

@ -1,5 +1,8 @@
from collections.abc import Callable
from nonebot_plugin_uninfo import Uninfo
from zhenxun.models.bot_console import BotConsole
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.utils.enum import PluginType
@ -27,13 +30,15 @@ async def sort_type() -> dict[str, list[PluginInfo]]:
async def classify_plugin(
group_id: str | None, is_detail: bool, handle: Callable
session: Uninfo, group_id: str | None, is_detail: bool, handle: Callable
) -> dict[str, list]:
"""对插件进行分类并判断状态
参数:
session: Uninfo对象
group_id: 群组id
is_detail: 是否详细帮助
handle: 回调方法
返回:
dict[str, list[Item]]: 分类插件数据
@ -41,9 +46,10 @@ async def classify_plugin(
sort_data = await sort_type()
classify: dict[str, list] = {}
group = await GroupConsole.get_or_none(group_id=group_id) if group_id else None
bot = await BotConsole.get_or_none(bot_id=session.self_id)
for menu, value in sort_data.items():
for plugin in value:
if not classify.get(menu):
classify[menu] = []
classify[menu].append(handle(plugin, group, is_detail))
classify[menu].append(handle(bot, plugin, group, is_detail))
return classify

View File

@ -2,9 +2,11 @@ import os
import random
from nonebot_plugin_htmlrender import template_to_pic
from nonebot_plugin_uninfo import Uninfo
from pydantic import BaseModel
from zhenxun.configs.path_config import TEMPLATE_PATH
from zhenxun.models.bot_console import BotConsole
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.utils.enum import BlockType
@ -48,11 +50,12 @@ ICON2STR = {
def __handle_item(
plugin: PluginInfo, group: GroupConsole | None, is_detail: bool
bot: BotConsole, plugin: PluginInfo, group: GroupConsole | None, is_detail: bool
) -> Item:
"""构造Item
参数:
bot: BotConsole
plugin: PluginInfo
group: 群组
is_detail: 是否详细
@ -73,10 +76,13 @@ def __handle_item(
]:
sta = 2
if group:
if f"{plugin.module}:super," in group.block_plugin:
if f"{plugin.module}," in group.superuser_block_plugin:
sta = 2
if f"{plugin.module}," in group.block_plugin:
sta = 1
if bot:
if f"{plugin.module}," in bot.block_plugins:
sta = 2
return Item(plugin_name=plugin.name, sta=sta)
@ -119,14 +125,17 @@ def build_plugin_data(classify: dict[str, list[Item]]) -> list[dict[str, str]]:
return plugin_list
async def build_html_image(group_id: str | None, is_detail: bool) -> bytes:
async def build_html_image(
session: Uninfo, group_id: str | None, is_detail: bool
) -> bytes:
"""构造HTML帮助图片
参数:
session: Uninfo
group_id: 群号
is_detail: 是否详细帮助
"""
classify = await classify_plugin(group_id, is_detail, __handle_item)
classify = await classify_plugin(session, group_id, is_detail, __handle_item)
plugin_list = build_plugin_data(classify)
return await template_to_pic(
template_path=str((TEMPLATE_PATH / "menu").absolute()),

View File

@ -6,6 +6,7 @@ from pydantic import BaseModel
from zhenxun.configs.config import BotConfig
from zhenxun.configs.path_config import TEMPLATE_PATH
from zhenxun.configs.utils import PluginExtraData
from zhenxun.models.bot_console import BotConsole
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.utils.enum import BlockType
@ -21,12 +22,19 @@ class Item(BaseModel):
"""插件命令"""
def __handle_item(plugin: PluginInfo, group: GroupConsole | None, is_detail: bool):
def __handle_item(
bot: BotConsole | None,
plugin: PluginInfo,
group: GroupConsole | None,
is_detail: bool,
):
"""构造Item
参数:
bot: BotConsole
plugin: PluginInfo
group: 群组
is_detail: 是否为详细
返回:
Item: Item
@ -40,6 +48,8 @@ def __handle_item(plugin: PluginInfo, group: GroupConsole | None, is_detail: boo
plugin.name = f"{plugin.name}(不可用)"
elif group and f"{plugin.module}," in group.block_plugin:
plugin.name = f"{plugin.name}(不可用)"
elif bot and f"{plugin.module}," in bot.block_plugins:
plugin.name = f"{plugin.name}(不可用)"
commands = []
nb_plugin = nonebot.get_plugin_by_module_name(plugin.module_path)
if is_detail and nb_plugin and nb_plugin.metadata and nb_plugin.metadata.extra:
@ -142,7 +152,7 @@ async def build_zhenxun_image(
group_id: 群号
is_detail: 是否详细帮助
"""
classify = await classify_plugin(group_id, is_detail, __handle_item)
classify = await classify_plugin(session, group_id, is_detail, __handle_item)
plugin_list = build_plugin_data(classify)
platform = PlatformUtils.get_platform(session)
bot_id = BotConfig.get_qbot_uid(session.self_id) or session.self_id

View File

@ -46,7 +46,10 @@ class MenuManage:
icon="database",
),
MenuItem(
name="系统信息", module="system", router="/system", icon="system"
name="文件管理", module="system", router="/system", icon="system"
),
MenuItem(
name="关于我们", module="about", router="/about", icon="about"
),
]
self.save()

View File

@ -16,7 +16,7 @@ from zhenxun.utils.platform import PlatformUtils
from ....base_model import Result
from ....config import QueryDateType
from ....utils import authentication, get_system_status
from ....utils import authentication, clear_help_image, get_system_status
from .data_source import ApiDataSource
from .model import (
ActiveGroup,
@ -234,6 +234,7 @@ async def _(param: BotManageUpdateParam):
bot_data.block_plugins = CommonUtils.convert_module_format(param.block_plugins)
bot_data.block_tasks = CommonUtils.convert_module_format(param.block_tasks)
await bot_data.save(update_fields=["block_plugins", "block_tasks"])
clear_help_image()
return Result.ok()
except Exception as e:
logger.error(f"{router.prefix}/update_bot_manage 调用错误", "WebUi", e=e)

View File

@ -92,7 +92,7 @@ class ApiDataSource:
"""
version_file = Path() / "__version__"
if version_file.exists():
if text := version_file.open().read():
if text := version_file.open(encoding="utf-8").read():
return text.replace("__version__: ", "").strip()
return "unknown"

View File

@ -1,3 +1,5 @@
from datetime import datetime
from fastapi import APIRouter
import nonebot
from nonebot import on_message
@ -49,13 +51,14 @@ async def message_handle(
message: UniMsg,
group_id: str | None,
):
time = str(datetime.now().replace(microsecond=0))
messages = []
for m in message:
if isinstance(m, Text | str):
messages.append(MessageItem(type="text", msg=str(m)))
messages.append(MessageItem(type="text", msg=str(m), time=time))
elif isinstance(m, Image):
if m.url:
messages.append(MessageItem(type="img", msg=m.url))
messages.append(MessageItem(type="img", msg=m.url, time=time))
elif isinstance(m, At):
if group_id:
if m.target == "0":
@ -72,9 +75,9 @@ async def message_handle(
uname = group_user.user_name
if m.target not in ID2NAME[group_id]:
ID2NAME[group_id][m.target] = uname
messages.append(MessageItem(type="at", msg=f"@{uname}"))
messages.append(MessageItem(type="at", msg=f"@{uname}", time=time))
elif isinstance(m, Hyper):
messages.append(MessageItem(type="text", msg="[分享消息]"))
messages.append(MessageItem(type="text", msg="[分享消息]", time=time))
return messages

View File

@ -237,6 +237,8 @@ class MessageItem(BaseModel):
"""消息类型"""
msg: str
"""内容"""
time: str
"""发送日期"""
class Message(BaseModel):

View File

@ -6,7 +6,7 @@ from zhenxun.services.log import logger
from zhenxun.utils.enum import BlockType, PluginType
from ....base_model import Result
from ....utils import authentication
from ....utils import authentication, clear_help_image
from .data_source import ApiDataSource
from .model import (
BatchUpdatePlugins,
@ -80,6 +80,7 @@ async def _() -> Result[PluginCount]:
async def _(param: UpdatePlugin) -> Result:
try:
await ApiDataSource.update_plugin(param)
clear_help_image()
return Result.ok(info="已经帮你写好啦!")
except (ValueError, KeyError):
return Result.fail("插件数据不存在...")
@ -107,6 +108,7 @@ async def _(param: PluginSwitch) -> Result:
db_plugin.block_type = None
db_plugin.status = True
await db_plugin.save()
clear_help_image()
return Result.ok(info="成功改变了开关状态!")
except Exception as e:
logger.error(f"{router.prefix}/change_switch 调用错误", "WebUi", e=e)
@ -173,6 +175,7 @@ async def batch_update_plugin_config_api(
updated_count=result_dict["updated_count"],
errors=result_dict["errors"],
)
clear_help_image()
return Result.ok(result_model, "插件配置更新完成")
except Exception as e:
logger.error(f"{router.prefix}/plugins/batch_update 调用错误", "WebUi", e=e)
@ -192,6 +195,7 @@ async def rename_menu_type_api(payload: RenameMenuTypePayload) -> Result:
old_name=payload.old_name, new_name=payload.new_name
)
if result.get("success"):
clear_help_image()
return Result.ok(
info=result.get(
"info",

View File

@ -52,6 +52,10 @@ class ApiDataSource:
status=plugin.status,
author=plugin.author,
block_type=plugin.block_type,
is_builtin="builtin_plugins" in plugin.module_path
or plugin.plugin_type == PluginType.HIDDEN,
allow_setting=plugin.plugin_type != PluginType.HIDDEN,
allow_switch=plugin.plugin_type != PluginType.HIDDEN,
)
plugin_list.append(plugin_info)
return plugin_list

View File

@ -78,6 +78,13 @@ class PluginInfo(BaseModel):
author: str | None = None
"""作者"""
block_type: BlockType | None = Field(None, description="插件禁用状态 (None: 启用)")
"""禁用状态"""
is_builtin: bool = False
"""是否为内置插件"""
allow_switch: bool = True
"""是否允许开关"""
allow_setting: bool = True
"""是否允许设置"""
class PluginConfig(BaseModel):

View File

@ -36,6 +36,8 @@ async def _(path: str | None = None) -> Result[list[DirFile]]:
is_image=is_image,
name=file,
parent=path,
size=None if file_path.is_dir() else file_path.stat().st_size,
mtime=file_path.stat().st_mtime,
)
)
return Result.ok(data_list)
@ -215,3 +217,13 @@ async def _(full_path: str) -> Result[str]:
return Result.ok(BuildImage.open(path).pic2bs4())
except Exception as e:
return Result.warning_(f"获取图片失败: {e!s}")
@router.get(
"/ping",
response_model=Result[str],
response_class=JSONResponse,
description="检查服务器状态",
)
async def _() -> Result[str]:
return Result.ok("pong")

View File

@ -14,6 +14,10 @@ class DirFile(BaseModel):
"""文件夹或文件名称"""
parent: str | None = None
"""父级"""
size: int | None = None
"""文件大小"""
mtime: float | None = None
"""修改时间"""
class DeleteFile(BaseModel):

View File

@ -11,7 +11,7 @@ import psutil
import ujson as json
from zhenxun.configs.config import Config
from zhenxun.configs.path_config import DATA_PATH
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH
from .base_model import SystemFolderSize, SystemStatus, User
@ -28,6 +28,22 @@ if token_file.exists():
token_data = json.load(open(token_file, encoding="utf8"))
GROUP_HELP_PATH = DATA_PATH / "group_help"
SIMPLE_HELP_IMAGE = IMAGE_PATH / "SIMPLE_HELP.png"
SIMPLE_DETAIL_HELP_IMAGE = IMAGE_PATH / "SIMPLE_DETAIL_HELP.png"
def clear_help_image():
"""清理帮助图片"""
if SIMPLE_HELP_IMAGE.exists():
SIMPLE_HELP_IMAGE.unlink()
if SIMPLE_DETAIL_HELP_IMAGE.exists():
SIMPLE_DETAIL_HELP_IMAGE.unlink()
for file in GROUP_HELP_PATH.iterdir():
if file.is_file():
file.unlink()
def get_user(uname: str) -> User | None:
"""获取账号密码