初步尝试UI化
This commit is contained in:
@ -562,8 +562,8 @@ class ImageFilterImplement:
|
|||||||
def apply_shadow(image: Image.Image,
|
def apply_shadow(image: Image.Image,
|
||||||
x_offset: int = 10,
|
x_offset: int = 10,
|
||||||
y_offset: int = 10,
|
y_offset: int = 10,
|
||||||
blur = 10,
|
blur: float = 10,
|
||||||
opacity = 0.5,
|
opacity: float = 0.5,
|
||||||
shadow_color = "black") -> Image.Image:
|
shadow_color = "black") -> Image.Image:
|
||||||
if image.mode != 'RGBA':
|
if image.mode != 'RGBA':
|
||||||
image = image.convert('RGBA')
|
image = image.convert('RGBA')
|
||||||
|
|||||||
26
konabot/plugins/notice_ui/__init__.py
Normal file
26
konabot/plugins/notice_ui/__init__.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from loguru import logger
|
||||||
|
import nonebot
|
||||||
|
from nonebot.adapters import Event as BaseEvent
|
||||||
|
from nonebot.adapters.discord.event import MessageEvent as DiscordMessageEvent
|
||||||
|
from nonebot_plugin_alconna import (
|
||||||
|
UniMessage,
|
||||||
|
UniMsg
|
||||||
|
)
|
||||||
|
from konabot.plugins.notice_ui.notice import NoticeUI
|
||||||
|
from nonebot_plugin_alconna import on_alconna, Alconna, Args
|
||||||
|
|
||||||
|
evt = on_alconna(Alconna(
|
||||||
|
"notice",
|
||||||
|
Args["title", str],
|
||||||
|
Args["message", str]
|
||||||
|
),
|
||||||
|
use_cmd_start=True, use_cmd_sep=False, skip_for_unmatch=True
|
||||||
|
)
|
||||||
|
|
||||||
|
@evt.handle()
|
||||||
|
async def _(title: str, message: str, msg: UniMsg, event: BaseEvent):
|
||||||
|
logger.debug(f"Received notice command with title: {title}, message: {message}")
|
||||||
|
|
||||||
|
out = await NoticeUI.render_notice(title, message)
|
||||||
|
|
||||||
|
await evt.send(await UniMessage().image(raw=out).export())
|
||||||
53
konabot/plugins/notice_ui/notice.py
Normal file
53
konabot/plugins/notice_ui/notice.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
from io import BytesIO
|
||||||
|
from PIL import Image
|
||||||
|
from konabot.common.web_render import konaweb
|
||||||
|
from konabot.common.web_render.core import WebRenderer
|
||||||
|
|
||||||
|
from playwright.async_api import Page
|
||||||
|
|
||||||
|
class NoticeUI:
|
||||||
|
@staticmethod
|
||||||
|
async def render_notice(title: str, message: str) -> bytes:
|
||||||
|
"""
|
||||||
|
渲染一个通知图片,包含标题和消息内容。
|
||||||
|
"""
|
||||||
|
async def page_function(page: Page):
|
||||||
|
# 直到 setMaskMode 函数加载完成
|
||||||
|
await page.wait_for_function("typeof setMaskMode === 'function'", timeout=1000)
|
||||||
|
await page.evaluate('setMaskMode(false)')
|
||||||
|
# 直到 setContent 函数加载完成
|
||||||
|
await page.wait_for_function("typeof setContent === 'function'", timeout=1000)
|
||||||
|
# 设置标题和消息内容
|
||||||
|
await page.evaluate(f'setContent("{title}", "{message}")')
|
||||||
|
|
||||||
|
async def mask_function(page: Page):
|
||||||
|
# 直到 setContent 函数加载完成
|
||||||
|
await page.wait_for_function("typeof setContent === 'function'", timeout=1000)
|
||||||
|
# 设置标题和消息内容
|
||||||
|
await page.evaluate(f'setContent("{title}", "{message}")')
|
||||||
|
# 直到 setMaskMode 函数加载完成
|
||||||
|
await page.wait_for_function("typeof setMaskMode === 'function'", timeout=1000)
|
||||||
|
await page.evaluate('setMaskMode(true)')
|
||||||
|
|
||||||
|
image_bytes = await WebRenderer.render_with_persistent_page(
|
||||||
|
"notice_renderer",
|
||||||
|
konaweb('notice'),
|
||||||
|
target='#main',
|
||||||
|
other_function=page_function,
|
||||||
|
)
|
||||||
|
|
||||||
|
mask_bytes = await WebRenderer.render_with_persistent_page(
|
||||||
|
"notice_renderer",
|
||||||
|
konaweb('notice'),
|
||||||
|
target='#main',
|
||||||
|
other_function=mask_function)
|
||||||
|
|
||||||
|
image = Image.open(BytesIO(image_bytes)).convert("RGBA")
|
||||||
|
mask = Image.open(BytesIO(mask_bytes)).convert("L")
|
||||||
|
# 应用遮罩
|
||||||
|
image.putalpha(mask)
|
||||||
|
|
||||||
|
output_buffer = BytesIO()
|
||||||
|
image.save(output_buffer, format="GIF", disposal=2, loop=0)
|
||||||
|
output_buffer.seek(0)
|
||||||
|
return output_buffer.getvalue()
|
||||||
@ -6,6 +6,7 @@ from pathlib import Path
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import nanoid
|
import nanoid
|
||||||
|
from konabot.plugins.notice_ui.notice import NoticeUI
|
||||||
import nonebot
|
import nonebot
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from nonebot import get_plugin_config, on_message
|
from nonebot import get_plugin_config, on_message
|
||||||
@ -107,6 +108,10 @@ async def _(task: LongTask):
|
|||||||
await task.target.send_message(
|
await task.target.send_message(
|
||||||
UniMessage().text(f"代办提醒:{message}")
|
UniMessage().text(f"代办提醒:{message}")
|
||||||
)
|
)
|
||||||
|
notice_bytes = NoticeUI.render_notice("代办提醒", message)
|
||||||
|
await task.target.send_message(
|
||||||
|
await UniMessage().image(raw=notice_bytes).export()
|
||||||
|
)
|
||||||
async with DATA_FILE_LOCK:
|
async with DATA_FILE_LOCK:
|
||||||
data = load_notify_config()
|
data = load_notify_config()
|
||||||
if (chan := data.notify_channels.get(task.target.target_id)) is not None:
|
if (chan := data.notify_channels.get(task.target.target_id)) is not None:
|
||||||
|
|||||||
Reference in New Issue
Block a user