3
0

0.4.0 支持怎么养、给谁用 & 更新周本图片 & 支持深渊

This commit is contained in:
xtaodada 2022-03-17 23:44:43 +08:00
parent 6c677d1d8e
commit a395db7b50
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
13 changed files with 1260 additions and 39 deletions

Binary file not shown.

52
assets/data/id2name.json Normal file
View File

@ -0,0 +1,52 @@
{
"10000002": "神里绫华",
"10000003": "琴",
"10000006": "丽莎",
"10000005": "空",
"10000007": "荧",
"10000014": "芭芭拉",
"10000015": "凯亚",
"10000016": "迪卢克",
"10000020": "雷泽",
"10000021": "安柏",
"10000022": "温迪",
"10000023": "香菱",
"10000024": "北斗",
"10000025": "行秋",
"10000026": "魈",
"10000027": "凝光",
"10000029": "可莉",
"10000030": "钟离",
"10000031": "菲谢尔",
"10000032": "班尼特",
"10000033": "达达利亚",
"10000034": "诺艾尔",
"10000035": "七七",
"10000036": "重云",
"10000037": "甘雨",
"10000038": "阿贝多",
"10000039": "迪奥娜",
"10000041": "莫娜",
"10000042": "刻晴",
"10000043": "砂糖",
"10000044": "辛焱",
"10000045": "罗莎莉亚",
"10000046": "胡桃",
"10000047": "枫原万叶",
"10000048": "烟绯",
"10000049": "宵宫",
"10000050": "托马",
"10000051": "优菈",
"10000052": "雷电将军",
"10000053": "早柚",
"10000054": "珊瑚宫心海",
"10000055": "五郎",
"10000056": "九条裟罗",
"10000057": "荒泷一斗",
"10000058": "八重神子",
"10000062": "埃洛伊",
"10000063": "申鹤",
"10000064": "云堇",
"10000066": "神里绫人",
"注释1": "10000005/7分别对应哥哥和妹妹"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

After

Width:  |  Height:  |  Size: 7.4 MiB

91
defs/char_adv.py Normal file
View File

@ -0,0 +1,91 @@
import os
from openpyxl import load_workbook
FILE_PATH = "assets"
char_adv_im = '''{}
五星武器{}
四星武器{}
三星武器{}
圣遗物
{}'''
async def weapon_adv(name):
char_adv_path = os.path.join(FILE_PATH, "Genshin_All_Char.xlsx")
wb = load_workbook(char_adv_path)
ws = wb.active
weapon_name = ""
char_list = []
for c in range(2, 5):
for r in range(2, 300):
if ws.cell(r, c).value:
# if all(i in ws.cell(r,c).value for i in name):
if name in ws.cell(r, c).value:
weapon_name = ws.cell(r, c).value
char_list.append(ws.cell(2 + ((r - 2) // 5) * 5, 1).value)
if char_list:
im = ''.join(char_list)
im = im + " 可能会用到【{}".format(weapon_name)
else:
im = " 没有角色能使用【{}".format(weapon_name)
return im
async def char_adv(name):
char_adv_path = os.path.join(FILE_PATH, "Genshin_All_Char.xlsx")
wb = load_workbook(char_adv_path)
ws = wb.active
char_list = ws["A"]
index = None
for i in char_list:
if i.value:
if all(g in i.value for g in name):
# if name in i.value:
index = i.row
char_name = i.value
if index:
weapon_5star = ""
for i in range(index, index + 5):
if ws.cell(i, 2).value:
weapon_5star += ws.cell(i, 2).value + ">"
if weapon_5star != "":
weapon_5star = weapon_5star[:-1]
else:
weapon_5star = "无推荐"
weapon_4star = ""
for i in range(index, index + 5):
if ws.cell(i, 3).value:
weapon_4star += ws.cell(i, 3).value + ">"
if weapon_4star != "":
weapon_4star = weapon_4star[:-1]
else:
weapon_4star = "无推荐"
weapon_3star = ""
for i in range(index, index + 5):
if ws.cell(i, 4).value:
weapon_3star += ws.cell(i, 4).value + ">"
if weapon_3star != "":
weapon_3star = weapon_3star[:-1]
else:
weapon_3star = "无推荐"
artifacts = ""
for i in range(index, index + 5):
if ws.cell(i, 5).value:
if ws.cell(i, 6).value:
artifacts += ws.cell(i, 5).value + "*2" + ws.cell(i, 6).value + "*2" + "\n"
else:
artifacts += ws.cell(i, 5).value + "*4" + "\n"
if artifacts != "":
artifacts = artifacts[:-1]
else:
artifacts = "无推荐"
im = char_adv_im.format(char_name, weapon_5star, weapon_4star, weapon_3star, artifacts) # noqa
return im

View File

@ -9,12 +9,19 @@ import traceback
from shutil import copyfile from shutil import copyfile
import requests import requests
from httpx import AsyncClient
from ci import client from ci import client
from defs.mysbbs import MihoyoBbs from defs.mysbbs import MihoyoBbs
mhyVersion = "2.11.1" mhyVersion = "2.11.1"
def regex_func(value, patter):
c_pattern = re.compile(r"account_id={}".format(patter))
return c_pattern.search(value) is not None
async def cookiesDB(uid, Cookies, qid): async def cookiesDB(uid, Cookies, qid):
conn = sqlite3.connect('ID_DATA.db') conn = sqlite3.connect('ID_DATA.db')
c = conn.cursor() c = conn.cursor()
@ -406,29 +413,28 @@ def functionRegex(value, patter):
def cacheDB(uid, mode=1, mys=None): def cacheDB(uid, mode=1, mys=None):
use = ''
conn = sqlite3.connect('ID_DATA.db') conn = sqlite3.connect('ID_DATA.db')
c = conn.cursor() c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS CookiesCache c.execute('''CREATE TABLE IF NOT EXISTS CookiesCache
(UID TEXT PRIMARY KEY, (UID TEXT PRIMARY KEY,
MYSID TEXT, MYSID TEXT,
Cookies TEXT);''') Cookies TEXT);''')
if mode == 2:
cursor = c.execute("SELECT * FROM CookiesCache WHERE MYSID = ?", (uid,)) if mode == 1:
c_data = cursor.fetchall()
else:
if mys: if mys:
cursor = c.execute("SELECT * FROM CookiesCache WHERE MYSID = ?", (mys,)) cursor = c.execute("SELECT * FROM CookiesCache WHERE MYSID = ?", (mys,))
c_data = cursor.fetchall()
else: else:
cursor = c.execute("SELECT * FROM CookiesCache WHERE UID = ?", (uid,)) cursor = c.execute("SELECT * FROM CookiesCache WHERE UID = ?", (uid,))
c_data = cursor.fetchall() else:
cursor = c.execute("SELECT * FROM CookiesCache WHERE MYSID = ?", (uid,))
c_data = cursor.fetchall()
if len(c_data) == 0: if len(c_data) == 0:
if mode == 2: if mode == 2:
conn.create_function("REGEXP", 2, functionRegex) conn.create_function("REGEXP", 2, regex_func)
cursor = c.execute("SELECT * FROM NewCookiesTable WHERE REGEXP(Cookies, ?)", (uid,)) cursor = c.execute("SELECT * FROM NewCookiesTable WHERE REGEXP(Cookies, ?)", (uid,))
d_data = cursor.fetchall() d_data = cursor.fetchall()
else: else:
cursor = c.execute("SELECT * FROM NewCookiesTable WHERE UID = ?", (uid,)) cursor = c.execute("SELECT * FROM NewCookiesTable WHERE UID = ?", (uid,))
d_data = cursor.fetchall() d_data = cursor.fetchall()
@ -438,33 +444,33 @@ def cacheDB(uid, mode=1, mys=None):
use = d_data[0][1] use = d_data[0][1]
if mode == 1: if mode == 1:
c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,UID) \ c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,UID) \
VALUES (?, ?)", (use, uid)) VALUES (?, ?)", (use, uid))
elif mode == 2: elif mode == 2:
c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,MYSID) \ c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,MYSID) \
VALUES (?, ?)", (use, uid)) VALUES (?, ?)", (use, uid))
else: else:
cookiesrow = c.execute("SELECT * FROM NewCookiesTable WHERE Extra IS NULL ORDER BY RANDOM() LIMIT 1") cookies_row = c.execute("SELECT * FROM NewCookiesTable WHERE Extra IS NULL ORDER BY RANDOM() LIMIT 1")
e_data = cookiesrow.fetchall() e_data = cookies_row.fetchall()
if len(e_data) != 0: if len(e_data) != 0:
if mode == 1: if mode == 1:
c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,UID) \ c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,UID) \
VALUES (?, ?)", (e_data[0][1], uid)) VALUES (?, ?)", (e_data[0][1], uid))
elif mode == 2: elif mode == 2:
c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,MYSID) \ c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,MYSID) \
VALUES (?, ?)", (e_data[0][1], uid)) VALUES (?, ?)", (e_data[0][1], uid))
use = e_data[0][1] use = e_data[0][1]
else: else:
return "没有可以使用的Cookies" return "没有可以使用的Cookies"
else: else:
cookiesrow = c.execute("SELECT * FROM NewCookiesTable WHERE Extra IS NULL ORDER BY RANDOM() LIMIT 1") cookies_row = c.execute("SELECT * FROM NewCookiesTable WHERE Extra IS NULL ORDER BY RANDOM() LIMIT 1")
e_data = cookiesrow.fetchall() e_data = cookies_row.fetchall()
if len(e_data) != 0: if len(e_data) != 0:
if mode == 1: if mode == 1:
c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,UID) \ c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,UID) \
VALUES (?, ?)", (e_data[0][1], uid)) VALUES (?, ?)", (e_data[0][1], uid))
elif mode == 2: elif mode == 2:
c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,MYSID) \ c.execute("INSERT OR IGNORE INTO CookiesCache (Cookies,MYSID) \
VALUES (?, ?)", (e_data[0][1], uid)) VALUES (?, ?)", (e_data[0][1], uid))
use = e_data[0][1] use = e_data[0][1]
else: else:
return "没有可以使用的Cookies" return "没有可以使用的Cookies"
@ -608,3 +614,63 @@ async def GetInfo(Uid, ck, ServerID="cn_gf01"):
except Exception as e: except Exception as e:
print("米游社基础信息读取老Api失败") print("米游社基础信息读取老Api失败")
print(e.with_traceback) print(e.with_traceback)
async def get_spiral_abyss_info(uid, ck, schedule_type="1", server_id="cn_gf01"):
if uid[0] == '5':
server_id = "cn_qd01"
try:
async with AsyncClient() as c:
req = await c.get(
url="https://api-takumi.mihoyo.com/game_record/app/genshin/api/spiralAbyss",
headers={
'DS': DSGet("role_id=" + uid + "&schedule_type=" + schedule_type + "&server=" + server_id),
'Origin': 'https://webstatic.mihoyo.com',
'Cookie': ck,
'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/'
},
params={
"schedule_type": schedule_type,
"role_id": uid,
"server": server_id
}
)
data = json.loads(req.text)
return data
except requests.exceptions.SSLError:
try:
async with AsyncClient() as c:
req = await c.get(
url="https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/spiralAbyss",
headers={
'DS': DSGet(
"role_id=" + uid + "&schedule_type=" + schedule_type + "&server=" + server_id),
'Origin': 'https://webstatic.mihoyo.com',
'Cookie': ck,
'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/'
},
params={
"role_id": uid,
"server": server_id,
"bbs_presentation_style": "fullscreen",
"bbs_auth_required": "true",
"utm_source": "bbs",
"utm_medium": "mys",
"utm_campaign": "icon"
}
)
data = json.loads(req.text)
return data
except json.decoder.JSONDecodeError:
print("深渊信息读取新Api失败")
except Exception as e:
print("深渊信息读取老Api失败")
print(e.with_traceback)

587
defs/spiral_abyss.py Normal file
View File

@ -0,0 +1,587 @@
import math
import os
import random
import time
from io import BytesIO
from httpx import get
from PIL import Image, ImageDraw, ImageFont
from defs.db import cacheDB, GetMysInfo, GetInfo, errorDB, get_spiral_abyss_info
FILE2_PATH = os.path.join("assets")
CHAR_DONE_PATH = os.path.join(FILE2_PATH, "char_done")
TEXT_PATH = os.path.join(FILE2_PATH, "bg2")
BG_PATH = os.path.join(FILE2_PATH, "bg")
def get_char_done_pic(_id, url, star):
char_data = get(url).content
if star == 4:
star1_path = os.path.join(TEXT_PATH, '4star_1.png')
star2_path = os.path.join(TEXT_PATH, '4star_2.png')
else:
star1_path = os.path.join(TEXT_PATH, '5star_1.png')
star2_path = os.path.join(TEXT_PATH, '5star_2.png')
star_1 = Image.open(star1_path)
star_2 = Image.open(star2_path)
char_img = Image.open(BytesIO(char_data)).resize((104, 104), Image.ANTIALIAS)
star_1.paste(char_img, (12, 15), char_img)
star_1.paste(star_2, (0, 0), star_2)
star_1.save(os.path.join(CHAR_DONE_PATH, str(_id) + '.png'))
def genshin_font(size):
return ImageFont.truetype(f"assets{os.sep}fonts{os.sep}yuan_shen.ttf", size=size, encoding="utf-8")
async def draw_abyss0_pic(uid, nickname, image=None, mode=2, date="1"):
# 获取Cookies
while True:
use_cookies = cacheDB(uid, mode - 1)
if use_cookies == '':
return "绑定记录不存在。"
elif use_cookies == "没有可以使用的Cookies":
return "没有可以使用的Cookies"
if mode == 3:
mys_data = await GetMysInfo(uid, use_cookies)
for i in mys_data['data']['list']:
if i['game_id'] != 2:
mys_data['data']['list'].remove(i)
uid = mys_data['data']['list'][0]['game_role_id']
nickname = mys_data['data']['list'][0]['nickname']
raw_data = await get_spiral_abyss_info(uid, use_cookies, date)
raw_char_data = await GetInfo(uid, use_cookies)
if raw_data["retcode"] != 0:
if raw_data["retcode"] == 10001:
# return ("Cookie错误/过期请重置Cookie")
errorDB(use_cookies, "error")
elif raw_data["retcode"] == 10101:
# return ("当前cookies已达到30人上限")
errorDB(use_cookies, "limit30")
elif raw_data["retcode"] == 10102:
return "当前查询id已经设置了隐私无法查询"
else:
return (
"Api报错返回内容为\r\n"
+ str(raw_data) + "\r\n出现这种情况可能的UID输入错误 or 不存在"
)
else:
break
# 获取数据
raw_data = raw_data["data"]
raw_char_data = raw_char_data['data']["avatars"]
# 获取查询者数据
if not raw_data['floors']:
return ""
floors_data = raw_data['floors'][-1]
levels_num = len(floors_data['levels'])
# 获取背景图片
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 image:
image_data = image.group(2)
edit_bg = Image.open(BytesIO(get(image_data).content))
else:
edit_bg = Image.open(bg2_path)
# 确定图片的长宽
based_w = 900
based_h = 660 + levels_num * 315
based_scale = '%.3f' % (based_w / based_h)
w, h = edit_bg.size
scale_f = '%.3f' % (w / h)
new_w = math.ceil(based_h * float(scale_f))
new_h = math.ceil(based_w / float(scale_f))
if scale_f > based_scale:
bg_img2 = edit_bg.resize((new_w, based_h), Image.ANTIALIAS)
else:
bg_img2 = edit_bg.resize((based_w, new_h), Image.ANTIALIAS)
bg_img = bg_img2.crop((0, 0, based_w, based_h))
# 获取背景主色
q = edit_bg.quantize(colors=3, method=2)
bg_num_temp = 0
for i in range(0, 3):
bg = tuple(q.getpalette()[i * 3:(i * 3) + 3])
bg_num = bg[0] + bg[1] + bg[2]
if bg_num >= bg_num_temp:
bg_num_temp = bg_num
bg_color = (bg[0], bg[1], bg[2])
# 通过背景主色bg_color确定文字主色
r = 140
if max(*bg_color) > 255 - r:
r *= -1
new_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))
# 确定贴图路径
abyss0_path = os.path.join(TEXT_PATH, "abyss_0.png")
abyss3_path = os.path.join(TEXT_PATH, "abyss_3.png")
abyss_star0_path = os.path.join(TEXT_PATH, "abyss_star0.png")
abyss_star1_path = os.path.join(TEXT_PATH, "abyss_star1.png")
avatar_bg_path = os.path.join(TEXT_PATH, "avatar_bg.png")
avatar_fg_path = os.path.join(TEXT_PATH, "avatar_fg.png")
all_mask_path = os.path.join(TEXT_PATH, "All_Mask.png")
# 转换遮罩的颜色、大小匹配并paste上去
all_mask = Image.open(all_mask_path).resize(bg_img.size, Image.ANTIALIAS)
all_mask_img = Image.new("RGBA", (based_w, based_h), bg_color)
bg_img.paste(all_mask_img, (0, 0), all_mask)
# 开启图片
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)
"""
x1, y1 = 65, 276
radius = 15
cropped_img1 = bg_img.crop((x1, y1, 836, 607))
blurred_img1 = cropped_img1.filter(ImageFilter.GaussianBlur(5),).convert("RGBA")
bg_img.paste(blurred_img1, (x1, y1), create_rounded_rectangle_mask(cropped_img1,radius))
for i in range(0,len(floors_data['levels'])):
x2, y2 = 65, 630 + 315*i
radius = 15
cropped_img2 = bg_img.crop((x2, y2, 836, 925+315*i))
blurred_img2 = cropped_img2.filter(ImageFilter.GaussianBlur(5),).convert("RGBA")
bg_img.paste(blurred_img2, (x2, y2), create_rounded_rectangle_mask(cropped_img2,radius))
"""
abyss0_bg_color = Image.new("RGBA", (900, 620), new_color)
abyss0 = Image.new("RGBA", (900, 620), (0, 0, 0, 0))
abyss0_pic = Image.open(abyss0_path)
abyss0.paste(abyss0_bg_color, (0, 0), abyss0_pic)
abyss3 = Image.open(abyss3_path)
abyss_star0 = Image.open(abyss_star0_path)
abyss_star1 = Image.open(abyss_star1_path)
for i in range(0, 4):
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(raw_data["reveal_rank"][i]["avatar_id"]) + ".png")):
get_char_done_pic(raw_data["reveal_rank"][i]["avatar_id"], raw_data["reveal_rank"][i]["avatar_icon"],
raw_data["reveal_rank"][i]["rarity"])
char = os.path.join(CHAR_DONE_PATH, str(raw_data["reveal_rank"][i]["avatar_id"]) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == raw_data["reveal_rank"][i]["avatar_id"]:
char_draw.text((63.5, 117), f'{str(raw_data["reveal_rank"][i]["value"])}', (21, 21, 21),
genshin_font(18), anchor="mm")
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (82 + 130 * i, 300)
abyss0.paste(char_img, char_crop, char_img)
for i in range(0, 1):
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(raw_data["damage_rank"][i]["avatar_id"]) + ".png")):
get_char_done_pic(raw_data["damage_rank"][i]["avatar_id"], raw_data["damage_rank"][i]["avatar_icon"],
raw_data["reveal_rank"][i]["rarity"])
char = os.path.join(CHAR_DONE_PATH, str(raw_data["damage_rank"][i]["avatar_id"]) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == raw_data["damage_rank"][i]["avatar_id"]:
char_draw.text((63.5, 117), f'{str(raw_data["damage_rank"][i]["value"])}', (21, 21, 21),
genshin_font(18), anchor="mm")
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (685, 470)
abyss0.paste(char_img, char_crop, char_img)
for i in range(0, 1):
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(raw_data["defeat_rank"][i]["avatar_id"]) + ".png")):
get_char_done_pic(raw_data["defeat_rank"][i]["avatar_id"], raw_data["defeat_rank"][i]["avatar_icon"],
raw_data["reveal_rank"][i]["rarity"])
char = os.path.join(CHAR_DONE_PATH, str(raw_data["defeat_rank"][i]["avatar_id"]) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == raw_data["defeat_rank"][i]["avatar_id"]:
char_draw.text((63.5, 117), f'{str(raw_data["defeat_rank"][i]["value"])}', (21, 21, 21),
genshin_font(18), anchor="mm")
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (82 + 123 * i, 470)
abyss0.paste(char_img, char_crop, char_img)
for i in range(0, 1):
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(raw_data["take_damage_rank"][i]["avatar_id"]) + ".png")):
get_char_done_pic(raw_data["take_damage_rank"][i]["avatar_id"],
raw_data["take_damage_rank"][i]["avatar_icon"], raw_data["reveal_rank"][i]["rarity"])
char = os.path.join(CHAR_DONE_PATH, str(raw_data["take_damage_rank"][i]["avatar_id"]) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == raw_data["take_damage_rank"][i]["avatar_id"]:
char_draw.text((63.5, 117), f'{str(raw_data["take_damage_rank"][i]["value"])}', (21, 21, 21),
genshin_font(18), anchor="mm")
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (232 + 123 * i, 470)
abyss0.paste(char_img, char_crop, char_img)
for i in range(0, 1):
if not os.path.exists(
os.path.join(CHAR_DONE_PATH, str(raw_data["normal_skill_rank"][i]["avatar_id"]) + ".png")):
get_char_done_pic(raw_data["normal_skill_rank"][i]["avatar_id"],
raw_data["normal_skill_rank"][i]["avatar_icon"], raw_data["reveal_rank"][i]["rarity"])
char = os.path.join(CHAR_DONE_PATH, str(raw_data["normal_skill_rank"][i]["avatar_id"]) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == raw_data["normal_skill_rank"][i]["avatar_id"]:
char_draw.text((63.5, 117), f'{str(raw_data["normal_skill_rank"][i]["value"])}', (21, 21, 21),
genshin_font(18), anchor="mm")
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (382 + 123 * i, 470)
abyss0.paste(char_img, char_crop, char_img)
for i in range(0, 1):
if not os.path.exists(
os.path.join(CHAR_DONE_PATH, str(raw_data["energy_skill_rank"][i]["avatar_id"]) + ".png")):
get_char_done_pic(raw_data["energy_skill_rank"][i]["avatar_id"],
raw_data["energy_skill_rank"][i]["avatar_icon"], raw_data["reveal_rank"][i]["rarity"])
char = os.path.join(CHAR_DONE_PATH, str(raw_data["energy_skill_rank"][i]["avatar_id"]) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == raw_data["energy_skill_rank"][i]["avatar_id"]:
char_draw.text((63.5, 118), f'{str(raw_data["energy_skill_rank"][i]["value"])}', (21, 21, 21),
genshin_font(18), anchor="mm")
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (532 + 123 * i, 470)
abyss0.paste(char_img, char_crop, char_img)
bg_img.paste(abyss0, (0, 0), abyss0)
for j in range(0, len(floors_data["levels"])):
abyss2 = Image.new("RGBA", (900, 340), (0, 0, 0, 0))
# abyss2 = Image.open(abyss2_path)
num_1 = 0
for i in floors_data['levels'][j]['battles'][0]['avatars']:
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")):
get_char_done_pic(i['id'], i['icon'], i['rarity'])
char = os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == i['id']:
char_draw.text((40, 108), f'Lv.{str(k["level"])}', (21, 21, 21), genshin_font(18))
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (70 + 125 * (num_1 % 4), 46)
abyss2.paste(char_img, char_crop, char_img)
num_1 = num_1 + 1
num_2 = 0
for i in floors_data['levels'][j]['battles'][1]['avatars']:
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")):
get_char_done_pic(i['id'], i['icon'], i['rarity'])
char = os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == i['id']:
char_draw.text((40, 108), f'Lv.{str(k["level"])}', (21, 21, 21), genshin_font(18))
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (70 + 125 * (num_2 % 4), 180)
abyss2.paste(char_img, char_crop, char_img)
num_2 = num_2 + 1
star_num = floors_data['levels'][j]['star']
if star_num == 1:
abyss2.paste(abyss_star1, (640, 155), abyss_star1)
abyss2.paste(abyss_star0, (685, 155), abyss_star0)
abyss2.paste(abyss_star0, (730, 155), abyss_star0)
elif star_num == 0:
abyss2.paste(abyss_star0, (640, 155), abyss_star0)
abyss2.paste(abyss_star0, (685, 155), abyss_star0)
abyss2.paste(abyss_star0, (730, 155), abyss_star0)
elif star_num == 2:
abyss2.paste(abyss_star1, (640, 155), abyss_star1)
abyss2.paste(abyss_star1, (685, 155), abyss_star1)
abyss2.paste(abyss_star0, (730, 155), abyss_star0)
else:
abyss2.paste(abyss_star1, (640, 155), abyss_star1)
abyss2.paste(abyss_star1, (685, 155), abyss_star1)
abyss2.paste(abyss_star1, (730, 155), abyss_star1)
abyss2_text_draw = ImageDraw.Draw(abyss2)
abyss2_text_draw.text((87, 30), f"{j + 1}", new_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}", new_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)
text_draw = ImageDraw.Draw(bg_img)
text_draw.text((220, 123), f"{nickname}", new_color, genshin_font(32))
text_draw.text((235, 163), 'UID ' + f"{uid}", new_color, genshin_font(14))
text_draw.text((690, 82), raw_data['max_floor'], new_color, genshin_font(26))
text_draw.text((690, 127), str(raw_data['total_battle_times']), new_color, genshin_font(26))
text_draw.text((690, 172), str(raw_data['total_star']), new_color, genshin_font(26))
bg_img = bg_img.convert('RGB')
bg_img.save(f"temp{os.sep}abyss.jpg", format='JPEG', subsampling=0, quality=90)
# bg_img.save(result_buffer, format='PNG')
return f"temp{os.sep}abyss.jpg"
async def draw_abyss_pic(uid, nickname, floor_num, image=None, mode=2, date="1"):
while True:
use_cookies = cacheDB(uid, mode - 1)
if use_cookies == '':
return "绑定记录不存在。"
elif use_cookies == "没有可以使用的Cookies":
return "没有可以使用的Cookies"
if mode == 3:
mys_data = await GetMysInfo(uid, use_cookies)
for i in mys_data['data']['list']:
if i['game_id'] != 2:
mys_data['data']['list'].remove(i)
uid = mys_data['data']['list'][0]['game_role_id']
nickname = mys_data['data']['list'][0]['nickname']
raw_data = await get_spiral_abyss_info(uid, use_cookies, date)
raw_char_data = await GetInfo(uid, use_cookies)
if raw_data["retcode"] != 0:
if raw_data["retcode"] == 10001:
# return ("Cookie错误/过期请重置Cookie")
errorDB(use_cookies, "error")
elif raw_data["retcode"] == 10101:
# return ("当前cookies已达到30人上限")
errorDB(use_cookies, "limit30")
elif raw_data["retcode"] == 10102:
return "当前查询id已经设置了隐私无法查询"
else:
return (
"Api报错返回内容为\r\n"
+ str(raw_data) + "\r\n出现这种情况可能的UID输入错误 or 不存在"
)
else:
break
# 获取数据
raw_data = raw_data["data"]
raw_char_data = raw_char_data['data']["avatars"]
floors_data = raw_data['floors']
if not floors_data:
return ""
based_data = []
for i in floors_data:
if str(i['index']) == floor_num:
based_data = i
levels_num = len(based_data['levels'])
# 获取背景图片
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 image:
image_data = image.group(2)
edit_bg = Image.open(BytesIO(get(image_data).content))
else:
edit_bg = Image.open(bg2_path)
# 确定图片的长宽
based_w = 900
based_h = 440 + levels_num * 340
based_scale = '%.3f' % (based_w / based_h)
w, h = edit_bg.size
scale_f = '%.3f' % (w / h)
new_w = math.ceil(based_h * float(scale_f))
new_h = math.ceil(based_w / float(scale_f))
if scale_f > based_scale:
bg_img2 = edit_bg.resize((new_w, based_h), Image.ANTIALIAS)
else:
bg_img2 = edit_bg.resize((based_w, new_h), Image.ANTIALIAS)
bg_img = bg_img2.crop((0, 0, based_w, based_h))
# 获取背景主色
q = edit_bg.quantize(colors=3, method=2)
bg_num_temp = 0
for i in range(0, 3):
bg = tuple(q.getpalette()[i * 3:(i * 3) + 3])
bg_num = bg[0] + bg[1] + bg[2]
if bg_num >= bg_num_temp:
bg_num_temp = bg_num
bg_color = (bg[0], bg[1], bg[2])
# 通过背景主色bg_color确定文字主色
r = 140
if max(*bg_color) > 255 - r:
r *= -1
new_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))
# 打开图片
abyss1_path = os.path.join(TEXT_PATH, "abyss_1.png")
abyss3_path = os.path.join(TEXT_PATH, "abyss_3.png")
abyss_star0_path = os.path.join(TEXT_PATH, "abyss_star0.png")
abyss_star1_path = os.path.join(TEXT_PATH, "abyss_star1.png")
abyss1 = Image.open(abyss1_path)
abyss3 = Image.open(abyss3_path)
abyss_star0 = Image.open(abyss_star0_path)
abyss_star1 = Image.open(abyss_star1_path)
avatar_bg_path = os.path.join(TEXT_PATH, "avatar_bg.png")
avatar_fg_path = os.path.join(TEXT_PATH, "avatar_fg.png")
all_mask_path = os.path.join(TEXT_PATH, "All_Mask.png")
# 转换遮罩的颜色、大小匹配并paste上去
all_mask = Image.open(all_mask_path).resize(bg_img.size, Image.ANTIALIAS)
all_mask_img = Image.new("RGBA", (based_w, based_h), bg_color)
bg_img.paste(all_mask_img, (0, 0), all_mask)
# 开启图片
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, 145), avatar_bg)
bg_img.paste(avatar_fg, (114, 142), avatar_fg)
"""
for i in range(0,len(based_data['levels'])):
x, y = 65, 220 + 340*i
radius = 10
cropped_img = bg_img.crop((x, y, 836, 517+340*i))
blurred_img = cropped_img.filter(ImageFilter.GaussianBlur(5),).convert("RGBA")
bg_img.paste(blurred_img, (x, y), create_rounded_rectangle_mask(cropped_img,radius))
"""
abyss1_bg_color = Image.new("RGBA", (900, 400), bg_color)
bg_img.paste(abyss1_bg_color, (0, 0), abyss1)
for j in range(0, len(based_data['levels'])):
abyss2 = Image.new("RGBA", (900, 340), (0, 0, 0, 0))
num_1 = 0
avatars = based_data['levels'][j]['battles'][0]['avatars'] + based_data['levels'][j]['battles'][1]['avatars']
for i in based_data['levels'][j]['battles'][0]['avatars']:
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")):
get_char_done_pic(i['id'], i['icon'], i['rarity'])
char = os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == i['id']:
char_draw.text((40, 108), f'Lv.{str(k["level"])}', (21, 21, 21), genshin_font(18))
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (70 + 125 * (num_1 % 4), 46)
abyss2.paste(char_img, char_crop, char_img)
num_1 = num_1 + 1
num_2 = 0
for i in based_data['levels'][j]['battles'][1]['avatars']:
if not os.path.exists(os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")):
get_char_done_pic(i['id'], i['icon'], i['rarity'])
char = os.path.join(CHAR_DONE_PATH, str(i['id']) + ".png")
char_img = Image.open(char)
char_draw = ImageDraw.Draw(char_img)
for k in raw_char_data:
if k['id'] == i['id']:
char_draw.text((40, 108), f'Lv.{str(k["level"])}', (21, 21, 21), genshin_font(18))
char_draw.text((95.3, 19), f'{str(k["actived_constellation_num"])}', 'white', genshin_font(18))
if str(k["fetter"]) == "10" or str(k["name"]) == "旅行者":
char_draw.text((93, 41.5), "", (21, 21, 21), genshin_font(15))
else:
char_draw.text((95.3, 40.5), f'{str(k["fetter"])}', (21, 21, 21), genshin_font(18))
char_crop = (70 + 125 * (num_2 % 4), 180)
abyss2.paste(char_img, char_crop, char_img)
num_2 = num_2 + 1
star_num = based_data['levels'][j]['star']
if star_num == 1:
abyss2.paste(abyss_star1, (640, 155), abyss_star1)
abyss2.paste(abyss_star0, (685, 155), abyss_star0)
abyss2.paste(abyss_star0, (730, 155), abyss_star0)
elif star_num == 0:
abyss2.paste(abyss_star0, (640, 155), abyss_star0)
abyss2.paste(abyss_star0, (685, 155), abyss_star0)
abyss2.paste(abyss_star0, (730, 155), abyss_star0)
elif star_num == 2:
abyss2.paste(abyss_star1, (640, 155), abyss_star1)
abyss2.paste(abyss_star1, (685, 155), abyss_star1)
abyss2.paste(abyss_star0, (730, 155), abyss_star0)
else:
abyss2.paste(abyss_star1, (640, 155), abyss_star1)
abyss2.paste(abyss_star1, (685, 155), abyss_star1)
abyss2.paste(abyss_star1, (730, 155), abyss_star1)
abyss2_text_draw = ImageDraw.Draw(abyss2)
abyss2_text_draw.text((87, 30), f"{j + 1}", new_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}", new_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)
text_draw = ImageDraw.Draw(bg_img)
text_draw.text((220, 163), f"{nickname}", new_color, genshin_font(32))
text_draw.text((235, 203), 'UID ' + f"{uid}", new_color, genshin_font(14))
text_draw.text((710, 190), f"{floor_num}", new_color, genshin_font(50), anchor="mm")
bg_img = bg_img.convert('RGB')
result_buffer = BytesIO()
bg_img.save(f"temp{os.sep}abyss.jpg", format='JPEG', subsampling=0, quality=90)
# bg_img.save(result_buffer, format='PNG')
return f"temp{os.sep}abyss.jpg"

233
defs/spiral_abyss_text.py Normal file
View File

@ -0,0 +1,233 @@
import json
import os
import time
from defs.db import GetInfo, cacheDB, GetMysInfo, get_spiral_abyss_info, errorDB
from pydantic import BaseModel
from typing import List
class GenshinUserCharacher(BaseModel):
id: int
image: str # 角色头图url
name: str # 角色名
element: str # 属性
fetter: int # 好感等级
level: int
rarity: int # 稀有度
actived_constellation_num: int # 命之座
class GenshinUserStats(BaseModel):
active_day_number: int # 活跃天数
achievement_number: int # 成就数
win_rate: int
anemoculus_number: int # 风神瞳数量
geoculus_number: int # 岩神瞳数
electroculus_number: int # 雷神瞳数量
avatar_number: int # 角色数量
way_point_number: int # 传送点解锁数
domain_number: int # 秘境解锁数
spiral_abyss: str # 深渊进度
common_chest_number: int # 普通宝箱数量
exquisite_chest_number: int # 精致宝箱数量
precious_chest_number: int # 珍贵宝箱数量
luxurious_chest_number: int # 华丽宝箱数量
magic_chest_number: int # 奇馈宝箱数量
class GenshinWorldOfferings(BaseModel):
name: str
level: int
class GenshinWorldInfo(BaseModel):
level: int # 声望等级
exploration_percentage: int # 探索度
icon: str # 区域图标url
name: str
type: str
id: int
offerings: List[GenshinWorldOfferings] # 供奉信息
class GenshinHomeInfo(BaseModel):
level: int # 信任等级
visit_num: int # 访客数
comfort_num: int # 洞天仙力
item_num: int # 摆件数量
name: str
icon: str # 背景图
comfort_level_name: str # 洞天仙力对应名称
comfort_level_icon: str # 等级图标
class GenshinUserData(BaseModel):
avatars: List[GenshinUserCharacher] # 角色列表
stats: GenshinUserStats
city_explorations: List # 不知道是啥玩意, 都是空的
world_explorations: List[GenshinWorldInfo] # 区域探索信息
homes: List[GenshinHomeInfo] # 家园信息
class GenshinAbyssRankInfo(BaseModel):
avatar_id: int
avatar_icon: str
value: int
rarity: int
class GenshinAbyssFloorInfoBattlesAvatars(BaseModel):
id: int
icon: str
level: int
rarity: int
class GenshinAbyssFloorInfoBattles(BaseModel):
index: int # 战斗场次
timestamp: str
avatars: List[GenshinAbyssFloorInfoBattlesAvatars]
class GenshinAbyssFloorInfo(BaseModel):
index: int # 间号
star: int
max_star: int
battles: List[GenshinAbyssFloorInfoBattles]
class GenshinAbyssFloors(BaseModel):
index: int # 层数
icon: str # 空的
is_unlock: bool
settle_time: str
star: int
max_star: int
levels: List[GenshinAbyssFloorInfo]
class GenshinAbyss(BaseModel):
schedule_id: int
start_time: int # 10位
end_time: int # 10位
total_battle_times: int
total_win_times: int
max_floor: str
reveal_rank: List[GenshinAbyssRankInfo] # 出战次数Rank
defeat_rank: List[GenshinAbyssRankInfo] # 击破数Rank
damage_rank: List[GenshinAbyssRankInfo] # 最强一击
take_damage_rank: List[GenshinAbyssRankInfo] # 承伤Rank
normal_skill_rank: List[GenshinAbyssRankInfo] # 元素战技释放数
energy_skill_rank: List[GenshinAbyssRankInfo] # 元素爆发次数
floors: List[GenshinAbyssFloors]
total_star: int
is_unlock: bool
def char_id_to_name(udata: GenshinUserData, charid: int): # id2name.json数据不全, 我也懒得去搜集了, 故采用此邪道方法(
chars = udata.avatars
for char in chars:
if charid == char.id:
return char.name
with open(f"assets{os.sep}data{os.sep}id2name.json", "r", encoding="utf-8") as f:
id2name = json.load(f)
if str(charid) in id2name:
return id2name[str(charid)]
return f"{charid}"
def timestamp_to_text(timestamp: int, _format="%Y-%m-%d %H:%M:%S"):
"""
:param timestamp: 时间戳,若输入13位时间戳则自动转为10位
:param _format: 格式,默认"%Y-%m-%d %H:%M:%S"
:return: %Y-%m-%d %H:%M:%S -> str
"""
if timestamp > 9999999999: # 13位时间戳转10位
timestamp = timestamp / 1000
ret = time.strftime(_format, time.localtime(timestamp))
return ret
async def get_user_abyss(uid, mode=2, date="1"): # 深境螺旋
# 获取Cookies
while True:
use_cookies = cacheDB(uid, mode - 1)
if use_cookies == '':
return "绑定记录不存在。"
elif use_cookies == "没有可以使用的Cookies":
return "没有可以使用的Cookies"
if mode == 3:
mys_data = await GetMysInfo(uid, use_cookies)
for i in mys_data['data']['list']:
if i['game_id'] != 2:
mys_data['data']['list'].remove(i)
uid = mys_data['data']['list'][0]['game_role_id']
nickname = mys_data['data']['list'][0]['nickname']
raw_data = await get_spiral_abyss_info(uid, use_cookies, date)
raw_char_data = await GetInfo(uid, use_cookies)
if raw_data["retcode"] != 0:
if raw_data["retcode"] == 10001:
# return ("Cookie错误/过期请重置Cookie")
errorDB(use_cookies, "error")
elif raw_data["retcode"] == 10101:
# return ("当前cookies已达到30人上限")
errorDB(use_cookies, "limit30")
elif raw_data["retcode"] == 10102:
return "当前查询id已经设置了隐私无法查询"
else:
return (
"Api报错返回内容为\r\n"
+ str(raw_data) + "\r\n出现这种情况可能的UID输入错误 or 不存在"
)
else:
break
# 获取数据
udata = GenshinUserData(**raw_char_data["data"])
aby = GenshinAbyss(**raw_data["data"])
breakpoint()
if not aby.floors: # 没打
return ""
rettext = f"<b>第{aby.schedule_id}期深境螺旋信息</b>\n\n" \
f"\t开始时间: {timestamp_to_text(aby.start_time)}\n" \
f"\t结束时间: {timestamp_to_text(aby.end_time)}\n" \
f"\t最深抵达:{aby.max_floor}\n" \
f"\t胜利场次/总场次: {aby.total_win_times}/{aby.total_battle_times}\n"
if aby.reveal_rank:
rettext += f"\t出战最多: {char_id_to_name(udata, aby.reveal_rank[0].avatar_id)} - {aby.reveal_rank[0].value}\n"
if aby.defeat_rank:
rettext += f"\t击破最多: {char_id_to_name(udata, aby.defeat_rank[0].avatar_id)} - {aby.defeat_rank[0].value}\n"
if aby.damage_rank:
rettext += f"\t最强一击: {char_id_to_name(udata, aby.damage_rank[0].avatar_id)} - {aby.damage_rank[0].value}\n"
if aby.take_damage_rank:
rettext += f"\t最高承伤: {char_id_to_name(udata, aby.take_damage_rank[0].avatar_id)} - {aby.take_damage_rank[0].value}\n"
if aby.normal_skill_rank:
rettext += f"\t元素战技: {char_id_to_name(udata, aby.normal_skill_rank[0].avatar_id)} - {aby.normal_skill_rank[0].value}\n"
if aby.energy_skill_rank:
rettext += f"\t元素爆发: {char_id_to_name(udata, aby.energy_skill_rank[0].avatar_id)} - {aby.energy_skill_rank[0].value}\n"
rettext += f"\t总星数: ★ {aby.total_star}\n\t"
floor_text = "" # 层
has_details = False
if len(aby.floors) >= 0:
if len(aby.floors[0].levels) > 0:
has_details = True
for floor in aby.floors: # 层
room_text = "" # 间
for room in floor.levels: # 间
battle_text = "" # 场
for battle in room.battles: # 场次
character_text = "" # 角色
for char in battle.avatars: # 角色列表
character_text += f"/{char_id_to_name(udata, char.id)}"
battle_text += f"\n\t\t\t\t{battle.index} 场: {character_text[1:]}"
room_text += f"\n\t\t\t{room.index} 间 (★ {room.star}/{room.max_star}):{battle_text}"
floor_text += f"\n\n\t\t{floor.index} 层:\t{room_text}"
rettext = f"{rettext}楼层信息:{floor_text}" if has_details else f"{rettext}未获取到详细楼层信息"
return rettext

View File

@ -2,6 +2,7 @@ from pyrogram import Client
from pyrogram.types import Message from pyrogram.types import Message
from os import getcwd, sep from os import getcwd, sep
from defs.challenge import get_day from defs.challenge import get_day
from defs.redis_load import redis_status, redis
async def tf_msg(client: Client, message: Message): async def tf_msg(client: Client, message: Message):
@ -23,4 +24,18 @@ async def wq_msg(client: Client, message: Message):
async def zb_msg(client: Client, message: Message): async def zb_msg(client: Client, message: Message):
await message.reply_photo(photo=f'{getcwd()}{sep}assets{sep}images{sep}zb.png', quote=True) if redis_status():
try:
data = redis.get("zb").decode()
except AttributeError:
data = None
if data != "2.5":
# 开始上传
msg = await message.reply_photo(photo=f"{getcwd()}{sep}assets{sep}images{sep}zb.png", quote=True)
# 缓存 file_id
redis.set("zb", "2.5")
redis.set("zb_file_id", msg.document.file_id)
else:
await message.reply_photo(photo=redis.get('zb_file_id').decode(), quote=True)
else:
await message.reply_photo(photo=f'{getcwd()}{sep}assets{sep}images{sep}zb.png', quote=True)

28
plugins/char_adv.py Normal file
View File

@ -0,0 +1,28 @@
from pyrogram import Client
from pyrogram.types import Message
from traceback import print_exc
from defs.char_adv import char_adv, weapon_adv
async def send_char_adv(client: Client, message: Message):
try:
name = message.text
for i in ["用什么", "能用啥", "怎么养"]:
name = name.replace(i, "").strip()
im = await char_adv(name)
await message.reply(im, quote=True)
except Exception as e:
print("获取建议失败。")
print_exc()
async def send_weapon_adv(client: Client, message: Message):
try:
name = message.text
for i in ["能给谁", "给谁用", "要给谁", "谁能用"]:
name = name.replace(i, "").strip()
im = await weapon_adv(name)
await message.reply(im, quote=True)
except Exception as e:
print("获取建议失败。")
print_exc()

View File

@ -15,6 +15,8 @@ from defs.mihoyo import draw_pic as draw_pic_2
from ci import scheduler, app, admin_id from ci import scheduler, app, admin_id
from defs.redis_load import redis from defs.redis_load import redis
from defs.spiral_abyss import draw_abyss_pic, draw_abyss0_pic
from defs.spiral_abyss_text import get_user_abyss
SUPERUSERS = [admin_id] SUPERUSERS = [admin_id]
@ -195,26 +197,89 @@ async def mys2_qun_msg(client: Client, message: Message):
elif "uid" in text: elif "uid" in text:
try: try:
uid = re.findall(r"\d+", text)[0] # str uid = re.findall(r"\d+", text)[0] # str
m = ''.join(re.findall('[\u4e00-\u9fa5]', text))
except IndexError: except IndexError:
return await message.reply("uid格式错误") return await message.reply("uid格式错误")
try: nickname = message.from_user.first_name
nickname = nickname if len(nickname) < 10 else (nickname[:10] + "...")
if m == "深渊":
try: try:
nickname = message.from_user.first_name if len(re.findall(r"\d+", text)) == 2:
nickname = nickname if len(nickname) < 10 else (nickname[:10] + "...") floor_num = re.findall(r"\d+", text)[1]
if is_chinese(uid): im = await draw_abyss_pic(uid, nickname, floor_num)
im = await draw_pic(uid, message, nickname=nickname, mode=2) if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply_photo(im)
else: else:
im = await draw_pic_2(uid, message, nickname=nickname, mode=2) im = await draw_abyss0_pic(uid, nickname)
if im.find(".") != -1: if not im:
await message.reply_photo(im) await message.reply("未查找到该用户的深渊信息。")
else: else:
await message.reply(im) await message.reply_photo(im)
except TypeError:
await message.reply("获取失败可能是Cookies失效或者未打开米游社角色详情开关。")
print("上期深渊数据获取失败Cookie失效/不公开信息)")
traceback.print_exc()
except Exception as e: except Exception as e:
await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e)) await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
print("上期深渊数据获取失败(数据状态问题)")
traceback.print_exc() traceback.print_exc()
except Exception as e: elif m == "上期深渊":
traceback.print_exc() try:
await message.reply("发生错误 {},请检查后台输出。".format(e)) if len(re.findall(r"\d+", text)) == 2:
floor_num = re.findall(r"\d+", text)[1]
im = await draw_abyss_pic(uid, nickname, floor_num, None, 2, "2")
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply_photo(im)
else:
im = await draw_abyss0_pic(uid, nickname, None, 2, "2")
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply_photo(im)
except TypeError:
await message.reply("获取失败可能是Cookies失效或者未打开米游社角色详情开关。")
print("上期深渊数据获取失败Cookie失效/不公开信息)")
traceback.print_exc()
except Exception as e:
await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
print("上期深渊数据获取失败(数据状态问题)")
traceback.print_exc()
elif m == "文本深渊":
try:
im = await get_user_abyss(uid, 2, "2")
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply(im)
except TypeError:
await message.reply("获取失败可能是Cookies失效或者未打开米游社角色详情开关。")
print("上期深渊数据获取失败Cookie失效/不公开信息)")
traceback.print_exc()
except Exception as e:
await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
print("上期深渊数据获取失败(数据状态问题)")
traceback.print_exc()
else:
try:
try:
if is_chinese(uid):
im = await draw_pic(uid, message, nickname=nickname, mode=2)
else:
im = await draw_pic_2(uid, message, nickname=nickname, mode=2)
if im.find(".") != -1:
await message.reply_photo(im)
else:
await message.reply(im)
except Exception as e:
await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
traceback.print_exc()
except Exception as e:
traceback.print_exc()
await message.reply("发生错误 {},请检查后台输出。".format(e))
elif "查询" in text: elif "查询" in text:
try: try:
at = message.reply_to_message at = message.reply_to_message
@ -227,7 +292,68 @@ async def mys2_qun_msg(client: Client, message: Message):
uid = await selectDB(message.from_user.id) uid = await selectDB(message.from_user.id)
nickname = nickname if len(nickname) < 10 else (nickname[:10] + "...") nickname = nickname if len(nickname) < 10 else (nickname[:10] + "...")
if uid: if uid:
if "词云" in text: if "深渊" in text and "上期" not in text and "文本" not in text:
try:
if len(re.findall(r"\d+", text)) == 1:
floor_num = re.findall(r"\d+", text)[0]
im = await draw_abyss_pic(uid[0], nickname, floor_num, None, uid[1])
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply_photo(im)
else:
im = await draw_abyss0_pic(uid[0], nickname, None, uid[1])
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply_photo(im)
except TypeError:
await message.reply("获取失败可能是Cookies失效或者未打开米游社角色详情开关。")
print("上期深渊数据获取失败Cookie失效/不公开信息)")
traceback.print_exc()
except Exception as e:
await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
print("上期深渊数据获取失败(数据状态问题)")
traceback.print_exc()
elif "深渊" in text and "文本" not in text:
try:
if len(re.findall(r"\d+", text)) == 1:
floor_num = re.findall(r"\d+", text)[0]
im = await draw_abyss_pic(uid[0], nickname, floor_num, None, uid[1], "2")
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply_photo(im)
else:
im = await draw_abyss0_pic(uid[0], nickname, None, uid[1], "2")
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply_photo(im)
except TypeError:
await message.reply("获取失败可能是Cookies失效或者未打开米游社角色详情开关。")
print("上期深渊数据获取失败Cookie失效/不公开信息)")
traceback.print_exc()
except Exception as e:
await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
print("上期深渊数据获取失败(数据状态问题)")
traceback.print_exc()
elif "深渊" in text:
try:
im = await get_user_abyss(uid[0], uid[1], "2")
if not im:
await message.reply("未查找到该用户的深渊信息。")
else:
await message.reply(im)
except TypeError:
await message.reply("获取失败可能是Cookies失效或者未打开米游社角色详情开关。")
print("上期深渊数据获取失败Cookie失效/不公开信息)")
traceback.print_exc()
except Exception as e:
await message.reply("获取失败,有可能是数据状态有问题,\n{}\n请检查后台输出。".format(e))
print("上期深渊数据获取失败(数据状态问题)")
traceback.print_exc()
elif "词云" in text:
try: try:
im = await draw_wordcloud(uid[0], message, uid[1]) im = await draw_wordcloud(uid[0], message, uid[1])
if im.find(".jpg") != -1: if im.find(".jpg") != -1:
@ -300,7 +426,8 @@ async def push():
if i['gid'] == "on": if i['gid'] == "on":
await app.send_message(int(i['qid']), i['message']) await app.send_message(int(i['qid']), i['message'])
else: else:
await app.send_message(int(i['gid']), f"[NOTICE {i['qid']}](tg://user?id={i['qid']})" + "\n" + i['message']) await app.send_message(int(i['gid']),
f"[NOTICE {i['qid']}](tg://user?id={i['qid']})" + "\n" + i['message'])
else: else:
pass pass

View File

@ -24,6 +24,7 @@ from plugins.foods import foods_msg
from plugins.artifacts import artifacts_msg from plugins.artifacts import artifacts_msg
from plugins.artifact_rate import artifact_rate_msg from plugins.artifact_rate import artifact_rate_msg
from plugins.query_resource_points import inquire_resource_points, inquire_resource_list from plugins.query_resource_points import inquire_resource_points, inquire_resource_list
from plugins.char_adv import send_char_adv, send_weapon_adv
from plugins.mys import mys_msg, promote_command from plugins.mys import mys_msg, promote_command
from defs.inline_query_result_cached_media import InlineQueryResultCachedDocument from defs.inline_query_result_cached_media import InlineQueryResultCachedDocument
@ -115,6 +116,14 @@ async def process_private_msg(client: Client, message: Message):
await mys2_msg(client, message) await mys2_msg(client, message)
if 'hoyolab' in message.text: if 'hoyolab' in message.text:
await mihoyo_msg(client, message) await mihoyo_msg(client, message)
for i in ["用什么", "能用啥", "怎么养"]:
if i in message.text:
await send_char_adv(client, message)
break
for i in ["能给谁", "给谁用", "要给谁", "谁能用"]:
if i in message.text:
await send_weapon_adv(client, message)
break
# 账号信息cookie 过期过快 不推荐启用) # 账号信息cookie 过期过快 不推荐启用)
# if '账号信息' in message.text or '用户信息' in message.text: # if '账号信息' in message.text or '用户信息' in message.text:
# await mys_msg(client, message) # await mys_msg(client, message)
@ -199,6 +208,15 @@ async def process_group_msg(client: Client, message: Message):
await guess_voice(client, message) await guess_voice(client, message)
if text.startswith("抽卡"): if text.startswith("抽卡"):
await gacha_msg(client, message) await gacha_msg(client, message)
# 建议
for i in ["用什么", "能用啥", "怎么养"]:
if i in message.text:
await send_char_adv(client, message)
break
for i in ["能给谁", "给谁用", "要给谁", "谁能用"]:
if i in message.text:
await send_weapon_adv(client, message)
break
# 处理猜语音游戏 # 处理猜语音游戏
await process_guess(client, message) await process_guess(client, message)

View File

@ -2,7 +2,8 @@ from ci import admin_id
from pyrogram import Client from pyrogram import Client
from pyrogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton from pyrogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
HELP_MSG_PRE = '<a href="https://git.io/JcbTD">PaimonBot</a> 0.3.8beta By Xtao-Labs\n\n' \ HELP_MSG_PRE = '<a href="https://gitlab.com/Xtao-Labs/Telegram_PaimonBot">PaimonBot</a> ' \
'0.4.0beta By Xtao-Labs\n\n' \
'🔅 以下是小派蒙我学会了的功能(部分):\n' '🔅 以下是小派蒙我学会了的功能(部分):\n'
HELP_MSG = """① [武器/今日武器] 查看今日武器材料和武器 HELP_MSG = """① [武器/今日武器] 查看今日武器材料和武器
[天赋/今日天赋] 查看今日天赋材料和角色 [天赋/今日天赋] 查看今日天赋材料和角色
@ -36,7 +37,9 @@ HELP_MSG = """① [武器/今日武器] 查看今日武器材料和武器
(17) [猜语音] 和群友一起玩猜语音小游戏吧群聊 (17) [猜语音] 和群友一起玩猜语音小游戏吧群聊
💠 <code>猜语音</code> 💠 <code>猜语音</code>
💠 <code>猜语音 无尽模式</code> 💠 <code>猜语音 无尽模式</code>
(18) [米游社/hoyolab] 米游社/hoyolab相关功能 (18) [怎么养 (角色名)] 输出角色适用武器&圣遗物
(19) [给谁用 (武器名)] 输出武器适用角色
(20) [米游社/hoyolab] 米游社/hoyolab相关功能
💠 <a href="https://telegra.ph/PaimonBot-02-18">点击查看</a>""" 💠 <a href="https://telegra.ph/PaimonBot-02-18">点击查看</a>"""

View File

@ -14,3 +14,4 @@ apscheduler>=3.8.1
wordcloud>=1.8.1 wordcloud>=1.8.1
numpy numpy
sqlitedict sqlitedict
openpyxl>=3.0.9