版本更新

This commit is contained in:
HibiKier
2024-10-20 21:11:16 +08:00
parent 4e33bf3a50
commit d594d17bf6
253 changed files with 34987 additions and 2241 deletions
@@ -1,22 +1,201 @@
from datetime import datetime, timedelta
import nonebot
from nonebot import require
from fastapi import APIRouter
from nonebot.config import Config
from tortoise.functions import Count
from tortoise.expressions import RawSQL
from fastapi.responses import JSONResponse
from zhenxun.models.statistics import Statistics
from zhenxun.models.chat_history import ChatHistory
from zhenxun.models.bot_connect_log import BotConnectLog
from ....base_model import Result
from .data_source import BotManage
from ....utils import authentication
from ....base_model import Result, QueryModel, BaseResultModel
from .model import BotInfo, ChatCallMonthCount, QueryChatCallCount, AllChatAndCallCount
require("plugin_store")
router = APIRouter(prefix="/dashboard")
driver = nonebot.get_driver()
@router.get(
"/get_bot_list",
dependencies=[authentication()],
response_model=Result[list[BotInfo]],
response_class=JSONResponse,
deprecated="获取bot列表", # type: ignore
)
async def _() -> Result:
async def _() -> Result[list[BotInfo]]:
try:
return Result.ok(await BotManage.get_bot_list(), "拿到信息啦!")
except Exception as e:
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
@router.get(
"/get_chat_and_call_count",
dependencies=[authentication()],
response_model=Result[QueryChatCallCount],
response_class=JSONResponse,
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,
)
)
@router.get(
"/get_all_chat_and_call_count",
dependencies=[authentication()],
response_model=Result[AllChatAndCallCount],
response_class=JSONResponse,
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,
)
)
@router.get(
"/get_chat_and_call_month",
dependencies=[authentication()],
response_model=Result[ChatCallMonthCount],
response_class=JSONResponse,
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)
)
@router.post(
"/get_connect_log",
dependencies=[authentication()],
response_model=Result[BaseResultModel],
response_class=JSONResponse,
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))
@router.get(
"/get_nonebot_config",
dependencies=[authentication()],
response_model=Result[Config],
response_class=JSONResponse,
deprecated="获取nb配置", # type: ignore
)
async def _() -> Result[Config]:
return Result.ok(driver.config)
@@ -49,11 +49,12 @@ class BotManage:
)
group_list, _ = await PlatformUtils.get_group_list(bot)
group_list = [g for g in group_list if g.channel_id is None]
friend_list = await PlatformUtils.get_friend_list(bot)
friend_list, _ = await PlatformUtils.get_friend_list(bot)
bot_info.group_count = len(group_list)
bot_info.friend_count = len(friend_list)
bot_info.day_call = await Statistics.filter(
create_time__gte=now - timedelta(hours=now.hour, minutes=now.minute)
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,
@@ -62,10 +63,7 @@ class BotManage:
bot_info.connect_time = bot_live.get(bot.self_id) or 0
if bot_info.connect_time:
connect_date = datetime.fromtimestamp(CONNECT_TIME)
connect_date_str = connect_date.strftime("%Y-%m-%d %H:%M:%S")
bot_info.connect_date = datetime.strptime(
connect_date_str, "%Y-%m-%d %H:%M:%S"
)
bot_info.connect_date = connect_date.strftime("%Y-%m-%d %H:%M:%S")
return bot_info
@classmethod
@@ -1,5 +1,3 @@
from datetime import datetime
from pydantic import BaseModel
@@ -22,5 +20,52 @@ class BotInfo(BaseModel):
"""今日调用插件次数"""
connect_time: int = 0
"""连接时间"""
connect_date: datetime | None = None
connect_date: str | None = None
"""连接日期"""
class QueryChatCallCount(BaseModel):
"""
查询聊天/调用记录次数
"""
chat_num: int
"""聊天记录总数"""
chat_day: int
"""今日消息"""
call_num: int
"""调用记录总数"""
call_day: int
"""今日调用"""
class ChatCallMonthCount(BaseModel):
"""
查询聊天/调用一个月记录次数
"""
chat: list[int]
"""一个月内聊天总数"""
call: list[int]
"""一个月内调用数据"""
date: list[str]
"""日期"""
class AllChatAndCallCount(BaseModel):
"""
查询聊天/调用记录次数
"""
chat_week: int
"""一周内聊天次数"""
chat_month: int
"""一月内聊天次数"""
chat_year: int
"""一年内聊天次数"""
call_week: int
"""一周内调用次数"""
call_month: int
"""一月内调用次数"""
call_year: int
"""一年内调用次数"""
@@ -2,6 +2,7 @@ import nonebot
from tortoise import Tortoise
from nonebot.drivers import Driver
from fastapi import Request, APIRouter
from fastapi.responses import JSONResponse
from tortoise.exceptions import OperationalError
from zhenxun.models.task_info import TaskInfo
@@ -62,26 +63,40 @@ async def _():
@router.get(
"/get_table_list", dependencies=[authentication()], description="获取数据库表"
"/get_table_list",
dependencies=[authentication()],
response_model=Result[list[dict]],
response_class=JSONResponse,
description="获取数据库表",
)
async def _() -> Result:
async def _() -> Result[list[dict]]:
db = Tortoise.get_connection("default")
query = await db.execute_query_dict(SELECT_TABLE_SQL)
return Result.ok(query)
@router.get(
"/get_table_column", dependencies=[authentication()], description="获取表字段"
"/get_table_column",
dependencies=[authentication()],
response_model=Result[list[dict]],
response_class=JSONResponse,
description="获取表字段",
)
async def _(table_name: str) -> Result:
async def _(table_name: str) -> Result[list[dict]]:
db = Tortoise.get_connection("default")
# print(SELECT_TABLE_COLUMN_SQL.format(table_name))
query = await db.execute_query_dict(SELECT_TABLE_COLUMN_SQL.format(table_name))
return Result.ok(query)
@router.post("/exec_sql", dependencies=[authentication()], description="执行sql")
async def _(sql: SqlText, request: Request) -> Result:
@router.post(
"/exec_sql",
dependencies=[authentication()],
response_model=Result[list[dict]],
response_class=JSONResponse,
description="执行sql",
)
async def _(sql: SqlText, request: Request) -> Result[list[dict]]:
ip = request.client.host if request.client else "unknown"
try:
if sql.sql.lower().startswith("select"):
@@ -98,8 +113,14 @@ async def _(sql: SqlText, request: Request) -> Result:
return Result.warning_(f"sql执行错误: {e}")
@router.post("/get_sql_log", dependencies=[authentication()], description="sql日志列表")
async def _(query: QueryModel) -> Result:
@router.post(
"/get_sql_log",
dependencies=[authentication()],
response_model=Result[BaseResultModel],
response_class=JSONResponse,
description="sql日志列表",
)
async def _(query: QueryModel) -> Result[BaseResultModel]:
total = await SqlLog.all().count()
if total % query.size:
total += 1
@@ -112,8 +133,14 @@ async def _(query: QueryModel) -> Result:
return Result.ok(BaseResultModel(total=total, data=data))
@router.get("/get_common_sql", dependencies=[authentication()], description="常用sql")
async def _(plugin_name: str | None = None) -> Result:
@router.get(
"/get_common_sql",
dependencies=[authentication()],
response_model=Result[dict],
response_class=JSONResponse,
description="常用sql",
)
async def _(plugin_name: str | None = None) -> Result[dict]:
if plugin_name:
return Result.ok(SQL_DICT.get(plugin_name))
return Result.ok(str(SQL_DICT))
@@ -6,31 +6,48 @@ from datetime import datetime, timedelta
import nonebot
from fastapi import APIRouter
from nonebot.config import Config
from tortoise.functions import Count
from fastapi.responses import JSONResponse
from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError
from starlette.websockets import WebSocket, WebSocketState, WebSocketDisconnect
from zhenxun.services.log import logger
from zhenxun.models.group_info import GroupInfo
from zhenxun.models.statistics import Statistics
from zhenxun.utils.platform import PlatformUtils
from zhenxun.models.plugin_info import PluginInfo
from zhenxun.models.chat_history import ChatHistory
from zhenxun.models.group_console import GroupConsole
from zhenxun.models.bot_connect_log import BotConnectLog
from ....base_model import Result
from .data_source import bot_live
from ....utils import authentication, get_system_status
from ....config import AVA_URL, GROUP_AVA_URL, QueryDateType
from .model import BaseInfo, HotPlugin, ActiveGroup, ChatHistoryCount
from .model import (
BaseInfo,
HotPlugin,
QueryCount,
ActiveGroup,
NonebotData,
TemplateBaseInfo,
)
driver = nonebot.get_driver()
run_time = time.time()
ws_router = APIRouter()
router = APIRouter(prefix="/main")
@router.get("/get_base_info", dependencies=[authentication()], description="基础信息")
async def _(bot_id: str | None = None) -> Result:
@router.get(
"/get_base_info",
dependencies=[authentication()],
response_model=Result[list[BaseInfo]],
response_class=JSONResponse,
description="基础信息",
)
async def _(bot_id: str | None = None) -> Result[list[BaseInfo]]:
"""获取Bot基础信息
参数:
@@ -39,13 +56,14 @@ async def _(bot_id: str | None = None) -> Result:
返回:
Result: 获取指定bot信息与bot列表
"""
bot_list: list[BaseInfo] = []
global run_time
bot_list: list[TemplateBaseInfo] = []
if bots := nonebot.get_bots():
select_bot: BaseInfo
for key, bot in bots.items():
for _, bot in bots.items():
login_info = await bot.get_login_info()
bot_list.append(
BaseInfo(
TemplateBaseInfo(
bot=bot, # type: ignore
self_id=bot.self_id,
nickname=login_info["nickname"],
@@ -58,7 +76,6 @@ async def _(bot_id: str | None = None) -> Result:
else:
select_bot = bot_list[0]
select_bot.is_select = True
select_bot.config = select_bot.bot.config
now = datetime.now()
# 今日累计接收消息
select_bot.received_messages = await ChatHistory.filter(
@@ -82,10 +99,7 @@ async def _(bot_id: str | None = None) -> Result:
select_bot.connect_time = bot_live.get(select_bot.self_id) or 0
if select_bot.connect_time:
connect_date = datetime.fromtimestamp(select_bot.connect_time)
connect_date_str = connect_date.strftime("%Y-%m-%d %H:%M:%S")
select_bot.connect_date = datetime.strptime(
connect_date_str, "%Y-%m-%d %H:%M:%S"
)
select_bot.connect_date = connect_date.strftime("%Y-%m-%d %H:%M:%S")
version_file = Path() / "__version__"
if version_file.exists():
if text := version_file.open().read():
@@ -95,30 +109,40 @@ async def _(bot_id: str | None = None) -> Result:
create_time__gte=now - timedelta(hours=now.hour)
).count()
select_bot.day_call = day_call
return Result.ok(bot_list, "拿到信息啦!")
select_bot.connect_count = await BotConnectLog.filter(
bot_id=select_bot.self_id
).count()
return Result.ok([BaseInfo(**e.dict()) for e in bot_list], "拿到信息啦!")
return Result.warning_("无Bot连接...")
@router.get(
"/get_all_ch_count", dependencies=[authentication()], description="获取接收消息数量"
"/get_all_chat_count",
dependencies=[authentication()],
response_model=Result[QueryCount],
response_class=JSONResponse,
description="获取接收消息数量",
)
async def _(bot_id: str) -> Result:
async def _(bot_id: str | None = None) -> Result[QueryCount]:
now = datetime.now()
all_count = await ChatHistory.filter(bot_id=bot_id).count()
day_count = await ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(hours=now.hour)
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 ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(days=7)
week_count = await query.filter(
create_time__gte=now - timedelta(days=7, hours=now.hour, minutes=now.minute)
).count()
month_count = await ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(days=30)
month_count = await query.filter(
create_time__gte=now - timedelta(days=30, hours=now.hour, minutes=now.minute)
).count()
year_count = await ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(days=365)
year_count = await query.filter(
create_time__gte=now - timedelta(days=365, hours=now.hour, minutes=now.minute)
).count()
return Result.ok(
ChatHistoryCount(
QueryCount(
num=all_count,
day=day_count,
week=week_count,
@@ -129,44 +153,49 @@ async def _(bot_id: str) -> Result:
@router.get(
"/get_ch_count", dependencies=[authentication()], description="获取接收消息数量"
"/get_all_call_count",
dependencies=[authentication()],
response_model=Result[QueryCount],
response_class=JSONResponse,
description="获取调用次数",
)
async def _(bot_id: str, query_type: QueryDateType | None = None) -> Result:
if nonebot.get_bot(bot_id):
if not query_type:
return Result.ok(await ChatHistory.filter(bot_id=bot_id).count())
now = datetime.now()
if query_type == QueryDateType.DAY:
return Result.ok(
await ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(hours=now.hour)
).count()
)
if query_type == QueryDateType.WEEK:
return Result.ok(
await ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(days=7)
).count()
)
if query_type == QueryDateType.MONTH:
return Result.ok(
await ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(days=30)
).count()
)
if query_type == QueryDateType.YEAR:
return Result.ok(
await ChatHistory.filter(
bot_id=bot_id, create_time__gte=now - timedelta(days=365)
).count()
)
return Result.warning_("无Bot连接...")
async def _(bot_id: str | None = None) -> Result[QueryCount]:
now = datetime.now()
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()
return Result.ok(
QueryCount(
num=all_count,
day=day_count,
week=week_count,
month=month_count,
year=year_count,
)
)
@router.get(
"get_fg_count", dependencies=[authentication()], description="好友/群组数量"
"get_fg_count",
dependencies=[authentication()],
response_model=Result[dict[str, int]],
response_class=JSONResponse,
description="好友/群组数量",
)
async def _(bot_id: str) -> Result:
async def _(bot_id: str) -> Result[dict[str, int]]:
if bots := nonebot.get_bots():
if bot_id not in bots:
return Result.warning_("指定Bot未连接...")
@@ -183,26 +212,60 @@ async def _(bot_id: str) -> Result:
@router.get(
"/get_run_time", dependencies=[authentication()], description="获取nb运行时间"
"/get_nb_data",
dependencies=[authentication()],
response_model=Result[NonebotData],
response_class=JSONResponse,
description="获取nb数据",
)
async def _() -> Result:
return Result.ok(int(time.time() - run_time))
async def _() -> Result[NonebotData]:
return Result.ok(NonebotData(config=driver.config, run_time=int(run_time)))
@router.get(
"/get_active_group", dependencies=[authentication()], description="获取活跃群聊"
"/get_nb_config",
dependencies=[authentication()],
response_model=Result[Config],
response_class=JSONResponse,
description="获取nb配置",
)
async def _(date_type: QueryDateType | None = None) -> Result:
async def _() -> Result[Config]:
return Result.ok(driver.config)
@router.get(
"/get_run_time",
dependencies=[authentication()],
response_model=Result[int],
response_class=JSONResponse,
description="获取nb运行时间",
)
async def _() -> Result[int]:
return Result.ok(int(run_time))
@router.get(
"/get_active_group",
dependencies=[authentication()],
response_model=Result[list[ActiveGroup]],
response_class=JSONResponse,
description="获取活跃群聊",
)
async def _(
date_type: QueryDateType | None = None, bot_id: str | None = None
) -> Result[list[ActiveGroup]]:
query = ChatHistory
now = datetime.now()
if bot_id:
query = query.filter(bot_id=bot_id)
if date_type == QueryDateType.DAY:
query = ChatHistory.filter(create_time__gte=now - timedelta(hours=now.hour))
query = query.filter(create_time__gte=now - timedelta(hours=now.hour))
if date_type == QueryDateType.WEEK:
query = ChatHistory.filter(create_time__gte=now - timedelta(days=7))
query = query.filter(create_time__gte=now - timedelta(days=7))
if date_type == QueryDateType.MONTH:
query = ChatHistory.filter(create_time__gte=now - timedelta(days=30))
query = query.filter(create_time__gte=now - timedelta(days=30))
if date_type == QueryDateType.YEAR:
query = ChatHistory.filter(create_time__gte=now - timedelta(days=365))
query = query.filter(create_time__gte=now - timedelta(days=365))
data_list = (
await query.annotate(count=Count("id"))
.filter(group_id__not_isnull=True)
@@ -213,7 +276,7 @@ async def _(date_type: QueryDateType | None = None) -> Result:
)
id2name = {}
if data_list:
if info_list := await GroupInfo.filter(
if info_list := await GroupConsole.filter(
group_id__in=[x[0] for x in data_list]
).all():
for group_info in info_list:
@@ -236,19 +299,27 @@ async def _(date_type: QueryDateType | None = None) -> Result:
@router.get(
"/get_hot_plugin", dependencies=[authentication()], description="获取热门插件"
"/get_hot_plugin",
dependencies=[authentication()],
response_model=Result[list[HotPlugin]],
response_class=JSONResponse,
description="获取热门插件",
)
async def _(date_type: QueryDateType | None = None) -> Result:
async def _(
date_type: QueryDateType | None = None, bot_id: str | None = None
) -> Result[list[HotPlugin]]:
query = Statistics
now = datetime.now()
if bot_id:
query = query.filter(bot_id=bot_id)
if date_type == QueryDateType.DAY:
query = Statistics.filter(create_time__gte=now - timedelta(hours=now.hour))
query = query.filter(create_time__gte=now - timedelta(hours=now.hour))
if date_type == QueryDateType.WEEK:
query = Statistics.filter(create_time__gte=now - timedelta(days=7))
query = query.filter(create_time__gte=now - timedelta(days=7))
if date_type == QueryDateType.MONTH:
query = Statistics.filter(create_time__gte=now - timedelta(days=30))
query = query.filter(create_time__gte=now - timedelta(days=30))
if date_type == QueryDateType.YEAR:
query = Statistics.filter(create_time__gte=now - timedelta(days=365))
query = query.filter(create_time__gte=now - timedelta(days=365))
data_list = (
await query.annotate(count=Count("id"))
.group_by("plugin_name")
@@ -281,4 +352,3 @@ async def system_logs_realtime(websocket: WebSocket, sleep: int = 5):
system_status = await get_system_status()
await websocket.send_text(system_status.json())
await asyncio.sleep(sleep)
return
@@ -1,8 +1,8 @@
import time
import nonebot
from nonebot.adapters.onebot.v11 import Bot
from nonebot.drivers import Driver
from nonebot.adapters.onebot.v11 import Bot
driver: Driver = nonebot.get_driver()
@@ -1,8 +1,6 @@
from datetime import datetime
from pydantic import BaseModel
from nonebot.adapters import Bot
from nonebot.config import Config
from pydantic import BaseModel
class SystemStatus(BaseModel):
@@ -20,8 +18,6 @@ class BaseInfo(BaseModel):
基础信息
"""
bot: Bot
"""Bot"""
self_id: str
"""SELF ID"""
nickname: str
@@ -36,8 +32,10 @@ class BaseInfo(BaseModel):
"""今日 累计接收消息"""
connect_time: int = 0
"""连接时间"""
connect_date: datetime | None = None
connect_date: str | None = None
"""连接日期"""
connect_count: int = 0
"""连接次数"""
plugin_count: int = 0
"""加载插件数量"""
@@ -48,9 +46,6 @@ class BaseInfo(BaseModel):
is_select: bool = False
"""当前选择"""
config: Config | None = None
"""nb配置"""
day_call: int = 0
"""今日调用插件次数"""
version: str = "unknown"
@@ -60,7 +55,16 @@ class BaseInfo(BaseModel):
arbitrary_types_allowed = True
class ChatHistoryCount(BaseModel):
class TemplateBaseInfo(BaseInfo):
"""
基础信息
"""
bot: Bot
"""bot"""
class QueryCount(BaseModel):
"""
聊天记录数量
"""
@@ -103,3 +107,10 @@ class HotPlugin(BaseModel):
"""插件名称"""
count: int
"""调用次数"""
class NonebotData(BaseModel):
config: Config
"""nb配置"""
run_time: int
"""运行时间"""
@@ -1,6 +1,7 @@
import nonebot
from fastapi import APIRouter
from tortoise.functions import Count
from fastapi.responses import JSONResponse
from nonebot.adapters.onebot.v11 import ActionFailed
from zhenxun.services.log import logger
@@ -41,7 +42,11 @@ router = APIRouter(prefix="/manage")
@router.get(
"/get_group_list", dependencies=[authentication()], description="获取群组列表"
"/get_group_list",
dependencies=[authentication()],
response_model=Result[list[GroupResult]],
response_class=JSONResponse,
description="获取群组列表",
)
async def _(bot_id: str) -> Result:
"""
@@ -65,9 +70,13 @@ async def _(bot_id: str) -> Result:
@router.post(
"/update_group", dependencies=[authentication()], description="修改群组信息"
"/update_group",
dependencies=[authentication()],
response_model=Result[str],
response_class=JSONResponse,
description="修改群组信息",
)
async def _(group: UpdateGroup) -> Result:
async def _(group: UpdateGroup) -> Result[str]:
try:
group_id = group.group_id
if db_group := await GroupConsole.get_group(group_id):
@@ -75,9 +84,11 @@ async def _(group: UpdateGroup) -> Result:
db_group.level = group.level
db_group.status = group.status
if group.close_plugins:
group.close_plugins = [f"<{module}" for module in group.close_plugins]
db_group.block_plugin = ",".join(group.close_plugins) + ","
if group.task:
if block_task := [t for t in task_list if t not in group.task]:
block_task = [f"<{module}" for module in block_task]
db_group.block_task = ",".join(block_task) + "," # type: ignore
await db_group.save(
update_fields=["level", "status", "block_plugin", "block_task"]
@@ -89,9 +100,13 @@ async def _(group: UpdateGroup) -> Result:
@router.get(
"/get_friend_list", dependencies=[authentication()], description="获取好友列表"
"/get_friend_list",
dependencies=[authentication()],
response_model=Result[list[Friend]],
response_class=JSONResponse,
description="获取好友列表",
)
async def _(bot_id: str) -> Result:
async def _(bot_id: str) -> Result[list[Friend]]:
"""
获取群信息
"""
@@ -116,9 +131,13 @@ async def _(bot_id: str) -> Result:
@router.get(
"/get_request_count", dependencies=[authentication()], description="获取请求数量"
"/get_request_count",
dependencies=[authentication()],
response_model=Result[dict[str, int]],
response_class=JSONResponse,
description="获取请求数量",
)
async def _() -> Result:
async def _() -> Result[dict[str, int]]:
f_count = await FgRequest.filter(
request_type=RequestType.FRIEND, handle_type__isnull=True
).count()
@@ -133,9 +152,13 @@ async def _() -> Result:
@router.get(
"/get_request_list", dependencies=[authentication()], description="获取请求列表"
"/get_request_list",
dependencies=[authentication()],
response_model=Result[ReqResult],
response_class=JSONResponse,
description="获取请求列表",
)
async def _() -> Result:
async def _() -> Result[ReqResult]:
try:
req_result = ReqResult()
data_list = await FgRequest.filter(handle_type__isnull=True).all()
@@ -177,7 +200,11 @@ async def _() -> Result:
@router.post(
"/clear_request", dependencies=[authentication()], description="清空请求列表"
"/clear_request",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="清空请求列表",
)
async def _(cr: ClearRequest) -> Result:
await FgRequest.filter(
@@ -186,7 +213,13 @@ async def _(cr: ClearRequest) -> Result:
return Result.ok(info="成功清除了数据!")
@router.post("/refuse_request", dependencies=[authentication()], description="拒绝请求")
@router.post(
"/refuse_request",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="拒绝请求",
)
async def _(parma: HandleRequest) -> Result:
try:
if bots := nonebot.get_bots():
@@ -207,14 +240,24 @@ async def _(parma: HandleRequest) -> Result:
return Result.fail(f"{type(e)}: {e}")
@router.post("/delete_request", dependencies=[authentication()], description="忽略请求")
@router.post(
"/delete_request",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="忽略请求",
)
async def _(parma: HandleRequest) -> Result:
await FgRequest.ignore(parma.id)
return Result.ok(info="成功处理了请求!")
@router.post(
"/approve_request", dependencies=[authentication()], description="同意请求"
"/approve_request",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="同意请求",
)
async def _(parma: HandleRequest) -> Result:
try:
@@ -245,7 +288,13 @@ async def _(parma: HandleRequest) -> Result:
return Result.fail(f"{type(e)}: {e}")
@router.post("/leave_group", dependencies=[authentication()], description="退群")
@router.post(
"/leave_group",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="退群",
)
async def _(param: LeaveGroup) -> Result:
try:
if bots := nonebot.get_bots():
@@ -264,7 +313,13 @@ async def _(param: LeaveGroup) -> Result:
return Result.fail(f"{type(e)}: {e}")
@router.post("/delete_friend", dependencies=[authentication()], description="删除好友")
@router.post(
"/delete_friend",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="删除好友",
)
async def _(param: DeleteFriend) -> Result:
try:
if bots := nonebot.get_bots():
@@ -284,9 +339,13 @@ async def _(param: DeleteFriend) -> Result:
@router.get(
"/get_friend_detail", dependencies=[authentication()], description="获取好友详情"
"/get_friend_detail",
dependencies=[authentication()],
response_model=Result[UserDetail],
response_class=JSONResponse,
description="获取好友详情",
)
async def _(bot_id: str, user_id: str) -> Result:
async def _(bot_id: str, user_id: str) -> Result[UserDetail]:
if bots := nonebot.get_bots():
if bot_id in bots:
if fd := [
@@ -327,9 +386,13 @@ async def _(bot_id: str, user_id: str) -> Result:
@router.get(
"/get_group_detail", dependencies=[authentication()], description="获取群组详情"
"/get_group_detail",
dependencies=[authentication()],
response_model=Result[GroupDetail],
response_class=JSONResponse,
description="获取群组详情",
)
async def _(bot_id: str, group_id: str) -> Result:
async def _(bot_id: str, group_id: str) -> Result[GroupDetail]:
if not (bots := nonebot.get_bots()):
return Result.warning_("无Bot连接...")
if bot_id not in bots:
@@ -346,34 +409,46 @@ async def _(bot_id: str, group_id: str) -> Result:
.values_list("plugin_name", "count")
)
like_plugin = {}
plugins = await PluginInfo.all()
plugins = await PluginInfo.get_plugins()
module2name = {p.module: p.name for p in plugins}
for data in like_plugin_list:
name = module2name.get(data[0]) or data[0]
like_plugin[name] = data[1]
close_plugins = []
close_plugins: list[Plugin] = []
if group.block_plugin:
for module in group.block_plugin.split(","):
module_ = module.replace(":super", "")
is_super_block = module.endswith(":super")
plugin = Plugin(
module=module_,
plugin_name=module,
is_super_block=is_super_block,
)
plugin.plugin_name = module2name.get(module) or module
close_plugins.append(plugin)
for module in group.block_plugin.replace("<", "").split(","):
if module:
plugin = Plugin(
module=module,
plugin_name=module,
is_super_block=False,
)
plugin.plugin_name = module2name.get(module) or module
close_plugins.append(plugin)
exists_modules = [p.module for p in close_plugins]
if group.superuser_block_plugin:
for module in group.superuser_block_plugin.replace("<", "").split(","):
if module and module not in exists_modules:
plugin = Plugin(
module=module,
plugin_name=module,
is_super_block=True,
)
plugin.plugin_name = module2name.get(module) or module
close_plugins.append(plugin)
all_task = await TaskInfo.annotate().values_list("module", "name")
task_module2name = {x[0]: x[1] for x in all_task}
task_list = []
if group.block_task:
split_task = group.block_task.split(",")
if group.block_task or group.superuser_block_plugin:
sbp = group.superuser_block_plugin.replace("<", "").split(",")
split_task = group.block_task.replace("<", "").split(",")
for task in all_task:
task_list.append(
Task(
name=task[0],
zh_name=task_module2name.get(task[0]) or task[0],
status=task[0] not in split_task,
status=task[0] not in split_task and task[0] not in sbp,
is_super_block=task[0] in sbp,
)
)
else:
@@ -383,6 +458,7 @@ async def _(bot_id: str, group_id: str) -> Result:
name=task[0],
zh_name=task_module2name.get(task[0]) or task[0],
status=True,
is_super_block=False,
)
)
group_detail = GroupDetail(
@@ -403,7 +479,11 @@ async def _(bot_id: str, group_id: str) -> Result:
@router.post(
"/send_message", dependencies=[authentication()], description="获取群组详情"
"/send_message",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="获取群组详情",
)
async def _(param: SendMessage) -> Result:
if not (bots := nonebot.get_bots()):
@@ -29,6 +29,8 @@ class Task(BaseModel):
"""被动中文名称"""
status: bool
"""状态"""
is_super_block: bool
"""是否超级用户禁用"""
class Plugin(BaseModel):
@@ -2,6 +2,7 @@ import re
import cattrs
from fastapi import Query, APIRouter
from fastapi.responses import JSONResponse
from zhenxun.services.log import logger
from zhenxun.configs.config import Config
@@ -25,11 +26,13 @@ router = APIRouter(prefix="/plugin")
@router.get(
"/get_plugin_list",
dependencies=[authentication()],
response_model=Result[list[PluginInfo]],
response_class=JSONResponse,
deprecated="获取插件列表", # type: ignore
)
async def _(
plugin_type: list[PluginType] = Query(None), menu_type: str | None = None
) -> Result:
) -> Result[list[PluginInfo]]:
try:
plugin_list: list[PluginInfo] = []
query = DbPluginInfo
@@ -61,9 +64,11 @@ async def _(
@router.get(
"/get_plugin_count",
dependencies=[authentication()],
response_model=Result[int],
response_class=JSONResponse,
deprecated="获取插件数量", # type: ignore
)
async def _() -> Result:
async def _() -> Result[int]:
plugin_count = PluginCount()
plugin_count.normal = await DbPluginInfo.filter(
plugin_type=PluginType.NORMAL, load_status=True
@@ -82,7 +87,11 @@ async def _() -> Result:
@router.post(
"/update_plugin", dependencies=[authentication()], description="更新插件参数"
"/update_plugin",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="更新插件参数",
)
async def _(plugin: UpdatePlugin) -> Result:
try:
@@ -113,7 +122,13 @@ async def _(plugin: UpdatePlugin) -> Result:
return Result.ok(info="已经帮你写好啦!")
@router.post("/change_switch", dependencies=[authentication()], description="开关插件")
@router.post(
"/change_switch",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="开关插件",
)
async def _(param: PluginSwitch) -> Result:
db_plugin = await DbPluginInfo.get_or_none(module=param.module, load_status=True)
if not db_plugin:
@@ -129,9 +144,13 @@ async def _(param: PluginSwitch) -> Result:
@router.get(
"/get_plugin_menu_type", dependencies=[authentication()], description="获取插件类型"
"/get_plugin_menu_type",
dependencies=[authentication()],
response_model=Result[list[str]],
response_class=JSONResponse,
description="获取插件类型",
)
async def _() -> Result:
async def _() -> Result[list[str]]:
menu_type_list = []
result = await DbPluginInfo.annotate().values_list("menu_type", flat=True)
for r in result:
@@ -140,8 +159,14 @@ async def _() -> Result:
return Result.ok(menu_type_list)
@router.get("/get_plugin", dependencies=[authentication()], description="获取插件详情")
async def _(module: str) -> Result:
@router.get(
"/get_plugin",
dependencies=[authentication()],
response_model=Result[PluginDetail],
response_class=JSONResponse,
description="获取插件详情",
)
async def _(module: str) -> Result[PluginDetail]:
db_plugin = await DbPluginInfo.get_or_none(module=module, load_status=True)
if not db_plugin:
return Result.fail("插件不存在...")
@@ -1,25 +1,37 @@
from nonebot import require
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from zhenxun.models.plugin_info import PluginInfo
from .model import PluginIr
from ....base_model import Result
from ....utils import authentication
require("plugin_store")
from zhenxun.builtin_plugins.plugin_store import ShopManage
router = APIRouter(prefix="/store")
@router.get(
"/get_plugin_store",
dependencies=[authentication()],
response_model=Result[dict],
response_class=JSONResponse,
deprecated="获取插件商店插件信息", # type: ignore
)
async def _() -> Result:
async def _() -> Result[dict]:
try:
require("plugin_store")
from zhenxun.builtin_plugins.plugin_store import ShopManage
data = await ShopManage.get_data()
return Result.ok(data)
plugin_list = [
{**data[name].dict(), "name": name, "id": idx}
for idx, name in enumerate(data)
]
modules = await PluginInfo.filter(load_status=True).values_list(
"module", flat=True
)
return Result.ok({"install_module": modules, "plugin_list": plugin_list})
except Exception as e:
return Result.fail(f"获取插件商店插件信息失败: {type(e)}: {e}")
@@ -27,24 +39,52 @@ async def _() -> Result:
@router.post(
"/install_plugin",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
deprecated="安装插件", # type: ignore
)
async def _(param: PluginIr) -> Result:
try:
require("plugin_store")
from zhenxun.builtin_plugins.plugin_store import ShopManage
result = await ShopManage.add_plugin(param.id) # type: ignore
return Result.ok(result)
return Result.ok(info=result)
except Exception as e:
return Result.fail(f"安装插件失败: {type(e)}: {e}")
@router.post(
"/update_plugin",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
deprecated="更新插件", # type: ignore
)
async def _(param: PluginIr) -> Result:
try:
require("plugin_store")
from zhenxun.builtin_plugins.plugin_store import ShopManage
result = await ShopManage.update_plugin(param.id) # type: ignore
return Result.ok(info=result)
except Exception as e:
return Result.fail(f"更新插件失败: {type(e)}: {e}")
@router.post(
"/remove_plugin",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
deprecated="移除插件", # type: ignore
)
async def _(param: PluginIr) -> Result:
try:
require("plugin_store")
from zhenxun.builtin_plugins.plugin_store import ShopManage
result = await ShopManage.remove_plugin(param.id) # type: ignore
return Result.ok(result)
return Result.ok(info=result)
except Exception as e:
return Result.fail(f"移除插件失败: {type(e)}: {e}")
@@ -4,10 +4,11 @@ from pathlib import Path
import aiofiles
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from zhenxun.utils._build_image import BuildImage
from ....base_model import Result
from ....base_model import Result, SystemFolderSize
from ....utils import authentication, get_system_disk
from .model import AddFile, DirFile, SaveFile, DeleteFile, RenameFile
@@ -17,9 +18,13 @@ IMAGE_TYPE = ["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"]
@router.get(
"/get_dir_list", dependencies=[authentication()], description="获取文件列表"
"/get_dir_list",
dependencies=[authentication()],
response_model=Result[list[DirFile]],
response_class=JSONResponse,
description="获取文件列表",
)
async def _(path: str | None = None) -> Result:
async def _(path: str | None = None) -> Result[list[DirFile]]:
base_path = Path(path) if path else Path()
data_list = []
for file in os.listdir(base_path):
@@ -37,13 +42,23 @@ async def _(path: str | None = None) -> Result:
@router.get(
"/get_resources_size", dependencies=[authentication()], description="获取文件列表"
"/get_resources_size",
dependencies=[authentication()],
response_model=Result[SystemFolderSize],
response_class=JSONResponse,
description="获取文件列表",
)
async def _(full_path: str | None = None) -> Result:
async def _(full_path: str | None = None) -> Result[SystemFolderSize]:
return Result.ok(await get_system_disk(full_path))
@router.post("/delete_file", dependencies=[authentication()], description="删除文件")
@router.post(
"/delete_file",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="删除文件",
)
async def _(param: DeleteFile) -> Result:
path = Path(param.full_path)
if not path or not path.exists():
@@ -56,7 +71,11 @@ async def _(param: DeleteFile) -> Result:
@router.post(
"/delete_folder", dependencies=[authentication()], description="删除文件夹"
"/delete_folder",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="删除文件夹",
)
async def _(param: DeleteFile) -> Result:
path = Path(param.full_path)
@@ -69,7 +88,13 @@ async def _(param: DeleteFile) -> Result:
return Result.warning_(f"删除失败: {e!s}")
@router.post("/rename_file", dependencies=[authentication()], description="重命名文件")
@router.post(
"/rename_file",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="重命名文件",
)
async def _(param: RenameFile) -> Result:
path = (
(Path(param.parent) / param.old_name) if param.parent else Path(param.old_name)
@@ -84,7 +109,11 @@ async def _(param: RenameFile) -> Result:
@router.post(
"/rename_folder", dependencies=[authentication()], description="重命名文件夹"
"/rename_folder",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="重命名文件夹",
)
async def _(param: RenameFile) -> Result:
path = (
@@ -100,7 +129,13 @@ async def _(param: RenameFile) -> Result:
return Result.warning_(f"重命名失败: {e!s}")
@router.post("/add_file", dependencies=[authentication()], description="新建文件")
@router.post(
"/add_file",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="新建文件",
)
async def _(param: AddFile) -> Result:
path = (Path(param.parent) / param.name) if param.parent else Path(param.name)
if path.exists():
@@ -112,7 +147,13 @@ async def _(param: AddFile) -> Result:
return Result.warning_(f"新建文件失败: {e!s}")
@router.post("/add_folder", dependencies=[authentication()], description="新建文件夹")
@router.post(
"/add_folder",
dependencies=[authentication()],
response_model=Result,
response_class=JSONResponse,
description="新建文件夹",
)
async def _(param: AddFile) -> Result:
path = (Path(param.parent) / param.name) if param.parent else Path(param.name)
if path.exists():
@@ -124,7 +165,13 @@ async def _(param: AddFile) -> Result:
return Result.warning_(f"新建文件夹失败: {e!s}")
@router.get("/read_file", dependencies=[authentication()], description="读取文件")
@router.get(
"/read_file",
dependencies=[authentication()],
response_model=Result[str],
response_class=JSONResponse,
description="读取文件",
)
async def _(full_path: str) -> Result:
path = Path(full_path)
if not path.exists():
@@ -136,8 +183,14 @@ async def _(full_path: str) -> Result:
return Result.warning_(f"读取文件失败: {e!s}")
@router.post("/save_file", dependencies=[authentication()], description="读取文件")
async def _(param: SaveFile) -> Result:
@router.post(
"/save_file",
dependencies=[authentication()],
response_model=Result[str],
response_class=JSONResponse,
description="读取文件",
)
async def _(param: SaveFile) -> Result[str]:
path = Path(param.full_path)
try:
async with aiofiles.open(path, "w", encoding="utf-8") as f:
@@ -147,8 +200,14 @@ async def _(param: SaveFile) -> Result:
return Result.warning_(f"保存文件失败: {e!s}")
@router.get("/get_image", dependencies=[authentication()], description="读取图片base64")
async def _(full_path: str) -> Result:
@router.get(
"/get_image",
dependencies=[authentication()],
response_model=Result[str],
response_class=JSONResponse,
description="读取图片base64",
)
async def _(full_path: str) -> Result[str]:
path = Path(full_path)
if not path.exists():
return Result.warning_("文件不存在...")