mirror of
https://github.com/KimigaiiWuyi/GenshinUID.git
synced 2025-05-07 20:45:49 +08:00
✨ 新增今日素材
(#292)
This commit is contained in:
parent
569e08b9a1
commit
ac7d036e19
22
GenshinUID/genshinuid_dailycost/__init__.py
Normal file
22
GenshinUID/genshinuid_dailycost/__init__.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
from gsuid_core.sv import SV
|
||||||
|
from gsuid_core.bot import Bot
|
||||||
|
from gsuid_core.models import Event
|
||||||
|
from gsuid_core.aps import scheduler
|
||||||
|
from gsuid_core.logger import logger
|
||||||
|
|
||||||
|
from .draw_daily_cost import draw_daily_cost_img
|
||||||
|
|
||||||
|
sv_daily_cost = SV('查询每日材料')
|
||||||
|
|
||||||
|
|
||||||
|
@sv_daily_cost.on_command(('每日材料', '今日材料', '每日素材'), block=True)
|
||||||
|
async def send_collection_info(bot: Bot, ev: Event):
|
||||||
|
logger.info('开始执行[每日材料]')
|
||||||
|
im = await draw_daily_cost_img()
|
||||||
|
await bot.send(im)
|
||||||
|
|
||||||
|
|
||||||
|
# 每日四点出头执行刷新材料图
|
||||||
|
@scheduler.scheduled_job('cron', hour=4, minute=1)
|
||||||
|
async def refresh_daily_cost():
|
||||||
|
await draw_daily_cost_img()
|
151
GenshinUID/genshinuid_dailycost/draw_daily_cost.py
Normal file
151
GenshinUID/genshinuid_dailycost/draw_daily_cost.py
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
from gsuid_core.utils.image.convert import convert_img
|
||||||
|
from gsuid_core.utils.api.ambr.request import get_ambr_icon
|
||||||
|
|
||||||
|
from .get_daily_data import generate_daily_data
|
||||||
|
from ..utils.map.name_covert import name_to_avatar_id
|
||||||
|
from ..utils.image.image_tools import get_color_bg, get_weapon_pic
|
||||||
|
from ..utils.fonts.genshin_fonts import gs_font_26, gs_font_36, gs_font_44
|
||||||
|
from ..utils.resource.RESOURCE_PATH import (
|
||||||
|
CHAR_PATH,
|
||||||
|
ICON_PATH,
|
||||||
|
TEMP_PATH,
|
||||||
|
WEAPON_PATH,
|
||||||
|
)
|
||||||
|
|
||||||
|
TEXT_PATH = Path(__file__).parent / 'texture2d'
|
||||||
|
|
||||||
|
|
||||||
|
async def draw_daily_cost_img() -> Union[str, bytes]:
|
||||||
|
path = TEMP_PATH / 'daily_cost.jpg'
|
||||||
|
if path.exists():
|
||||||
|
return await convert_img(Image.open(path))
|
||||||
|
|
||||||
|
data = await generate_daily_data()
|
||||||
|
if data is None:
|
||||||
|
return '获取信息错误...'
|
||||||
|
elif data == {}:
|
||||||
|
return '今天是周日, 所有材料都能获得噢!'
|
||||||
|
|
||||||
|
w, h = 950, 630
|
||||||
|
for domain in data:
|
||||||
|
h += 110 + ((len(data[domain]) - 2) // 8 + 1) * 110
|
||||||
|
|
||||||
|
img = await get_color_bg(w, h)
|
||||||
|
|
||||||
|
weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
|
||||||
|
|
||||||
|
timestamp = time.time()
|
||||||
|
timestamp -= 14400
|
||||||
|
_t = time.localtime(timestamp)
|
||||||
|
|
||||||
|
title = Image.open(TEXT_PATH / 'title.png')
|
||||||
|
title_draw = ImageDraw.Draw(title)
|
||||||
|
title_draw.text(
|
||||||
|
(475, 474),
|
||||||
|
f'今天是{time.strftime(weekdays[_t.tm_wday], _t)}哦!',
|
||||||
|
'black',
|
||||||
|
gs_font_36,
|
||||||
|
'mm',
|
||||||
|
)
|
||||||
|
title_draw.text((475, 531), '每日材料', 'black', gs_font_36, 'mm')
|
||||||
|
|
||||||
|
img.paste(title, (0, 0), title)
|
||||||
|
|
||||||
|
y = 600
|
||||||
|
for domain in data:
|
||||||
|
icon_id = data[domain][0]
|
||||||
|
icon = await get_ambr_icon('UI', icon_id, ICON_PATH, 'ItemIcon')
|
||||||
|
|
||||||
|
icon = icon.resize((77, 77))
|
||||||
|
bar = Image.open(TEXT_PATH / 'bar.png')
|
||||||
|
bar_draw = ImageDraw.Draw(bar)
|
||||||
|
bar.paste(icon, (43, 10), icon)
|
||||||
|
|
||||||
|
domain1, domain2 = domain.split(':')
|
||||||
|
|
||||||
|
bar_draw.text((142, 50), domain2, 'black', gs_font_44, 'lm')
|
||||||
|
bar_draw.text((900, 50), domain1, 'black', gs_font_26, 'rm')
|
||||||
|
|
||||||
|
img.paste(bar, (0, y), bar)
|
||||||
|
|
||||||
|
for index, item in enumerate(data[domain]):
|
||||||
|
if isinstance(item, int):
|
||||||
|
continue
|
||||||
|
|
||||||
|
rank: int = item['rank']
|
||||||
|
|
||||||
|
if '炼武' in domain:
|
||||||
|
item_path = WEAPON_PATH / f'{item["name"]}.png'
|
||||||
|
if not item_path.exists():
|
||||||
|
item = await get_ambr_icon(
|
||||||
|
'UI',
|
||||||
|
item['icon'].replace('UI_EquipIcon_', ''),
|
||||||
|
WEAPON_PATH,
|
||||||
|
'EquipIcon',
|
||||||
|
f'{item["name"]}.png',
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
item = Image.open(item_path)
|
||||||
|
else:
|
||||||
|
if 'name' in item:
|
||||||
|
avatar_id = await name_to_avatar_id(item['name'])
|
||||||
|
item_path = CHAR_PATH / f'{avatar_id}.png'
|
||||||
|
elif 'Boy' in item['icon']:
|
||||||
|
avatar_id = 10000005
|
||||||
|
else:
|
||||||
|
avatar_id = 10000007
|
||||||
|
|
||||||
|
item_path = CHAR_PATH / f'{avatar_id}.png'
|
||||||
|
|
||||||
|
if not item_path.exists():
|
||||||
|
item = await get_ambr_icon(
|
||||||
|
'UI',
|
||||||
|
item['icon'].replace('UI_AvatarIcon_', ''),
|
||||||
|
CHAR_PATH,
|
||||||
|
'AvatarIcon',
|
||||||
|
f'{avatar_id}.png',
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
item = Image.open(item_path)
|
||||||
|
|
||||||
|
if ((index - 1) % 8) == 0 and index != 0:
|
||||||
|
y += 110
|
||||||
|
|
||||||
|
item = item.resize((100, 100))
|
||||||
|
item_bg = await get_weapon_pic(rank)
|
||||||
|
item_bg = item_bg.resize((100, 100))
|
||||||
|
|
||||||
|
img.paste(
|
||||||
|
item_bg,
|
||||||
|
(36 + ((index - 1) % 8) * 110, y),
|
||||||
|
item_bg,
|
||||||
|
)
|
||||||
|
|
||||||
|
temp = Image.new('RGBA', (100, 100))
|
||||||
|
temp.paste(item, (0, 0), item_bg)
|
||||||
|
|
||||||
|
img.paste(
|
||||||
|
temp,
|
||||||
|
(36 + ((index - 1) % 8) * 110, y),
|
||||||
|
temp,
|
||||||
|
)
|
||||||
|
|
||||||
|
y += 110
|
||||||
|
|
||||||
|
# 最后生成图片
|
||||||
|
all_black = Image.new('RGBA', img.size, (255, 255, 255))
|
||||||
|
img = Image.alpha_composite(all_black, img)
|
||||||
|
|
||||||
|
img.save(
|
||||||
|
TEMP_PATH / 'daily_cost.jpg',
|
||||||
|
'JPEG',
|
||||||
|
quality=89,
|
||||||
|
subsampling=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
return await convert_img(img)
|
48
GenshinUID/genshinuid_dailycost/get_daily_data.py
Normal file
48
GenshinUID/genshinuid_dailycost/get_daily_data.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import time
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Dict, Literal, Optional
|
||||||
|
|
||||||
|
from gsuid_core.utils.api.ambr.request import (
|
||||||
|
get_all_upgrade,
|
||||||
|
get_ambr_daily_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _add_result(upgrades, type: Literal['weapon', 'avatar'], domain, result):
|
||||||
|
for _th in upgrades[type]:
|
||||||
|
for item in upgrades[type][_th]['items']:
|
||||||
|
if int(item) in domain['reward']:
|
||||||
|
if domain['name'] not in result:
|
||||||
|
result[domain['name']] = []
|
||||||
|
if domain['reward'][-1] not in result[domain['name']]:
|
||||||
|
result[domain['name']].append(domain['reward'][-1])
|
||||||
|
if upgrades[type][_th] not in result[domain['name']]:
|
||||||
|
result[domain['name']].append(upgrades[type][_th])
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
async def generate_daily_data() -> Optional[Dict]:
|
||||||
|
upgrades = await get_all_upgrade()
|
||||||
|
daily_data = await get_ambr_daily_data()
|
||||||
|
|
||||||
|
if upgrades is None or daily_data is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 获取当前日期并以4点为分界线
|
||||||
|
now = time.localtime()
|
||||||
|
now_str = time.strftime('%Y-%m-%d %H:%M:%S', now)
|
||||||
|
now_dt = datetime.strptime(now_str, '%Y-%m-%d %H:%M:%S')
|
||||||
|
new_dt = now_dt - timedelta(hours=4)
|
||||||
|
day = new_dt.strftime('%A').lower()
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
if day == 'sunday':
|
||||||
|
return result
|
||||||
|
|
||||||
|
for domain in daily_data[day]:
|
||||||
|
if '炼武' in domain['name']:
|
||||||
|
result = _add_result(upgrades, 'weapon', domain, result)
|
||||||
|
else:
|
||||||
|
result = _add_result(upgrades, 'avatar', domain, result)
|
||||||
|
return result
|
BIN
GenshinUID/genshinuid_dailycost/texture2d/bar.png
Normal file
BIN
GenshinUID/genshinuid_dailycost/texture2d/bar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
GenshinUID/genshinuid_dailycost/texture2d/title.png
Normal file
BIN
GenshinUID/genshinuid_dailycost/texture2d/title.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 107 KiB |
@ -64,7 +64,7 @@ def draw_text_by_line(
|
|||||||
line_space 行间距, 单位像素, 默认是字体高度的0.3倍
|
line_space 行间距, 单位像素, 默认是字体高度的0.3倍
|
||||||
"""
|
"""
|
||||||
x, y = pos
|
x, y = pos
|
||||||
_, h = font.getsize('X')
|
_, h = font.getsize('X') # type: ignore
|
||||||
if line_space is None:
|
if line_space is None:
|
||||||
y_add = math.ceil(1.3 * h)
|
y_add = math.ceil(1.3 * h)
|
||||||
else:
|
else:
|
||||||
@ -73,14 +73,15 @@ def draw_text_by_line(
|
|||||||
row = "" # 存储本行文字
|
row = "" # 存储本行文字
|
||||||
length = 0 # 记录本行长度
|
length = 0 # 记录本行长度
|
||||||
for character in text:
|
for character in text:
|
||||||
w, h = font.getsize(character) # 获取当前字符的宽度
|
# 获取当前字符的宽度
|
||||||
|
w, h = font.getsize(character) # type: ignore
|
||||||
if length + w * 2 <= max_length:
|
if length + w * 2 <= max_length:
|
||||||
row += character
|
row += character
|
||||||
length += w
|
length += w
|
||||||
else:
|
else:
|
||||||
row += character
|
row += character
|
||||||
if center:
|
if center:
|
||||||
font_size = font.getsize(row)
|
font_size = font.getsize(row) # type: ignore
|
||||||
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
||||||
draw.text((x, y), row, font=font, fill=fill)
|
draw.text((x, y), row, font=font, fill=fill)
|
||||||
row = ""
|
row = ""
|
||||||
@ -88,7 +89,7 @@ def draw_text_by_line(
|
|||||||
y += y_add
|
y += y_add
|
||||||
if row != "":
|
if row != "":
|
||||||
if center:
|
if center:
|
||||||
font_size = font.getsize(row)
|
font_size = font.getsize(row) # type: ignore
|
||||||
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
x = math.ceil((img.size[0] - font_size[0]) / 2)
|
||||||
draw.text((x, y), row, font=font, fill=fill)
|
draw.text((x, y), row, font=font, fill=fill)
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ from .download_url import PATH_MAP, download_file
|
|||||||
|
|
||||||
# MINIGG_FILE = 'http://file.microgg.cn/KimigaiiWuyi/resource/'
|
# MINIGG_FILE = 'http://file.microgg.cn/KimigaiiWuyi/resource/'
|
||||||
BASE_TAG = '[HKFRP]'
|
BASE_TAG = '[HKFRP]'
|
||||||
BASE_URL = 'http://hk-1.5gbps-2.lcf.icu:10200'
|
BASE_URL = 'http://jp-iij-1.lcf.icu:10200'
|
||||||
RESOURCE_FILE = f'{BASE_URL}/resource/'
|
RESOURCE_FILE = f'{BASE_URL}/resource/'
|
||||||
WIKI_FILE = f'{BASE_URL}/wiki/'
|
WIKI_FILE = f'{BASE_URL}/wiki/'
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user