diff --git a/src/plugins/nonebot_hk_reporter/utils.py b/src/plugins/nonebot_hk_reporter/utils.py index 6da7785..56db32a 100644 --- a/src/plugins/nonebot_hk_reporter/utils.py +++ b/src/plugins/nonebot_hk_reporter/utils.py @@ -2,11 +2,14 @@ import asyncio from html import escape import os from tempfile import NamedTemporaryFile +from time import asctime from typing import Awaitable, Callable, Optional from pyppeteer import launch +from pyppeteer.browser import Browser from pyppeteer.chromium_downloader import check_chromium, download_chromium from pyppeteer.page import Page +from nonebot.log import logger from .plugin_config import plugin_config @@ -28,31 +31,56 @@ class Render(metaclass=Singleton): def __init__(self): self.lock = asyncio.Lock() + self.browser: Browser + self.interval_log = '' async def render(self, url: str, viewport: Optional[dict] = None, target: Optional[str] = None, + operation: Optional[Callable[[Page], Awaitable[None]]] = None) -> Optional[str]: + retry_times = 0 + while retry_times < 3: + try: + return await asyncio.wait_for(self.do_render(url, viewport, target, operation), 10) + except asyncio.TimeoutError: + retry_times += 1 + logger.warning("render error {}\n".format(retry_times) + self.interval_log) + self.interval_log = '' + if self.browser: + await self.browser.close() + + def _inter_log(self, message: str) -> None: + # self.interval_log += asctime() + '' + message + '\n' + logger.debug(message) + + async def do_render(self, url: str, viewport: Optional[dict] = None, target: Optional[str] = None, operation: Optional[Callable[[Page], Awaitable[None]]] = None) -> str: async with self.lock: if plugin_config.hk_reporter_use_local: - browser = await launch(executablePath='/usr/bin/chromium', args=['--no-sandbox']) + self.browser = await launch(executablePath='/usr/bin/chromium', args=['--no-sandbox']) else: - browser = await launch(args=['--no-sandbox']) - page = await browser.newPage() + self.browser = await launch(args=['--no-sandbox']) + self._inter_log('open browser') + page = await self.browser.newPage() if operation: await operation(page) else: await page.goto(url) + self._inter_log('open page') if viewport: await page.setViewport(viewport) + logger._inter_log('set viewport') if target: target_ele = await page.querySelector(target) data = await target_ele.screenshot(type='jpeg', encoding='base64') else: data = await page.screenshot(type='jpeg', encoding='base64') + self._inter_log('screenshot') await page.close() - await browser.close() + self._inter_log('close page') + await self.browser.close() + self._inter_log('close browser') return str(data) - async def text_to_pic(self, text: str) -> str: + async def text_to_pic(self, text: str) -> Optional[str]: lines = text.split('\n') parsed_lines = list(map(lambda x: '
{}
'.format(escape(x)), lines)) html_text = '