diff --git a/GenshinUID/genshinuid_wikitext/__init__.py b/GenshinUID/genshinuid_wikitext/__init__.py index 375079e9..b64ca7e7 100644 --- a/GenshinUID/genshinuid_wikitext/__init__.py +++ b/GenshinUID/genshinuid_wikitext/__init__.py @@ -9,6 +9,11 @@ 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) diff --git a/GenshinUID/genshinuid_wikitext/get_artifacts_pic.py b/GenshinUID/genshinuid_wikitext/get_artifacts_pic.py index d26c0533..3d4528a8 100644 --- a/GenshinUID/genshinuid_wikitext/get_artifacts_pic.py +++ b/GenshinUID/genshinuid_wikitext/get_artifacts_pic.py @@ -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) diff --git a/GenshinUID/genshinuid_wikitext/get_constellation_pic.py b/GenshinUID/genshinuid_wikitext/get_constellation_pic.py index 971d4bdd..30dff5ae 100644 --- a/GenshinUID/genshinuid_wikitext/get_constellation_pic.py +++ b/GenshinUID/genshinuid_wikitext/get_constellation_pic.py @@ -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 @@ 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) - - ''' - 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 - ) + icon = await draw_pic_with_ring(char_img, 148) + img.paste(icon, (40, 77), icon) + + 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) diff --git a/GenshinUID/genshinuid_wikitext/get_foods_pic.py b/GenshinUID/genshinuid_wikitext/get_foods_pic.py index 7935660e..6f4f00ef 100644 --- a/GenshinUID/genshinuid_wikitext/get_foods_pic.py +++ b/GenshinUID/genshinuid_wikitext/get_foods_pic.py @@ -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) diff --git a/GenshinUID/genshinuid_wikitext/get_weapons_pic.py b/GenshinUID/genshinuid_wikitext/get_weapons_pic.py index 98595d82..c8edf1e8 100644 --- a/GenshinUID/genshinuid_wikitext/get_weapons_pic.py +++ b/GenshinUID/genshinuid_wikitext/get_weapons_pic.py @@ -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) diff --git a/GenshinUID/genshinuid_wikitext/texture2D/ring_bg.png b/GenshinUID/genshinuid_wikitext/texture2D/ring_bg.png new file mode 100644 index 00000000..00bb4093 Binary files /dev/null and b/GenshinUID/genshinuid_wikitext/texture2D/ring_bg.png differ diff --git "a/GenshinUID/genshinuid_wikitext/texture2D/\345\206\260.png" "b/GenshinUID/genshinuid_wikitext/texture2D/\345\206\260.png" new file mode 100644 index 00000000..a2d8e8b9 Binary files /dev/null and "b/GenshinUID/genshinuid_wikitext/texture2D/\345\206\260.png" differ diff --git "a/GenshinUID/genshinuid_wikitext/texture2D/\345\262\251.png" "b/GenshinUID/genshinuid_wikitext/texture2D/\345\262\251.png" new file mode 100644 index 00000000..7073f997 Binary files /dev/null and "b/GenshinUID/genshinuid_wikitext/texture2D/\345\262\251.png" differ diff --git "a/GenshinUID/genshinuid_wikitext/texture2D/\346\260\264.png" "b/GenshinUID/genshinuid_wikitext/texture2D/\346\260\264.png" new file mode 100644 index 00000000..7a795693 Binary files /dev/null and "b/GenshinUID/genshinuid_wikitext/texture2D/\346\260\264.png" differ diff --git "a/GenshinUID/genshinuid_wikitext/texture2D/\347\201\253.png" "b/GenshinUID/genshinuid_wikitext/texture2D/\347\201\253.png" new file mode 100644 index 00000000..2a740c39 Binary files /dev/null and "b/GenshinUID/genshinuid_wikitext/texture2D/\347\201\253.png" differ diff --git "a/GenshinUID/genshinuid_wikitext/texture2D/\350\215\211.png" "b/GenshinUID/genshinuid_wikitext/texture2D/\350\215\211.png" new file mode 100644 index 00000000..eb63967a Binary files /dev/null and "b/GenshinUID/genshinuid_wikitext/texture2D/\350\215\211.png" differ diff --git "a/GenshinUID/genshinuid_wikitext/texture2D/\351\233\267.png" "b/GenshinUID/genshinuid_wikitext/texture2D/\351\233\267.png" new file mode 100644 index 00000000..fd10fcde Binary files /dev/null and "b/GenshinUID/genshinuid_wikitext/texture2D/\351\233\267.png" differ diff --git "a/GenshinUID/genshinuid_wikitext/texture2D/\351\243\216.png" "b/GenshinUID/genshinuid_wikitext/texture2D/\351\243\216.png" new file mode 100644 index 00000000..7c83f3f8 Binary files /dev/null and "b/GenshinUID/genshinuid_wikitext/texture2D/\351\243\216.png" differ diff --git a/poetry.lock b/poetry.lock index a0c54edb..b7d180ea 100644 --- a/poetry.lock +++ b/poetry.lock @@ -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)"] diff --git a/requirements.txt b/requirements.txt index 5852bc04..16e6463e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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"