新增角色命座的图片版 (#500)

This commit is contained in:
Wuyi无疑 2023-04-20 02:51:29 +08:00
parent ee9d941c6b
commit 1f48c58f30
15 changed files with 138 additions and 75 deletions

View File

@ -9,6 +9,11 @@ from .get_foods_pic import get_foods_wiki_img
from .get_weapons_pic import get_weapons_wiki_img
from ..genshinuid_config.gs_config import gsconfig
from .get_artifacts_pic import get_artifacts_wiki_img
from ..utils.map.name_covert import alias_to_char_name
from .get_constellation_pic import (
get_constellation_wiki_img,
get_single_constellation_img,
)
from .get_wiki_text import (
char_wiki,
foods_wiki,
@ -66,6 +71,7 @@ async def send_weapon(bot: Bot, ev: Event):
@sv_wiki_text.on_prefix(('角色天赋', '查天赋'))
async def send_talents(bot: Bot, ev: Event):
name = ''.join(re.findall('[\u4e00-\u9fa5]', ev.text))
name = await alias_to_char_name(name)
num = re.findall(r'\d+', ev.text)
if len(num) == 1:
im = await talent_wiki(name, int(num[0]))
@ -79,6 +85,7 @@ async def send_talents(bot: Bot, ev: Event):
@sv_wiki_text.on_prefix(('角色介绍', '角色资料', '查角色'))
async def send_char(bot: Bot, ev: Event):
name = ''.join(re.findall('[\u4e00-\u9fa5]', ev.text))
name = await alias_to_char_name(name)
level = re.findall(r'\d+', ev.text)
if len(level) == 1:
im = await char_stats_wiki(name, int(level[0]))
@ -89,7 +96,8 @@ async def send_char(bot: Bot, ev: Event):
@sv_wiki_text.on_prefix(('角色材料'))
async def send_char_cost(bot: Bot, ev: Event):
im = await char_costs_wiki(ev.text)
name = await alias_to_char_name(ev.text)
im = await char_costs_wiki(name)
await bot.send(im)
@ -104,18 +112,21 @@ async def send_polar(bot: Bot, ev: Event):
m = ''.join(re.findall('[\u4e00-\u9fa5]', ev.text))
num_re = re.findall(r'\d+', ev.text)
m = await alias_to_char_name(m)
if num_re:
num = int(num_re[0])
else:
return
'''
if gsconfig.get_config('PicWiki').data:
return await bot.send(await get_constellation_wiki_img(m))
else:
return await bot.send('请输入正确的命座数,例如 角色命座申鹤2!')
'''
if num <= 0 or num > 6:
return await bot.send('你家{}{}命?'.format(m, num))
im = await constellation_wiki(m, num)
if gsconfig.get_config('PicWiki').data:
im = await get_single_constellation_img(m, num)
else:
im = await constellation_wiki(m, num)
await bot.send(im)

View File

@ -170,7 +170,7 @@ async def draw_artifacts_wiki_img(data: Artifact) -> bytes:
result_img.save(
WIKI_REL_PATH / '{}.jpg'.format(data['name']),
format='JPEG',
quality=100,
quality=95,
subsampling=0,
)
return await convert_img(result_img)

View File

@ -1,26 +1,39 @@
from typing import Dict, Tuple, Union
from typing import Dict, List, Tuple, Union
import aiofiles
from PIL import Image, ImageDraw
from .path import TEXT_PATH
from ..utils.colors import first_color
from ..utils.error_reply import get_error
from ..utils.resource.download_url import download
from ..utils.map.name_covert import name_to_avatar_id
from ..utils.map.GS_MAP_PATH import avatarName2Element
from ..utils.image.convert import str_lenth, convert_img
from ..utils.fonts.genshin_fonts import gs_font_20, gs_font_28
from ..gsuid_utils.api.minigg.request import get_constellation_info
from ..utils.image.image_tools import get_color_bg, draw_pic_with_ring
from ..gsuid_utils.api.minigg.request import (
get_character_info,
get_constellation_info,
)
from ..utils.resource.RESOURCE_PATH import (
CHAR_PATH,
ICON_PATH,
CONSTELLATION_PATH,
)
from ..utils.fonts.genshin_fonts import (
gs_font_18,
gs_font_20,
gs_font_28,
gs_font_32,
)
from ..gsuid_utils.api.minigg.models import (
Character,
CharacterConstellation,
CharacterConstellations,
)
from ..utils.image.image_tools import (
get_star_png,
get_simple_bg,
get_unknown_png,
draw_pic_with_ring,
)
COLOR_MAP = {
'Anemo': (0, 145, 137),
@ -35,26 +48,47 @@ COLOR_MAP = {
async def get_constellation_wiki_img(name: str) -> Union[str, bytes]:
data = await get_constellation_info(name)
char_data = await get_character_info(name)
if isinstance(data, int):
return get_error(data)
elif isinstance(char_data, int):
return get_error(char_data)
elif isinstance(char_data, List):
return get_error(-400)
else:
pass
'''
full_name = data['name']
path = CONSTELLATION_PATH / f'{full_name}.jpg'
if path.exists():
async with aiofiles.open(path, 'rb') as f:
return await f.read()
'''
img = await draw_constellation_wiki_img(data)
img = await draw_constellation_wiki_img(data, char_data)
return img
async def get_single_constellation_img(
name: str, num: int
) -> Union[str, bytes]:
data = await get_constellation_info(name)
if isinstance(data, int):
return get_error(data)
else:
full_name = data['name']
path = CONSTELLATION_PATH / f'{full_name}_{num}.jpg'
if path.exists():
async with aiofiles.open(path, 'rb') as f:
return await f.read()
con = data[f'c{num}']
url = data['images'][f'c{num}']
img = await draw_single_constellation(con, url, num, data['name'], True)
return await convert_img(img)
async def draw_single_constellation(
data: CharacterConstellation,
image: str,
num: int,
color: Tuple[int, int, int],
char_name: str,
is_single: bool = False,
) -> Image.Image:
# 计算长度
effect = data['effect']
@ -64,96 +98,114 @@ async def draw_single_constellation(
else:
effect = effect.replace('**', '', 1)
effect = '  ' + effect.replace('\n', '\n  ')
effect = await str_lenth(effect, 20, 465)
effect += '\n'
img1 = Image.new('RGBA', (600, 1400))
effect = await str_lenth(effect, 20, 420)
img1 = Image.new('RGBA', (1, 1))
img1_draw = ImageDraw.Draw(img1)
_, _, _, y1 = img1_draw.textbbox((0, 0), effect, gs_font_20)
y = 110 + y1
img = Image.new('RGBA', (600, y))
y = 90 + y1
if is_single:
bg = Image.open(TEXT_PATH / 'wiki_weapon_bg.jpg')
img = await get_simple_bg(600, y, bg)
else:
img = Image.new('RGBA', (600, y))
img_draw = ImageDraw.Draw(img)
img_draw.rounded_rectangle(
(45, 18, 555, y),
fill=(255, 255, 255, 125),
radius=20,
)
if is_single:
img_test = Image.new('RGBA', (600, y))
img_test_draw = ImageDraw.Draw(img_test)
img_test_draw.rounded_rectangle(
(28, 7, 572, 80 + y1),
fill=(255, 255, 255, 60),
radius=20,
)
img.paste(img_test, (0, 0), img_test)
icon_bg = Image.open(TEXT_PATH / 'ring_bg.png').resize((74, 74))
img.paste(icon_bg, (38, 20), icon_bg)
icon_name = image.split('/')[-1]
path = ICON_PATH / icon_name
if not path.exists():
await download(image, 8, icon_name)
icon = Image.open(path).resize((51, 51))
img.paste(icon, (60, 28), icon)
icon = Image.open(path).resize((38, 38))
img.paste(icon, (57, 37), icon)
img_draw.text(
(128, 52),
f'{num}命 | {data["name"]}',
color,
(134, 40),
f'{data["name"]}',
(255, 206, 51),
gs_font_28,
'lm',
)
# line = '·' * 25 + '\n'
# img_draw.text((300, 95), line, (243, 180, 133), gs_font_20, 'mm')
img_draw.text((60, 95), effect, first_color, gs_font_20)
# img_draw.text((300, 120 + y1), line, (243, 180, 133), gs_font_20, 'mm')
img_draw.text((130, 60), effect, (230, 230, 230), gs_font_20)
if is_single:
img = img.convert('RGB')
img.save(
CONSTELLATION_PATH / f'{char_name}_{num}.jpg',
format='JPEG',
quality=95,
subsampling=0,
)
return img
async def draw_constellation_wiki_img(data: CharacterConstellations) -> bytes:
async def draw_constellation_wiki_img(
data: CharacterConstellations, char_data: Character
) -> bytes:
img_list: Dict[int, Tuple[Image.Image, int]] = {}
element = avatarName2Element[data['name']]
bg_color = COLOR_MAP[element]
# element = avatarName2Element[data['name']]
# bg_color = COLOR_MAP[element]
y = 0
for i in range(1, 7):
_img = await draw_single_constellation(
data[f'c{i}'], data['images'][f'c{i}'], i, bg_color
data[f'c{i}'], data['images'][f'c{i}'], i, char_data['name']
)
img_list[i] = (_img, _img.size[1])
y += _img.size[1]
title = Image.open(TEXT_PATH / 'con_title.png')
bg = Image.open(TEXT_PATH / 'wiki_weapon_bg.jpg')
img = await get_simple_bg(600, 280 + y, bg)
img_draw = ImageDraw.Draw(img)
desc = await str_lenth(char_data['description'], 18, 341)
avatar_id = await name_to_avatar_id(data['name'])
char_img = Image.open(CHAR_PATH / f'{avatar_id}.png')
icon = await draw_pic_with_ring(char_img, 210)
title.paste(icon, (192, 44), icon)
title_draw = ImageDraw.Draw(title)
title_draw.text(
(300, 296), f'{data["name"]}命座', bg_color, gs_font_28, 'mm'
)
'''
overlay = Image.open(TEXT_PATH / 'wiki_grad_black.png').resize(
(600, y + 400)
)
color_img = Image.new('RGBA', overlay.size, bg_color)
img = ImageChops.difference(color_img, overlay)
'''
img = await get_color_bg(600, y + 400)
icon = await draw_pic_with_ring(char_img, 148)
img.paste(icon, (40, 77), icon)
'''
gacha_img = Image.open(GACHA_IMG_PATH / f'{data["name"]}.png')
gacha_img.putalpha(
gacha_img.getchannel('A').point(
lambda x: round(x * 0.2) if x > 0 else 0
)
img_draw.text((205, 161), desc, (230, 230, 230), gs_font_18)
img_draw.text(
(232, 102),
f'{char_data["title"]}·{char_data["name"]}',
(255, 255, 255),
gs_font_32,
'lm',
)
img.paste(gacha_img, (-724, 275), gacha_img)
'''
temp = 365
star_pic = get_star_png(char_data['rarity'])
element_pic_path = TEXT_PATH / f'{char_data["element"]}.png'
if element_pic_path.exists():
element_pic = Image.open(element_pic_path).resize((36, 36))
else:
element_pic = get_unknown_png().resize((36, 36))
img.paste(element_pic, (188, 81), element_pic)
img.paste(star_pic, (201, 120), star_pic)
temp = 253
for index in img_list:
_img = img_list[index][0]
img.paste(_img, (0, temp), _img)
temp += img_list[index][1]
img.paste(title, (0, 0), title)
img = img.convert('RGB')
img.save(
CONSTELLATION_PATH / '{}.jpg'.format(data['name']),
format='JPEG',
quality=100,
quality=95,
subsampling=0,
)
return await convert_img(img)

View File

@ -123,7 +123,7 @@ async def draw_foods_wiki_img(data: Food):
img.save(
WIKI_FOOD_PATH / '{}.jpg'.format(data['name']),
format='JPEG',
quality=100,
quality=95,
subsampling=0,
)
return await convert_img(img)

View File

@ -214,7 +214,7 @@ async def draw_weapons_wiki_img(data: Weapon, stats: WeaponStats):
img.save(
WIKI_WEAPON_PATH / '{}.jpg'.format(data['name']),
format='JPEG',
quality=100,
quality=95,
subsampling=0,
)
return await convert_img(img)

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

8
poetry.lock generated
View File

@ -619,14 +619,14 @@ test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==23.1.0)", "coverage[toml] (>=6
[[package]]
name = "fastapi-amis-admin"
version = "0.5.4"
version = "0.5.5"
description = "FastAPI-Amis-Admin is a high-performance, efficient and easily extensible FastAPI admin framework. Inspired by Django-admin, and has as many powerful functions as Django-admin. "
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "fastapi_amis_admin-0.5.4-py3-none-any.whl", hash = "sha256:1cacef8681c35dbaa12a9ee7136161eca57b3f449cba18a885410ede00ced9d7"},
{file = "fastapi_amis_admin-0.5.4.tar.gz", hash = "sha256:0d56c53a8766672b54de0e779b02c321bdd6fd09c754a1a99212bf5da24fc04f"},
{file = "fastapi_amis_admin-0.5.5-py3-none-any.whl", hash = "sha256:8faeece0962a7db0f807e68c09fa45ed75e79ba55c9990e734de486ee6bbf4c1"},
{file = "fastapi_amis_admin-0.5.5.tar.gz", hash = "sha256:b3c57f42fad800906cb39e0d1ea67d597747c09875ae74f20fda1d516e8b2580"},
]
[package.dependencies]
@ -639,7 +639,7 @@ sqlmodel = ">=0.0.7"
[package.extras]
all = ["fastapi-amis-admin[dev]"]
cli = ["fastapi-amis-admin-cli (>=0.1.0,<0.2.0)"]
dev = ["fastapi-amis-admin[test]", "pre-commit (>=2.20.0)"]
dev = ["fastapi-amis-admin[test]", "pre-commit (>=2.20.0)", "ruff (>=0.0.261)"]
standard = ["fastapi-amis-admin-cli (>=0.1.0,<0.2.0)", "uvicorn[standard] (>=0.19.0,<1.0)"]
test = ["aiosqlite (>=0.15.0)", "fastapi-amis-admin[standard]", "httpx (>=0.23.0,<1.0)", "jinja2 (>=2.11.2,<4.0.0)", "pytest (>=6.2.4,<7.0.0)", "pytest-asyncio (>=0.17)", "requests (>=2.28.1)", "ujson (>=4.0.1)"]

View File

@ -15,7 +15,7 @@ colorama==0.4.6 ; python_full_version >= "3.8.1" and python_version < "4.0" and
dnspython==2.3.0 ; python_full_version >= "3.8.1" and python_version < "4.0"
email-validator==2.0.0.post1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
et-xmlfile==1.1.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-amis-admin==0.5.4 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-amis-admin==0.5.5 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi-user-auth==0.5.0 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
fastapi==0.95.1 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"
frozenlist==1.3.3 ; python_full_version >= "3.8.1" and python_full_version < "4.0.0"