diff --git a/konabot/common/render_error_message.py b/konabot/common/render_error_message.py new file mode 100644 index 0000000..9c89f92 --- /dev/null +++ b/konabot/common/render_error_message.py @@ -0,0 +1,34 @@ +from typing import Any +from loguru import logger +from nonebot_plugin_alconna import UniMessage +import playwright.async_api +from playwright.async_api import Page + +from konabot.common.web_render import WebRenderer, konaweb + + +async def render_error_message(message: str) -> UniMessage[Any]: + """ + 渲染文本消息为错误信息图片。 + + 如果无法访达 Web 端则返回纯文本给用户。 + """ + + async def page_function(page: Page): + await page.wait_for_function("typeof setContent === 'function'", timeout=3000) + await page.evaluate( + """(message) => {return setContent(message);}""", + message, + ) + + try: + img_data = await WebRenderer.render( + url=konaweb("error_report"), + target="#main", + other_function=page_function, + ) + return UniMessage.image(raw=img_data) + except (playwright.async_api.Error, ConnectionError) as e: + logger.warning("渲染报错信息图片时出错了,回退到文本 ERR={}", e) + return UniMessage.text(message) + diff --git a/konabot/plugins/handle_text/__init__.py b/konabot/plugins/handle_text/__init__.py index f8d417f..c8da6d1 100644 --- a/konabot/plugins/handle_text/__init__.py +++ b/konabot/plugins/handle_text/__init__.py @@ -10,6 +10,7 @@ from nonebot.adapters.onebot.v11.message import Message as OB11Message from konabot.common.apis.ali_content_safety import AlibabaGreen from konabot.common.longtask import DepLongTaskTarget +from konabot.common.render_error_message import render_error_message from konabot.plugins.handle_text.base import ( PipelineRunner, TextHandlerEnvironment, @@ -75,7 +76,9 @@ async def _(msg: UniMsg, evt: Event, bot: Bot, target: DepLongTaskTarget): # 检查是否有错误 for r in results: if r.code != 0: - await target.send_message(f"处理指令时出现问题:{r.ostream}") + message = f"处理指令时出现问题:{r.ostream}" + rendered = await render_error_message(message) + await target.send_message(rendered) return # 收集所有组的文本输出和附件 diff --git a/konabot/plugins/man/__init__.py b/konabot/plugins/man/__init__.py index a7b9585..7dad88b 100644 --- a/konabot/plugins/man/__init__.py +++ b/konabot/plugins/man/__init__.py @@ -5,6 +5,7 @@ import nonebot.adapters import nonebot.rule from nonebot import on_command from nonebot_plugin_alconna import Alconna, Args, UniMessage, on_alconna +import playwright.async_api from konabot.common.nb.is_admin import is_admin from konabot.common.path import DOCS_PATH_MAN1, DOCS_PATH_MAN3, DOCS_PATH_MAN7, DOCS_PATH_MAN8 @@ -87,7 +88,7 @@ async def _( return mans_dict: dict[tuple[int, str], Path] = {} for section in section_set: - mans_dict: dict[tuple[int, str], Path] = {**mans_dict, **search_man(section)} + mans_dict = {**mans_dict, **search_man(section)} mans_dict_2 = {key[1]: val for key, val in mans_dict.items()} mans_fp = mans_dict_2.get(doc.lower()) if mans_fp is None: @@ -95,8 +96,12 @@ async def _( return mans_msg = mans_fp.read_text('utf-8', 'replace') # await man.send(UniMessage().text(mans_msg)) - img = await MarkDownCore.render_markdown(mans_msg) - await man.send(UniMessage.image(raw=img)) + try: + img = await MarkDownCore.render_markdown(mans_msg) + await man.send(UniMessage.image(raw=img)) + except (playwright.async_api.Error, ConnectionError): + # 图片渲染出错,改成发纯文本 + await man.send(UniMessage.text(mans_msg)) help_deprecated = on_command('help', rule=nonebot.rule.to_me()) diff --git a/konabot/plugins/markdown/core.py b/konabot/plugins/markdown/core.py index b9d2202..2c97ce0 100644 --- a/konabot/plugins/markdown/core.py +++ b/konabot/plugins/markdown/core.py @@ -1,5 +1,4 @@ -from loguru import logger -from playwright.async_api import ConsoleMessage, Page +from playwright.async_api import Page from konabot.common.web_render import konaweb from konabot.common.web_render.core import WebRenderer @@ -12,7 +11,7 @@ class MarkDownCore: await page.locator('textarea[name=content]').fill(markdown_text) await page.locator('#button').click() - + # 等待 checkState 函数加载完成 await page.wait_for_function("typeof checkState === 'function'", timeout=1000) # 访问 checkState 函数,确保渲染完成 @@ -27,7 +26,7 @@ class MarkDownCore: ) return out - + @staticmethod async def render_latex(text: str, theme: str = "dark") -> bytes: params = { @@ -40,7 +39,7 @@ class MarkDownCore: await page.locator('textarea[name=content]').fill(f"$$ {text} $$") page.wait_for_selector('#button') await page.locator('#button').click() - + # 等待 checkState 函数加载完成 await page.wait_for_function("typeof checkState === 'function'", timeout=2000) # 访问 checkState 函数,确保渲染完成 @@ -54,4 +53,4 @@ class MarkDownCore: params=params ) - return out \ No newline at end of file + return out