使用 msgspec 作为model, 完成 hakush api model

This commit is contained in:
qwerdvd 2023-09-24 14:24:21 +08:00
parent 03adfff3b4
commit ad53d53dc9
16 changed files with 499 additions and 368 deletions

View File

@ -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

View File

@ -1,55 +1,56 @@
from __future__ import annotations from __future__ import annotations
from typing import TypedDict from msgspec import Struct, field
class MihomoData(TypedDict): class MihomoData(Struct):
detailInfo: PlayerDetailInfo detailInfo: PlayerDetailInfo
class Behavior(TypedDict): class Behavior(Struct):
pointId: int pointId: int
level: int level: int
class Equipment(TypedDict): class Equipment(Struct):
level: int level: int
tid: int tid: int
promotion: int | None promotion: int | None = field(default=0)
rank: int | None rank: int | None = field(default=0)
class Relic(TypedDict): class Relic(Struct):
subAffixList: list[SubAffix] subAffixList: list[SubAffix]
tid: int tid: int
mainAffixId: int mainAffixId: int
type: int type: int
level: int | None = field(default=0)
class SubAffix(TypedDict): class SubAffix(Struct):
affixId: int affixId: int
cnt: int cnt: int
step: int step: int | None = field(default=0)
class Avatar(TypedDict): class Avatar(Struct):
skillTreeList: list[Behavior] skillTreeList: list[Behavior]
rank: int | None
pos: int | None
avatarId: int avatarId: int
level: int level: int
equipment: Equipment | None equipment: Equipment | None
relicList: list[Relic] 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 scheduleMaxLevel: int
MazeGroupIndex: int | None MazeGroupIndex: int | None = None
PreMazeGroupIndex: int | None PreMazeGroupIndex: int | None = None
class PlayerSpaceInfo(TypedDict): class PlayerSpaceInfo(Struct):
challengeInfo: Challenge challengeInfo: Challenge
maxRogueChallengeScore: int maxRogueChallengeScore: int
equipmentCount: int equipmentCount: int
@ -57,7 +58,7 @@ class PlayerSpaceInfo(TypedDict):
achievementCount: int achievementCount: int
class PlayerDetailInfo(TypedDict): class PlayerDetailInfo(Struct):
assistAvatarDetail: Avatar assistAvatarDetail: Avatar
platform: str platform: str
isDisplayAvatar: bool isDisplayAvatar: bool
@ -66,8 +67,8 @@ class PlayerDetailInfo(TypedDict):
friendCount: int friendCount: int
worldLevel: int worldLevel: int
nickname: str nickname: str
Birthday: int | None
level: int level: int
recordInfo: PlayerSpaceInfo | None recordInfo: PlayerSpaceInfo | None
headIcon: int headIcon: int
signature: str | None signature: str | None = None
Birthday: int | None = None

View File

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
from msgspec import convert
from httpx import AsyncClient from httpx import AsyncClient
from ..utils import _HEADER from ..utils import _HEADER
@ -13,4 +14,4 @@ async def get_char_card_info(uid: str) -> MihomoData:
timeout=30, timeout=30,
) as client: ) as client:
req = await client.get(f'/sr_info/{uid}') req = await client.get(f'/sr_info/{uid}')
return req.json() return convert(req.json(), type=MihomoData)

View File

@ -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 uid: str
gacha_id: str gacha_id: str
gacha_type: str gacha_type: str
@ -19,7 +21,7 @@ class SingleGachaLog(TypedDict):
id: str id: str
class GachaLog(TypedDict): class GachaLog(Struct):
page: str page: str
size: str size: str
list: List[SingleGachaLog] list: List[SingleGachaLog]
@ -27,7 +29,7 @@ class GachaLog(TypedDict):
region_time_zone: int region_time_zone: int
class RoleBasicInfo(TypedDict): class RoleBasicInfo(Struct):
avatar: str avatar: str
nickname: str nickname: str
region: str region: str
@ -39,7 +41,7 @@ class RoleBasicInfo(TypedDict):
################ ################
class RogueTime(TypedDict): class RogueTime(Struct):
year: int year: int
month: int month: int
day: int day: int
@ -48,7 +50,7 @@ class RogueTime(TypedDict):
second: int second: int
class RogueAvatar(TypedDict): class RogueAvatar(Struct):
id: int id: int
icon: str icon: str
level: int level: int
@ -56,31 +58,31 @@ class RogueAvatar(TypedDict):
element: str element: str
class RogueBaseType(TypedDict): class RogueBaseType(Struct):
id: int id: int
name: str name: str
cnt: int cnt: int
class RogueBuffitems(TypedDict): class RogueBuffitems(Struct):
id: int id: int
name: str name: str
is_evoluted: str is_evoluted: str
rank: int rank: int
class RogueMiracles(TypedDict): class RogueMiracles(Struct):
id: int id: int
name: str name: str
icon: str icon: str
class RogueBuffs(TypedDict): class RogueBuffs(Struct):
base_type: RogueBaseType base_type: RogueBaseType
items: List[RogueBuffitems] items: List[RogueBuffitems]
class RogueRecordInfo(TypedDict): class RogueRecordInfo(Struct):
name: str name: str
finish_time: RogueTime finish_time: RogueTime
score: int score: int
@ -94,60 +96,63 @@ class RogueRecordInfo(TypedDict):
detail_h: Union[int, None] detail_h: Union[int, None]
start_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 id: int
finish_cnt: int finish_cnt: int
schedule_begin: RogueTime schedule_begin: RogueTime
schedule_end: RogueTime schedule_end: RogueTime
class RogueRecord(TypedDict): class RogueRecord(Struct):
basic: RogueBasic basic: RogueBasic
records: List[RogueRecordInfo] records: List[RogueRecordInfo]
class RogueBasicInfo(TypedDict): class RogueBasicInfo(Struct):
unlocked_buff_num: int unlocked_buff_num: int
unlocked_miracle_num: int unlocked_miracle_num: int
unlocked_skill_points: int unlocked_skill_points: int
class LocustCntInfo(TypedDict): class LocustCntInfo(Struct):
narrow: int narrow: int
miracle: int miracle: int
event: int event: int
class LocustDestinyInfo(TypedDict): class LocustDestinyInfo(Struct):
id: int id: int
desc: str desc: str
level: int level: int
class LocustBasicInfo(TypedDict): class LocustBasicInfo(Struct):
cnt: LocustCntInfo cnt: LocustCntInfo
destiny: List[LocustDestinyInfo] destiny: List[LocustDestinyInfo]
class RoleInfo(TypedDict): class RoleInfo(Struct):
server: str server: str
nickname: str nickname: str
level: int level: int
class LocustBlocks(TypedDict): class LocustBlocks(Struct):
block_id: int block_id: int
name: str name: str
num: int num: int
class LocustFury(TypedDict): class LocustFury(Struct):
type: int type: int
point: str point: str
class LocustRecordInfo(TypedDict): class LocustRecordInfo(Struct):
name: str name: str
finish_time: RogueTime finish_time: RogueTime
final_lineup: List[RogueAvatar] final_lineup: List[RogueAvatar]
@ -162,19 +167,22 @@ class LocustRecordInfo(TypedDict):
detail_h: Union[int, None] detail_h: Union[int, None]
start_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] records: List[LocustRecordInfo]
class RogueData(TypedDict): class RogueData(Struct):
role: RoleInfo role: RoleInfo
basic_info: RogueBasicInfo basic_info: RogueBasicInfo
current_record: RogueRecord current_record: RogueRecord
last_record: RogueRecord last_record: RogueRecord
class RogueLocustData(TypedDict): class RogueLocustData(Struct):
role: RoleInfo role: RoleInfo
basic: LocustBasicInfo basic: LocustBasicInfo
detail: LocustRecord detail: LocustRecord
@ -185,7 +193,7 @@ class RogueLocustData(TypedDict):
################ ################
class AbyssTime(TypedDict): class AbyssTime(Struct):
year: int year: int
month: int month: int
day: int day: int
@ -193,7 +201,7 @@ class AbyssTime(TypedDict):
minute: int minute: int
class AbyssAvatar(TypedDict): class AbyssAvatar(Struct):
id: int id: int
level: int level: int
icon: str icon: str
@ -201,12 +209,12 @@ class AbyssAvatar(TypedDict):
element: str element: str
class AbyssNodeDetail(TypedDict): class AbyssNodeDetail(Struct):
challenge_time: AbyssTime challenge_time: AbyssTime
avatars: List[AbyssAvatar] avatars: List[AbyssAvatar]
class AbyssFloorDetail(TypedDict): class AbyssFloorDetail(Struct):
name: str name: str
round_num: int round_num: int
star_num: int star_num: int
@ -214,7 +222,7 @@ class AbyssFloorDetail(TypedDict):
node_2: List[AbyssNodeDetail] node_2: List[AbyssNodeDetail]
class AbyssData(TypedDict): class AbyssData(Struct):
schedule_id: int schedule_id: int
begin_time: AbyssTime begin_time: AbyssTime
end_time: AbyssTime end_time: AbyssTime
@ -231,27 +239,27 @@ class AbyssData(TypedDict):
################ ################
class DataText(TypedDict): class DataText(Struct):
type: str type: str
key: str key: str
mi18n_key: str mi18n_key: str
class DayData(TypedDict): class DayData(Struct):
current_hcoin: int current_hcoin: int
current_rails_pass: int current_rails_pass: int
last_hcoin: int last_hcoin: int
last_rails_pass: int last_rails_pass: int
class GroupBy(TypedDict): class GroupBy(Struct):
action: str action: str
num: int num: int
percent: int percent: int
action_name: str action_name: str
class MonthData(TypedDict): class MonthData(Struct):
current_hcoin: int current_hcoin: int
current_rails_pass: int current_rails_pass: int
last_hcoin: int last_hcoin: int
@ -261,7 +269,7 @@ class MonthData(TypedDict):
group_by: List[GroupBy] group_by: List[GroupBy]
class MonthlyAward(TypedDict): class MonthlyAward(Struct):
uid: str uid: str
region: str region: str
login_flag: bool login_flag: bool
@ -278,14 +286,14 @@ class MonthlyAward(TypedDict):
################ ################
# 实时便签 # # 实时便签 #
################ ################
class Expedition(TypedDict): class Expedition(Struct):
avatars: List[str] # 头像Url avatars: List[str] # 头像Url
status: str status: str
remaining_time: int remaining_time: int
name: str name: str
class DailyNoteData(TypedDict): class DailyNoteData(Struct):
current_stamina: int current_stamina: int
max_stamina: int max_stamina: int
stamina_recover_time: int stamina_recover_time: int
@ -294,7 +302,7 @@ class DailyNoteData(TypedDict):
expeditions: List[Expedition] expeditions: List[Expedition]
class WidgetStamina(TypedDict): class WidgetStamina(Struct):
current_stamina: int current_stamina: int
max_stamina: int max_stamina: int
stamina_recover_time: int stamina_recover_time: int
@ -314,7 +322,7 @@ class WidgetStamina(TypedDict):
################ ################
# 签到相关 # # 签到相关 #
################ ################
class MysSign(TypedDict): class MysSign(Struct):
code: str code: str
risk_code: int risk_code: int
gt: str gt: str
@ -323,7 +331,7 @@ class MysSign(TypedDict):
is_risk: bool is_risk: bool
class SignInfo(TypedDict): class SignInfo(Struct):
total_sign_day: int total_sign_day: int
today: str today: str
is_sign: bool is_sign: bool
@ -333,13 +341,13 @@ class SignInfo(TypedDict):
short_sign_day: int short_sign_day: int
class SignAward(TypedDict): class SignAward(Struct):
icon: str icon: str
name: str name: str
cnt: int cnt: int
class SignExtraAward(TypedDict): class SignExtraAward(Struct):
has_extra_award: bool has_extra_award: bool
start_time: str start_time: str
end_time: str end_time: str
@ -348,7 +356,7 @@ class SignExtraAward(TypedDict):
end_timestamp: str end_timestamp: str
class SignList(TypedDict): class SignList(Struct):
month: int month: int
awards: List[SignAward] awards: List[SignAward]
biz: str biz: str
@ -361,7 +369,7 @@ class SignList(TypedDict):
#################### ####################
class Stats(TypedDict): class Stats(Struct):
active_days: int active_days: int
avatar_num: int avatar_num: int
achievement_num: int achievement_num: int
@ -369,7 +377,7 @@ class Stats(TypedDict):
abyss_process: str abyss_process: str
class AvatarListItem(TypedDict): class AvatarListItem(Struct):
id: int id: int
level: int level: int
name: str name: str
@ -380,7 +388,7 @@ class AvatarListItem(TypedDict):
is_chosen: bool is_chosen: bool
class RoleIndex(TypedDict): class RoleIndex(Struct):
stats: Stats stats: Stats
avatar_list: List[AvatarListItem] avatar_list: List[AvatarListItem]
@ -390,7 +398,7 @@ class RoleIndex(TypedDict):
################ ################
class Equip(TypedDict): class Equip(Struct):
id: int id: int
level: int level: int
rank: int rank: int
@ -399,7 +407,7 @@ class Equip(TypedDict):
icon: str icon: str
class RelicsItem(TypedDict): class RelicsItem(Struct):
id: int id: int
level: int level: int
pos: int pos: int
@ -409,7 +417,7 @@ class RelicsItem(TypedDict):
rarity: int rarity: int
class RanksItem(TypedDict): class RanksItem(Struct):
id: int id: int
pos: int pos: int
name: str name: str
@ -418,7 +426,7 @@ class RanksItem(TypedDict):
is_unlocked: bool is_unlocked: bool
class AvatarListItemDetail(TypedDict): class AvatarListItemDetail(Struct):
id: int id: int
level: int level: int
name: str name: str
@ -433,7 +441,7 @@ class AvatarListItemDetail(TypedDict):
ranks: List[RanksItem] ranks: List[RanksItem]
class AvatarInfo(TypedDict): class AvatarInfo(Struct):
avatar_list: List[AvatarListItemDetail] avatar_list: List[AvatarListItemDetail]
equip_wiki: Dict[str, str] equip_wiki: Dict[str, str]
relic_wiki: Dict relic_wiki: Dict

