diff --git a/LittlePaimon/plugins/Paimon_Abyss/draw_abyss.py b/LittlePaimon/plugins/Paimon_Abyss/draw_abyss.py index 6369ceb..a51f4c1 100644 --- a/LittlePaimon/plugins/Paimon_Abyss/draw_abyss.py +++ b/LittlePaimon/plugins/Paimon_Abyss/draw_abyss.py @@ -2,9 +2,13 @@ import asyncio import datetime from LittlePaimon.database import AbyssInfo -from LittlePaimon.utils.path import RESOURCE_BASE_PATH -from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image +from LittlePaimon.utils.image import PMImage +from LittlePaimon.utils.image import font_manager as fm +from LittlePaimon.utils.image import load_image from LittlePaimon.utils.message import MessageBuild +from LittlePaimon.utils.path import RESOURCE_BASE_PATH + +time_str = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'] def datetime_to_cn(time: datetime.datetime) -> str: @@ -13,7 +17,6 @@ def datetime_to_cn(time: datetime.datetime) -> str: :param time: 时间 :return: 中文时间 """ - time_str = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'] if time.day < 16: return f'{time_str[time.month]}月上半' else: @@ -24,7 +27,9 @@ async def draw_abyss_card(info: AbyssInfo): if not info.total_battle or not info.max_battle: return '暂无深渊挑战数据,请稍候再试' # 加载图片素材 - img = PMImage(await load_image(RESOURCE_BASE_PATH / 'abyss' / 'bg.png', mode='RGBA')) + img = PMImage( + await load_image(RESOURCE_BASE_PATH / 'abyss' / 'bg.png', mode='RGBA') + ) orange_line = await load_image(RESOURCE_BASE_PATH / 'general' / 'line.png') # 标题文字 await img.text('深渊战报', 36, 29, fm.get('优设标题黑', 108), '#40342d') @@ -37,60 +42,173 @@ async def draw_abyss_card(info: AbyssInfo): await img.text(time_str, 438, 41, fm.get('SourceHanSansCN-Bold.otf', 30), 'white') # UID和昵称 if info.nickname: - await img.text(f'UID{info.uid}', 1040, 72, fm.get('bahnschrift_regular.ttf', 36), '#40342d', 'right') - await img.text(info.nickname, 1040, 114, fm.get('SourceHanSansCN-Bold.otf', 30), '#40342d', 'right') + await img.text( + f'UID{info.uid}', + 1040, + 72, + fm.get('bahnschrift_regular.ttf', 36), + '#40342d', + 'right', + ) + await img.text( + info.nickname, + 1040, + 114, + fm.get('SourceHanSansCN-Bold.otf', 30), + '#40342d', + 'right', + ) else: - await img.text(f'UID{info.uid}', 1040, 114, fm.get('bahnschrift_regular.ttf', 36), '#40342d', 'right') + await img.text( + f'UID{info.uid}', + 1040, + 114, + fm.get('bahnschrift_regular.ttf', 36), + '#40342d', + 'right', + ) # 战绩速览标题 await img.paste(orange_line, (40, 164)) await img.text('战绩速览', 63, 176, fm.get('SourceHanSansCN-Bold.otf', 30), 'white') # logo和生成时间 - await img.text(f'CREATED BY LITTLEPAIMON AT {datetime.datetime.now().strftime("%m-%d %H:%M")}', - 1025, 178, fm.get('bahnschrift_regular.ttf', 30), '#8c4c2e', 'right') + await img.text( + f'CREATED BY LITTLEPAIMON AT {datetime.datetime.now().strftime("%m-%d %H:%M")}', + 1025, + 178, + fm.get('bahnschrift_regular.ttf', 30), + '#8c4c2e', + 'right', + ) # 数据栏 - await img.paste(await load_image(RESOURCE_BASE_PATH / 'abyss' / 'data_line.png'), (40, 246)) + await img.paste( + await load_image(RESOURCE_BASE_PATH / 'abyss' / 'data_line.png'), (40, 246) + ) # 获得总星数 - await img.text(f'{info.total_star}/36', (47, 150), 357, fm.get('bahnschrift_regular.ttf', 56), '#40342d', 'center') + await img.text( + f'{info.total_star}/36', + (47, 150), + 357, + fm.get('bahnschrift_regular.ttf', 56), + '#40342d', + 'center', + ) # 战斗次数 - await img.text(str(info.total_battle), (209, 312), 357, fm.get('bahnschrift_regular.ttf', 56), '#40342d', 'center') + await img.text( + str(info.total_battle), + (209, 312), + 357, + fm.get('bahnschrift_regular.ttf', 56), + '#40342d', + 'center', + ) # 最多击破 - await img.text(str(info.max_defeat.value), (370, 473), 357, fm.get('bahnschrift_regular.ttf', 56), '#40342d', - 'center') - chara_img = PMImage(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{info.max_defeat.icon}.png', size=(96, 96))) - await chara_img.to_circle('circle') - await img.paste(chara_img, (373, 248)) + if info.max_defeat is not None: + await img.text( + str(info.max_defeat.value), + (370, 473), + 357, + fm.get('bahnschrift_regular.ttf', 56), + '#40342d', + 'center', + ) + chara_img = PMImage( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{info.max_defeat.icon}.png', + size=(96, 96), + ) + ) + await chara_img.to_circle('circle') + await img.paste(chara_img, (373, 248)) # 战技次数 - await img.text(str(info.max_normal_skill.value), (532, 635), 357, fm.get('bahnschrift_regular.ttf', 56), '#40342d', - 'center') - chara_img = PMImage( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{info.max_normal_skill.icon}.png', size=(96, 96))) - await chara_img.to_circle('circle') - await img.paste(chara_img, (536, 248)) + if info.max_normal_skill is not None: + await img.text( + str(info.max_normal_skill.value), + (532, 635), + 357, + fm.get('bahnschrift_regular.ttf', 56), + '#40342d', + 'center', + ) + chara_img = PMImage( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{info.max_normal_skill.icon}.png', + size=(96, 96), + ) + ) + await chara_img.to_circle('circle') + await img.paste(chara_img, (536, 248)) # 爆发次数 - await img.text(str(info.max_energy_skill.value), (693, 796), 357, fm.get('bahnschrift_regular.ttf', 56), '#40342d', - 'center') - chara_img = PMImage( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{info.max_energy_skill.icon}.png', size=(96, 96))) - await chara_img.to_circle('circle') - await img.paste(chara_img, (696, 248)) + if info.max_energy_skill is not None: + await img.text( + str(info.max_energy_skill.value), + (693, 796), + 357, + fm.get('bahnschrift_regular.ttf', 56), + '#40342d', + 'center', + ) + chara_img = PMImage( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{info.max_energy_skill.icon}.png', + size=(96, 96), + ) + ) + await chara_img.to_circle('circle') + await img.paste(chara_img, (696, 248)) # 最深抵达 - await img.text(str(info.max_floor), (838, 1038), 298, fm.get('bahnschrift_regular.ttf', 60), '#40342d', 'center') + if info.max_floor is not None: + await img.text( + str(info.max_floor), + (838, 1038), + 298, + fm.get('bahnschrift_regular.ttf', 60), + '#40342d', + 'center', + ) # 最强一击 circle = await load_image(RESOURCE_BASE_PATH / 'general' / 'orange_circle.png') - chara_img = PMImage(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{info.max_damage.icon}.png', size=(205, 205))) - await chara_img.to_circle('circle') - await img.text('最强一击', 270, 520, fm.get('SourceHanSansCN-Bold.otf', 48), '#40342d') - await img.text(str(info.max_damage.value), 270, 590, fm.get('bahnschrift_bold.ttf', 72, 'Bold'), '#40342d') - await img.paste(circle, (46, 485)) - await img.paste(chara_img, (49, 488)) + if info.max_damage is not None: + chara_img = PMImage( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{info.max_damage.icon}.png', + size=(205, 205), + ) + ) + await chara_img.to_circle('circle') + await img.text( + '最强一击', 270, 520, fm.get('SourceHanSansCN-Bold.otf', 48), '#40342d' + ) + await img.text( + str(info.max_damage.value), + 270, + 590, + fm.get('bahnschrift_bold.ttf', 72, 'Bold'), + '#40342d', + ) + await img.paste(circle, (46, 485)) + await img.paste(chara_img, (49, 488)) # 最多承伤 - chara_img = PMImage(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{info.max_take_damage.icon}.png', size=(205, 205))) - await chara_img.to_circle('circle') - await img.text('最多承伤', 791, 520, fm.get('SourceHanSansCN-Bold.otf', 48), '#40342d') - await img.text(str(info.max_take_damage.value), 791, 590, fm.get('bahnschrift_bold.ttf', 72, 'Bold'), '#40342d') - await img.paste(circle, (560, 485)) - await img.paste(chara_img, (563, 488)) + if info.info.max_take_damage is not None: + chara_img = PMImage( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{info.max_take_damage.icon}.png', + size=(205, 205), + ) + ) + await chara_img.to_circle('circle') + await img.text( + '最多承伤', 791, 520, fm.get('SourceHanSansCN-Bold.otf', 48), '#40342d' + ) + await img.text( + str(info.max_take_damage.value), + 791, + 590, + fm.get('bahnschrift_bold.ttf', 72, 'Bold'), + '#40342d', + ) + await img.paste(circle, (560, 485)) + await img.paste(chara_img, (563, 488)) # 没有9-12层信息时不会只详细战绩 if all(info.floors.get(i) is None for i in range(9, 13)): return MessageBuild.Image(img) @@ -98,74 +216,159 @@ async def draw_abyss_card(info: AbyssInfo): await img.paste(orange_line, (40, 747)) await img.text('详细战绩', 63, 759, fm.get('SourceHanSansCN-Bold.otf', 30), 'white') for i in range(9, 13): - await img.paste(await load_image(RESOURCE_BASE_PATH / 'abyss' / f'floor{i}.png'), (41, 834 + (i - 9) * 194)) + await img.paste( + await load_image(RESOURCE_BASE_PATH / 'abyss' / f'floor{i}.png'), + (41, 834 + (i - 9) * 194), + ) if info.floors.get(i): if info.floors[i].stars: - await img.text('-'.join(map(str, info.floors[i].stars)), 91, 960 + (i - 9) * 194, - fm.get('bahnschrift_bold.ttf', 30, 'Bold'), 'white') + await img.text( + '-'.join(map(str, info.floors[i].stars)), + 91, + 960 + (i - 9) * 194, + fm.get('bahnschrift_bold.ttf', 30, 'Bold'), + 'white', + ) if info.floors[i].battles_up: up = info.floors[i].battles_up down = info.floors[i].battles_down j = 0 for character in up[0]: await img.paste( - await load_image(RESOURCE_BASE_PATH / 'icon' / f'star{character.rarity}.png', size=(95, 95)), - (192 + (j % 4) * 103, 832 + (i - 9) * 194)) + await load_image( + RESOURCE_BASE_PATH / 'icon' / f'star{character.rarity}.png', + size=(95, 95), + ), + (192 + (j % 4) * 103, 832 + (i - 9) * 194), + ) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{character.icon}.png', size=(95, 95)), - (192 + (j % 4) * 103, 832 + (i - 9) * 194)) - await img.draw_rounded_rectangle2((192 + (j % 4) * 103, 903 + (i - 9) * 194), (30, 23), 10, - '#333333', - ['ll', 'ur']) - await img.text(str(character.level), (192 + (j % 4) * 103, 192 + (j % 4) * 103 + 30), - 906 + (i - 9) * 194, - fm.get('bahnschrift_bold.ttf', 20, 'Bold'), 'white', 'center') + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{character.icon}.png', + size=(95, 95), + ), + (192 + (j % 4) * 103, 832 + (i - 9) * 194), + ) + await img.draw_rounded_rectangle2( + (192 + (j % 4) * 103, 903 + (i - 9) * 194), + (30, 23), + 10, + '#333333', + ['ll', 'ur'], + ) + await img.text( + str(character.level), + (192 + (j % 4) * 103, 192 + (j % 4) * 103 + 30), + 906 + (i - 9) * 194, + fm.get('bahnschrift_bold.ttf', 20, 'Bold'), + 'white', + 'center', + ) j += 1 j = 0 for character in down[0]: await img.paste( - await load_image(RESOURCE_BASE_PATH / 'icon' / f'star{character.rarity}.png', size=(95, 95)), - (637 + (j % 4) * 103, 832 + (i - 9) * 194)) + await load_image( + RESOURCE_BASE_PATH / 'icon' / f'star{character.rarity}.png', + size=(95, 95), + ), + (637 + (j % 4) * 103, 832 + (i - 9) * 194), + ) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{character.icon}.png', size=(95, 95)), - (637 + (j % 4) * 103, 832 + (i - 9) * 194)) - await img.draw_rounded_rectangle2((637 + (j % 4) * 103, 903 + (i - 9) * 194), (30, 23), 10, - '#333333', - ['ll', 'ur']) - await img.text(str(character.level), (637 + (j % 4) * 103, 637 + (j % 4) * 103 + 30), - 906 + (i - 9) * 194, - fm.get('bahnschrift_bold.ttf', 20, 'Bold'), 'white', 'center') + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{character.icon}.png', + size=(95, 95), + ), + (637 + (j % 4) * 103, 832 + (i - 9) * 194), + ) + await img.draw_rounded_rectangle2( + (637 + (j % 4) * 103, 903 + (i - 9) * 194), + (30, 23), + 10, + '#333333', + ['ll', 'ur'], + ) + await img.text( + str(character.level), + (637 + (j % 4) * 103, 637 + (j % 4) * 103 + 30), + 906 + (i - 9) * 194, + fm.get('bahnschrift_bold.ttf', 20, 'Bold'), + 'white', + 'center', + ) j += 1 j = 0 for group in up: - await img.paste(await load_image(RESOURCE_BASE_PATH / 'general' / 'orange_bord_small.png'), - (192 + (j % 3) * 287, 936 + (i - 9) * 194)) - - await asyncio.gather(*[img.paste( + await img.paste( await load_image( - RESOURCE_BASE_PATH / 'avatar_side' / f'{group[k].icon.replace("Icon_", "Icon_Side_")}.png', - size=(40, 40)), (190 + (j % 3) * 287 + (k % 4) * 32, 928 + (i - 9) * 194)) for k in - range(len(group))]) - await img.text(f'{i}-{j + 1} {info.floors[i].end_times_down[j].strftime("%H:%M:%S")}', - (192 + (j % 3) * 287, 463 + (j % 3) * 287), (978 + (i - 9) * 194), - fm.get('bahnschrift_regular.ttf', 24), '#40342d', 'center') + RESOURCE_BASE_PATH / 'general' / 'orange_bord_small.png' + ), + (192 + (j % 3) * 287, 936 + (i - 9) * 194), + ) + + await asyncio.gather( + *[ + img.paste( + await load_image( + RESOURCE_BASE_PATH + / 'avatar_side' + / f'{group[k].icon.replace("Icon_", "Icon_Side_")}.png', + size=(40, 40), + ), + ( + 190 + (j % 3) * 287 + (k % 4) * 32, + 928 + (i - 9) * 194, + ), + ) + for k in range(len(group)) + ] + ) + await img.text( + f'{i}-{j + 1} {info.floors[i].end_times_down[j].strftime("%H:%M:%S")}', + (192 + (j % 3) * 287, 463 + (j % 3) * 287), + (978 + (i - 9) * 194), + fm.get('bahnschrift_regular.ttf', 24), + '#40342d', + 'center', + ) j += 1 j = 0 for group in down: - await img.paste(await load_image(RESOURCE_BASE_PATH / 'general' / 'orange_bord_small.png'), - (330 + (j % 3) * 287, 936 + (i - 9) * 194)) - await asyncio.gather(*[img.paste( + await img.paste( await load_image( - RESOURCE_BASE_PATH / 'avatar_side' / f'{group[k].icon.replace("Icon_", "Icon_Side_")}.png', - size=(40, 40)), (328 + (j % 3) * 287 + (k % 4) * 32, 928 + (i - 9) * 194)) for k in - range(len(group))]) + RESOURCE_BASE_PATH / 'general' / 'orange_bord_small.png' + ), + (330 + (j % 3) * 287, 936 + (i - 9) * 194), + ) + await asyncio.gather( + *[ + img.paste( + await load_image( + RESOURCE_BASE_PATH + / 'avatar_side' + / f'{group[k].icon.replace("Icon_", "Icon_Side_")}.png', + size=(40, 40), + ), + ( + 328 + (j % 3) * 287 + (k % 4) * 32, + 928 + (i - 9) * 194, + ), + ) + for k in range(len(group)) + ] + ) j += 1 else: - await img.paste(await load_image(RESOURCE_BASE_PATH / 'abyss' / 'nock.png'), (192, 834 + (i - 9) * 194)) + await img.paste( + await load_image(RESOURCE_BASE_PATH / 'abyss' / 'nock.png'), + (192, 834 + (i - 9) * 194), + ) else: - await img.paste(await load_image(RESOURCE_BASE_PATH / 'abyss' / 'nodata.png'), (192, 834 + (i - 9) * 194)) + await img.paste( + await load_image(RESOURCE_BASE_PATH / 'abyss' / 'nodata.png'), + (192, 834 + (i - 9) * 194), + ) return MessageBuild.Image(img, quality=80, mode='RGB') diff --git a/src/plugins/.gitkeep b/src/plugins/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/plugins/nonebot_plugin_myb_exchange/README.md b/src/plugins/nonebot_plugin_myb_exchange/README.md deleted file mode 100644 index 4a60eb4..0000000 --- a/src/plugins/nonebot_plugin_myb_exchange/README.md +++ /dev/null @@ -1,44 +0,0 @@ -
-- - - - - -
- -## 安装 -> 需要配合nonebot2使用,安装方法详见[nb文档](https://v2.nonebot.dev/) -- 通过nb脚手架安装(推荐) -``` -nb plugin install nonebot-plugin-myb-exchange -``` -- 通过pip安装 -``` -pip install nonebot-plugin-myb-exchange - -# 还需要在bot.py加载插件,在bot.py中添加 -nonebot.load_plugin("nonebot-plugin-myb-exchange") -``` -- 通过poetry安装 -``` -poetry add nonebot-plugin-myb-exchange - -# 还需要在bot.py加载插件,同上 -``` - - -## 使用方法 -> 由于涉及到cookie、地址等敏感信息,所以仅限**私聊**Bot使用 - -- 发送`myb`,跟随Bot的指引一步一步录入信息,需要用户提供`米游社cookie、收货地址、商品名称`等信息 -- 发送`myb_info`可查看已录入的兑换计划 -- 发送`myb_delete`可一键删除所有你的兑换计划 - -## 成功兑换示范 - - \ No newline at end of file diff --git a/src/plugins/nonebot_plugin_myb_exchange/__init__.py b/src/plugins/nonebot_plugin_myb_exchange/__init__.py deleted file mode 100644 index 39321bd..0000000 --- a/src/plugins/nonebot_plugin_myb_exchange/__init__.py +++ /dev/null @@ -1,166 +0,0 @@ -import re - -from nonebot import on_command -from nonebot.adapters.onebot.v11 import PrivateMessageEvent, Message -from nonebot.params import CommandArg, T_State, Arg -from nonebot.plugin import PluginMetadata - -from .data_source import get_address, get_goods, save_exchange_info, get_exchange_info, delete_exchange_info - -__plugin_meta__ = PluginMetadata( - name="米游币商品自动兑换插件", - description="录入米游币兑换计划,Bot会在对应时间自动帮你抢兑商品", - usage=( - "myb 跟随Bot的指引录入兑换计划\n" - "myb_info 查看当前的兑换计划\n" - "myb_delete 删除你的所有兑换计划\n" - ), - extra={ - "author": "惜月 <277073121@qq.com>", - "version": "1.0.0", - }, -) - -myb_exchange = on_command('myb', aliases={'米游币兑换', '米游币商品兑换', '米游社商品兑换'}, priority=6, state={ - 'pm_name': '米游币兑换', - 'pm_usage': 'myb', - 'pm_show': True, - 'pm_priority': 15, - 'pm_description': '录入米游币商品自动兑换计划', -}) -myb_info = on_command('myb_info', aliases={'米游币兑换信息', '米游币兑换计划'}, priority=6, state={ - 'pm_name': '米游币兑换信息', - 'pm_usage': 'myb_info', - 'pm_show': True, - 'pm_priority': 16, - 'pm_description': '查看你的米游币兑换计划', -}) -myb_delete = on_command('myb_delete', aliases={'米游币兑换删除', '米游币兑换取消'}, priority=6, state={ - 'pm_name': '米游币兑换删除', - 'pm_usage': 'myb_delete', - 'pm_show': True, - 'pm_priority': 17, - 'pm_description': '取消你的米游币兑换计划', -}) - - -@myb_exchange.handle() -async def _(event: PrivateMessageEvent, state: T_State, msg: Message = CommandArg()): - if msg: - msg = msg.extract_plain_text().strip() - if '虚拟' in msg: - state['商品类型'] = '虚拟' - elif '实体' in msg: - state['商品类型'] = '实体' - state['uid'] = None - - -@myb_exchange.got('商品类型', prompt='请给出要抢的商品类型(虚拟|实体),例如原石属于虚拟') -async def _(event: PrivateMessageEvent, state: T_State, type: Message = Arg('商品类型')): - type = type.extract_plain_text().strip() - if '虚拟' in type: - state['商品类型'] = '虚拟' - print(state) - elif '实体' in type: - state['商品类型'] = '实体' - state['uid'] = None - else: - await myb_exchange.reject('请给出要抢的商品类型(虚拟|实体),例如原石属于虚拟') - - -@myb_exchange.got('uid', prompt='请把虚拟商品要兑换到的游戏uid告诉我') -async def _(event: PrivateMessageEvent, state: T_State, uid: Message = Arg('uid')): - uid = uid.extract_plain_text().strip() - if find_uid := re.search(r'(?P