支持网页控制台调整从米游社更新角色面板 (#641)

This commit is contained in:
KimigaiiWuyi 2024-08-15 17:26:27 +08:00
parent 9d4270d67e
commit 426540cfae
10 changed files with 738 additions and 5 deletions

View File

@ -129,4 +129,9 @@ CONIFG_DEFAULT: Dict[str, GSC] = {
'修改帮助图有多少列',
'6',
),
'EnableCharCardByMys': GsBoolConfig(
'从米游社获取面板替代Enka服务',
'开启后角色卡片将从米游社获取, 可能会遇到验证码',
False,
),
}

View File

@ -16,6 +16,7 @@ from .to_card import enka_to_card
from ..utils.convert import get_uid
from .get_akasha_data import get_rank
from .start import refresh_player_list
from .to_data_by_mys import mys_to_card
from .draw_artifacts_lib import draw_lib
from .draw_rank_list import draw_rank_img
from ..utils.image.convert import convert_img
@ -24,10 +25,13 @@ from .draw_arti_rank import draw_arti_rank_img
from .draw_char_info import draw_all_char_list
from .draw_char_rank import draw_cahrcard_list
from .draw_role_rank import draw_role_rank_img
from ..genshinuid_config.gs_config import gsconfig
from .get_enka_img import draw_enka_img, get_full_char
from ..genshinuid_enka.start import check_artifacts_list
from ..utils.resource.RESOURCE_PATH import TEMP_PATH, PLAYER_PATH
EnableCharCardByMys = gsconfig.get_config('EnableCharCardByMys').data
sv_enka_admin = SV('面板管理', pm=1)
sv_enka_config = SV('面板设置', pm=2)
sv_akasha = SV('排名查询', priority=10)
@ -332,7 +336,10 @@ async def send_card_info(bot: Bot, ev: Event):
if uid is None:
return await bot.send(UID_HINT)
logger.info('[强制刷新]uid: {}'.format(uid))
im = await enka_to_card(uid)
if EnableCharCardByMys:
im = await mys_to_card(uid)
else:
im = await enka_to_card(uid)
logger.info(f'UID{uid}获取角色数据成功!')
if isinstance(im, Tuple):

View File

