使用 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 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

View File

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

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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}'
)

View File

@ -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,7 +57,6 @@ 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')
async def get_stoken(self, uid: str) -> Optional[str]:
@ -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