2024-10-11 12:59:56 +08:00

269 lines
8.2 KiB
Python

from pathlib import Path
from typing import Any, Dict, Union
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.convert import convert_img
from gsuid_core.utils.image.image_tools import (
draw_pic_with_ring,
get_qq_avatar,
)
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,
)
from ..utils.mys_api import mys_api
from ..utils.resource.get_pic_from import get_roleinfo_icon
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_roleinfo_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,
sum_score: Union[int, None],
):
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",
)
#总分todo
if sum_score:
floor_pic_draw.text(
(800, 60),
f"{sum_score}",
font=sr_font_42,
fill="#fec86f",
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: Dict[str, Any],
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
if node_1.score and node_2.score:
sum_score = int(node_1.score) + int(node_2.score)
else:
sum_score = None
for index_part in [0, 1]:
node_num = index_part + 1
if node_num == 1:
time_array = node_1.challenge_time
score = node_1.score
else:
time_array = node_2.challenge_time
score = node_2.score
assert time_array is not None
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",
)
# 分数todo
if score :
floor_pic_draw.text(
(800, 120 + index_part * 219),
f"{score}",
"#fec86f",
sr_font_30,
"rm",
)
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,
sum_score,
)
res = await convert_img(img)
logger.info("[查询末日幻影信息]绘图已完成,等待发送!")
return res