dify 支持图片http请求,方便随时追加API
This commit is contained in:
@@ -11,6 +11,7 @@ from plugin_common.message_plugin_interface import MessagePluginInterface
|
||||
from plugin_common.plugin_interface import PluginStatus
|
||||
from plugins.stats_collector.decorators import plugin_stats_decorator
|
||||
from robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
|
||||
from utils.media_downloader import MediaDownloader
|
||||
|
||||
|
||||
class DifyPlugin(MessagePluginInterface):
|
||||
@@ -152,7 +153,13 @@ class DifyPlugin(MessagePluginInterface):
|
||||
|
||||
# 发送回复
|
||||
if response:
|
||||
wcf.send_text(response, (roomid if roomid else sender), sender if roomid else "")
|
||||
# 判断是否为本地文件路径
|
||||
if os.path.isfile(response):
|
||||
# 如果是文件路径,使用发送文件方法
|
||||
wcf.send_file(response, (roomid if roomid else sender))
|
||||
else:
|
||||
# 如果是普通文本,使用发送文本方法
|
||||
wcf.send_text(response, (roomid if roomid else sender), sender if roomid else "")
|
||||
return True, "发送成功"
|
||||
else:
|
||||
wcf.send_text("❌未能获取到回复,请稍后再试", (roomid if roomid else sender), sender if roomid else "")
|
||||
@@ -256,10 +263,17 @@ class DifyPlugin(MessagePluginInterface):
|
||||
# 获取输出内容
|
||||
outputs = response_data.get("data", {}).get("outputs", {})
|
||||
if outputs:
|
||||
# 尝试从text字段获取回答
|
||||
if "text" in outputs and isinstance(outputs["text"], str):
|
||||
# 处理媒体类型返回
|
||||
if "result" in outputs and "type" in outputs:
|
||||
if outputs["type"] == "image":
|
||||
downloader = MediaDownloader()
|
||||
image_url = outputs["result"]
|
||||
image_path = downloader.download_media(image_url)
|
||||
answer = image_path
|
||||
# 处理文本类型返回
|
||||
elif "text" in outputs and isinstance(outputs["text"], str):
|
||||
answer = outputs["text"]
|
||||
# 如果没有text字段,尝试从其他字段获取
|
||||
# 兼容旧版处理逻辑
|
||||
else:
|
||||
for key, value in outputs.items():
|
||||
if isinstance(value, str) and value.strip():
|
||||
|
||||
149
utils/media_downloader.py
Normal file
149
utils/media_downloader.py
Normal file
@@ -0,0 +1,149 @@
|
||||
import os
|
||||
import requests
|
||||
import uuid
|
||||
from typing import Optional
|
||||
from urllib.parse import urlparse
|
||||
import logging
|
||||
import time
|
||||
|
||||
class MediaDownloader:
|
||||
"""媒体下载工具类,用于下载图片等媒体文件"""
|
||||
|
||||
def __init__(self, download_dir: str = None):
|
||||
"""
|
||||
初始化下载器
|
||||
|
||||
Args:
|
||||
download_dir: 下载目录,默认为项目下的 media_downloads 目录
|
||||
"""
|
||||
self.logger = logging.getLogger("MediaDownloader")
|
||||
self.download_dir = download_dir or os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||
"media_downloads"
|
||||
)
|
||||
os.makedirs(self.download_dir, exist_ok=True)
|
||||
self.logger.info(f"媒体下载目录: {self.download_dir}")
|
||||
|
||||
def download_media(self, url: str, file_type: str = None) -> Optional[str]:
|
||||
"""
|
||||
下载媒体文件
|
||||
|
||||
Args:
|
||||
url: 媒体文件URL
|
||||
file_type: 文件类型(如'jpg','png'等),如果不指定则从URL中推断
|
||||
|
||||
Returns:
|
||||
下载文件的本地绝对路径,如果下载失败则返回None
|
||||
"""
|
||||
try:
|
||||
# 从URL获取文件名和扩展名
|
||||
parsed_url = urlparse(url)
|
||||
filename = os.path.basename(parsed_url.path)
|
||||
|
||||
# 如果没有文件名或扩展名,则生成一个随机文件名
|
||||
if not filename or '.' not in filename:
|
||||
ext = file_type if file_type else self._guess_file_type(url)
|
||||
filename = f"{uuid.uuid4().hex}.{ext}" if ext else f"{uuid.uuid4().hex}"
|
||||
|
||||
local_path = os.path.join(self.download_dir, filename)
|
||||
|
||||
self.logger.info(f"开始下载媒体文件: {url} -> {local_path}")
|
||||
|
||||
# 下载文件
|
||||
response = requests.get(url, stream=True, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
with open(local_path, 'wb') as f:
|
||||
for chunk in response.iter_content(chunk_size=8192):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
|
||||
self.logger.info(f"媒体文件下载成功: {local_path}")
|
||||
|
||||
# 下载成功后清理旧文件
|
||||
self.clear_downloads()
|
||||
|
||||
return os.path.abspath(local_path)
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"下载媒体文件失败: {url}, 错误: {str(e)}")
|
||||
return None
|
||||
|
||||
def _guess_file_type(self, url: str) -> Optional[str]:
|
||||
"""
|
||||
从URL推断文件类型
|
||||
|
||||
Args:
|
||||
url: 媒体文件URL
|
||||
|
||||
Returns:
|
||||
文件扩展名(不含点),如果无法推断则返回None
|
||||
"""
|
||||
try:
|
||||
parsed_url = urlparse(url)
|
||||
path = parsed_url.path.lower()
|
||||
|
||||
if path.endswith('.jpg') or path.endswith('.jpeg'):
|
||||
return 'jpg'
|
||||
elif path.endswith('.png'):
|
||||
return 'png'
|
||||
elif path.endswith('.gif'):
|
||||
return 'gif'
|
||||
elif path.endswith('.mp4'):
|
||||
return 'mp4'
|
||||
elif path.endswith('.mp3'):
|
||||
return 'mp3'
|
||||
elif path.endswith('.pdf'):
|
||||
return 'pdf'
|
||||
else:
|
||||
# 检查Content-Type
|
||||
response = requests.head(url, timeout=5)
|
||||
content_type = response.headers.get('Content-Type', '')
|
||||
|
||||
if 'image/jpeg' in content_type:
|
||||
return 'jpg'
|
||||
elif 'image/png' in content_type:
|
||||
return 'png'
|
||||
elif 'image/gif' in content_type:
|
||||
return 'gif'
|
||||
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
def clear_downloads(self, max_age_days: int = 3) -> None:
|
||||
"""
|
||||
清理超过指定天数的下载文件
|
||||
|
||||
Args:
|
||||
max_age_days: 最大保留天数,默认为3天
|
||||
"""
|
||||
try:
|
||||
current_time = time.time()
|
||||
max_age_seconds = max_age_days * 24 * 60 * 60
|
||||
cleared_count = 0
|
||||
|
||||
# 遍历下载目录中的所有文件
|
||||
for filename in os.listdir(self.download_dir):
|
||||
file_path = os.path.join(self.download_dir, filename)
|
||||
|
||||
# 检查是否为文件
|
||||
if os.path.isfile(file_path):
|
||||
# 获取文件最后修改时间
|
||||
file_mtime = os.path.getmtime(file_path)
|
||||
file_age = current_time - file_mtime
|
||||
|
||||
# 如果文件超过最大保留时间,则删除
|
||||
if file_age > max_age_seconds:
|
||||
try:
|
||||
os.remove(file_path)
|
||||
cleared_count += 1
|
||||
self.logger.debug(f"已删除过期文件: {file_path}")
|
||||
except Exception as e:
|
||||
self.logger.error(f"删除文件失败 {file_path}: {str(e)}")
|
||||
|
||||
if cleared_count > 0:
|
||||
self.logger.info(f"清理完成,共删除 {cleared_count} 个过期文件")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"清理下载文件时出错: {str(e)}")
|
||||
Reference in New Issue
Block a user