重构webui主页与好友/群组api

This commit is contained in:
HibiKier 2023-12-30 05:27:45 +08:00
parent 081c86aba0
commit 25af1802af
27 changed files with 1530 additions and 897 deletions

View File

@ -1,5 +1,5 @@
from nonebot import on_message
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
from configs.config import Config
from models.chat_history import ChatHistory
@ -32,7 +32,7 @@ TEMP_LIST = []
@chat_history.handle()
async def _(event: MessageEvent, msg: str = PlaintText()):
async def _(bot: Bot, event: MessageEvent, msg: str = PlaintText()):
group_id = None
if isinstance(event, GroupMessageEvent):
group_id = str(event.group_id)
@ -42,6 +42,7 @@ async def _(event: MessageEvent, msg: str = PlaintText()):
group_id=group_id,
text=str(event.get_message()),
plain_text=msg,
bot_id=str(bot.self_id),
)
)

View File

@ -58,9 +58,12 @@ async def _(bot: Bot, event: FriendRequestEvent):
if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
logger.debug(f"已开启好友请求自动同意,成功通过该请求", "好友请求", target=event.user_id)
await bot.set_friend_add_request(flag=event.flag, approve=True)
await FriendUser.create(user_id=str(user["user_id"]), user_name=user["nickname"])
await FriendUser.create(
user_id=str(user["user_id"]), user_name=user["nickname"]
)
else:
requests_manager.add_request(
str(bot.self_id),
event.user_id,
"private",
event.flag,
@ -126,6 +129,7 @@ async def _(bot: Bot, event: GroupRequestEvent):
"等待管理员处理吧!",
)
requests_manager.add_request(
str(bot.self_id),
event.user_id,
"group",
event.flag,

View File

@ -21,6 +21,8 @@ class ChatHistory(Model):
"""纯文本"""
create_time = fields.DatetimeField(auto_now_add=True)
"""创建时间"""
bot_id = fields.CharField(255, null=True)
"""bot记录id"""
class Meta:
table = "chat_history"
@ -56,7 +58,9 @@ class ChatHistory(Model):
) # type: ignore
@classmethod
async def get_group_first_msg_datetime(cls, group_id: Union[int, str]) -> Optional[datetime]:
async def get_group_first_msg_datetime(
cls, group_id: Union[int, str]
) -> Optional[datetime]:
"""
说明:
获取群第一条记录消息时间
@ -117,4 +121,6 @@ class ChatHistory(Model):
"ALTER TABLE chat_history RENAME COLUMN user_qq TO user_id;", # 将user_id改为user_id
"ALTER TABLE chat_history ALTER COLUMN user_id TYPE character varying(255);",
"ALTER TABLE chat_history ALTER COLUMN group_id TYPE character varying(255);",
"ALTER TABLE chat_history ADD bot_id VARCHAR(255);", # 添加bot_id字段
"ALTER TABLE chat_history ALTER COLUMN bot_id TYPE character varying(255);",
]

View File

@ -1,56 +1,67 @@
# import asyncio
import asyncio
# import nonebot
# from fastapi import APIRouter, FastAPI
# from nonebot.adapters.onebot.v11 import Bot, MessageEvent
# from nonebot.log import default_filter, default_format
# from nonebot.matcher import Matcher
# from nonebot.message import run_preprocessor
# from nonebot.typing import T_State
import nonebot
from fastapi import APIRouter, FastAPI
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.log import default_filter, default_format
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor
from nonebot.typing import T_State
# from configs.config import Config as gConfig
# from services.log import logger, logger_
# from utils.manager import plugins2settings_manager
from configs.config import Config as gConfig
from services.log import logger, logger_
from utils.manager import plugins2settings_manager
# from .api.base_info import router as base_info_routes
# from .api.group import router as group_routes
# from .api.logs import router as ws_routes
# from .api.logs.log_manager import LOG_STORAGE
from .api.logs import router as ws_log_routes
from .api.logs.log_manager import LOG_STORAGE
# from .api.plugins import router as plugin_routes
# from .api.request import router as request_routes
from .api.request import router as request_routes
# from .api.system import router as system_routes
from .api.tabs.main import router as main_router
from .api.tabs.main import ws_router as status_routes
from .api.tabs.manage import router as manage_router
# # from .api.g import *
# from .auth import router as auth_router
# from .api.g import *
from .auth import router as auth_router
# driver = nonebot.get_driver()
driver = nonebot.get_driver()
# gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名")
gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名")
# gConfig.add_plugin_config("web-ui", "password", None, name="web-ui", help_="前端管理密码")
gConfig.add_plugin_config("web-ui", "password", None, name="web-ui", help_="前端管理密码")
# BaseApiRouter = APIRouter(prefix="/zhenxun/api")
BaseApiRouter = APIRouter(prefix="/zhenxun/api")
# BaseApiRouter.include_router(auth_router)
BaseApiRouter.include_router(auth_router)
# BaseApiRouter.include_router(plugin_routes)
# BaseApiRouter.include_router(group_routes)
# BaseApiRouter.include_router(request_routes)
BaseApiRouter.include_router(request_routes)
# BaseApiRouter.include_router(system_routes)
# BaseApiRouter.include_router(base_info_routes)
BaseApiRouter.include_router(main_router)
BaseApiRouter.include_router(manage_router)
# @driver.on_startup
# def _():
@driver.on_startup
def _():
try:
loop = asyncio.get_running_loop()
# loop = asyncio.get_running_loop()
def log_sink(message: str):
loop.create_task(LOG_STORAGE.add(message.rstrip("\n")))
# def log_sink(message: str):
# loop.create_task(LOG_STORAGE.add(message.rstrip("\n")))
logger_.add(
log_sink, colorize=True, filter=default_filter, format=default_format
)
# logger_.add(log_sink, colorize=True, filter=default_filter, format=default_format)
# app: FastAPI = nonebot.get_app()
# app.include_router(BaseApiRouter)
# app.include_router(ws_routes)
# logger.info("<g>API启动成功</g>", "Web UI")
app: FastAPI = nonebot.get_app()
app.include_router(BaseApiRouter)
app.include_router(ws_log_routes)
app.include_router(status_routes)
logger.info("<g>API启动成功</g>", "Web UI")
except Exception as e:
logger.error("<g>API启动失败</g>", "Web UI", e=e)

View File

@ -1,4 +1,5 @@
from .group import *
from .plugins import *
from .request import *
from .system import *
# from .group import *
# from .plugins import *
# from .request import *
# from .system import *
from .tabs import *

View File

@ -1,75 +1,75 @@
from datetime import datetime, timedelta
from typing import List, Optional
# from datetime import datetime, timedelta
# from typing import List, Optional
import nonebot
from fastapi import APIRouter
# import nonebot
# from fastapi import APIRouter
from configs.config import Config
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 configs.config import Config
# 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 ..models.model import BotInfo, Result
from ..models.params import UpdateConfig, UpdatePlugin
from ..utils import authentication
# from ..base_model import BotInfo, Result
# from ..models.params import UpdateConfig, UpdatePlugin
# from ..utils import authentication
AVA_URL = "http://q1.qlogo.cn/g?b=qq&nk={}&s=160"
# AVA_URL = "http://q1.qlogo.cn/g?b=qq&nk={}&s=160"
router = APIRouter()
# router = APIRouter()
@router.get("/get_bot_info", dependencies=[authentication()])
async def _(self_id: Optional[str] = None) -> Result:
"""
获取Bot基础信息
# @router.get("/get_bot_info", dependencies=[authentication()])
# async def _(self_id: Optional[str] = None) -> Result:
# """
# 获取Bot基础信息
Args:
qq (Optional[str], optional): qq号. Defaults to None.
# Args:
# qq (Optional[str], optional): qq号. Defaults to None.
Returns:
Result: 获取指定bot信息与bot列表
"""
bot_list: List[BotInfo] = []
if bots := nonebot.get_bots():
select_bot: BotInfo
for key, bot in bots.items():
bot_list.append(
BotInfo(
bot=bot, # type: ignore
self_id=bot.self_id,
nickname="可爱的小真寻",
ava_url=AVA_URL.format(bot.self_id),
)
)
if _bl := [b for b in bot_list if b.self_id == self_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=int(select_bot.self_id)
).count()
select_bot.received_messages_day = await ChatHistory.filter(
bot_id=int(select_bot.self_id),
create_time__gte=now - timedelta(hours=now.hour),
).count()
select_bot.received_messages_week = await ChatHistory.filter(
bot_id=int(select_bot.self_id),
create_time__gte=now - timedelta(days=7),
).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
)
# Returns:
# Result: 获取指定bot信息与bot列表
# """
# bot_list: List[BotInfo] = []
# if bots := nonebot.get_bots():
# select_bot: BotInfo
# for key, bot in bots.items():
# bot_list.append(
# BotInfo(
# bot=bot, # type: ignore
# self_id=bot.self_id,
# nickname="可爱的小真寻",
# ava_url=AVA_URL.format(bot.self_id),
# )
# )
# if _bl := [b for b in bot_list if b.self_id == self_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=int(select_bot.self_id)
# ).count()
# select_bot.received_messages_day = await ChatHistory.filter(
# bot_id=int(select_bot.self_id),
# create_time__gte=now - timedelta(hours=now.hour),
# ).count()
# select_bot.received_messages_week = await ChatHistory.filter(
# bot_id=int(select_bot.self_id),
# create_time__gte=now - timedelta(days=7),
# ).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
# )
return Result.ok(bot_list, "已获取操作列表")
return Result.fail("无Bot连接")
# return Result.ok(bot_list, "已获取操作列表")
# return Result.fail("无Bot连接")

View File

@ -1,69 +1,69 @@
from fastapi import APIRouter
from pydantic.error_wrappers import ValidationError
# from fastapi import APIRouter
# from pydantic.error_wrappers import ValidationError
from services.log import logger
from utils.manager import group_manager
from utils.utils import get_bot
# from services.log import logger
# from utils.manager import group_manager
# from utils.utils import get_bot
from ..models.model import Group, GroupResult, Result, Task
from ..models.params import UpdateGroup
from ..utils import authentication
# from ..base_model import Group, GroupResult, Result, Task
# from ..models.params import UpdateGroup
# from ..utils import authentication
router = APIRouter()
# router = APIRouter()
@router.get("/get_group", dependencies=[authentication()])
async def _() -> Result:
"""
获取群信息
"""
group_list_result = []
try:
group_info = {}
if bot := get_bot():
group_list = await bot.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", e=e)
return Result.fail(f"{type(e)}: {e}")
return Result.ok(group_list_result, "拿到了新鲜出炉的数据!")
# @router.get("/get_group", dependencies=[authentication()])
# async def _() -> Result:
# """
# 获取群信息
# """
# group_list_result = []
# try:
# group_info = {}
# if bot := get_bot():
# group_list = await bot.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", e=e)
# return Result.fail(f"{type(e)}: {e}")
# return Result.ok(group_list_result, "拿到了新鲜出炉的数据!")
@router.post("/update_group", dependencies=[authentication()])
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)
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.post("/update_group", dependencies=[authentication()])
# 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)
# 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="已完成记录!")

View File

@ -1,6 +1,6 @@
import asyncio
import re
from typing import Awaitable, Callable, ClassVar, Dict, Generic, List, Set, TypeVar
from typing import Awaitable, Callable, Dict, Generic, List, Set, TypeVar
from urllib.parse import urlparse
PATTERN = r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))"
@ -10,6 +10,11 @@ LogListener = Callable[[_T], Awaitable[None]]
class LogStorage(Generic[_T]):
"""
日志存储
"""
def __init__(self, rotation: float = 5 * 60):
self.count, self.rotation = 0, rotation
self.logs: Dict[int, str] = {}
@ -42,4 +47,4 @@ class LogStorage(Generic[_T]):
return
LOG_STORAGE = LogStorage[str]()
LOG_STORAGE: LogStorage[str] = LogStorage[str]()

View File

@ -2,7 +2,7 @@ from typing import List
from fastapi import APIRouter, WebSocket
from loguru import logger
from nonebot.utils import escape_tag, run_sync
from nonebot.utils import escape_tag
from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState
from .log_manager import LOG_STORAGE
@ -12,7 +12,12 @@ router = APIRouter()
@router.get("/logs", response_model=List[str])
async def system_logs_history(reverse: bool = False):
return LOG_STORAGE.list(reverse=reverse)
"""历史日志
参数:
reverse: 反转顺序.
"""
return LOG_STORAGE.list(reverse=reverse) # type: ignore
@router.websocket("/logs")

View File

@ -1,115 +1,115 @@
from typing import Optional
# from typing import Optional
import cattrs
from fastapi import APIRouter
# import cattrs
# from fastapi import APIRouter
from configs.config import Config
from services.log import logger
from utils.manager import plugin_data_manager, plugins2settings_manager, plugins_manager
from utils.manager.models import PluginData, PluginType
# from configs.config import Config
# 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 *
from ..models.model import Plugin, PluginConfig, Result
from ..models.params import UpdateConfig, UpdatePlugin
from ..utils import authentication
# from ..config import *
# from ..base_model import Plugin, PluginConfig, Result
# from ..models.params import UpdateConfig, UpdatePlugin
# from ..utils import authentication
router = APIRouter()
# router = APIRouter()
@router.get("/get_plugins", dependencies=[authentication()])
def _(
plugin_type: PluginType,
) -> Result:
"""
获取插件列表
:param plugin_type: 类型 normal, superuser, hidden, admin
"""
try:
plugin_list = []
for module in plugin_data_manager.keys():
plugin_data: Optional[PluginData] = plugin_data_manager[module]
if plugin_data and plugin_data.plugin_type == plugin_type:
plugin_config = None
if plugin_data.plugin_configs:
plugin_config = {}
for key in plugin_data.plugin_configs:
plugin_config[key] = PluginConfig(
key=key,
module=module,
has_type=bool(plugin_data.plugin_configs[key].type),
**plugin_data.plugin_configs[key].dict(),
)
plugin_list.append(
Plugin(
model=module,
plugin_settings=plugin_data.plugin_setting,
plugin_manager=plugin_data.plugin_status,
plugin_config=plugin_config,
cd_limit=plugin_data.plugin_cd,
block_limit=plugin_data.plugin_block,
count_limit=plugin_data.plugin_count,
)
)
except Exception as e:
logger.error("调用API错误", "/get_plugins", e=e)
return Result.fail(f"{type(e)}: {e}")
return Result.ok(plugin_list, "拿到了新鲜出炉的数据!")
# @router.get("/get_plugins", dependencies=[authentication()])
# def _(
# plugin_type: PluginType,
# ) -> Result:
# """
# 获取插件列表
# :param plugin_type: 类型 normal, superuser, hidden, admin
# """
# try:
# plugin_list = []
# for module in plugin_data_manager.keys():
# plugin_data: Optional[PluginData] = plugin_data_manager[module]
# if plugin_data and plugin_data.plugin_type == plugin_type:
# plugin_config = None
# if plugin_data.plugin_configs:
# plugin_config = {}
# for key in plugin_data.plugin_configs:
# plugin_config[key] = PluginConfig(
# key=key,
# module=module,
# has_type=bool(plugin_data.plugin_configs[key].type),
# **plugin_data.plugin_configs[key].dict(),
# )
# plugin_list.append(
# Plugin(
# model=module,
# plugin_settings=plugin_data.plugin_setting,
# plugin_manager=plugin_data.plugin_status,
# plugin_config=plugin_config,
# cd_limit=plugin_data.plugin_cd,
# block_limit=plugin_data.plugin_block,
# count_limit=plugin_data.plugin_count,
# )
# )
# except Exception as e:
# logger.error("调用API错误", "/get_plugins", e=e)
# return Result.fail(f"{type(e)}: {e}")
# return Result.ok(plugin_list, "拿到了新鲜出炉的数据!")
@router.post("/update_plugins", dependencies=[authentication()])
def _(plugin: UpdatePlugin) -> Result:
"""
修改插件信息
:param plugin: 插件内容
"""
try:
module = plugin.module
if p2s := plugins2settings_manager.get(module):
p2s.default_status = plugin.default_status
p2s.limit_superuser = plugin.limit_superuser
p2s.cost_gold = plugin.cost_gold
p2s.cmd = plugin.cmd
p2s.level = plugin.group_level
if pd := plugin_data_manager.get(module):
menu_lin = None
if len(pd.menu_type) > 1:
menu_lin = pd.menu_type[1]
if menu_lin is not None:
pd.menu_type = (plugin.menu_type, menu_lin)
else:
pd.menu_type = (plugin.menu_type,)
if pm := plugins_manager.get(module):
if plugin.block_type:
pm.block_type = plugin.block_type
pm.status = False
else:
pm.block_type = None
pm.status = True
plugins2settings_manager.save()
plugins_manager.save()
except Exception as e:
logger.error("调用API错误", "/update_plugins", e=e)
return Result.fail(f"{type(e)}: {e}")
return Result.ok(info="已经帮你写好啦!")
# @router.post("/update_plugins", dependencies=[authentication()])
# def _(plugin: UpdatePlugin) -> Result:
# """
# 修改插件信息
# :param plugin: 插件内容
# """
# try:
# module = plugin.module
# if p2s := plugins2settings_manager.get(module):
# p2s.default_status = plugin.default_status
# p2s.limit_superuser = plugin.limit_superuser
# p2s.cost_gold = plugin.cost_gold
# p2s.cmd = plugin.cmd
# p2s.level = plugin.group_level
# if pd := plugin_data_manager.get(module):
# menu_lin = None
# if len(pd.menu_type) > 1:
# menu_lin = pd.menu_type[1]
# if menu_lin is not None:
# pd.menu_type = (plugin.menu_type, menu_lin)
# else:
# pd.menu_type = (plugin.menu_type,)
# if pm := plugins_manager.get(module):
# if plugin.block_type:
# pm.block_type = plugin.block_type
# pm.status = False
# else:
# pm.block_type = None
# pm.status = True
# plugins2settings_manager.save()
# plugins_manager.save()
# except Exception as e:
# logger.error("调用API错误", "/update_plugins", e=e)
# return Result.fail(f"{type(e)}: {e}")
# return Result.ok(info="已经帮你写好啦!")
@router.post("/update_config", dependencies=[authentication()])
def _(config_list: List[UpdateConfig]) -> Result:
try:
for config in config_list:
if cg := Config.get(config.module):
if c := cg.configs.get(config.key):
if isinstance(c.value, (list, tuple)) or isinstance(
c.default_value, (list, tuple)
):
value = config.value.split(",")
else:
value = config.value
if c.type and value is not None:
value = cattrs.structure(value, c.type)
Config.set_config(config.module, config.key, value)
except Exception as e:
logger.error("调用API错误", "/update_config", e=e)
return Result.fail(f"{type(e)}: {e}")
Config.save(save_simple_data=True)
return Result.ok(info="写入配置项了哦!")
# @router.post("/update_config", dependencies=[authentication()])
# def _(config_list: List[UpdateConfig]) -> Result:
# try:
# for config in config_list:
# if cg := Config.get(config.module):
# if c := cg.configs.get(config.key):
# if isinstance(c.value, (list, tuple)) or isinstance(
# c.default_value, (list, tuple)
# ):
# value = config.value.split(",")
# else:
# value = config.value
# if c.type and value is not None:
# value = cattrs.structure(value, c.type)
# Config.set_config(config.module, config.key, value)
# except Exception as e:
# logger.error("调用API错误", "/update_config", e=e)
# return Result.fail(f"{type(e)}: {e}")
# Config.save(save_simple_data=True)
# return Result.ok(info="写入配置项了哦!")

View File

