🎨 适配新版GsCore

This commit is contained in:
Wuyi无疑 2023-08-06 16:24:58 +08:00
parent d298424796
commit ba13c517d8
13 changed files with 109 additions and 336 deletions

View File

@ -20,12 +20,18 @@ class Equipment(TypedDict):
class Relic(TypedDict):
subAffixList: List[subAffixList]
subAffixList: List[SubAffix]
tid: int
mainAffixId: int
type: int
class SubAffix(TypedDict):
affixID: int
cnt: int
step: int
class Avatar(TypedDict):
skillTreeList: List[Behavior]
rank: Optional[int]

View File

@ -4,12 +4,15 @@ from typing import Union, Optional
from PIL import Image, ImageDraw
from gsuid_core.logger import logger
from gsuid_core.utils.error_reply import get_error
from gsuid_core.utils.image.image_tools import (
get_qq_avatar,
draw_pic_with_ring,
)
from .utils import get_icon
from ..utils.convert import GsCookie
from ..utils.image.convert import convert_img
from ..sruid_utils.api.mys.models import AbyssAvatar
from ..utils.image.image_tools import get_qq_avatar, draw_pic_with_ring
from ..utils.fonts.starrail_fonts import (
sr_font_22,
sr_font_28,
@ -190,7 +193,7 @@ async def draw_abyss_img(
char_pic = await get_qq_avatar(avatar_url=_id)
else:
char_pic = await get_qq_avatar(qid=qid)
char_pic = await draw_pic_with_ring(char_pic, 250)
char_pic = await draw_pic_with_ring(char_pic, 250, None, False)
img.paste(char_pic, (325, 132), char_pic)

View File

@ -1,18 +1,34 @@
import re
import json
import math
import re
from pathlib import Path
from typing import Dict, Optional, Union
from typing import Dict, Union, Optional
from mpmath import mp, nstr
from PIL import Image, ImageDraw
from gsuid_core.logger import logger
from gsuid_core.utils.image.convert import convert_img
from gsuid_core.utils.image.image_tools import draw_text_by_line
from mpmath import mp, nstr
from PIL import Image, ImageDraw
from .to_data import api_to_dict
from .mono.Character import Character
from ..utils.error_reply import CHAR_HINT
from ..utils.excel.read_excel import light_cone_ranks
from ..utils.fonts.first_world import fw_font_28
from ..utils.excel.read_excel import light_cone_ranks
from ..utils.map.name_covert import name_to_avatar_id, alias_to_char_name
from ..utils.map.SR_MAP_PATH import (
RelicId2Rarity,
AvatarRelicScore,
avatarId2Name,
avatarId2DamageType,
)
from ..utils.resource.RESOURCE_PATH import (
RELIC_PATH,
SKILL_PATH,
PLAYER_PATH,
WEAPON_PATH,
CHAR_PORTRAIT_PATH,
)
from ..utils.fonts.starrail_fonts import (
sr_font_20,
sr_font_23,
@ -22,22 +38,6 @@ from ..utils.fonts.starrail_fonts import (
sr_font_34,
sr_font_38,
)
from ..utils.map.name_covert import alias_to_char_name, name_to_avatar_id
from ..utils.map.SR_MAP_PATH import (
AvatarRelicScore,
RelicId2Rarity,
avatarId2DamageType,
avatarId2Name,
)
from ..utils.resource.RESOURCE_PATH import (
CHAR_PORTRAIT_PATH,
PLAYER_PATH,
RELIC_PATH,
SKILL_PATH,
WEAPON_PATH,
)
from .mono.Character import Character
from .to_data import api_to_dict
mp.dps = 14
@ -103,7 +103,11 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
char_img_draw.text(
(620, 207), char.char_name, (255, 255, 255), sr_font_38, 'lm'
)
char_name_len = sr_font_38.getsize(char.char_name)[0]
if hasattr(sr_font_38, 'getsize'):
char_name_len = sr_font_38.getsize(char.char_name)[0]
else:
bbox = sr_font_38.getbbox(char.char_name)
char_name_len = bbox[2] - bbox[0]
# 放等级
char_img_draw.text(
@ -346,9 +350,13 @@ async def draw_char_info_img(raw_mes: str, sr_uid: str, url: Optional[str]):
sr_font_34,
'lm',
)
weapon_name_len = sr_font_34.getsize(char.equipment["equipmentName"])[
0
]
if hasattr(sr_font_34, 'getsize'):
weapon_name_len = sr_font_34.getsize(
char.equipment["equipmentName"]
)[0]
else:
bbox = sr_font_34.getbbox(char.equipment["equipmentName"])
weapon_name_len = bbox[2] - bbox[0]
# 放阶
rank_img = Image.open(TEXT_PATH / 'ImgNewBg.png')
rank_img_draw = ImageDraw.Draw(rank_img)

View File

@ -6,6 +6,11 @@ from typing import List, Tuple, Union
from PIL import Image, ImageDraw
from gsuid_core.logger import logger
from gsuid_core.utils.image.image_tools import (
get_color_bg,
get_qq_avatar,
draw_pic_with_ring,
)
from ..utils.image.convert import convert_img
from ..utils.map.name_covert import name_to_avatar_id, name_to_weapon_id
@ -14,11 +19,6 @@ from ..utils.resource.RESOURCE_PATH import (
WEAPON_PATH,
CHAR_ICON_PATH,
)
from ..utils.image.image_tools import (
get_color_bg,
get_qq_avatar,
draw_pic_with_ring,
)
from ..utils.fonts.starrail_fonts import (
sr_font_20,
sr_font_24,
@ -324,7 +324,7 @@ async def draw_gachalogs_img(uid: str, user_id: str) -> Union[bytes, str]:
char_pic = await get_qq_avatar(avatar_url=_id)
else:
char_pic = await get_qq_avatar(qid=user_id)
char_pic = await draw_pic_with_ring(char_pic, 206)
char_pic = await draw_pic_with_ring(char_pic, 206, None, False)
# 获取背景图片各项参数
img = Abg3_img.copy()

View File

@ -5,11 +5,14 @@ from typing import List, Union, Optional
from PIL import Image, ImageDraw
from gsuid_core.logger import logger
from gsuid_core.utils.error_reply import get_error
from gsuid_core.utils.image.image_tools import (
get_qq_avatar,
draw_pic_with_ring,
)
from .utils import get_icon
from ..utils.convert import GsCookie
from ..utils.image.convert import convert_img
from ..utils.image.image_tools import get_qq_avatar, draw_pic_with_ring
from ..sruid_utils.api.mys.models import (
RogueAvatar,
RogueMiracles,
@ -283,7 +286,7 @@ async def draw_rogue_img(
char_pic = await get_qq_avatar(avatar_url=_id)
else:
char_pic = await get_qq_avatar(qid=qid)
char_pic = await draw_pic_with_ring(char_pic, 250)
char_pic = await draw_pic_with_ring(char_pic, 250, None, False)
img.paste(char_pic, (325, 132), char_pic)

View File

@ -3,6 +3,7 @@ import re
from gsuid_core.sv import SV
from gsuid_core.bot import Bot
from gsuid_core.models import Event
from gsuid_core.logger import logger
from ..utils.convert import get_uid
from ..utils.sr_prefix import PREFIX
@ -21,5 +22,6 @@ async def send_role_info(bot: Bot, ev: Event):
if uid is None:
return '你还没有绑定UID噢,请使用[sr绑定uid123]完成绑定!'
logger.info(f'[sr查询信息]UID: {uid}')
await bot.logger.info('开始执行[sr查询信息]')
await bot.send(await get_role_img(uid))

View File

@ -13,7 +13,7 @@ from ..sruid_utils.api.mys.models import AbyssData, RogueData
@overload
async def get_uid(
bot: Bot, ev: Event, only_uid: bool = False
bot: Bot, ev: Event, get_user_id: bool = False, only_uid: bool = False
) -> Optional[str]:
...

View File

@ -1,22 +1,20 @@
import math
import random
from io import BytesIO
from pathlib import Path
from typing import Tuple, Union, Optional
from typing import Union, Optional
from httpx import get
from PIL import Image, ImageDraw, ImageFont
from PIL import Image
from gsuid_core.utils.image.image_tools import TEXT_PATH, CustomizeImage
from ..resource.RESOURCE_PATH import CU_BG_PATH
from ...starrailuid_config.sr_config import srconfig
from ..resource.RESOURCE_PATH import CU_BG_PATH, TEXT2D_PATH
BG_PATH = Path(__file__).parent / 'bg'
TEXT_PATH = Path(__file__).parent / 'texture2d'
ring_pic = Image.open(TEXT_PATH / 'ring.png')
mask_pic = Image.open(TEXT_PATH / 'mask.png')
NM_BG_PATH = BG_PATH / 'nm_bg'
SP_BG_PATH = BG_PATH / 'sp_bg'
if list(CU_BG_PATH.iterdir()) != []:
bg_path = CU_BG_PATH
else:
bg_path = NM_BG_PATH
if list(CU_BG_PATH.iterdir()) != []:
bg_path = CU_BG_PATH
@ -24,60 +22,11 @@ else:
bg_path = NM_BG_PATH
def draw_text_by_line(
img: Image.Image,
pos: Tuple[int, int],
text: str,
font: ImageFont.FreeTypeFont,
fill: Union[Tuple[int, int, int, int], str],
max_length: float,
center=False,
line_space: Optional[float] = None,
):
"""
在图片上写长段文字, 自动换行
max_length单行最大长度, 单位像素
line_space 行间距, 单位像素, 默认是字体高度的0.3
"""
x, y = pos
_, h = font.getsize('X')
if line_space is None:
y_add = math.ceil(1.3 * h)
else:
y_add = math.ceil(h + line_space)
draw = ImageDraw.Draw(img)
row = "" # 存储本行文字
length = 0 # 记录本行长度
for character in text:
w, h = font.getsize(character) # 获取当前字符的宽度
if length + w * 2 <= max_length:
row += character
length += w
else:
row += character
if center:
font_size = font.getsize(row)
x = math.ceil((img.size[0] - font_size[0]) / 2)
draw.text((x, y), row, font=font, fill=fill)
row = ""
length = 0
y += y_add
if row != "":
if center:
font_size = font.getsize(row)
x = math.ceil((img.size[0] - font_size[0]) / 2)
draw.text((x, y), row, font=font, fill=fill)
async def get_qq_avatar(
qid: Optional[Union[int, str]] = None, avatar_url: Optional[str] = None
async def get_simple_bg(
based_w: int, based_h: int, image: Union[str, None, Image.Image] = None
) -> Image.Image:
if qid:
avatar_url = f'http://q1.qlogo.cn/g?b=qq&nk={qid}&s=640'
elif avatar_url is None:
avatar_url = 'https://q1.qlogo.cn/g?b=qq&nk=3399214199&s=640'
char_pic = Image.open(BytesIO(get(avatar_url).content)).convert('RGBA')
return char_pic
CIL = CustomizeImage(NM_BG_PATH)
return CIL.get_image(image, based_w, based_h)
async def get_color_bg(
@ -94,233 +43,13 @@ async def get_color_bg(
image = Image.open(path2)
elif path.exists():
image = Image.open(path)
CI_img = CustomizeImage(image, based_w, based_h)
img = CI_img.bg_img
color = CI_img.bg_color
CI_img = CustomizeImage(bg_path)
img = CI_img.get_image(image, based_w, based_h)
color = CI_img.get_bg_color(img)
if not without_mask:
color_mask = Image.new('RGBA', (based_w, based_h), color)
enka_mask = Image.open(TEXT2D_PATH / 'mask.png').resize(
enka_mask = Image.open(TEXT_PATH / 'bg_mask.png').resize(
(based_w, based_h)
)
img.paste(color_mask, (0, 0), enka_mask)
return img
async def get_simple_bg(
based_w: int, based_h: int, image: Union[str, None, Image.Image] = None
) -> Image.Image:
if image:
if isinstance(image, str):
edit_bg = Image.open(BytesIO(get(image).content)).convert('RGBA')
elif isinstance(image, Image.Image):
edit_bg = image.convert('RGBA')
else:
bg_path = random.choice(list(NM_BG_PATH.iterdir()))
edit_bg = Image.open(bg_path).convert('RGBA')
# 确定图片的长宽
bg_img = crop_center_img(edit_bg, based_w, based_h)
return bg_img
def crop_center_img(
img: Image.Image, based_w: int, based_h: int
) -> Image.Image:
# 确定图片的长宽
based_scale = '%.3f' % (based_w / based_h)
w, h = img.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:
resize_img = img.resize((new_w, based_h), Image.ANTIALIAS)
x1 = int(new_w / 2 - based_w / 2)
y1 = 0
x2 = int(new_w / 2 + based_w / 2)
y2 = based_h
else:
resize_img = img.resize((based_w, new_h), Image.ANTIALIAS)
x1 = 0
y1 = int(new_h / 2 - based_h / 2)
x2 = based_w
y2 = int(new_h / 2 + based_h / 2)
crop_img = resize_img.crop((x1, y1, x2, y2))
return crop_img
async def draw_pic_with_ring(
pic: Image.Image,
size: int,
bg_color: Optional[Tuple[int, int, int]] = None,
):
'''
:说明:
绘制一张带白色圆环的1:1比例图片
:参数:
* pic: `Image.Image`: 要修改的图片
* size: `int`: 最后传出图片的大小(1:1)
* bg_color: `Optional[Tuple[int, int, int]]`: 是否指定圆环内背景颜色
:返回:
* img: `Image.Image`: 图片对象
'''
img = Image.new('RGBA', (size, size))
mask = mask_pic.resize((size, size))
# ring = ring_pic.resize((size, size))
resize_pic = crop_center_img(pic, size, size)
if bg_color:
img_color = Image.new('RGBA', (size, size), bg_color)
img_color.paste(resize_pic, (0, 0), resize_pic)
img.paste(img_color, (0, 0), mask)
else:
img.paste(resize_pic, (0, 0), mask)
# img.paste(ring, (0, 0), ring)
return img
class CustomizeImage:
def __init__(
self, image: Union[str, Image.Image], 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, is_light=True)
self.text_color = self.get_text_color(self.bg_color)
self.highlight_color = self.get_highlight_color(self.bg_color)
self.char_color = self.get_char_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)
@staticmethod
def get_image(
image: Union[str, Image.Image], based_w: int, based_h: int
) -> Image.Image:
# 获取背景图片
if isinstance(image, Image.Image):
edit_bg = image
elif image:
edit_bg = Image.open(BytesIO(get(image).content)).convert('RGBA')
else:
path = random.choice(list(bg_path.iterdir()))
edit_bg = Image.open(path).convert('RGBA')
# 确定图片的长宽
bg_img = crop_center_img(edit_bg, based_w, based_h)
return bg_img
@staticmethod
def get_dominant_color(pil_img: Image.Image) -> Tuple[int, int, int]:
img = pil_img.copy()
img = img.convert("RGBA")
img = img.resize((1, 1), resample=0)
dominant_color = img.getpixel((0, 0))
return dominant_color
@staticmethod
def get_bg_color(
edit_bg: Image.Image, is_light: Optional[bool] = False
) -> Tuple[int, int, int]:
# 获取背景主色
color = 8
q = edit_bg.quantize(colors=color, method=2)
bg_color = (0, 0, 0)
if is_light:
based_light = 195
else:
based_light = 120
temp = 9999
for i in range(color):
bg = tuple(
q.getpalette()[ # type:ignore
i * 3 : (i * 3) + 3 # noqa:E203
]
)
light_value = bg[0] * 0.3 + bg[1] * 0.6 + bg[2] * 0.1
if abs(light_value - based_light) < temp: # noqa:E203
bg_color = bg
temp = abs(light_value - based_light)
return bg_color
@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),
)
return text_color
@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),
)
return char_color
@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),
)
return char_color
@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),
)
return bg_detail_color
@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 = {
'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':
return highlight_color['red'], green_color, highlight_color['blue']
elif name == 'blue':
return highlight_color['red'], highlight_color['green'], blue_color
else:
return 0, 0, 0 # Error

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -45,7 +45,7 @@
"天才俱乐部第83席",
"天才俱乐部第八十三席",
"黑塔女士",
"转圈圈"
"转圈圈"
],
"1003": [
"姬子",
@ -128,7 +128,7 @@
"骚狐狸"
],
"8002": [
"开拓者",
"开拓者",
"开拓者物理",
"爷",
"星爷",
@ -143,7 +143,7 @@
"毁灭主"
],
"8004": [
"开拓者",
"开拓者",
"开拓者火",
"火主",
"存护主"

View File

@ -76,7 +76,10 @@ class MysApi(_MysApi):
is_os = self.check_os(uid)
if is_os:
HEADER = copy.deepcopy(self._HEADER_OS)
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
ck = await self.get_ck(uid, 'OWNER')
if ck is None:
return -51
HEADER['Cookie'] = ck
HEADER['DS'] = generate_os_ds()
header = HEADER
data = await self.simple_mys_req(
@ -105,10 +108,14 @@ class MysApi(_MysApi):
return -51
header['Cookie'] = sk
header['x-rpc-channel'] = 'beta'
header['x-rpc-device_id'] = await self.get_user_device_id(uid)
device_id = await self.get_user_device_id(uid)
header['x-rpc-device_id'] = (
'233333' if device_id is None else device_id
)
header['x-rpc-app_version'] = '2.53.0'
header['x-rpc-device_model'] = 'Mi 10'
header['x-rpc-device_fp'] = await self.get_user_fp(uid)
fp = await self.get_user_fp(uid)
header['x-rpc-device_fp'] = 'Asmr489' if fp is None else fp
header['x-rpc-client_type'] = '2'
header['DS'] = get_ds_token2()
header['Referer'] = 'https://app.mihoyo.com'
@ -126,7 +133,10 @@ class MysApi(_MysApi):
is_os = self.check_os(uid)
if is_os:
HEADER = copy.deepcopy(self._HEADER_OS)
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
ck = await self.get_ck(uid, 'OWNER')
if ck is None:
return -51
HEADER['Cookie'] = ck
HEADER['DS'] = generate_os_ds()
header = HEADER
data = await self.simple_mys_req(
@ -159,7 +169,10 @@ class MysApi(_MysApi):
server_id = RECOGNIZE_SERVER.get(str(uid)[0])
if self.check_os(uid):
HEADER = copy.deepcopy(self._HEADER_OS)
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
ck = await self.get_ck(uid, 'OWNER')
if ck is None:
return -51
HEADER['Cookie'] = ck
HEADER['DS'] = generate_os_ds()
header = HEADER
url = self.MAPI['STAR_RAIL_GACHA_LOG_URL_OS']
@ -200,7 +213,10 @@ class MysApi(_MysApi):
is_os = self.check_os(uid)
if is_os:
HEADER = copy.deepcopy(self._HEADER_OS)
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
ck = await self.get_ck(uid, 'OWNER')
if ck is None:
return -51
HEADER['Cookie'] = ck
HEADER['DS'] = generate_os_ds()
header = HEADER
data = await self.simple_mys_req(
@ -259,7 +275,10 @@ class MysApi(_MysApi):
'lang': 'zh-cn',
}
HEADER = copy.deepcopy(self._HEADER_OS)
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
ck = await self.get_ck(uid, 'OWNER')
if ck is None:
return -51
HEADER['Cookie'] = ck
HEADER['DS'] = generate_os_ds()
header = HEADER
else:
@ -287,7 +306,10 @@ class MysApi(_MysApi):
is_os = self.check_os(uid)
if is_os:
HEADER = copy.deepcopy(self._HEADER_OS)
HEADER['Cookie'] = await self.get_ck(uid, 'OWNER')
ck = await self.get_ck(uid, 'OWNER')
if ck is None:
return -51
HEADER['Cookie'] = ck
HEADER['DS'] = generate_os_ds()
header = HEADER
data = await self.simple_mys_req(