️ 提升 avatars-list 的性能

并发获取角色详情

Signed-off-by: Karako <karakohear@gmail.com>
This commit is contained in:
Karako 2022-10-21 23:52:59 +08:00
parent 7c34167ff4
commit e524a1b8bb
No known key found for this signature in database
GPG Key ID: 5920831B0095D4A0

View File

@ -1,5 +1,6 @@
"""练度统计""" """练度统计"""
from typing import Iterable, List, Optional, Sequence import asyncio
from typing import Iterable, List, Optional, Sequence, Tuple
from arkowrapper import ArkoWrapper from arkowrapper import ArkoWrapper
from enkanetwork import Assets as EnkaAssets, EnkaNetworkAPI from enkanetwork import Assets as EnkaAssets, EnkaNetworkAPI
@ -61,52 +62,69 @@ class AvatarListPlugin(Plugin, BasePlugin):
else: else:
await message.reply_text("此功能需要绑定<code>cookie</code>后使用,请先私聊派蒙进行绑定", parse_mode=ParseMode.HTML) await message.reply_text("此功能需要绑定<code>cookie</code>后使用,请先私聊派蒙进行绑定", parse_mode=ParseMode.HTML)
async def get_avatars_data(self, characters: Sequence[Character], client: Client, max_length: int = None): async def get_avatar_data(self, character: Character, client: Client) -> Optional["AvatarData"]:
avatar_datas: List[AvatarData] = [] detail = None
for num, character in enumerate(characters): for _ in range(5):
if num == max_length: # 若已经有 max_length 个角色
break
try: try:
detail = await client.get_character_details(character) detail = await client.get_character_details(character)
except Exception as e: # pylint: disable=W0703 except Exception as e: # pylint: disable=W0703
if isinstance(e, GenshinException) and "Too Many Requests" in e.msg:
await asyncio.sleep(0.2)
continue
if character.name != "旅行者": if character.name != "旅行者":
raise e raise e
logger.debug(f"解析旅行者数据时遇到了错误:{e}") logger.debug(f"解析旅行者数据时遇到了错误:{e}")
continue return None
if character.id == 10000005: # 针对男草主 if detail is None:
talents = [] logger.warning(f"解析[bold]{character.name}[/]的数据时遇到了错误Too Many Requests", extra={"markup": True})
for talent in detail.talents: return None
if "普通攻击" in talent.name: if character.id == 10000005: # 针对男草主
talent.Config.allow_mutation = True talents = []
# noinspection Pydantic for talent in detail.talents:
talent.group_id = 1131 if "普通攻击" in talent.name:
if talent.type in ["attack", "skill", "burst"]: talent.Config.allow_mutation = True
talents.append(talent) # noinspection Pydantic
else: talent.group_id = 1131
talents = [t for t in detail.talents if t.type in ["attack", "skill", "burst"]] if talent.type in ["attack", "skill", "burst"]:
buffed_talents = [] talents.append(talent)
for constellation in filter(lambda x: x.pos in [3, 5], character.constellations[: character.constellation]): else:
if result := list( talents = [t for t in detail.talents if t.type in ["attack", "skill", "burst"]]
filter(lambda x: all([x.name in constellation.effect]), talents) # pylint: disable=W0640 buffed_talents = []
): for constellation in filter(lambda x: x.pos in [3, 5], character.constellations[: character.constellation]):
buffed_talents.append(result[0].type) if result := list(
avatar_datas.append( filter(lambda x: all([x.name in constellation.effect]), talents) # pylint: disable=W0640
AvatarData( ):
avatar=character, buffed_talents.append(result[0].type)
detail=detail, return AvatarData(
icon=(await self.assets_service.avatar(character.id).side()).as_uri(), avatar=character,
weapon=( detail=detail,
await self.assets_service.weapon(character.weapon.id).__getattr__( icon=(await self.assets_service.avatar(character.id).side()).as_uri(),
"icon" if character.weapon.ascension < 2 else "awaken" weapon=(
)() await self.assets_service.weapon(character.weapon.id).__getattr__(
).as_uri(), "icon" if character.weapon.ascension < 2 else "awaken"
skills=[ )()
SkillData(skill=s, buffed=s.type in buffed_talents) ).as_uri(),
for s in sorted(talents, key=lambda x: ["attack", "skill", "burst"].index(x.type)) skills=[
], SkillData(skill=s, buffed=s.type in buffed_talents)
) for s in sorted(talents, key=lambda x: ["attack", "skill", "burst"].index(x.type))
) ],
return avatar_datas )
async def get_avatars_data(
self, characters: Sequence[Character], client: Client, max_length: int = None
) -> List["AvatarData"]:
task_result: List[Tuple[int, AvatarData]] = []
async def _task(c, n):
if (result := await self.get_avatar_data(c, client)) is not None:
task_result.append((n, result))
task_list = []
for num, character in enumerate(characters[:max_length]):
task_list.append(asyncio.create_task(_task(character, num)))
await asyncio.gather(*task_list)
return list(map(lambda x: x[1], sorted(task_result, key=lambda x: x[0])))
async def get_final_data(self, client: Client, characters: Sequence[Character], update: Update): async def get_final_data(self, client: Client, characters: Sequence[Character], update: Update):
try: try: