diff --git a/StarRailUID/sruid_utils/api/hakush/__init__.py b/StarRailUID/sruid_utils/api/hakush/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/StarRailUID/sruid_utils/api/hakush/model.py b/StarRailUID/sruid_utils/api/hakush/model.py new file mode 100644 index 0000000..6fa4a25 --- /dev/null +++ b/StarRailUID/sruid_utils/api/hakush/model.py @@ -0,0 +1,112 @@ +from typing import Dict, List, Union + +from msgspec import Struct + + +class HakushHsrCharacterInfoVoiceline(Struct): + VoiceID: int + VoiceTitle: str + VoiceM: str + IsBattleVoice: bool + UnlockDesc: Union[str, None] = None + + +class HakushHsrCharacterInfo(Struct): + Camp: str + VA: Dict[str, str] + Stories: Dict[str, str] + Voicelines: List[HakushHsrCharacterInfoVoiceline] + + +class HakushHsrCharacterRank(Struct): + Id: int + Name: str + Desc: str + ParamList: List[float] + + +class HakushHsrCharacterSkillLevel(Struct): + Level: int + ParamList: List[float] + + +class HakushHsrCharacterSkill(Struct): + Name: str + Desc: str + Type: Union[str, None] + Tag: str + SPBase: Union[float, None] + ShowStanceList: List[float] + SkillComboValueDelta: Union[float, None] + Level: Dict[str, HakushHsrCharacterSkillLevel] + + +class HakushHsrCharacterMaterial(Struct): + ItemID: int + ItemNum: int + + +class HakushHsrCharacterStatusAdd(Struct): + PropertyType: str + Value: float + + +class HakushHsrCharacterSkillTree(Struct): + Anchor: str + DefaultUnlock: bool + Icon: str + LevelUpSkillID: List[int] + MaterialList: List[Union[HakushHsrCharacterMaterial, None]] + MaxLevel: int + ParamList: List[float] + PointID: int + PointName: str + PointDesc: str + PointTriggerKey: int + PointType: int + PrePoint: List[int] + StatusAddList: List[Union[HakushHsrCharacterStatusAdd, None]] + AvatarPromotionLimit: Union[int, None] = None + AvatarLevelLimit: Union[int, None] = None + + +class HakushHsrCharacterStats(Struct): + AttackBase: float + AttackAdd: float + DefenceBase: float + DefenceAdd: float + HPBase: float + HPAdd: float + SpeedBase: float + CriticalChance: float + CriticalDamage: float + BaseAggro: float + Cost: List[Union[HakushHsrCharacterMaterial, None]] + + +class HakushHsrCharacterRelicProperty(Struct): + PropertyType: str + RelicType: str + + +class HakushHsrCharacterRelic(Struct): + AvatarID: int + PropertyList: List[HakushHsrCharacterRelicProperty] + Set2IDList: List[int] + Set4IDList: List[int] + + +class HakushHsrCharacter(Struct): + Name: str + Desc: str + CharaInfo: HakushHsrCharacterInfo + Rarity: str + AvatarVOTag: str + SPNeed: float + BaseType: str + DamageType: str + Ranks: Dict[str, HakushHsrCharacterRank] + Skills: Dict[str, HakushHsrCharacterSkill] + SkillTrees: Dict[str, Dict[str, HakushHsrCharacterSkillTree]] + Stats: Dict[str, HakushHsrCharacterStats] + Relics: HakushHsrCharacterRelic diff --git a/StarRailUID/sruid_utils/api/mihomo/models.py b/StarRailUID/sruid_utils/api/mihomo/models.py index 8efeb1f..6f79d82 100644 --- a/StarRailUID/sruid_utils/api/mihomo/models.py +++ b/StarRailUID/sruid_utils/api/mihomo/models.py @@ -1,55 +1,56 @@ from __future__ import annotations -from typing import TypedDict +from msgspec import Struct, field -class MihomoData(TypedDict): +class MihomoData(Struct): detailInfo: PlayerDetailInfo -class Behavior(TypedDict): +class Behavior(Struct): pointId: int level: int -class Equipment(TypedDict): +class Equipment(Struct): level: int tid: int - promotion: int | None - rank: int | None + promotion: int | None = field(default=0) + rank: int | None = field(default=0) -class Relic(TypedDict): +class Relic(Struct): subAffixList: list[SubAffix] tid: int mainAffixId: int type: int + level: int | None = field(default=0) -class SubAffix(TypedDict): +class SubAffix(Struct): affixId: int cnt: int - step: int + step: int | None = field(default=0) -class Avatar(TypedDict): +class Avatar(Struct): skillTreeList: list[Behavior] - rank: int | None - pos: int | None avatarId: int level: int equipment: Equipment | None relicList: list[Relic] - promotion: int + pos: int | None = field(default=0) + rank: int | None = field(default=0) + promotion: int | None = field(default=0) -class Challenge(TypedDict): +class Challenge(Struct): scheduleMaxLevel: int - MazeGroupIndex: int | None - PreMazeGroupIndex: int | None + MazeGroupIndex: int | None = None + PreMazeGroupIndex: int | None = None -class PlayerSpaceInfo(TypedDict): +class PlayerSpaceInfo(Struct): challengeInfo: Challenge maxRogueChallengeScore: int equipmentCount: int @@ -57,7 +58,7 @@ class PlayerSpaceInfo(TypedDict): achievementCount: int -class PlayerDetailInfo(TypedDict): +class PlayerDetailInfo(Struct): assistAvatarDetail: Avatar platform: str isDisplayAvatar: bool @@ -66,8 +67,8 @@ class PlayerDetailInfo(TypedDict): friendCount: int worldLevel: int nickname: str - Birthday: int | None level: int recordInfo: PlayerSpaceInfo | None headIcon: int - signature: str | None + signature: str | None = None + Birthday: int | None = None diff --git a/StarRailUID/sruid_utils/api/mihomo/requests.py b/StarRailUID/sruid_utils/api/mihomo/requests.py index 47efbc0..a08720a 100644 --- a/StarRailUID/sruid_utils/api/mihomo/requests.py +++ b/StarRailUID/sruid_utils/api/mihomo/requests.py @@ -1,5 +1,6 @@ from __future__ import annotations +from msgspec import convert from httpx import AsyncClient from ..utils import _HEADER @@ -13,4 +14,4 @@ async def get_char_card_info(uid: str) -> MihomoData: timeout=30, ) as client: req = await client.get(f'/sr_info/{uid}') - return req.json() + return convert(req.json(), type=MihomoData) diff --git a/StarRailUID/sruid_utils/api/mys/models.py b/StarRailUID/sruid_utils/api/mys/models.py index 3236b9a..c5aa468 100644 --- a/StarRailUID/sruid_utils/api/mys/models.py +++ b/StarRailUID/sruid_utils/api/mys/models.py @@ -1,11 +1,13 @@ -from typing import Any, Dict, List, Union, TypedDict +from typing import Any, Dict, List, Union + +from msgspec import Struct ################ # 抽卡记录相关 # ################ -class SingleGachaLog(TypedDict): +class SingleGachaLog(Struct): uid: str gacha_id: str gacha_type: str @@ -19,7 +21,7 @@ class SingleGachaLog(TypedDict): id: str -class GachaLog(TypedDict): +class GachaLog(Struct): page: str size: str list: List[SingleGachaLog] @@ -27,7 +29,7 @@ class GachaLog(TypedDict): region_time_zone: int -class RoleBasicInfo(TypedDict): +class RoleBasicInfo(Struct): avatar: str nickname: str region: str @@ -39,7 +41,7 @@ class RoleBasicInfo(TypedDict): ################ -class RogueTime(TypedDict): +class RogueTime(Struct): year: int month: int day: int @@ -48,7 +50,7 @@ class RogueTime(TypedDict): second: int -class RogueAvatar(TypedDict): +class RogueAvatar(Struct): id: int icon: str level: int @@ -56,31 +58,31 @@ class RogueAvatar(TypedDict): element: str -class RogueBaseType(TypedDict): +class RogueBaseType(Struct): id: int name: str cnt: int -class RogueBuffitems(TypedDict): +class RogueBuffitems(Struct): id: int name: str is_evoluted: str rank: int -class RogueMiracles(TypedDict): +class RogueMiracles(Struct): id: int name: str icon: str -class RogueBuffs(TypedDict): +class RogueBuffs(Struct): base_type: RogueBaseType items: List[RogueBuffitems] -class RogueRecordInfo(TypedDict): +class RogueRecordInfo(Struct): name: str finish_time: RogueTime score: int @@ -94,60 +96,63 @@ class RogueRecordInfo(TypedDict): detail_h: Union[int, None] start_h: Union[int, None] + def __setitem__(self, key: str, value: Any) -> None: + self.__dict__[key] = value -class RogueBasic(TypedDict): + +class RogueBasic(Struct): id: int finish_cnt: int schedule_begin: RogueTime schedule_end: RogueTime -class RogueRecord(TypedDict): +class RogueRecord(Struct): basic: RogueBasic records: List[RogueRecordInfo] -class RogueBasicInfo(TypedDict): +class RogueBasicInfo(Struct): unlocked_buff_num: int unlocked_miracle_num: int unlocked_skill_points: int -class LocustCntInfo(TypedDict): +class LocustCntInfo(Struct): narrow: int miracle: int event: int -class LocustDestinyInfo(TypedDict): +class LocustDestinyInfo(Struct): id: int desc: str level: int -class LocustBasicInfo(TypedDict): +class LocustBasicInfo(Struct): cnt: LocustCntInfo destiny: List[LocustDestinyInfo] -class RoleInfo(TypedDict): +class RoleInfo(Struct): server: str nickname: str level: int -class LocustBlocks(TypedDict): +class LocustBlocks(Struct): block_id: int name: str num: int -class LocustFury(TypedDict): +class LocustFury(Struct): type: int point: str -class LocustRecordInfo(TypedDict): +class LocustRecordInfo(Struct): name: str finish_time: RogueTime final_lineup: List[RogueAvatar] @@ -162,19 +167,22 @@ class LocustRecordInfo(TypedDict): detail_h: Union[int, None] start_h: Union[int, None] + def __setitem__(self, key: str, value: Any) -> None: + self.__dict__[key] = value -class LocustRecord(TypedDict): + +class LocustRecord(Struct): records: List[LocustRecordInfo] -class RogueData(TypedDict): +class RogueData(Struct): role: RoleInfo basic_info: RogueBasicInfo current_record: RogueRecord last_record: RogueRecord -class RogueLocustData(TypedDict): +class RogueLocustData(Struct): role: RoleInfo basic: LocustBasicInfo detail: LocustRecord @@ -185,7 +193,7 @@ class RogueLocustData(TypedDict): ################ -class AbyssTime(TypedDict): +class AbyssTime(Struct): year: int month: int day: int @@ -193,7 +201,7 @@ class AbyssTime(TypedDict): minute: int -class AbyssAvatar(TypedDict): +class AbyssAvatar(Struct): id: int level: int icon: str @@ -201,12 +209,12 @@ class AbyssAvatar(TypedDict): element: str -class AbyssNodeDetail(TypedDict): +class AbyssNodeDetail(Struct): challenge_time: AbyssTime avatars: List[AbyssAvatar] -class AbyssFloorDetail(TypedDict): +class AbyssFloorDetail(Struct): name: str round_num: int star_num: int @@ -214,7 +222,7 @@ class AbyssFloorDetail(TypedDict): node_2: List[AbyssNodeDetail] -class AbyssData(TypedDict): +class AbyssData(Struct): schedule_id: int begin_time: AbyssTime end_time: AbyssTime @@ -231,27 +239,27 @@ class AbyssData(TypedDict): ################ -class DataText(TypedDict): +class DataText(Struct): type: str key: str mi18n_key: str -class DayData(TypedDict): +class DayData(Struct): current_hcoin: int current_rails_pass: int last_hcoin: int last_rails_pass: int -class GroupBy(TypedDict): +class GroupBy(Struct): action: str num: int percent: int action_name: str -class MonthData(TypedDict): +class MonthData(Struct): current_hcoin: int current_rails_pass: int last_hcoin: int @@ -261,7 +269,7 @@ class MonthData(TypedDict): group_by: List[GroupBy] -class MonthlyAward(TypedDict): +class MonthlyAward(Struct): uid: str region: str login_flag: bool @@ -278,14 +286,14 @@ class MonthlyAward(TypedDict): ################ # 实时便签 # ################ -class Expedition(TypedDict): +class Expedition(Struct): avatars: List[str] # 头像Url status: str remaining_time: int name: str -class DailyNoteData(TypedDict): +class DailyNoteData(Struct): current_stamina: int max_stamina: int stamina_recover_time: int @@ -294,7 +302,7 @@ class DailyNoteData(TypedDict): expeditions: List[Expedition] -class WidgetStamina(TypedDict): +class WidgetStamina(Struct): current_stamina: int max_stamina: int stamina_recover_time: int @@ -314,7 +322,7 @@ class WidgetStamina(TypedDict): ################ # 签到相关 # ################ -class MysSign(TypedDict): +class MysSign(Struct): code: str risk_code: int gt: str @@ -323,7 +331,7 @@ class MysSign(TypedDict): is_risk: bool -class SignInfo(TypedDict): +class SignInfo(Struct): total_sign_day: int today: str is_sign: bool @@ -333,13 +341,13 @@ class SignInfo(TypedDict): short_sign_day: int -class SignAward(TypedDict): +class SignAward(Struct): icon: str name: str cnt: int -class SignExtraAward(TypedDict): +class SignExtraAward(Struct): has_extra_award: bool start_time: str end_time: str @@ -348,7 +356,7 @@ class SignExtraAward(TypedDict): end_timestamp: str -class SignList(TypedDict): +class SignList(Struct): month: int awards: List[SignAward] biz: str @@ -361,7 +369,7 @@ class SignList(TypedDict): #################### -class Stats(TypedDict): +class Stats(Struct): active_days: int avatar_num: int achievement_num: int @@ -369,7 +377,7 @@ class Stats(TypedDict): abyss_process: str -class AvatarListItem(TypedDict): +class AvatarListItem(Struct): id: int level: int name: str @@ -380,7 +388,7 @@ class AvatarListItem(TypedDict): is_chosen: bool -class RoleIndex(TypedDict): +class RoleIndex(Struct): stats: Stats avatar_list: List[AvatarListItem] @@ -390,7 +398,7 @@ class RoleIndex(TypedDict): ################ -class Equip(TypedDict): +class Equip(Struct): id: int level: int rank: int @@ -399,7 +407,7 @@ class Equip(TypedDict): icon: str -class RelicsItem(TypedDict): +class RelicsItem(Struct): id: int level: int pos: int @@ -409,7 +417,7 @@ class RelicsItem(TypedDict): rarity: int -class RanksItem(TypedDict): +class RanksItem(Struct): id: int pos: int name: str @@ -418,7 +426,7 @@ class RanksItem(TypedDict): is_unlocked: bool -class AvatarListItemDetail(TypedDict): +class AvatarListItemDetail(Struct): id: int level: int name: str @@ -433,7 +441,7 @@ class AvatarListItemDetail(TypedDict): ranks: List[RanksItem] -class AvatarInfo(TypedDict): +class AvatarInfo(Struct): avatar_list: List[AvatarListItemDetail] equip_wiki: Dict[str, str] relic_wiki: Dict diff --git a/StarRailUID/starrailuid_abyss/draw_abyss_card.py b/StarRailUID/starrailuid_abyss/draw_abyss_card.py index bda8468..bdc2d85 100644 --- a/StarRailUID/starrailuid_abyss/draw_abyss_card.py +++ b/StarRailUID/starrailuid_abyss/draw_abyss_card.py @@ -78,9 +78,9 @@ async def _draw_abyss_card( # char_id = char['id'] # # 确认角色头像路径 # char_pic_path = CHAR_ICON_PATH / f'{char_id}.png' - char_bg = (char_bg_4 if char['rarity'] == 4 else char_bg_5).copy() - char_icon = (await get_icon(char['icon'])).resize((151, 170)) - element_icon = elements[char['element']] + char_bg = (char_bg_4 if char.rarity == 4 else char_bg_5).copy() + char_icon = (await get_icon(char.icon)).resize((151, 170)) + element_icon = elements[char.element] char_bg.paste(char_icon, (24, 16), mask=char_icon) char_bg.paste(level_cover, (0, 0), mask=level_cover) char_bg.paste(element_icon, (135, 30), mask=element_icon) @@ -93,7 +93,7 @@ async def _draw_abyss_card( char_card_draw = ImageDraw.Draw(char_bg) char_card_draw.text( (100, 165), - f'等级 {char["level"]}', + f'等级 {char.level}', font=sr_font_22, fill=white_color, anchor='mm', @@ -154,12 +154,12 @@ async def draw_abyss_img( floor_num = 1 if floor > 10: return '楼层不能大于10层!' - if len(raw_abyss_data['all_floor_detail']) < floor: + if len(raw_abyss_data.all_floor_detail) < floor: return '你还没有挑战该层!' else: - if raw_abyss_data['max_floor'] == '': + if raw_abyss_data.max_floor == '': return '你还没有挑战本期深渊!\n可以使用[sr上期深渊]命令查询上期~' - floor_num = len(raw_abyss_data['all_floor_detail']) + floor_num = len(raw_abyss_data.all_floor_detail) # 获取背景图片各项参数 based_w = 900 @@ -193,7 +193,7 @@ async def draw_abyss_img( # 最深抵达 img_draw.text( (220, 565), - f'{raw_abyss_data["max_floor"]}', + f'{raw_abyss_data.max_floor}', white_color, sr_font_34, 'lm', @@ -201,7 +201,7 @@ async def draw_abyss_img( # 挑战次数 img_draw.text( (220, 612), - f'{raw_abyss_data["battle_num"]}', + f'{raw_abyss_data.battle_num}', white_color, sr_font_34, 'lm', @@ -212,34 +212,35 @@ async def draw_abyss_img( img_draw.text( (695, 590), - f'{raw_abyss_data["star_num"]}/30', + f'{raw_abyss_data.star_num}/30', white_color, sr_font_42, 'lm', ) - for index_floor, level in enumerate(raw_abyss_data['all_floor_detail']): + for index_floor, level in enumerate(raw_abyss_data.all_floor_detail): if floor: - if abyss_list[str(floor)] == level['name']: + if abyss_list[str(floor)] == level.name: index_floor = 0 # noqa: PLW2901 else: continue elif index_floor >= 3: break floor_pic = Image.open(TEXT_PATH / 'floor_bg.png') - level_star = level['star_num'] - floor_name = level['name'] - round_num = level['round_num'] + level_star = level.star_num + floor_name = level.name + round_num = level.round_num + node_1 = level.node_1 + node_2 = level.node_2 for index_part in [0, 1]: node_num = index_part + 1 - node = f'node_{node_num}' - # 节点1 - time_array = level[node]['challenge_time'] - time_str = f"{time_array['year']}-{time_array['month']}" - time_str = f"{time_str}-{time_array['day']}" - time_str = ( - f"{time_str} {time_array['hour']}:{time_array['minute']}:00" - ) + if node_num == 1: + time_array = node_1[-1].challenge_time + else: + time_array = node_2[-1].challenge_time + time_str = f'{time_array.year}-{time_array.month}' + time_str = f'{time_str}-{time_array.day}' + time_str = f'{time_str} {time_array.hour}:{time_array.minute}:00' floor_pic_draw = ImageDraw.Draw(floor_pic) floor_pic_draw.text( (112, 120 + index_part * 219), @@ -255,8 +256,12 @@ async def draw_abyss_img( sr_font_22, 'lm', ) + if node_num == 1: + avatars_array = node_1[-1] + else: + avatars_array = node_2[-1] - for index_char, char in enumerate(level[node]['avatars']): + for index_char, char in enumerate(avatars_array.avatars): # 获取命座 # if char["id"] in char_temp: # talent_num = char_temp[char["id"]] diff --git a/StarRailUID/starrailuid_charinfo/to_data.py b/StarRailUID/starrailuid_charinfo/to_data.py index 47e14fd..406c574 100644 --- a/StarRailUID/starrailuid_charinfo/to_data.py +++ b/StarRailUID/starrailuid_charinfo/to_data.py @@ -3,6 +3,7 @@ from pathlib import Path from typing import Dict, List, Union, Optional from httpx import ReadTimeout +from msgspec import json as msgjson from ..utils.error_reply import UID_HINT from ..sruid_utils.api.mihomo import MihomoData @@ -60,42 +61,38 @@ async def api_to_dict( elif sr_data is None: return [] - PlayerDetailInfo = sr_data['detailInfo'] + PlayerDetailInfo = sr_data.detailInfo path = PLAYER_PATH / str(sr_uid) path.mkdir(parents=True, exist_ok=True) - with Path.open(path / f'{sr_uid!s}.json', 'w', encoding='UTF-8') as file: - json.dump(PlayerDetailInfo, file, ensure_ascii=False) - with Path.open(path / 'rawData.json', 'w', encoding='UTF-8') as file: - json.dump(sr_data, file, ensure_ascii=False) + with Path.open(path / f'{sr_uid!s}.json', 'wb') as file: + file.write(msgjson.format(msgjson.encode(PlayerDetailInfo), indent=4)) + with Path.open(path / 'rawData.json', 'wb') as file: + file.write(msgjson.format(msgjson.encode(sr_data), indent=4)) + # json.dump(sr_data, file, ensure_ascii=False) - if 'detailInfo' not in sr_data: + if sr_data.detailInfo is None: return f'SR_UID{sr_uid}刷新失败!未打开角色展柜!' char_name_list = [] char_id_list = [] im = f'UID: {sr_uid} 的角色展柜刷新成功\n' - if PlayerDetailInfo.get('assistAvatarDetail'): - if ( - PlayerDetailInfo['assistAvatarDetail']['avatarId'] - not in char_id_list - ): + if PlayerDetailInfo.assistAvatarDetail: + if PlayerDetailInfo.assistAvatarDetail.avatarId not in char_id_list: char_dict, avatarName = await get_data( - PlayerDetailInfo['assistAvatarDetail'], sr_data, sr_uid + PlayerDetailInfo.assistAvatarDetail, sr_data, sr_uid ) im += f'支援角色 {avatarName}\n' char_name_list.append(avatarName) - char_id_list.append( - PlayerDetailInfo['assistAvatarDetail']['avatarId'] - ) - if PlayerDetailInfo.get('avatarDetailList'): + char_id_list.append(PlayerDetailInfo.assistAvatarDetail.avatarId) + if PlayerDetailInfo.avatarDetailList: im += '星海同行' - if PlayerDetailInfo['avatarDetailList'] is not None: - for char in PlayerDetailInfo['avatarDetailList']: - if char['avatarId'] not in char_id_list: + if PlayerDetailInfo.avatarDetailList is not None: + for char in PlayerDetailInfo.avatarDetailList: + if char.avatarId not in char_id_list: _, avatarName = await get_data(char, sr_data, sr_uid) im += f' {avatarName}' char_name_list.append(avatarName) - char_id_list.append(char['avatarId']) + char_id_list.append(char.avatarId) if not char_name_list: return f'UID: {sr_uid} 的角色展柜刷新失败!\n请检查UID是否正确或者角色展柜是否打开!' @@ -104,33 +101,31 @@ async def api_to_dict( async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str): - PlayerDetailInfo = sr_data['detailInfo'] + PlayerDetailInfo = sr_data.detailInfo path = PLAYER_PATH / str(sr_uid) # 处理基本信息 char_data = { 'uid': str(sr_uid), - 'nickName': PlayerDetailInfo['nickname'], - 'avatarId': char['avatarId'], - 'avatarName': avatarId2Name[str(char['avatarId'])], - 'avatarElement': avatarId2DamageType[str(char['avatarId'])], - 'avatarRarity': avatarId2Rarity[str(char['avatarId'])], - 'avatarPromotion': char.get('promotion', 0), - 'avatarLevel': char['level'], + 'nickName': PlayerDetailInfo.nickname, + 'avatarId': char.avatarId, + 'avatarName': avatarId2Name[str(char.avatarId)], + 'avatarElement': avatarId2DamageType[str(char.avatarId)], + 'avatarRarity': avatarId2Rarity[str(char.avatarId)], + 'avatarPromotion': char.promotion, + 'avatarLevel': char.level, 'avatarSkill': [], 'avatarExtraAbility': [], 'avatarAttributeBonus': [], 'RelicInfo': [], } - avatarName = avatarId2Name[str(char['avatarId'])] - char_data['avatarEnName'] = avatarId2EnName[str(char['avatarId'])] + avatarName = avatarId2Name[str(char.avatarId)] + char_data['avatarEnName'] = avatarId2EnName[str(char.avatarId)] # 处理技能 - for behavior in char['skillTreeList']: + for behavior in char.skillTreeList: # 处理技能 - if f'{char["avatarId"]}0' == str(behavior['pointId'])[0:5]: + if f'{char.avatarId}0' == str(behavior.pointId)[0:5]: skill_temp = {} - skill_temp['skillId'] = ( - char['avatarId'] * 100 + behavior['pointId'] % 10 - ) + skill_temp['skillId'] = char.avatarId * 100 + behavior.pointId % 10 skill_temp['skillName'] = skillId2Name[str(skill_temp['skillId'])] skill_temp['skillEffect'] = skillId2Effect[ str(skill_temp['skillId']) @@ -138,24 +133,24 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str): skill_temp['skillAttackType'] = skillId2AttackType[ str(skill_temp['skillId']) ] - skill_temp['skillLevel'] = behavior['level'] + skill_temp['skillLevel'] = behavior.level char_data['avatarSkill'].append(skill_temp) # 处理技能树中的额外能力 - if f'{char["avatarId"]}1' == str(behavior['pointId'])[0:5]: + if f'{char.avatarId}1' == str(behavior.pointId)[0:5]: extra_ability_temp = {} - extra_ability_temp['extraAbilityId'] = behavior['pointId'] - extra_ability_temp['extraAbilityLevel'] = behavior['level'] + extra_ability_temp['extraAbilityId'] = behavior.pointId + extra_ability_temp['extraAbilityLevel'] = behavior.level char_data['avatarExtraAbility'].append(extra_ability_temp) # 处理技能树中的属性加成 - if f'{char["avatarId"]}2' == str(behavior['pointId'])[0:5]: + if f'{char.avatarId}2' == str(behavior.pointId)[0:5]: attribute_bonus_temp = {} - attribute_bonus_temp['attributeBonusId'] = behavior['pointId'] - attribute_bonus_temp['attributeBonusLevel'] = behavior['level'] - status_add = characterSkillTree[str(char['avatarId'])][ - str(behavior['pointId']) - ]['levels'][behavior['level'] - 1]['properties'] + attribute_bonus_temp['attributeBonusId'] = behavior.pointId + attribute_bonus_temp['attributeBonusLevel'] = behavior.level + status_add = characterSkillTree[str(char.avatarId)][ + str(behavior.pointId) + ]['levels'][behavior.level - 1]['properties'] attribute_bonus_temp['statusAdd'] = {} if status_add: for property_ in status_add: @@ -173,23 +168,23 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str): ) # 处理遗器 - if char.get('relicList'): - for relic in char['relicList']: + if char.relicList: + for relic in char.relicList: relic_temp = {} - relic_temp['relicId'] = relic['tid'] - relic_temp['relicName'] = ItemId2Name[str(relic['tid'])] - relic_temp['SetId'] = int(RelicId2SetId[str(relic['tid'])]) + relic_temp['relicId'] = relic.tid + relic_temp['relicName'] = ItemId2Name[str(relic.tid)] + relic_temp['SetId'] = int(RelicId2SetId[str(relic.tid)]) relic_temp['SetName'] = SetId2Name[str(relic_temp['SetId'])] - relic_temp['Level'] = relic['level'] if 'level' in relic else 0 - relic_temp['Type'] = relic['type'] + relic_temp['Level'] = relic.level if relic.level else 0 + relic_temp['Type'] = relic.type relic_temp['MainAffix'] = {} - relic_temp['MainAffix']['AffixID'] = relic['mainAffixId'] + relic_temp['MainAffix']['AffixID'] = relic.mainAffixId affix_property, value = await cal_relic_main_affix( - relic_id=relic['tid'], + relic_id=relic.tid, set_id=str(relic_temp['SetId']), - affix_id=relic['mainAffixId'], - relic_type=relic['type'], + affix_id=relic.mainAffixId, + relic_type=relic.type, relic_level=relic_temp['Level'], ) relic_temp['MainAffix']['Property'] = affix_property @@ -197,21 +192,21 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str): relic_temp['MainAffix']['Value'] = value relic_temp['SubAffixList'] = [] - if relic.get('subAffixList'): - for sub_affix in relic['subAffixList']: + if relic.subAffixList: + for sub_affix in relic.subAffixList: sub_affix_temp = {} - sub_affix_temp['SubAffixID'] = sub_affix['affixId'] + sub_affix_temp['SubAffixID'] = sub_affix.affixId sub_affix_property, value = await cal_relic_sub_affix( - relic_id=relic['tid'], - affix_id=sub_affix['affixId'], - cnt=sub_affix['cnt'], - step=sub_affix['step'] if 'step' in sub_affix else 0, + relic_id=relic.tid, + affix_id=sub_affix.affixId, + cnt=sub_affix.cnt, + step=sub_affix.step if sub_affix.step else 0, ) sub_affix_temp['Property'] = sub_affix_property sub_affix_temp['Name'] = Property2Name[sub_affix_property] - sub_affix_temp['Cnt'] = sub_affix['cnt'] + sub_affix_temp['Cnt'] = sub_affix.cnt sub_affix_temp['Step'] = ( - sub_affix['step'] if 'step' in sub_affix else 0 + sub_affix.step if sub_affix.step else 0 ) sub_affix_temp['Value'] = value relic_temp['SubAffixList'].append(sub_affix_temp) @@ -219,11 +214,11 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str): # 处理命座 rank_temp = [] - if char.get('rank') and char['rank'] is not None: - char_data['rank'] = char['rank'] - for index in range(char['rank']): + if char.rank and char.rank is not None: + char_data['rank'] = char.rank + for index in range(char.rank): rankTemp = {} - rank_id = int(str(char['avatarId']) + '0' + str(index + 1)) + rank_id = int(str(char.avatarId) + '0' + str(index + 1)) rankTemp['rankId'] = rank_id rankTemp['rankName'] = rankId2Name[str(rank_id)] rank_temp.append(rankTemp) @@ -250,24 +245,24 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str): # 处理基础属性 base_attributes = {} - avatar_promotion_base = AvatarPromotionConfig.Avatar[ - str(char['avatarId']) - ][str(char.get('promotion', 0))] + avatar_promotion_base = AvatarPromotionConfig.Avatar[str(char.avatarId)][ + str(char.promotion) + ] # 攻击力 base_attributes['attack'] = ( avatar_promotion_base.AttackBase.Value - + avatar_promotion_base.AttackAdd.Value * (char['level'] - 1) + + avatar_promotion_base.AttackAdd.Value * (char.level - 1) ) # 防御力 base_attributes['defence'] = ( avatar_promotion_base.DefenceBase.Value - + avatar_promotion_base.DefenceAdd.Value * (char['level'] - 1) + + avatar_promotion_base.DefenceAdd.Value * (char.level - 1) ) # 血量 base_attributes['hp'] = ( avatar_promotion_base.HPBase.Value - + avatar_promotion_base.HPAdd.Value * (char['level'] - 1) + + avatar_promotion_base.HPAdd.Value * (char.level - 1) ) # 速度 base_attributes['speed'] = avatar_promotion_base.SpeedBase.Value @@ -287,42 +282,40 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str): # 处理武器 equipment_info = {} - if char.get('equipment') and char['equipment'] is not None: - equipment_info['equipmentID'] = char['equipment']['tid'] + if char.equipment and char.equipment is not None: + equipment_info['equipmentID'] = char.equipment.tid equipment_info['equipmentName'] = EquipmentID2Name[ - str(char['equipment']['tid']) + str(char.equipment.tid) ] - equipment_info['equipmentLevel'] = char['equipment']['level'] - equipment_info['equipmentPromotion'] = char['equipment'].get( - 'promotion', 0 - ) - equipment_info['equipmentRank'] = char['equipment']['rank'] + equipment_info['equipmentLevel'] = char.equipment.level + equipment_info['equipmentPromotion'] = char.equipment.promotion + equipment_info['equipmentRank'] = char.equipment.rank equipment_info['equipmentRarity'] = EquipmentID2Rarity[ - str(char['equipment']['tid']) + str(char.equipment.tid) ] equipment_base_attributes = {} equipment_promotion_base = EquipmentPromotionConfig.Equipment[ - str(char['equipment']['tid']) + str(char.equipment.tid) ][str(equipment_info['equipmentPromotion'])] # 生命值 equipment_base_attributes['hp'] = ( equipment_promotion_base.BaseHP.Value + equipment_promotion_base.BaseHPAdd.Value - * (char['equipment']['level'] - 1) + * (char.equipment.level - 1) ) # 攻击力 equipment_base_attributes['attack'] = ( equipment_promotion_base.BaseAttack.Value + equipment_promotion_base.BaseAttackAdd.Value - * (char['equipment']['level'] - 1) + * (char.equipment.level - 1) ) # 防御力 equipment_base_attributes['defence'] = ( equipment_promotion_base.BaseDefence.Value + equipment_promotion_base.BaseDefenceAdd.Value - * (char['equipment']['level'] - 1) + * (char.equipment.level - 1) ) equipment_info['baseAttributes'] = equipment_base_attributes diff --git a/StarRailUID/starrailuid_gachalog/get_gachalogs.py b/StarRailUID/starrailuid_gachalog/get_gachalogs.py index abdba69..6176d33 100644 --- a/StarRailUID/starrailuid_gachalog/get_gachalogs.py +++ b/StarRailUID/starrailuid_gachalog/get_gachalogs.py @@ -34,10 +34,10 @@ async def get_new_gachalog_by_link( ) if isinstance(data, int): return {} - data = data['list'] + data = data.list if not data: break - end_id = data[-1]['id'] + end_id = data[-1].id if data[-1] in full_data[gacha_name] and not is_force: for item in data: if item not in full_data[gacha_name]: @@ -46,9 +46,7 @@ async def get_new_gachalog_by_link( temp = [] break if len(full_data[gacha_name]) >= 1: - if int(data[-1]['id']) <= int( - full_data[gacha_name][0]['id'] - ): + if int(data[-1].id) <= int(full_data[gacha_name][0]['id']): full_data[gacha_name].extend(data) else: full_data[gacha_name][0:0] = data diff --git a/StarRailUID/starrailuid_note/draw_note_card.py b/StarRailUID/starrailuid_note/draw_note_card.py index 09eef2e..0132c31 100644 --- a/StarRailUID/starrailuid_note/draw_note_card.py +++ b/StarRailUID/starrailuid_note/draw_note_card.py @@ -96,19 +96,19 @@ async def draw_note_img(sr_uid: str) -> Union[bytes, str]: role_basic_info = await mys_api.get_role_basic_info(sr_uid) if isinstance(role_basic_info, int): return get_error(role_basic_info) - nickname = role_basic_info['nickname'] + nickname = role_basic_info.nickname - day_hcoin = data['day_data']['current_hcoin'] - day_rails_pass = data['day_data']['current_rails_pass'] + day_hcoin = data.day_data.current_hcoin + day_rails_pass = data.day_data.current_rails_pass lastday_hcoin = 0 lastday_rails_pass = 0 if int(sr_uid[0]) < 6: - lastday_hcoin = data['day_data']['last_hcoin'] - lastday_rails_pass = data['day_data']['last_rails_pass'] - month_hcoin = data['month_data']['current_hcoin'] - month_rails_pass = data['month_data']['current_rails_pass'] - lastmonth_hcoin = data['month_data']['last_hcoin'] - lastmonth_rails_pass = data['month_data']['last_rails_pass'] + lastday_hcoin = data.day_data.last_hcoin + lastday_rails_pass = data.day_data.last_rails_pass + month_hcoin = data.month_data.current_hcoin + month_rails_pass = data.month_data.current_rails_pass + lastmonth_hcoin = data.month_data.last_hcoin + lastmonth_rails_pass = data.month_data.last_rails_pass day_hcoin_str = await int_carry(day_hcoin) day_rails_pass_str = await int_carry(day_rails_pass) @@ -214,21 +214,21 @@ async def draw_note_img(sr_uid: str) -> Union[bytes, str]: ) xy = ((0, 0), (2100, 2100)) temp = -90 - if not data['month_data']['group_by']: + if not data.month_data.group_by: pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image_draw = ImageDraw.Draw(pie_image) pie_image_draw.ellipse(xy, fill=(128, 128, 128)) else: pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image_draw = ImageDraw.Draw(pie_image) - for _index, i in enumerate(data['month_data']['group_by']): + for _index, i in enumerate(data.month_data.group_by): pie_image_draw.pieslice( xy, temp, - temp + (i['percent'] / 100) * 360, - COLOR_MAP[i['action_name']], + temp + (i.percent / 100) * 360, + COLOR_MAP[i.action_name], ) - temp = temp + (i['percent'] / 100) * 360 + temp = temp + (i.percent / 100) * 360 # 绘制蒙版圆形 new_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image_draw.ellipse((150, 150, 1950, 1950), fill=(255, 255, 255, 0)) @@ -241,16 +241,14 @@ async def draw_note_img(sr_uid: str) -> Union[bytes, str]: if last_monthly_data: pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image_draw = ImageDraw.Draw(pie_image) - for _index, i in enumerate( - last_monthly_data['month_data']['group_by'] - ): + for _index, i in enumerate(last_monthly_data.month_data.group_by): pie_image_draw.pieslice( xy, temp, - temp + (i['percent'] / 100) * 360, - COLOR_MAP[i['action_name']], + temp + (i.percent / 100) * 360, + COLOR_MAP[i.action_name], ) - temp = temp + (i['percent'] / 100) * 360 + temp = temp + (i.percent / 100) * 360 else: pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image_draw = ImageDraw.Draw(pie_image) diff --git a/StarRailUID/starrailuid_note/note_text.py b/StarRailUID/starrailuid_note/note_text.py index 9dad63b..c78ef07 100644 --- a/StarRailUID/starrailuid_note/note_text.py +++ b/StarRailUID/starrailuid_note/note_text.py @@ -27,26 +27,26 @@ async def award(uid) -> str: data = await mys_api.get_award(uid, datetime.now().month) if isinstance(data, int): return get_error(data) - day_hcoin = data['day_data']['current_hcoin'] - day_rails_pass = data['day_data']['current_rails_pass'] + day_hcoin = data.day_data.current_hcoin + day_rails_pass = data.day_data.current_rails_pass lastday_hcoin = 0 lastday_rails_pass = 0 if int(uid[0]) < 6: - lastday_hcoin = data['day_data']['last_hcoin'] - lastday_rails_pass = data['day_data']['last_rails_pass'] - month_stone = data['month_data']['current_hcoin'] - month_rails_pass = data['month_data']['current_rails_pass'] - lastmonth_stone = data['month_data']['last_hcoin'] - lastmonth_rails_pass = data['month_data']['last_rails_pass'] + lastday_hcoin = data.day_data.last_hcoin + lastday_rails_pass = data.day_data.last_rails_pass + month_stone = data.month_data.current_hcoin + month_rails_pass = data.month_data.current_rails_pass + lastmonth_stone = data.month_data.last_hcoin + lastmonth_rails_pass = data.month_data.last_rails_pass group_str = '' - for i in data['month_data']['group_by']: + for i in data.month_data.group_by: group_str = ( group_str - + i['action_name'] + + i.action_name + ':' - + str(i['num']) + + str(i.num) + '(' - + str(i['percent']) + + str(i.percent) + '%)' + '\n' ) diff --git a/StarRailUID/starrailuid_rogue/draw_rogue_card.py b/StarRailUID/starrailuid_rogue/draw_rogue_card.py index 9e6e797..b2bff6b 100644 --- a/StarRailUID/starrailuid_rogue/draw_rogue_card.py +++ b/StarRailUID/starrailuid_rogue/draw_rogue_card.py @@ -117,12 +117,12 @@ async def _draw_rogue_buff( zb_list.append([m, n]) jishu = 0 for item in buffs: - if item['is_evoluted'] is True: + if item.is_evoluted is True: is_evoluted = 1 else: is_evoluted = 0 buff_bg = Image.open( - TEXT_PATH / f'zhufu_{item["rank"]}_{is_evoluted}.png' + TEXT_PATH / f'zhufu_{item.rank}_{is_evoluted}.png' ) buff_bg = buff_bg.resize((233, 35)) z_left = 90 + 240 * zb_list[jishu][1] @@ -131,7 +131,7 @@ async def _draw_rogue_buff( floor_pic.paste(buff_bg, (z_left, z_top), mask=buff_bg) floor_pic_draw.text( (z_left + 115, z_top + 18), - item['name'], + item.name, font=sr_font_22, fill=white_color, anchor='mm', @@ -155,7 +155,7 @@ async def _draw_rogue_blocks( zb_list.append([m, n]) jishu = 0 for block in blocks: - block_icon = Image.open(TEXT_PATH / f'{block["name"]}.png') + block_icon = Image.open(TEXT_PATH / f'{block.name}.png') z_left_bg = 90 + 357 * zb_list[jishu][1] z_top_bg = buff_height + 470 + 80 * zb_list[jishu][0] jishu = jishu + 1 @@ -164,7 +164,7 @@ async def _draw_rogue_blocks( floor_pic.paste(block_icon, (z_left_icon, z_top_icon), mask=block_icon) floor_pic_draw.text( (z_left_bg + 80, z_top_bg + 35), - f"{block['name']} x{block['num']}", + f'{block.name} x{block.num}', font=sr_font_22, fill=white_color, anchor='lm', @@ -187,7 +187,7 @@ async def _draw_rogue_miracles( zb_list.append([m, n]) jishu = 0 for miracle in miracles: - miracles_icon = (await get_icon(miracle['icon'])).resize((80, 80)) + miracles_icon = (await get_icon(miracle.icon)).resize((80, 80)) z_left = 90 + 90 * zb_list[jishu][1] z_top = buff_height + 470 + 90 * zb_list[jishu][0] jishu = jishu + 1 @@ -205,9 +205,9 @@ async def _draw_rogue_card( # char_id = char['id'] # # 确认角色头像路径 # char_pic_path = CHAR_ICON_PATH / f'{char_id}.png' - char_bg = (char_bg_4 if char['rarity'] == 4 else char_bg_5).copy() - char_icon = (await get_icon(char['icon'])).resize((151, 170)) - element_icon = elements[char['element']] + char_bg = (char_bg_4 if char.rarity == 4 else char_bg_5).copy() + char_icon = (await get_icon(char.icon)).resize((151, 170)) + element_icon = elements[char.element] char_bg.paste(char_icon, (24, 16), mask=char_icon) char_bg.paste(level_cover, (0, 0), mask=level_cover) char_bg.paste(element_icon, (135, 30), mask=element_icon) @@ -220,7 +220,7 @@ async def _draw_rogue_card( char_card_draw = ImageDraw.Draw(char_bg) char_card_draw.text( (100, 165), - f'等级 {char["level"]}', + f'等级 {char.level}', font=sr_font_22, fill=white_color, anchor='mm', @@ -245,9 +245,9 @@ async def draw_rogue_img( # 计算背景图尺寸 if schedule_type == '3': - rogue_detail = raw_rogue_data['current_record']['records'] + rogue_detail = raw_rogue_data.current_record.records else: - rogue_detail = raw_rogue_data['last_record']['records'] + rogue_detail = raw_rogue_data.last_record.records # 记录打的宇宙列表 detail_list = [] @@ -256,23 +256,23 @@ async def draw_rogue_img( # 100+70+170 # 头+底+角色 detail_h = 340 - progress = detail['progress'] + progress = detail.progress detail_list.append(progress) # 祝福 - if len(detail['base_type_list']) > 0: + if len(detail.base_type_list) > 0: buff_h = 60 - for buff in detail['buffs']: + for buff in detail.buffs: buff_h = buff_h + 50 - buff_num = len(buff['items']) + buff_num = len(buff.items) buff_h = buff_h + math.ceil(buff_num / 3) * 55 else: buff_h = 0 detail_h = detail_h + buff_h # 奇物 - if len(detail['miracles']) > 0: + if len(detail.miracles) > 0: miracles_h = 60 - miracles_num = len(detail['miracles']) + miracles_num = len(detail.miracles) miracles_h = miracles_h + math.ceil(miracles_num / 8) * 90 else: miracles_h = 0 @@ -292,9 +292,9 @@ async def draw_rogue_img( if floor not in detail_list: return '你还没有挑战该模拟宇宙!' elif schedule_type == '3': - if raw_rogue_data['current_record']['basic']['finish_cnt'] == 0: + if raw_rogue_data.current_record.basic.finish_cnt == 0: return '你还没有挑战本期模拟宇宙!\n可以使用[sr上期模拟宇宙]命令查询上期~' - elif raw_rogue_data['last_record']['basic']['finish_cnt'] == 0: + elif raw_rogue_data.last_record.basic.finish_cnt == 0: return '你还没有挑战上期模拟宇宙!\n可以使用[sr模拟宇宙]命令查询本期~' # 获取背景图片各项参数 @@ -326,7 +326,7 @@ async def draw_rogue_img( # 技能树激活 img_draw.text( (165, 569), - f'{raw_rogue_data["basic_info"]["unlocked_skill_points"]}', + f'{raw_rogue_data.basic_info.unlocked_skill_points}', white_color, sr_font_42, 'mm', @@ -342,7 +342,7 @@ async def draw_rogue_img( # 奇物解锁 img_draw.text( (450, 569), - f'{raw_rogue_data["basic_info"]["unlocked_miracle_num"]}', + f'{raw_rogue_data.basic_info.unlocked_miracle_num}', white_color, sr_font_42, 'mm', @@ -358,7 +358,7 @@ async def draw_rogue_img( # 祝福解锁 img_draw.text( (730, 569), - f'{raw_rogue_data["basic_info"]["unlocked_buff_num"]}', + f'{raw_rogue_data.basic_info.unlocked_buff_num}', white_color, sr_font_42, 'mm', @@ -373,16 +373,16 @@ async def draw_rogue_img( for index_floor, detail in enumerate(rogue_detail): if floor: - if floor == detail['progress']: + if floor == detail.progress: index_floor = 0 # noqa: PLW2901 else: continue - if detail['detail_h'] is None: + if detail.detail_h is None: continue floor_pic = Image.open(TEXT_PATH / 'detail_bg.png').convert('RGBA') - floor_pic = floor_pic.resize((900, detail['detail_h'])) + floor_pic = floor_pic.resize((900, detail.detail_h)) floor_top_pic = Image.open(TEXT_PATH / 'floor_bg_top.png').convert( 'RGBA' @@ -393,7 +393,7 @@ async def draw_rogue_img( TEXT_PATH / 'floor_bg_center.png' ).convert('RGBA') floor_center_pic = floor_center_pic.resize( - (900, detail['detail_h'] - 170) + (900, detail.detail_h - 170) ) floor_pic.paste(floor_center_pic, (0, 100), floor_center_pic) @@ -401,16 +401,16 @@ async def draw_rogue_img( 'RGBA' ) floor_pic.paste( - floor_bot_pic, (0, detail['detail_h'] - 70), floor_bot_pic + floor_bot_pic, (0, detail.detail_h - 70), floor_bot_pic ) - floor_name = progresslist[detail['progress']] - difficulty_name = difficultylist[detail['difficulty']] + floor_name = progresslist[detail.progress] + difficulty_name = difficultylist[detail.difficulty] - time_array = detail['finish_time'] - time_str = f"{time_array['year']}-{time_array['month']}" - time_str = f"{time_str}-{time_array['day']}" - time_str = f"{time_str} {time_array['hour']}:{time_array['minute']}" + time_array = detail.finish_time + time_str = f'{time_array.year}-{time_array.month}' + time_str = f'{time_str}-{time_array.day}' + time_str = f'{time_str} {time_array.hour}:{time_array.minute}' floor_pic_draw = ImageDraw.Draw(floor_pic) floor_pic_draw.text( (450, 60), @@ -428,14 +428,14 @@ async def draw_rogue_img( ) floor_pic_draw.text( (800, 120), - f'当前积分:{detail["score"]}', + f'当前积分:{detail.score}', gray_color, sr_font_22, 'rm', ) # 角色 - for index_char, char in enumerate(detail['final_lineup']): + for index_char, char in enumerate(detail.final_lineup): # 获取命座 # if char["id"] in char_temp: # talent_num = char_temp[char["id"]] @@ -456,7 +456,7 @@ async def draw_rogue_img( # 祝福 buff_height = 0 - if len(detail['base_type_list']) > 0: + if len(detail.base_type_list) > 0: floor_pic_draw.text( (93, 370), '获得祝福', @@ -465,10 +465,10 @@ async def draw_rogue_img( 'lm', ) floor_pic.paste(content_center, (0, 390), content_center) - for buff in detail['buffs']: - buff_icon = bufflist[buff['base_type']['id']] - buff_name = buff['base_type']['name'] - buffs = buff['items'] + for buff in detail.buffs: + buff_icon = bufflist[buff.base_type.id] + buff_name = buff.base_type.name + buffs = buff.items draw_height = await _draw_rogue_buff( buffs, buff_icon, @@ -479,7 +479,7 @@ async def draw_rogue_img( buff_height = buff_height + draw_height # 奇物 - if len(detail['miracles']) > 0: + if len(detail.miracles) > 0: floor_pic_draw.text( (93, 370 + buff_height + 60), '获得奇物', @@ -491,15 +491,15 @@ async def draw_rogue_img( content_center, (0, 370 + buff_height + 80), content_center ) await _draw_rogue_miracles( - detail['miracles'], + detail.miracles, floor_pic, buff_height, ) - if detail['start_h'] is None: + if detail.start_h is None: continue - img.paste(floor_pic, (0, detail['start_h']), floor_pic) + img.paste(floor_pic, (0, detail.start_h), floor_pic) # await _draw_floor_card( # level_star, # floor_pic, @@ -531,7 +531,7 @@ async def draw_rogue_locust_img( # char_temp = {} # 计算背景图尺寸 - rogue_detail = raw_rogue_data['detail']['records'] + rogue_detail = raw_rogue_data.detail.records # 记录打的宇宙列表 # detail_list = [] @@ -542,20 +542,20 @@ async def draw_rogue_locust_img( detail_h = 340 # 祝福 - if len(detail['base_type_list']) > 0: + if len(detail.base_type_list) > 0: buff_h = 60 - for buff in detail['buffs']: + for buff in detail.buffs: buff_h = buff_h + 50 - buff_num = len(buff['items']) + buff_num = len(buff.items) buff_h = buff_h + math.ceil(buff_num / 3) * 55 else: buff_h = 0 detail_h = detail_h + buff_h # 奇物 - if len(detail['miracles']) > 0: + if len(detail.miracles) > 0: miracles_h = 60 - miracles_num = len(detail['miracles']) + miracles_num = len(detail.miracles) miracles_h = miracles_h + math.ceil(miracles_num / 8) * 90 else: miracles_h = 0 @@ -563,9 +563,9 @@ async def draw_rogue_locust_img( # 事件 blocks_h = 0 - if len(detail['blocks']) > 0: + if len(detail.blocks) > 0: blocks_h = 60 - blocks_num = len(detail['blocks']) + blocks_num = len(detail.blocks) blocks_h = blocks_h + math.ceil(blocks_num / 2) * 80 else: blocks_num = 0 @@ -608,7 +608,7 @@ async def draw_rogue_locust_img( # 行者之道激活 img_draw.text( (165, 569), - f'{raw_rogue_data["basic"]["cnt"]["narrow"]}', + f'{raw_rogue_data.basic.cnt.narrow}', white_color, sr_font_42, 'mm', @@ -624,7 +624,7 @@ async def draw_rogue_locust_img( # 奇物解锁 img_draw.text( (450, 569), - f'{raw_rogue_data["basic"]["cnt"]["miracle"]}', + f'{raw_rogue_data.basic.cnt.miracle}', white_color, sr_font_42, 'mm', @@ -640,7 +640,7 @@ async def draw_rogue_locust_img( # 事件解锁 img_draw.text( (730, 569), - f'{raw_rogue_data["basic"]["cnt"]["event"]}', + f'{raw_rogue_data.basic.cnt.event}', white_color, sr_font_42, 'mm', @@ -654,11 +654,11 @@ async def draw_rogue_locust_img( ) for _, detail in enumerate(rogue_detail): - if detail['detail_h'] is None: + if detail.detail_h is None: continue floor_pic = Image.open(TEXT_PATH / 'detail_bg.png').convert('RGBA') - floor_pic = floor_pic.resize((900, detail['detail_h'])) + floor_pic = floor_pic.resize((900, detail.detail_h)) floor_top_pic = Image.open(TEXT_PATH / 'floor_bg_top.png').convert( 'RGBA' @@ -669,7 +669,7 @@ async def draw_rogue_locust_img( TEXT_PATH / 'floor_bg_center.png' ).convert('RGBA') floor_center_pic = floor_center_pic.resize( - (900, detail['detail_h'] - 170) + (900, detail.detail_h - 170) ) floor_pic.paste(floor_center_pic, (0, 100), floor_center_pic) @@ -677,16 +677,16 @@ async def draw_rogue_locust_img( 'RGBA' ) floor_pic.paste( - floor_bot_pic, (0, detail['detail_h'] - 70), floor_bot_pic + floor_bot_pic, (0, detail.detail_h - 70), floor_bot_pic ) - floor_name = detail['name'] - difficulty_name = difficultylist[detail['difficulty']] + floor_name = detail.name + difficulty_name = difficultylist[detail.difficulty] - time_array = detail['finish_time'] - time_str = f"{time_array['year']}-{time_array['month']}" - time_str = f"{time_str}-{time_array['day']}" - time_str = f"{time_str} {time_array['hour']}:{time_array['minute']}" + time_array = detail.finish_time + time_str = f'{time_array.year}-{time_array.month}' + time_str = f'{time_str}-{time_array.day}' + time_str = f'{time_str} {time_array.hour}:{time_array.minute}' floor_pic_draw = ImageDraw.Draw(floor_pic) floor_pic_draw.text( (450, 60), @@ -702,10 +702,10 @@ async def draw_rogue_locust_img( sr_font_22, 'lm', ) - if detail['fury']['type'] == 1: + if detail.fury.type == 1: floor_pic_draw.text( (800, 120), - f'扰动等级:{detail["fury"]["point"]}', + f'扰动等级:{detail.fury.point}', gray_color, sr_font_22, 'rm', @@ -713,14 +713,14 @@ async def draw_rogue_locust_img( else: floor_pic_draw.text( (800, 120), - f'位面紊乱倒计时:{detail["fury"]["point"]}', + f'位面紊乱倒计时:{detail.fury.point}', gray_color, sr_font_22, 'rm', ) # 角色 - for index_char, char in enumerate(detail['final_lineup']): + for index_char, char in enumerate(detail.final_lineup): # 获取命座 # if char["id"] in char_temp: # talent_num = char_temp[char["id"]] @@ -741,7 +741,7 @@ async def draw_rogue_locust_img( # 祝福 buff_height = 0 - if len(detail['base_type_list']) > 0: + if len(detail.base_type_list) > 0: floor_pic_draw.text( (93, 370), '获得祝福', @@ -750,10 +750,10 @@ async def draw_rogue_locust_img( 'lm', ) floor_pic.paste(content_center, (0, 390), content_center) - for buff in detail['buffs']: - buff_icon = bufflist[buff['base_type']['id']] - buff_name = buff['base_type']['name'] - buffs = buff['items'] + for buff in detail.buffs: + buff_icon = bufflist[buff.base_type.id] + buff_name = buff.base_type.name + buffs = buff.items draw_height = await _draw_rogue_buff( buffs, buff_icon, @@ -765,7 +765,7 @@ async def draw_rogue_locust_img( # 奇物 miracles_height = buff_height - if len(detail['miracles']) > 0: + if len(detail.miracles) > 0: floor_pic_draw.text( (93, 370 + miracles_height + 60), '获得奇物', @@ -777,7 +777,7 @@ async def draw_rogue_locust_img( content_center, (0, 370 + miracles_height + 80), content_center ) draw_height = await _draw_rogue_miracles( - detail['miracles'], + detail.miracles, floor_pic, miracles_height, ) @@ -786,7 +786,7 @@ async def draw_rogue_locust_img( # 事件 blocks_height = miracles_height - if len(detail['blocks']) > 0: + if len(detail.blocks) > 0: floor_pic_draw.text( (93, 370 + blocks_height + 60), '通过区域类型', @@ -798,17 +798,17 @@ async def draw_rogue_locust_img( content_center, (0, 370 + blocks_height + 80), content_center ) draw_height = await _draw_rogue_blocks( - detail['blocks'], + detail.blocks, floor_pic, blocks_height, ) blocks_height = blocks_height + 80 blocks_height = blocks_height + draw_height - if detail['start_h'] is None: + if detail.start_h is None: continue - img.paste(floor_pic, (0, detail['start_h']), floor_pic) + img.paste(floor_pic, (0, detail.start_h), floor_pic) # await _draw_floor_card( # level_star, # floor_pic, diff --git a/StarRailUID/starrailuid_roleinfo/draw_roleinfo_card.py b/StarRailUID/starrailuid_roleinfo/draw_roleinfo_card.py index 7dd5119..d48fed9 100644 --- a/StarRailUID/starrailuid_roleinfo/draw_roleinfo_card.py +++ b/StarRailUID/starrailuid_roleinfo/draw_roleinfo_card.py @@ -59,17 +59,17 @@ async def _draw_card_1( sr_uid: str, role_basic_info: RoleBasicInfo, stats: Stats ) -> Image.Image: # 名称 - nickname = role_basic_info['nickname'] + nickname = role_basic_info.nickname # 基本状态 - active_days = stats['active_days'] - avater_num = stats['avatar_num'] - achievement_num = stats['achievement_num'] - chest_num = stats['chest_num'] - level = role_basic_info['level'] + active_days = stats.active_days + avater_num = stats.avatar_num + achievement_num = stats.achievement_num + chest_num = stats.chest_num + level = role_basic_info.level # 忘却之庭 - abyss_process = stats['abyss_process'] + abyss_process = stats.abyss_process img_bg1 = bg1.copy() bg1_draw = ImageDraw.Draw(img_bg1) @@ -137,22 +137,22 @@ async def _draw_card_1( async def _draw_avatar_card( avatar: AvatarListItem, equips: Dict[int, Optional[str]] ) -> Image.Image: - char_bg = (char_bg_4 if avatar['rarity'] == 4 else char_bg_5).copy() + char_bg = (char_bg_4 if avatar.rarity == 4 else char_bg_5).copy() char_draw = ImageDraw.Draw(char_bg) - char_icon = await get_icon(avatar['icon']) - element_icon = elements[avatar['element']] + char_icon = await get_icon(avatar.icon) + element_icon = elements[avatar.element] char_bg.paste(char_icon, (4, 8), mask=char_icon) char_bg.paste(element_icon, (81, 10), mask=element_icon) - if equip := equips[avatar['id']]: + if equip := equips[avatar.id]: char_bg.paste(circle, (0, 0), mask=circle) equip_icon = (await get_icon(equip)).resize((48, 48)) char_bg.paste(equip_icon, (9, 80), mask=equip_icon) char_draw.text( (60, 146), - _lv(avatar['level']), + _lv(avatar.level), font=sr_font_24, fill=color_color, anchor='mm', @@ -208,19 +208,19 @@ async def draw_role_card(sr_uid: str) -> Union[bytes, str]: if isinstance(role_index, int): return get_error(role_index) - stats = role_index['stats'] - avatars = role_index['avatar_list'] + stats = role_index.stats + avatars = role_index.avatar_list - detail = await mys_api.get_avatar_info(sr_uid, avatars[0]['id']) + detail = await mys_api.get_avatar_info(sr_uid, avatars[0].id) if isinstance(detail, int): return get_error(detail) # 角色武器 - details = detail['avatar_list'] + details = detail.avatar_list equips: Dict[int, Optional[str]] = {} for detail in details: - equip = detail['equip'] - equips[detail['id']] = equip['icon'] if equip is not None else None + equip = detail.equip + equips[detail.id] = equip.icon if equip is not None else None # 绘制总图 img1, img2 = await asyncio.gather( diff --git a/StarRailUID/starrailuid_stamina/draw_stamina_card.py b/StarRailUID/starrailuid_stamina/draw_stamina_card.py index ba1f95f..2e1fe67 100644 --- a/StarRailUID/starrailuid_stamina/draw_stamina_card.py +++ b/StarRailUID/starrailuid_stamina/draw_stamina_card.py @@ -62,18 +62,18 @@ async def _draw_task_img( char: Optional[Expedition], ): if char is not None: - expedition_name = char['name'] - remaining_time: str = seconds2hours(char['remaining_time']) + expedition_name = char.name + remaining_time: str = seconds2hours(char.remaining_time) note_travel_img = note_travel_bg.copy() for i in range(2): - avatar_url = char['avatars'][i] + avatar_url = char.avatars[i] image = await download_image(avatar_url) char_pic = image.convert('RGBA').resize( (40, 40), Image.Resampling.LANCZOS # type: ignore ) note_travel_img.paste(char_pic, (495 + 68 * i, 20), char_pic) img.paste(note_travel_img, (0, 790 + index * 80), note_travel_img) - if char['status'] == 'Finished': + if char.status == 'Finished': status_mark = '待收取' else: status_mark = str(remaining_time) @@ -155,7 +155,7 @@ def get_error(img: Image.Image, uid: str, daily_data: int): error_text = get_error_msg(daily_data) img_draw.text( (350, 650), - f'{error_text} ,错误码{daily_data}', + f'{error_text}, 错误码{daily_data}', font=sr_font_26, fill=red_color, anchor='mm', @@ -191,15 +191,15 @@ async def draw_stamina_img(sr_uid: str) -> Image.Image: role_basic_info = await mys_api.get_role_basic_info(sr_uid) if isinstance(role_basic_info, int): return get_error(img, sr_uid, role_basic_info) - nickname = role_basic_info['nickname'] - level = role_basic_info['level'] + nickname = role_basic_info.nickname + level = role_basic_info.level else: nickname = '开拓者' level = '0' # 开拓力 - stamina = daily_data['current_stamina'] - max_stamina = daily_data['max_stamina'] + stamina = daily_data.current_stamina + max_stamina = daily_data.max_stamina stamina_str = f'{stamina}/{max_stamina}' stamina_percent = stamina / max_stamina if stamina_percent > 0.8: @@ -207,7 +207,7 @@ async def draw_stamina_img(sr_uid: str) -> Image.Image: else: stamina_color = second_color stamina_recovery_time = await seconds2hours_zhcn( - daily_data['stamina_recover_time'] + daily_data.stamina_recover_time ) img.paste(note_bg, (0, 0), note_bg) @@ -217,8 +217,8 @@ async def draw_stamina_img(sr_uid: str) -> Image.Image: task_task = [] for i in range(4): char = ( - daily_data['expeditions'][i] - if i < len(daily_data['expeditions']) + daily_data.expeditions[i] + if i < len(daily_data.expeditions) else None ) task_task.append(_draw_task_img(img, img_draw, i, char)) diff --git a/StarRailUID/starrailuid_stamina/notice.py b/StarRailUID/starrailuid_stamina/notice.py index 03ac84f..348d8c4 100644 --- a/StarRailUID/starrailuid_stamina/notice.py +++ b/StarRailUID/starrailuid_stamina/notice.py @@ -54,7 +54,7 @@ async def all_check( if srconfig.get_config('CrazyNotice').data: if not await check(mode, raw_data, push_data[f'{mode}_value']): await sqla.update_push_data( - uid, {f'{mode}_is_push': 'off'} + uid, bot_id, {f'{mode}_is_push': 'off'} ) continue # 准备推送 @@ -73,7 +73,9 @@ async def all_check( msg_dict[bot_id]['direct'][user_id] = NOTICE[mode] else: msg_dict[bot_id]['direct'][user_id] += NOTICE[mode] - await sqla.update_push_data(uid, {f'{mode}_is_push': 'on'}) + await sqla.update_push_data( + uid, bot_id, {f'{mode}_is_push': 'on'} + ) # 群号推送到群聊 else: # 初始化 @@ -85,21 +87,23 @@ async def all_check( msg_dict[bot_id]['group'][gid][user_id] = NOTICE[mode] else: msg_dict[bot_id]['group'][gid][user_id] += NOTICE[mode] - await sqla.update_push_data(uid, {f'{mode}_is_push': 'on'}) + await sqla.update_push_data( + uid, bot_id, {f'{mode}_is_push': 'on'} + ) return msg_dict async def check(mode: str, data: DailyNoteData, limit: int) -> bool: if mode == 'resin': - if data['current_stamina'] >= limit: + if data.current_stamina >= limit: return True - if data['current_stamina'] >= data['max_stamina']: + if data.current_stamina >= data.max_stamina: return True return False if mode == 'go': - for i in data['expeditions']: - if i['status'] == 'Ongoing': - if int(i['remaining_time']) <= limit * 60: + for i in data.expeditions: + if i.status == 'Ongoing': + if i.remaining_time <= limit * 60: return True else: return True diff --git a/StarRailUID/starrailuid_stamina/stamina_text.py b/StarRailUID/starrailuid_stamina/stamina_text.py index e54df50..bbb8828 100644 --- a/StarRailUID/starrailuid_stamina/stamina_text.py +++ b/StarRailUID/starrailuid_stamina/stamina_text.py @@ -24,38 +24,36 @@ async def get_stamina_text(uid: str) -> str: dailydata = await mys_api.get_daily_data(uid) if isinstance(dailydata, int): return get_error(dailydata) - max_stamina = dailydata['max_stamina'] + max_stamina = dailydata.max_stamina rec_time = '' - current_stamina = dailydata['current_stamina'] + current_stamina = dailydata.current_stamina if current_stamina < 160: stamina_recover_time = seconds2hours( - dailydata['stamina_recover_time'] + dailydata.stamina_recover_time ) next_stamina_rec_time = seconds2hours( 8 * 60 - ( - (dailydata['max_stamina'] - dailydata['current_stamina']) + (dailydata.max_stamina - dailydata.current_stamina) * 8 * 60 - - int(dailydata['stamina_recover_time']) + - dailydata.stamina_recover_time ) ) rec_time = f' ({next_stamina_rec_time}/{stamina_recover_time})' - accepted_epedition_num = dailydata['accepted_expedition_num'] - total_expedition_num = dailydata['total_expedition_num'] + accepted_epedition_num = dailydata.accepted_expedition_num + total_expedition_num = dailydata.total_expedition_num finished_expedition_num = 0 expedition_info: List[str] = [] - for expedition in dailydata['expeditions']: - expedition_name = expedition['name'] + for expedition in dailydata.expeditions: + expedition_name = expedition.name - if expedition['status'] == 'Finished': + if expedition.status == 'Finished': expedition_info.append(f'{expedition_name} 探索完成') finished_expedition_num += 1 else: - remaining_time: str = seconds2hours( - expedition['remaining_time'] - ) + remaining_time: str = seconds2hours(expedition.remaining_time) expedition_info.append( f'{expedition_name} 剩余时间{remaining_time}' ) diff --git a/StarRailUID/utils/mys_api.py b/StarRailUID/utils/mys_api.py index 4a80329..e64c490 100644 --- a/StarRailUID/utils/mys_api.py +++ b/StarRailUID/utils/mys_api.py @@ -2,8 +2,9 @@ import copy import time import random from string import digits, ascii_letters -from typing import Any, Dict, Union, Literal, Optional, cast +from typing import Any, Dict, Union, Literal, Optional +import msgspec from gsuid_core.utils.api.mys_api import _MysApi from gsuid_core.utils.database.models import GsUser from gsuid_core.utils.api.mys.models import MysSign, SignInfo, SignList @@ -56,8 +57,7 @@ class MysApi(_MysApi): ) -> Optional[str]: if mode == 'RANDOM': return await GsUser.get_random_cookie(uid, game_name='sr') - else: - return await GsUser.get_user_cookie_by_uid(uid, game_name='sr') + return await GsUser.get_user_cookie_by_uid(uid, game_name='sr') async def get_stoken(self, uid: str) -> Optional[str]: return await GsUser.get_user_stoken_by_uid(uid, 'sr') @@ -125,7 +125,8 @@ class MysApi(_MysApi): 'STAR_RAIL_NOTE_URL', uid, header=self._HEADER ) if isinstance(data, Dict): - data = cast(DailyNoteData, data['data']) + data = msgspec.convert(data['data'], type=DailyNoteData) + # data = cast(DailyNoteData, data['data']) return data async def get_widget_stamina_data( @@ -155,7 +156,8 @@ class MysApi(_MysApi): _API['STAR_RAIL_WIDGRT_URL'], 'GET', header ) if isinstance(data, Dict): - data = cast(WidgetStamina, data['data']) + data = msgspec.convert(data['data'], type=WidgetStamina) + # data = cast(WidgetStamina, data['data']) return data async def get_role_index(self, uid: str) -> Union[RoleIndex, int]: @@ -182,7 +184,8 @@ class MysApi(_MysApi): 'STAR_RAIL_INDEX_URL', uid, header=self._HEADER ) if isinstance(data, Dict): - data = cast(RoleIndex, data['data']) + data = msgspec.convert(data['data'], type=RoleIndex) + # data = cast(RoleIndex, data['data']) return data async def get_gacha_log_by_link_in_authkey( @@ -233,7 +236,8 @@ class MysApi(_MysApi): }, ) if isinstance(data, Dict): - data = cast(GachaLog, data['data']) + data = msgspec.convert(data['data'], type=GachaLog) + # data = cast(GachaLog, data['data']) return data async def get_avatar_info( @@ -271,7 +275,8 @@ class MysApi(_MysApi): header=self._HEADER, ) if isinstance(data, Dict): - data = cast(AvatarInfo, data['data']) + data = msgspec.convert(data['data'], type=AvatarInfo) + # data = cast(AvatarInfo, data['data']) return data async def get_sign_list(self, uid) -> Union[SignList, int]: @@ -291,7 +296,8 @@ class MysApi(_MysApi): 'STAR_RAIL_SIGN_LIST_URL', is_os, params ) if isinstance(data, Dict): - data = cast(SignList, data['data']) + data = msgspec.convert(data['data'], type=SignList) + # data = cast(SignList, data['data']) return data async def get_sign_info(self, uid) -> Union[SignInfo, int]: @@ -322,7 +328,8 @@ class MysApi(_MysApi): 'STAR_RAIL_SIGN_INFO_URL', is_os, params, header ) if isinstance(data, Dict): - data = cast(SignInfo, data['data']) + data = msgspec.convert(data['data'], type=SignInfo) + # data = cast(SignInfo, data['data']) return data async def get_srspiral_abyss_info( @@ -367,7 +374,8 @@ class MysApi(_MysApi): header=self._HEADER, ) if isinstance(data, Dict): - data = cast(AbyssData, data['data']) + data = msgspec.convert(data['data'], type=AbyssData) + # data = cast(AbyssData, data['data']) return data async def get_rogue_info( @@ -390,7 +398,8 @@ class MysApi(_MysApi): header=self._HEADER, ) if isinstance(data, Dict): - data = cast(RogueData, data['data']) + data = msgspec.convert(data['data'], type=RogueData) + # data = cast(RogueData, data['data']) return data async def get_rogue_locust_info( @@ -411,7 +420,8 @@ class MysApi(_MysApi): header=self._HEADER, ) if isinstance(data, Dict): - data = cast(RogueLocustData, data['data']) + data = msgspec.convert(data['data'], type=RogueLocustData) + # data = cast(RogueLocustData, data['data']) return data async def mys_sign( @@ -457,7 +467,8 @@ class MysApi(_MysApi): }, ) if isinstance(data, Dict): - data = cast(MysSign, data['data']) + data = msgspec.convert(data['data'], type=MysSign) + # data = cast(MysSign, data['data']) return data async def get_award(self, sr_uid, month) -> Union[MonthlyAward, int]: @@ -487,7 +498,8 @@ class MysApi(_MysApi): use_proxy=True, ) if isinstance(data, Dict): - data = cast(MonthlyAward, data['data']) + data = msgspec.convert(data['data'], type=MonthlyAward) + # data = cast(MonthlyAward, data['data']) return data async def get_role_basic_info( @@ -497,7 +509,8 @@ class MysApi(_MysApi): 'STAR_RAIL_ROLE_BASIC_INFO_URL', sr_uid, header=self._HEADER ) if isinstance(data, Dict): - data = cast(RoleBasicInfo, data['data']) + data = msgspec.convert(data['data'], type=RoleBasicInfo) + # data = cast(RoleBasicInfo, data['data']) return data