mirror of
https://github.com/KimigaiiWuyi/GenshinUID.git
synced 2025-05-07 12:43:26 +08:00
✨ 支持网页控制台调整从米游社更新角色面板 (#641)
This commit is contained in:
parent
9d4270d67e
commit
426540cfae
@ -129,4 +129,9 @@ CONIFG_DEFAULT: Dict[str, GSC] = {
|
||||
'修改帮助图有多少列',
|
||||
'6',
|
||||
),
|
||||
'EnableCharCardByMys': GsBoolConfig(
|
||||
'从米游社获取面板替代Enka服务',
|
||||
'开启后角色卡片将从米游社获取, 可能会遇到验证码',
|
||||
False,
|
||||
),
|
||||
}
|
||||
|
@ -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):
|
||||
|
273
GenshinUID/genshinuid_enka/to_data_by_mys.py
Normal file
273
GenshinUID/genshinuid_enka/to_data_by_mys.py
Normal 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
|
@ -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'
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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])
|
||||
|
||||
|
34
GenshinUID/utils/map/data/Id2propId_mapping.json
Normal file
34
GenshinUID/utils/map/data/Id2propId_mapping.json
Normal 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"
|
||||
}
|
254
GenshinUID/utils/map/data/name2Icon_mapping_4.8.0.json
Normal file
254
GenshinUID/utils/map/data/name2Icon_mapping_4.8.0.json
Normal 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"
|
||||
}
|
@ -72,4 +72,7 @@ pytest = "^7.2.0"
|
||||
pytest-asyncio = "^0.20.3"
|
||||
|
||||
[tool.pyright]
|
||||
disableBytesTypePromotions = false
|
||||
disableBytesTypePromotions = false
|
||||
|
||||
[tool.basedpyright]
|
||||
deprecateTypingAliases = false
|
Loading…
x
Reference in New Issue
Block a user