mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-09-05 23:56:37 +08:00
feat: 添加图片生成功能及相关配置
- 添加图片生成相关配置和环境变量 - 新增图片上传服务和模型定义 - 扩展模型服务以支持图片生成模型 - 添加图片生成响应处理器 - 更新README文档以反映新功能 - 添加GitHub Actions发布工作流
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
import requests
|
||||
from app.schemas.image_models import ImageMetadata, ImageUploader, UploadResponse
|
||||
from enum import Enum
|
||||
from typing import Optional, Any
|
||||
|
||||
class UploadErrorType(Enum):
|
||||
"""上传错误类型枚举"""
|
||||
NETWORK_ERROR = "network_error" # 网络请求错误
|
||||
AUTH_ERROR = "auth_error" # 认证错误
|
||||
INVALID_FILE = "invalid_file" # 无效文件
|
||||
SERVER_ERROR = "server_error" # 服务器错误
|
||||
PARSE_ERROR = "parse_error" # 响应解析错误
|
||||
UNKNOWN = "unknown" # 未知错误
|
||||
|
||||
|
||||
class UploadError(Exception):
|
||||
"""图片上传错误异常类"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message: str,
|
||||
error_type: UploadErrorType = UploadErrorType.UNKNOWN,
|
||||
status_code: Optional[int] = None,
|
||||
details: Optional[dict] = None,
|
||||
original_error: Optional[Exception] = None
|
||||
):
|
||||
"""
|
||||
初始化上传错误异常
|
||||
|
||||
Args:
|
||||
message: 错误消息
|
||||
error_type: 错误类型
|
||||
status_code: HTTP状态码
|
||||
details: 详细错误信息
|
||||
original_error: 原始异常
|
||||
"""
|
||||
self.message = message
|
||||
self.error_type = error_type
|
||||
self.status_code = status_code
|
||||
self.details = details or {}
|
||||
self.original_error = original_error
|
||||
|
||||
# 构建完整错误信息
|
||||
full_message = f"[{error_type.value}] {message}"
|
||||
if status_code:
|
||||
full_message = f"{full_message} (Status: {status_code})"
|
||||
if details:
|
||||
full_message = f"{full_message} - Details: {details}"
|
||||
|
||||
super().__init__(full_message)
|
||||
|
||||
@classmethod
|
||||
def from_response(cls, response: Any, message: Optional[str] = None) -> "UploadError":
|
||||
"""
|
||||
从HTTP响应创建错误实例
|
||||
|
||||
Args:
|
||||
response: HTTP响应对象
|
||||
message: 自定义错误消息
|
||||
"""
|
||||
try:
|
||||
error_data = response.json()
|
||||
details = error_data.get("data", {})
|
||||
return cls(
|
||||
message=message or error_data.get("message", "Unknown error"),
|
||||
error_type=UploadErrorType.SERVER_ERROR,
|
||||
status_code=response.status_code,
|
||||
details=details
|
||||
)
|
||||
except Exception:
|
||||
return cls(
|
||||
message=message or "Failed to parse error response",
|
||||
error_type=UploadErrorType.PARSE_ERROR,
|
||||
status_code=response.status_code
|
||||
)
|
||||
|
||||
|
||||
class SmMsUploader(ImageUploader):
|
||||
API_URL = "https://sm.ms/api/v2/upload"
|
||||
|
||||
def __init__(self, api_key: str):
|
||||
self.api_key = api_key
|
||||
|
||||
def upload(self, file: bytes, filename: str) -> UploadResponse:
|
||||
try:
|
||||
# 准备请求头
|
||||
headers = {
|
||||
"Authorization": f"Basic {self.api_key}"
|
||||
}
|
||||
|
||||
# 准备文件数据
|
||||
files = {
|
||||
"smfile": (filename, file, "image/png")
|
||||
}
|
||||
|
||||
# 发送请求
|
||||
response = requests.post(
|
||||
self.API_URL,
|
||||
headers=headers,
|
||||
files=files
|
||||
)
|
||||
|
||||
# 检查响应状态
|
||||
response.raise_for_status()
|
||||
|
||||
# 解析响应
|
||||
result = response.json()
|
||||
|
||||
# 验证上传是否成功
|
||||
if not result.get("success"):
|
||||
raise UploadError(result.get("message", "Upload failed"))
|
||||
|
||||
# 转换为统一格式
|
||||
data = result["data"]
|
||||
image_metadata = ImageMetadata(
|
||||
width=data["width"],
|
||||
height=data["height"],
|
||||
filename=data["filename"],
|
||||
size=data["size"],
|
||||
url=data["url"],
|
||||
delete_url=data["delete"]
|
||||
)
|
||||
|
||||
return UploadResponse(
|
||||
success=True,
|
||||
code="success",
|
||||
message="Upload success",
|
||||
data=image_metadata
|
||||
)
|
||||
|
||||
except requests.RequestException as e:
|
||||
# 处理网络请求相关错误
|
||||
raise UploadError(f"Upload request failed: {str(e)}")
|
||||
except (KeyError, ValueError) as e:
|
||||
# 处理响应解析错误
|
||||
raise UploadError(f"Invalid response format: {str(e)}")
|
||||
except Exception as e:
|
||||
# 处理其他未预期的错误
|
||||
raise UploadError(f"Upload failed: {str(e)}")
|
||||
|
||||
|
||||
class QiniuUploader(ImageUploader):
|
||||
def __init__(self, access_key: str, secret_key: str):
|
||||
self.access_key = access_key
|
||||
self.secret_key = secret_key
|
||||
|
||||
def upload(self, file: bytes, filename: str) -> UploadResponse:
|
||||
# 实现七牛云的具体上传逻辑
|
||||
pass
|
||||
|
||||
|
||||
class ImageUploaderFactory:
|
||||
@staticmethod
|
||||
def create(provider: str, **credentials) -> ImageUploader:
|
||||
if provider == "smms":
|
||||
return SmMsUploader(credentials["api_key"])
|
||||
elif provider == "qiniu":
|
||||
return QiniuUploader(
|
||||
credentials["access_key"],
|
||||
credentials["secret_key"]
|
||||
)
|
||||
raise ValueError(f"Unknown provider: {provider}")
|
||||
|
||||
Reference in New Issue
Block a user