109 lines
3.7 KiB
Python
109 lines
3.7 KiB
Python
"""通知图片测试命令 - 供超级用户在群聊/私聊中预览统一通知卡片。
|
||
|
||
用法(仅超级用户,群内直接发送或私聊发送,均无需 @机器人):
|
||
测试通知图片
|
||
通知图片测试
|
||
测试通知卡片
|
||
"""
|
||
import asyncio
|
||
|
||
from nonebot import on_command, logger
|
||
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent, MessageSegment
|
||
from nonebot.matcher import Matcher
|
||
from nonebot.permission import SUPERUSER
|
||
|
||
from .preview_image_render import get_preview_renderer
|
||
from .text_parser import TextParser
|
||
|
||
# 主命令与别名,唯一的命令入口定义,测试直接据此断言
|
||
TEST_COMMAND = "测试通知图片"
|
||
"""主命令"""
|
||
TEST_COMMAND_ALIASES = ("通知图片测试", "测试通知卡片")
|
||
"""命令别名"""
|
||
|
||
# 固定预览内容:覆盖标题、中文、多行、Emoji 与中文标点,便于肉眼核对版式
|
||
PREVIEW_TITLE = "# 会被解析为换行:"
|
||
"""预览卡片标题行文案:同时演示 # 作为换行符的用法"""
|
||
PREVIEW_TEXT = "\n".join(
|
||
(
|
||
"【通知卡片测试】",
|
||
"本卡片由「测试通知图片」命令生成,用于核对统一通知卡片版式。",
|
||
"中文标点:逗号,句号。顿号、分号;冒号:问号?感叹号!",
|
||
"Emoji:🎉 🏇 😀 👍🏻 🇨🇳",
|
||
"混合排版:emoji 与正文之间不应错位 🎊,行距与折行都要正常。",
|
||
)
|
||
)
|
||
"""预览正文(按换行符直接给出,未经 # 替换)"""
|
||
PREVIEW_PREVIEW_TEXT = PREVIEW_TEXT.replace("\n", "#")
|
||
"""预览文本的 # 写法,经 TextParser 解析后与 PREVIEW_TEXT 一致"""
|
||
|
||
|
||
def resolve_scene(event: MessageEvent) -> str:
|
||
"""
|
||
按事件来源选择场景徽章
|
||
|
||
Args:
|
||
event: 消息事件
|
||
|
||
Returns:
|
||
群聊为 "group",否则为 "private"
|
||
"""
|
||
return "group" if getattr(event, "group_id", None) else "private"
|
||
|
||
|
||
def build_message(image_base64: str) -> Message:
|
||
"""
|
||
构建 OneBot V11 图片消息
|
||
|
||
Args:
|
||
image_base64: base64:// 前缀的图片数据
|
||
|
||
Returns:
|
||
可直接发送的 Message
|
||
"""
|
||
return Message(MessageSegment.image(image_base64))
|
||
|
||
|
||
def preview_text() -> str:
|
||
"""
|
||
构造固定预览文本(以 # 表示换行,交由 TextParser 解析)
|
||
|
||
Returns:
|
||
预览文本
|
||
"""
|
||
return PREVIEW_PREVIEW_TEXT
|
||
|
||
|
||
test_notification_image = on_command(
|
||
TEST_COMMAND,
|
||
aliases=set(TEST_COMMAND_ALIASES),
|
||
permission=SUPERUSER,
|
||
priority=1,
|
||
block=True,
|
||
)
|
||
|
||
|
||
@test_notification_image.handle()
|
||
async def handle_test_notification_image(matcher: Matcher, bot: Bot, event: MessageEvent):
|
||
"""把固定预览内容渲染成通知卡片并回发到当前会话。"""
|
||
from . import plugin_config
|
||
|
||
scene = resolve_scene(event)
|
||
parsed_text = TextParser(max_length=plugin_config.MaxTextLength).parse(preview_text())
|
||
renderer = get_preview_renderer(plugin_config)
|
||
|
||
try:
|
||
# Pillow 渲染是同步阻塞操作,放到线程池避免阻塞事件循环
|
||
image_base64 = await asyncio.to_thread(
|
||
renderer.render_to_base64, parsed_text, PREVIEW_TITLE, scene
|
||
)
|
||
# 用当前事件的 Bot 直接发送 OneBot V11 图片消息,群聊/私聊都回到触发会话
|
||
await bot.send(event, build_message(image_base64))
|
||
logger.info(f"[Danding_QqPush] 通知图片测试成功 - scene={scene}")
|
||
except BaseException as e:
|
||
# 保留 NoneBot 控制流异常(如 FinishedException),只处理真正的异常
|
||
if not isinstance(e, Exception):
|
||
raise
|
||
logger.error(f"[Danding_QqPush] 通知图片测试失败 - scene={scene}: {e}")
|
||
await matcher.finish("通知图片生成失败,请查看机器人日志后重试。")
|