66Documentation: https://github.com/botuniverse/onebot-11
77"""
88
9+ import base64
910import json
1011import logging
12+ import os
1113from typing import TYPE_CHECKING
1214
1315from module .models .bangumi import Notification
@@ -78,6 +80,53 @@ async def _post_json(self, url: str, data: dict) -> object:
7880 logger .warning (f"[OneBot] Request failed: { e } " )
7981 return None
8082
83+ def _get_image_file (self , poster_path : str ) -> str | None :
84+ """Convert poster_path to a OneBot-compatible image file reference.
85+
86+ Handles three cases:
87+ 1. Remote URL (contains ://) - use as-is
88+ 2. Local file path - read and convert to base64
89+ 3. Invalid/missing - return None
90+
91+ Args:
92+ poster_path: The poster path or URL from the database.
93+
94+ Returns:
95+ A OneBot-compatible file string (URL or base64), or None.
96+ """
97+ if not poster_path or poster_path in ("" , "https://mikanani.me" ):
98+ return None
99+
100+ # If it's a remote URL, use it directly
101+ if "://" in poster_path :
102+ return poster_path
103+
104+ # Otherwise, try to read it as a local file
105+ # The path is relative to the data directory (e.g. "posters/xxx.jpg")
106+ local_path = os .path .join ("data" , poster_path .lstrip ("/" ))
107+ if os .path .exists (local_path ):
108+ try :
109+ with open (local_path , "rb" ) as f :
110+ img_data = f .read ()
111+ img_b64 = base64 .b64encode (img_data ).decode ("ascii" )
112+ # Determine MIME type from extension
113+ ext = os .path .splitext (local_path )[1 ].lower ()
114+ mime_map = {
115+ ".jpg" : "image/jpeg" ,
116+ ".jpeg" : "image/jpeg" ,
117+ ".png" : "image/png" ,
118+ ".gif" : "image/gif" ,
119+ ".webp" : "image/webp" ,
120+ }
121+ mime = mime_map .get (ext , "image/jpeg" )
122+ return f"base64://{ img_b64 } "
123+ except Exception as e :
124+ logger .warning (f"[OneBot] Failed to read local image { local_path } : { e } " )
125+ return None
126+ else :
127+ logger .warning (f"[OneBot] Local image not found: { local_path } " )
128+ return None
129+
81130 def _build_payload (
82131 self , text : str , poster_path : str = None
83132 ) -> str | list :
@@ -89,14 +138,15 @@ def _build_payload(
89138
90139 Args:
91140 text: The text message content.
92- poster_path: Optional URL to a poster image.
141+ poster_path: Optional URL or local path to a poster image.
93142
94143 Returns:
95144 A string (plain text) or list (message segments).
96145 """
97- if poster_path and poster_path not in ("" , "https://mikanani.me" ):
146+ image_file = self ._get_image_file (poster_path ) if poster_path else None
147+ if image_file :
98148 return [
99- {"type" : "image" , "data" : {"file" : poster_path }},
149+ {"type" : "image" , "data" : {"file" : image_file }},
100150 {"type" : "text" , "data" : {"text" : text }},
101151 ]
102152 return text
0 commit comments