重构webui适配 (#1801)

* ♻️ 使用Uninfo重构PlatformUtils基础方法

* 🩹 优化插件加载与模块格式转换逻辑

* 🚑 修复商店道具无法使用

* 🚑 修复道具无法正常使用

* 🔧 增加Bot状态管理及模块禁用功能

* 🎨  优化Web UI代码结构,修改target方法

* 🚨 auto fix by pre-commit hooks

* 🎨 添加菜单API及优化异常处理

* 🐛 优化菜单API及模型结构,修复WebUi插件列表Api

* 📝 更新仓库readme

* 🚨 add mdlint file

* 📝 Add help chapter.

* 🐛 修复优化AuthChecker逻辑

* 🐛 优化数据库API,移除冗余导入及修正SQL_DICT引用

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: BalconyJH <balconyjh@gmail.com>
This commit is contained in:
HibiKier
2024-12-25 12:03:49 +08:00
committed by GitHub
co-authored by pre-commit-ci[bot] BalconyJH
parent ebf05fd884
commit 35014e4048
32 changed files with 1939 additions and 1754 deletions
@@ -1,20 +1,14 @@
from datetime import datetime, timedelta
from fastapi import APIRouter
from fastapi.responses import JSONResponse
import nonebot
from nonebot import require
from nonebot.config import Config
from tortoise.expressions import RawSQL
from tortoise.functions import Count
from zhenxun.models.bot_connect_log import BotConnectLog
from zhenxun.models.chat_history import ChatHistory
from zhenxun.models.statistics import Statistics
from zhenxun.services.log import logger
from ....base_model import BaseResultModel, QueryModel, Result
from ....utils import authentication
from .data_source import BotManage
from .data_source import ApiDataSource
from .model import AllChatAndCallCount, BotInfo, ChatCallMonthCount, QueryChatCallCount
require("plugin_store")
@@ -33,8 +27,9 @@ driver = nonebot.get_driver()
)
async def _() -> Result[list[BotInfo]]:
try:
return Result.ok(await BotManage.get_bot_list(), "拿到信息啦!")
return Result.ok(await ApiDataSource.get_bot_list(), "拿到信息啦!")
except Exception as e:
logger.error(f"{router.prefix}/get_bot_list 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -46,29 +41,13 @@ async def _() -> Result[list[BotInfo]]:
description="获取聊天/调用记录的全部和今日数量",
)
async def _(bot_id: str | None = None) -> Result[QueryChatCallCount]:
now = datetime.now()
query = ChatHistory
if bot_id:
query = query.filter(bot_id=bot_id)
chat_all_count = await query.annotate().count()
chat_day_count = await query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count()
query = Statistics
if bot_id:
query = query.filter(bot_id=bot_id)
call_all_count = await query.annotate().count()
call_day_count = await query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count()
return Result.ok(
QueryChatCallCount(
chat_num=chat_all_count,
chat_day=chat_day_count,
call_num=call_all_count,
call_day=call_day_count,
try:
return Result.ok(
await ApiDataSource.get_chat_and_call_count(bot_id), "拿到信息啦!"
)
)
except Exception as e:
logger.error(f"{router.prefix}/get_chat_and_call_count 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@router.get(
@@ -79,41 +58,15 @@ async def _(bot_id: str | None = None) -> Result[QueryChatCallCount]:
description="获取聊天/调用记录的全部数据次数",
)
async def _(bot_id: str | None = None) -> Result[AllChatAndCallCount]:
now = datetime.now()
query = ChatHistory
if bot_id:
query = query.filter(bot_id=bot_id)
chat_week_count = await query.filter(
create_time__gte=now - timedelta(days=7, hours=now.hour, minutes=now.minute)
).count()
chat_month_count = await query.filter(
create_time__gte=now - timedelta(days=30, hours=now.hour, minutes=now.minute)
).count()
chat_year_count = await query.filter(
create_time__gte=now - timedelta(days=365, hours=now.hour, minutes=now.minute)
).count()
query = Statistics
if bot_id:
query = query.filter(bot_id=bot_id)
call_week_count = await query.filter(
create_time__gte=now - timedelta(days=7, hours=now.hour, minutes=now.minute)
).count()
call_month_count = await query.filter(
create_time__gte=now - timedelta(days=30, hours=now.hour, minutes=now.minute)
).count()
call_year_count = await query.filter(
create_time__gte=now - timedelta(days=365, hours=now.hour, minutes=now.minute)
).count()
return Result.ok(
AllChatAndCallCount(
chat_week=chat_week_count,
chat_month=chat_month_count,
chat_year=chat_year_count,
call_week=call_week_count,
call_month=call_month_count,
call_year=call_year_count,
try:
return Result.ok(
await ApiDataSource.get_all_chat_and_call_count(bot_id), "拿到信息啦!"
)
)
except Exception as e:
logger.error(
f"{router.prefix}/get_all_chat_and_call_count 调用错误", "WebUi", e=e
)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@router.get(
@@ -124,48 +77,13 @@ async def _(bot_id: str | None = None) -> Result[AllChatAndCallCount]:
deprecated="获取聊天/调用记录的一个月数量", # type: ignore
)
async def _(bot_id: str | None = None) -> Result[ChatCallMonthCount]:
now = datetime.now()
filter_date = now - timedelta(days=30, hours=now.hour, minutes=now.minute)
chat_query = ChatHistory
call_query = Statistics
if bot_id:
chat_query = chat_query.filter(bot_id=bot_id)
call_query = call_query.filter(bot_id=bot_id)
chat_date_list = (
await chat_query.filter(create_time__gte=filter_date)
.annotate(date=RawSQL("DATE(create_time)"), count=Count("id"))
.group_by("date")
.values("date", "count")
)
call_date_list = (
await call_query.filter(create_time__gte=filter_date)
.annotate(date=RawSQL("DATE(create_time)"), count=Count("id"))
.group_by("date")
.values("date", "count")
)
date_list = []
chat_count_list = []
call_count_list = []
chat_date2cnt = {str(date["date"]): date["count"] for date in chat_date_list}
call_date2cnt = {str(date["date"]): date["count"] for date in call_date_list}
date = now.date()
for _ in range(30):
if str(date) in chat_date2cnt:
chat_count_list.append(chat_date2cnt[str(date)])
else:
chat_count_list.append(0)
if str(date) in call_date2cnt:
call_count_list.append(call_date2cnt[str(date)])
else:
call_count_list.append(0)
date_list.append(str(date)[5:])
date -= timedelta(days=1)
chat_count_list.reverse()
call_count_list.reverse()
date_list.reverse()
return Result.ok(
ChatCallMonthCount(chat=chat_count_list, call=call_count_list, date=date_list)
)
try:
return Result.ok(
await ApiDataSource.get_chat_and_call_month(bot_id), "拿到信息啦!"
)
except Exception as e:
logger.error(f"{router.prefix}/get_chat_and_call_month 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@router.post(
@@ -176,18 +94,11 @@ async def _(bot_id: str | None = None) -> Result[ChatCallMonthCount]:
deprecated="获取Bot连接记录", # type: ignore
)
async def _(query: QueryModel) -> Result[BaseResultModel]:
total = await BotConnectLog.all().count()
if total % query.size:
total += 1
data = (
await BotConnectLog.all()
.order_by("-id")
.offset((query.index - 1) * query.size)
.limit(query.size)
)
for v in data:
v.connect_time = v.connect_time.replace(tzinfo=None).replace(microsecond=0)
return Result.ok(BaseResultModel(total=total, data=data))
try:
return Result.ok(await ApiDataSource.get_connect_log(query), "拿到信息啦!")
except Exception as e:
logger.error(f"{router.prefix}/get_connect_log 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@router.get(
@@ -4,13 +4,17 @@ import time
import nonebot
from nonebot.adapters import Bot
from nonebot.drivers import Driver
from tortoise.expressions import RawSQL
from tortoise.functions import Count
from zhenxun.models.bot_connect_log import BotConnectLog
from zhenxun.models.chat_history import ChatHistory
from zhenxun.models.statistics import Statistics
from zhenxun.utils.platform import PlatformUtils
from ....base_model import BaseResultModel, QueryModel
from ..main.data_source import bot_live
from .model import BotInfo
from .model import AllChatAndCallCount, BotInfo, ChatCallMonthCount, QueryChatCallCount
driver: Driver = nonebot.get_driver()
@@ -24,7 +28,7 @@ async def _():
CONNECT_TIME = int(time.time())
class BotManage:
class ApiDataSource:
@classmethod
async def __build_bot_info(cls, bot: Bot) -> BotInfo:
"""构建Bot信息
@@ -47,8 +51,7 @@ class BotManage:
bot_info = BotInfo(
self_id=bot.self_id, nickname=nickname, ava_url=ava_url, platform=platform
)
group_list, _ = await PlatformUtils.get_group_list(bot)
group_list = [g for g in group_list if g.channel_id is None]
group_list, _ = await PlatformUtils.get_group_list(bot, True)
friend_list, _ = await PlatformUtils.get_friend_list(bot)
bot_info.group_count = len(group_list)
bot_info.friend_count = len(friend_list)
@@ -77,3 +80,161 @@ class BotManage:
for _, bot in nonebot.get_bots().items():
bot_list.append(await cls.__build_bot_info(bot))
return bot_list
@classmethod
async def get_chat_and_call_count(cls, bot_id: str | None) -> QueryChatCallCount:
"""获取今日聊天和调用次数
参数:
bot_id: bot id
返回:
QueryChatCallCount: 数据内容
"""
now = datetime.now()
query = ChatHistory
if bot_id:
query = query.filter(bot_id=bot_id)
chat_all_count = await query.annotate().count()
chat_day_count = await query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count()
query = Statistics
if bot_id:
query = query.filter(bot_id=bot_id)
call_all_count = await query.annotate().count()
call_day_count = await query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count()
return QueryChatCallCount(
chat_num=chat_all_count,
chat_day=chat_day_count,
call_num=call_all_count,
call_day=call_day_count,
)
@classmethod
async def get_all_chat_and_call_count(
cls, bot_id: str | None
) -> AllChatAndCallCount:
"""获取全部聊天和调用记录
参数:
bot_id: bot id
返回:
AllChatAndCallCount: 数据内容
"""
now = datetime.now()
query = ChatHistory
if bot_id:
query = query.filter(bot_id=bot_id)
chat_week_count = await query.filter(
create_time__gte=now - timedelta(days=7, hours=now.hour, minutes=now.minute)
).count()
chat_month_count = await query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count()
chat_year_count = await query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count()
query = Statistics
if bot_id:
query = query.filter(bot_id=bot_id)
call_week_count = await query.filter(
create_time__gte=now - timedelta(days=7, hours=now.hour, minutes=now.minute)
).count()
call_month_count = await query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count()
call_year_count = await query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count()
return AllChatAndCallCount(
chat_week=chat_week_count,
chat_month=chat_month_count,
chat_year=chat_year_count,
call_week=call_week_count,
call_month=call_month_count,
call_year=call_year_count,
)
@classmethod
async def get_chat_and_call_month(cls, bot_id: str | None) -> ChatCallMonthCount:
"""获取一个月内的调用/消息记录次数,并根据日期对数据填充0
参数:
bot_id: bot id
返回:
ChatCallMonthCount: 数据内容
"""
now = datetime.now()
filter_date = now - timedelta(days=30, hours=now.hour, minutes=now.minute)
chat_query = ChatHistory
call_query = Statistics
if bot_id:
chat_query = chat_query.filter(bot_id=bot_id)
call_query = call_query.filter(bot_id=bot_id)
chat_date_list = (
await chat_query.filter(create_time__gte=filter_date)
.annotate(date=RawSQL("DATE(create_time)"), count=Count("id"))
.group_by("date")
.values("date", "count")
)
call_date_list = (
await call_query.filter(create_time__gte=filter_date)
.annotate(date=RawSQL("DATE(create_time)"), count=Count("id"))
.group_by("date")
.values("date", "count")
)
date_list = []
chat_count_list = []
call_count_list = []
chat_date2cnt = {str(date["date"]): date["count"] for date in chat_date_list}
call_date2cnt = {str(date["date"]): date["count"] for date in call_date_list}
date = now.date()
for _ in range(30):
if str(date) in chat_date2cnt:
chat_count_list.append(chat_date2cnt[str(date)])
else:
chat_count_list.append(0)
if str(date) in call_date2cnt:
call_count_list.append(call_date2cnt[str(date)])
else:
call_count_list.append(0)
date_list.append(str(date)[5:])
date -= timedelta(days=1)
chat_count_list.reverse()
call_count_list.reverse()
date_list.reverse()
return ChatCallMonthCount(
chat=chat_count_list, call=call_count_list, date=date_list
)
@classmethod
async def get_connect_log(cls, query: QueryModel) -> BaseResultModel:
"""获取bot连接日志
参数:
query: 查询模型
返回:
BaseResultModel: 数据内容
"""
total = await BotConnectLog.all().count()
if total % query.size:
total += 1
data = (
await BotConnectLog.all()
.order_by("-id")
.offset((query.index - 1) * query.size)
.limit(query.size)
)
for v in data:
v.connect_time = v.connect_time.replace(tzinfo=None).replace(microsecond=0)
return BaseResultModel(total=total, data=data)