diff --git a/StarRailUID/sruid_utils/api/mys/api.py b/StarRailUID/sruid_utils/api/mys/api.py index 256ddae..2772f51 100644 --- a/StarRailUID/sruid_utils/api/mys/api.py +++ b/StarRailUID/sruid_utils/api/mys/api.py @@ -49,8 +49,10 @@ STAR_RAIL_AVATAR_INFO_URL_OS = ( STAR_RAIL_AVATAR_LIST_URL = f'{OLD_URL}/event/rpgcalc/avatar/list' STAR_RAIL_AVATAR_DETAIL_URL = f'{OLD_URL}/event/rpgcalc/avatar/detail' -CHALLENGE_INFO_URL = f'{NEW_URL}/game_record/app/hkrpg/api/challenge' -CHALLENGE_INFO_URL_OS = f'{OS_INFO_URL}/game_record/hkrpg/api/challenge' +CHALLENGE_INFO_URL = f'{NEW_URL}/game_record/app/hkrpg/api/challenge' # 忘却之庭 +CHALLENGE_INFO_URL_OS = f'{OS_INFO_URL}/game_record/hkrpg/api/challenge' # OS忘却之庭 +CHALLENGE_STORY_INFO_URL = f'{NEW_URL}/game_record/app/hkrpg/api/challenge_story' # 虚构叙事 +CHALLENGE_BOSS_INFO_URL = f'{NEW_URL}/game_record/app/hkrpg/api/challenge_boss' # 末日幻影 ROGUE_INFO_URL = ( f'{NEW_URL}/game_record/app/hkrpg/api/rogue' # 角色模拟宇宙信息接口 diff --git a/StarRailUID/sruid_utils/api/mys/models.py b/StarRailUID/sruid_utils/api/mys/models.py index 3763e9a..945474d 100644 --- a/StarRailUID/sruid_utils/api/mys/models.py +++ b/StarRailUID/sruid_utils/api/mys/models.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Union +from typing import Any, Dict, List, Union, Optional from msgspec import Struct @@ -254,16 +254,17 @@ class AbyssAvatar(Struct): class AbyssNodeDetail(Struct): - challenge_time: AbyssTime + challenge_time: Union[AbyssTime, None] avatars: List[AbyssAvatar] class AbyssFloorDetail(Struct): name: str - round_num: int - star_num: int + star_num: Union[int, str] node_1: AbyssNodeDetail node_2: AbyssNodeDetail + round_num: Optional[int] = None + is_fast: Optional[bool] = False class AbyssData(Struct): @@ -278,6 +279,26 @@ class AbyssData(Struct): max_floor_detail: Union[bool, None] = None +class AbyssStoryData(Struct): + groups: Any + star_num: int + max_floor: str + battle_num: int + has_data: bool + all_floor_detail: List[AbyssFloorDetail] + max_floor_id: int + + +class AbyssBossData(Struct): + groups: Any + star_num: int + max_floor: str + battle_num: int + has_data: bool + all_floor_detail: List[AbyssFloorDetail] + max_floor_id: int + + ################ # 每月札记相关 # ################ diff --git a/StarRailUID/starrailuid_abyss/__init__.py b/StarRailUID/starrailuid_abyss/__init__.py index 05777db..2589776 100644 --- a/StarRailUID/starrailuid_abyss/__init__.py +++ b/StarRailUID/starrailuid_abyss/__init__.py @@ -1,68 +1,46 @@ -import re - -from gsuid_core.sv import SV -from gsuid_core.bot import Bot -from gsuid_core.models import Event -from gsuid_core.utils.error_reply import UID_HINT - -from ..utils.convert import get_uid -from ..utils.sr_prefix import PREFIX -from .draw_abyss_card import draw_abyss_img - -sv_srabyss = SV('sr查询深渊') - - -@sv_srabyss.on_command( - ( - f'{PREFIX}查询深渊', - f'{PREFIX}sy', - f'{PREFIX}查询上期深渊', - f'{PREFIX}sqsy', - f'{PREFIX}上期深渊', - f'{PREFIX}深渊', - ), - block=True, -) -async def send_srabyss_info(bot: Bot, ev: Event): - name = ''.join(re.findall('[\u4e00-\u9fa5]', ev.text)) - if name: - return None - - await bot.logger.info('开始执行[sr查询深渊信息]') - get_uid_ = await get_uid(bot, ev, True) - if get_uid_ is None: - return await bot.send(UID_HINT) - uid, user_id = get_uid_ - if uid is None: - return await bot.send(UID_HINT) - await bot.logger.info(f'[sr查询深渊信息]uid: {uid}') - - if 'sq' in ev.command or '上期' in ev.command: - schedule_type = '2' - else: - schedule_type = '1' - await bot.logger.info(f'[sr查询深渊信息]深渊期数: {schedule_type}') - - if ev.text in ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']: - floor = ( - ev.text.replace('一', '1') - .replace('二', '2') - .replace('三', '3') - .replace('四', '4') - .replace('五', '5') - .replace('六', '6') - .replace('七', '7') - .replace('八', '8') - .replace('九', '9') - .replace('十', '10') - ) - else: - floor = ev.text - if floor and floor.isdigit(): - floor = int(floor) - else: - floor = None - await bot.logger.info(f'[sr查询深渊信息]深渊层数: {floor}') - im = await draw_abyss_img(user_id, uid, ev.sender, floor, schedule_type) - await bot.send(im) - return None +import re + +from gsuid_core.sv import SV +from gsuid_core.bot import Bot +from gsuid_core.models import Event +from gsuid_core.utils.error_reply import UID_HINT + +from ..utils.convert import get_uid +from ..utils.sr_prefix import PREFIX +from .draw_abyss_card import draw_abyss_img + +sv_srabyss = SV('sr查询深渊') + + +@sv_srabyss.on_command( + ( + f'{PREFIX}查询深渊', + f'{PREFIX}查询上期深渊', + f'{PREFIX}上期深渊', + f'{PREFIX}深渊', + ), + block=True, +) +async def send_srabyss_info(bot: Bot, ev: Event): + name = ''.join(re.findall('[\u4e00-\u9fa5]', ev.text)) + if name: + return None + + await bot.logger.info('开始执行[sr查询深渊信息]') + get_uid_ = await get_uid(bot, ev, True) + if get_uid_ is None: + return await bot.send(UID_HINT) + uid, user_id = get_uid_ + if uid is None: + return await bot.send(UID_HINT) + await bot.logger.info(f'[sr查询深渊信息]uid: {uid}') + + if '上期' in ev.command: + schedule_type = '2' + else: + schedule_type = '1' + await bot.logger.info(f'[sr查询深渊信息]深渊期数: {schedule_type}') + + im = await draw_abyss_img(user_id, uid, ev.sender, schedule_type) + await bot.send(im) + return None diff --git a/StarRailUID/starrailuid_abyss/draw_abyss_card.py b/StarRailUID/starrailuid_abyss/draw_abyss_card.py index 063717f..ec42950 100644 --- a/StarRailUID/starrailuid_abyss/draw_abyss_card.py +++ b/StarRailUID/starrailuid_abyss/draw_abyss_card.py @@ -21,19 +21,6 @@ from ..utils.fonts.starrail_fonts import ( sr_font_42, ) -abyss_list = { - '1': '一', - '2': '二', - '3': '三', - '4': '四', - '5': '五', - '6': '六', - '7': '七', - '8': '八', - '9': '九', - '10': '十', -} - TEXT_PATH = Path(__file__).parent / 'texture2D' white_color = (255, 255, 255) gray_color = (175, 175, 175) @@ -70,14 +57,10 @@ async def get_abyss_star_pic(star: int) -> Image.Image: async def _draw_abyss_card( char: AbyssAvatar, - talent_num: str, floor_pic: Image.Image, index_char: int, index_part: int, ): - # 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((150, 170)) element_icon = elements[char.element] @@ -94,12 +77,6 @@ async def _draw_abyss_card( fill=white_color, anchor='mm', ) - # 不存在自动下载 - # if not char_pic_path.exists(): - # await create_single_char_card(char_id) - # talent_pic = await get_talent_pic(int(talent_num)) - # talent_pic = talent_pic.resize((90, 45)) - # char_card.paste(talent_pic, (137, 260), talent_pic) char_card_draw.text( (100, 165), f'等级 {char.level}', @@ -151,32 +128,23 @@ async def draw_abyss_img( qid: Union[str, int], uid: str, sender: Union[str, str], - floor: Optional[int] = None, schedule_type: str = '1', ) -> Union[bytes, str]: - raw_abyss_data = await mys_api.get_srspiral_abyss_info(uid, schedule_type) + raw_abyss_data = await mys_api.get_abyss_info(uid, schedule_type) if isinstance(raw_abyss_data, int): return get_error(raw_abyss_data) # 获取查询者数据 - if floor: - floor_num = 1 - if floor > 12: - return '楼层不能大于12层!' - if len(raw_abyss_data.all_floor_detail) < floor: - return '你还没有挑战该层!' - else: - if raw_abyss_data.max_floor == '': - return '你还没有挑战本期深渊!\n可以使用[sr上期深渊]命令查询上期~' - floor_num = len(raw_abyss_data.all_floor_detail) + if raw_abyss_data.max_floor == '': + return '你还没有挑战本期深渊!\n可以使用[sr上期深渊]命令查询上期~' + # 过滤掉 is_fast(快速通关) 为 True 的项 + floor_detail = [detail for detail in raw_abyss_data.all_floor_detail if not detail.is_fast] + floor_num = len(floor_detail) # 获取背景图片各项参数 based_w = 900 - if floor_num >= 3: - based_h = 2367 - else: - based_h = 657 + 570 * floor_num + based_h = 657 + 570 * floor_num img = img_bg.copy() img = img.crop((0, 0, based_w, based_h)) abyss_title = Image.open(TEXT_PATH / 'head.png') @@ -231,13 +199,6 @@ async def draw_abyss_img( ) for index_floor, level in enumerate(raw_abyss_data.all_floor_detail): - if floor: - if abyss_list[str(floor)] == level.name.split('其')[1]: - 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 @@ -276,7 +237,6 @@ async def draw_abyss_img( for index_char, char in enumerate(avatars_array.avatars): await _draw_abyss_card( char, - 0, # type: ignore floor_pic, index_char, index_part, @@ -290,114 +250,6 @@ async def draw_abyss_img( round_num, ) - # title_data = { - # '最强一击!': damage_rank[0], - # '最多击破!': defeat_rank[0], - # '承受伤害': take_damage_rank[0], - # '元素战技': energy_skill_rank[0], - # } - # for _index, _name in enumerate(title_data): - # _char = title_data[_name] - # _char_id = _char['avatar_id'] - # char_side_path = TEXT_PATH / f'{_char_id}.png' - # # if not char_side_path.exists(): - # # await download_file(_char['avatar_icon'], 3, f'{_char_id}.png') - # char_side = Image.open(char_side_path) - # char_side = char_side.resize((75, 75)) - # intent = _index * 224 - # title_xy = (115 + intent, 523) - # val_xy = (115 + intent, 545) - # _val = str(_char['value']) - # img.paste(char_side, (43 + intent, 484), char_side) - # img_draw.text(title_xy, _name, white_color, gs_font_20, 'lm') - # img_draw.text(val_xy, _val, white_color, gs_font_26, 'lm') - - # 过滤数据 - # raw_abyss_data['floors'] = [ - # i for i in raw_abyss_data['floors'] if i['index'] >= 9 - # ] - - # 绘制缩略信息 - # for num in range(4): - # omit_bg = Image.open(TEXT_PATH / 'abyss_omit.png') - # omit_draw = ImageDraw.Draw(omit_bg) - # omit_draw.text((56, 34), f'第{num+9}层', white_color, gs_font_32, 'lm') - # omit_draw.rounded_rectangle((165, 19, 225, 49), 20, red_color) - # if len(raw_abyss_data['floors']) - 1 >= num: - # _floor = raw_abyss_data['floors'][num] - # if _floor['star'] == _floor['max_star']: - # _color = red_color - # _text = '全满星' - # else: - # _gap = _floor['max_star'] - _floor['star'] - # _color = blue_color - # _text = f'差{_gap}颗' - # if not is_unfull: - # _timestamp = int( - # _floor['levels'][-1]['battles'][-1]['timestamp'] - # ) - # _time_array = time.localtime(_timestamp) - # _time_str = time.strftime('%Y-%m-%d %H:%M:%S', _time_array) - # else: - # _time_str = '请挑战后查看时间数据!' - # else: - # _color = gray_color - # _text = '未解锁' - # _time_str = '请挑战后查看时间数据!' - # omit_draw.rounded_rectangle((165, 19, 255, 49), 20, _color) - # omit_draw.text((210, 34), _text, white_color, gs_font_26, 'mm') - # omit_draw.text((54, 65), _time_str, sec_color, gs_font_22, 'lm') - # pos = (20 + 459 * (num % 2), 613 + 106 * (num // 2)) - # img.paste(omit_bg, pos, omit_bg) - - # if is_unfull: - # hint = Image.open(TEXT_PATH / 'hint.png') - # img.paste(hint, (0, 830), hint) - # else: - # task = [] - # floor_num = floors_data['index'] - # for index_floor, level in enumerate(floors_data['levels']): - # floor_pic = Image.open(TEXT_PATH / 'abyss_floor.png') - # level_star = level['star'] - # timestamp = int(level['battles'][0]['timestamp']) - # time_array = time.localtime(timestamp) - # time_str = time.strftime('%Y-%m-%d %H:%M:%S', time_array) - # for index_part, battle in enumerate(level['battles']): - # for index_char, char in enumerate(battle['avatars']): - # # 获取命座 - # if char["id"] in char_temp: - # talent_num = char_temp[char["id"]] - # else: - # for i in char_data: - # if i["id"] == char["id"]: - # talent_num = str( - # i["actived_constellation_num"] - # ) - # char_temp[char["id"]] = talent_num - # break - # task.append( - # _draw_abyss_card( - # char, - # talent_num, # type: ignore - # floor_pic, - # index_char, - # index_part, - # ) - # ) - # await asyncio.gather(*task) - # task.clear() - # task.append( - # _draw_floor_card( - # level_star, - # floor_pic, - # img, - # time_str, - # index_floor, - # floor_num, - # ) - # ) - # await asyncio.gather(*task) - res = await convert_img(img) logger.info('[查询深渊信息]绘图已完成,等待发送!') return res diff --git a/StarRailUID/starrailuid_abyss_boss/__init__.py b/StarRailUID/starrailuid_abyss_boss/__init__.py new file mode 100644 index 0000000..4f862a3 --- /dev/null +++ b/StarRailUID/starrailuid_abyss_boss/__init__.py @@ -0,0 +1,46 @@ +import re + +from gsuid_core.sv import SV +from gsuid_core.bot import Bot +from gsuid_core.models import Event +from gsuid_core.utils.error_reply import UID_HINT + +from ..utils.convert import get_uid +from ..utils.sr_prefix import PREFIX +from .draw_abyss_card import draw_abyss_img + +sv_abyss_boss = SV('sr查询末日幻影') + + +@sv_abyss_boss.on_command( + ( + f'{PREFIX}查询末日幻影', + f'{PREFIX}查询上期末日幻影', + f'{PREFIX}上期末日', + f'{PREFIX}末日', + ), + block=True, +) +async def send_srabyss_info(bot: Bot, ev: Event): + name = ''.join(re.findall('[\u4e00-\u9fa5]', ev.text)) + if name: + return None + + await bot.logger.info('开始执行[sr查询末日幻影信息]') + get_uid_ = await get_uid(bot, ev, True) + if get_uid_ is None: + return await bot.send(UID_HINT) + uid, user_id = get_uid_ + if uid is None: + return await bot.send(UID_HINT) + await bot.logger.info(f'[sr查询末日幻影信息]uid: {uid}') + + if '上期' in ev.command: + schedule_type = '2' + else: + schedule_type = '1' + await bot.logger.info(f'[sr查询末日幻影信息]末日幻影期数: {schedule_type}') + + im = await draw_abyss_img(user_id, uid, ev.sender, schedule_type) + await bot.send(im) + return None diff --git a/StarRailUID/starrailuid_abyss_boss/draw_abyss_card.py b/StarRailUID/starrailuid_abyss_boss/draw_abyss_card.py new file mode 100644 index 0000000..24f40a7 --- /dev/null +++ b/StarRailUID/starrailuid_abyss_boss/draw_abyss_card.py @@ -0,0 +1,248 @@ +from pathlib import Path +from typing import Union, Optional + +from PIL import Image, ImageDraw +from gsuid_core.logger import logger +from gsuid_core.utils.error_reply import get_error +from gsuid_core.utils.image.image_tools import ( + get_qq_avatar, + draw_pic_with_ring, +) + +from .utils import get_icon +from ..utils.mys_api import mys_api +from ..utils.image.convert import convert_img +from ..sruid_utils.api.mys.models import AbyssAvatar +from ..utils.fonts.starrail_fonts import ( + sr_font_22, + sr_font_28, + sr_font_30, + sr_font_34, + sr_font_42, +) + +TEXT_PATH = Path(__file__).parent / 'texture2D' +white_color = (255, 255, 255) +gray_color = (175, 175, 175) +img_bg = Image.open(TEXT_PATH / 'bg.jpg') +level_cover = Image.open(TEXT_PATH / 'level_cover.png').convert('RGBA') +char_bg_4 = Image.open(TEXT_PATH / 'char4_bg.png').convert('RGBA') +char_bg_5 = Image.open(TEXT_PATH / 'char5_bg.png').convert('RGBA') +rank_bg = Image.open(TEXT_PATH / 'rank_bg.png').convert('RGBA') +star_yes = Image.open(TEXT_PATH / 'star.png').convert('RGBA') +star_gray = Image.open(TEXT_PATH / 'star_gray.png').convert('RGBA') + +elements = { + 'ice': Image.open(TEXT_PATH / 'IconNatureColorIce.png').convert('RGBA'), + 'fire': Image.open(TEXT_PATH / 'IconNatureColorFire.png').convert('RGBA'), + 'imaginary': Image.open( + TEXT_PATH / 'IconNatureColorImaginary.png' + ).convert('RGBA'), + 'quantum': Image.open(TEXT_PATH / 'IconNatureColorQuantum.png').convert( + 'RGBA' + ), + 'lightning': Image.open(TEXT_PATH / 'IconNatureColorThunder.png').convert( + 'RGBA' + ), + 'wind': Image.open(TEXT_PATH / 'IconNatureColorWind.png').convert('RGBA'), + 'physical': Image.open(TEXT_PATH / 'IconNaturePhysical.png').convert( + 'RGBA' + ), +} + + +async def get_abyss_star_pic(star: int) -> Image.Image: + return Image.open(TEXT_PATH / f'star{star}.png') + + +async def _draw_abyss_card( + char: AbyssAvatar, + floor_pic: Image.Image, + index_char: int, + index_part: int, +): + # 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((150, 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, (35, 25), mask=element_icon) + char_card_draw = ImageDraw.Draw(char_bg) + if char.rank > 0: + char_bg.paste(rank_bg, (150, 16), mask=rank_bg) + char_card_draw.text( + (162, 31), + f'{char.rank}', + font=sr_font_22, + fill=white_color, + anchor='mm', + ) + char_card_draw.text( + (100, 165), + f'等级 {char.level}', + font=sr_font_22, + fill=white_color, + anchor='mm', + ) + floor_pic.paste( + char_bg, + (75 + 185 * index_char, 130 + index_part * 219), + char_bg, + ) + + +async def _draw_floor_card( + level_star: int, + floor_pic: Image.Image, + img: Image.Image, + index_floor: int, + floor_name: str, +): + for index_num in [0, 1, 2]: + star_num = index_num + 1 + if star_num <= level_star: + star_pic = star_yes.copy() + else: + star_pic = star_gray.copy() + floor_pic.paste(star_pic, (103 + index_num * 50, 25), star_pic) + floor_pic_draw = ImageDraw.Draw(floor_pic) + floor_pic_draw.text( + (450, 60), + floor_name, + font=sr_font_42, + fill=white_color, + anchor='mm', + ) + img.paste(floor_pic, (0, 657 + index_floor * 570), floor_pic) + + +async def draw_abyss_img( + qid: Union[str, int], + uid: str, + sender: Union[str, str], + schedule_type: str = '1', +) -> Union[bytes, str]: + raw_abyss_data = await mys_api.get_abyss_boss_info(uid, schedule_type) + if isinstance(raw_abyss_data, int): + return get_error(raw_abyss_data) + + # 获取查询者数据 + if raw_abyss_data.max_floor == '': + return '你还没有挑战本期末日幻影!\n可以使用[sr上期末日幻影]命令查询上期~' + # 过滤掉 is_fast(快速通关) 为 True 的项 + floor_detail = [detail for detail in raw_abyss_data.all_floor_detail if not detail.is_fast] + floor_num = len(floor_detail) + + # 获取背景图片各项参数 + based_w = 900 + based_h = 657 + 570 * floor_num + img = img_bg.copy() + img = img.crop((0, 0, based_w, based_h)) + abyss_title = Image.open(TEXT_PATH / 'head.png') + img.paste(abyss_title, (0, 0), abyss_title) + + # 获取头像 + _id = str(qid) + if _id.startswith('http'): + char_pic = await get_qq_avatar(avatar_url=_id) + elif sender.get('avatar') is not None: + char_pic = await get_qq_avatar(avatar_url=sender['avatar']) + else: + char_pic = await get_qq_avatar(qid=qid) + char_pic = await draw_pic_with_ring(char_pic, 250, None, False) + + img.paste(char_pic, (325, 132), char_pic) + + # 绘制抬头 + img_draw = ImageDraw.Draw(img) + img_draw.text((450, 442), f'UID {uid}', white_color, sr_font_28, 'mm') + + # 总体数据 + abyss_data = Image.open(TEXT_PATH / 'data.png') + img.paste(abyss_data, (0, 500), abyss_data) + + # 最深抵达 + img_draw.text( + (220, 565), + f'{raw_abyss_data.max_floor}', + white_color, + sr_font_34, + 'lm', + ) + # 挑战次数 + img_draw.text( + (220, 612), + f'{raw_abyss_data.battle_num}', + white_color, + sr_font_34, + 'lm', + ) + + star_num_pic = Image.open(TEXT_PATH / 'star.png') + img.paste(star_num_pic, (615, 557), star_num_pic) + + img_draw.text( + (695, 590), + f'{raw_abyss_data.star_num}/12', + white_color, + sr_font_42, + 'lm', + ) + + for index_floor, level in enumerate(floor_detail): + floor_pic = Image.open(TEXT_PATH / 'floor_bg.png') + level_star = int(level.star_num) + floor_name = level.name + node_1 = level.node_1 + node_2 = level.node_2 + for index_part in [0, 1]: + node_num = index_part + 1 + if node_num == 1: + time_array = node_1.challenge_time + else: + time_array = node_2.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), + f'节点{node_num}', + white_color, + sr_font_30, + 'lm', + ) + floor_pic_draw.text( + (201, 120 + index_part * 219), + f'{time_str}', + gray_color, + sr_font_22, + 'lm', + ) + if node_num == 1: + avatars_array = node_1 + else: + avatars_array = node_2 + + for index_char, char in enumerate(avatars_array.avatars): + await _draw_abyss_card( + char, + floor_pic, + index_char, + index_part, + ) + await _draw_floor_card( + level_star, + floor_pic, + img, + index_floor, + floor_name, + + ) + + res = await convert_img(img) + logger.info('[查询末日幻影信息]绘图已完成,等待发送!') + return res diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorFire.png b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorFire.png new file mode 100644 index 0000000..c0e5c09 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorFire.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorIce.png b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorIce.png new file mode 100644 index 0000000..9026e17 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorIce.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorImaginary.png b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorImaginary.png new file mode 100644 index 0000000..da9f292 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorImaginary.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorQuantum.png b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorQuantum.png new file mode 100644 index 0000000..3ba24c0 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorQuantum.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorThunder.png b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorThunder.png new file mode 100644 index 0000000..9982c61 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorThunder.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorWind.png b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorWind.png new file mode 100644 index 0000000..f92982a Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNatureColorWind.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/IconNaturePhysical.png b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNaturePhysical.png new file mode 100644 index 0000000..e78da4f Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/IconNaturePhysical.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/bg.jpg b/StarRailUID/starrailuid_abyss_boss/texture2D/bg.jpg new file mode 100644 index 0000000..1d4db8c Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/bg.jpg differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/char4_bg.png b/StarRailUID/starrailuid_abyss_boss/texture2D/char4_bg.png new file mode 100644 index 0000000..1f62615 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/char4_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/char5_bg.png b/StarRailUID/starrailuid_abyss_boss/texture2D/char5_bg.png new file mode 100644 index 0000000..0a8f204 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/char5_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/data.png b/StarRailUID/starrailuid_abyss_boss/texture2D/data.png new file mode 100644 index 0000000..1e2d3f4 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/data.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/floor_bg.png b/StarRailUID/starrailuid_abyss_boss/texture2D/floor_bg.png new file mode 100644 index 0000000..05af753 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/floor_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/head.png b/StarRailUID/starrailuid_abyss_boss/texture2D/head.png new file mode 100644 index 0000000..b8917c0 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/head.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/level_cover.png b/StarRailUID/starrailuid_abyss_boss/texture2D/level_cover.png new file mode 100644 index 0000000..2b0df3c Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/level_cover.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/rank_bg.png b/StarRailUID/starrailuid_abyss_boss/texture2D/rank_bg.png new file mode 100644 index 0000000..e335727 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/rank_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/star.png b/StarRailUID/starrailuid_abyss_boss/texture2D/star.png new file mode 100644 index 0000000..c30ab43 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/star.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/texture2D/star_gray.png b/StarRailUID/starrailuid_abyss_boss/texture2D/star_gray.png new file mode 100644 index 0000000..91cdb18 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_boss/texture2D/star_gray.png differ diff --git a/StarRailUID/starrailuid_abyss_boss/utils.py b/StarRailUID/starrailuid_abyss_boss/utils.py new file mode 100644 index 0000000..a18f624 --- /dev/null +++ b/StarRailUID/starrailuid_abyss_boss/utils.py @@ -0,0 +1,26 @@ +from io import BytesIO +from pathlib import Path +from typing import TypeVar + +from PIL import Image +from aiohttp import ClientSession +from gsuid_core.data_store import get_res_path + +T = TypeVar('T') + +ROLEINFO_PATH = get_res_path() / 'StarRailUID' / 'roleinfo' +ROLEINFO_PATH.mkdir(parents=True, exist_ok=True) + + +async def get_icon(url: str) -> Image.Image: + name = url.split('/')[-1] + path = ROLEINFO_PATH / name + if (path).exists(): + content = path.read_bytes() + else: + async with ClientSession() as client: + async with client.get(url) as resp: + content = await resp.read() + with Path.open(path, 'wb') as f: + f.write(content) + return Image.open(BytesIO(content)).convert('RGBA') diff --git a/StarRailUID/starrailuid_abyss_story/__init__.py b/StarRailUID/starrailuid_abyss_story/__init__.py new file mode 100644 index 0000000..433622f --- /dev/null +++ b/StarRailUID/starrailuid_abyss_story/__init__.py @@ -0,0 +1,48 @@ +import re + +from gsuid_core.sv import SV +from gsuid_core.bot import Bot +from gsuid_core.models import Event +from gsuid_core.utils.error_reply import UID_HINT + +from ..utils.convert import get_uid +from ..utils.sr_prefix import PREFIX +from .draw_abyss_card import draw_abyss_img + +sv_abyss_story = SV('sr查询虚构叙事') + + +@sv_abyss_story.on_command( + ( + f'{PREFIX}查询虚构叙事', + f'{PREFIX}xg', + f'{PREFIX}查询上期虚构叙事', + f'{PREFIX}sqxg', + f'{PREFIX}上期虚构', + f'{PREFIX}虚构', + ), + block=True, +) +async def send_srabyss_info(bot: Bot, ev: Event): + name = ''.join(re.findall('[\u4e00-\u9fa5]', ev.text)) + if name: + return None + + await bot.logger.info('开始执行[sr查询虚构叙事信息]') + get_uid_ = await get_uid(bot, ev, True) + if get_uid_ is None: + return await bot.send(UID_HINT) + uid, user_id = get_uid_ + if uid is None: + return await bot.send(UID_HINT) + await bot.logger.info(f'[sr查询虚构叙事信息]uid: {uid}') + + if 'sq' in ev.command or '上期' in ev.command: + schedule_type = '2' + else: + schedule_type = '1' + await bot.logger.info(f'[sr查询虚构叙事信息]虚构叙事期数: {schedule_type}') + + im = await draw_abyss_img(user_id, uid, ev.sender, schedule_type) + await bot.send(im) + return None diff --git a/StarRailUID/starrailuid_abyss_story/draw_abyss_card.py b/StarRailUID/starrailuid_abyss_story/draw_abyss_card.py new file mode 100644 index 0000000..41c30d6 --- /dev/null +++ b/StarRailUID/starrailuid_abyss_story/draw_abyss_card.py @@ -0,0 +1,265 @@ +from pathlib import Path +from typing import Union, Optional + +from PIL import Image, ImageDraw +from gsuid_core.logger import logger +from gsuid_core.utils.error_reply import get_error +from gsuid_core.utils.image.image_tools import ( + get_qq_avatar, + draw_pic_with_ring, +) + +from .utils import get_icon +from ..utils.mys_api import mys_api +from ..utils.image.convert import convert_img +from ..sruid_utils.api.mys.models import AbyssAvatar +from ..utils.fonts.starrail_fonts import ( + sr_font_22, + sr_font_28, + sr_font_30, + sr_font_34, + sr_font_42, +) + +TEXT_PATH = Path(__file__).parent / 'texture2D' +white_color = (255, 255, 255) +gray_color = (175, 175, 175) +img_bg = Image.open(TEXT_PATH / 'bg.jpg') +level_cover = Image.open(TEXT_PATH / 'level_cover.png').convert('RGBA') +char_bg_4 = Image.open(TEXT_PATH / 'char4_bg.png').convert('RGBA') +char_bg_5 = Image.open(TEXT_PATH / 'char5_bg.png').convert('RGBA') +rank_bg = Image.open(TEXT_PATH / 'rank_bg.png').convert('RGBA') +star_yes = Image.open(TEXT_PATH / 'star.png').convert('RGBA') +star_gray = Image.open(TEXT_PATH / 'star_gray.png').convert('RGBA') + +elements = { + 'ice': Image.open(TEXT_PATH / 'IconNatureColorIce.png').convert('RGBA'), + 'fire': Image.open(TEXT_PATH / 'IconNatureColorFire.png').convert('RGBA'), + 'imaginary': Image.open( + TEXT_PATH / 'IconNatureColorImaginary.png' + ).convert('RGBA'), + 'quantum': Image.open(TEXT_PATH / 'IconNatureColorQuantum.png').convert( + 'RGBA' + ), + 'lightning': Image.open(TEXT_PATH / 'IconNatureColorThunder.png').convert( + 'RGBA' + ), + 'wind': Image.open(TEXT_PATH / 'IconNatureColorWind.png').convert('RGBA'), + 'physical': Image.open(TEXT_PATH / 'IconNaturePhysical.png').convert( + 'RGBA' + ), +} + + +async def get_abyss_star_pic(star: int) -> Image.Image: + return Image.open(TEXT_PATH / f'star{star}.png') + + +async def _draw_abyss_card( + char: AbyssAvatar, + talent_num: str, + floor_pic: Image.Image, + index_char: int, + index_part: int, +): + # 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((150, 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, (35, 25), mask=element_icon) + char_card_draw = ImageDraw.Draw(char_bg) + if char.rank > 0: + char_bg.paste(rank_bg, (150, 16), mask=rank_bg) + char_card_draw.text( + (162, 31), + f'{char.rank}', + font=sr_font_22, + fill=white_color, + anchor='mm', + ) + # 不存在自动下载 + # if not char_pic_path.exists(): + # await create_single_char_card(char_id) + # talent_pic = await get_talent_pic(int(talent_num)) + # talent_pic = talent_pic.resize((90, 45)) + # char_card.paste(talent_pic, (137, 260), talent_pic) + char_card_draw.text( + (100, 165), + f'等级 {char.level}', + font=sr_font_22, + fill=white_color, + anchor='mm', + ) + floor_pic.paste( + char_bg, + (75 + 185 * index_char, 130 + index_part * 219), + char_bg, + ) + + +async def _draw_floor_card( + level_star: int, + floor_pic: Image.Image, + img: Image.Image, + index_floor: int, + floor_name: str, + round_num: int, +): + for index_num in [0, 1, 2]: + star_num = index_num + 1 + if star_num <= level_star: + star_pic = star_yes.copy() + else: + star_pic = star_gray.copy() + floor_pic.paste(star_pic, (103 + index_num * 50, 25), star_pic) + floor_pic_draw = ImageDraw.Draw(floor_pic) + floor_pic_draw.text( + (450, 60), + floor_name, + font=sr_font_42, + fill=white_color, + anchor='mm', + ) + floor_pic_draw.text( + (802, 60), + f'使用轮: {round_num}', + font=sr_font_28, + fill=gray_color, + anchor='rm', + ) + img.paste(floor_pic, (0, 657 + index_floor * 570), floor_pic) + + +async def draw_abyss_img( + qid: Union[str, int], + uid: str, + sender: Union[str, str], + schedule_type: str = '1', +) -> Union[bytes, str]: + raw_abyss_data = await mys_api.get_abyss_story_info(uid, schedule_type) + if isinstance(raw_abyss_data, int): + return get_error(raw_abyss_data) + + # 获取查询者数据 + if raw_abyss_data.max_floor == '': + return '你还没有挑战本期虚构叙事!\n可以使用[sr上期虚构叙事]命令查询上期~' + # 过滤掉 is_fast(快速通关) 为 True 的项 + floor_detail = [detail for detail in raw_abyss_data.all_floor_detail if not detail.is_fast] + floor_num = len(floor_detail) + + # 获取背景图片各项参数 + based_w = 900 + based_h = 657 + 570 * floor_num + img = img_bg.copy() + img = img.crop((0, 0, based_w, based_h)) + abyss_title = Image.open(TEXT_PATH / 'head.png') + img.paste(abyss_title, (0, 0), abyss_title) + + # 获取头像 + _id = str(qid) + if _id.startswith('http'): + char_pic = await get_qq_avatar(avatar_url=_id) + elif sender.get('avatar') is not None: + char_pic = await get_qq_avatar(avatar_url=sender['avatar']) + else: + char_pic = await get_qq_avatar(qid=qid) + char_pic = await draw_pic_with_ring(char_pic, 250, None, False) + + img.paste(char_pic, (325, 132), char_pic) + + # 绘制抬头 + img_draw = ImageDraw.Draw(img) + img_draw.text((450, 442), f'UID {uid}', white_color, sr_font_28, 'mm') + + # 总体数据 + abyss_data = Image.open(TEXT_PATH / 'data.png') + img.paste(abyss_data, (0, 500), abyss_data) + + # 最深抵达 + img_draw.text( + (220, 565), + f'{raw_abyss_data.max_floor}', + white_color, + sr_font_34, + 'lm', + ) + # 挑战次数 + img_draw.text( + (220, 612), + f'{raw_abyss_data.battle_num}', + white_color, + sr_font_34, + 'lm', + ) + + star_num_pic = Image.open(TEXT_PATH / 'star.png') + img.paste(star_num_pic, (615, 557), star_num_pic) + + img_draw.text( + (695, 590), + f'{raw_abyss_data.star_num}/12', + white_color, + sr_font_42, + 'lm', + ) + + for index_floor, level in enumerate(raw_abyss_data.all_floor_detail): + floor_pic = Image.open(TEXT_PATH / 'floor_bg.png') + 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 + if node_num == 1: + time_array = node_1.challenge_time + else: + time_array = node_2.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), + f'节点{node_num}', + white_color, + sr_font_30, + 'lm', + ) + floor_pic_draw.text( + (201, 120 + index_part * 219), + f'{time_str}', + gray_color, + sr_font_22, + 'lm', + ) + if node_num == 1: + avatars_array = node_1 + else: + avatars_array = node_2 + + for index_char, char in enumerate(avatars_array.avatars): + await _draw_abyss_card( + char, + 0, # type: ignore + floor_pic, + index_char, + index_part, + ) + await _draw_floor_card( + level_star, + floor_pic, + img, + index_floor, + floor_name, + round_num, + ) + + res = await convert_img(img) + logger.info('[查询虚构叙事信息]绘图已完成,等待发送!') + return res diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorFire.png b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorFire.png new file mode 100644 index 0000000..c0e5c09 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorFire.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorIce.png b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorIce.png new file mode 100644 index 0000000..9026e17 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorIce.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorImaginary.png b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorImaginary.png new file mode 100644 index 0000000..da9f292 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorImaginary.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorQuantum.png b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorQuantum.png new file mode 100644 index 0000000..3ba24c0 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorQuantum.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorThunder.png b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorThunder.png new file mode 100644 index 0000000..9982c61 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorThunder.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorWind.png b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorWind.png new file mode 100644 index 0000000..f92982a Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/IconNatureColorWind.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/IconNaturePhysical.png b/StarRailUID/starrailuid_abyss_story/texture2D/IconNaturePhysical.png new file mode 100644 index 0000000..e78da4f Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/IconNaturePhysical.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/bg.jpg b/StarRailUID/starrailuid_abyss_story/texture2D/bg.jpg new file mode 100644 index 0000000..1d4db8c Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/bg.jpg differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/char4_bg.png b/StarRailUID/starrailuid_abyss_story/texture2D/char4_bg.png new file mode 100644 index 0000000..1f62615 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/char4_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/char5_bg.png b/StarRailUID/starrailuid_abyss_story/texture2D/char5_bg.png new file mode 100644 index 0000000..0a8f204 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/char5_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/data.png b/StarRailUID/starrailuid_abyss_story/texture2D/data.png new file mode 100644 index 0000000..1e2d3f4 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/data.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/floor_bg.png b/StarRailUID/starrailuid_abyss_story/texture2D/floor_bg.png new file mode 100644 index 0000000..05af753 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/floor_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/head.png b/StarRailUID/starrailuid_abyss_story/texture2D/head.png new file mode 100644 index 0000000..b8917c0 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/head.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/level_cover.png b/StarRailUID/starrailuid_abyss_story/texture2D/level_cover.png new file mode 100644 index 0000000..2b0df3c Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/level_cover.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/rank_bg.png b/StarRailUID/starrailuid_abyss_story/texture2D/rank_bg.png new file mode 100644 index 0000000..e335727 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/rank_bg.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/star.png b/StarRailUID/starrailuid_abyss_story/texture2D/star.png new file mode 100644 index 0000000..c30ab43 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/star.png differ diff --git a/StarRailUID/starrailuid_abyss_story/texture2D/star_gray.png b/StarRailUID/starrailuid_abyss_story/texture2D/star_gray.png new file mode 100644 index 0000000..91cdb18 Binary files /dev/null and b/StarRailUID/starrailuid_abyss_story/texture2D/star_gray.png differ diff --git a/StarRailUID/starrailuid_abyss_story/utils.py b/StarRailUID/starrailuid_abyss_story/utils.py new file mode 100644 index 0000000..a18f624 --- /dev/null +++ b/StarRailUID/starrailuid_abyss_story/utils.py @@ -0,0 +1,26 @@ +from io import BytesIO +from pathlib import Path +from typing import TypeVar + +from PIL import Image +from aiohttp import ClientSession +from gsuid_core.data_store import get_res_path + +T = TypeVar('T') + +ROLEINFO_PATH = get_res_path() / 'StarRailUID' / 'roleinfo' +ROLEINFO_PATH.mkdir(parents=True, exist_ok=True) + + +async def get_icon(url: str) -> Image.Image: + name = url.split('/')[-1] + path = ROLEINFO_PATH / name + if (path).exists(): + content = path.read_bytes() + else: + async with ClientSession() as client: + async with client.get(url) as resp: + content = await resp.read() + with Path.open(path, 'wb') as f: + f.write(content) + return Image.open(BytesIO(content)).convert('RGBA') diff --git a/StarRailUID/starrailuid_config/config_default.py b/StarRailUID/starrailuid_config/config_default.py index 22ef0d0..e905d05 100644 --- a/StarRailUID/starrailuid_config/config_default.py +++ b/StarRailUID/starrailuid_config/config_default.py @@ -4,7 +4,7 @@ from gsuid_core.utils.plugins_config.models import ( GSC, GsStrConfig, GsBoolConfig, - GsListStrConfig, + GsListStrConfig, GsIntConfig, ) CONIFG_DEFAULT: Dict[str, GSC] = { @@ -21,6 +21,17 @@ CONIFG_DEFAULT: Dict[str, GSC] = { '开启后每晚00:30将开始自动签到任务', True, ), + 'SchedStaminaPush': GsBoolConfig( + '定时检查开拓力', + '开启后每隔半小时检查一次开拓力', + True, + ), + 'push_max_value': GsIntConfig( + '提醒阈值', + '发送提醒的阈值', + 200, + 240 + ), 'CrazyNotice': GsBoolConfig( '催命模式', '开启后当达到推送阈值将会一直推送', diff --git a/StarRailUID/utils/mys_api.py b/StarRailUID/utils/mys_api.py index b8d00d9..8f20de0 100644 --- a/StarRailUID/utils/mys_api.py +++ b/StarRailUID/utils/mys_api.py @@ -28,7 +28,7 @@ from ..sruid_utils.api.mys.models import ( DailyNoteData, RoleBasicInfo, WidgetStamina, - RogueLocustData, + RogueLocustData, AbyssStoryData, AbyssBossData, ) RECOGNIZE_SERVER = { @@ -340,7 +340,7 @@ class MysApi(_MysApi): # data = cast(SignInfo, data['data']) return data - async def get_srspiral_abyss_info( + async def get_abyss_info( self, uid: str, schedule_type='1', @@ -386,6 +386,98 @@ class MysApi(_MysApi): # data = cast(AbyssData, data['data']) return data + async def get_abyss_story_info( + self, + uid: str, + schedule_type='1', + ck: Optional[str] = None, + ) -> Union[AbyssData, int]: + server_id = self.RECOGNIZE_SERVER.get(uid[0]) + is_os = self.check_os(uid) + if is_os: + HEADER = copy.deepcopy(self._HEADER_OS) + ck = await self.get_sr_ck(uid, 'OWNER') + if ck is None: + return -51 + HEADER['Cookie'] = ck + HEADER['DS'] = generate_os_ds() + header = HEADER + data = await self.simple_sr_req( + 'CHALLENGE_STORY_INFO_URL', + uid, + params={ + 'need_all': 'true', + 'role_id': uid, + 'schedule_type': schedule_type, + 'server': server_id, + }, + header=header, + ) + else: + data = await self.simple_sr_req( + 'CHALLENGE_STORY_INFO_URL', + uid, + params={ + 'isPrev': 'true', + 'need_all': 'true', + 'role_id': uid, + 'schedule_type': schedule_type, + 'server': server_id, + }, + cookie=ck, + header=self._HEADER, + ) + if isinstance(data, Dict): + data = msgspec.convert(data['data'], type=AbyssStoryData) + + return data + + async def get_abyss_boss_info( + self, + uid: str, + schedule_type='1', + ck: Optional[str] = None, + ) -> Union[AbyssBossData, int]: + server_id = self.RECOGNIZE_SERVER.get(uid[0]) + is_os = self.check_os(uid) + if is_os: + HEADER = copy.deepcopy(self._HEADER_OS) + ck = await self.get_sr_ck(uid, 'OWNER') + if ck is None: + return -51 + HEADER['Cookie'] = ck + HEADER['DS'] = generate_os_ds() + header = HEADER + data = await self.simple_sr_req( + 'CHALLENGE_BOSS_INFO_URL', + uid, + params={ + 'need_all': 'true', + 'role_id': uid, + 'schedule_type': schedule_type, + 'server': server_id, + }, + header=header, + ) + else: + data = await self.simple_sr_req( + 'CHALLENGE_BOSS_INFO_URL', + uid, + params={ + 'isPrev': 'true', + 'need_all': 'true', + 'role_id': uid, + 'schedule_type': schedule_type, + 'server': server_id, + }, + cookie=ck, + header=self._HEADER, + ) + if isinstance(data, Dict): + data = msgspec.convert(data['data'], type=AbyssBossData) + # data = cast(AbyssData, data['data']) + return data + async def get_rogue_info( self, uid: str,