@ -8,7 +8,7 @@ from services.log import logger
from utils.manager import requests_manager
from utils.utils import get_bot
from ..models.model import RequestResult, Result
from ..base_model import RequestResult, Result
from ..models.params import HandleRequest
from ..utils import authentication
@ -42,46 +42,46 @@ def _(request_type: Optional[str]) -> Result:
return Result.ok(info="成功清除了数据")
@router.post("/handle_request", dependencies=[authentication()])
async def _(parma: HandleRequest) -> Result:
"""
操作请求
:param parma: 参数
"""
try:
result = "操作成功!"
flag = 3
if bot := get_bot():
if parma.handle == "approve":
if parma.type == "group":
if rid := requests_manager.get_group_id(parma.id):
# await GroupInfo.update_or_create(defaults={"group_flag": 1}, )
if group := await GroupInfo.get_or_none(group_id=str(rid)):
await group.update_or_create(group_flag=1)
else:
group_info = await bot.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,
},
)
flag = await requests_manager.approve(bot, parma.id, parma.type)
elif parma.handle == "refuse":
flag = await requests_manager.refused(bot, parma.id, parma.type)
elif parma.handle == "delete":
requests_manager.delete_request(parma.id, parma.type)
if parma.handle != "delete":
if flag == 1:
result = "该请求已失效"
requests_manager.delete_request(parma.id, parma.type)
elif flag == 2:
result = "未找到此Id"
return Result.ok(result, "成功处理了请求!")
return Result.fail("Bot未连接")
except Exception as e:
logger.error("调用API错误", "/get_group", e=e)
return Result.fail(f"{type(e)}: {e}")
# @router.post("/handle_request", dependencies=[authentication()])
# async def _(parma: HandleRequest) -> Result:
# """
# 操作请求
# :param parma: 参数
# """
# try:
# result = "操作成功!"
# flag = 3
# if bot := get_bot():
# if parma.handle == "approve":
# if parma.type == "group":
# if rid := requests_manager.get_group_id(parma.id):
# # await GroupInfo.update_or_create(defaults={"group_flag": 1}, )
# if group := await GroupInfo.get_or_none(group_id=str(rid)):
# await group.update_or_create(group_flag=1)
# else:
# group_info = await bot.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,
# },
# )
# flag = await requests_manager.approve(bot, parma.id, parma.type)
# elif parma.handle == "refuse":
# flag = await requests_manager.refused(bot, parma.id, parma.type)
# elif parma.handle == "delete":
# requests_manager.delete_request(parma.id, parma.type)
# if parma.handle != "delete":
# if flag == 1:
# result = "该请求已失效"
# requests_manager.delete_request(parma.id, parma.type)
# elif flag == 2:
# result = "未找到此Id"
# return Result.ok(result, "成功处理了请求!")
# return Result.fail("Bot未连接")
# except Exception as e:
# logger.error("调用API错误", "/get_group", e=e)
# return Result.fail(f"{type(e)}: {e}")

View File

