mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-05-11 18:09:55 +08:00
- 添加图片生成相关配置和环境变量 - 新增图片上传服务和模型定义 - 扩展模型服务以支持图片生成模型 - 添加图片生成响应处理器 - 更新README文档以反映新功能 - 添加GitHub Actions发布工作流
164 lines
5.2 KiB
Python
164 lines
5.2 KiB
Python
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}")
|
|
|