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

View File

@ -236,6 +236,16 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
## 更新 ## 更新
### 2022/4/4 \[v0.1.4.5]
* 替换了bt搜索URL
* 优化使用playwright的相关代码
* 原神玩家查询新增层岩巨渊探索
* 修复原神便笺角色头像黑框
* 修复同意群聊请求错误
* 提供webui方面的api
* 新增web-ui前端简易管理页面插件插件
### 2022/3/21 ### 2022/3/21
* 修复statistics_handle.py乱码 * 修复statistics_handle.py乱码
@ -318,15 +328,15 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
* epic restful 替换 [@pull/119](https://github.com/HibiKier/zhenxun_bot/pull/119) * epic restful 替换 [@pull/119](https://github.com/HibiKier/zhenxun_bot/pull/119)
* fix: 修复远古时期残留的epic推送问题 [@pull/122](https://github.com/HibiKier/zhenxun_bot/pull/122) * fix: 修复远古时期残留的epic推送问题 [@pull/122](https://github.com/HibiKier/zhenxun_bot/pull/122)
### 2022/2/11 ### 2021/2/11
* 修复pix不使用反代无法下载图片 * 修复pix不使用反代无法下载图片
### 2022/2/10 \[v0.1.1] ### 2021/2/10 \[v0.1.1]
* 修复购买道具出错 * 修复购买道具出错
### 2022/2/9 \[v0.1] ### 2021/2/9 \[v0.1]
* 新增原神自动签到和手动签到 * 新增原神自动签到和手动签到
* 新增原神树脂提醒 * 新增原神树脂提醒
@ -336,7 +346,7 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
* 修复修改商品时限制时间出错 * 修复修改商品时限制时间出错
* 修复超时商品依旧可以被购买 * 修复超时商品依旧可以被购买
### 2022/1/16 \[v0.0.9.0] ### 2021/1/16 \[v0.0.9.0]
* Ai提供文本敏感词过滤器 * Ai提供文本敏感词过滤器
* 疫情插件适配新版腾讯API * 疫情插件适配新版腾讯API
@ -355,7 +365,7 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
* “send_success_msg”(发送成功的交互信息->即:使用道具 {name} {num} 次成功) * “send_success_msg”(发送成功的交互信息->即:使用道具 {name} {num} 次成功)
* “_max_num_limit”(该道具单次使用的最多个数默认1) * “_max_num_limit”(该道具单次使用的最多个数默认1)
### 2022/1/5 \[v0.0.8.2] ### 2021/1/5 \[v0.0.8.2]
* 提供金币消费hook可在plugins2settings.yaml中配置该功能需要消费的金币 * 提供金币消费hook可在plugins2settings.yaml中配置该功能需要消费的金币
* 商店插件将作为内置插件移动至basic_plugins * 商店插件将作为内置插件移动至basic_plugins

View File

@ -1 +1 @@
__version__: v0.1.4.4 __version__: v0.1.4.5

View File

@ -24,11 +24,17 @@ def switch_rule(event: Event) -> bool:
_data = plugins2settings_manager.get_data() _data = plugins2settings_manager.get_data()
for key in _data: for key in _data:
try: try:
for x in _data[key]["cmd"]: if isinstance(_data[key]["cmd"], list):
cmd.append(f"开启{x}") for x in _data[key]["cmd"]:
cmd.append(f"关闭{x}") cmd.append(f"开启{x}")
cmd.append(f"开启 {x}") cmd.append(f"关闭{x}")
cmd.append(f"关闭 {x}") cmd.append(f"开启 {x}")
cmd.append(f"关闭 {x}")
else:
cmd.append(f"开启{key}")
cmd.append(f"关闭{key}")
cmd.append(f"开启 {key}")
cmd.append(f"关闭 {key}")
except KeyError: except KeyError:
pass pass
msg = get_message_text(event.json()).split() msg = get_message_text(event.json()).split()

View File

@ -74,7 +74,7 @@ def init_plugins_settings(data_path: str):
if plugin_settings.get('cost_gold') is None: if plugin_settings.get('cost_gold') is None:
plugin_settings['cost_gold'] = 0 plugin_settings['cost_gold'] = 0
if ( if (
plugin_settings["cmd"] is not None plugin_settings.get("cmd") is not None
and plugin_name not in plugin_settings["cmd"] and plugin_name not in plugin_settings["cmd"]
): ):
plugin_settings["cmd"].append(plugin_name) plugin_settings["cmd"].append(plugin_name)

View File

@ -57,7 +57,7 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
if random.random() < 0.2: if random.random() < 0.2:
if nickname.find("大人") == -1: if nickname.find("大人") == -1:
nickname += "大~人~" nickname += "大~人~"
rst = rst.replace("小主人", nickname).replace("小朋友", nickname) rst = str(rst).replace("小主人", nickname).replace("小朋友", nickname)
ai_message_manager.add_result(user_id, rst) ai_message_manager.add_result(user_id, rst)
return rst return rst

View File

@ -56,15 +56,15 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
) )
if is_number(msg) and 0 < int(msg) <= 50: if is_number(msg) and 0 < int(msg) <= 50:
url = wbtop_data[int(msg) - 1]["url"] url = wbtop_data[int(msg) - 1]["url"]
try: await wbtop.send("开始截取数据...")
await wbtop.send("开始截取数据...") img = await AsyncPlaywright.screenshot(
img = await AsyncPlaywright.screenshot( url,
url, f"{IMAGE_PATH}/temp/wbtop_{event.user_id}.png",
f"{IMAGE_PATH}/temp/wbtop_{event.user_id}.png", "#pl_feedlist_index",
"#pl_feedlist_index", wait_time=5
sleep=5 )
) if img:
await wbtop.send(img) await wbtop.send(img)
except Exception as e: else:
logger.error(f"微博热搜截图出错... {type(e)}: {e}")
await wbtop.send("发生了一些错误.....") await wbtop.send("发生了一些错误.....")

