优化帮助图显示,增加图片资源缓存配置项

This commit is contained in:
CMHopeSunshine 2023-01-08 15:37:19 +08:00
parent 584ee1aa80
commit 0546be70c8
22 changed files with 152 additions and 158 deletions

View File

@ -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='模拟抽卡单次最多十连数')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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:

View File

@ -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文件返回文件数据

View File

@ -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
@ -29,10 +30,7 @@ class PMImage:
: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])
@ -69,7 +67,6 @@ class PMImage:
"""
保存图像
:param path: 保存路径
:return:
"""
self.image.save(path, **kwargs)
@ -235,7 +232,6 @@ class PMImage:
else:
width_now += c_length
@run_sync
def stretch(self,
pos: Tuple[int, int],
@ -331,10 +327,11 @@ class PMImage:
:param radius: 半径
:param color: 颜色
:param angles: 角列表
:return:
"""
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),
@ -359,7 +356,6 @@ class PMImage:
:param end: 终点
:param color: 颜色
:param width: 宽度
:return:
"""
self.draw.line(begin + end, fill=color, width=width)
@ -468,7 +464,7 @@ 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: 边框宽度
@ -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:
"""

View File

@ -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

View File

@ -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
@ -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]))