@ -1,228 +1,228 @@
import asyncio
import os
from datetime import datetime
from pathlib import Path
from typing import Dict, Optional, Union
# import asyncio
# import os
# from datetime import datetime
# from pathlib import Path
# from typing import Dict, Optional, Union
import psutil
import ujson as json
from fastapi import APIRouter
# import psutil
# import ujson as json
# from fastapi import APIRouter
from configs.path_config import (
DATA_PATH,
FONT_PATH,
IMAGE_PATH,
LOG_PATH,
RECORD_PATH,
TEMP_PATH,
TEXT_PATH,
)
from services.log import logger
from utils.http_utils import AsyncHttpx
# from configs.path_config import (
# DATA_PATH,
# FONT_PATH,
# IMAGE_PATH,
# LOG_PATH,
# RECORD_PATH,
# TEMP_PATH,
# TEXT_PATH,
# )
# from services.log import logger
# from utils.http_utils import AsyncHttpx
from ..models.model import (
Result,
SystemFolderSize,
SystemNetwork,
SystemResult,
SystemStatus,
SystemStatusList,
)
from ..utils import authentication
# from ..base_model import (
# Result,
# SystemFolderSize,
# SystemNetwork,
# SystemResult,
# SystemStatus,
# SystemStatusList,
# )
# from ..utils import authentication
CPU_DATA_PATH = DATA_PATH / "system" / "cpu.json"
MEMORY_DATA_PATH = DATA_PATH / "system" / "memory.json"
DISK_DATA_PATH = DATA_PATH / "system" / "disk.json"
CPU_DATA_PATH.parent.mkdir(exist_ok=True, parents=True)
cpu_data = {"data": []}
memory_data = {"data": []}
disk_data = {"data": []}
# CPU_DATA_PATH = DATA_PATH / "system" / "cpu.json"
# MEMORY_DATA_PATH = DATA_PATH / "system" / "memory.json"
# DISK_DATA_PATH = DATA_PATH / "system" / "disk.json"
# CPU_DATA_PATH.parent.mkdir(exist_ok=True, parents=True)
# cpu_data = {"data": []}
# memory_data = {"data": []}
# disk_data = {"data": []}
router = APIRouter()
# router = APIRouter()
@router.get("/system", dependencies=[authentication()])
async def _() -> Result:
return await get_system_data()
# @router.get("/system", dependencies=[authentication()])
# async def _() -> Result:
# return await get_system_data()
@router.get("/status", dependencies=[authentication()])
async def _() -> Result:
return Result.ok(
await asyncio.get_event_loop().run_in_executor(None, _get_system_status),
)
# @router.get("/status", dependencies=[authentication()])
# async def _() -> Result:
# return Result.ok(
# await asyncio.get_event_loop().run_in_executor(None, _get_system_status),
# )
@router.get("/system/disk", dependencies=[authentication()])
async def _(type_: Optional[str] = None) -> Result:
return Result.ok(
data=await asyncio.get_event_loop().run_in_executor(
None, _get_system_disk, type_
),
)
# @router.get("/system/disk", dependencies=[authentication()])
# async def _(type_: Optional[str] = None) -> Result:
# return Result.ok(
# data=await asyncio.get_event_loop().run_in_executor(
# None, _get_system_disk, type_
# ),
# )
@router.get("/system/statusList", dependencies=[authentication()])
async def _() -> Result:
global cpu_data, memory_data, disk_data
await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
cpu_rst = cpu_data["data"][-10:] if len(cpu_data["data"]) > 10 else cpu_data["data"]
memory_rst = (
memory_data["data"][-10:]
if len(memory_data["data"]) > 10
else memory_data["data"]
)
disk_rst = (
disk_data["data"][-10:] if len(disk_data["data"]) > 10 else disk_data["data"]
)
return Result.ok(
SystemStatusList(
cpu_data=cpu_rst,
memory_data=memory_rst,
disk_data=disk_rst,
),
)
# @router.get("/system/statusList", dependencies=[authentication()])
# async def _() -> Result:
# global cpu_data, memory_data, disk_data
# await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
# cpu_rst = cpu_data["data"][-10:] if len(cpu_data["data"]) > 10 else cpu_data["data"]
# memory_rst = (
# memory_data["data"][-10:]
# if len(memory_data["data"]) > 10
# else memory_data["data"]
# )
# disk_rst = (
# disk_data["data"][-10:] if len(disk_data["data"]) > 10 else disk_data["data"]
# )
# return Result.ok(
# SystemStatusList(
# cpu_data=cpu_rst,
# memory_data=memory_rst,
# disk_data=disk_rst,
# ),
# )
async def get_system_data():
"""
说明:
获取系统信息资源文件大小网络状态等
"""
baidu = 200
google = 200
try:
await AsyncHttpx.get("https://www.baidu.com/", timeout=5)
except Exception as e:
logger.warning(f"访问BaiDu失败... {type(e)}: {e}")
baidu = 404
try:
await AsyncHttpx.get("https://www.google.com/", timeout=5)
except Exception as e:
logger.warning(f"访问Google失败... {type(e)}: {e}")
google = 404
network = SystemNetwork(baidu=baidu, google=google)
disk = await asyncio.get_event_loop().run_in_executor(None, _get_system_disk, None)
status = await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
return Result.ok(
SystemResult(
status=status,
network=network,
disk=disk, # type: ignore
check_time=datetime.now().replace(microsecond=0),
),
)
# async def get_system_data():
# """
# 说明:
# 获取系统信息,资源文件大小,网络状态等
# """
# baidu = 200
# google = 200
# try:
# await AsyncHttpx.get("https://www.baidu.com/", timeout=5)
# except Exception as e:
# logger.warning(f"访问BaiDu失败... {type(e)}: {e}")
# baidu = 404
# try:
# await AsyncHttpx.get("https://www.google.com/", timeout=5)
# except Exception as e:
# logger.warning(f"访问Google失败... {type(e)}: {e}")
# google = 404
# network = SystemNetwork(baidu=baidu, google=google)
# disk = await asyncio.get_event_loop().run_in_executor(None, _get_system_disk, None)
# status = await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
# return Result.ok(
# SystemResult(
# status=status,
# network=network,
# disk=disk, # type: ignore
# check_time=datetime.now().replace(microsecond=0),
# ),
# )
def _get_system_status() -> SystemStatus:
"""
说明:
获取系统信息等
"""
cpu = psutil.cpu_percent()
memory = psutil.virtual_memory().percent
disk = psutil.disk_usage("/").percent
save_system_data(cpu, memory, disk)
return SystemStatus(
cpu=cpu,
memory=memory,
disk=disk,
check_time=datetime.now().replace(microsecond=0),
)
# def _get_system_status() -> SystemStatus:
# """
# 说明:
# 获取系统信息等
# """
# cpu = psutil.cpu_percent()
# memory = psutil.virtual_memory().percent
# disk = psutil.disk_usage("/").percent
# save_system_data(cpu, memory, disk)
# return SystemStatus(
# cpu=cpu,
# memory=memory,
# disk=disk,
# check_time=datetime.now().replace(microsecond=0),
# )
def _get_system_disk(
type_: Optional[str],
) -> Union[SystemFolderSize, Dict[str, Union[float, datetime]]]:
"""
说明:
获取资源文件大小等
"""
if not type_:
disk = SystemFolderSize(
font_dir_size=_get_dir_size(FONT_PATH) / 1024 / 1024,
image_dir_size=_get_dir_size(IMAGE_PATH) / 1024 / 1024,
text_dir_size=_get_dir_size(TEXT_PATH) / 1024 / 1024,
record_dir_size=_get_dir_size(RECORD_PATH) / 1024 / 1024,
temp_dir_size=_get_dir_size(TEMP_PATH) / 1024 / 102,
data_dir_size=_get_dir_size(DATA_PATH) / 1024 / 1024,
log_dir_size=_get_dir_size(LOG_PATH) / 1024 / 1024,
check_time=datetime.now().replace(microsecond=0),
)
return disk
else:
if type_ == "image":
dir_path = IMAGE_PATH
elif type_ == "font":
dir_path = FONT_PATH
elif type_ == "text":
dir_path = TEXT_PATH
elif type_ == "record":
dir_path = RECORD_PATH
elif type_ == "data":
dir_path = DATA_PATH
elif type_ == "temp":
dir_path = TEMP_PATH
else:
dir_path = LOG_PATH
dir_map = {}
other_file_size = 0
for file in os.listdir(dir_path):
file = Path(dir_path / file)
if file.is_dir():
dir_map[file.name] = _get_dir_size(file) / 1024 / 1024
else:
other_file_size += os.path.getsize(file) / 1024 / 1024
dir_map["其他文件"] = other_file_size
dir_map["check_time"] = datetime.now().replace(microsecond=0)
return dir_map
# def _get_system_disk(
# type_: Optional[str],
# ) -> Union[SystemFolderSize, Dict[str, Union[float, datetime]]]:
# """
# 说明:
# 获取资源文件大小等
# """
# if not type_:
# disk = SystemFolderSize(
# font_dir_size=_get_dir_size(FONT_PATH) / 1024 / 1024,
# image_dir_size=_get_dir_size(IMAGE_PATH) / 1024 / 1024,
# text_dir_size=_get_dir_size(TEXT_PATH) / 1024 / 1024,
# record_dir_size=_get_dir_size(RECORD_PATH) / 1024 / 1024,
# temp_dir_size=_get_dir_size(TEMP_PATH) / 1024 / 102,
# data_dir_size=_get_dir_size(DATA_PATH) / 1024 / 1024,
# log_dir_size=_get_dir_size(LOG_PATH) / 1024 / 1024,
# check_time=datetime.now().replace(microsecond=0),
# )
# return disk
# else:
# if type_ == "image":
# dir_path = IMAGE_PATH
# elif type_ == "font":
# dir_path = FONT_PATH
# elif type_ == "text":
# dir_path = TEXT_PATH
# elif type_ == "record":
# dir_path = RECORD_PATH
# elif type_ == "data":
# dir_path = DATA_PATH
# elif type_ == "temp":
# dir_path = TEMP_PATH
# else:
# dir_path = LOG_PATH
# dir_map = {}
# other_file_size = 0
# for file in os.listdir(dir_path):
# file = Path(dir_path / file)
# if file.is_dir():
# dir_map[file.name] = _get_dir_size(file) / 1024 / 1024
# else:
# other_file_size += os.path.getsize(file) / 1024 / 1024
# dir_map["其他文件"] = other_file_size
# dir_map["check_time"] = datetime.now().replace(microsecond=0)
# return dir_map
def _get_dir_size(dir_path: Path) -> float:
"""
说明:
获取文件夹大小
参数:
:param dir_path: 文件夹路径
"""
size = 0
for root, dirs, files in os.walk(dir_path):
size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
return size
# def _get_dir_size(dir_path: Path) -> float:
# """
# 说明:
# 获取文件夹大小
# 参数:
# :param dir_path: 文件夹路径
# """
# size = 0
# for root, dirs, files in os.walk(dir_path):
# size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
# return size
def save_system_data(cpu: float, memory: float, disk: float):
"""
说明:
保存一些系统信息
参数:
:param cpu: cpu
:param memory: memory
:param disk: disk
"""
global cpu_data, memory_data, disk_data
if CPU_DATA_PATH.exists() and not cpu_data["data"]:
with open(CPU_DATA_PATH, "r") as f:
cpu_data = json.load(f)
if MEMORY_DATA_PATH.exists() and not memory_data["data"]:
with open(MEMORY_DATA_PATH, "r") as f:
memory_data = json.load(f)
if DISK_DATA_PATH.exists() and not disk_data["data"]:
with open(DISK_DATA_PATH, "r") as f:
disk_data = json.load(f)
now = str(datetime.now().time().replace(microsecond=0))
cpu_data["data"].append({"time": now, "data": cpu})
memory_data["data"].append({"time": now, "data": memory})
disk_data["data"].append({"time": now, "data": disk})
if len(cpu_data["data"]) > 50:
cpu_data["data"] = cpu_data["data"][-50:]
if len(memory_data["data"]) > 50:
memory_data["data"] = memory_data["data"][-50:]
if len(disk_data["data"]) > 50:
disk_data["data"] = disk_data["data"][-50:]
with open(CPU_DATA_PATH, "w") as f:
json.dump(cpu_data, f, indent=4, ensure_ascii=False)
with open(MEMORY_DATA_PATH, "w") as f:
json.dump(memory_data, f, indent=4, ensure_ascii=False)
with open(DISK_DATA_PATH, "w") as f:
json.dump(disk_data, f, indent=4, ensure_ascii=False)
# def save_system_data(cpu: float, memory: float, disk: float):
# """
# 说明:
# 保存一些系统信息
# 参数:
# :param cpu: cpu
# :param memory: memory
# :param disk: disk
# """
# global cpu_data, memory_data, disk_data
# if CPU_DATA_PATH.exists() and not cpu_data["data"]:
# with open(CPU_DATA_PATH, "r") as f:
# cpu_data = json.load(f)
# if MEMORY_DATA_PATH.exists() and not memory_data["data"]:
# with open(MEMORY_DATA_PATH, "r") as f:
# memory_data = json.load(f)
# if DISK_DATA_PATH.exists() and not disk_data["data"]:
# with open(DISK_DATA_PATH, "r") as f:
# disk_data = json.load(f)
# now = str(datetime.now().time().replace(microsecond=0))
# cpu_data["data"].append({"time": now, "data": cpu})
# memory_data["data"].append({"time": now, "data": memory})
# disk_data["data"].append({"time": now, "data": disk})
# if len(cpu_data["data"]) > 50:
# cpu_data["data"] = cpu_data["data"][-50:]
# if len(memory_data["data"]) > 50:
# memory_data["data"] = memory_data["data"][-50:]
# if len(disk_data["data"]) > 50:
# disk_data["data"] = disk_data["data"][-50:]
# with open(CPU_DATA_PATH, "w") as f:
# json.dump(cpu_data, f, indent=4, ensure_ascii=False)
# with open(MEMORY_DATA_PATH, "w") as f:
# json.dump(memory_data, f, indent=4, ensure_ascii=False)
# with open(DISK_DATA_PATH, "w") as f:
# json.dump(disk_data, f, indent=4, ensure_ascii=False)