View File

@ -211,7 +211,7 @@ async def _():
await sub_manager.reload_sub_data() await sub_manager.reload_sub_data()
sub = await sub_manager.random_sub_data() sub = await sub_manager.random_sub_data()
if sub: if sub:
logger.info(f"Bilibili订阅开始检测{sub.sub_id}") logger.debug(f"Bilibili订阅开始检测{sub.sub_id}")
rst = await get_sub_status(sub.sub_id, sub.sub_type) rst = await get_sub_status(sub.sub_id, sub.sub_type)
await send_sub_msg(rst, sub, bot) await send_sub_msg(rst, sub, bot)
if sub.sub_type == "live": if sub.sub_type == "live":

View File

@ -311,28 +311,32 @@ async def get_user_dynamic(
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"] dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
if local_user.dynamic_upload_time < dynamic_upload_time: if local_user.dynamic_upload_time < dynamic_upload_time:
page = await browser.new_page() page = await browser.new_page()
await page.goto( try:
f"https://space.bilibili.com/{local_user.uid}/dynamic", await page.goto(
wait_until="networkidle", f"https://space.bilibili.com/{local_user.uid}/dynamic",
timeout=10000, wait_until="networkidle",
) timeout=10000,
await page.set_viewport_size({"width": 2560, "height": 1080}) )
# 删除置顶 await page.set_viewport_size({"width": 2560, "height": 1080})
await page.evaluate( # 删除置顶
await page.evaluate(
"""
xs = document.getElementsByClassName('first-card-with-title');
for (x of xs) {
x.remove();
}
""" """
xs = document.getElementsByClassName('first-card-with-title'); )
for (x of xs) { card = await page.query_selector(".card")
x.remove(); # 截图并保存
} await card.screenshot(
""" path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
) timeout=100000,
card = await page.query_selector(".card") )
# 截图并保存 except Exception as e:
await card.screenshot( logger.error(f"B站订阅获取用户动态 发送错误 {type(e)}{e}")
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg", finally:
timeout=100000, await page.close()
)
await page.close()
return ( return (
image( image(
f"{local_user.sub_id}_{dynamic_upload_time}.jpg", f"{local_user.sub_id}_{dynamic_upload_time}.jpg",

View File

@ -9,7 +9,7 @@ if platform.system() == "Windows":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
url = "http://www.eclzz.world" url = "http://www.eclzz.mobi"
async def get_bt_info(keyword: str, page: int): async def get_bt_info(keyword: str, page: int):

View File

@ -200,7 +200,7 @@ def _parse_data_and_draw(
file_name = x["avatar_side_icon"].split("_")[-1] file_name = x["avatar_side_icon"].split("_")[-1]
role_avatar = memo_path / "role_avatar" / file_name role_avatar = memo_path / "role_avatar" / file_name
_ava_img = BuildImage(75, 75, background=role_avatar) _ava_img = BuildImage(75, 75, background=role_avatar)
_ava_img.circle() # _ava_img.circle()
if x["status"] == "Finished": if x["status"] == "Finished":
msg = "探索完成" msg = "探索完成"
font_color = (146, 188, 63) font_color = (146, 188, 63)
@ -218,10 +218,10 @@ def _parse_data_and_draw(
a_circle.circle() a_circle.circle()
b_circle = BuildImage(47, 47) b_circle = BuildImage(47, 47)
b_circle.circle() b_circle.circle()
a_circle.paste(b_circle, (4, 4), alpha=True) a_circle.paste(b_circle, (4, 4), True)
_circle_bk.paste(a_circle, (4, 4), alpha=True) _circle_bk.paste(a_circle, (4, 4), True)
_bk.paste(_circle_bk, (25, 0), True, center_type="by_height") _bk.paste(_circle_bk, (25, 0), True, "by_height")
_bk.paste(_ava_img, (19, -13), True) _bk.paste(_ava_img, (19, -13), True)
_bk.text((100, 0), msg, font_color, "by_height") _bk.text((100, 0), msg, font_color, "by_height")
_bk.circle_corner(20) _bk.circle_corner(20)

View File

@ -296,9 +296,11 @@ def get_country_data_image(world_data_dict: Dict) -> BuildImage:
画出国家探索供奉等图像 画出国家探索供奉等图像
:param world_data_dict: 国家数据字典 :param world_data_dict: 国家数据字典
""" """
region = BuildImage(790, 267 * len(world_data_dict), color="#F9F6F2") # 层岩巨渊 和 地下矿区 算一个
region = BuildImage(790, 267 * (len(world_data_dict) - 1), color="#F9F6F2")
height = 0 height = 0
for country in ["蒙德", "龙脊雪山", "璃月", "稻妻", "渊下宫"]:
for country in ["蒙德", "龙脊雪山", "璃月", "璃月层岩巨渊", "稻妻", "渊下宫"]:
x = BuildImage(790, 250, color="#3A4467") x = BuildImage(790, 250, color="#3A4467")
logo = BuildImage(180, 180, background=image_path / "logo" / f"{country}.png") logo = BuildImage(180, 180, background=image_path / "logo" / f"{country}.png")
tmp_bk = BuildImage(770, 230, color="#606779") tmp_bk = BuildImage(770, 230, color="#606779")
@ -320,6 +322,25 @@ def get_country_data_image(world_data_dict: Dict) -> BuildImage:
f"Lv.{world_data_dict[country]['level']}", f"Lv.{world_data_dict[country]['level']}",
fill=(255, 255, 255), fill=(255, 255, 255),
) )
elif country in ["璃月层岩巨渊"]:
content_bk.text((300, 20), "层岩巨渊探索", fill=(239, 211, 114))
content_bk.text(
(570, 20),
f"{world_data_dict['璃月层岩巨渊']['exploration_percentage'] / 10}%",
fill=(255, 255, 255),
)
content_bk.text((300, 85), "地下矿区探索", fill=(239, 211, 114))
content_bk.text(
(570, 85),
f"{world_data_dict['璃月层岩巨渊·地下矿区']['exploration_percentage'] / 10}%",
fill=(255, 255, 255),
)
content_bk.text((300, 150), "流明石触媒", fill=(239, 211, 114))
content_bk.text(
(570, 150),
f"LV.{world_data_dict['璃月层岩巨渊·地下矿区']['offerings'][0]['level']}",
fill=(255, 255, 255),
)
elif country in ["龙脊雪山"]: elif country in ["龙脊雪山"]:
content_bk.text((300, 40), "探索", fill=(239, 211, 114)) content_bk.text((300, 40), "探索", fill=(239, 211, 114))
content_bk.text( content_bk.text(

View File

@ -276,4 +276,4 @@ def update_data(data: dict):
tmp_dict[plugin_name] = 1 tmp_dict[plugin_name] = 1
else: else:
tmp_dict[plugin_name] += data[day][plugin_name] tmp_dict[plugin_name] += data[day][plugin_name]
return tmp_dict return tmp_dict

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_="前端管理密码"
)

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
plugins/web_ui/config.py Normal file
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

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)

174
poetry.lock generated
View File

@ -377,6 +377,26 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple" url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua" reference = "tsinghua"
[[package]]
name = "ecdsa"
version = "0.17.0"
description = "ECDSA cryptographic signature library (pure python)"
category = "main"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[package.dependencies]
six = ">=1.9.0"
[package.extras]
gmpy = ["gmpy"]
gmpy2 = ["gmpy2"]
[package.source]
type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua"
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.73.0" version = "0.73.0"
@ -520,14 +540,14 @@ reference = "tsinghua"
[[package]] [[package]]
name = "httptools" name = "httptools"
version = "0.2.0" version = "0.4.0"
description = "A collection of framework independent HTTP protocol utils." description = "A collection of framework independent HTTP protocol utils."
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = ">=3.5.0"
[package.extras] [package.extras]
test = ["Cython (==0.29.22)"] test = ["Cython (>=0.29.24,<0.30.0)"]
[package.source] [package.source]
type = "legacy" type = "legacy"
@ -915,6 +935,19 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple" url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua" reference = "tsinghua"
[[package]]
name = "pyasn1"
version = "0.4.8"
description = "ASN.1 types and codecs"
category = "main"
optional = false
python-versions = "*"
[package.source]
type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua"
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "1.9.0" version = "1.9.0"
@ -1023,6 +1056,45 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple" url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua" reference = "tsinghua"
[[package]]
name = "python-jose"
version = "3.3.0"
description = "JOSE implementation in Python"
category = "main"
optional = false
python-versions = "*"
[package.dependencies]
ecdsa = "!=0.15"
pyasn1 = "*"
rsa = "*"
[package.extras]
cryptography = ["cryptography (>=3.4.0)"]
pycrypto = ["pycrypto (>=2.6.0,<2.7.0)", "pyasn1"]
pycryptodome = ["pycryptodome (>=3.3.1,<4.0.0)", "pyasn1"]
[package.source]
type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua"
[[package]]
name = "python-multipart"
version = "0.0.5"
description = "A streaming multipart parser for Python"
category = "main"
optional = false
python-versions = "*"
[package.dependencies]
six = ">=1.4.0"
[package.source]
type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua"
[[package]] [[package]]
name = "pytz" name = "pytz"
version = "2021.3" version = "2021.3"
@ -1130,6 +1202,22 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple" url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua" reference = "tsinghua"
[[package]]
name = "rsa"
version = "4.8"
description = "Pure-Python RSA implementation"
category = "main"
optional = false
python-versions = ">=3.6,<4"
[package.dependencies]
pyasn1 = ">=0.1.3"
[package.source]
type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
reference = "tsinghua"
[[package]] [[package]]
name = "ruamel.yaml" name = "ruamel.yaml"
version = "0.17.21" version = "0.17.21"
@ -1403,7 +1491,7 @@ reference = "tsinghua"
[[package]] [[package]]
name = "uvicorn" name = "uvicorn"
version = "0.17.5" version = "0.17.6"
description = "The lightning-fast ASGI server." description = "The lightning-fast ASGI server."
category = "main" category = "main"
optional = false optional = false
@ -1414,7 +1502,7 @@ asgiref = ">=3.4.0"
click = ">=7.0" click = ">=7.0"
colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""}
h11 = ">=0.8" h11 = ">=0.8"
httptools = {version = ">=0.2.0,<0.4.0", optional = true, markers = "extra == \"standard\""} httptools = {version = ">=0.4.0", optional = true, markers = "extra == \"standard\""}
python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""}
PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
@ -1422,7 +1510,7 @@ watchgod = {version = ">=0.6", optional = true, markers = "extra == \"standard\"
websockets = {version = ">=10.0", optional = true, markers = "extra == \"standard\""} websockets = {version = ">=10.0", optional = true, markers = "extra == \"standard\""}
[package.extras] [package.extras]
standard = ["websockets (>=10.0)", "httptools (>=0.2.0,<0.4.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] standard = ["websockets (>=10.0)", "httptools (>=0.4.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"]
[package.source] [package.source]
type = "legacy" type = "legacy"
@ -1522,7 +1610,7 @@ reference = "tsinghua"
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "2521c3cd7346f1f1b3b22276fa71ca9680447f85fc13fd23ede0e33d6f942423" content-hash = "a467c2f5d871d65cd76363a2839023a38bde9b4aacd37f3019dca6fe0f199723"
[metadata.files] [metadata.files]
aiofiles = [ aiofiles = [
@ -1764,6 +1852,10 @@ dateparser = [
{file = "dateparser-1.1.0-py2.py3-none-any.whl", hash = "sha256:fec344db1f73d005182e214c0ff27313c748bbe0c1638ce9d48a809ddfdab2a0"}, {file = "dateparser-1.1.0-py2.py3-none-any.whl", hash = "sha256:fec344db1f73d005182e214c0ff27313c748bbe0c1638ce9d48a809ddfdab2a0"},
{file = "dateparser-1.1.0.tar.gz", hash = "sha256:faa2b97f51f3b5ff1ba2f17be90de2b733fb6191f89b4058787473e8202f3044"}, {file = "dateparser-1.1.0.tar.gz", hash = "sha256:faa2b97f51f3b5ff1ba2f17be90de2b733fb6191f89b4058787473e8202f3044"},
] ]
ecdsa = [
{file = "ecdsa-0.17.0-py2.py3-none-any.whl", hash = "sha256:5cf31d5b33743abe0dfc28999036c849a69d548f994b535e527ee3cb7f3ef676"},
{file = "ecdsa-0.17.0.tar.gz", hash = "sha256:b9f500bb439e4153d0330610f5d26baaf18d17b8ced1bc54410d189385ea68aa"},
]
fastapi = [ fastapi = [
{file = "fastapi-0.73.0-py3-none-any.whl", hash = "sha256:f0a618aff5f6942862f2d3f20f39b1c037e33314d1b8207fd1c3a2cca76dfd8c"}, {file = "fastapi-0.73.0-py3-none-any.whl", hash = "sha256:f0a618aff5f6942862f2d3f20f39b1c037e33314d1b8207fd1c3a2cca76dfd8c"},
{file = "fastapi-0.73.0.tar.gz", hash = "sha256:dcfee92a7f9a72b5d4b7ca364bd2b009f8fc10d95ed5769be20e94f39f7e5a15"}, {file = "fastapi-0.73.0.tar.gz", hash = "sha256:dcfee92a7f9a72b5d4b7ca364bd2b009f8fc10d95ed5769be20e94f39f7e5a15"},
@ -1846,21 +1938,40 @@ httpcore = [
{file = "httpcore-0.14.7.tar.gz", hash = "sha256:7503ec1c0f559066e7e39bc4003fd2ce023d01cf51793e3c173b864eb456ead1"}, {file = "httpcore-0.14.7.tar.gz", hash = "sha256:7503ec1c0f559066e7e39bc4003fd2ce023d01cf51793e3c173b864eb456ead1"},
] ]
httptools = [ httptools = [
{file = "httptools-0.2.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5"}, {file = "httptools-0.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcddfe70553be717d9745990dfdb194e22ee0f60eb8f48c0794e7bfeda30d2d5"},
{file = "httptools-0.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:78d03dd39b09c99ec917d50189e6743adbfd18c15d5944392d2eabda688bf149"}, {file = "httptools-0.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1ee0b459257e222b878a6c09ccf233957d3a4dcb883b0847640af98d2d9aac23"},
{file = "httptools-0.2.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a23166e5ae2775709cf4f7ad4c2048755ebfb272767d244e1a96d55ac775cca7"}, {file = "httptools-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceafd5e960b39c7e0d160a1936b68eb87c5e79b3979d66e774f0c77d4d8faaed"},
{file = "httptools-0.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3ab1f390d8867f74b3b5ee2a7ecc9b8d7f53750bd45714bf1cb72a953d7dfa77"}, {file = "httptools-0.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fdb9f9ed79bc6f46b021b3319184699ba1a22410a82204e6e89c774530069683"},
{file = "httptools-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a7594f9a010cdf1e16a58b3bf26c9da39bbf663e3b8d46d39176999d71816658"}, {file = "httptools-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:abe829275cdd4174b4c4e65ad718715d449e308d59793bf3a931ee1bf7e7b86c"},
{file = "httptools-0.2.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:01b392a166adcc8bc2f526a939a8aabf89fe079243e1543fd0e7dc1b58d737cb"}, {file = "httptools-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7af6bdbd21a2a25d6784f6d67f44f5df33ef39b6159543b9f9064d365c01f919"},
{file = "httptools-0.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:80ffa04fe8c8dfacf6e4cef8277347d35b0442c581f5814f3b0cf41b65c43c6e"}, {file = "httptools-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d1fe6b6661022fd6cac541f54a4237496b246e6f1c0a6b41998ee08a1135afe"},
{file = "httptools-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d5682eeb10cca0606c4a8286a3391d4c3c5a36f0c448e71b8bd05be4e1694bfb"}, {file = "httptools-0.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:48e48530d9b995a84d1d89ae6b3ec4e59ea7d494b150ac3bbc5e2ac4acce92cd"},
{file = "httptools-0.2.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a289c27ccae399a70eacf32df9a44059ca2ba4ac444604b00a19a6c1f0809943"}, {file = "httptools-0.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a113789e53ac1fa26edf99856a61e4c493868e125ae0dd6354cf518948fbbd5c"},
{file = "httptools-0.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:813871f961edea6cb2fe312f2d9b27d12a51ba92545380126f80d0de1917ea15"}, {file = "httptools-0.4.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e2eb957787cbb614a0f006bfc5798ff1d90ac7c4dd24854c84edbdc8c02369e"},
{file = "httptools-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:cc9be041e428c10f8b6ab358c6b393648f9457094e1dcc11b4906026d43cd380"}, {file = "httptools-0.4.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:7ee9f226acab9085037582c059d66769862706e8e8cd2340470ceb8b3850873d"},
{file = "httptools-0.2.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b08d00d889a118f68f37f3c43e359aab24ee29eb2e3fe96d64c6a2ba8b9d6557"}, {file = "httptools-0.4.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:701e66b59dd21a32a274771238025d58db7e2b6ecebbab64ceff51b8e31527ae"},
{file = "httptools-0.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fd3b8905e21431ad306eeaf56644a68fdd621bf8f3097eff54d0f6bdf7262065"}, {file = "httptools-0.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6a1a7dfc1f9c78a833e2c4904757a0f47ce25d08634dd2a52af394eefe5f9777"},
{file = "httptools-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:200fc1cdf733a9ff554c0bb97a4047785cfaad9875307d6087001db3eb2b417f"}, {file = "httptools-0.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:903f739c9fb78dab8970b0f3ea51f21955b24b45afa77b22ff0e172fc11ef111"},
{file = "httptools-0.2.0.tar.gz", hash = "sha256:94505026be56652d7a530ab03d89474dc6021019d6b8682281977163b3471ea0"}, {file = "httptools-0.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54bbd295f031b866b9799dd39cb45deee81aca036c9bff9f58ca06726f6494f1"},
{file = "httptools-0.4.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3194f6d6443befa8d4db16c1946b2fc428a3ceb8ab32eb6f09a59f86104dc1a0"},
{file = "httptools-0.4.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cd1295f52971097f757edfbfce827b6dbbfb0f7a74901ee7d4933dff5ad4c9af"},
{file = "httptools-0.4.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:20a45bcf22452a10fa8d58b7dbdb474381f6946bf5b8933e3662d572bc61bae4"},
{file = "httptools-0.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d1f27bb0f75bef722d6e22dc609612bfa2f994541621cd2163f8c943b6463dfe"},
{file = "httptools-0.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7f7bfb74718f52d5ed47d608d507bf66d3bc01d4a8b3e6dd7134daaae129357b"},
{file = "httptools-0.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a522d12e2ddbc2e91842ffb454a1aeb0d47607972c7d8fc88bd0838d97fb8a2a"},
{file = "httptools-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2db44a0b294d317199e9f80123e72c6b005c55b625b57fae36de68670090fa48"},
{file = "httptools-0.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c286985b5e194ca0ebb2908d71464b9be8f17cc66d6d3e330e8d5407248f56ad"},
{file = "httptools-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3a4e165ca6204f34856b765d515d558dc84f1352033b8721e8d06c3e44930c3"},
{file = "httptools-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:72aa3fbe636b16d22e04b5a9d24711b043495e0ecfe58080addf23a1a37f3409"},
{file = "httptools-0.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9967d9758df505975913304c434cb9ab21e2c609ad859eb921f2f615a038c8de"},
{file = "httptools-0.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f72b5d24d6730035128b238decdc4c0f2104b7056a7ca55cf047c106842ec890"},
{file = "httptools-0.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:29bf97a5c532da9c7a04de2c7a9c31d1d54f3abd65a464119b680206bbbb1055"},
{file = "httptools-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98993805f1e3cdb53de4eed02b55dcc953cdf017ba7bbb2fd89226c086a6d855"},
{file = "httptools-0.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d9b90bf58f3ba04e60321a23a8723a1ff2a9377502535e70495e5ada8e6e6722"},
{file = "httptools-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a99346ebcb801b213c591540837340bdf6fd060a8687518d01c607d338b7424"},
{file = "httptools-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:645373c070080e632480a3d251d892cb795be3d3a15f86975d0f1aca56fd230d"},
{file = "httptools-0.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:34d2903dd2a3dd85d33705b6fde40bf91fc44411661283763fd0746723963c83"},
{file = "httptools-0.4.0.tar.gz", hash = "sha256:2c9a930c378b3d15d6b695fb95ebcff81a7395b4f9775c4f10a076beb0b2c1ff"},
] ]
httpx = [ httpx = [
{file = "httpx-0.22.0-py3-none-any.whl", hash = "sha256:e35e83d1d2b9b2a609ef367cc4c1e66fd80b750348b20cc9e19d1952fc2ca3f6"}, {file = "httpx-0.22.0-py3-none-any.whl", hash = "sha256:e35e83d1d2b9b2a609ef367cc4c1e66fd80b750348b20cc9e19d1952fc2ca3f6"},
@ -2228,6 +2339,10 @@ psutil = [
{file = "psutil-5.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:7d190ee2eaef7831163f254dc58f6d2e2a22e27382b936aab51c835fc080c3d3"}, {file = "psutil-5.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:7d190ee2eaef7831163f254dc58f6d2e2a22e27382b936aab51c835fc080c3d3"},
{file = "psutil-5.9.0.tar.gz", hash = "sha256:869842dbd66bb80c3217158e629d6fceaecc3a3166d3d1faee515b05dd26ca25"}, {file = "psutil-5.9.0.tar.gz", hash = "sha256:869842dbd66bb80c3217158e629d6fceaecc3a3166d3d1faee515b05dd26ca25"},
] ]
pyasn1 = [
{file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"},
{file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"},
]
pydantic = [ pydantic = [
{file = "pydantic-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb23bcc093697cdea2708baae4f9ba0e972960a835af22560f6ae4e7e47d33f5"}, {file = "pydantic-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb23bcc093697cdea2708baae4f9ba0e972960a835af22560f6ae4e7e47d33f5"},
{file = "pydantic-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1d5278bd9f0eee04a44c712982343103bba63507480bfd2fc2790fa70cd64cf4"}, {file = "pydantic-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1d5278bd9f0eee04a44c712982343103bba63507480bfd2fc2790fa70cd64cf4"},
@ -2288,6 +2403,13 @@ python-dotenv = [
{file = "python-dotenv-0.19.2.tar.gz", hash = "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"}, {file = "python-dotenv-0.19.2.tar.gz", hash = "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"},
{file = "python_dotenv-0.19.2-py2.py3-none-any.whl", hash = "sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3"}, {file = "python_dotenv-0.19.2-py2.py3-none-any.whl", hash = "sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3"},
] ]
python-jose = [
{file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"},
{file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"},
]
python-multipart = [
{file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"},
]
pytz = [ pytz = [
{file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"}, {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"},
{file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"}, {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"},
@ -2450,6 +2572,10 @@ rfc3986 = [
{file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"},
{file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"},
] ]
rsa = [
{file = "rsa-4.8-py3-none-any.whl", hash = "sha256:95c5d300c4e879ee69708c428ba566c59478fd653cc3a22243eeb8ed846950bb"},
{file = "rsa-4.8.tar.gz", hash = "sha256:5c6bd9dc7a543b7fe4304a631f8a8a3b674e2bbfc49c2ae96200cdbe55df6b17"},
]
"ruamel.yaml" = [ "ruamel.yaml" = [
{file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
{file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"},
@ -2638,8 +2764,8 @@ urllib3 = [
{file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"},
] ]
uvicorn = [ uvicorn = [
{file = "uvicorn-0.17.5-py3-none-any.whl", hash = "sha256:8adddf629b79857b48b999ae1b14d6c92c95d4d7840bd86461f09bee75f1653e"}, {file = "uvicorn-0.17.6-py3-none-any.whl", hash = "sha256:19e2a0e96c9ac5581c01eb1a79a7d2f72bb479691acd2b8921fce48ed5b961a6"},
{file = "uvicorn-0.17.5.tar.gz", hash = "sha256:c04a9c069111489c324f427501b3840d306c6b91a77b00affc136a840a3f45f1"}, {file = "uvicorn-0.17.6.tar.gz", hash = "sha256:5180f9d059611747d841a4a4c4ab675edf54c8489e97f96d0583ee90ac3bfc23"},
] ]
uvloop = [ uvloop = [
{file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"}, {file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"},

View File

@ -38,6 +38,8 @@ black = "^22.1.0"
pypinyin = "^0.46.0" pypinyin = "^0.46.0"
dateparser = "^1.1.0" dateparser = "^1.1.0"
cn2an = "^0.5.16" cn2an = "^0.5.16"
python-jose = "^3.3.0"
python-multipart = "^0.0.5"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]

View File

@ -8,7 +8,8 @@
"configs/path_config.py", "configs/path_config.py",
"configs/utils", "configs/utils",
"poetry.lock", "poetry.lock",
"pyproject.toml" "pyproject.toml",
"resources/font"
], ],
"add_file": [], "add_file": [],
"delete_file": [] "delete_file": []

View File

@ -295,7 +295,7 @@ class AsyncPlaywright:
path: Union[Path, str], path: Union[Path, str],
element: Union[str, List[str]], element: Union[str, List[str]],
*, *,
sleep: Optional[int] = None, wait_time: Optional[int] = None,
viewport_size: Dict[str, int] = None, viewport_size: Dict[str, int] = None,
wait_until: Optional[ wait_until: Optional[
Literal["domcontentloaded", "load", "networkidle"] Literal["domcontentloaded", "load", "networkidle"]
@ -311,7 +311,7 @@ class AsyncPlaywright:
:param url: 网址 :param url: 网址
:param path: 存储路径 :param path: 存储路径
:param element: 元素选择 :param element: 元素选择
:param sleep: 延迟截取 :param wait_time: 等待截取超时时间
:param viewport_size: 窗口大小 :param viewport_size: 窗口大小
:param wait_until: 等待类型 :param wait_until: 等待类型
:param timeout: 超时限制 :param timeout: 超时限制
@ -325,14 +325,18 @@ class AsyncPlaywright:
try: try:
page = await cls.goto(url, wait_until=wait_until, **kwargs) page = await cls.goto(url, wait_until=wait_until, **kwargs)
await page.set_viewport_size(viewport_size) await page.set_viewport_size(viewport_size)
if sleep:
await asyncio.sleep(sleep)
if isinstance(element, str): if isinstance(element, str):
card = await page.query_selector(element) if wait_time:
card = await page.wait_for_selector(element, timeout=wait_time)
else:
card = await page.query_selector(element)
else: else:
card = page card = page
for e in element: for e in element:
card = await card.query_selector(e) if wait_time:
card = await card.wait_for_selector(e, timeout=wait_time)
else:
card = await card.query_selector(e)
await card.screenshot(path=path, timeout=timeout, type=type_) await card.screenshot(path=path, timeout=timeout, type=type_)
return image(path) return image(path)
except Exception as e: except Exception as e:

View File

@ -2,6 +2,7 @@ from typing import Union, Optional
from pathlib import Path from pathlib import Path
from ruamel.yaml import YAML from ruamel.yaml import YAML
import ujson as json import ujson as json
import copy
yaml = YAML(typ="safe") yaml = YAML(typ="safe")
@ -47,7 +48,7 @@ class StaticData:
del self._data[key] del self._data[key]
def get_data(self) -> dict: def get_data(self) -> dict:
return self._data return copy.deepcopy(self._data)
def save(self, path: Union[str, Path] = None): def save(self, path: Union[str, Path] = None):
path = path if path else self.file path = path if path else self.file

View File

@ -2,7 +2,7 @@ from utils.manager.data_class import StaticData
from nonebot.adapters.onebot.v11 import Bot from nonebot.adapters.onebot.v11 import Bot
from nonebot.adapters.onebot.v11.exception import ActionFailed from nonebot.adapters.onebot.v11.exception import ActionFailed
from services.log import logger from services.log import logger
from typing import Optional from typing import Optional, Literal
from utils.image_utils import BuildImage from utils.image_utils import BuildImage
from utils.utils import get_user_avatar from utils.utils import get_user_avatar
from pathlib import Path from pathlib import Path
@ -80,7 +80,10 @@ class RequestManager(StaticData):
通过id获取群号 通过id获取群号
:param id_: id :param id_: id
""" """
return self._data["group"].get(id_) data = self._data["group"].get(str(id_))
if data:
return data["invite_group"]
return None
async def approve(self, bot: Bot, id_: int, type_: str) -> Optional[int]: async def approve(self, bot: Bot, id_: int, type_: str) -> Optional[int]:
""" """
@ -100,13 +103,28 @@ class RequestManager(StaticData):
""" """
return await self._set_add_request(bot, id_, type_, False) return await self._set_add_request(bot, id_, type_, False)
def clear(self): def clear(self, type_: Optional[str] = None): # type_: Optional[Literal["group", "private"]] = None
""" """
清空所有请求信息无视请求 清空所有请求信息无视请求
:param type_: 类型
""" """
self._data = {"private": {}, "group": {}} if type_:
self._data[type_] = {}
else:
self._data = {"private": {}, "group": {}}
self.save() self.save()
def delete_request(self, id_: int, type_: str): # type_: Literal["group", "private"]
"""
删除请求
:param id_: id
:param type_: 类型
"""
id_ = str(id_)
if self._data[type_].get(id_):
del self._data[type_][id_]
self.save()
def set_group_name(self, group_name: str, group_id: int): def set_group_name(self, group_name: str, group_id: int):
""" """
设置群聊名称 设置群聊名称
@ -223,7 +241,7 @@ class RequestManager(StaticData):
:param approve: 是否同意 :param approve: 是否同意
""" """
id_ = str(id_) id_ = str(id_)
if id_ in self._data[type_]: if id_ in self._data[type_].keys():
try: try:
if type_ == "private": if type_ == "private":
await bot.set_friend_add_request( await bot.set_friend_add_request(
@ -244,7 +262,7 @@ class RequestManager(StaticData):
) )
return None return None
logger.info( logger.info(
f"同意{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})" f"{'同意' if approve else '拒绝'}{self._data[type_][id_]['nickname']}({self._data[type_][id_]['id']})"
f"{'好友' if type_ == 'private' else '入群'}请求..." f"{'好友' if type_ == 'private' else '入群'}请求..."
) )
del self._data[type_][id_] del self._data[type_][id_]