PamGram/plugins/starrail/avatar_list.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

155 lines
5.7 KiB
Python
Raw Normal View History

2023-04-29 16:15:21 +00:00
from typing import List, Optional, TYPE_CHECKING
from pydantic import BaseModel
from simnet.models.starrail.chronicle.characters import StarRailDetailCharacter
from telegram.constants import ChatAction
2023-04-29 16:15:21 +00:00
from telegram.ext import filters
from core.dependence.assets import AssetsService, AssetsCouldNotFound
from core.plugin import Plugin, handler
from core.services.cookies import CookiesService
from core.services.template.models import FileType
from core.services.template.services import TemplateService
from core.services.wiki.services import WikiService
from plugins.tools.genshin import GenshinHelper
2023-04-29 16:15:21 +00:00
from utils.log import logger
from utils.uid import mask_number
2023-04-29 16:15:21 +00:00
if TYPE_CHECKING:
from simnet import StarRailClient
2023-04-29 16:15:21 +00:00
from telegram.ext import ContextTypes
from telegram import Update
class EquipmentData(BaseModel):
id: int
name: str
level: int
eidolon: int
rarity: int
2023-04-29 16:15:21 +00:00
icon: str
class AvatarData(BaseModel):
id: int
name: str
level: int
eidolon: int
rarity: int
icon: str = ""
equipment: Optional[EquipmentData] = None
class AvatarListPlugin(Plugin):
"""练度统计"""
def __init__(
self,
cookies_service: CookiesService = None,
assets_service: AssetsService = None,
template_service: TemplateService = None,
wiki_service: WikiService = None,
2023-04-29 16:15:21 +00:00
helper: GenshinHelper = None,
) -> None:
self.cookies_service = cookies_service
self.assets_service = assets_service
self.template_service = template_service
self.wiki_service = wiki_service
2023-04-29 16:15:21 +00:00
self.helper = helper
@staticmethod
async def get_avatars_data(client: "StarRailClient") -> List[StarRailDetailCharacter]:
2023-04-29 16:15:21 +00:00
task_results = (await client.get_starrail_characters()).avatar_list
return sorted(
list(filter(lambda x: x, task_results)),
key=lambda x: (
x.level,
x.rarity,
sum([i.is_unlocked for i in x.ranks]),
),
reverse=True,
)
def get_light_cone_star(self, name: str) -> int:
light_cone = self.wiki_service.light_cone.get_by_name(name)
2023-08-29 06:50:37 +00:00
return light_cone.rank if light_cone else 3
2023-04-29 16:15:21 +00:00
async def get_final_data(self, characters: List[StarRailDetailCharacter]) -> List[AvatarData]:
data = []
for character in characters:
try:
2023-05-04 14:28:13 +00:00
equip = (
EquipmentData(
id=character.equip.id,
name=character.equip.name,
level=character.equip.level,
eidolon=character.equip.rank,
rarity=self.get_light_cone_star(character.equip.name),
2023-05-04 14:28:13 +00:00
icon=self.assets_service.light_cone.icon(character.equip.id, character.equip.name).as_uri(),
)
if character.equip
else None
)
2023-04-29 16:15:21 +00:00
avatar = AvatarData(
id=character.id,
name=character.name,
level=character.level,
eidolon=sum([i.is_unlocked for i in character.ranks]),
rarity=character.rarity,
icon=self.assets_service.avatar.icon(character.id, character.name).as_uri(),
equipment=equip,
)
data.append(avatar)
except AssetsCouldNotFound as e:
logger.warning("未找到角色 %s[%s] 的资源: %s", character.name, character.id, e)
return data
@handler.command("avatars", block=False)
2023-04-29 16:15:21 +00:00
@handler.message(filters.Regex(r"^(全部)?练度统计$"), block=False)
async def avatar_list(self, update: "Update", _: "ContextTypes.DEFAULT_TYPE"):
2023-04-29 16:15:21 +00:00
user = update.effective_user
message = update.effective_message
2023-05-04 14:28:13 +00:00
all_avatars = "全部" in message.text or "all" in message.text # 是否发送全部角色
2023-04-29 16:15:21 +00:00
logger.info("用户 %s[%s] [bold]练度统计[/bold]: all=%s", user.full_name, user.id, all_avatars, extra={"markup": True})
await message.reply_chat_action(ChatAction.TYPING)
async with self.helper.genshin(user.id) as client:
2023-04-29 16:15:21 +00:00
characters: List[StarRailDetailCharacter] = await self.get_avatars_data(client)
record_card = await client.get_record_card()
2023-04-29 16:15:21 +00:00
nickname = record_card.nickname
has_more = (not all_avatars) and len(characters) > 20
if has_more:
characters = characters[:20]
avatar_datas = await self.get_final_data(characters)
render_data = {
"uid": mask_number(client.player_id), # 玩家uid
2023-04-29 16:15:21 +00:00
"nickname": nickname, # 玩家昵称
"avatar_datas": avatar_datas, # 角色数据
"has_more": has_more, # 是否显示了全部角色
}
as_document = all_avatars and len(characters) > 20
await message.reply_chat_action(ChatAction.UPLOAD_DOCUMENT if as_document else ChatAction.UPLOAD_PHOTO)
image = await self.template_service.render(
"starrail/avatar_list/main.html",
render_data,
viewport={"width": 1040, "height": 500},
full_page=True,
query_selector=".container",
file_type=FileType.DOCUMENT if as_document else FileType.PHOTO,
ttl=30 * 24 * 60 * 60,
)
if as_document:
await image.reply_document(message, filename="练度统计.png")
else:
await image.reply_photo(message)
logger.info(
"用户 %s[%s] [bold]练度统计[/bold]发送%s成功",
user.full_name,
user.id,
"文件" if all_avatars else "图片",
extra={"markup": True},
)