View File

@ -0,0 +1,2 @@
from .main import *
from .manage import *

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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}")

View File

@ -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"""

View File

@ -5,7 +5,7 @@ import nonebot
from fastapi import APIRouter, Depends
from fastapi.security import OAuth2PasswordRequestForm
from ..models.model import Result
from ..base_model import Result
from ..utils import (
ACCESS_TOKEN_EXPIRE_MINUTES,
create_token,

View File

@ -0,0 +1,139 @@
from datetime import datetime
from logging import warning
from typing import Any, Dict, List, Optional, TypeVar, Union
from nonebot.adapters.onebot.v11 import Bot
from pydantic import BaseModel
from configs.utils import Config
from utils.manager.models import Plugin as PluginManager
from utils.manager.models import PluginBlock, PluginCd, PluginCount, PluginSetting
class User(BaseModel):
username: str
password: str
class Token(BaseModel):
access_token: str
token_type: str
class Result(BaseModel):
"""
总体返回
"""
suc: bool
"""调用状态"""
code: int = 200
"""code"""
info: str = "操作成功"
"""info"""
warning: Optional[str] = None
"""警告信息"""
data: Any = None
"""返回数据"""
@classmethod
def warning_(cls, info: str, code: int = 200) -> "Result":
return cls(suc=True, warning=info, code=code)
@classmethod
def fail(cls, info: str = "异常错误", code: int = 500) -> "Result":
return cls(suc=False, info=info, code=code)
@classmethod
def ok(cls, data: Any = None, info: str = "操作成功", code: int = 200) -> "Result":
return cls(suc=True, info=info, code=code, data=data)
# class PluginConfig(BaseModel):
# """
# 插件配置项
# """
# module: str
# key: str
# value: Optional[Any]
# help: Optional[str]
# default_value: Optional[Any]
# has_type: bool
# class Plugin(BaseModel):
# """
# 插件
# """
# model: str
# """模块名称"""
# plugin_settings: Optional[PluginSetting]
# """settings"""
# plugin_manager: Optional[PluginManager]
# """manager"""
# plugin_config: Optional[Dict[str, PluginConfig]]
# """配置项"""
# cd_limit: Optional[PluginCd]
# """cd限制"""
# block_limit: Optional[PluginBlock]
# """阻断限制"""
# count_limit: Optional[PluginCount]
# """次数限制"""
class SystemStatus(BaseModel):
"""
系统状态
"""
cpu: float
memory: float
disk: float
check_time: datetime
class SystemNetwork(BaseModel):
"""
系统网络状态
"""
baidu: int
google: int
class SystemFolderSize(BaseModel):
"""
资源文件占比
"""
font_dir_size: float
image_dir_size: float
text_dir_size: float
record_dir_size: float
temp_dir_size: float
data_dir_size: float
log_dir_size: float
check_time: datetime
class SystemStatusList(BaseModel):
"""
状态记录
"""
cpu_data: List[Dict[str, Union[float, str]]]
memory_data: List[Dict[str, Union[float, str]]]
disk_data: List[Dict[str, Union[float, str]]]
class SystemResult(BaseModel):
"""
系统api返回
"""
status: SystemStatus
network: SystemNetwork
disk: SystemFolderSize
check_time: datetime

View File

