diff --git a/plugins/message_summary/main.py b/plugins/message_summary/main.py index 04e65fa..831b9b0 100644 --- a/plugins/message_summary/main.py +++ b/plugins/message_summary/main.py @@ -1,3 +1,4 @@ +import asyncio import json import re import threading @@ -115,12 +116,8 @@ class MessageSummaryPlugin(MessagePluginInterface): await self.bot.send_text_message(group_id, "⏳群消息总结中… 😊") # 创建线程异步处理总结生成和发送 - summary_thread = threading.Thread( - target=self._async_generate_and_send_summary, - args=(chat_content, group_name, group_id, message) - ) - summary_thread.daemon = True # 设置为守护线程,主程序退出时线程也会退出 - summary_thread.start() + self._run_async_in_thread(self._async_generate_and_send_summary, chat_content, group_name, group_id, + message) return True, "异步总结已启动" @@ -128,12 +125,21 @@ class MessageSummaryPlugin(MessagePluginInterface): self.LOG.error(f"处理消息总结命令失败: {e}") return False, None + def _run_async_in_thread(self, coro, *args, **kwargs): + def runner(): + asyncio.run(coro(*args, **kwargs)) + + t = threading.Thread(target=runner) + t.daemon = True + t.start() + return t + async def _async_generate_and_send_summary(self, chat_content: str, group_name: str, group_id: str, - message: Dict[str, Any]): + message: Dict[str, Any]): """异步生成并发送总结""" try: # 生成总结 - summary, image_path = self._generate_summary(chat_content, group_name) + summary, image_path = await self._generate_summary(chat_content, group_name) if image_path: await self.bot.send_image_message(group_id, Path(image_path)) @@ -155,7 +161,7 @@ class MessageSummaryPlugin(MessagePluginInterface): sanitized_name = "群聊" return sanitized_name - def _generate_summary(self, chat_content: str, group_name: str) -> Tuple[str, Optional[str]]: + async def _generate_summary(self, chat_content: str, group_name: str) -> Tuple[str, Optional[str]]: """生成总结""" # Dify API配置 content_compress = chat_content @@ -210,7 +216,7 @@ class MessageSummaryPlugin(MessagePluginInterface): tokens_info = f"\n\n【tokens】输入: {prompt_tokens} 生成: {completion_tokens} 总: {total_tokens}" answer += tokens_info try: - spath = convert_md_str_to_image(answer, "output.png") + spath = await convert_md_str_to_image(answer, "output.png") except Exception as e: self.LOG.error(f"生成image失败:{e}") # 返回文本内容和图片路径 diff --git a/utils/markdown_to_image.py b/utils/markdown_to_image.py index 0008539..b8284ef 100644 --- a/utils/markdown_to_image.py +++ b/utils/markdown_to_image.py @@ -1,6 +1,7 @@ import markdown -from playwright.sync_api import sync_playwright +from playwright.async_api import async_playwright import os +import asyncio # 将 Markdown 字符串转换为 HTML @@ -154,73 +155,45 @@ def md_str_to_html(md_content, output_html): f.write('') -# 使用 Playwright 将 HTML 渲染并截图 -def html_to_image(html_file, output_image): +# 使用 Playwright 将 HTML 渲染并截图(异步版) +async def html_to_image(html_file, output_image): """ - 使用 Playwright 加载 HTML 文件并截图。 - - :param html_file: 输入的 HTML 文件路径 - :param output_image: 输出的图片文件路径 + 使用 Playwright 加载 HTML 文件并截图(异步)。 """ - with sync_playwright() as p: - # 定义可能的Chrome浏览器路径列表 + async with async_playwright() as p: possible_chrome_paths = [ r"C:\Users\Liu_WIN10\AppData\Local\Google\Chrome\Application\chrome.exe", r"C:\Users\Liu-OPEN\AppData\Local\Google\Chrome\Application\chrome.exe", r"C:\Program Files\Google\Chrome\Application\chrome.exe", r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" ] - - # 查找可用的浏览器路径 browser_path = None for path in possible_chrome_paths: if os.path.exists(path): browser_path = path print(f"找到浏览器路径: {browser_path}") break - - # 如果没有找到可用的路径,则使用默认启动方式 if browser_path: - browser = p.chromium.launch(executable_path=browser_path) - + browser = await p.chromium.launch(executable_path=browser_path) else: print("未找到指定的Chrome浏览器路径,使用默认浏览器") - browser = p.chromium.launch() - page = browser.new_page() - - # 加载本地的 HTML 文件 - page.goto(f'file://{os.path.abspath(html_file)}') - - # 设置 viewport(调整为更合适的宽度) - page.set_viewport_size({"width": 750, "height": 800}) - - # 等待内容完全渲染 - page.wait_for_timeout(500) - - # 截图 - page.screenshot(path=output_image, full_page=True) - - browser.close() + browser = await p.chromium.launch() + page = await browser.new_page() + await page.goto(f'file://{os.path.abspath(html_file)}') + await page.set_viewport_size({"width": 750, "height": 800}) + await page.wait_for_timeout(500) + await page.screenshot(path=output_image, full_page=True) + await browser.close() -# 主函数:从字符串转换 Markdown 到图片 -def convert_md_str_to_image(md_content, output_image): +# 主函数:从字符串转换 Markdown 到图片(异步版) +async def convert_md_str_to_image(md_content, output_image): """ - 将 Markdown 字符串转换为图片。 - - :param md_content: 输入的 Markdown 字符串 - :param output_image: 输出的图片文件路径 + 将 Markdown 字符串转换为图片(异步)。 """ - # 中间生成的 HTML 文件 temp_html = 'temp_output.html' - - # 第一步:将 Markdown 字符串转换为 HTML md_str_to_html(md_content, temp_html) - - # 第二步:将 HTML 渲染为图片 - html_to_image(temp_html, output_image) - - # 可选:删除临时的 HTML 文件 + await html_to_image(temp_html, output_image) os.remove(temp_html) print(f"图片已生成:{output_image}") return os.path.abspath(output_image) @@ -276,5 +249,5 @@ if __name__ == "__main__": ✨ *本总结由 AI 自动生成,快来看看你今天是不是最靓的崽!🔥* """ - spath = convert_md_str_to_image(md_content, "output.png") + spath = asyncio.run(convert_md_str_to_image(md_content, "output.png")) print(spath) \ No newline at end of file