mirror of
https://github.com/KimigaiiWuyi/GenshinUID.git
synced 2025-05-08 04:55:51 +08:00
✨ gs深渊概览
替换为小助手的数据源
This commit is contained in:
parent
9dbfa8e308
commit
357d74c7bd
@ -4,7 +4,8 @@ import threading
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from ..genshinuid_resource import startup
|
||||
from ..genshinuid_xkdata import draw_xk_abyss_img
|
||||
|
||||
# from ..genshinuid_xkdata import draw_teyvat_abyss_img
|
||||
from ..genshinuid_guide.get_new_abyss_data import download_Oceanid
|
||||
|
||||
# from ..genshinuid_enka.start import check_artifacts_list
|
||||
@ -22,7 +23,7 @@ async def all_start():
|
||||
await startup()
|
||||
# await check_artifacts_list()
|
||||
await create_all_char_card()
|
||||
await draw_xk_abyss_img()
|
||||
# await draw_teyvat_abyss_img()
|
||||
# await generate_data()
|
||||
await save_all_char_info()
|
||||
await save_all_abyss_rank()
|
||||
|
@ -5,10 +5,12 @@ from gsuid_core.sv import SV
|
||||
from gsuid_core.bot import Bot
|
||||
from gsuid_core.models import Event
|
||||
from gsuid_core.aps import scheduler
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from ..utils.image.convert import convert_img
|
||||
from .draw_char_abyss import draw_char_abyss_info
|
||||
from .draw_abyss_total import TOTAL_IMG, draw_xk_abyss_img
|
||||
from .draw_teyvat_img import draw_teyvat_abyss_img
|
||||
|
||||
# from .draw_abyss_total import TOTAL_IMG, draw_xk_abyss_img
|
||||
from .get_all_char_data import save_all_char_info, save_all_abyss_rank
|
||||
|
||||
sv_get_abyss_database = SV('查询深渊数据库', priority=4)
|
||||
@ -17,7 +19,7 @@ sv_get_abyss_database = SV('查询深渊数据库', priority=4)
|
||||
@scheduler.scheduled_job('interval', hours=3)
|
||||
async def scheduled_draw_abyss():
|
||||
await asyncio.sleep(random.randint(0, 60))
|
||||
await draw_xk_abyss_img()
|
||||
await draw_teyvat_abyss_img()
|
||||
|
||||
|
||||
@scheduler.scheduled_job('interval', hours=11)
|
||||
@ -32,9 +34,10 @@ async def scheduled_get_xk_data():
|
||||
('深渊概览', '深渊统计', '深渊使用率'), block=True
|
||||
)
|
||||
async def send_abyss_pic(bot: Bot, ev: Event):
|
||||
await draw_xk_abyss_img()
|
||||
img = await convert_img(TOTAL_IMG)
|
||||
await bot.logger.info('获得深渊概览图片成功!')
|
||||
# await draw_xk_abyss_img()
|
||||
img = await draw_teyvat_abyss_img()
|
||||
# img = await convert_img(TOTAL_IMG)
|
||||
logger.info('获得深渊概览图片成功!')
|
||||
await bot.send(img)
|
||||
|
||||
|
||||
|
138
GenshinUID/genshinuid_xkdata/draw_teyvat_img.py
Normal file
138
GenshinUID/genshinuid_xkdata/draw_teyvat_img.py
Normal file
@ -0,0 +1,138 @@
|
||||
from typing import List
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
from gsuid_core.utils.error_reply import get_error
|
||||
|
||||
from ..utils.image.convert import convert_img
|
||||
from ..utils.api.teyvat.request import teyvat_api
|
||||
from ..utils.api.teyvat.models import FakeTeyvatRank
|
||||
from ..utils.resource.RESOURCE_PATH import CHAR_PATH
|
||||
from ..utils.map.name_covert import name_to_avatar_id
|
||||
from ..utils.image.image_tools import get_v4_bg, add_footer
|
||||
from ..utils.fonts.genshin_fonts import (
|
||||
gs_font_24,
|
||||
gs_font_26,
|
||||
gs_font_30,
|
||||
gs_font_32,
|
||||
gs_font_36,
|
||||
)
|
||||
|
||||
TEXT_PATH = Path(__file__).parent / 'texture2d2'
|
||||
TOTAL_IMG = Path(__file__).parent / 'abyss_total.png'
|
||||
|
||||
GREY = (200, 200, 200)
|
||||
|
||||
COLOR_MAP = {
|
||||
'S+': (225, 67, 67),
|
||||
'S': (255, 188, 0),
|
||||
'A': (189, 0, 255),
|
||||
'B': (0, 186, 255),
|
||||
'C': (148, 204, 97),
|
||||
}
|
||||
|
||||
|
||||
async def draw_teyvat_abyss_img():
|
||||
data = await teyvat_api.get_abyss_rank()
|
||||
if isinstance(data, int):
|
||||
return get_error(data)
|
||||
|
||||
version = data['version'].replace('当前版本:', '')
|
||||
data_time = data['update']
|
||||
tip1 = data['tips']
|
||||
tip2 = data['tips2']
|
||||
|
||||
w, h = 1500, 500
|
||||
result = data['result'][0]
|
||||
|
||||
temp_result: List[FakeTeyvatRank] = []
|
||||
for rank_data in result:
|
||||
char_lst = rank_data['list']
|
||||
h += 90
|
||||
h += (((len(char_lst) - 1) // 7) + 1) * 266
|
||||
lst = []
|
||||
for char in char_lst:
|
||||
char_name = char['name']
|
||||
for e_char in data['result'][1]:
|
||||
if e_char['name'] == char_name:
|
||||
char['use_rate'] = e_char['use_rate']
|
||||
lst.append(e_char)
|
||||
|
||||
temp_result.append(
|
||||
{
|
||||
'rank_name': rank_data['rank_name'],
|
||||
'rank_class': rank_data['rank_class'],
|
||||
'list': lst,
|
||||
},
|
||||
)
|
||||
|
||||
h += 200
|
||||
title = Image.open(TEXT_PATH / 'title_bg.png')
|
||||
title_draw = ImageDraw.Draw(title)
|
||||
|
||||
title_draw.text((664, 318), version, 'white', gs_font_36, 'mm')
|
||||
title_draw.text((287, 364), data_time, GREY, gs_font_26, 'lm')
|
||||
|
||||
img = get_v4_bg(w, h)
|
||||
img.paste(title, (0, 0), title)
|
||||
|
||||
img_draw = ImageDraw.Draw(img)
|
||||
|
||||
img_draw.text((750, h - 130), tip1, GREY, gs_font_26, 'mm')
|
||||
img_draw.text((750, h - 80), tip2, GREY, gs_font_26, 'mm')
|
||||
|
||||
y = 500
|
||||
for rank_data in temp_result:
|
||||
rank_name = rank_data['rank_name'] # S+
|
||||
img_draw.rounded_rectangle(
|
||||
(50, y + 30, 1450, y + 66),
|
||||
4,
|
||||
COLOR_MAP.get(rank_name, (44, 44, 44)),
|
||||
)
|
||||
img_draw.text((750, y + 48), rank_name, 'white', gs_font_30, 'mm')
|
||||
|
||||
for c_index, char in enumerate(rank_data['list']):
|
||||
char_star = char['star']
|
||||
char_use_rate = f"{char['use_rate']}%"
|
||||
use_rate_change = char['use_rate_change']
|
||||
if use_rate_change < 0:
|
||||
rate_color = (49, 165, 57)
|
||||
rate_change = f'{use_rate_change}%'
|
||||
else:
|
||||
rate_color = (255, 57, 57)
|
||||
rate_change = f'+{use_rate_change}%'
|
||||
|
||||
char_bg = Image.open(TEXT_PATH / f'star{char_star}_bg.png')
|
||||
char_draw = ImageDraw.Draw(char_bg)
|
||||
|
||||
char_id = await name_to_avatar_id(char['name'])
|
||||
char_path = CHAR_PATH / f'{char_id}.png'
|
||||
char = Image.open(char_path)
|
||||
char = char.resize((158, 158))
|
||||
char = char.convert('RGBA')
|
||||
|
||||
char_bg.paste(char, (19, 28), char)
|
||||
char_draw.text((98, 240), '使用率', GREY, gs_font_24, 'mm')
|
||||
char_draw.text((98, 211), char_use_rate, 'white', gs_font_32, 'mm')
|
||||
|
||||
char_draw.rounded_rectangle((46, 22, 150, 48), 20, rate_color)
|
||||
char_draw.text((98, 35), rate_change, 'white', gs_font_26, 'mm')
|
||||
|
||||
img.paste(
|
||||
char_bg,
|
||||
(65 + (c_index % 7) * 194, y + 100 + (c_index // 7) * 266),
|
||||
char_bg,
|
||||
)
|
||||
y += (((len(rank_data['list']) - 1) // 7) + 1) * 266 + 100
|
||||
|
||||
img = add_footer(img)
|
||||
img = img.convert('RGB')
|
||||
'''
|
||||
img.save(
|
||||
TOTAL_IMG,
|
||||
format='JPEG',
|
||||
quality=90,
|
||||
subsampling=0,
|
||||
)
|
||||
'''
|
||||
return await convert_img(img)
|
BIN
GenshinUID/genshinuid_xkdata/texture2d2/star4_bg.png
Normal file
BIN
GenshinUID/genshinuid_xkdata/texture2d2/star4_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
GenshinUID/genshinuid_xkdata/texture2d2/star5_bg.png
Normal file
BIN
GenshinUID/genshinuid_xkdata/texture2d2/star5_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
BIN
GenshinUID/genshinuid_xkdata/texture2d2/title_bg.png
Normal file
BIN
GenshinUID/genshinuid_xkdata/texture2d2/title_bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
@ -1,7 +1,6 @@
|
||||
import sys
|
||||
import json
|
||||
import asyncio
|
||||
from re import T
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
|
3
GenshinUID/utils/api/teyvat/api.py
Normal file
3
GenshinUID/utils/api/teyvat/api.py
Normal file
@ -0,0 +1,3 @@
|
||||
LELAER_API = 'https://api.lelaer.com/ys'
|
||||
|
||||
AbyssRank_API = f'{LELAER_API}/getAbyssRank.php?star=all&role=all'
|
104
GenshinUID/utils/api/teyvat/models.py
Normal file
104
GenshinUID/utils/api/teyvat/models.py
Normal file
@ -0,0 +1,104 @@
|
||||
from typing import List, Tuple, TypedDict
|
||||
|
||||
|
||||
class TeyvatChar(TypedDict):
|
||||
name: str
|
||||
star: int
|
||||
avatar: str
|
||||
use: int
|
||||
own: int
|
||||
use_rate: float
|
||||
own_rate: float
|
||||
rank_class: str
|
||||
|
||||
|
||||
class TeyvatSelect(TypedDict):
|
||||
title: str
|
||||
value: str
|
||||
|
||||
|
||||
class TeyvatRestart(TypedDict):
|
||||
intro: str
|
||||
rate: float
|
||||
width: int
|
||||
|
||||
|
||||
class CharacterUsage(TypedDict):
|
||||
name: str
|
||||
star: int
|
||||
avatar: str
|
||||
use: int
|
||||
own: int
|
||||
use_rate: float
|
||||
own_rate: float
|
||||
rank_class: str
|
||||
use_rate_old: float
|
||||
use_rate_change: float
|
||||
|
||||
|
||||
class CharacterRank(TypedDict):
|
||||
name: str
|
||||
ename: str
|
||||
star: int
|
||||
avatar: str
|
||||
use: int
|
||||
own: int
|
||||
use_rate: float
|
||||
own_rate: float
|
||||
|
||||
|
||||
class TeyvatRank(TypedDict):
|
||||
rank_name: str # S/S+
|
||||
rank_class: str # s1
|
||||
list: List[CharacterRank]
|
||||
|
||||
|
||||
class FakeTeyvatRank(TypedDict):
|
||||
rank_name: str # S/S+
|
||||
rank_class: str # s1
|
||||
list: List[CharacterUsage]
|
||||
|
||||
|
||||
class Role(TypedDict):
|
||||
avatar: str
|
||||
star: int
|
||||
|
||||
|
||||
class TeyvatTeam(TypedDict):
|
||||
role: List[Role]
|
||||
use: int
|
||||
use_rate: float
|
||||
has: int
|
||||
has_rate: float
|
||||
attend_rate: float
|
||||
up_use: int
|
||||
down_use: int
|
||||
up_use_num: int
|
||||
down_use_num: int
|
||||
|
||||
|
||||
class TeyvatAbyssRank(TypedDict):
|
||||
code: int
|
||||
title: str
|
||||
rank_btn: str
|
||||
version: str
|
||||
now_version: str
|
||||
old_version: str
|
||||
last_update: str
|
||||
update: str
|
||||
top_own: int
|
||||
tips: str
|
||||
tips2: str
|
||||
select_list: List[TeyvatSelect]
|
||||
has_list: List[TeyvatChar]
|
||||
star36_rate: str
|
||||
star36_once_rate: str
|
||||
restart_times_avg: float
|
||||
nandu: int
|
||||
restart_info: List[TeyvatRestart]
|
||||
result: Tuple[
|
||||
List[TeyvatRank],
|
||||
List[CharacterUsage],
|
||||
List[CharacterUsage],
|
||||
List[TeyvatTeam],
|
||||
]
|
52
GenshinUID/utils/api/teyvat/request.py
Normal file
52
GenshinUID/utils/api/teyvat/request.py
Normal file
@ -0,0 +1,52 @@
|
||||
import json
|
||||
from typing import Any, Dict, Union, Literal, Optional, cast
|
||||
|
||||
from httpx import AsyncClient
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from .api import AbyssRank_API
|
||||
from .models import TeyvatAbyssRank
|
||||
|
||||
|
||||
class _TeyvatAPI:
|
||||
ssl_verify = True
|
||||
_HEADER = {'User-Agent': 'GenshinUID & GsCore'}
|
||||
|
||||
async def get_abyss_rank(self) -> Union[TeyvatAbyssRank, int]:
|
||||
data = await self._teyvat_request(AbyssRank_API)
|
||||
if isinstance(data, Dict) and 'code' in data:
|
||||
if data['code'] == 200:
|
||||
return cast(TeyvatAbyssRank, data)
|
||||
else:
|
||||
return data['code']
|
||||
else:
|
||||
return -500
|
||||
|
||||
async def _teyvat_request(
|
||||
self,
|
||||
url: str,
|
||||
method: Literal['GET', 'POST'] = 'GET',
|
||||
header: Dict[str, Any] = _HEADER,
|
||||
params: Optional[Dict[str, Any]] = None,
|
||||
_json: Optional[Dict[str, Any]] = None,
|
||||
) -> Union[Dict, int]:
|
||||
async with AsyncClient(timeout=None) as client:
|
||||
resp = await client.request(
|
||||
method,
|
||||
url,
|
||||
headers=header,
|
||||
params=params,
|
||||
json=_json,
|
||||
)
|
||||
try:
|
||||
raw_data = await resp.json()
|
||||
except: # noqa
|
||||
try:
|
||||
raw_data = json.loads(resp.text)
|
||||
except: # noqa
|
||||
raw_data = {'retcode': -999, 'data': resp.text}
|
||||
logger.debug(raw_data)
|
||||
return raw_data
|
||||
|
||||
|
||||
teyvat_api = _TeyvatAPI()
|
Loading…
x
Reference in New Issue
Block a user