修复网络IO堵塞导致图片丢失问题(fix #152)

This commit is contained in:
MingxuanGame 2022-03-30 13:07:12 +08:00
parent b80464a8ca
commit 4e326368a2
No known key found for this signature in database
GPG Key ID: 90C7EFA11DC3C2FF
21 changed files with 158 additions and 95 deletions

View File

@ -1,42 +1,44 @@
import asyncio,os,sys
import base64,re
import base64
import traceback
from aiocqhttp.exceptions import ActionFailed
from aiohttp import ClientConnectorError
from nonebot import get_bot, MessageSegment
from hoshino import Service
from hoshino.typing import CQEvent, HoshinoBot
from nonebot import get_bot, logger, MessageSegment
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
from mihoyo_libs.get_data import *
from mihoyo_libs.get_image import *
from mihoyo_libs.get_mihoyo_bbs_data import *
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
sv = Service('genshinuid')
hoshino_bot = get_bot()
FILE_PATH = os.path.join(os.path.join(os.path.dirname(__file__), 'mihoyo_libs'),'mihoyo_bbs')
FILE_PATH = os.path.join(os.path.join(os.path.dirname(__file__), 'mihoyo_libs'), 'mihoyo_bbs')
INDEX_PATH = os.path.join(FILE_PATH, 'index')
Texture_PATH = os.path.join(FILE_PATH, 'texture2d')
@sv.on_rex('[\u4e00-\u9fa5]+(用什么|能用啥|怎么养)')
async def send_char_adv(bot: HoshinoBot, ev: CQEvent):
try:
name = str(ev.message).strip().replace(" ","")[:-3]
name = str(ev.message).strip().replace(" ", "")[:-3]
im = await char_adv(name)
await bot.send(ev, im)
except Exception as e:
logger.exception("获取建议失败。")
@sv.on_rex('[\u4e00-\u9fa5]+(能给谁|给谁用|要给谁|谁能用)')
async def send_weapon_adv(bot: HoshinoBot, ev: CQEvent):
try:
name = str(ev.message).strip().replace(" ","")[:-3]
name = str(ev.message).strip().replace(" ", "")[:-3]
im = await weapon_adv(name)
await bot.send(ev, im)
except Exception as e:
logger.exception("获取建议失败。")
@sv.on_prefix('语音')
async def send_audio(bot: HoshinoBot, ev: CQEvent):
try:
@ -158,7 +160,7 @@ async def send_talents(bot: HoshinoBot, ev: CQEvent):
num = re.findall(r"[0-9]+", message)
if len(num) == 1:
im = await char_wiki(name, "talents", num[0])
if isinstance(im,list):
if isinstance(im, list):
await hoshino_bot.send_group_forward_msg(group_id=ev.group_id, messages=im)
return
else:
@ -240,6 +242,7 @@ async def clean_cache():
async def draw_event():
await draw_event_pic()
@sv.on_fullmatch('开始获取米游币')
async def send_mihoyo_coin(bot: HoshinoBot, ev: CQEvent):
await bot.send(ev, "开始操作……", at_sender=True)
@ -260,6 +263,7 @@ async def send_mihoyo_coin(bot: HoshinoBot, ev: CQEvent):
await bot.send(ev, "机器人发送消息失败:{}".format(e.info['wording']))
logger.exception("发送签到信息失败")
@sv.on_fullmatch('全部重签')
async def _(bot: HoshinoBot, ev: CQEvent):
try:
@ -273,6 +277,7 @@ async def _(bot: HoshinoBot, ev: CQEvent):
traceback.print_exc()
await bot.send(ev, "发生错误 {},请检查后台输出。".format(e))
@sv.on_fullmatch('全部重获取')
async def bbscoin_resign(bot: HoshinoBot, ev: CQEvent):
try:
@ -286,6 +291,7 @@ async def bbscoin_resign(bot: HoshinoBot, ev: CQEvent):
traceback.print_exc()
await bot.send(ev, "发生错误 {},请检查后台输出。".format(e))
# 每隔半小时检测树脂是否超过设定值
@sv.scheduled_job('cron', minute="*/30")
async def push():
@ -366,11 +372,13 @@ async def daily_sign():
conn.close()
return
# 每日零点五十进行米游币获取
@sv.scheduled_job('cron', hour='0', minute="50")
async def sign_at_night():
await daily_mihoyo_bbs_sign()
async def daily_mihoyo_bbs_sign():
conn = sqlite3.connect('ID_DATA.db')
c = conn.cursor()
@ -382,15 +390,16 @@ async def daily_mihoyo_bbs_sign():
logger.info("正在执行{}".format(row[0]))
if row[8]:
await asyncio.sleep(5 + random.randint(1, 3))
im = await mihoyo_coin(str(row[2]),str(row[8]))
im = await mihoyo_coin(str(row[2]), str(row[8]))
logger.info(im)
try:
await hoshino_bot.call_api(api='send_private_msg',
user_id=row[2], message=im)
user_id=row[2], message=im)
except Exception:
logger.exception(f"{im} Error")
logger.info("已结束。")
# 私聊事件
@hoshino_bot.on_message('private')
async def setting(ctx):
@ -441,19 +450,19 @@ async def setting(ctx):
uid = await select_db(userid, mode="uid")
im = await open_push(int(uid[0]), userid, "off", "StatusC")
await hoshino_bot.send_msg(self_id=sid, user_id=userid, group_id=gid,
message=im, at_sender=True)
message=im, at_sender=True)
except Exception:
await hoshino_bot.send_msg(self_id=sid, user_id=userid, group_id=gid,
message="未绑定uid信息", at_sender=True)
message="未绑定uid信息", at_sender=True)
elif "gs关闭自动米游币" in message:
try:
uid = await select_db(userid, mode="uid")
im = await open_push(int(uid[0]), userid, "on", "StatusC")
await hoshino_bot.send_msg(self_id=sid, user_id=userid, group_id=gid,
message=im, at_sender=True)
message=im, at_sender=True)
except Exception:
await hoshino_bot.send_msg(self_id=sid, user_id=userid, group_id=gid,
message="未绑定uid信息", at_sender=True)
message="未绑定uid信息", at_sender=True)
elif 'gs开启自动签到' in message:
try:
uid = await select_db(userid, mode="uid")
@ -481,6 +490,7 @@ async def setting(ctx):
await hoshino_bot.send_msg(self_id=sid, user_id=userid, group_id=gid, message="未找到uid绑定记录。")
logger.exception("关闭自动签到失败")
# 群聊开启 自动签到 和 推送树脂提醒 功能
@sv.on_prefix('gs开启')
async def open_switch_func(bot: HoshinoBot, ev: CQEvent):
@ -589,10 +599,10 @@ async def close_switch_func(bot: HoshinoBot, ev: CQEvent):
else:
return
except ActionFailed as e:
await bot.send("机器人发送消息失败:{}".format(e))
await bot.send(ev, "机器人发送消息失败:{}".format(e))
logger.exception("发送设置成功信息失败")
except Exception as e:
await bot.send("发生错误 {},请检查后台输出。".format(e))
await bot.send(ev, "发生错误 {},请检查后台输出。".format(e))
logger.exception("设置简洁签到报告失败")
except Exception as e:
await bot.send(ev, "发生错误 {},请检查后台输出。".format(e))
@ -670,7 +680,8 @@ async def send_daily_data(bot: HoshinoBot, ev: CQEvent):
await bot.send(ev, "机器人发送消息失败:{}".format(e))
logger.exception("发送当前状态信息失败")
#图片版信息
# 图片版信息
@sv.on_fullmatch('当前信息')
async def send_genshin_info(bot: HoshinoBot, ev: CQEvent):
try:
@ -678,7 +689,7 @@ async def send_genshin_info(bot: HoshinoBot, ev: CQEvent):
uid = await select_db(ev.sender['user_id'], mode="uid")
uid = uid[0]
image = re.search(r"\[CQ:image,file=(.*),url=(.*)]", message)
im = await draw_info_pic(uid,image)
im = await draw_info_pic(uid, image)
try:
await bot.send(ev, MessageSegment.image(im), at_sender=True)
except ActionFailed as e:
@ -894,6 +905,9 @@ async def get_info(bot, ev):
except TypeError:
await bot.send(ev, "获取失败可能是Cookies失效或者未打开米游社角色详情开关。")
logger.exception("数据获取失败Cookie失效/不公开信息)")
except ClientConnectorError:
await bot.send(ev, "获取失败:连接超时")
logger.exception("连接超时")
except Exception as e:
await bot.send(ev, "获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
logger.exception("数据获取失败(数据状态问题)")

View File

@ -10,6 +10,7 @@ import time
from shutil import copyfile
import requests
from aiohttp import ClientSession
from httpx import AsyncClient
from nonebot import logger
@ -726,28 +727,29 @@ def get_character(uid, character_ids, ck, server_id="cn_gf01"):
logger.info(e.with_traceback)
async def get_calculate_info(uid, char_id, ck, server_id="cn_gf01"):
async def get_calculate_info(client: ClientSession, uid, char_id, ck, name, server_id="cn_gf01"):
if uid[0] == '5':
server_id = "cn_qd01"
url = "https://api-takumi.mihoyo.com/event/e20200928calculate/v1/sync/avatar/detail"
async with AsyncClient() as client:
req = await client.get(
url=url,
headers={
'DS' : get_ds_token("uid={}&avatar_id={}&region={}".format(uid, char_id, server_id)),
'x-rpc-app_version': mhyVersion,
'User-Agent' : 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 ('
'KHTML, like Gecko) miHoYoBBS/2.11.1',
'x-rpc-client_type': '5',
'Referer' : 'https://webstatic.mihoyo.com/',
"Cookie" : ck},
params={
"avatar_id": char_id,
"uid" : uid,
"region" : server_id
}
)
data = json.loads(req.text)
req = await client.get(
url=url,
headers={
'DS': get_ds_token("uid={}&avatar_id={}&region={}".format(uid, char_id, server_id)),
'x-rpc-app_version': mhyVersion,
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 ('
'KHTML, like Gecko) miHoYoBBS/2.11.1',
'x-rpc-client_type': '5',
'Referer': 'https://webstatic.mihoyo.com/',
"Cookie": ck},
params={
"avatar_id": char_id,
"uid": uid,
"region": server_id
}
)
data = await req.json()
data.update({"name": name})
logger.debug(name + "=" + str(char_id) + "===" + str(data)) # DEBUG
return data

View File

@ -14,8 +14,9 @@ from wordcloud import WordCloud
from .get_data import *
STATUS = []
FILE_PATH = os.path.dirname(__file__)
FILE2_PATH = os.path.join(FILE_PATH, 'mihoyo_libs/mihoyo_bbs')
FILE2_PATH = os.path.join(FILE_PATH, 'mihoyo_bbs')
CHAR_PATH = os.path.join(FILE2_PATH, 'chars')
CHAR_DONE_PATH = os.path.join(FILE2_PATH, 'char_done')
CHAR_IMG_PATH = os.path.join(FILE2_PATH, 'char_img')
@ -27,7 +28,7 @@ WEAPON_PATH = os.path.join(FILE2_PATH, 'weapon')
BG_PATH = os.path.join(FILE2_PATH, 'bg')
class customize_image:
class CustomizeImage:
def __init__(self, image: Match, based_w: int, based_h: int) -> None:
self.bg_img = self.get_image(image, based_w, based_h)
@ -131,9 +132,9 @@ class customize_image:
green_color = color[1]
blue_color = color[2]
highlight_color = {"red" : red_color - 127 if red_color > 127 else 127,
highlight_color = {"red": red_color - 127 if red_color > 127 else 127,
"green": green_color - 127 if green_color > 127 else 127,
"blue" : blue_color - 127 if blue_color > 127 else 127}
"blue": blue_color - 127 if blue_color > 127 else 127}
max_color = max(highlight_color.values())
@ -192,7 +193,7 @@ def get_rel_pic(url: str):
f.write(get(url).content)
class get_cookies:
class GetCookies:
def __init__(self) -> None:
self.useable_cookies: Optional[str] = None
self.uid: Optional[str] = None
@ -545,7 +546,7 @@ async def draw_word_cloud(uid: str, image: Optional[Match] = None, mode: int = 2
async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"):
# 获取Cookies
data_def = get_cookies()
data_def = GetCookies()
retcode = await data_def.get_useable_cookies(uid, mode, date)
if not retcode:
return retcode
@ -565,7 +566,7 @@ async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"):
# 获取背景图片各项参数
based_w = 900
based_h = 660 + levels_num * 315
image_def = customize_image(image, based_w, based_h)
image_def = CustomizeImage(image, based_w, based_h)
bg_img = image_def.bg_img
bg_color = image_def.bg_color
text_color = image_def.text_color
@ -794,13 +795,13 @@ async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"):
abyss2.paste(abyss_star1, (730, 155), abyss_star1)
abyss2_text_draw = ImageDraw.Draw(abyss2)
abyss2_text_draw.text((87, 30), f"{j + 1}", text_color, genshin_font(21))
timeStamp1 = int(floors_data['levels'][j]['battles'][0]['timestamp'])
timeStamp2 = int(floors_data['levels'][j]['battles'][1]['timestamp'])
timeArray1 = time.localtime(timeStamp1)
timeArray2 = time.localtime(timeStamp2)
otherStyleTime1 = time.strftime("%Y--%m--%d %H:%M:%S", timeArray1)
otherStyleTime2 = time.strftime("%Y--%m--%d %H:%M:%S", timeArray2)
abyss2_text_draw.text((167, 33), f"{otherStyleTime1}/{otherStyleTime2}", text_color, genshin_font(19))
timestamp1 = int(floors_data['levels'][j]['battles'][0]['timestamp'])
timestamp2 = int(floors_data['levels'][j]['battles'][1]['timestamp'])
time_array1 = time.localtime(timestamp1)
time_array2 = time.localtime(timestamp2)
other_style_time1 = time.strftime("%Y--%m--%d %H:%M:%S", time_array1)
other_style_time2 = time.strftime("%Y--%m--%d %H:%M:%S", time_array2)
abyss2_text_draw.text((167, 33), f"{other_style_time1}/{other_style_time2}", text_color, genshin_font(19))
bg_img.paste(abyss2, (0, 605 + j * 315), abyss2)
bg_img.paste(abyss3, (0, len(floors_data["levels"]) * 315 + 610), abyss3)
@ -826,7 +827,7 @@ async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"):
async def draw_abyss_pic(uid: str, nickname: str, floor_num: int, image: Optional[Match] = None, mode: int = 2,
date: str = "1"):
# 获取Cookies
data_def = get_cookies()
data_def = GetCookies()
retcode = await data_def.get_useable_cookies(uid, mode, date)
if not retcode:
return retcode
@ -848,7 +849,7 @@ async def draw_abyss_pic(uid: str, nickname: str, floor_num: int, image: Optiona
# 获取背景图片各项参数
based_w = 900
based_h = 440 + levels_num * 340
image_def = customize_image(image, based_w, based_h)
image_def = CustomizeImage(image, based_w, based_h)
bg_img = image_def.bg_img
bg_color = image_def.bg_color
text_color = image_def.text_color
@ -952,13 +953,13 @@ async def draw_abyss_pic(uid: str, nickname: str, floor_num: int, image: Optiona
abyss2.paste(abyss_star1, (730, 155), abyss_star1)
abyss2_text_draw = ImageDraw.Draw(abyss2)
abyss2_text_draw.text((87, 30), f"{j + 1}", text_color, genshin_font(21))
timeStamp1 = int(based_data['levels'][j]['battles'][0]['timestamp'])
timeStamp2 = int(based_data['levels'][j]['battles'][1]['timestamp'])
timeArray1 = time.localtime(timeStamp1)
timeArray2 = time.localtime(timeStamp2)
otherStyleTime1 = time.strftime("%Y--%m--%d %H:%M:%S", timeArray1)
otherStyleTime2 = time.strftime("%Y--%m--%d %H:%M:%S", timeArray2)
abyss2_text_draw.text((167, 33), f"{otherStyleTime1}/{otherStyleTime2}", text_color, genshin_font(19))
timestamp1 = int(based_data['levels'][j]['battles'][0]['timestamp'])
timestamp2 = int(based_data['levels'][j]['battles'][1]['timestamp'])
time_array1 = time.localtime(timestamp1)
time_array2 = time.localtime(timestamp2)
other_style_time1 = time.strftime("%Y--%m--%d %H:%M:%S", time_array1)
other_style_time2 = time.strftime("%Y--%m--%d %H:%M:%S", time_array2)
abyss2_text_draw.text((167, 33), f"{other_style_time1}/{other_style_time2}", text_color, genshin_font(19))
bg_img.paste(abyss2, (0, 350 + j * 340), abyss2)
bg_img.paste(abyss3, (0, len(based_data['levels']) * 340 + 400), abyss3)
@ -979,9 +980,20 @@ async def draw_abyss_pic(uid: str, nickname: str, floor_num: int, image: Optiona
return resultmes
async def get_all_calculate_info(client: ClientSession, uid: str, char_id: list[str], ck: str, name: list):
tasks = []
for id_, name_ in zip(char_id, name):
tasks.append(get_calculate_info(client, uid, id_, ck, name_))
data = []
repos = await asyncio.wait(tasks)
for i in repos[0]:
data.append(i.result())
return data
async def draw_char_pic(img: Image, char_data: dict, index: int, bg_color: tuple[int, int, int],
text_color: tuple[int, int, int], bg_detail_color: tuple[int, int, int],
char_high_color: tuple[int, int, int], uid, use_cookies):
char_high_color: tuple[int, int, int], char_talent_data: dict):
char_mingzuo = 0
for k in char_data['constellations']:
if k['is_actived']:
@ -1006,8 +1018,7 @@ async def draw_char_pic(img: Image, char_data: dict, index: int, bg_color: tuple
char_3.putalpha(alpha)
"""
char_1_mask = Image.open(os.path.join(TEXT_PATH, "char_1_mask.png"))
char_talent_data = await get_calculate_info(uid, str(char_data["id"]), use_cookies)
STATUS.append(char_data['name'])
if not os.path.exists(os.path.join(WEAPON_PATH, str(char_data['weapon']['icon'].split('/')[-1]))):
get_weapon_pic(char_data['weapon']['icon'])
if not os.path.exists(os.path.join(CHAR_PATH, str(char_data['id']) + ".png")):
@ -1055,13 +1066,14 @@ async def draw_char_pic(img: Image, char_data: dict, index: int, bg_color: tuple
anchor="mm")
char_crop = (75 + 190 * (index % 4), 800 + 100 * (index // 4))
STATUS.remove(char_data['name'])
img.paste(char_0, char_crop, char_0)
async def draw_pic(uid: str, nickname: str, image: Optional[Match] = None, mode: int = 2,
role_level: Optional[int] = None):
# 获取Cookies
data_def = get_cookies()
data_def = GetCookies()
retcode = await data_def.get_useable_cookies(uid, mode)
if not retcode:
return retcode
@ -1089,7 +1101,7 @@ async def draw_pic(uid: str, nickname: str, image: Optional[Match] = None, mode:
# 获取背景图片各项参数
based_w = 900
based_h = 870 + char_hang * 100 if char_num > 8 else 890 + char_hang * 110
image_def = customize_image(image, based_w, based_h)
image_def = CustomizeImage(image, based_w, based_h)
bg_img = image_def.bg_img
bg_color = image_def.bg_color
text_color = image_def.text_color
@ -1154,34 +1166,46 @@ async def draw_pic(uid: str, nickname: str, image: Optional[Match] = None, mode:
text_draw.text((258, 625.4), str(raw_data['stats']['way_point_number']), text_color, genshin_font(24))
text_draw.text((258, 675.4), str(raw_data['stats']['domain_number']), text_color, genshin_font(24))
# 蒙德
text_draw.text((490, 370), str(raw_data['world_explorations'][4]['exploration_percentage'] / 10) + '%', text_color,
mondstadt = liyue = dragonspine = inazuma = offering = dict()
for i in raw_data['world_explorations']:
if i["name"] == "蒙德":
mondstadt = i
elif i["name"] == "璃月":
liyue = i
elif i["name"] == "龙脊雪山":
dragonspine = i
elif i["name"] == "稻妻":
inazuma = i
elif i["name"] == "渊下宫":
offering = i
text_draw.text((490, 370), str(mondstadt['exploration_percentage'] / 10) + '%', text_color,
genshin_font(22))
text_draw.text((490, 400), 'lv.' + str(raw_data['world_explorations'][4]['level']), text_color, genshin_font(22))
text_draw.text((490, 400), 'lv.' + str(mondstadt['level']), text_color, genshin_font(22))
text_draw.text((513, 430), str(raw_data['stats']['anemoculus_number']), text_color, genshin_font(22))
# 璃月
text_draw.text((490, 490), str(raw_data['world_explorations'][3]['exploration_percentage'] / 10) + '%', text_color,
text_draw.text((490, 490), str(liyue['exploration_percentage'] / 10) + '%', text_color,
genshin_font(22))
text_draw.text((490, 520), 'lv.' + str(raw_data['world_explorations'][3]['level']), text_color, genshin_font(22))
text_draw.text((490, 520), 'lv.' + str(liyue['level']), text_color, genshin_font(22))
text_draw.text((513, 550), str(raw_data['stats']['geoculus_number']), text_color, genshin_font(22))
# 雪山
text_draw.text((745, 373.5), str(raw_data['world_explorations'][2]['exploration_percentage'] / 10) + '%',
text_draw.text((745, 373.5), str(dragonspine['exploration_percentage'] / 10) + '%',
text_color,
genshin_font(22))
text_draw.text((745, 407.1), 'lv.' + str(raw_data['world_explorations'][2]['level']), text_color, genshin_font(22))
text_draw.text((745, 407.1), 'lv.' + str(dragonspine['level']), text_color, genshin_font(22))
# 稻妻
text_draw.text((490, 608), str(raw_data['world_explorations'][1]['exploration_percentage'] / 10) + '%', text_color,
text_draw.text((490, 608), str(inazuma['exploration_percentage'] / 10) + '%', text_color,
genshin_font(22))
text_draw.text((490, 635), 'lv.' + str(raw_data['world_explorations'][1]['level']), text_color, genshin_font(22))
text_draw.text((490, 662), 'lv.' + str(raw_data['world_explorations'][1]['offerings'][0]['level']), text_color,
text_draw.text((490, 635), 'lv.' + str(inazuma['level']), text_color, genshin_font(22))
text_draw.text((490, 662), 'lv.' + str(inazuma['offerings'][0]['level']), text_color,
genshin_font(22))
text_draw.text((513, 689), str(raw_data['stats']['electroculus_number']), text_color, genshin_font(22))
# 渊下宫
text_draw.text((745, 480), str(raw_data['world_explorations'][0]['exploration_percentage'] / 10) + '%', text_color,
text_draw.text((745, 480), str(offering['exploration_percentage'] / 10) + '%', text_color,
genshin_font(22))
# 家园
@ -1231,10 +1255,30 @@ async def draw_pic(uid: str, nickname: str, image: Optional[Match] = None, mode:
char_datas.sort(key=lambda x: (-x['rarity'], -x['level'], -x['fetter']))
if char_num > 8:
char_names = []
client = ClientSession()
for i in char_datas:
char_names.append(i['name'])
talent_data = await get_all_calculate_info(client, uid, char_ids,
use_cookies, char_names)
await client.close()
tasks = []
for index, i in enumerate(char_datas):
tasks.append(draw_char_pic(bg_img, i, index, char_color, text_color, bg_detail_color, char_high_color, uid,
use_cookies))
for j in talent_data:
if j["name"] == i['name']:
tasks.append(
draw_char_pic(
bg_img,
i,
index,
char_color,
text_color,
bg_detail_color,
char_high_color,
j
)
)
await asyncio.wait(tasks)
"""
char_mingzuo = 0
@ -1428,7 +1472,7 @@ async def draw_info_pic(uid: str, image: Optional[Match] = None) -> str:
return "%02d:%02d:%02d" % (h, m, s)
# 获取Cookies
data_def = get_cookies()
data_def = GetCookies()
retcode = await data_def.get_useable_cookies(uid)
if not retcode:
return retcode
@ -1443,7 +1487,7 @@ async def draw_info_pic(uid: str, image: Optional[Match] = None) -> str:
# 获取背景图片各项参数
based_w = 900
based_h = 1380
image_def = customize_image(image, based_w, based_h)
image_def = CustomizeImage(image, based_w, based_h)
bg_img = image_def.bg_img
bg_color = image_def.bg_color
text_color = image_def.text_color
@ -1492,7 +1536,8 @@ async def draw_info_pic(uid: str, image: Optional[Match] = None) -> str:
# 本日原石/摩拉
text_draw.text((675, 148),
f"{award_data['data']['day_data']['current_primogems']}/{award_data['data']['day_data']['last_primogems']}",
f"{award_data['data']['day_data']['current_primogems']}/"
f"{award_data['data']['day_data']['last_primogems']}",
text_color, genshin_font(28), anchor="lm")
text_draw.text((675, 212),
f"{award_data['data']['day_data']['current_mora']}\n{award_data['data']['day_data']['last_mora']}",
@ -1523,7 +1568,8 @@ async def draw_info_pic(uid: str, image: Optional[Match] = None) -> str:
text_draw.text((390, 503), f"{daily_data['finished_task_num']}/{daily_data['total_task_num']}", text_color,
genshin_font(26), anchor="lm")
text_draw.text((390, 597),
f"{str(daily_data['resin_discount_num_limit'] - daily_data['remain_resin_discount_num'])}/{daily_data['resin_discount_num_limit']}",
f"{str(daily_data['resin_discount_num_limit'] - daily_data['remain_resin_discount_num'])}/"
f"{daily_data['resin_discount_num_limit']}",
text_color, genshin_font(26), anchor="lm")
# 树脂恢复时间计算
@ -1532,13 +1578,13 @@ async def draw_info_pic(uid: str, image: Optional[Match] = None) -> str:
else:
resin_recovery_time = seconds2hours(
daily_data['resin_recovery_time'])
next_resin_rec_time = seconds2hours(
8 * 60 - ((daily_data['max_resin'] - daily_data['current_resin']) * 8 * 60 - int(
daily_data['resin_recovery_time'])))
text_draw.text((268, 305), f" {next_resin_rec_time}", text_color, genshin_font(18), anchor="lm")
next_resin_rec_time = seconds2hours(
8 * 60 - ((daily_data['max_resin'] - daily_data['current_resin']) * 8 * 60 - int(
daily_data['resin_recovery_time'])))
text_draw.text((268, 305), f" {next_resin_rec_time}", text_color, genshin_font(18), anchor="lm")
text_draw.text((170, 331), f"预计 后全部恢复", text_color, genshin_font(18), anchor="lm")
text_draw.text((208, 331), f"{resin_recovery_time}", highlight_color, genshin_font(18), anchor="lm")
text_draw.text((170, 331), f"预计 后全部恢复", text_color, genshin_font(18), anchor="lm")
text_draw.text((208, 331), f"{resin_recovery_time}", highlight_color, genshin_font(18), anchor="lm")
# 洞天宝钱时间计算
coin_rec_time = seconds2hours(int(daily_data["home_coin_recovery_time"]))
@ -1576,10 +1622,11 @@ async def draw_info_pic(uid: str, image: Optional[Match] = None) -> str:
if not os.path.exists(
os.path.join(CHAR_IMG_PATH, f"UI_AvatarIcon_{i['avatar_side_icon'].split('_')[-1][:-4]}@2x.png")):
get_char_img_pic(
f"https://upload-bbs.mihoyo.com/game_record/genshin/character_image/UI_AvatarIcon_{i['avatar_side_icon'].split('_')[-1][:-4]}@2x.png")
# char_stand_img = os.path.join(CHAR_IMG_PATH, f"UI_AvatarIcon_{i['avatar_side_icon'].split('_')[-1][:-4]}@2x.png")
# char_stand = Image.open(char_stand_img)
# char_stand_mask = Image.open(os.path.join(TEXT_PATH, "stand_mask.png"))
f"https://upload-bbs.mihoyo.com/game_record/genshin/character_image"
f"/UI_AvatarIcon_{i['avatar_side_icon'].split('_')[-1][:-4]}@2x.png")
# char_stand_img = os.path.join(CHAR_IMG_PATH, f"UI_AvatarIcon_{i['avatar_side_icon'].split('_')[-1][
# :-4]}@2x.png") char_stand = Image.open(char_stand_img) char_stand_mask = Image.open(os.path.join(TEXT_PATH,
# "stand_mask.png"))
# charpic_temp = Image.new("RGBA", (900, 130))
# charpic_temp.paste(char_stand, (395, -99), char_stand_mask)
@ -1702,4 +1749,4 @@ async def draw_event_pic() -> None:
base_img = base_img.convert('RGB')
base_img.save(os.path.join(FILE2_PATH, 'event.jpg'), format='JPEG', subsampling=0, quality=90)
return
return

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB