diff --git a/genshinuid.py b/genshinuid.py index 5489054b..c3bf03d5 100644 --- a/genshinuid.py +++ b/genshinuid.py @@ -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("数据获取失败(数据状态问题)") diff --git a/mihoyo_libs/get_data.py b/mihoyo_libs/get_data.py index d63c3b3f..3d8d3a58 100644 --- a/mihoyo_libs/get_data.py +++ b/mihoyo_libs/get_data.py @@ -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={}®ion={}".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={}®ion={}".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 diff --git a/mihoyo_libs/get_image.py b/mihoyo_libs/get_image.py index fb1b3b04..a1496eeb 100644 --- a/mihoyo_libs/get_image.py +++ b/mihoyo_libs/get_image.py @@ -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 \ No newline at end of file + return diff --git a/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Itto@2x.png b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Itto@2x.png new file mode 100644 index 00000000..3da72257 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Itto@2x.png differ diff --git a/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Kokomi@2x.png b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Kokomi@2x.png new file mode 100644 index 00000000..3c89ad6a Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Kokomi@2x.png differ diff --git a/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Shenhe@2x.png b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Shenhe@2x.png new file mode 100644 index 00000000..38db2c00 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Shenhe@2x.png differ diff --git a/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Yae@2x.png b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Yae@2x.png new file mode 100644 index 00000000..1e101747 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/char_img/UI_AvatarIcon_Yae@2x.png differ diff --git a/mihoyo_libs/mihoyo_bbs/chars/10000038.png b/mihoyo_libs/mihoyo_bbs/chars/10000038.png new file mode 100644 index 00000000..ea7579d7 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/chars/10000038.png differ diff --git a/mihoyo_libs/mihoyo_bbs/chars/10000050.png b/mihoyo_libs/mihoyo_bbs/chars/10000050.png new file mode 100644 index 00000000..9b9dc517 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/chars/10000050.png differ diff --git a/mihoyo_libs/mihoyo_bbs/chars/10000055.png b/mihoyo_libs/mihoyo_bbs/chars/10000055.png new file mode 100644 index 00000000..4be8af45 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/chars/10000055.png differ diff --git a/mihoyo_libs/mihoyo_bbs/chars/10000057.png b/mihoyo_libs/mihoyo_bbs/chars/10000057.png new file mode 100644 index 00000000..4fc2af02 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/chars/10000057.png differ diff --git a/mihoyo_libs/mihoyo_bbs/chars/10000058.png b/mihoyo_libs/mihoyo_bbs/chars/10000058.png new file mode 100644 index 00000000..b51ec2bf Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/chars/10000058.png differ diff --git a/mihoyo_libs/mihoyo_bbs/chars/10000063.png b/mihoyo_libs/mihoyo_bbs/chars/10000063.png new file mode 100644 index 00000000..d4d2c9df Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/chars/10000063.png differ diff --git a/mihoyo_libs/mihoyo_bbs/chars/10000064.png b/mihoyo_libs/mihoyo_bbs/chars/10000064.png new file mode 100644 index 00000000..b9474489 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/chars/10000064.png differ diff --git a/mihoyo_libs/mihoyo_bbs/reliquaries/UI_RelicIcon_10010_2.png b/mihoyo_libs/mihoyo_bbs/reliquaries/UI_RelicIcon_10010_2.png new file mode 100644 index 00000000..8c21edc9 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/reliquaries/UI_RelicIcon_10010_2.png differ diff --git a/mihoyo_libs/mihoyo_bbs/reliquaries/UI_RelicIcon_15008_3.png b/mihoyo_libs/mihoyo_bbs/reliquaries/UI_RelicIcon_15008_3.png new file mode 100644 index 00000000..fdff7942 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/reliquaries/UI_RelicIcon_15008_3.png differ diff --git a/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Catalyst_Narukami.png b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Catalyst_Narukami.png new file mode 100644 index 00000000..0088c7af Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Catalyst_Narukami.png differ diff --git a/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Claymore_MillenniaTuna.png b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Claymore_MillenniaTuna.png new file mode 100644 index 00000000..d1f5c43a Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Claymore_MillenniaTuna.png differ diff --git a/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Pole_Maria.png b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Pole_Maria.png new file mode 100644 index 00000000..38f399a7 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Pole_Maria.png differ diff --git a/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Pole_Mori.png b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Pole_Mori.png new file mode 100644 index 00000000..2f49b9bb Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Pole_Mori.png differ diff --git a/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Sword_Opus.png b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Sword_Opus.png new file mode 100644 index 00000000..a5692458 Binary files /dev/null and b/mihoyo_libs/mihoyo_bbs/weapon/UI_EquipIcon_Sword_Opus.png differ