diff --git a/.gitignore b/.gitignore index 7b9fe23b..546a912d 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,4 @@ Yu-Gi-Oh/ search_image/ black_word/ csgo/ +fantasy_card/ diff --git a/README.md b/README.md index af826ec2..064ed779 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,26 @@ python bot.py ## 更新 -### 2021/1/5 \[v0.0.7.2] +### 2021/1/16 \[v0.0.9.0] + +* Ai提供文本敏感词过滤器 +* 疫情插件适配新版腾讯API +* 修复/t回复带空格切分 +* 修复原神玩家查询缺少渊下宫和稻妻家园以及角色不完全 +* 修复方法 text2image 中 padding 和 font 无法对纯文本生效 +* 修复签到图片中信息并未使用配置文件中的色图概率 +* 修改原神大地图合成方式,改为先压缩再合成 +* bag_user弃用字段props(该字段会在下次更新删除),使用新字段property +* 数据库中所有belonging_group统一修改为group_id +* 商店将registered_use和register_goods更名为register_use何register_goods +* 商品注册提供了kwargs参数提供: + * bot + * event + * 特殊字段 + * “send_success_msg”(发送成功的交互信息->即:使用道具 {name} {num} 次成功) + * “_max_num_limit”(该道具单次使用的最多个数,默认1) + +### 2021/1/5 \[v0.0.8.3] * 提供金币消费hook,可在plugins2settings.yaml中配置该功能需要消费的金币 * 商店插件将作为内置插件移动至basic_plugins diff --git a/__version__ b/__version__ index 0cfce081..9665f943 100644 --- a/__version__ +++ b/__version__ @@ -1 +1 @@ -__version__: v0.0.8.0 +__version__: v0.0.8.1 diff --git a/basic_plugins/admin_bot_manage/custom_welcome_message.py b/basic_plugins/admin_bot_manage/custom_welcome_message.py index dc06f9ef..6d50842d 100755 --- a/basic_plugins/admin_bot_manage/custom_welcome_message.py +++ b/basic_plugins/admin_bot_manage/custom_welcome_message.py @@ -1,5 +1,5 @@ from nonebot import on_command -from utils.utils import get_message_text, get_message_imgs +from utils.utils import get_message_text, get_message_img from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, GroupMessageEvent from .data_source import custom_group_welcome @@ -38,7 +38,7 @@ custom_welcome = on_command( async def _(bot: Bot, event: GroupMessageEvent, state: T_State): try: msg = get_message_text(event.json()) - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) if not msg and not imgs: await custom_welcome.finish(__plugin_usage__) await custom_welcome.send( diff --git a/basic_plugins/broadcast/__init__.py b/basic_plugins/broadcast/__init__.py index 97f129b4..1d5b3d3c 100755 --- a/basic_plugins/broadcast/__init__.py +++ b/basic_plugins/broadcast/__init__.py @@ -3,7 +3,7 @@ from nonebot.typing import T_State from nonebot.adapters import Bot, Event from nonebot.permission import SUPERUSER import asyncio -from utils.utils import get_message_text, get_message_imgs +from utils.utils import get_message_text, get_message_img from services.log import logger from utils.message_builder import image from utils.manager import group_manager @@ -35,7 +35,7 @@ broadcast = on_command("广播-", priority=1, permission=SUPERUSER, block=True) @broadcast.handle() async def _(bot: Bot, event: Event, state: T_State): msg = get_message_text(event.json()) - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) rst = "" for img in imgs: rst += image(img) diff --git a/basic_plugins/help/data_source.py b/basic_plugins/help/data_source.py index e10fc521..fe25a262 100755 --- a/basic_plugins/help/data_source.py +++ b/basic_plugins/help/data_source.py @@ -111,7 +111,7 @@ def _create_help_img( logger.warning(f"{type(e)}: {e}") else: matchers_data[plugin_type][plugin_name] = { - "module": matcher.module, + "modules": matcher.module, "des": plugin_des, "cmd": plugin_cmd, "text_type": text_type, @@ -147,16 +147,16 @@ def _create_help_img( # 禁用flag flag = True if plugins_manager.get_plugin_status( - matchers_data[type_][k]["module"], "all" + matchers_data[type_][k]["modules"], "all" ): flag = False if group_id: flag = flag and plugins_manager.get_plugin_status( - matchers_data[type_][k]["module"], "group" + matchers_data[type_][k]["modules"], "group" ) simple_help_str += ( f"{i+1}.{k}<|_|~|>" - f"{group_manager.get_plugin_status(matchers_data[type_][k]['module'], group_id) if group_id else '_'}|" + f"{group_manager.get_plugin_status(matchers_data[type_][k]['modules'], group_id) if group_id else '_'}|" f"{flag}\n" ) if matchers_data[type_][k]["text_type"] == 1: diff --git a/basic_plugins/hooks/auth_hook.py b/basic_plugins/hooks/auth_hook.py index 865b07bc..a93b0b03 100755 --- a/basic_plugins/hooks/auth_hook.py +++ b/basic_plugins/hooks/auth_hook.py @@ -260,34 +260,6 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State): # 以下为限制检测 ####################################################### # 以下为限制检测 ####################################################### # 以下为限制检测 ####################################################### - - # Cd - if plugins2cd_manager.check_plugin_cd_status(module): - plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module) - check_type = plugin_cd_data["check_type"] - limit_type = plugin_cd_data["limit_type"] - rst = plugin_cd_data["rst"] - if ( - (isinstance(event, PrivateMessageEvent) and check_type == "private") - or (isinstance(event, GroupMessageEvent) and check_type == "group") - or plugins2cd_manager.get_plugin_data(module).get("check_type") == "all" - ): - cd_type_ = event.user_id - if limit_type == "group" and isinstance(event, GroupMessageEvent): - cd_type_ = event.group_id - if not plugins2cd_manager.check(module, cd_type_): - if rst: - rst = await init_rst(rst, event) - await send_msg(rst, bot, event) - raise IgnoredException(f"{module} 正在cd中...") - else: - plugins2cd_manager.start_cd(module, cd_type_) - module = matcher.module - if ( - isinstance(event, GroupMessageEvent) - and status_message_manager.get(event.group_id) is None - ): - status_message_manager.delete(event.group_id) # Cd if plugins2cd_manager.check_plugin_cd_status(module): plugin_cd_data = plugins2cd_manager.get_plugin_cd_data(module) diff --git a/basic_plugins/scripts.py b/basic_plugins/scripts.py index 90ae168e..8272239d 100755 --- a/basic_plugins/scripts.py +++ b/basic_plugins/scripts.py @@ -1,11 +1,17 @@ +from asyncpg.exceptions import ( + DuplicateColumnError, + UndefinedColumnError, + PostgresSyntaxError, +) from nonebot import Driver from services.db_context import db -from asyncpg.exceptions import DuplicateColumnError from models.group_info import GroupInfo +from models.bag_user import BagUser from nonebot.adapters.cqhttp import Bot from services.log import logger from configs.path_config import TEXT_PATH from asyncio.exceptions import TimeoutError +from typing import List from utils.http_utils import AsyncHttpx from utils.utils import scheduler from pathlib import Path @@ -61,15 +67,70 @@ async def _(): """ 数据库表结构变换 """ + _flag = [] sql_str = [ - "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;" # group_info表添加一个group_flag + ( + "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;", + "group_info", + ), # group_info表添加一个group_flag + ( + "ALTER TABLE bag_users rename belonging_group To group_id;", + "bag_users", + ), # 将 bag_users 的 belonging_group 改为 group_id + ( + "ALTER TABLE group_info_users rename belonging_group To group_id;", + "group_info_users", + ), + ( + "ALTER TABLE sign_group_users rename belonging_group To group_id;", + "sign_group_users", + ), + ( + "ALTER TABLE open_cases_users rename belonging_group To group_id;", + "open_cases_users", + ), + ( + "ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';", + "bag_users", + ), # bag_users 新增字段 property 替代 props ] for sql in sql_str: try: + flag = sql[1] + sql = sql[0] query = db.text(sql) await db.first(query) - except DuplicateColumnError: + logger.info(f"完成sql操作:{sql}") + _flag.append(flag) + except (DuplicateColumnError, UndefinedColumnError): pass + except PostgresSyntaxError: + logger.error(f"语法错误:执行sql失败:{sql}") + # bag_user 将文本转为字典格式 + await __database_script(_flag) + + # 完成后 + end_sql_str = [ + # "ALTER TABLE bag_users DROP COLUMN props;" # 删除 bag_users 的 props 字段(还不到时候) + ] + for sql in end_sql_str: + try: + query = db.text(sql) + await db.first(query) + logger.info(f"完成执行sql操作:{sql}") + except (DuplicateColumnError, UndefinedColumnError): + pass + except PostgresSyntaxError: + logger.error(f"语法错误:执行sql失败:{sql}") + + # str2json_sql = ["alter table bag_users alter COLUMN props type json USING props::json;"] # 字段类型替换 + # rename_sql = 'alter table {} rename {} to {};' # 字段更名 + # for sql in str2json_sql: + # try: + # query = db.text(sql) + # await db.first(query) + # except DuplicateColumnError: + # pass @driver.on_bot_connect @@ -105,6 +166,26 @@ async def _(bot: Bot): logger.info(f"移除不存在的群聊信息:{group_id}") +async def __database_script(_flag: List[str]): + # bag_user 将文本转为字典格式 + if "bag_users" in _flag: + for x in await BagUser.get_all_users(): + props = {} + if x.props: + for prop in [p for p in x.props.split(",") if p]: + if props.get(prop): + props[prop] += 1 + else: + props[prop] = 1 + logger.info( + f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}" + ) + await x.update( + property=props, + props="", + ).apply() + + # 自动更新城市列表 @scheduler.scheduled_job( "cron", diff --git a/basic_plugins/shop/buy.py b/basic_plugins/shop/buy.py index 8b627c4d..374464dc 100644 --- a/basic_plugins/shop/buy.py +++ b/basic_plugins/shop/buy.py @@ -29,6 +29,9 @@ __plugin_settings__ = { "limit_superuser": False, "cmd": ["商店", "购买道具"], } +__plugin_cd_limit__ = { + "cd": 3 +} buy = on_command("购买", aliases={"购买道具"}, priority=5, block=True, permission=GROUP) @@ -69,7 +72,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): await BagUser.get_gold(event.user_id, event.group_id) ) < goods.goods_price * num * goods.goods_discount: await buy.finish("您的金币好像不太够哦", at_sender=True) - if await BagUser.buy_props(event.user_id, event.group_id, goods, num): + if await BagUser.buy_property(event.user_id, event.group_id, goods, num): await buy.send( f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!", at_sender=True, diff --git a/basic_plugins/shop/gold.py b/basic_plugins/shop/gold.py index 688df78b..e748c9b5 100644 --- a/basic_plugins/shop/gold.py +++ b/basic_plugins/shop/gold.py @@ -34,7 +34,7 @@ gold_rank = on_command("金币排行", priority=5, block=True, permission=GROUP) @my_gold.handle() async def _(bot: Bot, event: GroupMessageEvent, state: T_State): - await my_gold.finish(await BagUser.get_my_total_gold(event.user_id, event.group_id)) + await my_gold.finish(await BagUser.get_user_total_gold(event.user_id, event.group_id)) @gold_rank.handle() diff --git a/basic_plugins/shop/my_props.py b/basic_plugins/shop/my_props.py index cbf0f778..8d8d686d 100644 --- a/basic_plugins/shop/my_props.py +++ b/basic_plugins/shop/my_props.py @@ -31,21 +31,11 @@ my_props = on_command("我的道具", priority=5, block=True, permission=GROUP) @my_props.handle() async def _(bot: Bot, event: GroupMessageEvent, state: T_State): - props = await BagUser.get_props(event.user_id, event.group_id) + props = await BagUser.get_property(event.user_id, event.group_id) if props: - pname_list = [] - pnum_list = [] rst = "" - props = props[:-1].split(",") - for p in props: - if p != "": - if p in pname_list: - pnum_list[pname_list.index(p)] += 1 - else: - pname_list.append(p) - pnum_list.append(1) - for i in range(len(pname_list)): - rst += f"{i+1}.{pname_list[i]}\t×{pnum_list[i]}\n" + for i, p in enumerate(props.keys()): + rst += f"{i+1}.{p}\t×{props[p]}\n" await my_props.send("\n" + rst[:-1], at_sender=True) logger.info(f"USER {event.user_id} GROUP {event.group_id} 查看我的道具") else: diff --git a/basic_plugins/shop/shop_handle/__init__.py b/basic_plugins/shop/shop_handle/__init__.py index a1db15cf..74082045 100644 --- a/basic_plugins/shop/shop_handle/__init__.py +++ b/basic_plugins/shop/shop_handle/__init__.py @@ -3,7 +3,7 @@ from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent from nonebot.typing import T_State from configs.path_config import IMAGE_PATH from utils.message_builder import image -from .data_source import create_shop_help, delete_goods, update_goods, registered_goods, parse_goods_info +from .data_source import create_shop_help, delete_goods, update_goods, register_goods, parse_goods_info from nonebot.permission import SUPERUSER from utils.utils import get_message_text, is_number from nonebot.plugin import export @@ -53,7 +53,7 @@ __plugin_block_limit__ = { # 导出方法供其他插件使用 export = export() -export.registered_goods = registered_goods +export.register_goods = register_goods export.delete_goods = delete_goods export.update_goods = update_goods @@ -80,7 +80,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): await shop_add_goods.finish(data) if not data.get("name") or not data.get("price") or not data.get("des"): await shop_add_goods.finish("name:price:des 参数不可缺少!") - if await registered_goods(**data): + if await register_goods(**data): await shop_add_goods.send(f"添加商品 {data['name']} 成功!\n" f"名称:{data['name']}\n" f"价格:{data['price']}金币\n" diff --git a/basic_plugins/shop/shop_handle/data_source.py b/basic_plugins/shop/shop_handle/data_source.py index e2196f27..2c4973ef 100644 --- a/basic_plugins/shop/shop_handle/data_source.py +++ b/basic_plugins/shop/shop_handle/data_source.py @@ -20,36 +20,24 @@ async def init_default_shop_goods(): """ 导入内置的三个商品 """ - - async def sign_card_1(**kwargs): + async def sign_card(**kwargs): user_id = kwargs['user_id'] group_id = kwargs['group_id'] + prob = kwargs["prob"] user = await SignGroupUser.ensure(user_id, group_id) - await user.update(add_probability=0.1).apply() - - async def sign_card_2(**kwargs): - user_id = kwargs['user_id'] - group_id = kwargs['group_id'] - user = await SignGroupUser.ensure(user_id, group_id) - await user.update(add_probability=0.2).apply() - - async def sign_card_3(**kwargs): - user_id = kwargs['user_id'] - group_id = kwargs['group_id'] - user = await SignGroupUser.ensure(user_id, group_id) - await user.update(add_probability=0.3).apply() + await user.update(add_probability=prob).apply() if Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS"): - await registered_goods( + await register_goods( "好感度双倍加持卡Ⅰ", 30, "下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)" ) - use.registered_use("好感度双倍加持卡Ⅰ", sign_card_1) - await registered_goods("好感度双倍加持卡Ⅱ", 150, "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)") - use.registered_use("好感度双倍加持卡Ⅱ", sign_card_2) - await registered_goods( + use.register_use("好感度双倍加持卡Ⅰ", sign_card, **{"prob": 0.1}) + await register_goods("好感度双倍加持卡Ⅱ", 150, "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)") + use.register_use("好感度双倍加持卡Ⅱ", sign_card, **{"prob": 0.2}) + await register_goods( "好感度双倍加持卡Ⅲ", 250, "下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)" ) - use.registered_use("好感度双倍加持卡Ⅲ", sign_card_3) + use.register_use("好感度双倍加持卡Ⅲ", sign_card, **{"prob": 0.3}) # 创建商店界面 @@ -136,7 +124,7 @@ async def create_shop_help() -> str: return shop.pic2bs4() -async def registered_goods( +async def register_goods( name: str, price: int, des: str, diff --git a/basic_plugins/shop/use/__init__.py b/basic_plugins/shop/use/__init__.py index addcd695..408dc6d8 100644 --- a/basic_plugins/shop/use/__init__.py +++ b/basic_plugins/shop/use/__init__.py @@ -7,7 +7,7 @@ from models.bag_user import BagUser from nonebot.adapters.cqhttp.permission import GROUP from services.db_context import db from nonebot.plugin import export -from .data_source import effect, registered_use +from .data_source import effect, register_use, func_manager __zx_plugin_name__ = "商店 - 使用道具" @@ -15,7 +15,7 @@ __plugin_usage__ = """ usage: 普通的使用道具 指令: - 使用道具 [序号或道具名称] + 使用道具 [序号或道具名称] ?[数量]=1 * 序号以 ”我的道具“ 为准 * """.strip() __plugin_des__ = "商店 - 使用道具" @@ -32,7 +32,7 @@ __plugin_settings__ = { # 导出方法供其他插件使用 export = export() -export.registered_use = registered_use +export.register_use = register_use use_props = on_command("使用道具", priority=5, block=True, permission=GROUP) @@ -42,35 +42,40 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): msg = get_message_text(event.json()) if msg in ["", "帮助"]: await use_props.finish(__plugin_usage__) - props = await BagUser.get_props(event.user_id, event.group_id) - if props: + num = 1 + msg_sp = msg.split() + if len(msg_sp) > 1 and is_number(msg_sp[-1]) and int(msg_sp[-1]) > 0: + num = int(msg.split()[-1]) + msg = " ".join(msg.split()[:-1]) + property_ = await BagUser.get_property(event.user_id, event.group_id) + if property_: async with db.transaction(): - pname_list = [] - props = props[:-1].split(",") - for p in props: - if p != "": - if p not in pname_list: - pname_list.append(p) if is_number(msg): - if 0 < int(msg) <= len(pname_list): - name = pname_list[int(msg) - 1] + if 0 < int(msg) <= len(property_): + name = list(property_.keys())[int(msg) - 1] else: await use_props.finish("仔细看看自己的道具仓库有没有这个道具?", at_sender=True) else: - if msg not in pname_list: + if msg not in property_.keys(): await use_props.finish("道具名称错误!", at_sender=True) name = msg - if await BagUser.del_props( - event.user_id, event.group_id, name - ) and await effect(event.user_id, event.group_id, name): - await use_props.send(f"使用道具 {name} 成功!", at_sender=True) + _user_prop_count = property_[name] + if num > _user_prop_count: + await use_props.finish(f"道具数量不足,无法使用{num}次!") + if num > (n := func_manager.get_max_num_limit(name)): + await use_props.finish(f"该道具单次只能使用 {n} 个!") + if await BagUser.delete_property( + event.user_id, event.group_id, name, num + ) and await effect(bot, event, name, num): + if func_manager.check_send_success_message(name): + await use_props.send(f"使用道具 {name} {num} 次成功!", at_sender=True) logger.info( - f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 成功" + f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次成功" ) else: - await use_props.send(f"使用道具 {name} 失败!", at_sender=True) + await use_props.send(f"使用道具 {name} {num} 次失败!", at_sender=True) logger.info( - f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 失败" + f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次失败" ) else: - await use_props.send("您的背包里没有任何的道具噢~", at_sender=True) + await use_props.send("您的背包里没有任何的道具噢", at_sender=True) diff --git a/basic_plugins/shop/use/data_source.py b/basic_plugins/shop/use/data_source.py index 4629e757..d1fc82bc 100644 --- a/basic_plugins/shop/use/data_source.py +++ b/basic_plugins/shop/use/data_source.py @@ -1,45 +1,119 @@ -import asyncio +from nonebot.adapters.cqhttp import GroupMessageEvent from services.log import logger - -_use_func_data = {} +from nonebot.adapters.cqhttp import Bot +import asyncio -async def effect(user_id: int, group_id: int, goods_name: str) -> bool: +class GoodsUseFuncManager: + def __init__(self): + self._data = {} + + def register_use(self, goods_name: str, **kwargs): + """ + 注册商品使用方法 + :param goods_name: 商品名称 + :param kwargs: kwargs + """ + self._data[goods_name] = kwargs + + def exists(self, goods_name: str) -> bool: + """ + 判断商品使用方法是否被注册 + :param goods_name: 商品名称 + """ + return bool(self._data.get(goods_name)) + + def get_max_num_limit(self, goods_name: str) -> int: + """ + 获取单次商品使用数量 + :param goods_name: 商品名称 + """ + if self.exists(goods_name): + return self._data[goods_name]["kwargs"]["_max_num_limit"] + return 1 + + async def use(self, **kwargs): + """ + 使用道具 + :param kwargs: kwargs + """ + goods_name = kwargs.get("goods_name") + if self.exists(goods_name): + if asyncio.iscoroutinefunction(self._data[goods_name]["func"]): + await self._data[goods_name]["func"]( + **kwargs, + ) + else: + self._data[goods_name]["func"]( + **kwargs, + ) + + def check_send_success_message(self, goods_name: str) -> bool: + """ + 检查是否发送使用成功信息 + :param goods_name: 商品名称 + """ + if self.exists(goods_name): + return bool(self._data[goods_name]["kwargs"]["send_success_msg"]) + return False + + def get_kwargs(self, goods_name: str) -> dict: + """ + 获取商品使用方法的kwargs + :param goods_name: 商品名称 + """ + if self.exists(goods_name): + return self._data[goods_name]["kwargs"] + return {} + + +func_manager = GoodsUseFuncManager() + + +async def effect(bot: Bot, event: GroupMessageEvent, goods_name: str, num: int) -> bool: """ 商品生效 - :param user_id: 用户id - :param group_id: 群号 + :param bot: Bot + :param event: GroupMessageEvent :param goods_name: 商品名称 + :param num: 使用数量 :return: 使用是否成功 """ # 优先使用注册的商品插件 try: - if _use_func_data.get(goods_name): - _kwargs = _use_func_data[goods_name]["kwargs"] - _kwargs["goods_name"] = goods_name - _kwargs["user_id"] = user_id - _kwargs["group_id"] = group_id - if asyncio.iscoroutinefunction(_use_func_data[goods_name]["func"]): - await _use_func_data[goods_name]["func"]( + if func_manager.exists(goods_name): + _kwargs = func_manager.get_kwargs(goods_name) + await func_manager.use( + **{ **_kwargs, - ) - else: - _use_func_data[goods_name]["func"]( - **_kwargs, - ) + "_bot": bot, + "event": event, + "group_id": event.group_id, + "user_id": event.user_id, + "num": num, + "goods_name": goods_name, + } + ) return True except Exception as e: logger.error(f"use 商品生效函数effect 发生错误 {type(e)}:{e}") return False -def registered_use(goods_name: str, func, **kwargs): +def register_use(goods_name: str, func, **kwargs): """ 注册商品使用方法 :param goods_name: 商品名称 :param func: 使用函数 :param kwargs: kwargs """ - if goods_name in _use_func_data.keys(): + if func_manager.exists(goods_name): raise ValueError("该商品使用函数已被注册!") - _use_func_data[goods_name] = {"func": func, "kwargs": kwargs} + # 发送使用成功信息 + if kwargs.get("send_success_msg") is None: + kwargs["send_success_msg"] = True + kwargs["_max_num_limit"] = ( + kwargs.get("_max_num_limit") if kwargs.get("_max_num_limit") else 1 + ) + func_manager.register_use(goods_name, **{"func": func, "kwargs": kwargs}) + logger.info(f"register_use 成功注册商品:{goods_name} 的使用函数") diff --git a/docs_image/3238573864-836268675-E2FFBB2AC143EAF4DDDF150438508721.png b/docs_image/3238573864-836268675-E2FFBB2AC143EAF4DDDF150438508721.png new file mode 100644 index 00000000..204a26ad Binary files /dev/null and b/docs_image/3238573864-836268675-E2FFBB2AC143EAF4DDDF150438508721.png differ diff --git a/models/bag_user.py b/models/bag_user.py index 935d50c5..63a3a282 100755 --- a/models/bag_user.py +++ b/models/bag_user.py @@ -1,4 +1,5 @@ from services.db_context import db +from typing import Dict from typing import Optional, List from services.log import logger @@ -7,33 +8,32 @@ class BagUser(db.Model): __tablename__ = "bag_users" id = db.Column(db.Integer(), primary_key=True) user_qq = db.Column(db.BigInteger(), nullable=False) - belonging_group = db.Column(db.BigInteger(), nullable=False) + group_id = db.Column(db.BigInteger(), nullable=False) gold = db.Column(db.Integer(), default=100) - props = db.Column(db.TEXT(), nullable=False, default="") + props = db.Column(db.TEXT(), nullable=False, default="") # 旧道具字段(废弃) spend_total_gold = db.Column(db.Integer(), default=0) get_total_gold = db.Column(db.Integer(), default=0) get_today_gold = db.Column(db.Integer(), default=0) spend_today_gold = db.Column(db.Integer(), default=0) + property = db.Column(db.JSON(), nullable=False, default={}) # 新道具字段 - _idx1 = db.Index("bag_group_users_idx1", "user_qq", "belonging_group", unique=True) + _idx1 = db.Index("bag_group_users_idx1", "user_qq", "group_id", unique=True) @classmethod - async def get_my_total_gold(cls, user_qq: int, belonging_group: int) -> str: + async def get_user_total_gold(cls, user_qq: int, group_id: int) -> str: """ 说明: 获取金币概况 参数: :param user_qq: qq号 - :param belonging_group: 所在群号 + :param group_id: 所在群号 """ - query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) - ) + query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id)) user = await query.gino.first() if not user: user = await cls.create( user_qq=user_qq, - belonging_group=belonging_group, + group_id=group_id, ) return ( f"当前金币:{user.gold}\n今日获取金币:{user.get_today_gold}\n今日花费金币:{user.spend_today_gold}" @@ -42,62 +42,56 @@ class BagUser(db.Model): ) @classmethod - async def get_gold(cls, user_qq: int, belonging_group: int) -> int: + async def get_gold(cls, user_qq: int, group_id: int) -> int: """ 说明: 获取当前金币 参数: :param user_qq: qq号 - :param belonging_group: 所在群号 + :param group_id: 所在群号 """ - query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) - ) + query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id)) user = await query.gino.first() if user: return user.gold else: await cls.create( user_qq=user_qq, - belonging_group=belonging_group, + group_id=group_id, ) return 100 @classmethod - async def get_props(cls, user_qq: int, belonging_group: int) -> str: + async def get_property(cls, user_qq: int, group_id: int) -> Dict[str, int]: """ 说明: 获取当前道具 参数: :param user_qq: qq号 - :param belonging_group: 所在群号 + :param group_id: 所在群号 """ - query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) - ) + query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id)) user = await query.gino.first() if user: - return user.props + return user.property else: await cls.create( user_qq=user_qq, - belonging_group=belonging_group, + group_id=group_id, ) - return "" + return {} @classmethod - async def add_gold(cls, user_qq: int, belonging_group: int, num: int): + async def add_gold(cls, user_qq: int, group_id: int, num: int): """ 说明: 增加金币 参数: :param user_qq: qq号 - :param belonging_group: 所在群号 + :param group_id: 所在群号 :param num: 金币数量 """ - query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) - ) + query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id)) query = query.with_for_update() user = await query.gino.first() if user: @@ -109,25 +103,23 @@ class BagUser(db.Model): else: await cls.create( user_qq=user_qq, - belonging_group=belonging_group, + group_id=group_id, gold=100 + num, get_total_gold=num, get_today_gold=num, ) @classmethod - async def spend_gold(cls, user_qq: int, belonging_group: int, num: int): + async def spend_gold(cls, user_qq: int, group_id: int, num: int): """ 说明: 花费金币 参数: :param user_qq: qq号 - :param belonging_group: 所在群号 + :param group_id: 所在群号 :param num: 金币数量 """ - query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) - ) + query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id)) query = query.with_for_update() user = await query.gino.first() if user: @@ -139,91 +131,84 @@ class BagUser(db.Model): else: await cls.create( user_qq=user_qq, - belonging_group=belonging_group, + group_id=group_id, gold=100 - num, spend_total_gold=num, spend_today_gold=num, ) @classmethod - async def add_props(cls, user_qq: int, belonging_group: int, name: str): + async def add_property(cls, user_qq: int, group_id: int, name: str): """ 说明: 增加道具 参数: :param user_qq: qq号 - :param belonging_group: 所在群号 + :param group_id: 所在群号 :param name: 道具名称 """ - query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) - ) + query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id)) query = query.with_for_update() user = await query.gino.first() if user: - await user.update(props=user.props + f"{name},").apply() + p = user.property + if p.get(name) is None: + p[name] = 1 + else: + p[name] += 1 + await user.update(property=p).apply() else: - await cls.create( - user_qq=user_qq, belonging_group=belonging_group, props=f"{name}," - ) + await cls.create(user_qq=user_qq, group_id=group_id, property={name: 1}) @classmethod - async def del_props(cls, user_qq: int, belonging_group: int, name: str) -> bool: + async def delete_property( + cls, user_qq: int, group_id: int, name: str, num: int = 1 + ) -> bool: """ 说明: - 使用道具 + 使用/删除 道具 参数: :param user_qq: qq号 - :param belonging_group: 所在群号 + :param group_id: 所在群号 :param name: 道具名称 + :param num: 使用个数 """ - query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) - ) + query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id)) query = query.with_for_update() user = await query.gino.first() if user: - rst = "" - props = user.props - if props.find(name) != -1: - props = props.split(",") - try: - index = props.index(name) - except ValueError: - return False - props = props[:index] + props[index + 1 :] - for p in props: - if p != "": - rst += p + "," - await user.update(props=rst).apply() + property_ = user.property + if name in property_: + if property_.get(name) == num: + del property_[name] + else: + property_[name] -= num + await user.update(property=property_).apply() return True - else: - return False - else: - return False + return False @classmethod - async def buy_props( - cls, user_qq: int, belonging_group: int, goods: "GoodsInfo", goods_num: int + async def buy_property( + cls, user_qq: int, group_id: int, goods: "GoodsInfo", goods_num: int ) -> bool: """ 说明: 购买道具 参数: :param user_qq: 用户qq - :param belonging_group: 所在群聊 + :param group_id: 所在群聊 :param goods: 商品 :param goods_num: 商品数量 """ try: # 折扣后金币 spend_gold = goods.goods_discount * goods.goods_price * goods_num - await BagUser.spend_gold(user_qq, belonging_group, spend_gold) + await BagUser.spend_gold(user_qq, group_id, spend_gold) for _ in range(goods_num): - await BagUser.add_props(user_qq, belonging_group, goods.goods_name) + await BagUser.add_property(user_qq, group_id, goods.goods_name) return True except Exception as e: - logger.error(f"buy_props 发生错误 {type(e)}:{e}") + logger.error(f"buy_property 发生错误 {type(e)}:{e}") return False @classmethod @@ -237,5 +222,5 @@ class BagUser(db.Model): if not group_id: query = await cls.query.gino.all() else: - query = await cls.query.where((cls.belonging_group == group_id)).gino.all() + query = await cls.query.where((cls.group_id == group_id)).gino.all() return query diff --git a/models/group_member_info.py b/models/group_member_info.py index 6db45bab..54c4ac11 100755 --- a/models/group_member_info.py +++ b/models/group_member_info.py @@ -10,18 +10,18 @@ class GroupInfoUser(db.Model): id = db.Column(db.Integer(), primary_key=True) user_qq = db.Column(db.BigInteger(), nullable=False) user_name = db.Column(db.Unicode(), nullable=False) - belonging_group = db.Column(db.BigInteger(), nullable=False) + group_id = db.Column(db.BigInteger(), nullable=False) user_join_time = db.Column(db.DateTime(), nullable=False) nickname = db.Column(db.Unicode()) uid = db.Column(db.BigInteger()) - _idx1 = db.Index("info_group_users_idx1", "user_qq", "belonging_group", unique=True) + _idx1 = db.Index("info_group_users_idx1", "user_qq", "group_id", unique=True) @classmethod async def add_member_info( cls, user_qq: int, - belonging_group: int, + group_id: int, user_name: str, user_join_time: datetime, uid: Optional[int] = None, @@ -31,20 +31,20 @@ class GroupInfoUser(db.Model): 添加群内用户信息 参数: :param user_qq: qq号 - :param belonging_group: 群号 + :param group_id: 群号 :param user_name: 用户名称 :param user_join_time: 入群时间 :param uid: 用户唯一 id(自动生成) """ query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ) try: if not await query.gino.first(): await cls.create( user_qq=user_qq, user_name=user_name, - belonging_group=belonging_group, + group_id=group_id, user_join_time=user_join_time, uid=uid ) @@ -54,31 +54,31 @@ class GroupInfoUser(db.Model): @classmethod async def get_member_info( - cls, user_qq: int, belonging_group: int + cls, user_qq: int, group_id: int ) -> "GroupInfoUser": """ 说明: 查询群员信息 参数: :param user_qq: qq号 - :param belonging_group: 群号 + :param group_id: 群号 """ query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ) return await query.gino.first() @classmethod - async def delete_member_info(cls, user_qq: int, belonging_group: int) -> bool: + async def delete_member_info(cls, user_qq: int, group_id: int) -> bool: """ 说明: 删除群员信息 参数: :param user_qq: qq号 - :param belonging_group: 群号 + :param group_id: 群号 """ query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ) query = query.with_for_update() user = await query.gino.first() @@ -87,40 +87,40 @@ class GroupInfoUser(db.Model): return True else: await cls.delete.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ).gino.status() return True except Exception: return False @classmethod - async def get_group_member_id_list(cls, belonging_group: int) -> List[int]: + async def get_group_member_id_list(cls, group_id: int) -> List[int]: """ 说明: 获取该群所有用户qq 参数: - :param belonging_group: 群号 + :param group_id: 群号 """ member_list = [] - query = cls.query.where((cls.belonging_group == belonging_group)) + query = cls.query.where((cls.group_id == group_id)) for user in await query.gino.all(): member_list.append(user.user_qq) return member_list @classmethod async def set_group_member_nickname( - cls, user_qq: int, belonging_group: int, nickname: str + cls, user_qq: int, group_id: int, nickname: str ) -> bool: """ 说明: 设置群员在该群内的昵称 参数: :param user_qq: qq号 - :param belonging_group: 群号 + :param group_id: 群号 :param nickname: 昵称 """ query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ) user = await query.with_for_update().gino.first() if user: @@ -136,20 +136,20 @@ class GroupInfoUser(db.Model): """ query = await cls.query.where(cls.user_qq == user_qq).gino.all() if query: - query = [x.belonging_group for x in query] + query = [x.group_id for x in query] return query @classmethod - async def get_group_member_nickname(cls, user_qq: int, belonging_group: int) -> str: + async def get_group_member_nickname(cls, user_qq: int, group_id: int) -> str: """ 说明: 获取用户在该群的昵称 参数: :param user_qq: qq号 - :param belonging_group: 群号 + :param group_id: 群号 """ query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ) user = await query.gino.first() if user: @@ -163,12 +163,12 @@ class GroupInfoUser(db.Model): return "" @classmethod - async def get_group_member_uid(cls, user_qq: int, belonging_group: int) -> Optional[str]: + async def get_group_member_uid(cls, user_qq: int, group_id: int) -> Optional[str]: query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ) user = await query.gino.first() - _max_uid = cls.query.where((cls.user_qq == 114514) & (cls.belonging_group == 114514)).with_for_update() + _max_uid = cls.query.where((cls.user_qq == 114514) & (cls.group_id == 114514)).with_for_update() _max_uid_user = await _max_uid.gino.first() _max_uid = _max_uid_user.uid if not user or not user.uid: @@ -178,9 +178,9 @@ class GroupInfoUser(db.Model): return x.uid else: if not user: - await GroupInfoUser.add_member_info(user_qq, belonging_group, '', datetime.min) + await GroupInfoUser.add_member_info(user_qq, group_id, '', datetime.min) user = await cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ).gino.first() await user.update( uid=_max_uid + 1, diff --git a/models/sign_group_user.py b/models/sign_group_user.py index 1c86677c..719f6889 100755 --- a/models/sign_group_user.py +++ b/models/sign_group_user.py @@ -8,8 +8,7 @@ class SignGroupUser(db.Model): id = db.Column(db.Integer(), primary_key=True) user_qq = db.Column(db.BigInteger(), nullable=False) - belonging_group = db.Column(db.BigInteger(), nullable=False) - + group_id = db.Column(db.BigInteger(), nullable=False) checkin_count = db.Column(db.Integer(), nullable=False) checkin_time_last = db.Column(db.DateTime(timezone=True), nullable=False) impression = db.Column(db.Numeric(scale=3, asdecimal=False), nullable=False) @@ -20,29 +19,29 @@ class SignGroupUser(db.Model): db.Numeric(scale=3, asdecimal=False), nullable=False, default=0 ) - _idx1 = db.Index("sign_group_users_idx1", "user_qq", "belonging_group", unique=True) + _idx1 = db.Index("sign_group_users_idx1", "user_qq", "group_id", unique=True) @classmethod async def ensure( - cls, user_qq: int, belonging_group: int, for_update: bool = False + cls, user_qq: int, group_id: int, for_update: bool = False ) -> "SignGroupUser": """ 说明: 获取签到用户 参数: :param user_qq: 用户qq - :param belonging_group: 所在群聊 + :param group_id: 所在群聊 :param for_update: 是否存在修改数据 """ query = cls.query.where( - (cls.user_qq == user_qq) & (cls.belonging_group == belonging_group) + (cls.user_qq == user_qq) & (cls.group_id == group_id) ) if for_update: query = query.with_for_update() user = await query.gino.first() return user or await cls.create( user_qq=user_qq, - belonging_group=belonging_group, + group_id=group_id, checkin_count=0, checkin_time_last=datetime.min, # 从未签到过 impression=0, @@ -79,22 +78,22 @@ class SignGroupUser(db.Model): ).apply() @classmethod - async def get_all_impression(cls, belonging_group: int) -> "list, list, list": + async def get_all_impression(cls, group_id: int) -> "list, list, list": """ 说明: 获取该群所有用户 id 及对应 好感度 参数: - :param belonging_group: 群号 + :param group_id: 群号 """ impression_list = [] user_qq_list = [] user_group = [] - if belonging_group: - query = cls.query.where(cls.belonging_group == belonging_group) + if group_id: + query = cls.query.where(cls.group_id == group_id) else: query = cls.query for user in await query.gino.all(): impression_list.append(user.impression) user_qq_list.append(user.user_qq) - user_group.append(user.belonging_group) + user_group.append(user.group_id) return user_qq_list, impression_list, user_group diff --git a/plugins/ai/__init__.py b/plugins/ai/__init__.py index 673844dd..37bc87b0 100755 --- a/plugins/ai/__init__.py +++ b/plugins/ai/__init__.py @@ -11,7 +11,7 @@ from nonebot.typing import T_State from models.friend_user import FriendUser from models.group_member_info import GroupInfoUser from services.log import logger -from utils.utils import get_message_text, get_message_imgs +from utils.utils import get_message_text, get_message_img from .data_source import get_chat_result, hello, no_result from configs.config import NICKNAME, Config @@ -21,27 +21,22 @@ usage: 与{NICKNAME}普普通通的对话吧! """ __plugin_version__ = 0.1 -__plugin_author__ = 'HibiKier' +__plugin_author__ = "HibiKier" __plugin_settings__ = { "level": 5, "cmd": ["Ai", "ai", "AI", "aI"], } __plugin_configs__ = { - "TL_KEY": { - "value": [], - "help": "图灵Key" + "TL_KEY": {"value": [], "help": "图灵Key"}, + "ALAPI_AI_CHECK": {"value": False, "help": "是否检测青云客骂娘回复", "default_value": False}, + "TEXT_FILTER": { + "value": ["鸡", "口交"], + "help": "文本过滤器,将敏感词更改为*", + "default_value": [], }, - "ALAPI_AI_CHECK": { - "value": False, - "help": "是否检测青云客骂娘回复", - "default_value": False - } } 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" ) ai = on_message(rule=to_me(), priority=8) @@ -50,11 +45,11 @@ ai = on_message(rule=to_me(), priority=8) @ai.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): msg = get_message_text(event.json()) - imgs = get_message_imgs(event.json()) + img = get_message_img(event.json()) if "CQ:xml" in str(event.get_message()): return # 打招呼 - if (not msg and not imgs) or msg in [ + if (not msg and not img) or msg in [ "你好啊", "你好", "在吗", @@ -65,7 +60,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): "在", ]: await ai.finish(hello()) - img = imgs[0] if imgs else "" + img = img[0] if img else "" if isinstance(event, GroupMessageEvent): nickname = await GroupInfoUser.get_group_member_nickname( event.user_id, event.group_id @@ -83,6 +78,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): f"问题:{msg} ---- 回答:{result}" ) if result: + for t in Config.get_config("ai", "TEXT_FILTER"): + result = result.replace(t, "*") await ai.finish(Message(result)) else: await ai.finish(no_result()) diff --git a/plugins/bilibili_sub/__init__.py b/plugins/bilibili_sub/__init__.py index 32697051..c7d316d0 100755 --- a/plugins/bilibili_sub/__init__.py +++ b/plugins/bilibili_sub/__init__.py @@ -9,7 +9,7 @@ from .data_source import ( get_media_id, get_sub_status, SubManager, - BilibiliSub + BilibiliSub, ) from models.level_user import LevelUser from configs.config import Config @@ -163,11 +163,10 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): @show_sub_info.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): - id_ = ( - f"{event.user_id}:{event.group_id}" - if isinstance(event, GroupMessageEvent) - else f"{event.user_id}" - ) + if isinstance(event, GroupMessageEvent): + id_ = f"{event.group_id}" + else: + id_ = f"{event.user_id}" data = await BilibiliSub.get_sub_data(id_) live_rst = "" up_rst = "" @@ -181,6 +180,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): up_rst += f"\tUP:{x.uname}\n" f"\tuid:{x.uid}\n" f"------------------\n" if x.sub_type == "season": season_rst += ( + f"\t番剧id:{x.sub_id}\n" f"\t番名:{x.season_name}\n" f"\t当前集数:{x.season_current_episode}\n" f"------------------\n" @@ -189,7 +189,9 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): up_rst = "当前订阅的UP:\n" + up_rst if up_rst else up_rst season_rst = "当前订阅的番剧:\n" + season_rst if season_rst else season_rst if not live_rst and not up_rst and not season_rst: - live_rst = "您目前没有任何订阅..." + live_rst = ( + "该群目前没有任何订阅..." if isinstance(event, GroupMessageEvent) else "您目前没有任何订阅..." + ) await show_sub_info.send(live_rst + up_rst + season_rst) diff --git a/plugins/bilibili_sub/data_source.py b/plugins/bilibili_sub/data_source.py index 039689da..338dc54c 100755 --- a/plugins/bilibili_sub/data_source.py +++ b/plugins/bilibili_sub/data_source.py @@ -165,7 +165,9 @@ async def get_media_id(keyword: str) -> dict: for _ in range(3): try: _season_data = {} - response = await AsyncHttpx.get(bilibili_search_url, params=params, timeout=5) + response = await AsyncHttpx.get( + bilibili_search_url, params=params, timeout=5 + ) if response.status_code == 200: data = response.json() if data.get("data"): @@ -254,7 +256,12 @@ async def _get_up_status(id_: int) -> Optional[str]: if dynamic_img: await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time) rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n" - if _user.latest_video_created < latest_video_created and video: + if ( + latest_video_created + and _user.latest_video_created + and video + and _user.latest_video_created < latest_video_created + ): rst = rst + "-------------\n" if rst else rst await BilibiliSub.update_sub_info( id_, latest_video_created=latest_video_created diff --git a/plugins/dialogue/__init__.py b/plugins/dialogue/__init__.py index 2d003ab2..a57bbdaa 100755 --- a/plugins/dialogue/__init__.py +++ b/plugins/dialogue/__init__.py @@ -2,7 +2,7 @@ from nonebot import on_command from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, MessageEvent, Message, GroupMessageEvent from nonebot.permission import SUPERUSER -from utils.utils import get_message_text, is_number, get_message_imgs +from utils.utils import get_message_text, is_number, get_message_img from utils.message_builder import image from utils.message_builder import text as _text from services.log import logger @@ -63,7 +63,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): coffee = int(list(bot.config.superusers)[0]) text = get_message_text(event.json()) img_msg = _text("") - for img in get_message_imgs(event.json()): + for img in get_message_img(event.json()): img_msg += image(img) if not text and not img_msg: await dialogue.send("请发送[滴滴滴]+您要说的内容~", at_sender=True) @@ -127,7 +127,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): id_ = msg[0] user_id = dialogue_data[id_]["user_id"] group_id = dialogue_data[id_]["group_id"] - text = msg[1] + text = " ".join(msg[1:]) dialogue_data.pop(id_) else: user_id = 0 @@ -140,13 +140,13 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): user_id = int(msg[0]) if is_number(msg[1]) and len(msg[1]) > 5: group_id = int(msg[1]) - text = msg[2] + text = " ".join(msg[2:]) else: group_id = 0 - text = msg[1] + text = " ".join(msg[1:]) else: await reply.finish("第一参数,请输入数字.....", at_sender=True) - for img in get_message_imgs(event.json()): + for img in get_message_img(event.json()): text += image(img) if group_id: if user_id: diff --git a/plugins/draw_card/announcement.py b/plugins/draw_card/announcement.py index f5c9f7f2..cb8b1813 100755 --- a/plugins/draw_card/announcement.py +++ b/plugins/draw_card/announcement.py @@ -35,7 +35,7 @@ def is_expired(data: dict): now = datetime.now().date() except ValueError: return False - return start_date <= now <= end_date + return not start_date <= now <= end_date # 检查写入 @@ -175,7 +175,7 @@ class GenshinAnnouncement: data[itype]['time'] = data[itype]['time'][:-1] if '版本更新后' in data[itype]['time']: sp = data[itype]['time'].split('~') - end_time = datetime.strptime(sp[1].strip(), "%Y/%m/%d %H:%M:%S") + end_time = datetime.strptime(sp[1].strip(), "%Y/%m/%d %H:%M") start_time = end_time - timedelta(days=20) data[itype]['time'] = start_time.strftime('%Y/%m/%d') + ' ~ ' + end_time.strftime('%Y/%m/%d') tmp = '' diff --git a/plugins/draw_card/genshin_handle.py b/plugins/draw_card/genshin_handle.py index e1f551aa..1d766ac4 100755 --- a/plugins/draw_card/genshin_handle.py +++ b/plugins/draw_card/genshin_handle.py @@ -2,9 +2,24 @@ import os from nonebot.adapters.cqhttp import MessageSegment, Message import random from .update_game_info import update_info -from .util import generate_img, init_star_rst, BaseData, set_list, get_star, init_up_char -from .config import GENSHIN_FIVE_P, GENSHIN_FOUR_P, GENSHIN_G_FIVE_P, GENSHIN_G_FOUR_P, GENSHIN_THREE_P, I72_ADD, \ - DRAW_PATH, GENSHIN_FLAG +from .util import ( + generate_img, + init_star_rst, + BaseData, + set_list, + get_star, + init_up_char, +) +from .config import ( + GENSHIN_FIVE_P, + GENSHIN_FOUR_P, + GENSHIN_G_FIVE_P, + GENSHIN_G_FOUR_P, + GENSHIN_THREE_P, + I72_ADD, + DRAW_PATH, + GENSHIN_FLAG, +) from dataclasses import dataclass from .init_card_pool import init_game_pool from .announcement import GenshinAnnouncement @@ -27,9 +42,9 @@ ALL_ARMS = [] UP_CHAR = [] UP_ARMS = [] -_CURRENT_CHAR_POOL_TITLE = '' -_CURRENT_ARMS_POOL_TITLE = '' -POOL_IMG = '' +_CURRENT_CHAR_POOL_TITLE = "" +_CURRENT_ARMS_POOL_TITLE = "" +POOL_IMG = "" @dataclass @@ -39,19 +54,25 @@ class GenshinChar(BaseData): async def genshin_draw(user_id: int, count: int, pool_name: str): # 0 1 2 - cnlist = ['★★★★★', '★★★★', '★★★'] - char_list, five_list, five_index_list, char_dict, star_list = _format_card_information(count, user_id, pool_name) - temp = '' - title = '' + cnlist = ["★★★★★", "★★★★", "★★★"] + ( + char_list, + five_list, + five_index_list, + char_dict, + star_list, + ) = _format_card_information(count, user_id, pool_name) + temp = "" + title = "" up_type = [] up_list = [] - if pool_name == 'char' and _CURRENT_CHAR_POOL_TITLE: + if pool_name == "char" and _CURRENT_CHAR_POOL_TITLE: up_type = UP_CHAR title = _CURRENT_CHAR_POOL_TITLE - elif pool_name == 'arms' and _CURRENT_ARMS_POOL_TITLE: + elif pool_name == "arms" and _CURRENT_ARMS_POOL_TITLE: up_type = UP_ARMS title = _CURRENT_ARMS_POOL_TITLE - tmp = '' + tmp = "" if up_type: for x in up_type: for operator in x.operators: @@ -61,80 +82,118 @@ async def genshin_draw(user_id: int, count: int, pool_name: str): elif x.star == 4: tmp += f'四星UP:{" ".join(x.operators)}' rst = init_star_rst(star_list, cnlist, five_list, five_index_list, up_list) - pool_info = f'当前up池:{title}\n{tmp}' if title else '' + pool_info = f"当前up池:{title}\n{tmp}" if title else "" if count > 90: char_list = set_list(char_list) - return pool_info + '\n' + MessageSegment.image( - "base64://" + await generate_img(char_list, 'genshin', star_list)) + '\n' + rst[:-1] + \ - temp[:-1] + f'\n距离保底发还剩 {90 - genshin_count[user_id] if genshin_count.get(user_id) else "^"} 抽' \ - + "\n【五星:0.6%,四星:5.1%\n第72抽开始五星概率每抽加0.585%】" + return ( + pool_info + + "\n" + + MessageSegment.image( + "base64://" + await generate_img(char_list, "genshin", star_list) + ) + + "\n" + + rst[:-1] + + temp[:-1] + + f'\n距离保底发还剩 {90 - genshin_count[user_id] if genshin_count.get(user_id) else "^"} 抽' + + "\n【五星:0.6%,四星:5.1%\n第72抽开始五星概率每抽加0.585%】" + ) async def update_genshin_info(): global ALL_CHAR, ALL_ARMS - url = 'https://wiki.biligame.com/ys/角色筛选' - data, code = await update_info(url, 'genshin') + url = "https://wiki.biligame.com/ys/角色筛选" + data, code = await update_info(url, "genshin") if code == 200: - ALL_CHAR = init_game_pool('genshin', data, GenshinChar) - url = 'https://wiki.biligame.com/ys/武器图鉴' - data, code = await update_info(url, 'genshin_arms', ['头像', '名称', '类型', '稀有度.alt', - '获取途径', '初始基础属性1', '初始基础属性2', - '攻击力(MAX)', '副属性(MAX)', '技能']) + ALL_CHAR = init_game_pool("genshin", data, GenshinChar) + url = "https://wiki.biligame.com/ys/武器图鉴" + data, code = await update_info( + url, + "genshin_arms", + [ + "头像", + "名称", + "类型", + "稀有度.alt", + "获取途径", + "初始基础属性1", + "初始基础属性2", + "攻击力(MAX)", + "副属性(MAX)", + "技能", + ], + ) if code == 200: - ALL_ARMS = init_game_pool('genshin_arms', data, GenshinChar) + ALL_ARMS = init_game_pool("genshin_arms", data, GenshinChar) await _genshin_init_up_char() async def init_genshin_data(): global ALL_CHAR, ALL_ARMS if GENSHIN_FLAG: - if not os.path.exists(DRAW_PATH + 'genshin.json') or not os.path.exists(DRAW_PATH + 'genshin_arms.json'): + if not os.path.exists(DRAW_PATH + "genshin.json") or not os.path.exists( + DRAW_PATH + "genshin_arms.json" + ): await update_genshin_info() else: - with open(DRAW_PATH + 'genshin.json', 'r', encoding='utf8') as f: + with open(DRAW_PATH + "genshin.json", "r", encoding="utf8") as f: genshin_dict = json.load(f) - with open(DRAW_PATH + 'genshin_arms.json', 'r', encoding='utf8') as f: + with open(DRAW_PATH + "genshin_arms.json", "r", encoding="utf8") as f: genshin_ARMS_dict = json.load(f) - ALL_CHAR = init_game_pool('genshin', genshin_dict, GenshinChar) - ALL_ARMS = init_game_pool('genshin_arms', genshin_ARMS_dict, GenshinChar) + ALL_CHAR = init_game_pool("genshin", genshin_dict, GenshinChar) + ALL_ARMS = init_game_pool("genshin_arms", genshin_ARMS_dict, GenshinChar) await _genshin_init_up_char() # 抽取卡池 -def _get_genshin_card(mode: int = 1, pool_name: str = '', add: float = 0.0): +def _get_genshin_card(mode: int = 1, pool_name: str = "", add: float = 0.0): global ALL_ARMS, ALL_CHAR, UP_ARMS, UP_CHAR, _CURRENT_ARMS_POOL_TITLE, _CURRENT_CHAR_POOL_TITLE if mode == 1: - star = get_star([5, 4, 3], [GENSHIN_FIVE_P + add, GENSHIN_FOUR_P, GENSHIN_THREE_P]) + star = get_star( + [5, 4, 3], [GENSHIN_FIVE_P + add, GENSHIN_FOUR_P, GENSHIN_THREE_P] + ) elif mode == 2: star = get_star([5, 4], [GENSHIN_G_FIVE_P + add, GENSHIN_G_FOUR_P]) else: star = 5 - if pool_name == 'char': + if pool_name == "char": data_lst = UP_CHAR flag = _CURRENT_CHAR_POOL_TITLE - itype_all_lst = ALL_CHAR + [x for x in ALL_ARMS if x.star == star and x.star < 5] - elif pool_name == 'arms': + itype_all_lst = ALL_CHAR + [ + x for x in ALL_ARMS if x.star == star and x.star < 5 + ] + elif pool_name == "arms": data_lst = UP_ARMS flag = _CURRENT_ARMS_POOL_TITLE - itype_all_lst = ALL_ARMS + [x for x in ALL_CHAR if x.star == star and x.star < 5] + itype_all_lst = ALL_ARMS + [ + x for x in ALL_CHAR if x.star == star and x.star < 5 + ] else: - data_lst = '' - flag = '' - itype_all_lst = '' + data_lst = "" + flag = "" + itype_all_lst = "" all_lst = ALL_ARMS + ALL_CHAR # 是否UP - if flag and star > 3 and pool_name: - # 获取up角色列表 - up_char_lst = [x.operators for x in data_lst if x.star == star][0] - # 成功获取up角色 - if random.random() < 0.5: - up_char_name = random.choice(up_char_lst) - acquire_char = [x for x in all_lst if x.name == up_char_name][0] + try: + if flag and star > 3 and pool_name: + # 获取up角色列表 + up_char_lst = [x.operators for x in data_lst if x.star == star][0] + print(up_char_lst) + # 成功获取up角色 + if random.random() < 0.5: + up_char_name = random.choice(up_char_lst) + acquire_char = [x for x in all_lst if x.name == up_char_name][0] + else: + # 无up + all_char_lst = [ + x + for x in itype_all_lst + if x.star == star and x.name not in up_char_lst and not x.limited + ] + acquire_char = random.choice(all_char_lst) else: - # 无up - all_char_lst = [x for x in itype_all_lst if x.star == star and x.name not in up_char_lst and not x.limited] - acquire_char = random.choice(all_char_lst) - else: + chars = [x for x in all_lst if x.star == star and not x.limited] + acquire_char = random.choice(chars) + except IndexError: chars = [x for x in all_lst if x.star == star and not x.limited] acquire_char = random.choice(chars) return acquire_char, 5 - star @@ -146,8 +205,8 @@ def _format_card_information(_count: int, user_id, pool_name): five_index_list = [] five_list = [] five_dict = {} - _start_add_count = 72 if pool_name == 'char' else 62 - _x = 90 if pool_name == 'char' else 80 # 保底 + _start_add_count = 72 if pool_name == "char" else 62 + _x = 90 if pool_name == "char" else 80 # 保底 add = 0.0 if genshin_count.get(user_id) and _count <= _x: f_count = genshin_count[user_id] @@ -202,9 +261,17 @@ def reset_count(user_id: int): # 获取up和概率 async def _genshin_init_up_char(): global _CURRENT_CHAR_POOL_TITLE, _CURRENT_ARMS_POOL_TITLE, UP_CHAR, UP_ARMS, POOL_IMG - _CURRENT_CHAR_POOL_TITLE, _CURRENT_ARMS_POOL_TITLE, POOL_IMG, UP_CHAR, UP_ARMS = await init_up_char(announcement) + ( + _CURRENT_CHAR_POOL_TITLE, + _CURRENT_ARMS_POOL_TITLE, + POOL_IMG, + UP_CHAR, + UP_ARMS, + ) = await init_up_char(announcement) async def reload_genshin_pool(): await _genshin_init_up_char() - return Message(f'当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE} {POOL_IMG}') + return Message( + f"当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE} {POOL_IMG}" + ) diff --git a/plugins/draw_card/update_game_info.py b/plugins/draw_card/update_game_info.py index c9a16ae9..f3289e7b 100755 --- a/plugins/draw_card/update_game_info.py +++ b/plugins/draw_card/update_game_info.py @@ -182,7 +182,7 @@ def intermediate_check(member_dict: dict, key: str, game_name: str, td: bs4.elem if game_name == 'prts': if key == '获取途径': msg = re.search('