✨ 支持mr
新版小组件体力UI
@ -6,6 +6,7 @@ from typing import List, Union
|
||||
from PIL import Image, ImageDraw
|
||||
from gsuid_core.logger import logger
|
||||
from gsuid_core.utils.api.mys.models import Expedition
|
||||
from gsuid_core.utils.error_reply import get_error_img
|
||||
|
||||
from ..utils.mys_api import mys_api
|
||||
from ..utils.database import get_sqla
|
||||
@ -13,7 +14,6 @@ from ..utils.api.mys.models import FakeResin
|
||||
from ..utils.image.convert import convert_img
|
||||
from ..genshinuid_config.gs_config import gsconfig
|
||||
from ..genshinuid_enka.to_data import get_enka_info
|
||||
from ..utils.image.image_tools import get_simple_bg
|
||||
from ..utils.map.name_covert import enName_to_avatarId
|
||||
from ..utils.api.mys.models import Expedition as WidgetExpedition
|
||||
from ..utils.resource.RESOURCE_PATH import PLAYER_PATH, CHAR_SIDE_PATH
|
||||
@ -21,20 +21,16 @@ from ..utils.api.mys.models import Transformer, WidgetResin, RecoveryTime
|
||||
from ..utils.fonts.genshin_fonts import (
|
||||
gs_font_20,
|
||||
gs_font_26,
|
||||
gs_font_28,
|
||||
gs_font_32,
|
||||
gs_font_60,
|
||||
gs_font_58,
|
||||
gs_font_70,
|
||||
)
|
||||
|
||||
TEXT_PATH = Path(__file__).parent / 'texture2D'
|
||||
|
||||
resin_fg_pic = Image.open(TEXT_PATH / 'resin_fg.png')
|
||||
yes_pic = Image.open(TEXT_PATH / 'yes.png')
|
||||
ok_pic = Image.open(TEXT_PATH / 'ok.png')
|
||||
no_pic = Image.open(TEXT_PATH / 'no.png')
|
||||
warn_pic = Image.open(TEXT_PATH / 'warn.png')
|
||||
|
||||
based_w = 500
|
||||
based_h = 900
|
||||
white_overlay = Image.new('RGBA', (based_w, based_h), (255, 251, 242, 225))
|
||||
un_pic = Image.open(TEXT_PATH / 'un.png')
|
||||
|
||||
first_color = (29, 29, 29)
|
||||
second_color = (98, 98, 98)
|
||||
@ -46,33 +42,40 @@ use_widget = gsconfig.get_config('WidgetResin').data
|
||||
|
||||
|
||||
async def _draw_task_img(
|
||||
img: Image.Image,
|
||||
img_draw: ImageDraw.ImageDraw,
|
||||
index: int,
|
||||
char: Union[Expedition, WidgetExpedition],
|
||||
):
|
||||
) -> Image.Image:
|
||||
go_img = Image.open(TEXT_PATH / 'go_bg.png')
|
||||
|
||||
if not char['avatar_side_icon']:
|
||||
return go_img
|
||||
|
||||
char_en_name = char['avatar_side_icon'].split('_')[-1].split('.')[0]
|
||||
avatar_id = await enName_to_avatarId(char_en_name)
|
||||
char_pic = (
|
||||
Image.open(CHAR_SIDE_PATH / f'{avatar_id}.png')
|
||||
.convert('RGBA')
|
||||
.resize((80, 80), Image.Resampling.LANCZOS) # type: ignore
|
||||
.resize((115, 115), Image.Resampling.LANCZOS) # type: ignore
|
||||
)
|
||||
img.paste(char_pic, (22 + index * 90, 770), char_pic)
|
||||
go_img.paste(char_pic, (0, -12), char_pic)
|
||||
go_draw = ImageDraw.ImageDraw(go_img)
|
||||
|
||||
if char['status'] == 'Finished':
|
||||
status_mark = '待收取'
|
||||
status_color = red_color
|
||||
else:
|
||||
status_mark = '已派遣'
|
||||
status_color = green_color
|
||||
img_draw.text(
|
||||
(65 + index * 90, 870),
|
||||
|
||||
go_draw.text(
|
||||
(60, 125),
|
||||
status_mark,
|
||||
font=gs_font_20,
|
||||
fill=status_color,
|
||||
anchor='mm',
|
||||
)
|
||||
|
||||
return go_img
|
||||
|
||||
|
||||
async def get_resin_img(bot_id: str, user_id: str):
|
||||
try:
|
||||
@ -91,7 +94,7 @@ async def get_resin_img(bot_id: str, user_id: str):
|
||||
# 开始绘图任务
|
||||
task = []
|
||||
img = Image.new(
|
||||
'RGBA', (based_w * len(useable_uid_list), based_h), (0, 0, 0, 0)
|
||||
'RGBA', (700 * len(useable_uid_list), 1200), (0, 0, 0, 0)
|
||||
)
|
||||
for uid_index, uid in enumerate(useable_uid_list):
|
||||
task.append(_draw_all_resin_img(img, uid, uid_index))
|
||||
@ -119,12 +122,12 @@ async def seconds2hours(seconds: int) -> str:
|
||||
def transform_fake_resin(data: WidgetResin) -> FakeResin:
|
||||
return FakeResin(
|
||||
**data,
|
||||
remain_resin_discount_num=0,
|
||||
remain_resin_discount_num=-99,
|
||||
resin_discount_num_limit=0,
|
||||
transformer=Transformer(
|
||||
obtained=True,
|
||||
recovery_time=RecoveryTime(
|
||||
Day=1, Hour=1, Minute=1, Second=1, reached=False
|
||||
Day=-99, Hour=1, Minute=1, Second=1, reached=False
|
||||
),
|
||||
wiki='',
|
||||
noticed=False,
|
||||
@ -133,43 +136,47 @@ def transform_fake_resin(data: WidgetResin) -> FakeResin:
|
||||
)
|
||||
|
||||
|
||||
def get_error(img: Image.Image, uid: str, daily_data: int):
|
||||
img_draw = ImageDraw.Draw(img)
|
||||
img.paste(warn_pic, (0, 0), warn_pic)
|
||||
# 写UID
|
||||
img_draw.text(
|
||||
(250, 553),
|
||||
f'UID{uid}',
|
||||
font=gs_font_26,
|
||||
fill=first_color,
|
||||
anchor='mm',
|
||||
)
|
||||
img_draw.text(
|
||||
(250, 518),
|
||||
f'错误码 {daily_data}',
|
||||
font=gs_font_26,
|
||||
fill=red_color,
|
||||
anchor='mm',
|
||||
)
|
||||
return img
|
||||
async def draw_bar(
|
||||
status: str = 'un', text: str = '洞天宝钱', data: str = '未知'
|
||||
) -> Image.Image:
|
||||
bar = Image.open(TEXT_PATH / 'bar_bg.png')
|
||||
bar_draw = ImageDraw.ImageDraw(bar)
|
||||
bar_draw.text((219, 50), text, (31, 32, 26), gs_font_32, 'lm')
|
||||
bar_draw.text((367, 52), data, (49, 49, 49), gs_font_28, 'lm')
|
||||
if status == 'ok':
|
||||
bar.paste(ok_pic, (151, 25), ok_pic)
|
||||
elif status == 'un':
|
||||
bar.paste(un_pic, (151, 25), un_pic)
|
||||
else:
|
||||
bar.paste(no_pic, (151, 25), no_pic)
|
||||
return bar
|
||||
|
||||
|
||||
async def draw_resin_img(uid: str) -> Image.Image:
|
||||
# 获取背景图片各项参数
|
||||
img = await get_simple_bg(based_w, based_h)
|
||||
img.paste(white_overlay, (0, 0), white_overlay)
|
||||
img = Image.open(TEXT_PATH / 'bg.png')
|
||||
|
||||
# 获取数据
|
||||
if use_widget and int(str(uid)[0]) <= 5:
|
||||
_daily_data = await mys_api.get_widget_resin_data(uid)
|
||||
if isinstance(_daily_data, int):
|
||||
return get_error(img, uid, _daily_data)
|
||||
return Image.open(await get_error_img(_daily_data))
|
||||
daily_data = transform_fake_resin(_daily_data)
|
||||
data_res = '当前数据源:小组件 (可能存在数据不准、数据缺失)'
|
||||
warn = '数据未知...'
|
||||
|
||||
is_sign = 'ok' if _daily_data['has_signed'] else 'no'
|
||||
else:
|
||||
daily_data = await mys_api.get_daily_data(uid)
|
||||
if isinstance(daily_data, int):
|
||||
return Image.open(await get_error_img(daily_data))
|
||||
data_res = '当前数据源:战绩'
|
||||
warn = '未知情况'
|
||||
|
||||
if isinstance(daily_data, int):
|
||||
return get_error(img, uid, daily_data)
|
||||
sign_info = await mys_api.get_sign_info(uid)
|
||||
if isinstance(sign_info, int):
|
||||
is_sign = 'un'
|
||||
else:
|
||||
is_sign = 'ok' if sign_info['is_sign'] else 'no'
|
||||
|
||||
enta_data_path = PLAYER_PATH / uid / 'rawData.json'
|
||||
if enta_data_path.exists():
|
||||
@ -183,18 +190,20 @@ async def draw_resin_img(uid: str) -> Image.Image:
|
||||
|
||||
# 处理数据
|
||||
if player_data and 'playerInfo' in player_data:
|
||||
name = player_data['playerInfo']['nickname']
|
||||
'''
|
||||
if 'signature' in player_data['playerInfo']:
|
||||
signature = player_data['playerInfo']['signature']
|
||||
else:
|
||||
signature = '该旅行者还没有签名噢~'
|
||||
'''
|
||||
world_level = player_data['playerInfo']['level']
|
||||
world_level_str = f'探索等级{str(world_level)}'
|
||||
else:
|
||||
signature = '暂无获取数据'
|
||||
name = '旅行者'
|
||||
# signature = '暂无获取数据'
|
||||
world_level_str = '暂无数据'
|
||||
|
||||
img.paste(resin_fg_pic, (0, 0), resin_fg_pic)
|
||||
|
||||
# 树脂
|
||||
resin = daily_data['current_resin']
|
||||
max_resin = daily_data['max_resin']
|
||||
@ -208,65 +217,70 @@ async def draw_resin_img(uid: str) -> Image.Image:
|
||||
int(daily_data['resin_recovery_time'])
|
||||
)
|
||||
|
||||
delay = 53
|
||||
# 洞天宝钱
|
||||
home_coin = daily_data['current_home_coin']
|
||||
max_home_coin = daily_data['max_home_coin']
|
||||
home_coin_str = f'{home_coin}/{max_home_coin}'
|
||||
home_coin_str = f'{home_coin} / {max_home_coin}'
|
||||
if max_home_coin - home_coin < 200:
|
||||
home_coin_mark = '可收取'
|
||||
home_coin_color = red_color
|
||||
img.paste(no_pic, (35, 559), no_pic)
|
||||
coin_status = 'no'
|
||||
else:
|
||||
home_coin_mark = '已收取'
|
||||
home_coin_color = green_color
|
||||
img.paste(yes_pic, (35, 559), yes_pic)
|
||||
coin_status = 'ok'
|
||||
coin_bar = await draw_bar(coin_status, '洞天宝钱', home_coin_str)
|
||||
|
||||
# 完成委托
|
||||
finish_task = daily_data['finished_task_num']
|
||||
total_task = daily_data['total_task_num']
|
||||
is_task_reward = daily_data['is_extra_task_reward_received']
|
||||
task_str = f'{finish_task}/{total_task}'
|
||||
task_str = f'{finish_task} / {total_task}'
|
||||
if is_task_reward:
|
||||
task_mark = '已领取'
|
||||
task_color = green_color
|
||||
img.paste(yes_pic, (35, 559 + delay), yes_pic)
|
||||
task_status = 'ok'
|
||||
else:
|
||||
task_mark = '未领取'
|
||||
task_color = red_color
|
||||
img.paste(no_pic, (35, 559 + delay), no_pic)
|
||||
task_status = 'no'
|
||||
task_bar = await draw_bar(task_status, '完成委托', task_str)
|
||||
|
||||
# 周本减半
|
||||
weekly_half = daily_data['remain_resin_discount_num']
|
||||
max_weekly_half = daily_data['resin_discount_num_limit']
|
||||
weekly_half_str = f'{weekly_half}/{max_weekly_half}'
|
||||
if weekly_half == 0:
|
||||
weekly_half_mark = '已使用'
|
||||
weekly_half_color = green_color
|
||||
img.paste(yes_pic, (35, 559 + delay * 2), yes_pic)
|
||||
if weekly_half == -99:
|
||||
weekly_status = 'un'
|
||||
weekly_half_str = warn
|
||||
elif weekly_half == 0:
|
||||
weekly_status = 'ok'
|
||||
else:
|
||||
weekly_half_mark = '未用完'
|
||||
weekly_half_color = red_color
|
||||
img.paste(no_pic, (35, 559 + delay * 2), no_pic)
|
||||
weekly_status = 'no'
|
||||
weekly_bar = await draw_bar(weekly_status, '周本减半', weekly_half_str)
|
||||
|
||||
# 参量质变仪
|
||||
transformer = daily_data['transformer']['recovery_time']['reached']
|
||||
transformer_day = daily_data['transformer']['recovery_time']['Day']
|
||||
transformer_hour = daily_data['transformer']['recovery_time']['Hour']
|
||||
transformer_str = f'还剩{transformer_day}天{transformer_hour}小时'
|
||||
if transformer:
|
||||
transformer_mark = '可使用'
|
||||
transformer_color = red_color
|
||||
img.paste(no_pic, (35, 559 + delay * 3), no_pic)
|
||||
if transformer_day == -99:
|
||||
trans_status = 'un'
|
||||
transformer_str = warn
|
||||
elif transformer:
|
||||
trans_status = 'no'
|
||||
else:
|
||||
transformer_mark = '已使用'
|
||||
transformer_color = green_color
|
||||
img.paste(yes_pic, (35, 559 + delay * 3), yes_pic)
|
||||
trans_status = 'ok'
|
||||
trans_bar = await draw_bar(trans_status, '周本减半', transformer_str)
|
||||
|
||||
img_draw = ImageDraw.Draw(img)
|
||||
|
||||
for _ in range(5):
|
||||
if len(daily_data['expeditions']) < 5:
|
||||
daily_data['expeditions'].append(
|
||||
Expedition(
|
||||
avatar_side_icon='', status='Ongoing', remained_time=233
|
||||
)
|
||||
)
|
||||
else:
|
||||
break
|
||||
|
||||
# 派遣
|
||||
task_task = []
|
||||
for index, char in enumerate(daily_data['expeditions']):
|
||||
task_task.append(_draw_task_img(img, img_draw, index, char))
|
||||
await asyncio.gather(*task_task)
|
||||
go_img = await _draw_task_img(char)
|
||||
img.paste(go_img, (81 + index * 106, 971), go_img)
|
||||
|
||||
# 绘制树脂圆环
|
||||
ring_pic = Image.open(TEXT_PATH / 'ring.apng')
|
||||
@ -274,99 +288,48 @@ async def draw_resin_img(uid: str) -> Image.Image:
|
||||
round(resin_percent * 49) if round(resin_percent * 49) <= 49 else 49
|
||||
)
|
||||
ring_pic.seek(percent)
|
||||
img.paste(ring_pic, (0, 0), ring_pic)
|
||||
img.paste(ring_pic, (0, -21), ring_pic)
|
||||
|
||||
# 写树脂剩余时间
|
||||
img_draw.text(
|
||||
(250, 370),
|
||||
(350, 466),
|
||||
f'还剩{resin_recovery_time}',
|
||||
font=gs_font_20,
|
||||
font=gs_font_28,
|
||||
fill=resin_color,
|
||||
anchor='mm',
|
||||
)
|
||||
# 写签名
|
||||
img_draw.text(
|
||||
(48, 137), signature, font=gs_font_26, fill=second_color, anchor='lm'
|
||||
)
|
||||
|
||||
# 写UID
|
||||
img_draw.text(
|
||||
(250, 518), f'UID{uid}', font=gs_font_26, fill=first_color, anchor='mm'
|
||||
)
|
||||
img_draw.text((350, 135), f'UID{uid}', (38, 38, 38), gs_font_26, 'mm')
|
||||
|
||||
# 写探索等级
|
||||
img_draw.text(
|
||||
(250, 281),
|
||||
(350, 354),
|
||||
world_level_str,
|
||||
font=gs_font_26,
|
||||
font=gs_font_28,
|
||||
fill=second_color,
|
||||
anchor='mm',
|
||||
)
|
||||
|
||||
# 写树脂
|
||||
img_draw.text(
|
||||
(250, 327),
|
||||
(350, 408),
|
||||
resin_str,
|
||||
font=gs_font_60,
|
||||
font=gs_font_70,
|
||||
fill=first_color,
|
||||
anchor='mm',
|
||||
)
|
||||
# 写洞天宝钱
|
||||
img_draw.text(
|
||||
(335, 588),
|
||||
home_coin_str,
|
||||
font=gs_font_20,
|
||||
fill=first_color,
|
||||
anchor='lm',
|
||||
)
|
||||
img_draw.text(
|
||||
(225, 584),
|
||||
home_coin_mark,
|
||||
font=gs_font_32,
|
||||
fill=home_coin_color,
|
||||
anchor='lm',
|
||||
)
|
||||
# 写完成委托
|
||||
img_draw.text(
|
||||
(335, 588 + delay),
|
||||
task_str,
|
||||
font=gs_font_20,
|
||||
fill=first_color,
|
||||
anchor='lm',
|
||||
)
|
||||
img_draw.text(
|
||||
(225, 584 + delay),
|
||||
task_mark,
|
||||
font=gs_font_32,
|
||||
fill=task_color,
|
||||
anchor='lm',
|
||||
)
|
||||
# 写周本减半
|
||||
img_draw.text(
|
||||
(335, 588 + delay * 2),
|
||||
weekly_half_str,
|
||||
font=gs_font_20,
|
||||
fill=first_color,
|
||||
anchor='lm',
|
||||
)
|
||||
img_draw.text(
|
||||
(225, 584 + delay * 2),
|
||||
weekly_half_mark,
|
||||
font=gs_font_32,
|
||||
fill=weekly_half_color,
|
||||
anchor='lm',
|
||||
)
|
||||
# 写参量质变仪
|
||||
img_draw.text(
|
||||
(335, 588 + delay * 3),
|
||||
transformer_str,
|
||||
font=gs_font_20,
|
||||
fill=first_color,
|
||||
anchor='lm',
|
||||
)
|
||||
img_draw.text(
|
||||
(225, 584 + delay * 3),
|
||||
transformer_mark,
|
||||
font=gs_font_32,
|
||||
fill=transformer_color,
|
||||
anchor='lm',
|
||||
)
|
||||
|
||||
img_draw.text((350, 89), name, (13, 13, 13), gs_font_58, 'mm')
|
||||
img_draw.text((350, 1140), data_res, (92, 92, 92), gs_font_20, 'mm')
|
||||
|
||||
delay = 78
|
||||
img.paste(coin_bar, (0, 642), coin_bar)
|
||||
img.paste(task_bar, (0, 642 + delay), task_bar)
|
||||
img.paste(weekly_bar, (0, 642 + delay * 2), weekly_bar)
|
||||
img.paste(trans_bar, (0, 642 + delay * 3), trans_bar)
|
||||
|
||||
sign_pic = Image.open(TEXT_PATH / f'sign_{is_sign}.png')
|
||||
img.paste(sign_pic, (275, 500), sign_pic)
|
||||
|
||||
return img
|
||||
|
BIN
GenshinUID/genshinuid_resin/texture2D/bar_bg.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
GenshinUID/genshinuid_resin/texture2D/bg.png
Normal file
After Width: | Height: | Size: 222 KiB |
BIN
GenshinUID/genshinuid_resin/texture2D/go_bg.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 4.2 KiB |
BIN
GenshinUID/genshinuid_resin/texture2D/ok.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 335 KiB After Width: | Height: | Size: 572 KiB |
BIN
GenshinUID/genshinuid_resin/texture2D/sign_no.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
GenshinUID/genshinuid_resin/texture2D/sign_ok.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
GenshinUID/genshinuid_resin/texture2D/sign_un.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
GenshinUID/genshinuid_resin/texture2D/un.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 1.8 KiB |