mirror of
https://github.com/xuthus83/LittlePaimon.git
synced 2024-10-21 16:27:15 +08:00
✨ 优化帮助图
显示,增加图片资源缓存
配置项
This commit is contained in:
parent
584ee1aa80
commit
0546be70c8
@ -8,6 +8,8 @@ class ConfigModel(BaseModel):
|
||||
CookieWeb_url: str = Field('http://127.0.0.1:13579/LittlePaimon/cookie', alias='CookieWeb地址')
|
||||
qrcode_bind_use_url: bool = Field(False, alias='绑定二维码以链接形式发送')
|
||||
|
||||
img_use_cache: bool = Field(True, alias='图片资源缓存开关')
|
||||
|
||||
sim_gacha_cd_group: int = Field(30, alias='模拟抽卡群冷却')
|
||||
sim_gacha_cd_member: int = Field(60, alias='模拟抽卡群员冷却')
|
||||
sim_gacha_max: int = Field(5, alias='模拟抽卡单次最多十连数')
|
||||
|
@ -2,8 +2,7 @@ import asyncio
|
||||
from typing import List
|
||||
|
||||
from LittlePaimon.database import GenshinVoice
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
|
||||
|
@ -6,8 +6,7 @@ import pytz
|
||||
from nonebot import get_bot
|
||||
|
||||
from LittlePaimon.database import AbyssInfo
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, get_qq_avatar
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, get_qq_avatar, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from LittlePaimon.utils.requests import aiorequests
|
||||
|
@ -3,8 +3,7 @@ import datetime
|
||||
|
||||
from LittlePaimon.database import AbyssInfo
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
|
||||
|
||||
|
@ -3,8 +3,7 @@ from typing import List
|
||||
|
||||
from LittlePaimon.database import Character, LastQuery
|
||||
from LittlePaimon.utils.alias import get_chara_icon
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from .api import get_team_rate
|
||||
|
@ -2,8 +2,7 @@ import math
|
||||
from collections import defaultdict
|
||||
from enum import IntEnum, auto
|
||||
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
import datetime
|
||||
import random
|
||||
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage
|
||||
from LittlePaimon.utils.image import font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
|
||||
|
@ -4,8 +4,7 @@ import math
|
||||
import random
|
||||
from typing import Tuple, List, Optional
|
||||
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, get_qq_avatar, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, get_qq_avatar, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from .models import GachaLogInfo, FiveStarItem, FourStarItem
|
||||
|
@ -5,9 +5,8 @@ from typing import List
|
||||
|
||||
from LittlePaimon.database import Character, PlayerInfo, Player
|
||||
from LittlePaimon.utils.alias import get_chara_icon
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.genshin import GenshinTools
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from .draw_player_card import get_avatar, draw_weapon_icon
|
||||
|
@ -1,9 +1,8 @@
|
||||
import math
|
||||
|
||||
from LittlePaimon.database import Character
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.genshin import GenshinTools
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from LittlePaimon.utils.requests import aiorequests
|
||||
|
@ -2,9 +2,8 @@ from nonebot import logger
|
||||
|
||||
from LittlePaimon.database import Character
|
||||
from LittlePaimon.utils.alias import get_chara_icon
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.genshin import GenshinTools
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import ENKA_RES, RESOURCE_BASE_PATH
|
||||
from .damage_cal import get_role_dmg
|
||||
|
@ -3,8 +3,7 @@ from typing import List, Tuple, Optional
|
||||
|
||||
from LittlePaimon.database import PlayerInfo, Character, PlayerWorldInfo, Weapon, Player
|
||||
from LittlePaimon.utils.alias import get_chara_icon
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, get_qq_avatar, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, get_qq_avatar, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import random
|
||||
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
|
||||
|
@ -3,8 +3,7 @@ import math
|
||||
from typing import Optional
|
||||
|
||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from LittlePaimon.utils.requests import aiorequests
|
||||
|
@ -3,8 +3,8 @@ from pathlib import Path
|
||||
|
||||
from LittlePaimon.database import Character, LastQuery
|
||||
from LittlePaimon.utils import scheduler
|
||||
from LittlePaimon.utils.files import save_json, load_json, load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.files import save_json, load_json
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from LittlePaimon.utils.requests import aiorequests
|
||||
|
@ -4,8 +4,7 @@ from typing import List
|
||||
from PIL import Image, ImageFile, ImageOps
|
||||
|
||||
from LittlePaimon.utils import logger
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
from LittlePaimon.utils.requests import aiorequests
|
||||
|
@ -3,8 +3,7 @@ from typing import List
|
||||
|
||||
from LittlePaimon import __version__
|
||||
from LittlePaimon.config import PluginInfo
|
||||
from LittlePaimon.utils.files import load_image
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm
|
||||
from LittlePaimon.utils.image import PMImage, font_manager as fm, load_image
|
||||
from LittlePaimon.utils.message import MessageBuild
|
||||
from LittlePaimon.utils.path import RESOURCE_BASE_PATH
|
||||
|
||||
@ -47,22 +46,22 @@ async def draw_help(plugin_list: List[PluginInfo]):
|
||||
plugin_line = PMImage(orange_line)
|
||||
plugin_name_bg = PMImage(orange_name_bg)
|
||||
matcher_card = PMImage(orange_bord)
|
||||
name_length = img.text_length(plugin.name, fm.get('SourceHanSerifCN-Bold.otf', 30))
|
||||
plugin_name = plugin.name.replace('\n', '')
|
||||
name_length = img.text_length(plugin_name, fm.get('SourceHanSerifCN-Bold.otf', 30))
|
||||
await img.paste(plugin_line, (40, height_now))
|
||||
await plugin_name_bg.stretch((23, plugin_name_bg.width - 36), int(name_length), 'width')
|
||||
await img.paste(plugin_name_bg, (40, height_now))
|
||||
await img.text(plugin.name, 63, height_now + 5, fm.get('SourceHanSerifCN-Bold.otf', 30), 'white')
|
||||
await img.text(plugin_name, 63, height_now + 5, fm.get('SourceHanSerifCN-Bold.otf', 30), 'white')
|
||||
height_now += plugin_line.height + 11
|
||||
if plugin.matchers:
|
||||
matchers = [matcher for matcher in plugin.matchers if matcher.pm_show and matcher.pm_usage]
|
||||
if plugin.matchers and (matchers := [matcher for matcher in plugin.matchers if matcher.pm_show and (matcher.pm_usage or matcher.pm_name)]):
|
||||
matcher_groups = [matchers[i:i + 3] for i in range(0, len(matchers), 3)]
|
||||
for matcher_group in matcher_groups:
|
||||
max_length = max(len(matcher.pm_description) if matcher.pm_description else 0 for matcher in matcher_group)
|
||||
max_length = max(len(matcher.pm_description.replace('\n', '')) if matcher.pm_description else 0 for matcher in matcher_group)
|
||||
max_height = math.ceil(max_length / 16) * 22 + 40
|
||||
await matcher_card.stretch((5, matcher_card.height - 5), max_height, 'height')
|
||||
for matcher in matcher_group:
|
||||
await img.paste(matcher_card, (40 + 336 * matcher_group.index(matcher), height_now))
|
||||
await img.text(matcher.pm_usage, 40 + 336 * matcher_group.index(matcher) + 15, height_now + 10, fm.get('SourceHanSansCN-Bold.otf', 24), 'black')
|
||||
await img.text(matcher.pm_usage or matcher.pm_name, 40 + 336 * matcher_group.index(matcher) + 15, height_now + 10, fm.get('SourceHanSansCN-Bold.otf', 24), 'black')
|
||||
if matcher.pm_description:
|
||||
await img.text_box(matcher.pm_description.replace('\n', '^'), (40 + 336 * matcher_group.index(matcher) + 10, 40 + 336 * matcher_group.index(matcher) + matcher_card.width - 22),
|
||||
(height_now + 44, height_now + max_height - 10), fm.get('SourceHanSansCN-Bold.otf', 18), '#40342d')
|
||||
|
@ -4,7 +4,7 @@ from nonebot import get_driver
|
||||
from .logger import logger
|
||||
from .scheduler import scheduler
|
||||
|
||||
__version__ = '3.0.2'
|
||||
__version__ = '3.0.3'
|
||||
|
||||
DRIVER = get_driver()
|
||||
try:
|
||||
|
@ -4,60 +4,15 @@ except ImportError:
|
||||
import json
|
||||
from pathlib import Path
|
||||
from ssl import SSLCertVerificationError
|
||||
from typing import Union, Optional, Tuple, Dict
|
||||
from typing import Union
|
||||
|
||||
import httpx
|
||||
import tqdm.asyncio
|
||||
from PIL import Image
|
||||
from ruamel import yaml
|
||||
|
||||
from .requests import aiorequests
|
||||
|
||||
|
||||
cache_image: Dict[str, any] = {}
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'}
|
||||
|
||||
|
||||
async def load_image(
|
||||
path: Union[Path, str],
|
||||
*,
|
||||
size: Optional[Union[Tuple[int, int], float]] = None,
|
||||
crop: Optional[Tuple[int, int, int, int]] = None,
|
||||
mode: Optional[str] = None,
|
||||
) -> Image.Image:
|
||||
"""
|
||||
读取图像,并预处理
|
||||
:param path: 图片路径
|
||||
:param size: 预处理尺寸
|
||||
:param crop: 预处理裁剪大小
|
||||
:param mode: 预处理图像模式
|
||||
:return: 图像对象
|
||||
"""
|
||||
if str(path) in cache_image:
|
||||
img = cache_image[str(path)]
|
||||
else:
|
||||
if path.exists():
|
||||
img = Image.open(path)
|
||||
elif path.name.startswith(('UI_', 'Skill_')):
|
||||
img = await aiorequests.download_icon(path.name, headers=headers, save_path=path, follow_redirects=True)
|
||||
if img is None or isinstance(img, str):
|
||||
return Image.new('RGBA', size=size or (50, 50), color=(0, 0, 0, 0))
|
||||
else:
|
||||
raise FileNotFoundError(f'{path} not found')
|
||||
cache_image[str(path)] = img
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
if size:
|
||||
if isinstance(size, float):
|
||||
img = img.resize((int(img.size[0] * size), int(img.size[1] * size)), Image.ANTIALIAS)
|
||||
elif isinstance(size, tuple):
|
||||
img = img.resize(size, Image.ANTIALIAS)
|
||||
if crop:
|
||||
img = img.crop(crop)
|
||||
return img
|
||||
|
||||
|
||||
def load_json(path: Union[Path, str], encoding: str = 'utf-8'):
|
||||
"""
|
||||
读取本地json文件,返回文件数据。
|
||||
|
@ -1,11 +1,12 @@
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from typing import Tuple, Union, Literal, List
|
||||
from typing import Tuple, Union, Literal, List, Optional, Dict
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from PIL import Image, ImageDraw, ImageFont, ImageOps
|
||||
from nonebot.utils import run_sync
|
||||
|
||||
from LittlePaimon.config import config
|
||||
from .path import FONTS_PATH
|
||||
from .requests import aiorequests
|
||||
|
||||
@ -22,17 +23,14 @@ class PMImage:
|
||||
mode: str = 'RGBA'
|
||||
):
|
||||
"""
|
||||
初始化图像,优先读取image参数,如无则新建图像
|
||||
:param image: PIL对象或图像路径
|
||||
:param size: 图像大小
|
||||
:param color: 图像颜色
|
||||
:param mode: 图像模式
|
||||
初始化图像,优先读取image参数,如无则新建图像
|
||||
:param image: PIL对象或图像路径
|
||||
:param size: 图像大小
|
||||
:param color: 图像颜色
|
||||
:param mode: 图像模式
|
||||
"""
|
||||
if image:
|
||||
if isinstance(image, Path):
|
||||
self.image = Image.open(image)
|
||||
else:
|
||||
self.image = image.copy()
|
||||
self.image = Image.open(image) if isinstance(image, Path) else image.copy()
|
||||
else:
|
||||
if mode == 'RGB':
|
||||
color = (color[0], color[1], color[2])
|
||||
@ -68,8 +66,7 @@ class PMImage:
|
||||
def save(self, path: Union[str, Path], **kwargs):
|
||||
"""
|
||||
保存图像
|
||||
:param path: 保存路径
|
||||
:return:
|
||||
:param path: 保存路径
|
||||
"""
|
||||
self.image.save(path, **kwargs)
|
||||
|
||||
@ -84,7 +81,7 @@ class PMImage:
|
||||
def copy(self) -> "PMImage":
|
||||
"""
|
||||
返回一个本对象的复制
|
||||
:return: PMImage
|
||||
:return: PMImage
|
||||
"""
|
||||
return PMImage(self.image.copy())
|
||||
|
||||
@ -117,7 +114,7 @@ class PMImage:
|
||||
def resize(self, size: Union[float, Tuple[int, int]]):
|
||||
"""
|
||||
缩放图片
|
||||
:param size: 缩放大小/区域
|
||||
:param size: 缩放大小/区域
|
||||
"""
|
||||
if isinstance(size, (float, int)):
|
||||
self.image = self.image.resize((int(self.width * size), int(self.height * size)), Image.Resampling.LANCZOS)
|
||||
@ -129,7 +126,7 @@ class PMImage:
|
||||
def crop(self, box: Tuple[int, int, int, int]):
|
||||
"""
|
||||
裁剪图像
|
||||
:param box: 目标区域
|
||||
:param box: 目标区域
|
||||
"""
|
||||
self.image = self.image.crop(box)
|
||||
self.draw = ImageDraw.Draw(self.image)
|
||||
@ -138,8 +135,8 @@ class PMImage:
|
||||
def rotate(self, angle: float, expand: bool = False, **kwargs):
|
||||
"""
|
||||
旋转图像
|
||||
:param angle: 角度
|
||||
:param expand: expand
|
||||
:param angle: 角度
|
||||
:param expand: expand
|
||||
"""
|
||||
self.image.rotate(angle, resample=Image.BICUBIC, expand=expand, **kwargs)
|
||||
self.draw = ImageDraw.Draw(self.image)
|
||||
@ -152,9 +149,9 @@ class PMImage:
|
||||
):
|
||||
"""
|
||||
粘贴图像
|
||||
:param image: 图像
|
||||
:param pos: 位置
|
||||
:param alpha: 是否透明
|
||||
:param image: 图像
|
||||
:param pos: 位置
|
||||
:param alpha: 是否透明
|
||||
"""
|
||||
if image is None:
|
||||
return
|
||||
@ -178,12 +175,12 @@ class PMImage:
|
||||
):
|
||||
"""
|
||||
写文本
|
||||
:param text: 文本
|
||||
:param width: 位置横坐标
|
||||
:param height: 位置纵坐标
|
||||
:param font: 字体
|
||||
:param color: 颜色
|
||||
:param align: 对齐类型
|
||||
:param text: 文本
|
||||
:param width: 位置横坐标
|
||||
:param height: 位置纵坐标
|
||||
:param font: 字体
|
||||
:param color: 颜色
|
||||
:param align: 对齐类型
|
||||
"""
|
||||
if align == 'left':
|
||||
if isinstance(width, tuple):
|
||||
@ -235,7 +232,6 @@ class PMImage:
|
||||
else:
|
||||
width_now += c_length
|
||||
|
||||
|
||||
@run_sync
|
||||
def stretch(self,
|
||||
pos: Tuple[int, int],
|
||||
@ -243,9 +239,9 @@ class PMImage:
|
||||
type: Literal['width', 'height'] = 'height'):
|
||||
"""
|
||||
将某一部分进行拉伸
|
||||
:param pos: 拉伸的部分
|
||||
:param length: 拉伸的目标长/宽度
|
||||
:param type: 拉伸方向,width:横向, height: 竖向
|
||||
:param pos: 拉伸的部分
|
||||
:param length: 拉伸的目标长/宽度
|
||||
:param type: 拉伸方向,width:横向, height: 竖向
|
||||
"""
|
||||
if pos[0] <= 0:
|
||||
raise ValueError('起始轴必须大于等于0')
|
||||
@ -295,9 +291,9 @@ class PMImage:
|
||||
width: int = 1):
|
||||
"""
|
||||
绘制矩形
|
||||
:param pos: 位置
|
||||
:param color: 颜色
|
||||
:param width: 宽度
|
||||
:param pos: 位置
|
||||
:param color: 颜色
|
||||
:param width: 宽度
|
||||
"""
|
||||
self.draw.rectangle(pos, color, width=width)
|
||||
|
||||
@ -309,10 +305,10 @@ class PMImage:
|
||||
width: int = 1):
|
||||
"""
|
||||
绘制圆角矩形
|
||||
:param pos: 圆角矩形的位置
|
||||
:param radius: 半径
|
||||
:param color: 颜色
|
||||
:param width: 宽度
|
||||
:param pos: 圆角矩形的位置
|
||||
:param radius: 半径
|
||||
:param color: 颜色
|
||||
:param width: 宽度
|
||||
"""
|
||||
self.convert("RGBA")
|
||||
self.draw.rounded_rectangle(xy=pos, radius=radius, fill=color, width=width)
|
||||
@ -326,15 +322,16 @@ class PMImage:
|
||||
angles: List[Literal['ul', 'ur', 'll', 'lr']] = None):
|
||||
"""
|
||||
选择最多4个角绘制圆角矩形
|
||||
:param pos: 左上角起点坐标
|
||||
:param size: 矩形大小
|
||||
:param radius: 半径
|
||||
:param color: 颜色
|
||||
:param angles: 角列表
|
||||
:return:
|
||||
:param pos: 左上角起点坐标
|
||||
:param size: 矩形大小
|
||||
:param radius: 半径
|
||||
:param color: 颜色
|
||||
:param angles: 角列表
|
||||
"""
|
||||
self.draw.rectangle((pos[0] + radius / 2, pos[1], pos[0] + size[0] - (radius / 2), pos[1] + size[1]), fill=color)
|
||||
self.draw.rectangle((pos[0], pos[1] + radius / 2, pos[0] + size[0], pos[1] + size[1] - (radius / 2)), fill=color)
|
||||
self.draw.rectangle((pos[0] + radius / 2, pos[1], pos[0] + size[0] - (radius / 2), pos[1] + size[1]),
|
||||
fill=color)
|
||||
self.draw.rectangle((pos[0], pos[1] + radius / 2, pos[0] + size[0], pos[1] + size[1] - (radius / 2)),
|
||||
fill=color)
|
||||
angle_pos = {
|
||||
'ul': (pos[0], pos[1], pos[0] + radius, pos[1] + radius),
|
||||
'ur': (pos[0] + size[0] - radius, pos[1], pos[0] + size[0], pos[1] + radius),
|
||||
@ -355,11 +352,10 @@ class PMImage:
|
||||
width: int = 1):
|
||||
"""
|
||||
画线
|
||||
:param begin: 起始点
|
||||
:param end: 终点
|
||||
:param color: 颜色
|
||||
:param width: 宽度
|
||||
:return:
|
||||
:param begin: 起始点
|
||||
:param end: 终点
|
||||
:param color: 颜色
|
||||
:param width: 宽度
|
||||
"""
|
||||
self.draw.line(begin + end, fill=color, width=width)
|
||||
|
||||
@ -375,13 +371,13 @@ class PMImage:
|
||||
):
|
||||
"""
|
||||
画百分比圆环
|
||||
:param size: 圆环大小
|
||||
:param pos: 圆环位置
|
||||
:param width: 圆环宽度
|
||||
:param percent: 百分比
|
||||
:param colors: 颜色
|
||||
:param startangle: 角度
|
||||
:param transparent: 是否透明
|
||||
:param size: 圆环大小
|
||||
:param pos: 圆环位置
|
||||
:param width: 圆环宽度
|
||||
:param percent: 百分比
|
||||
:param colors: 颜色
|
||||
:param startangle: 角度
|
||||
:param transparent: 是否透明
|
||||
"""
|
||||
if isinstance(percent, float):
|
||||
if percent < 0 or percent > 1:
|
||||
@ -449,7 +445,7 @@ class PMImage:
|
||||
def to_rounded_corner(self, radii: int = 30):
|
||||
"""
|
||||
将图片变为圆角
|
||||
:param radii: 半径
|
||||
:param radii: 半径
|
||||
"""
|
||||
circle = Image.new("L", (radii * 2, radii * 2), 0)
|
||||
draw = ImageDraw.Draw(circle)
|
||||
@ -468,12 +464,12 @@ class PMImage:
|
||||
|
||||
@run_sync
|
||||
def add_border(self, border_size: int = 10, color: Union[str, Tuple[int, int, int, int]] = 'black',
|
||||
shape: str = 'rectangle'):
|
||||
shape: Literal['rectangle', 'circle'] = 'rectangle'):
|
||||
"""
|
||||
给图片添加边框
|
||||
:param border_size: 边框宽度
|
||||
:param color: 边框颜色
|
||||
:param shape: 边框形状,rectangle或circle
|
||||
:param border_size: 边框宽度
|
||||
:param color: 边框颜色
|
||||
:param shape: 边框形状,rectangle或circle
|
||||
"""
|
||||
self.convert("RGBA")
|
||||
if shape == 'circle':
|
||||
@ -502,9 +498,9 @@ class FontManager:
|
||||
def get(self, font_name: str = 'hywh.ttf', size: int = 25, variation: str = None) -> ImageFont.ImageFont:
|
||||
"""
|
||||
获取字体,如果已在缓存中,则直接返回
|
||||
:param font_name: 字体名称
|
||||
:param size: 字体大小
|
||||
:param variation: 字体变体
|
||||
:param font_name: 字体名称
|
||||
:param size: 字体大小
|
||||
:param variation: 字体变体
|
||||
"""
|
||||
if 'ttf' not in font_name and 'ttc' not in font_name and 'otf' not in font_name:
|
||||
font_name += '.ttf'
|
||||
@ -524,6 +520,50 @@ class FontManager:
|
||||
|
||||
font_manager = FontManager()
|
||||
|
||||
cache_image: Dict[str, any] = {}
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'}
|
||||
|
||||
|
||||
async def load_image(
|
||||
path: Union[Path, str],
|
||||
*,
|
||||
size: Optional[Union[Tuple[int, int], float]] = None,
|
||||
crop: Optional[Tuple[int, int, int, int]] = None,
|
||||
mode: Optional[str] = None,
|
||||
) -> Image.Image:
|
||||
"""
|
||||
读取图像,并预处理
|
||||
:param path: 图片路径
|
||||
:param size: 预处理尺寸
|
||||
:param crop: 预处理裁剪大小
|
||||
:param mode: 预处理图像模式
|
||||
:return: 图像对象
|
||||
"""
|
||||
if config.img_use_cache and str(path) in cache_image:
|
||||
img = cache_image[str(path)]
|
||||
else:
|
||||
if path.exists():
|
||||
img = Image.open(path)
|
||||
elif path.name.startswith(('UI_', 'Skill_')):
|
||||
img = await aiorequests.download_icon(path.name, headers=headers, save_path=path, follow_redirects=True)
|
||||
if img is None or isinstance(img, str):
|
||||
return Image.new('RGBA', size=size or (50, 50), color=(0, 0, 0, 0))
|
||||
else:
|
||||
raise FileNotFoundError(f'{path} not found')
|
||||
if config.img_use_cache:
|
||||
cache_image[str(path)] = img
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
if size:
|
||||
if isinstance(size, float):
|
||||
img = img.resize((int(img.size[0] * size), int(img.size[1] * size)), Image.ANTIALIAS)
|
||||
elif isinstance(size, tuple):
|
||||
img = img.resize(size, Image.ANTIALIAS)
|
||||
if crop:
|
||||
img = img.crop(crop)
|
||||
return img
|
||||
|
||||
|
||||
async def get_qq_avatar(qid: str) -> PMImage:
|
||||
"""
|
||||
|
@ -16,9 +16,8 @@ from nonebot.typing import T_State
|
||||
from LittlePaimon.database import LastQuery, PrivateCookie, Player, PlayerAlias
|
||||
from . import NICKNAME
|
||||
from .alias import get_match_alias
|
||||
from .files import load_image
|
||||
from .filter import filter_msg
|
||||
from .image import PMImage
|
||||
from .image import PMImage, load_image
|
||||
from .requests import aiorequests
|
||||
from .typing import CHARACTERS, MALE_CHARACTERS, FEMALE_CHARACTERS, GIRL_CHARACTERS, BOY_CHARACTERS, \
|
||||
LOLI_CHARACTERS
|
||||
|
@ -1,4 +1,5 @@
|
||||
from amis import Action, Divider, Form, InputText, LevelEnum, Page, PageSchema, Switch, Remark, InputNumber, InputTime, InputTimeRange, Alert, Editor, \
|
||||
from amis import Action, Divider, Form, InputText, LevelEnum, Page, PageSchema, Switch, Remark, InputNumber, InputTime, \
|
||||
InputTimeRange, Alert, Editor, \
|
||||
Select
|
||||
|
||||
action_button = [Action(label='保存', level=LevelEnum.success, type='submit'),
|
||||
@ -65,7 +66,8 @@ cookie_web_form = Form(
|
||||
label='Web端token密钥',
|
||||
name='Web端token密钥',
|
||||
value='${Web端token密钥}',
|
||||
labelRemark=Remark(shape='circle', content='用于对Web端身份认证的token进行加密,为32位字符串,请不要保持为默认密钥,务必进行修改,修改后重启生效')
|
||||
labelRemark=Remark(shape='circle',
|
||||
content='用于对Web端身份认证的token进行加密,为32位字符串,请不要保持为默认密钥,务必进行修改,修改后重启生效')
|
||||
),
|
||||
],
|
||||
actions=action_button
|
||||
@ -180,7 +182,7 @@ ssbq_form = Form(
|
||||
name='实时便签停止检查时间段',
|
||||
value='${实时便签停止检查时间段}',
|
||||
labelRemark=Remark(shape='circle',
|
||||
content='在这段时间(例如深夜)不进行实时便签检查,注意开始时间不要晚于结束时间,不然会有问题'),
|
||||
content='在这段时间(例如深夜)不进行实时便签检查,注意开始时间不要晚于结束时间,不然会有问题'),
|
||||
timeFormat='HH',
|
||||
format='HH',
|
||||
inputFormat='HH时'
|
||||
@ -277,6 +279,15 @@ other_form = Form(
|
||||
api='/LittlePaimon/api/set_config',
|
||||
visibleOn='${select == 7}',
|
||||
body=[
|
||||
Switch(
|
||||
label='图片资源缓存',
|
||||
name='图片资源缓存开关',
|
||||
value='${图片资源缓存开关}',
|
||||
labelRemark=Remark(shape='circle',
|
||||
content='开启时,会将制图所需的图片资源加载到内存中进行缓存,以提高制图速度,如果机器内存较小,建议关闭'),
|
||||
onText='开启',
|
||||
offText='关闭'
|
||||
),
|
||||
Switch(
|
||||
label='网页截图权限',
|
||||
name='启用网页截图权限',
|
||||
@ -306,7 +317,8 @@ other_form = Form(
|
||||
label='github资源地址',
|
||||
name='github资源地址',
|
||||
value='${github资源地址}',
|
||||
labelRemark=Remark(shape='circle', content='本bot部分资源托管在github,如果下载缓慢或无法正常访问,可以尝试更换地址,或者添加你自己的代理地址,注意最后要有/'),
|
||||
labelRemark=Remark(shape='circle',
|
||||
content='本bot部分资源托管在github,如果下载缓慢或无法正常访问,可以尝试更换地址,或者添加你自己的代理地址,注意最后要有/'),
|
||||
creatable=True,
|
||||
options=[
|
||||
{
|
||||
@ -403,4 +415,6 @@ select = Select(label='选择配置类',
|
||||
}
|
||||
])
|
||||
page = PageSchema(url='/bot_config/configs', icon='fa fa-wrench', label='配置项管理',
|
||||
schema=Page(title='配置项管理', initApi='/LittlePaimon/api/get_config', body=[select, cookie_web_form, sim_gacha_form, auto_mys_form, ssbq_form, ys_form, notice_form, other_form, nonebot_form]))
|
||||
schema=Page(title='配置项管理', initApi='/LittlePaimon/api/get_config',
|
||||
body=[select, cookie_web_form, sim_gacha_form, auto_mys_form, ssbq_form, ys_form,
|
||||
notice_form, other_form, nonebot_form]))
|
||||
|
Loading…
Reference in New Issue
Block a user