diff --git a/README.md b/README.md
index bbda4355..1a3054b4 100644
--- a/README.md
+++ b/README.md
@@ -331,6 +331,15 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
## 更新
+### 2023/5/22
+
+* 群聊中B站订阅所有管理员共享增删操作
+* 数据库中所有user_qq改名以及user_id和group_id改为字符串
+
+### 2023/5/16
+
+* 修复因明日方舟新增“中坚寻访”导致抽卡模拟不可用的问题 [@pull/1418](https://github.com/HibiKier/zhenxun_bot/pull/1418)
+
### 2023/4/16
* 修复开箱更新未登录时没有停止更新
diff --git a/basic_plugins/admin_bot_manage/_data_source.py b/basic_plugins/admin_bot_manage/_data_source.py
index 97e787e1..8e433183 100644
--- a/basic_plugins/admin_bot_manage/_data_source.py
+++ b/basic_plugins/admin_bot_manage/_data_source.py
@@ -17,14 +17,16 @@ from utils.http_utils import AsyncHttpx
from utils.image_utils import BuildImage
from utils.manager import group_manager, plugins2settings_manager, plugins_manager
from utils.message_builder import image
+from utils.typing import BLOCK_TYPE
from utils.utils import get_matchers
-custom_welcome_msg_json = (
- Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
-)
+CUSTOM_WELCOME_FILE = Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
+CUSTOM_WELCOME_FILE.parent.mkdir(parents=True, exist_ok=True)
ICON_PATH = IMAGE_PATH / "other"
+GROUP_HELP_PATH = DATA_PATH / "group_help"
+
async def group_current_status(group_id: int) -> str:
"""
@@ -66,14 +68,14 @@ async def group_current_status(group_id: int) -> str:
async def custom_group_welcome(
- msg: str, img_list: List[str], user_id: int, group_id: int
+ msg: str, img_list: List[str], user_id: str, group_id: str
) -> Union[str, Message]:
"""
说明:
替换群欢迎消息
参数:
:param msg: 欢迎消息文本
- :param img_list: 欢迎消息图片,只取第一张
+ :param img_list: 欢迎消息图片
:param user_id: 用户id,用于log记录
:param group_id: 群号
"""
@@ -84,18 +86,16 @@ async def custom_group_welcome(
if msg_image.exists():
msg_image.unlink()
data = {}
- if not custom_welcome_msg_json.exists():
- custom_welcome_msg_json.parent.mkdir(parents=True, exist_ok=True)
- else:
- try:
- data = json.load(open(custom_welcome_msg_json, "r"))
- except FileNotFoundError:
- pass
+ if CUSTOM_WELCOME_FILE.exists():
+ data = json.load(CUSTOM_WELCOME_FILE.open("r", encoding="utf8"))
try:
if msg:
- data[str(group_id)] = str(msg)
+ data[group_id] = msg
json.dump(
- data, open(custom_welcome_msg_json, "w"), indent=4, ensure_ascii=False
+ data,
+ CUSTOM_WELCOME_FILE.open("w", encoding="utf8"),
+ indent=4,
+ ensure_ascii=False,
)
logger.info(f"更换群欢迎消息 {msg}", "更换群欢迎信息", user_id, group_id)
result += msg
@@ -151,12 +151,12 @@ async def change_group_switch(cmd: str, group_id: int, is_super: bool = False) -
参数:
:param cmd: 功能名称
:param group_id: 群号
- :param is_super: 是否位超级用户,超级用户用于私聊开关功能状态
+ :param is_super: 是否为超级用户,超级用户用于私聊开关功能状态
"""
global task_data
if not task_data:
task_data = group_manager.get_task_data()
- group_help_file = DATA_PATH / "group_help" / f"{group_id}.png"
+ help_path = GROUP_HELP_PATH / f"{group_id}.png"
status = cmd[:2]
cmd = cmd[2:]
type_ = "plugin"
@@ -169,8 +169,8 @@ async def change_group_switch(cmd: str, group_id: int, is_super: bool = False) -
else:
if group_manager.check_group_task_status(group_id, task):
group_manager.close_group_task(group_id, task)
- if group_help_file.exists():
- group_help_file.unlink()
+ if help_path.exists():
+ help_path.unlink()
return f"已 {status} 全部被动技能!"
if cmd == "全部功能":
for f in plugins2settings_manager.get_data():
@@ -179,8 +179,8 @@ async def change_group_switch(cmd: str, group_id: int, is_super: bool = False) -
else:
group_manager.block_plugin(f, group_id, False)
group_manager.save()
- if group_help_file.exists():
- group_help_file.unlink()
+ if help_path.exists():
+ help_path.unlink()
return f"已 {status} 全部功能!"
if cmd.lower() in [task_data[x].lower() for x in task_data.keys()]:
type_ = "task"
@@ -206,27 +206,28 @@ async def change_group_switch(cmd: str, group_id: int, is_super: bool = False) -
if not group_manager.get_plugin_status(module, group_id):
return f"功能 {cmd} 正处于关闭状态!不要重复关闭."
group_manager.block_plugin(module, group_id)
- if group_help_file.exists():
- group_help_file.unlink()
+ if help_path.exists():
+ help_path.unlink()
if is_super:
- for file in os.listdir(DATA_PATH / "group_help"):
- file = DATA_PATH / "group_help" / file
+ for file in os.listdir(GROUP_HELP_PATH):
+ file = GROUP_HELP_PATH / file
file.unlink()
else:
- _help_image = DATA_PATH / "group_help" / f"{group_id}.png"
- if _help_image.exists():
- _help_image.unlink()
+ if help_path.exists():
+ help_path.unlink()
return f"{status} {cmd} 功能!"
-def set_plugin_status(cmd: str, block_type: str = "all"):
+def set_plugin_status(cmd: str, block_type: BLOCK_TYPE = "all"):
"""
说明:
设置插件功能状态(超级用户使用)
参数:
:param cmd: 功能名称
- :param block_type: 限制类型, 'all': 私聊+群里, 'private': 私聊, 'group': 群聊
+ :param block_type: 限制类型, 'all': 全局, 'private': 私聊, 'group': 群聊
"""
+ if block_type not in ["all", "private", "group"]:
+ raise TypeError("block_type类型错误, 可选值: ['all', 'private', 'group']")
status = cmd[:2]
cmd = cmd[2:]
module = plugins2settings_manager.get_plugin_module(cmd)
@@ -234,8 +235,8 @@ def set_plugin_status(cmd: str, block_type: str = "all"):
plugins_manager.unblock_plugin(module)
else:
plugins_manager.block_plugin(module, block_type=block_type)
- for file in os.listdir(DATA_PATH / "group_help"):
- file = DATA_PATH / "group_help" / file
+ for file in os.listdir(GROUP_HELP_PATH):
+ file = GROUP_HELP_PATH / file
file.unlink()
@@ -306,7 +307,9 @@ async def update_member_info(
if user_info["role"] in [
"owner",
"admin",
- ] and not await LevelUser.is_group_flag(user_info["user_id"], str(group_id)):
+ ] and not await LevelUser.is_group_flag(
+ user_info["user_id"], str(group_id)
+ ):
await LevelUser.set_level(
user_info["user_id"],
user_info["group_id"],
@@ -356,7 +359,9 @@ async def update_member_info(
)
if _del_member_list:
for del_user in _del_member_list:
- await GroupInfoUser.filter(user_id=str(del_user), group_id=str(group_id)).delete()
+ await GroupInfoUser.filter(
+ user_id=str(del_user), group_id=str(group_id)
+ ).delete()
logger.info(f"删除已退群用户", "更新群组成员信息", del_user, group_id)
if _error_member_list and remind_superuser:
result = ""
diff --git a/basic_plugins/admin_bot_manage/admin_config.py b/basic_plugins/admin_bot_manage/admin_config.py
index 49a5a632..ee751ff9 100755
--- a/basic_plugins/admin_bot_manage/admin_config.py
+++ b/basic_plugins/admin_bot_manage/admin_config.py
@@ -16,10 +16,10 @@ admin_notice = on_notice(priority=5)
@admin_notice.handle()
async def _(event: GroupAdminNoticeEvent):
- if user := await GroupInfoUser.filter(
+ if user := await GroupInfoUser.get_or_none(
user_id=str(event.user_id), group_id=str(event.group_id)
- ).first():
- nickname = user.nickname
+ ):
+ nickname = user.user_name
else:
nickname = event.user_id
if event.sub_type == "set":
@@ -31,7 +31,10 @@ async def _(event: GroupAdminNoticeEvent):
admin_default_auth,
)
logger.info(
- f"为新晋管理员 {nickname}({event.user_id}) " f"添加权限等级:{admin_default_auth}"
+ f"成为管理员,添加权限: {admin_default_auth}",
+ "群管理员变动监测",
+ event.user_id,
+ event.group_id,
)
else:
logger.warning(
@@ -39,4 +42,4 @@ async def _(event: GroupAdminNoticeEvent):
)
elif event.sub_type == "unset":
await LevelUser.delete_level(event.user_id, event.group_id)
- logger.info(f"将非管理员 {nickname}({event.user_id}) 取消权限等级")
+ logger.info("撤销管理员,,取消权限等级", "群管理员变动监测", event.user_id, event.group_id)
diff --git a/basic_plugins/admin_bot_manage/custom_welcome_message.py b/basic_plugins/admin_bot_manage/custom_welcome_message.py
index 9f175226..7f890bb4 100755
--- a/basic_plugins/admin_bot_manage/custom_welcome_message.py
+++ b/basic_plugins/admin_bot_manage/custom_welcome_message.py
@@ -16,8 +16,8 @@ __plugin_usage__ = """
usage:
指令:
自定义进群欢迎消息 ?[文本] ?[图片]
- 示例:自定义进群欢迎消息 欢迎新人![图片]
Note:可以通过[at]来确认是否艾特新成员
+ 示例:自定义进群欢迎消息 欢迎新人![图片]
示例:自定义进群欢迎消息 欢迎你[at]
""".strip()
__plugin_des__ = "简易的自定义群欢迎消息"
@@ -51,10 +51,12 @@ async def _(
await custom_welcome.finish(__plugin_usage__)
try:
await custom_welcome.send(
- await custom_group_welcome(msg, img, event.user_id, event.group_id),
+ await custom_group_welcome(
+ msg, img, str(event.user_id), str(event.group_id)
+ ),
at_sender=True,
)
- logger.info(f"USER {event.user_id} GROUP {event.group_id} 自定义群欢迎消息:{msg}")
+ logger.info(f"自定义群欢迎消息:{msg}", cmd, event.user_id, event.group_id)
except Exception as e:
logger.error(
f"自定义进群欢迎消息发生错误", cmd, event.user_id, getattr(event, "group_id", None), e=e
diff --git a/basic_plugins/admin_bot_manage/switch_rule.py b/basic_plugins/admin_bot_manage/switch_rule.py
index 70a50b8b..5b3ec056 100755
--- a/basic_plugins/admin_bot_manage/switch_rule.py
+++ b/basic_plugins/admin_bot_manage/switch_rule.py
@@ -9,7 +9,7 @@ from nonebot.adapters.onebot.v11 import (
MessageEvent,
PrivateMessageEvent,
)
-from nonebot.params import RegexGroup
+from nonebot.params import CommandArg, RegexGroup
from nonebot.permission import SUPERUSER
from configs.config import NICKNAME, Config
@@ -111,7 +111,7 @@ async def _(
block_type = "all" if block_type == "a" else block_type
block_type = "private" if block_type == "p" else block_type
block_type = "group" if block_type == "g" else block_type
- set_plugin_status(_cmd, block_type)
+ set_plugin_status(_cmd, block_type) # type: ignore
if block_type == "all":
await switch_rule_matcher.send(f"已{_cmd[:2]}功能:{_cmd[2:]}")
elif block_type == "private":
diff --git a/basic_plugins/admin_bot_manage/update_group_member_info.py b/basic_plugins/admin_bot_manage/update_group_member_info.py
index 4a5b2c4a..6a59f418 100755
--- a/basic_plugins/admin_bot_manage/update_group_member_info.py
+++ b/basic_plugins/admin_bot_manage/update_group_member_info.py
@@ -6,6 +6,8 @@ from nonebot.adapters.onebot.v11 import (
GroupMessageEvent,
)
+from services.log import logger
+
from ._data_source import update_member_info
__zx_plugin_name__ = "更新群组成员列表 [Admin]"
@@ -32,9 +34,11 @@ refresh_member_group = on_command(
@refresh_member_group.handle()
async def _(bot: Bot, event: GroupMessageEvent):
if await update_member_info(bot, event.group_id):
- await refresh_member_group.finish("更新群员信息成功!", at_sender=True)
+ await refresh_member_group.send("更新群员信息成功!", at_sender=True)
+ logger.info("更新群员信息成功!", "更新群组成员列表", event.user_id, event.group_id)
else:
- await refresh_member_group.finish("更新群员信息失败!", at_sender=True)
+ await refresh_member_group.send("更新群员信息失败!", at_sender=True)
+ logger.info("更新群员信息失败!", "更新群组成员列表", event.user_id, event.group_id)
group_increase_handle = on_notice(priority=1, block=False)
@@ -42,5 +46,6 @@ group_increase_handle = on_notice(priority=1, block=False)
@group_increase_handle.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
- if event.user_id == int(bot.self_id):
+ if str(event.user_id) == bot.self_id:
await update_member_info(bot, event.group_id)
+ logger.info("{NICKNAME}加入群聊更新群组信息", "更新群组成员列表", event.user_id, event.group_id)
diff --git a/basic_plugins/admin_help/data_source.py b/basic_plugins/admin_help/data_source.py
index 7bc78e1d..7474f44d 100755
--- a/basic_plugins/admin_help/data_source.py
+++ b/basic_plugins/admin_help/data_source.py
@@ -10,7 +10,6 @@ from utils.manager.models import PluginType
driver: Driver = nonebot.get_driver()
-background = IMAGE_PATH / "background" / "0.png"
ADMIN_HELP_IMAGE = IMAGE_PATH / "admin_help_img.png"
diff --git a/basic_plugins/apscheduler/__init__.py b/basic_plugins/apscheduler/__init__.py
index 35f4056f..de0a1962 100755
--- a/basic_plugins/apscheduler/__init__.py
+++ b/basic_plugins/apscheduler/__init__.py
@@ -118,10 +118,15 @@ async def _():
bot = bots[key]
fl = await bot.get_friend_list()
for f in fl:
- await FriendUser.create(user_id=str(f["user_id"]), user_name=f["nickname"])
- logger.debug(f"更新好友信息成功", "自动更新好友", f["user_id"])
+ if FriendUser.exists(user_id=str(f["user_id"])):
+ await FriendUser.create(
+ user_id=str(f["user_id"]), user_name=f["nickname"]
+ )
+ logger.debug(f"更新好友信息成功", "自动更新好友", f["user_id"])
+ else:
+ logger.debug(f"好友信息已存在", "自动更新好友", f["user_id"])
except Exception as e:
- logger.error(f"自动更新群组信息错误", e=e)
+ logger.error(f"自动更新好友信息错误", "自动更新好友", e=e)
logger.info("自动更新好友信息成功...")
diff --git a/basic_plugins/ban/__init__.py b/basic_plugins/ban/__init__.py
index 5dc6ad11..ead19ac2 100755
--- a/basic_plugins/ban/__init__.py
+++ b/basic_plugins/ban/__init__.py
@@ -56,7 +56,7 @@ __plugin_configs__ = {
"value": 5,
"help": "ban/unban所需要的管理员权限等级",
"default_value": 5,
- "type": int
+ "type": int,
}
}
diff --git a/basic_plugins/ban/data_source.py b/basic_plugins/ban/data_source.py
index 6878a8b9..b25a29c4 100644
--- a/basic_plugins/ban/data_source.py
+++ b/basic_plugins/ban/data_source.py
@@ -30,7 +30,7 @@ def parse_ban_time(msg: str) -> Union[int, str]:
return int(msg_split[0]) * 60 * 60 + int(msg_split[1]) * 60
except ValueError as e:
logger.error("解析ban时长错误", ".ban", e=e)
- return "时长不可以带小数点!"
+ return "时间解析错误!"
async def a_ban(
@@ -56,7 +56,7 @@ async def a_ban(
return "未查询到ban级用户权限"
if await BanUser.ban(qq, ban_level, time):
logger.info(
- f"将 [Target]({qq})封禁 时长 {time / 60} 分钟", ".ban", event.user_id, group_id
+ f"封禁 时长 {time / 60} 分钟", ".ban", event.user_id, group_id, qq
)
result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
if time != -1:
diff --git a/basic_plugins/chat_history/chat_message.py b/basic_plugins/chat_history/chat_message.py
index 3abb5ace..bca98e22 100644
--- a/basic_plugins/chat_history/chat_message.py
+++ b/basic_plugins/chat_history/chat_message.py
@@ -37,12 +37,12 @@ async def _(event: MessageEvent, msg: str = PlaintText()):
if isinstance(event, GroupMessageEvent):
group_id = str(event.group_id)
TEMP_LIST.append(
- {
- "user_id": str(event.user_id),
- "group_id": group_id,
- "text": str(event.get_message()),
- "plain_text": msg,
- }
+ ChatHistory(
+ user_id=str(event.user_id),
+ group_id=group_id,
+ text=str(event.get_message()),
+ plain_text=msg,
+ )
)
@@ -55,8 +55,7 @@ async def _():
message_list = TEMP_LIST.copy()
TEMP_LIST.clear()
if message_list:
- model_list = [ChatHistory(**x) for x in message_list]
- await ChatHistory.bulk_create(model_list)
+ await ChatHistory.bulk_create(message_list)
logger.debug(f"批量添加聊天记录 {len(message_list)} 条", "定时任务")
except Exception as e:
logger.error(f"定时批量添加聊天记录", "定时任务", e=e)
diff --git a/basic_plugins/chat_history/chat_message_handle.py b/basic_plugins/chat_history/chat_message_handle.py
index e262ccad..99d2f40a 100644
--- a/basic_plugins/chat_history/chat_message_handle.py
+++ b/basic_plugins/chat_history/chat_message_handle.py
@@ -69,7 +69,7 @@ async def _(event: GroupMessageEvent, reg_group: Tuple[Any, ...] = RegexGroup())
num_str = "发言次数:\n\n"
idx = 1
for uid, num in rank_data:
- if user := await GroupInfoUser.filter(user_id=str(uid), group_id=str(gid)).first():
+ if user := await GroupInfoUser.filter(user_id=uid, group_id=gid).first():
user_name = user.user_name
else:
user_name = uid
diff --git a/basic_plugins/group_handle/__init__.py b/basic_plugins/group_handle/__init__.py
index c67b06f1..6fd2b4bc 100755
--- a/basic_plugins/group_handle/__init__.py
+++ b/basic_plugins/group_handle/__init__.py
@@ -139,7 +139,7 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
group_id=event.group_id, user_id=event.user_id
)
await GroupInfoUser.update_or_create(
- user_qq=str(user_info["user_id"]),
+ user_id=str(user_info["user_id"]),
group_id=str(user_info["group_id"]),
defaults={"user_name": user_info["nickname"], "user_join_time": join_time},
)
@@ -187,7 +187,7 @@ async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
group_id = event.group_id
operator_id = event.operator_id
if user := await GroupInfoUser.get_or_none(
- user_qq=str(event.operator_id), group_id=str(event.group_id)
+ user_id=str(event.operator_id), group_id=str(event.group_id)
):
operator_name = user.user_name
else:
@@ -207,12 +207,14 @@ async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
group_manager.delete_group(event.group_id)
return
if user := await GroupInfoUser.get_or_none(
- user_qq=str(event.user_id), group_id=str(event.group_id)
+ user_id=str(event.user_id), group_id=str(event.group_id)
):
user_name = user.user_name
else:
user_name = f"{event.user_id}"
- await GroupInfoUser.filter(user_id=str(event.user_id), group_id=str(event.group_id)).delete()
+ await GroupInfoUser.filter(
+ user_id=str(event.user_id), group_id=str(event.group_id)
+ ).delete()
logger.info(
f"名称: {user_name} 退出群聊",
"group_decrease_handle",
diff --git a/basic_plugins/init_plugin_config/init_plugins_settings.py b/basic_plugins/init_plugin_config/init_plugins_settings.py
index 4165d1ca..52864ef2 100755
--- a/basic_plugins/init_plugin_config/init_plugins_settings.py
+++ b/basic_plugins/init_plugin_config/init_plugins_settings.py
@@ -19,25 +19,25 @@ def init_plugins_settings():
for matcher in get_matchers(True):
try:
if matcher.plugin_name not in plugins2settings_manager.keys():
- _plugin = matcher.plugin
- try:
- _module = _plugin.module
- except AttributeError:
- logger.warning(f"插件 {matcher.plugin_name} 加载失败...,插件控制未加载.")
- else:
- if plugin_data := plugin_data_manager.get(matcher.plugin_name):
- if plugin_settings := plugin_data.plugin_setting:
- if (name := _module.__getattribute__("__zx_plugin_name__")) not in plugin_settings.cmd:
- plugin_settings.cmd.append(name)
- # 管理员命令
- if plugin_data.plugin_type == PluginType.ADMIN:
- admin_manager.add_admin_plugin_settings(
- matcher.plugin_name, plugin_settings.cmd, plugin_settings.level
- )
- else:
- plugins2settings_manager.add_plugin_settings(
- matcher.plugin_name, plugin_settings
- )
+ if _plugin := matcher.plugin:
+ try:
+ _module = _plugin.module
+ except AttributeError:
+ logger.warning(f"插件 {matcher.plugin_name} 加载失败...,插件控制未加载.")
+ else:
+ if plugin_data := plugin_data_manager.get(matcher.plugin_name):
+ if plugin_settings := plugin_data.plugin_setting:
+ if (name := _module.__getattribute__("__zx_plugin_name__")) not in plugin_settings.cmd:
+ plugin_settings.cmd.append(name)
+ # 管理员命令
+ if plugin_data.plugin_type == PluginType.ADMIN:
+ admin_manager.add_admin_plugin_settings(
+ matcher.plugin_name, plugin_settings.cmd, plugin_settings.level
+ )
+ else:
+ plugins2settings_manager.add_plugin_settings(
+ matcher.plugin_name, plugin_settings
+ )
except Exception as e:
logger.error(f'{matcher.plugin_name} 初始化 plugin_settings 发生错误 {type(e)}:{e}')
plugins2settings_manager.save()
diff --git a/basic_plugins/scripts.py b/basic_plugins/scripts.py
index f9d350a3..1a6bc456 100755
--- a/basic_plugins/scripts.py
+++ b/basic_plugins/scripts.py
@@ -98,26 +98,6 @@ async def _(bot: Bot):
logger.info(f"移除不存在的群聊信息", group_id=group_id)
-# async def __database_script(_flag: List[str]):
-# # bag_user 将文本转为字典格式
-# if "bag_users" in _flag:
-# for x in await BagUser.get_all_users():
-# props = {}
-# if x.props:
-# for prop in [p for p in x.props.split(",") if p]:
-# if props.get(prop):
-# props[prop] += 1
-# else:
-# props[prop] = 1
-# logger.info(
-# f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}"
-# )
-# await x.update(
-# property=props,
-# props="",
-# ).apply()
-
-
# 自动更新城市列表
@scheduler.scheduled_job(
"cron",
diff --git a/plugins/bilibili_sub/__init__.py b/plugins/bilibili_sub/__init__.py
index 6f258626..ca205a5b 100755
--- a/plugins/bilibili_sub/__init__.py
+++ b/plugins/bilibili_sub/__init__.py
@@ -9,6 +9,7 @@ from nonebot.typing import T_State
from configs.config import Config
from models.level_user import LevelUser
from services.log import logger
+from utils.depends import GetConfig
from utils.image_utils import text2image
from utils.manager import group_manager
from utils.message_builder import image
@@ -89,7 +90,12 @@ async def _():
@add_sub.handle()
@del_sub.handle()
-async def _(event: MessageEvent, state: T_State, arg: Message = CommandArg()):
+async def _(
+ event: MessageEvent,
+ state: T_State,
+ arg: Message = CommandArg(),
+ sub_level: Optional[int] = GetConfig(config="GROUP_BILIBILI_SUB_LEVEL"),
+):
msg = arg.extract_plain_text().strip().split()
if len(msg) < 2:
await add_sub.finish("参数不完全,请查看订阅帮助...")
@@ -99,10 +105,10 @@ async def _(event: MessageEvent, state: T_State, arg: Message = CommandArg()):
if not await LevelUser.check_level(
event.user_id,
event.group_id,
- Config.get_config("bilibili_sub", "GROUP_BILIBILI_SUB_LEVEL"), # type: ignore
+ sub_level, # type: ignore
):
await add_sub.finish(
- f"您的权限不足,群内订阅的需要 {Config.get_config('bilibili_sub', 'GROUP_BILIBILI_SUB_LEVEL')} 级权限..",
+ f"您的权限不足,群内订阅的需要 {sub_level} 级权限..",
at_sender=True,
)
sub_user = f"{event.user_id}:{event.group_id}"
@@ -155,9 +161,10 @@ async def _(
else:
await add_sub.finish("参数错误,第一参数必须为:主播/up/番剧!")
logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 添加订阅:{sub_type} -> {sub_user} -> {id_}"
+ f"添加订阅:{sub_type} -> {sub_user} -> {id_}",
+ "添加订阅",
+ event.user_id,
+ getattr(event, "group_id", None),
)
@@ -171,20 +178,27 @@ async def _(
sub_user: str = ArgStr("sub_user"),
):
if sub_type in ["主播", "直播"]:
- result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user, "live")
+ result = await BilibiliSub.delete_bilibili_sub(id_, sub_user, "live")
elif sub_type.lower() in ["up", "用户"]:
- result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user, "up")
+ result = await BilibiliSub.delete_bilibili_sub(id_, sub_user, "up")
else:
- result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user)
+ result = await BilibiliSub.delete_bilibili_sub(id_, sub_user)
if result:
await del_sub.send(f"删除订阅id:{id_} 成功...")
logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 删除订阅 {id_}"
+ f"删除订阅 {id_}",
+ "删除订阅",
+ event.user_id,
+ getattr(event, "group_id", None),
)
else:
await del_sub.send(f"删除订阅id:{id_} 失败...")
+ logger.info(
+ f"删除订阅 {id_} 失败",
+ "删除订阅",
+ event.user_id,
+ getattr(event, "group_id", None),
+ )
@show_sub_info.handle()
@@ -236,18 +250,18 @@ async def _():
bot = get_bot()
sub = None
if bot:
- # try:
await sub_manager.reload_sub_data()
sub = await sub_manager.random_sub_data()
if sub:
- logger.debug(f"Bilibili订阅开始检测:{sub.sub_id}")
- rst = await get_sub_status(sub.sub_id, sub.sub_type)
- await send_sub_msg(rst or "", sub, bot) # type: ignore
- if sub.sub_type == "live":
- rst = await get_sub_status(sub.sub_id, "up")
+ try:
+ logger.debug(f"Bilibili订阅开始检测:{sub.sub_id}")
+ rst = await get_sub_status(sub.sub_id, sub.sub_type)
await send_sub_msg(rst or "", sub, bot) # type: ignore
- # except Exception as e:
- # logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id if sub else 0} {type(e)}:{e}")
+ if sub.sub_type == "live":
+ rst = await get_sub_status(sub.sub_id, "up")
+ await send_sub_msg(rst or "", sub, bot) # type: ignore
+ except Exception as e:
+ logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id}", e=e)
async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
@@ -284,4 +298,4 @@ async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
else:
await bot.send_private_msg(user_id=int(x), message=Message(rst))
except Exception as e:
- logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id} {type(e)}:{e}")
+ logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id}", e=e)
diff --git a/plugins/bilibili_sub/data_source.py b/plugins/bilibili_sub/data_source.py
index 5e393862..d06ee563 100755
--- a/plugins/bilibili_sub/data_source.py
+++ b/plugins/bilibili_sub/data_source.py
@@ -38,12 +38,16 @@ async def add_live_sub(live_id: str, sub_user: str) -> str:
:return:
"""
try:
+ if await BilibiliSub.exists(
+ sub_type="live", sub_id=live_id, sub_users__contains=sub_user + ","
+ ):
+ return "该订阅Id已存在..."
try:
"""bilibili_api.live库的LiveRoom类中get_room_info改为bilireq.live库的get_room_info_by_id方法"""
live_info = await get_room_info_by_id(live_id)
except ResponseCodeError:
return f"未找到房间号Id:{live_id} 的信息,请检查Id是否正确"
- uid = live_info["uid"]
+ uid = str(live_info["uid"])
room_id = live_info["room_id"]
short_id = live_info["short_id"]
title = live_info["title"]
@@ -56,7 +60,10 @@ async def add_live_sub(live_id: str, sub_user: str) -> str:
live_short_id=short_id,
live_status=live_status,
):
- await _get_up_status(room_id)
+ try:
+ await _get_up_status(room_id)
+ except Exception as e:
+ logger.error(f"获取主播UP信息失败: {live_id} 错误", e=e)
if data := await BilibiliSub.get_or_none(sub_id=room_id):
uname = data.uname
return (
@@ -66,11 +73,9 @@ async def add_live_sub(live_id: str, sub_user: str) -> str:
f"\tlive_id:{room_id}\n"
f"\tuid:{uid}"
)
- return "添加订阅失败..."
- else:
- return "添加订阅失败..."
+ return "添加订阅失败..."
except Exception as e:
- logger.error(f"订阅主播live_id:{live_id} 发生了错误 {type(e)}:{e}")
+ logger.error(f"订阅主播live_id: {live_id} 错误", e=e)
return "添加订阅失败..."
@@ -80,7 +85,14 @@ async def add_up_sub(uid: str, sub_user: str) -> str:
:param uid: UP uid
:param sub_user: 订阅用户
"""
+ uname = uid
+ dynamic_upload_time = 0
+ latest_video_created = 0
try:
+ if await BilibiliSub.exists(
+ sub_type="up", sub_id=uid, sub_users__contains=sub_user + ","
+ ):
+ return "该订阅Id已存在..."
try:
"""bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
user_info = await get_user_card(uid)
@@ -89,29 +101,26 @@ async def add_up_sub(uid: str, sub_user: str) -> str:
uname = user_info["name"]
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
dynamic_info = await dynamic.get_user_dynamics(int(uid))
- dynamic_upload_time = 0
if dynamic_info.get("cards"):
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
"""bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
video_info = await get_videos(int(uid))
- latest_video_created = 0
if video_info["list"].get("vlist"):
latest_video_created = video_info["list"]["vlist"][0]["created"]
- if await BilibiliSub.sub_handle(
- uid,
- "up",
- sub_user,
- uid=int(uid),
- uname=uname,
- dynamic_upload_time=dynamic_upload_time,
- latest_video_created=latest_video_created,
- ):
- return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
- else:
- return "添加订阅失败..."
except Exception as e:
- logger.error(f"订阅Up uid:{uid} 发生了错误 {type(e)}:{e}")
- return "添加订阅失败..."
+ logger.error(f"订阅Up uid: {uid} 错误", e=e)
+ if await BilibiliSub.sub_handle(
+ uid,
+ "up",
+ sub_user,
+ uid=uid,
+ uname=uname,
+ dynamic_upload_time=dynamic_upload_time,
+ latest_video_created=latest_video_created,
+ ):
+ return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
+ else:
+ return "添加订阅失败..."
async def add_season_sub(media_id: str, sub_user: str) -> str:
@@ -121,6 +130,10 @@ async def add_season_sub(media_id: str, sub_user: str) -> str:
:param sub_user: 订阅用户
"""
try:
+ if await BilibiliSub.exists(
+ sub_type="season", sub_id=media_id, sub_users__contains=sub_user + ","
+ ):
+ return "该订阅Id已存在..."
try:
"""bilibili_api.bangumi库中get_meta改为bilireq.bangumi库的get_meta方法"""
season_info = await get_meta(media_id)
@@ -145,7 +158,7 @@ async def add_season_sub(media_id: str, sub_user: str) -> str:
else:
return "添加订阅失败..."
except Exception as e:
- logger.error(f"订阅番剧 media_id:{media_id} 发生了错误 {type(e)}:{e}")
+ logger.error(f"订阅番剧 media_id: {media_id} 错误", e=e)
return "添加订阅失败..."
@@ -155,7 +168,7 @@ async def delete_sub(sub_id: str, sub_user: str) -> str:
:param sub_id: 订阅 id
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
"""
- if await BilibiliSub.delete_bilibili_sub(int(sub_id), sub_user):
+ if await BilibiliSub.delete_bilibili_sub(sub_id, sub_user):
return f"已成功取消订阅:{sub_id}"
else:
return f"取消订阅:{sub_id} 失败,请检查是否订阅过该Id...."
@@ -204,12 +217,11 @@ async def get_sub_status(id_: str, sub_type: str) -> Optional[str]:
return await _get_up_status(id_)
elif sub_type == "season":
return await _get_season_status(id_)
- except ResponseCodeError as msg:
- logger.info(f"Id:{id_} 获取信息失败...{msg}")
- return None
+ except ResponseCodeError as e:
+ logger.error(f"Id:{id_} 获取信息失败...", e=e)
# return f"Id:{id_} 获取信息失败...请检查订阅Id是否存在或稍后再试..."
- # except Exception as e:
- # logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
+ except Exception as e:
+ logger.error(f"获取订阅状态发生预料之外的错误 Id_:{id_}", e=e)
# return "发生了预料之外的错误..请稍后再试或联系管理员....."
@@ -250,7 +262,7 @@ async def _get_up_status(id_: str) -> Optional[str]:
user_info = await get_user_card(_user.uid)
uname = user_info["name"]
"""bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
- video_info = await get_videos(_user.uid)
+ video_info = await get_videos(int(_user.uid))
latest_video_created = 0
video = None
dividing_line = "\n-------------\n"
@@ -308,7 +320,7 @@ async def _get_season_status(id_: str) -> Optional[str]:
async def get_user_dynamic(
- uid: int, local_user: BilibiliSub
+ uid: str, local_user: BilibiliSub
) -> Tuple[Optional[MessageSegment], int, str]:
"""
获取用户动态
@@ -317,7 +329,7 @@ async def get_user_dynamic(
:return: 最新动态截图与时间
"""
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
- dynamic_info = await dynamic.get_user_dynamics(uid)
+ dynamic_info = await dynamic.get_user_dynamics(int(uid))
if dynamic_info.get("cards"):
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
dynamic_id = dynamic_info["cards"][0]["desc"]["dynamic_id"]
diff --git a/plugins/bilibili_sub/model.py b/plugins/bilibili_sub/model.py
index 590ebfa6..28c6cf7f 100755
--- a/plugins/bilibili_sub/model.py
+++ b/plugins/bilibili_sub/model.py
@@ -21,7 +21,7 @@ class BilibiliSub(Model):
"""直播短id"""
live_status = fields.IntField(null=True)
"""直播状态 0: 停播 1: 直播"""
- uid = fields.BigIntField(null=True)
+ uid = fields.CharField(255, null=True)
"""主播/UP UID"""
uname = fields.CharField(255, null=True)
"""主播/UP 名称"""
@@ -53,7 +53,7 @@ class BilibiliSub(Model):
live_short_id: Optional[str] = None,
live_status: Optional[int] = None,
dynamic_upload_time: int = 0,
- uid: Optional[int] = None,
+ uid: Optional[str] = None,
uname: Optional[str] = None,
latest_video_created: Optional[int] = None,
season_name: Optional[str] = None,
@@ -80,59 +80,63 @@ class BilibiliSub(Model):
:param season_update_time: 番剧更新时间
"""
sub_id = str(sub_id)
- # try:
- data = {
- "sub_type": sub_type,
- "sub_user": sub_user,
- "live_short_id": live_short_id,
- "live_status": live_status,
- "dynamic_upload_time": dynamic_upload_time,
- "uid": uid,
- "uname": uname,
- "latest_video_created": latest_video_created,
- "season_name": season_name,
- "season_id": season_id,
- "season_current_episode": season_current_episode,
- "season_update_time": season_update_time,
- }
- if sub_user:
- sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
- sub = None
- if sub_type:
- sub = await cls.get_or_none(sub_id=sub_id, sub_type=sub_type)
- else:
- sub = await cls.get_or_none(sub_id=sub_id)
- if sub:
- sub_users = sub.sub_users + sub_user
- data["sub_type"] = sub_type or sub.sub_type
- data["sub_users"] = sub_users
- data["live_short_id"] = live_short_id or sub.live_short_id
- data["live_status"] = (
- live_status if live_status is not None else sub.live_status
- )
- data["dynamic_upload_time"] = dynamic_upload_time or sub.dynamic_upload_time
- data["uid"] = uid or sub.uid
- data["uname"] = uname or sub.uname
- data["latest_video_created"] = (
- latest_video_created or sub.latest_video_created
- )
- data["season_name"] = season_name or sub.season_name
- data["season_id"] = season_id or sub.season_id
- data["season_current_episode"] = (
- season_current_episode or sub.season_current_episode
- )
- data["season_update_time"] = season_update_time or sub.season_update_time
- else:
- await cls.create(sub_id=sub_id, sub_type=sub_type, sub_users=sub_user)
- await cls.update_or_create(sub_id=sub_id, defaults=data)
- return True
- # except Exception as e:
- # logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
- # return False
+ try:
+ data = {
+ "sub_type": sub_type,
+ "sub_user": sub_user,
+ "live_short_id": live_short_id,
+ "live_status": live_status,
+ "dynamic_upload_time": dynamic_upload_time,
+ "uid": uid,
+ "uname": uname,
+ "latest_video_created": latest_video_created,
+ "season_name": season_name,
+ "season_id": season_id,
+ "season_current_episode": season_current_episode,
+ "season_update_time": season_update_time,
+ }
+ if sub_user:
+ sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
+ sub = None
+ if sub_type:
+ sub = await cls.get_or_none(sub_id=sub_id, sub_type=sub_type)
+ else:
+ sub = await cls.get_or_none(sub_id=sub_id)
+ if sub:
+ sub_users = sub.sub_users + sub_user
+ data["sub_type"] = sub_type or sub.sub_type
+ data["sub_users"] = sub_users
+ data["live_short_id"] = live_short_id or sub.live_short_id
+ data["live_status"] = (
+ live_status if live_status is not None else sub.live_status
+ )
+ data["dynamic_upload_time"] = (
+ dynamic_upload_time or sub.dynamic_upload_time
+ )
+ data["uid"] = uid or sub.uid
+ data["uname"] = uname or sub.uname
+ data["latest_video_created"] = (
+ latest_video_created or sub.latest_video_created
+ )
+ data["season_name"] = season_name or sub.season_name
+ data["season_id"] = season_id or sub.season_id
+ data["season_current_episode"] = (
+ season_current_episode or sub.season_current_episode
+ )
+ data["season_update_time"] = (
+ season_update_time or sub.season_update_time
+ )
+ else:
+ await cls.create(sub_id=sub_id, sub_type=sub_type, sub_users=sub_user)
+ await cls.update_or_create(sub_id=sub_id, defaults=data)
+ return True
+ except Exception as e:
+ logger.error(f"添加订阅 Id: {sub_id} 错误", e=e)
+ return False
@classmethod
async def delete_bilibili_sub(
- cls, sub_id: int, sub_user: str, sub_type: Optional[str] = None
+ cls, sub_id: str, sub_user: str, sub_type: Optional[str] = None
) -> bool:
"""
说明:
@@ -142,24 +146,34 @@ class BilibiliSub(Model):
:param sub_user: 删除此条目的用户
"""
try:
+ group_id = None
+ contains_str = sub_user
+ if ":" in sub_user:
+ group_id = sub_user.split(":")[1]
+ contains_str = f":{group_id}"
if sub_type:
- sub = await cls.filter(
- sub_id=sub_id, sub_type=sub_type, sub_users__contains=sub_user
- ).first()
+ sub = await cls.get_or_none(
+ sub_id=sub_id, sub_type=sub_type, sub_users__contains=contains_str
+ )
else:
- sub = await cls.filter(
- sub_id=sub_id, sub_users__contains=sub_user
- ).first()
+ sub = await cls.get_or_none(
+ sub_id=sub_id, sub_users__contains=contains_str
+ )
if not sub:
return False
- sub.sub_users = sub.sub_users.replace(f"{sub_user},", "")
+ if group_id:
+ sub.sub_users = ",".join(
+ [s for s in sub.sub_users.split(",") if f":{group_id}" not in s]
+ )
+ else:
+ sub.sub_users = sub.sub_users.replace(f"{sub_user},", "")
if sub.sub_users.strip():
await sub.save(update_fields=["sub_users"])
else:
await sub.delete()
return True
except Exception as e:
- logger.info(f"bilibili_sub 删除订阅错误 {type(e)}: {e}")
+ logger.error(f"bilibili_sub 删除订阅错误", target=sub_id, e=e)
return False
@classmethod
@@ -189,4 +203,5 @@ class BilibiliSub(Model):
"ALTER TABLE bilibili_sub ALTER COLUMN season_update_time TYPE timestamp with time zone USING season_update_time::timestamp with time zone;",
"alter table bilibili_sub alter COLUMN sub_id type varchar(255);", # 将sub_id字段改为字符串
"alter table bilibili_sub alter COLUMN live_short_id type varchar(255);", # 将live_short_id字段改为字符串
+ "alter table bilibili_sub alter COLUMN uid type varchar(255);", # 将live_short_id字段改为字符串
]
diff --git a/plugins/black_word/__init__.py b/plugins/black_word/__init__.py
index 3547a51d..fde8e4dd 100644
--- a/plugins/black_word/__init__.py
+++ b/plugins/black_word/__init__.py
@@ -96,7 +96,7 @@ Config.add_plugin_config(
"BAN_3_DURATION",
7,
help_="Union[int, List[int, int]]Ban时长(天),三级惩罚,可以为指定数字或指定列表区间(随机),例如 [7, 30]",
- default_value=360,
+ default_value=7,
type=int,
)
@@ -171,8 +171,8 @@ async def _(
and event.is_tome()
and not msg.startswith("原神绑定")
):
- # if str(event.user_id) not in bot.config.superusers:
- # return logger.debug(f"超级用户跳过黑名单词汇检查 Message: {msg}", target=event.user_id)
+ if str(event.user_id) in bot.config.superusers:
+ return logger.debug(f"超级用户跳过黑名单词汇检查 Message: {msg}", target=event.user_id)
if (
event.is_tome()
and matcher.plugin_name == "black_word"
@@ -184,8 +184,8 @@ async def _(
and group_manager.get_group_level(event.group_id) < 0
):
return
- user_id = event.user_id
- group_id = event.group_id if isinstance(event, GroupMessageEvent) else None
+ user_id = str(event.user_id)
+ group_id = str(event.group_id) if isinstance(event, GroupMessageEvent) else None
msg = get_message_text(event.json())
if await black_word_manager.check(
user_id, group_id, msg
@@ -206,8 +206,8 @@ async def _(bot: Bot, reg_group: Tuple[Any, ...] = RegexGroup()):
await show_black.finish("日期格式错误,需要:年-月-日")
pic = await show_black_text_image(
bot,
- int(user_id.split(":")[1]) if user_id else None,
- int(group_id.split(":")[1]) if group_id else None,
+ user_id.split(":")[1] if user_id else None,
+ group_id.split(":")[1] if group_id else None,
date,
date_type,
)
@@ -266,11 +266,13 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
or not is_number(msg[2])
):
await set_punish.finish("参数错误,请查看帮助...", at_sender=True)
- uid = int(msg[0])
+ uid = msg[0]
id_ = int(msg[1])
punish_level = int(msg[2])
rst = await set_user_punish(uid, id_, punish_level)
await set_punish.send(rst)
logger.info(
- f"USER {event.user_id} 设置惩罚 uid:{uid} id_:{id_} punish_level:{punish_level} --> {rst}"
+ f"设置惩罚 uid:{uid} id_:{id_} punish_level:{punish_level} --> {rst}",
+ "设置惩罚",
+ event.user_id,
)
diff --git a/plugins/black_word/data_source.py b/plugins/black_word/data_source.py
index b792df5d..2da848d2 100644
--- a/plugins/black_word/data_source.py
+++ b/plugins/black_word/data_source.py
@@ -1,16 +1,19 @@
-from nonebot.adapters.onebot.v11 import Bot
-from utils.image_utils import BuildImage, text2image
-from services.log import logger
-from typing import Optional
from datetime import datetime
+from typing import Optional
+
+from nonebot.adapters.onebot.v11 import Bot
+
+from services.log import logger
+from utils.image_utils import BuildImage, text2image
+
from .model import BlackWord
-from .utils import _get_punish, Config
+from .utils import Config, _get_punish
async def show_black_text_image(
bot: Bot,
- user: Optional[int],
- group_id: Optional[int],
+ user_id: Optional[str],
+ group_id: Optional[str],
date: Optional[datetime],
data_type: str = "=",
) -> BuildImage:
@@ -23,7 +26,7 @@ async def show_black_text_image(
:param data_type: 日期搜索类型
:return:
"""
- data = await BlackWord.get_black_data(user, group_id, date, data_type)
+ data = await BlackWord.get_black_data(user_id, group_id, date, data_type)
A = BuildImage(0, 0, color="#f9f6f2", font_size=20)
image_list = []
friend_str = await bot.get_friend_list()
@@ -41,21 +44,21 @@ async def show_black_text_image(
if x.group_id:
user_name = (
await bot.get_group_member_info(
- group_id=x.group_id, user_id=x.user_qq
+ group_id=int(x.group_id), user_id=int(x.user_id)
)
)["card"]
else:
user_name = [
- u["nickname"] for u in friend_str if u["user_id"] == x.user_qq
+ u["nickname"] for u in friend_str if u["user_id"] == int(x.user_id)
][0]
except Exception as e:
logger.warning(
- f"show_black_text_image 获取 USER {x.user_qq} user_name 失败 {type(e)}:{e}"
+ f"show_black_text_image 获取 USER {x.user_id} user_name 失败", e=e
)
- user_name = x.user_qq
+ user_name = x.user_id
id_str += f"{i}\n"
uname_str += f"{user_name}\n"
- uid_str += f"{x.user_qq}\n"
+ uid_str += f"{x.user_id}\n"
gid_str += f"{x.group_id}\n"
plant_text = " ".join(x.plant_text.split("\n"))
if A.getsize(plant_text)[0] > 200:
@@ -97,7 +100,7 @@ async def show_black_text_image(
return A
-async def set_user_punish(user_id: int, id_: int, punish_level: int) -> str:
+async def set_user_punish(user_id: str, id_: int, punish_level: int) -> str:
"""
设置惩罚
:param user_id: 用户id
diff --git a/plugins/black_word/model.py b/plugins/black_word/model.py
index ef746f77..d3cd3afa 100644
--- a/plugins/black_word/model.py
+++ b/plugins/black_word/model.py
@@ -7,13 +7,12 @@ from services.db_context import Model
class BlackWord(Model):
- # __tablename__ = "black_word"
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField(null=True)
+ group_id = fields.CharField(255, null=True)
"""群聊id"""
plant_text = fields.TextField()
"""检测文本"""
@@ -33,7 +32,7 @@ class BlackWord(Model):
@classmethod
async def set_user_punish(
cls,
- user_qq: int,
+ user_id: str,
punish: str,
black_word: Optional[str] = None,
id_: Optional[int] = None,
@@ -42,22 +41,22 @@ class BlackWord(Model):
说明:
设置处罚
参数:
- :param user_qq: 用户id
+ :param user_id: 用户id
:param punish: 处罚
:param black_word: 黑名单词汇
:param id_: 记录下标
"""
user = None
- if (not black_word and not id_) or not punish:
+ if (not black_word and id_ is None) or not punish:
return False
if black_word:
user = (
- await cls.filter(user_qq=user_qq, black_word=black_word)
+ await cls.filter(user_id=user_id, black_word=black_word, punish="")
.order_by("id")
.first()
)
- elif id_:
- user_list = await cls.filter(user_qq=user_qq).order_by("id").all()
+ elif id_ is not None:
+ user_list = await cls.filter(user_id=user_id).order_by("id").all()
if len(user_list) == 0 or (id_ < 0 or id_ > len(user_list)):
return False
user = user_list[id_]
@@ -69,18 +68,18 @@ class BlackWord(Model):
@classmethod
async def get_user_count(
- cls, user_qq: int, days: int = 7, punish_level: Optional[int] = None
+ cls, user_id: str, days: int = 7, punish_level: Optional[int] = None
) -> int:
"""
说明:
获取用户规定周期内的犯事次数
参数:
- :param user_qq: 用户qq
+ :param user_id: 用户id
:param days: 周期天数
:param punish_level: 惩罚等级
"""
query = cls.filter(
- user_qq=user_qq,
+ user_id=user_id,
create_time__gte=datetime.now() - timedelta(days=days),
punish_level__not_in=[-1],
)
@@ -89,17 +88,17 @@ class BlackWord(Model):
return await query.count()
@classmethod
- async def get_user_punish_level(cls, user_qq: int, days: int = 7) -> Optional[int]:
+ async def get_user_punish_level(cls, user_id: str, days: int = 7) -> Optional[int]:
"""
说明:
获取用户最近一次的惩罚记录等级
参数:
- :param user_qq: 用户qq
+ :param user_id: 用户id
:param days: 周期天数
"""
if (
user := await cls.filter(
- user_qq=user_qq,
+ user_id=user_id,
create_time__gte=datetime.now() - timedelta(days=days),
)
.order_by("id")
@@ -111,8 +110,8 @@ class BlackWord(Model):
@classmethod
async def get_black_data(
cls,
- user_qq: Optional[int],
- group_id: Optional[int],
+ user_id: Optional[str],
+ group_id: Optional[str],
date: Optional[datetime],
date_type: str = "=",
) -> List["BlackWord"]:
@@ -120,14 +119,14 @@ class BlackWord(Model):
说明:
通过指定条件查询数据
参数:
- :param user_qq: 用户qq
+ :param user_id: 用户id
:param group_id: 群号
:param date: 日期
:param date_type: 日期查询类型
"""
query = cls
- if user_qq:
- query = query.filter(user_qq=user_qq)
+ if user_id:
+ query = query.filter(user_id=user_id)
if group_id:
query = query.filter(group_id=group_id)
if date:
@@ -139,4 +138,12 @@ class BlackWord(Model):
query = query.filter(create_time__gte=date)
elif date_type == "<":
query = query.filter(create_time__lte=date)
- return await query.order_by("id").all()
+ return await query.all().order_by("id") # type: ignore
+
+ @classmethod
+ async def _run_script(cls):
+ return [
+ "ALTER TABLE black_word RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE black_word ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE black_word ALTER COLUMN group_id TYPE character varying(255);",
+ ]
diff --git a/plugins/black_word/utils.py b/plugins/black_word/utils.py
index 7bf9a56c..f1b5842d 100644
--- a/plugins/black_word/utils.py
+++ b/plugins/black_word/utils.py
@@ -83,7 +83,7 @@ class BlackWordManager:
)
async def check(
- self, user_id: int, group_id: Optional[int], message: str
+ self, user_id: str, group_id: Optional[str], message: str
) -> Optional[Union[str, bool]]:
"""
检查是否包含黑名单词汇
@@ -91,6 +91,7 @@ class BlackWordManager:
:param group_id: 群号
:param message: 消息
"""
+ logger.debug(f"检查文本是否含有黑名单词汇: {message}", "敏感词检测", user_id, group_id)
if data := self._check(message):
if data[0]:
await _add_user_black_word(
@@ -117,7 +118,7 @@ class BlackWordManager:
for x in [self._word_list, self._py_list]:
for level in x:
if message in x[level] or py_msg in x[level]:
- return message if message in x[level] else py_msg, level
+ return message if message in x[level] else py_msg, int(level)
# 模糊匹配
for x in [self._word_list, self._py_list]:
for level in x:
@@ -128,8 +129,8 @@ class BlackWordManager:
async def _add_user_black_word(
- user_id: int,
- group_id: Optional[int],
+ user_id: str,
+ group_id: Optional[str],
black_word: str,
message: str,
punish_level: int,
@@ -144,13 +145,17 @@ async def _add_user_black_word(
"""
cycle_days = Config.get_config("black_word", "CYCLE_DAYS") or 7
user_count = await BlackWord.get_user_count(user_id, cycle_days, punish_level)
+ add_punish_level_to_count = Config.get_config(
+ "black_word", "ADD_PUNISH_LEVEL_TO_COUNT"
+ )
# 周期内超过次数直接提升惩罚
- if Config.get_config(
- "black_word", "AUTO_ADD_PUNISH_LEVEL"
- ) and user_count > Config.get_config("black_word", "ADD_PUNISH_LEVEL_TO_COUNT"):
+ if (
+ Config.get_config("black_word", "AUTO_ADD_PUNISH_LEVEL")
+ and add_punish_level_to_count
+ ):
punish_level -= 1
await BlackWord.create(
- user_qq=user_id,
+ user_id=user_id,
group_id=group_id,
plant_text=message,
black_word=black_word,
@@ -165,7 +170,7 @@ async def _add_user_black_word(
async def _punish_handle(
- user_id: int, group_id: Optional[int], punish_level: int, black_word: str
+ user_id: str, group_id: Optional[str], punish_level: int, black_word: str
):
"""
惩罚措施,级别越低惩罚越严
@@ -218,7 +223,7 @@ async def _punish_handle(
async def _get_punish(
- id_: int, user_id: int, group_id: Optional[int] = None
+ id_: int, user_id: str, group_id: Optional[str] = None
) -> Optional[Union[int, str]]:
"""
通过id_获取惩罚
@@ -230,12 +235,12 @@ async def _get_punish(
# 忽略的群聊
# _ignore_group = Config.get_config("black_word", "IGNORE_GROUP")
# 处罚 id 4 ban 时间:int,List[int]
- ban_3_duration = Config.get_config("black_word", "BAN_3_DURATION")
+ ban_3_duration = Config.get_config("black_word", "BAN_3_DURATION") or 7
# 处罚 id 4 ban 时间:int,List[int]
- ban_4_duration = Config.get_config("black_word", "BAN_4_DURATION")
+ ban_4_duration = Config.get_config("black_word", "BAN_4_DURATION") or 360
# 口头警告内容
warning_result = Config.get_config("black_word", "WARNING_RESULT")
- if user := await GroupInfoUser.get_or_none(user_id=str(user_id), group_id=str(group_id)):
+ if user := await GroupInfoUser.get_or_none(user_id=user_id, group_id=group_id):
uname = user.user_name
else:
uname = user_id
@@ -285,28 +290,30 @@ async def _get_punish(
# 口头警告
elif id_ == 5:
if group_id:
- await bot.send_group_msg(group_id=group_id, message=warning_result)
+ await bot.send_group_msg(group_id=int(group_id), message=warning_result)
else:
- await bot.send_private_msg(user_id=user_id, message=warning_result)
+ await bot.send_private_msg(user_id=int(user_id), message=warning_result)
logger.info(f"BlackWord 口头警告 USER {user_id}")
return warning_result
return None
-async def send_msg(user_id: int, group_id: Optional[int], message: str):
+async def send_msg(
+ user_id: Union[str, int], group_id: Optional[Union[str, int]], message: str
+):
"""
发送消息
:param user_id: user_id
:param group_id: group_id
:param message: message
"""
- bot = get_bot()
- if not user_id:
- user_id = int(list(bot.config.superusers)[0])
- if group_id:
- await bot.send_group_msg(group_id=group_id, message=message)
- else:
- await bot.send_private_msg(user_id=user_id, message=message)
+ if bot := get_bot():
+ if not user_id:
+ user_id = list(bot.config.superusers)[0]
+ if group_id:
+ await bot.send_group_msg(group_id=int(group_id), message=message)
+ else:
+ await bot.send_private_msg(user_id=int(user_id), message=message)
async def check_text(text: str) -> bool:
diff --git a/plugins/bt/data_source.py b/plugins/bt/data_source.py
index a35382ae..1b3ba7cd 100755
--- a/plugins/bt/data_source.py
+++ b/plugins/bt/data_source.py
@@ -3,7 +3,7 @@ from bs4 import BeautifulSoup
from configs.config import Config
from utils.http_utils import AsyncHttpx
-url = "http://www.eclzz.love"
+url = "http://www.eclzz.ink"
async def get_bt_info(keyword: str, page: int):
@@ -17,7 +17,7 @@ async def get_bt_info(keyword: str, page: int):
return
soup = BeautifulSoup(text, "lxml")
item_lst = soup.find_all("div", {"class": "search-item"})
- bt_max_num = Config.get_config("bt", "BT_MAX_NUM")
+ bt_max_num = Config.get_config("bt", "BT_MAX_NUM") or 10
bt_max_num = bt_max_num if bt_max_num < len(item_lst) else len(item_lst)
for item in item_lst[:bt_max_num]:
divs = item.find_all("div")
diff --git a/plugins/genshin/query_user/_models/__init__.py b/plugins/genshin/query_user/_models/__init__.py
index 9bf3a26f..dacb029e 100644
--- a/plugins/genshin/query_user/_models/__init__.py
+++ b/plugins/genshin/query_user/_models/__init__.py
@@ -13,7 +13,7 @@ class Genshin(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
uid = fields.BigIntField()
"""uid"""
@@ -43,7 +43,7 @@ class Genshin(Model):
class Meta:
table = "genshin"
table_description = "原神数据表"
- unique_together = ("user_qq", "uid")
+ unique_together = ("user_id", "uid")
@classmethod
async def random_sign_time(cls, uid: int) -> Optional[datetime]:
@@ -103,4 +103,6 @@ class Genshin(Model):
"ALTER TABLE genshin ADD login_ticket VARCHAR(255) DEFAULT '';",
"ALTER TABLE genshin ADD stuid VARCHAR(255) DEFAULT '';",
"ALTER TABLE genshin ADD stoken VARCHAR(255) DEFAULT '';",
+ "ALTER TABLE genshin RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE genshin ALTER COLUMN user_id TYPE character varying(255);",
]
diff --git a/plugins/genshin/query_user/bind/__init__.py b/plugins/genshin/query_user/bind/__init__.py
index 9c9bbaca..86da4281 100644
--- a/plugins/genshin/query_user/bind/__init__.py
+++ b/plugins/genshin/query_user/bind/__init__.py
@@ -55,7 +55,7 @@ bbs_Cookie_url2 = (
@bind.handle()
async def _(event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
- user = await Genshin.get_or_none(user_qq=event.user_id)
+ user = await Genshin.get_or_none(user_id=str(event.user_id))
if cmd in ["原神绑定uid", "原神绑定米游社id"]:
if not is_number(msg):
await bind.finish("uid/id必须为纯数字!", at_senders=True)
@@ -63,9 +63,9 @@ async def _(event: MessageEvent, cmd: str = OneCommand(), arg: Message = Command
if cmd == "原神绑定uid":
if user:
await bind.finish(f"您已绑定过uid:{user.uid},如果希望更换uid,请先发送原神解绑")
- if await Genshin.get_or_none(user_qq=event.user_id, uid=msg):
+ if await Genshin.get_or_none(user_id=str(event.user_id), uid=msg):
await bind.finish("添加失败,该uid可能已存在...")
- user = await Genshin.create(user_qq=event.user_id, uid=msg)
+ user = await Genshin.create(user_id=str(event.user_id), uid=msg)
_x = f"已成功添加原神uid:{msg}"
elif cmd == "原神绑定米游社id":
if not user:
@@ -144,7 +144,7 @@ async def _(event: MessageEvent, cmd: str = OneCommand(), arg: Message = Command
@unbind.handle()
async def _(event: MessageEvent):
- await Genshin.filter(user_qq=event.user_id).delete()
+ await Genshin.filter(user_id=str(event.user_id)).delete()
await unbind.send("用户数据删除成功...")
logger.info(
f"(USER {event.user_id}, GROUP "
diff --git a/plugins/genshin/query_user/genshin_sign/__init__.py b/plugins/genshin/query_user/genshin_sign/__init__.py
index 79a76c31..732f0f44 100644
--- a/plugins/genshin/query_user/genshin_sign/__init__.py
+++ b/plugins/genshin/query_user/genshin_sign/__init__.py
@@ -43,7 +43,7 @@ genshin_matcher = on_command(
@genshin_matcher.handle()
async def _(event: MessageEvent, cmd: str = OneCommand()):
- user = await Genshin.get_or_none(user_qq=event.user_id)
+ user = await Genshin.get_or_none(user_id=str(event.user_id))
if not user:
await genshin_matcher.finish("请先绑定user.uid...")
if cmd == "查看我的cookie":
diff --git a/plugins/genshin/query_user/genshin_sign/init_task.py b/plugins/genshin/query_user/genshin_sign/init_task.py
index 318a0867..828727e1 100644
--- a/plugins/genshin/query_user/genshin_sign/init_task.py
+++ b/plugins/genshin/query_user/genshin_sign/init_task.py
@@ -31,11 +31,11 @@ async def _():
_sign,
"date",
run_date=date.replace(microsecond=0),
- id=f"genshin_auto_sign_{u.uid}_{u.user_qq}_0",
- args=[u.user_qq, u.uid, 0],
+ id=f"genshin_auto_sign_{u.uid}_{u.user_id}_0",
+ args=[u.user_id, u.uid, 0],
)
logger.info(
- f"genshin_sign add_job:USER:{u.user_qq} UID:{u.uid} "
+ f"genshin_sign add_job:USER:{u.user_id} UID:{u.uid} "
f"{date} 原神自动签到"
)
diff --git a/plugins/genshin/query_user/mihoyobbs_sign/__init__.py b/plugins/genshin/query_user/mihoyobbs_sign/__init__.py
index e98d67cd..5bd3267c 100644
--- a/plugins/genshin/query_user/mihoyobbs_sign/__init__.py
+++ b/plugins/genshin/query_user/mihoyobbs_sign/__init__.py
@@ -47,7 +47,7 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
async def mihoyobbs_sign(user_id):
- user = await Genshin.get_or_none(user_qq=user_id)
+ user = await Genshin.get_or_none(user_id=str(user_id))
if not user or not user.uid or not user.cookie:
await mihoyobbs_matcher.finish("请先绑定uid和cookie!", at_sender=True)
bbs = mihoyobbs.Mihoyobbs(stuid=user.stuid, stoken=user.stoken, cookie=user.cookie)
diff --git a/plugins/genshin/query_user/query_memo/__init__.py b/plugins/genshin/query_user/query_memo/__init__.py
index 5331c2bf..090c2a7f 100644
--- a/plugins/genshin/query_user/query_memo/__init__.py
+++ b/plugins/genshin/query_user/query_memo/__init__.py
@@ -35,7 +35,7 @@ query_memo_matcher = on_command(
@query_memo_matcher.handle()
async def _(event: MessageEvent):
- user = await Genshin.get_or_none(user_qq=event.user_id)
+ user = await Genshin.get_or_none(user_id=str(event.user_id))
if not user or not user.uid or not user.cookie:
await query_memo_matcher.finish("请先绑定uid和cookie!")
if isinstance(event, GroupMessageEvent):
diff --git a/plugins/genshin/query_user/query_role/__init__.py b/plugins/genshin/query_user/query_role/__init__.py
index ce39e809..c203439f 100644
--- a/plugins/genshin/query_user/query_role/__init__.py
+++ b/plugins/genshin/query_user/query_role/__init__.py
@@ -44,7 +44,7 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
await query_role_info_matcher.finish("查询uid必须为数字!")
msg = int(msg)
uid = None
- user = await Genshin.get_or_none(user_qq=event.user_id)
+ user = await Genshin.get_or_none(user_id=str(event.user_id))
if not msg and user:
uid = user.uid
else:
diff --git a/plugins/genshin/query_user/resin_remind/__init__.py b/plugins/genshin/query_user/resin_remind/__init__.py
index de4452c0..7d1400a8 100644
--- a/plugins/genshin/query_user/resin_remind/__init__.py
+++ b/plugins/genshin/query_user/resin_remind/__init__.py
@@ -52,7 +52,7 @@ resin_remind = on_command("开原神树脂提醒", aliases={"关原神树脂提
@resin_remind.handle()
async def _(event: MessageEvent, cmd: str = OneCommand()):
- user = await Genshin.get_or_none(user_qq=event.user_id)
+ user = await Genshin.get_or_none(user_id=str(event.user_id))
if not user or not user.uid or not user.cookie:
await resin_remind.finish("请先绑定uid和cookie!")
try:
diff --git a/plugins/genshin/query_user/resin_remind/init_task.py b/plugins/genshin/query_user/resin_remind/init_task.py
index a87e9a83..fefabc17 100644
--- a/plugins/genshin/query_user/resin_remind/init_task.py
+++ b/plugins/genshin/query_user/resin_remind/init_task.py
@@ -88,35 +88,27 @@ async def _():
if u.resin_recovery_time and u.resin_recovery_time > datetime.now(
pytz.timezone("Asia/Shanghai")
):
- # date = await Genshin.get_user_resin_recovery_time(u.uid) # 不能要,因为可能在这期间用户使用了树脂
- add_job(u.user_qq, u.uid)
- # scheduler.add_job(
- # _remind,
- # "date",
- # run_date=date.replace(microsecond=0),
- # id=f"genshin_resin_remind_{u.uid}_{u.user_qq}",
- # args=[u.user_qq, u.uid],
- # )
+ add_job(u.user_id, u.uid)
logger.info(
- f"genshin_resin_remind add_job:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
+ f"genshin_resin_remind add_job:USER:{u.user_id} UID:{u.uid}启动原神树脂提醒 "
)
else:
u.resin_recovery_time = None # type: ignore
update_list.append(u)
- add_job(u.user_qq, u.uid)
+ add_job(u.user_id, u.uid)
logger.info(
- f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
+ f"genshin_resin_remind add_job CHECK:USER:{u.user_id} UID:{u.uid}启动原神树脂提醒 "
)
else:
- add_job(u.user_qq, u.uid)
+ add_job(u.user_id, u.uid)
logger.info(
- f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
+ f"genshin_resin_remind add_job CHECK:USER:{u.user_id} UID:{u.uid}启动原神树脂提醒 "
)
if update_list:
await Genshin.bulk_update(update_list, ["resin_recovery_time"])
-def add_job(user_id: int, uid: int):
+def add_job(user_id: str, uid: int):
# 移除
try:
scheduler.remove_job(f"genshin_resin_remind_{uid}_{user_id}")
@@ -136,7 +128,7 @@ def add_job(user_id: int, uid: int):
async def _remind(user_id: int, uid: str):
- user = await Genshin.get_or_none(user_qq=user_id, uid=int(uid))
+ user = await Genshin.get_or_none(user_id=str(user_id), uid=int(uid))
uid = str(uid)
if uid[0] in ["1", "2"]:
server_id = "cn_gf01"
diff --git a/plugins/gold_redbag/__init__.py b/plugins/gold_redbag/__init__.py
index 8e578fcc..ef9522f0 100755
--- a/plugins/gold_redbag/__init__.py
+++ b/plugins/gold_redbag/__init__.py
@@ -1,33 +1,36 @@
-from nonebot import on_command, on_notice
-from nonebot.adapters.onebot.v11 import (
- Bot,
- ActionFailed,
- GroupMessageEvent,
- PokeNotifyEvent,
- Message
-)
-from .data_source import (
- check_gold,
- generate_send_redbag_pic,
- open_redbag,
- generate_open_redbag_pic,
- return_gold,
-)
-from nonebot.adapters.onebot.v11.permission import GROUP
-from nonebot.message import run_preprocessor, IgnoredException
-from nonebot.matcher import Matcher
-from utils.utils import is_number, scheduler
-from utils.message_builder import image
-from services.log import logger
-from configs.path_config import IMAGE_PATH
-from nonebot.permission import SUPERUSER
-from nonebot.rule import to_me
-from datetime import datetime, timedelta
-from configs.config import NICKNAME
-from apscheduler.jobstores.base import JobLookupError
-from nonebot.params import CommandArg
import random
import time
+from datetime import datetime, timedelta
+
+from apscheduler.jobstores.base import JobLookupError
+from nonebot import on_command, on_notice
+from nonebot.adapters.onebot.v11 import (
+ ActionFailed,
+ Bot,
+ GroupMessageEvent,
+ Message,
+ PokeNotifyEvent,
+)
+from nonebot.adapters.onebot.v11.permission import GROUP
+from nonebot.matcher import Matcher
+from nonebot.message import IgnoredException, run_preprocessor
+from nonebot.params import CommandArg
+from nonebot.permission import SUPERUSER
+from nonebot.rule import to_me
+
+from configs.config import NICKNAME
+from configs.path_config import IMAGE_PATH
+from services.log import logger
+from utils.message_builder import image
+from utils.utils import is_number, scheduler
+
+from .data_source import (
+ check_gold,
+ generate_open_redbag_pic,
+ generate_send_redbag_pic,
+ open_redbag,
+ return_gold,
+)
__zx_plugin_name__ = "金币红包"
__plugin_usage__ = """
@@ -72,7 +75,9 @@ gold_redbag = on_command(
"塞红包", aliases={"金币红包"}, priority=5, block=True, permission=GROUP
)
-open_ = on_command("开", aliases={"抢"}, priority=5, block=True, permission=GROUP, rule=rule)
+open_ = on_command(
+ "开", aliases={"抢"}, priority=5, block=True, permission=GROUP, rule=rule
+)
poke_ = on_notice(priority=6, block=False)
@@ -89,7 +94,10 @@ festive_redbag_data = {}
# 阻断其他poke
@run_preprocessor
-async def _(matcher: Matcher, event: PokeNotifyEvent, ):
+async def _(
+ matcher: Matcher,
+ event: PokeNotifyEvent,
+):
try:
if matcher.type == "notice" and event.self_id == event.target_id:
flag = check_on_gold_red(event)
@@ -109,10 +117,12 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
try:
if time.time() - redbag_data[event.group_id]["time"] > 60:
amount = (
- redbag_data[event.group_id]["amount"]
- - redbag_data[event.group_id]["open_amount"]
+ redbag_data[event.group_id]["amount"]
+ - redbag_data[event.group_id]["open_amount"]
+ )
+ await return_gold(
+ redbag_data[event.group_id]["user_id"], str(event.group_id), amount
)
- await return_gold(redbag_data[event.group_id]["user_id"], event.group_id, amount)
await gold_redbag.send(
f'{redbag_data[event.group_id]["nickname"]}的红包过时未开完,退还{amount}金币...'
)
@@ -128,18 +138,18 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
msg = msg.split()
if len(msg) == 1:
- flag, amount = await check_gold(event.user_id, event.group_id, msg[0])
+ flag, amount = await check_gold(str(event.user_id), str(event.group_id), msg[0])
if not flag:
- await gold_redbag.finish(amount)
+ await gold_redbag.finish(str(amount))
num = 5
else:
amount = msg[0]
num = msg[1]
if not is_number(num) or int(num) < 1:
await gold_redbag.finish("红包个数给我输正确啊!", at_sender=True)
- flag, amount = await check_gold(event.user_id, event.group_id, amount)
+ flag, amount = await check_gold(str(event.user_id), str(event.group_id), amount)
if not flag:
- await gold_redbag.finish(amount, at_sender=True)
+ await gold_redbag.finish(str(amount), at_sender=True)
group_member_num = (await bot.get_group_info(group_id=event.group_id))[
"member_count"
]
@@ -149,7 +159,12 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
num = group_member_num
nickname = event.sender.card or event.sender.nickname
flag, result = init_redbag(
- event.user_id, event.group_id, nickname, amount, num, int(bot.self_id)
+ str(event.user_id),
+ str(event.group_id),
+ nickname or str(event.user_id),
+ amount,
+ num,
+ int(bot.self_id),
)
if not flag:
await gold_redbag.finish(result, at_sender=True)
@@ -158,13 +173,11 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
f"{nickname}发起了金币红包\n金额:{amount}\n数量:{num}\n"
+ image(
b64=await generate_send_redbag_pic(
- redbag_data[event.group_id]["user_id"]
+ redbag_data[str(event.group_id)]["user_id"]
)
)
)
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id} 塞入 {num} 个红包,共 {amount} 金币"
- )
+ logger.info(f"塞入 {num} 个红包,共 {amount} 金币", "金币红包", event.user_id, event.group_id)
@open_.handle()
@@ -173,20 +186,20 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
msg = (
msg.replace("!", "")
- .replace("!", "")
- .replace(",", "")
- .replace(",", "")
- .replace(".", "")
- .replace("。", "")
+ .replace("!", "")
+ .replace(",", "")
+ .replace(",", "")
+ .replace(".", "")
+ .replace("。", "")
)
if msg:
if "红包" not in msg:
return
try:
await open_.send(
- image(b64=await get_redbag_img(event.user_id, event.group_id)),
+ image(b64=await get_redbag_img(str(event.user_id), str(event.group_id))),
at_sender=True,
- )
+ )
except KeyError:
await open_.finish("真贪心,明明已经开过这个红包了的说...", at_sender=True)
@@ -199,7 +212,7 @@ async def _poke_(event: PokeNotifyEvent):
if not flag:
return
await poke_.send(
- image(b64=await get_redbag_img(event.user_id, event.group_id)),
+ image(b64=await get_redbag_img(str(event.user_id), str(event.group_id))),
at_sender=True,
)
@@ -217,8 +230,8 @@ async def _(event: GroupMessageEvent):
at_sender=True,
)
await return_gold(
- event.user_id,
- event.group_id,
+ str(event.user_id),
+ str(event.group_id),
redbag_data[event.group_id]["amount"]
- redbag_data[event.group_id]["open_amount"],
)
@@ -272,9 +285,7 @@ async def _(bot: Bot, arg: Message = CommandArg()):
await end_festive_redbag(bot, g)
except JobLookupError:
pass
- init_redbag(
- int(bot.self_id), g, f"{NICKNAME}", amount, num, int(bot.self_id), 1
- )
+ init_redbag(bot.self_id, g, f"{NICKNAME}", amount, num, int(bot.self_id), 1)
scheduler.add_job(
end_festive_redbag,
"date",
@@ -286,7 +297,7 @@ async def _(bot: Bot, arg: Message = CommandArg()):
await bot.send_group_msg(
group_id=g,
message=f"{NICKNAME}发起了金币红包\n金额:{amount}\n数量:{num}\n"
- + image(
+ + image(
b64=await generate_send_redbag_pic(int(bot.self_id), greetings)
),
)
@@ -297,13 +308,13 @@ async def _(bot: Bot, arg: Message = CommandArg()):
# 红包数据初始化
def init_redbag(
- user_id: int,
- group_id: int,
- nickname: str,
- amount: int,
- num: int,
- bot_self_id: int,
- mode: int = 0,
+ user_id: str,
+ group_id: str,
+ nickname: str,
+ amount: int,
+ num: int,
+ bot_self_id: int,
+ mode: int = 0,
):
global redbag_data, festive_redbag_data
data = redbag_data if mode == 0 else festive_redbag_data
@@ -341,7 +352,7 @@ def random_redbag(amount: int, num: int) -> list:
# 返回开红包图片
-async def get_redbag_img(user_id: int, group_id: int):
+async def get_redbag_img(user_id: str, group_id: str):
global redbag_data, festive_redbag_data
data = redbag_data
mode = 0
@@ -389,17 +400,14 @@ def check_on_gold_red(event) -> bool:
flag1 = True
flag2 = True
try:
- if festive_redbag_data[event.group_id]["user_id"]:
- if (
- event.user_id
- in festive_redbag_data[event.group_id]["open_user"]
- ):
+ if festive_redbag_data[str(event.group_id)]["user_id"]:
+ if event.user_id in festive_redbag_data[str(event.group_id)]["open_user"]:
flag1 = False
except KeyError:
flag1 = False
try:
- if redbag_data[event.group_id]["user_id"]:
- if event.user_id in redbag_data[event.group_id]["open_user"]:
+ if redbag_data[str(event.group_id)]["user_id"]:
+ if event.user_id in redbag_data[str(event.group_id)]["open_user"]:
flag2 = False
except KeyError:
flag2 = False
diff --git a/plugins/gold_redbag/data_source.py b/plugins/gold_redbag/data_source.py
index 5e91e90b..1eb8de59 100755
--- a/plugins/gold_redbag/data_source.py
+++ b/plugins/gold_redbag/data_source.py
@@ -1,87 +1,108 @@
-from models.bag_user import BagUser
-from utils.utils import is_number, get_user_avatar
-from utils.image_utils import BuildImage
-from configs.path_config import IMAGE_PATH
-from .model import RedbagUser
-import random
-import os
-from io import BytesIO
import asyncio
+import os
+import random
+from io import BytesIO
+from typing import Union
+
+from configs.path_config import IMAGE_PATH
+from models.bag_user import BagUser
+from utils.image_utils import BuildImage
+from utils.utils import get_user_avatar, is_number
+
+from .model import RedbagUser
# 检查金币数量合法性,并添加记录数据
-async def check_gold(user_id: int, group_id: int, amount: str):
+async def check_gold(user_id: str, group_id: str, amount: Union[str, int]):
if is_number(amount):
amount = int(amount)
user_gold = await BagUser.get_gold(user_id, group_id)
if amount < 1:
- return False, '小气鬼,要别人倒贴金币给你嘛!'
+ return False, "小气鬼,要别人倒贴金币给你嘛!"
if user_gold < amount:
- return False, '没有金币的话请不要发红包...'
+ return False, "没有金币的话请不要发红包..."
await BagUser.spend_gold(user_id, group_id, amount)
- await RedbagUser.add_redbag_data(user_id, group_id, 'send', amount)
+ await RedbagUser.add_redbag_data(user_id, group_id, "send", amount)
return True, amount
else:
- return False, '给我好好的输入红包里金币的数量啊喂!'
+ return False, "给我好好的输入红包里金币的数量啊喂!"
# 金币退回
-async def return_gold(user_id: int, group_id: int, amount: int):
+async def return_gold(user_id: str, group_id: str, amount: int):
await BagUser.add_gold(user_id, group_id, amount)
# 开红包
-async def open_redbag(user_id: int, group_id: int, redbag_data: dict):
- amount = random.choice(redbag_data[group_id]['redbag'])
- redbag_data[group_id]['redbag'].remove(amount)
- redbag_data[group_id]['open_user'].append(user_id)
- redbag_data[group_id]['open_amount'] += amount
- await RedbagUser.add_redbag_data(user_id, group_id, 'get', amount)
+async def open_redbag(user_id: str, group_id: str, redbag_data: dict):
+ amount = random.choice(redbag_data[group_id]["redbag"])
+ redbag_data[group_id]["redbag"].remove(amount)
+ redbag_data[group_id]["open_user"].append(user_id)
+ redbag_data[group_id]["open_amount"] += amount
+ await RedbagUser.add_redbag_data(user_id, group_id, "get", amount)
await BagUser.add_gold(user_id, group_id, amount)
return amount, redbag_data
# 随机红包图片
-async def generate_send_redbag_pic(user_id: int, msg: str = '恭喜发财 大吉大利'):
+async def generate_send_redbag_pic(user_id: int, msg: str = "恭喜发财 大吉大利"):
random_redbag = random.choice(os.listdir(f"{IMAGE_PATH}/prts/redbag_2"))
- redbag = BuildImage(0, 0, font_size=38, background=f'{IMAGE_PATH}/prts/redbag_2/{random_redbag}')
+ redbag = BuildImage(
+ 0, 0, font_size=38, background=f"{IMAGE_PATH}/prts/redbag_2/{random_redbag}"
+ )
ava = BuildImage(65, 65, background=BytesIO(await get_user_avatar(user_id)))
await asyncio.get_event_loop().run_in_executor(None, ava.circle)
- redbag.text((int((redbag.size[0] - redbag.getsize(msg)[0]) / 2), 210), msg, (240, 218, 164))
- redbag.paste(ava, (int((redbag.size[0] - ava.size[0])/2), 130), True)
+ redbag.text(
+ (int((redbag.size[0] - redbag.getsize(msg)[0]) / 2), 210), msg, (240, 218, 164)
+ )
+ redbag.paste(ava, (int((redbag.size[0] - ava.size[0]) / 2), 130), True)
return redbag.pic2bs4()
# 开红包图片
-async def generate_open_redbag_pic(user_id: int, send_user_nickname: str, amount: int, text: str):
- return await asyncio.create_task(_generate_open_redbag_pic(user_id, send_user_nickname, amount, text))
+async def generate_open_redbag_pic(
+ user_id: str, send_user_nickname: str, amount: int, text: str
+):
+ return await asyncio.create_task(
+ _generate_open_redbag_pic(user_id, send_user_nickname, amount, text)
+ )
# 开红包图片
-async def _generate_open_redbag_pic(user_id: int, send_user_nickname: str, amount: int, text: str):
- send_user_nickname += '的红包'
- amount = str(amount)
+async def _generate_open_redbag_pic(
+ user_id: str, send_user_nickname: str, amount: int, text: str
+):
+ send_user_nickname += "的红包"
+ amount_str = str(amount)
random_redbag = random.choice(os.listdir(f"{IMAGE_PATH}/prts/redbag_1"))
- head = BuildImage(1000, 980, font_size=30, background=f'{IMAGE_PATH}/prts/redbag_1/{random_redbag}')
+ head = BuildImage(
+ 1000,
+ 980,
+ font_size=30,
+ background=f"{IMAGE_PATH}/prts/redbag_1/{random_redbag}",
+ )
size = BuildImage(0, 0, font_size=50).getsize(send_user_nickname)
# QQ头像
ava_bk = BuildImage(100 + size[0], 66, is_alpha=True, font_size=50)
- ava = BuildImage(66, 66, is_alpha=True, background=BytesIO(await get_user_avatar(user_id)))
+ ava = BuildImage(
+ 66, 66, is_alpha=True, background=BytesIO(await get_user_avatar(user_id))
+ )
ava_bk.paste(ava)
ava_bk.text((100, 7), send_user_nickname)
# ava_bk.show()
ava_bk_w, ava_bk_h = ava_bk.size
head.paste(ava_bk, (int((1000 - ava_bk_w) / 2), 300), alpha=True)
# 金额
- size = BuildImage(0, 0, font_size=150).getsize(amount)
+ size = BuildImage(0, 0, font_size=150).getsize(amount_str)
price = BuildImage(size[0], size[1], is_alpha=True, font_size=150)
- price.text((0, 0), amount, fill=(209, 171, 108))
+ price.text((0, 0), amount_str, fill=(209, 171, 108))
# 金币中文
head.paste(price, (int((1000 - size[0]) / 2) - 50, 460), alpha=True)
- head.text((int((1000 - size[0]) / 2 + size[0]) - 50, 500 + size[1] - 70), '金币', fill=(209, 171, 108))
+ head.text(
+ (int((1000 - size[0]) / 2 + size[0]) - 50, 500 + size[1] - 70),
+ "金币",
+ fill=(209, 171, 108),
+ )
# 剩余数量和金额
head.text((350, 900), text, (198, 198, 198))
return head.pic2bs4()
-
-
-
diff --git a/plugins/gold_redbag/model.py b/plugins/gold_redbag/model.py
index 9516a4bd..76755b0d 100755
--- a/plugins/gold_redbag/model.py
+++ b/plugins/gold_redbag/model.py
@@ -9,9 +9,9 @@ class RedbagUser(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField()
+ group_id = fields.CharField(255)
"""群聊id"""
send_redbag_count = fields.IntField(default=0)
"""发送红包次数"""
@@ -25,23 +25,23 @@ class RedbagUser(Model):
class Meta:
table = "redbag_users"
table_description = "红包统计数据表"
- unique_together = ("user_qq", "group_id")
+ unique_together = ("user_id", "group_id")
@classmethod
async def add_redbag_data(
- cls, user_qq: int, group_id: int, i_type: str, money: int
+ cls, user_id: str, group_id: str, i_type: str, money: int
):
"""
说明:
添加收发红包数据
参数:
- :param user_qq: qq号
+ :param user_id: 用户id
:param group_id: 群号
:param i_type: 收或发
:param money: 金钱数量
"""
- user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ user, _ = await cls.get_or_create(user_id=user_id, group_id=group_id)
if i_type == "get":
user.get_redbag_count = user.get_redbag_count + 1
user.get_gold = user.get_gold + money
@@ -56,3 +56,11 @@ class RedbagUser(Model):
"spend_gold",
]
)
+
+ @classmethod
+ async def _run_script(cls):
+ return [
+ "ALTER TABLE redbag_users RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE redbag_users ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE redbag_users ALTER COLUMN group_id TYPE character varying(255);",
+ ]
diff --git a/plugins/my_info/__init__.py b/plugins/my_info/__init__.py
index 9e3d73c8..94ea437b 100644
--- a/plugins/my_info/__init__.py
+++ b/plugins/my_info/__init__.py
@@ -27,12 +27,12 @@ my_level = on_command("我的权限", permission=GROUP, priority=5, block=True)
@get_my_group_info.handle()
async def _(event: GroupMessageEvent):
- result = await get_member_info(event.user_id, event.group_id)
+ result = await get_member_info(str(event.user_id), str(event.group_id))
await get_my_group_info.finish(result)
-async def get_member_info(user_qq: int, group_id: int) -> str:
- if user := await GroupInfoUser.get_or_none(user_id=str(user_qq), group_id=str(group_id)):
+async def get_member_info(user_id: str, group_id: str) -> str:
+ if user := await GroupInfoUser.get_or_none(user_id=user_id, group_id=group_id):
result = ""
result += "昵称:" + user.user_name + "\n"
result += "加群时间:" + str(user.user_join_time.date())
diff --git a/plugins/open_cases/__init__.py b/plugins/open_cases/__init__.py
index 34539ea6..d2e61014 100755
--- a/plugins/open_cases/__init__.py
+++ b/plugins/open_cases/__init__.py
@@ -33,6 +33,7 @@ from .utils import (
CaseManager,
build_case_image,
get_skin_case,
+ init_skin_trends,
reset_count_daily,
update_skin_data,
)
@@ -135,6 +136,31 @@ update_case = on_command(
show_case = on_command("查看武器箱", priority=5, block=True)
my_knifes = on_command("我的金色", priority=1, permission=GROUP, block=True)
show_skin = on_command("查看皮肤", priority=5, block=True)
+price_trends = on_command("价格趋势", priority=5, block=True)
+
+
+@price_trends.handle()
+async def _(event: MessageEvent, arg: Message = CommandArg()):
+ msg = arg.extract_plain_text().replace("武器箱", "").strip()
+ if not msg:
+ await price_trends.finish("未指定皮肤")
+ msg_split = msg.split()
+ if len(msg_split) < 3:
+ await price_trends.finish("参数不足, [类型名称] [皮肤名称] [磨损程度] ?[天数=7]")
+ abrasion = msg_split[2]
+ day = 7
+ if len(msg_split) > 3:
+ if not is_number(msg_split[3]):
+ await price_trends.finish("天数必须为数字")
+ day = int(msg_split[3])
+ if day <= 0 or day > 180:
+ await price_trends.finish("天数必须大于0且小于180")
+ result = await init_skin_trends(msg_split[0], msg_split[1], msg_split[2], day)
+ if not result:
+ await price_trends.finish("未查询到数据")
+ await price_trends.send(
+ image(await init_skin_trends(msg_split[0], msg_split[1], msg_split[2], day))
+ )
@reload_count.handle()
diff --git a/plugins/open_cases/models/open_cases_log.py b/plugins/open_cases/models/open_cases_log.py
index 68b27cf0..ebcaf5bc 100644
--- a/plugins/open_cases/models/open_cases_log.py
+++ b/plugins/open_cases/models/open_cases_log.py
@@ -10,9 +10,9 @@ class OpenCasesLog(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField()
+ group_id = fields.CharField(255)
"""群聊id"""
case_name = fields.CharField(255)
"""箱子名称"""
@@ -36,3 +36,11 @@ class OpenCasesLog(Model):
class Meta:
table = "open_cases_log"
table_description = "开箱日志表"
+
+ @classmethod
+ async def _run_script(cls):
+ return [
+ "ALTER TABLE open_cases_log RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE open_cases_log ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE open_cases_log ALTER COLUMN group_id TYPE character varying(255);",
+ ]
diff --git a/plugins/open_cases/models/open_cases_user.py b/plugins/open_cases/models/open_cases_user.py
index e2de05c1..6f3482a1 100755
--- a/plugins/open_cases/models/open_cases_user.py
+++ b/plugins/open_cases/models/open_cases_user.py
@@ -7,9 +7,9 @@ class OpenCasesUser(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField()
+ group_id = fields.CharField(255)
"""群聊id"""
total_count: int = fields.IntField(default=0)
"""总开启次数"""
@@ -47,11 +47,14 @@ class OpenCasesUser(Model):
class Meta:
table = "open_cases_users"
table_description = "开箱统计数据表"
- unique_together = ("user_qq", "group_id")
+ unique_together = ("user_id", "group_id")
@classmethod
async def _run_script(cls):
return [
"alter table open_cases_users alter COLUMN make_money type float;", # 将make_money字段改为float
"alter table open_cases_users alter COLUMN spend_money type float;", # 将spend_money字段改为float
+ "ALTER TABLE open_cases_users RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE open_cases_users ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE open_cases_users ALTER COLUMN group_id TYPE character varying(255);",
]
diff --git a/plugins/open_cases/open_cases_c.py b/plugins/open_cases/open_cases_c.py
index b3bba8fe..be2d9596 100755
--- a/plugins/open_cases/open_cases_c.py
+++ b/plugins/open_cases/open_cases_c.py
@@ -63,17 +63,19 @@ def add_count(user: OpenCasesUser, skin: BuffSkin, case_price: float):
user.spend_money += 17 + case_price
-async def get_user_max_count(user_qq: int, group_id: int) -> int:
+async def get_user_max_count(user_id: str, group_id: int) -> int:
"""获取用户每日最大开箱次数
Args:
- user_qq (int): 用户id
+ user_id (str): 用户id
group_id (int): 群号
Returns:
int: 最大开箱次数
"""
- user, _ = await SignGroupUser.get_or_create(user_id=str(user_qq), group_id=str(group_id))
+ user, _ = await SignGroupUser.get_or_create(
+ user_id=str(user_id), group_id=str(group_id)
+ )
impression = int(user.impression)
initial_open_case_count = Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
each_impression_add_count = Config.get_config(
@@ -82,11 +84,11 @@ async def get_user_max_count(user_qq: int, group_id: int) -> int:
return int(initial_open_case_count + impression / each_impression_add_count) # type: ignore
-async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, Message]:
+async def open_case(user_id: str, group_id: int, case_name: str) -> Union[str, Message]:
"""开箱
Args:
- user_qq (int): 用户id
+ user_id (str): 用户id
group_id (int): 群号
case_name (str, optional): 武器箱名称. Defaults to "狂牙大行动".
@@ -99,14 +101,14 @@ async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, M
case_name = random.choice(CaseManager.CURRENT_CASES) # type: ignore
if case_name not in CaseManager.CURRENT_CASES:
return "武器箱未收录, 当前可用武器箱:\n" + ", ".join(CaseManager.CURRENT_CASES) # type: ignore
- logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_qq, group_id)
+ logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_id, group_id)
case = cn2py(case_name)
- user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group_id)
+ user = await OpenCasesUser.get_or_none(user_id=user_id, group_id=group_id)
if not user:
user = await OpenCasesUser.create(
- user_qq=user_qq, group_id=group_id, open_cases_time_last=datetime.now()
+ user_id=user_id, group_id=group_id, open_cases_time_last=datetime.now()
)
- max_count = await get_user_max_count(user_qq, group_id)
+ max_count = await get_user_max_count(user_id, group_id)
# 一天次数上限
if user.today_open_total >= max_count:
return _handle_is_MAX_COUNT()
@@ -129,12 +131,12 @@ async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, M
logger.info(
f"开启{case_name}武器箱获得 {skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand}] 价格: {skin.sell_min_price}",
"开箱",
- user_qq,
+ user_id,
group_id,
)
await user.save()
await OpenCasesLog.create(
- user_qq=user_qq,
+ user_id=user_id,
group_id=group_id,
case_name=case_name,
name=skin.name,
@@ -146,7 +148,7 @@ async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, M
abrasion_value=rand,
create_time=datetime.now(),
)
- logger.debug(f"添加 1 条开箱日志", "开箱", user_qq, group_id)
+ logger.debug(f"添加 1 条开箱日志", "开箱", user_id, group_id)
over_count = max_count - user.today_open_total
img = await draw_card(skin, rand)
return (
@@ -157,12 +159,12 @@ async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, M
async def open_multiple_case(
- user_qq: int, group_id: int, case_name: str, num: int = 10
+ user_id: str, group_id: int, case_name: str, num: int = 10
):
"""多连开箱
Args:
- user_qq (int): 用户id
+ user_id (int): 用户id
group_id (int): 群号
case_name (str): 箱子名称
num (int, optional): 数量. Defaults to 10.
@@ -177,11 +179,11 @@ async def open_multiple_case(
if case_name not in CaseManager.CURRENT_CASES:
return "武器箱未收录, 当前可用武器箱:\n" + ", ".join(CaseManager.CURRENT_CASES) # type: ignore
user, _ = await OpenCasesUser.get_or_create(
- user_qq=user_qq,
+ user_id=user_id,
group_id=group_id,
defaults={"open_cases_time_last": datetime.now()},
)
- max_count = await get_user_max_count(user_qq, group_id)
+ max_count = await get_user_max_count(user_id, group_id)
if user.today_open_total >= max_count:
return _handle_is_MAX_COUNT()
if max_count - user.today_open_total < num:
@@ -189,7 +191,7 @@ async def open_multiple_case(
f"今天开箱次数不足{num}次噢,请单抽试试看(也许单抽运气更好?)"
f"\n剩余开箱次数:{max_count - user.today_open_total}"
)
- logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_qq, group_id)
+ logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_id, group_id)
case = cn2py(case_name)
skin_count = {}
img_list = []
@@ -219,12 +221,12 @@ async def open_multiple_case(
logger.info(
f"开启{case_name}武器箱获得 {skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand:.11f}] 价格: {skin.sell_min_price}",
"开箱",
- user_qq,
+ user_id,
group_id,
)
log_list.append(
OpenCasesLog(
- user_qq=user_qq,
+ user_id=user_id,
group_id=group_id,
case_name=case_name,
name=skin.name,
@@ -240,7 +242,7 @@ async def open_multiple_case(
await user.save()
if log_list:
await OpenCasesLog.bulk_create(log_list, 10)
- logger.debug(f"添加 {len(log_list)} 条开箱日志", "开箱", user_qq, group_id)
+ logger.debug(f"添加 {len(log_list)} 条开箱日志", "开箱", user_id, group_id)
img_w += 10
img_h += 10
w = img_w * 5
@@ -273,8 +275,8 @@ def _handle_is_MAX_COUNT() -> str:
return f"今天已达开箱上限了喔,明天再来吧\n(提升好感度可以增加每日开箱数 #疯狂暗示)"
-async def total_open_statistics(user_qq: int, group: int) -> str:
- user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
+async def total_open_statistics(user_id: str, group: str) -> str:
+ user, _ = await OpenCasesUser.get_or_create(user_id=user_id, group_id=group)
return (
f"开箱总数:{user.total_count}\n"
f"今日开箱:{user.today_open_total}\n"
@@ -294,7 +296,7 @@ async def total_open_statistics(user_qq: int, group: int) -> str:
)
-async def group_statistics(group: int):
+async def group_statistics(group: str):
user_list = await OpenCasesUser.filter(group_id=group).all()
# lan zi fen hong jin pricei
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0]
@@ -330,19 +332,19 @@ async def group_statistics(group: int):
)
-async def get_my_knifes(user_id: int, group_id: int) -> Union[str, MessageSegment]:
+async def get_my_knifes(user_id: str, group_id: str) -> Union[str, MessageSegment]:
"""获取我的金色
Args:
- user_id (int): 用户id
- group_id (int): 群号
+ user_id (str): 用户id
+ group_id (str): 群号
Returns:
Union[str, MessageSegment]: 回复消息或图片
"""
data_list = await get_old_knife(user_id, group_id)
data_list += await OpenCasesLog.filter(
- user_qq=user_id, group_id=group_id, color="KNIFE"
+ user_id=user_id, group_id=group_id, color="KNIFE"
).all()
if not data_list:
return "您木有开出金色级别的皮肤喔"
@@ -377,17 +379,17 @@ async def get_my_knifes(user_id: int, group_id: int) -> Union[str, MessageSegmen
return image(A)
-async def get_old_knife(user_id: int, group_id: int) -> List[OpenCasesLog]:
+async def get_old_knife(user_id: str, group_id: str) -> List[OpenCasesLog]:
"""获取旧数据字段
Args:
- user_id (int): 用户id
- group_id (int): 群号
+ user_id (str): 用户id
+ group_id (str): 群号
Returns:
List[OpenCasesLog]: 旧数据兼容
"""
- user, _ = await OpenCasesUser.get_or_create(user_qq=user_id, group_id=group_id)
+ user, _ = await OpenCasesUser.get_or_create(user_id=user_id, group_id=group_id)
knifes_name = user.knifes_name
data_list = []
if knifes_name:
@@ -406,7 +408,7 @@ async def get_old_knife(user_id: int, group_id: int) -> List[OpenCasesLog]:
name = name.replace("(StatTrak™)", "")
data_list.append(
OpenCasesLog(
- user_qq=user_id,
+ user_id=user_id,
group_id=group_id,
name=name.strip(),
case_name=case_name_py.strip(),
diff --git a/plugins/open_cases/utils.py b/plugins/open_cases/utils.py
index c91607f3..f90651c6 100755
--- a/plugins/open_cases/utils.py
+++ b/plugins/open_cases/utils.py
@@ -3,7 +3,7 @@ import os
import random
import re
import time
-from datetime import datetime
+from datetime import datetime, timedelta
from typing import List, Optional, Tuple, Union
import nonebot
@@ -13,7 +13,7 @@ from configs.config import Config
from configs.path_config import IMAGE_PATH
from services.log import logger
from utils.http_utils import AsyncHttpx
-from utils.image_utils import BuildImage
+from utils.image_utils import BuildImage, BuildMat
from utils.utils import broadcast_group, cn2py
from .build_image import generate_skin
@@ -547,6 +547,49 @@ async def get_skin_case(id_: str) -> Optional[List[str]]:
return None
+async def init_skin_trends(
+ name: str, skin: str, abrasion: str, day: int = 7
+) -> Optional[BuildMat]:
+ date = datetime.now() - timedelta(days=day)
+ log_list = (
+ await BuffSkinLog.filter(
+ name__contains=name.upper(),
+ skin_name=skin,
+ abrasion__contains=abrasion,
+ create_time__gt=date,
+ is_stattrak=False,
+ )
+ .order_by("create_time")
+ .limit(day * 5)
+ .all()
+ )
+ if not log_list:
+ return None
+ date_list = []
+ price_list = []
+ for log in log_list:
+ date = str(log.create_time.date())
+ if date not in date_list:
+ date_list.append(date)
+ price_list.append(log.sell_min_price)
+ bar_graph = BuildMat(
+ y=price_list,
+ mat_type="line",
+ title=f"{name}({skin})价格趋势({day})",
+ x_index=date_list,
+ x_min_spacing=90,
+ display_num=True,
+ x_rotate=30,
+ background=[
+ f"{IMAGE_PATH}/background/create_mat/{x}"
+ for x in os.listdir(f"{IMAGE_PATH}/background/create_mat")
+ ],
+ bar_color=["*"],
+ )
+ await asyncio.get_event_loop().run_in_executor(None, bar_graph.gen_graph)
+ return bar_graph
+
+
async def reset_count_daily():
"""
重置每日开箱
diff --git a/plugins/pix_gallery/_model/pixiv_keyword_user.py b/plugins/pix_gallery/_model/pixiv_keyword_user.py
index 4e7797c0..829a1040 100644
--- a/plugins/pix_gallery/_model/pixiv_keyword_user.py
+++ b/plugins/pix_gallery/_model/pixiv_keyword_user.py
@@ -6,14 +6,12 @@ from services.db_context import Model
class PixivKeywordUser(Model):
- __tablename__ = "pixiv_keyword_users"
- __table_args__ = {"extend_existing": True}
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField()
+ group_id = fields.CharField(255)
"""群聊id"""
keyword = fields.CharField(255, unique=True)
"""关键词"""
@@ -46,9 +44,17 @@ class PixivKeywordUser(Model):
获取黑名单PID
"""
black_pid = []
- keyword_list = await cls.filter(user_qq=114514).values_list(
+ keyword_list = await cls.filter(user_id="114514").values_list(
"keyword", flat=True
)
for image in keyword_list:
black_pid.append(image[6:])
return black_pid
+
+ @classmethod
+ async def _run_script(cls):
+ return [
+ "ALTER TABLE pixiv_keyword_users RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE pixiv_keyword_users ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE pixiv_keyword_users ALTER COLUMN group_id TYPE character varying(255);",
+ ]
diff --git a/plugins/pix_gallery/pix_add_keyword.py b/plugins/pix_gallery/pix_add_keyword.py
index 9ac1bdf1..0377f78d 100755
--- a/plugins/pix_gallery/pix_add_keyword.py
+++ b/plugins/pix_gallery/pix_add_keyword.py
@@ -54,8 +54,8 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
# ):
if not await PixivKeywordUser.exists(keyword=msg):
await PixivKeywordUser.create(
- user_qq=event.user_id,
- group_id=group_id,
+ user_id=str(event.user_id),
+ group_id=str(group_id),
keyword=msg,
is_pass=str(event.user_id) in bot.config.superusers,
)
@@ -104,8 +104,8 @@ async def _(
# ):
if not await PixivKeywordUser.exists(keyword=msg):
await PixivKeywordUser.create(
- user_qq=event.user_id,
- group_id=group_id,
+ user_id=str(event.user_id),
+ group_id=str(group_id),
keyword=msg,
is_pass=str(event.user_id) in bot.config.superusers,
)
@@ -138,7 +138,7 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}"
):
await PixivKeywordUser.create(
- user_qq=114514,
+ user_id=114514,
group_id=114514,
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}",
is_pass=str(event.user_id) in bot.config.superusers,
diff --git a/plugins/pix_gallery/pix_pass_del_keyword.py b/plugins/pix_gallery/pix_pass_del_keyword.py
index 293bb80b..37045d80 100755
--- a/plugins/pix_gallery/pix_pass_del_keyword.py
+++ b/plugins/pix_gallery/pix_pass_del_keyword.py
@@ -110,8 +110,8 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}"
):
await PixivKeywordUser.create(
- user_qq=114514,
- group_id=114514,
+ user_id="114514",
+ group_id="114514",
keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}",
is_pass=False,
)
@@ -168,7 +168,7 @@ async def _(
if data:
data.is_pass = flag
await data.save(update_fields=["is_pass"])
- user_id, group_id = data.user_qq, data.group_id
+ user_id, group_id = data.user_id, data.group_id
if not user_id:
await pass_keyword.send(f"未找到关键词/UID:{x},请检查关键词/UID是否存在...")
continue
diff --git a/plugins/pix_gallery/pix_show_info.py b/plugins/pix_gallery/pix_show_info.py
index dcfbef4b..2b8aaab9 100755
--- a/plugins/pix_gallery/pix_show_info.py
+++ b/plugins/pix_gallery/pix_show_info.py
@@ -37,7 +37,7 @@ show_pix = on_command("查看pix图库", priority=1, block=True)
@my_keyword.handle()
async def _(event: MessageEvent):
- data = await PixivKeywordUser.filter(user_qq=event.user_id).values_list(
+ data = await PixivKeywordUser.filter(user_id=str(event.user_id)).values_list(
"keyword", flat=True
)
if not data:
diff --git a/plugins/russian/__init__.py b/plugins/russian/__init__.py
index d5c1a3d1..e4c16c41 100755
--- a/plugins/russian/__init__.py
+++ b/plugins/russian/__init__.py
@@ -14,6 +14,7 @@ from models.group_member_info import GroupInfoUser
from services.log import logger
from utils.message_builder import at, image
from utils.utils import get_message_at, is_number
+
from .data_source import rank
from .model import RussianUser
@@ -445,10 +446,10 @@ async def end_game(bot: Bot, event: GroupMessageEvent):
await BagUser.add_gold(win_user_id, event.group_id, money - fee)
await BagUser.spend_gold(lose_user_id, event.group_id, money)
win_user, _ = await RussianUser.get_or_create(
- user_qq=win_user_id, group_id=event.group_id
+ user_id=str(win_user_id), group_id=str(event.group_id)
)
lose_user, _ = await RussianUser.get_or_create(
- user_qq=lose_user_id, group_id=event.group_id
+ user_id=str(lose_user_id), group_id=str(event.group_id)
)
bullet_str = ""
for x in rs_player[event.group_id]["bullet"]:
@@ -476,7 +477,7 @@ async def end_game(bot: Bot, event: GroupMessageEvent):
@record.handle()
async def _(event: GroupMessageEvent):
user, _ = await RussianUser.get_or_create(
- user_qq=event.user_id, group_id=event.group_id
+ user_id=str(event.user_id), group_id=str(event.group_id)
)
await record.send(
f"俄罗斯轮盘\n"
diff --git a/plugins/russian/data_source.py b/plugins/russian/data_source.py
index e5ae6e7d..2f9546e0 100755
--- a/plugins/russian/data_source.py
+++ b/plugins/russian/data_source.py
@@ -8,7 +8,7 @@ from .model import RussianUser
async def rank(group_id: int, itype: str, num: int) -> Optional[BuildMat]:
all_users = await RussianUser.filter(group_id=group_id).all()
- all_user_id = [user.user_qq for user in all_users]
+ all_user_id = [user.user_id for user in all_users]
if itype == "win_rank":
rank_name = "胜场排行榜"
all_user_data = [user.win_count for user in all_users]
diff --git a/plugins/russian/model.py b/plugins/russian/model.py
index 62a4a08c..4875f185 100755
--- a/plugins/russian/model.py
+++ b/plugins/russian/model.py
@@ -1,4 +1,3 @@
-
from tortoise import fields
from services.db_context import Model
@@ -8,9 +7,9 @@ class RussianUser(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField()
+ group_id = fields.CharField(255)
"""群聊id"""
win_count = fields.IntField(default=0)
"""胜利次数"""
@@ -32,19 +31,19 @@ class RussianUser(Model):
class Meta:
table = "russian_users"
table_description = "俄罗斯轮盘数据表"
- unique_together = ("user_qq", "group_id")
+ unique_together = ("user_id", "group_id")
@classmethod
- async def add_count(cls, user_qq: int, group_id: int, itype: str):
+ async def add_count(cls, user_id: str, group_id: str, itype: str):
"""
说明:
添加用户输赢次数
说明:
- :param user_qq: qq号
+ :param user_id: qq号
:param group_id: 群号
:param itype: 输或赢 'win' or 'lose'
"""
- user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ user, _ = await cls.get_or_create(user_id=user_id, group_id=group_id)
if itype == "win":
_max = (
user.max_winning_streak
@@ -83,19 +82,27 @@ class RussianUser(Model):
)
@classmethod
- async def money(cls, user_qq: int, group_id: int, itype: str, count: int) -> bool:
+ async def money(cls, user_id: str, group_id: str, itype: str, count: int) -> bool:
"""
说明:
添加用户输赢金钱
参数:
- :param user_qq: qq号
+ :param user_id: qq号
:param group_id: 群号
:param itype: 输或赢 'win' or 'lose'
:param count: 金钱数量
"""
- user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ user, _ = await cls.get_or_create(user_id=str(user_id), group_id=group_id)
if itype == "win":
user.make_money = user.make_money + count
elif itype == "lose":
user.lose_money = user.lose_money + count
await user.save(update_fields=["make_money", "lose_money"])
+
+ @classmethod
+ async def _run_script(cls):
+ return [
+ "ALTER TABLE russian_users RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE russian_users ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE russian_users ALTER COLUMN group_id TYPE character varying(255);",
+ ]
diff --git a/plugins/sign_in/group_user_checkin.py b/plugins/sign_in/group_user_checkin.py
index 95ade971..ce5f9721 100755
--- a/plugins/sign_in/group_user_checkin.py
+++ b/plugins/sign_in/group_user_checkin.py
@@ -23,46 +23,48 @@ from .utils import SIGN_TODAY_CARD_PATH, get_card
async def group_user_check_in(
- nickname: str, user_qq: int, group: int
+ nickname: str, user_id: int, group: int
) -> MessageSegment:
"Returns string describing the result of checking in"
present = datetime.now()
# 取得相应用户
- user, is_create = await SignGroupUser.get_or_create(user_id=str(user_qq), group_id=str(group))
+ user, is_create = await SignGroupUser.get_or_create(
+ user_id=str(user_id), group_id=str(group)
+ )
# 如果同一天签到过,特殊处理
if not is_create and (
user.checkin_time_last.date() >= present.date()
or f"{user}_{group}_sign_{datetime.now().date()}"
in os.listdir(SIGN_TODAY_CARD_PATH)
):
- gold = await BagUser.get_gold(user_qq, group)
+ gold = await BagUser.get_gold(user_id, group)
return await get_card(user, nickname, -1, gold, "")
- return await _handle_check_in(nickname, user_qq, group, present) # ok
+ return await _handle_check_in(nickname, user_id, group, present) # ok
-async def check_in_all(nickname: str, user_qq: int):
+async def check_in_all(nickname: str, user_id: str):
"""
说明:
签到所有群
参数:
:param nickname: 昵称
- :param user_qq: 用户qq
+ :param user_id: 用户id
"""
present = datetime.now()
- for u in await SignGroupUser.filter(user_id=str(user_qq)).all():
+ for u in await SignGroupUser.filter(user_id=user_id).all():
group = u.group_id
if not (
u.checkin_time_last.date() >= present.date()
or f"{u}_{group}_sign_{datetime.now().date()}"
in os.listdir(SIGN_TODAY_CARD_PATH)
):
- await _handle_check_in(nickname, user_qq, group, present)
+ await _handle_check_in(nickname, user_id, group, present)
async def _handle_check_in(
- nickname: str, user_qq: int, group: int, present: datetime
+ nickname: str, user_id: str, group: str, present: datetime
) -> MessageSegment:
- user, _ = await SignGroupUser.get_or_create(user_id=str(user_qq), group_id=str(group))
+ user, _ = await SignGroupUser.get_or_create(user_id=user_id, group_id=group)
impression_added = (secrets.randbelow(99) + 1) / 100
critx2 = random.random()
add_probability = float(user.add_probability)
@@ -75,11 +77,11 @@ async def _handle_check_in(
gold = random.randint(1, 100)
gift, gift_type = random_event(float(user.impression))
if gift_type == "gold":
- await BagUser.add_gold(user_qq, group, gold + gift)
+ await BagUser.add_gold(user_id, group, gold + gift)
gift = f"额外金币 + {gift}"
else:
- await BagUser.add_gold(user_qq, group, gold)
- await BagUser.add_property(user_qq, group, gift)
+ await BagUser.add_gold(user_id, group, gold)
+ await BagUser.add_property(user_id, group, gift)
gift += " + 1"
logger.info(
@@ -93,10 +95,12 @@ async def _handle_check_in(
return await get_card(user, nickname, impression_added, gold, gift)
-async def group_user_check(nickname: str, user_qq: int, group: int) -> MessageSegment:
+async def group_user_check(nickname: str, user_id: str, group: str) -> MessageSegment:
# heuristic: if users find they have never checked in they are probable to check in
- user, _ = await SignGroupUser.get_or_create(user_id=str(user_qq), group_id=str(group))
- gold = await BagUser.get_gold(user_qq, group)
+ user, _ = await SignGroupUser.get_or_create(
+ user_id=str(user_id), group_id=str(group)
+ )
+ gold = await BagUser.get_gold(user_id, group)
return await get_card(user, nickname, None, gold, "", is_card_view=True)
@@ -171,7 +175,9 @@ async def _pst(users: list, impressions: list, groups: list):
impressions.pop(index)
users.pop(index)
groups.pop(index)
- if user_ := await GroupInfoUser.get_or_none(user_id=str(user), group_id=str(group)):
+ if user_ := await GroupInfoUser.get_or_none(
+ user_id=str(user), group_id=str(group)
+ ):
user_name = user_.user_name
else:
user_name = f"我名字呢?"
diff --git a/plugins/statistics/_model.py b/plugins/statistics/_model.py
index 2de65d60..28ce3814 100644
--- a/plugins/statistics/_model.py
+++ b/plugins/statistics/_model.py
@@ -9,9 +9,9 @@ class Statistics(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField(null=True)
+ group_id = fields.CharField(255, null=True)
"""群聊id"""
plugin_name = fields.CharField(255)
"""插件名称"""
@@ -21,3 +21,11 @@ class Statistics(Model):
class Meta:
table = "statistics"
table_description = "用户权限数据库"
+
+ @classmethod
+ async def _run_script(cls):
+ return [
+ "ALTER TABLE statistics RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE statistics ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE statistics ALTER COLUMN group_id TYPE character varying(255);",
+ ]
\ No newline at end of file
diff --git a/plugins/statistics/statistics_hook.py b/plugins/statistics/statistics_hook.py
index 31250b2f..2de3a1f1 100755
--- a/plugins/statistics/statistics_hook.py
+++ b/plugins/statistics/statistics_hook.py
@@ -102,7 +102,7 @@ async def _(
and matcher.plugin_name not in ["update_info", "statistics_handle"]
):
await Statistics.create(
- user_qq=event.user_id,
+ user_id=str(event.user_id),
group_id=getattr(event, "group_id", None),
plugin_name=matcher.plugin_name,
create_time=datetime.now(),
diff --git a/plugins/web_ui/__init__.py b/plugins/web_ui/__init__.py
index 5af537d7..622f87b2 100644
--- a/plugins/web_ui/__init__.py
+++ b/plugins/web_ui/__init__.py
@@ -1,15 +1,21 @@
+import asyncio
+
import nonebot
from fastapi import APIRouter, FastAPI
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
+from nonebot.log import default_filter, default_format
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor
from nonebot.typing import T_State
from configs.config import Config as gConfig
-from services.log import logger
+from services.log import logger, logger_
from utils.manager import plugins2settings_manager
+from .api.base_info import router as base_info_routes
from .api.group import router as group_routes
+from .api.logs import router as ws_routes
+from .api.logs.log_manager import LOG_STORAGE
from .api.plugins import router as plugin_routes
from .api.request import router as request_routes
from .api.system import router as system_routes
@@ -31,10 +37,20 @@ BaseApiRouter.include_router(plugin_routes)
BaseApiRouter.include_router(group_routes)
BaseApiRouter.include_router(request_routes)
BaseApiRouter.include_router(system_routes)
+BaseApiRouter.include_router(base_info_routes)
@driver.on_startup
def _():
+
+ loop = asyncio.get_running_loop()
+
+ def log_sink(message: str):
+ loop.create_task(LOG_STORAGE.add(message.rstrip("\n")))
+
+ logger_.add(log_sink, colorize=True, filter=default_filter, format=default_format)
+
app: FastAPI = nonebot.get_app()
app.include_router(BaseApiRouter)
+ app.include_router(ws_routes)
logger.info("API启动成功", "Web UI")
diff --git a/plugins/web_ui/api/base_info.py b/plugins/web_ui/api/base_info.py
new file mode 100644
index 00000000..1bfbb2f7
--- /dev/null
+++ b/plugins/web_ui/api/base_info.py
@@ -0,0 +1,75 @@
+from datetime import datetime, timedelta
+from typing import List, Optional
+
+import nonebot
+from fastapi import APIRouter
+
+from configs.config import Config
+from models.chat_history import ChatHistory
+from services.log import logger
+from utils.manager import plugin_data_manager, plugins2settings_manager, plugins_manager
+from utils.manager.models import PluginData, PluginType
+
+from ..models.model import BotInfo, Result
+from ..models.params import UpdateConfig, UpdatePlugin
+from ..utils import authentication
+
+AVA_URL = "http://q1.qlogo.cn/g?b=qq&nk={}&s=160"
+
+router = APIRouter()
+
+
+@router.get("/get_bot_info", dependencies=[authentication()])
+async def _(self_id: Optional[str] = None) -> Result:
+ """
+ 获取Bot基础信息
+
+ Args:
+ qq (Optional[str], optional): qq号. Defaults to None.
+
+ Returns:
+ Result: 获取指定bot信息与bot列表
+ """
+ bot_list: List[BotInfo] = []
+ if bots := nonebot.get_bots():
+ select_bot: BotInfo
+ for key, bot in bots.items():
+ bot_list.append(
+ BotInfo(
+ bot=bot, # type: ignore
+ self_id=bot.self_id,
+ nickname="可爱的小真寻",
+ ava_url=AVA_URL.format(bot.self_id),
+ )
+ )
+ if _bl := [b for b in bot_list if b.self_id == self_id]:
+ select_bot = _bl[0]
+ else:
+ select_bot = bot_list[0]
+ select_bot.is_select = True
+ now = datetime.now()
+ select_bot.received_messages = await ChatHistory.filter(
+ bot_id=int(select_bot.self_id)
+ ).count()
+ select_bot.received_messages_day = await ChatHistory.filter(
+ bot_id=int(select_bot.self_id),
+ create_time__gte=now - timedelta(hours=now.hour),
+ ).count()
+ select_bot.received_messages_week = await ChatHistory.filter(
+ bot_id=int(select_bot.self_id),
+ create_time__gte=now - timedelta(days=7),
+ ).count()
+ select_bot.group_count = len(await select_bot.bot.get_group_list())
+ select_bot.friend_count = len(await select_bot.bot.get_friend_list())
+ for bot in bot_list:
+ bot.bot = None # type: ignore
+ # 插件加载数量
+ select_bot.plugin_count = len(plugins2settings_manager)
+ pm_data = plugins_manager.get_data()
+ select_bot.fail_plugin_count = len([pd for pd in pm_data if pm_data[pd].error])
+ select_bot.success_plugin_count = (
+ select_bot.plugin_count - select_bot.fail_plugin_count
+ )
+
+ return Result.ok(bot_list, "已获取操作列表")
+ return Result.fail("无Bot连接")
diff --git a/plugins/web_ui/api/logs/__init__.py b/plugins/web_ui/api/logs/__init__.py
new file mode 100644
index 00000000..d6684888
--- /dev/null
+++ b/plugins/web_ui/api/logs/__init__.py
@@ -0,0 +1 @@
+from .logs import *
diff --git a/plugins/web_ui/api/logs/log_manager.py b/plugins/web_ui/api/logs/log_manager.py
new file mode 100644
index 00000000..ed773766
--- /dev/null
+++ b/plugins/web_ui/api/logs/log_manager.py
@@ -0,0 +1,45 @@
+import asyncio
+import re
+from typing import Awaitable, Callable, ClassVar, Dict, Generic, List, Set, TypeVar
+from urllib.parse import urlparse
+
+PATTERN = r"\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))"
+
+_T = TypeVar("_T")
+LogListener = Callable[[_T], Awaitable[None]]
+
+
+class LogStorage(Generic[_T]):
+ def __init__(self, rotation: float = 5 * 60):
+ self.count, self.rotation = 0, rotation
+ self.logs: Dict[int, str] = {}
+ self.listeners: Set[LogListener[str]] = set()
+
+ async def add(self, log: str):
+ log = re.sub(PATTERN, "", log)
+ log_split = log.split()
+ time = log_split[0] + " " + log_split[1]
+ level = log_split[2]
+ main = log_split[3]
+ type_ = None
+ log_ = " ".join(log_split[3:])
+ if "Calling API" in log_:
+ sp = log_.split("|")
+ type_ = sp[1]
+ log_ = "|".join(log_[1:])
+ data = {"time": time, "level": level, "main": main, "type": type_, "log": log_}
+ seq = self.count = self.count + 1
+ self.logs[seq] = log
+ asyncio.get_running_loop().call_later(self.rotation, self.remove, seq)
+ await asyncio.gather(
+ *map(lambda listener: listener(log), self.listeners),
+ return_exceptions=True,
+ )
+ return seq
+
+ def remove(self, seq: int):
+ del self.logs[seq]
+ return
+
+
+LOG_STORAGE = LogStorage[str]()
diff --git a/plugins/web_ui/api/logs/logs.py b/plugins/web_ui/api/logs/logs.py
new file mode 100644
index 00000000..4b5b1138
--- /dev/null
+++ b/plugins/web_ui/api/logs/logs.py
@@ -0,0 +1,37 @@
+from typing import List
+
+from fastapi import APIRouter, WebSocket
+from loguru import logger
+from nonebot.utils import escape_tag, run_sync
+from starlette.websockets import WebSocket, WebSocketDisconnect, WebSocketState
+
+from .log_manager import LOG_STORAGE
+
+router = APIRouter()
+
+
+@router.get("/logs", response_model=List[str])
+async def system_logs_history(reverse: bool = False):
+ return LOG_STORAGE.list(reverse=reverse)
+
+
+@router.websocket("/logs")
+async def system_logs_realtime(websocket: WebSocket):
+ await websocket.accept()
+
+ async def log_listener(log: str):
+ await websocket.send_text(log)
+
+ LOG_STORAGE.listeners.add(log_listener)
+ try:
+ while websocket.client_state == WebSocketState.CONNECTED:
+ recv = await websocket.receive()
+ logger.trace(
+ f"{system_logs_realtime.__name__!r} received "
+ f"{escape_tag(repr(recv))}"
+ )
+ except WebSocketDisconnect:
+ pass
+ finally:
+ LOG_STORAGE.listeners.remove(log_listener)
+ return
diff --git a/plugins/web_ui/models/model.py b/plugins/web_ui/models/model.py
index dc56656d..257678b0 100644
--- a/plugins/web_ui/models/model.py
+++ b/plugins/web_ui/models/model.py
@@ -1,6 +1,7 @@
from datetime import datetime
from typing import Any, Dict, List, Optional, TypeVar, Union
+from nonebot.adapters.onebot.v11 import Bot
from pydantic import BaseModel
from configs.utils import Config
@@ -180,3 +181,43 @@ class SystemResult(BaseModel):
network: SystemNetwork
disk: SystemFolderSize
check_time: datetime
+
+
+class BotInfo(BaseModel):
+ """
+ Bot基础信息
+ """
+
+ bot: Bot
+ """Bot"""
+ self_id: str
+ """SELF ID"""
+ nickname: str
+ """昵称"""
+ ava_url: str
+ """头像url"""
+ friend_count: int = 0
+ """好友数量"""
+ group_count: int = 0
+ """群聊数量"""
+ received_messages: int = 0
+ """累计接收消息"""
+ received_messages_day: int = 0
+ """今日累计接收消息"""
+ received_messages_week: int = 0
+ """一周内累计接收消息"""
+ received_messages_month: int = 0
+ """一月内累计接收消息"""
+
+ plugin_count: int = 0
+ """加载插件数量"""
+ success_plugin_count: int = 0
+ """加载成功插件数量"""
+ fail_plugin_count: int = 0
+ """加载失败插件数量"""
+
+ is_select: bool = False
+ """当前选择"""
+
+ class Config:
+ arbitrary_types_allowed = True
diff --git a/plugins/word_bank/_data_source.py b/plugins/word_bank/_data_source.py
index c707ae3d..12bc2f83 100644
--- a/plugins/word_bank/_data_source.py
+++ b/plugins/word_bank/_data_source.py
@@ -1,16 +1,17 @@
import random
import time
from pathlib import Path
+from typing import Any, List, Optional, Tuple, Union
+import nonebot
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from services import logger
from utils.image_utils import text2image
from utils.message_builder import image
-from ._model import WordBank
-from typing import Optional, Tuple, Union, List, Any
from utils.utils import is_number
-import nonebot
+
+from ._model import WordBank
driver = nonebot.get_driver()
@@ -197,7 +198,7 @@ async def _():
new_answer_path.mkdir(exist_ok=True, parents=True)
for word in word_list:
problem: str = word.problem
- user_id = word.user_qq
+ user_id = word.user_id
group_id = word.group_id
format_ = word.format
answer = word.answer
diff --git a/plugins/word_bank/_model.py b/plugins/word_bank/_model.py
index 2bb1257c..ca07c9b9 100644
--- a/plugins/word_bank/_model.py
+++ b/plugins/word_bank/_model.py
@@ -31,9 +31,9 @@ class WordBank(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
- user_qq = fields.BigIntField()
+ user_id = fields.CharField(255)
"""用户id"""
- group_id = fields.BigIntField(null=True)
+ group_id = fields.CharField(255, null=True)
"""群聊id"""
word_scope = fields.IntField(default=0)
"""生效范围 0: 全局 1: 群聊 2: 私聊"""
@@ -63,8 +63,8 @@ class WordBank(Model):
@classmethod
async def exists(
cls,
- user_id: Optional[int],
- group_id: Optional[int],
+ user_id: Optional[str],
+ group_id: Optional[str],
problem: str,
answer: Optional[str],
word_scope: Optional[int] = None,
@@ -83,7 +83,7 @@ class WordBank(Model):
"""
query = cls.filter(problem=problem)
if user_id:
- query = query.filter(user_qq=user_id)
+ query = query.filter(user_id=user_id)
if group_id:
query = query.filter(group_id=group_id)
if answer:
@@ -97,8 +97,8 @@ class WordBank(Model):
@classmethod
async def add_problem_answer(
cls,
- user_id: int,
- group_id: Optional[int],
+ user_id: str,
+ group_id: Optional[str],
word_scope: int,
word_type: int,
problem: Union[str, Message],
@@ -133,7 +133,7 @@ class WordBank(Model):
user_id, group_id, str(problem), answer, word_scope, word_type
):
await cls.create(
- user_qq=user_id,
+ user_id=user_id,
group_id=group_id,
word_scope=word_scope,
word_type=word_type,
@@ -149,7 +149,7 @@ class WordBank(Model):
@classmethod
async def _answer2format(
- cls, answer: Union[str, Message], user_id: int, group_id: Optional[int]
+ cls, answer: Union[str, Message], user_id: str, group_id: Optional[str]
) -> Tuple[str, List[Any]]:
"""
说明:
@@ -213,7 +213,7 @@ class WordBank(Model):
if not query:
query = await cls.get_or_none(
problem=problem,
- user_qq=user_id,
+ user_id=user_id,
group_id=group_id,
answer=answer,
)
@@ -311,7 +311,7 @@ class WordBank(Model):
await cls._format2answer(
random_answer.problem,
random_answer.answer,
- random_answer.user_qq,
+ random_answer.user_id,
random_answer.group_id,
random_answer,
)
@@ -351,7 +351,7 @@ class WordBank(Model):
async def delete_group_problem(
cls,
problem: str,
- group_id: int,
+ group_id: str,
index: Optional[int] = None,
word_scope: int = 1,
):
@@ -386,7 +386,7 @@ class WordBank(Model):
cls,
problem: str,
replace_str: str,
- group_id: int,
+ group_id: str,
index: Optional[int] = None,
word_scope: int = 1,
):
@@ -419,7 +419,7 @@ class WordBank(Model):
@classmethod
async def get_group_all_problem(
- cls, group_id: int
+ cls, group_id: str
) -> List[Tuple[Any, Union[MessageSegment, str]]]:
"""
说明:
@@ -480,8 +480,8 @@ class WordBank(Model):
@classmethod
async def _move(
cls,
- user_id: int,
- group_id: Optional[int],
+ user_id: str,
+ group_id: Optional[str],
problem: Union[str, Message],
answer: Union[str, Message],
placeholder: str,
@@ -503,7 +503,7 @@ class WordBank(Model):
user_id, group_id, problem, answer, word_scope, word_type
):
await cls.create(
- user_qq=user_id,
+ user_id=user_id,
group_id=group_id,
word_scope=word_scope,
word_type=word_type,
@@ -522,4 +522,7 @@ class WordBank(Model):
"ALTER TABLE word_bank2 ADD to_me varchar(255);", # 添加 to_me 字段
"ALTER TABLE word_bank2 ALTER COLUMN create_time TYPE timestamp with time zone USING create_time::timestamp with time zone;",
"ALTER TABLE word_bank2 ALTER COLUMN update_time TYPE timestamp with time zone USING update_time::timestamp with time zone;",
+ "ALTER TABLE word_bank2 RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
+ "ALTER TABLE word_bank2 ALTER COLUMN user_id TYPE character varying(255);",
+ "ALTER TABLE word_bank2 ALTER COLUMN group_id TYPE character varying(255);",
]
diff --git a/plugins/word_bank/message_handle.py b/plugins/word_bank/message_handle.py
index 3f3d3890..9f9fe4d7 100644
--- a/plugins/word_bank/message_handle.py
+++ b/plugins/word_bank/message_handle.py
@@ -1,11 +1,13 @@
-from services import logger
-from ._rule import check
-from ._model import WordBank
-from configs.path_config import DATA_PATH
-from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
from nonebot import on_message
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
from nonebot.typing import T_State
+from configs.path_config import DATA_PATH
+from services import logger
+
+from ._model import WordBank
+from ._rule import check
+
__zx_plugin_name__ = "词库问答回复操作 [Hidden]"
data_dir = DATA_PATH / "word_bank"
@@ -20,7 +22,8 @@ async def _(event: MessageEvent, state: T_State):
if msg := await WordBank.get_answer(event, problem):
await message_handle.send(msg)
logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 触发词条 {problem}"
+ f" 触发词条 {problem}",
+ "词条检测",
+ event.user_id,
+ getattr(event, "group_id", None),
)
diff --git a/plugins/word_bank/word_handle.py b/plugins/word_bank/word_handle.py
index 52f99357..24b529d2 100644
--- a/plugins/word_bank/word_handle.py
+++ b/plugins/word_bank/word_handle.py
@@ -196,11 +196,11 @@ async def _(
if problem and bot.config.nickname:
nickname = [nk for nk in bot.config.nickname if problem.startswith(nk)]
await WordBank.add_problem_answer(
- event.user_id,
- event.group_id
+ str(event.user_id),
+ str(event.group_id)
if isinstance(event, GroupMessageEvent)
and (not word_scope or word_scope == "私聊")
- else 0,
+ else "0",
scope2int[word_scope] if word_scope else 1,
type2int[word_type] if word_type else 0,
problem or problem_image,
@@ -211,16 +211,16 @@ async def _(
if isinstance(e, FinishedException):
await add_word.finish()
logger.error(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 添加词条 {problem} 发生错误 {type(e)}: {e} "
+ f"添加词条 {problem} 错误...",
+ "添加词条",
+ event.user_id,
+ getattr(event, "group_id", None),
+ e=e,
)
await add_word.finish(f"添加词条 {problem} 发生错误!")
await add_word.send("添加词条 " + (problem or problem_image) + " 成功!")
logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 添加词条 {problem} 成功!"
+ f"添加词条 {problem} 成功!", "添加词条", event.user_id, getattr(event, "group_id", None)
)
@@ -230,7 +230,7 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
await delete_word_matcher.finish("此命令之后需要跟随指定词条,通过“显示词条“查看")
result = await delete_word(msg, event.group_id)
await delete_word_matcher.send(result)
- logger.info(f"(USER {event.user_id}, GROUP " f"{event.group_id})" f" 删除词条:" + msg)
+ logger.info(f"删除词条:" + msg, "删除词条", event.user_id, event.group_id)
@delete_word_matcher.handle()
@@ -246,7 +246,7 @@ async def _(
await delete_word_matcher.finish("此命令之后需要跟随指定词条,通过“显示词条“查看")
result = await delete_word(msg, word_scope=2 if cmd[0] == "删除词条" else 0)
await delete_word_matcher.send(result)
- logger.info(f"(USER {event.user_id})" f" 删除词条:" + msg)
+ logger.info(f"删除词条:" + msg, "删除词条", event.user_id)
@update_word_matcher.handle()
@@ -257,7 +257,7 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
await update_word_matcher.finish("此命令需要两个参数,请查看帮助")
result = await update_word(msg, event.group_id)
await update_word_matcher.send(result)
- logger.info(f"(USER {event.user_id}, GROUP " f"{event.group_id})" f" 更新词条词条:" + msg)
+ logger.info(f"更新词条词条:" + msg, "更新词条", event.user_id, event.group_id)
@update_word_matcher.handle()
@@ -275,7 +275,7 @@ async def _(
await update_word_matcher.finish("此命令需要两个参数,请查看帮助")
result = await update_word(msg, word_scope=2 if cmd[0] == "修改词条" else 0)
await update_word_matcher.send(result)
- logger.info(f"(USER {event.user_id})" f" 更新词条词条:" + msg)
+ logger.info(f"更新词条词条:" + msg, "更新词条", event.user_id)
@show_word_matcher.handle()
@@ -288,7 +288,8 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
if (
not is_number(id_)
or int(id_) < 0
- or int(id_) >= len(await WordBank.get_group_all_problem(event.group_id))
+ or int(id_)
+ >= len(await WordBank.get_group_all_problem(str(event.group_id)))
):
await show_word_matcher.finish("id必须为数字且在范围内")
id_ = int(id_)
@@ -311,9 +312,7 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
group_id=event.group_id, messages=custom_forward_msg(msg_list, bot.self_id)
)
logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送查看词条回答:" + problem
+ f"查看词条回答:" + problem, "显示词条", event.user_id, getattr(event, "group_id", None)
)
@@ -352,4 +351,6 @@ async def _(event: PrivateMessageEvent, arg: Message = CommandArg()):
for msg in msg_list:
t += msg + "\n"
await show_word_matcher.send(t[:-1])
- logger.info(f"(USER {event.user_id}, GROUP " f"private)" f" 发送查看词条回答:" + problem)
+ logger.info(
+ f"查看词条回答:" + problem, "显示词条", event.user_id, getattr(event, "group_id", None)
+ )
diff --git a/poetry.lock b/poetry.lock
index f32793b7..5cadd75d 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -194,7 +194,7 @@ reference = "ali"
[[package]]
name = "bilireq"
-version = "0.2.3.post0"
+version = "0.2.4"
description = ""
category = "main"
optional = false
@@ -472,7 +472,7 @@ reference = "ali"
[[package]]
name = "fastapi"
-version = "0.88.0"
+version = "0.95.0"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
category = "main"
optional = false
@@ -480,13 +480,13 @@ python-versions = ">=3.7"
[package.dependencies]
pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
-starlette = "0.22.0"
+starlette = ">=0.26.1,<0.27.0"
[package.extras]
all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
-dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.19.0)"]
-doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer[all] (>=0.6.1,<0.7.0)"]
-test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==22.10.0)", "coverage[toml] (>=6.5.0,<7.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<=1.4.41)", "types-orjson (==3.6.2)", "types-ujson (==5.5.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"]
+dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.21.0)"]
+doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer-cli (>=0.0.13,<0.0.14)", "typer[all] (>=0.6.1,<0.8.0)"]
+test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.7)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.7.0.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"]
[package.source]
type = "legacy"
@@ -1148,7 +1148,7 @@ reference = "ali"
[[package]]
name = "pydantic"
-version = "1.10.2"
+version = "1.10.7"
description = "Data validation and settings management using python type hints"
category = "main"
optional = false
@@ -1156,7 +1156,7 @@ python-versions = ">=3.7"
[package.dependencies]
python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""}
-typing-extensions = ">=4.1.0"
+typing-extensions = ">=4.2.0"
[package.extras]
dotenv = ["python-dotenv (>=0.10.4)"]
@@ -1631,7 +1631,7 @@ reference = "ali"
[[package]]
name = "starlette"
-version = "0.22.0"
+version = "0.26.1"
description = "The little ASGI library that shines."
category = "main"
optional = false
@@ -1766,7 +1766,7 @@ reference = "ali"
[[package]]
name = "uvicorn"
-version = "0.20.0"
+version = "0.22.0"
description = "The lightning-fast ASGI server."
category = "main"
optional = false
@@ -1909,7 +1909,7 @@ reference = "ali"
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
-content-hash = "30f718b1d834abeaf0be2239ac66ebf40d71ca72b28ecea5b13d64aedeaaa6a9"
+content-hash = "4cb77a7a5a9777d704c3862467937cd307d119bdd8825a0278fdd063b8695851"
[metadata.files]
aiofiles = [
@@ -2037,8 +2037,8 @@ beautifulsoup4 = [
{file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
]
bilireq = [
- {file = "bilireq-0.2.3.post0-py3-none-any.whl", hash = "sha256:8d1f98bb8fb59c0ce1dec226329353ce51e2efaad0a6b4d240437b6132648322"},
- {file = "bilireq-0.2.3.post0.tar.gz", hash = "sha256:3185c3952a2becc7d31b0c01a12fda463fa477253504a68f81ea871594887ab4"},
+ {file = "bilireq-0.2.4-py3-none-any.whl", hash = "sha256:b5396164b27657cac8008c6a2d9bf6a8b5414d92d2b27cb5bee074f1fd0b5b0b"},
+ {file = "bilireq-0.2.4.tar.gz", hash = "sha256:0c52c7c1fbe1f1b9d8b53ab9a6d4fbae363f6d6dc35c6a7cf1cc8652a10e2e00"},
]
black = [
{file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
@@ -2177,8 +2177,8 @@ exceptiongroup = [
{file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"},
]
fastapi = [
- {file = "fastapi-0.88.0-py3-none-any.whl", hash = "sha256:263b718bb384422fe3d042ffc9a0c8dece5e034ab6586ff034f6b4b1667c3eee"},
- {file = "fastapi-0.88.0.tar.gz", hash = "sha256:915bf304180a0e7c5605ec81097b7d4cd8826ff87a02bb198e336fb9f3b5ff02"},
+ {file = "fastapi-0.95.0-py3-none-any.whl", hash = "sha256:daf73bbe844180200be7966f68e8ec9fd8be57079dff1bacb366db32729e6eb5"},
+ {file = "fastapi-0.95.0.tar.gz", hash = "sha256:99d4fdb10e9dd9a24027ac1d0bd4b56702652056ca17a6c8721eec4ad2f14e18"},
]
feedparser = [
{file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"},
@@ -2914,42 +2914,42 @@ pyasn1 = [
{file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"},
]
pydantic = [
- {file = "pydantic-1.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb6ad4489af1bac6955d38ebcb95079a836af31e4c4f74aba1ca05bb9f6027bd"},
- {file = "pydantic-1.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1f5a63a6dfe19d719b1b6e6106561869d2efaca6167f84f5ab9347887d78b98"},
- {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352aedb1d71b8b0736c6d56ad2bd34c6982720644b0624462059ab29bd6e5912"},
- {file = "pydantic-1.10.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19b3b9ccf97af2b7519c42032441a891a5e05c68368f40865a90eb88833c2559"},
- {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9069e1b01525a96e6ff49e25876d90d5a563bc31c658289a8772ae186552236"},
- {file = "pydantic-1.10.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:355639d9afc76bcb9b0c3000ddcd08472ae75318a6eb67a15866b87e2efa168c"},
- {file = "pydantic-1.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:ae544c47bec47a86bc7d350f965d8b15540e27e5aa4f55170ac6a75e5f73b644"},
- {file = "pydantic-1.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4c805731c33a8db4b6ace45ce440c4ef5336e712508b4d9e1aafa617dc9907f"},
- {file = "pydantic-1.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49f3db871575e0426b12e2f32fdb25e579dea16486a26e5a0474af87cb1ab0a"},
- {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37c90345ec7dd2f1bcef82ce49b6235b40f282b94d3eec47e801baf864d15525"},
- {file = "pydantic-1.10.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b5ba54d026c2bd2cb769d3468885f23f43710f651688e91f5fb1edcf0ee9283"},
- {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05e00dbebbe810b33c7a7362f231893183bcc4251f3f2ff991c31d5c08240c42"},
- {file = "pydantic-1.10.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2d0567e60eb01bccda3a4df01df677adf6b437958d35c12a3ac3e0f078b0ee52"},
- {file = "pydantic-1.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:c6f981882aea41e021f72779ce2a4e87267458cc4d39ea990729e21ef18f0f8c"},
- {file = "pydantic-1.10.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4aac8e7103bf598373208f6299fa9a5cfd1fc571f2d40bf1dd1955a63d6eeb5"},
- {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a7b66c3f499108b448f3f004801fcd7d7165fb4200acb03f1c2402da73ce4c"},
- {file = "pydantic-1.10.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bedf309630209e78582ffacda64a21f96f3ed2e51fbf3962d4d488e503420254"},
- {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9300fcbebf85f6339a02c6994b2eb3ff1b9c8c14f502058b5bf349d42447dcf5"},
- {file = "pydantic-1.10.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:216f3bcbf19c726b1cc22b099dd409aa371f55c08800bcea4c44c8f74b73478d"},
- {file = "pydantic-1.10.2-cp37-cp37m-win_amd64.whl", hash = "sha256:dd3f9a40c16daf323cf913593083698caee97df2804aa36c4b3175d5ac1b92a2"},
- {file = "pydantic-1.10.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b97890e56a694486f772d36efd2ba31612739bc6f3caeee50e9e7e3ebd2fdd13"},
- {file = "pydantic-1.10.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9cabf4a7f05a776e7793e72793cd92cc865ea0e83a819f9ae4ecccb1b8aa6116"},
- {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06094d18dd5e6f2bbf93efa54991c3240964bb663b87729ac340eb5014310624"},
- {file = "pydantic-1.10.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc78cc83110d2f275ec1970e7a831f4e371ee92405332ebfe9860a715f8336e1"},
- {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ee433e274268a4b0c8fde7ad9d58ecba12b069a033ecc4645bb6303c062d2e9"},
- {file = "pydantic-1.10.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c2abc4393dea97a4ccbb4ec7d8658d4e22c4765b7b9b9445588f16c71ad9965"},
- {file = "pydantic-1.10.2-cp38-cp38-win_amd64.whl", hash = "sha256:0b959f4d8211fc964772b595ebb25f7652da3f22322c007b6fed26846a40685e"},
- {file = "pydantic-1.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c33602f93bfb67779f9c507e4d69451664524389546bacfe1bee13cae6dc7488"},
- {file = "pydantic-1.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5760e164b807a48a8f25f8aa1a6d857e6ce62e7ec83ea5d5c5a802eac81bad41"},
- {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eb843dcc411b6a2237a694f5e1d649fc66c6064d02b204a7e9d194dff81eb4b"},
- {file = "pydantic-1.10.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b8795290deaae348c4eba0cebb196e1c6b98bdbe7f50b2d0d9a4a99716342fe"},
- {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e0bedafe4bc165ad0a56ac0bd7695df25c50f76961da29c050712596cf092d6d"},
- {file = "pydantic-1.10.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e05aed07fa02231dbf03d0adb1be1d79cabb09025dd45aa094aa8b4e7b9dcda"},
- {file = "pydantic-1.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c1ba1afb396148bbc70e9eaa8c06c1716fdddabaf86e7027c5988bae2a829ab6"},
- {file = "pydantic-1.10.2-py3-none-any.whl", hash = "sha256:1b6ee725bd6e83ec78b1aa32c5b1fa67a3a65badddde3976bca5fe4568f27709"},
- {file = "pydantic-1.10.2.tar.gz", hash = "sha256:91b8e218852ef6007c2b98cd861601c6a09f1aa32bbbb74fab5b1c33d4a1e410"},
+ {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"},
+ {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"},
+ {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"},
+ {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"},
+ {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"},
+ {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"},
+ {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"},
+ {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"},
+ {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"},
+ {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"},
+ {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"},
+ {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"},
+ {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"},
+ {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"},
+ {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"},
+ {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"},
+ {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"},
+ {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"},
+ {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"},
+ {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"},
+ {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"},
+ {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"},
+ {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"},
+ {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"},
+ {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"},
+ {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"},
+ {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"},
+ {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"},
+ {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"},
+ {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"},
+ {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"},
+ {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"},
+ {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"},
+ {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"},
+ {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"},
+ {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"},
]
pyee = [
{file = "pyee-9.0.4-py2.py3-none-any.whl", hash = "sha256:9f066570130c554e9cc12de5a9d86f57c7ee47fece163bbdaa3e9c933cfbdfa5"},
@@ -3253,8 +3253,8 @@ soupsieve = [
{file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"},
]
starlette = [
- {file = "starlette-0.22.0-py3-none-any.whl", hash = "sha256:b5eda991ad5f0ee5d8ce4c4540202a573bb6691ecd0c712262d0bc85cf8f2c50"},
- {file = "starlette-0.22.0.tar.gz", hash = "sha256:b092cbc365bea34dd6840b42861bdabb2f507f8671e642e8272d2442e08ea4ff"},
+ {file = "starlette-0.26.1-py3-none-any.whl", hash = "sha256:e87fce5d7cbdde34b76f0ac69013fd9d190d581d80681493016666e6f96c6d5e"},
+ {file = "starlette-0.26.1.tar.gz", hash = "sha256:41da799057ea8620e4667a3e69a5b1923ebd32b1819c8fa75634bbe8d8bea9bd"},
]
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
@@ -3348,8 +3348,8 @@ ujson = [
{file = "ujson-5.6.0.tar.gz", hash = "sha256:f881e2d8a022e9285aa2eab6ba8674358dbcb2b57fa68618d88d62937ac3ff04"},
]
uvicorn = [
- {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"},
- {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"},
+ {file = "uvicorn-0.22.0-py3-none-any.whl", hash = "sha256:e9434d3bbf05f310e762147f769c9f21235ee118ba2d2bf1155a7196448bd996"},
+ {file = "uvicorn-0.22.0.tar.gz", hash = "sha256:79277ae03db57ce7d9aa0567830bbb51d7a612f54d6e1e3e92da3ef24c2c8ed8"},
]
uvloop = [
{file = "uvloop-0.17.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718"},
diff --git a/pyproject.toml b/pyproject.toml
index bac2193f..e12b2b32 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -46,6 +46,7 @@ nonebot-plugin-htmlrender = "^0.2.0"
cachetools = "^5.2.0"
tortoise-orm = {extras = ["asyncpg"], version = "^0.19.3"}
cattrs = "^22.2.0"
+starlette = "^0.26.1"
[tool.poetry.dev-dependencies]
diff --git a/utils/image_utils.py b/utils/image_utils.py
index 7686ce9e..2c5a30bf 100755
--- a/utils/image_utils.py
+++ b/utils/image_utils.py
@@ -958,6 +958,7 @@ class BuildMat:
y_name: Optional[str] = None,
x_index: List[Union[str, int, float]] = None,
y_index: List[Union[str, int, float]] = None,
+ x_min_spacing: Optional[int] = None,
x_rotate: int = 0,
title: Optional[str] = None,
size: Tuple[int, int] = (1000, 1000),
@@ -979,6 +980,7 @@ class BuildMat:
:param y_name: 纵坐标名称
:param x_index: 横坐标值
:param y_index: 纵坐标值
+ :param x_min_spacing: x轴最小间距
:param x_rotate: 横坐标旋转角度
:param title: 标题
:param size: 图像大小,建议默认
@@ -1000,6 +1002,7 @@ class BuildMat:
self.y_name = y_name
self.x_index = x_index
self.y_index = y_index
+ self.x_min_spacing = x_min_spacing
self.x_rotate = x_rotate
self.title = title
self.font = font
@@ -1030,7 +1033,10 @@ class BuildMat:
]
if not x_index:
raise ValueError("缺少 x_index [横坐标值]...")
- self._x_interval = int((self.line_length - 70) / len(x_index))
+ if x_min_spacing:
+ self._x_interval = x_min_spacing
+ else:
+ self._x_interval = int((self.line_length - 70) / len(x_index))
self._bar_width = int(30 * (1 - (len(x_index) + 10) / 100))
# 没有 y_index 时自动生成
if not y_index:
@@ -1181,7 +1187,7 @@ class BuildMat:
:param y: 坐标点
:param display_num: 显示该点的值
"""
- _black_point = BuildImage(7, 7, color=random.choice(self.bar_color))
+ _black_point = BuildImage(11, 11, color=random.choice(self.bar_color))
_black_point.circle()
x_interval = self._x_interval
current_w = self.padding_w + x_interval
@@ -1196,14 +1202,6 @@ class BuildMat:
),
f"{y[i]:.2f}" if isinstance(y[i], float) else f"{y[i]}",
)
- self.markImg.paste(
- _black_point,
- (
- current_w - 3,
- current_h - int(y[i] * self._p * self._deviation) - 3,
- ),
- True,
- )
if i != len(y) - 1:
self.markImg.line(
(
@@ -1215,6 +1213,14 @@ class BuildMat:
fill=(0, 0, 0),
width=2,
)
+ self.markImg.paste(
+ _black_point,
+ (
+ current_w - 3,
+ current_h - int(y[i] * self._p * self._deviation) - 3,
+ ),
+ True,
+ )
current_w += x_interval
def _gen_bar_graph(
@@ -1319,6 +1325,11 @@ class BuildMat:
padding_h = self.padding_h
line_length = self.line_length
background = random.choice(self.background) if self.background else None
+ if self.x_min_spacing:
+ length = (len(self.x_index) + 1) * self.x_min_spacing
+ if 2 * padding_w + length > self.w:
+ self.w = 2 * padding_w + length
+ background = None
A = BuildImage(
self.w, self.h, font_size=font_size, font=self.font, background=background
)
@@ -1341,7 +1352,7 @@ class BuildMat:
(
padding_w,
padding_h + line_length,
- padding_w + line_length,
+ self.w - padding_w,
padding_h + line_length,
),
(0, 0, 0),
diff --git a/utils/manager/data_class.py b/utils/manager/data_class.py
index bbfbaab8..cdfcd64d 100755
--- a/utils/manager/data_class.py
+++ b/utils/manager/data_class.py
@@ -35,11 +35,11 @@ class StaticData(Generic[T]):
elif file.name.endswith("yaml"):
self._data = _yaml.load(f)
- def set(self, key, value) -> NoReturn:
+ def set(self, key, value):
self._data[key] = value
self.save()
- def set_module_data(self, module, key, value, auto_save: bool = True) -> NoReturn:
+ def set_module_data(self, module, key, value, auto_save: bool = True):
if module in self._data.keys():
self._data[module][key] = value
if auto_save:
@@ -51,7 +51,7 @@ class StaticData(Generic[T]):
def keys(self) -> List[str]:
return self._data.keys()
- def delete(self, key) -> NoReturn:
+ def delete(self, key):
if self._data.get(key) is not None:
del self._data[key]
@@ -105,3 +105,6 @@ class StaticData(Generic[T]):
def __getitem__(self, key) -> T:
return self._data[key]
+
+ def __len__(self) -> int:
+ return len(self._data)
diff --git a/utils/manager/models.py b/utils/manager/models.py
index 82f1dd0c..1981e0d0 100644
--- a/utils/manager/models.py
+++ b/utils/manager/models.py
@@ -35,10 +35,17 @@ class BaseData(BaseModel):
群基本信息
"""
- white_group: List[int] = [] # 白名单
- close_task: List[str] = [] # 全局关闭的被动任务
- group_manager: Dict[str, BaseGroup] = {} # 群组管理
- task: Dict[str, str] = {} # 被动任务 【英文:中文】
+ white_group: List[int] = []
+ """白名单"""
+ close_task: List[str] = []
+ """全局关闭的被动任务"""
+ group_manager: Dict[str, BaseGroup] = {}
+ """群组管理"""
+ task: Dict[str, str] = {}
+ """被动任务 英文:中文名"""
+
+ def __len__(self) -> int:
+ return len(self.group_manager)
class PluginBlock(BaseModel):
diff --git a/utils/message_builder.py b/utils/message_builder.py
index dd8fcfa2..f19876da 100755
--- a/utils/message_builder.py
+++ b/utils/message_builder.py
@@ -7,11 +7,11 @@ from nonebot.adapters.onebot.v11.message import Message, MessageSegment
from configs.config import NICKNAME
from configs.path_config import IMAGE_PATH, RECORD_PATH
from services.log import logger
-from utils.image_utils import BuildImage
+from utils.image_utils import BuildImage, BuildMat
def image(
- file: Optional[Union[str, Path, bytes, BuildImage, io.BytesIO]] = None,
+ file: Optional[Union[str, Path, bytes, BuildImage, io.BytesIO, BuildMat]] = None,
b64: Optional[str] = None,
) -> MessageSegment:
"""
@@ -38,7 +38,7 @@ def image(
logger.warning(f"图片 {file.absolute()}缺失...")
if isinstance(file, (bytes, io.BytesIO)):
return MessageSegment.image(file)
- if isinstance(file, BuildImage):
+ if isinstance(file, (BuildImage, BuildMat)):
return MessageSegment.image(file.pic2bs4())
return MessageSegment.image("")
diff --git a/utils/typing.py b/utils/typing.py
new file mode 100644
index 00000000..5d8fa815
--- /dev/null
+++ b/utils/typing.py
@@ -0,0 +1,3 @@
+from typing import Literal
+
+BLOCK_TYPE = Literal["all", "private", "group"]