为支持的平台添加更多按钮适配

This commit is contained in:
KimigaiiWuyi 2023-11-21 00:32:20 +08:00
parent e4b93d6418
commit d20418376d
12 changed files with 232 additions and 58 deletions

View File

@ -3,6 +3,7 @@ import re
from gsuid_core.sv import SV from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.message_models import Button
from gsuid_core.utils.error_reply import UID_HINT from gsuid_core.utils.error_reply import UID_HINT
from ..utils.convert import get_uid from ..utils.convert import get_uid
@ -48,4 +49,8 @@ async def send_abyss_info(bot: Bot, ev: Event):
await bot.logger.info('[查询深渊信息]深渊层数: {}'.format(floor)) await bot.logger.info('[查询深渊信息]深渊层数: {}'.format(floor))
im = await draw_abyss_img(user_id, uid, floor, schedule_type) im = await draw_abyss_img(user_id, uid, floor, schedule_type)
await bot.send(im) a = Button('🔍查询深渊11', '查询深渊11')
b = Button('🔚查询上期深渊', '查询上期深渊')
c = Button('♾️深渊概览', '深渊概览')
d = Button('👾怪物阵容', '版本深渊')
await bot.send_option(im, [a, b, c, d])

View File

@ -1,15 +1,35 @@
from gsuid_core.sv import SV from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.message_models import Button
from gsuid_core.utils.error_reply import UID_HINT from gsuid_core.utils.error_reply import UID_HINT
from ..utils.convert import get_uid from ..utils.convert import get_uid
from .draw_new_collection_card import draw_explore
from .draw_collection_card import draw_explora_img, draw_collection_img from .draw_collection_card import draw_explora_img, draw_collection_img
sv_cp = SV('查询完成度')
sv_sj = SV('查询收集') sv_sj = SV('查询收集')
sv_ts = SV('查询探索') sv_ts = SV('查询探索')
@sv_cp.on_command(('查询完成度', 'wcd'), block=True)
async def send_cp_info(bot: Bot, ev: Event):
await bot.logger.info('开始执行[查询完成度信息]')
# user_id = ev.at if ev.at else ev.user_id
# 获取uid
uid = await get_uid(bot, ev)
if uid is None:
return await bot.send(UID_HINT)
await bot.logger.info('[查询角色面板]uid: {}'.format(uid))
im = await draw_explore(uid)
a = Button('🔍查询探索', '查询探索')
b = Button('🔍查询收集', '查询收集')
await bot.send_option(im, [a, b])
@sv_sj.on_command(('查询收集', 'sj'), block=True) @sv_sj.on_command(('查询收集', 'sj'), block=True)
async def send_collection_info(bot: Bot, ev: Event): async def send_collection_info(bot: Bot, ev: Event):
await bot.logger.info('开始执行[查询收集信息]') await bot.logger.info('开始执行[查询收集信息]')
@ -22,7 +42,9 @@ async def send_collection_info(bot: Bot, ev: Event):
await bot.logger.info('[查询角色面板]uid: {}'.format(uid)) await bot.logger.info('[查询角色面板]uid: {}'.format(uid))
im = await draw_collection_img(user_id, uid) im = await draw_collection_img(user_id, uid)
await bot.send(im) a = Button('🔍查询探索', '查询探索')
b = Button('🔍查询收集', '查询收集')
await bot.send_option(im, [a, b])
@sv_ts.on_command(('查询探索', 'ts'), block=True) @sv_ts.on_command(('查询探索', 'ts'), block=True)
@ -37,4 +59,6 @@ async def send_explora_info(bot: Bot, ev: Event):
await bot.logger.info('[查询角色面板]uid: {}'.format(uid)) await bot.logger.info('[查询角色面板]uid: {}'.format(uid))
im = await draw_explora_img(user_id, uid) im = await draw_explora_img(user_id, uid)
await bot.send(im) a = Button('🔍查询探索', '查询探索')
b = Button('🔍查询收集', '查询收集')
await bot.send_option(im, [a, b])

View File

