Compare commits

...
15 Commits
Author SHA1 Message Date
HibiKier 0f59895c3b update v0.1.4.5 2022-04-04 20:33:37 +08:00
HibiKier b5ce4fab31 Merge pull request #135 from Sakuracio/main
fix GB18030 to UTF-8.
2022-03-28 00:04:32 +08:00
MangataAkihi 062e4c2062 fix GB18030 to UTF-8. 2022-03-26 23:43:21 +08:00
MangataAkihi 0adb66a8bf fix GB18030 to UTF-8. 2022-03-26 23:43:06 +08:00
HibiKier 2aad517112 fix statistics_handle 2022-03-21 18:43:06 +08:00
HibiKier 14d1512b1e update v0.1.4.4 2022-03-18 20:55:05 +08:00
HibiKier 3f533516af Update README.md 2022-03-07 20:46:48 +08:00
HibiKier f1354308fd Update set_admin_permissions.py 2022-03-07 20:46:13 +08:00
HibiKier c06248e46b Update README.md 2022-03-06 18:00:58 +08:00
HibiKier 9c8eaed938 Update pid_search.py 2022-03-06 18:00:35 +08:00
HibiKier 2081302e32 Update README.md 2022-03-06 17:04:34 +08:00
HibiKier 678fc19f2d Update __init__.py 2022-03-06 17:02:59 +08:00
HibiKier adc2757e8e Merge pull request #128 from Sakuracio/main
去除背景图上的(白点?
2022-03-03 21:18:43 +08:00
Sakuracio 82a1261371 去除背景图上的(白点? 2022-03-03 00:38:54 +08:00
HibiKier 067da9dc57 update 0.1.4.3 2022-03-03 00:18:59 +08:00
36 changed files with 1256 additions and 425 deletions
-1
View File
@@ -142,7 +142,6 @@ test.py
server_ip.py
member_activity_handle.py
Yu-Gi-Oh/
search_image/
black_word/
csgo/
fantasy_card/
+32 -1
View File
@@ -236,6 +236,38 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
## 更新
### 2022/4/4 \[v0.1.4.5]
* 替换了bt搜索URL
* 优化使用playwright的相关代码
* 原神玩家查询新增层岩巨渊探索
* 修复原神便笺角色头像黑框
* 修复同意群聊请求错误
* 提供webui方面的api
* 新增web-ui(前端简易管理页面插件)插件
### 2022/3/21
* 修复statistics_handle.py乱码
### 2022/3/18 \[v0.1.4.4]
* 修复戳一戳无法功能关闭与ban禁用
* 新增图片搜索 search_image
### 2022/3/7
* 优化增删权限插件
### 2022/3/6
* 修复树脂提醒无法开启
* 修复p搜图片路径错误
### 2022/3/3 \[v0.1.4.3]
* 修复手动同意群聊请求依旧退出
### 2022/3/1 \[v0.1.4.2]
* 0.1.4内容
@@ -288,7 +320,6 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
* 适配nonebot.beta2
* 删除图片搜索 nonebot_plugin_picsearcher
* 新增图片搜索 search_image
* 替换cos api
* 原神签到树脂提醒新增绑定群里,在某群绑定uid就会在某群发送提醒信息(有好友则私聊,需要重新绑定uid
* 修改update_info.json
+1 -1
View File
@@ -1 +1 @@
__version__: v0.1.4.2
__version__: v0.1.4.5
+11 -5
View File
@@ -24,11 +24,17 @@ def switch_rule(event: Event) -> bool:
_data = plugins2settings_manager.get_data()
for key in _data:
try:
for x in _data[key]["cmd"]:
cmd.append(f"开启{x}")
cmd.append(f"关闭{x}")
cmd.append(f"开启 {x}")
cmd.append(f"关闭 {x}")
if isinstance(_data[key]["cmd"], list):
for x in _data[key]["cmd"]:
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:
pass
msg = get_message_text(event.json()).split()
+4
View File
@@ -2,6 +2,10 @@ from nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent
from utils.manager import plugins2block_manager, StaticData
import time
ignore_rst_module = ["ai", "poke", "dialogue"]
other_limit_plugins = ["poke"]
class StatusMessageManager(StaticData):
+10 -9
View File
@@ -13,7 +13,12 @@ from utils.manager import (
plugins2block_manager,
plugins2count_manager,
)
from ._utils import set_block_limit_false, status_message_manager
from ._utils import (
set_block_limit_false,
status_message_manager,
ignore_rst_module,
other_limit_plugins,
)
from nonebot.typing import T_State
from typing import Optional
from nonebot.adapters.onebot.v11 import (
@@ -37,12 +42,10 @@ _flmt_g = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
_flmt_s = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
_flmt_c = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
ignore_rst_module = ["ai", "poke", "dialogue"]
# 权限检测
@run_preprocessor
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
module = matcher.plugin_name
plugins2info_dict = plugins2settings_manager.get_data()
# 功能的金币检测 #######################################
@@ -64,7 +67,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
await BagUser.spend_gold(event.user_id, event.group_id, cost_gold)
try:
if (
(not isinstance(event, MessageEvent) and module != "poke")
(not isinstance(event, MessageEvent) and module not in other_limit_plugins)
or await BanUser.is_ban(event.user_id)
and str(event.user_id) not in bot.config.superusers
) or (
@@ -88,7 +91,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
except AttributeError:
pass
# 群黑名单检测 群总开关检测
if isinstance(event, GroupMessageEvent) or matcher.plugin_name == "poke":
if isinstance(event, GroupMessageEvent) or matcher.plugin_name == other_limit_plugins:
try:
if (
group_manager.get_group_level(event.group_id) < 0
@@ -145,9 +148,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
raise IgnoredException("权限不足")
if module in plugins2info_dict.keys() and matcher.priority not in [1, 9]:
# 戳一戳单独判断
if isinstance(event, GroupMessageEvent) or (
isinstance(event, PokeNotifyEvent) and event.group_id
):
if isinstance(event, GroupMessageEvent) or isinstance(event, PokeNotifyEvent) or matcher.plugin_name in other_limit_plugins:
if status_message_manager.get(event.group_id) is None:
status_message_manager.delete(event.group_id)
if plugins2info_dict[module]["level"] > group_manager.get_group_level(
+22 -14
View File
@@ -4,13 +4,16 @@ from nonebot.adapters.onebot.v11.exception import ActionFailed
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import (
Bot,
Event,
MessageEvent,
PokeNotifyEvent,
GroupMessageEvent,
)
from configs.config import Config
from models.ban_user import BanUser
from utils.utils import is_number, static_flmt, FreqLimiter
from utils.message_builder import at
from ._utils import ignore_rst_module, other_limit_plugins
Config.add_plugin_config(
@@ -25,18 +28,19 @@ _flmt = FreqLimiter(300)
# 检查是否被ban
@run_preprocessor
async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
try:
if (
await BanUser.is_super_ban(event.user_id)
and str(event.user_id) not in bot.config.superusers
):
raise IgnoredException("用户处于超级黑名单中")
except AttributeError:
pass
if not isinstance(event, MessageEvent):
return
if matcher.type == "message" and matcher.priority not in [1, 9]:
async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
if (
(isinstance(event, MessageEvent) or isinstance(event, PokeNotifyEvent))
and matcher.priority not in [1, 9]
) or matcher.plugin_name in other_limit_plugins:
try:
if (
await BanUser.is_super_ban(event.user_id)
and str(event.user_id) not in bot.config.superusers
):
raise IgnoredException("用户处于超级黑名单中")
except AttributeError:
pass
if (
await BanUser.is_ban(event.user_id)
and str(event.user_id) not in bot.config.superusers
@@ -57,7 +61,11 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if matcher.priority != 9:
try:
ban_result = Config.get_config("hook", "BAN_RESULT")
if ban_result and _flmt.check(event.user_id):
if (
ban_result
and _flmt.check(event.user_id)
and matcher.plugin_name not in ignore_rst_module
):
_flmt.start_cd(event.user_id)
await bot.send_group_msg(
group_id=event.group_id,
@@ -74,7 +82,7 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
if matcher.priority != 9:
try:
ban_result = Config.get_config("hook", "BAN_RESULT")
if ban_result:
if ban_result and matcher.plugin_name not in ignore_rst_module:
await bot.send_private_msg(
user_id=event.user_id,
message=at(event.user_id)
+12 -2
View File
@@ -14,10 +14,20 @@ async def handle_api_call(bot: Bot, api: str, data: Dict[str, Any]):
or api == "send_group_msg"
)
and (
(r := re.search("^\[\[_task\|(.*)]]", str(data["message"]["text"]).strip()))
(
r := re.search(
"^\[\[_task\|(.*)]]",
data["message"].strip()
if isinstance(data["message"], str)
else str(data["message"]["text"]).strip(),
)
)
or (
r := re.search(
"^&#91;&#91;_task\|(.*)&#93;&#93;", str(data["message"]["text"]).strip()
"^&#91;&#91;_task\|(.*)&#93;&#93;",
data["message"].strip()
if isinstance(data["message"], str)
else str(data["message"]["text"]).strip(),
)
)
)
@@ -74,7 +74,7 @@ def init_plugins_settings(data_path: str):
if plugin_settings.get('cost_gold') is None:
plugin_settings['cost_gold'] = 0
if (
plugin_settings["cmd"] is not None
plugin_settings.get("cmd") is not None
and plugin_name not in plugin_settings["cmd"]
):
plugin_settings["cmd"].append(plugin_name)
+2 -1
View File
@@ -102,7 +102,7 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
if is_number(id_):
id_ = int(id_)
if cmd[:2] == "同意":
rid = await requests_manager.approve(bot, id_, "group")
rid = requests_manager.get_group_id(id_)
if rid:
await friend_handle.send("同意群聊请求成功..")
if await GroupInfo.get_group_info(rid):
@@ -116,6 +116,7 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
group_info["member_count"],
1
)
await requests_manager.approve(bot, id_, "group")
else:
await friend_handle.send("同意群聊请求失败,可能是未找到此id的请求..")
else:
@@ -1,7 +1,7 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from models.level_user import LevelUser
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
from utils.utils import get_message_at, is_number
from services.log import logger
from utils.message_builder import at
@@ -37,41 +37,49 @@ super_cmd = on_command(
@super_cmd.handle()
async def _(bot: Bot, event: GroupMessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
cmd = cmd[0]
group_id = -1
level = 0
async def _(
bot: Bot,
event: MessageEvent,
cmd: Tuple[str, ...] = Command(),
arg: Message = CommandArg(),
):
group_id = event.group_id if isinstance(event, GroupMessageEvent) else -1
level = None
args = arg.extract_plain_text().strip().split()
qq = get_message_at(event.json())
flag = 2
try:
args = arg.extract_plain_text().strip().split()
qq = get_message_at(event.json())
flag = -1
if not qq:
if len(args) > 2:
if is_number(args[0]) and is_number(args[1]) and is_number(args[2]):
if qq:
qq = qq[0]
if cmd[0][:2] == "添加" and args and is_number(args[0]):
level = int(args[0])
else:
if cmd[0][:2] == "添加":
if (
len(args) > 2
and is_number(args[0])
and is_number(args[1])
and is_number(args[2])
):
qq = int(args[0])
group_id = int(args[1])
level = int(args[2])
flag = 1
else:
await super_cmd.finish("所有参数必须是数字!", at_sender=True)
else:
await super_cmd.finish(
"权限参数不完全\n\t格式:添加/删除权限 [at] [level]"
"\n\t格式:添加/删除权限 [qq] [group_id] [level]",
at_sender=True,
)
else:
if not is_number(args[0]):
await super_cmd.finish("所有参数必须是数字!", at_sender=True)
level = int(args[0])
qq = qq[0]
group_id = event.group_id
flag = 2
if cmd[:2] == "添加":
if len(args) > 1 and is_number(args[0]) and is_number(args[1]):
qq = int(args[0])
group_id = int(args[1])
flag = 1
level = -1 if cmd[0][:2] == "删除" else level
if group_id == -1 or not level or not qq:
raise IndexError()
except IndexError:
await super_cmd.finish(__plugin_usage__)
try:
if cmd[0][:2] == "添加":
if await LevelUser.set_level(qq, group_id, level, 1):
result = "添加管理成功, 权限: " + str(level)
result = f"添加管理成功, 权限: {level}"
else:
result = "管理已存在, 更新权限: " + str(level)
result = f"管理已存在, 更新权限: {level}"
else:
if await LevelUser.delete_level(qq, event.group_id):
result = "删除管理成功!"
@@ -82,7 +90,10 @@ async def _(bot: Bot, event: GroupMessageEvent, cmd: Tuple[str, ...] = Command()
elif flag == 1:
await bot.send_group_msg(
group_id=group_id,
message=Message(f"{at(qq)}管理员修改了你的权限" f"\n--------\n你当前的权限等级:{level}"),
message=Message(
f"{at(qq)}管理员修改了你的权限"
f"\n--------\n你当前的权限等级:{level if level != -1 else 0}"
),
)
await super_cmd.send("修改成功")
except Exception as e:
+1 -1
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 nickname.find("大人") == -1:
nickname += "大~人~"
rst = rst.replace("小主人", nickname).replace("小朋友", nickname)
rst = str(rst).replace("小主人", nickname).replace("小朋友", nickname)
ai_message_manager.add_result(user_id, rst)
return rst
+10 -10
View File
@@ -56,15 +56,15 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
)
if is_number(msg) and 0 < int(msg) <= 50:
url = wbtop_data[int(msg) - 1]["url"]
try:
await wbtop.send("开始截取数据...")
img = await AsyncPlaywright.screenshot(
url,
f"{IMAGE_PATH}/temp/wbtop_{event.user_id}.png",
"#pl_feedlist_index",
sleep=5
)
await wbtop.send("开始截取数据...")
img = await AsyncPlaywright.screenshot(
url,
f"{IMAGE_PATH}/temp/wbtop_{event.user_id}.png",
"#pl_feedlist_index",
wait_time=5
)
if img:
await wbtop.send(img)
except Exception as e:
logger.error(f"微博热搜截图出错... {type(e)}: {e}")
else:
await wbtop.send("发生了一些错误.....")
+1 -1
View File
@@ -211,7 +211,7 @@ async def _():
await sub_manager.reload_sub_data()
sub = await sub_manager.random_sub_data()
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)
await send_sub_msg(rst, sub, bot)
if sub.sub_type == "live":
+25 -21
View File
@@ -311,28 +311,32 @@ async def get_user_dynamic(
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
if local_user.dynamic_upload_time < dynamic_upload_time:
page = await browser.new_page()
await page.goto(
f"https://space.bilibili.com/{local_user.uid}/dynamic",
wait_until="networkidle",
timeout=10000,
)
await page.set_viewport_size({"width": 2560, "height": 1080})
# 删除置顶
await page.evaluate(
try:
await page.goto(
f"https://space.bilibili.com/{local_user.uid}/dynamic",
wait_until="networkidle",
timeout=10000,
)
await page.set_viewport_size({"width": 2560, "height": 1080})
# 删除置顶
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) {
x.remove();
}
"""
)
card = await page.query_selector(".card")
# 截图并保存
await card.screenshot(
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
timeout=100000,
)
await page.close()
)
card = await page.query_selector(".card")
# 截图并保存
await card.screenshot(
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
timeout=100000,
)
except Exception as e:
logger.error(f"B站订阅:获取用户动态 发送错误 {type(e)}:{e}")
finally:
await page.close()
return (
image(
f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
+1 -1
View File
@@ -9,7 +9,7 @@ if platform.system() == "Windows":
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):
+1 -1
View File
@@ -132,4 +132,4 @@ async def get_fudu_img_hash(url, group_id):
logger.warning(f"复读下载图片失败...")
except Exception as e:
logger.warning(f"复读读取图片Hash出错 {type(e)}:{e}")
return ""
return ""
@@ -254,6 +254,7 @@ class Genshin(db.Model):
query = cls.query.where(cls.today_query_uid.contains(str(uid)))
x = await query.gino.first()
if x:
await cls._add_query_uid(uid, uid)
return x.cookie
for u in [
x for x in await cls.query.order_by(db.func.random()).gino.all() if x.cookie
@@ -356,7 +357,7 @@ class Genshin(db.Model):
"""
query = cls.query.where(cls.uid == cookie_uid).with_for_update()
user = await query.gino.first()
await user.update(today_query_uid=cls.today_query_uid + f"{uid} ").apply()
await user.update(today_query_uid=user.today_query_uid + f"{uid} ").apply()
@classmethod
async def _get_user_data(
@@ -200,7 +200,7 @@ def _parse_data_and_draw(
file_name = x["avatar_side_icon"].split("_")[-1]
role_avatar = memo_path / "role_avatar" / file_name
_ava_img = BuildImage(75, 75, background=role_avatar)
_ava_img.circle()
# _ava_img.circle()
if x["status"] == "Finished":
msg = "探索完成"
font_color = (146, 188, 63)
@@ -218,10 +218,10 @@ def _parse_data_and_draw(
a_circle.circle()
b_circle = BuildImage(47, 47)
b_circle.circle()
a_circle.paste(b_circle, (4, 4), alpha=True)
_circle_bk.paste(a_circle, (4, 4), alpha=True)
a_circle.paste(b_circle, (4, 4), 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.text((100, 0), msg, font_color, "by_height")
_bk.circle_corner(20)
@@ -296,9 +296,11 @@ def get_country_data_image(world_data_dict: Dict) -> BuildImage:
画出国家探索供奉等图像
: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
for country in ["蒙德", "龙脊雪山", "璃月", "稻妻", "渊下宫"]:
for country in ["蒙德", "龙脊雪山", "璃月", "璃月层岩巨渊", "稻妻", "渊下宫"]:
x = BuildImage(790, 250, color="#3A4467")
logo = BuildImage(180, 180, background=image_path / "logo" / f"{country}.png")
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']}",
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 ["龙脊雪山"]:
content_bk.text((300, 40), "探索", fill=(239, 211, 114))
content_bk.text(
@@ -55,7 +55,7 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
scheduler.remove_job(f"genshin_resin_remind_{uid}_{event.user_id}")
except JobLookupError:
pass
if cmd == "开":
if cmd[0] == "开":
await Genshin.set_resin_remind(uid, True)
add_job(event.user_id, uid)
logger.info(
@@ -5,6 +5,7 @@ from apscheduler.jobstores.base import ConflictingIdError
from nonebot import Driver
from .._models import Genshin
from datetime import datetime, timedelta
from apscheduler.jobstores.base import JobLookupError
from services.log import logger
from nonebot.plugin import require
from configs.config import Config
@@ -108,6 +109,11 @@ async def _():
def add_job(user_id: int, uid: int):
# 移除
try:
scheduler.remove_job(f"genshin_resin_remind_{uid}_{user_id}")
except JobLookupError:
pass
date = datetime.now(pytz.timezone("Asia/Shanghai")) + timedelta(seconds=30)
try:
scheduler.add_job(
+1 -1
View File
@@ -84,7 +84,7 @@ async def _(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
f"pid:{pid}\n"
f"author:{author}\n"
f"author_id:{author_id}\n"
f'{image(f"pid_search_{event.user_id}.png", "temp")}'
f'{image(TEMP_PATH / f"pid_search_{event.user_id}.png")}'
f"{tmp}"
)
)
+91
View File
@@ -0,0 +1,91 @@
from nonebot.plugin import on_command
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
from nonebot.typing import T_State
from services.log import logger
from utils.utils import get_message_img
from utils.message_builder import custom_forward_msg
from nonebot.params import CommandArg, Arg, ArgStr, Depends
from .saucenao import get_saucenao_image
__zx_plugin_name__ = "识图"
__plugin_usage__ = """
usage:
识别图片 [二次元图片]
指令:
识图 [图片]
""".strip()
__plugin_des__ = "以图搜图,看破本源"
__plugin_cmd__ = ["识图"]
__plugin_type__ = ("一些工具",)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["识图"],
}
__plugin_configs__ = {
"MAX_FIND_IMAGE_COUNT": {"value": 3, "help": "识图返回的最大结果数", "default_value": 3},
"API_KEY": {
"value": None,
"help": "Saucenao的API_KEY,通过 https://saucenao.com/user.php?page=search-api 注册获取",
},
}
search_image = on_command("识图", block=True, priority=5)
async def get_image_info(mod: str, url: str):
if mod == "saucenao":
return await get_saucenao_image(url)
def parse_image(key: str):
async def _key_parser(
state: T_State, img: Message = Arg(key)
):
if not get_message_img(img):
await search_image.reject_arg(key, "请发送要识别的图片!")
state[key] = img
return _key_parser
@search_image.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
if msg:
state["mod"] = msg
else:
state["mod"] = "saucenao"
if get_message_img(event.json()):
state["img"] = event.message
@search_image.got("img", prompt="图来!", parameterless=[Depends(parse_image("img"))])
async def _(
bot: Bot,
event: MessageEvent,
state: T_State,
mod: str = ArgStr("mod"),
img: Message = Arg("img"),
):
img = get_message_img(img)[0]
await search_image.send("开始处理图片...")
msg = await get_image_info(mod, img)
if isinstance(msg, str):
await search_image.finish(msg, at_sender=True)
if isinstance(event, GroupMessageEvent):
await bot.send_group_forward_msg(
group_id=event.group_id, messages=custom_forward_msg(msg, bot.self_id)
)
else:
for m in msg[1:]:
await search_image.send(m)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 识图:" + img
)
+50
View File
@@ -0,0 +1,50 @@
from utils.http_utils import AsyncHttpx
from configs.config import Config
from configs.path_config import TEMP_PATH
from utils.message_builder import image
from typing import Union, List
import random
API_URL_SAUCENAO = "https://saucenao.com/search.php"
API_URL_ASCII2D = "https://ascii2d.net/search/url/"
API_URL_IQDB = "https://iqdb.org/"
async def get_saucenao_image(url: str) -> Union[str, List[str]]:
api_key = Config.get_config("search_image", "API_KEY")
if not api_key:
return "Saucenao 缺失API_KEY!"
params = {
"output_type": 2,
"api_key": api_key,
"testmode": 1,
"numres": 6,
"db": 999,
"url": url,
}
data = (await AsyncHttpx.post(API_URL_SAUCENAO, params=params)).json()
if data["header"]["status"] != 0:
return "Saucenao识图失败.."
data = data["results"]
data = (
data
if len(data) < Config.get_config("search_image", "MAX_FIND_IMAGE_COUNT")
else data[: Config.get_config("search_image", "MAX_FIND_IMAGE_COUNT")]
)
msg_list = []
index = random.randint(0, 10000)
if await AsyncHttpx.download_file(
url, TEMP_PATH / f"saucenao_search_{index}.jpg"
):
msg_list.append(image(TEMP_PATH / f"saucenao_search_{index}.jpg"))
for info in data:
similarity = info["header"]["similarity"]
tmp = f"相似度:{similarity}%\n"
for x in info["data"].keys():
if x != "ext_urls":
tmp += f"{x}:{info['data'][x]}\n"
if "source" not in info["data"].keys():
tmp += f'source:{info["data"]["ext_urls"][0]}\n'
msg_list.append(tmp[:-1])
return msg_list
+279 -280
View File
@@ -1,280 +1,279 @@
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent, Message
from models.group_info import GroupInfo
from configs.path_config import DATA_PATH, IMAGE_PATH
from nonebot.params import CommandArg, Command
from utils.image_utils import BuildMat
from utils.message_builder import image
from utils.manager import plugins2settings_manager
from typing import Tuple
import asyncio
import os
try:
import ujson as json
except ModuleNotFoundError:
import json
__zx_plugin_name__ = "功能调用统计可视化"
__plugin_usage__ = """
usage:
功能调用统计可视化
指令:
功能调用统计
日功能调用统计
周功能调用统计 ?[功能]
月功能调用统计 ?[功能]
我的功能调用统计
我的日功能调用统计 ?[功能]
我的周功能调用统计 ?[功能]
我的月功能调用统计 ?[功能]
""".strip()
__plugin_superuser_usage__ = """
usage:
功能调用统计可视化
指令:
全局功能调用统计
全局日功能调用统计
全局周功能调用统计 ?[功能]
全局月功能调用统计 ?[功能]
""".strip()
__plugin_des__ = "功能调用统计可视化"
__plugin_cmd__ = [
"功能调用统计",
"全局功能调用统计 [_superuser]",
"全局日功能调用统计 [_superuser]",
"全局周功能调用统计 ?[功能] [_superuser]",
"全局月功能调用统计 ?[功能] [_superuser]",
"周功能调用统计 ?[功能]",
"月功能调用统计 ?[功能]",
"我的功能调用统计",
"我的日功能调用统计 ?[功能]",
"我的周功能调用统计 ?[功能]",
"我的月功能调用统计 ?[功能]",
]
__plugin_type__ = ("功能调用统计可视化", 1)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["功能调用统计"],
}
statistics = on_command(
"功能调用统计",
aliases={
"全局功能调用统计",
"全局日功能调用统计",
"全局周功能调用统计",
"全局月功能调用统计",
"日功能调用统计",
"周功能调用统计",
"月功能调用统计",
"我的功能调用统计",
"我的日功能调用统计",
"我的周功能调用统计",
"我的月功能调用统计",
},
priority=5,
block=True,
)
statistics_group_file = DATA_PATH / "statistics" / "_prefix_count.json"
statistics_user_file = DATA_PATH / "statistics" / "_prefix_user_count.json"
@statistics.handle()
async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
if cmd[0][:2] == "全局":
if str(event.user_id) in bot.config.superusers:
data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
if cmd[0][2] == '日':
_type = 'day_statistics'
elif cmd[0][2] == '周':
_type = 'week_statistics'
elif cmd[0][2] == '月':
_type = 'month_statistics'
else:
_type = 'total_statistics'
tmp_dict = {}
data = data[_type]
if _type in ["day_statistics", "total_statistics"]:
for key in data['total']:
tmp_dict[key] = data['total'][key]
else:
for group in data.keys():
if group != 'total':
for day in data[group].keys():
for plugin_name in data[group][day].keys():
if data[group][day][plugin_name] is not None:
if tmp_dict.get(plugin_name) is None:
tmp_dict[plugin_name] = 1
else:
tmp_dict[plugin_name] += data[group][day][plugin_name]
bar_graph = await init_bar_graph(tmp_dict, cmd[0])
await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
await statistics.finish(image(b64=bar_graph.pic2bs4()))
return
if cmd[0][:2] == "我的":
_type = "user"
key = str(event.user_id)
cmd = list(cmd)
cmd[0] = cmd[0][2:]
if not statistics_user_file.exists():
await statistics.finish("统计文件不存在...", at_sender=True)
else:
if not isinstance(event, GroupMessageEvent):
await statistics.finish("请在群内调用此功能...")
_type = "group"
key = str(event.group_id)
if not statistics_group_file.exists():
await statistics.finish("统计文件不存在...", at_sender=True)
plugin = ""
if cmd[0][0] == "日":
arg = "day_statistics"
elif cmd[0][0] == "周":
arg = "week_statistics"
elif cmd[0][0] == "月":
arg = "month_statistics"
else:
arg = "total_statistics"
if msg:
plugin = plugins2settings_manager.get_plugin_module(msg)
if not plugin:
if arg not in ["day_statistics", "total_statistics"]:
await statistics.finish("未找到此功能的调用...", at_sender=True)
if _type == "group":
data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
if not data[arg].get(str(event.group_id)):
await statistics.finish("该群统计数据不存在...", at_sender=True)
else:
data: dict = json.load(open(statistics_user_file, "r", encoding="utf8"))
if not data[arg].get(str(event.user_id)):
await statistics.finish("该用户统计数据不存在...", at_sender=True)
day_index = data["day_index"]
data = data[arg][key]
if _type == "group":
name = await GroupInfo.get_group_info(event.group_id)
name = name.group_name if name else str(event.group_id)
else:
name = event.sender.card or event.sender.nickname
img = await generate_statistics_img(data, arg, name, plugin, day_index)
await statistics.send(image(b64=img))
async def generate_statistics_img(
data: dict, arg: str, name: str, plugin: str, day_index: int
):
try:
plugin = plugins2settings_manager.get_plugin_data(plugin)['cmd'][0]
except (KeyError, IndexError):
pass
bar_graph = None
if arg == "day_statistics":
bar_graph = await init_bar_graph(data, f"{name} 日功能调用统计")
elif arg == "week_statistics":
if plugin:
current_week = day_index % 7
week_lst = []
if current_week == 0:
week_lst = [1, 2, 3, 4, 5, 6, 7]
else:
for i in range(current_week + 1, 7):
week_lst.append(str(i))
for i in range(current_week + 1):
week_lst.append(str(i))
count = []
for i in range(7):
if int(week_lst[i]) == 7:
try:
count.append(data[str(0)][plugin])
except KeyError:
count.append(0)
else:
try:
count.append(data[str(week_lst[i])][plugin])
except KeyError:
count.append(0)
week_lst = ["7" if i == "0" else i for i in week_lst]
bar_graph = BuildMat(
y=count,
mat_type="line",
title=f"{name} 周 {plugin} 功能调用统计【为7天统计】",
x_index=week_lst,
display_num=True,
background=[
f"{IMAGE_PATH}/background/create_mat/{x}"
for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
],
bar_color=["*"],
)
else:
bar_graph = await init_bar_graph(update_data(data), f"{name} 周功能调用统计【为7天统计】")
elif arg == "month_statistics":
if plugin:
day_index = day_index % 30
day_lst = []
for i in range(day_index + 1, 30):
day_lst.append(i)
for i in range(day_index + 1):
day_lst.append(i)
count = [data[str(day_lst[i])][plugin] for i in range(30)]
day_lst = [str(x + 1) for x in day_lst]
bar_graph = BuildMat(
y=count,
mat_type="line",
title=f"{name} 月 {plugin} 功能调用统计【为30天统计】",
x_index=day_lst,
display_num=True,
background=[
f"{IMAGE_PATH}/background/create_mat/{x}"
for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
],
bar_color=["*"],
)
else:
bar_graph = await init_bar_graph(update_data(data), f"{name} 月功能调用统计【为30天统计】")
elif arg == "total_statistics":
bar_graph = await init_bar_graph(data, f"{name} 功能调用统计")
await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
return bar_graph.pic2bs4()
async def init_bar_graph(data: dict, title: str) -> BuildMat:
return await asyncio.get_event_loop().run_in_executor(None, _init_bar_graph, data, title)
def _init_bar_graph(data: dict, title: str) -> BuildMat:
bar_graph = BuildMat(
y=[data[x] for x in data.keys() if data[x] != 0],
mat_type="barh",
title=title,
x_index=[x for x in data.keys() if data[x] != 0],
display_num=True,
background=[
f"{IMAGE_PATH}/background/create_mat/{x}"
for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
],
bar_color=["*"],
)
return bar_graph
def update_data(data: dict):
tmp_dict = {}
for day in data.keys():
for plugin_name in data[day].keys():
# print(f'{day}:{plugin_name} = {data[day][plugin_name]}')
if data[day][plugin_name] is not None:
if tmp_dict.get(plugin_name) is None:
tmp_dict[plugin_name] = 1
else:
tmp_dict[plugin_name] += data[day][plugin_name]
return tmp_dict
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent, Message
from models.group_info import GroupInfo
from configs.path_config import DATA_PATH, IMAGE_PATH
from nonebot.params import CommandArg, Command
from utils.image_utils import BuildMat
from utils.message_builder import image
from utils.manager import plugins2settings_manager
from typing import Tuple
import asyncio
import os
try:
import ujson as json
except ModuleNotFoundError:
import json
__zx_plugin_name__ = "功能调用统计可视化"
__plugin_usage__ = """
usage:
功能调用统计可视化
指令:
功能调用统计
日功能调用统计
周功能调用统计 ?[功能]
月功能调用统计 ?[功能]
我的功能调用统计
我的日功能调用统计 ?[功能]
我的周功能调用统计 ?[功能]
我的月功能调用统计 ?[功能]
""".strip()
__plugin_superuser_usage__ = """
usage:
功能调用统计可视化
指令:
全局功能调用统计
全局日功能调用统计
全局周功能调用统计 ?[功能]
全局月功能调用统计 ?[功能]
""".strip()
__plugin_des__ = "功能调用统计可视化"
__plugin_cmd__ = [
"功能调用统计",
"全局功能调用统计 [_superuser]",
"全局日功能调用统计 [_superuser]",
"全局周功能调用统计 ?[功能] [_superuser]",
"全局月功能调用统计 ?[功能] [_superuser]",
"周功能调用统计 ?[功能]",
"月功能调用统计 ?[功能]",
"我的功能调用统计",
"我的日功能调用统计 ?[功能]",
"我的周功能调用统计 ?[功能]",
"我的月功能调用统计 ?[功能]",
]
__plugin_type__ = ("功能调用统计可视化", 1)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["功能调用统计"],
}
statistics = on_command(
"功能调用统计",
aliases={
"全局功能调用统计",
"全局日功能调用统计",
"全局周功能调用统计",
"全局月功能调用统计",
"日功能调用统计",
"周功能调用统计",
"月功能调用统计",
"我的功能调用统计",
"我的日功能调用统计",
"我的周功能调用统计",
"我的月功能调用统计",
},
priority=5,
block=True,
)
statistics_group_file = DATA_PATH / "statistics" / "_prefix_count.json"
statistics_user_file = DATA_PATH / "statistics" / "_prefix_user_count.json"
@statistics.handle()
async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
if cmd[0][:2] == "全局":
if str(event.user_id) in bot.config.superusers:
data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
if cmd[0][2] == '日':
_type = 'day_statistics'
elif cmd[0][2] == '周':
_type = 'week_statistics'
elif cmd[0][2] == '月':
_type = 'month_statistics'
else:
_type = 'total_statistics'
tmp_dict = {}
data = data[_type]
if _type in ["day_statistics", "total_statistics"]:
for key in data['total']:
tmp_dict[key] = data['total'][key]
else:
for group in data.keys():
if group != 'total':
for day in data[group].keys():
for plugin_name in data[group][day].keys():
if data[group][day][plugin_name] is not None:
if tmp_dict.get(plugin_name) is None:
tmp_dict[plugin_name] = 1
else:
tmp_dict[plugin_name] += data[group][day][plugin_name]
bar_graph = await init_bar_graph(tmp_dict, cmd[0])
await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
await statistics.finish(image(b64=bar_graph.pic2bs4()))
return
if cmd[0][:2] == "我的":
_type = "user"
key = str(event.user_id)
cmd = list(cmd)
cmd[0] = cmd[0][2:]
if not statistics_user_file.exists():
await statistics.finish("统计文件不存在...", at_sender=True)
else:
if not isinstance(event, GroupMessageEvent):
await statistics.finish("请在群内调用此功能...")
_type = "group"
key = str(event.group_id)
if not statistics_group_file.exists():
await statistics.finish("统计文件不存在...", at_sender=True)
plugin = ""
if cmd[0][0] == "日":
arg = "day_statistics"
elif cmd[0][0] == "周":
arg = "week_statistics"
elif cmd[0][0] == "月":
arg = "month_statistics"
else:
arg = "total_statistics"
if msg:
plugin = plugins2settings_manager.get_plugin_module(msg)
if not plugin:
if arg not in ["day_statistics", "total_statistics"]:
await statistics.finish("未找到此功能的调用...", at_sender=True)
if _type == "group":
data: dict = json.load(open(statistics_group_file, "r", encoding="utf8"))
if not data[arg].get(str(event.group_id)):
await statistics.finish("该群统计数据不存在...", at_sender=True)
else:
data: dict = json.load(open(statistics_user_file, "r", encoding="utf8"))
if not data[arg].get(str(event.user_id)):
await statistics.finish("该用户统计数据不存在...", at_sender=True)
day_index = data["day_index"]
data = data[arg][key]
if _type == "group":
name = await GroupInfo.get_group_info(event.group_id)
name = name.group_name if name else str(event.group_id)
else:
name = event.sender.card or event.sender.nickname
img = await generate_statistics_img(data, arg, name, plugin, day_index)
await statistics.send(image(b64=img))
async def generate_statistics_img(
data: dict, arg: str, name: str, plugin: str, day_index: int
):
try:
plugin = plugins2settings_manager.get_plugin_data(plugin)['cmd'][0]
except (KeyError, IndexError):
pass
bar_graph = None
if arg == "day_statistics":
bar_graph = await init_bar_graph(data, f"{name} 日功能调用统计")
elif arg == "week_statistics":
if plugin:
current_week = day_index % 7
week_lst = []
if current_week == 0:
week_lst = [1, 2, 3, 4, 5, 6, 7]
else:
for i in range(current_week + 1, 7):
week_lst.append(str(i))
for i in range(current_week + 1):
week_lst.append(str(i))
count = []
for i in range(7):
if int(week_lst[i]) == 7:
try:
count.append(data[str(0)][plugin])
except KeyError:
count.append(0)
else:
try:
count.append(data[str(week_lst[i])][plugin])
except KeyError:
count.append(0)
week_lst = ["7" if i == "0" else i for i in week_lst]
bar_graph = BuildMat(
y=count,
mat_type="line",
title=f"{name} 周 {plugin} 功能调用统计【为7天统计】",
x_index=week_lst,
display_num=True,
background=[
f"{IMAGE_PATH}/background/create_mat/{x}"
for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
],
bar_color=["*"],
)
else:
bar_graph = await init_bar_graph(update_data(data), f"{name} 周功能调用统计【为7天统计】")
elif arg == "month_statistics":
if plugin:
day_index = day_index % 30
day_lst = []
for i in range(day_index + 1, 30):
day_lst.append(i)
for i in range(day_index + 1):
day_lst.append(i)
count = [data[str(day_lst[i])][plugin] for i in range(30)]
day_lst = [str(x + 1) for x in day_lst]
bar_graph = BuildMat(
y=count,
mat_type="line",
title=f"{name} 月 {plugin} 功能调用统计【为30天统计】",
x_index=day_lst,
display_num=True,
background=[
f"{IMAGE_PATH}/background/create_mat/{x}"
for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
],
bar_color=["*"],
)
else:
bar_graph = await init_bar_graph(update_data(data), f"{name} 月功能调用统计【为30天统计】")
elif arg == "total_statistics":
bar_graph = await init_bar_graph(data, f"{name} 功能调用统计")
await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
return bar_graph.pic2bs4()
async def init_bar_graph(data: dict, title: str) -> BuildMat:
return await asyncio.get_event_loop().run_in_executor(None, _init_bar_graph, data, title)
def _init_bar_graph(data: dict, title: str) -> BuildMat:
bar_graph = BuildMat(
y=[data[x] for x in data.keys() if data[x] != 0],
mat_type="barh",
title=title,
x_index=[x for x in data.keys() if data[x] != 0],
display_num=True,
background=[
f"{IMAGE_PATH}/background/create_mat/{x}"
for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
],
bar_color=["*"],
)
return bar_graph
def update_data(data: dict):
tmp_dict = {}
for day in data.keys():
for plugin_name in data[day].keys():
# print(f'{day}:{plugin_name} = {data[day][plugin_name]}')
if data[day][plugin_name] is not None:
if tmp_dict.get(plugin_name) is None:
tmp_dict[plugin_name] = 1
else:
tmp_dict[plugin_name] += data[day][plugin_name]
return tmp_dict
+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)
Generated
+150 -24
View File
@@ -377,6 +377,26 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
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]]
name = "fastapi"
version = "0.73.0"
@@ -520,14 +540,14 @@ reference = "tsinghua"
[[package]]
name = "httptools"
version = "0.2.0"
version = "0.4.0"
description = "A collection of framework independent HTTP protocol utils."
category = "main"
optional = false
python-versions = "*"
python-versions = ">=3.5.0"
[package.extras]
test = ["Cython (==0.29.22)"]
test = ["Cython (>=0.29.24,<0.30.0)"]
[package.source]
type = "legacy"
@@ -915,6 +935,19 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
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]]
name = "pydantic"
version = "1.9.0"
@@ -1023,6 +1056,45 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
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]]
name = "pytz"
version = "2021.3"
@@ -1130,6 +1202,22 @@ type = "legacy"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
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]]
name = "ruamel.yaml"
version = "0.17.21"
@@ -1403,7 +1491,7 @@ reference = "tsinghua"
[[package]]
name = "uvicorn"
version = "0.17.5"
version = "0.17.6"
description = "The lightning-fast ASGI server."
category = "main"
optional = false
@@ -1414,7 +1502,7 @@ asgiref = ">=3.4.0"
click = ">=7.0"
colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""}
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\""}
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\""}
@@ -1422,7 +1510,7 @@ watchgod = {version = ">=0.6", optional = true, markers = "extra == \"standard\"
websockets = {version = ">=10.0", optional = true, markers = "extra == \"standard\""}
[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]
type = "legacy"
@@ -1522,7 +1610,7 @@ reference = "tsinghua"
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "2521c3cd7346f1f1b3b22276fa71ca9680447f85fc13fd23ede0e33d6f942423"
content-hash = "a467c2f5d871d65cd76363a2839023a38bde9b4aacd37f3019dca6fe0f199723"
[metadata.files]
aiofiles = [
@@ -1764,6 +1852,10 @@ dateparser = [
{file = "dateparser-1.1.0-py2.py3-none-any.whl", hash = "sha256:fec344db1f73d005182e214c0ff27313c748bbe0c1638ce9d48a809ddfdab2a0"},
{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 = [
{file = "fastapi-0.73.0-py3-none-any.whl", hash = "sha256:f0a618aff5f6942862f2d3f20f39b1c037e33314d1b8207fd1c3a2cca76dfd8c"},
{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"},
]
httptools = [
{file = "httptools-0.2.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5"},
{file = "httptools-0.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:78d03dd39b09c99ec917d50189e6743adbfd18c15d5944392d2eabda688bf149"},
{file = "httptools-0.2.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a23166e5ae2775709cf4f7ad4c2048755ebfb272767d244e1a96d55ac775cca7"},
{file = "httptools-0.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3ab1f390d8867f74b3b5ee2a7ecc9b8d7f53750bd45714bf1cb72a953d7dfa77"},
{file = "httptools-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a7594f9a010cdf1e16a58b3bf26c9da39bbf663e3b8d46d39176999d71816658"},
{file = "httptools-0.2.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:01b392a166adcc8bc2f526a939a8aabf89fe079243e1543fd0e7dc1b58d737cb"},
{file = "httptools-0.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:80ffa04fe8c8dfacf6e4cef8277347d35b0442c581f5814f3b0cf41b65c43c6e"},
{file = "httptools-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d5682eeb10cca0606c4a8286a3391d4c3c5a36f0c448e71b8bd05be4e1694bfb"},
{file = "httptools-0.2.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a289c27ccae399a70eacf32df9a44059ca2ba4ac444604b00a19a6c1f0809943"},
{file = "httptools-0.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:813871f961edea6cb2fe312f2d9b27d12a51ba92545380126f80d0de1917ea15"},
{file = "httptools-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:cc9be041e428c10f8b6ab358c6b393648f9457094e1dcc11b4906026d43cd380"},
{file = "httptools-0.2.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b08d00d889a118f68f37f3c43e359aab24ee29eb2e3fe96d64c6a2ba8b9d6557"},
{file = "httptools-0.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fd3b8905e21431ad306eeaf56644a68fdd621bf8f3097eff54d0f6bdf7262065"},
{file = "httptools-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:200fc1cdf733a9ff554c0bb97a4047785cfaad9875307d6087001db3eb2b417f"},
{file = "httptools-0.2.0.tar.gz", hash = "sha256:94505026be56652d7a530ab03d89474dc6021019d6b8682281977163b3471ea0"},
{file = "httptools-0.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcddfe70553be717d9745990dfdb194e22ee0f60eb8f48c0794e7bfeda30d2d5"},
{file = "httptools-0.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1ee0b459257e222b878a6c09ccf233957d3a4dcb883b0847640af98d2d9aac23"},
{file = "httptools-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceafd5e960b39c7e0d160a1936b68eb87c5e79b3979d66e774f0c77d4d8faaed"},
{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.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:abe829275cdd4174b4c4e65ad718715d449e308d59793bf3a931ee1bf7e7b86c"},
{file = "httptools-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7af6bdbd21a2a25d6784f6d67f44f5df33ef39b6159543b9f9064d365c01f919"},
{file = "httptools-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d1fe6b6661022fd6cac541f54a4237496b246e6f1c0a6b41998ee08a1135afe"},
{file = "httptools-0.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:48e48530d9b995a84d1d89ae6b3ec4e59ea7d494b150ac3bbc5e2ac4acce92cd"},
{file = "httptools-0.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a113789e53ac1fa26edf99856a61e4c493868e125ae0dd6354cf518948fbbd5c"},
{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.4.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:7ee9f226acab9085037582c059d66769862706e8e8cd2340470ceb8b3850873d"},
{file = "httptools-0.4.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:701e66b59dd21a32a274771238025d58db7e2b6ecebbab64ceff51b8e31527ae"},
{file = "httptools-0.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6a1a7dfc1f9c78a833e2c4904757a0f47ce25d08634dd2a52af394eefe5f9777"},
{file = "httptools-0.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:903f739c9fb78dab8970b0f3ea51f21955b24b45afa77b22ff0e172fc11ef111"},
{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 = [
{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.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 = [
{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"},
@@ -2288,6 +2403,13 @@ python-dotenv = [
{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"},
]
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 = [
{file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"},
{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.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" = [
{file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
{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"},
]
uvicorn = [
{file = "uvicorn-0.17.5-py3-none-any.whl", hash = "sha256:8adddf629b79857b48b999ae1b14d6c92c95d4d7840bd86461f09bee75f1653e"},
{file = "uvicorn-0.17.5.tar.gz", hash = "sha256:c04a9c069111489c324f427501b3840d306c6b91a77b00affc136a840a3f45f1"},
{file = "uvicorn-0.17.6-py3-none-any.whl", hash = "sha256:19e2a0e96c9ac5581c01eb1a79a7d2f72bb479691acd2b8921fce48ed5b961a6"},
{file = "uvicorn-0.17.6.tar.gz", hash = "sha256:5180f9d059611747d841a4a4c4ab675edf54c8489e97f96d0583ee90ac3bfc23"},
]
uvloop = [
{file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"},
+2
View File
@@ -38,6 +38,8 @@ black = "^22.1.0"
pypinyin = "^0.46.0"
dateparser = "^1.1.0"
cn2an = "^0.5.16"
python-jose = "^3.3.0"
python-multipart = "^0.0.5"
[tool.poetry.dev-dependencies]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 88 KiB

+10 -6
View File
@@ -295,7 +295,7 @@ class AsyncPlaywright:
path: Union[Path, str],
element: Union[str, List[str]],
*,
sleep: Optional[int] = None,
wait_time: Optional[int] = None,
viewport_size: Dict[str, int] = None,
wait_until: Optional[
Literal["domcontentloaded", "load", "networkidle"]
@@ -311,7 +311,7 @@ class AsyncPlaywright:
:param url: 网址
:param path: 存储路径
:param element: 元素选择
:param sleep: 延迟截取
:param wait_time: 等待截取超时时间
:param viewport_size: 窗口大小
:param wait_until: 等待类型
:param timeout: 超时限制
@@ -325,14 +325,18 @@ class AsyncPlaywright:
try:
page = await cls.goto(url, wait_until=wait_until, **kwargs)
await page.set_viewport_size(viewport_size)
if sleep:
await asyncio.sleep(sleep)
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:
card = page
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_)
return image(path)
except Exception as e:
+2 -1
View File
@@ -2,6 +2,7 @@ from typing import Union, Optional
from pathlib import Path
from ruamel.yaml import YAML
import ujson as json
import copy
yaml = YAML(typ="safe")
@@ -47,7 +48,7 @@ class StaticData:
del self._data[key]
def get_data(self) -> dict:
return self._data
return copy.deepcopy(self._data)
def save(self, path: Union[str, Path] = None):
path = path if path else self.file
+30 -5
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.exception import ActionFailed
from services.log import logger
from typing import Optional
from typing import Optional, Literal
from utils.image_utils import BuildImage
from utils.utils import get_user_avatar
from pathlib import Path
@@ -75,6 +75,16 @@ class RequestManager(StaticData):
break
self.save()
def get_group_id(self, id_: int) -> Optional[int]:
"""
通过id获取群号
:param id_: 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]:
"""
同意请求
@@ -93,13 +103,28 @@ class RequestManager(StaticData):
"""
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()
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):
"""
设置群聊名称
@@ -216,7 +241,7 @@ class RequestManager(StaticData):
:param approve: 是否同意
"""
id_ = str(id_)
if id_ in self._data[type_]:
if id_ in self._data[type_].keys():
try:
if type_ == "private":
await bot.set_friend_add_request(
@@ -237,7 +262,7 @@ class RequestManager(StaticData):
)
return None
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 '入群'}请求..."
)
del self._data[type_][id_]