diff --git a/LittlePaimon/plugins/Genshin_Voice/resources.py b/LittlePaimon/plugins/Genshin_Voice/resources.py index af589f3..e6588ac 100644 --- a/LittlePaimon/plugins/Genshin_Voice/resources.py +++ b/LittlePaimon/plugins/Genshin_Voice/resources.py @@ -1,6 +1,6 @@ import asyncio import contextlib -from typing import Union, Dict +from typing import Dict, Optional from lxml import etree @@ -9,53 +9,49 @@ from LittlePaimon.utils import aiorequests from LittlePaimon.utils import logger -async def get_character_list() -> Union[Dict[str, str], str]: +async def get_character_list() -> Optional[Dict[str, int]]: """ 从米游社观测枢获取人物链接列表 :return: """ try: - resp = await aiorequests.get(url='https://bbs.mihoyo.com/ys/obc/channel/map/189/25?bbs_presentation_style=no_header') - - html = etree.HTML(resp.text) - character_dict = {} - character_list = html.xpath('//*[@id="__layout"]/div/div[2]/div[2]/div/div[1]/div[2]/ul/li/div/ul/li[1]/div/div/a[@class="collection-avatar__item"]') - - for character in character_list: - with contextlib.suppress(IndexError): - character_name = character.xpath('./div/text()')[0] - character_url = character.xpath('./@href')[0] - character_dict[character_name] = character_url - return character_dict - except Exception as e: - return str(e) + resp = await aiorequests.get(url='https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/home/content/list?app_sn=ys_obc&channel_id=189') + data = resp.json() + if data['retcode'] != 0: + return None + data = data['data']['list'][0]['children'][0]['list'] + return {c['title']: c['content_id'] for c in data} + except Exception: + return None -async def get_voice(character_name: str, character_url: str): +async def get_voice(character_name: str, content_id: int): """ 获取单个角色的四国语音 :param character_name: 角色名称 - :param character_url: 角色链接 + :param content_id: 角色id """ try: - resp = await aiorequests.get(url=f'https://bbs.mihoyo.com{character_url}') - html = etree.HTML(resp.text) + resp = await aiorequests.get(url=f'https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/content/info?app_sn=ys_obc&content_id={content_id}', + headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'}) + data = resp.json() + if data['retcode'] != 0: + return None + data = data['data']['content']['contents'][2] + html = etree.HTML(data['text']) lang = ['中', '英', '日', '韩'] for i in range(1, 5): - voice_list = html.xpath(f'////*[@class="obc-tmpl__part obc-tmpl-character obc-tmpl__part--voiceTab obc-tmpl__part--align-banner"]/ul[2]/li[{i}]/table[2]/tbody/tr') - + voice_list = html.xpath(f'//*[@class="obc-tmpl__part obc-tmpl-character obc-tmpl__part--voiceTab obc-tmpl__part--align-banner"]/ul[2]/li[{i}]/table[2]/tbody/tr') for voice in voice_list: with contextlib.suppress(IndexError): voice_name = voice.xpath('./td/text()')[0] voice_url = voice.xpath('./td/div/div/audio/source/@src')[0] voice_content = voice.xpath('./td/div/span/text()')[0].strip() await GenshinVoice.update_or_create(character=character_name, voice_name=voice_name, language=lang[i - 1], defaults={'voice_content': voice_content, 'voice_url': voice_url}) - if voice_list: logger.info('原神猜语音', f'➤➤角色{character_name}{lang[i - 1]}文语音获取成功') else: logger.info('原神猜语音', f'➤➤角色{character_name}{lang[i - 1]}文语音获取失败') - except Exception as e: logger.warning('原神猜语音', f'➤➤获取{character_name}的语音资源时出错:', str(e)) @@ -63,11 +59,11 @@ async def get_voice(character_name: str, character_url: str): async def update_voice_resources(): logger.info('原神猜语音', '开始更新原神语音资源') character_list = await get_character_list() - if isinstance(character_list, str): - logger.warning('原神猜语音', '➤更新语音资源时出错:', character_list) - return f'更新语音资源时出错:{character_list}' - for character_name, character_url in character_list.items(): - await get_voice(character_name, character_url) + if character_list is None: + logger.warning('原神猜语音', '➤更新语音资源出错') + return '更新语音资源出错' + for name, content_id in character_list.items(): + await get_voice(name, content_id) await asyncio.sleep(1) voice_num = await GenshinVoice.all().count() return f'更新语音资源成功,当前数据库中共有{voice_num}条语音资源' diff --git a/LittlePaimon/plugins/Paimon_Info/__init__.py b/LittlePaimon/plugins/Paimon_Info/__init__.py index a412cf6..93ac23d 100644 --- a/LittlePaimon/plugins/Paimon_Info/__init__.py +++ b/LittlePaimon/plugins/Paimon_Info/__init__.py @@ -221,11 +221,14 @@ async def _(event: MessageEvent, uid=CommandUID(), msg: str = Arg('msg')): await update_info.finish(f'UID{uid}正在更新信息中,请勿重复发送指令') else: running_udi.append(f'{event.user_id}-{uid}') - include_talent = any(i in msg for i in ['全部', '技能', '天赋', 'talent', 'all']) - await update_info.send('开始更新原神信息,请稍后...') - logger.info('原神信息', '➤开始更新', {'用户': event.user_id, 'UID': uid}) - freq_limiter.start(f'udi{uid}', 180) - gim = GenshinInfoManager(str(event.user_id), uid) - result = await gim.update_all(include_talent) + try: + include_talent = any(i in msg for i in ['全部', '技能', '天赋', 'talent', 'all']) + await update_info.send('开始更新原神信息,请稍后...') + logger.info('原神信息', '➤开始更新', {'用户': event.user_id, 'UID': uid}) + freq_limiter.start(f'udi{uid}', 180) + gim = GenshinInfoManager(str(event.user_id), uid) + result = await gim.update_all(include_talent) + except Exception as e: + result = f'更新失败,错误信息:{e}' running_udi.remove(f'{event.user_id}-{uid}') await update_info.finish(f'UID{uid}:\n {result}', at_sender=True) diff --git a/LittlePaimon/plugins/Paimon_Info/draw_player_card.py b/LittlePaimon/plugins/Paimon_Info/draw_player_card.py index 046c26e..30a96c0 100644 --- a/LittlePaimon/plugins/Paimon_Info/draw_player_card.py +++ b/LittlePaimon/plugins/Paimon_Info/draw_player_card.py @@ -1,5 +1,5 @@ import asyncio -from typing import List, Tuple +from typing import List, Tuple, Optional from LittlePaimon.config import RESOURCE_BASE_PATH from LittlePaimon.database.models import PlayerInfo, Character, PlayerWorldInfo, Weapon, Player @@ -40,7 +40,9 @@ async def draw_weapon_icon(weapon: Weapon, size: Tuple[int, int] = (65, 65)) -> return weapon_bg -async def draw_character_card(info: Character) -> PMImage: +async def draw_character_card(info: Character) -> Optional[PMImage]: + if info is None: + return None # 头像 avatar = PMImage(await load_image(THUMB / f'{info.name}.png')) await avatar.to_circle('circle') diff --git a/LittlePaimon/utils/image.py b/LittlePaimon/utils/image.py index 310ee7a..bc92bce 100644 --- a/LittlePaimon/utils/image.py +++ b/LittlePaimon/utils/image.py @@ -158,6 +158,8 @@ class PMImage: :param pos: 位置 :param alpha: 是否透明 """ + if image is None: + return if isinstance(image, PMImage): image = image.image if alpha: