From d26849207a37f780400c7346d7ff79aa4ba89ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wuyi=E6=97=A0=E7=96=91?= <444835641@qq.com> Date: Tue, 29 Mar 2022 23:13:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- mihoyo_libs/get_data.py | 30 +- mihoyo_libs/get_image.py | 448 ++++++++++++++++------------- mihoyo_libs/get_mihoyo_bbs_data.py | 30 +- 4 files changed, 283 insertions(+), 228 deletions(-) diff --git a/.gitignore b/.gitignore index 57f1cb2a..709d4406 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -/.idea/ \ No newline at end of file +/.idea/ +mihoyo_libs/mihoyo_bbs/bg/** \ No newline at end of file diff --git a/mihoyo_libs/get_data.py b/mihoyo_libs/get_data.py index 0bbfaa4a..d63c3b3f 100644 --- a/mihoyo_libs/get_data.py +++ b/mihoyo_libs/get_data.py @@ -16,7 +16,7 @@ from nonebot import logger mhyVersion = "2.11.1" BASE_PATH = os.path.dirname(__file__) -BASE2_PATH = os.path.join(BASE_PATH, 'mihoyo_bbs') +BASE2_PATH = os.path.join(BASE_PATH, 'mihoyo_libs/mihoyo_bbs') INDEX_PATH = os.path.join(BASE2_PATH, 'index') @@ -725,6 +725,7 @@ def get_character(uid, character_ids, ck, server_id="cn_gf01"): logger.info("深渊信息读取老Api失败!") logger.info(e.with_traceback) + async def get_calculate_info(uid, char_id, ck, server_id="cn_gf01"): if uid[0] == '5': server_id = "cn_qd01" @@ -732,23 +733,24 @@ async def get_calculate_info(uid, char_id, ck, server_id="cn_gf01"): 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 = { + 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 + "uid" : uid, + "region" : server_id } ) data = json.loads(req.text) return data - + + async def get_mihoyo_bbs_info(mysid, ck): try: async with AsyncClient() as client: @@ -927,4 +929,4 @@ async def get_genshin_events(mode="List"): params=params ) data = json.loads(req.text) - return data + return data \ No newline at end of file diff --git a/mihoyo_libs/get_image.py b/mihoyo_libs/get_image.py index d6f3dc1c..fb1b3b04 100644 --- a/mihoyo_libs/get_image.py +++ b/mihoyo_libs/get_image.py @@ -1,12 +1,10 @@ -import json import asyncio -from typing import Optional, Union, Any -import os,time import math import threading from base64 import b64encode from io import BytesIO -from re import findall +from re import Match, findall +from typing import Optional import numpy as np from PIL import Image, ImageDraw, ImageFilter, ImageFont @@ -17,7 +15,7 @@ from wordcloud import WordCloud from .get_data import * FILE_PATH = os.path.dirname(__file__) -FILE2_PATH = os.path.join(FILE_PATH, 'mihoyo_bbs') +FILE2_PATH = os.path.join(FILE_PATH, 'mihoyo_libs/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') @@ -28,10 +26,11 @@ TEXT_PATH = os.path.join(FILE2_PATH, 'texture2d') WEAPON_PATH = os.path.join(FILE2_PATH, 'weapon') BG_PATH = os.path.join(FILE2_PATH, 'bg') + class customize_image: - def __init__(self,image: str,based_w: int,based_h: int) -> None: - - self.bg_img = self.get_image(image,based_w,based_h) + def __init__(self, image: Match, based_w: int, based_h: int) -> None: + + self.bg_img = self.get_image(image, based_w, based_h) self.bg_color = self.get_bg_color(self.bg_img) self.text_color = self.get_text_color(self.bg_color) self.highlight_color = self.get_highlight_color(self.bg_color) @@ -39,7 +38,8 @@ class customize_image: self.bg_detail_color = self.get_bg_detail_color(self.bg_color) self.char_high_color = self.get_char_high_color(self.bg_color) - def get_image(self,image: str,based_w: int,based_h: int) -> Image: + @staticmethod + def get_image(image: Match, based_w: int, based_h: int) -> Image: # 获取背景图片 bg2_path = os.path.join(BG_PATH, random.choice([x for x in os.listdir(BG_PATH) if os.path.isfile(os.path.join(BG_PATH, x))])) @@ -65,7 +65,8 @@ class customize_image: return bg_img - def get_bg_color(self,edit_bg:Image) -> tuple[int, int, int]: + @staticmethod + def get_bg_color(edit_bg: Image) -> tuple[int, int, int]: # 获取背景主色 color = 8 q = edit_bg.quantize(colors=color, method=2) @@ -78,64 +79,69 @@ class customize_image: if abs(light_value - based_light) < temp: bg_color = bg temp = abs(light_value - based_light) - #if max(*bg) < 240 and min(*bg) > 20: + # if max(*bg) < 240 and min(*bg) > 20: # bg_color = bg return bg_color - def get_text_color(self,bg_color: tuple[int, int, int]) -> tuple[int, int, int]: + @staticmethod + def get_text_color(bg_color: tuple[int, int, int]) -> tuple[int, int, int]: # 通过背景主色(bg_color)确定文字主色 r = 125 if max(*bg_color) > 255 - r: r *= -1 text_color = (math.floor(bg_color[0] + r if bg_color[0] + r <= 255 else 255), - math.floor(bg_color[1] + r if bg_color[1] + r <= 255 else 255), - math.floor(bg_color[2] + r if bg_color[2] + r <= 255 else 255)) + math.floor(bg_color[1] + r if bg_color[1] + r <= 255 else 255), + math.floor(bg_color[2] + r if bg_color[2] + r <= 255 else 255)) return text_color - def get_char_color(self,bg_color: tuple[int, int, int]) -> tuple[int, int, int]: + @staticmethod + def get_char_color(bg_color: tuple[int, int, int]) -> tuple[int, int, int]: r = 140 if max(*bg_color) > 255 - r: r *= -1 char_color = (math.floor(bg_color[0] + 5 if bg_color[0] + r <= 255 else 255), - math.floor(bg_color[1] + 5 if bg_color[1] + r <= 255 else 255), - math.floor(bg_color[2] + 5 if bg_color[2] + r <= 255 else 255)) + math.floor(bg_color[1] + 5 if bg_color[1] + r <= 255 else 255), + math.floor(bg_color[2] + 5 if bg_color[2] + r <= 255 else 255)) return char_color - - def get_char_high_color(self,bg_color: tuple[int, int, int]) -> tuple[int, int, int]: + + @staticmethod + def get_char_high_color(bg_color: tuple[int, int, int]) -> tuple[int, int, int]: r = 140 d = 20 if max(*bg_color) > 255 - r: r *= -1 char_color = (math.floor(bg_color[0] + d if bg_color[0] + r <= 255 else 255), - math.floor(bg_color[1] + d if bg_color[1] + r <= 255 else 255), - math.floor(bg_color[2] + d if bg_color[2] + r <= 255 else 255)) + math.floor(bg_color[1] + d if bg_color[1] + r <= 255 else 255), + math.floor(bg_color[2] + d if bg_color[2] + r <= 255 else 255)) return char_color - - def get_bg_detail_color(self,bg_color: tuple[int, int, int]) -> tuple[int, int, int]: + + @staticmethod + def get_bg_detail_color(bg_color: tuple[int, int, int]) -> tuple[int, int, int]: r = 140 if max(*bg_color) > 255 - r: r *= -1 bg_detail_color = (math.floor(bg_color[0] - 20 if bg_color[0] + r <= 255 else 255), - math.floor(bg_color[1] - 20 if bg_color[1] + r <= 255 else 255), - math.floor(bg_color[2] - 20 if bg_color[2] + r <= 255 else 255)) + math.floor(bg_color[1] - 20 if bg_color[1] + r <= 255 else 255), + math.floor(bg_color[2] - 20 if bg_color[2] + r <= 255 else 255)) return bg_detail_color - def get_highlight_color(self,color: tuple[int, int, int]) -> tuple[int, int, int]: + @staticmethod + def get_highlight_color(color: tuple[int, int, int]) -> tuple[int, int, int]: red_color = color[0] green_color = color[1] blue_color = color[2] - highlight_color = {} - highlight_color["red"] = red_color - 127 if red_color > 127 else 127 - highlight_color["green"] = green_color - 127 if green_color > 127 else 127 - highlight_color["blue"] = blue_color - 127 if blue_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} max_color = max(highlight_color.values()) + name = '' for _highlight_color in highlight_color: if highlight_color[_highlight_color] == max_color: name = str(_highlight_color) - + if name == "red": return red_color, highlight_color["green"], highlight_color["blue"] elif name == "green": @@ -145,6 +151,7 @@ class customize_image: else: return 0, 0, 0 # Error + def genshin_font(size: int): return ImageFont.truetype(os.path.join(FILE2_PATH, "yuanshen.ttf"), size=size) @@ -184,17 +191,18 @@ def get_rel_pic(url: str): with open(os.path.join(REL_PATH, url.split('/')[-1]), 'wb') as f: f.write(get(url).content) + class get_cookies: def __init__(self) -> None: self.useable_cookies: Optional[str] = None self.uid: Optional[str] = None self.mode: Optional[int] = None - self.raw_abyss_data: Optional[json] = None - self.raw_data: Optional[json] = None + self.raw_abyss_data: Optional[dict] = None + self.raw_data: Optional[dict] = None self.nickname: Optional[int] = None self.schedule_type: Optional[str] = None - async def get_useable_cookies(self, uid: str, mode: int = 2,schedule_type: str = "1"): + async def get_useable_cookies(self, uid: str, mode: int = 2, schedule_type: str = "1"): self.uid = uid self.schedule_type = schedule_type while True: @@ -224,11 +232,11 @@ class get_cookies: self.nickname = mys_data['data']['list'][0]['nickname'] self.raw_data = await get_info(self.uid, self.useable_cookies) self.raw_abyss_data = await get_spiral_abyss_info(self.uid, self.useable_cookies, self.schedule_type) - + async def get_uid_data(self): self.raw_abyss_data = await get_spiral_abyss_info(self.uid, self.useable_cookies, self.schedule_type) self.raw_data = await get_info(self.uid, self.useable_cookies) - + async def check_cookies_useable(self): if self.raw_data: if self.raw_data["retcode"] != 0: @@ -250,27 +258,28 @@ class get_cookies: else: return "没有可以使用的Cookies!" -async def draw_word_cloud(uid: str, image: Optional[str] = None, mode: int = 2): - def create_rounded_rectangle_mask(rectangle, radius): - solid_fill = (50, 50, 50, 255) - i = Image.new("RGBA", rectangle.size, (0, 0, 0, 0)) - corner = Image.new('RGBA', (radius, radius), (0, 0, 0, 0)) +async def draw_word_cloud(uid: str, image: Optional[Match] = None, mode: int = 2): + def create_rounded_rectangle_mask(rectangle, _radius): + solid_fill = (50, 50, 50, 255) + img = Image.new("RGBA", rectangle.size, (0, 0, 0, 0)) + + corner = Image.new('RGBA', (_radius, _radius), (0, 0, 0, 0)) draw = ImageDraw.Draw(corner) - draw.pieslice(((0, 0), (radius * 2, radius * 2)), 180, 270, fill=solid_fill) + draw.pieslice(((0, 0), (_radius * 2, _radius * 2)), 180, 270, fill=solid_fill) mx, my = rectangle.size - i.paste(corner, (0, 0), corner) - i.paste(corner.rotate(90), (0, my - radius), corner.rotate(90)) - i.paste(corner.rotate(180), (mx - radius, my - radius), corner.rotate(180)) - i.paste(corner.rotate(270), (mx - radius, 0), corner.rotate(270)) + img.paste(corner, (0, 0), corner) + img.paste(corner.rotate(90), (0, my - _radius), corner.rotate(90)) + img.paste(corner.rotate(180), (mx - _radius, my - _radius), corner.rotate(180)) + img.paste(corner.rotate(270), (mx - _radius, 0), corner.rotate(270)) - draw = ImageDraw.Draw(i) - draw.rectangle(((radius, 0), (mx - radius, my)), fill=solid_fill) - draw.rectangle(((0, radius), (mx, my - radius)), fill=solid_fill) + draw = ImageDraw.Draw(img) + draw.rectangle(((_radius, 0), (mx - _radius, my)), fill=solid_fill) + draw.rectangle(((0, _radius), (mx, my - _radius)), fill=solid_fill) - return i + return img nickname = '' while True: @@ -533,11 +542,12 @@ async def draw_word_cloud(uid: str, image: Optional[str] = None, mode: int = 2): resultmes = imgmes return resultmes + async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"): # 获取Cookies data_def = get_cookies() retcode = await data_def.get_useable_cookies(uid, mode, date) - if retcode != True: + if not retcode: return retcode raw_char_data = data_def.raw_data raw_data = data_def.raw_abyss_data @@ -551,15 +561,15 @@ async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"): # 获取查询者数据 floors_data = raw_data['floors'][-1] levels_num = len(floors_data['levels']) - + # 获取背景图片各项参数 based_w = 900 based_h = 660 + levels_num * 315 - image_def = customize_image(image,based_w,based_h) + image_def = customize_image(image, based_w, based_h) bg_img = image_def.bg_img bg_color = image_def.bg_color text_color = image_def.text_color - highlight_color = image_def.highlight_color + # highlight_color = image_def.highlight_color # 确定贴图路径 abyss0_path = os.path.join(TEXT_PATH, "abyss_0.png") @@ -813,11 +823,12 @@ async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"): return resultmes -async def draw_abyss_pic(uid: str, nickname: str, floor_num : int, image: Optional[str] = None, mode: int = 2, date : str = "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() retcode = await data_def.get_useable_cookies(uid, mode, date) - if retcode != True: + if not retcode: return retcode raw_char_data = data_def.raw_data raw_data = data_def.raw_abyss_data @@ -837,11 +848,11 @@ async def draw_abyss_pic(uid: str, nickname: str, floor_num : int, image: Option # 获取背景图片各项参数 based_w = 900 based_h = 440 + levels_num * 340 - image_def = customize_image(image,based_w,based_h) + image_def = customize_image(image, based_w, based_h) bg_img = image_def.bg_img bg_color = image_def.bg_color text_color = image_def.text_color - highlight_color = image_def.highlight_color + # highlight_color = image_def.highlight_color # 打开图片 abyss1_path = os.path.join(TEXT_PATH, "abyss_1.png") @@ -968,11 +979,91 @@ async def draw_abyss_pic(uid: str, nickname: str, floor_num : int, image: Option return resultmes -async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: int = 2, role_level: Optional[int] = None): +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_mingzuo = 0 + for k in char_data['constellations']: + if k['is_actived']: + char_mingzuo += 1 + if char_data['rarity'] == 5: + char_0 = Image.new("RGBA", (180, 90), char_high_color) + else: + char_0 = Image.new("RGBA", (180, 90), bg_color) + char_0_raw = Image.open(os.path.join(TEXT_PATH, "char_0.png")) + alpha = char_0_raw.getchannel('A') + char_0.putalpha(alpha) + + char_2 = Image.new("RGBA", (180, 90), bg_detail_color) + char_2_raw = Image.open(os.path.join(TEXT_PATH, "char_2.png")) + alpha = char_2_raw.getchannel('A') + char_2.putalpha(alpha) + + """ + char_3 = Image.new("RGBA", (180, 90), bg_detail_color) + char_3_raw = Image.open(os.path.join(TEXT_PATH, "char_3.png")) + alpha = char_3_raw.getchannel('A') + 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) + 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")): + get_char_pic(char_data['id'], char_data['icon']) + + char_img = Image.open(os.path.join(CHAR_PATH, str(char_data["id"]) + ".png")).resize((81, 81), + Image.ANTIALIAS) + weapon_img = Image.open( + os.path.join(WEAPON_PATH, str(char_data['weapon']['icon'].split('/')[-1]))).resize((40, 40), + Image.ANTIALIAS) + weapon_1_mask = char_1_mask.resize((40, 40), Image.ANTIALIAS) + char_0_temp = Image.new("RGBA", (180, 90)) + char_0_temp.paste(char_img, (8, 5), char_1_mask) + char_0_temp.paste(weapon_img, (70, 45), weapon_1_mask) + char_0.paste(char_0_temp, (0, 0), char_0_temp) + char_0.paste(char_2, (0, 0), char_2) + # char_0.paste(char_3, (0, 0), char_3) + draw_text = ImageDraw.Draw(char_0) + for i in range(0, 2): + draw_text.text((106 + 23 * i, 17), + f'{str(char_talent_data["data"]["skill_list"][i]["level_current"])}', text_color, + genshin_font(15), anchor="mm") + + if len(char_talent_data["data"]["skill_list"]) == 7 and char_data["name"] != "珊瑚宫心海": + draw_text.text((106 + 23 * 2, 17), + f'{str(char_talent_data["data"]["skill_list"][3]["level_current"])}', text_color, + genshin_font(15), anchor="mm") + else: + draw_text.text((106 + 23 * 2, 17), + f'{str(char_talent_data["data"]["skill_list"][2]["level_current"])}', text_color, + genshin_font(15), anchor="mm") + + draw_text.text((42, 77), "Lv.{}".format(str(char_data["level"])), text_color, genshin_font(16), + anchor="mm") + draw_text.text((162, 38), "{}命".format(char_mingzuo), text_color, genshin_font(18), anchor="rm") + draw_text.text((115, 57), 'Lv.{}'.format(str(char_data['weapon']['level'])), text_color, + genshin_font(18), anchor="lm") + draw_text.text((115, 75), '{}精'.format(str(char_data['weapon']['affix_level'])), text_color, + genshin_font(16), anchor="lm") + + if str(char_data["fetter"]) == "10" or str(char_data["name"]) == "旅行者": + draw_text.text((74, 19), "♥", text_color, genshin_font(14), anchor="mm") + else: + draw_text.text((73, 18), '{}'.format(str(char_data['fetter'])), text_color, genshin_font(16), + anchor="mm") + + char_crop = (75 + 190 * (index % 4), 800 + 100 * (index // 4)) + 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() retcode = await data_def.get_useable_cookies(uid, mode) - if retcode != True: + if not retcode: return retcode use_cookies = data_def.useable_cookies raw_data = data_def.raw_data @@ -998,11 +1089,11 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i # 获取背景图片各项参数 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 = customize_image(image, based_w, based_h) bg_img = image_def.bg_img bg_color = image_def.bg_color text_color = image_def.text_color - highlight_color = image_def.highlight_color + # highlight_color = image_def.highlight_color char_color = image_def.char_color bg_detail_color = image_def.bg_detail_color char_high_color = image_def.char_high_color @@ -1076,7 +1167,8 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i 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_color, + text_draw.text((745, 373.5), str(raw_data['world_explorations'][2]['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)) @@ -1133,79 +1225,16 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i char_fg = Image.open(char_fg_path) num = 0 - for index,i in enumerate(char_datas): + for index, i in enumerate(char_datas): if i['rarity'] > 5: char_datas[index]['rarity'] = 3 char_datas.sort(key=lambda x: (-x['rarity'], -x['level'], -x['fetter'])) if char_num > 8: tasks = [] - for index,i in enumerate(char_datas): - async def draw_char_pic(img: Image, char_data: json, 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]): - char_mingzuo = 0 - for k in char_data['constellations']: - if k['is_actived']: - char_mingzuo += 1 - if char_data['rarity'] == 5: - char_0 = Image.new("RGBA", (180, 90), char_high_color) - else: - char_0 = Image.new("RGBA", (180, 90), bg_color) - char_0_raw = Image.open(os.path.join(TEXT_PATH, "char_0.png")) - alpha = char_0_raw.getchannel('A') - char_0.putalpha(alpha) - - char_2 = Image.new("RGBA", (180, 90), bg_detail_color) - char_2_raw = Image.open(os.path.join(TEXT_PATH, "char_2.png")) - alpha = char_2_raw.getchannel('A') - char_2.putalpha(alpha) - - """ - char_3 = Image.new("RGBA", (180, 90), bg_detail_color) - char_3_raw = Image.open(os.path.join(TEXT_PATH, "char_3.png")) - alpha = char_3_raw.getchannel('A') - 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) - 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")): - get_char_pic(char_data['id'], char_data['icon']) - - char_img = Image.open(os.path.join(CHAR_PATH, str(char_data["id"]) + ".png")).resize((81, 81), Image.ANTIALIAS) - weapon_img = Image.open(os.path.join(WEAPON_PATH, str(char_data['weapon']['icon'].split('/')[-1]))).resize((40, 40), Image.ANTIALIAS) - weapon_1_mask = char_1_mask.resize((40, 40), Image.ANTIALIAS) - char_0_temp = Image.new("RGBA", (180, 90)) - char_0_temp.paste(char_img,(8, 5),char_1_mask) - char_0_temp.paste(weapon_img,(70, 45),weapon_1_mask) - char_0.paste(char_0_temp, (0, 0), char_0_temp) - char_0.paste(char_2, (0, 0), char_2) - #char_0.paste(char_3, (0, 0), char_3) - draw_text = ImageDraw.Draw(char_0) - for i in range(0,2): - draw_text.text((106 + 23*i, 17), f'{str(char_talent_data["data"]["skill_list"][i]["level_current"])}', text_color, genshin_font(15),anchor="mm") - - if len(char_talent_data["data"]["skill_list"]) == 7 and char_data["name"] != "珊瑚宫心海": - draw_text.text((106 + 23*2, 17), f'{str(char_talent_data["data"]["skill_list"][3]["level_current"])}', text_color, genshin_font(15),anchor="mm") - else: - draw_text.text((106 + 23*2, 17), f'{str(char_talent_data["data"]["skill_list"][2]["level_current"])}', text_color, genshin_font(15),anchor="mm") - - draw_text.text((42,77), "Lv.{}".format(str(char_data["level"])), text_color, genshin_font(16),anchor="mm") - draw_text.text((162,38), "{}命".format( char_mingzuo), text_color, genshin_font(18),anchor="rm") - draw_text.text((115,57), 'Lv.{}'.format(str(char_data['weapon']['level'])), text_color, genshin_font(18),anchor="lm") - draw_text.text((115,75), '{}精'.format(str(char_data['weapon']['affix_level'])), text_color, genshin_font(16),anchor="lm") - - if str(char_data["fetter"]) == "10" or str(char_data["name"]) == "旅行者": - draw_text.text((74, 19), "♥", text_color, genshin_font(14),anchor="mm") - else: - draw_text.text((73, 18), '{}'.format(str(char_data['fetter'])), text_color, genshin_font(16),anchor="mm") - - char_crop = (75 + 190 * (index % 4), 800 + 100 * (index // 4)) - img.paste(char_0, char_crop, char_0) - tasks.append(draw_char_pic(bg_img, i, index, char_color, text_color, bg_detail_color, char_high_color)) + 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)) await asyncio.wait(tasks) """ char_mingzuo = 0 @@ -1323,9 +1352,9 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i char_stand_img = os.path.join(CHAR_IMG_PATH, str(char_img_icon.split('/')[-1])) char_stand_mask = Image.open(os.path.join(TEXT_PATH, "stand_mask.png")) - #char_namecard_img = Image.open(os.path.join(CHAR_NAMECARD_PATH,str(i['icon'].split('_')[-1]))) - #char_namecard_img = char_namecard_img.resize((591,81), Image.ANTIALIAS) - #char_namecard_img.putalpha(char_namecard_img.getchannel('A').point(lambda i: i*0.8 if i>0 else 0)) + # char_namecard_img = Image.open(os.path.join(CHAR_NAMECARD_PATH,str(i['icon'].split('_')[-1]))) + # char_namecard_img = char_namecard_img.resize((591,81), Image.ANTIALIAS) + # char_namecard_img.putalpha(char_namecard_img.getchannel('A').point(lambda i: i*0.8 if i>0 else 0)) char_stand = Image.open(char_stand_img) char_img = Image.open(char) char_img = char_img.resize((100, 100), Image.ANTIALIAS) @@ -1339,7 +1368,7 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i weapon_bg = Image.open(get_text(char_weapon_star, 3)) charpic_temp.paste(char_stand, (395, -99), char_stand_mask) - #charpic_temp.paste(char_namecard_img, (247, 24), char_namecard_img) + # charpic_temp.paste(char_namecard_img, (247, 24), char_namecard_img) charpic.paste(weapon_bg, (72, 10), weapon_bg) charpic_temp.paste(char_img, (81, 13), charpic_mask) charpic_temp.paste(char_fg, (0, 0), char_fg) @@ -1392,8 +1421,7 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i return resultmes -async def draw_info_pic(uid: str,image :Optional[str] = None) -> str: - +async def draw_info_pic(uid: str, image: Optional[Match] = None) -> str: def seconds2hours(seconds: int) -> str: m, s = divmod(int(seconds), 60) h, m = divmod(m, 60) @@ -1402,11 +1430,11 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str: # 获取Cookies data_def = get_cookies() retcode = await data_def.get_useable_cookies(uid) - if retcode != True: + if not retcode: return retcode raw_data = data_def.raw_data char_data = raw_data["data"]["avatars"] - #获取数据 + # 获取数据 award_data = await get_award(uid) daily_data = await get_daily_data(uid) daily_data = daily_data["data"] @@ -1415,7 +1443,7 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str: # 获取背景图片各项参数 based_w = 900 based_h = 1380 - image_def = customize_image(image,based_w,based_h) + image_def = customize_image(image, based_w, based_h) bg_img = image_def.bg_img bg_color = image_def.bg_color text_color = image_def.text_color @@ -1443,7 +1471,7 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str: info3 = Image.open(info3_path) avatar_bg = Image.open(avatar_bg_path) avatar_fg = Image.open(avatar_fg_path) - + avatar_bg_color = Image.new("RGBA", (316, 100), bg_color) bg_img.paste(avatar_bg_color, (113, 98), avatar_bg) bg_img.paste(avatar_fg, (114, 95), avatar_fg) @@ -1455,111 +1483,130 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str: bg_img.paste(info2_color, (0, 0), info2) bg_img.paste(info3, (0, 0), info3) - text_draw = ImageDraw.Draw(bg_img) - #用户信息 - text_draw.text((220, 137), f"{nickname}", text_color, genshin_font(32),anchor="lm") - text_draw.text((235, 170), 'UID ' + f"{uid}", text_color, genshin_font(14),anchor="lm") + # 用户信息 + text_draw.text((220, 137), f"{nickname}", text_color, genshin_font(32), anchor="lm") + text_draw.text((235, 170), 'UID ' + f"{uid}", text_color, genshin_font(14), anchor="lm") - #本日原石/摩拉 - text_draw.text((675, 148), f"{award_data['data']['day_data']['current_primogems']}/{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']}", text_color, genshin_font(28),anchor="lm") + # 本日原石/摩拉 + text_draw.text((675, 148), + f"{award_data['data']['day_data']['current_primogems']}/{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']}", + text_color, genshin_font(28), anchor="lm") - #本月/上月原石 - text_draw.text((722, 287), f"{award_data['data']['month_data']['current_primogems']}", text_color, genshin_font(21),anchor="lm") - text_draw.text((722, 323), f"{award_data['data']['month_data']['last_primogems']}", text_color, genshin_font(21),anchor="lm") + # 本月/上月原石 + text_draw.text((722, 287), f"{award_data['data']['month_data']['current_primogems']}", text_color, genshin_font(21), + anchor="lm") + text_draw.text((722, 323), f"{award_data['data']['month_data']['last_primogems']}", text_color, genshin_font(21), + anchor="lm") - #本月/上月摩拉 - text_draw.text((722, 359), f"{award_data['data']['month_data']['current_mora']}", text_color, genshin_font(21),anchor="lm") - text_draw.text((722, 395), f"{award_data['data']['month_data']['last_mora']}", text_color, genshin_font(21),anchor="lm") + # 本月/上月摩拉 + text_draw.text((722, 359), f"{award_data['data']['month_data']['current_mora']}", text_color, genshin_font(21), + anchor="lm") + text_draw.text((722, 395), f"{award_data['data']['month_data']['last_mora']}", text_color, genshin_font(21), + anchor="lm") - #收入比例 - for index,i in enumerate(award_data['data']['month_data']['group_by']): - text_draw.text((681, 445 + index * 32), f"{str(i['num'])}({str(i['percent'])}%)", text_color, genshin_font(21),anchor="lm") + # 收入比例 + for index, i in enumerate(award_data['data']['month_data']['group_by']): + text_draw.text((681, 445 + index * 32), f"{str(i['num'])}({str(i['percent'])}%)", text_color, genshin_font(21), + anchor="lm") - #基本四项 - text_draw.text((390, 314), f"{daily_data['current_resin']}/{daily_data['max_resin']}", text_color, genshin_font(26),anchor="lm") - text_draw.text((390, 408), f'{daily_data["current_home_coin"]}/{daily_data["max_home_coin"]}', text_color, genshin_font(26),anchor="lm") - 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']}", text_color, genshin_font(26),anchor="lm") + # 基本四项 + text_draw.text((390, 314), f"{daily_data['current_resin']}/{daily_data['max_resin']}", text_color, genshin_font(26), + anchor="lm") + text_draw.text((390, 408), f'{daily_data["current_home_coin"]}/{daily_data["max_home_coin"]}', text_color, + genshin_font(26), anchor="lm") + 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']}", + text_color, genshin_font(26), anchor="lm") - #树脂恢复时间计算 - 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") + # 树脂恢复时间计算 + if int(daily_data['resin_recovery_time']) <= 0: + text_draw.text((170, 331), f"已全部恢复", text_color, genshin_font(18), anchor="lm") + 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") - 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"])) - if daily_data["home_coin_recovery_time"] == "0": - text_draw.text((170, 425), f"已满", text_color, genshin_font(18),anchor="lm") + if int(daily_data["home_coin_recovery_time"]) <= 0: + text_draw.text((170, 425), f"已达到上限", text_color, genshin_font(18), anchor="lm") else: coin_add_speed = math.ceil((daily_data["max_home_coin"] - daily_data["current_home_coin"]) / ( int(daily_data["home_coin_recovery_time"]) / 60 / 60)) - text_draw.text((270, 399), f"约{coin_add_speed}/h", text_color, genshin_font(18),anchor="lm") - text_draw.text((170, 425), f"预计 后达到上限", text_color, genshin_font(18),anchor="lm") - text_draw.text((208, 425), f"{coin_rec_time}", highlight_color, genshin_font(18),anchor="lm") + text_draw.text((270, 399), f"约{coin_add_speed}/h", text_color, genshin_font(18), anchor="lm") + text_draw.text((170, 425), f"预计 后达到上限", text_color, genshin_font(18), anchor="lm") + text_draw.text((208, 425), f"{coin_rec_time}", highlight_color, genshin_font(18), anchor="lm") if daily_data['is_extra_task_reward_received']: daily_task_status = "「每日委托」奖励已领取" else: daily_task_status = "「每日委托」奖励未领取" - #详细信息 - text_draw.text((170, 518), f"{daily_task_status}", text_color, genshin_font(18),anchor="lm") - text_draw.text((170, 614), f"本周剩余消耗减半次数", text_color, genshin_font(18),anchor="lm") + # 详细信息 + text_draw.text((170, 518), f"{daily_task_status}", text_color, genshin_font(18), anchor="lm") + text_draw.text((170, 614), f"本周剩余消耗减半次数", text_color, genshin_font(18), anchor="lm") - #派遣图片准备 + # 派遣图片准备 char_bg_path = os.path.join(TEXT_PATH, "char_bg.png") char_bg = Image.open(char_bg_path) charset_mask = Image.new("RGBA", (900, 130), char_color) - #派遣 - for index,i in enumerate(daily_data["expeditions"]): + # 派遣 + for index, i in enumerate(daily_data["expeditions"]): + name = '' for j in char_data: if i["avatar_side_icon"].split("_")[-1] == j["image"].split("_")[-1]: name = j["name"] - 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")) + 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")) - #charpic_temp = Image.new("RGBA", (900, 130)) - #charpic_temp.paste(char_stand, (395, -99), char_stand_mask) + # charpic_temp = Image.new("RGBA", (900, 130)) + # charpic_temp.paste(char_stand, (395, -99), char_stand_mask) charpic = Image.new("RGBA", (900, 130)) char_icon = Image.open(BytesIO(get(i['avatar_side_icon']).content)) - char_namecard_img = Image.open(os.path.join(CHAR_NAMECARD_PATH,str(name + ".png"))) - char_namecard_img = char_namecard_img.resize((591,81), Image.ANTIALIAS) - char_namecard_img.putalpha(char_namecard_img.getchannel('A').point(lambda i: i*0.8 if i>0 else 0)) + char_namecard_img = Image.open(os.path.join(CHAR_NAMECARD_PATH, str(name + ".png"))) + char_namecard_img = char_namecard_img.resize((591, 81), Image.ANTIALIAS) + char_namecard_img.putalpha(char_namecard_img.getchannel('A').point(lambda x: round(x * 0.8) if x > 0 else 0)) - char_icon_scale = char_icon.resize((140,140),Image.ANTIALIAS) + char_icon_scale = char_icon.resize((140, 140), Image.ANTIALIAS) charpic.paste(charset_mask, (0, 0), char_bg) charpic.paste(char_icon_scale, (63, -26), char_icon_scale) charpic.paste(char_namecard_img, (247, 24), char_namecard_img) charpic_draw = ImageDraw.Draw(charpic) - + if i['status'] == 'Finished': - charpic_draw.text((200, 65), f"探索完成", text_color, genshin_font(24),anchor="lm") + charpic_draw.text((200, 65), f"探索完成", text_color, genshin_font(24), anchor="lm") else: remained_timed: str = seconds2hours(i['remained_time']) - charpic_draw.text((200, 65), f"剩余时间 {remained_timed}", text_color, genshin_font(24),anchor="lm") + charpic_draw.text((200, 65), f"剩余时间 {remained_timed}", text_color, genshin_font(24), anchor="lm") - bg_img.paste(charpic, (-15,748 + 115*index), charpic) + bg_img.paste(charpic, (-15, 748 + 115 * index), charpic) - end_pic = Image.open(os.path.join(TEXT_PATH,"abyss_3.png")) - bg_img.paste(end_pic,(0,1340),end_pic) + end_pic = Image.open(os.path.join(TEXT_PATH, "abyss_3.png")) + bg_img.paste(end_pic, (0, 1340), end_pic) bg_img = bg_img.convert('RGB') result_buffer = BytesIO() @@ -1568,6 +1615,7 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str: resultmes = imgmes return resultmes + async def draw_event_pic() -> None: raw_data = await get_genshin_events("List") raw_time_data = await get_genshin_events("Content") @@ -1654,4 +1702,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 \ No newline at end of file diff --git a/mihoyo_libs/get_mihoyo_bbs_data.py b/mihoyo_libs/get_mihoyo_bbs_data.py index 7cd1eff7..55aea3ad 100644 --- a/mihoyo_libs/get_mihoyo_bbs_data.py +++ b/mihoyo_libs/get_mihoyo_bbs_data.py @@ -1,15 +1,10 @@ -import json import math import os import sys -import random -import re -import sqlite3 from base64 import b64encode -from openpyxl import load_workbook from io import BytesIO -import requests +from openpyxl import load_workbook sys.path.append(os.path.dirname(os.path.abspath(__file__))) from .get_data import * @@ -17,7 +12,7 @@ from .get_image import draw_event_pic import get_mihoyo_bbs_coin as coin FILE_PATH = os.path.dirname(__file__) -FILE2_PATH = os.path.join(FILE_PATH, 'mihoyo_bbs') +FILE2_PATH = os.path.join(FILE_PATH, 'mihoyo_libs/mihoyo_bbs') INDEX_PATH = os.path.join(FILE2_PATH, 'index') Texture_PATH = os.path.join(FILE2_PATH, 'texture2d') @@ -160,6 +155,7 @@ char_adv_im = '''【{}】 【圣遗物】: {}''' + async def weapon_adv(name): char_adv_path = os.path.join(FILE_PATH, "mihoyo_libs/Genshin All Char.xlsx") wb = load_workbook(char_adv_path) @@ -182,6 +178,7 @@ async def weapon_adv(name): im = "没有角色能使用【{}】".format(weapon_name) return im + async def char_adv(name): char_name = None char_adv_path = os.path.join(FILE_PATH, "mihoyo_libs/Genshin All Char.xlsx") @@ -192,7 +189,7 @@ async def char_adv(name): for i in char_list: if i.value: if all(g in i.value for g in name): - #if name in i.value: + # if name in i.value: index = i.row char_name = i.value if index: @@ -204,7 +201,7 @@ async def char_adv(name): weapon_5star = weapon_5star[:-1] else: weapon_5star = "无推荐" - + weapon_4star = "" for i in range(index, index + 5): if ws.cell(i, 3).value: @@ -213,7 +210,7 @@ async def char_adv(name): weapon_4star = weapon_4star[:-1] else: weapon_4star = "无推荐" - + weapon_3star = "" for i in range(index, index + 5): if ws.cell(i, 4).value: @@ -239,6 +236,7 @@ async def char_adv(name): im = char_adv_im.format(char_name, weapon_5star, weapon_4star, weapon_3star, artifacts) return im + async def deal_ck(mes, qid): if "stoken" in mes: login_ticket = re.search(r"login_ticket=([0-9a-zA-Z]+)", mes).group(0).split('=')[1] @@ -276,7 +274,8 @@ async def deal_ck(mes, qid): await cookies_db(uid, cookie, qid) return f'添加Cookies成功!\nCookies属于个人重要信息,如果你是在不知情的情况下添加,请马上修改米游社账户密码,保护个人隐私!\n————\n' \ - f'如果需要【开启自动签到】和【开启推送】还需要在【群聊中】使用命令“绑定uid”绑定你的uid。\n例如:绑定uid123456789。' + f'如果需要【开启自动签到】和【开启推送】还需要在【群聊中】使用命令“绑定uid”绑定你的uid。\n例如:绑定uid123456789。' + async def award(uid): data = await get_award(uid) @@ -422,6 +421,7 @@ async def daily(mode="push", uid=None): temp_list = [] conn = sqlite3.connect('ID_DATA.db') c = conn.cursor() + c_data = None if mode == "push": cursor = c.execute( "SELECT * FROM NewCookiesTable WHERE StatusA != ?", ("off",)) @@ -509,7 +509,8 @@ async def daily(mode="push", uid=None): {"qid": row[2], "gid": row[3], "message": send_mes}) return temp_list -async def mihoyo_coin(qid,s_cookies = None): + +async def mihoyo_coin(qid, s_cookies=None): uid = await select_db(qid, mode="uid") uid = uid[0] if s_cookies is None: @@ -522,6 +523,7 @@ async def mihoyo_coin(qid,s_cookies = None): im = "你还没有绑定Stoken~" return im + async def get_event_pic(): img_path = os.path.join(FILE2_PATH, "event.jpg") while True: @@ -535,6 +537,7 @@ async def get_event_pic(): await draw_event_pic() return img_mes + async def weapon_wiki(name, level=None): data = await get_weapon_info(name) if "errcode" in data: @@ -581,6 +584,7 @@ async def weapon_wiki(name, level=None): async def char_wiki(name, mode="char", level=None): + im = '' data = await get_char_info(name, mode, level if mode == "char" else None) if mode == "char": if isinstance(data, list): @@ -744,4 +748,4 @@ async def char_wiki(name, mode="char", level=None): im = "【{}】\n{}".format(skill_name, skill_info) else: im = "不存在该天赋。" - return im + return im \ No newline at end of file