From a43a7b5f75c47963ab4173108a906bd875fe98ec Mon Sep 17 00:00:00 2001 From: HibiKier <775757368@qq.com> Date: Sun, 12 Mar 2023 19:50:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=BC=80=E7=AE=B1=E6=8C=87?= =?UTF-8?q?=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- models/group_member_info.py | 11 +- plugins/open_cases/__init__.py | 130 ++++++++++++++---------- plugins/open_cases/build_image.py | 94 +++++++++++++++++ plugins/open_cases/config.py | 36 +++++++ plugins/open_cases/open_cases_c.py | 34 ++----- plugins/open_cases/utils.py | 157 +++++++++++++++++++++++++++-- utils/utils.py | 34 +++++++ 7 files changed, 407 insertions(+), 89 deletions(-) create mode 100644 plugins/open_cases/build_image.py diff --git a/models/group_member_info.py b/models/group_member_info.py index 74d856c0..fc03b32f 100755 --- a/models/group_member_info.py +++ b/models/group_member_info.py @@ -5,6 +5,7 @@ from tortoise import fields from configs.config import Config from services.db_context import Model +from services.log import logger class GroupInfoUser(Model): @@ -39,7 +40,7 @@ class GroupInfoUser(Model): """ return set( await cls.filter(group_id=group_id).values_list("user_qq", flat=True) - ) + ) # type: ignore @classmethod async def set_user_nickname(cls, user_qq: int, group_id: int, nickname: str): @@ -67,7 +68,7 @@ class GroupInfoUser(Model): """ return list( await cls.filter(user_qq=user_qq).values_list("group_id", flat=True) - ) + ) # type: ignore @classmethod async def get_user_nickname(cls, user_qq: int, group_id: int) -> str: @@ -90,6 +91,9 @@ class GroupInfoUser(Model): @classmethod async def get_group_member_uid(cls, user_qq: int, group_id: int) -> Optional[int]: + logger.debug( + f"GroupInfoUser 尝试获取 用户[{user_qq}] 群聊[{group_id}] UID" + ) user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id) _max_uid_user, _ = await cls.get_or_create(user_qq=114514, group_id=114514) _max_uid = _max_uid_user.uid @@ -101,6 +105,9 @@ class GroupInfoUser(Model): user.uid = _max_uid + 1 _max_uid_user.uid = _max_uid + 1 await cls.bulk_update([user, _max_uid_user], ["uid"]) + logger.debug( + f"GroupInfoUser 获取 用户[{user_qq}] 群聊[{group_id}] UID: {user.uid}" + ) return user.uid @classmethod diff --git a/plugins/open_cases/__init__.py b/plugins/open_cases/__init__.py index e8fefd18..caebe66e 100755 --- a/plugins/open_cases/__init__.py +++ b/plugins/open_cases/__init__.py @@ -1,4 +1,6 @@ +import asyncio import random +from datetime import datetime, timedelta from typing import Any, List, Tuple from nonebot import on_command @@ -12,17 +14,25 @@ from nonebot.typing import T_State from configs.config import Config from configs.path_config import IMAGE_PATH -from utils.utils import is_number, scheduler +from services.log import logger +from utils.message_builder import image +from utils.utils import CN2NUM, is_number, scheduler from .open_cases_c import ( + auto_update, get_my_knifes, group_statistics, open_case, open_multiple_case, total_open_statistics, - update, ) -from .utils import CASE2ID, CaseManager, reset_count_daily, update_case_data +from .utils import ( + CASE2ID, + CaseManager, + build_case_image, + reset_count_daily, + update_case_data, +) __zx_plugin_name__ = "开箱" __plugin_usage__ = """ @@ -35,14 +45,10 @@ usage: 我的开箱 我的金色 群开箱统计 + 查看武器箱?[武器箱] * 不包含[武器箱]时随机开箱 * - 目前支持的武器箱: - 1.狂牙大行动武器箱 - 2.突围大行动武器箱 - 3.命悬一线武器箱 - 4.裂空武器箱 - 5.光谱武器箱 - 示例:开箱 命悬一线 + 示例: 查看武器箱 + 示例: 查看武器箱英勇 """.strip() __plugin_superuser_usage__ = """ usage: @@ -61,6 +67,7 @@ __plugin_cmd__ = [ "我的开箱", "我的金色", "群开箱统计", + "查看武器箱?[武器箱]", "更新开箱图片 ?[武器箱] [_superuser]", "更新开箱价格 ?[武器箱] [_superuser]", ] @@ -89,10 +96,7 @@ __plugin_configs__ = { "default_value": 3, "type": int, }, - "COOKIE": { - "value": None, - "help": "BUFF的cookie", - }, + "COOKIE": {"value": None, "help": "BUFF的cookie", "type": str}, "BUFF_PROXY": {"value": None, "help": "使用代理访问BUFF"}, "DAILY_UPDATE": { "value": None, @@ -121,8 +125,11 @@ total_case_data = cases_matcher_group.on_command( ) group_open_case_statistics = cases_matcher_group.on_command("群开箱统计") open_multiple = cases_matcher_group.on_regex("(.*)连开箱(.*)?") -update_data = on_command("更新武器箱", priority=1, permission=SUPERUSER, block=True) +update_case = on_command("更新武器箱", priority=1, permission=SUPERUSER, block=True) +show_case = on_command("查看武器箱", priority=5, block=True) my_knifes = on_command("我的金色", priority=1, permission=GROUP, block=True) +show_skin = on_command("查看皮肤", priority=5, block=True) +# show_case = on_command("test", priority=1, permission=GROUP, block=True) @reload_count.handle() @@ -163,9 +170,9 @@ async def _( event: GroupMessageEvent, state: T_State, reg_group: Tuple[Any, ...] = RegexGroup() ): num, case_name = reg_group - if is_number(num) or num_dict.get(num): + if is_number(num) or CN2NUM.get(num): try: - num = num_dict[num] + num = CN2NUM[num] except KeyError: num = int(num) if num > 30: @@ -181,41 +188,7 @@ async def _( ) -num_dict = { - "一": 1, - "二": 2, - "三": 3, - "四": 4, - "五": 5, - "六": 6, - "七": 7, - "八": 8, - "九": 9, - "十": 10, - "十一": 11, - "十二": 12, - "十三": 13, - "十四": 14, - "十五": 15, - "十六": 16, - "十七": 17, - "十八": 18, - "十九": 19, - "二十": 20, - "二十一": 21, - "二十二": 22, - "二十三": 23, - "二十四": 24, - "二十五": 25, - "二十六": 26, - "二十七": 27, - "二十八": 28, - "二十九": 29, - "三十": 30, -} - - -@update_data.handle() +@update_case.handle() async def _(event: MessageEvent, arg: Message = CommandArg()): msg = arg.extract_plain_text().strip() if not msg: @@ -225,9 +198,38 @@ async def _(event: MessageEvent, arg: Message = CommandArg()): case_list.append(f"{i+1}.{case_name} [已更新]") else: case_list.append(f"{i+1}.{case_name}") - await update_data.finish("未指定武器箱, 当前已包含武器箱\n" + "\n".join(case_list)) - await update_data.send(f"开始更新武器箱: {msg}, 请稍等") - await update_data.send(await update_case_data(msg), at_sender=True) + await update_case.finish("未指定武器箱, 当前已包含武器箱\n" + "\n".join(case_list)) + if msg == "ALL": + await update_case.send(f"即将更新所有武器箱, 请稍等") + case_list = list(CASE2ID.keys()) + for i, case_name in enumerate(case_list): + try: + await update_case_data(case_name) + rand = random.randint(300, 500) + result = "更新全部武器箱完成" + if i < len(case_list): + next_case = case_list[i + 1] + result = f"将在 {rand} 秒后更新下一武器箱: {next_case}" + await update_case.send(f"成功更新武器箱: {case_name}, {result}") + logger.info(f"成功更新武器箱: {case_name}, {result}", "更新武器箱") + await asyncio.sleep(rand) + except Exception as e: + logger.error(f"自动更新武器箱: {case_name}", e=e) + await update_case.send(f"成功自动更新武器箱: {case_name} 发生错误: {type(e)}: {e}") + await update_case.send(f"开始更新全部武器箱完成") + else: + await update_case.send(f"开始更新武器箱: {msg}, 请稍等") + await update_case.send(await update_case_data(msg), at_sender=True) + + +@show_case.handle() +async def _(arg: Message = CommandArg()): + msg = arg.extract_plain_text().strip() + result = await build_case_image(msg) + if isinstance(result, str): + await show_case.send(result) + else: + await show_case.send(image(result)) # 重置开箱 @@ -238,3 +240,21 @@ async def _(event: MessageEvent, arg: Message = CommandArg()): ) async def _(): await reset_count_daily() + + +@scheduler.scheduled_job( + "cron", + hour=23, + minute=48, +) +async def _(): + now = datetime.now() + hour = random.choice([0, 1, 2, 3]) + date = now + timedelta(minutes=1) + logger.debug(f"将在 {date} 时自动更新武器箱...", "更新武器箱") + scheduler.add_job( + auto_update, + "date", + run_date=date.replace(microsecond=0), + id=f"auto_update_csgo_cases", + ) diff --git a/plugins/open_cases/build_image.py b/plugins/open_cases/build_image.py new file mode 100644 index 00000000..c60a6a42 --- /dev/null +++ b/plugins/open_cases/build_image.py @@ -0,0 +1,94 @@ +from datetime import timedelta, timezone +from typing import Optional + +from configs.path_config import IMAGE_PATH +from services.log import logger +from utils.image_utils import BuildImage +from utils.utils import cn2py + +from .config import COLOR2COLOR, COLOR2NAME +from .models.buff_skin import BuffSkin + +BASE_PATH = IMAGE_PATH / "csgo_cases" + +ICON_PATH = IMAGE_PATH / "_icon" + + +async def generate_skin(skin: BuffSkin) -> Optional[BuildImage]: + """构造皮肤图片 + + Args: + skin (BuffSkin): BuffSkin + + Returns: + Optional[BuildImage]: 图片 + """ + name = skin.name + "-" + skin.skin_name + "-" + skin.abrasion + file_path = BASE_PATH / cn2py(skin.case_name) / f"{cn2py(name)}.jpg" + if not file_path.exists(): + logger.warning(f"皮肤图片: {name} 不存在", "查看武器箱") + return None + if skin.color == "CASE": + skin_img = BuildImage(200, 200, background=file_path) + case_bk = BuildImage( + 700, 200, color=(25, 25, 25, 100), font_size=25, font="CJGaoDeGuo.otf" + ) + await case_bk.apaste(skin_img, (10, 10), True) + await case_bk.aline((250, 10, 250, 190)) + await case_bk.aline((280, 160, 660, 160)) + name_icon = BuildImage(30, 30, background=ICON_PATH / "box_white.png") + await case_bk.apaste(name_icon, (260, 25), True) + await case_bk.atext((295, 30), "名称:", (255, 255, 255)) + await case_bk.atext((345, 25), skin.case_name, (255, 0, 38), font_size=30) + + type_icon = BuildImage(30, 30, background=ICON_PATH / "type_white.png") + await case_bk.apaste(type_icon, (260, 70), True) + await case_bk.atext((295, 75), "类型:", (255, 255, 255)) + await case_bk.atext((345, 72), "武器箱", (0, 157, 255), font_size=30) + + price_icon = BuildImage(30, 30, background=ICON_PATH / "price_white.png") + await case_bk.apaste(price_icon, (260, 114), True) + await case_bk.atext((295, 120), "单价:", (255, 255, 255)) + await case_bk.atext( + (340, 116), str(skin.sell_min_price), (0, 255, 98), font_size=30 + ) + + price_icon = BuildImage(30, 30, background=ICON_PATH / "num_white.png") + await case_bk.apaste(price_icon, (455, 70), True) + await case_bk.atext((490, 75), "在售:", (255, 255, 255)) + await case_bk.atext((535, 72), str(skin.sell_num), (144, 0, 255), font_size=30) + + price_icon = BuildImage(30, 30, background=ICON_PATH / "want_buy_white.png") + await case_bk.apaste(price_icon, (455, 114), True) + await case_bk.atext((490, 120), "求购:", (255, 255, 255)) + await case_bk.atext((535, 116), str(skin.buy_num), (144, 0, 255), font_size=30) + + await case_bk.atext((275, 165), "更新时间", (255, 255, 255), font_size=22) + date = str( + skin.update_time.replace(microsecond=0).astimezone( + timezone(timedelta(hours=8)) + ) + ).split("+")[0] + await case_bk.atext( + (344, 170), + date, + (255, 255, 255), + font_size=30, + ) + return case_bk + else: + skin_bk = BuildImage( + 235, 250, color=(25, 25, 25, 100), font_size=25, font="CJGaoDeGuo.otf" + ) + skin_image = BuildImage(205, 153, background=file_path) + skin_bk.paste(skin_image, (10, 30), alpha=True) + # skin_bk.paste(circular_red, (-20, 10), True) + skin_bk.line((10, 180, 220, 180)) + skin_bk.text((10, 10), skin.name, (255, 255, 255)) + skin_bk.text((10, 185), f"{skin.skin_name}", (255, 255, 255), "by_width") + skin_bk.text((10, 218), "品质:", (255, 255, 255)) + skin_bk.text((55, 218), COLOR2NAME[skin.color][:2], COLOR2COLOR[skin.color]) + skin_bk.text((100, 218), "类型:", (255, 255, 255)) + skin_bk.text((145, 218), skin.weapon_type, (255, 255, 255)) + return skin_bk + return None diff --git a/plugins/open_cases/config.py b/plugins/open_cases/config.py index 36f8cc9b..469278e6 100755 --- a/plugins/open_cases/config.py +++ b/plugins/open_cases/config.py @@ -1,6 +1,7 @@ import random from typing import List, Tuple +from configs.path_config import IMAGE_PATH from services.log import logger from .models.buff_skin import BuffSkin @@ -33,6 +34,41 @@ BATTLE_SCARED_S = 0.45 BATTLE_SCARED_E = 0.99999 +NAME2COLOR = { + "消费级": "WHITE", + "工业级": "LIGHTBLUE", + "军规级": "BLUE", + "受限": "PURPLE", + "保密": "PINK", + "隐秘": "RED", + "非凡": "KNIFE", +} + +COLOR2NAME = { + "WHITE": "消费级", + "LIGHTBLUE": "工业级", + "BLUE": "军规级", + "PURPLE": "受限", + "PINK": "保密", + "RED": "隐秘", + "KNIFE": "非凡", +} + +COLOR2COLOR = { + "WHITE": (255, 255, 255), + "LIGHTBLUE": (0, 179, 255), + "BLUE": (0, 85, 255), + "PURPLE": (149, 0, 255), + "PINK": (255, 0, 162), + "RED": (255, 34, 0), + "KNIFE": (255, 225, 0), +} + +ABRASION_SORT = ["崭新出厂", "略有磨损", "久经沙场", "破损不堪", "战横累累"] + +CASE_BACKGROUND = IMAGE_PATH / "csgo_cases" / "_background" / "shu" + + CASE2ID = { "变革": "set_community_32", "反冲": "set_community_31", diff --git a/plugins/open_cases/open_cases_c.py b/plugins/open_cases/open_cases_c.py index eddb5a61..9de630d2 100755 --- a/plugins/open_cases/open_cases_c.py +++ b/plugins/open_cases/open_cases_c.py @@ -12,7 +12,7 @@ from models.sign_group_user import SignGroupUser from services.log import logger from utils.image_utils import BuildImage from utils.message_builder import image -from utils.utils import cn2py, scheduler +from utils.utils import cn2py from .config import * from .models.open_cases_log import OpenCasesLog @@ -99,7 +99,7 @@ async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, M if not case_name: case_name = random.choice(CaseManager.CURRENT_CASES) # type: ignore if case_name not in CaseManager.CURRENT_CASES: - return "武器箱未收录, 当前可用武器箱:\n" + "\n".join(CaseManager.CURRENT_CASES) # type: ignore + return "武器箱未收录, 当前可用武器箱:\n" + ", ".join(CaseManager.CURRENT_CASES) # type: ignore logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_qq, group_id) case = cn2py(case_name) user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group_id) @@ -152,7 +152,7 @@ async def open_case(user_qq: int, group_id: int, case_name: str) -> Union[str, M + "\n" + f"皮肤:[{COLOR2NAME[skin.color]}]{skin.name}{'(StatTrak™)' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion})\n" f"磨损:{rand}\n" - f"价格:{price_result}\n箱子单价:{case_price}\n花费:{17 + case_price}\n" + f"价格:{price_result}\n箱子单价:{case_price}\n花费:{17 + case_price:.2f}\n" f":{ridicule_result}" ) @@ -176,7 +176,7 @@ async def open_multiple_case( if not case_name: case_name = random.choice(CaseManager.CURRENT_CASES) # type: ignore if case_name not in CaseManager.CURRENT_CASES: - return "武器箱未收录, 当前可用武器箱:\n" + "\n".join(CaseManager.CURRENT_CASES) # type: ignore + return "武器箱未收录, 当前可用武器箱:\n" + ", ".join(CaseManager.CURRENT_CASES) # type: ignore user, _ = await OpenCasesUser.get_or_create( user_qq=user_qq, group_id=group_id, @@ -208,7 +208,6 @@ async def open_multiple_case( case_price = 0 if case_skin := await BuffSkin.get_or_none(case_name=case_name, color="CASE"): case_price = case_skin.sell_min_price - print(user.today_open_total) cnt = 0 for skin, rand in skin_list: total_price += skin.sell_min_price @@ -255,7 +254,6 @@ async def open_multiple_case( ) ) await user.save() - print(user.today_open_total) if log_list: await OpenCasesLog.bulk_create(log_list, 10) logger.debug(f"添加 {len(log_list)} 条开箱日志", "开箱", user_qq, group_id) @@ -271,7 +269,7 @@ async def open_multiple_case( + image(markImg.pic2bs4()) + "\n" + result[:-1] - + f"\n箱子单价:{case_price}\n总获取金额:{total_price:.2f}\n总花费:{(17 + case_price) * num}" + + f"\n箱子单价:{case_price}\n总获取金额:{total_price:.2f}\n总花费:{(17 + case_price) * num:.2f}" ) @@ -427,24 +425,8 @@ async def get_old_knife(user_id: int, group_id: int) -> List[OpenCasesLog]: return data_list -@scheduler.scheduled_job( - "cron", - hour=0, - minute=1, -) -async def _(): - now = datetime.now() - hour = random.choice([0, 1, 2, 3]) - date = now + timedelta(hours=hour) - scheduler.add_job( - update, - "date", - run_date=date.replace(microsecond=0), - id=f"auto_update_csgo_cases", - ) - - -async def update(): +async def auto_update(): + """自动更新武器箱""" if case_list := Config.get_config("open_cases", "DAILY_UPDATE"): logger.debug("尝试自动更新武器箱", "更新武器箱") if "ALL" in case_list: @@ -455,7 +437,7 @@ async def update(): try: await update_case_data(case_name) rand = random.randint(300, 500) - logger.debug(f"成功自动更新武器箱: {case_name}, 将在 {rand} 秒后再次更新下一武器箱", "更新武器箱") + logger.info(f"成功自动更新武器箱: {case_name}, 将在 {rand} 秒后再次更新下一武器箱", "更新武器箱") await asyncio.sleep(rand) except Exception as e: logger.error(f"自动更新武器箱: {case_name}", e=e) diff --git a/plugins/open_cases/utils.py b/plugins/open_cases/utils.py index 820d2d51..a28ed53e 100755 --- a/plugins/open_cases/utils.py +++ b/plugins/open_cases/utils.py @@ -1,4 +1,5 @@ import asyncio +import os import random import time from datetime import datetime @@ -10,9 +11,11 @@ from configs.config import Config from configs.path_config import IMAGE_PATH from services.log import logger from utils.http_utils import AsyncHttpx +from utils.image_utils import BuildImage from utils.utils import broadcast_group, cn2py -from .config import CASE2ID +from .build_image import generate_skin +from .config import CASE2ID, CASE_BACKGROUND, COLOR2NAME, NAME2COLOR from .models.buff_skin import BuffSkin from .models.buff_skin_log import BuffSkinLog from .models.open_cases_user import OpenCasesUser @@ -20,9 +23,6 @@ from .models.open_cases_user import OpenCasesUser URL = "https://buff.163.com/api/market/goods" # proxies = 'http://49.75.59.242:3128' -NAME2COLOR = {"消费级": "WHITE", "工业级": "LIGHTBLUE", "军规级": "BLUE", "受限": "PURPLE", "保密": "PINK", "隐秘": "RED", "非凡": "KNIFE"} - -CURRENT_CASES = [] driver = nonebot.get_driver() @@ -220,10 +220,10 @@ async def search_skin_page( obj["weapon_type"] = tags["type"]["localized_name"] # 枪械类型 if obj["weapon_type"] in ["音乐盒", "印花", "探员"]: continue - if obj["weapon_type"] in ["匕首", "手套"]: + elif obj["weapon_type"] in ["匕首", "手套"]: obj["color"] = "KNIFE" obj["name"] = data["short_name"].split("(")[0].strip() # 名称 - if obj["weapon_type"] in ["武器箱"]: + elif obj["weapon_type"] in ["武器箱"]: obj["color"] = "CASE" obj["name"] = data["short_name"] else: @@ -260,6 +260,151 @@ async def search_skin_page( return f'访问失败: {json_data["error"]}', -1 +async def build_case_image(case_name: str) -> Union[BuildImage, str]: + """构造武器箱图片 + + Args: + case_name (str): 名称 + + Returns: + Union[BuildImage, str]: 图片 + """ + background = random.choice(os.listdir(CASE_BACKGROUND)) + background_img = BuildImage(0, 0, background=CASE_BACKGROUND / background) + if case_name: + skin_list_ = await BuffSkin.filter(case_name=case_name).all() + case = None + skin_list: List[BuffSkin] = [] + exists_name = [] + for skin in skin_list_: + if skin.color == "CASE": + case = skin + else: + name = skin.name + skin.skin_name + if name not in exists_name: + skin_list.append(skin) + exists_name.append(name) + generate_img = {} + for skin in skin_list: + skin_img = await generate_skin(skin) + if skin_img: + if not generate_img.get(skin.color): + generate_img[skin.color] = [] + generate_img[skin.color].append(skin_img) + skin_image_list = [] + for color in COLOR2NAME: + if generate_img.get(color): + skin_image_list = skin_image_list + generate_img[color] + img = skin_image_list[0] + img_w, img_h = img.size + total_size = (img_w + 25) * (img_h + 10) * len(skin_image_list) # 总面积 + new_size = get_bk_image_size(total_size, background_img.size, img.size, 250) + A = BuildImage( + new_size[0] + 50, new_size[1], background=CASE_BACKGROUND / background + ) + await A.afilter("GaussianBlur", 2) + if case: + case_img = await generate_skin(case) + if case_img: + A.paste(case_img, (25, 25), True) + w = 25 + h = 230 + skin_image_list.reverse() + for image in skin_image_list: + A.paste(image, (w, h), True) + w += image.w + 20 + if w + image.w - 25 > A.w: + h += image.h + 10 + w = 25 + if h + img_h + 100 < A.h: + await A.acrop((0, 0, A.w, h + img_h + 100)) + return A + else: + skin_list = await BuffSkin.filter(color="CASE").all() + image_list: List[BuildImage] = [] + for skin in skin_list: + if img := await generate_skin(skin): + image_list.append(img) + if not image_list: + return "未收录武器箱" + w = 25 + h = 150 + img = image_list[0] + img_w, img_h = img.size + total_size = (img_w + 25) * (img_h + 10) * len(image_list) # 总面积 + + new_size = get_bk_image_size(total_size, background_img.size, img.size, 155) + A = BuildImage( + new_size[0] + 50, new_size[1], background=CASE_BACKGROUND / background + ) + await A.afilter("GaussianBlur", 2) + bk_img = BuildImage( + img_w, 120, color=(25, 25, 25, 100), font_size=60, font="CJGaoDeGuo.otf" + ) + await bk_img.atext( + (0, 0), f"已收录 {len(image_list)} 个武器箱", (255, 255, 255), center_type="center" + ) + await A.apaste(bk_img, (10, 10), True, "by_width") + for image in image_list: + A.paste(image, (w, h), True) + w += image.w + 20 + if w + image.w - 25 > A.w: + h += image.h + 10 + w = 25 + if h + img_h + 100 < A.h: + await A.acrop((0, 0, A.w, h + img_h + 100)) + return A + + +def get_bk_image_size( + total_size: int, + base_size: Tuple[int, int], + img_size: Tuple[int, int], + extra_height: int = 0, +): + """获取所需背景大小且不改变图片长宽比 + + Args: + total_size (int): 总面积 + base_size (Tuple[int, int]): 初始背景大小 + img_size (Tuple[int, int]): 贴图大小 + + Returns: + _type_: 满足所有贴图大小 + """ + bk_w, bk_h = base_size + img_w, img_h = img_size + is_add_title_size = False + left_dis = 0 + right_dis = 0 + old_size = (0, 0) + new_size = (0, 0) + ratio = 1.1 + while 1: + w_ = int(ratio * bk_w) + h_ = int(ratio * bk_h) + size = w_ * h_ + if size < total_size: + left_dis = size + else: + right_dis = size + r = w_ / (img_w + 25) + if right_dis and r - int(r) < 0.1: + if not is_add_title_size and extra_height: + total_size = int(total_size + w_ * extra_height) + is_add_title_size = True + right_dis = 0 + continue + if total_size - left_dis > right_dis - total_size: + new_size = (w_, h_) + else: + new_size = old_size + break + old_size = (w_, h_) + ratio += 0.1 + return new_size + + async def reset_count_daily(): """ 重置每日开箱 diff --git a/utils/utils.py b/utils/utils.py index 3e87e95e..50e8feb0 100755 --- a/utils/utils.py +++ b/utils/utils.py @@ -34,6 +34,40 @@ GDict = { } +CN2NUM = { + "一": 1, + "二": 2, + "三": 3, + "四": 4, + "五": 5, + "六": 6, + "七": 7, + "八": 8, + "九": 9, + "十": 10, + "十一": 11, + "十二": 12, + "十三": 13, + "十四": 14, + "十五": 15, + "十六": 16, + "十七": 17, + "十八": 18, + "十九": 19, + "二十": 20, + "二十一": 21, + "二十二": 22, + "二十三": 23, + "二十四": 24, + "二十五": 25, + "二十六": 26, + "二十七": 27, + "二十八": 28, + "二十九": 29, + "三十": 30, +} + + class CountLimiter: """ 次数检测工具,检测调用次数是否超过设定值