This commit is contained in:
Wuyi无疑 2022-03-29 23:13:03 +08:00
parent a2b1f47256
commit d26849207a
4 changed files with 283 additions and 228 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/.idea/ /.idea/
mihoyo_libs/mihoyo_bbs/bg/**

View File

@ -16,7 +16,7 @@ from nonebot import logger
mhyVersion = "2.11.1" mhyVersion = "2.11.1"
BASE_PATH = os.path.dirname(__file__) 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') 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("深渊信息读取老Api失败")
logger.info(e.with_traceback) logger.info(e.with_traceback)
async def get_calculate_info(uid, char_id, ck, server_id="cn_gf01"): async def get_calculate_info(uid, char_id, ck, server_id="cn_gf01"):
if uid[0] == '5': if uid[0] == '5':
server_id = "cn_qd01" server_id = "cn_qd01"
@ -749,6 +750,7 @@ async def get_calculate_info(uid, char_id, ck, server_id="cn_gf01"):
data = json.loads(req.text) data = json.loads(req.text)
return data return data
async def get_mihoyo_bbs_info(mysid, ck): async def get_mihoyo_bbs_info(mysid, ck):
try: try:
async with AsyncClient() as client: async with AsyncClient() as client:

View File

@ -1,12 +1,10 @@
import json
import asyncio import asyncio
from typing import Optional, Union, Any
import os,time
import math import math
import threading import threading
from base64 import b64encode from base64 import b64encode
from io import BytesIO from io import BytesIO
from re import findall from re import Match, findall
from typing import Optional
import numpy as np import numpy as np
from PIL import Image, ImageDraw, ImageFilter, ImageFont from PIL import Image, ImageDraw, ImageFilter, ImageFont
@ -17,7 +15,7 @@ from wordcloud import WordCloud
from .get_data import * from .get_data import *
FILE_PATH = os.path.dirname(__file__) 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_PATH = os.path.join(FILE2_PATH, 'chars')
CHAR_DONE_PATH = os.path.join(FILE2_PATH, 'char_done') CHAR_DONE_PATH = os.path.join(FILE2_PATH, 'char_done')
CHAR_IMG_PATH = os.path.join(FILE2_PATH, 'char_img') CHAR_IMG_PATH = os.path.join(FILE2_PATH, 'char_img')
@ -28,8 +26,9 @@ TEXT_PATH = os.path.join(FILE2_PATH, 'texture2d')
WEAPON_PATH = os.path.join(FILE2_PATH, 'weapon') WEAPON_PATH = os.path.join(FILE2_PATH, 'weapon')
BG_PATH = os.path.join(FILE2_PATH, 'bg') BG_PATH = os.path.join(FILE2_PATH, 'bg')
class customize_image: class customize_image:
def __init__(self,image: str,based_w: int,based_h: int) -> None: 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_img = self.get_image(image, based_w, based_h)
self.bg_color = self.get_bg_color(self.bg_img) self.bg_color = self.get_bg_color(self.bg_img)
@ -39,7 +38,8 @@ class customize_image:
self.bg_detail_color = self.get_bg_detail_color(self.bg_color) self.bg_detail_color = self.get_bg_detail_color(self.bg_color)
self.char_high_color = self.get_char_high_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) 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))])) if os.path.isfile(os.path.join(BG_PATH, x))]))
@ -65,7 +65,8 @@ class customize_image:
return bg_img 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 color = 8
q = edit_bg.quantize(colors=color, method=2) q = edit_bg.quantize(colors=color, method=2)
@ -82,7 +83,8 @@ class customize_image:
# bg_color = bg # bg_color = bg
return bg_color 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确定文字主色 # 通过背景主色bg_color确定文字主色
r = 125 r = 125
if max(*bg_color) > 255 - r: if max(*bg_color) > 255 - r:
@ -92,7 +94,8 @@ class customize_image:
math.floor(bg_color[2] + r if bg_color[2] + r <= 255 else 255)) math.floor(bg_color[2] + r if bg_color[2] + r <= 255 else 255))
return text_color 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 r = 140
if max(*bg_color) > 255 - r: if max(*bg_color) > 255 - r:
r *= -1 r *= -1
@ -101,7 +104,8 @@ class customize_image:
math.floor(bg_color[2] + 5 if bg_color[2] + r <= 255 else 255)) math.floor(bg_color[2] + 5 if bg_color[2] + r <= 255 else 255))
return char_color 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 r = 140
d = 20 d = 20
if max(*bg_color) > 255 - r: if max(*bg_color) > 255 - r:
@ -111,7 +115,8 @@ class customize_image:
math.floor(bg_color[2] + d if bg_color[2] + r <= 255 else 255)) math.floor(bg_color[2] + d if bg_color[2] + r <= 255 else 255))
return char_color 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 r = 140
if max(*bg_color) > 255 - r: if max(*bg_color) > 255 - r:
r *= -1 r *= -1
@ -120,18 +125,19 @@ class customize_image:
math.floor(bg_color[2] - 20 if bg_color[2] + r <= 255 else 255)) math.floor(bg_color[2] - 20 if bg_color[2] + r <= 255 else 255))
return bg_detail_color 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] red_color = color[0]
green_color = color[1] green_color = color[1]
blue_color = color[2] blue_color = color[2]
highlight_color = {} 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,
highlight_color["green"] = green_color - 127 if green_color > 127 else 127 "blue" : blue_color - 127 if blue_color > 127 else 127}
highlight_color["blue"] = blue_color - 127 if blue_color > 127 else 127
max_color = max(highlight_color.values()) max_color = max(highlight_color.values())
name = ''
for _highlight_color in highlight_color: for _highlight_color in highlight_color:
if highlight_color[_highlight_color] == max_color: if highlight_color[_highlight_color] == max_color:
name = str(_highlight_color) name = str(_highlight_color)
@ -145,6 +151,7 @@ class customize_image:
else: else:
return 0, 0, 0 # Error return 0, 0, 0 # Error
def genshin_font(size: int): def genshin_font(size: int):
return ImageFont.truetype(os.path.join(FILE2_PATH, "yuanshen.ttf"), size=size) return ImageFont.truetype(os.path.join(FILE2_PATH, "yuanshen.ttf"), size=size)
@ -184,13 +191,14 @@ def get_rel_pic(url: str):
with open(os.path.join(REL_PATH, url.split('/')[-1]), 'wb') as f: with open(os.path.join(REL_PATH, url.split('/')[-1]), 'wb') as f:
f.write(get(url).content) f.write(get(url).content)
class get_cookies: class get_cookies:
def __init__(self) -> None: def __init__(self) -> None:
self.useable_cookies: Optional[str] = None self.useable_cookies: Optional[str] = None
self.uid: Optional[str] = None self.uid: Optional[str] = None
self.mode: Optional[int] = None self.mode: Optional[int] = None
self.raw_abyss_data: Optional[json] = None self.raw_abyss_data: Optional[dict] = None
self.raw_data: Optional[json] = None self.raw_data: Optional[dict] = None
self.nickname: Optional[int] = None self.nickname: Optional[int] = None
self.schedule_type: Optional[str] = None self.schedule_type: Optional[str] = None
@ -250,27 +258,28 @@ class get_cookies:
else: else:
return "没有可以使用的Cookies" 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 = 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 mx, my = rectangle.size
i.paste(corner, (0, 0), corner) img.paste(corner, (0, 0), corner)
i.paste(corner.rotate(90), (0, my - radius), corner.rotate(90)) img.paste(corner.rotate(90), (0, my - _radius), corner.rotate(90))
i.paste(corner.rotate(180), (mx - radius, my - radius), corner.rotate(180)) img.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.rotate(270), (mx - _radius, 0), corner.rotate(270))
draw = ImageDraw.Draw(i) draw = ImageDraw.Draw(img)
draw.rectangle(((radius, 0), (mx - radius, my)), fill=solid_fill) draw.rectangle(((_radius, 0), (mx - _radius, my)), fill=solid_fill)
draw.rectangle(((0, radius), (mx, my - radius)), fill=solid_fill) draw.rectangle(((0, _radius), (mx, my - _radius)), fill=solid_fill)
return i return img
nickname = '' nickname = ''
while True: while True:
@ -533,11 +542,12 @@ async def draw_word_cloud(uid: str, image: Optional[str] = None, mode: int = 2):
resultmes = imgmes resultmes = imgmes
return resultmes return resultmes
async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"): async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"):
# 获取Cookies # 获取Cookies
data_def = get_cookies() data_def = get_cookies()
retcode = await data_def.get_useable_cookies(uid, mode, date) retcode = await data_def.get_useable_cookies(uid, mode, date)
if retcode != True: if not retcode:
return retcode return retcode
raw_char_data = data_def.raw_data raw_char_data = data_def.raw_data
raw_data = data_def.raw_abyss_data raw_data = data_def.raw_abyss_data
@ -559,7 +569,7 @@ async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"):
bg_img = image_def.bg_img bg_img = image_def.bg_img
bg_color = image_def.bg_color bg_color = image_def.bg_color
text_color = image_def.text_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") 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 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 # 获取Cookies
data_def = get_cookies() data_def = get_cookies()
retcode = await data_def.get_useable_cookies(uid, mode, date) retcode = await data_def.get_useable_cookies(uid, mode, date)
if retcode != True: if not retcode:
return retcode return retcode
raw_char_data = data_def.raw_data raw_char_data = data_def.raw_data
raw_data = data_def.raw_abyss_data raw_data = data_def.raw_abyss_data
@ -841,7 +852,7 @@ async def draw_abyss_pic(uid: str, nickname: str, floor_num : int, image: Option
bg_img = image_def.bg_img bg_img = image_def.bg_img
bg_color = image_def.bg_color bg_color = image_def.bg_color
text_color = image_def.text_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") 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 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 # 获取Cookies
data_def = get_cookies() data_def = get_cookies()
retcode = await data_def.get_useable_cookies(uid, mode) retcode = await data_def.get_useable_cookies(uid, mode)
if retcode != True: if not retcode:
return retcode return retcode
use_cookies = data_def.useable_cookies use_cookies = data_def.useable_cookies
raw_data = data_def.raw_data raw_data = data_def.raw_data
@ -1002,7 +1093,7 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i
bg_img = image_def.bg_img bg_img = image_def.bg_img
bg_color = image_def.bg_color bg_color = image_def.bg_color
text_color = image_def.text_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 char_color = image_def.char_color
bg_detail_color = image_def.bg_detail_color bg_detail_color = image_def.bg_detail_color
char_high_color = image_def.char_high_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((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)) 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(raw_data['world_explorations'][2]['level']), text_color, genshin_font(22))
@ -1141,71 +1233,8 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i
if char_num > 8: if char_num > 8:
tasks = [] tasks = []
for index, i in enumerate(char_datas): 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], tasks.append(draw_char_pic(bg_img, i, index, char_color, text_color, bg_detail_color, char_high_color, uid,
text_color: tuple[int, int, int], bg_detail_color: tuple[int, int, int], use_cookies))
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))
await asyncio.wait(tasks) await asyncio.wait(tasks)
""" """
char_mingzuo = 0 char_mingzuo = 0
@ -1392,8 +1421,7 @@ async def draw_pic(uid: str, nickname: str, image: Optional[str] = None, mode: i
return resultmes 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: def seconds2hours(seconds: int) -> str:
m, s = divmod(int(seconds), 60) m, s = divmod(int(seconds), 60)
h, m = divmod(m, 60) h, m = divmod(m, 60)
@ -1402,7 +1430,7 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str:
# 获取Cookies # 获取Cookies
data_def = get_cookies() data_def = get_cookies()
retcode = await data_def.get_useable_cookies(uid) retcode = await data_def.get_useable_cookies(uid)
if retcode != True: if not retcode:
return retcode return retcode
raw_data = data_def.raw_data raw_data = data_def.raw_data
char_data = raw_data["data"]["avatars"] char_data = raw_data["data"]["avatars"]
@ -1456,7 +1484,6 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str:
bg_img.paste(info3, (0, 0), info3) bg_img.paste(info3, (0, 0), info3)
text_draw = ImageDraw.Draw(bg_img) text_draw = ImageDraw.Draw(bg_img)
# 用户信息 # 用户信息
@ -1464,28 +1491,45 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str:
text_draw.text((235, 170), 'UID ' + f"{uid}", text_color, genshin_font(14), 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, 148),
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") 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, 287), f"{award_data['data']['month_data']['current_primogems']}", text_color, genshin_font(21),
text_draw.text((722, 323), f"{award_data['data']['month_data']['last_primogems']}", text_color, genshin_font(21),anchor="lm") 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, 359), f"{award_data['data']['month_data']['current_mora']}", text_color, genshin_font(21),
text_draw.text((722, 395), f"{award_data['data']['month_data']['last_mora']}", text_color, genshin_font(21),anchor="lm") 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']): 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((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, 314), f"{daily_data['current_resin']}/{daily_data['max_resin']}", text_color, genshin_font(26),
text_draw.text((390, 408), f'{daily_data["current_home_coin"]}/{daily_data["max_home_coin"]}', text_color, genshin_font(26),anchor="lm") 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, 408), f'{daily_data["current_home_coin"]}/{daily_data["max_home_coin"]}', text_color,
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") 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")
# 树脂恢复时间计算 # 树脂恢复时间计算
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( resin_recovery_time = seconds2hours(
daily_data['resin_recovery_time']) daily_data['resin_recovery_time'])
next_resin_rec_time = seconds2hours( next_resin_rec_time = seconds2hours(
@ -1499,8 +1543,8 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str:
# 洞天宝钱时间计算 # 洞天宝钱时间计算
coin_rec_time = seconds2hours(int(daily_data["home_coin_recovery_time"])) coin_rec_time = seconds2hours(int(daily_data["home_coin_recovery_time"]))
if daily_data["home_coin_recovery_time"] == "0": if int(daily_data["home_coin_recovery_time"]) <= 0:
text_draw.text((170, 425), f"", text_color, genshin_font(18),anchor="lm") text_draw.text((170, 425), f"达到上限", text_color, genshin_font(18), anchor="lm")
else: else:
coin_add_speed = math.ceil((daily_data["max_home_coin"] - daily_data["current_home_coin"]) / ( coin_add_speed = math.ceil((daily_data["max_home_coin"] - daily_data["current_home_coin"]) / (
int(daily_data["home_coin_recovery_time"]) / 60 / 60)) int(daily_data["home_coin_recovery_time"]) / 60 / 60))
@ -1525,11 +1569,14 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str:
# 派遣 # 派遣
for index, i in enumerate(daily_data["expeditions"]): for index, i in enumerate(daily_data["expeditions"]):
name = ''
for j in char_data: for j in char_data:
if i["avatar_side_icon"].split("_")[-1] == j["image"].split("_")[-1]: if i["avatar_side_icon"].split("_")[-1] == j["image"].split("_")[-1]:
name = j["name"] 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")): if not os.path.exists(
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") 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_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 = Image.open(char_stand_img)
# char_stand_mask = Image.open(os.path.join(TEXT_PATH, "stand_mask.png")) # char_stand_mask = Image.open(os.path.join(TEXT_PATH, "stand_mask.png"))
@ -1541,7 +1588,7 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str:
char_namecard_img = Image.open(os.path.join(CHAR_NAMECARD_PATH, str(name + ".png"))) 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 = 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.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(charset_mask, (0, 0), char_bg)
@ -1568,6 +1615,7 @@ async def draw_info_pic(uid: str,image :Optional[str] = None) -> str:
resultmes = imgmes resultmes = imgmes
return resultmes return resultmes
async def draw_event_pic() -> None: async def draw_event_pic() -> None:
raw_data = await get_genshin_events("List") raw_data = await get_genshin_events("List")
raw_time_data = await get_genshin_events("Content") raw_time_data = await get_genshin_events("Content")

View File

@ -1,15 +1,10 @@
import json
import math import math
import os import os
import sys import sys
import random
import re
import sqlite3
from base64 import b64encode from base64 import b64encode
from openpyxl import load_workbook
from io import BytesIO from io import BytesIO
import requests from openpyxl import load_workbook
sys.path.append(os.path.dirname(os.path.abspath(__file__))) sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from .get_data import * from .get_data import *
@ -17,7 +12,7 @@ from .get_image import draw_event_pic
import get_mihoyo_bbs_coin as coin import get_mihoyo_bbs_coin as coin
FILE_PATH = os.path.dirname(__file__) 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') INDEX_PATH = os.path.join(FILE2_PATH, 'index')
Texture_PATH = os.path.join(FILE2_PATH, 'texture2d') Texture_PATH = os.path.join(FILE2_PATH, 'texture2d')
@ -160,6 +155,7 @@ char_adv_im = '''【{}】
圣遗物 圣遗物
{}''' {}'''
async def weapon_adv(name): async def weapon_adv(name):
char_adv_path = os.path.join(FILE_PATH, "mihoyo_libs/Genshin All Char.xlsx") char_adv_path = os.path.join(FILE_PATH, "mihoyo_libs/Genshin All Char.xlsx")
wb = load_workbook(char_adv_path) wb = load_workbook(char_adv_path)
@ -182,6 +178,7 @@ async def weapon_adv(name):
im = "没有角色能使用【{}".format(weapon_name) im = "没有角色能使用【{}".format(weapon_name)
return im return im
async def char_adv(name): async def char_adv(name):
char_name = None char_name = None
char_adv_path = os.path.join(FILE_PATH, "mihoyo_libs/Genshin All Char.xlsx") char_adv_path = os.path.join(FILE_PATH, "mihoyo_libs/Genshin All Char.xlsx")
@ -239,6 +236,7 @@ async def char_adv(name):
im = char_adv_im.format(char_name, weapon_5star, weapon_4star, weapon_3star, artifacts) im = char_adv_im.format(char_name, weapon_5star, weapon_4star, weapon_3star, artifacts)
return im return im
async def deal_ck(mes, qid): async def deal_ck(mes, qid):
if "stoken" in mes: if "stoken" in mes:
login_ticket = re.search(r"login_ticket=([0-9a-zA-Z]+)", mes).group(0).split('=')[1] login_ticket = re.search(r"login_ticket=([0-9a-zA-Z]+)", mes).group(0).split('=')[1]
@ -278,6 +276,7 @@ async def deal_ck(mes, qid):
return f'添加Cookies成功\nCookies属于个人重要信息如果你是在不知情的情况下添加请马上修改米游社账户密码保护个人隐私\n————\n' \ return f'添加Cookies成功\nCookies属于个人重要信息如果你是在不知情的情况下添加请马上修改米游社账户密码保护个人隐私\n————\n' \
f'如果需要【开启自动签到】和【开启推送】还需要在【群聊中】使用命令“绑定uid”绑定你的uid。\n例如绑定uid123456789。' f'如果需要【开启自动签到】和【开启推送】还需要在【群聊中】使用命令“绑定uid”绑定你的uid。\n例如绑定uid123456789。'
async def award(uid): async def award(uid):
data = await get_award(uid) data = await get_award(uid)
nickname = data['data']['nickname'] nickname = data['data']['nickname']
@ -422,6 +421,7 @@ async def daily(mode="push", uid=None):
temp_list = [] temp_list = []
conn = sqlite3.connect('ID_DATA.db') conn = sqlite3.connect('ID_DATA.db')
c = conn.cursor() c = conn.cursor()
c_data = None
if mode == "push": if mode == "push":
cursor = c.execute( cursor = c.execute(
"SELECT * FROM NewCookiesTable WHERE StatusA != ?", ("off",)) "SELECT * FROM NewCookiesTable WHERE StatusA != ?", ("off",))
@ -509,6 +509,7 @@ async def daily(mode="push", uid=None):
{"qid": row[2], "gid": row[3], "message": send_mes}) {"qid": row[2], "gid": row[3], "message": send_mes})
return temp_list 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 = await select_db(qid, mode="uid")
uid = uid[0] uid = uid[0]
@ -522,6 +523,7 @@ async def mihoyo_coin(qid,s_cookies = None):
im = "你还没有绑定Stoken~" im = "你还没有绑定Stoken~"
return im return im
async def get_event_pic(): async def get_event_pic():
img_path = os.path.join(FILE2_PATH, "event.jpg") img_path = os.path.join(FILE2_PATH, "event.jpg")
while True: while True:
@ -535,6 +537,7 @@ async def get_event_pic():
await draw_event_pic() await draw_event_pic()
return img_mes return img_mes
async def weapon_wiki(name, level=None): async def weapon_wiki(name, level=None):
data = await get_weapon_info(name) data = await get_weapon_info(name)
if "errcode" in data: if "errcode" in data:
@ -581,6 +584,7 @@ async def weapon_wiki(name, level=None):
async def char_wiki(name, mode="char", 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) data = await get_char_info(name, mode, level if mode == "char" else None)
if mode == "char": if mode == "char":
if isinstance(data, list): if isinstance(data, list):