diff --git a/GenshinUID/genshinuid_enka/__init__.py b/GenshinUID/genshinuid_enka/__init__.py index d194b756..e9dc9b1b 100644 --- a/GenshinUID/genshinuid_enka/__init__.py +++ b/GenshinUID/genshinuid_enka/__init__.py @@ -61,8 +61,24 @@ async def sned_rank_pic(bot: Bot, ev: Event): ) -@sv_akasha.on_prefix('角色排名') +@sv_akasha.on_prefix('角色排行榜') async def sned_role_rank_pic(bot: Bot, ev: Event): + # 获取角色名 + msg = ''.join(re.findall('[\u4e00-\u9fa5 ]', ev.text)) + if not msg: + return + logger.info(f'[角色排行榜]角色: {msg}') + a = Button('💖排名列表', '排名列表') + b = Button(f'✅查询{msg}', f'查询{msg}') + c = Button(f'💖角色排名{msg}', f'角色排名{msg}') + d = Button('✅圣遗物排名', '圣遗物排名') + + im = await draw_role_rank_img(msg) + await bot.send_option(im, [a, c, b, d]) + + +@sv_akasha.on_prefix('角色排名') +async def sned_my_role_rank_pic(bot: Bot, ev: Event): # 获取角色名 msg = ''.join(re.findall('[\u4e00-\u9fa5 ]', ev.text)) if not msg: @@ -70,7 +86,17 @@ async def sned_role_rank_pic(bot: Bot, ev: Event): logger.info(f'[角色排名]角色: {msg}') a = Button('💖排名列表', '排名列表') b = Button(f'✅查询{msg}', f'查询{msg}') - await bot.send_option(await draw_role_rank_img(msg), [a, b]) + c = Button(f'💖角色排行榜{msg}', f'角色排行榜{msg}') + d = Button('✅圣遗物排名', '圣遗物排名') + + msg = msg.replace('附近', '') + # 获取uid + uid = await get_uid(bot, ev) + if uid is None: + return await bot.send(UID_HINT) + + im = await draw_role_rank_img(msg, uid) + await bot.send_option(im, [a, c, b, d]) @sv_akasha.on_command('圣遗物排名') diff --git a/GenshinUID/genshinuid_enka/draw_role_rank.py b/GenshinUID/genshinuid_enka/draw_role_rank.py index 0e8acf90..5177c1de 100644 --- a/GenshinUID/genshinuid_enka/draw_role_rank.py +++ b/GenshinUID/genshinuid_enka/draw_role_rank.py @@ -1,26 +1,28 @@ -from typing import Union +from typing import Union, Optional from PIL import Image, ImageDraw from gsuid_core.utils.image.convert import convert_img from ..utils.colors import get_color from .draw_rank_list import RANK_TEXT +from .get_akasha_data import _get_rank from ..utils.api.cv.request import _CvApi from ..utils.map.GS_MAP_PATH import icon2Name from ..genshinuid_config.gs_config import gsconfig from ..utils.resource.RESOURCE_PATH import REL_PATH, CHAR_PATH from ..utils.map.name_covert import name_to_avatar_id, alias_to_char_name -from ..utils.fonts.genshin_fonts import ( - gs_font_18, - gs_font_20, - gs_font_26, - gs_font_30, -) from ..utils.image.image_tools import ( get_talent_pic, draw_pic_with_ring, get_weapon_affix_pic, ) +from ..utils.fonts.genshin_fonts import ( + gs_font_18, + gs_font_20, + gs_font_24, + gs_font_26, + gs_font_30, +) is_enable_akasha = gsconfig.get_config('EnableAkasha').data @@ -36,21 +38,39 @@ REGION_MAP = { grey = (170, 170, 170) -async def draw_role_rank_img(char_name: str) -> Union[str, bytes]: +async def draw_role_rank_img( + char_name: str, player_uid: Optional[str] = None +) -> Union[str, bytes]: if not is_enable_akasha: return '未开启排名系统...' cv_api = _CvApi() char_name = await alias_to_char_name(char_name) char_id = await name_to_avatar_id(char_name) - raw_data = await cv_api.get_sort_list(char_id) + + if player_uid: + rank_data = await _get_rank(player_uid) + if isinstance(rank_data, str): + return rank_data + if char_id not in rank_data: + return f'你还暂无{char_name}的数据, 请先[强制刷新]...' + + fit = rank_data[char_id]['calculations']['fit'] + calculation_id = fit['calculationId'] + r0 = int(fit["result"]) + r1 = int(r0 * 1.00005) + raw_data = await cv_api.get_sort_list(char_id, calculation_id, r1) + tag = '角色附近' + else: + raw_data = await cv_api.get_sort_list(char_id) + tag = '前20' if raw_data is None: return '该角色尚未有排名...' data, count = raw_data - img = Image.open(RANK_TEXT / 'deep_grey.jpg') + img = Image.open(RANK_TEXT / 'deep_grey.jpg').resize((950, 2450)) title = Image.open(RANK_TEXT / 'title.png') user_pic = await draw_pic_with_ring( Image.open(CHAR_PATH / f'{char_id}.png'), 314 @@ -59,19 +79,35 @@ async def draw_role_rank_img(char_name: str) -> Union[str, bytes]: img.paste(title, (0, 0), title) img_draw = ImageDraw.Draw(img) - img_draw.text((475, 425), f'前20 / 总数据 {count}条', 'white', gs_font_26, 'mm') + img_draw.text( + (475, 425), f'{tag} / 总数据 {count}条', 'white', gs_font_26, 'mm' + ) + rank = 0 for index, char in enumerate(data): - if index % 2 == 0: + region: str = char['owner']['region'] + nickname: str = char['owner']['nickname'] + + if index == 0: + _rank: str = char['index'] + rank = ( + int(_rank[1:]) + if isinstance(_rank, str) and _rank.startswith('~') + else int(_rank) + ) + else: + rank += 1 + + uid: str = char['uid'] + + char_c = 'white' + if player_uid and player_uid == uid: + bar = Image.open(RANK_TEXT / 'sp.png') + elif index % 2 == 0: bar = Image.open(RANK_TEXT / 'white.png') else: bar = Image.open(RANK_TEXT / 'black.png') - bar_draw = ImageDraw.Draw(bar) - - region: str = char['owner']['region'] - nickname: str = char['owner']['nickname'] - uid: str = char['uid'] _c: int = char['constellation'] _wc: int = char['weapon']['weaponInfo']['refinementLevel']['value'] + 1 hp: int = int(char['stats']['maxHp']['value']) @@ -103,10 +139,18 @@ async def draw_role_rank_img(char_name: str) -> Union[str, bytes]: else: icon_list.append(icon_img.resize((51, 51))) - bar_draw.rounded_rectangle((47, 30, 150, 70), 10, region_color) - bar_draw.text((99, 50), region, 'white', gs_font_30, 'mm') + x1, x2 = 15, 64 + 15 * len(str(rank)) + x3 = int((x1 + x2) / 2) - bar_draw.text((162, 41), nickname, 'white', gs_font_26, 'lm') + bar_draw = ImageDraw.Draw(bar) + + bar_draw.rounded_rectangle((x1, 0, x2, 25), 9, (96, 33, 109)) + bar_draw.text((x3 + 1, 13), f'#{rank}名', 'white', gs_font_24, 'mm') + + bar_draw.rounded_rectangle((47, 35, 150, 75), 10, region_color) + bar_draw.text((99, 55), region, 'white', gs_font_30, 'mm') + + bar_draw.text((162, 41), nickname, char_c, gs_font_26, 'lm') bar_draw.text((162, 66), f'UID {uid}', grey, gs_font_20, 'lm') bar_draw.text((398, 42), f'{cr}: {cd}', 'white', gs_font_26, 'lm') bar_draw.text((398, 66), f'{cv} cv', cv_color, gs_font_20, 'lm') @@ -127,7 +171,7 @@ async def draw_role_rank_img(char_name: str) -> Union[str, bytes]: bar_draw.text((370, 67), text, (214, 255, 192), gs_font_20, 'mm') - img.paste(bar, (0, 475 + index * 90), bar) + img.paste(bar, (0, 475 + index * 95), bar) img_draw.text( (475, img.size[1] - 35), diff --git a/GenshinUID/genshinuid_enka/texture2D/rank_img/sp.png b/GenshinUID/genshinuid_enka/texture2D/rank_img/sp.png new file mode 100644 index 00000000..d46c635a Binary files /dev/null and b/GenshinUID/genshinuid_enka/texture2D/rank_img/sp.png differ diff --git a/GenshinUID/utils/api/cv/api.py b/GenshinUID/utils/api/cv/api.py index d500f232..ba4fe0f1 100644 --- a/GenshinUID/utils/api/cv/api.py +++ b/GenshinUID/utils/api/cv/api.py @@ -6,9 +6,9 @@ DATA_API = BASE + '/user/{}' REFRESH_API = BASE + '/user/refresh/{}' LEADERBOARD_API = BASE + '/v2/leaderboards/categories?characterId={}' -SORT_PROMOT = 'sort=calculation.result&' +SORT_PROMOT = 'sort=calculation.result' UNI_PROMOT = 'order=-1&size=20&page=1&filter=&uids=&fromId=' SORT_API = ( - BASE + '/leaderboards?' + SORT_PROMOT + 'p=&calculationId={}&' + UNI_PROMOT + BASE + '/leaderboards?' + SORT_PROMOT + '&calculationId={}&' + UNI_PROMOT ) ARTI_SORT_API = BASE + '/artifacts?sort={}&p=&' + UNI_PROMOT diff --git a/GenshinUID/utils/api/cv/request.py b/GenshinUID/utils/api/cv/request.py index 5d91a056..2b5ec4e2 100644 --- a/GenshinUID/utils/api/cv/request.py +++ b/GenshinUID/utils/api/cv/request.py @@ -105,18 +105,42 @@ class _CvApi: ) async def get_sort_list( - self, char_id: str + self, + char_id: str, + calculation_id: Optional[str] = None, + combo: Optional[Union[str, int]] = None, ) -> Optional[Tuple[List[Dict], int]]: - _raw_data = await self.get_calculation_info(char_id) - if _raw_data is not None: - calculation_id, count = _raw_data - raw_data = await self._cv_request( - SORT_API.format(calculation_id), - 'GET', - self._HEADER, - ) - if isinstance(raw_data, Dict) and 'data' in raw_data: - return raw_data['data'], count + count = 0 + if calculation_id is None: + _raw_data = await self.get_calculation_info(char_id) + if _raw_data is not None: + calculation_id, count = _raw_data + else: + lb_data = await self.get_leaderboard_id_list(char_id) + if lb_data: + for i in lb_data: + for g in i['weapons']: + if g['calculationId'] == calculation_id: + count = i['count'] + break + + if count == 0: + return None + + extra = '' + if combo: + extra += f'&p=lt%7C{combo}' + else: + extra = '&p=' + + url = SORT_API.format(calculation_id) + extra + raw_data = await self._cv_request( + url, + 'GET', + self._HEADER, + ) + if isinstance(raw_data, Dict) and 'data' in raw_data: + return raw_data['data'], count async def get_session_id(self) -> str: async with self.session.get(MAIN_API) as resp: