mirror of
https://github.com/PaiGramTeam/PaiGram.git
synced 2024-11-21 22:58:05 +00:00
⚡️ 为抽卡分析添加缓存
This commit is contained in:
parent
ccd1eaab8d
commit
b1c6e7456f
@ -29,16 +29,15 @@ from utils.typedefs import StrOrInt, StrOrURL
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from multiprocessing.synchronize import RLock
|
||||
ICON_TYPE = Union[
|
||||
Callable[[bool], Awaitable[Optional[Path]]],
|
||||
Callable[..., Awaitable[Optional[Path]]]
|
||||
]
|
||||
ICON_TYPE = Union[Callable[[bool], Awaitable[Optional[Path]]], Callable[..., Awaitable[Optional[Path]]]]
|
||||
NAME_MAP_TYPE = Dict[str, StrOrURL]
|
||||
|
||||
ASSETS_PATH = PROJECT_ROOT.joinpath('resources/assets')
|
||||
ASSETS_PATH = PROJECT_ROOT.joinpath("resources/assets")
|
||||
ASSETS_PATH.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
DATA_MAP = {'avatar': AVATAR_DATA, 'weapon': WEAPON_DATA, 'material': MATERIAL_DATA}
|
||||
DATA_MAP = {"avatar": AVATAR_DATA, "weapon": WEAPON_DATA, "material": MATERIAL_DATA}
|
||||
|
||||
DEFAULT_EnkaAssets = EnkaAssets(lang="chs")
|
||||
|
||||
|
||||
class AssetsServiceError(Exception):
|
||||
@ -50,7 +49,7 @@ class AssetsCouldNotFound(AssetsServiceError):
|
||||
|
||||
|
||||
class _AssetsService(ABC):
|
||||
_lock: ClassVar['RLock'] = Lock()
|
||||
_lock: ClassVar["RLock"] = Lock()
|
||||
_dir: ClassVar[Path]
|
||||
icon_types: ClassVar[list[str]]
|
||||
|
||||
@ -70,7 +69,7 @@ class _AssetsService(ABC):
|
||||
@cached_property
|
||||
def honey_id(self) -> str:
|
||||
"""当前资源在 Honey Impact 所对应的 ID"""
|
||||
return HONEY_DATA[self.type].get(str(self.id), [''])[0]
|
||||
return HONEY_DATA[self.type].get(str(self.id), [""])[0]
|
||||
|
||||
@property
|
||||
def path(self) -> Path:
|
||||
@ -98,26 +97,20 @@ class _AssetsService(ABC):
|
||||
def __init_subclass__(cls, **kwargs) -> None:
|
||||
"""初始化一些类变量"""
|
||||
from itertools import chain
|
||||
|
||||
cls.icon_types = [ # 支持的图标类型
|
||||
k
|
||||
for k, v in
|
||||
chain(
|
||||
cls.__annotations__.items(),
|
||||
*map(
|
||||
lambda x: x.__annotations__.items(),
|
||||
cls.__bases__
|
||||
)
|
||||
)
|
||||
if v in [ICON_TYPE, 'ICON_TYPE']
|
||||
for k, v in chain(cls.__annotations__.items(), *map(lambda x: x.__annotations__.items(), cls.__bases__))
|
||||
if v in [ICON_TYPE, "ICON_TYPE"]
|
||||
]
|
||||
cls.type = cls.__name__.lstrip('_').split('Assets')[0].lower() # 当前 assert 的类型
|
||||
cls.type = cls.__name__.lstrip("_").split("Assets")[0].lower() # 当前 assert 的类型
|
||||
cls._dir = ASSETS_PATH.joinpath(cls.type) # 图标保存的文件夹
|
||||
cls._dir.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
async def _download(self, url: StrOrURL, path: Path, retry: int = 5) -> Path | None:
|
||||
"""从 url 下载图标至 path"""
|
||||
logger.debug(f"正在从 {url} 下载图标至 {path}")
|
||||
headers = {'user-agent': 'TGPaimonBot/3.0'} if URL(url).host == 'enka.network' else None
|
||||
headers = {"user-agent": "TGPaimonBot/3.0"} if URL(url).host == "enka.network" else None
|
||||
for time in range(retry):
|
||||
try:
|
||||
response = await self.client.get(url, follow_redirects=False, headers=headers)
|
||||
@ -131,7 +124,7 @@ class _AssetsService(ABC):
|
||||
continue
|
||||
if response.status_code != 200: # 判定页面是否正常
|
||||
return None
|
||||
async with async_open(path, 'wb') as file:
|
||||
async with async_open(path, "wb") as file:
|
||||
await file.write(response.content) # 保存图标
|
||||
return path.resolve()
|
||||
|
||||
@ -159,7 +152,7 @@ class _AssetsService(ABC):
|
||||
if overwrite and path is not None and path.exists():
|
||||
await async_remove(path)
|
||||
# 依次从使用当前 assets class 中的爬虫下载图标,顺序为爬虫名的字母顺序
|
||||
for func in map(lambda x: getattr(self, x), sorted(filter(lambda x: x.startswith('_get_from_'), dir(self)))):
|
||||
for func in map(lambda x: getattr(self, x), sorted(filter(lambda x: x.startswith("_get_from_"), dir(self)))):
|
||||
if (path := await func(item)) is not None:
|
||||
return path
|
||||
|
||||
@ -200,26 +193,26 @@ class _AvatarAssets(_AssetsService):
|
||||
def game_name(self) -> str:
|
||||
icon = "UI_AvatarIcon_"
|
||||
if (avatar := AVATAR_DATA.get(str(self.id), None)) is not None:
|
||||
icon = avatar['icon']
|
||||
icon = avatar["icon"]
|
||||
else:
|
||||
for aid, avatar in AVATAR_DATA.items():
|
||||
if aid.startswith(str(self.id)):
|
||||
icon = avatar['icon']
|
||||
icon = avatar["icon"]
|
||||
return re.findall(r"UI_AvatarIcon_(.*)", icon)[0]
|
||||
|
||||
@cached_property
|
||||
def honey_id(self) -> str:
|
||||
return HONEY_DATA['avatar'].get(str(self.id), '')[0]
|
||||
return HONEY_DATA["avatar"].get(str(self.id), "")[0]
|
||||
|
||||
@cached_property
|
||||
def enka(self) -> Optional[EnkaCharacterAsset]:
|
||||
api = getattr(self, '_enka_api', None)
|
||||
cid = getattr(self, 'id', None)
|
||||
api = getattr(self, "_enka_api", None)
|
||||
cid = getattr(self, "id", None)
|
||||
return None if api is None or cid is None else api.character(cid)
|
||||
|
||||
def __init__(self, client: Optional[AsyncClient] = None, enka: Optional[EnkaAssets] = None):
|
||||
super().__init__(client)
|
||||
self._enka_api = enka or EnkaAssets(lang='chs')
|
||||
self._enka_api = enka or DEFAULT_EnkaAssets
|
||||
|
||||
def __call__(self, target: StrOrInt) -> "_AvatarAssets":
|
||||
temp = target
|
||||
@ -236,39 +229,33 @@ class _AvatarAssets(_AssetsService):
|
||||
return result
|
||||
|
||||
async def _get_from_ambr(self, item: str) -> Path | None:
|
||||
if item in {'icon', 'side', 'gacha'}:
|
||||
if item in {"icon", "side", "gacha"}:
|
||||
url = AMBR_HOST.join(f"assets/UI/{self.game_name_map[item]}.png")
|
||||
return await self._download(url, self.path.joinpath(f"{item}.png"))
|
||||
|
||||
async def _get_from_enka(self, item: str) -> Path | None:
|
||||
path = self.path.joinpath(f"{item}.png")
|
||||
item = 'banner' if item == 'gacha' else item
|
||||
item = "banner" if item == "gacha" else item
|
||||
# noinspection PyUnboundLocalVariable
|
||||
if (
|
||||
self.enka is not None
|
||||
and
|
||||
item in (data := self.enka.images.dict()).keys()
|
||||
and
|
||||
(url := data[item]['url'])
|
||||
):
|
||||
if self.enka is not None and item in (data := self.enka.images.dict()).keys() and (url := data[item]["url"]):
|
||||
return await self._download(url, path)
|
||||
|
||||
@cached_property
|
||||
def honey_name_map(self) -> dict[str, str]:
|
||||
return {
|
||||
'icon': f"{self.honey_id}_icon",
|
||||
'side': f"{self.honey_id}_side_icon",
|
||||
'gacha': f"{self.honey_id}_gacha_splash",
|
||||
'gacha_card': f"{self.honey_id}_gacha_card",
|
||||
"icon": f"{self.honey_id}_icon",
|
||||
"side": f"{self.honey_id}_side_icon",
|
||||
"gacha": f"{self.honey_id}_gacha_splash",
|
||||
"gacha_card": f"{self.honey_id}_gacha_card",
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def game_name_map(self) -> dict[str, str]:
|
||||
return {
|
||||
'icon': f"UI_AvatarIcon_{self.game_name}",
|
||||
'card': f"UI_AvatarIcon_{self.game_name}_Card",
|
||||
'side': f"UI_AvatarIcon_Side_{self.game_name}",
|
||||
'gacha': f"UI_Gacha_AvatarImg_{self.game_name}",
|
||||
"icon": f"UI_AvatarIcon_{self.game_name}",
|
||||
"card": f"UI_AvatarIcon_{self.game_name}_Card",
|
||||
"side": f"UI_AvatarIcon_Side_{self.game_name}",
|
||||
"gacha": f"UI_Gacha_AvatarImg_{self.game_name}",
|
||||
}
|
||||
|
||||
|
||||
@ -281,14 +268,14 @@ class _WeaponAssets(_AssetsService):
|
||||
|
||||
@cached_property
|
||||
def game_name(self) -> str:
|
||||
return re.findall(r"UI_EquipIcon_(.*)", WEAPON_DATA[str(self.id)]['icon'])[0]
|
||||
return re.findall(r"UI_EquipIcon_(.*)", WEAPON_DATA[str(self.id)]["icon"])[0]
|
||||
|
||||
@cached_property
|
||||
def game_name_map(self) -> dict[str, str]:
|
||||
return {
|
||||
'icon': f"UI_EquipIcon_{self.game_name}",
|
||||
'awaken': f"UI_EquipIcon_{self.game_name}_Awaken",
|
||||
'gacha': f"UI_Gacha_EquipIcon_{self.game_name}"
|
||||
"icon": f"UI_EquipIcon_{self.game_name}",
|
||||
"awaken": f"UI_EquipIcon_{self.game_name}_Awaken",
|
||||
"gacha": f"UI_Gacha_EquipIcon_{self.game_name}",
|
||||
}
|
||||
|
||||
@cached_property
|
||||
@ -307,16 +294,16 @@ class _WeaponAssets(_AssetsService):
|
||||
|
||||
async def _get_from_enka(self, item: str) -> Path | None:
|
||||
if item in self.game_name_map:
|
||||
url = ENKA_HOST.join(f'ui/{self.game_name_map.get(item)}.png')
|
||||
url = ENKA_HOST.join(f"ui/{self.game_name_map.get(item)}.png")
|
||||
path = self.path.joinpath(f"{item}.png")
|
||||
return await self._download(url, path)
|
||||
|
||||
@cached_property
|
||||
def honey_name_map(self) -> dict[str, str]:
|
||||
return {
|
||||
'icon': f'{self.honey_id}',
|
||||
'awaken': f'{self.honey_id}_awaken_icon',
|
||||
'gacha': f'{self.honey_id}_gacha_icon',
|
||||
"icon": f"{self.honey_id}",
|
||||
"awaken": f"{self.honey_id}_awaken_icon",
|
||||
"gacha": f"{self.honey_id}_gacha_icon",
|
||||
}
|
||||
|
||||
|
||||
@ -327,11 +314,11 @@ class _MaterialAssets(_AssetsService):
|
||||
|
||||
@cached_property
|
||||
def game_name_map(self) -> dict[str, str]:
|
||||
return {'icon': f"UI_ItemIcon_{self.game_name}"}
|
||||
return {"icon": f"UI_ItemIcon_{self.game_name}"}
|
||||
|
||||
@cached_property
|
||||
def honey_name_map(self) -> dict[str, str]:
|
||||
return {'icon': self.honey_id}
|
||||
return {"icon": self.honey_id}
|
||||
|
||||
def __call__(self, target: StrOrInt) -> Self:
|
||||
temp = target
|
||||
@ -340,24 +327,24 @@ class _MaterialAssets(_AssetsService):
|
||||
if target.isnumeric():
|
||||
target = int(target)
|
||||
else:
|
||||
target = {v['name']: int(k) for k, v in MATERIAL_DATA.items()}.get(target)
|
||||
target = {v["name"]: int(k) for k, v in MATERIAL_DATA.items()}.get(target)
|
||||
if isinstance(target, str) or target is None:
|
||||
raise AssetsCouldNotFound(f"找不到对应的素材: target={temp}")
|
||||
result.id = target
|
||||
return result
|
||||
|
||||
async def _get_from_ambr(self, item: str) -> Path | None:
|
||||
if item == 'icon':
|
||||
if item == "icon":
|
||||
url = AMBR_HOST.join(f"assets/UI/{self.game_name_map.get(item)}.png")
|
||||
path = self.path.joinpath(f"{item}.png")
|
||||
return await self._download(url, path)
|
||||
|
||||
async def _get_from_honey(self, item: str) -> Path | None:
|
||||
path = self.path.joinpath(f"{item}.png")
|
||||
url = HONEY_HOST.join(f'/img/{self.honey_name_map.get(item)}.png')
|
||||
url = HONEY_HOST.join(f"/img/{self.honey_name_map.get(item)}.png")
|
||||
if (result := await self._download(url, path)) is None:
|
||||
path = self.path.joinpath(f"{item}.webp")
|
||||
url = HONEY_HOST.join(f'/img/{self.honey_name_map.get(item)}.webp')
|
||||
url = HONEY_HOST.join(f"/img/{self.honey_name_map.get(item)}.webp")
|
||||
return await self._download(url, path)
|
||||
return result
|
||||
|
||||
@ -380,7 +367,7 @@ class _ArtifactAssets(_AssetsService):
|
||||
|
||||
@cached_property
|
||||
def honey_id(self) -> str:
|
||||
return HONEY_DATA['artifact'][str(self.id)][0]
|
||||
return HONEY_DATA["artifact"][str(self.id)][0]
|
||||
|
||||
@cached_property
|
||||
def game_name(self) -> str:
|
||||
@ -388,7 +375,7 @@ class _ArtifactAssets(_AssetsService):
|
||||
|
||||
async def _get_from_enka(self, item: str) -> Path | None:
|
||||
if item in self.game_name_map:
|
||||
url = ENKA_HOST.join(f'ui/{self.game_name_map.get(item)}.png')
|
||||
url = ENKA_HOST.join(f"ui/{self.game_name_map.get(item)}.png")
|
||||
path = self.path.joinpath(f"{item}.png")
|
||||
return await self._download(url, path)
|
||||
|
||||
@ -410,7 +397,7 @@ class _ArtifactAssets(_AssetsService):
|
||||
|
||||
@cached_property
|
||||
def honey_name_map(self) -> dict[str, str]:
|
||||
first_id = int(re.findall(r'\d+', HONEY_DATA['artifact'][str(self.id)][-1])[0])
|
||||
first_id = int(re.findall(r"\d+", HONEY_DATA["artifact"][str(self.id)][-1])[0])
|
||||
return {
|
||||
"icon": f"i_n{first_id + 30}",
|
||||
"flower": f"i_n{first_id + 30}",
|
||||
@ -432,43 +419,43 @@ class _NamecardAssets(_AssetsService):
|
||||
|
||||
@cached_property
|
||||
def honey_id(self) -> str:
|
||||
return HONEY_DATA['namecard'][str(self.id)][0]
|
||||
return HONEY_DATA["namecard"][str(self.id)][0]
|
||||
|
||||
@cached_property
|
||||
def game_name(self) -> str:
|
||||
return NAMECARD_DATA[str(self.id)]['icon']
|
||||
return NAMECARD_DATA[str(self.id)]["icon"]
|
||||
|
||||
def __call__(self, target: int) -> "_NamecardAssets":
|
||||
result = _NamecardAssets(self.client)
|
||||
result.id = target
|
||||
result.enka = EnkaAssets(lang='chs').namecards(target)
|
||||
result.enka = DEFAULT_EnkaAssets.namecards(target)
|
||||
return result
|
||||
|
||||
async def _get_from_ambr(self, item: str) -> Path | None:
|
||||
if item == 'profile':
|
||||
if item == "profile":
|
||||
url = AMBR_HOST.join(f"assets/UI/namecard/{self.game_name_map[item]}.png.png")
|
||||
return await self._download(url, self.path.joinpath(f"{item}.png"))
|
||||
|
||||
async def _get_from_enka(self, item: str) -> Path | None:
|
||||
path = self.path.joinpath(f"{item}.png")
|
||||
url = getattr(self.enka, {'profile': 'banner'}.get(item, item), None)
|
||||
url = getattr(self.enka, {"profile": "banner"}.get(item, item), None)
|
||||
if url is not None:
|
||||
return await self._download(url.url, path)
|
||||
|
||||
@cached_property
|
||||
def game_name_map(self) -> dict[str, str]:
|
||||
return {
|
||||
'icon': self.game_name,
|
||||
'navbar': NAMECARD_DATA[str(self.id)]['navbar'],
|
||||
'profile': NAMECARD_DATA[str(self.id)]['profile']
|
||||
"icon": self.game_name,
|
||||
"navbar": NAMECARD_DATA[str(self.id)]["navbar"],
|
||||
"profile": NAMECARD_DATA[str(self.id)]["profile"],
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def honey_name_map(self) -> dict[str, str]:
|
||||
return {
|
||||
'icon': self.honey_id,
|
||||
'navbar': f"{self.honey_id}_back",
|
||||
'profile': f"{self.honey_id}_profile",
|
||||
"icon": self.honey_id,
|
||||
"navbar": f"{self.honey_id}_back",
|
||||
"profile": f"{self.honey_id}_profile",
|
||||
}
|
||||
|
||||
|
||||
@ -497,8 +484,7 @@ class AssetsService(Service):
|
||||
|
||||
def __init__(self):
|
||||
for attr, assets_type_name in filter(
|
||||
lambda x: (not x[0].startswith('_')) and x[1].endswith('Assets'),
|
||||
self.__annotations__.items()
|
||||
lambda x: (not x[0].startswith("_")) and x[1].endswith("Assets"), self.__annotations__.items()
|
||||
):
|
||||
setattr(self, attr, globals()[assets_type_name]())
|
||||
|
||||
@ -510,4 +496,4 @@ class AssetsService(Service):
|
||||
logger.info("刷新元数据成功")
|
||||
|
||||
|
||||
AssetsServiceType = TypeVar('AssetsServiceType', bound=_AssetsService)
|
||||
AssetsServiceType = TypeVar("AssetsServiceType", bound=_AssetsService)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
from typing import Any, Generic, ItemsView, Iterator, KeysView, TypeVar
|
||||
|
||||
import ujson as json
|
||||
@ -11,16 +12,20 @@ from utils.log import logger
|
||||
from utils.typedefs import StrOrInt
|
||||
|
||||
__all__ = [
|
||||
'HONEY_DATA',
|
||||
'AVATAR_DATA', 'WEAPON_DATA', 'MATERIAL_DATA', 'ARTIFACT_DATA', 'NAMECARD_DATA',
|
||||
'honey_id_to_game_id',
|
||||
'Data'
|
||||
"HONEY_DATA",
|
||||
"AVATAR_DATA",
|
||||
"WEAPON_DATA",
|
||||
"MATERIAL_DATA",
|
||||
"ARTIFACT_DATA",
|
||||
"NAMECARD_DATA",
|
||||
"honey_id_to_game_id",
|
||||
"Data",
|
||||
]
|
||||
|
||||
K = TypeVar('K')
|
||||
V = TypeVar('V')
|
||||
K = TypeVar("K")
|
||||
V = TypeVar("V")
|
||||
|
||||
data_dir = PROJECT_ROOT.joinpath('metadata/data/')
|
||||
data_dir = PROJECT_ROOT.joinpath("metadata/data/")
|
||||
data_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
_cache = {}
|
||||
@ -35,15 +40,14 @@ class Data(dict, Generic[K, V]):
|
||||
if (result := _cache.get(self._file_name)) not in [None, {}]:
|
||||
self._dict = result
|
||||
else:
|
||||
path = data_dir.joinpath(self._file_name).with_suffix('.json')
|
||||
path = data_dir.joinpath(self._file_name).with_suffix(".json")
|
||||
if not path.exists():
|
||||
logger.error(
|
||||
f"暂未找到名为 \"{self._file_name}.json\" 的 metadata , "
|
||||
"请先使用 [yellow bold]/refresh_metadata[/] 命令下载",
|
||||
extra={'markup': True}
|
||||
f'暂未找到名为 "{self._file_name}.json" 的 metadata , ' "请先使用 [yellow bold]/refresh_metadata[/] 命令下载",
|
||||
extra={"markup": True},
|
||||
)
|
||||
self._dict = {}
|
||||
with open(path, encoding='utf-8') as file:
|
||||
with open(path, encoding="utf-8") as file:
|
||||
self._dict = json.load(file)
|
||||
_cache.update({self._file_name: self._dict})
|
||||
return self._dict
|
||||
@ -75,14 +79,15 @@ class Data(dict, Generic[K, V]):
|
||||
return self.data.items()
|
||||
|
||||
|
||||
HONEY_DATA: dict[str, dict[StrOrInt, list[str | int]]] = Data('honey')
|
||||
HONEY_DATA: dict[str, dict[StrOrInt, list[str | int]]] = Data("honey")
|
||||
|
||||
AVATAR_DATA: dict[str, dict[str, int | str | list[int]]] = Data('avatar')
|
||||
WEAPON_DATA: dict[str, dict[str, int | str]] = Data('weapon')
|
||||
MATERIAL_DATA: dict[str, dict[str, int | str]] = Data('material')
|
||||
ARTIFACT_DATA: dict[str, dict[str, int | str | list[int] | dict[str, str]]] = Data('reliquary')
|
||||
NAMECARD_DATA: dict[str, dict[str, int | str]] = Data('namecard')
|
||||
AVATAR_DATA: dict[str, dict[str, int | str | list[int]]] = Data("avatar")
|
||||
WEAPON_DATA: dict[str, dict[str, int | str]] = Data("weapon")
|
||||
MATERIAL_DATA: dict[str, dict[str, int | str]] = Data("material")
|
||||
ARTIFACT_DATA: dict[str, dict[str, int | str | list[int] | dict[str, str]]] = Data("reliquary")
|
||||
NAMECARD_DATA: dict[str, dict[str, int | str]] = Data("namecard")
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
def honey_id_to_game_id(honey_id: str, item_type: str) -> str | None:
|
||||
return next((key for key, value in HONEY_DATA[item_type].items() if value[0] == honey_id), None)
|
||||
|
@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
|
||||
from metadata.genshin import WEAPON_DATA
|
||||
|
||||
__all__ = [
|
||||
@ -183,24 +185,28 @@ weapons = {
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@functools.lru_cache()
|
||||
def roleToName(shortname: str) -> str:
|
||||
"""讲角色昵称转为正式名"""
|
||||
return next((value[0] for value in roles.values() for name in value if name == shortname), shortname)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@functools.lru_cache()
|
||||
def roleToId(name: str) -> int | None:
|
||||
"""获取角色ID"""
|
||||
return next((key for key, value in roles.items() for n in value if n == name), None)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@functools.lru_cache()
|
||||
def weaponToName(shortname: str) -> str:
|
||||
"""讲武器昵称转为正式名"""
|
||||
return next((key for key, value in weapons.items() if shortname == key or shortname in value), shortname)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@functools.lru_cache()
|
||||
def weaponToId(name: str) -> int | None:
|
||||
"""获取武器ID"""
|
||||
return next((int(key) for key, value in WEAPON_DATA.items() if weaponToName(name) in value['name']), None)
|
||||
|
@ -374,29 +374,27 @@ class GachaLog:
|
||||
count += 1
|
||||
if item.rank_type == "5":
|
||||
if item.item_type == "角色" and pool_name in {"角色祈愿", "常驻祈愿"}:
|
||||
result.append(
|
||||
FiveStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.avatar(roleToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="角色",
|
||||
isUp=GachaLog.check_avatar_up(item.name, item.time) if pool_name == "角色祈愿" else False,
|
||||
isBig=(not result[-1].isUp) if result and pool_name == "角色祈愿" else False,
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
data = {
|
||||
"name": item.name,
|
||||
"icon": (await assets.avatar(roleToId(item.name)).icon()).as_uri(),
|
||||
"count": count,
|
||||
"type": "角色",
|
||||
"isUp": GachaLog.check_avatar_up(item.name, item.time) if pool_name == "角色祈愿" else False,
|
||||
"isBig": (not result[-1].isUp) if result and pool_name == "角色祈愿" else False,
|
||||
"time": item.time,
|
||||
}
|
||||
result.append(FiveStarItem.construct(**data))
|
||||
elif item.item_type == "武器" and pool_name in {"武器祈愿", "常驻祈愿"}:
|
||||
result.append(
|
||||
FiveStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.weapon(weaponToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="武器",
|
||||
isUp=False,
|
||||
isBig=False,
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
data = {
|
||||
"name": item.name,
|
||||
"icon": (await assets.weapon(weaponToId(item.name)).icon()).as_uri(),
|
||||
"count": count,
|
||||
"type": "武器",
|
||||
"isUp": False,
|
||||
"isBig": False,
|
||||
"time": item.time,
|
||||
}
|
||||
result.append(FiveStarItem.construct(**data))
|
||||
count = 0
|
||||
result.reverse()
|
||||
return result, count
|
||||
@ -415,25 +413,23 @@ class GachaLog:
|
||||
count += 1
|
||||
if item.rank_type == "4":
|
||||
if item.item_type == "角色":
|
||||
result.append(
|
||||
FourStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.avatar(roleToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="角色",
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
data = {
|
||||
"name": item.name,
|
||||
"icon": (await assets.avatar(roleToId(item.name)).icon()).as_uri(),
|
||||
"count": count,
|
||||
"type": "角色",
|
||||
"time": item.time,
|
||||
}
|
||||
result.append(FourStarItem.construct(**data))
|
||||
elif item.item_type == "武器":
|
||||
result.append(
|
||||
FourStarItem(
|
||||
name=item.name,
|
||||
icon=(await assets.weapon(weaponToId(item.name)).icon()).as_uri(),
|
||||
count=count,
|
||||
type="武器",
|
||||
time=item.time,
|
||||
)
|
||||
)
|
||||
data = {
|
||||
"name": item.name,
|
||||
"icon": (await assets.weapon(weaponToId(item.name)).icon()).as_uri(),
|
||||
"count": count,
|
||||
"type": "武器",
|
||||
"time": item.time,
|
||||
}
|
||||
result.append(FourStarItem.construct(**data))
|
||||
count = 0
|
||||
result.reverse()
|
||||
return result, count
|
||||
|
@ -22,6 +22,7 @@ from telegram import InlineKeyboardButton, InlineKeyboardMarkup, InputMediaPhoto
|
||||
from telegram.constants import ChatAction
|
||||
from telegram.ext import CallbackContext, CallbackQueryHandler, CommandHandler, MessageHandler, filters
|
||||
|
||||
from core.base.assets import DEFAULT_EnkaAssets
|
||||
from core.baseplugin import BasePlugin
|
||||
from core.config import config
|
||||
from core.plugin import Plugin, handler
|
||||
@ -38,8 +39,6 @@ from utils.log import logger
|
||||
from utils.models.base import RegionEnum
|
||||
from utils.patch.aiohttp import AioHttpTimeoutException
|
||||
|
||||
assets = Assets(lang="chs")
|
||||
|
||||
|
||||
class PlayerCards(Plugin, BasePlugin):
|
||||
def __init__(self, user_service: UserService = None, template_service: TemplateService = None):
|
||||
@ -82,12 +81,8 @@ class PlayerCards(Plugin, BasePlugin):
|
||||
except UserNotFoundError:
|
||||
reply_message = await message.reply_text("未查询到账号信息,请先私聊派蒙绑定账号")
|
||||
if filters.ChatType.GROUPS.filter(message):
|
||||
self._add_delete_message_job(
|
||||
context, reply_message.chat_id, reply_message.message_id, 30
|
||||
)
|
||||
self._add_delete_message_job(
|
||||
context, message.chat_id, message.message_id, 30
|
||||
)
|
||||
self._add_delete_message_job(context, reply_message.chat_id, reply_message.message_id, 30)
|
||||
self._add_delete_message_job(context, message.chat_id, message.message_id, 30)
|
||||
return
|
||||
data = await self._fetch_user(uid)
|
||||
if isinstance(data, str):
|
||||
@ -98,25 +93,26 @@ class PlayerCards(Plugin, BasePlugin):
|
||||
return
|
||||
if len(args) == 1:
|
||||
character_name = roleToName(args[0])
|
||||
logger.info(
|
||||
f"用户 {user.full_name}[{user.id}] 角色卡片查询命令请求 || character_name[{character_name}] uid[{uid}]"
|
||||
)
|
||||
logger.info(f"用户 {user.full_name}[{user.id}] 角色卡片查询命令请求 || character_name[{character_name}] uid[{uid}]")
|
||||
else:
|
||||
logger.info(f"用户 {user.full_name}[{user.id}] 角色卡片查询命令请求")
|
||||
buttons = []
|
||||
temp = []
|
||||
for index, value in enumerate(data.characters):
|
||||
temp.append(InlineKeyboardButton(
|
||||
value.name,
|
||||
callback_data=f"get_player_card|{user.id}|{uid}|{value.name}",
|
||||
))
|
||||
temp.append(
|
||||
InlineKeyboardButton(
|
||||
value.name,
|
||||
callback_data=f"get_player_card|{user.id}|{uid}|{value.name}",
|
||||
)
|
||||
)
|
||||
if index == 3:
|
||||
buttons.append(temp)
|
||||
temp = []
|
||||
if len(temp) > 0:
|
||||
buttons.append(temp)
|
||||
reply_message = await message.reply_photo(photo=self.temp_photo, caption="请选择你要查询的角色",
|
||||
reply_markup=InlineKeyboardMarkup(buttons))
|
||||
reply_message = await message.reply_photo(
|
||||
photo=self.temp_photo, caption="请选择你要查询的角色", reply_markup=InlineKeyboardMarkup(buttons)
|
||||
)
|
||||
if reply_message.photo:
|
||||
self.temp_photo = reply_message.photo[-1].file_id
|
||||
return
|
||||
@ -148,8 +144,7 @@ class PlayerCards(Plugin, BasePlugin):
|
||||
|
||||
result, user_id, uid = await get_player_card_callback(callback_query.data)
|
||||
if user.id != user_id:
|
||||
await callback_query.answer(text="这不是你的按钮!\n"
|
||||
"再乱点再按我叫西风骑士团、千岩军、天领奉和教令院了!", show_alert=True)
|
||||
await callback_query.answer(text="这不是你的按钮!\n" "再乱点再按我叫西风骑士团、千岩军、天领奉和教令院了!", show_alert=True)
|
||||
return
|
||||
logger.info(f"用户 {user.full_name}[{user.id}] 角色卡片查询命令请求 || character_name[{result}] uid[{uid}]")
|
||||
data = await self._fetch_user(uid)
|
||||
@ -190,15 +185,17 @@ class Artifact(BaseModel):
|
||||
self.score += substat_scores
|
||||
self.score = round(self.score, 1)
|
||||
|
||||
for r in (("D", 10),
|
||||
("C", 16.5),
|
||||
("B", 23.1),
|
||||
("A", 29.7),
|
||||
("S", 36.3),
|
||||
("SS", 42.9),
|
||||
("SSS", 49.5),
|
||||
("ACE", 56.1),
|
||||
("ACE²", 66)):
|
||||
for r in (
|
||||
("D", 10),
|
||||
("C", 16.5),
|
||||
("B", 23.1),
|
||||
("A", 29.7),
|
||||
("S", 36.3),
|
||||
("SS", 42.9),
|
||||
("SSS", 49.5),
|
||||
("ACE", 56.1),
|
||||
("ACE²", 66),
|
||||
):
|
||||
if self.score >= r[1]:
|
||||
self.score_label = r[0]
|
||||
self.score_class = self.get_score_class(r[0])
|
||||
@ -236,15 +233,17 @@ class RenderTemplate:
|
||||
artifact_total_score = round(artifact_total_score, 1)
|
||||
|
||||
artifact_total_score_label: str = "E"
|
||||
for r in (("D", 10),
|
||||
("C", 16.5),
|
||||
("B", 23.1),
|
||||
("A", 29.7),
|
||||
("S", 36.3),
|
||||
("SS", 42.9),
|
||||
("SSS", 49.5),
|
||||
("ACE", 56.1),
|
||||
("ACE²", 66)):
|
||||
for r in (
|
||||
("D", 10),
|
||||
("C", 16.5),
|
||||
("B", 23.1),
|
||||
("A", 29.7),
|
||||
("S", 36.3),
|
||||
("SS", 42.9),
|
||||
("SSS", 49.5),
|
||||
("ACE", 56.1),
|
||||
("ACE²", 66),
|
||||
):
|
||||
if artifact_total_score / 5 >= r[1]:
|
||||
artifact_total_score_label = r[0]
|
||||
|
||||
@ -262,7 +261,6 @@ class RenderTemplate:
|
||||
# 圣遗物评级颜色
|
||||
"artifact_total_score_class": Artifact.get_score_class(artifact_total_score_label),
|
||||
"artifacts": artifacts,
|
||||
|
||||
# 需要在模板中使用的 enum 类型
|
||||
"DigitType": DigitType,
|
||||
}
|
||||
@ -278,7 +276,7 @@ class RenderTemplate:
|
||||
data,
|
||||
{"width": 950, "height": 1080},
|
||||
full_page=True,
|
||||
query_selector=".text-neutral-200"
|
||||
query_selector=".text-neutral-200",
|
||||
)
|
||||
|
||||
async def de_stats(self) -> List[Tuple[str, Any]]:
|
||||
@ -317,14 +315,10 @@ class RenderTemplate:
|
||||
pass
|
||||
elif stat[1].id != 26: # 治疗加成
|
||||
continue
|
||||
value = (
|
||||
stat[1].to_rounded()
|
||||
if isinstance(stat[1], Stats)
|
||||
else stat[1].to_percentage_symbol()
|
||||
)
|
||||
value = stat[1].to_rounded() if isinstance(stat[1], Stats) else stat[1].to_percentage_symbol()
|
||||
if value in ("0%", 0):
|
||||
continue
|
||||
name = assets.get_hash_map(stat[0])
|
||||
name = DEFAULT_EnkaAssets.get_hash_map(stat[0])
|
||||
if name is None:
|
||||
continue
|
||||
items.append((name, value))
|
||||
|
Loading…
Reference in New Issue
Block a user