番号插件新增封面全图模糊,发送前自动遮罩处理
变更项: 1. 在 fanhao_search 插件中新增全图高斯模糊处理函数,发送封面前统一执行。 2. 增加 cover_blur_enable 与 cover_blur_radius 配置项,支持开关和模糊强度调节。 3. 封面处理失败时回退原图并记录日志,保证主流程可用。 4. 初始化日志补充模糊配置参数,便于排查线上行为。
This commit is contained in:
@@ -20,9 +20,14 @@ http_proxy = ""
|
|||||||
allow_download_link = true
|
allow_download_link = true
|
||||||
|
|
||||||
# 是否发送封面预览图(默认关闭)
|
# 是否发送封面预览图(默认关闭)
|
||||||
allow_preview_cover = false
|
allow_preview_cover = true
|
||||||
|
|
||||||
# 当开启磁力时,是否优先返回“带字幕”磁力
|
# 当开启磁力时,是否优先返回“带字幕”磁力
|
||||||
prefer_subtitle_magnet = true
|
prefer_subtitle_magnet = true
|
||||||
|
|
||||||
|
# 封面图是否开启全图模糊(建议开启)
|
||||||
|
cover_blur_enable = true
|
||||||
|
|
||||||
|
# 全图模糊强度(高斯半径,数值越大越模糊)
|
||||||
|
cover_blur_radius = 18
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
import re
|
import re
|
||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
|
import io
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
from PIL import Image, ImageFilter
|
||||||
|
|
||||||
from base.plugin_common.message_plugin_interface import MessagePluginInterface
|
from base.plugin_common.message_plugin_interface import MessagePluginInterface
|
||||||
from base.plugin_common.plugin_interface import PluginStatus
|
from base.plugin_common.plugin_interface import PluginStatus
|
||||||
@@ -73,6 +75,9 @@ class FanhaoSearchPlugin(MessagePluginInterface):
|
|||||||
self.allow_download_link = False
|
self.allow_download_link = False
|
||||||
self.allow_preview_cover = False
|
self.allow_preview_cover = False
|
||||||
self.prefer_subtitle_magnet = True
|
self.prefer_subtitle_magnet = True
|
||||||
|
# 封面图降敏配置:默认开启全图模糊,降低群内图片内容风险。
|
||||||
|
self.cover_blur_enable = True
|
||||||
|
self.cover_blur_radius = 18
|
||||||
|
|
||||||
def initialize(self, context: Dict[str, Any]) -> bool:
|
def initialize(self, context: Dict[str, Any]) -> bool:
|
||||||
"""初始化插件配置。"""
|
"""初始化插件配置。"""
|
||||||
@@ -90,11 +95,14 @@ class FanhaoSearchPlugin(MessagePluginInterface):
|
|||||||
self.allow_download_link = bool(cfg.get("allow_download_link", False))
|
self.allow_download_link = bool(cfg.get("allow_download_link", False))
|
||||||
self.allow_preview_cover = bool(cfg.get("allow_preview_cover", False))
|
self.allow_preview_cover = bool(cfg.get("allow_preview_cover", False))
|
||||||
self.prefer_subtitle_magnet = bool(cfg.get("prefer_subtitle_magnet", True))
|
self.prefer_subtitle_magnet = bool(cfg.get("prefer_subtitle_magnet", True))
|
||||||
|
self.cover_blur_enable = bool(cfg.get("cover_blur_enable", True))
|
||||||
|
self.cover_blur_radius = max(1, int(cfg.get("cover_blur_radius", 18) or 18))
|
||||||
|
|
||||||
self.LOG.info(
|
self.LOG.info(
|
||||||
f"[{self.name}] 初始化完成: enable={self.enable}, commands={self._commands}, "
|
f"[{self.name}] 初始化完成: enable={self.enable}, commands={self._commands}, "
|
||||||
f"base_url={self.javbus_base_url}, allow_download_link={self.allow_download_link}, "
|
f"base_url={self.javbus_base_url}, allow_download_link={self.allow_download_link}, "
|
||||||
f"allow_preview_cover={self.allow_preview_cover}, timeout={self.request_timeout_seconds}s"
|
f"allow_preview_cover={self.allow_preview_cover}, cover_blur_enable={self.cover_blur_enable}, "
|
||||||
|
f"cover_blur_radius={self.cover_blur_radius}, timeout={self.request_timeout_seconds}s"
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -176,6 +184,32 @@ class FanhaoSearchPlugin(MessagePluginInterface):
|
|||||||
raise RuntimeError(f"图片下载失败 status={resp.status}, url={url}")
|
raise RuntimeError(f"图片下载失败 status={resp.status}, url={url}")
|
||||||
return await resp.read()
|
return await resp.read()
|
||||||
|
|
||||||
|
def _apply_full_blur_to_image_bytes(self, image_bytes: bytes) -> bytes:
|
||||||
|
"""对图片执行全图高斯模糊。
|
||||||
|
|
||||||
|
设计说明:
|
||||||
|
1. 这里使用 Pillow 的 GaussianBlur 对整图处理,不做局部区域判断;
|
||||||
|
2. 输出统一转为 JPEG,避免源图格式差异导致发送失败;
|
||||||
|
3. 若处理异常则回退原图,保证主流程可用性。
|
||||||
|
"""
|
||||||
|
if not image_bytes:
|
||||||
|
return image_bytes
|
||||||
|
if not self.cover_blur_enable:
|
||||||
|
return image_bytes
|
||||||
|
try:
|
||||||
|
with Image.open(io.BytesIO(image_bytes)) as image:
|
||||||
|
# 转为 RGB 统一颜色空间,避免 RGBA 保存 JPEG 报错。
|
||||||
|
if image.mode in ("RGBA", "P"):
|
||||||
|
image = image.convert("RGB")
|
||||||
|
# 全图高斯模糊,半径可在配置中调整。
|
||||||
|
blurred = image.filter(ImageFilter.GaussianBlur(radius=float(self.cover_blur_radius)))
|
||||||
|
output = io.BytesIO()
|
||||||
|
blurred.save(output, format="JPEG", quality=88)
|
||||||
|
return output.getvalue()
|
||||||
|
except Exception as e:
|
||||||
|
self.LOG.warning(f"[{self.name}] 封面全图模糊失败,回退原图: error={e}")
|
||||||
|
return image_bytes
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _extract_plain_value_from_info_p(info_p) -> str:
|
def _extract_plain_value_from_info_p(info_p) -> str:
|
||||||
"""从详情页 <p> 节点中提取纯文本值。
|
"""从详情页 <p> 节点中提取纯文本值。
|
||||||
@@ -462,6 +496,8 @@ class FanhaoSearchPlugin(MessagePluginInterface):
|
|||||||
if cover_url:
|
if cover_url:
|
||||||
try:
|
try:
|
||||||
cover_bytes = await self._http_get_bytes(cover_url, referer=detail_url)
|
cover_bytes = await self._http_get_bytes(cover_url, referer=detail_url)
|
||||||
|
# 发送前执行全图模糊,避免直接发送原始封面。
|
||||||
|
cover_bytes = self._apply_full_blur_to_image_bytes(cover_bytes)
|
||||||
await bot.send_image_message(target, cover_bytes)
|
await bot.send_image_message(target, cover_bytes)
|
||||||
except Exception as cover_error:
|
except Exception as cover_error:
|
||||||
self.LOG.warning(f"[{self.name}] 封面发送失败: code={normalized_code}, error={cover_error}")
|
self.LOG.warning(f"[{self.name}] 封面发送失败: code={normalized_code}, error={cover_error}")
|
||||||
@@ -475,4 +511,3 @@ class FanhaoSearchPlugin(MessagePluginInterface):
|
|||||||
def get_plugin():
|
def get_plugin():
|
||||||
"""返回插件实例。"""
|
"""返回插件实例。"""
|
||||||
return FanhaoSearchPlugin()
|
return FanhaoSearchPlugin()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user