diff --git a/README.md b/README.md index 858720e6..92ac121e 100644 --- a/README.md +++ b/README.md @@ -331,6 +331,10 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能 ## 更新 +### 2023/2/26 + +* Config提供`type`字段确定配置项类型 + ### 2023/2/25 * 修复ys查询,尘歌壶背景尺寸与内容不匹配的问题 [@pull/1270](https://github.com/HibiKier/zhenxun_bot/pull/1275) diff --git a/basic_plugins/admin_bot_manage/__init__.py b/basic_plugins/admin_bot_manage/__init__.py index f768f272..79aa5bca 100755 --- a/basic_plugins/admin_bot_manage/__init__.py +++ b/basic_plugins/admin_bot_manage/__init__.py @@ -1,8 +1,8 @@ from pathlib import Path -from configs.config import Config import nonebot +from configs.config import Config Config.add_plugin_config( "admin_bot_manage:custom_welcome_message", @@ -11,6 +11,7 @@ Config.add_plugin_config( name="群管理员操作", help_="设置群欢迎消息权限", default_value=2, + type=int, ) Config.add_plugin_config( @@ -19,6 +20,7 @@ Config.add_plugin_config( 2, help_="开关群功能权限", default_value=2, + type=int, ) Config.add_plugin_config( @@ -26,7 +28,8 @@ Config.add_plugin_config( "ADMIN_DEFAULT_AUTH", 5, help_="默认群管理员权限", - default_value=5 + default_value=5, + type=int, ) nonebot.load_plugins(str(Path(__file__).parent.resolve())) diff --git a/basic_plugins/apscheduler/__init__.py b/basic_plugins/apscheduler/__init__.py index 7818d8c0..682597f0 100755 --- a/basic_plugins/apscheduler/__init__.py +++ b/basic_plugins/apscheduler/__init__.py @@ -1,5 +1,6 @@ import shutil from pathlib import Path +from typing import List import nonebot from nonebot import on_message @@ -20,15 +21,11 @@ __plugin_task__ = {"zwa": "早晚安"} Config.add_plugin_config( - "_task", - "DEFAULT_ZWA", - True, - help_="被动 早晚安 进群默认开关状态", - default_value=True, + "_task", "DEFAULT_ZWA", True, help_="被动 早晚安 进群默认开关状态", default_value=True, type=bool ) Config.add_plugin_config( - "_backup", "BACKUP_FLAG", True, help_="是否开启文件备份", default_value=True + "_backup", "BACKUP_FLAG", True, help_="是否开启文件备份", default_value=True, type=bool ) Config.add_plugin_config( @@ -45,6 +42,7 @@ Config.add_plugin_config( name="文件备份", help_="备份的文件夹或文件", default_value=[], + type=List[str], ) diff --git a/basic_plugins/ban/__init__.py b/basic_plugins/ban/__init__.py index a9a3318c..5dc6ad11 100755 --- a/basic_plugins/ban/__init__.py +++ b/basic_plugins/ban/__init__.py @@ -56,6 +56,7 @@ __plugin_configs__ = { "value": 5, "help": "ban/unban所需要的管理员权限等级", "default_value": 5, + "type": int } } diff --git a/basic_plugins/broadcast/__init__.py b/basic_plugins/broadcast/__init__.py index 0f6a7c94..1be81793 100755 --- a/basic_plugins/broadcast/__init__.py +++ b/basic_plugins/broadcast/__init__.py @@ -1,14 +1,15 @@ -from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent -from nonebot import on_command -from nonebot.permission import SUPERUSER -from nonebot.params import CommandArg -from utils.utils import get_message_img -from services.log import logger -from utils.message_builder import image -from utils.manager import group_manager -from configs.config import Config import asyncio +from nonebot import on_command +from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent +from nonebot.params import CommandArg +from nonebot.permission import SUPERUSER + +from configs.config import Config +from services.log import logger +from utils.manager import group_manager +from utils.message_builder import image +from utils.utils import get_message_img __zx_plugin_name__ = "广播 [Superuser]" __plugin_usage__ = """ @@ -28,6 +29,7 @@ Config.add_plugin_config( True, help_="被动 广播 进群默认开关状态", default_value=True, + type=bool, ) broadcast = on_command("广播-", priority=1, permission=SUPERUSER, block=True) diff --git a/basic_plugins/chat_history/chat_message.py b/basic_plugins/chat_history/chat_message.py index fbfa1d6a..c68cfdc2 100644 --- a/basic_plugins/chat_history/chat_message.py +++ b/basic_plugins/chat_history/chat_message.py @@ -15,7 +15,13 @@ __plugin_author__ = "HibiKier" Config.add_plugin_config( - "chat_history", "FLAG", True, help_="是否开启消息自从存储", name="消息存储", default_value=True + "chat_history", + "FLAG", + True, + help_="是否开启消息自从存储", + name="消息存储", + default_value=True, + type=bool, ) diff --git a/basic_plugins/group_handle/__init__.py b/basic_plugins/group_handle/__init__.py index d30fcdf7..45d7cee8 100755 --- a/basic_plugins/group_handle/__init__.py +++ b/basic_plugins/group_handle/__init__.py @@ -31,10 +31,10 @@ Config.add_plugin_config( "invite_manager", "message", f"请不要未经同意就拉{NICKNAME}入群!告辞!", help_="强制拉群后进群回复的内容.." ) Config.add_plugin_config( - "invite_manager", "flag", True, help_="被强制拉群后是否直接退出", default_value=True + "invite_manager", "flag", True, help_="被强制拉群后是否直接退出", default_value=True, type=bool ) Config.add_plugin_config( - "invite_manager", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5 + "invite_manager", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5, type=int ) Config.add_plugin_config( "_task", @@ -42,6 +42,7 @@ Config.add_plugin_config( True, help_="被动 进群欢迎 进群默认开关状态", default_value=True, + type=bool, ) Config.add_plugin_config( "_task", @@ -49,10 +50,11 @@ Config.add_plugin_config( True, help_="被动 退群提醒 进群默认开关状态", default_value=True, + type=bool, ) -_flmt = FreqLimiter(Config.get_config("invite_manager", "welcome_msg_cd")) +_flmt = FreqLimiter(Config.get_config("invite_manager", "welcome_msg_cd") or 5) # 群员增加处理 diff --git a/basic_plugins/hooks/__init__.py b/basic_plugins/hooks/__init__.py index 9ca94805..b236939d 100755 --- a/basic_plugins/hooks/__init__.py +++ b/basic_plugins/hooks/__init__.py @@ -1,13 +1,13 @@ from configs.config import Config - Config.add_plugin_config( "hook", "CHECK_NOTICE_INFO_CD", 300, name="基础hook配置", help_="群检测,个人权限检测等各种检测提示信息cd", - default_value=300 + default_value=300, + type=int, ) Config.add_plugin_config( @@ -15,7 +15,8 @@ Config.add_plugin_config( "MALICIOUS_BAN_TIME", 30, help_="恶意命令触发检测触发后ban的时长(分钟)", - default_value=30 + default_value=30, + type=int, ) Config.add_plugin_config( @@ -23,14 +24,10 @@ Config.add_plugin_config( "MALICIOUS_CHECK_TIME", 5, help_="恶意命令触发检测规定时间内(秒)", - default_value=5 + default_value=5, + type=int, ) Config.add_plugin_config( - "hook", - "MALICIOUS_BAN_COUNT", - 6, - help_="恶意命令触发检测最大触发次数", - default_value=6 + "hook", "MALICIOUS_BAN_COUNT", 6, help_="恶意命令触发检测最大触发次数", default_value=6, type=int ) - diff --git a/basic_plugins/init_plugin_config/init_plugin_info.py b/basic_plugins/init_plugin_config/init_plugin_info.py index 1048233d..1a56795a 100644 --- a/basic_plugins/init_plugin_config/init_plugin_info.py +++ b/basic_plugins/init_plugin_config/init_plugin_info.py @@ -1,14 +1,26 @@ import random from types import ModuleType -from typing import Any +from typing import Any, Dict from configs.config import Config from services import logger -from utils.manager import (plugin_data_manager, plugins2block_manager, - plugins2cd_manager, plugins2count_manager, - plugins2settings_manager, plugins_manager) -from utils.manager.models import (Plugin, PluginBlock, PluginCd, PluginCount, - PluginData, PluginSetting, PluginType) +from utils.manager import ( + plugin_data_manager, + plugins2block_manager, + plugins2cd_manager, + plugins2count_manager, + plugins2settings_manager, + plugins_manager, +) +from utils.manager.models import ( + Plugin, + PluginBlock, + PluginCd, + PluginCount, + PluginData, + PluginSetting, + PluginType, +) from utils.utils import get_matchers @@ -21,104 +33,115 @@ def get_attr(module: ModuleType, name: str, default: Any = None) -> Any: :param name: name :param default: default """ - return getattr(module, name) if hasattr(module, name) else default + return getattr(module, name, None) or default def init_plugin_info(): - for matcher in [x for x in get_matchers(True) if x.plugin]: + for matcher in [x for x in get_matchers(True)]: try: - plugin = matcher.plugin - metadata = plugin.metadata - extra = metadata.extra if metadata else {} - if hasattr(plugin, "module"): - module = plugin.module - plugin_model = matcher.plugin_name - plugin_name = ( - metadata.name - if metadata and metadata.name - else get_attr(module, "__zx_plugin_name__", matcher.plugin_name) - ) - if not plugin_name: - logger.warning(f"配置文件 模块:{plugin_model} 获取 plugin_name 失败...") - continue - if "[Admin]" in plugin_name: - plugin_type = PluginType.ADMIN - plugin_name = plugin_name.replace("[Admin]", "").strip() - elif "[Hidden]" in plugin_name: - plugin_type = PluginType.HIDDEN - plugin_name = plugin_name.replace("[Hidden]", "").strip() - elif "[Superuser]" in plugin_name: - plugin_type = PluginType.SUPERUSER - plugin_name = plugin_name.replace("[Superuser]", "").strip() - else: - plugin_type = PluginType.NORMAL - plugin_usage = ( - metadata.usage - if metadata and metadata.usage - else get_attr(module, "__plugin_usage__") - ) - plugin_des = ( - metadata.description - if metadata and metadata.description - else get_attr(module, "__plugin_des__") - ) - menu_type = get_attr(module, "__plugin_type__") or ("normal",) - plugin_setting = get_attr(module, "__plugin_settings__") - if plugin_setting: - plugin_setting = PluginSetting(**plugin_setting) - plugin_setting.plugin_type = menu_type - plugin_superuser_usage = get_attr(module, "__plugin_super_usage__") - plugin_task = get_attr(module, "__plugin_task__") - plugin_version = extra.get("__plugin_version__") or get_attr( - module, "__plugin_version__" - ) - plugin_author = extra.get("__plugin_author__") or get_attr( - module, "__plugin_author__" - ) - plugin_cd = get_attr(module, "__plugin_cd_limit__") - if plugin_cd: - plugin_cd = PluginCd(**plugin_cd) - plugin_block = get_attr(module, "__plugin_block_limit__") - if plugin_block: - plugin_block = PluginBlock(**plugin_block) - plugin_count = get_attr(module, "__plugin_count_limit__") - if plugin_count: - plugin_count = PluginCount(**plugin_count) - plugin_resources = get_attr(module, "__plugin_resources__") - plugin_configs = get_attr(module, "__plugin_configs__") - if settings := plugins2settings_manager.get(plugin_model): - plugin_setting = settings - if plugin_cd_limit := plugins2cd_manager.get(plugin_model): - plugin_cd = plugin_cd_limit - if plugin_block_limit := plugins2block_manager.get(plugin_model): - plugin_block = plugin_block_limit - if plugin_count_limit := plugins2count_manager.get(plugin_model): - plugin_count = plugin_count_limit - if plugin_cfg := Config.get(plugin_model): - plugin_configs = plugin_cfg - plugin_status = plugins_manager.get(plugin_model) - if not plugin_status: - plugin_status = Plugin(plugin_name=plugin_model) - plugin_status.author = plugin_author - plugin_status.version = plugin_version - plugin_data = PluginData( - model=plugin_model, - name=plugin_name.strip(), - plugin_type=plugin_type, - usage=plugin_usage, - superuser_usage=plugin_superuser_usage, - des=plugin_des, - task=plugin_task, - menu_type=menu_type, - plugin_setting=plugin_setting, - plugin_cd=plugin_cd, - plugin_block=plugin_block, - plugin_count=plugin_count, - plugin_resources=plugin_resources, - plugin_configs=plugin_configs, - plugin_status=plugin_status, - ) - plugin_data_manager.add_plugin_info(plugin_data) + if (plugin := matcher.plugin) and matcher.plugin_name: + metadata = plugin.metadata + extra = metadata.extra if metadata else {} + if hasattr(plugin, "module"): + module = plugin.module + plugin_model = matcher.plugin_name + plugin_name = ( + metadata.name + if metadata and metadata.name + else get_attr(module, "__zx_plugin_name__", matcher.plugin_name) + ) + if not plugin_name: + logger.warning(f"配置文件 模块:{plugin_model} 获取 plugin_name 失败...") + continue + if "[Admin]" in plugin_name: + plugin_type = PluginType.ADMIN + plugin_name = plugin_name.replace("[Admin]", "").strip() + elif "[Hidden]" in plugin_name: + plugin_type = PluginType.HIDDEN + plugin_name = plugin_name.replace("[Hidden]", "").strip() + elif "[Superuser]" in plugin_name: + plugin_type = PluginType.SUPERUSER + plugin_name = plugin_name.replace("[Superuser]", "").strip() + else: + plugin_type = PluginType.NORMAL + plugin_usage = ( + metadata.usage + if metadata and metadata.usage + else get_attr(module, "__plugin_usage__") + ) + plugin_des = ( + metadata.description + if metadata and metadata.description + else get_attr(module, "__plugin_des__") + ) + menu_type = get_attr(module, "__plugin_type__") or ("normal",) + plugin_setting = get_attr(module, "__plugin_settings__") + if plugin_setting: + plugin_setting = PluginSetting(**plugin_setting) + plugin_setting.plugin_type = menu_type + plugin_superuser_usage = get_attr(module, "__plugin_super_usage__") + plugin_task = get_attr(module, "__plugin_task__") + plugin_version = extra.get("__plugin_version__") or get_attr( + module, "__plugin_version__" + ) + plugin_author = extra.get("__plugin_author__") or get_attr( + module, "__plugin_author__" + ) + plugin_cd = get_attr(module, "__plugin_cd_limit__") + if plugin_cd: + plugin_cd = PluginCd(**plugin_cd) + plugin_block = get_attr(module, "__plugin_block_limit__") + if plugin_block: + plugin_block = PluginBlock(**plugin_block) + plugin_count = get_attr(module, "__plugin_count_limit__") + if plugin_count: + plugin_count = PluginCount(**plugin_count) + plugin_resources = get_attr(module, "__plugin_resources__") + plugin_configs = get_attr(module, "__plugin_configs__") + if settings := plugins2settings_manager.get(plugin_model): + plugin_setting = settings + if plugin_cd_limit := plugins2cd_manager.get(plugin_model): + plugin_cd = plugin_cd_limit + if plugin_block_limit := plugins2block_manager.get(plugin_model): + plugin_block = plugin_block_limit + if plugin_count_limit := plugins2count_manager.get(plugin_model): + plugin_count = plugin_count_limit + if plugin_cfg := Config.get(plugin_model): + if plugin_configs: + for config_name in plugin_configs: + config: Dict[str, Any] = plugin_configs[config_name] # type: ignore + Config.add_plugin_config( + plugin_model, + config_name, + config.get("value"), + help_=config.get("help"), + default_value=config.get("default_value"), + type=config.get("type") or str, + ) + plugin_configs = plugin_cfg.configs + plugin_status = plugins_manager.get(plugin_model) + if not plugin_status: + plugin_status = Plugin(plugin_name=plugin_model) + plugin_status.author = plugin_author + plugin_status.version = plugin_version + plugin_data = PluginData( + model=plugin_model, + name=plugin_name.strip(), + plugin_type=plugin_type, + usage=plugin_usage, + superuser_usage=plugin_superuser_usage, + des=plugin_des, + task=plugin_task, + menu_type=menu_type, + plugin_setting=plugin_setting, + plugin_cd=plugin_cd, + plugin_block=plugin_block, + plugin_count=plugin_count, + plugin_resources=plugin_resources, + plugin_configs=plugin_configs, # type: ignore + plugin_status=plugin_status, + ) + plugin_data_manager.add_plugin_info(plugin_data) except Exception as e: - logger.error(f"构造插件数据失败 {matcher.plugin_name} - {type(e)}:{e}") + logger.error(f"构造插件数据失败 {matcher.plugin_name}", e=e) diff --git a/basic_plugins/init_plugin_config/init_plugins_config.py b/basic_plugins/init_plugin_config/init_plugins_config.py index 0f12b630..b936a306 100755 --- a/basic_plugins/init_plugin_config/init_plugins_config.py +++ b/basic_plugins/init_plugin_config/init_plugins_config.py @@ -1,13 +1,14 @@ from pathlib import Path -from ruamel.yaml import round_trip_load, round_trip_dump, YAML -from utils.manager import admin_manager, plugins_manager, plugin_data_manager + +from ruamel import yaml +from ruamel.yaml import YAML, round_trip_dump, round_trip_load + from configs.config import Config +from configs.path_config import DATA_PATH from services.log import logger +from utils.manager import admin_manager, plugin_data_manager, plugins_manager from utils.text_utils import prompt2cn from utils.utils import get_matchers -from configs.path_config import DATA_PATH -from ruamel import yaml - _yaml = YAML(typ="safe") @@ -20,47 +21,60 @@ def init_plugins_config(): _data = Config.get_data() # 优先使用 metadata 数据 for matcher in get_matchers(True): - if plugin_data := plugin_data_manager.get(matcher.plugin_name): - # 插件配置版本更新或为Version为None或不在存储配置内,当使用metadata时,必定更新 - if plugin_data.plugin_configs and ( - isinstance(plugin_data.plugin_status.version, str) - or ( - plugin_data.plugin_status.version is None + if matcher.plugin_name: + if plugin_data := plugin_data_manager.get(matcher.plugin_name): + # 插件配置版本更新或为Version为None或不在存储配置内,当使用metadata时,必定更新 + version = plugin_data.plugin_status.version + config = _data.get(matcher.plugin_name) + plugin = plugins_manager.get(matcher.plugin_name) + if plugin_data.plugin_configs and ( + isinstance(version, str) or ( - _data.get(matcher.plugin_name) - and _data[matcher.plugin_name].keys() - != plugin_data.plugin_configs.keys() + version is None + or ( + config + and config.configs.keys() + != plugin_data.plugin_configs.keys() + ) + or version > int(plugin.version or 0) + or matcher.plugin_name not in _data.keys() ) - or plugin_data.plugin_status.version - > plugins_manager.get(matcher.plugin_name).version - or matcher.plugin_name not in _data.keys() - ) - ): - plugin_configs = plugin_data.plugin_configs - for key in plugin_configs: - if isinstance(plugin_data.plugin_configs[key], dict): + ): + plugin_configs = plugin_data.plugin_configs + for key in plugin_configs: + if isinstance(plugin_data.plugin_configs[key], dict): + Config.add_plugin_config( + matcher.plugin_name, + key, + plugin_configs[key].get("value"), + help_=plugin_configs[key].get("help"), + default_value=plugin_configs[key].get("default_value"), + _override=True, + type=plugin_configs[key].get("type") or str, + ) + else: + config = plugin_configs[key] + Config.add_plugin_config( + matcher.plugin_name, + key, + config.value, + name=config.name, + help_=config.help, + default_value=config.default_value, + _override=True, + type=config.type or str, + ) + elif plugin_configs := _data.get(matcher.plugin_name): + for key in plugin_configs.configs: Config.add_plugin_config( matcher.plugin_name, key, - plugin_configs[key].get("value"), - help_=plugin_configs[key].get("help"), - default_value=plugin_configs[key].get("default_value"), + plugin_configs.configs[key].value, + help_=plugin_configs.configs[key].help, + default_value=plugin_configs.configs[key].default_value, _override=True, + type=plugin_configs.configs[key].type, ) - else: - Config.add_plugin_config( - matcher.plugin_name, key, plugin_configs[key] - ) - elif plugin_configs := _data.get(matcher.plugin_name): - for key in plugin_configs: - Config.add_plugin_config( - matcher.plugin_name, - key, - plugin_configs[key]["value"], - help_=plugin_configs[key]["help"], - default_value=plugin_configs[key]["default_value"], - _override=True, - ) if not Config.is_empty(): Config.save() _data = round_trip_load(open(plugins2config_file, encoding="utf8")) @@ -96,7 +110,7 @@ def _replace_config(): # 数据替换 for plugin in Config.keys(): _tmp_data[plugin] = {} - for k in Config[plugin].keys(): + for k in Config[plugin].configs.keys(): try: if _data.get(plugin) and k in _data[plugin].keys(): Config.set_config(plugin, k, _data[plugin][k]) @@ -126,14 +140,14 @@ def _replace_config(): rst = "" plugin_name = None try: - plugin_data = Config.get(plugin) - for x in list(Config.get(plugin).keys()): - try: - _x = plugin_data[x].get("name") - if _x: - plugin_name = _x - except AttributeError: - pass + if config_group := Config.get(plugin): + for key in list(config_group.configs.keys()): + try: + if config := config_group.configs[key]: + if config.name: + plugin_name = config.name + except AttributeError: + pass except (KeyError, AttributeError): plugin_name = None if not plugin_name: @@ -149,7 +163,7 @@ def _replace_config(): ) rst += plugin_name + "\n" for k in _data[plugin].keys(): - rst += f'{k}: {Config[plugin][k]["help"]}' + "\n" + rst += f"{k}: {Config[plugin].configs[k].help}" + "\n" _data[plugin].yaml_set_start_comment(rst[:-1], indent=2) with open(Path() / "configs" / "config.yaml", "w", encoding="utf8") as wf: round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True) diff --git a/basic_plugins/invite_manager/__init__.py b/basic_plugins/invite_manager/__init__.py index 4a07128f..a9becf02 100755 --- a/basic_plugins/invite_manager/__init__.py +++ b/basic_plugins/invite_manager/__init__.py @@ -25,7 +25,12 @@ __zx_plugin_name__ = "好友群聊处理请求 [Hidden]" __plugin_version__ = 0.1 __plugin_author__ = "HibiKier" __plugin_configs__ = { - "AUTO_ADD_FRIEND": {"value": False, "help": "是否自动同意好友添加", "default_value": False} + "AUTO_ADD_FRIEND": { + "value": False, + "help": "是否自动同意好友添加", + "default_value": False, + "type": bool, + } } friend_req = on_request(priority=5, block=True) diff --git a/basic_plugins/nickname.py b/basic_plugins/nickname.py index 74ed4542..46341207 100755 --- a/basic_plugins/nickname.py +++ b/basic_plugins/nickname.py @@ -1,5 +1,5 @@ import random -from typing import Any, Tuple +from typing import Any, List, Tuple from nonebot import on_command, on_regex from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent @@ -39,6 +39,7 @@ __plugin_configs__ = { "value": ["爸", "爹", "爷", "父"], "help": "昵称所屏蔽的关键词,已设置的昵称会被替换为 *,未设置的昵称会在设置时提示", "default_value": None, + "type": List[str], } } diff --git a/basic_plugins/shop/__init__.py b/basic_plugins/shop/__init__.py index 58dac39a..f6a49be9 100644 --- a/basic_plugins/shop/__init__.py +++ b/basic_plugins/shop/__init__.py @@ -10,33 +10,18 @@ driver: Driver = nonebot.get_driver() Config.add_plugin_config( - "shop", "IMPORT_DEFAULT_SHOP_GOODS", True, help_="导入商店自带的三个商品", default_value=True + "shop", + "IMPORT_DEFAULT_SHOP_GOODS", + True, + help_="导入商店自带的三个商品", + default_value=True, + type=bool, ) nonebot.load_plugins(str(Path(__file__).parent.resolve())) -@shop_register( - name=("好感度双倍加持卡Ⅰ", "好感度双倍加持卡Ⅱ", "好感度双倍加持卡Ⅲ"), - price=(30, 150, 250), - des=( - "下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)", - "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)", - "下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)", - ), - load_status=bool(Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS")), - icon=( - "favorability_card_1.png", - "favorability_card_2.png", - "favorability_card_3.png", - ), - **{"好感度双倍加持卡Ⅰ_prob": 0.1, "好感度双倍加持卡Ⅱ_prob": 0.2, "好感度双倍加持卡Ⅲ_prob": 0.3}, -) -async def sign_card(user_id: int, group_id: int): - pass - - @driver.on_bot_connect async def _(): await shop_register.load_register() diff --git a/basic_plugins/super_cmd/reload_setting.py b/basic_plugins/super_cmd/reload_setting.py index c57c77a0..c6460b40 100755 --- a/basic_plugins/super_cmd/reload_setting.py +++ b/basic_plugins/super_cmd/reload_setting.py @@ -30,8 +30,8 @@ __plugin_cmd__ = [ __plugin_version__ = 0.2 __plugin_author__ = "HibiKier" __plugin_configs__ = { - "AUTO_RELOAD": {"value": False, "help": "自动重载配置文件", "default_value": False}, - "AUTO_RELOAD_TIME": {"value": 180, "help": "控制自动重载配置文件时长", "default_value": 180}, + "AUTO_RELOAD": {"value": False, "help": "自动重载配置文件", "default_value": False, "type": bool}, + "AUTO_RELOAD_TIME": {"value": 180, "help": "控制自动重载配置文件时长", "default_value": 180, "type": int}, } diff --git a/configs/utils/__init__.py b/configs/utils/__init__.py index 79641dd7..9b998ca0 100644 --- a/configs/utils/__init__.py +++ b/configs/utils/__init__.py @@ -1,11 +1,53 @@ import copy from pathlib import Path -from typing import Any, Optional, Union +from typing import Any, Callable, Dict, Optional, Type, Union +import cattrs +from pydantic import BaseModel from ruamel import yaml from ruamel.yaml import YAML from ruamel.yaml.scanner import ScannerError +from services.log import logger + + +class Config(BaseModel): + + """ + 配置项 + """ + + value: Any + """配置项值""" + name: Optional[str] + """插件名称""" + help: Optional[str] + """配置注解""" + default_value: Optional[Any] = None + """默认值""" + level_module: Optional[str] + """受权限模块""" + type: Any = None + """参数类型""" + arg_parser: Optional[Callable] = None + """参数解析""" + + +class ConfigGroup(BaseModel): + + """ + 配置组 + """ + + module: str + """模块名""" + configs: Dict[str, Config] = {} + """配置项列表""" + + +class NoSuchConfig(Exception): + pass + class ConfigsManager: """ @@ -13,35 +55,25 @@ class ConfigsManager: """ def __init__(self, file: Path): - self._data: dict = {} + self._data: Dict[str, ConfigGroup] = {} self._simple_data: dict = {} self._admin_level_data = [] self._simple_file = Path() / "configs" / "config.yaml" + _yaml = YAML() if file: file.parent.mkdir(exist_ok=True, parents=True) self.file = file - _yaml = YAML() - if file.exists(): - with open(file, "r", encoding="utf8") as f: - self._data = _yaml.load(f) - if not self._data: - self.file.unlink() - raise ValueError( - "配置文件为空!\n" - "***********************************************************\n" - "****** 配置文件 plugins2config.yaml 为空,已删除,请重启 ******\n" - "***********************************************************" - ) - if self._simple_file.exists(): - try: - with open(self._simple_file, "r", encoding="utf8") as f: - self._simple_data = _yaml.load(f) - except ScannerError as e: - raise ScannerError( - f"{e}\n**********************************************\n" - f"****** 可能为config.yaml配置文件填写不规范 ******\n" - f"**********************************************" - ) + self.load_data() + if self._simple_file.exists(): + try: + with open(self._simple_file, "r", encoding="utf8") as f: + self._simple_data = _yaml.load(f) + except ScannerError as e: + raise ScannerError( + f"{e}\n**********************************************\n" + f"****** 可能为config.yaml配置文件填写不规范 ******\n" + f"**********************************************" + ) def add_plugin_config( self, @@ -52,6 +84,8 @@ class ConfigsManager: name: Optional[str] = None, help_: Optional[str] = None, default_value: Optional[Any] = None, + type: Optional[Type] = str, + arg_parser: Optional[Callable] = None, _override: bool = False, ): """ @@ -62,41 +96,49 @@ class ConfigsManager: :param name: 插件名称 :param help_: 配置注解 :param default_value: 默认值 - :param _override: 覆盖前值 + :param _override: 强制覆盖值 """ - if ( - not (module in self._data.keys() and self._data[module].get(key)) - or _override - ): + if not module or not key: + raise ValueError("add_plugin_config: module和key不能为为空") + if module in self._data and (config := self._data[module].configs.get(key)): + config.help = help_ + config.arg_parser = arg_parser + config.type = type + if _override: + config.value = value + config.name = name + config.default_value = default_value + else: _module = None if ":" in module: - module = module.split(":") - _module = module[-1] - module = module[0] + module_split = module.split(":") + if len(module_split) < 2: + raise ValueError(f"module: {module} 填写错误") + _module = module_split[-1] + module = module_split[0] if "[LEVEL]" in key and _module: key = key.replace("[LEVEL]", "").strip() self._admin_level_data.append((_module, value)) - if self._data.get(module) is None: - self._data[module] = {} key = key.upper() - self._data[module][key] = { - "value": value, - "name": name.strip() if isinstance(name, str) else name, - "help": help_.strip() if isinstance(help_, str) else help_, - "default_value": default_value, - "level_module": _module, - } + if not self._data.get(module): + self._data[module] = ConfigGroup(module=module) + self._data[module].configs[key] = Config( + value=value, + name=name, + help=help_, + default_value=default_value, + level_module=_module, + type=type, + ) - def remove_plugin_config(self, module: str): - """ - 为插件删除一个配置 - :param module: 模块名 - """ - if module in self._data.keys(): - del self._data[module] - self.save() - - def set_config(self, module: str, key: str, value: Any, auto_save: bool = False, save_simple_data: bool = True): + def set_config( + self, + module: str, + key: str, + value: Any, + auto_save: bool = False, + save_simple_data: bool = True, + ): """ 设置配置值 :param module: 模块名 @@ -105,40 +147,16 @@ class ConfigsManager: :param auto_save: 自动保存 :param save_simple_data: 保存至config.yaml """ - if module in self._data.keys(): + if module in self._data: if ( - self._data[module].get(key) is not None - and self._data[module][key] != value + self._data[module].configs.get(key) + and self._data[module].configs[key] != value ): - self._data[module][key]["value"] = value + self._data[module].configs[key].value = value self._simple_data[module][key] = value if auto_save: self.save(save_simple_data=save_simple_data) - def set_help(self, module: str, key: str, help_: str): - """ - 设置配置注释 - :param module: 模块名 - :param key: 配置名称 - :param help_: 注释文本 - """ - if module in self._data.keys(): - if self._data[module].get(key) is not None: - self._data[module][key]["help"] = help_ - self.save() - - def set_default_value(self, module: str, key: str, value: Any): - """ - 设置配置默认值 - :param module: 模块名 - :param key: 配置名称 - :param value: 值 - """ - if module in self._data.keys(): - if self._data[module].get(key) is not None: - self._data[module][key]["default_value"] = value - self.save() - def get_config( self, module: str, key: str, default: Optional[Any] = None ) -> Optional[Any]: @@ -148,37 +166,68 @@ class ConfigsManager: :param key: 配置名称 :param default: 没有key值内容的默认返回值 """ + logger.debug( + f"尝试获取配置 MODULE: [{module}] | KEY: [{key}]" + ) key = key.upper() + value = None if module in self._data.keys(): - for key in [key, f"{key} [LEVEL]"]: - if self._data[module].get(key) is not None: - if self._data[module][key]["value"] is None: - return self._data[module][key]["default_value"] - return self._data[module][key]["value"] - if default is not None: - return default - return None + config = self._data[module].configs.get(key) + if not config: + config = self._data[module].configs.get(f"{key} [LEVEL]") + if not config: + raise NoSuchConfig(f"未查询到配置项 MODULE: [ {module} ] | KEY: [ {key} ]") + if config.arg_parser: + value = config.arg_parser(value or config.default_value) + else: + try: + if config.value is not None: + value = ( + cattrs.structure(config.value, config.type) + if config.type + else config.value + ) + else: + if config.default_value is not None: + value = ( + cattrs.structure(config.default_value, config.type) + if config.type + else config.default_value + ) + except Exception as e: + logger.warning( + f"配置项类型转换 MODULE: [{module}] | KEY: [{key}]", + e=e, + ) + value = config.value or config.default_value + if not value: + value = default + logger.debug( + f"获取配置 MODULE: [{module}] | KEY: [{key}] -> [{value}]" + ) + return value def get_level2module(self, module: str, key: str) -> Optional[str]: """ - 获取指定key所绑定的module,一般为权限等级 + 获取指定key所绑定的module,一般为权限等级 :param module: 模块名 :param key: 配置名称 :return: """ if self._data.get(module) is not None: - if self._data[module].get(key) is not None: - return self._data[module][key].get("level_module") + if config := self._data[module].configs.get(key): + return config.level_module - def get(self, key: str): + def get(self, key: str) -> Optional[ConfigGroup]: """ 获取插件配置数据 :param key: 名称 """ - if key in self._data.keys(): - return self._data[key] + return self._data.get(key) - def save(self, path: Union[str, Path] = None, save_simple_data: bool = False): + def save( + self, path: Optional[Union[str, Path]] = None, save_simple_data: bool = False + ): """ 保存数据 :param path: 路径 @@ -193,10 +242,17 @@ class ConfigsManager: Dumper=yaml.RoundTripDumper, allow_unicode=True, ) - path = path if path else self.file + path = path or self.file + data = {} + for module in self._data: + data[module] = {} + for config in self._data[module].configs: + value = self._data[module].configs[config].dict() + del value["type"] + data[module][config] = value with open(path, "w", encoding="utf8") as f: yaml.dump( - self._data, f, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True + data, f, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True ) def reload(self): @@ -209,16 +265,46 @@ class ConfigsManager: self._simple_data = _yaml.load(f) for key in self._simple_data.keys(): for k in self._simple_data[key].keys(): - self._data[key][k]["value"] = self._simple_data[key][k] + self._data[key].configs[k].value = self._simple_data[key][k] self.save() + def load_data(self): + """ + 加载数据 + + Raises: + ValueError: _description_ + """ + if self.file.exists(): + _yaml = YAML() + with open(self.file, "r", encoding="utf8") as f: + temp_data = _yaml.load(f) + if not temp_data: + self.file.unlink() + raise ValueError( + "配置文件为空!\n" + "***********************************************************\n" + "****** 配置文件 plugins2config.yaml 为空,已删除,请重启 ******\n" + "***********************************************************" + ) + count = 0 + for module in temp_data: + config_group = ConfigGroup(module=module) + for config in temp_data[module]: + config_group.configs[config] = Config(**temp_data[module][config]) + count += 1 + self._data[module] = config_group + logger.info( + f"加载配置完成,共加载 {len(temp_data)} 个配置组及对应 {count} 个配置项" + ) + def get_admin_level_data(self): """ 获取管理插件等级 """ return self._admin_level_data - def get_data(self): + def get_data(self) -> Dict[str, ConfigGroup]: return copy.deepcopy(self._data) def is_empty(self) -> bool: diff --git a/plugins/ai/__init__.py b/plugins/ai/__init__.py index 361f5e34..15ce091c 100755 --- a/plugins/ai/__init__.py +++ b/plugins/ai/__init__.py @@ -1,3 +1,5 @@ +from typing import List + from nonebot import on_message from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent from nonebot.rule import to_me @@ -22,12 +24,18 @@ __plugin_settings__ = { "cmd": ["Ai", "ai", "AI", "aI"], } __plugin_configs__ = { - "TL_KEY": {"value": [], "help": "图灵Key"}, - "ALAPI_AI_CHECK": {"value": False, "help": "是否检测青云客骂娘回复", "default_value": False}, + "TL_KEY": {"value": [], "help": "图灵Key", "type": List[str]}, + "ALAPI_AI_CHECK": { + "value": False, + "help": "是否检测青云客骂娘回复", + "default_value": False, + "type": bool, + }, "TEXT_FILTER": { "value": ["鸡", "口交"], "help": "文本过滤器,将敏感词更改为*", "default_value": [], + "type": List[str], }, } Config.add_plugin_config( diff --git a/plugins/alapi/__init__.py b/plugins/alapi/__init__.py index 2135b636..749529c7 100755 --- a/plugins/alapi/__init__.py +++ b/plugins/alapi/__init__.py @@ -1,14 +1,11 @@ -from configs.config import Config +from pathlib import Path + import nonebot +from configs.config import Config Config.add_plugin_config( - "alapi", - "ALAPI_TOKEN", - None, - help_="在https://admin.alapi.cn/user/login登录后获取token" + "alapi", "ALAPI_TOKEN", None, help_="在https://admin.alapi.cn/user/login登录后获取token" ) - -nonebot.load_plugins("plugins/alapi") - +nonebot.load_plugins(str(Path(__file__).parent.resolve())) diff --git a/plugins/bilibili_sub/__init__.py b/plugins/bilibili_sub/__init__.py index 83f30471..e936addb 100755 --- a/plugins/bilibili_sub/__init__.py +++ b/plugins/bilibili_sub/__init__.py @@ -55,16 +55,19 @@ __plugin_configs__ = { "value": 5, "help": "群内bilibili订阅需要管理的权限", "default_value": 5, + "type": int, }, "LIVE_MSG_AT_ALL": { "value": False, "help": "直播提醒是否AT全体(仅在真寻是管理员时生效)", "default_value": False, + "type": bool, }, "UP_MSG_AT_ALL": { "value": False, "help": "UP动态投稿提醒是否AT全体(仅在真寻是管理员时生效)", "default_value": False, + "type": bool, }, } diff --git a/plugins/black_word/__init__.py b/plugins/black_word/__init__.py index 04372d59..3547a51d 100644 --- a/plugins/black_word/__init__.py +++ b/plugins/black_word/__init__.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import Any, Tuple +from typing import Any, List, Tuple from nonebot import on_command, on_message, on_regex from nonebot.adapters.onebot.v11 import ( @@ -56,7 +56,13 @@ __plugin_settings__ = { Config.add_plugin_config( - "black_word", "CYCLE_DAYS", 30, name="敏感词检测与惩罚", help_="黑名单词汇记录周期", default_value=30 + "black_word", + "CYCLE_DAYS", + 30, + name="敏感词检测与惩罚", + help_="黑名单词汇记录周期", + default_value=30, + type=int, ) Config.add_plugin_config( @@ -65,10 +71,11 @@ Config.add_plugin_config( [5, 1, 1, 1, 1], help_="各个级别惩罚的容忍次数,依次为:1, 2, 3, 4, 5", default_value=[5, 1, 1, 1, 1], + type=List[int], ) Config.add_plugin_config( - "black_word", "AUTO_PUNISH", True, help_="是否启动自动惩罚机制", default_value=True + "black_word", "AUTO_PUNISH", True, help_="是否启动自动惩罚机制", default_value=True, type=bool ) # Config.add_plugin_config( @@ -81,6 +88,7 @@ Config.add_plugin_config( 360, help_="Union[int, List[int, int]]Ban时长(分钟),四级惩罚,可以为指定数字或指定列表区间(随机),例如 [30, 360]", default_value=360, + type=int, ) Config.add_plugin_config( @@ -89,6 +97,7 @@ Config.add_plugin_config( 7, help_="Union[int, List[int, int]]Ban时长(天),三级惩罚,可以为指定数字或指定列表区间(随机),例如 [7, 30]", default_value=360, + type=int, ) Config.add_plugin_config( @@ -105,6 +114,7 @@ Config.add_plugin_config( True, help_="自动提级机制,当周期内处罚次数大于某一特定值就提升惩罚等级", default_value=True, + type=bool, ) Config.add_plugin_config( @@ -113,6 +123,7 @@ Config.add_plugin_config( 3, help_="在CYCLE_DAYS周期内触发指定惩罚次数后提升惩罚等级", default_value=3, + type=int, ) Config.add_plugin_config( @@ -121,6 +132,7 @@ Config.add_plugin_config( False, help_="当未检测到已收录的敏感词时,开启ALAPI文本检测并将疑似文本发送给超级用户", default_value=False, + type=bool, ) Config.add_plugin_config( @@ -129,6 +141,7 @@ Config.add_plugin_config( True, help_="当文本包含任意敏感词时,停止向下级插件传递,即不触发ai", default_value=True, + type=bool, ) message_matcher = on_message(priority=1, block=False) diff --git a/plugins/bt/__init__.py b/plugins/bt/__init__.py index 3c87235e..d2571441 100755 --- a/plugins/bt/__init__.py +++ b/plugins/bt/__init__.py @@ -1,13 +1,16 @@ -from nonebot import on_command -from .data_source import get_bt_info -from services.log import logger -from nonebot.adapters.onebot.v11 import PrivateMessageEvent, Message -from nonebot.adapters.onebot.v11.permission import PRIVATE from asyncio.exceptions import TimeoutError -from utils.utils import is_number -from nonebot.params import CommandArg, ArgStr + +from nonebot import on_command +from nonebot.adapters.onebot.v11 import Message, PrivateMessageEvent +from nonebot.adapters.onebot.v11.permission import PRIVATE +from nonebot.params import ArgStr, CommandArg from nonebot.typing import T_State +from services.log import logger +from utils.utils import is_number + +from .data_source import get_bt_info + __zx_plugin_name__ = "磁力搜索" __plugin_usage__ = """ usage: @@ -34,6 +37,7 @@ __plugin_configs__ = { "value": 10, "help": "单次BT搜索返回最大消息数量", "default_value": 10, + "type": int, } } diff --git a/plugins/check_zhenxun_update/__init__.py b/plugins/check_zhenxun_update/__init__.py index 91ee819d..6344bd36 100755 --- a/plugins/check_zhenxun_update/__init__.py +++ b/plugins/check_zhenxun_update/__init__.py @@ -1,16 +1,18 @@ -from nonebot.adapters.onebot.v11 import Bot, MessageEvent -from nonebot.permission import SUPERUSER -from nonebot import on_command -from .data_source import check_update, get_latest_version_data -from services.log import logger -from utils.utils import scheduler, get_bot -from pathlib import Path -from configs.config import NICKNAME, Config -from nonebot.rule import to_me -from nonebot.params import ArgStr -import platform import os +import platform +from pathlib import Path +from nonebot import on_command +from nonebot.adapters.onebot.v11 import Bot, MessageEvent +from nonebot.params import ArgStr +from nonebot.permission import SUPERUSER +from nonebot.rule import to_me + +from configs.config import NICKNAME, Config +from services.log import logger +from utils.utils import get_bot, scheduler + +from .data_source import check_update, get_latest_version_data __zx_plugin_name__ = "自动更新 [Superuser]" __plugin_usage__ = """ @@ -29,12 +31,14 @@ __plugin_configs__ = { "value": True, "help": "真寻是否检测版本状态", "default": True, + "type": bool, }, "AUTO_UPDATE_ZHENXUN": { "value": False, "help": "真寻是否自动检查更新", "default": False, - } + "type": bool, + }, } update_zhenxun = on_command("检查更新真寻", permission=SUPERUSER, priority=1, block=True) @@ -66,9 +70,7 @@ async def _(bot: Bot, event: MessageEvent): ) else: if code == 200: - await bot.send_private_msg( - user_id=event.user_id, message=f"更新完毕,请重启真寻...." - ) + await bot.send_private_msg(user_id=event.user_id, message=f"更新完毕,请重启真寻....") @restart.got("flag", prompt=f"确定是否重启{NICKNAME}?确定请回复[是|好|确定](重启失败咱们将失去联系,请谨慎!)") @@ -78,6 +80,7 @@ async def _(flag: str = ArgStr("flag")): open("is_restart", "w") if str(platform.system()).lower() == "windows": import sys + python = sys.executable os.execl(python, python, *sys.argv) else: @@ -109,8 +112,7 @@ async def _(): bot = get_bot() await bot.send_private_msg( user_id=int(list(bot.config.superusers)[0]), - message=f"检测到真寻版本更新\n" - f"当前版本:{_version},最新版本:{latest_version}", + message=f"检测到真寻版本更新\n" f"当前版本:{_version},最新版本:{latest_version}", ) if Config.get_config("check_zhenxun_update", "AUTO_UPDATE_ZHENXUN"): try: diff --git a/plugins/coser/__init__.py b/plugins/coser/__init__.py index 9e0eb42c..925af3c2 100755 --- a/plugins/coser/__init__.py +++ b/plugins/coser/__init__.py @@ -1,15 +1,16 @@ -from typing import Tuple, Any +import time +from typing import Any, Tuple from nonebot import on_regex -from nonebot.params import RegexGroup -from configs.path_config import TEMP_PATH from nonebot.adapters.onebot.v11 import Bot, MessageEvent -import time -from utils.http_utils import AsyncHttpx -from utils.message_builder import image -from services.log import logger -from utils.manager import withdraw_message_manager +from nonebot.params import RegexGroup + from configs.config import Config +from configs.path_config import TEMP_PATH +from services.log import logger +from utils.http_utils import AsyncHttpx +from utils.manager import withdraw_message_manager +from utils.message_builder import image __zx_plugin_name__ = "coser" __plugin_usage__ = """ @@ -35,6 +36,7 @@ __plugin_configs__ = { "value": (0, 1), "help": "自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)", "default_value": (0, 1), + "type": Tuple[int, int], }, } @@ -49,7 +51,7 @@ url = "https://picture.yinux.workers.dev" async def _(event: MessageEvent, reg_group: Tuple[Any, ...] = RegexGroup()): num = reg_group[0] or 1 for _ in range(int(num)): - path = TEMP_PATH / f'cos_cc{int(time.time())}.jpeg' + path = TEMP_PATH / f"cos_cc{int(time.time())}.jpeg" try: await AsyncHttpx.download_file(url, path) msg_id = await coser.send(image(path)) diff --git a/plugins/draw_card/config.py b/plugins/draw_card/config.py index c166c591..d809b1fd 100644 --- a/plugins/draw_card/config.py +++ b/plugins/draw_card/config.py @@ -1,9 +1,11 @@ -import nonebot from pathlib import Path + +import nonebot from nonebot.log import logger from pydantic import BaseModel, Extra, ValidationError + from configs.config import Config as AConfig -from configs.path_config import IMAGE_PATH, DATA_PATH +from configs.path_config import DATA_PATH, IMAGE_PATH try: import ujson as json @@ -147,9 +149,20 @@ for game_flag, game_name in zip( "FGO_FLAG", "ONMYOJI_FLAG", "PCR_TAI", - "BA_FLAG" + "BA_FLAG", + ], + [ + "明日方舟", + "原神", + "赛马娘", + "坎公骑冠剑", + "公主连结", + "碧蓝航线", + "命运-冠位指定(FGO)", + "阴阳师", + "pcr台服卡池", + "碧蓝档案", ], - ["明日方舟", "原神", "赛马娘", "坎公骑冠剑", "公主连结", "碧蓝航线", "命运-冠位指定(FGO)", "阴阳师", "pcr台服卡池", "碧蓝档案"], ): AConfig.add_plugin_config( "draw_card", @@ -158,9 +171,10 @@ for game_flag, game_name in zip( name="游戏抽卡", help_=f"{game_name} 抽卡开关", default_value=True, + type=bool, ) AConfig.add_plugin_config( - "draw_card", "SEMAPHORE", 5, help_=f"异步数据下载数量限制", default_value=5 + "draw_card", "SEMAPHORE", 5, help_=f"异步数据下载数量限制", default_value=5, type=int ) diff --git a/plugins/epic/__init__.py b/plugins/epic/__init__.py index 62cb170d..e3fc54e6 100755 --- a/plugins/epic/__init__.py +++ b/plugins/epic/__init__.py @@ -1,11 +1,13 @@ from nonebot import on_regex -from services.log import logger -from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent +from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent from nonebot.typing import T_State -from utils.utils import scheduler, get_bot -from .data_source import get_epic_free -from utils.manager import group_manager + from configs.config import Config +from services.log import logger +from utils.manager import group_manager +from utils.utils import get_bot, scheduler + +from .data_source import get_epic_free __zx_plugin_name__ = "epic免费游戏" __plugin_usage__ = """ @@ -31,6 +33,7 @@ Config.add_plugin_config( True, help_="被动 epic免费游戏 进群默认开关状态", default_value=True, + type=bool, ) epic = on_regex("^epic$", priority=5, block=True) diff --git a/plugins/fudu.py b/plugins/fudu.py index 7688df26..972f5f24 100755 --- a/plugins/fudu.py +++ b/plugins/fudu.py @@ -1,16 +1,16 @@ -from utils.image_utils import get_img_hash -from nonebot.adapters.onebot.v11.permission import GROUP -from configs.path_config import TEMP_PATH import random -from utils.message_builder import image -from nonebot import on_message -from utils.utils import get_message_img, get_message_text -from nonebot.adapters.onebot.v11 import GroupMessageEvent -from configs.config import Config -from utils.http_utils import AsyncHttpx -from services.log import logger -from configs.config import NICKNAME +from nonebot import on_message +from nonebot.adapters.onebot.v11 import GroupMessageEvent +from nonebot.adapters.onebot.v11.permission import GROUP + +from configs.config import NICKNAME, Config +from configs.path_config import TEMP_PATH +from services.log import logger +from utils.http_utils import AsyncHttpx +from utils.image_utils import get_img_hash +from utils.message_builder import image +from utils.utils import get_message_img, get_message_text __zx_plugin_name__ = "复读" __plugin_usage__ = """ @@ -23,14 +23,15 @@ __plugin_version__ = 0.1 __plugin_author__ = "HibiKier" __plugin_task__ = {"fudu": "复读"} __plugin_configs__ = { - "FUDU_PROBABILITY": {"value": 0.7, "help": "复读概率", "default_value": 0.7} + "FUDU_PROBABILITY": { + "value": 0.7, + "help": "复读概率", + "default_value": 0.7, + "type": float, + } } Config.add_plugin_config( - "_task", - "DEFAULT_FUDU", - True, - help_="被动 复读 进群默认开关状态", - default_value=True, + "_task", "DEFAULT_FUDU", True, help_="被动 复读 进群默认开关状态", default_value=True, type=bool ) @@ -90,7 +91,7 @@ async def _(event: GroupMessageEvent): if not img and not msg: return if img: - img_hash = await get_fudu_img_hash(img[0],event.group_id) + img_hash = await get_fudu_img_hash(img[0], event.group_id) else: img_hash = "" add_msg = msg + "|-|" + img_hash @@ -107,7 +108,7 @@ async def _(event: GroupMessageEvent): ) and not _fudu_list.is_repeater(event.group_id): if random.random() < 0.2: if msg.endswith("打断施法!"): - await fudu.finish("[[_task|fudu]]打断" + msg) + await fudu.finish("[[_task|fudu]]打断" + msg) else: await fudu.finish("[[_task|fudu]]打断施法!") _fudu_list.set_repeater(event.group_id) diff --git a/plugins/genshin/almanac/__init__.py b/plugins/genshin/almanac/__init__.py index a1f29e7f..ecbe8e75 100755 --- a/plugins/genshin/almanac/__init__.py +++ b/plugins/genshin/almanac/__init__.py @@ -1,7 +1,8 @@ -from configs.config import Config -from configs.path_config import IMAGE_PATH from nonebot import on_command from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent + +from configs.config import Config +from configs.path_config import IMAGE_PATH from services.log import logger from utils.manager import group_manager from utils.message_builder import image @@ -35,6 +36,7 @@ Config.add_plugin_config( True, help_="被动 原神黄历提醒 进群默认开关状态", default_value=True, + type=bool, ) almanac = on_command("原神黄历", priority=5, block=True) diff --git a/plugins/genshin/query_user/resin_remind/__init__.py b/plugins/genshin/query_user/resin_remind/__init__.py index 60c1984d..de4452c0 100644 --- a/plugins/genshin/query_user/resin_remind/__init__.py +++ b/plugins/genshin/query_user/resin_remind/__init__.py @@ -37,11 +37,13 @@ __plugin_configs__ = { "value": True, "help": "当请求连续三次失败时,关闭用户的树脂提醒", "default_value": True, + "type": bool, }, "CUSTOM_RESIN_OVERFLOW_REMIND": { "value": 20, "help": "自定义树脂溢出指定数量时的提醒,空值是为关闭", "default_value": None, + "type": int, }, } diff --git a/plugins/image_management/__init__.py b/plugins/image_management/__init__.py index 92d70819..16a9738f 100755 --- a/plugins/image_management/__init__.py +++ b/plugins/image_management/__init__.py @@ -1,8 +1,10 @@ -from configs.config import Config -from configs.path_config import IMAGE_PATH from pathlib import Path +from typing import List, Tuple + import nonebot +from configs.config import Config +from configs.path_config import IMAGE_PATH Config.add_plugin_config( "image_management", @@ -11,6 +13,7 @@ Config.add_plugin_config( name="图库操作", help_="公开图库列表,可自定义添加 [如果含有send_setu插件,请不要添加色图库]", default_value=[], + type=List[str], ) Config.add_plugin_config( @@ -20,6 +23,7 @@ Config.add_plugin_config( name="图库操作", help_="自动撤回,参1:延迟撤回发送图库图片的时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)", default_value=(0, 1), + type=Tuple[int, int], ) Config.add_plugin_config( @@ -28,6 +32,7 @@ Config.add_plugin_config( 7, help_="删除图库图片需要的管理员等级", default_value=7, + type=int, ) Config.add_plugin_config( @@ -36,6 +41,7 @@ Config.add_plugin_config( 7, help_="移动图库图片需要的管理员等级", default_value=7, + type=int, ) Config.add_plugin_config( @@ -44,6 +50,7 @@ Config.add_plugin_config( 6, help_="上传图库图片需要的管理员等级", default_value=6, + type=int, ) Config.add_plugin_config( @@ -51,11 +58,12 @@ Config.add_plugin_config( "SHOW_ID", True, help_="是否消息显示图片下标id", - default_value=True + default_value=True, + type=bool, ) (IMAGE_PATH / "image_management").mkdir(parents=True, exist_ok=True) -nonebot.load_plugins("plugins/image_management") +nonebot.load_plugins(str(Path(__file__).parent.resolve())) diff --git a/plugins/image_management/send_image/__init__.py b/plugins/image_management/send_image/__init__.py index 827201c4..4adb9390 100755 --- a/plugins/image_management/send_image/__init__.py +++ b/plugins/image_management/send_image/__init__.py @@ -13,11 +13,6 @@ from utils.utils import FreqLimiter, cn2py, get_message_text, is_number from .rule import rule -try: - import ujson as json -except ModuleNotFoundError: - import json - __zx_plugin_name__ = "本地图库" __plugin_usage__ = f""" usage: @@ -36,16 +31,12 @@ __plugin_settings__ = { "level": 5, "default_status": True, "limit_superuser": False, - "cmd": ["发送图片"] + Config.get_config("image_management", "IMAGE_DIR_LIST"), + "cmd": ["发送图片"] + (Config.get_config("image_management", "IMAGE_DIR_LIST") or []), } __plugin_resources__ = {"pa": IMAGE_PATH / "pa"} Config.add_plugin_config( - "_task", - "DEFAULT_PA", - True, - help_="被动 爬 进群默认开关状态", - default_value=True, + "_task", "DEFAULT_PA", True, help_="被动 爬 进群默认开关状态", default_value=True, type=int ) _flmt = FreqLimiter(1) diff --git a/plugins/mute.py b/plugins/mute.py index ab39e8df..b4e200e9 100755 --- a/plugins/mute.py +++ b/plugins/mute.py @@ -1,19 +1,20 @@ +import time from io import BytesIO +from typing import Any, Dict, Tuple import imagehash -from PIL import Image -from nonebot import on_message, on_command -from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, ActionFailed +from nonebot import on_command, on_message +from nonebot.adapters.onebot.v11 import ActionFailed, Bot, GroupMessageEvent, Message from nonebot.adapters.onebot.v11.permission import GROUP -from utils.utils import is_number, get_message_img, get_message_text -from configs.path_config import DATA_PATH, TEMP_PATH -from utils.image_utils import get_img_hash -from services.log import logger +from nonebot.params import Command, CommandArg +from PIL import Image + from configs.config import NICKNAME, Config +from configs.path_config import DATA_PATH, TEMP_PATH +from services.log import logger from utils.http_utils import AsyncHttpx -from nonebot.params import CommandArg, Command -from typing import Tuple, Dict, Any -import time +from utils.image_utils import get_img_hash +from utils.utils import get_message_img, get_message_text, is_number try: import ujson as json @@ -38,13 +39,29 @@ __plugin_version__ = 0.1 __plugin_author__ = "HibiKier" __plugin_settings__ = {"admin_level": Config.get_config("mute", "MUTE_LEVEL")} __plugin_configs__ = { - "MUTE_LEVEL [LEVEL]": {"value": 5, "help": "更改禁言设置的管理权限", "default_value": 5}, - "MUTE_DEFAULT_COUNT": {"value": 10, "help": "刷屏禁言默认检测次数", "default_value": 10}, - "MUTE_DEFAULT_TIME": {"value": 7, "help": "刷屏检测默认规定时间", "default_value": 7}, + "MUTE_LEVEL [LEVEL]": { + "value": 5, + "help": "更改禁言设置的管理权限", + "default_value": 5, + "type": int, + }, + "MUTE_DEFAULT_COUNT": { + "value": 10, + "help": "刷屏禁言默认检测次数", + "default_value": 10, + "type": int, + }, + "MUTE_DEFAULT_TIME": { + "value": 7, + "help": "刷屏检测默认规定时间", + "default_value": 7, + "type": int, + }, "MUTE_DEFAULT_DURATION": { "value": 10, "help": "刷屏检测默禁言时长(分钟)", "default_value": 10, + "type": int, }, } @@ -75,7 +92,9 @@ def save_data(): async def download_img_and_hash(url) -> str: - return str(imagehash.average_hash(Image.open(BytesIO((await AsyncHttpx.get(url)).content)))) + return str( + imagehash.average_hash(Image.open(BytesIO((await AsyncHttpx.get(url)).content))) + ) mute_dict = {} diff --git a/plugins/open_cases/__init__.py b/plugins/open_cases/__init__.py index f1a49076..b3ef0d7f 100755 --- a/plugins/open_cases/__init__.py +++ b/plugins/open_cases/__init__.py @@ -1,24 +1,27 @@ -from typing import Type, Tuple, Any -from nonebot import on_command -from nonebot.matcher import Matcher -from utils.utils import scheduler, is_number -from nonebot.adapters.onebot.v11.permission import GROUP -from nonebot.typing import T_State -from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent, Message -from nonebot.permission import SUPERUSER import random -from nonebot.plugin import MatcherGroup -from configs.path_config import IMAGE_PATH +from typing import Any, Tuple, Type + +from nonebot import on_command +from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent +from nonebot.adapters.onebot.v11.permission import GROUP +from nonebot.matcher import Matcher from nonebot.params import CommandArg, RegexGroup +from nonebot.permission import SUPERUSER +from nonebot.plugin import MatcherGroup +from nonebot.typing import T_State + +from configs.config import Config +from configs.path_config import IMAGE_PATH +from utils.utils import is_number, scheduler + from .open_cases_c import ( - open_case, - total_open_statistics, group_statistics, my_knifes_name, - open_shilian_case, + open_case, + open_multiple_case, + total_open_statistics, ) -from .utils import util_get_buff_price, util_get_buff_img, update_count_daily -from configs.config import Config +from .utils import reset_count_daily, util_get_buff_img, util_get_buff_price __zx_plugin_name__ = "开箱" __plugin_usage__ = """ @@ -73,11 +76,17 @@ __plugin_task__ = {"open_case_reset_remind": "每日开箱重置提醒"} __plugin_cd_limit__ = {"rst": "着什么急啊,慢慢来!"} __plugin_resources__ = {f"cases": IMAGE_PATH} __plugin_configs__ = { - "INITIAL_OPEN_CASE_COUNT": {"value": 20, "help": "初始每日开箱次数", "default_value": 20}, + "INITIAL_OPEN_CASE_COUNT": { + "value": 20, + "help": "初始每日开箱次数", + "default_value": 20, + "type": int, + }, "EACH_IMPRESSION_ADD_COUNT": { "value": 3, "help": "每 * 点好感度额外增加开箱次数", "default_value": 3, + "type": int, }, "COOKIE": { "value": None, @@ -92,6 +101,7 @@ Config.add_plugin_config( True, help_="被动 每日开箱重置提醒 进群默认开关状态", default_value=True, + type=int, ) cases_name = ["狂牙大行动", "突围大行动", "命悬一线", "裂空", "光谱"] @@ -101,12 +111,12 @@ cases_matcher_group = MatcherGroup(priority=5, permission=GROUP, block=True) k_open_case = cases_matcher_group.on_command("开箱") -reload_count = cases_matcher_group.on_command("重置开箱",permission=SUPERUSER) +reload_count = cases_matcher_group.on_command("重置开箱", permission=SUPERUSER) @reload_count.handle() async def _(event: GroupMessageEvent): - await update_count_daily() + await reset_count_daily() @k_open_case.handle() @@ -153,11 +163,13 @@ async def _(event: GroupMessageEvent): ) -open_shilian: Type[Matcher] = cases_matcher_group.on_regex("(.*)连开箱(.*)?") +open_multiple: Type[Matcher] = cases_matcher_group.on_regex("(.*)连开箱(.*)?") -@open_shilian.handle() -async def _(event: GroupMessageEvent, state: T_State, reg_group: Tuple[Any, ...] = RegexGroup()): +@open_multiple.handle() +async def _( + event: GroupMessageEvent, state: T_State, reg_group: Tuple[Any, ...] = RegexGroup() +): num, case_name = reg_group if is_number(num) or num_dict.get(num): try: @@ -165,18 +177,18 @@ async def _(event: GroupMessageEvent, state: T_State, reg_group: Tuple[Any, ...] except KeyError: num = int(num) if num > 30: - await open_shilian.finish("开箱次数不要超过30啊笨蛋!", at_sender=True) + await open_multiple.finish("开箱次数不要超过30啊笨蛋!", at_sender=True) if num < 0: - await open_shilian.finish("再负开箱就扣你明天开箱数了!", at_sender=True) + await open_multiple.finish("再负开箱就扣你明天开箱数了!", at_sender=True) else: - await open_shilian.finish("必须要是数字切不要超过30啊笨蛋!中文也可!", at_sender=True) + await open_multiple.finish("必须要是数字切不要超过30啊笨蛋!中文也可!", at_sender=True) case_name = case_name.replace("武器箱", "").strip() if not case_name: case_name = random.choice(cases_name) elif case_name not in cases_name: - await open_shilian.finish("武器箱未收录!", at_sender=True) - await open_shilian.finish( - await open_shilian_case(event.user_id, event.group_id, case_name, num), + await open_multiple.finish("武器箱未收录!", at_sender=True) + await open_multiple.finish( + await open_multiple_case(event.user_id, event.group_id, case_name, num), at_sender=True, ) @@ -220,7 +232,9 @@ update_price = on_command("更新开箱价格", priority=1, permission=SUPERUSER @update_price.handle() async def _(event: MessageEvent, arg: Message = CommandArg()): - await update_price.send(await util_get_buff_price(arg.extract_plain_text().strip() or "狂牙大行动")) + await update_price.send( + await util_get_buff_price(arg.extract_plain_text().strip() or "狂牙大行动") + ) update_img = on_command("更新开箱图片", priority=1, permission=SUPERUSER, block=True) @@ -228,7 +242,9 @@ update_img = on_command("更新开箱图片", priority=1, permission=SUPERUSER, @update_img.handle() async def _(event: MessageEvent, arg: Message = CommandArg()): - await update_img.send(await util_get_buff_img(arg.extract_plain_text().strip() or "狂牙大行动")) + await update_img.send( + await util_get_buff_img(arg.extract_plain_text().strip() or "狂牙大行动") + ) # 重置开箱 @@ -238,4 +254,4 @@ async def _(event: MessageEvent, arg: Message = CommandArg()): minute=1, ) async def _(): - await update_count_daily() + await reset_count_daily() diff --git a/plugins/open_cases/config.py b/plugins/open_cases/config.py index 4caab25e..5efafea5 100755 --- a/plugins/open_cases/config.py +++ b/plugins/open_cases/config.py @@ -1,5 +1,9 @@ import random -import pypinyin +from typing import List, Tuple + +from services.log import logger + +from .models.buff_skin import BuffSkin BLUE = 0.7981 BLUE_ST = 0.0699 @@ -29,152 +33,360 @@ BATTLE_SCARED_S = 0.45 BATTLE_SCARED_E = 0.99999 # 狂牙大行动 -KUANGYADAXINGDONG_CASE_KNIFE = ['摩托手套 | 第三特种兵连', '狂牙手套 | 翡翠', '驾驶手套 | 美洲豹女王', '运动手套 | 弹弓', '专业手套 | 老虎精英' - , '专业手套 | 渐变大理石', '运动手套 | 夜行衣', '驾驶手套 | 西装革履', '摩托手套 | 终点线', '摩托手套 | 血压', - '运动手套 | 猩红头巾', '驾驶手套 | 雪豹', '裹手 | 长颈鹿', '驾驶手套 | 绯红列赞', '裹手 | 沙漠头巾', - '专业手套 | 一线特工', '狂牙手套 | 黄色斑纹', '摩托手套 | 小心烟幕弹', '裹手 | 蟒蛇', '裹手 | 警告!', - '狂牙手套 | 精神错乱', '运动手套 | 大型猎物', '狂牙手套 | 针尖', '专业手套 | 陆军少尉长官'] -KUANGYADAXINGDONG_CASE_RED = ['M4A1 | 印花集', '格洛克 | 黑色魅影'] -KUANGYADAXINGDONG_CASE_PINK = ['FN57 | 童话城堡', 'M4A4 | 赛博', 'USP | 小绿怪'] -KUANGYADAXINGDONG_CASE_PURPLE = ['AWP | 亡灵之主', '双持贝瑞塔 | 灾难', '新星 | 一见青心', 'SSG 08 | 抖枪', 'UMP-45 | 金铋辉煌'] -KUANGYADAXINGDONG_CASE_BLUE = ['CZ75 | 世仇', 'P90 | 大怪兽RUSH', 'G3SG1 | 血腥迷彩', '加利尔 AR | 破坏者', 'P250 | 污染物', - 'M249 | 等高线', 'MP5-SD | 零点行动'] +KUANGYADAXINGDONG_CASE_KNIFE = [ + "摩托手套 | 第三特种兵连", + "狂牙手套 | 翡翠", + "驾驶手套 | 美洲豹女王", + "运动手套 | 弹弓", + "专业手套 | 老虎精英", + "专业手套 | 渐变大理石", + "运动手套 | 夜行衣", + "驾驶手套 | 西装革履", + "摩托手套 | 终点线", + "摩托手套 | 血压", + "运动手套 | 猩红头巾", + "驾驶手套 | 雪豹", + "裹手 | 长颈鹿", + "驾驶手套 | 绯红列赞", + "裹手 | 沙漠头巾", + "专业手套 | 一线特工", + "狂牙手套 | 黄色斑纹", + "摩托手套 | 小心烟幕弹", + "裹手 | 蟒蛇", + "裹手 | 警告!", + "狂牙手套 | 精神错乱", + "运动手套 | 大型猎物", + "狂牙手套 | 针尖", + "专业手套 | 陆军少尉长官", +] +KUANGYADAXINGDONG_CASE_RED = ["M4A1 | 印花集", "格洛克 | 黑色魅影"] +KUANGYADAXINGDONG_CASE_PINK = ["FN57 | 童话城堡", "M4A4 | 赛博", "USP | 小绿怪"] +KUANGYADAXINGDONG_CASE_PURPLE = [ + "AWP | 亡灵之主", + "双持贝瑞塔 | 灾难", + "新星 | 一见青心", + "SSG 08 | 抖枪", + "UMP-45 | 金铋辉煌", +] +KUANGYADAXINGDONG_CASE_BLUE = [ + "CZ75 | 世仇", + "P90 | 大怪兽RUSH", + "G3SG1 | 血腥迷彩", + "加利尔 AR | 破坏者", + "P250 | 污染物", + "M249 | 等高线", + "MP5-SD | 零点行动", +] # 突围大行动 -TUWEIDAXINGDONG_CASE_KNIFE = ['蝴蝶刀 | 无涂装', '蝴蝶刀 | 蓝钢', '蝴蝶刀 | 屠夫', '蝴蝶刀 | 森林 DDPAT', '蝴蝶刀 | 北方森林', - '蝴蝶刀 | 狩猎网格', '蝴蝶刀 | 枯焦之色', '蝴蝶刀 | 人工染色', '蝴蝶刀 | 都市伪装', '蝴蝶刀 | 表面淬火', - '蝴蝶刀 | 深红之网', '蝴蝶刀 | 渐变之色', '蝴蝶刀 | 噩梦之夜'] -TUWEIDAXINGDONG_CASE_RED = ['P90 | 二西莫夫', 'M4A1 | 次时代'] -TUWEIDAXINGDONG_CASE_PINK = ['沙漠之鹰 | 阴谋者', 'FN57 | 狩猎利器', '格洛克 | 水灵'] -TUWEIDAXINGDONG_CASE_PURPLE = ['PP-野牛 | 死亡主宰者', 'CZ75 | 猛虎', '新星 | 锦鲤', 'P250 | 超新星'] -TUWEIDAXINGDONG_CASE_BLUE = ['MP7 | 都市危机', '内格夫 | 沙漠精英', 'P2000 | 乳白象牙', 'SSG 08 | 无尽深海', 'UMP-45 | 迷之宫'] +TUWEIDAXINGDONG_CASE_KNIFE = [ + "蝴蝶刀 | 无涂装", + "蝴蝶刀 | 蓝钢", + "蝴蝶刀 | 屠夫", + "蝴蝶刀 | 森林 DDPAT", + "蝴蝶刀 | 北方森林", + "蝴蝶刀 | 狩猎网格", + "蝴蝶刀 | 枯焦之色", + "蝴蝶刀 | 人工染色", + "蝴蝶刀 | 都市伪装", + "蝴蝶刀 | 表面淬火", + "蝴蝶刀 | 深红之网", + "蝴蝶刀 | 渐变之色", + "蝴蝶刀 | 噩梦之夜", +] +TUWEIDAXINGDONG_CASE_RED = ["P90 | 二西莫夫", "M4A1 | 次时代"] +TUWEIDAXINGDONG_CASE_PINK = ["沙漠之鹰 | 阴谋者", "FN57 | 狩猎利器", "格洛克 | 水灵"] +TUWEIDAXINGDONG_CASE_PURPLE = ["PP-野牛 | 死亡主宰者", "CZ75 | 猛虎", "新星 | 锦鲤", "P250 | 超新星"] +TUWEIDAXINGDONG_CASE_BLUE = [ + "MP7 | 都市危机", + "内格夫 | 沙漠精英", + "P2000 | 乳白象牙", + "SSG 08 | 无尽深海", + "UMP-45 | 迷之宫", +] # 命悬一线 -MINGXUANYIXIAN_CASE_KNIFE = ['专业手套 | 大腕', '专业手套 | 深红之网', '专业手套 | 渐变之色', '专业手套 | 狩鹿', '九头蛇手套 | 响尾蛇', - '九头蛇手套 | 红树林', '九头蛇手套 | 翡翠色调', '九头蛇手套 | 表面淬火', '摩托手套 | 交运', '摩托手套 | 嘭!', - '摩托手套 | 多边形', '摩托手套 | 玳瑁', '裹手 | 套印', '裹手 | 森林色调', '裹手 | 钴蓝骷髅', '裹手 | 防水布胶带', - '运动手套 | 双栖', '运动手套 | 欧米伽', '运动手套 | 迈阿密风云', '运动手套 | 青铜形态', '驾驶手套 | 墨绿色调', - '驾驶手套 | 王蛇', '驾驶手套 | 蓝紫格子', '驾驶手套 | 超越'] -MINGXUANYIXIAN_CASE_RED = ['M4A4 | 黑色魅影', 'MP7 | 血腥运动'] -MINGXUANYIXIAN_CASE_PINK = ['AUG | 湖怪鸟', 'AWP | 死神', 'USP | 脑洞大开'] -MINGXUANYIXIAN_CASE_PURPLE = ['MAG-7 | SWAG-7', 'UMP-45 | 白狼', '内格夫 | 狮子鱼', '新星 | 狂野六号', '格洛克 | 城里的月光'] -MINGXUANYIXIAN_CASE_BLUE = ['FN57 | 焰色反应', 'MP9 | 黑砂', 'P2000 | 都市危机', 'PP-野牛 | 黑夜暴乱', 'R8 左轮手枪 | 稳', - 'SG 553 | 阿罗哈', 'XM1014 | 锈蚀烈焰'] +MINGXUANYIXIAN_CASE_KNIFE = [ + "专业手套 | 大腕", + "专业手套 | 深红之网", + "专业手套 | 渐变之色", + "专业手套 | 狩鹿", + "九头蛇手套 | 响尾蛇", + "九头蛇手套 | 红树林", + "九头蛇手套 | 翡翠色调", + "九头蛇手套 | 表面淬火", + "摩托手套 | 交运", + "摩托手套 | 嘭!", + "摩托手套 | 多边形", + "摩托手套 | 玳瑁", + "裹手 | 套印", + "裹手 | 森林色调", + "裹手 | 钴蓝骷髅", + "裹手 | 防水布胶带", + "运动手套 | 双栖", + "运动手套 | 欧米伽", + "运动手套 | 迈阿密风云", + "运动手套 | 青铜形态", + "驾驶手套 | 墨绿色调", + "驾驶手套 | 王蛇", + "驾驶手套 | 蓝紫格子", + "驾驶手套 | 超越", +] +MINGXUANYIXIAN_CASE_RED = ["M4A4 | 黑色魅影", "MP7 | 血腥运动"] +MINGXUANYIXIAN_CASE_PINK = ["AUG | 湖怪鸟", "AWP | 死神", "USP | 脑洞大开"] +MINGXUANYIXIAN_CASE_PURPLE = [ + "MAG-7 | SWAG-7", + "UMP-45 | 白狼", + "内格夫 | 狮子鱼", + "新星 | 狂野六号", + "格洛克 | 城里的月光", +] +MINGXUANYIXIAN_CASE_BLUE = [ + "FN57 | 焰色反应", + "MP9 | 黑砂", + "P2000 | 都市危机", + "PP-野牛 | 黑夜暴乱", + "R8 左轮手枪 | 稳", + "SG 553 | 阿罗哈", + "XM1014 | 锈蚀烈焰", +] -LIEKONG_CASE_KNIFE = ['求生匕首 | 无涂装', '求生匕首 | 人工染色', '求生匕首 | 北方森林', '求生匕首 | 夜色', '求生匕首 | 屠夫', - '求生匕首 | 枯焦之色', '求生匕首 | 森林 DDPAT', '求生匕首 | 深红之网', '求生匕首 | 渐变之色', '求生匕首 | 狩猎网格', - '求生匕首 | 蓝钢', '求生匕首 | 表面淬火', '求生匕首 | 都市伪装', '流浪者匕首 | 无涂装', '流浪者匕首 | 人工染色', - '流浪者匕首 | 北方森林', '流浪者匕首 | 夜色', '流浪者匕首 | 屠夫', '流浪者匕首 | 枯焦之色', '流浪者匕首 | 森林 DDPAT', - '流浪者匕首 | 深红之网', '流浪者匕首 | 渐变之色', '流浪者匕首 | 狩猎网格', '流浪者匕首 | 蓝钢', '流浪者匕首 | 表面淬火', - '流浪者匕首 | 都市伪装', '系绳匕首 | 无涂装', '系绳匕首 | 人工染色', '系绳匕首 | 北方森林', '系绳匕首 | 夜色', - '系绳匕首 | 屠夫', '系绳匕首 | 枯焦之色', '系绳匕首 | 森林 DDPAT', '系绳匕首 | 深红之网', '系绳匕首 | 渐变之色', - '系绳匕首 | 狩猎网格', '系绳匕首 | 蓝钢', '系绳匕首 | 表面淬火', '系绳匕首 | 都市伪装', '骷髅匕首 | 无涂装', - '骷髅匕首 | 人工染色', '骷髅匕首 | 北方森林', '骷髅匕首 | 夜色', '骷髅匕首 | 屠夫', '骷髅匕首 | 枯焦之色', - '骷髅匕首 | 森林 DDPAT', '骷髅匕首 | 深红之网', '骷髅匕首 | 渐变之色', '骷髅匕首 | 狩猎网格', '骷髅匕首 | 蓝钢', - '骷髅匕首 | 表面淬火', '骷髅匕首 | 都市伪装'] -LIEKONG_CASE_RED = ['AK-47 | 阿努比斯军团', '沙漠之鹰 | 印花集'] -LIEKONG_CASE_PINK = ['M4A4 | 齿仙', 'XM1014 | 埋葬之影', '格洛克 | 摩登时代'] -LIEKONG_CASE_PURPLE = ['加利尔 AR | 凤凰商号', 'Tec-9 | 兄弟连', 'MP5-SD | 猛烈冲锋', 'MAG-7 | 北冥有鱼', 'MAC-10 | 魅惑'] -LIEKONG_CASE_BLUE = ['内格夫 | 飞羽', 'SSG 08 | 主机001', 'SG 553 | 锈蚀之刃', 'PP-野牛 | 神秘碑文', 'P90 | 集装箱', 'P250 | 卡带', - 'P2000 | 盘根错节'] +LIEKONG_CASE_KNIFE = [ + "求生匕首 | 无涂装", + "求生匕首 | 人工染色", + "求生匕首 | 北方森林", + "求生匕首 | 夜色", + "求生匕首 | 屠夫", + "求生匕首 | 枯焦之色", + "求生匕首 | 森林 DDPAT", + "求生匕首 | 深红之网", + "求生匕首 | 渐变之色", + "求生匕首 | 狩猎网格", + "求生匕首 | 蓝钢", + "求生匕首 | 表面淬火", + "求生匕首 | 都市伪装", + "流浪者匕首 | 无涂装", + "流浪者匕首 | 人工染色", + "流浪者匕首 | 北方森林", + "流浪者匕首 | 夜色", + "流浪者匕首 | 屠夫", + "流浪者匕首 | 枯焦之色", + "流浪者匕首 | 森林 DDPAT", + "流浪者匕首 | 深红之网", + "流浪者匕首 | 渐变之色", + "流浪者匕首 | 狩猎网格", + "流浪者匕首 | 蓝钢", + "流浪者匕首 | 表面淬火", + "流浪者匕首 | 都市伪装", + "系绳匕首 | 无涂装", + "系绳匕首 | 人工染色", + "系绳匕首 | 北方森林", + "系绳匕首 | 夜色", + "系绳匕首 | 屠夫", + "系绳匕首 | 枯焦之色", + "系绳匕首 | 森林 DDPAT", + "系绳匕首 | 深红之网", + "系绳匕首 | 渐变之色", + "系绳匕首 | 狩猎网格", + "系绳匕首 | 蓝钢", + "系绳匕首 | 表面淬火", + "系绳匕首 | 都市伪装", + "骷髅匕首 | 无涂装", + "骷髅匕首 | 人工染色", + "骷髅匕首 | 北方森林", + "骷髅匕首 | 夜色", + "骷髅匕首 | 屠夫", + "骷髅匕首 | 枯焦之色", + "骷髅匕首 | 森林 DDPAT", + "骷髅匕首 | 深红之网", + "骷髅匕首 | 渐变之色", + "骷髅匕首 | 狩猎网格", + "骷髅匕首 | 蓝钢", + "骷髅匕首 | 表面淬火", + "骷髅匕首 | 都市伪装", +] +LIEKONG_CASE_RED = ["AK-47 | 阿努比斯军团", "沙漠之鹰 | 印花集"] +LIEKONG_CASE_PINK = ["M4A4 | 齿仙", "XM1014 | 埋葬之影", "格洛克 | 摩登时代"] +LIEKONG_CASE_PURPLE = [ + "加利尔 AR | 凤凰商号", + "Tec-9 | 兄弟连", + "MP5-SD | 猛烈冲锋", + "MAG-7 | 北冥有鱼", + "MAC-10 | 魅惑", +] +LIEKONG_CASE_BLUE = [ + "内格夫 | 飞羽", + "SSG 08 | 主机001", + "SG 553 | 锈蚀之刃", + "PP-野牛 | 神秘碑文", + "P90 | 集装箱", + "P250 | 卡带", + "P2000 | 盘根错节", +] -GUANGPU_CASE_KNIFE = ['弯刀 | 外表生锈', '弯刀 | 多普勒', '弯刀 | 大马士革钢', '弯刀 | 渐变大理石', '弯刀 | 致命紫罗兰', '弯刀 | 虎牙', - '暗影双匕 | 外表生锈', '暗影双匕 | 多普勒', '暗影双匕 | 大马士革钢', '暗影双匕 | 渐变大理石', '暗影双匕 | 致命紫罗兰', - '暗影双匕 | 虎牙', '猎杀者匕首 | 外表生锈', '猎杀者匕首 | 多普勒', '猎杀者匕首 | 大马士革钢', '猎杀者匕首 | 渐变大理石', - '猎杀者匕首 | 致命紫罗兰', '猎杀者匕首 | 虎牙', '蝴蝶刀 | 外表生锈', '蝴蝶刀 | 多普勒', '蝴蝶刀 | 大马士革钢', - '蝴蝶刀 | 渐变大理石', '蝴蝶刀 | 致命紫罗兰', '蝴蝶刀 | 虎牙', '鲍伊猎刀 | 外表生锈', '鲍伊猎刀 | 多普勒', - '鲍伊猎刀 | 大马士革钢', '鲍伊猎刀 | 渐变大理石', '鲍伊猎刀 | 致命紫罗兰', '鲍伊猎刀 | 虎牙'] -GUANGPU_CASE_RED = ['USP | 黑色魅影', 'AK-47 | 血腥运动'] -GUANGPU_CASE_PINK = ['M4A1 | 毁灭者 2000', 'CZ75 | 相柳', 'AWP | 浮生如梦'] -GUANGPU_CASE_PURPLE = ['加利尔 AR | 深红海啸', 'XM1014 | 四季', 'UMP-45 | 支架', 'MAC-10 | 绝界之行', 'M249 | 翠绿箭毒蛙'] -GUANGPU_CASE_BLUE = ['沙漠之鹰 | 锈蚀烈焰', '截短霰弹枪 | 梭鲈', 'SCAR-20 | 蓝图', 'PP-野牛 | 丛林滑流', 'P250 | 涟漪', 'MP7 | 非洲部落', - 'FN57 | 毛细血管'] +GUANGPU_CASE_KNIFE = [ + "弯刀 | 外表生锈", + "弯刀 | 多普勒", + "弯刀 | 大马士革钢", + "弯刀 | 渐变大理石", + "弯刀 | 致命紫罗兰", + "弯刀 | 虎牙", + "暗影双匕 | 外表生锈", + "暗影双匕 | 多普勒", + "暗影双匕 | 大马士革钢", + "暗影双匕 | 渐变大理石", + "暗影双匕 | 致命紫罗兰", + "暗影双匕 | 虎牙", + "猎杀者匕首 | 外表生锈", + "猎杀者匕首 | 多普勒", + "猎杀者匕首 | 大马士革钢", + "猎杀者匕首 | 渐变大理石", + "猎杀者匕首 | 致命紫罗兰", + "猎杀者匕首 | 虎牙", + "蝴蝶刀 | 外表生锈", + "蝴蝶刀 | 多普勒", + "蝴蝶刀 | 大马士革钢", + "蝴蝶刀 | 渐变大理石", + "蝴蝶刀 | 致命紫罗兰", + "蝴蝶刀 | 虎牙", + "鲍伊猎刀 | 外表生锈", + "鲍伊猎刀 | 多普勒", + "鲍伊猎刀 | 大马士革钢", + "鲍伊猎刀 | 渐变大理石", + "鲍伊猎刀 | 致命紫罗兰", + "鲍伊猎刀 | 虎牙", +] +GUANGPU_CASE_RED = ["USP | 黑色魅影", "AK-47 | 血腥运动"] +GUANGPU_CASE_PINK = ["M4A1 | 毁灭者 2000", "CZ75 | 相柳", "AWP | 浮生如梦"] +GUANGPU_CASE_PURPLE = [ + "加利尔 AR | 深红海啸", + "XM1014 | 四季", + "UMP-45 | 支架", + "MAC-10 | 绝界之行", + "M249 | 翠绿箭毒蛙", +] +GUANGPU_CASE_BLUE = [ + "沙漠之鹰 | 锈蚀烈焰", + "截短霰弹枪 | 梭鲈", + "SCAR-20 | 蓝图", + "PP-野牛 | 丛林滑流", + "P250 | 涟漪", + "MP7 | 非洲部落", + "FN57 | 毛细血管", +] -NO_STA_KNIFE = ['求生匕首 | 北方森林', '求生匕首 | 夜色', '求生匕首 | 枯焦之色', '流浪者匕首 | 夜色', '流浪者匕首 | 枯焦之色', '流浪者匕首 | 森林 DDPAT', - '系绳匕首 | 夜色', '系绳匕首 | 狩猎网格', '骷髅匕首 | 夜色', '骷髅匕首 | 森林 DDPAT', '骷髅匕首 | 狩猎网格'] +NO_STA_KNIFE = [ + "求生匕首 | 北方森林", + "求生匕首 | 夜色", + "求生匕首 | 枯焦之色", + "流浪者匕首 | 夜色", + "流浪者匕首 | 枯焦之色", + "流浪者匕首 | 森林 DDPAT", + "系绳匕首 | 夜色", + "系绳匕首 | 狩猎网格", + "骷髅匕首 | 夜色", + "骷髅匕首 | 森林 DDPAT", + "骷髅匕首 | 狩猎网格", +] -def get_wear(num: float) -> str: - if num <= FACTORY_NEW_E: +def get_wear(rand: float) -> str: + """判断磨损度 + + Args: + rand (float): 随机rand + + Returns: + str: 磨损名称 + """ + if rand <= FACTORY_NEW_E: return "崭新出厂" - if MINIMAL_WEAR_S <= num <= MINIMAL_WEAR_E: + if MINIMAL_WEAR_S <= rand <= MINIMAL_WEAR_E: return "略有磨损" - if FIELD_TESTED_S <= num <= FIELD_TESTED_E: + if FIELD_TESTED_S <= rand <= FIELD_TESTED_E: return "久经沙场" - if WELL_WORN_S <= num <= WELL_WORN_E: + if WELL_WORN_S <= rand <= WELL_WORN_E: return "破损不堪" return "战痕累累" -def get_color_quality(rand: float, case_name: str): - case = "" - mosun = random.random()/2 + random.random()/2 - for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL): - case += ''.join(i) - case = case.upper() - CASE_KNIFE = eval(case + "_CASE_KNIFE") - CASE_RED = eval(case + "_CASE_RED") - CASE_PINK = eval(case + "_CASE_PINK") - CASE_PURPLE = eval(case + "_CASE_PURPLE") - CASE_BLUE = eval(case + "_CASE_BLUE") - if rand <= KNIFE: - skin = "罕见级(金色): " + random.choice(CASE_KNIFE) - if random.random() <= KNIFE_ST and (skin[2:4] != "手套" or skin[:2] != "裹手") and skin.split(':')[1] \ - not in NO_STA_KNIFE: - skin_sp = skin.split("|") - skin = skin_sp[0] + "(StatTrak™) | " + skin_sp[1] - elif KNIFE < rand <= RED: - skin = "隐秘级(红色): " + random.choice(CASE_RED) - if random.random() <= RED_ST: - skin_sp = skin.split("|") - skin = skin_sp[0] + "(StatTrak™) | " + skin_sp[1] - elif RED < rand <= PINK: - skin = "保密级(粉色): " + random.choice(CASE_PINK) - if random.random() <= PINK_ST: - skin_sp = skin.split("|") - skin = skin_sp[0] + "(StatTrak™) | " + skin_sp[1] - elif PINK < rand <= PURPLE: - skin = "受限级(紫色): " + random.choice(CASE_PURPLE) - if random.random() <= PURPLE_ST: - skin_sp = skin.split("|") - skin = skin_sp[0] + "(StatTrak™) | " + skin_sp[1] - else: - skin = "军规级(蓝色): " + random.choice(CASE_BLUE) - if random.random() <= BLUE_ST: - skin_sp = skin.split("|") - skin = skin_sp[0] + "(StatTrak™) | " + skin_sp[1] - if skin.find("(") != -1: - cpskin = skin.split(":")[1] - ybskin = cpskin.split("|") - temp_skin = ybskin[0].strip()[:-11] + " | " + ybskin[1].strip() - else: - temp_skin = skin.split(":")[1].strip() - # 崭新 -> 略磨 - if temp_skin in [] or temp_skin.find('渐变之色') != -1 or temp_skin.find('多普勒') != -1 or temp_skin.find('虎牙') != -1\ - or temp_skin.find('渐变大理石') != -1: - mosun = random.uniform(FACTORY_NEW_S, MINIMAL_WEAR_E) / 2 + random.uniform(FACTORY_NEW_S, MINIMAL_WEAR_E) / 2 - # 崭新 -> 久经 - if temp_skin in ['沙漠之鹰 | 阴谋者', '新星 | 锦鲤'] or temp_skin.find('屠夫') != -1: - mosun = random.uniform(FACTORY_NEW_S, FIELD_TESTED_E) / 2 + random.uniform(FACTORY_NEW_S, FIELD_TESTED_E) / 2 - # 崭新 -> 破损 - if temp_skin in ['UMP-45 | 迷之宫', 'P250 | 超新星', '系绳匕首 | 深红之网', 'M249 | 翠绿箭毒蛙', 'AK-47 | 血腥运动']: - mosun = random.uniform(FACTORY_NEW_S, WELL_WORN_E) / 2 + random.uniform(FACTORY_NEW_S, WELL_WORN_E) / 2 - # 破损 -> 战痕 - if temp_skin in [] or temp_skin.find('外表生锈') != -1: - mosun = random.uniform(WELL_WORN_S, BATTLE_SCARED_E) / 2 + random.uniform(WELL_WORN_S, BATTLE_SCARED_E) / 2 - if mosun > MINIMAL_WEAR_E: - for _ in range(2): - if random.random() < 5: - if random.random() < 0.2: - mosun /= 3 - else: - mosun /= 2 - break - skin += " (" + get_wear(mosun) + ")" - return skin, mosun +def random_color_and_st(rand: float) -> Tuple[str, bool]: + """获取皮肤品质及是否暗金 -# M249(StatTrak™) | 等高线 \ No newline at end of file + Args: + rand (float): 随机rand + + Returns: + Tuple[str, bool]: 品质,是否暗金 + """ + if rand <= KNIFE: + if random.random() <= KNIFE_ST: + return ("KNIFE", True) + return ("KNIFE", False) + elif KNIFE < rand <= RED: + if random.random() <= RED_ST: + return ("RED", True) + return ("RED", False) + elif RED < rand <= PINK: + if random.random() <= PINK_ST: + return ("PINK", True) + return ("PINK", False) + elif PINK < rand <= PURPLE: + if random.random() <= PURPLE_ST: + return ("PURPLE", True) + return ("PURPLE", False) + else: + if random.random() <= BLUE_ST: + return ("BLUE", True) + return ("BLUE", False) + + +async def random_skin(num: int, case_name: str) -> List[Tuple[BuffSkin, float]]: + """ + 随机抽取皮肤 + """ + color_map = {} + for _ in range(num): + rand = random.random() + # 尝试降低磨损 + if rand > MINIMAL_WEAR_E: + for _ in range(2): + if random.random() < 0.5: + logger.debug(f"[START]开箱随机磨损触发降低磨损条件: {rand}") + if random.random() < 0.2: + rand /= 3 + else: + rand /= 2 + logger.debug(f"[END]开箱随机磨损触发降低磨损条件: {rand}") + break + abrasion = get_wear(rand) + logger.debug(f"开箱随机磨损: {rand} | {abrasion}") + color, is_stattrak = random_color_and_st(rand) + if not color_map.get(color): + color_map[color] = {} + if is_stattrak: + if not color_map[color].get(f"{abrasion}_st"): + color_map[color][f"{abrasion}_st"] = [] + color_map[color][f"{abrasion}_st"].append(rand) + else: + if not color_map[color].get(abrasion): + color_map[color][f"{abrasion}"] = [] + color_map[color][f"{abrasion}"].append(rand) + skin_list = [] + for color in color_map: + for abrasion in color_map[color]: + rand_list = color_map[color][abrasion] + is_stattrak = "_st" in abrasion + abrasion = abrasion.replace("_st", "") + skin_list_ = await BuffSkin.random_skin( + len(rand_list), color, abrasion, is_stattrak, case_name + ) + skin_list += [(skin, rand) for skin, rand in zip(skin_list_, rand_list)] + return skin_list + + +# M249(StatTrak™) | 等高线 diff --git a/plugins/open_cases/models/__init__.py b/plugins/open_cases/models/__init__.py index acf2ed1e..e69de29b 100755 --- a/plugins/open_cases/models/__init__.py +++ b/plugins/open_cases/models/__init__.py @@ -1,2 +0,0 @@ -from .open_cases_user import * -from .buff_prices import * diff --git a/plugins/open_cases/models/buff_skin.py b/plugins/open_cases/models/buff_skin.py new file mode 100644 index 00000000..b6ef5ce8 --- /dev/null +++ b/plugins/open_cases/models/buff_skin.py @@ -0,0 +1,50 @@ +import random +from typing import List, Optional + +from tortoise import fields +from tortoise.contrib.postgres.functions import Random + +from services.db_context import Model + + +class BuffSkin(Model): + + id = fields.IntField(pk=True, generated=True, auto_increment=True) + """自增id""" + case_name = fields.CharField(255) + """箱子名称""" + name = fields.CharField(255) + """武器/手套/刀名称""" + skin_name = fields.CharField(255) + """皮肤名称""" + is_stattrak = fields.BooleanField(default=False) + """是否暗金(计数)""" + abrasion = fields.CharField(255) + """磨损度""" + color = fields.CharField(255) + """颜色(品质)""" + skin_price = fields.FloatField(default=0) + """皮肤价格""" + create_time = fields.DatetimeField(auto_add_now=True) + """创建日期""" + update_time = fields.DatetimeField(auto_add=True) + """更新日期""" + + class Meta: + table = "buff_skin" + table_description = "Buff皮肤数据表" + + @classmethod + async def random_skin( + cls, + num: int, + color: str, + abrasion: str, + is_stattrak: bool = False, + case_name: Optional[str] = None, + ) -> List["BuffSkin"]: + query = cls + if case_name: + query = query.filter(case_name=case_name) + query = query.filter(abrasion=abrasion, is_stattrak=is_stattrak, color=color) + return await query.annotate(rand=Random()).limit(num) # type:ignore diff --git a/plugins/open_cases/models/open_cases_user.py b/plugins/open_cases/models/open_cases_user.py index 0cef31bc..66985170 100755 --- a/plugins/open_cases/models/open_cases_user.py +++ b/plugins/open_cases/models/open_cases_user.py @@ -4,7 +4,6 @@ from services.db_context import Model class OpenCasesUser(Model): - __tablename__ = "open_cases_users" id = fields.IntField(pk=True, generated=True, auto_increment=True) """自增id""" @@ -12,40 +11,47 @@ class OpenCasesUser(Model): """用户id""" group_id = fields.BigIntField() """群聊id""" - total_count = fields.IntField(default=0) + total_count: int = fields.IntField(default=0) """总开启次数""" - blue_count = fields.IntField(default=0) + blue_count: int = fields.IntField(default=0) """蓝色""" - blue_st_count = fields.IntField(default=0) + blue_st_count: int = fields.IntField(default=0) """蓝色暗金""" - purple_count = fields.IntField(default=0) + purple_count: int = fields.IntField(default=0) """紫色""" - purple_st_count = fields.IntField(default=0) + purple_st_count: int = fields.IntField(default=0) """紫色暗金""" - pink_count = fields.IntField(default=0) + pink_count: int = fields.IntField(default=0) """粉色""" - pink_st_count = fields.IntField(default=0) + pink_st_count: int = fields.IntField(default=0) """粉色暗金""" - red_count = fields.IntField(default=0) + red_count: int = fields.IntField(default=0) """紫色""" - red_st_count = fields.IntField(default=0) + red_st_count: int = fields.IntField(default=0) """紫色暗金""" - knife_count = fields.IntField(default=0) + knife_count: int = fields.IntField(default=0) """金色""" - knife_st_count = fields.IntField(default=0) + knife_st_count: int = fields.IntField(default=0) """金色暗金""" - spend_money = fields.IntField(default=0) + spend_money: int = fields.IntField(default=0) """花费金币""" - make_money = fields.IntField(default=0) + make_money: float = fields.FloatField(default=0) """赚取金币""" - today_open_total = fields.IntField(default=0) + today_open_total: int = fields.IntField(default=0) """今日开箱数量""" open_cases_time_last = fields.DatetimeField() """最后开箱日期""" - knifes_name = fields.TextField(default="") + knifes_name: str = fields.TextField(default="") """已获取金色""" class Meta: table = "open_cases_users" table_description = "开箱统计数据表" unique_together = ("user_qq", "group_id") + + @classmethod + async def _run_script(cls): + await cls.raw( + "alter table open_cases_users alter COLUMN make_money type float;" + ) + """将make_money字段改为float""" diff --git a/plugins/open_cases/open_cases_c.py b/plugins/open_cases/open_cases_c.py index ed1c83b3..96e4b552 100755 --- a/plugins/open_cases/open_cases_c.py +++ b/plugins/open_cases/open_cases_c.py @@ -1,8 +1,10 @@ import asyncio import random -from datetime import datetime, timedelta +from datetime import datetime +from typing import Union import pypinyin +from nonebot.adapters.onebot.v11 import Message from PIL import Image from configs.config import Config @@ -16,164 +18,147 @@ from utils.utils import cn2py from .config import * from .models.buff_prices import BuffPrice from .models.open_cases_user import OpenCasesUser -from .utils import get_price + +RESULT_MESSAGE = { + "BLUE": ["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"], + "PURPLE": ["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."], + "PINK": ["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"], + "RED": ["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"], + "KNIFE": ["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."], +} + +COLOR2NAME = {"BLUE": "军规", "PURPLE": "受限", "PINK": "保密", "RED": "隐秘", "KNIFE": "罕见"} + +COLOR2CN = {"BLUE": "蓝", "PURPLE": "紫", "PINK": "粉", "RED": "红", "KNIFE": "金"} -async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动") -> str: +def add_count(user: OpenCasesUser, skin: BuffSkin): + if skin.color == "BLUE": + if skin.is_stattrak: + user.blue_st_count += 1 + else: + user.blue_count += 1 + elif skin.color == "PURPLE": + if skin.is_stattrak: + user.purple_st_count += 1 + else: + user.purple_count += 1 + elif skin.color == "PINK": + if skin.is_stattrak: + user.pink_st_count += 1 + else: + user.pink_count += 1 + elif skin.color == "RED": + if skin.is_stattrak: + user.red_st_count += 1 + else: + user.red_count += 1 + elif skin.color == "KNIFE": + if skin.is_stattrak: + user.knife_st_count += 1 + else: + user.knife_count += 1 + user.today_open_total += 1 + user.total_count += 1 + user.make_money += skin.skin_price + user.spend_money += 17 + + +async def get_user_max_count(user_qq: int, group_id: int) -> int: + """获取用户每日最大开箱次数 + + Args: + user_qq (int): 用户id + group_id (int): 群号 + + Returns: + int: 最大开箱次数 + """ + user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=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( + "open_cases", "EACH_IMPRESSION_ADD_COUNT" + ) + 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]: + """开箱 + + Args: + user_qq (int): 用户id + group_id (int): 群号 + case_name (str, optional): 武器箱名称. Defaults to "狂牙大行动". + + Returns: + Union[str, Message]: 回复消息 + """ if case_name not in ["狂牙大行动", "突围大行动", "命悬一线", "裂空", "光谱"]: return "武器箱未收录" - knifes_flag = False - # lan zi fen hong jin price - uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0] - case = "" - for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL): - case += "".join(i) - user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group) - impression = user.impression - rand = random.random() - await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group) - # user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group) - user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group) + logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_qq, group_id) + case = cn2py(case_name) + user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group_id) if not user: user = await OpenCasesUser.create( - user_qq=user_qq, group_id=group, open_cases_time_last=datetime.now() + user_qq=user_qq, group_id=group_id, open_cases_time_last=datetime.now() ) + max_count = await get_user_max_count(user_qq, group_id) # 一天次数上限 - if user.today_open_total >= int( - Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT") - + int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT") - ): + if user.today_open_total >= max_count: return _handle_is_MAX_COUNT() - skin, mosun = get_color_quality(rand, case_name) - # 调侃 - if skin[:2] == "军规": - if skin.find("StatTrak") == -1: - uplist[0] = 1 - else: - uplist[1] = 1 - ridicule_result = random.choice(["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"]) - if skin[:2] == "受限": - if skin.find("StatTrak") == -1: - uplist[2] = 1 - else: - uplist[3] = 1 - ridicule_result = random.choice( - ["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."] + skin_list = await random_skin(1, case_name) + if not skin_list: + return "未抽取到任何皮肤..." + skin, rand = skin_list[0] + rand = str(rand)[:11] + add_count(user, skin) + ridicule_result = random.choice(RESULT_MESSAGE[skin.color]) + price_result = skin.skin_price + if skin.color == "KNIFE": + user.knifes_name = ( + user.knifes_name + + f"{case}||{skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损:{rand}, 价格:{skin.skin_price}," ) - if skin[:2] == "保密": - if skin.find("StatTrak") == -1: - uplist[4] = 1 - else: - uplist[5] = 1 - ridicule_result = random.choice(["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"]) - if skin[:2] == "隐秘": - if skin.find("StatTrak") == -1: - uplist[6] = 1 - else: - uplist[7] = 1 - ridicule_result = random.choice( - ["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"] - ) - if skin[:2] == "罕见": - knifes_flag = True - if skin.find("StatTrak") == -1: - uplist[8] = 1 - else: - uplist[9] = 1 - ridicule_result = random.choice( - ["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."] - ) - if skin.find("(") != -1: - cskin = skin.split("(") - skin = cskin[0].strip() + "(" + cskin[1].strip() - skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip() - # 价格 - if skin.find("无涂装") == -1: - search_name = skin[9:] - else: - search_name = skin[9 : skin.rfind("(")].strip() - price_result = 0 - if data := await BuffPrice.get_or_none(skin_name=search_name): - if data.skin_price != 0: - price_result = data.skin_price - logger.info("数据库查询到价格: ", data.skin_price) - uplist[10] = data.skin_price - else: - price = -1 - price_result = "未查询到" - price_list, status = await get_price(skin[9:]) - if price_list not in ["访问超时! 请重试或稍后再试!", "访问失败!"]: - for price_l in price_list[1:]: - pcp = price_l.split(":") - if pcp[0] == skin[9:]: - price = float(pcp[1].strip()) - break - if price != -1: - logger.info("存储入数据库---->{price}") - uplist[10] = price - price_result = str(price) - data.skin_price = price - data.update_date = datetime.now() - await data.save(update_fields=["skin_price", "update_date"]) - # sp = skin.split("|") - # cskin_word = sp[1][:sp[1].find("(") - 1].strip() - if knifes_flag: - await user.update( - knifes_name=user.knifes_name - + f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]}, 价格:{uplist[10]}," - ).apply() - cskin_word = skin.split(":")[1].replace("|", "-").replace("(StatTrak™)", "") - cskin_word = cskin_word[: cskin_word.rfind("(")].strip() - skin_name = cn2py(cskin_word.replace("|", "-").replace("(StatTrak™)", "").strip()) - img = image(IMAGE_PATH / "cases" / case / f"{skin_name}.png") - # if knifes_flag: - # await user.update( - # knifes_name=user.knifes_name + f"{skin} 磨损:{mosun}, 价格:{uplist[10]}" - # ).apply() - if await update_user_total(user, uplist): - logger.info( - f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新成功" - ) - else: - logger.warning( - f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新失败" - ) - user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group) - over_count = ( - int( - Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT") - + int(impression) - / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT") - ) - - user.today_open_total + img_path = ( + IMAGE_PATH + / "cases" + / case + / f"{cn2py(skin.name)} - {cn2py(skin.skin_name)}.png" ) + logger.info( + f"开启{case_name}武器箱获得 {skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand}] 价格: {skin.skin_price}", + "开箱", + user_qq, + group_id, + ) + await user.save() + over_count = max_count - user.today_open_total return ( - f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" + img + "\n" + f"皮肤:{skin}\n" - f"磨损:{mosun:.9f}\n" + f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" + + image(img_path) + + "\n" + + f"皮肤:[{COLOR2NAME[skin.color]}]{skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion})\n" + f"磨损:{rand}\n" f"价格:{price_result}\n" - f"{ridicule_result}" + f":{ridicule_result}" ) -async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int = 10): - user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group) - sign_user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group) - impression = sign_user.impression - max_count = int( - Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT") - + int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT") - ) +async def open_multiple_case( + user_qq: int, group_id: int, case_name: str, num: int = 10 +): + user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group_id) + max_count = await get_user_max_count(user_qq, group_id) if user.today_open_total >= max_count: return _handle_is_MAX_COUNT() if max_count - user.today_open_total < num: return ( f"今天开箱次数不足{num}次噢,请单抽试试看(也许单抽运气更好?)" - f"\n剩余开箱次数:{max_count - user.today_open_total}" + f"\n剩余开箱次数:{max_count - user.today_open_total}" ) - user.total_count = user.total_count + num - user.spend_money = user.spend_money + 17 * num - user.today_open_total = user.today_open_total + num - await user.save(update_fields=["total_count", "spend_money", "today_open_total"]) if num < 5: h = 270 elif num % 5 == 0: @@ -181,149 +166,73 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int = else: h = 270 * int(num / 5) + 270 case = cn2py(case_name) - # lan zi fen hong jin - # skin_list = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - # lan zi fen hong jin price - uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0] + skin_count = {} img_list = [] - name_list = ["蓝", "蓝(暗金)", "紫", "紫(暗金)", "粉", "粉(暗金)", "红", "红(暗金)", "金", "金(暗金)"] - for _ in range(num): - knifes_flag = False - rand = random.random() - skin, mosun = get_color_quality(rand, case_name) - if skin[:2] == "军规": - if skin.find("StatTrak") == -1: - uplist[0] += 1 - else: - uplist[1] += 1 - if skin[:2] == "受限": - if skin.find("StatTrak") == -1: - uplist[2] += 1 - else: - uplist[3] += 1 - if skin[:2] == "保密": - if skin.find("StatTrak") == -1: - uplist[4] += 1 - else: - uplist[5] += 1 - if skin[:2] == "隐秘": - if skin.find("StatTrak") == -1: - uplist[6] += 1 - else: - uplist[7] += 1 - if skin[:2] == "罕见": - knifes_flag = True - if skin.find("StatTrak") == -1: - uplist[8] += 1 - else: - uplist[9] += 1 - if skin.find("(") != -1: - cskin = skin.split("(") - skin = cskin[0].strip() + "(" + cskin[1].strip() - skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip() - # 价格 - if skin.find("无涂装") == -1: - search_name = skin[9:] - else: - search_name = skin[9 : skin.rfind("(")].strip() - if dbprice := await BuffPrice.get_or_none(skin_name=search_name): - if dbprice.skin_price != 0: - price_result = dbprice.skin_price - uplist[10] += price_result - else: - price_result = "未查询到" - if knifes_flag: - await user.update( - knifes_name=user.knifes_name - + f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]}, 价格:{dbprice.skin_price}," - ).apply() - cskin_word = skin.split(":")[1].replace("|", "-").replace("(StatTrak™)", "") - cskin_word = cskin_word[: cskin_word.rfind("(")].strip() - skin_name = "" - for i in pypinyin.pinyin( - cskin_word.replace("|", "-").replace("(StatTrak™)", "").strip(), - style=pypinyin.NORMAL, - ): - skin_name += "".join(i) - wImg = BuildImage(200, 270, 200, 200) - wImg.paste( - alpha2white_pil( - Image.open(IMAGE_PATH / "cases" / case / f"{skin_name}.png").resize( - (200, 200), Image.ANTIALIAS - ) - ), - (0, 0), + skin_list = await random_skin(num, case_name) + if not skin_list: + return "未抽取到任何皮肤..." + total_price = 0 + for skin, rand in skin_list: + total_price += skin.skin_price + rand = str(rand)[:11] + add_count(user, skin) + color_name = COLOR2CN[skin.color] + if skin.is_stattrak: + color_name += "(暗金)" + if not skin_count.get(color_name): + skin_count[color_name] = 0 + skin_count[color_name] += 1 + if skin.color == "KNIFE": + user.knifes_name = ( + user.knifes_name + + f"{case}||{skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损:{rand}, 价格:{skin.skin_price}," ) - wImg.text((5, 200), skin) - wImg.text((5, 220), f"磨损:{str(mosun)[:9]}") - wImg.text((5, 240), f"价格:{price_result}") - img_list.append(wImg) - logger.info( - f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}" - ) - if await update_user_total(user, uplist, 0): - logger.info( - f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 {num} 次, 数据更新成功" - ) - else: - logger.warning( - f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 {num} 次, 价格:{uplist[10]}, 数据更新失败" - ) - # markImg = BuildImage(1000, h, 200, 270) - # for img in img_list: - # markImg.paste(img) - markImg = await asyncio.get_event_loop().run_in_executor( - None, paste_markImg, h, img_list - ) - over_count = max_count - user.today_open_total - result = "" - for i in range(len(name_list)): - if uplist[i]: - result += f"[{name_list[i]}:{uplist[i]}] " - return ( - f"开启{case_name}武器箱\n剩余开箱次数:{over_count}\n" - + image(b64=markImg.pic2bs4()) - + "\n" - + result[:-1] - + f"\n总获取金额:{uplist[-1]:.2f}\n总花费:{17 * num}" - ) - - -def paste_markImg(h: int, img_list: list): + wImg = BuildImage(200, 270, 200, 200) + await wImg.apaste( + alpha2white_pil( + Image.open( + IMAGE_PATH + / "cases" + / case + / f"{cn2py(skin.name)} - {cn2py(skin.skin_name)}.png" + ).resize((200, 200), Image.ANTIALIAS) + ), + (0, 0), + ) + await wImg.atext( + (5, 200), + f"{skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion})", + ) + await wImg.atext((5, 220), f"磨损:{rand}") + await wImg.atext((5, 240), f"价格:{skin.skin_price}") + img_list.append(wImg) + logger.info( + f"开启{case_name}武器箱获得 {skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand}] 价格: {skin.skin_price}", + "开箱", + user_qq, + group_id, + ) + await user.save() markImg = BuildImage(1000, h, 200, 270) for img in img_list: markImg.paste(img) - return markImg + over_count = max_count - user.today_open_total + result = "" + for color_name in skin_count: + result += f"[{color_name}:{skin_count[color_name]}] " + return ( + f"开启{case_name}武器箱\n剩余开箱次数:{over_count}\n" + + image(markImg.pic2bs4()) + + "\n" + + result[:-1] + + f"\n总获取金额:{total_price:.2f}\n总花费:{17 * num}" + ) def _handle_is_MAX_COUNT() -> str: return f"今天已达开箱上限了喔,明天再来吧\n(提升好感度可以增加每日开箱数 #疯狂暗示)" -async def update_user_total(user: OpenCasesUser, up_list: list, num: int = 1) -> bool: - try: - await user.update_or_create( - total_count=user.total_count + num, - blue_count=user.blue_count + up_list[0], - blue_st_count=user.blue_st_count + up_list[1], - purple_count=user.purple_count + up_list[2], - purple_st_count=user.purple_st_count + up_list[3], - pink_count=user.pink_count + up_list[4], - pink_st_count=user.pink_st_count + up_list[5], - red_count=user.red_count + up_list[6], - red_st_count=user.red_st_count + up_list[7], - knife_count=user.knife_count + up_list[8], - knife_st_count=user.knife_st_count + up_list[9], - spend_money=user.spend_money + 17 * num, - make_money=user.make_money + up_list[10], - today_open_total=user.today_open_total + num, - open_cases_time_last=datetime.now(), - ) - return True - except: - return False - - async def total_open_statistics(user_qq: int, group: int) -> str: user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group) return ( diff --git a/plugins/open_cases/utils.py b/plugins/open_cases/utils.py index d588e55d..ce282528 100755 --- a/plugins/open_cases/utils.py +++ b/plugins/open_cases/utils.py @@ -1,23 +1,25 @@ -import os from asyncio.exceptions import TimeoutError -from datetime import datetime, timedelta +from datetime import datetime +from typing import Optional -from nonebot.adapters.onebot.v11 import ActionFailed +import nonebot 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.manager import group_manager -from utils.utils import cn2py, get_bot +from utils.utils import broadcast_group, cn2py from .config import * from .models.buff_prices import BuffPrice +from .models.buff_skin import BuffSkin from .models.open_cases_user import OpenCasesUser url = "https://buff.163.com/api/market/goods" # proxies = 'http://49.75.59.242:3128' +driver = nonebot.get_driver() + async def util_get_buff_price(case_name: str = "狂牙大行动") -> str: cookie = {"session": Config.get_config("open_cases", "COOKIE")} @@ -255,22 +257,86 @@ async def get_price(d_name): return result[:-1], 999 -async def update_count_daily(): +async def reset_count_daily(): + """ + 重置每日开箱 + """ try: await OpenCasesUser.all().update(today_open_total=0) - bot = get_bot() - gl = await bot.get_group_list() - gl = [g["group_id"] for g in gl] - for g in gl: - try: - await bot.send_group_msg( - group_id=g, message="[[_task|open_case_reset_remind]]今日开箱次数重置成功" - ) - except ActionFailed: - logger.warning(f"{g} 群被禁言,无法发送 开箱重置提醒") - logger.info("今日开箱次数重置成功") + await broadcast_group( + "[[_task|open_case_reset_remind]]今日开箱次数重置成功", log_cmd="开箱重置提醒" + ) except Exception as e: - logger.error(f"开箱重置错误 e:{e}") + logger.error(f"开箱重置错误", e=e) + + +def get_color(case_name: str, name: str, skin_name: str) -> Optional[str]: + case_py = cn2py(case_name).upper() + color_map = {} + color_map["KNIFE"] = eval(case_py + "_CASE_KNIFE") + color_map["RED"] = eval(case_py + "_CASE_RED") + color_map["PINK"] = eval(case_py + "_CASE_PINK") + color_map["PURPLE"] = eval(case_py + "_CASE_PURPLE") + color_map["BLUE"] = eval(case_py + "_CASE_BLUE") + for key in color_map: + for skin in color_map[key]: + if name in skin and skin_name in skin: + return key + return None + + +@driver.on_startup +async def _(): + """ + 将旧表数据移动到新表 + """ + if not await BuffSkin.first() and await BuffPrice.first(): + logger.debug("开始移动旧表数据 BuffPrice -> BuffSkin") + id2name = {1: "狂牙大行动", 2: "突围大行动", 3: "命悬一线", 4: "裂空", 5: "光谱"} + data_list: List[BuffSkin] = [] + for data in await BuffPrice.all(): + logger.debug(f"移动旧表数据: {data.skin_name}") + case_name = id2name[data.case_id] + name = data.skin_name + is_stattrak = "StatTrak" in name + name = name.replace("(★ StatTrak™)", "").replace("(StatTrak™)", "").strip() + name, skin_name = name.split("|") + abrasion = "无涂装" + if "(" in skin_name: + skin_name, abrasion = skin_name.split("(") + if abrasion.endswith(")"): + abrasion = abrasion[:-1] + color = get_color(case_name, name.strip(), skin_name.strip()) + if not color: + search_list = [ + x + for x in data_list + if x.skin_name == skin_name.strip() and x.name == name.strip() + ] + if search_list: + color = get_color( + case_name, search_list[0].name, search_list[0].skin_name + ) + if not color: + logger.debug( + f"箱子: [{case_name}] 皮肤: [{name}|{skin_name}] 未获取到皮肤品质,跳过..." + ) + continue + data_list.append( + BuffSkin( + case_name=case_name, + name=name.strip(), + skin_name=skin_name.strip(), + is_stattrak=is_stattrak, + abrasion=abrasion.strip(), + skin_price=data.skin_price, + color=color, + create_time=datetime.now(), + update_time=datetime.now(), + ) + ) + await BuffSkin.bulk_create(data_list, batch_size=10) + logger.debug("完成移动旧表数据 BuffPrice -> BuffSkin") # 蝴蝶刀(★) | 噩梦之夜 (久经沙场) diff --git a/plugins/parse_bilibili_json.py b/plugins/parse_bilibili_json.py index 13aa7e57..4a9a91a3 100755 --- a/plugins/parse_bilibili_json.py +++ b/plugins/parse_bilibili_json.py @@ -35,6 +35,7 @@ Config.add_plugin_config( True, help_="被动 B站转发解析 进群默认开关状态", default_value=True, + type=bool ) diff --git a/plugins/pix_gallery/__init__.py b/plugins/pix_gallery/__init__.py index b33c447a..dc9c130a 100755 --- a/plugins/pix_gallery/__init__.py +++ b/plugins/pix_gallery/__init__.py @@ -1,7 +1,9 @@ +from pathlib import Path +from typing import Tuple + import nonebot from configs.config import Config -from utils.utils import GDict Config.add_plugin_config( "hibiapi", @@ -25,6 +27,7 @@ Config.add_plugin_config( 5000, help_="最低收藏,PIX使用HIBIAPI搜索图片时达到最低收藏才会添加至图库", default_value=5000, + type=int, ) Config.add_plugin_config( "pix", @@ -32,6 +35,7 @@ Config.add_plugin_config( (0, 1), help_="自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)", default_value=(0, 1), + type=Tuple[int, int], ) Config.add_plugin_config( "pix", @@ -39,13 +43,15 @@ Config.add_plugin_config( (10, 0), help_="PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1:PIX图库 参2:OmegaPixivIllusts扩展图库(没有此图库请设置为0)", default_value=(10, 0), + type=Tuple[int, int], +) +Config.add_plugin_config( + "pix", "TIMEOUT", 10, help_="下载图片超时限制(秒)", default_value=10, type=int ) -Config.add_plugin_config("pix", "TIMEOUT", 10, help_="下载图片超时限制(秒)", default_value=10) Config.add_plugin_config( - "pix", "SHOW_INFO", True, help_="是否显示图片的基本信息,如PID等", default_value=True + "pix", "SHOW_INFO", True, help_="是否显示图片的基本信息,如PID等", default_value=True, type=bool ) -GDict["run_sql"].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;") - -nonebot.load_plugins("plugins/pix_gallery") +# GDict["run_sql"].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;") +nonebot.load_plugins(str(Path(__file__).parent.resolve())) diff --git a/plugins/pix_gallery/pix.py b/plugins/pix_gallery/pix.py index e9cacd5e..a01fd792 100755 --- a/plugins/pix_gallery/pix.py +++ b/plugins/pix_gallery/pix.py @@ -1,16 +1,18 @@ -from utils.utils import is_number -from configs.config import Config -from ._model.omega_pixiv_illusts import OmegaPixivIllusts -from utils.message_builder import image, custom_forward_msg -from utils.manager import withdraw_message_manager -from services.log import logger -from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message -from nonebot.params import CommandArg -from ._data_source import get_image -from ._model.pixiv import Pixiv -from nonebot import on_command import random +from nonebot import on_command +from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent +from nonebot.params import CommandArg + +from configs.config import Config +from services.log import logger +from utils.manager import withdraw_message_manager +from utils.message_builder import custom_forward_msg, image +from utils.utils import is_number + +from ._data_source import get_image +from ._model.omega_pixiv_illusts import OmegaPixivIllusts +from ._model.pixiv import Pixiv __zx_plugin_name__ = "PIX" __plugin_usage__ = """ @@ -55,9 +57,20 @@ __plugin_configs__ = { "value": None, "help": "单次发送的图片数量达到指定值时转发为合并消息", "default_value": None, + "type": int, + }, + "ALLOW_GROUP_SETU": { + "value": False, + "help": "允许非超级用户使用-s参数", + "default_value": False, + "type": bool, + }, + "ALLOW_GROUP_R18": { + "value": False, + "help": "允许非超级用户使用-r参数", + "default_value": False, + "type": bool, }, - "ALLOW_GROUP_SETU": {"value": False, "help": "允许非超级用户使用-s参数", "default_value": False}, - "ALLOW_GROUP_R18": {"value": False, "help": "允许非超级用户使用-r参数", "default_value": False}, } diff --git a/plugins/pixiv_rank_search/__init__.py b/plugins/pixiv_rank_search/__init__.py index eb3c412c..351f5a49 100755 --- a/plugins/pixiv_rank_search/__init__.py +++ b/plugins/pixiv_rank_search/__init__.py @@ -1,16 +1,25 @@ -from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message, NetworkError +import time +from asyncio.exceptions import TimeoutError +from typing import Type + +from nonebot import on_command +from nonebot.adapters.onebot.v11 import ( + Bot, + GroupMessageEvent, + Message, + MessageEvent, + NetworkError, +) from nonebot.matcher import Matcher from nonebot.params import CommandArg -from nonebot import on_command -from utils.utils import is_number -from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls -from services.log import logger -from asyncio.exceptions import TimeoutError -from utils.message_builder import custom_forward_msg -from configs.config import Config -from typing import Type from nonebot.rule import to_me -import time + +from configs.config import Config +from services.log import logger +from utils.message_builder import custom_forward_msg +from utils.utils import is_number + +from .data_source import download_pixiv_imgs, get_pixiv_urls, search_pixiv_urls __zx_plugin_name__ = "P站排行/搜图" @@ -61,21 +70,19 @@ __plugin_settings__ = { } __plugin_block_limit__ = {"rst": "P站排行榜或搜图正在搜索,请不要重复触发命令..."} __plugin_configs__ = { - "TIMEOUT": { - "value": 10, - "help": "图片下载超时限制", - "default_value": 10 - }, + "TIMEOUT": {"value": 10, "help": "图片下载超时限制", "default_value": 10, "type": int}, "MAX_PAGE_LIMIT": { "value": 20, "help": "作品最大页数限制,超过的作品会被略过", - "default_value": 20 + "default_value": 20, + "type": int, }, "ALLOW_GROUP_R18": { "value": False, "help": "允许群聊中使用 r18 参数", - "default_value": False - } + "default_value": False, + "type": bool, + }, } Config.add_plugin_config( "hibiapi", @@ -84,12 +91,7 @@ Config.add_plugin_config( help_="如果没有自建或其他hibiapi请不要修改", default_value="https://api.obfs.dev", ) -Config.add_plugin_config( - "pixiv", - "PIXIV_NGINX_URL", - "i.pixiv.re", - help_="Pixiv反向代理" -) +Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pixiv.re", help_="Pixiv反向代理") rank_dict = { @@ -158,7 +160,9 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()): async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()): msg = arg.extract_plain_text().strip() if isinstance(event, GroupMessageEvent): - if "r18" in msg.lower() and not Config.get_config("pixiv_rank_search", "ALLOW_GROUP_R18"): + if "r18" in msg.lower() and not Config.get_config( + "pixiv_rank_search", "ALLOW_GROUP_R18" + ): await pixiv_keyword.finish("(脸红#) 你不会害羞的 八嘎!", at_sender=True) r18 = 0 if "r18" in msg else 1 msg = msg.replace("r18", "").strip().split() @@ -168,7 +172,7 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()): num = 10 page = 1 if (n := len(msg)) > 0: - keyword = msg[0].replace("#"," ") + keyword = msg[0].replace("#", " ") if n > 1: if not is_number(msg[1]): await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True) @@ -206,7 +210,10 @@ async def send_image( idx = 0 mes_list = [] for title, author, urls in info_list: - _message = f"title: {title}\nauthor: {author}\n" + await download_pixiv_imgs(urls, event.user_id, idx) + _message = ( + f"title: {title}\nauthor: {author}\n" + + await download_pixiv_imgs(urls, event.user_id, idx) + ) mes_list.append(_message) idx += 1 mes_list = custom_forward_msg(mes_list, bot.self_id) diff --git a/plugins/russian/__init__.py b/plugins/russian/__init__.py index 99b8792d..ff8f5bc2 100755 --- a/plugins/russian/__init__.py +++ b/plugins/russian/__init__.py @@ -57,6 +57,7 @@ __plugin_configs__ = { "value": 1000, "help": "俄罗斯轮盘最大赌注金额", "default_value": 1000, + "type": int, } } diff --git a/plugins/search_anime/__init__.py b/plugins/search_anime/__init__.py index 447031a8..c57cd73d 100755 --- a/plugins/search_anime/__init__.py +++ b/plugins/search_anime/__init__.py @@ -1,12 +1,13 @@ from nonebot import on_command -from .data_source import from_anime_get_info -from services.log import logger -from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message +from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent +from nonebot.params import ArgStr, CommandArg from nonebot.typing import T_State -from configs.config import Config -from utils.message_builder import custom_forward_msg -from nonebot.params import CommandArg, ArgStr +from configs.config import Config +from services.log import logger +from utils.message_builder import custom_forward_msg + +from .data_source import from_anime_get_info __zx_plugin_name__ = "搜番" __plugin_usage__ = f""" @@ -29,7 +30,12 @@ __plugin_settings__ = { } __plugin_block_limit__ = {"rst": "搜索还未完成,不要重复触发!"} __plugin_configs__ = { - "SEARCH_ANIME_MAX_INFO": {"value": 20, "help": "搜索动漫返回的最大数量", "default_value": 20} + "SEARCH_ANIME_MAX_INFO": { + "value": 20, + "help": "搜索动漫返回的最大数量", + "default_value": 20, + "type": int, + } } search_anime = on_command("搜番", aliases={"搜动漫"}, priority=5, block=True) @@ -42,7 +48,9 @@ async def _(state: T_State, arg: Message = CommandArg()): @search_anime.got("anime", prompt="是不是少了番名?") -async def _(bot: Bot, event: MessageEvent, state: T_State, key_word: str = ArgStr("anime")): +async def _( + bot: Bot, event: MessageEvent, state: T_State, key_word: str = ArgStr("anime") +): await search_anime.send(f"开始搜番 {key_word}", at_sender=True) anime_report = await from_anime_get_info( key_word, diff --git a/plugins/search_image/__init__.py b/plugins/search_image/__init__.py index 7f296034..d32ebf5c 100644 --- a/plugins/search_image/__init__.py +++ b/plugins/search_image/__init__.py @@ -1,12 +1,13 @@ +from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent +from nonebot.params import Arg, ArgStr, CommandArg, Depends from nonebot.plugin import on_command -from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message from nonebot.typing import T_State -from services.log import logger -from utils.utils import get_message_img -from utils.message_builder import custom_forward_msg -from nonebot.params import CommandArg, Arg, ArgStr, Depends -from .saucenao import get_saucenao_image +from services.log import logger +from utils.message_builder import custom_forward_msg +from utils.utils import get_message_img + +from .saucenao import get_saucenao_image __zx_plugin_name__ = "识图" __plugin_usage__ = """ @@ -27,7 +28,12 @@ __plugin_settings__ = { "cmd": ["识图"], } __plugin_configs__ = { - "MAX_FIND_IMAGE_COUNT": {"value": 3, "help": "识图返回的最大结果数", "default_value": 3}, + "MAX_FIND_IMAGE_COUNT": { + "value": 3, + "help": "识图返回的最大结果数", + "default_value": 3, + "type": int, + }, "API_KEY": { "value": None, "help": "Saucenao的API_KEY,通过 https://saucenao.com/user.php?page=search-api 注册获取", @@ -44,12 +50,11 @@ async def get_image_info(mod: str, url: str): def parse_image(key: str): - async def _key_parser( - state: T_State, img: Message = Arg(key) - ): + async def _key_parser(state: T_State, img: Message = Arg(key)): if not get_message_img(img): await search_image.reject_arg(key, "请发送要识别的图片!") state[key] = img + return _key_parser diff --git a/plugins/self_message/__init__.py b/plugins/self_message/__init__.py index 4720f948..59720338 100644 --- a/plugins/self_message/__init__.py +++ b/plugins/self_message/__init__.py @@ -1,13 +1,17 @@ from datetime import datetime -from configs.config import Config from nonebot import on -from nonebot.adapters.onebot.v11 import (Bot, Event, GroupMessageEvent, - PrivateMessageEvent) +from nonebot.adapters.onebot.v11 import ( + Bot, + Event, + GroupMessageEvent, + PrivateMessageEvent, +) from nonebot.message import handle_event -from ._rule import rule +from configs.config import Config +from ._rule import rule __zx_plugin_name__ = "自身消息触发 [Hidden]" __plugin_version__ = 0.1 @@ -18,6 +22,7 @@ Config.add_plugin_config( False, help_="允许真寻自身触发命令,需要在go-cqhttp配置文件中report-self-message修改为true,触发命令时需前缀cmd且受权限影响,例如:cmd签到", default_value=False, + type=bool, ) message_sent = on( diff --git a/plugins/send_setu_/send_setu/__init__.py b/plugins/send_setu_/send_setu/__init__.py index b6c4fb6c..cc693bbb 100755 --- a/plugins/send_setu_/send_setu/__init__.py +++ b/plugins/send_setu_/send_setu/__init__.py @@ -78,29 +78,44 @@ __plugin_configs__ = { "value": (0, 1), "help": "自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)", "default_value": (0, 1), + "type": Tuple[int, int], }, "ONLY_USE_LOCAL_SETU": { "value": False, "help": "仅仅使用本地色图,不在线搜索", "default_value": False, + "type": bool, }, "INITIAL_SETU_PROBABILITY": { "value": 0.7, "help": "初始色图概率,总概率 = 初始色图概率 + 好感度", "default_value": 0.7, + "type": float, }, "DOWNLOAD_SETU": { "value": True, "help": "是否存储下载的色图,使用本地色图可以加快图片发送速度", "default_value": True, + "type": bool, + }, + "TIMEOUT": {"value": 10, "help": "色图下载超时限制(秒)", "default_value": 10, "type": int}, + "SHOW_INFO": { + "value": True, + "help": "是否显示色图的基本信息,如PID等", + "default_value": True, + "type": bool, + }, + "ALLOW_GROUP_R18": { + "value": False, + "help": "在群聊中启用R18权限", + "default_value": False, + "type": bool, }, - "TIMEOUT": {"value": 10, "help": "色图下载超时限制(秒)", "default_value": 10}, - "SHOW_INFO": {"value": True, "help": "是否显示色图的基本信息,如PID等", "default_value": True}, - "ALLOW_GROUP_R18": {"value": False, "help": "在群聊中启用R18权限", "default_value": False}, "MAX_ONCE_NUM2FORWARD": { "value": None, "help": "单次发送的图片数量达到指定值时转发为合并消息", "default_value": None, + "type": int, }, } Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pixiv.re", help_="Pixiv反向代理") diff --git a/plugins/sign_in/__init__.py b/plugins/sign_in/__init__.py index fd001d65..78c5c3bc 100755 --- a/plugins/sign_in/__init__.py +++ b/plugins/sign_in/__init__.py @@ -1,24 +1,25 @@ -from typing import Tuple, Any +from pathlib import Path +from typing import Any, Tuple -from .group_user_checkin import ( - group_user_check_in, - group_user_check, - group_impression_rank, - impression_rank, - check_in_all -) +from nonebot import on_command, on_regex from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message from nonebot.adapters.onebot.v11.permission import GROUP -from utils.message_builder import image -from nonebot import on_command, on_regex -from utils.utils import scheduler from nonebot.params import CommandArg, RegexGroup -from pathlib import Path + from configs.path_config import DATA_PATH from services.log import logger -from .utils import clear_sign_data_pic -from utils.utils import is_number +from utils.message_builder import image +from utils.utils import is_number, scheduler + from .goods_register import driver +from .group_user_checkin import ( + check_in_all, + group_impression_rank, + group_user_check, + group_user_check_in, + impression_rank, +) +from .utils import clear_sign_data_pic try: import ujson as json @@ -49,22 +50,34 @@ __plugin_settings__ = { } __plugin_cd_limit__ = {} __plugin_configs__ = { - "MAX_SIGN_GOLD": {"value": 200, "help": "签到好感度加成额外获得的最大金币数", "default_value": 200}, - "SIGN_CARD1_PROB": {"value": 0.2, "help": "签到好感度双倍加持卡Ⅰ掉落概率", "default_value": 0.2}, + "MAX_SIGN_GOLD": { + "value": 200, + "help": "签到好感度加成额外获得的最大金币数", + "default_value": 200, + "type": int, + }, + "SIGN_CARD1_PROB": { + "value": 0.2, + "help": "签到好感度双倍加持卡Ⅰ掉落概率", + "default_value": 0.2, + "type": float, + }, "SIGN_CARD2_PROB": { "value": 0.09, "help": "签到好感度双倍加持卡Ⅱ掉落概率", "default_value": 0.09, + "type": float, }, "SIGN_CARD3_PROB": { "value": 0.05, "help": "签到好感度双倍加持卡Ⅲ掉落概率", "default_value": 0.05, + "type": float, }, } -_file = Path(f"{DATA_PATH}/not_show_sign_rank_user.json") +_file = DATA_PATH / "not_show_sign_rank_user.json" try: data = json.load(open(_file, "r", encoding="utf8")) except (FileNotFoundError, ValueError, TypeError): diff --git a/plugins/update_gocqhttp/__init__.py b/plugins/update_gocqhttp/__init__.py index 41750f5c..a5edde60 100755 --- a/plugins/update_gocqhttp/__init__.py +++ b/plugins/update_gocqhttp/__init__.py @@ -1,14 +1,17 @@ -from nonebot import on_command -from nonebot.typing import T_State -from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent -from .data_source import download_gocq_lasted, upload_gocq_lasted -from services.log import logger -from utils.utils import scheduler, get_bot -from nonebot.permission import SUPERUSER -from configs.config import Config -from pathlib import Path import os +from pathlib import Path +from typing import List +from nonebot import on_command +from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent +from nonebot.permission import SUPERUSER +from nonebot.typing import T_State + +from configs.config import Config +from services.log import logger +from utils.utils import get_bot, scheduler + +from .data_source import download_gocq_lasted, upload_gocq_lasted __zx_plugin_name__ = "更新gocq [Superuser]" __plugin_usage__ = """ @@ -25,6 +28,7 @@ __plugin_configs__ = { "value": [], "help": "需要为哪些群更新最新版gocq吗?(上传最新版gocq)示例:[434995955, 239483248]", "default_value": [], + "type": List[int], } } diff --git a/plugins/web_ui/__init__.py b/plugins/web_ui/__init__.py index 29e8a05d..866a76ca 100644 --- a/plugins/web_ui/__init__.py +++ b/plugins/web_ui/__init__.py @@ -1,12 +1,13 @@ +from nonebot.adapters.onebot.v11 import Bot, MessageEvent +from nonebot.matcher import Matcher +from nonebot.message import IgnoredException, run_preprocessor +from nonebot.typing import T_State + from configs.config import Config as gConfig +from utils.manager import plugins2settings_manager + from .api import * from .auth import * -from nonebot.matcher import Matcher -from nonebot.message import run_preprocessor, IgnoredException -from utils.manager import plugins2settings_manager -from nonebot.typing import T_State -from nonebot.adapters.onebot.v11 import Bot, MessageEvent - gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名") diff --git a/plugins/word_bank/__init__.py b/plugins/word_bank/__init__.py index fbb865c6..53560769 100644 --- a/plugins/word_bank/__init__.py +++ b/plugins/word_bank/__init__.py @@ -1,6 +1,9 @@ +from pathlib import Path + +import nonebot + from configs.config import Config from utils.utils import GDict -import nonebot Config.add_plugin_config( "word_bank", @@ -8,9 +11,10 @@ Config.add_plugin_config( 5, name="词库问答", help_="设置增删词库的权限等级", - default_value=5 + default_value=5, + type=int, ) -GDict['run_sql'].append("ALTER TABLE word_bank2 ADD to_me VARCHAR(255);") +GDict["run_sql"].append("ALTER TABLE word_bank2 ADD to_me VARCHAR(255);") -nonebot.load_plugins("plugins/word_bank") +nonebot.load_plugins(str(Path(__file__).parent.resolve())) diff --git a/plugins/word_clouds/__init__.py b/plugins/word_clouds/__init__.py index 944d40ab..ab703941 100644 --- a/plugins/word_clouds/__init__.py +++ b/plugins/word_clouds/__init__.py @@ -1,16 +1,19 @@ import re from datetime import datetime, timedelta from typing import Tuple, Union + import pytz -from nonebot import on_command, get_driver +from nonebot import get_driver, on_command from nonebot.adapters.onebot.v11 import Message, MessageSegment from nonebot.adapters.onebot.v11.event import GroupMessageEvent from nonebot.matcher import Matcher from nonebot.params import Arg, Command, CommandArg, Depends from nonebot.typing import T_State -from .data_source import draw_word_cloud, get_list_msg + from configs.config import Config +from .data_source import draw_word_cloud, get_list_msg + __zx_plugin_name__ = "词云" __plugin_usage__ = """ @@ -60,13 +63,16 @@ wordcloud_cmd = on_command( "我的本月词云", "我的年度词云", "我的历史词云", - }, block=True, priority=5 + }, + block=True, + priority=5, ) Config.add_plugin_config( "word_clouds", "WORD_CLOUDS_TEMPLATE", 1, - help_="词云模板 参1:图片生成,默认使用真寻图片,可在项目路径resources/image/wordcloud下配置图片,多张则随机 | 参2/其他:黑底图片" + help_="词云模板 参1:图片生成,默认使用真寻图片,可在项目路径resources/image/wordcloud下配置图片,多张则随机 | 参2/其他:黑底图片", + type=int, ) @@ -74,9 +80,9 @@ def parse_datetime(key: str): """解析数字,并将结果存入 state 中""" async def _key_parser( - matcher: Matcher, - state: T_State, - input_: Union[datetime, Message] = Arg(key), + matcher: Matcher, + state: T_State, + input_: Union[datetime, Message] = Arg(key), ): if isinstance(input_, datetime): return @@ -102,10 +108,10 @@ def get_datetime_fromisoformat_with_timezone(date_string: str) -> datetime: @wordcloud_cmd.handle() async def handle_first_receive( - event: GroupMessageEvent, - state: T_State, - commands: Tuple[str, ...] = Command(), - args: Message = CommandArg(), + event: GroupMessageEvent, + state: T_State, + commands: Tuple[str, ...] = Command(), + args: Message = CommandArg(), ): command = commands[0] @@ -172,10 +178,10 @@ async def handle_first_receive( parameterless=[Depends(parse_datetime("stop"))], ) async def handle_message( - event: GroupMessageEvent, - start: datetime = Arg(), - stop: datetime = Arg(), - my: bool = Arg(), + event: GroupMessageEvent, + start: datetime = Arg(), + stop: datetime = Arg(), + my: bool = Arg(), ): # 是否只查询自己的记录 if my: @@ -183,9 +189,14 @@ async def handle_message( else: user_id = None # 将时间转换到 东八 时区 - messages = await get_list_msg(user_id, int(event.group_id), - days=(start.astimezone(pytz.timezone("Asia/Shanghai")), - stop.astimezone(pytz.timezone("Asia/Shanghai")))) + messages = await get_list_msg( + user_id, + int(event.group_id), + days=( + start.astimezone(pytz.timezone("Asia/Shanghai")), + stop.astimezone(pytz.timezone("Asia/Shanghai")), + ), + ) if messages: image_bytes = await draw_word_cloud(messages, get_driver().config) if image_bytes: diff --git a/poetry.lock b/poetry.lock index c5887772..f32793b7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -254,6 +254,23 @@ type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" reference = "ali" +[[package]] +name = "cattrs" +version = "22.2.0" +description = "Composable complex class support for attrs and dataclasses." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=20" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} + +[package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" +reference = "ali" + [[package]] name = "certifi" version = "2022.12.7" @@ -437,6 +454,22 @@ type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" reference = "ali" +[[package]] +name = "exceptiongroup" +version = "1.1.0" +description = "Backport of PEP 654 (exception groups)" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest (>=6)"] + +[package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" +reference = "ali" + [[package]] name = "fastapi" version = "0.88.0" @@ -1876,7 +1909,7 @@ reference = "ali" [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "98eb1c3b662c674caee17f448657522b88489ea5b7ad13c5ccc02dde313ce7ab" +content-hash = "30f718b1d834abeaf0be2239ac66ebf40d71ca72b28ecea5b13d64aedeaaa6a9" [metadata.files] aiofiles = [ @@ -2025,6 +2058,10 @@ cachetools = [ {file = "cachetools-5.2.0-py3-none-any.whl", hash = "sha256:f9f17d2aec496a9aa6b76f53e3b614c965223c061982d434d160f930c698a9db"}, {file = "cachetools-5.2.0.tar.gz", hash = "sha256:6a94c6402995a99c3970cc7e4884bb60b4a8639938157eeed436098bf9831757"}, ] +cattrs = [ + {file = "cattrs-22.2.0-py3-none-any.whl", hash = "sha256:bc12b1f0d000b9f9bee83335887d532a1d3e99a833d1bf0882151c97d3e68c21"}, + {file = "cattrs-22.2.0.tar.gz", hash = "sha256:f0eed5642399423cf656e7b66ce92cdc5b963ecafd041d1b24d136fdde7acf6d"}, +] certifi = [ {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, @@ -2135,6 +2172,10 @@ ecdsa = [ emoji = [ {file = "emoji-1.7.0.tar.gz", hash = "sha256:65c54533ea3c78f30d0729288998715f418d7467de89ec258a31c0ce8660a1d1"}, ] +exceptiongroup = [ + {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, + {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"}, diff --git a/pyproject.toml b/pyproject.toml index 2a147cb3..bac2193f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ nonebot-plugin-apscheduler = "^0.2.0" nonebot-plugin-htmlrender = "^0.2.0" cachetools = "^5.2.0" tortoise-orm = {extras = ["asyncpg"], version = "^0.19.3"} +cattrs = "^22.2.0" [tool.poetry.dev-dependencies]