update v0.1.4.5

This commit is contained in:
HibiKier
2022-04-04 20:33:37 +08:00
parent b5ce4fab31
commit 0f59895c3b
22 changed files with 714 additions and 91 deletions
+20
View File
@@ -0,0 +1,20 @@
from configs.config import Config as gConfig
from .manager import *
from .auth import *
gConfig.add_plugin_config(
"web-ui",
"username",
"admin",
name="web-ui",
help_="前端管理用户名"
)
gConfig.add_plugin_config(
"web-ui",
"password",
None,
name="web-ui",
help_="前端管理密码"
)
+89
View File
@@ -0,0 +1,89 @@
from datetime import datetime, timedelta
from typing import Optional
from starlette import status
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from configs.config import Config
from jose import JWTError, jwt
import nonebot
app = nonebot.get_app()
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="webui/login")
class User(BaseModel):
username: str
password: str
class Token(BaseModel):
access_token: str
token_type: str
# USER_LIST = [
# User(username="admin", password="123")
# ]
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
)
@app.post("/webui/login")
async def login_get_token(form_data: OAuth2PasswordRequestForm = Depends()):
user: User = get_user(form_data.username)
if not user or user.password != form_data.password:
raise form_exception
access_token = create_token(user=user, expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
return {"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"},
)
def token_to_user(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)
if user is None:
raise JWTError
except JWTError:
raise credentials_exception
return user
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8080)
+112
View File
@@ -0,0 +1,112 @@
from typing import Optional, List, Any
from pydantic import BaseModel
from fastapi.middleware.cors import CORSMiddleware
import nonebot
app = nonebot.get_app()
origins = ["http://localhost"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class CdLimit(BaseModel):
cd: int
status: bool
check_type: str
limit_type: str
rst: Optional[str]
class BlockLimit(BaseModel):
status: bool
check_type: str
limit_type: str
rst: Optional[str]
class CountLimit(BaseModel):
max_count: int
status: bool
limit_type: bool
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[str] # 帮助类型
class Plugin(BaseModel):
model: str # 模块
plugin_settings: Optional[PluginSettings]
plugin_manager: Optional[PluginManager]
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):
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 RequestParma(BaseModel):
id: int
handle: str
type: str
class Result(BaseModel):
code: int
data: Any
+209
View File
@@ -0,0 +1,209 @@
from utils.manager import (
plugins_manager,
group_manager,
plugins2settings_manager,
plugins2cd_manager,
plugins2block_manager,
plugins2count_manager,
requests_manager,
)
from ..auth import token_to_user, Depends, User
from utils.utils import get_matchers, get_bot
from models.group_info import GroupInfo
from pydantic.error_wrappers import ValidationError
from services.log import logger
from ..config import *
import nonebot
app = nonebot.get_app()
plugin_name_list = None
@app.get("/webui/plugins")
def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
"""
获取插件列表
:param type_: 类型 normal, superuser, hidden, admin
"""
global plugin_name_list
if not plugin_name_list:
plugin_name_list = [x.plugin_name for x in get_matchers()]
plugin_list = []
plugin_data = plugins_manager.get_data()
for model in plugin_data:
if model in plugin_name_list:
data = plugin_data.get(model)
data["model"] = model
plugin_name = data.get("plugin_name")
if (
(type_ == "hidden" and "[hidden]" not in plugin_name.lower())
or (type_ == "admin" and "[admin]" not in plugin_name.lower())
or (type_ == "superuser" and "[superuser]" not in plugin_name.lower())
):
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.get("status") and x.get("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)
if x := plugins2settings_manager.get(model):
if x.get("cmd") and isinstance(x.get("cmd"), list):
x["cmd"] = ",".join(x["cmd"])
if isinstance(x["plugin_type"], list):
x["plugin_type"] = x["plugin_type"][0]
data["plugin_settings"] = PluginSettings(**x)
if x := plugins2cd_manager.get(model):
data["cd_limit"] = CdLimit(**x)
if x := plugins2block_manager.get(model):
data["block_limit"] = BlockLimit(**x)
if x := plugins2count_manager.get(model):
data["count_limit"] = CountLimit(**x)
# if x := resources_manager.get(model):
# data = dict(data, **x)
plugin_list.append(Plugin(**data))
return Result(code=200, data=plugin_list)
@app.post("/webui/plugins")
def _(plugin: Plugin, user: User = Depends(token_to_user)) -> Result:
"""
修改插件信息
:param plugin: 插件内容
"""
print(plugin)
if plugin.plugin_settings:
for key, value in plugin.plugin_settings:
plugins2settings_manager.set_module_data(plugin.model, key, value)
if plugin.plugin_manager:
for key, value in plugin.plugin_manager:
print(key, value)
plugins_manager.set_module_data(plugin.model, key, value)
return Result(code=200)
@app.get("/webui/group")
async def _(user: User = Depends(token_to_user)) -> Result:
"""
获取群信息
"""
group_list_result = []
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"]:
try:
task_list = []
data = group_data["group_manager"][group_id]
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
try:
group_list_result.append(GroupResult(**data))
except ValidationError:
pass
except Exception as e:
logger.error(f"WEB_UI /webui/group 发生错误 {type(e)}:{e}")
return Result(code=200, data=group_list_result)
@app.post("/webui/group")
async def _(group: GroupResult, user: User = Depends(token_to_user)) -> Result:
"""
修改群信息
"""
group_id = group.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)
return Result(code=200)
@app.get("/webui/request")
def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
req_data = requests_manager.get_data()
req_list = []
if type_ in ["group", "private"]:
req_data = req_data[type_]
for x in req_data:
req_data[x]["oid"] = x
req_list.append(RequestResult(**req_data[x]))
return Result(code=200, data=req_list)
@app.delete("/webui/request")
def _(type_: Optional[str], user: User = Depends(token_to_user)) -> Result:
"""
清空请求
:param type_: 类型
"""
requests_manager.clear(type_)
return Result(code=200)
@app.post("/webui/request")
async def _(parma: RequestParma, user: User = Depends(token_to_user)) -> Result:
"""
操作请求
:param parma: 参数
"""
result = "error"
if bot := get_bot():
if parma.handle == "approve":
if parma.type == "group":
rid = requests_manager.get_group_id(parma.id)
if await GroupInfo.get_group_info(rid):
await GroupInfo.set_group_flag(rid, 1)
else:
group_info = await bot.get_group_info(group_id=rid)
await GroupInfo.add_group_info(
rid,
group_info["group_name"],
group_info["max_member_count"],
group_info["member_count"],
1,
)
if await requests_manager.approve(bot, parma.id, parma.type):
result = "ok"
elif parma.handle == "refuse":
if await requests_manager.refused(bot, parma.id, parma.type):
result = "ok"
elif parma.handle == "delete":
requests_manager.delete_request(parma.id, parma.type)
result = "ok"
return Result(code=200, data=result)