mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 14:22:55 +08:00
UPDATE WEB UI
This commit is contained in:
parent
3cc834d424
commit
62e29f389b
@ -1,32 +1,40 @@
|
|||||||
|
import nonebot
|
||||||
|
from fastapi import APIRouter, FastAPI
|
||||||
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
|
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
|
||||||
from nonebot.matcher import Matcher
|
from nonebot.matcher import Matcher
|
||||||
from nonebot.message import IgnoredException, run_preprocessor
|
from nonebot.message import run_preprocessor
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
|
|
||||||
from configs.config import Config as gConfig
|
from configs.config import Config as gConfig
|
||||||
|
from services.log import logger
|
||||||
from utils.manager import plugins2settings_manager
|
from utils.manager import plugins2settings_manager
|
||||||
|
|
||||||
from .api import *
|
from .api.group import router as group_routes
|
||||||
from .auth import *
|
from .api.plugins import router as plugin_routes
|
||||||
|
from .api.request import router as request_routes
|
||||||
|
from .api.system import router as system_routes
|
||||||
|
|
||||||
|
# from .api.g import *
|
||||||
|
from .auth import router as auth_router
|
||||||
|
|
||||||
|
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_="前端管理密码")
|
||||||
|
|
||||||
|
|
||||||
# 使用webui访问api后plugins2settings中的cmd字段将从list变为str
|
BaseApiRouter = APIRouter(prefix="/zhenxun/api")
|
||||||
# 暂时找不到原因
|
|
||||||
# 先使用hook修复
|
BaseApiRouter.include_router(auth_router)
|
||||||
@run_preprocessor
|
BaseApiRouter.include_router(plugin_routes)
|
||||||
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
|
BaseApiRouter.include_router(group_routes)
|
||||||
flag = False
|
BaseApiRouter.include_router(request_routes)
|
||||||
for module in plugins2settings_manager.keys():
|
BaseApiRouter.include_router(system_routes)
|
||||||
if plugins2settings_manager.get_plugin_data(module).cmd and isinstance(
|
|
||||||
plugins2settings_manager.get_plugin_data(module).cmd, str
|
|
||||||
):
|
@driver.on_startup
|
||||||
plugins2settings_manager[module].cmd = plugins2settings_manager[
|
def _():
|
||||||
module
|
app: FastAPI = nonebot.get_app()
|
||||||
].cmd.split(",")
|
app.include_router(BaseApiRouter)
|
||||||
flag = True
|
logger.info("<g>API启动成功</g>", "Web UI")
|
||||||
if flag:
|
|
||||||
plugins2settings_manager.save()
|
|
||||||
|
|||||||
@ -1,27 +1,31 @@
|
|||||||
|
from fastapi import APIRouter
|
||||||
from pydantic.error_wrappers import ValidationError
|
from pydantic.error_wrappers import ValidationError
|
||||||
|
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from utils.manager import group_manager
|
from utils.manager import group_manager
|
||||||
from utils.utils import get_bot
|
from utils.utils import get_bot
|
||||||
|
|
||||||
from ..auth import Depends, User, token_to_user
|
from ..models.model import Group, GroupResult, Result, Task
|
||||||
from ..config import *
|
from ..models.params import UpdateGroup
|
||||||
|
from ..utils import authentication
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/group", dependencies=[token_to_user()])
|
@router.get("/get_group", dependencies=[authentication()])
|
||||||
async def _() -> Result:
|
async def _() -> Result:
|
||||||
"""
|
"""
|
||||||
获取群信息
|
获取群信息
|
||||||
"""
|
"""
|
||||||
group_list_result = []
|
group_list_result = []
|
||||||
group_info = {}
|
try:
|
||||||
if bot := get_bot():
|
group_info = {}
|
||||||
group_list = await bot.get_group_list()
|
if bot := get_bot():
|
||||||
for g in group_list:
|
group_list = await bot.get_group_list()
|
||||||
group_info[g["group_id"]] = Group(**g)
|
for g in group_list:
|
||||||
group_data = group_manager.get_data()
|
group_info[g["group_id"]] = Group(**g)
|
||||||
for group_id in group_data.group_manager:
|
group_data = group_manager.get_data()
|
||||||
try:
|
for group_id in group_data.group_manager:
|
||||||
task_list = []
|
task_list = []
|
||||||
data = group_manager[group_id].dict()
|
data = group_manager[group_id].dict()
|
||||||
for tn, status in data["group_task_status"].items():
|
for tn, status in data["group_task_status"].items():
|
||||||
@ -39,24 +43,27 @@ async def _() -> Result:
|
|||||||
data["group"] = x
|
data["group"] = x
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
try:
|
group_list_result.append(GroupResult(**data))
|
||||||
group_list_result.append(GroupResult(**data))
|
except Exception as e:
|
||||||
except ValidationError:
|
logger.error("调用API错误", "/get_group", e=e)
|
||||||
pass
|
return Result.fail(f"{type(e)}: {e}")
|
||||||
except Exception as e:
|
return Result.ok(group_list_result, "拿到了新鲜出炉的数据!")
|
||||||
logger.error(f"WEB_UI /webui/group 发生错误 {type(e)}:{e}")
|
|
||||||
return Result(code=200, data=group_list_result)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/group", dependencies=[token_to_user()])
|
@router.post("/update_group", dependencies=[authentication()])
|
||||||
async def _(group: GroupResult) -> Result:
|
async def _(group: UpdateGroup) -> Result:
|
||||||
"""
|
"""
|
||||||
修改群信息
|
修改群信息
|
||||||
"""
|
"""
|
||||||
group_id = group.group.group_id
|
try:
|
||||||
group_manager.set_group_level(group_id, group.level)
|
group_id = group.group_id
|
||||||
if group.status:
|
group_manager.set_group_level(group_id, group.level)
|
||||||
group_manager.turn_on_group_bot_status(group_id)
|
if group.status:
|
||||||
else:
|
group_manager.turn_on_group_bot_status(group_id)
|
||||||
group_manager.shutdown_group_bot_status(group_id)
|
else:
|
||||||
return Result(data="修改成功!")
|
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="已完成记录!")
|
||||||
|
|||||||
@ -1,176 +1,115 @@
|
|||||||
from pydantic import ValidationError
|
from typing import Optional
|
||||||
|
|
||||||
|
import cattrs
|
||||||
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from configs.config import Config
|
from configs.config import Config
|
||||||
from services.log import logger
|
from services.log import logger
|
||||||
from utils.manager import (
|
from utils.manager import plugin_data_manager, plugins2settings_manager, plugins_manager
|
||||||
plugins2block_manager,
|
from utils.manager.models import PluginData, PluginType
|
||||||
plugins2cd_manager,
|
|
||||||
plugins2count_manager,
|
|
||||||
plugins2settings_manager,
|
|
||||||
plugins_manager,
|
|
||||||
)
|
|
||||||
from utils.utils import get_matchers
|
|
||||||
|
|
||||||
from ..auth import Depends, User, token_to_user
|
|
||||||
from ..config import *
|
from ..config import *
|
||||||
|
from ..models.model import Plugin, PluginConfig, Result
|
||||||
|
from ..models.params import UpdateConfig, UpdatePlugin
|
||||||
|
from ..utils import authentication
|
||||||
|
|
||||||
plugin_name_list = None
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/plugins", dependencies=[token_to_user()])
|
@router.get("/get_plugins", dependencies=[authentication()])
|
||||||
def _(type_: Optional[str]) -> Result:
|
def _(
|
||||||
|
plugin_type: PluginType,
|
||||||
|
) -> Result:
|
||||||
"""
|
"""
|
||||||
获取插件列表
|
获取插件列表
|
||||||
:param type_: 类型 normal, superuser, hidden, admin
|
:param plugin_type: 类型 normal, superuser, hidden, admin
|
||||||
"""
|
"""
|
||||||
global plugin_name_list
|
try:
|
||||||
if not plugin_name_list:
|
plugin_list = []
|
||||||
plugin_name_list = [x.plugin_name for x in get_matchers(True)]
|
for module in plugin_data_manager.keys():
|
||||||
plugin_list = []
|
plugin_data: Optional[PluginData] = plugin_data_manager[module]
|
||||||
plugin_data = plugins_manager.get_data()
|
if plugin_data and plugin_data.plugin_type == plugin_type:
|
||||||
for model in plugin_data:
|
plugin_config = None
|
||||||
if model in plugin_name_list:
|
if plugin_data.plugin_configs:
|
||||||
try:
|
plugin_config = {}
|
||||||
data = plugin_data.get(model)
|
for key in plugin_data.plugin_configs:
|
||||||
# data.model = model
|
plugin_config[key] = PluginConfig(
|
||||||
plugin_name = data.plugin_name
|
key=key,
|
||||||
if (
|
module=module,
|
||||||
(type_ == "hidden" and "[hidden]" not in plugin_name.lower())
|
has_type=bool(plugin_data.plugin_configs[key].type),
|
||||||
or (type_ == "admin" and "[admin]" not in plugin_name.lower())
|
**plugin_data.plugin_configs[key].dict(),
|
||||||
or (
|
)
|
||||||
type_ == "superuser"
|
plugin_list.append(
|
||||||
and "[superuser]" not in plugin_name.lower()
|
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,
|
||||||
)
|
)
|
||||||
):
|
|
||||||
continue
|
|
||||||
if type_ == "normal" and (
|
|
||||||
"[hidden]" in plugin_name.lower()
|
|
||||||
or "[admin]" in plugin_name.lower()
|
|
||||||
or "[superuser]" in plugin_name.lower()
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
data = {"model": model}
|
|
||||||
if x := plugin_data.get(model):
|
|
||||||
if not x.status and x.block_type in [
|
|
||||||
"group",
|
|
||||||
"private",
|
|
||||||
"all",
|
|
||||||
]:
|
|
||||||
x.block_type = (
|
|
||||||
"群聊"
|
|
||||||
if x.block_type == "group"
|
|
||||||
else "私聊"
|
|
||||||
if x.block_type == "private"
|
|
||||||
else "全部"
|
|
||||||
)
|
|
||||||
data["plugin_manager"] = PluginManager(**x.dict())
|
|
||||||
if x := plugins2settings_manager.get(model):
|
|
||||||
if x.cmd and isinstance(x.cmd, list):
|
|
||||||
x.cmd = ",".join(x.cmd)
|
|
||||||
data["plugin_settings"] = PluginSettings(**x.dict())
|
|
||||||
if x := plugins2cd_manager.get(model):
|
|
||||||
data["cd_limit"] = CdLimit(**x.dict())
|
|
||||||
if x := plugins2block_manager.get(model):
|
|
||||||
data["block_limit"] = BlockLimit(**x.dict())
|
|
||||||
if x := plugins2count_manager.get(model):
|
|
||||||
data["count_limit"] = CountLimit(**x.dict())
|
|
||||||
if x := Config.get(model):
|
|
||||||
id_ = 0
|
|
||||||
tmp = []
|
|
||||||
for key in x.keys():
|
|
||||||
tmp.append(
|
|
||||||
PluginConfig(
|
|
||||||
**{
|
|
||||||
"key": key,
|
|
||||||
"help_": x[key].get("help"),
|
|
||||||
"id": id_,
|
|
||||||
**x[key],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
id_ += 1
|
|
||||||
data["plugin_config"] = tmp
|
|
||||||
plugin_list.append(Plugin(**data))
|
|
||||||
except (AttributeError, ValidationError) as e:
|
|
||||||
logger.error(
|
|
||||||
f"WEB_UI GET /webui/plugins model:{model} 发生错误 {type(e)}:{e}"
|
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(
|
logger.error("调用API错误", "/get_plugins", e=e)
|
||||||
f"WEB_UI GET /webui/plugins model:{model} 发生错误 {type(e)}:{e}"
|
return Result.fail(f"{type(e)}: {e}")
|
||||||
)
|
return Result.ok(plugin_list, "拿到了新鲜出炉的数据!")
|
||||||
return Result(
|
|
||||||
code=500,
|
|
||||||
data=f"WEB_UI GET /webui/plugins model:{model} 发生错误 {type(e)}:{e}",
|
|
||||||
)
|
|
||||||
return Result(code=200, data=plugin_list)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/plugins", dependencies=[token_to_user()])
|
@router.post("/update_plugins", dependencies=[authentication()])
|
||||||
def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
|
def _(plugin: UpdatePlugin) -> Result:
|
||||||
"""
|
"""
|
||||||
修改插件信息
|
修改插件信息
|
||||||
:param plugin: 插件内容
|
:param plugin: 插件内容
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if plugin.plugin_config:
|
module = plugin.module
|
||||||
for c in plugin.plugin_config:
|
if p2s := plugins2settings_manager.get(module):
|
||||||
if not c.value:
|
p2s.default_status = plugin.default_status
|
||||||
Config.set_config(plugin.model, c.key, None)
|
p2s.limit_superuser = plugin.limit_superuser
|
||||||
continue
|
p2s.cost_gold = plugin.cost_gold
|
||||||
if str(c.value).lower() in ["true", "false"] and (
|
p2s.cmd = plugin.cmd
|
||||||
c.default_value is None or isinstance(c.default_value, bool)
|
p2s.level = plugin.group_level
|
||||||
):
|
if pd := plugin_data_manager.get(module):
|
||||||
c.value = str(c.value).lower() == "true"
|
menu_lin = None
|
||||||
elif isinstance(
|
if len(pd.menu_type) > 1:
|
||||||
Config.get_config(plugin.model, c.key, c.value), int
|
menu_lin = pd.menu_type[1]
|
||||||
) or isinstance(c.default_value, int):
|
if menu_lin is not None:
|
||||||
c.value = int(c.value)
|
pd.menu_type = (plugin.menu_type, menu_lin)
|
||||||
elif isinstance(
|
else:
|
||||||
Config.get_config(plugin.model, c.key, c.value), float
|
pd.menu_type = (plugin.menu_type,)
|
||||||
) or isinstance(c.default_value, float):
|
if pm := plugins_manager.get(module):
|
||||||
c.value = float(c.value)
|
if plugin.block_type:
|
||||||
elif isinstance(c.value, str) and (
|
pm.block_type = plugin.block_type
|
||||||
isinstance(
|
pm.status = False
|
||||||
Config.get_config(plugin.model, c.key, c.value), (list, tuple)
|
else:
|
||||||
)
|
pm.block_type = None
|
||||||
or isinstance(c.default_value, (list, tuple))
|
pm.status = True
|
||||||
):
|
plugins2settings_manager.save()
|
||||||
default_value = Config.get_config(plugin.model, c.key, c.value)
|
plugins_manager.save()
|
||||||
c.value = c.value.split(",")
|
|
||||||
if default_value and isinstance(default_value[0], int):
|
|
||||||
c.value = [int(x) for x in c.value]
|
|
||||||
elif default_value and isinstance(default_value[0], float):
|
|
||||||
c.value = [float(x) for x in c.value]
|
|
||||||
elif default_value and isinstance(default_value[0], bool):
|
|
||||||
temp = []
|
|
||||||
for x in c.value:
|
|
||||||
temp.append(x.lower() == "true")
|
|
||||||
c.value = temp
|
|
||||||
Config.set_config(plugin.model, c.key, c.value)
|
|
||||||
Config.save(None, True)
|
|
||||||
else:
|
|
||||||
if plugin.plugin_settings:
|
|
||||||
for key, value in plugin.plugin_settings:
|
|
||||||
if key == "cmd":
|
|
||||||
value = value.split(",")
|
|
||||||
setattr(plugins2settings_manager[plugin.model], key, value)
|
|
||||||
if plugin.plugin_manager:
|
|
||||||
for key, value in plugin.plugin_manager:
|
|
||||||
setattr(plugins_manager[plugin.model], key, value)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(
|
logger.error("调用API错误", "/update_plugins", e=e)
|
||||||
f"WEB_UI POST /webui/plugins model:{plugin.model} 发生错误 {type(e)}:{e}"
|
return Result.fail(f"{type(e)}: {e}")
|
||||||
)
|
return Result.ok(info="已经帮你写好啦!")
|
||||||
return Result(
|
|
||||||
code=500,
|
|
||||||
data=f"WEB_UI POST /webui/plugins model:{plugin.model} 发生错误 {type(e)}:{e}",
|
@router.post("/update_config", dependencies=[authentication()])
|
||||||
)
|
def _(config_list: List[UpdateConfig]) -> Result:
|
||||||
for key in plugins2settings_manager.keys():
|
try:
|
||||||
if isinstance(plugins2settings_manager[key].cmd, str):
|
for config in config_list:
|
||||||
plugins2settings_manager[key].cmd = plugins2settings_manager[key].cmd.split(
|
if cg := Config.get(config.module):
|
||||||
","
|
if c := cg.configs.get(config.key):
|
||||||
)
|
if isinstance(c.value, (list, tuple)) or isinstance(
|
||||||
plugins2settings_manager.save()
|
c.default_value, (list, tuple)
|
||||||
plugins_manager.save()
|
):
|
||||||
return Result(code=200, data="修改成功!")
|
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="写入配置项了哦!")
|
||||||
|
|||||||
@ -1,69 +1,87 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from fastapi import APIRouter
|
||||||
|
|
||||||
|
from configs.config import NICKNAME
|
||||||
from models.group_info import GroupInfo
|
from models.group_info import GroupInfo
|
||||||
|
from services.log import logger
|
||||||
from utils.manager import requests_manager
|
from utils.manager import requests_manager
|
||||||
from utils.utils import get_bot
|
from utils.utils import get_bot
|
||||||
|
|
||||||
from ..auth import Depends, User, token_to_user
|
from ..models.model import RequestResult, Result
|
||||||
from ..config import *
|
from ..models.params import HandleRequest
|
||||||
|
from ..utils import authentication
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/webui/request", dependencies=[token_to_user()])
|
@router.get("/get_request", dependencies=[authentication()])
|
||||||
def _(type_: Optional[str]) -> Result:
|
def _(request_type: Optional[str]) -> Result:
|
||||||
req_data = requests_manager.get_data()
|
try:
|
||||||
req_list = []
|
req_data = requests_manager.get_data()
|
||||||
if type_ in ["group", "private"]:
|
req_list = []
|
||||||
req_data = req_data[type_]
|
if request_type in ["group", "private"]:
|
||||||
for x in req_data:
|
req_data = req_data[request_type]
|
||||||
req_data[x]["oid"] = x
|
for x in req_data:
|
||||||
req_list.append(RequestResult(**req_data[x]))
|
req_data[x]["oid"] = x
|
||||||
req_list.reverse()
|
req_list.append(RequestResult(**req_data[x]))
|
||||||
return Result(code=200, data=req_list)
|
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("/webui/request", dependencies=[token_to_user()])
|
@router.delete("/clear_request", dependencies=[authentication()])
|
||||||
def _(type_: Optional[str]) -> Result:
|
def _(request_type: Optional[str]) -> Result:
|
||||||
"""
|
"""
|
||||||
清空请求
|
清空请求
|
||||||
:param type_: 类型
|
:param type_: 类型
|
||||||
"""
|
"""
|
||||||
requests_manager.clear(type_)
|
requests_manager.clear(request_type)
|
||||||
return Result(code=200)
|
return Result.ok(info="成功清除了数据")
|
||||||
|
|
||||||
|
|
||||||
@router.post("/webui/request", dependencies=[token_to_user()])
|
@router.post("/handle_request", dependencies=[authentication()])
|
||||||
async def _(parma: RequestParma) -> Result:
|
async def _(parma: HandleRequest) -> Result:
|
||||||
"""
|
"""
|
||||||
操作请求
|
操作请求
|
||||||
:param parma: 参数
|
:param parma: 参数
|
||||||
"""
|
"""
|
||||||
result = "操作成功!"
|
try:
|
||||||
flag = 3
|
result = "操作成功!"
|
||||||
if bot := get_bot():
|
flag = 3
|
||||||
if parma.handle == "approve":
|
if bot := get_bot():
|
||||||
if parma.type == "group":
|
if parma.handle == "approve":
|
||||||
if rid := requests_manager.get_group_id(parma.id):
|
if parma.type == "group":
|
||||||
# await GroupInfo.update_or_create(defaults={"group_flag": 1}, )
|
if rid := requests_manager.get_group_id(parma.id):
|
||||||
if group := await GroupInfo.filter(group_id=rid).first():
|
# await GroupInfo.update_or_create(defaults={"group_flag": 1}, )
|
||||||
await group.update_or_create(group_flag=1)
|
if group := await GroupInfo.get_or_none(group_id=rid):
|
||||||
else:
|
await group.update_or_create(group_flag=1)
|
||||||
group_info = await bot.get_group_info(group_id=rid)
|
else:
|
||||||
await GroupInfo.update_or_create(
|
group_info = await bot.get_group_info(group_id=rid)
|
||||||
group_id=group_info["group_id"],
|
await GroupInfo.update_or_create(
|
||||||
defaults={
|
group_id=group_info["group_id"],
|
||||||
"group_name": group_info["group_name"],
|
defaults={
|
||||||
"max_member_count": group_info["max_member_count"],
|
"group_name": group_info["group_name"],
|
||||||
"member_count": group_info["member_count"],
|
"max_member_count": group_info["max_member_count"],
|
||||||
"group_flag": 1,
|
"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.approve(bot, parma.id, parma.type)
|
||||||
flag = await requests_manager.refused(bot, parma.id, parma.type)
|
elif parma.handle == "refuse":
|
||||||
elif parma.handle == "delete":
|
flag = await requests_manager.refused(bot, parma.id, parma.type)
|
||||||
requests_manager.delete_request(parma.id, parma.type)
|
elif parma.handle == "delete":
|
||||||
if parma.handle != "delete":
|
|
||||||
if flag == 1:
|
|
||||||
result = "该请求已失效"
|
|
||||||
requests_manager.delete_request(parma.id, parma.type)
|
requests_manager.delete_request(parma.id, parma.type)
|
||||||
elif flag == 2:
|
if parma.handle != "delete":
|
||||||
result = "未找到此Id"
|
if flag == 1:
|
||||||
return Result(code=200, data=result)
|
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}")
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Dict, Optional, Union
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
import ujson as json
|
import ujson as json
|
||||||
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from configs.path_config import (
|
from configs.path_config import (
|
||||||
DATA_PATH,
|
DATA_PATH,
|
||||||
@ -17,8 +20,15 @@ from configs.path_config import (
|
|||||||
from services.log import logger
|
from services.log import logger
|
||||||
from utils.http_utils import AsyncHttpx
|
from utils.http_utils import AsyncHttpx
|
||||||
|
|
||||||
from ..auth import Depends, User, token_to_user
|
from ..models.model import (
|
||||||
from ..config import *
|
Result,
|
||||||
|
SystemFolderSize,
|
||||||
|
SystemNetwork,
|
||||||
|
SystemResult,
|
||||||
|
SystemStatus,
|
||||||
|
SystemStatusList,
|
||||||
|
)
|
||||||
|
from ..utils import authentication
|
||||||
|
|
||||||
CPU_DATA_PATH = DATA_PATH / "system" / "cpu.json"
|
CPU_DATA_PATH = DATA_PATH / "system" / "cpu.json"
|
||||||
MEMORY_DATA_PATH = DATA_PATH / "system" / "memory.json"
|
MEMORY_DATA_PATH = DATA_PATH / "system" / "memory.json"
|
||||||
@ -28,31 +38,31 @@ cpu_data = {"data": []}
|
|||||||
memory_data = {"data": []}
|
memory_data = {"data": []}
|
||||||
disk_data = {"data": []}
|
disk_data = {"data": []}
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
@router.get("/system", dependencies=[token_to_user()])
|
|
||||||
|
@router.get("/system", dependencies=[authentication()])
|
||||||
async def _() -> Result:
|
async def _() -> Result:
|
||||||
return await get_system_data()
|
return await get_system_data()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/webui/system/status", dependencies=[token_to_user()])
|
@router.get("/status", dependencies=[authentication()])
|
||||||
async def _() -> Result:
|
async def _() -> Result:
|
||||||
return Result(
|
return Result.ok(
|
||||||
code=200,
|
await asyncio.get_event_loop().run_in_executor(None, _get_system_status),
|
||||||
data=await asyncio.get_event_loop().run_in_executor(None, _get_system_status),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/webui/system/disk", dependencies=[token_to_user()])
|
@router.get("/system/disk", dependencies=[authentication()])
|
||||||
async def _(type_: Optional[str] = None) -> Result:
|
async def _(type_: Optional[str] = None) -> Result:
|
||||||
return Result(
|
return Result.ok(
|
||||||
code=200,
|
|
||||||
data=await asyncio.get_event_loop().run_in_executor(
|
data=await asyncio.get_event_loop().run_in_executor(
|
||||||
None, _get_system_disk, type_
|
None, _get_system_disk, type_
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/webui/system/statusList", dependencies=[token_to_user()])
|
@router.get("/system/statusList", dependencies=[authentication()])
|
||||||
async def _() -> Result:
|
async def _() -> Result:
|
||||||
global cpu_data, memory_data, disk_data
|
global cpu_data, memory_data, disk_data
|
||||||
await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
|
await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
|
||||||
@ -65,9 +75,8 @@ async def _() -> Result:
|
|||||||
disk_rst = (
|
disk_rst = (
|
||||||
disk_data["data"][-10:] if len(disk_data["data"]) > 10 else disk_data["data"]
|
disk_data["data"][-10:] if len(disk_data["data"]) > 10 else disk_data["data"]
|
||||||
)
|
)
|
||||||
return Result(
|
return Result.ok(
|
||||||
code=200,
|
SystemStatusList(
|
||||||
data=SystemStatusList(
|
|
||||||
cpu_data=cpu_rst,
|
cpu_data=cpu_rst,
|
||||||
memory_data=memory_rst,
|
memory_data=memory_rst,
|
||||||
disk_data=disk_rst,
|
disk_data=disk_rst,
|
||||||
@ -95,12 +104,11 @@ async def get_system_data():
|
|||||||
network = SystemNetwork(baidu=baidu, google=google)
|
network = SystemNetwork(baidu=baidu, google=google)
|
||||||
disk = await asyncio.get_event_loop().run_in_executor(None, _get_system_disk, None)
|
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)
|
status = await asyncio.get_event_loop().run_in_executor(None, _get_system_status)
|
||||||
return Result(
|
return Result.ok(
|
||||||
code=200,
|
SystemResult(
|
||||||
data=SystemResult(
|
|
||||||
status=status,
|
status=status,
|
||||||
network=network,
|
network=network,
|
||||||
disk=disk,
|
disk=disk, # type: ignore
|
||||||
check_time=datetime.now().replace(microsecond=0),
|
check_time=datetime.now().replace(microsecond=0),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,74 +1,32 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime, timedelta
|
from datetime import timedelta
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
from fastapi import Depends, HTTPException
|
from fastapi import APIRouter, Depends
|
||||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
from fastapi.security import OAuth2PasswordRequestForm
|
||||||
from jose import JWTError, jwt
|
|
||||||
from pydantic import BaseModel
|
|
||||||
from starlette import status
|
|
||||||
|
|
||||||
from configs.config import Config
|
from ..models.model import Result
|
||||||
from configs.path_config import DATA_PATH
|
from ..utils import (
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES,
|
||||||
from ..config import Result, router
|
create_token,
|
||||||
|
get_user,
|
||||||
|
token_data,
|
||||||
|
token_file,
|
||||||
|
)
|
||||||
|
|
||||||
app = nonebot.get_app()
|
app = nonebot.get_app()
|
||||||
|
|
||||||
|
|
||||||
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
|
router = APIRouter()
|
||||||
ALGORITHM = "HS256"
|
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES = 30
|
|
||||||
|
|
||||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/login")
|
|
||||||
|
|
||||||
|
|
||||||
token_file = DATA_PATH / "web_ui" / "token.json"
|
|
||||||
token_file.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
token_data = {"token": []}
|
|
||||||
if token_file.exists():
|
|
||||||
token_data = json.load(open(token_file, "r", encoding="utf8"))
|
|
||||||
|
|
||||||
|
|
||||||
class User(BaseModel):
|
|
||||||
username: str
|
|
||||||
password: str
|
|
||||||
|
|
||||||
|
|
||||||
class Token(BaseModel):
|
|
||||||
access_token: str
|
|
||||||
token_type: str
|
|
||||||
|
|
||||||
|
|
||||||
def get_user(uname: str) -> Optional[User]:
|
|
||||||
username = Config.get_config("web-ui", "username")
|
|
||||||
password = Config.get_config("web-ui", "password")
|
|
||||||
if username and password and uname == username:
|
|
||||||
return User(username=username, password=password)
|
|
||||||
|
|
||||||
|
|
||||||
form_exception = HTTPException(
|
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
||||||
detail="Could not validate credentials",
|
|
||||||
headers={"WWW-Authenticate": "Bearer"},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def create_token(user: User, expires_delta: Optional[timedelta] = None):
|
|
||||||
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
|
|
||||||
return jwt.encode(
|
|
||||||
claims={"sub": user.username, "exp": expire},
|
|
||||||
key=SECRET_KEY,
|
|
||||||
algorithm=ALGORITHM,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/login")
|
@router.post("/login")
|
||||||
async def login_get_token(form_data: OAuth2PasswordRequestForm = Depends()):
|
async def login_get_token(form_data: OAuth2PasswordRequestForm = Depends()):
|
||||||
user = get_user(form_data.username)
|
if user := get_user(form_data.username):
|
||||||
if not user or user.password != form_data.password:
|
if user.password != form_data.password:
|
||||||
raise form_exception
|
return Result.fail("真笨, 密码都能记错!", 999)
|
||||||
|
else:
|
||||||
|
return Result.fail("你滴配置文件里用户名密码配置项为空", 998)
|
||||||
access_token = create_token(
|
access_token = create_token(
|
||||||
user=user, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
user=user, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||||
)
|
)
|
||||||
@ -77,31 +35,6 @@ async def login_get_token(form_data: OAuth2PasswordRequestForm = Depends()):
|
|||||||
token_data["token"] = token_data["token"][1:]
|
token_data["token"] = token_data["token"][1:]
|
||||||
with open(token_file, "w", encoding="utf8") as f:
|
with open(token_file, "w", encoding="utf8") as f:
|
||||||
json.dump(token_data, f, ensure_ascii=False, indent=4)
|
json.dump(token_data, f, ensure_ascii=False, indent=4)
|
||||||
return {"access_token": access_token, "token_type": "bearer"}
|
return Result.ok(
|
||||||
|
{"access_token": access_token, "token_type": "bearer"}, "欢迎回家, 欧尼酱!"
|
||||||
|
)
|
||||||
credentials_exception = HTTPException(
|
|
||||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
||||||
detail="Could not validate credentials",
|
|
||||||
headers={"WWW-Authenticate": "Bearer"},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/auth")
|
|
||||||
def token_to_user(token: str = Depends(oauth2_scheme)):
|
|
||||||
if token not in token_data["token"]:
|
|
||||||
try:
|
|
||||||
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
||||||
username, expire = payload.get("sub"), payload.get("exp")
|
|
||||||
user = get_user(username) # type: ignore
|
|
||||||
if user is None:
|
|
||||||
raise JWTError
|
|
||||||
except JWTError:
|
|
||||||
return Result(code=401)
|
|
||||||
return Result(code=200, info="登录成功")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
import uvicorn
|
|
||||||
|
|
||||||
uvicorn.run(app, host="127.0.0.1", port=8080)
|
|
||||||
|
|||||||
@ -18,127 +18,6 @@ app.add_middleware(
|
|||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
router = APIRouter(tags=["api"])
|
|
||||||
|
|
||||||
|
|
||||||
class CdLimit(BaseModel):
|
|
||||||
"""
|
|
||||||
Cd 限制
|
|
||||||
"""
|
|
||||||
|
|
||||||
cd: int
|
|
||||||
status: bool
|
|
||||||
check_type: str
|
|
||||||
limit_type: str
|
|
||||||
rst: Optional[str]
|
|
||||||
|
|
||||||
|
|
||||||
class BlockLimit(BaseModel):
|
|
||||||
"""
|
|
||||||
Block限制
|
|
||||||
"""
|
|
||||||
|
|
||||||
status: bool
|
|
||||||
check_type: str
|
|
||||||
limit_type: str
|
|
||||||
rst: Optional[str]
|
|
||||||
|
|
||||||
|
|
||||||
class CountLimit(BaseModel):
|
|
||||||
"""
|
|
||||||
Count限制
|
|
||||||
"""
|
|
||||||
|
|
||||||
max_count: int
|
|
||||||
status: bool
|
|
||||||
limit_type: str
|
|
||||||
rst: Optional[str]
|
|
||||||
|
|
||||||
|
|
||||||
class PluginManager(BaseModel):
|
|
||||||
"""
|
|
||||||
插件信息
|
|
||||||
"""
|
|
||||||
|
|
||||||
plugin_name: str # 插件名称
|
|
||||||
status: Optional[bool] # 插件状态
|
|
||||||
error: Optional[bool] # 加载状态
|
|
||||||
version: Optional[float] # 版本
|
|
||||||
author: Optional[str] # 作者
|
|
||||||
block_type: Optional[str] # 禁用类型
|
|
||||||
|
|
||||||
|
|
||||||
class PluginSettings(BaseModel):
|
|
||||||
"""
|
|
||||||
插件基本设置
|
|
||||||
"""
|
|
||||||
|
|
||||||
level: Optional[int] # 群权限等级
|
|
||||||
default_status: Optional[bool] # 默认开关
|
|
||||||
limit_superuser: Optional[bool] # 是否限制超级用户
|
|
||||||
cmd: Optional[str] # cmd别名
|
|
||||||
cost_gold: Optional[int] # 花费金币限制
|
|
||||||
plugin_type: Optional[List[Union[str, int]]] # 帮助类型
|
|
||||||
|
|
||||||
|
|
||||||
class PluginConfig(BaseModel):
|
|
||||||
"""
|
|
||||||
插件配置项
|
|
||||||
"""
|
|
||||||
|
|
||||||
id: int
|
|
||||||
key: str
|
|
||||||
value: Optional[Any]
|
|
||||||
help_: Optional[str]
|
|
||||||
default_value: Optional[Any]
|
|
||||||
|
|
||||||
|
|
||||||
class Plugin(BaseModel):
|
|
||||||
"""
|
|
||||||
插件
|
|
||||||
"""
|
|
||||||
|
|
||||||
model: str # 模块
|
|
||||||
plugin_settings: Optional[PluginSettings]
|
|
||||||
plugin_manager: Optional[PluginManager]
|
|
||||||
plugin_config: Optional[List[PluginConfig]]
|
|
||||||
cd_limit: Optional[CdLimit]
|
|
||||||
block_limit: Optional[BlockLimit]
|
|
||||||
count_limit: Optional[CountLimit]
|
|
||||||
|
|
||||||
|
|
||||||
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):
|
class RequestResult(BaseModel):
|
||||||
"""
|
"""
|
||||||
@ -222,13 +101,3 @@ class SystemResult(BaseModel):
|
|||||||
network: SystemNetwork
|
network: SystemNetwork
|
||||||
disk: SystemFolderSize
|
disk: SystemFolderSize
|
||||||
check_time: datetime
|
check_time: datetime
|
||||||
|
|
||||||
|
|
||||||
class Result(BaseModel):
|
|
||||||
"""
|
|
||||||
总体返回
|
|
||||||
"""
|
|
||||||
|
|
||||||
code: int = 200
|
|
||||||
info: str = "操作成功"
|
|
||||||
data: Any = None
|
|
||||||
|
|||||||
182
plugins/web_ui/models/model.py
Normal file
182
plugins/web_ui/models/model.py
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from typing import Any, Dict, List, Optional, TypeVar, Union
|
||||||
|
|
||||||
|
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
|
||||||
61
plugins/web_ui/models/params.py
Normal file
61
plugins/web_ui/models/params.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
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: int
|
||||||
|
"""群号"""
|
||||||
|
status: bool
|
||||||
|
"""状态"""
|
||||||
|
level: int
|
||||||
|
"""群权限"""
|
||||||
|
|
||||||
|
|
||||||
|
class HandleRequest(BaseModel):
|
||||||
|
"""
|
||||||
|
操作请求接收数据
|
||||||
|
"""
|
||||||
|
|
||||||
|
id: int
|
||||||
|
handle: str
|
||||||
|
type: str
|
||||||
|
|
||||||
|
|
||||||
59
plugins/web_ui/utils.py
Normal file
59
plugins/web_ui/utils.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
import nonebot
|
||||||
|
import ujson as json
|
||||||
|
from fastapi import Depends, HTTPException
|
||||||
|
from fastapi.security import OAuth2PasswordBearer
|
||||||
|
from jose import JWTError, jwt
|
||||||
|
|
||||||
|
from configs.config import Config
|
||||||
|
from configs.path_config import DATA_PATH
|
||||||
|
|
||||||
|
from .models.model import Result, User
|
||||||
|
|
||||||
|
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
|
||||||
|
ALGORITHM = "HS256"
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES = 30
|
||||||
|
|
||||||
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/login")
|
||||||
|
|
||||||
|
token_file = DATA_PATH / "web_ui" / "token.json"
|
||||||
|
token_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
token_data = {"token": []}
|
||||||
|
if token_file.exists():
|
||||||
|
try:
|
||||||
|
token_data = json.load(open(token_file, "r", encoding="utf8"))
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_user(uname: str) -> Optional[User]:
|
||||||
|
username = Config.get_config("web-ui", "username")
|
||||||
|
password = Config.get_config("web-ui", "password")
|
||||||
|
if username and password and uname == username:
|
||||||
|
return User(username=username, password=password)
|
||||||
|
|
||||||
|
|
||||||
|
def create_token(user: User, expires_delta: Optional[timedelta] = None):
|
||||||
|
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
|
||||||
|
return jwt.encode(
|
||||||
|
claims={"sub": user.username, "exp": expire},
|
||||||
|
key=SECRET_KEY,
|
||||||
|
algorithm=ALGORITHM,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def authentication():
|
||||||
|
# if token not in token_data["token"]:
|
||||||
|
def inner(token: str = Depends(oauth2_scheme)):
|
||||||
|
try:
|
||||||
|
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||||
|
username, expire = payload.get("sub"), payload.get("exp")
|
||||||
|
user = get_user(username) # type: ignore
|
||||||
|
if user is None:
|
||||||
|
raise JWTError
|
||||||
|
except JWTError:
|
||||||
|
raise HTTPException(status_code=400, detail="登录验证失败或已失效, 踢出房间!")
|
||||||
|
|
||||||
|
return Depends(inner)
|
||||||
@ -67,18 +67,24 @@ class StaticData(Generic[T]):
|
|||||||
temp[k] = copy.deepcopy(v)
|
temp[k] = copy.deepcopy(v)
|
||||||
return temp
|
return temp
|
||||||
|
|
||||||
def save(self, path: Union[str, Path] = None) -> NoReturn:
|
def save(self, path: Optional[Union[str, Path]] = None):
|
||||||
path = path or self.file
|
path = path or self.file
|
||||||
if isinstance(path, str):
|
if isinstance(path, str):
|
||||||
path = Path(path)
|
path = Path(path)
|
||||||
if path:
|
if path:
|
||||||
with open(path, "w", encoding="utf8") as f:
|
with open(path, "w", encoding="utf8") as f:
|
||||||
if path.name.endswith("yaml"):
|
if path.name.endswith("yaml"):
|
||||||
yaml.dump(self._data, f, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True)
|
yaml.dump(
|
||||||
|
self._data,
|
||||||
|
f,
|
||||||
|
indent=2,
|
||||||
|
Dumper=yaml.RoundTripDumper,
|
||||||
|
allow_unicode=True,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
json.dump(self.dict(), f, ensure_ascii=False, indent=4)
|
json.dump(self.dict(), f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
def reload(self) -> NoReturn:
|
def reload(self):
|
||||||
if self.file.exists():
|
if self.file.exists():
|
||||||
if self.file.name.endswith("json"):
|
if self.file.name.endswith("json"):
|
||||||
self._data: dict = json.load(open(self.file, "r", encoding="utf8"))
|
self._data: dict = json.load(open(self.file, "r", encoding="utf8"))
|
||||||
@ -94,7 +100,7 @@ class StaticData(Generic[T]):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return str(self._data)
|
return str(self._data)
|
||||||
|
|
||||||
def __setitem__(self, key, value) -> NoReturn:
|
def __setitem__(self, key, value):
|
||||||
self._data[key] = value
|
self._data[key] = value
|
||||||
|
|
||||||
def __getitem__(self, key) -> T:
|
def __getitem__(self, key) -> T:
|
||||||
|
|||||||
@ -140,4 +140,4 @@ class PluginData(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.name + self.menu_type[0])
|
return hash(self.name + str(self.menu_type[0]))
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class PluginDataManager(StaticData[PluginData]):
|
|||||||
raise ValueError(f"PluginInfoManager {info.model}:{info.name} 插件名称及类型已存在")
|
raise ValueError(f"PluginInfoManager {info.model}:{info.name} 插件名称及类型已存在")
|
||||||
self._data[info.model] = info
|
self._data[info.model] = info
|
||||||
|
|
||||||
def get(self, item: str, default: Any = None) -> PluginData:
|
def get(self, item: str, default: Any = None) -> Optional[PluginData]:
|
||||||
return self._data.get(item, default)
|
return self._data.get(item, default)
|
||||||
|
|
||||||
def __getitem__(self, item) -> Optional[PluginData]:
|
def __getitem__(self, item) -> Optional[PluginData]:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user