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('([\\s\\S]*)', str(td)).group(1).strip() - msg = msg[:-1] if msg[-1] == '\n' else msg + msg = msg[:-1] if msg and msg[-1] == '\n' else msg if msg.find(' 1: if len(msg) == 2: url = msg[0] diff --git a/plugins/fudu.py b/plugins/fudu.py index 475e3ab7..3555ccc3 100755 --- a/plugins/fudu.py +++ b/plugins/fudu.py @@ -4,7 +4,7 @@ from utils.image_utils import get_img_hash import random from utils.message_builder import image from nonebot import on_message -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 configs.config import Config @@ -90,7 +90,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): if get_message_text(event.json()): if get_message_text(event.json()).find("@可爱的小真寻") != -1: await fudu.finish("复制粘贴的虚空艾特?", at_sender=True) - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) msg = get_message_text(event.json()) if not imgs and not msg: return diff --git a/plugins/genshin/query_resource_points/query_resource.py b/plugins/genshin/query_resource_points/query_resource.py index 7f06a903..717a6652 100755 --- a/plugins/genshin/query_resource_points/query_resource.py +++ b/plugins/genshin/query_resource_points/query_resource.py @@ -108,7 +108,6 @@ async def init(flag: bool = False): resource_name_list.append(x["name"]) except TimeoutError: logger.warning('原神资源查询信息初始化超时....') - pass # 图标及位置资源 @@ -185,12 +184,13 @@ async def download_map_init( semaphore, force_flag=flag, ) + BuildImage(0, 0, background=f"{map_path}/{idx}.png", ratio=MAP_RATIO).save() idx += 1 - _w, h = BuildImage(0, 0, background=f"{map_path}/0.png", ratio=MAP_RATIO).size + _w, h = BuildImage(0, 0, background=f"{map_path}/0.png").size w = _w * len(os.listdir(map_path)) map_file = BuildImage(w, h, _w, h, ratio=MAP_RATIO) for i in range(idx): - map_file.paste(BuildImage(0, 0, background=f"{map_path}/{i}.png", ratio=MAP_RATIO)) + map_file.paste(BuildImage(0, 0, background=f"{map_path}/{i}.png")) map_file.save(f"{map_path}/map.png") else: logger.warning(f'获取原神地图失败 msg: {data["message"]}') diff --git a/plugins/genshin/query_user/query_role/data_source.py b/plugins/genshin/query_user/query_role/data_source.py index 14772a9a..ff25b21a 100644 --- a/plugins/genshin/query_user/query_role/data_source.py +++ b/plugins/genshin/query_user/query_role/data_source.py @@ -64,7 +64,7 @@ async def get_image( "affix_level": char["weapon"]["affix_level"], } - await init_image(char_data_list, _x, home_data_list) + await init_image(world_data_dict, char_data_list, _x, home_data_list) return await get_genshin_image( user_id, uid, @@ -204,6 +204,7 @@ def parsed_data( "image": world["icon"], "name": world["name"], "offerings": world["offerings"], + "icon": world["icon"] } world_data_dict[world["name"]] = _x home_data_list = [] diff --git a/plugins/genshin/query_user/query_role/draw_image.py b/plugins/genshin/query_user/query_role/draw_image.py index efa13abf..c41aaff8 100644 --- a/plugins/genshin/query_user/query_role/draw_image.py +++ b/plugins/genshin/query_user/query_role/draw_image.py @@ -77,42 +77,38 @@ def _get_genshin_image( :param nickname: 用户昵称 :param user_ava:用户头像 """ - x = 450 if char_detailed_dict else 330 - char_height = ( - len(char_data_list) / 7 - if len(char_data_list) % 7 == 0 - else len(char_data_list) / 7 + 1 - ) - foot = BuildImage(1700, 87, background=image_path / "head.png") - head = BuildImage(1700, 87, background=image_path / "head.png") - head.rotate(180) - middle = BuildImage( - 1700, int(1600 + 200 + x * char_height), background=image_path / "middle.png" - ) - A = BuildImage(middle.w, middle.h + foot.h + head.h) - A.paste(head, (-5, 0), True) - A.paste(middle, (0, head.h), True) - A.paste(foot, (0, head.h + middle.h), True) - A.crop((0, 0, A.w - 5, A.h)) user_image = get_user_data_image(uid, role_data, mys_data, nickname, user_ava) home_image = get_home_data_image(home_data_list) country_image = get_country_data_image(world_data_dict) - char_image, _h = get_char_data_image(char_data_list, char_detailed_dict) - top_bk = BuildImage(user_image.w, user_image.h + home_image.h + 100, color="#F9F6F2") + char_image = get_char_data_image(char_data_list, char_detailed_dict) + top_bk = BuildImage(user_image.w, user_image.h + max([home_image.h, country_image.h]) + 100, color="#F9F6F2") top_bk.paste(user_image, alpha=True) top_bk.paste(home_image, (0, user_image.h + 50), alpha=True) top_bk.paste(country_image, (home_image.w + 100, user_image.h + 50), alpha=True) bar = BuildImage(1600, 200, font_size=50, color="#F9F6F2", font="HYWenHei-85W.ttf") bar.text((50, 10), "角色背包", (104, 103, 101)) bar.line((50, 90, 1550, 90), (227, 219, 209), width=10) - if A.h - top_bk.h - bar.h - _h > 200: - _h = A.h - top_bk.h - bar.h - _h - 200 + + foot = BuildImage(1700, 87, background=image_path / "head.png") + head = BuildImage(1700, 87, background=image_path / "head.png") + head.rotate(180) + middle = BuildImage( + 1700, top_bk.h + bar.h + char_image.h, background=image_path / "middle.png" + ) + A = BuildImage(middle.w, middle.h + foot.h + head.h) + A.paste(head, (-5, 0), True) + A.paste(middle, (0, head.h), True) + A.paste(foot, (0, head.h + middle.h), True) + A.crop((0, 0, A.w - 5, A.h)) + if A.h - top_bk.h - bar.h - char_image.h > 200: + _h = A.h - top_bk.h - bar.h - char_image.h - 200 A.crop((0, 0, A.w, A.h - _h)) A.paste(foot, (0, A.h - 87)) A.paste(top_bk, (0, 100), center_type="by_width") A.paste(bar, (50, top_bk.h + 80)) A.paste(char_image, (0, top_bk.h + bar.h + 10), center_type="by_width") rand = random.randint(1, 10000) + A.resize(0.8) A.save(Path(IMAGE_PATH) / "temp" / f"genshin_user_card_{rand}.png") return image(f"genshin_user_card_{rand}.png", "temp") @@ -233,8 +229,9 @@ def get_home_data_image(home_data_list: List[Dict]) -> BuildImage: 画出家园数据 :param home_data_list: 家园列表 """ + h = 130 + 300 * 4 region = BuildImage( - 550, 1050, color="#E3DBD1", font="HYWenHei-85W.ttf", font_size=40 + 550, h, color="#E3DBD1", font="HYWenHei-85W.ttf", font_size=40 ) try: region.text( @@ -245,7 +242,7 @@ def get_home_data_image(home_data_list: List[Dict]) -> BuildImage: ) except (IndexError, KeyError): region.text((0, 30), f"尘歌壶 Lv.0", center_type="by_width") - region.text((0, 980), f"仙力: 0", center_type="by_width") + region.text((0, region.h - 70), f"仙力: 0", center_type="by_width") region.circle_corner(30) height = 100 homes = os.listdir(image_path / "homes") @@ -300,9 +297,9 @@ def get_country_data_image(world_data_dict: Dict) -> BuildImage: 画出国家探索供奉等图像 :param world_data_dict: 国家数据字典 """ - region = BuildImage(790, 1050, color="#F9F6F2") + region = BuildImage(790, 267 * len(world_data_dict), color="#F9F6F2") height = 0 - for country in ["蒙德", "龙脊雪山", "璃月", "稻妻"]: + for country in ["蒙德", "龙脊雪山", "璃月", "稻妻", "渊下宫"]: x = BuildImage(790, 250, color="#3A4467") logo = BuildImage(180, 180, background=image_path / "logo" / f"{country}.png") tmp_bk = BuildImage(770, 230, color="#606779") @@ -356,6 +353,14 @@ def get_country_data_image(world_data_dict: Dict) -> BuildImage: f"Lv.{world_data_dict[country]['offerings'][0]['level']}", fill=(255, 255, 255), ) + elif country in ["渊下宫"]: + content_bk.text((300, 0), "探索", fill=(239, 211, 114), center_type="by_height") + content_bk.text( + (450, 20), + f"{world_data_dict[country]['exploration_percentage'] / 10}%", + fill=(255, 255, 255), + center_type="by_height", + ) x.paste(tmp_bk, alpha=True, center_type="center") x.paste(content_bk, alpha=True, center_type="center") x.circle_corner(20) @@ -372,12 +377,9 @@ def get_char_data_image( :param char_data_list: 角色列表 :param char_detailed_dict: 角色武器 """ - x = 420 if char_detailed_dict else 350 - _h = x * int( - len(char_data_list) / 7 - if len(char_data_list) % 7 == 0 - else len(char_data_list) / 7 + 1 - ) + lens = len(char_data_list) / 7 if len(char_data_list) % 7 == 0 else len(char_data_list) / 7 + 1 + x = 500 + _h = int(x * lens) region = BuildImage( 1600, _h, @@ -389,12 +391,12 @@ def get_char_data_image( for char in char_data_list: if width + 230 > 1550: width = 120 - height += x + height += 420 idx += 1 char_img = image_path / "chars" / f'{char["name"]}.png' char_bk = BuildImage( 270, - 500 if char_detailed_dict else 400, + 500, background=image_path / "element.png", font="HYWenHei-85W.ttf", font_size=35, @@ -507,16 +509,23 @@ def get_char_data_image( char_bk.resize(0.8) region.paste(char_bk, (width, height), True) width += 230 - return region, _h + region.crop((0, 0, region.w, height + 430)) + return region -async def init_image(char_data_list: List[Dict], char_detailed_dict: dict, home_data_list: List[Dict]): +async def init_image(world_data_dict: Dict[str, Dict[str, str]], char_data_list: List[Dict[str, str]], char_detailed_dict: dict, home_data_list: List[Dict]): """ 下载头像 + :param world_data_dict: 地图标志 :param char_data_list: 角色列表 :param char_detailed_dict: 角色武器 :param home_data_list: 家园列表 """ + for world in world_data_dict: + file = image_path / "logo" / f'{world_data_dict[world]["name"]}.png' + file.parent.mkdir(parents=True, exist_ok=True) + if not file.exists(): + await AsyncHttpx.download_file(world_data_dict[world]["icon"], file) for char in char_data_list: file = image_path / "chars" / f'{char["name"]}.png' file.parent.mkdir(parents=True, exist_ok=True) diff --git a/plugins/image_management/upload_image/__init__.py b/plugins/image_management/upload_image/__init__.py index b67abf61..cfc7c119 100755 --- a/plugins/image_management/upload_image/__init__.py +++ b/plugins/image_management/upload_image/__init__.py @@ -3,7 +3,7 @@ from nonebot.rule import to_me from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent from configs.config import Config -from utils.utils import get_message_imgs, get_message_text +from utils.utils import get_message_img, get_message_text from .data_source import upload_image_to_local @@ -49,15 +49,15 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): await upload_img.reject("此目录不正确,请重新输入目录!") state["path"] = msg if state["_current_key"] in ["imgs"]: - if not get_message_imgs(event.json()): + if not get_message_img(event.json()): await upload_img.reject("图呢图呢图呢图呢!GKD!") - state["imgs"] = get_message_imgs(event.json()) + state["imgs"] = get_message_img(event.json()) @upload_img.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): raw_arg = get_message_text(event.json()) - img_list = get_message_imgs(event.json()) + img_list = get_message_img(event.json()) if raw_arg: if raw_arg in Config.get_config("image_management", "IMAGE_DIR_LIST"): state["path"] = raw_arg @@ -92,7 +92,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): state[state["_current_key"]] = str(event.get_message()) else: if get_message_text(event.json()) not in ["stop"]: - img = get_message_imgs(event.json()) + img = get_message_img(event.json()) if img: state["tmp"].extend(img) await continuous_upload_img.reject("图再来!!") @@ -102,7 +102,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): @continuous_upload_img.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): - path = get_message_imgs(event.json()) + path = get_message_img(event.json()) if path in Config.get_config("image_management", "IMAGE_DIR_LIST"): state["path"] = path await continuous_upload_img.send("图来!!【停止请发送 ‘stop’ 开始上传】") diff --git a/plugins/mute.py b/plugins/mute.py index 4cf1d569..b3c91873 100755 --- a/plugins/mute.py +++ b/plugins/mute.py @@ -1,7 +1,7 @@ from nonebot import on_message, on_command from nonebot.adapters.cqhttp import Bot, GroupMessageEvent from nonebot.adapters.cqhttp.permission import GROUP -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 nonebot.typing import T_State from nonebot.adapters.cqhttp.exception import ActionFailed from configs.path_config import DATA_PATH, TEMP_PATH @@ -87,7 +87,7 @@ mute_data = get_data() async def _(bot: Bot, event: GroupMessageEvent, state: T_State): group_id = str(event.group_id) msg = get_message_text(event.json()) - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) img_hash = "" for img in imgs: img_hash += await download_img_and_hash(img, event.group_id) diff --git a/plugins/nonebot_plugin_picsearcher/__init__.py b/plugins/nonebot_plugin_picsearcher/__init__.py index 21eb8617..6f97e9e7 100755 --- a/plugins/nonebot_plugin_picsearcher/__init__.py +++ b/plugins/nonebot_plugin_picsearcher/__init__.py @@ -5,7 +5,7 @@ from nonebot.plugin import on_command, on_message from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent from nonebot.typing import T_State 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 configs.config import Config from nonebot.rule import to_me @@ -72,7 +72,7 @@ setu = on_command("识图", aliases={"search"}, block=True, priority=5) @setu.handle() async def handle_first_receive(bot: Bot, event: MessageEvent, state: T_State): msg = get_message_text(event.json()) - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) if imgs: state["setu"] = imgs[0] if msg: @@ -87,7 +87,7 @@ async def handle_first_receive(bot: Bot, event: MessageEvent, state: T_State): @setu.args_parser async def get_setu(bot: Bot, event: MessageEvent, state: T_State): - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) msg = get_message_text(event.json()) if not imgs: await setu.reject() diff --git a/plugins/open_cases/models/open_cases_user.py b/plugins/open_cases/models/open_cases_user.py index 99662bb2..c74cd9f6 100755 --- a/plugins/open_cases/models/open_cases_user.py +++ b/plugins/open_cases/models/open_cases_user.py @@ -9,7 +9,7 @@ class OpenCasesUser(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) total_count = db.Column(db.Integer(), nullable=False, default=0) blue_count = db.Column(db.Integer(), nullable=False, default=0) blue_st_count = db.Column(db.Integer(), nullable=False, default=0) @@ -27,19 +27,19 @@ class OpenCasesUser(db.Model): open_cases_time_last = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.now()) knifes_name = db.Column(db.Unicode(), nullable=False, default="") - _idx1 = db.Index('open_cases_group_users_idx1', 'user_qq', 'belonging_group', unique=True) + _idx1 = db.Index('open_cases_group_users_idx1', 'user_qq', 'group_id', unique=True) @classmethod - async def ensure(cls, user_qq: int, belonging_group: int, for_update: bool = False) -> 'OpenCasesUser': + async def ensure(cls, user_qq: int, group_id: int, for_update: bool = False) -> 'OpenCasesUser': 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, ) @classmethod @@ -49,7 +49,7 @@ class OpenCasesUser(db.Model): query = await cls.query.gino.all() else: query = await cls.query.where( - (cls.belonging_group == group_id) + (cls.group_id == group_id) ).gino.all() for user in query: user_list.append(user) diff --git a/plugins/send_setu_/send_setu/__init__.py b/plugins/send_setu_/send_setu/__init__.py index 464626ab..e06bde93 100755 --- a/plugins/send_setu_/send_setu/__init__.py +++ b/plugins/send_setu_/send_setu/__init__.py @@ -9,7 +9,7 @@ from gino.exceptions import UninitializedError from utils.utils import ( is_number, get_message_text, - get_message_imgs, + get_message_img, ) from nonebot.typing import T_State from nonebot.adapters.cqhttp import ( @@ -243,7 +243,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): async def _(bot: Bot, event: MessageEvent, state: T_State): if str(event.message) == "取消": await find_setu.finish("取消了操作", at_sender=True) - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) if not imgs: await find_setu.reject("不搞错了,俺要图!") state["img"] = imgs[0] @@ -253,7 +253,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): async def _(bot: Bot, event: MessageEvent, state: T_State): if get_message_text(event.json()) in ["帮助"]: await find_setu.finish("通过图片获取本地色图id\n\t示例:查色图(图片)") - imgs = get_message_imgs(event.json()) + imgs = get_message_img(event.json()) if imgs: state["img"] = imgs[0] diff --git a/plugins/send_setu_/update_setu/__init__.py b/plugins/send_setu_/update_setu/__init__.py index ff9018b4..747185df 100755 --- a/plugins/send_setu_/update_setu/__init__.py +++ b/plugins/send_setu_/update_setu/__init__.py @@ -32,7 +32,7 @@ update_setu = on_command( async def _(bot: Bot, event: Event, state: T_State): if Config.get_config("send_setu", "DOWNLOAD_SETU"): await update_setu.send("开始更新色图...", at_sender=True) - await update_setu.send(await update_setu_img(), at_sender=True) + await update_setu_img(True) else: await update_setu.finish("更新色图配置未开启") diff --git a/plugins/send_setu_/update_setu/data_source.py b/plugins/send_setu_/update_setu/data_source.py index 18189eaa..c5a7752b 100755 --- a/plugins/send_setu_/update_setu/data_source.py +++ b/plugins/send_setu_/update_setu/data_source.py @@ -90,7 +90,11 @@ headers = { } -async def update_setu_img(): +async def update_setu_img(flag: bool = False): + """ + 更新色图 + :param flag: 是否手动更新 + """ image_list = await Setu.get_all_setu() image_list.reverse() _success = 0 @@ -105,6 +109,9 @@ async def update_setu_img(): path.mkdir(exist_ok=True, parents=True) rar_path.mkdir(exist_ok=True, parents=True) if not local_image.exists() or not image.img_hash: + temp_file = rar_path / f"{image.local_id}.jpg" + if temp_file.exists(): + temp_file.unlink() url_ = image.img_url ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL") if ws_url: @@ -158,8 +165,7 @@ async def update_setu_img(): error_info.append(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}") else: logger.info(f"更新色图 {image.local_id}.jpg 已存在") - error_info = ["无报错.."] if not error_info else error_info - if count or _success or error_info: + if _success or error_info or flag: await get_bot().send_private_msg( user_id=int(list(get_bot().config.superusers)[0]), message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,本地存在 {count} 张,实际更新 {_success} 张,' diff --git a/plugins/sign_in/group_user_checkin.py b/plugins/sign_in/group_user_checkin.py index 12ec7aa0..fb12adbf 100755 --- a/plugins/sign_in/group_user_checkin.py +++ b/plugins/sign_in/group_user_checkin.py @@ -50,7 +50,7 @@ async def check_in_all(nickname: str, user_qq: int): async with db.transaction(): present = datetime.now() for u in await SignGroupUser.get_user_all_data(user_qq): - group = u.belonging_group + group = u.group_id if not (( u.checkin_time_last + timedelta(hours=8) ).date() >= present.date() or f"{u}_{group}_sign_{datetime.now().date()}" in os.listdir( @@ -79,18 +79,18 @@ async def _handle_check_in( gift = f"额外金币 + {gift}" else: await BagUser.add_gold(user_qq, group, gold) - await BagUser.add_props(user_qq, group, gift) + await BagUser.add_property(user_qq, group, gift) gift += ' + 1' if critx2 + add_probability > 0.97 or critx2 < specify_probability: logger.info( - f"(USER {user.user_qq}, GROUP {user.belonging_group})" + f"(USER {user.user_qq}, GROUP {user.group_id})" f" CHECKED IN successfully. score: {user.impression:.2f} " f"(+{impression_added * 2:.2f}).获取金币:{gold + gift if gift == 'gold' else gold}" ) return await get_card(user, nickname, impression_added, gold, gift, True) else: logger.info( - f"(USER {user.user_qq}, GROUP {user.belonging_group})" + f"(USER {user.user_qq}, GROUP {user.group_id})" f" CHECKED IN successfully. score: {user.impression:.2f} " f"(+{impression_added:.2f}).获取金币:{gold + gift if gift == 'gold' else gold}" ) diff --git a/plugins/sign_in/utils.py b/plugins/sign_in/utils.py index 25975713..10dff67b 100755 --- a/plugins/sign_in/utils.py +++ b/plugins/sign_in/utils.py @@ -11,6 +11,7 @@ from .config import ( from models.sign_group_user import SignGroupUser from models.group_member_info import GroupInfoUser from nonebot.adapters.cqhttp import MessageSegment +from configs.config import Config from utils.utils import get_user_avatar from utils.image_utils import BuildImage from utils.message_builder import image @@ -55,32 +56,32 @@ async def get_card( _type = "view" if is_card_view else "sign" card_file = ( Path(SIGN_TODAY_CARD_PATH) - / f"{user_id}_{user.belonging_group}_{_type}_{date}.png" + / f"{user_id}_{user.group_id}_{_type}_{date}.png" ) if card_file.exists(): return image( - f"{user_id}_{user.belonging_group}_{_type}_{date}.png", "sign/today_card" + f"{user_id}_{user.group_id}_{_type}_{date}.png", "sign/today_card" ) else: if add_impression == -1: card_file = ( Path(SIGN_TODAY_CARD_PATH) - / f"{user_id}_{user.belonging_group}_view_{date}.png" + / f"{user_id}_{user.group_id}_view_{date}.png" ) if card_file.exists(): return image( - f"{user_id}_{user.belonging_group}_view_{date}.png", + f"{user_id}_{user.group_id}_view_{date}.png", "sign/today_card", ) is_card_view = True ava = BytesIO(await get_user_avatar(user_id)) uid = await GroupInfoUser.get_group_member_uid( - user.user_qq, user.belonging_group + user.user_qq, user.group_id ) impression_list = None if is_card_view: _, impression_list, _ = await SignGroupUser.get_all_impression( - user.belonging_group + user.group_id ) return await asyncio.get_event_loop().run_in_executor( None, @@ -239,9 +240,10 @@ def _generate_card( f"上次签到日期:{'从未' if user.checkin_time_last == datetime.min else user.checkin_time_last.date()}", ) today_data.text((0, 25), f"总金币:{gold}") + default_setu_prob = Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100 today_data.text( (0, 50), - f"色图概率:{(70 + user.impression if user.impression < 100 else 100):.2f}%", + f"色图概率:{(default_setu_prob + user.impression if user.impression < 100 else 100):.2f}%", ) today_data.text((0, 75), f"开箱次数:{(20 + int(user.impression / 3))}") _type = "view" @@ -285,10 +287,10 @@ def _generate_card( bk.paste(today_data, (580, 220), True) bk.paste(watermark, (15, 400), True) bk.save( - SIGN_TODAY_CARD_PATH / f"{user_id}_{user.belonging_group}_{_type}_{data}.png" + SIGN_TODAY_CARD_PATH / f"{user_id}_{user.group_id}_{_type}_{data}.png" ) return image( - f"{user_id}_{user.belonging_group}_{_type}_{data}.png", "sign/today_card" + f"{user_id}_{user.group_id}_{_type}_{data}.png", "sign/today_card" ) diff --git a/plugins/translate/data_source.py b/plugins/translate/data_source.py index 77df30a1..567b521c 100755 --- a/plugins/translate/data_source.py +++ b/plugins/translate/data_source.py @@ -16,7 +16,7 @@ async def translate_msg(language_type, msg): } data = (await AsyncHttpx.post(url, data=data)).json() if data["errorCode"] == 0: - return data["translateResult"][0][0]["tgt"] + return f'原文:{msg}\n翻译{data["translateResult"][0][0]["tgt"]}' return "翻译惜败.." diff --git a/plugins/update_picture.py b/plugins/update_picture.py index 13b16ad5..56d70e81 100755 --- a/plugins/update_picture.py +++ b/plugins/update_picture.py @@ -6,7 +6,7 @@ from services.log import logger from nonebot.rule import to_me from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent from nonebot.typing import T_State -from utils.utils import get_message_imgs +from utils.utils import get_message_img from pathlib import Path from utils.utils import is_number, get_message_text from utils.image_utils import BuildImage, pic2b64 @@ -150,9 +150,9 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): await update_img.reject("请输入支持的替换的底色:\n红色 蓝色 白色 绿色") state["y"] = str(event.get_message()) if state["_current_key"] == "imgs": - if not get_message_imgs(event.json()): + if not get_message_img(event.json()): await update_img.reject("没图?没图?没图?来图速来!") - state[state["_current_key"]] = get_message_imgs(event.json()) + state[state["_current_key"]] = get_message_img(event.json()) @update_img.handle() @@ -160,7 +160,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): if str(event.get_message()) in ["帮助"]: await update_img.finish(image("update_img_help.png")) raw_arg = get_message_text(event.json()) - img_list = get_message_imgs(event.json()) + img_list = get_message_img(event.json()) if raw_arg: args = raw_arg.split("[")[0].split(" ") print(args) diff --git a/plugins/what_anime/__init__.py b/plugins/what_anime/__init__.py index c4c9006d..823551be 100755 --- a/plugins/what_anime/__init__.py +++ b/plugins/what_anime/__init__.py @@ -2,7 +2,7 @@ from .data_source import get_anime from nonebot import on_command from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent -from utils.utils import get_message_imgs +from utils.utils import get_message_img from services.log import logger @@ -33,7 +33,7 @@ what_anime = on_command("识番", priority=5, block=True) async def _(bot: Bot, event: MessageEvent, state: T_State): if str(event.get_message()) in ["取消", "算了"]: await what_anime.finish("已取消操作..", at_sender=True) - img_url = get_message_imgs(event.json()) + img_url = get_message_img(event.json()) if not img_url: await what_anime.reject(prompt="图呢图呢图呢图呢GKD", at_sender=True) state["img_url"] = img_url @@ -43,7 +43,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): async def _(bot: Bot, event: MessageEvent, state: T_State): if str(event.get_message()) in ["帮助"]: await what_anime.finish(__plugin_usage__) - img_url = get_message_imgs(event.json()) + img_url = get_message_img(event.json()) if img_url: state["img_url"] = img_url diff --git a/plugins/white2black_image.py b/plugins/white2black_image.py index 40637ba5..d453595c 100755 --- a/plugins/white2black_image.py +++ b/plugins/white2black_image.py @@ -1,7 +1,7 @@ from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent from nonebot import on_command -from utils.utils import get_message_imgs, get_message_text, is_chinese +from utils.utils import get_message_img, get_message_text, is_chinese from utils.message_builder import image from configs.path_config import TEMP_PATH from utils.image_utils import BuildImage @@ -47,7 +47,7 @@ w2b_img = on_command("黑白草图", aliases={"黑白图"}, priority=5, block=Tr @w2b_img.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): # try: - img = get_message_imgs(event.json()) + img = get_message_img(event.json()) msg = get_message_text(event.json()) if not img or not msg: await w2b_img.finish(f"格式错误:\n" + __plugin_usage__) diff --git a/plugins/word_bank/word_hanlde.py b/plugins/word_bank/word_hanlde.py index 0a0ceb9b..268c4044 100644 --- a/plugins/word_bank/word_hanlde.py +++ b/plugins/word_bank/word_hanlde.py @@ -1,9 +1,11 @@ -from utils.utils import get_message_at, is_number, get_message_imgs, get_message_text +from utils.utils import get_message_at, is_number, get_message_img, get_message_text from services.log import logger from configs.path_config import DATA_PATH from utils.http_utils import AsyncHttpx from .data_source import WordBankBuilder from configs.config import Config +from utils.message_builder import image +from utils.image_utils import text2image from .model import WordBank from nonebot.adapters.cqhttp import ( Bot, @@ -42,7 +44,7 @@ __plugin_version__ = 0.1 __plugin_author__ = "HibiKier" __plugin_settings__ = { "admin_level": Config.get_config("word_bank", "WORD_BANK_LEVEL"), - "cmd": ["词库问答", "添加词条", "删除词条", "查看词条"] + "cmd": ["词库问答", "添加词条", "删除词条", "查看词条"], } data_dir = Path(DATA_PATH) / "word_bank" @@ -65,13 +67,13 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): problem = r.group(1).strip() if not problem: await add_word.finish("未检测到词条问题...") - answer = msg.split('答', maxsplit=1)[-1] + answer = msg.split("答", maxsplit=1)[-1] if not answer: await add_word.finish("未检测到词条回答...") idx = 0 for n in bot.config.nickname: if problem.startswith(n): - _problem = f"[_to_me|{n}]" + problem[len(n):] + _problem = f"[_to_me|{n}]" + problem[len(n) :] break else: _problem = problem @@ -82,7 +84,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): answer = answer.replace(f"[CQ:at,qq={at_}]", f"[__placeholder_{idx}]", 1) _builder.set_placeholder(idx, at_) idx += 1 - for img in get_message_imgs(event.json()): + for img in get_message_img(event.json()): _x = img.split("?")[0] r = re.search(rf"\[CQ:image,file=(.*),url={_x}.*?]", answer) if r: @@ -90,7 +92,8 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): for i in range(3): answer = answer.replace(f",subType={i}", "") answer = answer.replace( - rf"[CQ:image,file={r.group(1)},url={img}]", f"[__placeholder_{idx}]", + rf"[CQ:image,file={r.group(1)},url={img}]", + f"[__placeholder_{idx}]", ) await AsyncHttpx.download_file( img, data_dir / f"{event.group_id}" / f"__placeholder_{rand}_{idx}.jpg" @@ -119,11 +122,13 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): x = problem.split(":")[-1] if not is_number(x) or int(x) < 0: await delete_word.finish("id必须为数字且符合规范!") - p = (await WordBank.get_group_all_problem(event.group_id)) + p = await WordBank.get_group_all_problem(event.group_id) if p: problem = p[int(x)] try: - if answer := await WordBank.delete_problem_answer(event.user_id, event.group_id, problem, index): + if answer := await WordBank.delete_problem_answer( + event.user_id, event.group_id, problem, index + ): await delete_word.send(f"删除词条成功:{problem}\n回答:\n{answer}") logger.info( f"(USER {event.user_id}, GROUP " @@ -143,21 +148,20 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): _problem_list = await WordBank.get_group_all_problem(event.group_id) if not _problem_list: await show_word.finish("该群未收录任何词条..") - _problem_list = [f"{i}. {x}" for i, x in enumerate(_problem_list)] + _problem_list = [f"\t{i}. {x}" for i, x in enumerate(_problem_list)] await show_word.send( - "该群已收录的词条:\n" + "\n".join(_problem_list) + image( + b64=await text2image( + "该群已收录的词条:\n\n" + "\n".join(_problem_list), + padding=10, + color="#f9f6f2", + ) + ) ) else: _answer_list = await WordBank.get_group_all_answer(event.group_id, msg) if not _answer_list: - await show_word.send( - "未收录该词条..." - ) + await show_word.send("未收录该词条...") else: _answer_list = [f"{i}. {x}" for i, x in enumerate(_answer_list)] - await show_word.send( - f"词条 {msg} 回答:\n" + "\n".join(_answer_list) - ) - - - + await show_word.send(f"词条 {msg} 回答:\n" + "\n".join(_answer_list)) diff --git a/plugins/yiqing/__init__.py b/plugins/yiqing/__init__.py index fd6c103e..5c0c6834 100755 --- a/plugins/yiqing/__init__.py +++ b/plugins/yiqing/__init__.py @@ -20,7 +20,7 @@ usage: """.strip() __plugin_des__ = "实时疫情数据查询" __plugin_cmd__ = ["疫情 [省份/城市]", "疫情 中国"] -__plugin_type__ = ('一些工具',) +__plugin_type__ = ("一些工具",) __plugin_version__ = 0.1 __plugin_author__ = "HibiKier & yzyyz1387" __plugin_settings__ = { diff --git a/plugins/yiqing/data_source.py b/plugins/yiqing/data_source.py index 61b4462d..78bde6c5 100755 --- a/plugins/yiqing/data_source.py +++ b/plugins/yiqing/data_source.py @@ -56,18 +56,26 @@ async def get_yiqing_data(area: str) -> Union[str, MessageSegment]: confirm = data_["total"]["confirm"] # 累计确诊 heal = data_["total"]["heal"] # 累计治愈 dead = data_["total"]["dead"] # 累计死亡 - dead_rate = data_["total"]["deadRate"] # 死亡率 - heal_rate = data_["total"]["healRate"] # 治愈率 now_confirm = data_["total"]["nowConfirm"] # 目前确诊 - suspect = data_["total"]["suspect"] # 疑似 add_confirm = data_["today"]["confirm"] # 新增确诊 + grade = "" + _grade_color = "" + if data_["total"].get("grade"): + grade = data_["total"]["grade"] + if "中风险" in grade: + _grade_color = "#fa9424" + else: + _grade_color = "red" + + dead_rate = f"{dead / confirm * 100:.2f}" # 死亡率 + heal_rate = f"{heal / confirm * 100:.2f}" # 治愈率 + x = f"{city}市" if city else f"{province}{province_type}" return image(b64=await text2image( f""" - {x} 疫情数据: + {x} 疫情数据 {f"({grade})" if grade else ""}: 目前确诊: 确诊人数:{now_confirm}(+{add_confirm}) - 疑似人数:{suspect} ----------------- 累计数据: 确诊人数:{confirm} @@ -75,7 +83,7 @@ async def get_yiqing_data(area: str) -> Union[str, MessageSegment]: 死亡人数:{dead} 治愈率:{heal_rate}% 死亡率:{dead_rate}% - 更新日期:{last_update_time} + 更新日期:{last_update_time} """, font_size=30, color="#f9f6f2" )) diff --git a/update_info.json b/update_info.json index 58aed646..38b4c20a 100644 --- a/update_info.json +++ b/update_info.json @@ -4,8 +4,8 @@ "models", "services", "utils", - "resources/ttf" + "basic_plugins" ], - "add_file": ["resources/img/other/time.png"], + "add_file": [], "delete_file": [] } diff --git a/utils/image_utils.py b/utils/image_utils.py index a66b0973..a8a23e98 100755 --- a/utils/image_utils.py +++ b/utils/image_utils.py @@ -168,6 +168,17 @@ async def text2image( :param font_color: 普通字体颜色 :param padding: 文本外边距,元组类型时为 (上,左,下,右) """ + pw = ph = top_padding = left_padding = 0 + if padding: + if isinstance(padding, int): + pw = padding * 2 + ph = padding * 2 + top_padding = left_padding = padding + elif isinstance(padding, tuple): + pw = padding[0] + padding[2] + ph = padding[1] + padding[3] + top_padding = padding[0] + left_padding = padding[1] if auto_parse and re.search(r"(.*)", text): _data = [] new_text = "" @@ -277,24 +288,13 @@ async def text2image( for img in image_list: height += img.h width = width if width > img.w else img.w - top_padding = left_padding = 0 - if padding: - if isinstance(padding, int): - width += padding * 2 - height += padding * 2 - top_padding = left_padding = padding - elif isinstance(padding, tuple): - width += padding[0] + padding[2] - height += padding[1] + padding[3] - top_padding = padding[0] - left_padding = padding[1] + width += pw + height += ph A = BuildImage(width + left_padding, height + top_padding, color=color) current_height = top_padding for img in image_list: await A.apaste(img, (left_padding, current_height), True) current_height += img.h - # A.show() - return A.pic2bs4() else: width = 0 height = 0 @@ -303,10 +303,18 @@ async def text2image( w, h = _tmp.getsize(x) height += h width = width if width > w else w - A = BuildImage(width, height, font_size=font_size, color=color) - await A.atext((0, 0), text, font_color) - # A.show() - return A.pic2bs4() + width += pw + height += ph + A = BuildImage( + width + left_padding, + height + top_padding, + font_size=font_size, + color=color, + font=font, + ) + await A.atext((left_padding, top_padding), text, font_color) + # A.show() + return A.pic2bs4() class BuildImage: @@ -354,6 +362,7 @@ class BuildImage: self.font = ImageFont.truetype(FONT_PATH + font, int(font_size)) if not plain_text and not color: color = (255, 255, 255) + self.background = background if not background: if plain_text: if not color: @@ -589,7 +598,7 @@ class BuildImage: pos = (w, h) self.draw.text(pos, text, fill=fill, font=self.font) - async def asave(self, path: Union[str, Path]): + async def asave(self, path: Optional[Union[str, Path]] = None): """ 说明: 异步 保存图片 @@ -598,15 +607,15 @@ class BuildImage: """ await self.loop.run_in_executor(None, self.save, path) - def save(self, path: Union[str, Path]): + def save(self, path: Optional[Union[str, Path]] = None): """ 说明: 保存图片 参数: :param path: 图片路径 """ - if isinstance(path, Path): - path = path.absolute() + if not path: + path = self.background self.markImg.save(path) def show(self): @@ -847,8 +856,8 @@ class BuildImage: for j in range(r2): lx = abs(i - r) # 到圆心距离的横坐标 ly = abs(j - r) # 到圆心距离的纵坐标 - l = (pow(lx, 2) + pow(ly, 2)) ** 0.5 # 三角函数 半径 - if l < r3: + l_ = (pow(lx, 2) + pow(ly, 2)) ** 0.5 # 三角函数 半径 + if l_ < r3: pim_b[i - (r - r3), j - (r - r3)] = pim_a[i, j] self.markImg = imb diff --git a/utils/manager/admin_manager.py b/utils/manager/admin_manager.py index c0a8380e..2f4688c4 100755 --- a/utils/manager/admin_manager.py +++ b/utils/manager/admin_manager.py @@ -59,7 +59,7 @@ class AdminManager(StaticData): def get_plugin_module(self, cmd: str) -> Optional[str]: """ - 根据 cmd 获取功能 module + 根据 cmd 获取功能 modules :param cmd: 命令 """ for key in self._data.keys(): diff --git a/utils/manager/configs_manager.py b/utils/manager/configs_manager.py index 9736f21c..b6f106c2 100755 --- a/utils/manager/configs_manager.py +++ b/utils/manager/configs_manager.py @@ -18,7 +18,7 @@ # # def add_plugin_config( # self, -# module: str, +# modules: str, # key: str, # value: str, # help_: Optional[str] = None, @@ -26,39 +26,39 @@ # ): # """ # 为插件添加一个配置 -# :param module: 模块 +# :param modules: 模块 # :param key: 键 # :param value: 值 # :param help_: 配置注解 # :param default_value: 默认值 # """ -# if self._data.get(module) is None: -# self._data[module] = {} -# self._data[module][key] = { +# if self._data.get(modules) is None: +# self._data[modules] = {} +# self._data[modules][key] = { # "value": value, # "help": help_, # "default_value": default_value, # } # -# def remove_plugin_config(self, module: str): +# def remove_plugin_config(self, modules: str): # """ # 为插件删除一个配置 -# :param module: 模块名 +# :param modules: 模块名 # """ -# if module in self._data.keys(): -# del self._data[module] +# if modules in self._data.keys(): +# del self._data[modules] # -# def get_config(self, module: str, key: str) -> Optional[Any]: +# def get_config(self, modules: str, key: str) -> Optional[Any]: # """ # 获取指定配置值 -# :param module: 模块名 +# :param modules: 模块名 # :param key: 配置名称 # """ -# if module in self._data.keys(): -# if self._data[module].get(key): -# if self._data[module][key]["value"] is None: -# return self._data[module][key]["default_value"] -# return self._data[module][key]["value"] +# if modules in self._data.keys(): +# if self._data[modules].get(key): +# if self._data[modules][key]["value"] is None: +# return self._data[modules][key]["default_value"] +# return self._data[modules][key]["value"] # return None # # diff --git a/utils/manager/plugins2settings_manager.py b/utils/manager/plugins2settings_manager.py index 5b3abf7d..7761bb7f 100755 --- a/utils/manager/plugins2settings_manager.py +++ b/utils/manager/plugins2settings_manager.py @@ -86,7 +86,7 @@ class Plugins2settingsManager(StaticData): self, cmd: str, is_all: bool = False ) -> Union[str, List[str]]: """ - 根据 cmd 获取功能 module + 根据 cmd 获取功能 modules :param cmd: 命令 :param is_all: 获取全部包含cmd的模块 """ diff --git a/utils/utils.py b/utils/utils.py index 96fa0efb..f4eabf85 100755 --- a/utils/utils.py +++ b/utils/utils.py @@ -208,7 +208,7 @@ def get_message_at(data: str) -> List[int]: return [] -def get_message_imgs(data: str) -> List[str]: +def get_message_img(data: str) -> List[str]: """ 说明: 获取消息中所有的 图片 的链接