@ -0,0 +1,273 @@
import json
from datetime import datetime
from typing import Dict, List, Tuple, Union
import aiofiles
from gsuid_core.utils.error_reply import get_error
from .to_card import pic_500, draw_enka_card
from ..utils.image.convert import convert_img
from ..utils.mys_api import mys_api, get_base_data
from ..utils.map.name_covert import avatarId_to_enName
from ..utils.resource.RESOURCE_PATH import PLAYER_PATH
from ..utils.map.GS_MAP_PATH import (
Id2PropId,
name2Icon,
propId2Name,
skillId2Name,
talentId2Name,
)
elementMap = {
'Anemo': 44,
'Geo': 45,
'Dendro': 43,
'Pyro': 40,
'Hydro': 42,
'Cryo': 46,
'Electro': 41,
}
posMap = {
"空之杯": "goblet",
"死之羽": "plume",
"理之冠": "circlet",
"生之花": "flower",
"时之沙": "sands",
}
def get_value(value: str):
if not value:
return 0
return float(value.replace('%', ''))
async def mys_to_data(uid: str):
path = PLAYER_PATH / uid
raw_data = await get_base_data(uid)
if isinstance(raw_data, (str, bytes)):
return raw_data
elif isinstance(raw_data, (bytearray, memoryview)):
return bytes(raw_data)
char_data = raw_data['avatars']
char_ids = []
for i in char_data:
char_ids.append(i['id'])
data = await mys_api.get_char_detail_data(uid, char_ids)
if isinstance(data, int):
return get_error(data)
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
skill_icon_map = skillId2Name['Icon']
talent_icon_map = talentId2Name['Icon']
char_dict_list = []
for char in data:
base = char['base']
avatar_name = base['name']
avatar_id = base['id']
en_name = await avatarId_to_enName(str(avatar_id))
avatar_skill = []
avatar_talent = []
avatar_fight_prop = {}
weapon_info = {}
for skill in char['skills']:
skill_id = str(skill['skill_id'])
if len(skill_id) <= 4:
continue
avatar_skill.append(
{
"skillId": skill_id,
"skillName": skill['name'],
"skillLevel": skill['level'],
"skillIcon": skill_icon_map[skill_id],
}
)
for talent in char['constellations']:
if talent['is_actived']:
talent_id = talent['id']
avatar_talent.append(
{
"talentId": talent_id,
"talentName": talent['name'],
"talentIcon": talent_icon_map[str(talent_id)],
}
)
weapon = char['weapon']
weapon_main = weapon['main_property']
main_prop_id = Id2PropId[str(weapon_main['property_type'])]
weaponStats = [
{
"appendPropId": main_prop_id,
"statName": propId2Name[main_prop_id],
"statValue": get_value(weapon_main['final']),
}
]
weapon_sub = weapon['sub_property']
if weapon_sub:
sub_prop_id = Id2PropId[str(weapon_sub['property_type'])]
weaponStats.append(
{
"appendPropId": sub_prop_id,
"statName": propId2Name[sub_prop_id],
"statValue": get_value(weapon_sub['final']),
}
)
weapon_info = {
"itemId": weapon['id'],
"nameTextMapHash": "807607555",
"weaponIcon": "UI_EquipIcon_Catalyst_Dvalin",
"weaponType": weapon['type_name'],
"weaponName": weapon['name'],
"weaponStar": weapon['rarity'],
"promoteLevel": 1,
"weaponLevel": weapon['level'],
"weaponAffix": weapon['affix_level'],
"weaponStats": weaponStats,
"weaponEffect": weapon['desc'],
}
all_prop = (
char['base_properties']
+ char['extra_properties']
+ char['element_properties']
)
element_id = elementMap.get(base['element'], 41)
for prop in all_prop:
prop_id = prop['property_type']
if prop_id == 2000:
avatar_fight_prop['baseHp'] = get_value(prop['base'])
avatar_fight_prop['addHp'] = get_value(prop['add'])
avatar_fight_prop['hp'] = get_value(prop['final'])
elif prop_id == 2001:
avatar_fight_prop['baseAtk'] = get_value(prop['base'])
avatar_fight_prop['addAtk'] = get_value(prop['add'])
avatar_fight_prop['atk'] = get_value(prop['final'])
elif prop_id == 2002:
avatar_fight_prop['baseDef'] = get_value(prop['base'])
avatar_fight_prop['addDef'] = get_value(prop['add'])
avatar_fight_prop['def'] = get_value(prop['final'])
elif prop_id == 28:
avatar_fight_prop['elementalMastery'] = get_value(
prop['final']
)
elif prop_id == 20:
avatar_fight_prop['critRate'] = get_value(prop['final'])
elif prop_id == 22:
avatar_fight_prop['critDmg'] = get_value(prop['final'])
elif prop_id == 23:
avatar_fight_prop['energyRecharge'] = get_value(prop['final'])
elif prop_id == 26:
avatar_fight_prop['healBonus'] = get_value(prop['final'])
elif prop_id == 27:
avatar_fight_prop['healedBonus'] = get_value(prop['final'])
elif prop_id == 30:
avatar_fight_prop['physicalDmgBonus'] = get_value(
prop['final']
)
elif prop_id == element_id:
avatar_fight_prop['dmgBonus'] = get_value(prop['final']) / 100
avatar_fight_prop['physicalDmgSub'] = 0
relic_list = []
artifact_set_list = []
for relic in char['relics']:
main_prop = relic['main_property']
main_prop_id = Id2PropId[str(main_prop['property_type'])]
sub_prop = relic['sub_property_list']
reliquarySubstats = []
for su in sub_prop:
sub_prop_id = Id2PropId[str(su['property_type'])]
reliquarySubstats.append(
{
"appendPropId": sub_prop_id,
"statName": propId2Name[sub_prop_id],
"statValue": get_value(su['value']),
}
)
artifact_set_list.append(relic['set']['name'])
relic_list.append(
{
"itemId": relic['id'],
"nameTextMapHash": "2007346252",
"icon": name2Icon[relic['name']],
"aritifactName": relic['name'],
"aritifactSetsName": relic['set']['name'],
"aritifactSetPiece": posMap[relic['pos_name']],
"aritifactPieceName": relic['pos_name'],
"aritifactStar": relic['rarity'],
"aritifactLevel": relic['level'],
"reliquaryMainstat": {
"mainPropId": main_prop_id,
"statValue": get_value(main_prop['value']),
"statName": propId2Name[main_prop_id],
},
"reliquarySubstats": reliquarySubstats,
}
)
equipSetList = set(artifact_set_list)
equipSets = {'type': '', 'set': ''}
for equip in equipSetList:
if artifact_set_list.count(equip) >= 4:
equipSets['type'] = '4'
equipSets['set'] = equip
break
elif artifact_set_list.count(equip) == 1:
pass
elif artifact_set_list.count(equip) >= 2:
equipSets['type'] += '2'
equipSets['set'] += '|' + equip
if equipSets['set'].startswith('|'):
equipSets['set'] = equipSets['set'][1:]
result = {
'playerUid': uid,
'playerName': raw_data['role']['nickname'],
'avatarId': avatar_id,
'avatarName': avatar_name,
'avatarFetter': base['fetter'],
'avatarLevel': str(base['level']),
'avatarElement': base['element'],
'dataTime': now,
'avatarEnName': en_name,
'avatarSkill': avatar_skill,
'talentList': avatar_talent,
'weaponInfo': weapon_info,
'avatarFightProp': avatar_fight_prop,
'equipSets': equipSets,
'equipList': relic_list,
}
char_dict_list.append(result)
async with aiofiles.open(
path / f'{avatar_name}.json', 'w', encoding='UTF-8'
) as file:
await file.write(json.dumps(result, indent=4, ensure_ascii=False))
return char_dict_list
async def mys_to_card(uid: str) -> Union[str, bytes, Tuple[bytes, List[Dict]]]:
char_data_list = await mys_to_data(uid)
if char_data_list == []:
return await convert_img(pic_500)
elif isinstance(char_data_list, str):
return char_data_list
elif isinstance(char_data_list, bytes):
return char_data_list
img = await draw_enka_card(uid=uid, char_data_list=char_data_list)
return img, char_data_list