View File

@ -78,9 +78,9 @@ async def _draw_abyss_card(
# char_id = char['id'] # char_id = char['id']
# # 确认角色头像路径 # # 确认角色头像路径
# char_pic_path = CHAR_ICON_PATH / f'{char_id}.png' # 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_bg = (char_bg_4 if char.rarity == 4 else char_bg_5).copy()
char_icon = (await get_icon(char['icon'])).resize((151, 170)) char_icon = (await get_icon(char.icon)).resize((151, 170))
element_icon = elements[char['element']] element_icon = elements[char.element]
char_bg.paste(char_icon, (24, 16), mask=char_icon) char_bg.paste(char_icon, (24, 16), mask=char_icon)
char_bg.paste(level_cover, (0, 0), mask=level_cover) char_bg.paste(level_cover, (0, 0), mask=level_cover)
char_bg.paste(element_icon, (135, 30), mask=element_icon) 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 = ImageDraw.Draw(char_bg)
char_card_draw.text( char_card_draw.text(
(100, 165), (100, 165),
f'等级 {char["level"]}', f'等级 {char.level}',
font=sr_font_22, font=sr_font_22,
fill=white_color, fill=white_color,
anchor='mm', anchor='mm',
@ -154,12 +154,12 @@ async def draw_abyss_img(
floor_num = 1 floor_num = 1
if floor > 10: if floor > 10:
return '楼层不能大于10层!' return '楼层不能大于10层!'
if len(raw_abyss_data['all_floor_detail']) < floor: if len(raw_abyss_data.all_floor_detail) < floor:
return '你还没有挑战该层!' return '你还没有挑战该层!'
else: else:
if raw_abyss_data['max_floor'] == '': if raw_abyss_data.max_floor == '':
return '你还没有挑战本期深渊!\n可以使用[sr上期深渊]命令查询上期~' return '你还没有挑战本期深渊!\n可以使用[sr上期深渊]命令查询上期~'
floor_num = len(raw_abyss_data['all_floor_detail']) floor_num = len(raw_abyss_data.all_floor_detail)
# 获取背景图片各项参数 # 获取背景图片各项参数
based_w = 900 based_w = 900
@ -193,7 +193,7 @@ async def draw_abyss_img(
# 最深抵达 # 最深抵达
img_draw.text( img_draw.text(
(220, 565), (220, 565),
f'{raw_abyss_data["max_floor"]}', f'{raw_abyss_data.max_floor}',
white_color, white_color,
sr_font_34, sr_font_34,
'lm', 'lm',
@ -201,7 +201,7 @@ async def draw_abyss_img(
# 挑战次数 # 挑战次数
img_draw.text( img_draw.text(
(220, 612), (220, 612),
f'{raw_abyss_data["battle_num"]}', f'{raw_abyss_data.battle_num}',
white_color, white_color,
sr_font_34, sr_font_34,
'lm', 'lm',
@ -212,34 +212,35 @@ async def draw_abyss_img(
img_draw.text( img_draw.text(
(695, 590), (695, 590),
f'{raw_abyss_data["star_num"]}/30', f'{raw_abyss_data.star_num}/30',
white_color, white_color,
sr_font_42, sr_font_42,
'lm', '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 floor:
if abyss_list[str(floor)] == level['name']: if abyss_list[str(floor)] == level.name:
index_floor = 0 # noqa: PLW2901 index_floor = 0 # noqa: PLW2901
else: else:
continue continue
elif index_floor >= 3: elif index_floor >= 3:
break break
floor_pic = Image.open(TEXT_PATH / 'floor_bg.png') floor_pic = Image.open(TEXT_PATH / 'floor_bg.png')
level_star = level['star_num'] level_star = level.star_num
floor_name = level['name'] floor_name = level.name
round_num = level['round_num'] round_num = level.round_num
node_1 = level.node_1
node_2 = level.node_2
for index_part in [0, 1]: for index_part in [0, 1]:
node_num = index_part + 1 node_num = index_part + 1
node = f'node_{node_num}' if node_num == 1:
# 节点1 time_array = node_1[-1].challenge_time
time_array = level[node]['challenge_time'] else:
time_str = f"{time_array['year']}-{time_array['month']}" time_array = node_2[-1].challenge_time
time_str = f"{time_str}-{time_array['day']}" time_str = f'{time_array.year}-{time_array.month}'
time_str = ( time_str = f'{time_str}-{time_array.day}'
f"{time_str} {time_array['hour']}:{time_array['minute']}:00" time_str = f'{time_str} {time_array.hour}:{time_array.minute}:00'
)
floor_pic_draw = ImageDraw.Draw(floor_pic) floor_pic_draw = ImageDraw.Draw(floor_pic)
floor_pic_draw.text( floor_pic_draw.text(
(112, 120 + index_part * 219), (112, 120 + index_part * 219),
@ -255,8 +256,12 @@ async def draw_abyss_img(
sr_font_22, sr_font_22,
'lm', '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: # if char["id"] in char_temp:
# talent_num = char_temp[char["id"]] # talent_num = char_temp[char["id"]]

View File

@ -3,6 +3,7 @@ from pathlib import Path
from typing import Dict, List, Union, Optional from typing import Dict, List, Union, Optional
from httpx import ReadTimeout from httpx import ReadTimeout
from msgspec import json as msgjson
from ..utils.error_reply import UID_HINT from ..utils.error_reply import UID_HINT
from ..sruid_utils.api.mihomo import MihomoData from ..sruid_utils.api.mihomo import MihomoData
@ -60,42 +61,38 @@ async def api_to_dict(
elif sr_data is None: elif sr_data is None:
return [] return []
PlayerDetailInfo = sr_data['detailInfo'] PlayerDetailInfo = sr_data.detailInfo
path = PLAYER_PATH / str(sr_uid) path = PLAYER_PATH / str(sr_uid)
path.mkdir(parents=True, exist_ok=True) path.mkdir(parents=True, exist_ok=True)
with Path.open(path / f'{sr_uid!s}.json', 'w', encoding='UTF-8') as file: with Path.open(path / f'{sr_uid!s}.json', 'wb') as file:
json.dump(PlayerDetailInfo, file, ensure_ascii=False) file.write(msgjson.format(msgjson.encode(PlayerDetailInfo), indent=4))
with Path.open(path / 'rawData.json', 'w', encoding='UTF-8') as file: with Path.open(path / 'rawData.json', 'wb') as file:
json.dump(sr_data, file, ensure_ascii=False) 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}刷新失败!未打开角色展柜!' return f'SR_UID{sr_uid}刷新失败!未打开角色展柜!'
char_name_list = [] char_name_list = []
char_id_list = [] char_id_list = []
im = f'UID: {sr_uid} 的角色展柜刷新成功\n' im = f'UID: {sr_uid} 的角色展柜刷新成功\n'
if PlayerDetailInfo.get('assistAvatarDetail'): if PlayerDetailInfo.assistAvatarDetail:
if ( if PlayerDetailInfo.assistAvatarDetail.avatarId not in char_id_list:
PlayerDetailInfo['assistAvatarDetail']['avatarId']
not in char_id_list
):
char_dict, avatarName = await get_data( char_dict, avatarName = await get_data(
PlayerDetailInfo['assistAvatarDetail'], sr_data, sr_uid PlayerDetailInfo.assistAvatarDetail, sr_data, sr_uid
) )
im += f'支援角色 {avatarName}\n' im += f'支援角色 {avatarName}\n'
char_name_list.append(avatarName) char_name_list.append(avatarName)
char_id_list.append( char_id_list.append(PlayerDetailInfo.assistAvatarDetail.avatarId)
PlayerDetailInfo['assistAvatarDetail']['avatarId'] if PlayerDetailInfo.avatarDetailList:
)
if PlayerDetailInfo.get('avatarDetailList'):
im += '星海同行' im += '星海同行'
if PlayerDetailInfo['avatarDetailList'] is not None: if PlayerDetailInfo.avatarDetailList is not None:
for char in PlayerDetailInfo['avatarDetailList']: for char in PlayerDetailInfo.avatarDetailList:
if char['avatarId'] not in char_id_list: if char.avatarId not in char_id_list:
_, avatarName = await get_data(char, sr_data, sr_uid) _, avatarName = await get_data(char, sr_data, sr_uid)
im += f' {avatarName}' im += f' {avatarName}'
char_name_list.append(avatarName) char_name_list.append(avatarName)
char_id_list.append(char['avatarId']) char_id_list.append(char.avatarId)
if not char_name_list: if not char_name_list:
return f'UID: {sr_uid} 的角色展柜刷新失败!\n请检查UID是否正确或者角色展柜是否打开!' 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): 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) path = PLAYER_PATH / str(sr_uid)
# 处理基本信息 # 处理基本信息
char_data = { char_data = {
'uid': str(sr_uid), 'uid': str(sr_uid),
'nickName': PlayerDetailInfo['nickname'], 'nickName': PlayerDetailInfo.nickname,
'avatarId': char['avatarId'], 'avatarId': char.avatarId,
'avatarName': avatarId2Name[str(char['avatarId'])], 'avatarName': avatarId2Name[str(char.avatarId)],
'avatarElement': avatarId2DamageType[str(char['avatarId'])], 'avatarElement': avatarId2DamageType[str(char.avatarId)],
'avatarRarity': avatarId2Rarity[str(char['avatarId'])], 'avatarRarity': avatarId2Rarity[str(char.avatarId)],
'avatarPromotion': char.get('promotion', 0), 'avatarPromotion': char.promotion,
'avatarLevel': char['level'], 'avatarLevel': char.level,
'avatarSkill': [], 'avatarSkill': [],
'avatarExtraAbility': [], 'avatarExtraAbility': [],
'avatarAttributeBonus': [], 'avatarAttributeBonus': [],
'RelicInfo': [], 'RelicInfo': [],
} }
avatarName = avatarId2Name[str(char['avatarId'])] avatarName = avatarId2Name[str(char.avatarId)]
char_data['avatarEnName'] = avatarId2EnName[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 = {}
skill_temp['skillId'] = ( skill_temp['skillId'] = char.avatarId * 100 + behavior.pointId % 10
char['avatarId'] * 100 + behavior['pointId'] % 10
)
skill_temp['skillName'] = skillId2Name[str(skill_temp['skillId'])] skill_temp['skillName'] = skillId2Name[str(skill_temp['skillId'])]
skill_temp['skillEffect'] = skillId2Effect[ skill_temp['skillEffect'] = skillId2Effect[
str(skill_temp['skillId']) str(skill_temp['skillId'])
@ -138,24 +133,24 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str):
skill_temp['skillAttackType'] = skillId2AttackType[ skill_temp['skillAttackType'] = skillId2AttackType[
str(skill_temp['skillId']) str(skill_temp['skillId'])
] ]
skill_temp['skillLevel'] = behavior['level'] skill_temp['skillLevel'] = behavior.level
char_data['avatarSkill'].append(skill_temp) 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 = {}
extra_ability_temp['extraAbilityId'] = behavior['pointId'] extra_ability_temp['extraAbilityId'] = behavior.pointId
extra_ability_temp['extraAbilityLevel'] = behavior['level'] extra_ability_temp['extraAbilityLevel'] = behavior.level
char_data['avatarExtraAbility'].append(extra_ability_temp) 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 = {}
attribute_bonus_temp['attributeBonusId'] = behavior['pointId'] attribute_bonus_temp['attributeBonusId'] = behavior.pointId
attribute_bonus_temp['attributeBonusLevel'] = behavior['level'] attribute_bonus_temp['attributeBonusLevel'] = behavior.level
status_add = characterSkillTree[str(char['avatarId'])][ status_add = characterSkillTree[str(char.avatarId)][
str(behavior['pointId']) str(behavior.pointId)
]['levels'][behavior['level'] - 1]['properties'] ]['levels'][behavior.level - 1]['properties']
attribute_bonus_temp['statusAdd'] = {} attribute_bonus_temp['statusAdd'] = {}
if status_add: if status_add:
for property_ in 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'): if char.relicList:
for relic in char['relicList']: for relic in char.relicList:
relic_temp = {} relic_temp = {}
relic_temp['relicId'] = relic['tid'] relic_temp['relicId'] = relic.tid
relic_temp['relicName'] = ItemId2Name[str(relic['tid'])] relic_temp['relicName'] = ItemId2Name[str(relic.tid)]
relic_temp['SetId'] = int(RelicId2SetId[str(relic['tid'])]) relic_temp['SetId'] = int(RelicId2SetId[str(relic.tid)])
relic_temp['SetName'] = SetId2Name[str(relic_temp['SetId'])] relic_temp['SetName'] = SetId2Name[str(relic_temp['SetId'])]
relic_temp['Level'] = relic['level'] if 'level' in relic else 0 relic_temp['Level'] = relic.level if relic.level else 0
relic_temp['Type'] = relic['type'] relic_temp['Type'] = relic.type
relic_temp['MainAffix'] = {} relic_temp['MainAffix'] = {}
relic_temp['MainAffix']['AffixID'] = relic['mainAffixId'] relic_temp['MainAffix']['AffixID'] = relic.mainAffixId
affix_property, value = await cal_relic_main_affix( affix_property, value = await cal_relic_main_affix(
relic_id=relic['tid'], relic_id=relic.tid,
set_id=str(relic_temp['SetId']), set_id=str(relic_temp['SetId']),
affix_id=relic['mainAffixId'], affix_id=relic.mainAffixId,
relic_type=relic['type'], relic_type=relic.type,
relic_level=relic_temp['Level'], relic_level=relic_temp['Level'],
) )
relic_temp['MainAffix']['Property'] = affix_property 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['MainAffix']['Value'] = value
relic_temp['SubAffixList'] = [] relic_temp['SubAffixList'] = []
if relic.get('subAffixList'): if relic.subAffixList:
for sub_affix in relic['subAffixList']: for sub_affix in relic.subAffixList:
sub_affix_temp = {} 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( sub_affix_property, value = await cal_relic_sub_affix(
relic_id=relic['tid'], relic_id=relic.tid,
affix_id=sub_affix['affixId'], affix_id=sub_affix.affixId,
cnt=sub_affix['cnt'], cnt=sub_affix.cnt,
step=sub_affix['step'] if 'step' in sub_affix else 0, step=sub_affix.step if sub_affix.step else 0,
) )
sub_affix_temp['Property'] = sub_affix_property sub_affix_temp['Property'] = sub_affix_property
sub_affix_temp['Name'] = Property2Name[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_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 sub_affix_temp['Value'] = value
relic_temp['SubAffixList'].append(sub_affix_temp) 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 = [] rank_temp = []
if char.get('rank') and char['rank'] is not None: if char.rank and char.rank is not None:
char_data['rank'] = char['rank'] char_data['rank'] = char.rank
for index in range(char['rank']): for index in range(char.rank):
rankTemp = {} 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['rankId'] = rank_id
rankTemp['rankName'] = rankId2Name[str(rank_id)] rankTemp['rankName'] = rankId2Name[str(rank_id)]
rank_temp.append(rankTemp) rank_temp.append(rankTemp)
@ -250,24 +245,24 @@ async def get_data(char: Avatar, sr_data: MihomoData, sr_uid: str):
# 处理基础属性 # 处理基础属性
base_attributes = {} base_attributes = {}
avatar_promotion_base = AvatarPromotionConfig.Avatar[ avatar_promotion_base = AvatarPromotionConfig.Avatar[str(char.avatarId)][
str(char['avatarId']) str(char.promotion)
][str(char.get('promotion', 0))] ]
# 攻击力 # 攻击力
base_attributes['attack'] = ( base_attributes['attack'] = (
avatar_promotion_base.AttackBase.Value avatar_promotion_base.AttackBase.Value
+ avatar_promotion_base.AttackAdd.Value * (char['level'] - 1) + avatar_promotion_base.AttackAdd.Value * (char.level - 1)
) )
# 防御力 # 防御力
base_attributes['defence'] = ( base_attributes['defence'] = (
avatar_promotion_base.DefenceBase.Value avatar_promotion_base.DefenceBase.Value
+ avatar_promotion_base.DefenceAdd.Value * (char['level'] - 1) + avatar_promotion_base.DefenceAdd.Value * (char.level - 1)
) )
# 血量 # 血量
base_attributes['hp'] = ( base_attributes['hp'] = (
avatar_promotion_base.HPBase.Value 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 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 = {} equipment_info = {}
if char.get('equipment') and char['equipment'] is not None: if char.equipment and char.equipment is not None:
equipment_info['equipmentID'] = char['equipment']['tid'] equipment_info['equipmentID'] = char.equipment.tid
equipment_info['equipmentName'] = EquipmentID2Name[ equipment_info['equipmentName'] = EquipmentID2Name[
str(char['equipment']['tid']) str(char.equipment.tid)
] ]
equipment_info['equipmentLevel'] = char['equipment']['level'] equipment_info['equipmentLevel'] = char.equipment.level
equipment_info['equipmentPromotion'] = char['equipment'].get( equipment_info['equipmentPromotion'] = char.equipment.promotion
'promotion', 0 equipment_info['equipmentRank'] = char.equipment.rank
)
equipment_info['equipmentRank'] = char['equipment']['rank']
equipment_info['equipmentRarity'] = EquipmentID2Rarity[ equipment_info['equipmentRarity'] = EquipmentID2Rarity[
str(char['equipment']['tid']) str(char.equipment.tid)
] ]
equipment_base_attributes = {} equipment_base_attributes = {}
equipment_promotion_base = EquipmentPromotionConfig.Equipment[ equipment_promotion_base = EquipmentPromotionConfig.Equipment[
str(char['equipment']['tid']) str(char.equipment.tid)
][str(equipment_info['equipmentPromotion'])] ][str(equipment_info['equipmentPromotion'])]
# 生命值 # 生命值
equipment_base_attributes['hp'] = ( equipment_base_attributes['hp'] = (
equipment_promotion_base.BaseHP.Value equipment_promotion_base.BaseHP.Value
+ equipment_promotion_base.BaseHPAdd.Value + equipment_promotion_base.BaseHPAdd.Value
* (char['equipment']['level'] - 1) * (char.equipment.level - 1)
) )
# 攻击力 # 攻击力
equipment_base_attributes['attack'] = ( equipment_base_attributes['attack'] = (
equipment_promotion_base.BaseAttack.Value equipment_promotion_base.BaseAttack.Value
+ equipment_promotion_base.BaseAttackAdd.Value + equipment_promotion_base.BaseAttackAdd.Value
* (char['equipment']['level'] - 1) * (char.equipment.level - 1)
) )
# 防御力 # 防御力
equipment_base_attributes['defence'] = ( equipment_base_attributes['defence'] = (
equipment_promotion_base.BaseDefence.Value equipment_promotion_base.BaseDefence.Value
+ equipment_promotion_base.BaseDefenceAdd.Value + equipment_promotion_base.BaseDefenceAdd.Value
* (char['equipment']['level'] - 1) * (char.equipment.level - 1)
) )
equipment_info['baseAttributes'] = equipment_base_attributes equipment_info['baseAttributes'] = equipment_base_attributes

View File

@ -34,10 +34,10 @@ async def get_new_gachalog_by_link(
) )
if isinstance(data, int): if isinstance(data, int):
return {} return {}
data = data['list'] data = data.list
if not data: if not data:
break break
end_id = data[-1]['id'] end_id = data[-1].id
if data[-1] in full_data[gacha_name] and not is_force: if data[-1] in full_data[gacha_name] and not is_force:
for item in data: for item in data:
if item not in full_data[gacha_name]: if item not in full_data[gacha_name]:
@ -46,9 +46,7 @@ async def get_new_gachalog_by_link(
temp = [] temp = []
break break
if len(full_data[gacha_name]) >= 1: if len(full_data[gacha_name]) >= 1:
if int(data[-1]['id']) <= int( if int(data[-1].id) <= int(full_data[gacha_name][0]['id']):
full_data[gacha_name][0]['id']
):
full_data[gacha_name].extend(data) full_data[gacha_name].extend(data)
else: else:
full_data[gacha_name][0:0] = data full_data[gacha_name][0:0] = data

View File

@ -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) role_basic_info = await mys_api.get_role_basic_info(sr_uid)
if isinstance(role_basic_info, int): if isinstance(role_basic_info, int):
return get_error(role_basic_info) return get_error(role_basic_info)
nickname = role_basic_info['nickname'] nickname = role_basic_info.nickname
day_hcoin = data['day_data']['current_hcoin'] day_hcoin = data.day_data.current_hcoin
day_rails_pass = data['day_data']['current_rails_pass'] day_rails_pass = data.day_data.current_rails_pass
lastday_hcoin = 0 lastday_hcoin = 0
lastday_rails_pass = 0 lastday_rails_pass = 0
if int(sr_uid[0]) < 6: if int(sr_uid[0]) < 6:
lastday_hcoin = data['day_data']['last_hcoin'] lastday_hcoin = data.day_data.last_hcoin
lastday_rails_pass = data['day_data']['last_rails_pass'] lastday_rails_pass = data.day_data.last_rails_pass
month_hcoin = data['month_data']['current_hcoin'] month_hcoin = data.month_data.current_hcoin
month_rails_pass = data['month_data']['current_rails_pass'] month_rails_pass = data.month_data.current_rails_pass
lastmonth_hcoin = data['month_data']['last_hcoin'] lastmonth_hcoin = data.month_data.last_hcoin
lastmonth_rails_pass = data['month_data']['last_rails_pass'] lastmonth_rails_pass = data.month_data.last_rails_pass
day_hcoin_str = await int_carry(day_hcoin) day_hcoin_str = await int_carry(day_hcoin)
day_rails_pass_str = await int_carry(day_rails_pass) 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)) xy = ((0, 0), (2100, 2100))
temp = -90 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 = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0))
pie_image_draw = ImageDraw.Draw(pie_image) pie_image_draw = ImageDraw.Draw(pie_image)
pie_image_draw.ellipse(xy, fill=(128, 128, 128)) pie_image_draw.ellipse(xy, fill=(128, 128, 128))
else: else:
pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0))
pie_image_draw = ImageDraw.Draw(pie_image) 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( pie_image_draw.pieslice(
xy, xy,
temp, temp,
temp + (i['percent'] / 100) * 360, temp + (i.percent / 100) * 360,
COLOR_MAP[i['action_name']], 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)) 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)) 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: if last_monthly_data:
pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0))
pie_image_draw = ImageDraw.Draw(pie_image) pie_image_draw = ImageDraw.Draw(pie_image)
for _index, i in enumerate( for _index, i in enumerate(last_monthly_data.month_data.group_by):
last_monthly_data['month_data']['group_by']
):
pie_image_draw.pieslice( pie_image_draw.pieslice(
xy, xy,
temp, temp,
temp + (i['percent'] / 100) * 360, temp + (i.percent / 100) * 360,
COLOR_MAP[i['action_name']], COLOR_MAP[i.action_name],
) )
temp = temp + (i['percent'] / 100) * 360 temp = temp + (i.percent / 100) * 360
else: else:
pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0)) pie_image = Image.new('RGBA', (2100, 2100), color=(255, 255, 255, 0))
pie_image_draw = ImageDraw.Draw(pie_image) pie_image_draw = ImageDraw.Draw(pie_image)

View File

@ -27,26 +27,26 @@ async def award(uid) -> str:
data = await mys_api.get_award(uid, datetime.now().month) data = await mys_api.get_award(uid, datetime.now().month)
if isinstance(data, int): if isinstance(data, int):
return get_error(data) return get_error(data)
day_hcoin = data['day_data']['current_hcoin'] day_hcoin = data.day_data.current_hcoin
day_rails_pass = data['day_data']['current_rails_pass'] day_rails_pass = data.day_data.current_rails_pass
lastday_hcoin = 0 lastday_hcoin = 0
lastday_rails_pass = 0 lastday_rails_pass = 0
if int(uid[0]) < 6: if int(uid[0]) < 6:
lastday_hcoin = data['day_data']['last_hcoin'] lastday_hcoin = data.day_data.last_hcoin
lastday_rails_pass = data['day_data']['last_rails_pass'] lastday_rails_pass = data.day_data.last_rails_pass
month_stone = data['month_data']['current_hcoin'] month_stone = data.month_data.current_hcoin
month_rails_pass = data['month_data']['current_rails_pass'] month_rails_pass = data.month_data.current_rails_pass
lastmonth_stone = data['month_data']['last_hcoin'] lastmonth_stone = data.month_data.last_hcoin
lastmonth_rails_pass = data['month_data']['last_rails_pass'] lastmonth_rails_pass = data.month_data.last_rails_pass
group_str = '' group_str = ''
for i in data['month_data']['group_by']: for i in data.month_data.group_by:
group_str = ( group_str = (
group_str group_str
+ i['action_name'] + i.action_name
+ ':' + ':'
+ str(i['num']) + str(i.num)
+ '(' + '('
+ str(i['percent']) + str(i.percent)
+ '%)' + '%)'
+ '\n' + '\n'
) )

View File

@ -117,12 +117,12 @@ async def _draw_rogue_buff(
zb_list.append([m, n]) zb_list.append([m, n])
jishu = 0 jishu = 0
for item in buffs: for item in buffs:
if item['is_evoluted'] is True: if item.is_evoluted is True:
is_evoluted = 1 is_evoluted = 1
else: else:
is_evoluted = 0 is_evoluted = 0
buff_bg = Image.open( 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)) buff_bg = buff_bg.resize((233, 35))
z_left = 90 + 240 * zb_list[jishu][1] 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.paste(buff_bg, (z_left, z_top), mask=buff_bg)
floor_pic_draw.text( floor_pic_draw.text(
(z_left + 115, z_top + 18), (z_left + 115, z_top + 18),
item['name'], item.name,
font=sr_font_22, font=sr_font_22,
fill=white_color, fill=white_color,
anchor='mm', anchor='mm',
@ -155,7 +155,7 @@ async def _draw_rogue_blocks(
zb_list.append([m, n]) zb_list.append([m, n])
jishu = 0 jishu = 0
for block in blocks: 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_left_bg = 90 + 357 * zb_list[jishu][1]
z_top_bg = buff_height + 470 + 80 * zb_list[jishu][0] z_top_bg = buff_height + 470 + 80 * zb_list[jishu][0]
jishu = jishu + 1 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.paste(block_icon, (z_left_icon, z_top_icon), mask=block_icon)
floor_pic_draw.text( floor_pic_draw.text(
(z_left_bg + 80, z_top_bg + 35), (z_left_bg + 80, z_top_bg + 35),
f"{block['name']} x{block['num']}", f'{block.name} x{block.num}',
font=sr_font_22, font=sr_font_22,
fill=white_color, fill=white_color,
anchor='lm', anchor='lm',
@ -187,7 +187,7 @@ async def _draw_rogue_miracles(
zb_list.append([m, n]) zb_list.append([m, n])
jishu = 0 jishu = 0
for miracle in miracles: 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_left = 90 + 90 * zb_list[jishu][1]
z_top = buff_height + 470 + 90 * zb_list[jishu][0] z_top = buff_height + 470 + 90 * zb_list[jishu][0]
jishu = jishu + 1 jishu = jishu + 1
@ -205,9 +205,9 @@ async def _draw_rogue_card(
# char_id = char['id'] # char_id = char['id']
# # 确认角色头像路径 # # 确认角色头像路径
# char_pic_path = CHAR_ICON_PATH / f'{char_id}.png' # 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_bg = (char_bg_4 if char.rarity == 4 else char_bg_5).copy()
char_icon = (await get_icon(char['icon'])).resize((151, 170)) char_icon = (await get_icon(char.icon)).resize((151, 170))
element_icon = elements[char['element']] element_icon = elements[char.element]
char_bg.paste(char_icon, (24, 16), mask=char_icon) char_bg.paste(char_icon, (24, 16), mask=char_icon)
char_bg.paste(level_cover, (0, 0), mask=level_cover) char_bg.paste(level_cover, (0, 0), mask=level_cover)
char_bg.paste(element_icon, (135, 30), mask=element_icon) 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 = ImageDraw.Draw(char_bg)
char_card_draw.text( char_card_draw.text(
(100, 165), (100, 165),
f'等级 {char["level"]}', f'等级 {char.level}',
font=sr_font_22, font=sr_font_22,
fill=white_color, fill=white_color,
anchor='mm', anchor='mm',
@ -245,9 +245,9 @@ async def draw_rogue_img(
# 计算背景图尺寸 # 计算背景图尺寸
if schedule_type == '3': if schedule_type == '3':
rogue_detail = raw_rogue_data['current_record']['records'] rogue_detail = raw_rogue_data.current_record.records
else: else:
rogue_detail = raw_rogue_data['last_record']['records'] rogue_detail = raw_rogue_data.last_record.records
# 记录打的宇宙列表 # 记录打的宇宙列表
detail_list = [] detail_list = []
@ -256,23 +256,23 @@ async def draw_rogue_img(
# 100+70+170 # 100+70+170
# 头+底+角色 # 头+底+角色
detail_h = 340 detail_h = 340
progress = detail['progress'] progress = detail.progress
detail_list.append(progress) detail_list.append(progress)
# 祝福 # 祝福
if len(detail['base_type_list']) > 0: if len(detail.base_type_list) > 0:
buff_h = 60 buff_h = 60
for buff in detail['buffs']: for buff in detail.buffs:
buff_h = buff_h + 50 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 buff_h = buff_h + math.ceil(buff_num / 3) * 55
else: else:
buff_h = 0 buff_h = 0
detail_h = detail_h + buff_h detail_h = detail_h + buff_h
# 奇物 # 奇物
if len(detail['miracles']) > 0: if len(detail.miracles) > 0:
miracles_h = 60 miracles_h = 60
miracles_num = len(detail['miracles']) miracles_num = len(detail.miracles)
miracles_h = miracles_h + math.ceil(miracles_num / 8) * 90 miracles_h = miracles_h + math.ceil(miracles_num / 8) * 90
else: else:
miracles_h = 0 miracles_h = 0
@ -292,9 +292,9 @@ async def draw_rogue_img(
if floor not in detail_list: if floor not in detail_list:
return '你还没有挑战该模拟宇宙!' return '你还没有挑战该模拟宇宙!'
elif schedule_type == '3': 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上期模拟宇宙]命令查询上期~' 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模拟宇宙]命令查询本期~' return '你还没有挑战上期模拟宇宙!\n可以使用[sr模拟宇宙]命令查询本期~'
# 获取背景图片各项参数 # 获取背景图片各项参数
@ -326,7 +326,7 @@ async def draw_rogue_img(
# 技能树激活 # 技能树激活
img_draw.text( img_draw.text(
(165, 569), (165, 569),
f'{raw_rogue_data["basic_info"]["unlocked_skill_points"]}', f'{raw_rogue_data.basic_info.unlocked_skill_points}',
white_color, white_color,
sr_font_42, sr_font_42,
'mm', 'mm',
@ -342,7 +342,7 @@ async def draw_rogue_img(
# 奇物解锁 # 奇物解锁
img_draw.text( img_draw.text(
(450, 569), (450, 569),
f'{raw_rogue_data["basic_info"]["unlocked_miracle_num"]}', f'{raw_rogue_data.basic_info.unlocked_miracle_num}',
white_color, white_color,
sr_font_42, sr_font_42,
'mm', 'mm',
@ -358,7 +358,7 @@ async def draw_rogue_img(
# 祝福解锁 # 祝福解锁
img_draw.text( img_draw.text(
(730, 569), (730, 569),
f'{raw_rogue_data["basic_info"]["unlocked_buff_num"]}', f'{raw_rogue_data.basic_info.unlocked_buff_num}',
white_color, white_color,
sr_font_42, sr_font_42,
'mm', 'mm',
@ -373,16 +373,16 @@ async def draw_rogue_img(
for index_floor, detail in enumerate(rogue_detail): for index_floor, detail in enumerate(rogue_detail):
if floor: if floor:
if floor == detail['progress']: if floor == detail.progress:
index_floor = 0 # noqa: PLW2901 index_floor = 0 # noqa: PLW2901
else: else:
continue continue
if detail['detail_h'] is None: if detail.detail_h is None:
continue continue
floor_pic = Image.open(TEXT_PATH / 'detail_bg.png').convert('RGBA') 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( floor_top_pic = Image.open(TEXT_PATH / 'floor_bg_top.png').convert(
'RGBA' 'RGBA'
@ -393,7 +393,7 @@ async def draw_rogue_img(
TEXT_PATH / 'floor_bg_center.png' TEXT_PATH / 'floor_bg_center.png'
).convert('RGBA') ).convert('RGBA')
floor_center_pic = floor_center_pic.resize( 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) floor_pic.paste(floor_center_pic, (0, 100), floor_center_pic)
@ -401,16 +401,16 @@ async def draw_rogue_img(
'RGBA' 'RGBA'
) )
floor_pic.paste( 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']] floor_name = progresslist[detail.progress]
difficulty_name = difficultylist[detail['difficulty']] difficulty_name = difficultylist[detail.difficulty]
time_array = detail['finish_time'] time_array = detail.finish_time
time_str = f"{time_array['year']}-{time_array['month']}" time_str = f'{time_array.year}-{time_array.month}'
time_str = f"{time_str}-{time_array['day']}" time_str = f'{time_str}-{time_array.day}'
time_str = f"{time_str} {time_array['hour']}:{time_array['minute']}" time_str = f'{time_str} {time_array.hour}:{time_array.minute}'
floor_pic_draw = ImageDraw.Draw(floor_pic) floor_pic_draw = ImageDraw.Draw(floor_pic)
floor_pic_draw.text( floor_pic_draw.text(
(450, 60), (450, 60),
@ -428,14 +428,14 @@ async def draw_rogue_img(
) )
floor_pic_draw.text( floor_pic_draw.text(
(800, 120), (800, 120),
f'当前积分:{detail["score"]}', f'当前积分:{detail.score}',
gray_color, gray_color,
sr_font_22, sr_font_22,
'rm', '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: # if char["id"] in char_temp:
# talent_num = char_temp[char["id"]] # talent_num = char_temp[char["id"]]
@ -456,7 +456,7 @@ async def draw_rogue_img(
# 祝福 # 祝福
buff_height = 0 buff_height = 0
if len(detail['base_type_list']) > 0: if len(detail.base_type_list) > 0:
floor_pic_draw.text( floor_pic_draw.text(
(93, 370), (93, 370),
'获得祝福', '获得祝福',
@ -465,10 +465,10 @@ async def draw_rogue_img(
'lm', 'lm',
) )
floor_pic.paste(content_center, (0, 390), content_center) floor_pic.paste(content_center, (0, 390), content_center)
for buff in detail['buffs']: for buff in detail.buffs:
buff_icon = bufflist[buff['base_type']['id']] buff_icon = bufflist[buff.base_type.id]
buff_name = buff['base_type']['name'] buff_name = buff.base_type.name
buffs = buff['items'] buffs = buff.items
draw_height = await _draw_rogue_buff( draw_height = await _draw_rogue_buff(
buffs, buffs,
buff_icon, buff_icon,
@ -479,7 +479,7 @@ async def draw_rogue_img(
buff_height = buff_height + draw_height buff_height = buff_height + draw_height
# 奇物 # 奇物
if len(detail['miracles']) > 0: if len(detail.miracles) > 0:
floor_pic_draw.text( floor_pic_draw.text(
(93, 370 + buff_height + 60), (93, 370 + buff_height + 60),
'获得奇物', '获得奇物',
@ -491,15 +491,15 @@ async def draw_rogue_img(
content_center, (0, 370 + buff_height + 80), content_center content_center, (0, 370 + buff_height + 80), content_center
) )
await _draw_rogue_miracles( await _draw_rogue_miracles(
detail['miracles'], detail.miracles,
floor_pic, floor_pic,
buff_height, buff_height,
) )
if detail['start_h'] is None: if detail.start_h is None:
continue 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( # await _draw_floor_card(
# level_star, # level_star,
# floor_pic, # floor_pic,
@ -531,7 +531,7 @@ async def draw_rogue_locust_img(
# char_temp = {} # char_temp = {}
# 计算背景图尺寸 # 计算背景图尺寸
rogue_detail = raw_rogue_data['detail']['records'] rogue_detail = raw_rogue_data.detail.records
# 记录打的宇宙列表 # 记录打的宇宙列表
# detail_list = [] # detail_list = []
@ -542,20 +542,20 @@ async def draw_rogue_locust_img(
detail_h = 340 detail_h = 340
# 祝福 # 祝福
if len(detail['base_type_list']) > 0: if len(detail.base_type_list) > 0:
buff_h = 60 buff_h = 60
for buff in detail['buffs']: for buff in detail.buffs:
buff_h = buff_h + 50 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 buff_h = buff_h + math.ceil(buff_num / 3) * 55
else: else:
buff_h = 0 buff_h = 0
detail_h = detail_h + buff_h detail_h = detail_h + buff_h
# 奇物 # 奇物
if len(detail['miracles']) > 0: if len(detail.miracles) > 0:
miracles_h = 60 miracles_h = 60
miracles_num = len(detail['miracles']) miracles_num = len(detail.miracles)
miracles_h = miracles_h + math.ceil(miracles_num / 8) * 90 miracles_h = miracles_h + math.ceil(miracles_num / 8) * 90
else: else:
miracles_h = 0 miracles_h = 0
@ -563,9 +563,9 @@ async def draw_rogue_locust_img(
# 事件 # 事件
blocks_h = 0 blocks_h = 0
if len(detail['blocks']) > 0: if len(detail.blocks) > 0:
blocks_h = 60 blocks_h = 60
blocks_num = len(detail['blocks']) blocks_num = len(detail.blocks)
blocks_h = blocks_h + math.ceil(blocks_num / 2) * 80 blocks_h = blocks_h + math.ceil(blocks_num / 2) * 80
else: else:
blocks_num = 0 blocks_num = 0
@ -608,7 +608,7 @@ async def draw_rogue_locust_img(
# 行者之道激活 # 行者之道激活
img_draw.text( img_draw.text(
(165, 569), (165, 569),
f'{raw_rogue_data["basic"]["cnt"]["narrow"]}', f'{raw_rogue_data.basic.cnt.narrow}',
white_color, white_color,
sr_font_42, sr_font_42,
'mm', 'mm',
@ -624,7 +624,7 @@ async def draw_rogue_locust_img(
# 奇物解锁 # 奇物解锁
img_draw.text( img_draw.text(
(450, 569), (450, 569),
f'{raw_rogue_data["basic"]["cnt"]["miracle"]}', f'{raw_rogue_data.basic.cnt.miracle}',
white_color, white_color,
sr_font_42, sr_font_42,
'mm', 'mm',
@ -640,7 +640,7 @@ async def draw_rogue_locust_img(
# 事件解锁 # 事件解锁
img_draw.text( img_draw.text(
(730, 569), (730, 569),
f'{raw_rogue_data["basic"]["cnt"]["event"]}', f'{raw_rogue_data.basic.cnt.event}',
white_color, white_color,
sr_font_42, sr_font_42,
'mm', 'mm',
@ -654,11 +654,11 @@ async def draw_rogue_locust_img(
) )
for _, detail in enumerate(rogue_detail): for _, detail in enumerate(rogue_detail):
if detail['detail_h'] is None: if detail.detail_h is None:
continue continue
floor_pic = Image.open(TEXT_PATH / 'detail_bg.png').convert('RGBA') 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( floor_top_pic = Image.open(TEXT_PATH / 'floor_bg_top.png').convert(
'RGBA' 'RGBA'
@ -669,7 +669,7 @@ async def draw_rogue_locust_img(
TEXT_PATH / 'floor_bg_center.png' TEXT_PATH / 'floor_bg_center.png'
).convert('RGBA') ).convert('RGBA')
floor_center_pic = floor_center_pic.resize( 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) floor_pic.paste(floor_center_pic, (0, 100), floor_center_pic)
@ -677,16 +677,16 @@ async def draw_rogue_locust_img(
'RGBA' 'RGBA'
) )
floor_pic.paste( 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'] floor_name = detail.name
difficulty_name = difficultylist[detail['difficulty']] difficulty_name = difficultylist[detail.difficulty]
time_array = detail['finish_time'] time_array = detail.finish_time
time_str = f"{time_array['year']}-{time_array['month']}" time_str = f'{time_array.year}-{time_array.month}'
time_str = f"{time_str}-{time_array['day']}" time_str = f'{time_str}-{time_array.day}'
time_str = f"{time_str} {time_array['hour']}:{time_array['minute']}" time_str = f'{time_str} {time_array.hour}:{time_array.minute}'
floor_pic_draw = ImageDraw.Draw(floor_pic) floor_pic_draw = ImageDraw.Draw(floor_pic)
floor_pic_draw.text( floor_pic_draw.text(
(450, 60), (450, 60),
@ -702,10 +702,10 @@ async def draw_rogue_locust_img(
sr_font_22, sr_font_22,
'lm', 'lm',
) )
if detail['fury']['type'] == 1: if detail.fury.type == 1:
floor_pic_draw.text( floor_pic_draw.text(
(800, 120), (800, 120),
f'扰动等级:{detail["fury"]["point"]}', f'扰动等级:{detail.fury.point}',
gray_color, gray_color,
sr_font_22, sr_font_22,
'rm', 'rm',
@ -713,14 +713,14 @@ async def draw_rogue_locust_img(
else: else:
floor_pic_draw.text( floor_pic_draw.text(
(800, 120), (800, 120),
f'位面紊乱倒计时:{detail["fury"]["point"]}', f'位面紊乱倒计时:{detail.fury.point}',
gray_color, gray_color,
sr_font_22, sr_font_22,
'rm', '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: # if char["id"] in char_temp:
# talent_num = char_temp[char["id"]] # talent_num = char_temp[char["id"]]
@ -741,7 +741,7 @@ async def draw_rogue_locust_img(
# 祝福 # 祝福
buff_height = 0 buff_height = 0
if len(detail['base_type_list']) > 0: if len(detail.base_type_list) > 0:
floor_pic_draw.text( floor_pic_draw.text(
(93, 370), (93, 370),
'获得祝福', '获得祝福',
@ -750,10 +750,10 @@ async def draw_rogue_locust_img(
'lm', 'lm',
) )
floor_pic.paste(content_center, (0, 390), content_center) floor_pic.paste(content_center, (0, 390), content_center)
for buff in detail['buffs']: for buff in detail.buffs:
buff_icon = bufflist[buff['base_type']['id']] buff_icon = bufflist[buff.base_type.id]
buff_name = buff['base_type']['name'] buff_name = buff.base_type.name
buffs = buff['items'] buffs = buff.items
draw_height = await _draw_rogue_buff( draw_height = await _draw_rogue_buff(
buffs, buffs,
buff_icon, buff_icon,
@ -765,7 +765,7 @@ async def draw_rogue_locust_img(
# 奇物 # 奇物
miracles_height = buff_height miracles_height = buff_height
if len(detail['miracles']) > 0: if len(detail.miracles) > 0:
floor_pic_draw.text( floor_pic_draw.text(
(93, 370 + miracles_height + 60), (93, 370 + miracles_height + 60),
'获得奇物', '获得奇物',
@ -777,7 +777,7 @@ async def draw_rogue_locust_img(
content_center, (0, 370 + miracles_height + 80), content_center content_center, (0, 370 + miracles_height + 80), content_center
) )
draw_height = await _draw_rogue_miracles( draw_height = await _draw_rogue_miracles(
detail['miracles'], detail.miracles,
floor_pic, floor_pic,
miracles_height, miracles_height,
) )
@ -786,7 +786,7 @@ async def draw_rogue_locust_img(
# 事件 # 事件
blocks_height = miracles_height blocks_height = miracles_height
if len(detail['blocks']) > 0: if len(detail.blocks) > 0:
floor_pic_draw.text( floor_pic_draw.text(
(93, 370 + blocks_height + 60), (93, 370 + blocks_height + 60),
'通过区域类型', '通过区域类型',
@ -798,17 +798,17 @@ async def draw_rogue_locust_img(
content_center, (0, 370 + blocks_height + 80), content_center content_center, (0, 370 + blocks_height + 80), content_center
) )
draw_height = await _draw_rogue_blocks( draw_height = await _draw_rogue_blocks(
detail['blocks'], detail.blocks,
floor_pic, floor_pic,
blocks_height, blocks_height,
) )
blocks_height = blocks_height + 80 blocks_height = blocks_height + 80
blocks_height = blocks_height + draw_height blocks_height = blocks_height + draw_height
if detail['start_h'] is None: if detail.start_h is None:
continue 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( # await _draw_floor_card(
# level_star, # level_star,
# floor_pic, # floor_pic,

View File

@ -59,17 +59,17 @@ async def _draw_card_1(
sr_uid: str, role_basic_info: RoleBasicInfo, stats: Stats sr_uid: str, role_basic_info: RoleBasicInfo, stats: Stats
) -> Image.Image: ) -> Image.Image:
# 名称 # 名称
nickname = role_basic_info['nickname'] nickname = role_basic_info.nickname
# 基本状态 # 基本状态
active_days = stats['active_days'] active_days = stats.active_days
avater_num = stats['avatar_num'] avater_num = stats.avatar_num
achievement_num = stats['achievement_num'] achievement_num = stats.achievement_num
chest_num = stats['chest_num'] chest_num = stats.chest_num
level = role_basic_info['level'] level = role_basic_info.level
# 忘却之庭 # 忘却之庭
abyss_process = stats['abyss_process'] abyss_process = stats.abyss_process
img_bg1 = bg1.copy() img_bg1 = bg1.copy()
bg1_draw = ImageDraw.Draw(img_bg1) bg1_draw = ImageDraw.Draw(img_bg1)
@ -137,22 +137,22 @@ async def _draw_card_1(
async def _draw_avatar_card( async def _draw_avatar_card(
avatar: AvatarListItem, equips: Dict[int, Optional[str]] avatar: AvatarListItem, equips: Dict[int, Optional[str]]
) -> Image.Image: ) -> 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_draw = ImageDraw.Draw(char_bg)
char_icon = await get_icon(avatar['icon']) char_icon = await get_icon(avatar.icon)
element_icon = elements[avatar['element']] element_icon = elements[avatar.element]
char_bg.paste(char_icon, (4, 8), mask=char_icon) char_bg.paste(char_icon, (4, 8), mask=char_icon)
char_bg.paste(element_icon, (81, 10), mask=element_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) char_bg.paste(circle, (0, 0), mask=circle)
equip_icon = (await get_icon(equip)).resize((48, 48)) equip_icon = (await get_icon(equip)).resize((48, 48))
char_bg.paste(equip_icon, (9, 80), mask=equip_icon) char_bg.paste(equip_icon, (9, 80), mask=equip_icon)
char_draw.text( char_draw.text(
(60, 146), (60, 146),
_lv(avatar['level']), _lv(avatar.level),
font=sr_font_24, font=sr_font_24,
fill=color_color, fill=color_color,
anchor='mm', anchor='mm',
@ -208,19 +208,19 @@ async def draw_role_card(sr_uid: str) -> Union[bytes, str]:
if isinstance(role_index, int): if isinstance(role_index, int):
return get_error(role_index) return get_error(role_index)
stats = role_index['stats'] stats = role_index.stats
avatars = role_index['avatar_list'] 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): if isinstance(detail, int):
return get_error(detail) return get_error(detail)
# 角色武器 # 角色武器
details = detail['avatar_list'] details = detail.avatar_list
equips: Dict[int, Optional[str]] = {} equips: Dict[int, Optional[str]] = {}
for detail in details: for detail in details:
equip = detail['equip'] equip = detail.equip
equips[detail['id']] = equip['icon'] if equip is not None else None equips[detail.id] = equip.icon if equip is not None else None
# 绘制总图 # 绘制总图
img1, img2 = await asyncio.gather( img1, img2 = await asyncio.gather(

View File

@ -62,18 +62,18 @@ async def _draw_task_img(
char: Optional[Expedition], char: Optional[Expedition],
): ):
if char is not None: if char is not None:
expedition_name = char['name'] expedition_name = char.name
remaining_time: str = seconds2hours(char['remaining_time']) remaining_time: str = seconds2hours(char.remaining_time)
note_travel_img = note_travel_bg.copy() note_travel_img = note_travel_bg.copy()
for i in range(2): for i in range(2):
avatar_url = char['avatars'][i] avatar_url = char.avatars[i]
image = await download_image(avatar_url) image = await download_image(avatar_url)
char_pic = image.convert('RGBA').resize( char_pic = image.convert('RGBA').resize(
(40, 40), Image.Resampling.LANCZOS # type: ignore (40, 40), Image.Resampling.LANCZOS # type: ignore
) )
note_travel_img.paste(char_pic, (495 + 68 * i, 20), char_pic) note_travel_img.paste(char_pic, (495 + 68 * i, 20), char_pic)
img.paste(note_travel_img, (0, 790 + index * 80), note_travel_img) img.paste(note_travel_img, (0, 790 + index * 80), note_travel_img)
if char['status'] == 'Finished': if char.status == 'Finished':
status_mark = '待收取' status_mark = '待收取'
else: else:
status_mark = str(remaining_time) 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) error_text = get_error_msg(daily_data)
img_draw.text( img_draw.text(
(350, 650), (350, 650),
f'{error_text} ,错误码{daily_data}', f'{error_text}, 错误码{daily_data}',
font=sr_font_26, font=sr_font_26,
fill=red_color, fill=red_color,
anchor='mm', 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) role_basic_info = await mys_api.get_role_basic_info(sr_uid)
if isinstance(role_basic_info, int): if isinstance(role_basic_info, int):
return get_error(img, sr_uid, role_basic_info) return get_error(img, sr_uid, role_basic_info)
nickname = role_basic_info['nickname'] nickname = role_basic_info.nickname
level = role_basic_info['level'] level = role_basic_info.level
else: else:
nickname = '开拓者' nickname = '开拓者'
level = '0' level = '0'
# 开拓力 # 开拓力
stamina = daily_data['current_stamina'] stamina = daily_data.current_stamina
max_stamina = daily_data['max_stamina'] max_stamina = daily_data.max_stamina
stamina_str = f'{stamina}/{max_stamina}' stamina_str = f'{stamina}/{max_stamina}'
stamina_percent = stamina / max_stamina stamina_percent = stamina / max_stamina
if stamina_percent > 0.8: if stamina_percent > 0.8:
@ -207,7 +207,7 @@ async def draw_stamina_img(sr_uid: str) -> Image.Image:
else: else:
stamina_color = second_color stamina_color = second_color
stamina_recovery_time = await seconds2hours_zhcn( stamina_recovery_time = await seconds2hours_zhcn(
daily_data['stamina_recover_time'] daily_data.stamina_recover_time
) )
img.paste(note_bg, (0, 0), note_bg) img.paste(note_bg, (0, 0), note_bg)
@ -217,8 +217,8 @@ async def draw_stamina_img(sr_uid: str) -> Image.Image:
task_task = [] task_task = []
for i in range(4): for i in range(4):
char = ( char = (
daily_data['expeditions'][i] daily_data.expeditions[i]
if i < len(daily_data['expeditions']) if i < len(daily_data.expeditions)
else None else None
) )
task_task.append(_draw_task_img(img, img_draw, i, char)) task_task.append(_draw_task_img(img, img_draw, i, char))

View File

@ -54,7 +54,7 @@ async def all_check(
if srconfig.get_config('CrazyNotice').data: if srconfig.get_config('CrazyNotice').data:
if not await check(mode, raw_data, push_data[f'{mode}_value']): if not await check(mode, raw_data, push_data[f'{mode}_value']):
await sqla.update_push_data( await sqla.update_push_data(
uid, {f'{mode}_is_push': 'off'} uid, bot_id, {f'{mode}_is_push': 'off'}
) )
continue continue
# 准备推送 # 准备推送
@ -73,7 +73,9 @@ async def all_check(
msg_dict[bot_id]['direct'][user_id] = NOTICE[mode] msg_dict[bot_id]['direct'][user_id] = NOTICE[mode]
else: else:
msg_dict[bot_id]['direct'][user_id] += NOTICE[mode] 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: else:
# 初始化 # 初始化
@ -85,21 +87,23 @@ async def all_check(
msg_dict[bot_id]['group'][gid][user_id] = NOTICE[mode] msg_dict[bot_id]['group'][gid][user_id] = NOTICE[mode]
else: else:
msg_dict[bot_id]['group'][gid][user_id] += NOTICE[mode] 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 return msg_dict
async def check(mode: str, data: DailyNoteData, limit: int) -> bool: async def check(mode: str, data: DailyNoteData, limit: int) -> bool:
if mode == 'resin': if mode == 'resin':
if data['current_stamina'] >= limit: if data.current_stamina >= limit:
return True return True
if data['current_stamina'] >= data['max_stamina']: if data.current_stamina >= data.max_stamina:
return True return True
return False return False
if mode == 'go': if mode == 'go':
for i in data['expeditions']: for i in data.expeditions:
if i['status'] == 'Ongoing': if i.status == 'Ongoing':
if int(i['remaining_time']) <= limit * 60: if i.remaining_time <= limit * 60:
return True return True
else: else:
return True return True

View File

@ -24,38 +24,36 @@ async def get_stamina_text(uid: str) -> str:
dailydata = await mys_api.get_daily_data(uid) dailydata = await mys_api.get_daily_data(uid)
if isinstance(dailydata, int): if isinstance(dailydata, int):
return get_error(dailydata) return get_error(dailydata)
max_stamina = dailydata['max_stamina'] max_stamina = dailydata.max_stamina
rec_time = '' rec_time = ''
current_stamina = dailydata['current_stamina'] current_stamina = dailydata.current_stamina
if current_stamina < 160: if current_stamina < 160:
stamina_recover_time = seconds2hours( stamina_recover_time = seconds2hours(
dailydata['stamina_recover_time'] dailydata.stamina_recover_time
) )
next_stamina_rec_time = seconds2hours( next_stamina_rec_time = seconds2hours(
8 * 60 8 * 60
- ( - (
(dailydata['max_stamina'] - dailydata['current_stamina']) (dailydata.max_stamina - dailydata.current_stamina)
* 8 * 8
* 60 * 60
- int(dailydata['stamina_recover_time']) - dailydata.stamina_recover_time
) )
) )
rec_time = f' ({next_stamina_rec_time}/{stamina_recover_time})' rec_time = f' ({next_stamina_rec_time}/{stamina_recover_time})'
accepted_epedition_num = dailydata['accepted_expedition_num'] accepted_epedition_num = dailydata.accepted_expedition_num
total_expedition_num = dailydata['total_expedition_num'] total_expedition_num = dailydata.total_expedition_num
finished_expedition_num = 0 finished_expedition_num = 0
expedition_info: List[str] = [] expedition_info: List[str] = []
for expedition in dailydata['expeditions']: for expedition in dailydata.expeditions:
expedition_name = expedition['name'] expedition_name = expedition.name
if expedition['status'] == 'Finished': if expedition.status == 'Finished':
expedition_info.append(f'{expedition_name} 探索完成') expedition_info.append(f'{expedition_name} 探索完成')
finished_expedition_num += 1 finished_expedition_num += 1
else: else:
remaining_time: str = seconds2hours( remaining_time: str = seconds2hours(expedition.remaining_time)
expedition['remaining_time']
)
expedition_info.append( expedition_info.append(
f'{expedition_name} 剩余时间{remaining_time}' f'{expedition_name} 剩余时间{remaining_time}'
) )

View File

@ -2,8 +2,9 @@ import copy
import time import time
import random import random
from string import digits, ascii_letters 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.api.mys_api import _MysApi
from gsuid_core.utils.database.models import GsUser from gsuid_core.utils.database.models import GsUser
from gsuid_core.utils.api.mys.models import MysSign, SignInfo, SignList from gsuid_core.utils.api.mys.models import MysSign, SignInfo, SignList
@ -56,8 +57,7 @@ class MysApi(_MysApi):
) -> Optional[str]: ) -> Optional[str]:
if mode == 'RANDOM': if mode == 'RANDOM':
return await GsUser.get_random_cookie(uid, game_name='sr') 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]: async def get_stoken(self, uid: str) -> Optional[str]:
return await GsUser.get_user_stoken_by_uid(uid, 'sr') 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 'STAR_RAIL_NOTE_URL', uid, header=self._HEADER
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(DailyNoteData, data['data']) data = msgspec.convert(data['data'], type=DailyNoteData)
# data = cast(DailyNoteData, data['data'])
return data return data
async def get_widget_stamina_data( async def get_widget_stamina_data(
@ -155,7 +156,8 @@ class MysApi(_MysApi):
_API['STAR_RAIL_WIDGRT_URL'], 'GET', header _API['STAR_RAIL_WIDGRT_URL'], 'GET', header
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(WidgetStamina, data['data']) data = msgspec.convert(data['data'], type=WidgetStamina)
# data = cast(WidgetStamina, data['data'])
return data return data
async def get_role_index(self, uid: str) -> Union[RoleIndex, int]: 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 'STAR_RAIL_INDEX_URL', uid, header=self._HEADER
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(RoleIndex, data['data']) data = msgspec.convert(data['data'], type=RoleIndex)
# data = cast(RoleIndex, data['data'])
return data return data
async def get_gacha_log_by_link_in_authkey( async def get_gacha_log_by_link_in_authkey(
@ -233,7 +236,8 @@ class MysApi(_MysApi):
}, },
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(GachaLog, data['data']) data = msgspec.convert(data['data'], type=GachaLog)
# data = cast(GachaLog, data['data'])
return data return data
async def get_avatar_info( async def get_avatar_info(
@ -271,7 +275,8 @@ class MysApi(_MysApi):
header=self._HEADER, header=self._HEADER,
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(AvatarInfo, data['data']) data = msgspec.convert(data['data'], type=AvatarInfo)
# data = cast(AvatarInfo, data['data'])
return data return data
async def get_sign_list(self, uid) -> Union[SignList, int]: 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 'STAR_RAIL_SIGN_LIST_URL', is_os, params
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(SignList, data['data']) data = msgspec.convert(data['data'], type=SignList)
# data = cast(SignList, data['data'])
return data return data
async def get_sign_info(self, uid) -> Union[SignInfo, int]: 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 'STAR_RAIL_SIGN_INFO_URL', is_os, params, header
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(SignInfo, data['data']) data = msgspec.convert(data['data'], type=SignInfo)
# data = cast(SignInfo, data['data'])
return data return data
async def get_srspiral_abyss_info( async def get_srspiral_abyss_info(
@ -367,7 +374,8 @@ class MysApi(_MysApi):
header=self._HEADER, header=self._HEADER,
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(AbyssData, data['data']) data = msgspec.convert(data['data'], type=AbyssData)
# data = cast(AbyssData, data['data'])
return data return data
async def get_rogue_info( async def get_rogue_info(
@ -390,7 +398,8 @@ class MysApi(_MysApi):
header=self._HEADER, header=self._HEADER,
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(RogueData, data['data']) data = msgspec.convert(data['data'], type=RogueData)
# data = cast(RogueData, data['data'])
return data return data
async def get_rogue_locust_info( async def get_rogue_locust_info(
@ -411,7 +420,8 @@ class MysApi(_MysApi):
header=self._HEADER, header=self._HEADER,
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(RogueLocustData, data['data']) data = msgspec.convert(data['data'], type=RogueLocustData)
# data = cast(RogueLocustData, data['data'])
return data return data
async def mys_sign( async def mys_sign(
@ -457,7 +467,8 @@ class MysApi(_MysApi):
}, },
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(MysSign, data['data']) data = msgspec.convert(data['data'], type=MysSign)
# data = cast(MysSign, data['data'])
return data return data
async def get_award(self, sr_uid, month) -> Union[MonthlyAward, int]: async def get_award(self, sr_uid, month) -> Union[MonthlyAward, int]:
@ -487,7 +498,8 @@ class MysApi(_MysApi):
use_proxy=True, use_proxy=True,
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(MonthlyAward, data['data']) data = msgspec.convert(data['data'], type=MonthlyAward)
# data = cast(MonthlyAward, data['data'])
return data return data
async def get_role_basic_info( async def get_role_basic_info(
@ -497,7 +509,8 @@ class MysApi(_MysApi):
'STAR_RAIL_ROLE_BASIC_INFO_URL', sr_uid, header=self._HEADER 'STAR_RAIL_ROLE_BASIC_INFO_URL', sr_uid, header=self._HEADER
) )
if isinstance(data, Dict): if isinstance(data, Dict):
data = cast(RoleBasicInfo, data['data']) data = msgspec.convert(data['data'], type=RoleBasicInfo)
# data = cast(RoleBasicInfo, data['data'])
return data return data