mirror of
https://github.com/KimigaiiWuyi/GenshinUID.git
synced 2025-05-07 04:03:45 +08:00
✨ 新增角色排名雷神
类似用法 (#493)
This commit is contained in:
parent
b142282281
commit
cbddd93616
@ -20,6 +20,7 @@ from .draw_rank_list import draw_rank_img
|
|||||||
from ..utils.image.convert import convert_img
|
from ..utils.image.convert import convert_img
|
||||||
from ..utils.map.GS_MAP_PATH import alias_data
|
from ..utils.map.GS_MAP_PATH import alias_data
|
||||||
from .draw_char_rank import draw_cahrcard_list
|
from .draw_char_rank import draw_cahrcard_list
|
||||||
|
from .draw_role_rank import draw_role_rank_img
|
||||||
from .get_enka_img import draw_enka_img, get_full_char
|
from .get_enka_img import draw_enka_img, get_full_char
|
||||||
from ..genshinuid_enka.start import check_artifacts_list
|
from ..genshinuid_enka.start import check_artifacts_list
|
||||||
from ..utils.resource.RESOURCE_PATH import TEMP_PATH, PLAYER_PATH
|
from ..utils.resource.RESOURCE_PATH import TEMP_PATH, PLAYER_PATH
|
||||||
@ -51,6 +52,16 @@ async def sned_rank_pic(bot: Bot, ev: Event):
|
|||||||
await bot.send(await draw_rank_img(ev.user_id, uid))
|
await bot.send(await draw_rank_img(ev.user_id, uid))
|
||||||
|
|
||||||
|
|
||||||
|
@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}')
|
||||||
|
await bot.send(await draw_role_rank_img(msg))
|
||||||
|
|
||||||
|
|
||||||
@sv_enka_admin.on_fullmatch('刷新全部圣遗物仓库')
|
@sv_enka_admin.on_fullmatch('刷新全部圣遗物仓库')
|
||||||
async def sned_fresh_all_list(bot: Bot, ev: Event):
|
async def sned_fresh_all_list(bot: Bot, ev: Event):
|
||||||
await bot.send('开始执行...可能时间较久, 执行完成会有提示, 请勿重复执行!')
|
await bot.send('开始执行...可能时间较久, 执行完成会有提示, 请勿重复执行!')
|
||||||
|
156
GenshinUID/genshinuid_enka/draw_role_rank.py
Normal file
156
GenshinUID/genshinuid_enka/draw_role_rank.py
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
from typing import Dict, Tuple, Union
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
from gsuid_core.utils.image.convert import convert_img
|
||||||
|
|
||||||
|
from ..utils.api.cv.request import _CvApi
|
||||||
|
from ..utils.map.GS_MAP_PATH import icon2Name
|
||||||
|
from .draw_rank_list import COLOR_MAP, RANK_TEXT
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
is_enable_akasha = gsconfig.get_config('EnableAkasha').data
|
||||||
|
|
||||||
|
CV_MAP = {
|
||||||
|
260: '1',
|
||||||
|
245: '2',
|
||||||
|
225: '3',
|
||||||
|
180: '4',
|
||||||
|
}
|
||||||
|
|
||||||
|
REGION_MAP = {
|
||||||
|
'CN': (255, 58, 58),
|
||||||
|
'ASIA': (255, 255, 127),
|
||||||
|
'NA': (255, 165, 0),
|
||||||
|
'EU': (80, 98, 255),
|
||||||
|
'TW': (37, 37, 37),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def _get_color(
|
||||||
|
cmap: Dict[int, str], value: float
|
||||||
|
) -> Tuple[int, int, int]:
|
||||||
|
for i in cmap:
|
||||||
|
if value >= i:
|
||||||
|
return COLOR_MAP[cmap[i]]
|
||||||
|
else:
|
||||||
|
return COLOR_MAP['5']
|
||||||
|
|
||||||
|
|
||||||
|
async def draw_role_rank_img(char_name: str) -> 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 raw_data is None:
|
||||||
|
return '该角色尚未有排名...'
|
||||||
|
|
||||||
|
data, count = raw_data
|
||||||
|
|
||||||
|
img = Image.open(RANK_TEXT / 'deep_grey.jpg')
|
||||||
|
title = Image.open(RANK_TEXT / 'title.png')
|
||||||
|
user_pic = await draw_pic_with_ring(
|
||||||
|
Image.open(CHAR_PATH / f'{char_id}.png'), 314
|
||||||
|
)
|
||||||
|
title.paste(user_pic, (318, 57), user_pic)
|
||||||
|
img.paste(title, (0, 0), title)
|
||||||
|
|
||||||
|
img_draw = ImageDraw.Draw(img)
|
||||||
|
img_draw.text((475, 425), f'前20 / 总数据 {count}条', 'white', gs_font_26, 'mm')
|
||||||
|
|
||||||
|
for index, char in enumerate(data):
|
||||||
|
if 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'])
|
||||||
|
atk: int = int(char['stats']['atk']['value'])
|
||||||
|
cr = '{:.1f}'.format(char['stats']['critRate']['value'] * 100)
|
||||||
|
cd = '{:.1f}'.format(char['stats']['critDamage']['value'] * 100)
|
||||||
|
cv = '{:.1f}'.format(char['critValue'])
|
||||||
|
|
||||||
|
cv_color = await _get_color(CV_MAP, float(cv))
|
||||||
|
|
||||||
|
affix_pic = await get_weapon_affix_pic(_wc)
|
||||||
|
talent_pic = await get_talent_pic(_c)
|
||||||
|
|
||||||
|
if region in REGION_MAP:
|
||||||
|
region_color = REGION_MAP[region]
|
||||||
|
else:
|
||||||
|
region_color = (128, 128, 128)
|
||||||
|
|
||||||
|
icon_list = []
|
||||||
|
for art in char['artifactSets']:
|
||||||
|
item = char['artifactSets'][art]
|
||||||
|
if item['count'] >= 2:
|
||||||
|
url: str = item['icon']
|
||||||
|
icon_name = url.split('/')[-1].split('.')[0]
|
||||||
|
icon_img = Image.open(REL_PATH / f'{icon2Name[icon_name]}.png')
|
||||||
|
if item['count'] >= 4:
|
||||||
|
icon_list.clear()
|
||||||
|
icon_list.append(icon_img.resize((64, 64)))
|
||||||
|
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, 'black', gs_font_30, 'mm')
|
||||||
|
|
||||||
|
grey = (170, 170, 170)
|
||||||
|
bar_draw.text((162, 41), nickname, 'white', 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')
|
||||||
|
bar_draw.text((665, 34), f'{hp}', 'white', gs_font_26, 'lm')
|
||||||
|
bar_draw.text((665, 70), f'{atk}', 'white', gs_font_26, 'lm')
|
||||||
|
bar.paste(talent_pic, (764, 35), talent_pic)
|
||||||
|
bar.paste(affix_pic, (840, 35), affix_pic)
|
||||||
|
|
||||||
|
if len(icon_list) == 1:
|
||||||
|
bar.paste(icon_list[0], (325, 18), icon_list[0])
|
||||||
|
text = '4'
|
||||||
|
elif len(icon_list) == 2:
|
||||||
|
text = '2+2'
|
||||||
|
bar.paste(icon_list[0], (334, 15), icon_list[0])
|
||||||
|
bar.paste(icon_list[1], (318, 30), icon_list[1])
|
||||||
|
else:
|
||||||
|
text = '0'
|
||||||
|
|
||||||
|
bar_draw.text((370, 67), text, (214, 255, 192), gs_font_20, 'mm')
|
||||||
|
|
||||||
|
img.paste(bar, (0, 475 + index * 90), bar)
|
||||||
|
|
||||||
|
img_draw.text(
|
||||||
|
(475, img.size[1] - 35),
|
||||||
|
'Power by Wuyi无疑 & '
|
||||||
|
'Data by AKS & CV '
|
||||||
|
'Created by GsCore & GenshinUID',
|
||||||
|
(200, 200, 200),
|
||||||
|
gs_font_18,
|
||||||
|
anchor='mm',
|
||||||
|
)
|
||||||
|
|
||||||
|
return await convert_img(img)
|
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/black.png
Normal file
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/deep_grey.jpg
Normal file
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/deep_grey.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 343 KiB |
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/white.png
Normal file
BIN
GenshinUID/genshinuid_enka/texture2D/rank_img/white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
@ -1,7 +1,15 @@
|
|||||||
MAIN_API = 'https://akasha.cv/api/filters/accounts/'
|
BASE = 'https://akasha.cv'
|
||||||
RANK_API = 'https://akasha.cv/api/getCalculationsForUser/{}'
|
|
||||||
DATA_API = 'https://akasha.cv/api/user/{}'
|
MAIN_API = BASE + '/api/filters/accounts/'
|
||||||
REFRESH_API = 'https://akasha.cv/api/user/refresh/{}'
|
RANK_API = BASE + '/api/getCalculationsForUser/{}'
|
||||||
LEADERBOARD_API = (
|
DATA_API = BASE + '/api/user/{}'
|
||||||
'https://akasha.cv/api/v2/leaderboards/categories?characterId={}'
|
REFRESH_API = BASE + '/api/user/refresh/{}'
|
||||||
|
LEADERBOARD_API = BASE + '/api/v2/leaderboards/categories?characterId={}'
|
||||||
|
|
||||||
|
SORT_PROMOT = 'sort=calculation.result&order=-1&size=20'
|
||||||
|
SORT_API = (
|
||||||
|
BASE
|
||||||
|
+ '/api/leaderboards?'
|
||||||
|
+ SORT_PROMOT
|
||||||
|
+ '&page=1&filter=&uids=&p=&fromId=&calculationId={}'
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
from typing import Any, Dict, Union, Literal, Optional
|
from typing import Any, Dict, List, Tuple, Union, Literal, Optional
|
||||||
|
|
||||||
from gsuid_core.logger import logger
|
from gsuid_core.logger import logger
|
||||||
from aiohttp import TCPConnector, ClientSession, ContentTypeError
|
from aiohttp import TCPConnector, ClientSession, ContentTypeError
|
||||||
|
|
||||||
from .api import DATA_API, MAIN_API, RANK_API, REFRESH_API
|
from .api import (
|
||||||
|
DATA_API,
|
||||||
|
MAIN_API,
|
||||||
|
RANK_API,
|
||||||
|
SORT_API,
|
||||||
|
REFRESH_API,
|
||||||
|
LEADERBOARD_API,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class _CvApi:
|
class _CvApi:
|
||||||
@ -17,6 +24,44 @@ class _CvApi:
|
|||||||
)
|
)
|
||||||
self.sessionID = None
|
self.sessionID = None
|
||||||
|
|
||||||
|
async def get_leaderboard_id_list(
|
||||||
|
self, char_id: str
|
||||||
|
) -> Optional[List[Dict]]:
|
||||||
|
raw_data = await self._cv_request(
|
||||||
|
LEADERBOARD_API.format(char_id),
|
||||||
|
'GET',
|
||||||
|
self._HEADER,
|
||||||
|
)
|
||||||
|
if isinstance(raw_data, Dict) and 'data' in raw_data:
|
||||||
|
if raw_data['data']:
|
||||||
|
return raw_data['data']
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def get_calculation_info(
|
||||||
|
self, char_id: str
|
||||||
|
) -> Optional[Tuple[str, int]]:
|
||||||
|
raw_data = await self.get_leaderboard_id_list(char_id)
|
||||||
|
if raw_data is not None:
|
||||||
|
return (
|
||||||
|
raw_data[0]['weapons'][0]['calculationId'],
|
||||||
|
raw_data[0]['count'],
|
||||||
|
)
|
||||||
|
|
||||||
|
async def get_sort_list(
|
||||||
|
self, char_id: str
|
||||||
|
) -> 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
|
||||||
|
|
||||||
async def get_session_id(self) -> str:
|
async def get_session_id(self) -> str:
|
||||||
async with self.session.get(MAIN_API) as resp:
|
async with self.session.get(MAIN_API) as resp:
|
||||||
cookies = resp.cookies
|
cookies = resp.cookies
|
||||||
|
Loading…
x
Reference in New Issue
Block a user