View File

@ -1,3 +1,4 @@
base_url = 'https://api-takumi-record.mihoyo.com'
widget_url = f'{base_url}/game_record/genshin/aapi/widget/v2'
new_abyss_url = f'{base_url}/game_record/app/genshin/api/role_combat'
char_detail_url = f'{base_url}/game_record/app/genshin/api/character/detail'

View File

@ -167,3 +167,124 @@ class PoetryAbyssDatas(TypedDict):
data: List[PoetryAbyssData]
is_unlock: bool
links: PoetryAbyssLinks
class MainProperty(TypedDict):
property_type: int
base: str
add: str
final: str
class SubProperty(TypedDict):
property_type: int
base: str
add: str
final: str
class RelicMainProperty(TypedDict):
property_type: int
value: str
times: int
class RelicSubProperty(TypedDict):
property_type: int
value: str
times: int
class RelicSet(TypedDict):
id: int
name: str
affixes: List[dict]
class Relic(TypedDict):
id: int
name: str
icon: str
pos: int
rarity: int
level: int
set: RelicSet
pos_name: str
main_property: RelicMainProperty
sub_property_list: List[RelicSubProperty]
class Constellation(TypedDict):
id: int
name: str
icon: str
effect: str
is_actived: bool
pos: int
class Property(TypedDict):
property_type: int
base: str
add: str
final: str
class Weapon(TypedDict):
id: int
name: str
icon: str
type: int
rarity: int
level: int
promote_level: int
type_name: str
desc: str
affix_level: int
main_property: MainProperty
sub_property: SubProperty
class CharacterBase(TypedDict):
id: int
icon: str
name: str
element: str
fetter: int
level: int
rarity: int
actived_constellation_num: int
image: str
is_chosen: bool
side_icon: str
weapon_type: int
weapon: Weapon
class SkillAffix(TypedDict):
name: str
value: str
class Skill(TypedDict):
skill_id: int
skill_type: int
level: int
desc: str
skill_affix_list: List[SkillAffix]
icon: str
is_unlock: bool
name: str
class Character(TypedDict):
base: CharacterBase
weapon: Weapon
relics: List[Relic]
constellations: List[Constellation]
costumes: List[dict]
selected_properties: List[Property]
base_properties: List[Property]
extra_properties: List[Property]
element_properties: List[Property]
skills: List[Skill]

View File

@ -1,11 +1,11 @@
from copy import deepcopy
from typing import Dict, Union, cast
from typing import Dict, List, Union, cast
from gsuid_core.utils.api.mys_api import _MysApi
from gsuid_core.utils.api.mys.tools import get_ds_token, get_web_ds_token
from .api import widget_url, new_abyss_url
from .models import WidgetResin, PoetryAbyssDatas
from .api import widget_url, new_abyss_url, char_detail_url
from .models import Character, WidgetResin, PoetryAbyssDatas
class GsMysAPI(_MysApi):
@ -55,3 +55,28 @@ class GsMysAPI(_MysApi):
if isinstance(data, Dict):
data = cast(PoetryAbyssDatas, data['data'])
return data
async def get_char_detail_data(
self, uid: str, char_id_list: List[str]
) -> Union[List[Character], int]:
server_id = self.RECOGNIZE_SERVER.get(uid[0], 'cn_gf01')
HEADER = deepcopy(self._HEADER)
ck = await self.get_ck(uid, 'OWNER')
if ck is None:
return -51
HEADER['Cookie'] = ck
data = await self._mys_request(
char_detail_url,
'POST',
HEADER,
data={
"role_id": uid,
"server": server_id,
"character_ids": char_id_list,
},
)
if isinstance(data, Dict):
data = cast(List[Character], data['data']['list'])
return data

View File

@ -19,6 +19,7 @@ avatarId2Star_fileName = f'avatarId2Star_mapping_{version}.json'
artifact2attr_fileName = f'artifact2attr_mapping_{version}.json'
enName2Id_fileName = f'enName2AvatarID_mapping_{version}.json'
icon2Name_fileName = f'icon2Name_mapping_{version}.json'
name2Icon_fileName = f'name2Icon_mapping_{version}.json'
avatarName2Weapon_fileName = f'avatarName2Weapon_mapping_{version}.json'
monster2entry_fileName = f'monster2entry_mapping_{version}.json'
avatarId2SkillList_fileName = f'avatarId2SkillList_mapping_{version}.json'
@ -40,9 +41,18 @@ with open(MAP / icon2Name_fileName, 'r', encoding='UTF-8') as f:
with open(MAP / artifact2attr_fileName, 'r', encoding='UTF-8') as f:
artifact2attr = msgjson.decode(f.read(), type=Dict[str, str])
with open(MAP / icon2Name_fileName, 'r', encoding='UTF-8') as f:
icon2Name = msgjson.decode(f.read(), type=Dict[str, str])
with open(MAP / name2Icon_fileName, 'r', encoding='UTF-8') as f:
name2Icon = msgjson.decode(f.read(), type=Dict[str, str])
with open(MAP / 'propId2Name_mapping.json', 'r', encoding='UTF-8') as f:
propId2Name = msgjson.decode(f.read(), type=Dict[str, str])
with open(MAP / 'Id2propId_mapping.json', 'r', encoding='UTF-8') as f:
Id2PropId = msgjson.decode(f.read(), type=Dict[str, str])
with open(MAP / weaponHash2Name_fileName, 'r', encoding='UTF-8') as f:
weaponHash2Name = msgjson.decode(f.read(), type=Dict[str, str])

View File

@ -0,0 +1,34 @@
{
"4": "FIGHT_PROP_BASE_ATTACK",
"7": "FIGHT_PROP_BASE_DEFENSE",
"1": "FIGHT_PROP_BASE_HP",
"5": "FIGHT_PROP_ATTACK",
"6": "FIGHT_PROP_ATTACK_PERCENT",
"2": "FIGHT_PROP_HP",
"3": "FIGHT_PROP_HP_PERCENT",
"8": "FIGHT_PROP_DEFENSE",
"9": "FIGHT_PROP_DEFENSE_PERCENT",
"28": "FIGHT_PROP_ELEMENT_MASTERY",
"20": "FIGHT_PROP_CRITICAL",
"22": "FIGHT_PROP_CRITICAL_HURT",
"23": "FIGHT_PROP_CHARGE_EFFICIENCY",
"50": "FIGHT_PROP_FIRE_SUB_HURT",
"51": "FIGHT_PROP_ELEC_SUB_HURT",
"56": "FIGHT_PROP_ICE_SUB_HURT",
"52": "FIGHT_PROP_WATER_SUB_HURT",
"54": "FIGHT_PROP_WIND_SUB_HURT",
"55": "FIGHT_PROP_ROCK_SUB_HURT",
"53": "FIGHT_PROP_GRASS_SUB_HURT",
"40": "FIGHT_PROP_FIRE_ADD_HURT",
"41": "FIGHT_PROP_ELEC_ADD_HURT",
"46": "FIGHT_PROP_ICE_ADD_HURT",
"42": "FIGHT_PROP_WATER_ADD_HURT",
"44": "FIGHT_PROP_WIND_ADD_HURT",
"45": "FIGHT_PROP_ROCK_ADD_HURT",
"43": "FIGHT_PROP_GRASS_ADD_HURT",
"30": "FIGHT_PROP_PHYSICAL_ADD_HURT",
"26": "FIGHT_PROP_HEAL_ADD",
"2000": "FIGHT_PROP_HP",
"2001": "FIGHT_PROP_ATTACK",
"2002": "FIGHT_PROP_DEFENSE"
}

