From 0221772beaf95684f1bf52559bd52ba7daa1f82c Mon Sep 17 00:00:00 2001 From: fllesser Date: Thu, 19 Mar 2026 11:20:33 +0800 Subject: [PATCH 1/2] feat(renderer): improve error handling with fallback images for missing resources --- src/nonebot_plugin_parser/renders/common.py | 17 +++++++---------- src/nonebot_plugin_parser/renders/htmlrender.py | 6 +----- .../renders/resources/__init__.py | 5 +++++ 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/nonebot_plugin_parser/renders/common.py b/src/nonebot_plugin_parser/renders/common.py index 2f491662..b541e3c3 100644 --- a/src/nonebot_plugin_parser/renders/common.py +++ b/src/nonebot_plugin_parser/renders/common.py @@ -387,15 +387,12 @@ async def _load_cover(self) -> PILImage | None: if self.result.video is None: return None - cover_task = self.result.video.cover + cover_path = None + if cover_task := self.result.video.cover: + cover_path = await cover_task.safe_get() - if cover_task is None: - return None - - cover_path = await cover_task.safe_get() - - if cover_path is None or not cover_path.exists(): - return None + if cover_path is None: + return Image.open(resources.random_failed_pic()) with Image.open(cover_path) as img: if img.mode != "RGBA": @@ -473,7 +470,7 @@ async def _render_image_grid(self) -> None: for content in display_contents: path = await content.safe_get() if path is None or not path.exists(): - continue + path = resources.random_failed_pic() if img := self._load_grid_image(path, len(display_contents)): images.append(img) @@ -578,7 +575,7 @@ async def _render_img_in_graphics(self, image_content: ImageContent) -> None: """渲染图片""" path = await image_content.path_task.safe_get() if path is None or not path.exists(): - return + path = resources.random_failed_pic() with Image.open(path) as img: if img.width > self.content_width: diff --git a/src/nonebot_plugin_parser/renders/htmlrender.py b/src/nonebot_plugin_parser/renders/htmlrender.py index e4b08055..41d79be4 100644 --- a/src/nonebot_plugin_parser/renders/htmlrender.py +++ b/src/nonebot_plugin_parser/renders/htmlrender.py @@ -1,4 +1,3 @@ -import random from typing_extensions import override from nonebot import require @@ -23,9 +22,6 @@ async def render_image(self) -> bytes: font = pconfig.custom_font or resources.DEFAULT_FONT_PATH font = font.as_uri() if font.exists() else None - fallback_pics = list(resources.FAILED_PIC_DIR.glob("*.jpg")) - fallback_pic = random.choice(fallback_pics).as_uri() if fallback_pics else None - return await template_to_pic( template_path=str(self.templates_dir), template_name="card.html.jinja2", @@ -33,8 +29,8 @@ async def render_image(self) -> bytes: "logo": logo, "font": font, "result": self.result, - "fallback_pic": fallback_pic, "font_weight": pconfig.custom_font_weight, + "fallback_pic": resources.random_failed_pic().as_uri(), "play_button": resources.DEFAULT_VIDEO_BUTTON_PATH.as_uri(), "default_avatar": resources.DEFAULT_AVATAR_PATH.as_uri(), }, diff --git a/src/nonebot_plugin_parser/renders/resources/__init__.py b/src/nonebot_plugin_parser/renders/resources/__init__.py index 89024cd0..5a7090d6 100644 --- a/src/nonebot_plugin_parser/renders/resources/__init__.py +++ b/src/nonebot_plugin_parser/renders/resources/__init__.py @@ -1,3 +1,4 @@ +import random from pathlib import Path RESOURCES_DIR = Path(__file__).parent @@ -10,3 +11,7 @@ """默认视频播放按钮文件路径""" FAILED_PIC_DIR = RESOURCES_DIR / "failed_pic" """下载失败显示的图片文件路径""" + + +def random_failed_pic() -> Path: + return FAILED_PIC_DIR / f"{random.randint(1, 9)}.jpg" From a28747ec4da14cef675ff4dcd21221ad8e1cf97e Mon Sep 17 00:00:00 2001 From: fllesser Date: Thu, 19 Mar 2026 11:25:35 +0800 Subject: [PATCH 2/2] rename to fallback --- src/nonebot_plugin_parser/renders/common.py | 6 +++--- src/nonebot_plugin_parser/renders/htmlrender.py | 2 +- .../renders/resources/__init__.py | 6 +++--- .../resources/{failed_pic => fallback_pic}/1.jpg | Bin .../resources/{failed_pic => fallback_pic}/2.jpg | Bin .../resources/{failed_pic => fallback_pic}/3.jpg | Bin .../resources/{failed_pic => fallback_pic}/4.jpg | Bin .../resources/{failed_pic => fallback_pic}/5.jpg | Bin .../resources/{failed_pic => fallback_pic}/6.jpg | Bin .../resources/{failed_pic => fallback_pic}/7.jpg | Bin .../resources/{failed_pic => fallback_pic}/8.jpg | Bin .../resources/{failed_pic => fallback_pic}/9.jpg | Bin 12 files changed, 7 insertions(+), 7 deletions(-) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/1.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/2.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/3.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/4.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/5.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/6.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/7.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/8.jpg (100%) rename src/nonebot_plugin_parser/renders/resources/{failed_pic => fallback_pic}/9.jpg (100%) diff --git a/src/nonebot_plugin_parser/renders/common.py b/src/nonebot_plugin_parser/renders/common.py index b541e3c3..21843a8b 100644 --- a/src/nonebot_plugin_parser/renders/common.py +++ b/src/nonebot_plugin_parser/renders/common.py @@ -392,7 +392,7 @@ async def _load_cover(self) -> PILImage | None: cover_path = await cover_task.safe_get() if cover_path is None: - return Image.open(resources.random_failed_pic()) + return Image.open(resources.random_fallback_pic()) with Image.open(cover_path) as img: if img.mode != "RGBA": @@ -470,7 +470,7 @@ async def _render_image_grid(self) -> None: for content in display_contents: path = await content.safe_get() if path is None or not path.exists(): - path = resources.random_failed_pic() + path = resources.random_fallback_pic() if img := self._load_grid_image(path, len(display_contents)): images.append(img) @@ -575,7 +575,7 @@ async def _render_img_in_graphics(self, image_content: ImageContent) -> None: """渲染图片""" path = await image_content.path_task.safe_get() if path is None or not path.exists(): - path = resources.random_failed_pic() + path = resources.random_fallback_pic() with Image.open(path) as img: if img.width > self.content_width: diff --git a/src/nonebot_plugin_parser/renders/htmlrender.py b/src/nonebot_plugin_parser/renders/htmlrender.py index 41d79be4..0eb95e73 100644 --- a/src/nonebot_plugin_parser/renders/htmlrender.py +++ b/src/nonebot_plugin_parser/renders/htmlrender.py @@ -30,7 +30,7 @@ async def render_image(self) -> bytes: "font": font, "result": self.result, "font_weight": pconfig.custom_font_weight, - "fallback_pic": resources.random_failed_pic().as_uri(), + "fallback_pic": resources.random_fallback_pic().as_uri(), "play_button": resources.DEFAULT_VIDEO_BUTTON_PATH.as_uri(), "default_avatar": resources.DEFAULT_AVATAR_PATH.as_uri(), }, diff --git a/src/nonebot_plugin_parser/renders/resources/__init__.py b/src/nonebot_plugin_parser/renders/resources/__init__.py index 5a7090d6..da3e7bc9 100644 --- a/src/nonebot_plugin_parser/renders/resources/__init__.py +++ b/src/nonebot_plugin_parser/renders/resources/__init__.py @@ -9,9 +9,9 @@ """默认头像文件路径""" DEFAULT_VIDEO_BUTTON_PATH = RESOURCES_DIR / "play.png" """默认视频播放按钮文件路径""" -FAILED_PIC_DIR = RESOURCES_DIR / "failed_pic" +FALLBACK_PIC_DIR = RESOURCES_DIR / "fallback_pic" """下载失败显示的图片文件路径""" -def random_failed_pic() -> Path: - return FAILED_PIC_DIR / f"{random.randint(1, 9)}.jpg" +def random_fallback_pic() -> Path: + return FALLBACK_PIC_DIR / f"{random.randint(1, 9)}.jpg" diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/1.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/1.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/1.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/1.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/2.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/2.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/2.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/2.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/3.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/3.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/3.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/3.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/4.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/4.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/4.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/4.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/5.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/5.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/5.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/5.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/6.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/6.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/6.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/6.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/7.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/7.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/7.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/7.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/8.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/8.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/8.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/8.jpg diff --git a/src/nonebot_plugin_parser/renders/resources/failed_pic/9.jpg b/src/nonebot_plugin_parser/renders/resources/fallback_pic/9.jpg similarity index 100% rename from src/nonebot_plugin_parser/renders/resources/failed_pic/9.jpg rename to src/nonebot_plugin_parser/renders/resources/fallback_pic/9.jpg