From 4c3b1e5631da030ab15f330f1827e79832c0e601 Mon Sep 17 00:00:00 2001 From: CMHopeSunshine <277073121@qq.com> Date: Fri, 17 Feb 2023 22:36:31 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D=E5=A4=9Abot?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=97=B6`=E6=B7=B1=E6=B8=8A=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1`=E5=92=8C`=E7=8C=9C=E8=AF=AD=E9=9F=B3`=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/Genshin_Voice/__init__.py | 114 ++++-- LittlePaimon/plugins/Genshin_Voice/handler.py | 75 +++- LittlePaimon/plugins/Paimon_Abyss/__init__.py | 67 ++-- .../plugins/Paimon_Abyss/abyss_statistics.py | 378 +++++++++++++----- LittlePaimon/plugins/bot_manager/__init__.py | 30 +- 5 files changed, 477 insertions(+), 187 deletions(-) diff --git a/LittlePaimon/plugins/Genshin_Voice/__init__.py b/LittlePaimon/plugins/Genshin_Voice/__init__.py index eb01b7d..fd60244 100644 --- a/LittlePaimon/plugins/Genshin_Voice/__init__.py +++ b/LittlePaimon/plugins/Genshin_Voice/__init__.py @@ -2,7 +2,13 @@ import random from typing import Union from nonebot import on_command -from nonebot.adapters.onebot.v11 import Message, MessageEvent, GroupMessageEvent, PrivateMessageEvent +from nonebot.adapters.onebot.v11 import ( + Bot, + GroupMessageEvent, + Message, + MessageEvent, + PrivateMessageEvent, +) from nonebot.adapters.onebot.v11.exception import ActionFailed from nonebot.params import CommandArg from nonebot.permission import SUPERUSER @@ -12,7 +18,14 @@ from LittlePaimon.config import config from LittlePaimon.database import GenshinVoice from LittlePaimon.utils.alias import get_match_alias from LittlePaimon.utils.message import CommandCharacter, CommandLang, MessageBuild -from .handler import GuessVoice, get_character_voice, get_rank, get_voice_list, get_record + +from .handler import ( + GuessVoice, + get_character_voice, + get_rank, + get_record, + get_voice_list, +) from .resources import update_voice_resources __plugin_meta__ = PluginMetadata( @@ -20,47 +33,70 @@ __plugin_meta__ = PluginMetadata( description='原神语音', usage='原神猜语音', extra={ - 'author': '惜月', - 'version': '3.0', + 'author': '惜月', + 'version': '3.0', 'priority': 6, - } + }, ) -guess_voice = on_command('原神猜语音', priority=12, block=True, state={ - 'pm_name': '原神猜语音', +guess_voice = on_command( + '原神猜语音', + priority=12, + block=True, + state={ + 'pm_name': '原神猜语音', 'pm_description': '原神猜语音小游戏', - 'pm_usage': '原神猜语音[语言][排行榜]', - 'pm_priority': 1 - }) -get_voice = on_command('原神语音', priority=12, block=True, state={ - 'pm_name': '原神语音', + 'pm_usage': '原神猜语音[语言][排行榜]', + 'pm_priority': 1, + }, +) +get_voice = on_command( + '原神语音', + priority=12, + block=True, + state={ + 'pm_name': '原神语音', 'pm_description': '获取指定角色的指定语音', - 'pm_usage': '原神语音<名|序号>[语言]', - 'pm_priority': 3 - }) -voice_list = on_command('原神语音列表', priority=12, block=True, state={ - 'pm_name': '原神语音列表', + 'pm_usage': '原神语音<名|序号>[语言]', + 'pm_priority': 3, + }, +) +voice_list = on_command( + '原神语音列表', + priority=12, + block=True, + state={ + 'pm_name': '原神语音列表', 'pm_description': '查看角色的语音列表', - 'pm_usage': '原神语音列表<名><语言>', - 'pm_priority': 2 - }) -update_voice = on_command('更新原神语音资源', priority=12, permission=SUPERUSER, block=True, state={ - 'pm_name': '更新原神语音资源', + 'pm_usage': '原神语音列表<名><语言>', + 'pm_priority': 2, + }, +) +update_voice = on_command( + '更新原神语音资源', + priority=12, + permission=SUPERUSER, + block=True, + state={ + 'pm_name': '更新原神语音资源', 'pm_description': '更新原神语音资源', - 'pm_usage': '更新原神语音资源', - 'pm_show': False, - 'pm_priority': 4 - }) + 'pm_usage': '更新原神语音资源', + 'pm_show': False, + 'pm_priority': 4, + }, +) @guess_voice.handle() -async def _(event: GroupMessageEvent, msg: Message = CommandArg(), lang=CommandLang()): +async def _( + bot: Bot, event: GroupMessageEvent, msg: Message = CommandArg(), lang=CommandLang() +): msg = msg.extract_plain_text().strip() if 'rank' in msg or '排行' in msg: result = await get_rank(event.group_id) await guess_voice.finish(result) else: - game = GuessVoice(event.group_id, config.guess_voice_time, lang) + game = GuessVoice(event.group_id, bot, config.guess_voice_time, lang) result = await game.start() await guess_voice.send(f'即将发送一段语音,将在{config.guess_voice_time}秒后公布答案') try: @@ -71,11 +107,19 @@ async def _(event: GroupMessageEvent, msg: Message = CommandArg(), lang=CommandL @get_voice.handle() -async def _(event: Union[GroupMessageEvent, PrivateMessageEvent], lang=CommandLang(), msg: Message = CommandArg()): +async def _( + event: Union[GroupMessageEvent, PrivateMessageEvent], + lang=CommandLang(), + msg: Message = CommandArg(), +): msg = msg.extract_plain_text().strip().split(' ')[0] if msg.isdigit(): voice = await GenshinVoice.get_or_none(id=int(msg)) - await get_voice.finish(await get_record(voice.voice_url) if voice else MessageBuild.Text(f'没有{msg}号原神语音')) + await get_voice.finish( + await get_record(voice.voice_url) + if voice + else MessageBuild.Text(f'没有{msg}号原神语音') + ) else: if chara := get_match_alias(msg, ['角色'], True): chara = chara[0] @@ -85,11 +129,17 @@ async def _(event: Union[GroupMessageEvent, PrivateMessageEvent], lang=CommandLa if voices: await get_voice.finish(await get_record(random.choice(voices).voice_url)) else: - await get_voice.finish(MessageBuild.Text(f'暂无{chara}的{lang}文语音资源,让超级用户[更新原神语音资源]吧!')) + await get_voice.finish( + MessageBuild.Text(f'暂无{chara}的{lang}文语音资源,让超级用户[更新原神语音资源]吧!') + ) @voice_list.handle() -async def _(event: Union[GroupMessageEvent, PrivateMessageEvent], character=CommandCharacter(1), lang=CommandLang()): +async def _( + event: Union[GroupMessageEvent, PrivateMessageEvent], + character=CommandCharacter(1), + lang=CommandLang(), +): result = await get_voice_list(character[0], lang) await get_voice.finish(result) diff --git a/LittlePaimon/plugins/Genshin_Voice/handler.py b/LittlePaimon/plugins/Genshin_Voice/handler.py index d147e81..364da8c 100644 --- a/LittlePaimon/plugins/Genshin_Voice/handler.py +++ b/LittlePaimon/plugins/Genshin_Voice/handler.py @@ -1,14 +1,15 @@ import datetime import random -from nonebot import get_bot, on_regex -from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageSegment +from nonebot import on_regex +from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageSegment from nonebot.rule import Rule from LittlePaimon.database import GenshinVoice, GuessVoiceRank -from LittlePaimon.utils import scheduler, logger +from LittlePaimon.utils import logger, scheduler from LittlePaimon.utils.alias import get_alias_by_name from LittlePaimon.utils.requests import aiorequests + from .draw import draw_voice_list gaming = {} @@ -19,10 +20,13 @@ class GuessVoice: group_id: int language: str - def __init__(self, group_id: int, game_time: int = 30, language: str = '中'): + def __init__( + self, group_id: int, bot: Bot, game_time: int = 30, language: str = '中' + ): self.group_id = group_id self.game_time = game_time self.language = language + self.bot = bot @property def is_gaming(self): @@ -39,10 +43,14 @@ class GuessVoice: create_guess_matcher(self.group_id, voice.character, self.game_time) if scheduler.get_job(f'Guess_voice_{self.group_id}'): scheduler.remove_job(f'Guess_voice_{self.group_id}') - scheduler.add_job(self.end, 'date', - run_date=datetime.datetime.now() + datetime.timedelta(seconds=self.game_time), - id=f'Guess_voice_{self.group_id}', - misfire_grace_time=10) + scheduler.add_job( + self.end, + 'date', + run_date=datetime.datetime.now() + + datetime.timedelta(seconds=self.game_time), + id=f'Guess_voice_{self.group_id}', + misfire_grace_time=10, + ) return await get_record(voice.voice_url) async def end(self, exception: bool = False): @@ -51,18 +59,22 @@ class GuessVoice: del gaming[self.group_id] msg = f'还没有人猜中呢,正确答案是:{answer}!' try: - await get_bot().send_group_msg(group_id=self.group_id, message=msg) + await self.bot.send_group_msg(group_id=self.group_id, message=msg) except Exception as e: logger.warning('原神猜语音', '➤发送结果时出错', str(e)) - logger.info('原神猜语音', f'➤群{self.group_id}猜语音游戏结束,答案为{answer},没有人猜对') + logger.info( + '原神猜语音', f'➤群{self.group_id}猜语音游戏结束,答案为{answer},没有人猜对' + ) elif exception: logger.warning('原神猜语音', f'➤群{self.group_id}猜语音游戏发送语音出错, 异常结束') del gaming[self.group_id] async def get_rank(group_id: int): - records = await GuessVoiceRank.filter(group_id=group_id, - guess_time__gte=datetime.datetime.now() - datetime.timedelta(days=7)) + records = await GuessVoiceRank.filter( + group_id=group_id, + guess_time__gte=datetime.datetime.now() - datetime.timedelta(days=7), + ) if not records: return '本群本周暂无排行榜数据哦!' rank = {} @@ -72,7 +84,9 @@ async def get_rank(group_id: int): else: rank[record.user_id] = 1 msg = '本周猜语音排行榜\n' - for i, (user_id, count) in enumerate(sorted(rank.items(), key=lambda x: x[1], reverse=True), start=1): + for i, (user_id, count) in enumerate( + sorted(rank.items(), key=lambda x: x[1], reverse=True), start=1 + ): msg += f'{i}.{user_id}: {count}次\n' return msg @@ -87,24 +101,39 @@ def create_guess_matcher(group_id, role_name, game_time): def check_group(event: GroupMessageEvent): return event.group_id == group_id + if '旅行者' in role_name: role_name = role_name.replace('旅行者(', '').replace(')', '') alias_list = get_alias_by_name(role_name) re_str = '|'.join(alias_list) - guess_matcher = on_regex(f'^{re_str}$', temp=True, rule=Rule(check_group), - expire_time=datetime.timedelta(seconds=game_time)) + guess_matcher = on_regex( + f'^{re_str}$', + temp=True, + rule=Rule(check_group), + expire_time=datetime.timedelta(seconds=game_time), + ) guess_matcher.plugin_name = "Genshin_Voice" @guess_matcher.handle() async def _(event: GroupMessageEvent): - await GuessVoiceRank.create(user_id=event.user_id, group_id=event.group_id, answer=role_name, - guess_time=datetime.datetime.now()) + await GuessVoiceRank.create( + user_id=event.user_id, + group_id=event.group_id, + answer=role_name, + guess_time=datetime.datetime.now(), + ) del gaming[event.group_id] if scheduler.get_job(f'Guess_voice_{event.group_id}'): scheduler.remove_job(f'Guess_voice_{event.group_id}') - logger.info('原神猜语音', f'➤群{event.group_id}猜语音游戏结束,答案为{role_name},由{event.sender.card}猜对') - msg = Message(MessageSegment.text('恭喜') + MessageSegment.at(event.user_id) + MessageSegment.text( - f'猜对了!\n正确答案是:{role_name}')) + logger.info( + '原神猜语音', + f'➤群{event.group_id}猜语音游戏结束,答案为{role_name},由{event.sender.card}猜对', + ) + msg = Message( + MessageSegment.text('恭喜') + + MessageSegment.at(event.user_id) + + MessageSegment.text(f'猜对了!\n正确答案是:{role_name}') + ) await guess_matcher.finish(msg) @@ -118,7 +147,11 @@ async def get_character_voice(character: str, language: str = '中'): async def get_voice_list(character: str, language: str = '中'): voice_list = await GenshinVoice.filter(character=character, language=language).all() - return await draw_voice_list(voice_list) if voice_list else MessageSegment.text(f'暂无{character}的{language}语音资源,让超级用户[更新原神语音资源]吧!') + return ( + await draw_voice_list(voice_list) + if voice_list + else MessageSegment.text(f'暂无{character}的{language}语音资源,让超级用户[更新原神语音资源]吧!') + ) async def get_record(url: str) -> MessageSegment.record: diff --git a/LittlePaimon/plugins/Paimon_Abyss/__init__.py b/LittlePaimon/plugins/Paimon_Abyss/__init__.py index 337f8ce..98fbcd0 100644 --- a/LittlePaimon/plugins/Paimon_Abyss/__init__.py +++ b/LittlePaimon/plugins/Paimon_Abyss/__init__.py @@ -1,11 +1,12 @@ from nonebot import on_command -from nonebot.adapters.onebot.v11 import Message, MessageEvent, GroupMessageEvent +from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent from nonebot.params import CommandArg from nonebot.plugin import PluginMetadata from LittlePaimon.utils import logger from LittlePaimon.utils.genshin import GenshinInfoManager from LittlePaimon.utils.message import CommandPlayer + from .abyss_statistics import get_statistics from .draw_abyss import draw_abyss_card from .youchuang import draw_team @@ -15,30 +16,48 @@ __plugin_meta__ = PluginMetadata( description='原神深渊查询', usage='...', extra={ - 'author': '惜月', - 'version': '3.0', + 'author': '惜月', + 'version': '3.0', 'priority': 2, - } + }, ) -sy = on_command('sy', aliases={'深渊战报', '深渊信息'}, priority=10, block=True, state={ - 'pm_name': 'sy', - 'pm_description': '查看本期|上期的深渊战报', - 'pm_usage': 'sy(uid)(本期|上期)', - 'pm_priority': 1 -}) -abyss_stat = on_command('深渊统计', aliases={'深渊群数据', '深渊群排行'}, priority=10, block=True, state={ - 'pm_name': '深渊统计', - 'pm_description': '查看本群深渊统计,仅群可用', - 'pm_usage': '深渊统计', - 'pm_priority': 2 -}) -abyss_team = on_command('深渊配队', aliases={'配队推荐', '深渊阵容'}, priority=10, block=True, state={ - 'pm_name': '深渊配队', - 'pm_description': '查看深渊配队推荐,数据来源于游创工坊', - 'pm_usage': '深渊配队', - 'pm_priority': 3 -}) +sy = on_command( + 'sy', + aliases={'深渊战报', '深渊信息'}, + priority=10, + block=True, + state={ + 'pm_name': 'sy', + 'pm_description': '查看本期|上期的深渊战报', + 'pm_usage': 'sy(uid)(本期|上期)', + 'pm_priority': 1, + }, +) +abyss_stat = on_command( + '深渊统计', + aliases={'深渊群数据', '深渊群排行'}, + priority=10, + block=True, + state={ + 'pm_name': '深渊统计', + 'pm_description': '查看本群深渊统计,仅群可用', + 'pm_usage': '深渊统计', + 'pm_priority': 2, + }, +) +abyss_team = on_command( + '深渊配队', + aliases={'配队推荐', '深渊阵容'}, + priority=10, + block=True, + state={ + 'pm_name': '深渊配队', + 'pm_description': '查看深渊配队推荐,数据来源于游创工坊', + 'pm_usage': '深渊配队', + 'pm_priority': 3, + }, +) @sy.handle() @@ -66,9 +85,9 @@ async def _(event: MessageEvent, players=CommandPlayer(), msg: Message = Command @abyss_stat.handle() -async def _(event: GroupMessageEvent): +async def _(bot: Bot, event: GroupMessageEvent): try: - result = await get_statistics(event.group_id) + result = await get_statistics(event.group_id, bot) except Exception as e: result = f'制作深渊统计时出错:{e}' await abyss_stat.finish(result) diff --git a/LittlePaimon/plugins/Paimon_Abyss/abyss_statistics.py b/LittlePaimon/plugins/Paimon_Abyss/abyss_statistics.py index faa9a85..8847bb7 100644 --- a/LittlePaimon/plugins/Paimon_Abyss/abyss_statistics.py +++ b/LittlePaimon/plugins/Paimon_Abyss/abyss_statistics.py @@ -1,12 +1,14 @@ import datetime from collections import Counter -from typing import Dict, Any, Tuple +from typing import Any, Dict, Tuple import pytz -from nonebot import get_bot +from nonebot.adapters.onebot.v11 import Bot from LittlePaimon.database import AbyssInfo -from LittlePaimon.utils.image import PMImage, font_manager as fm, get_qq_avatar, load_image +from LittlePaimon.utils.image import PMImage +from LittlePaimon.utils.image import font_manager as fm +from LittlePaimon.utils.image import get_qq_avatar, load_image from LittlePaimon.utils.message import MessageBuild from LittlePaimon.utils.path import RESOURCE_BASE_PATH from LittlePaimon.utils.requests import aiorequests @@ -24,7 +26,9 @@ async def get_user_avatar(user_id: str, size: Tuple[int, int] = (60, 60)): async def get_group_avatar(group_id: str): try: - img = await aiorequests.get_img(f'https://p.qlogo.cn/gh/{group_id}/{group_id}/100', size=(110, 110)) + img = await aiorequests.get_img( + f'https://p.qlogo.cn/gh/{group_id}/{group_id}/100', size=(110, 110) + ) img = PMImage(img) await img.to_circle('circle') return img @@ -32,28 +36,34 @@ async def get_group_avatar(group_id: str): return PMImage(size=(110, 110), color=(255, 255, 255, 255)) -async def get_statistics(group_id: int): - if not (info_list := await AbyssInfo.all()): +async def get_statistics(group_id: int, bot: Bot): + now = datetime.datetime.now() + abyss_info_list = await AbyssInfo.filter( + total_battle__not=None, + total_star__not=None, + max_damage__not=None, + max_take_damage__not=None, + start_time__lte=now, + end_time__gte=now, + ) + if not abyss_info_list: return '本群还没有深渊战斗数据哦!' - member_list = await get_bot().get_group_member_list(group_id=group_id) + member_list = await bot.get_group_member_list(group_id=group_id) member_id_list = [str(member['user_id']) for member in member_list] - info_list = [info for info in info_list if - info.user_id in member_id_list and info.total_battle and info.total_star and info.max_damage and info.max_take_damage] - now = datetime.datetime.now().replace(tzinfo=pytz.timezone('Asia/Shanghai')) - info_list = [info for info in info_list if info.start_time <= now <= info.end_time] - if not info_list: + info_list = [info for info in abyss_info_list if info.user_id in member_id_list] + if not abyss_info_list: return '本群还没有深渊战斗数据哦!' - elif len(info_list) < 3: + elif len(abyss_info_list) < 3: return '本群深渊有效战斗数据不足3人,无法生成统计图!' - for info in info_list: + for info in abyss_info_list: if info.nickname is None: for member in member_list: if info.user_id == str(member['user_id']): info.nickname = member['card'] or member['nickname'] break data = { - '群号': str(group_id), - '群名称': (await get_bot().get_group_info(group_id=group_id))['group_name'], + '群号': str(group_id), + '群名称': (await bot.get_group_info(group_id=group_id))['group_name'], } # 数据数 info_num = len(info_list) @@ -65,36 +75,42 @@ async def get_statistics(group_id: int): average_star = round(sum(info.total_star for info in info_list) / info_num, 1) data['平均星数'] = average_star # 平均战斗次数 - average_battle_num = round(sum(info.total_battle for info in info_list) / info_num, 1) + average_battle_num = round( + sum(info.total_battle for info in info_list) / info_num, 1 + ) data['平均战斗次数'] = average_battle_num # 最高伤害角色 # max_damage = max(info_list, key=lambda x: x.max_damage.value) max_damage = sorted(info_list, key=lambda x: x.max_damage.value, reverse=True) data['最高伤害'] = [ { - '图标': info.max_damage.icon, + '图标': info.max_damage.icon, '稀有度': info.max_damage.rarity, - '等级': info.max_damage.level, - '数值': info.max_damage.value, + '等级': info.max_damage.level, + '数值': info.max_damage.value, # '命座': (await Character.filter(user_id=info.user_id, uid=info.uid, character_id=info.max_damage.character_id).first()).constellation, '用户名': info.nickname, - 'qq号': info.user_id, - 'uid': info.uid, - } for info in max_damage[:3] + 'qq号': info.user_id, + 'uid': info.uid, + } + for info in max_damage[:3] ] # 最多承伤角色 - max_take_damage = sorted(info_list, key=lambda x: x.max_take_damage.value, reverse=True) + max_take_damage = sorted( + info_list, key=lambda x: x.max_take_damage.value, reverse=True + ) data['最高承受伤害'] = [ { - '图标': info.max_take_damage.icon, + '图标': info.max_take_damage.icon, '稀有度': info.max_take_damage.rarity, - '等级': info.max_take_damage.level, - '数值': info.max_take_damage.value, + '等级': info.max_take_damage.level, + '数值': info.max_take_damage.value, # '命座': (await Character.filter(user_id=info.user_id, uid=info.uid, character_id=info.max_damage.character_id).first()).constellation, '用户名': info.nickname, - 'qq号': info.user_id, - 'uid': info.uid, - } for info in max_take_damage[:3] + 'qq号': info.user_id, + 'uid': info.uid, + } + for info in max_take_damage[:3] ] # 11、12层阵容 battle_characters_up11 = Counter() @@ -108,14 +124,18 @@ async def get_statistics(group_id: int): battle_characters_up11[f'{character.icon}-{character.rarity}'] += 1 for battles in floor11.battles_down: for character in battles.characters: - battle_characters_down11[f'{character.icon}-{character.rarity}'] += 1 + battle_characters_down11[ + f'{character.icon}-{character.rarity}' + ] += 1 if floor12 := info.floors.get(12): for battles in floor12.battles_up: for character in battles.characters: battle_characters_up12[f'{character.icon}-{character.rarity}'] += 1 for battles in floor12.battles_down: for character in battles.characters: - battle_characters_down12[f'{character.icon}-{character.rarity}'] += 1 + battle_characters_down12[ + f'{character.icon}-{character.rarity}' + ] += 1 data['11层上半'] = battle_characters_up11.most_common(4) data['11层下半'] = battle_characters_down11.most_common(4) data['12层上半'] = battle_characters_up12.most_common(4) @@ -126,57 +146,133 @@ async def get_statistics(group_id: int): async def draw_statistics_img(data: Dict[str, Any]): img = PMImage(image=RESOURCE_BASE_PATH / 'abyss' / 'statistics_bg.png') box = { - '4big': await load_image(RESOURCE_BASE_PATH / 'abyss' / '4bigbox.png'), + '4big': await load_image(RESOURCE_BASE_PATH / 'abyss' / '4bigbox.png'), '4small': await load_image(RESOURCE_BASE_PATH / 'abyss' / '4smallbox.png'), - '5big': await load_image(RESOURCE_BASE_PATH / 'abyss' / '5bigbox.png'), + '5big': await load_image(RESOURCE_BASE_PATH / 'abyss' / '5bigbox.png'), '5small': await load_image(RESOURCE_BASE_PATH / 'abyss' / '5smallbox.png'), - '4bg': await load_image(RESOURCE_BASE_PATH / 'icon' / 'star4_no_line.png', size=(95, 95)), - '5bg': await load_image(RESOURCE_BASE_PATH / 'icon' / 'star5_no_line.png', size=(95, 95)) + '4bg': await load_image( + RESOURCE_BASE_PATH / 'icon' / 'star4_no_line.png', size=(95, 95) + ), + '5bg': await load_image( + RESOURCE_BASE_PATH / 'icon' / 'star5_no_line.png', size=(95, 95) + ), } avatar = await get_group_avatar(data['群号']) await img.paste(avatar, (38, 47)) await img.text(data['群名称'], 162, 58, fm.get('hywh', 48), '#040404') await img.text(data['群号'], 165, 116, fm.get('hywh', 36), '#040404') - await img.text(f'CREATED BY LITTLEPAIMON AT {datetime.datetime.now().strftime("%m-%d %H:%M")}', - 1033, 195, fm.get('bahnschrift_regular.ttf', 30), '#8c4c2e', 'right') - await img.text(str(data['总人数']), (233, 352), 296, fm.get('bahnschrift_regular.ttf', 48), '#040404', 'center') - await img.text(str(data['平均星数']), (492, 586), 296, fm.get('bahnschrift_regular.ttf', 48), '#040404', 'center') - await img.text(str(data['平均战斗次数']), (698, 840), 296, fm.get('bahnschrift_regular.ttf', 48), '#040404', - 'center') + await img.text( + f'CREATED BY LITTLEPAIMON AT {datetime.datetime.now().strftime("%m-%d %H:%M")}', + 1033, + 195, + fm.get('bahnschrift_regular.ttf', 30), + '#8c4c2e', + 'right', + ) + await img.text( + str(data['总人数']), + (233, 352), + 296, + fm.get('bahnschrift_regular.ttf', 48), + '#040404', + 'center', + ) + await img.text( + str(data['平均星数']), + (492, 586), + 296, + fm.get('bahnschrift_regular.ttf', 48), + '#040404', + 'center', + ) + await img.text( + str(data['平均战斗次数']), + (698, 840), + 296, + fm.get('bahnschrift_regular.ttf', 48), + '#040404', + 'center', + ) # 满星人数 full_num = [data['满星人数'] / data['总人数'], 1 - data['满星人数'] / data['总人数']] now_used_width = 36 if full_num[0] > 0.03: - await img.draw_rectangle((now_used_width, 402, now_used_width + int(1007 * full_num[0]), 449), '#b6d6f2') - await img.text(str(data['满星人数']), now_used_width + 18, 413, fm.get('bahnschrift_regular.ttf', 30), - '#3d6e99') + await img.draw_rectangle( + (now_used_width, 402, now_used_width + int(1007 * full_num[0]), 449), + '#b6d6f2', + ) + await img.text( + str(data['满星人数']), + now_used_width + 18, + 413, + fm.get('bahnschrift_regular.ttf', 30), + '#3d6e99', + ) now_used_width += int(1007 * full_num[0]) if full_num[1] > 0.03: - await img.draw_rectangle((now_used_width, 402, now_used_width + int(1007 * full_num[1]), 449), '#c8b6f2') - await img.text(str(data['总人数'] - data['满星人数']), now_used_width + 18, 413, - fm.get('bahnschrift_regular.ttf', 30), '#593d99') + await img.draw_rectangle( + (now_used_width, 402, now_used_width + int(1007 * full_num[1]), 449), + '#c8b6f2', + ) + await img.text( + str(data['总人数'] - data['满星人数']), + now_used_width + 18, + 413, + fm.get('bahnschrift_regular.ttf', 30), + '#593d99', + ) # 最高伤害 await img.paste(box[f'{data["最高伤害"][0]["稀有度"]}big'], (39, 512)) await img.paste(box[f'{data["最高伤害"][1]["稀有度"]}small'], (39, 664)) await img.paste(box[f'{data["最高伤害"][2]["稀有度"]}small'], (296, 664)) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][0]["图标"]}.png', size=(124, 124)), - (44, 525)) + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][0]["图标"]}.png', + size=(124, 124), + ), + (44, 525), + ) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][1]["图标"]}.png', size=(82, 82)), - (45, 673)) + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][1]["图标"]}.png', + size=(82, 82), + ), + (45, 673), + ) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][2]["图标"]}.png', size=(82, 82)), - (300, 673)) + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{data["最高伤害"][2]["图标"]}.png', + size=(82, 82), + ), + (300, 673), + ) await img.paste(await get_user_avatar(data['最高伤害'][0]['qq号']), (112, 588)) await img.paste(await get_user_avatar(data['最高伤害'][1]['qq号'], (42, 42)), (87, 713)) await img.paste(await get_user_avatar(data['最高伤害'][2]['qq号'], (42, 42)), (344, 713)) await img.text('最强一击', 180, 515, fm.get('hywh', 30), '#040404') await img.text('第二名', 139, 668, fm.get('hywh', 22), '#040404') await img.text('第三名', 397, 668, fm.get('hywh', 22), '#040404') - await img.text(str(data['最高伤害'][0]['数值']), 180, 547, fm.get('bahnschrift_regular.ttf', 68), '#040404') - await img.text(str(data['最高伤害'][1]['数值']), 137, 693, fm.get('bahnschrift_regular.ttf', 38), '#040404') - await img.text(str(data['最高伤害'][2]['数值']), 395, 693, fm.get('bahnschrift_regular.ttf', 38), '#040404') + await img.text( + str(data['最高伤害'][0]['数值']), + 180, + 547, + fm.get('bahnschrift_regular.ttf', 68), + '#040404', + ) + await img.text( + str(data['最高伤害'][1]['数值']), + 137, + 693, + fm.get('bahnschrift_regular.ttf', 38), + '#040404', + ) + await img.text( + str(data['最高伤害'][2]['数值']), + 395, + 693, + fm.get('bahnschrift_regular.ttf', 38), + '#040404', + ) await img.text(data['最高伤害'][0]['用户名'][:11], 180, 610, fm.get('hywh', 30), '#040404') await img.text(data['最高伤害'][1]['用户名'][:6], 137, 726, fm.get('hywh', 22), '#040404') await img.text(data['最高伤害'][2]['用户名'][:6], 395, 726, fm.get('hywh', 22), '#040404') @@ -186,66 +282,158 @@ async def draw_statistics_img(data: Dict[str, Any]): await img.paste(box[f'{data["最高承受伤害"][1]["稀有度"]}small'], (552, 664)) await img.paste(box[f'{data["最高承受伤害"][2]["稀有度"]}small'], (808, 664)) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][0]["图标"]}.png', size=(124, 124)), - (560, 525)) + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][0]["图标"]}.png', + size=(124, 124), + ), + (560, 525), + ) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][1]["图标"]}.png', size=(82, 82)), - (557, 673)) + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][1]["图标"]}.png', + size=(82, 82), + ), + (557, 673), + ) await img.paste( - await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][2]["图标"]}.png', size=(82, 82)), - (815, 673)) + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{data["最高承受伤害"][2]["图标"]}.png', + size=(82, 82), + ), + (815, 673), + ) await img.paste(await get_user_avatar(data['最高承受伤害'][0]['qq号']), (623, 588)) - await img.paste(await get_user_avatar(data['最高承受伤害'][1]['qq号'], (42, 42)), (600, 713)) - await img.paste(await get_user_avatar(data['最高承受伤害'][2]['qq号'], (42, 42)), (857, 713)) + await img.paste( + await get_user_avatar(data['最高承受伤害'][1]['qq号'], (42, 42)), (600, 713) + ) + await img.paste( + await get_user_avatar(data['最高承受伤害'][2]['qq号'], (42, 42)), (857, 713) + ) await img.text('最多承伤', 693, 515, fm.get('hywh', 30), '#040404') await img.text('第二名', 652, 668, fm.get('hywh', 22), '#040404') await img.text('第三名', 910, 668, fm.get('hywh', 22), '#040404') - await img.text(str(data['最高承受伤害'][0]['数值']), 693, 547, fm.get('bahnschrift_regular.ttf', 68), '#040404') - await img.text(str(data['最高承受伤害'][1]['数值']), 650, 693, fm.get('bahnschrift_regular.ttf', 38), '#040404') - await img.text(str(data['最高承受伤害'][2]['数值']), 908, 693, fm.get('bahnschrift_regular.ttf', 38), '#040404') - await img.text(data['最高承受伤害'][0]['用户名'][:11], 693, 610, fm.get('hywh', 30), '#040404') - await img.text(data['最高承受伤害'][1]['用户名'][:6], 650, 726, fm.get('hywh', 22), '#040404') - await img.text(data['最高承受伤害'][2]['用户名'][:6], 908, 726, fm.get('hywh', 22), '#040404') + await img.text( + str(data['最高承受伤害'][0]['数值']), + 693, + 547, + fm.get('bahnschrift_regular.ttf', 68), + '#040404', + ) + await img.text( + str(data['最高承受伤害'][1]['数值']), + 650, + 693, + fm.get('bahnschrift_regular.ttf', 38), + '#040404', + ) + await img.text( + str(data['最高承受伤害'][2]['数值']), + 908, + 693, + fm.get('bahnschrift_regular.ttf', 38), + '#040404', + ) + await img.text( + data['最高承受伤害'][0]['用户名'][:11], 693, 610, fm.get('hywh', 30), '#040404' + ) + await img.text( + data['最高承受伤害'][1]['用户名'][:6], 650, 726, fm.get('hywh', 22), '#040404' + ) + await img.text( + data['最高承受伤害'][2]['用户名'][:6], 908, 726, fm.get('hywh', 22), '#040404' + ) tag = await load_image(RESOURCE_BASE_PATH / 'general' / 'tag.png') # 角色出场率 for i in range(4): try: - icon, rarity, count = data['11层上半'][i][0].split('-')[0], data['11层上半'][i][0].split('-')[1], \ - data['11层上半'][i][1] + icon, rarity, count = ( + data['11层上半'][i][0].split('-')[0], + data['11层上半'][i][0].split('-')[1], + data['11层上半'][i][1], + ) await img.paste(box[f'{rarity}bg'], (182 + i * 101, 867)) - await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), - (182 + i * 101, 867)) + await img.paste( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95) + ), + (182 + i * 101, 867), + ) await img.paste(tag, (236 + i * 101, 942)) - await img.text(str(count), (236 + i * 101, 277 + i * 101), 943, fm.get('bahnschrift_regular.ttf', 19), - 'white', 'center') + await img.text( + str(count), + (236 + i * 101, 277 + i * 101), + 943, + fm.get('bahnschrift_regular.ttf', 19), + 'white', + 'center', + ) - icon, rarity, count = data['11层下半'][i][0].split('-')[0], data['11层下半'][i][0].split('-')[1], \ - data['11层下半'][i][1] + icon, rarity, count = ( + data['11层下半'][i][0].split('-')[0], + data['11层下半'][i][0].split('-')[1], + data['11层下半'][i][1], + ) await img.paste(box[f'{rarity}bg'], (642 + i * 101, 867)) - await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), - (642 + i * 101, 867)) + await img.paste( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95) + ), + (642 + i * 101, 867), + ) await img.paste(tag, (696 + i * 101, 942)) - await img.text(str(count), (696 + i * 101, 737 + i * 101), 943, fm.get('bahnschrift_regular.ttf', 19), - 'white', 'center') + await img.text( + str(count), + (696 + i * 101, 737 + i * 101), + 943, + fm.get('bahnschrift_regular.ttf', 19), + 'white', + 'center', + ) - icon, rarity, count = data['12层上半'][i][0].split('-')[0], data['12层上半'][i][0].split('-')[1], \ - data['12层上半'][i][1] + icon, rarity, count = ( + data['12层上半'][i][0].split('-')[0], + data['12层上半'][i][0].split('-')[1], + data['12层上半'][i][1], + ) await img.paste(box[f'{rarity}bg'], (182 + i * 101, 983)) - await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), - (182 + i * 101, 983)) + await img.paste( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95) + ), + (182 + i * 101, 983), + ) await img.paste(tag, (236 + i * 101, 1058)) - await img.text(str(count), (236 + i * 101, 278 + i * 101), 1059, fm.get('bahnschrift_regular.ttf', 19), - 'white', 'center') + await img.text( + str(count), + (236 + i * 101, 278 + i * 101), + 1059, + fm.get('bahnschrift_regular.ttf', 19), + 'white', + 'center', + ) - icon, rarity, count = data['12层下半'][i][0].split('-')[0], data['12层下半'][i][0].split('-')[1], \ - data['12层下半'][i][1] + icon, rarity, count = ( + data['12层下半'][i][0].split('-')[0], + data['12层下半'][i][0].split('-')[1], + data['12层下半'][i][1], + ) await img.paste(box[f'{rarity}bg'], (642 + i * 101, 983)) - await img.paste(await load_image(RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95)), - (642 + i * 101, 983)) + await img.paste( + await load_image( + RESOURCE_BASE_PATH / 'avatar' / f'{icon}.png', size=(95, 95) + ), + (642 + i * 101, 983), + ) await img.paste(tag, (696 + i * 101, 1058)) - await img.text(str(count), (696 + i * 101, 737 + i * 101), 1059, fm.get('bahnschrift_regular.ttf', 19), - 'white', 'center') + await img.text( + str(count), + (696 + i * 101, 737 + i * 101), + 1059, + fm.get('bahnschrift_regular.ttf', 19), + 'white', + 'center', + ) i += 1 except IndexError: pass diff --git a/LittlePaimon/plugins/bot_manager/__init__.py b/LittlePaimon/plugins/bot_manager/__init__.py index 71589c5..900f439 100644 --- a/LittlePaimon/plugins/bot_manager/__init__.py +++ b/LittlePaimon/plugins/bot_manager/__init__.py @@ -1,26 +1,27 @@ -import os import asyncio import contextlib +import os import random import sys from pathlib import Path -from nonebot import on_command, get_bot, get_app + +from nonebot import get_app, get_bot, on_command +from nonebot.adapters.onebot.v11 import ( + ActionFailed, + Bot, + GroupMessageEvent, + Message, + MessageEvent, +) +from nonebot.params import Arg, ArgPlainText, CommandArg from nonebot.permission import SUPERUSER from nonebot.plugin import PluginMetadata from nonebot.rule import to_me -from nonebot.params import CommandArg, ArgPlainText, Arg from nonebot.typing import T_State -from nonebot.adapters.onebot.v11 import ( - Bot, - Message, - MessageEvent, - GroupMessageEvent, - ActionFailed, -) from LittlePaimon.config import config -from LittlePaimon.utils import NICKNAME, DRIVER, __version__ -from LittlePaimon.utils.files import save_json, load_json +from LittlePaimon.utils import DRIVER, NICKNAME, __version__ +from LittlePaimon.utils.files import load_json, save_json from LittlePaimon.utils.update import check_update, update __plugin_meta__ = PluginMetadata( @@ -209,11 +210,11 @@ async def _( @DRIVER.on_bot_connect -async def _(): +async def _(bot: Bot): if not (reboot_file := (Path() / 'rebooting.json')).exists(): return - bot = get_bot() reboot_data = load_json(reboot_file) + reboot_file.unlink() if reboot_data['session_type'] == 'group': await bot.send_group_msg( group_id=reboot_data['session_id'], @@ -230,4 +231,3 @@ async def _(): group_id=int(group_id), user_id=int(bot.self_id), card=card_info ) await asyncio.sleep(0.25) - reboot_file.unlink()