mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-09-29 08:39:59 +08:00
重构webui主页与好友/群组api
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
from .main import *
|
||||
from .manage import *
|
||||
@@ -0,0 +1,149 @@
|
||||
import asyncio
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional
|
||||
|
||||
import nonebot
|
||||
from fastapi import APIRouter, WebSocket
|
||||
from nonebot.utils import escape_tag
|
||||
from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState
|
||||
|
||||
from configs.config import NICKNAME
|
||||
from models.chat_history import ChatHistory
|
||||
from services.log import logger
|
||||
from utils.manager import plugin_data_manager, plugins2settings_manager, plugins_manager
|
||||
from utils.manager.models import PluginData, PluginType
|
||||
|
||||
from ....config import QueryDateType
|
||||
from ....base_model import Result
|
||||
from ....utils import authentication, get_system_status
|
||||
from .data_source import bot_live
|
||||
from .model import BaseInfo
|
||||
|
||||
AVA_URL = "http://q1.qlogo.cn/g?b=qq&nk={}&s=160"
|
||||
|
||||
run_time = time.time()
|
||||
|
||||
ws_router = APIRouter()
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/get_base_info", dependencies=[authentication()], description="基础信息")
|
||||
async def _(bot_id: Optional[str] = None) -> Result:
|
||||
"""
|
||||
获取Bot基础信息
|
||||
|
||||
Args:
|
||||
qq (Optional[str], optional): qq号. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Result: 获取指定bot信息与bot列表
|
||||
"""
|
||||
bot_list: List[BaseInfo] = []
|
||||
if bots := nonebot.get_bots():
|
||||
select_bot: BaseInfo
|
||||
for key, bot in bots.items():
|
||||
bot_list.append(
|
||||
BaseInfo(
|
||||
bot=bot, # type: ignore
|
||||
self_id=bot.self_id,
|
||||
nickname=NICKNAME,
|
||||
ava_url=AVA_URL.format(bot.self_id),
|
||||
)
|
||||
)
|
||||
# 获取指定qq号的bot信息,若无指定则获取第一个
|
||||
if _bl := [b for b in bot_list if b.self_id == bot_id]:
|
||||
select_bot = _bl[0]
|
||||
else:
|
||||
select_bot = bot_list[0]
|
||||
select_bot.is_select = True
|
||||
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.group_count = len(await select_bot.bot.get_group_list())
|
||||
# 好友数量
|
||||
select_bot.friend_count = len(await select_bot.bot.get_friend_list())
|
||||
for bot in bot_list:
|
||||
bot.bot = None # type: ignore
|
||||
# 插件加载数量
|
||||
select_bot.plugin_count = len(plugins2settings_manager)
|
||||
pm_data = plugins_manager.get_data()
|
||||
select_bot.fail_plugin_count = len([pd for pd in pm_data if pm_data[pd].error])
|
||||
select_bot.success_plugin_count = (
|
||||
select_bot.plugin_count - select_bot.fail_plugin_count
|
||||
)
|
||||
# 连接时间
|
||||
select_bot.connect_time = bot_live.get(select_bot.self_id) or 0
|
||||
|
||||
return Result.ok(bot_list, "已获取操作列表")
|
||||
return Result.warning_("无Bot连接...")
|
||||
|
||||
|
||||
@router.get("/get_ch_count", dependencies=[authentication()], description="获取接收消息数量")
|
||||
async def _(bot_id: str, query_type: Optional[QueryDateType] = None) -> Result:
|
||||
if bots := nonebot.get_bots():
|
||||
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连接...")
|
||||
|
||||
|
||||
@router.get("get_fg_count", dependencies=[authentication()], description="好友/群组数量")
|
||||
async def _(bot_id: str) -> Result:
|
||||
if bots := nonebot.get_bots():
|
||||
if bot_id not in bots:
|
||||
return Result.warning_("指定Bot未连接...")
|
||||
bot = bots[bot_id]
|
||||
data = {
|
||||
"friend_count": len(await bot.get_friend_list()),
|
||||
"group_count": len(await bot.get_group_list()),
|
||||
}
|
||||
return Result.ok(data)
|
||||
return Result.warning_("无Bot连接...")
|
||||
|
||||
|
||||
@router.get("/get_run_time", dependencies=[authentication()], description="获取nb运行时间")
|
||||
async def _() -> Result:
|
||||
return Result.ok(int(time.time() - run_time))
|
||||
|
||||
|
||||
@ws_router.websocket("/system_status")
|
||||
async def system_logs_realtime(websocket: WebSocket):
|
||||
await websocket.accept()
|
||||
logger.debug("ws system_status is connect")
|
||||
try:
|
||||
while websocket.client_state == WebSocketState.CONNECTED:
|
||||
system_status = await get_system_status()
|
||||
await websocket.send_text(system_status.json())
|
||||
await asyncio.sleep(5)
|
||||
except WebSocketDisconnect:
|
||||
pass
|
||||
return
|
||||
@@ -0,0 +1,36 @@
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
import nonebot
|
||||
from nonebot import Driver
|
||||
from nonebot.adapters.onebot.v12 import Bot
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
|
||||
class BotLive:
|
||||
def __init__(self):
|
||||
self._data = {}
|
||||
|
||||
def add(self, bot_id: str):
|
||||
self._data[bot_id] = time.time()
|
||||
|
||||
def get(self, bot_id: str) -> Optional[int]:
|
||||
return self._data.get(bot_id)
|
||||
|
||||
def remove(self, bot_id: str):
|
||||
if bot_id in self._data:
|
||||
del self._data[bot_id]
|
||||
|
||||
|
||||
bot_live = BotLive()
|
||||
|
||||
|
||||
@driver.on_bot_connect
|
||||
async def _(bot: Bot):
|
||||
bot_live.add(bot.self_id)
|
||||
|
||||
|
||||
@driver.on_bot_disconnect
|
||||
async def _(bot: Bot):
|
||||
bot_live.remove(bot.self_id)
|
||||
@@ -0,0 +1,56 @@
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class SystemStatus(BaseModel):
|
||||
"""
|
||||
系统状态
|
||||
"""
|
||||
|
||||
cpu: float
|
||||
memory: float
|
||||
disk: float
|
||||
|
||||
|
||||
class BaseInfo(BaseModel):
|
||||
"""
|
||||
基础信息
|
||||
"""
|
||||
|
||||
bot: Bot
|
||||
"""Bot"""
|
||||
self_id: str
|
||||
"""SELF ID"""
|
||||
nickname: str
|
||||
"""昵称"""
|
||||
ava_url: str
|
||||
"""头像url"""
|
||||
friend_count: int = 0
|
||||
"""好友数量"""
|
||||
group_count: int = 0
|
||||
"""群聊数量"""
|
||||
received_messages: int = 0
|
||||
"""今日 累计接收消息"""
|
||||
# received_messages_day: int = 0
|
||||
# """今日累计接收消息"""
|
||||
# received_messages_week: int = 0
|
||||
# """一周内累计接收消息"""
|
||||
# received_messages_month: int = 0
|
||||
# """一月内累计接收消息"""
|
||||
# received_messages_year: int = 0
|
||||
# """一年内累计接受消息"""
|
||||
connect_time: int = 0
|
||||
"""连接时间"""
|
||||
|
||||
plugin_count: int = 0
|
||||
"""加载插件数量"""
|
||||
success_plugin_count: int = 0
|
||||
"""加载成功插件数量"""
|
||||
fail_plugin_count: int = 0
|
||||
"""加载失败插件数量"""
|
||||
|
||||
is_select: bool = False
|
||||
"""当前选择"""
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
@@ -0,0 +1,245 @@
|
||||
from typing import Literal
|
||||
|
||||
import nonebot
|
||||
from fastapi import APIRouter
|
||||
from pydantic.error_wrappers import ValidationError
|
||||
|
||||
from configs.config import NICKNAME
|
||||
from models.group_info import GroupInfo
|
||||
from services.log import logger
|
||||
from utils.manager import group_manager, requests_manager
|
||||
from utils.utils import get_bot
|
||||
|
||||
from ....base_model import Result
|
||||
from ....utils import authentication
|
||||
from .model import (
|
||||
DeleteFriend,
|
||||
Friend,
|
||||
FriendRequestResult,
|
||||
Group,
|
||||
GroupRequestResult,
|
||||
GroupResult,
|
||||
HandleRequest,
|
||||
LeaveGroup,
|
||||
Task,
|
||||
UpdateGroup,
|
||||
)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/get_group_list", dependencies=[authentication()], description="获取群组列表")
|
||||
async def _(bot_id: str) -> Result:
|
||||
"""
|
||||
获取群信息
|
||||
"""
|
||||
if bots := nonebot.get_bots():
|
||||
if bot_id not in bots:
|
||||
return Result.warning_("指定Bot未连接...")
|
||||
group_list_result = []
|
||||
try:
|
||||
group_info = {}
|
||||
group_list = await bots[bot_id].get_group_list()
|
||||
for g in group_list:
|
||||
group_info[g["group_id"]] = Group(**g)
|
||||
group_data = group_manager.get_data()
|
||||
for group_id in group_data.group_manager:
|
||||
task_list = []
|
||||
data = group_manager[group_id].dict()
|
||||
for tn, status in data["group_task_status"].items():
|
||||
task_list.append(
|
||||
Task(
|
||||
**{
|
||||
"name": tn,
|
||||
"nameZh": group_manager.get_task_data().get(tn) or tn,
|
||||
"status": status,
|
||||
}
|
||||
)
|
||||
)
|
||||
data["task"] = task_list
|
||||
if x := group_info.get(int(group_id)):
|
||||
data["group"] = x
|
||||
else:
|
||||
continue
|
||||
group_list_result.append(GroupResult(**data))
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/get_group_list", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
return Result.ok(group_list_result, "拿到了新鲜出炉的数据!")
|
||||
return Result.warning_("无Bot连接...")
|
||||
|
||||
|
||||
@router.post("/update_group", dependencies=[authentication()], description="修改群组信息")
|
||||
async def _(group: UpdateGroup) -> Result:
|
||||
try:
|
||||
group_id = group.group_id
|
||||
group_manager.set_group_level(group_id, group.level)
|
||||
if group.status:
|
||||
group_manager.turn_on_group_bot_status(group_id)
|
||||
else:
|
||||
group_manager.shutdown_group_bot_status(group_id)
|
||||
if group.task_status:
|
||||
for task in group.task_status:
|
||||
if group.task_status[task]:
|
||||
group_manager.open_group_task(group_id, task)
|
||||
else:
|
||||
group_manager.close_group_task(group_id, task)
|
||||
group_manager.save()
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/get_group", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
return Result.ok(info="已完成记录!")
|
||||
|
||||
|
||||
@router.get("/get_friend_list", dependencies=[authentication()], description="获取好友列表")
|
||||
async def _(bot_id: str) -> Result:
|
||||
"""
|
||||
获取群信息
|
||||
"""
|
||||
if bots := nonebot.get_bots():
|
||||
if bot_id not in bots:
|
||||
return Result.warning_("指定Bot未连接...")
|
||||
try:
|
||||
friend_list = await bots[bot_id].get_friend_list()
|
||||
return Result.ok([Friend(**f) for f in friend_list], "拿到了新鲜出炉的数据!")
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/get_group_list", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
return Result.warning_("无Bot连接...")
|
||||
|
||||
|
||||
@router.get("/get_request_count", dependencies=[authentication()], description="获取请求数量")
|
||||
def _() -> Result:
|
||||
data = {
|
||||
"friend_count": len(requests_manager.get_data().get("private") or []),
|
||||
"group_count": len(requests_manager.get_data().get("group") or []),
|
||||
}
|
||||
return Result.ok(data, f"{NICKNAME}带来了最新的数据!")
|
||||
|
||||
|
||||
@router.get("/get_request_list", dependencies=[authentication()], description="获取请求列表")
|
||||
def _(request_type: Literal["private", "group"]) -> Result:
|
||||
try:
|
||||
req_data = requests_manager.get_data().get(request_type) or []
|
||||
req_list = []
|
||||
for x in req_data:
|
||||
req_data[x]["oid"] = x
|
||||
if request_type == "private":
|
||||
req_list.append(FriendRequestResult(**req_data[x]))
|
||||
else:
|
||||
req_list.append(GroupRequestResult(**req_data[x]))
|
||||
req_list.reverse()
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/get_request", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
return Result.ok(req_list, f"{NICKNAME}带来了最新的数据!")
|
||||
|
||||
|
||||
@router.delete("/clear_request", dependencies=[authentication()], description="清空请求列表")
|
||||
def _(request_type: Literal["private", "group"]) -> Result:
|
||||
"""
|
||||
清空请求
|
||||
:param type_: 类型
|
||||
"""
|
||||
requests_manager.clear(request_type)
|
||||
return Result.ok(info="成功清除了数据!")
|
||||
|
||||
|
||||
@router.post("/refuse_request", dependencies=[authentication()], description="拒绝请求")
|
||||
async def _(parma: HandleRequest) -> Result:
|
||||
"""
|
||||
操作请求
|
||||
:param parma: 参数
|
||||
"""
|
||||
try:
|
||||
if bots := nonebot.get_bots():
|
||||
bot_id = parma.bot_id
|
||||
if bot_id not in nonebot.get_bots():
|
||||
return Result.warning_("指定Bot未连接...")
|
||||
flag = await requests_manager.refused(bots[bot_id], parma.id, parma.request_type) # type: ignore
|
||||
if flag == 1:
|
||||
requests_manager.delete_request(parma.id, parma.request_type)
|
||||
return Result.warning_("该请求已失效...")
|
||||
elif flag == 2:
|
||||
return Result.warning_("未找到此Id请求...")
|
||||
return Result.ok(info="成功处理了请求!")
|
||||
return Result.warning_("Bot未连接...")
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/refuse_request", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
|
||||
|
||||
@router.post("/delete_request", dependencies=[authentication()], description="忽略请求")
|
||||
async def _(parma: HandleRequest) -> Result:
|
||||
"""
|
||||
操作请求
|
||||
:param parma: 参数
|
||||
"""
|
||||
requests_manager.delete_request(parma.id, parma.request_type)
|
||||
return Result.ok(info="成功处理了请求!")
|
||||
|
||||
|
||||
@router.post("/approve_request", dependencies=[authentication()], description="同意请求")
|
||||
async def _(parma: HandleRequest) -> Result:
|
||||
"""
|
||||
操作请求
|
||||
:param parma: 参数
|
||||
"""
|
||||
try:
|
||||
if bots := nonebot.get_bots():
|
||||
bot_id = parma.bot_id
|
||||
if bot_id not in nonebot.get_bots():
|
||||
return Result.warning_("指定Bot未连接...")
|
||||
if parma.request_type == "group":
|
||||
if rid := requests_manager.get_group_id(parma.id):
|
||||
if group := await GroupInfo.get_or_none(group_id=str(rid)):
|
||||
await group.update_or_create(group_flag=1)
|
||||
else:
|
||||
group_info = await bots[bot_id].get_group_info(group_id=rid)
|
||||
await GroupInfo.update_or_create(
|
||||
group_id=str(group_info["group_id"]),
|
||||
defaults={
|
||||
"group_name": group_info["group_name"],
|
||||
"max_member_count": group_info["max_member_count"],
|
||||
"member_count": group_info["member_count"],
|
||||
"group_flag": 1,
|
||||
},
|
||||
)
|
||||
await requests_manager.approve(bots[bot_id], parma.id, parma.request_type) # type: ignore
|
||||
return Result.ok(info="成功处理了请求!")
|
||||
return Result.warning_("Bot未连接...")
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/approve_request", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
|
||||
|
||||
@router.post("/leave_group", dependencies=[authentication()], description="退群")
|
||||
async def _(param: LeaveGroup) -> Result:
|
||||
try:
|
||||
if bots := nonebot.get_bots():
|
||||
bot_id = param.bot_id
|
||||
group_list = await bots[bot_id].get_group_list()
|
||||
if param.group_id not in [str(g["group_id"]) for g in group_list]:
|
||||
return Result.warning_("Bot未在该群聊中...")
|
||||
await bots[bot_id].set_group_leave(group_id=param.group_id)
|
||||
return Result.ok(info="成功处理了请求!")
|
||||
return Result.warning_("Bot未连接...")
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/leave_group", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
|
||||
|
||||
@router.post("/delete_friend", dependencies=[authentication()], description="删除好友")
|
||||
async def _(param: DeleteFriend) -> Result:
|
||||
try:
|
||||
if bots := nonebot.get_bots():
|
||||
bot_id = param.bot_id
|
||||
friend_list = await bots[bot_id].get_friend_list()
|
||||
if param.user_id not in [str(g["user_id"]) for g in friend_list]:
|
||||
return Result.warning_("Bot未有其好友...")
|
||||
await bots[bot_id].delete_friend(user_id=param.user_id)
|
||||
return Result.ok(info="成功处理了请求!")
|
||||
return Result.warning_("Bot未连接...")
|
||||
except Exception as e:
|
||||
logger.error("调用API错误", "/delete_friend", e=e)
|
||||
return Result.fail(f"{type(e)}: {e}")
|
||||
@@ -0,0 +1,151 @@
|
||||
from typing import Dict, List, Literal, Optional, Union
|
||||
|
||||
from matplotlib.dates import FR
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Group(BaseModel):
|
||||
"""
|
||||
群组信息
|
||||
"""
|
||||
|
||||
group_id: Union[str, int]
|
||||
"""群组id"""
|
||||
group_name: str
|
||||
"""群组名称"""
|
||||
member_count: int
|
||||
"""成员人数"""
|
||||
max_member_count: int
|
||||
"""群组最大人数"""
|
||||
|
||||
|
||||
class Task(BaseModel):
|
||||
"""
|
||||
被动技能
|
||||
"""
|
||||
|
||||
name: str
|
||||
"""被动名称"""
|
||||
nameZh: str
|
||||
"""被动中文名称"""
|
||||
status: bool
|
||||
"""状态"""
|
||||
|
||||
|
||||
class GroupResult(BaseModel):
|
||||
"""
|
||||
群组返回数据
|
||||
"""
|
||||
|
||||
group: Group
|
||||
"""Group"""
|
||||
level: int
|
||||
"""群等级"""
|
||||
status: bool
|
||||
"""状态"""
|
||||
close_plugins: List[str]
|
||||
"""关闭的插件"""
|
||||
task: List[Task]
|
||||
"""被动列表"""
|
||||
|
||||
|
||||
class Friend(BaseModel):
|
||||
"""
|
||||
好友数据
|
||||
"""
|
||||
|
||||
user_id: Union[str, int]
|
||||
"""用户id"""
|
||||
nickname: str = ""
|
||||
"""昵称"""
|
||||
remark: str = ""
|
||||
"""备注"""
|
||||
|
||||
|
||||
class UpdateGroup(BaseModel):
|
||||
"""
|
||||
更新群组信息
|
||||
"""
|
||||
|
||||
group_id: str
|
||||
"""群号"""
|
||||
status: bool
|
||||
"""状态"""
|
||||
level: int
|
||||
"""群权限"""
|
||||
task_status: Dict[str, bool]
|
||||
"""被动状态"""
|
||||
|
||||
|
||||
class FriendRequestResult(BaseModel):
|
||||
"""
|
||||
好友/群组请求管理
|
||||
"""
|
||||
|
||||
bot_id: Union[str, int]
|
||||
"""bot_id"""
|
||||
oid: str
|
||||
"""排序"""
|
||||
id: int
|
||||
"""id"""
|
||||
flag: str
|
||||
"""flag"""
|
||||
nickname: Optional[str]
|
||||
"""昵称"""
|
||||
level: Optional[int]
|
||||
"""等级"""
|
||||
sex: Optional[str]
|
||||
"""性别"""
|
||||
age: Optional[int]
|
||||
"""年龄"""
|
||||
from_: Optional[str]
|
||||
"""来自"""
|
||||
comment: Optional[str]
|
||||
"""备注信息"""
|
||||
|
||||
|
||||
class GroupRequestResult(FriendRequestResult):
|
||||
"""
|
||||
群聊邀请请求
|
||||
"""
|
||||
|
||||
invite_group: Union[int, str]
|
||||
"""邀请群聊"""
|
||||
group_name: Optional[str]
|
||||
"""群聊名称"""
|
||||
|
||||
|
||||
class HandleRequest(BaseModel):
|
||||
"""
|
||||
操作请求接收数据
|
||||
"""
|
||||
|
||||
bot_id: str
|
||||
"""bot_id"""
|
||||
id: int
|
||||
"""id"""
|
||||
request_type: Literal["private", "group"]
|
||||
"""类型"""
|
||||
|
||||
|
||||
class LeaveGroup(BaseModel):
|
||||
"""
|
||||
退出群聊
|
||||
"""
|
||||
|
||||
bot_id: str
|
||||
"""bot_id"""
|
||||
group_id: str
|
||||
"""群聊id"""
|
||||
|
||||
|
||||
class DeleteFriend(BaseModel):
|
||||
"""
|
||||
删除好友
|
||||
"""
|
||||
|
||||
bot_id: str
|
||||
"""bot_id"""
|
||||
user_id: str
|
||||
"""用户id"""
|
||||
Reference in New Issue
Block a user