@ -5,6 +5,7 @@ import nonebot
from fastapi import APIRouter
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from strenum import StrEnum
app = nonebot.get_app()
@ -19,85 +20,62 @@ app.add_middleware(
)
class RequestResult(BaseModel):
class QueryDateType(StrEnum):
"""
好友/群组请求管理
查询日期类型
"""
oid: str
id: int
flag: str
nickname: Optional[str]
level: Optional[int]
sex: Optional[str]
age: Optional[int]
from_: Optional[str]
comment: Optional[str]
invite_group: Optional[int]
group_name: Optional[str]
DAY = "day"
""""""
WEEK = "week"
""""""
MONTH = "month"
""""""
YEAR = "year"
""""""
class RequestParma(BaseModel):
"""
操作请求接收数据
"""
# class SystemNetwork(BaseModel):
# """
# 系统网络状态
# """
id: int
handle: str
type: str
# baidu: int
# google: int
class SystemStatus(BaseModel):
"""
系统状态
"""
# class SystemFolderSize(BaseModel):
# """
# 资源文件占比
# """
cpu: int
memory: int
disk: int
check_time: datetime
# font_dir_size: float
# image_dir_size: float
# text_dir_size: float
# record_dir_size: float
# temp_dir_size: float
# data_dir_size: float
# log_dir_size: float
# check_time: datetime
class SystemNetwork(BaseModel):
"""
系统网络状态
"""
# class SystemStatusList(BaseModel):
# """
# 状态记录
# """
baidu: int
google: int
# cpu_data: List[Dict[str, Union[float, str]]]
# memory_data: List[Dict[str, Union[float, str]]]
# disk_data: List[Dict[str, Union[float, str]]]
class SystemFolderSize(BaseModel):
"""
资源文件占比
"""
# class SystemResult(BaseModel):
# """
# 系统api返回
# """
font_dir_size: float
image_dir_size: float
text_dir_size: float
record_dir_size: float
temp_dir_size: float
data_dir_size: float
log_dir_size: float
check_time: datetime
class SystemStatusList(BaseModel):
"""
状态记录
"""
cpu_data: List[Dict[str, Union[float, str]]]
memory_data: List[Dict[str, Union[float, str]]]
disk_data: List[Dict[str, Union[float, str]]]
class SystemResult(BaseModel):
"""
系统api返回
"""
status: SystemStatus
network: SystemNetwork
disk: SystemFolderSize
check_time: datetime
# status: SystemStatus
# network: SystemNetwork
# disk: SystemFolderSize
# check_time: datetime

View File

@ -1,223 +0,0 @@
from datetime import datetime
from typing import Any, Dict, List, Optional, TypeVar, Union
from nonebot.adapters.onebot.v11 import Bot
from pydantic import BaseModel
from configs.utils import Config
from utils.manager.models import Plugin as PluginManager
from utils.manager.models import PluginBlock, PluginCd, PluginCount, PluginSetting
class User(BaseModel):
username: str
password: str
class Token(BaseModel):
access_token: str
token_type: str
class Result(BaseModel):
"""
总体返回
"""
suc: bool
"""调用状态"""
code: int = 200
"""code"""
info: str = "操作成功"
"""info"""
data: Any = None
"""返回数据"""
@classmethod
def fail(cls, info: str = "异常错误", code: int = 500) -> "Result":
return cls(suc=False, info=info, code=code)
@classmethod
def ok(cls, data: Any = None, info: str = "操作成功", code: int = 200) -> "Result":
return cls(suc=True, info=info, code=code, data=data)
class PluginConfig(BaseModel):
"""
插件配置项
"""
module: str
key: str
value: Optional[Any]
help: Optional[str]
default_value: Optional[Any]
has_type: bool
class Plugin(BaseModel):
"""
插件
"""
model: str
"""模块名称"""
plugin_settings: Optional[PluginSetting]
"""settings"""
plugin_manager: Optional[PluginManager]
"""manager"""
plugin_config: Optional[Dict[str, PluginConfig]]
"""配置项"""
cd_limit: Optional[PluginCd]
"""cd限制"""
block_limit: Optional[PluginBlock]
"""阻断限制"""
count_limit: Optional[PluginCount]
"""次数限制"""
class Group(BaseModel):
"""
群组信息
"""
group_id: int
group_name: str
member_count: int
max_member_count: int
class Task(BaseModel):
"""
被动技能
"""
name: str
nameZh: str
status: bool
class GroupResult(BaseModel):
"""
群组返回数据
"""
group: Group
level: int
status: bool
close_plugins: List[str]
task: List[Task]
class RequestResult(BaseModel):
"""
好友/群组请求管理
"""
oid: str
id: int
flag: str
nickname: Optional[str]
level: Optional[int]
sex: Optional[str]
age: Optional[int]
from_: Optional[str]
comment: Optional[str]
invite_group: Optional[int]
group_name: Optional[str]
class SystemStatus(BaseModel):
"""
系统状态
"""
cpu: float
memory: float
disk: float
check_time: datetime
class SystemNetwork(BaseModel):
"""
系统网络状态
"""
baidu: int
google: int
class SystemFolderSize(BaseModel):
"""
资源文件占比
"""
font_dir_size: float
image_dir_size: float
text_dir_size: float
record_dir_size: float
temp_dir_size: float
data_dir_size: float
log_dir_size: float
check_time: datetime
class SystemStatusList(BaseModel):
"""
状态记录
"""
cpu_data: List[Dict[str, Union[float, str]]]
memory_data: List[Dict[str, Union[float, str]]]
disk_data: List[Dict[str, Union[float, str]]]
class SystemResult(BaseModel):
"""
系统api返回
"""
status: SystemStatus
network: SystemNetwork
disk: SystemFolderSize
check_time: datetime
class BotInfo(BaseModel):
"""
Bot基础信息
"""
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
"""一月内累计接收消息"""
plugin_count: int = 0
"""加载插件数量"""
success_plugin_count: int = 0
"""加载成功插件数量"""
fail_plugin_count: int = 0
"""加载失败插件数量"""
is_select: bool = False
"""当前选择"""
class Config:
arbitrary_types_allowed = True

View File

@ -1,59 +0,0 @@
from typing import Any, List
from pydantic import BaseModel
class UpdatePlugin(BaseModel):
"""
插件修改参数
"""
module: str
"""模块"""
default_status: bool
"""默认开关"""
limit_superuser: bool
"""限制超级用户"""
cost_gold: int
"""金币花费"""
cmd: List[str]
"""插件别名"""
menu_type: str
"""插件菜单类型"""
group_level: int
"""插件所需群权限"""
block_type: str
"""禁用类型"""
class UpdateConfig(BaseModel):
"""
配置项修改参数
"""
module: str
"""模块"""
key: str
"""配置项key"""
value: Any
"""配置项值"""
class UpdateGroup(BaseModel):
group_id: str
"""群号"""
status: bool
"""状态"""
level: int
"""群权限"""
class HandleRequest(BaseModel):
"""
操作请求接收数据
"""
id: int
handle: str
type: str

View File

