bugfix:修复sqlite部分场景下锁竞争问题;新增插件恶意触发配置文件 (#2144)

* bugfix:修复sqlite部分场景下锁竞争问题;新增插件恶意触发配置文件

* 文件没同步完
This commit is contained in:
Copaan
2026-06-24 09:11:03 +08:00
committed by GitHub
parent 73cbe2a609
commit f4d2342693
39 changed files with 1577 additions and 829 deletions
@@ -7,7 +7,7 @@ from nonebot.config import Config
from zhenxun.services.log import logger
from ....base_model import BaseResultModel, QueryModel, Result
from ....utils import authentication
from ....utils import DB_BUSY_MESSAGE, authentication
from .data_source import ApiDataSource
from .model import AllChatAndCallCount, BotInfo, ChatCallMonthCount, QueryChatCallCount
@@ -28,6 +28,8 @@ driver = nonebot.get_driver()
async def _() -> Result[list[BotInfo]]:
try:
return Result.ok(await ApiDataSource.get_bot_list(), "拿到信息啦!")
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_bot_list 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -45,6 +47,8 @@ async def _(bot_id: str | None = None) -> Result[QueryChatCallCount]:
return Result.ok(
await ApiDataSource.get_chat_and_call_count(bot_id), "拿到信息啦!"
)
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_chat_and_call_count 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -62,6 +66,8 @@ async def _(bot_id: str | None = None) -> Result[AllChatAndCallCount]:
return Result.ok(
await ApiDataSource.get_all_chat_and_call_count(bot_id), "拿到信息啦!"
)
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(
f"{router.prefix}/get_all_chat_and_call_count 调用错误", "WebUi", e=e
@@ -81,6 +87,8 @@ async def _(bot_id: str | None = None) -> Result[ChatCallMonthCount]:
return Result.ok(
await ApiDataSource.get_chat_and_call_month(bot_id), "拿到信息啦!"
)
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_chat_and_call_month 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -17,6 +17,7 @@ from zhenxun.utils.manager.priority_manager import PriorityLifecycle
from zhenxun.utils.platform import PlatformUtils
from ....base_model import BaseResultModel, QueryModel
from ....utils import webui_db_call
from ..main.data_source import bot_live
from .model import (
AllChatAndCallCount,
@@ -77,14 +78,20 @@ class ApiDataSource:
logger.warning("获取bot好友/群组信息失败...", "WebUi", e=e)
bot_info.group_count = 0
bot_info.friend_count = 0
bot_info.day_call = await Statistics.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute),
bot_id=bot.self_id,
).count()
bot_info.received_messages = await ChatHistory.filter(
bot_id=bot_info.self_id,
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute),
).count()
bot_info.day_call = await webui_db_call(
Statistics.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute),
bot_id=bot.self_id,
).count(),
"Dashboard.bot_day_call",
)
bot_info.received_messages = await webui_db_call(
ChatHistory.filter(
bot_id=bot_info.self_id,
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute),
).count(),
"Dashboard.bot_received_messages",
)
bot_info.connect_time = bot_live.get(bot.self_id) or 0
if bot_info.connect_time:
connect_date = datetime.fromtimestamp(CONNECT_TIME)
@@ -117,17 +124,29 @@ class ApiDataSource:
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()
chat_all_count = await webui_db_call(
query.annotate().count(),
"Dashboard.chat_all_count",
)
chat_day_count = await webui_db_call(
query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.chat_day_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()
call_all_count = await webui_db_call(
query.annotate().count(),
"Dashboard.call_all_count",
)
call_day_count = await webui_db_call(
query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.call_day_count",
)
return QueryChatCallCount(
chat_num=chat_all_count,
chat_day=chat_day_count,
@@ -151,31 +170,51 @@ class ApiDataSource:
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()
chat_week_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=7, hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.chat_week_count",
)
chat_month_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.chat_month_count",
)
chat_year_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.chat_year_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()
call_week_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=7, hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.call_week_count",
)
call_month_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.call_month_count",
)
call_year_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count(),
"Dashboard.call_year_count",
)
return AllChatAndCallCount(
chat_week=chat_week_count,
chat_month=chat_month_count,
@@ -202,17 +241,19 @@ class ApiDataSource:
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)
chat_date_list = await webui_db_call(
chat_query.filter(create_time__gte=filter_date)
.annotate(date=RawSQL("DATE(create_time)"), count=Count("id"))
.group_by("date")
.values("date", "count")
.values("date", "count"),
"Dashboard.chat_month_series",
)
call_date_list = (
await call_query.filter(create_time__gte=filter_date)
call_date_list = await webui_db_call(
call_query.filter(create_time__gte=filter_date)
.annotate(date=RawSQL("DATE(create_time)"), count=Count("id"))
.group_by("date")
.values("date", "count")
.values("date", "count"),
"Dashboard.call_month_series",
)
date_list = []
chat_count_list = []
@@ -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 DB_BUSY_MESSAGE, authentication, get_system_status
from .data_source import ApiDataSource
from .model import (
ActiveGroup,
@@ -82,6 +82,8 @@ async def _(bot_id: str | None = None) -> Result[list[BaseInfo]]:
if not result:
Result.warning_("无Bot连接...")
return Result.ok(result, "拿到信息啦!")
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_base_info 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -97,6 +99,8 @@ async def _(bot_id: str | None = None) -> Result[list[BaseInfo]]:
async def _(bot_id: str | None = None) -> Result[QueryCount]:
try:
return Result.ok(await ApiDataSource.get_all_chat_count(bot_id), "拿到信息啦!")
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_all_chat_count 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -112,6 +116,8 @@ async def _(bot_id: str | None = None) -> Result[QueryCount]:
async def _(bot_id: str | None = None) -> Result[QueryCount]:
try:
return Result.ok(await ApiDataSource.get_all_call_count(bot_id), "拿到信息啦!")
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_all_call_count 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -188,6 +194,8 @@ async def _(
return Result.ok(
await ApiDataSource.get_active_group(date_type, bot_id), "拿到信息啦!"
)
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_active_group 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -207,6 +215,8 @@ async def _(
return Result.ok(
await ApiDataSource.get_hot_plugin(date_type, bot_id), "拿到信息啦!"
)
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_hot_plugin 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -294,9 +304,14 @@ async def system_logs_realtime(websocket: WebSocket, sleep: int = 5):
await asyncio.wait_for(websocket.send_text(system_status.json()), timeout=5)
try:
await asyncio.wait_for(disconnect_event.wait(), timeout=max(sleep, 1))
except TimeoutError:
except asyncio.TimeoutError:
pass
except (WebSocketDisconnect, ConnectionClosedError, ConnectionClosedOK):
except (
asyncio.CancelledError,
WebSocketDisconnect,
ConnectionClosedError,
ConnectionClosedOK,
):
pass
finally:
_SYSTEM_STATUS_CONNECTIONS.discard(websocket)
@@ -20,6 +20,7 @@ from zhenxun.utils.enum import PluginType
from zhenxun.utils.platform import PlatformUtils
from ....config import AVA_URL, GROUP_AVA_URL, QueryDateType
from ....utils import webui_db_call
from .model import (
ActiveGroup,
BaseInfo,
@@ -105,10 +106,13 @@ class ApiDataSource:
"""
now = datetime.now()
# 今日累计接收消息
select_bot.received_messages = await ChatHistory.filter(
bot_id=select_bot.self_id,
create_time__gte=now - timedelta(hours=now.hour),
).count()
select_bot.received_messages = await webui_db_call(
ChatHistory.filter(
bot_id=select_bot.self_id,
create_time__gte=now - timedelta(hours=now.hour),
).count(),
"Main.received_messages",
)
# 群聊数量
try:
select_bot.group_count = len(
@@ -129,13 +133,15 @@ class ApiDataSource:
connect_date = datetime.fromtimestamp(select_bot.connect_time)
select_bot.connect_date = connect_date.strftime("%Y-%m-%d %H:%M:%S")
select_bot.version = cls.__get_bot_version()
day_call = await Statistics.filter(
create_time__gte=now - timedelta(hours=now.hour)
).count()
day_call = await webui_db_call(
Statistics.filter(create_time__gte=now - timedelta(hours=now.hour)).count(),
"Main.day_call",
)
select_bot.day_call = day_call
select_bot.connect_count = await BotConnectLog.filter(
bot_id=select_bot.self_id
).count()
select_bot.connect_count = await webui_db_call(
BotConnectLog.filter(bot_id=select_bot.self_id).count(),
"Main.connect_count",
)
@classmethod
async def get_base_info(cls, bot_id: str | None) -> list[BaseInfo] | None:
@@ -177,21 +183,37 @@ class ApiDataSource:
query = ChatHistory
if bot_id:
query = query.filter(bot_id=bot_id)
all_count = await query.annotate().count()
day_count = await query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count()
week_count = await query.filter(
create_time__gte=now - timedelta(days=7, hours=now.hour, minutes=now.minute)
).count()
month_count = await query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count()
year_count = await query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count()
all_count = await webui_db_call(
query.annotate().count(),
"Main.chat_all_count",
)
day_count = await webui_db_call(
query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count(),
"Main.chat_day_count",
)
week_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=7, hours=now.hour, minutes=now.minute)
).count(),
"Main.chat_week_count",
)
month_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count(),
"Main.chat_month_count",
)
year_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count(),
"Main.chat_year_count",
)
return QueryCount(
num=all_count,
day=day_count,
@@ -214,21 +236,37 @@ class ApiDataSource:
query = Statistics
if bot_id:
query = query.filter(bot_id=bot_id)
all_count = await query.annotate().count()
day_count = await query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count()
week_count = await query.filter(
create_time__gte=now - timedelta(days=7, hours=now.hour, minutes=now.minute)
).count()
month_count = await query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count()
year_count = await query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count()
all_count = await webui_db_call(
query.annotate().count(),
"Main.call_all_count",
)
day_count = await webui_db_call(
query.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
).count(),
"Main.call_day_count",
)
week_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=7, hours=now.hour, minutes=now.minute)
).count(),
"Main.call_week_count",
)
month_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=30, hours=now.hour, minutes=now.minute)
).count(),
"Main.call_month_count",
)
year_count = await webui_db_call(
query.filter(
create_time__gte=now
- timedelta(days=365, hours=now.hour, minutes=now.minute)
).count(),
"Main.call_year_count",
)
return QueryCount(
num=all_count,
day=day_count,
@@ -296,19 +334,21 @@ class ApiDataSource:
list[ActiveGroup]: 活跃群组列表
"""
query = cls.__get_query(ChatHistory, date_type, bot_id)
data_list = (
await query.annotate(count=Count("id"))
data_list = await webui_db_call(
query.annotate(count=Count("id"))
.filter(group_id__not_isnull=True)
.group_by("group_id")
.order_by("-count")
.limit(5)
.values_list("group_id", "count")
.values_list("group_id", "count"),
"Main.active_group",
)
id2name = {}
if data_list:
if info_list := await GroupConsole.filter(
group_id__in=[x[0] for x in data_list]
).all():
if info_list := await webui_db_call(
GroupConsole.filter(group_id__in=[x[0] for x in data_list]).all(),
"Main.active_group_names",
):
for group_info in info_list:
id2name[group_info.group_id] = group_info.group_name
active_group_list = [
@@ -341,19 +381,23 @@ class ApiDataSource:
list[HotPlugin]: 热门插件列表
"""
query = cls.__get_query(Statistics, date_type, bot_id)
data_list = (
await query.annotate(count=Count("id"))
data_list = await webui_db_call(
query.annotate(count=Count("id"))
.group_by("plugin_name")
.order_by("-count")
.limit(5)
.values_list("plugin_name", "count")
.values_list("plugin_name", "count"),
"Main.hot_plugin",
)
hot_plugin_list = []
module_list = [x[0] for x in data_list]
plugins = await PluginInfo.get_plugins(
load_status=None,
filter_parent=False,
module__in=module_list,
plugins = await webui_db_call(
PluginInfo.get_plugins(
load_status=None,
filter_parent=False,
module__in=module_list,
),
"Main.hot_plugin_names",
)
module2name = {p.module: p.name for p in plugins}
for data in data_list:
@@ -12,7 +12,7 @@ from zhenxun.utils.platform import PlatformUtils
from ....base_model import Result
from ....config import AVA_URL, GROUP_AVA_URL
from ....utils import authentication
from ....utils import DB_BUSY_MESSAGE, authentication
from .data_source import ApiDataSource
from .model import (
ClearRequest,
@@ -294,6 +294,8 @@ async def _(bot_id: str, user_id: str) -> Result[UserDetail]:
if result
else Result.warning_("未找到该好友...")
)
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except (ValueError, KeyError):
return Result.warning_("指定Bot未连接...")
except Exception as e:
@@ -311,6 +313,8 @@ async def _(bot_id: str, user_id: str) -> Result[UserDetail]:
async def _(group_id: str) -> Result[GroupDetail]:
try:
return Result.ok(await ApiDataSource.get_group_detail(group_id), "拿到信息啦!")
except TimeoutError:
return Result.fail(DB_BUSY_MESSAGE)
except Exception as e:
logger.error(f"{router.prefix}/get_group_detail 调用错误", "WebUi", e=e)
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@@ -13,6 +13,7 @@ from zhenxun.utils.enum import RequestType
from zhenxun.utils.platform import PlatformUtils
from ....config import AVA_URL, GROUP_AVA_URL
from ....utils import webui_db_call
from .model import (
FriendRequestResult,
GroupDetail,
@@ -110,20 +111,24 @@ class ApiDataSource:
fd = [x for x in friend_list if x.user_id == user_id]
if not fd:
return None
like_plugin_list = (
await Statistics.filter(user_id=user_id)
like_plugin_list = await webui_db_call(
Statistics.filter(user_id=user_id)
.annotate(count=Count("id"))
.group_by("plugin_name")
.order_by("-count")
.limit(5)
.values_list("plugin_name", "count")
.values_list("plugin_name", "count"),
"Manage.friend_like_plugin",
)
like_plugin = {}
module_list = [x[0] for x in like_plugin_list]
plugins = await PluginInfo.get_plugins(
load_status=None,
filter_parent=False,
module__in=module_list,
plugins = await webui_db_call(
PluginInfo.get_plugins(
load_status=None,
filter_parent=False,
module__in=module_list,
),
"Manage.friend_like_plugin_names",
)
module2name = {p.module: p.name for p in plugins}
for data in like_plugin_list:
@@ -136,8 +141,14 @@ class ApiDataSource:
nickname=user.user_name,
remark="",
is_ban=await BanConsole.is_ban(user_id),
chat_count=await ChatHistory.filter(user_id=user_id).count(),
call_count=await Statistics.filter(user_id=user_id).count(),
chat_count=await webui_db_call(
ChatHistory.filter(user_id=user_id).count(),
"Manage.friend_chat_count",
),
call_count=await webui_db_call(
Statistics.filter(user_id=user_id).count(),
"Manage.friend_call_count",
),
like_plugin=like_plugin,
)
@@ -151,16 +162,20 @@ class ApiDataSource:
返回:
dict[str, int]: 插件与调用次数
"""
like_plugin_list = (
await Statistics.filter(group_id=group_id)
like_plugin_list = await webui_db_call(
Statistics.filter(group_id=group_id)
.annotate(count=Count("id"))
.group_by("plugin_name")
.order_by("-count")
.limit(5)
.values_list("plugin_name", "count")
.values_list("plugin_name", "count"),
"Manage.group_like_plugin",
)
like_plugin = {}
plugins = await PluginInfo.get_plugins()
plugins = await webui_db_call(
PluginInfo.get_plugins(),
"Manage.group_like_plugin_names",
)
module2name = {p.module: p.name for p in plugins}
for data in like_plugin_list:
name = module2name.get(data[0]) or data[0]
@@ -268,8 +283,14 @@ class ApiDataSource:
name=group.group_name,
member_count=group.member_count,
max_member_count=group.max_member_count,
chat_count=await ChatHistory.filter(group_id=group_id).count(),
call_count=await Statistics.filter(group_id=group_id).count(),
chat_count=await webui_db_call(
ChatHistory.filter(group_id=group_id).count(),
"Manage.group_chat_count",
),
call_count=await webui_db_call(
Statistics.filter(group_id=group_id).count(),
"Manage.group_call_count",
),
like_plugin=like_plugin,
level=group.level,
status=group.status,
@@ -49,6 +49,7 @@ async def _(param: PluginIr) -> Result:
from zhenxun.builtin_plugins.plugin_store import StoreManager
result = await StoreManager.add_plugin(str(param.id)) # type: ignore
logger.info(result.replace("\n", ";"), "插件商店")
return Result.ok(info=result)
except Exception as e:
return Result.fail(f"安装插件失败: {type(e)}: {e}")