@ -1,8 +1,17 @@
from PIL import Image from PIL import Image, ImageDraw
from gsuid_core.utils.image.convert import convert_img
from gsuid_core.utils.image.image_tools import crop_center_img
from gsuid_core.utils.download_resource.download_image import get_image from gsuid_core.utils.download_resource.download_image import get_image
from ..utils.resource.RESOURCE_PATH import ICON_PATH from ..utils.resource.RESOURCE_PATH import ICON_PATH
from ..utils.image.image_tools import shift_image_hue
from .draw_collection_card import TEXT_PATH, get_base_data from .draw_collection_card import TEXT_PATH, get_base_data
from ..utils.fonts.genshin_fonts import (
gs_font_15,
gs_font_20,
gs_font_24,
gs_font_32,
)
async def draw_explore(uid: str): async def draw_explore(uid: str):
@ -12,14 +21,62 @@ async def draw_explore(uid: str):
): ):
return raw_data return raw_data
worlds = raw_data['world_explorations'] r = 20
for world in worlds: half_white = (255, 255, 255, 120)
area_bg = ( white = (255, 255, 255)
Image.open(TEXT_PATH / 'area_bg') black = (2, 2, 2)
.resize((216, 216))
.convert('RGBA')
)
icon = await get_image(world['icon'], ICON_PATH)
# percent = world['exploration_percentage']
area_bg.paste(icon, (27, 27), icon) worlds = raw_data['world_explorations']
image = crop_center_img(Image.open(TEXT_PATH / 'bg.jpg'), 1400, 950)
for index, world in enumerate(worlds):
area_bg = Image.open(TEXT_PATH / 'area_bg.png')
area_bg = await shift_image_hue(area_bg, 30)
icon = await get_image(world['icon'], ICON_PATH)
icon = icon.resize((150, 150)).convert('RGBA')
percent = world['exploration_percentage']
name = world['name']
if '·' in name:
name = name.split('·')[-1]
rank = f'等阶{world["level"]}'
completion = f'探索完成度: {percent / 10}%'
area_bg.paste(icon, (75, 36), icon)
area_draw = ImageDraw.Draw(area_bg)
# 标题
area_draw.text((150, 216), name, white, gs_font_32, 'mm')
# 等阶
area_draw.rounded_rectangle((98, 240, 201, 270), r, (137, 14, 14))
area_draw.text((150, 255), rank, white, gs_font_24, 'mm')
# 进度条
lenth = percent * 182 / 1000
area_draw.rounded_rectangle((59, 283, 241, 295), r, half_white)
area_draw.rounded_rectangle((59, 283, 59 + lenth, 295), r, white)
area_draw.text((150, 320), completion, white, gs_font_20, 'mm')
# 副等阶,如果有的话
if world['offerings']:
odata = world['offerings'][0]
oicon = await get_image(odata['icon'], ICON_PATH)
oicon = oicon.resize((38, 38)).convert('RGBA')
orank = f"等阶{odata['level']}"
area_draw.rounded_rectangle((59, 340, 241, 387), r, half_white)
area_bg.paste(oicon, (63, 343), oicon)
area_draw.text((107, 352), odata['name'], black, gs_font_20, 'lm')
area_draw.rounded_rectangle((107, 364, 173, 384), r, (137, 14, 14))
area_draw.text((140, 374), orank, white, gs_font_15, 'mm')
image.paste(
area_bg,
(100 + 240 * (index % 5), 25 + 450 * (index // 5)),
area_bg,
)
return await convert_img(image)

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -8,6 +8,7 @@ from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.logger import logger from gsuid_core.logger import logger
from gsuid_core.message_models import Button
from gsuid_core.utils.error_reply import UID_HINT from gsuid_core.utils.error_reply import UID_HINT
from .to_data import switch_api from .to_data import switch_api
@ -50,7 +51,14 @@ async def sned_rank_pic(bot: Bot, ev: Event):
if uid is None: if uid is None:
return await bot.send(UID_HINT) return await bot.send(UID_HINT)
logger.info(f'[排名列表]uid: {uid}') logger.info(f'[排名列表]uid: {uid}')
await bot.send(await draw_rank_img(ev.user_id, uid)) im = await draw_rank_img(ev.user_id, uid)
await bot.send_option(
im,
[
Button('♾️角色排名公子', '角色排名公子'),
Button('♾️圣遗物双爆排名', '圣遗物排名双爆'),
],
)
@sv_akasha.on_prefix('角色排名') @sv_akasha.on_prefix('角色排名')
@ -68,7 +76,16 @@ async def sned_arti_rank_pic(bot: Bot, ev: Event):
# 获取排序名 # 获取排序名
msg = ''.join(re.findall('[\u4e00-\u9fa5 ]', ev.text)) msg = ''.join(re.findall('[\u4e00-\u9fa5 ]', ev.text))
logger.info(f'[圣遗物排名]排序: {msg}') logger.info(f'[圣遗物排名]排序: {msg}')
await bot.send(await draw_arti_rank_img(msg)) im = await draw_arti_rank_img(msg)
await bot.send_option(
im,
[
Button('♾️双爆排名', '圣遗物排名双爆'),
Button('♾️暴击率排名', '圣遗物排名暴击率'),
Button('♾️元素精通排名', '圣遗物排名元素精通'),
Button('♾️暴击伤害排名', '圣遗物排名暴击伤害'),
],
)
@sv_enka_admin.on_fullmatch('刷新全部圣遗物仓库') @sv_enka_admin.on_fullmatch('刷新全部圣遗物仓库')
@ -108,7 +125,16 @@ async def sned_aritifacts_list(bot: Bot, ev: Event):
else: else:
num = 1 num = 1
await bot.send(await draw_lib(ev.user_id, uid, num)) im = await draw_lib(ev.user_id, uid, num)
await bot.send_option(
im,
[
Button('♾️双爆排名', '圣遗物排名双爆'),
Button('♾️暴击率排名', '圣遗物排名暴击率'),
Button('♾️元素精通排名', '圣遗物排名元素精通'),
Button('♾️暴击伤害排名', '圣遗物排名暴击伤害'),
],
)
@sv_get_original_pic.on_fullmatch(('原图')) @sv_get_original_pic.on_fullmatch(('原图'))
@ -128,7 +154,8 @@ async def send_change_api_info(bot: Bot, ev: Event):
@sv_get_enka.on_prefix('查询') @sv_get_enka.on_prefix('查询')
async def send_char_info(bot: Bot, ev: Event): async def send_char_info(bot: Bot, ev: Event):
im = await _get_char_info(bot, ev, ev.text) name = ev.text.strip()
im = await _get_char_info(bot, ev, name)
if isinstance(im, str): if isinstance(im, str):
await bot.send(im) await bot.send(im)
elif isinstance(im, Tuple): elif isinstance(im, Tuple):
@ -136,7 +163,15 @@ async def send_char_info(bot: Bot, ev: Event):
img = await convert_img(im[0]) img = await convert_img(im[0])
else: else:
img = im[0] img = im[0]
await bot.send(img) await bot.send_option(
img,
[
Button('🔄更换武器', f'查询{name}'),
Button('⏫提高命座', f'查询六命{name}'),
Button('*️⃣保存面板', f'保存面板{name}'),
Button('🔀对比面板', f'对比面板 {name} '),
],
)
if im[1]: if im[1]:
with open(TEMP_PATH / f'{ev.msg_id}.jpg', 'wb') as f: with open(TEMP_PATH / f'{ev.msg_id}.jpg', 'wb') as f:
f.write(im[1]) f.write(im[1])
@ -162,8 +197,10 @@ async def _get_char_info(bot: Bot, ev: Event, text: str):
return im return im
@sv_get_enka.on_prefix('对比面板') @sv_get_enka.on_command('对比面板')
async def contrast_char_info(bot: Bot, ev: Event): async def contrast_char_info(bot: Bot, ev: Event):
if not ev.text.strip():
return await bot.send('参考格式: 对比面板 公子 公子换可莉圣遗物')
contrast_list = ev.text.strip().split(' ') contrast_list = ev.text.strip().split(' ')
if len(contrast_list) <= 1: if len(contrast_list) <= 1:
return await bot.send('输入格式错误...参考格式: 对比面板 公子 公子换可莉圣遗物') return await bot.send('输入格式错误...参考格式: 对比面板 公子 公子换可莉圣遗物')
@ -194,8 +231,10 @@ async def contrast_char_info(bot: Bot, ev: Event):
await bot.send(await convert_img(base_img)) await bot.send(await convert_img(base_img))
@sv_get_enka.on_prefix('保存面板') @sv_get_enka.on_command('保存面板')
async def save_char_info(bot: Bot, ev: Event): async def save_char_info(bot: Bot, ev: Event):
if not ev.text.strip():
return await bot.send('后面需要跟自定义的保存名字\n例如:保存面板公子为核爆公子')
save_list = ev.text.strip().split('') save_list = ev.text.strip().split('')
if len(save_list) <= 1: if len(save_list) <= 1:
return await bot.send('输入格式错误...参考格式: 保存面板公子为核爆公子') return await bot.send('输入格式错误...参考格式: 保存面板公子为核爆公子')
@ -241,10 +280,16 @@ async def save_char_info(bot: Bot, ev: Event):
path = SELF_PATH / f'{save_name}.json' path = SELF_PATH / f'{save_name}.json'
async with aiofiles.open(path, 'wb') as file: async with aiofiles.open(path, 'wb') as file:
await file.write(json.dumps(char_data).encode('utf-8')) await file.write(json.dumps(char_data).encode('utf-8'))
return await bot.send(f'保存成功!你可以使用[查询{save_name}]调用该面板!') return await bot.send_option(
f'保存成功!你可以使用[查询{save_name}]调用该面板!',
[
Button(f'✅查询{save_name}', f'查询{save_name}'),
Button('💖刷新面板', '刷新面板'),
],
)
@sv_get_enka.on_command('强制刷新') @sv_get_enka.on_command(('强制刷新', '刷新面板'))
async def send_card_info(bot: Bot, ev: Event): async def send_card_info(bot: Bot, ev: Event):
uid = await get_uid(bot, ev) uid = await get_uid(bot, ev)
if uid is None: if uid is None:
@ -254,7 +299,13 @@ async def send_card_info(bot: Bot, ev: Event):
logger.info(f'UID{uid}获取角色数据成功!') logger.info(f'UID{uid}获取角色数据成功!')
if isinstance(im, Tuple): if isinstance(im, Tuple):
await bot.send_option(im[0], [f'查询{i["avatarName"]}' for i in im[1]]) buttons = [
Button(f'✅查询{i["avatarName"]}', f'查询{i["avatarName"]}')
for i in im[1]
]
buttons.append(Button('📦圣遗物仓库', '圣遗物仓库'))
buttons.append(Button('💖排名列表', '排名列表'))
await bot.send_option(im[0], buttons)
else: else:
await bot.send(im) await bot.send(im)

View File

@ -3,6 +3,7 @@ from pathlib import Path
from gsuid_core.sv import SV from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.message_models import Button
from ..version import Genshin_version from ..version import Genshin_version
from ..utils.image.convert import convert_img from ..utils.image.convert import convert_img
@ -28,7 +29,9 @@ async def send_primogems_data(bot: Bot, ev: Event):
primogems_img = PRIMOGEMS_DATA_PATH / img primogems_img = PRIMOGEMS_DATA_PATH / img
await bot.logger.info('[图片][版本规划]访问图片: {}'.format(img)) await bot.logger.info('[图片][版本规划]访问图片: {}'.format(img))
primogems_img = await convert_img(primogems_img) primogems_img = await convert_img(primogems_img)
await bot.send(primogems_img) a = Button('📄版本规划4.3', '版本规划4.3')
b = Button('🔔今日材料', '今日材料')
await bot.send_option(primogems_img, [a, b])
@sv_etc_img.on_fullmatch(('伤害乘区', '血量表', '抗性表', '血量排行')) @sv_etc_img.on_fullmatch(('伤害乘区', '血量表', '抗性表', '血量排行'))
@ -36,6 +39,10 @@ async def send_img_data(bot: Bot, ev: Event):
await bot.logger.info('开始执行[图片][杂图]') await bot.logger.info('开始执行[图片][杂图]')
img = IMG_PATH / f'{ev.command}.jpg' img = IMG_PATH / f'{ev.command}.jpg'
if img.exists(): if img.exists():
await bot.send(await convert_img(img)) a = Button('👾怪物血量表', '血量表')
b = Button('👾怪物抗性表', '抗性表')
c = Button('👾怪物血量排行', '血量排行')
d = Button('🤖伤害乘区', '伤害乘区')
await bot.send_option(await convert_img(img), [a, b, c, d])
else: else:
return return

View File

@ -2,6 +2,7 @@ from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.aps import scheduler from gsuid_core.aps import scheduler
from gsuid_core.message_models import Button
from ..utils.image.convert import convert_img from ..utils.image.convert import convert_img
from .draw_event_img import get_event_img, get_all_event_img from .draw_event_img import get_event_img, get_all_event_img
@ -17,10 +18,14 @@ async def draw_event():
@sv_event_list.on_fullmatch('活动列表') @sv_event_list.on_fullmatch('活动列表')
async def send_events(bot: Bot, ev: Event): async def send_events(bot: Bot, ev: Event):
img = await get_event_img('EVENT') img = await get_event_img('EVENT')
await bot.send(await convert_img(img)) a = Button('📢原神公告列表', '原神公告')
b = Button('💞卡池列表', '卡池列表')
await bot.send_option(await convert_img(img), [a, b])
@sv_event_list.on_fullmatch('卡池列表') @sv_event_list.on_fullmatch('卡池列表')
async def send_gachas(bot: Bot, ev: Event): async def send_gachas(bot: Bot, ev: Event):
img = await get_event_img('GACHA') img = await get_event_img('GACHA')
await bot.send(await convert_img(img)) a = Button('📢原神公告列表', '原神公告')
b = Button('💝活动列表', '活动列表')
await bot.send_option(await convert_img(img), [a, b])

View File

@ -1,6 +1,7 @@
from gsuid_core.sv import SV from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.message_models import Button
from gsuid_core.segment import MessageSegment from gsuid_core.segment import MessageSegment
from gsuid_core.utils.error_reply import UID_HINT from gsuid_core.utils.error_reply import UID_HINT
from gsuid_core.utils.database.models import GsBind from gsuid_core.utils.database.models import GsBind
@ -45,7 +46,10 @@ async def send_gacha_log_card_info(bot: Bot, ev: Event):
if uid is None: if uid is None:
return await bot.send(UID_HINT) return await bot.send(UID_HINT)
im = await draw_gachalogs_img(uid, user_id) im = await draw_gachalogs_img(uid, user_id)
await bot.send(im) a = Button('🔁刷新抽卡记录', '刷新抽卡记录')
b = Button('🔜导出抽卡记录至提瓦特小助手', '导出抽卡记录到小助手')
c = Button('🔙从提瓦特小助手导入抽卡记录', '从小助手导入抽卡记录')
await bot.send_option(im, [[a], [b], [c]])
@sv_refresh_gacha_log.on_fullmatch(('刷新抽卡记录', '强制刷新抽卡记录')) @sv_refresh_gacha_log.on_fullmatch(('刷新抽卡记录', '强制刷新抽卡记录'))
@ -60,7 +64,7 @@ async def send_refresh_gacha_info(bot: Bot, ev: Event):
is_force = True is_force = True
await bot.send(f'UID{uid}开始执行[刷新抽卡记录],需要一定时间...请勿重复触发!') await bot.send(f'UID{uid}开始执行[刷新抽卡记录],需要一定时间...请勿重复触发!')
im = await save_gachalogs(uid, None, is_force) im = await save_gachalogs(uid, None, is_force)
await bot.send(im) await bot.send_option(im, [Button('🃏抽卡记录', '抽卡记录')])
@sv_export_gacha_log.on_fullmatch(('导出抽卡记录')) @sv_export_gacha_log.on_fullmatch(('导出抽卡记录'))

View File

@ -1,6 +1,7 @@
from gsuid_core.sv import SV from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.message_models import Button
from gsuid_core.utils.error_reply import UID_HINT from gsuid_core.utils.error_reply import UID_HINT
from ..utils.convert import get_uid from ..utils.convert import get_uid
@ -10,7 +11,7 @@ from .draw_gcginfo import draw_gcg_info
sv_gcg = SV('查询七圣') sv_gcg = SV('查询七圣')
@sv_gcg.on_command(('七圣召唤', 'qszh')) @sv_gcg.on_command(('七圣召唤', 'qszh', '七圣数据总览'))
async def send_gcg_pic(bot: Bot, ev: Event): async def send_gcg_pic(bot: Bot, ev: Event):
uid = await get_uid(bot, ev) uid = await get_uid(bot, ev)
if uid is None: if uid is None:
@ -18,7 +19,7 @@ async def send_gcg_pic(bot: Bot, ev: Event):
await bot.logger.info('[七圣召唤]uid: {}'.format(uid)) await bot.logger.info('[七圣召唤]uid: {}'.format(uid))
im = await draw_gcg_info(uid) im = await draw_gcg_info(uid)
await bot.send(im) await bot.send_option(im, [Button('✅我的卡组', '我的卡组')])
@sv_gcg.on_command(('我的卡组', '我的牌组')) @sv_gcg.on_command(('我的卡组', '我的牌组'))
@ -34,4 +35,4 @@ async def send_deck_pic(bot: Bot, ev: Event):
else: else:
return bot.send('请输入正确的序号, 例如我的卡组1...') return bot.send('请输入正确的序号, 例如我的卡组1...')
im = await draw_deck_img(ev.user_id, uid, deck_id) im = await draw_deck_img(ev.user_id, uid, deck_id)
await bot.send(im) await bot.send_option(im, [Button('✅七圣数据总览', '七圣召唤')])

View File

@ -4,6 +4,7 @@ from typing import List
from gsuid_core.sv import SV from gsuid_core.sv import SV
from gsuid_core.bot import Bot from gsuid_core.bot import Bot
from gsuid_core.models import Event from gsuid_core.models import Event
from gsuid_core.message_models import Button
from gsuid_core.segment import MessageSegment from gsuid_core.segment import MessageSegment
from .get_guide import get_gs_guide from .get_guide import get_gs_guide
@ -25,7 +26,7 @@ async def send_guide_pic(bot: Bot, ev: Event):
if im: if im:
await bot.logger.info('获得{}攻略成功!'.format(ev.text)) await bot.logger.info('获得{}攻略成功!'.format(ev.text))
await bot.send(im) await bot.send_option(im, [Button(f'🎴参考面板{ev.text}', '参考面板{ev.text}')])
else: else:
await bot.logger.warning('未找到{}攻略图片'.format(ev.text)) await bot.logger.warning('未找到{}攻略图片'.format(ev.text))
@ -40,7 +41,7 @@ async def send_bluekun_pic(bot: Bot, ev: Event):
if img.exists(): if img.exists():
img = await convert_img(img) img = await convert_img(img)
await bot.logger.info('获得{}参考面板图片成功!'.format(name)) await bot.logger.info('获得{}参考面板图片成功!'.format(name))
await bot.send(img) await bot.send_option(img, [Button(f'🎴{name}攻略', f'{name}攻略')])
else: else:
await bot.logger.warning('未找到{}参考面板图片'.format(name)) await bot.logger.warning('未找到{}参考面板图片'.format(name))

View File

@ -16,6 +16,12 @@ from ..utils.get_assets import get_assets_from_ambr
from ..utils.map.name_covert import name_to_avatar_id from ..utils.map.name_covert import name_to_avatar_id
from ..utils.image.convert import str_lenth, convert_img from ..utils.image.convert import str_lenth, convert_img
from ..utils.resource.RESOURCE_PATH import CHAR_PATH, WIKI_COST_CHAR_PATH from ..utils.resource.RESOURCE_PATH import CHAR_PATH, WIKI_COST_CHAR_PATH
from ..utils.image.image_tools import (
get_star_png,
get_simple_bg,
get_unknown_png,
draw_pic_with_ring,
)
from ..utils.fonts.genshin_fonts import ( from ..utils.fonts.genshin_fonts import (
gs_font_24, gs_font_24,
gs_font_26, gs_font_26,
@ -23,12 +29,6 @@ from ..utils.fonts.genshin_fonts import (
gs_font_36, gs_font_36,
gs_font_44, gs_font_44,
) )
from ..utils.image.image_tools import (
get_star_png,
get_simple_bg,
get_unknown_png,
draw_pic_with_ring,
)
async def get_char_cost_wiki_img(name: str) -> Union[str, bytes]: async def get_char_cost_wiki_img(name: str) -> Union[str, bytes]:
@ -93,6 +93,7 @@ async def draw_single_cost(title: str, data: Dict) -> Tuple[Image.Image, str]:
y = 165 * (index // 5) y = 165 * (index // 5)
tent_x = 34 tent_x = 34
tent_y = 23 tent_y = 23
cost_pic = cost_pic.convert('RGBA')
img.paste(cost_pic, (67 + tent_x + t, 61 + tent_y + y), cost_pic) img.paste(cost_pic, (67 + tent_x + t, 61 + tent_y + y), cost_pic)
val = str(data[cost_name]) val = str(data[cost_name])
img_draw.text( img_draw.text(

View File

@ -31,6 +31,24 @@ else:
bg_path = NM_BG_PATH bg_path = NM_BG_PATH
async def shift_image_hue(img: Image.Image, angle: float = 30) -> Image.Image:
alpha = img.getchannel('A')
img = img.convert('HSV')
pixels = img.load()
hue_shift = angle
for y in range(img.height):
for x in range(img.width):
h, s, v = pixels[x, y]
h = (h + hue_shift) % 360
pixels[x, y] = (h, s, v)
img = img.convert('RGBA')
img.putalpha(alpha)
return img
async def _get(url: str): async def _get(url: str):
async with httpx.AsyncClient(timeout=None) as client: async with httpx.AsyncClient(timeout=None) as client:
resp = await client.get(url=url) resp = await client.get(url=url)
@ -38,9 +56,9 @@ async def _get(url: str):
async def get_pic(url, size: Optional[Tuple[int, int]] = None) -> Image.Image: async def get_pic(url, size: Optional[Tuple[int, int]] = None) -> Image.Image:
""" '''
从网络获取图片, 格式化为RGBA格式的指定尺寸 从网络获取图片, 格式化为RGBA格式的指定尺寸
""" '''
async with httpx.AsyncClient(timeout=None) as client: async with httpx.AsyncClient(timeout=None) as client:
resp = await client.get(url=url) resp = await client.get(url=url)
if resp.status_code != 200: if resp.status_code != 200:
@ -48,7 +66,7 @@ async def get_pic(url, size: Optional[Tuple[int, int]] = None) -> Image.Image:
size = (960, 600) size = (960, 600)
return Image.new('RGBA', size) return Image.new('RGBA', size)
pic = Image.open(BytesIO(resp.read())) pic = Image.open(BytesIO(resp.read()))
pic = pic.convert("RGBA") pic = pic.convert('RGBA')
if size is not None: if size is not None:
pic = pic.resize(size, Image.Resampling.LANCZOS) pic = pic.resize(size, Image.Resampling.LANCZOS)
return pic return pic
@ -74,11 +92,11 @@ def draw_text_by_line(
center=False, center=False,
line_space: Optional[float] = None, line_space: Optional[float] = None,
): ):
""" '''
在图片上写长段文字, 自动换行 在图片上写长段文字, 自动换行
max_length单行最大长度, 单位像素 max_length单行最大长度, 单位像素
line_space 行间距, 单位像素, 默认是字体高度的0.3 line_space 行间距, 单位像素, 默认是字体高度的0.3
""" '''
x, y = pos x, y = pos
_, h = get_size(font, 'X') _, h = get_size(font, 'X')
if line_space is None: if line_space is None:
@ -86,7 +104,7 @@ def draw_text_by_line(
else: else:
y_add = math.ceil(h + line_space) y_add = math.ceil(h + line_space)
draw = ImageDraw.Draw(img) draw = ImageDraw.Draw(img)
row = "" # 存储本行文字 row = '' # 存储本行文字
length = 0 # 记录本行长度 length = 0 # 记录本行长度
for character in text: for character in text:
# 获取当前字符的宽度 # 获取当前字符的宽度
@ -100,10 +118,10 @@ def draw_text_by_line(
fw, _ = get_size(font, row) fw, _ = get_size(font, row)
x = math.ceil((img.size[0] - fw) / 2) x = math.ceil((img.size[0] - fw) / 2)
draw.text((x, y), row, font=font, fill=fill) draw.text((x, y), row, font=font, fill=fill)
row = "" row = ''
length = 0 length = 0
y += y_add y += y_add
if row != "": if row != '':
if center: if center:
fw, _ = get_size(font, row) fw, _ = get_size(font, row)
x = math.ceil((img.size[0] - fw) / 2) x = math.ceil((img.size[0] - fw) / 2)
@ -111,32 +129,32 @@ def draw_text_by_line(
def easy_paste( def easy_paste(
im: Image.Image, im_paste: Image.Image, pos=(0, 0), direction="lt" im: Image.Image, im_paste: Image.Image, pos=(0, 0), direction='lt'
): ):
""" '''
inplace method inplace method
快速粘贴, 自动获取被粘贴图像的坐标 快速粘贴, 自动获取被粘贴图像的坐标
pos应当是粘贴点坐标direction指定粘贴点方位例如lt为左上 pos应当是粘贴点坐标direction指定粘贴点方位例如lt为左上
""" '''
x, y = pos x, y = pos
size_x, size_y = im_paste.size size_x, size_y = im_paste.size
if "d" in direction: if 'd' in direction:
y = y - size_y y = y - size_y
if "r" in direction: if 'r' in direction:
x = x - size_x x = x - size_x
if "c" in direction: if 'c' in direction:
x = x - int(0.5 * size_x) x = x - int(0.5 * size_x)
y = y - int(0.5 * size_y) y = y - int(0.5 * size_y)
im.paste(im_paste, (x, y, x + size_x, y + size_y), im_paste) im.paste(im_paste, (x, y, x + size_x, y + size_y), im_paste)
def easy_alpha_composite( def easy_alpha_composite(
im: Image.Image, im_paste: Image.Image, pos=(0, 0), direction="lt" im: Image.Image, im_paste: Image.Image, pos=(0, 0), direction='lt'
) -> Image.Image: ) -> Image.Image:
''' '''
透明图像快速粘贴 透明图像快速粘贴
''' '''
base = Image.new("RGBA", im.size) base = Image.new('RGBA', im.size)
easy_paste(base, im_paste, pos, direction) easy_paste(base, im_paste, pos, direction)
base = Image.alpha_composite(im, base) base = Image.alpha_composite(im, base)
return base return base
@ -358,7 +376,7 @@ class CustomizeImage:
@staticmethod @staticmethod
def get_dominant_color(pil_img: Image.Image) -> Tuple[int, int, int]: def get_dominant_color(pil_img: Image.Image) -> Tuple[int, int, int]:
img = pil_img.copy() img = pil_img.copy()
img = img.convert("RGBA") img = img.convert('RGBA')
img = img.resize((1, 1), resample=0) img = img.resize((1, 1), resample=0)
dominant_color = img.getpixel((0, 0)) dominant_color = img.getpixel((0, 0))
return dominant_color return dominant_color