View File

@ -0,0 +1,254 @@
{
"初学者之羽": "UI_RelicIcon_10000_2",
"初学者之花": "UI_RelicIcon_10000_4",
"逐光之石": "UI_RelicIcon_10001_5",
"异国之盏": "UI_RelicIcon_10001_1",
"归乡之羽": "UI_RelicIcon_10001_2",
"感别之冠": "UI_RelicIcon_10001_3",
"故人之心": "UI_RelicIcon_10001_4",
"勇士的壮行": "UI_RelicIcon_10002_1",
"勇士的期许": "UI_RelicIcon_10002_2",
"勇士的冠冕": "UI_RelicIcon_10002_3",
"勇士的勋章": "UI_RelicIcon_10002_4",
"勇士的坚毅": "UI_RelicIcon_10002_5",
"守护之皿": "UI_RelicIcon_10003_1",
"守护徽印": "UI_RelicIcon_10003_2",
"守护束带": "UI_RelicIcon_10003_3",
"守护之花": "UI_RelicIcon_10003_4",
"守护座钟": "UI_RelicIcon_10003_5",
"奇迹之杯": "UI_RelicIcon_10004_1",
"奇迹之羽": "UI_RelicIcon_10004_2",
"奇迹耳坠": "UI_RelicIcon_10004_3",
"奇迹之花": "UI_RelicIcon_10004_4",
"奇迹之沙": "UI_RelicIcon_10004_5",
"战狂的骨杯": "UI_RelicIcon_10005_1",
"战狂的翎羽": "UI_RelicIcon_10005_2",
"战狂的鬼面": "UI_RelicIcon_10005_3",
"战狂的蔷薇": "UI_RelicIcon_10005_4",
"战狂的时计": "UI_RelicIcon_10005_5",
"武人的酒杯": "UI_RelicIcon_10006_1",
"武人的羽饰": "UI_RelicIcon_10006_2",
"武人的头巾": "UI_RelicIcon_10006_3",
"武人的红花": "UI_RelicIcon_10006_4",
"武人的水漏": "UI_RelicIcon_10006_5",
"教官的茶杯": "UI_RelicIcon_10007_1",
"教官的羽饰": "UI_RelicIcon_10007_2",
"教官的帽子": "UI_RelicIcon_10007_3",
"教官的胸花": "UI_RelicIcon_10007_4",
"教官的怀表": "UI_RelicIcon_10007_5",
"赌徒的骰盅": "UI_RelicIcon_10008_1",
"赌徒的羽饰": "UI_RelicIcon_10008_2",
"赌徒的耳环": "UI_RelicIcon_10008_3",
"赌徒的胸花": "UI_RelicIcon_10008_4",
"赌徒的怀表": "UI_RelicIcon_10008_5",
"流放者之杯": "UI_RelicIcon_10009_1",
"流放者之羽": "UI_RelicIcon_10009_2",
"流放者头冠": "UI_RelicIcon_10009_3",
"流放者之花": "UI_RelicIcon_10009_4",
"流放者怀表": "UI_RelicIcon_10009_5",
"冒险家金杯": "UI_RelicIcon_10010_1",
"冒险家尾羽": "UI_RelicIcon_10010_2",
"冒险家头带": "UI_RelicIcon_10010_3",
"冒险家之花": "UI_RelicIcon_10010_4",
"冒险家怀表": "UI_RelicIcon_10010_5",
"幸运儿之杯": "UI_RelicIcon_10011_1",
"幸运儿鹰羽": "UI_RelicIcon_10011_2",
"幸运儿银冠": "UI_RelicIcon_10011_3",
"幸运儿绿花": "UI_RelicIcon_10011_4",
"幸运儿沙漏": "UI_RelicIcon_10011_5",
"学士的墨杯": "UI_RelicIcon_10012_1",
"学士的羽笔": "UI_RelicIcon_10012_2",
"学士的镜片": "UI_RelicIcon_10012_3",
"学士的书签": "UI_RelicIcon_10012_4",
"学士的时钟": "UI_RelicIcon_10012_5",
"游医的药壶": "UI_RelicIcon_10013_1",
"游医的枭羽": "UI_RelicIcon_10013_2",
"游医的方巾": "UI_RelicIcon_10013_3",
"游医的银莲": "UI_RelicIcon_10013_4",
"游医的怀钟": "UI_RelicIcon_10013_5",
"遍结寒霜的傲骨": "UI_RelicIcon_14001_1",
"摧冰而行的执望": "UI_RelicIcon_14001_2",
"破冰踏雪的回音": "UI_RelicIcon_14001_3",
"历经风雪的思念": "UI_RelicIcon_14001_4",
"冰雪故园的终期": "UI_RelicIcon_14001_5",
"平雷之器": "UI_RelicIcon_14002_1",
"平雷之羽": "UI_RelicIcon_14002_2",
"平雷之冠": "UI_RelicIcon_14002_3",
"平雷之心": "UI_RelicIcon_14002_4",
"平雷之刻": "UI_RelicIcon_14002_5",
"渡火者的醒悟": "UI_RelicIcon_14003_1",
"渡火者的解脱": "UI_RelicIcon_14003_2",
"渡火者的智慧": "UI_RelicIcon_14003_3",
"渡火者的决绝": "UI_RelicIcon_14003_4",
"渡火者的煎熬": "UI_RelicIcon_14003_5",
"少女片刻的闲暇": "UI_RelicIcon_14004_1",
"少女飘摇的思念": "UI_RelicIcon_14004_2",
"少女易逝的芳颜": "UI_RelicIcon_14004_3",
"远方的少女之心": "UI_RelicIcon_14004_4",
"少女苦短的良辰": "UI_RelicIcon_14004_5",
"角斗士的酣醉": "UI_RelicIcon_15001_1",
"角斗士的归宿": "UI_RelicIcon_15001_2",
"角斗士的凯旋": "UI_RelicIcon_15001_3",
"角斗士的留恋": "UI_RelicIcon_15001_4",
"角斗士的希冀": "UI_RelicIcon_15001_5",
"翠绿猎人的容器": "UI_RelicIcon_15002_1",
"猎人青翠的箭羽": "UI_RelicIcon_15002_2",
"翠绿的猎人之冠": "UI_RelicIcon_15002_3",
"野花记忆的绿野": "UI_RelicIcon_15002_4",
"翠绿猎人的笃定": "UI_RelicIcon_15002_5",
"吟游者之壶": "UI_RelicIcon_15003_1",
"琴师的箭羽": "UI_RelicIcon_15003_2",
"指挥的礼帽": "UI_RelicIcon_15003_3",
"乐团的晨光": "UI_RelicIcon_15003_4",
"终幕的时计": "UI_RelicIcon_15003_5",
"北风之盏": "UI_RelicIcon_15004_1",
"雪藏之羽": "UI_RelicIcon_15004_2",
"冰河之冠": "UI_RelicIcon_15004_3",
"凛冬霜心": "UI_RelicIcon_15004_4",
"凝冰成砂": "UI_RelicIcon_15004_5",
"降雷的凶兆": "UI_RelicIcon_15005_1",
"雷灾的孑遗": "UI_RelicIcon_15005_2",
"唤雷的头冠": "UI_RelicIcon_15005_3",
"雷鸟的怜悯": "UI_RelicIcon_15005_4",
"雷霆的时计": "UI_RelicIcon_15005_5",
"魔女的心之火": "UI_RelicIcon_15006_1",
"魔女常燃之羽": "UI_RelicIcon_15006_2",
"焦灼的魔女帽": "UI_RelicIcon_15006_3",
"魔女的炎之花": "UI_RelicIcon_15006_4",
"魔女破灭之时": "UI_RelicIcon_15006_5",
"宗室银瓮": "UI_RelicIcon_15007_1",
"宗室之翎": "UI_RelicIcon_15007_2",
"宗室面具": "UI_RelicIcon_15007_3",
"宗室之花": "UI_RelicIcon_15007_4",
"宗室时计": "UI_RelicIcon_15007_5",
"染血骑士之杯": "UI_RelicIcon_15008_1",
"染血的黑之羽": "UI_RelicIcon_15008_2",
"染血的铁假面": "UI_RelicIcon_15008_3",
"染血的铁之心": "UI_RelicIcon_15008_4",
"骑士染血之时": "UI_RelicIcon_15008_5",
"祭火礼冠": "UI_RelicIcon_15009_3",
"祭水礼冠": "UI_RelicIcon_15010_3",
"祭雷礼冠": "UI_RelicIcon_15011_3",
"祭风礼冠": "UI_RelicIcon_15012_3",
"祭冰礼冠": "UI_RelicIcon_15013_3",
"巉岩琢塑之樽": "UI_RelicIcon_15014_1",
"嵯峨群峰之翼": "UI_RelicIcon_15014_2",
"不动玄石之相": "UI_RelicIcon_15014_3",
"磐陀裂生之花": "UI_RelicIcon_15014_4",
"星罗圭璧之晷": "UI_RelicIcon_15014_5",
"夏祭水玉": "UI_RelicIcon_15015_1",
"夏祭终末": "UI_RelicIcon_15015_2",
"夏祭之面": "UI_RelicIcon_15015_3",
"夏祭之花": "UI_RelicIcon_15015_4",
"夏祭之刻": "UI_RelicIcon_15015_5",
"沉波之盏": "UI_RelicIcon_15016_1",
"追忆之风": "UI_RelicIcon_15016_2",
"酒渍船帽": "UI_RelicIcon_15016_3",
"饰金胸花": "UI_RelicIcon_15016_4",
"坚铜罗盘": "UI_RelicIcon_15016_5",
"盟誓金爵": "UI_RelicIcon_15017_1",
"昭武翎羽": "UI_RelicIcon_15017_2",
"将帅兜鍪": "UI_RelicIcon_15017_3",
"勋绩之花": "UI_RelicIcon_15017_4",
"金铜时晷": "UI_RelicIcon_15017_5",
"超越之盏": "UI_RelicIcon_15018_1",
"贤医之羽": "UI_RelicIcon_15018_2",
"嗤笑之面": "UI_RelicIcon_15018_3",
"无垢之花": "UI_RelicIcon_15018_4",
"停摆之刻": "UI_RelicIcon_15018_5",
"祈望之心": "UI_RelicIcon_15019_1",
"思忆之矢": "UI_RelicIcon_15019_2",
"无常之面": "UI_RelicIcon_15019_3",
"羁缠之花": "UI_RelicIcon_15019_4",
"朝露之时": "UI_RelicIcon_15019_5",
"绯花之壶": "UI_RelicIcon_15020_1",
"切落之羽": "UI_RelicIcon_15020_2",
"华饰之兜": "UI_RelicIcon_15020_3",
"明威之镡": "UI_RelicIcon_15020_4",
"雷云之笼": "UI_RelicIcon_15020_5",
"梦醒之瓢": "UI_RelicIcon_15021_1",
"华馆之羽": "UI_RelicIcon_15021_2",
"形骸之笠": "UI_RelicIcon_15021_3",
"荣花之期": "UI_RelicIcon_15021_4",
"众生之谣": "UI_RelicIcon_15021_5",
"真珠之笼": "UI_RelicIcon_15022_1",
"渊宫之羽": "UI_RelicIcon_15022_2",
"海祇之冠": "UI_RelicIcon_15022_3",
"海染之花": "UI_RelicIcon_15022_4",
"离别之贝": "UI_RelicIcon_15022_5",
"结契之刻": "UI_RelicIcon_15023_1",
"潜光片羽": "UI_RelicIcon_15023_2",
"虺雷之姿": "UI_RelicIcon_15023_3",
"生灵之华": "UI_RelicIcon_15023_4",
"阳辔之遗": "UI_RelicIcon_15023_5",
"涌泉之盏": "UI_RelicIcon_15024_1",
"垂玉之叶": "UI_RelicIcon_15024_2",
"浮溯之珏": "UI_RelicIcon_15024_3",
"魂香之花": "UI_RelicIcon_15024_4",
"祝祀之凭": "UI_RelicIcon_15024_5",
"高天的风之主杯": "UI_RelicIcon_15000_1",
"高天的风之主羽": "UI_RelicIcon_15000_2",
"高天的风之主冠": "UI_RelicIcon_15000_3",
"高天的风之主花": "UI_RelicIcon_15000_4",
"高天的风之主沙": "UI_RelicIcon_15000_5",
"迷误者之灯": "UI_RelicIcon_15025_1",
"翠蔓的智者": "UI_RelicIcon_15025_2",
"月桂的宝冠": "UI_RelicIcon_15025_3",
"迷宫的游人": "UI_RelicIcon_15025_4",
"贤智的定期": "UI_RelicIcon_15025_5",
"如蜜的终宴": "UI_RelicIcon_15026_1",
"裁断的翎羽": "UI_RelicIcon_15026_2",
"沙王的投影": "UI_RelicIcon_15026_3",
"梦中的铁花": "UI_RelicIcon_15026_4",
"沉金的岁月": "UI_RelicIcon_15026_5",
"迷醉长梦的守护": "UI_RelicIcon_15027_1",
"黄金邦国的结末": "UI_RelicIcon_15027_2",
"流沙贵嗣的遗宝": "UI_RelicIcon_15027_3",
"众王之都的开端": "UI_RelicIcon_15027_4",
"失落迷途的机芯": "UI_RelicIcon_15027_5",
"守秘的魔瓶": "UI_RelicIcon_15028_1",
"谢落的筵席": "UI_RelicIcon_15028_2",
"紫晶的花冠": "UI_RelicIcon_15028_3",
"月女的华彩": "UI_RelicIcon_15028_4",
"凝结的时刻": "UI_RelicIcon_15028_5",
"勇者们的茶会": "UI_RelicIcon_15029_1",
"坏巫师的羽杖": "UI_RelicIcon_15029_2",
"恶龙的单片镜": "UI_RelicIcon_15029_3",
"旅途中的鲜花": "UI_RelicIcon_15029_4",
"水仙的时时刻刻": "UI_RelicIcon_15029_5",
"无边酣乐之筵": "UI_RelicIcon_15030_1",
"琦色灵彩之羽": "UI_RelicIcon_15030_2",
"灵光明烁之心": "UI_RelicIcon_15030_3",
"灵光源起之蕊": "UI_RelicIcon_15030_4",
"久远花落之时": "UI_RelicIcon_15030_5",
"遗忘的容器": "UI_RelicIcon_15031_1",
"杰作的序曲": "UI_RelicIcon_15031_2",
"老兵的容颜": "UI_RelicIcon_15031_3",
"猎人的胸花": "UI_RelicIcon_15031_4",
"裁判的时刻": "UI_RelicIcon_15031_5",
"黄金之夜的喧嚣": "UI_RelicIcon_15032_1",
"黄金飞鸟的落羽": "UI_RelicIcon_15032_2",
"黄金剧团的奖赏": "UI_RelicIcon_15032_3",
"黄金乐曲的变奏": "UI_RelicIcon_15032_4",
"黄金时代的先声": "UI_RelicIcon_15032_5",
"昔时应许之梦": "UI_RelicIcon_15033_1",
"昔时浮想之思": "UI_RelicIcon_15033_2",
"昔时传奏之诗": "UI_RelicIcon_15033_3",
"昔时遗落之誓": "UI_RelicIcon_15033_4",
"昔时回映之音": "UI_RelicIcon_15033_5",
"慷慨的墨水瓶": "UI_RelicIcon_15034_1",
"诚恳的蘸水笔": "UI_RelicIcon_15034_2",
"慈爱的淑女帽": "UI_RelicIcon_15034_3",
"无私的妆饰花": "UI_RelicIcon_15034_4",
"忠实的砂时计": "UI_RelicIcon_15034_5",
"灵露倾洒的狂诗": "UI_RelicIcon_15035_1",
"古海玄幽的夜想": "UI_RelicIcon_15035_2",
"异想零落的圆舞": "UI_RelicIcon_15035_3",
"谐律交响的前奏": "UI_RelicIcon_15035_4",
"命途轮转的谐谑": "UI_RelicIcon_15035_5",
"筹谋的共樽": "UI_RelicIcon_15036_1",
"褪光的翠尾": "UI_RelicIcon_15036_2",
"失冕的宝冠": "UI_RelicIcon_15036_3",
"暗结的明花": "UI_RelicIcon_15036_4",
"举业的识刻": "UI_RelicIcon_15036_5"
}

View File

@ -72,4 +72,7 @@ pytest = "^7.2.0"
pytest-asyncio = "^0.20.3"
[tool.pyright]
disableBytesTypePromotions = false
disableBytesTypePromotions = false
[tool.basedpyright]
deprecateTypingAliases = false