@ -1,16 +1,35 @@
import os
from datetime import datetime, timedelta
from typing import Any, Optional
from pathlib import Path
from typing import Any, Dict, Optional, Union
import nonebot
import psutil
import ujson as json
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from nonebot.utils import run_sync
from configs.config import Config
from configs.path_config import DATA_PATH
from configs.path_config import (
DATA_PATH,
FONT_PATH,
IMAGE_PATH,
LOG_PATH,
RECORD_PATH,
TEMP_PATH,
TEXT_PATH,
)
from .models.model import Result, User
from .base_model import (
Result,
SystemFolderSize,
SystemNetwork,
SystemResult,
SystemStatus,
SystemStatusList,
User,
)
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
@ -29,6 +48,14 @@ if token_file.exists():
def get_user(uname: str) -> Optional[User]:
"""获取账号密码
参数:
uname: uname
返回:
Optional[User]: 用户信息
"""
username = Config.get_config("web-ui", "username")
password = Config.get_config("web-ui", "password")
if username and password and uname == username:
@ -36,6 +63,12 @@ def get_user(uname: str) -> Optional[User]:
def create_token(user: User, expires_delta: Optional[timedelta] = None):
"""创建token
参数:
user: 用户信息
expires_delta: 过期时间.
"""
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
return jwt.encode(
claims={"sub": user.username, "exp": expire},
@ -45,6 +78,13 @@ def create_token(user: User, expires_delta: Optional[timedelta] = None):
def authentication():
"""权限验证
异常:
JWTError: JWTError
HTTPException: HTTPException
"""
# if token not in token_data["token"]:
def inner(token: str = Depends(oauth2_scheme)):
try:
@ -57,3 +97,81 @@ def authentication():
raise HTTPException(status_code=400, detail="登录验证失败或已失效, 踢出房间!")
return Depends(inner)
def _get_dir_size(dir_path: Path) -> float:
"""
说明:
获取文件夹大小
参数:
:param dir_path: 文件夹路径
"""
size = 0
for root, dirs, files in os.walk(dir_path):
size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
return size
@run_sync
def get_system_status() -> SystemStatus:
"""
说明:
获取系统信息等
"""
cpu = psutil.cpu_percent()
memory = psutil.virtual_memory().percent
disk = psutil.disk_usage("/").percent
return SystemStatus(
cpu=cpu,
memory=memory,
disk=disk,
check_time=datetime.now().replace(microsecond=0),
)
@run_sync
def get_system_disk(
type_: Optional[str],
) -> Union[SystemFolderSize, Dict[str, Union[float, datetime]]]:
"""
说明:
获取资源文件大小等
"""
if not type_:
disk = SystemFolderSize(
font_dir_size=_get_dir_size(FONT_PATH) / 1024 / 1024,
image_dir_size=_get_dir_size(IMAGE_PATH) / 1024 / 1024,
text_dir_size=_get_dir_size(TEXT_PATH) / 1024 / 1024,
record_dir_size=_get_dir_size(RECORD_PATH) / 1024 / 1024,
temp_dir_size=_get_dir_size(TEMP_PATH) / 1024 / 102,
data_dir_size=_get_dir_size(DATA_PATH) / 1024 / 1024,
log_dir_size=_get_dir_size(LOG_PATH) / 1024 / 1024,
check_time=datetime.now().replace(microsecond=0),
)
return disk
else:
if type_ == "image":
dir_path = IMAGE_PATH
elif type_ == "font":
dir_path = FONT_PATH
elif type_ == "text":
dir_path = TEXT_PATH
elif type_ == "record":
dir_path = RECORD_PATH
elif type_ == "data":
dir_path = DATA_PATH
elif type_ == "temp":
dir_path = TEMP_PATH
else:
dir_path = LOG_PATH
dir_map = {}
other_file_size = 0
for file in os.listdir(dir_path):
file = Path(dir_path / file)
if file.is_dir():
dir_map[file.name] = _get_dir_size(file) / 1024 / 1024
else:
other_file_size += os.path.getsize(file) / 1024 / 1024
dir_map["其他文件"] = other_file_size
dir_map["check_time"] = datetime.now().replace(microsecond=0)
return dir_map

View File

@ -2,7 +2,6 @@ import asyncio
from typing import Optional
from nonebot import get_driver
from nonebot.log import logger
from playwright.async_api import Browser, Playwright, async_playwright
from services.log import logger
@ -26,7 +25,7 @@ async def shutdown_browser():
if _browser:
await _browser.close()
if _playwright:
_playwright.stop()
await _playwright.stop() # type: ignore
def get_browser() -> Browser:

View File

@ -30,7 +30,7 @@ class StaticData(Generic[T]):
try:
self._data: dict = json.load(f)
except ValueError:
if f.read().strip():
if not f.read().strip():
raise ValueError(f"{file} 文件加载错误,请检查文件内容格式.")
elif file.name.endswith("yaml"):
self._data = _yaml.load(f)

View File

@ -1,11 +1,13 @@
from utils.manager.data_class import StaticData
from nonebot.adapters.onebot.v11 import Bot, ActionFailed
from services.log import logger
from typing import Optional
from utils.image_utils import BuildImage
from utils.utils import get_user_avatar
from pathlib import Path
from io import BytesIO
from pathlib import Path
from typing import Optional
from nonebot.adapters.onebot.v11 import ActionFailed, Bot
from services.log import logger
from utils.image_utils import BuildImage
from utils.manager.data_class import StaticData
from utils.utils import get_user_avatar
class RequestManager(StaticData):
@ -21,6 +23,7 @@ class RequestManager(StaticData):
def add_request(
self,
bot_id: str,
id_: int,
type_: str,
flag: str,
@ -36,6 +39,7 @@ class RequestManager(StaticData):
):
"""
添加一个请求
:param bot_id: bot_id
:param id_: id用户id或群id
:param type_: 类型private group
:param flag: event.flag
@ -49,6 +53,7 @@ class RequestManager(StaticData):
:param group_name: 群聊名称
"""
self._data[type_][str(len(self._data[type_].keys()))] = {
"bot_id": bot_id,
"id": id_,
"flag": flag,
"nickname": nickname,
@ -102,7 +107,9 @@ class RequestManager(StaticData):
"""
return await self._set_add_request(bot, id_, type_, False)
def clear(self, type_: Optional[str] = None): # type_: Optional[Literal["group", "private"]] = None
def clear(
self, type_: Optional[str] = None
): # type_: Optional[Literal["group", "private"]] = None
"""
清空所有请求信息无视请求
:param type_: 类型
@ -113,7 +120,9 @@ class RequestManager(StaticData):
self._data = {"private": {}, "group": {}}
self.save()
def delete_request(self, id_: int, type_: str): # type_: Literal["group", "private"]
def delete_request(
self, id_: int, type_: str
): # type_: Literal["group", "private"]
"""
删除请求
:param id_: id
@ -230,7 +239,7 @@ class RequestManager(StaticData):
return bk.pic2bs4()
async def _set_add_request(
self, bot: Bot, id_: int, type_: str, approve: bool
self, bot: Bot, idx: int, type_: str, approve: bool
) -> int:
"""
处理请求
@ -239,7 +248,7 @@ class RequestManager(StaticData):
:param type_: 类型private group
:param approve: 是否同意
"""
id_ = str(id_)
id_ = str(idx)
if id_ in self._data[type_].keys():
try:
if type_ == "private":
@ -259,7 +268,7 @@ class RequestManager(StaticData):
f"同意{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})"
f"{'好友' if type_ == 'private' else '入群'}请求失败了..."
)
return 1 # flag失效
return 1 # flag失效
else:
logger.info(
f"{'同意' if approve else '拒绝'}{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})"
@ -268,4 +277,4 @@ class RequestManager(StaticData):
del self._data[type_][id_]
self.save()
return rid
return 2 # 未找到id
return 2 # 未找到id