mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-07-03 22:04:18 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89f2825ac7 |
@@ -14,6 +14,8 @@ CREATE_IMAGE_MODEL=imagen-3.0-generate-002
|
||||
UPLOAD_PROVIDER=smms
|
||||
SMMS_SECRET_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
PICGO_API_KEY=xxxx
|
||||
CLOUDFLARE_IMGBED_URL=https://xxxxxxx.pages.dev/upload
|
||||
CLOUDFLARE_IMGBED_AUTH_CODE=xxxxxxxxx
|
||||
##########################################################################
|
||||
#########################stream_optimizer 相关配置########################
|
||||
STREAM_MIN_DELAY=0.016
|
||||
|
||||
27
README.md
27
README.md
@@ -74,8 +74,11 @@
|
||||
CREATE_IMAGE_MODEL="imagen-3.0-generate-002" # 图片生成模型,默认使用imagen-3.0
|
||||
|
||||
# 图片上传配置
|
||||
UPLOAD_PROVIDER="smms" # 图片上传提供商,目前支持smms
|
||||
UPLOAD_PROVIDER="smms" # 图片上传提供商,目前支持smms、picgo、cloudflare_imgbed
|
||||
SMMS_SECRET_TOKEN="your-smms-token" # SM.MS图床的API Token
|
||||
PICGO_API_KEY="your-picogo-apikey" # PicoGo图床的API Key 可在 `https://www.picgo.net/settings/api` 获取
|
||||
CLOUDFLARE_IMGBED_URL="https://xxxxxxx.pages.dev/upload" # CloudFlare 图床上传地址,可自行搭建:`https://github.com/MarSeventh/CloudFlare-ImgBed`
|
||||
CLOUDFLARE_IMGBED_AUTH_CODE="your-cloudflare-imgber-auth-code" # CloudFlare图床的鉴权key,可在项目后台设置,若无鉴权则可直接置空。
|
||||
|
||||
# stream_optimizer 相关配置
|
||||
STREAM_MIN_DELAY=0.016
|
||||
@@ -138,10 +141,26 @@
|
||||
|
||||
- `UPLOAD_PROVIDER`: 图片上传服务提供商
|
||||
- 默认值: `smms`
|
||||
- 说明: 目前支持 SM.MS 图床
|
||||
- 可选值: `smms`, `picgo`, `cloudflare_imgbed`
|
||||
- 说明: 用于选择图片上传的服务提供商。目前支持 SM.MS 图床, PicGo 图床, 以及 Cloudflare ImgBed。
|
||||
|
||||
- `SMMS_SECRET_TOKEN`: SM.MS API Token
|
||||
- 用途: 用于图片上传到 SM.MS 图床
|
||||
- 获取方式: 需要在 SM.MS 官网注册并获取
|
||||
- 用途: 用于图片上传到 SM.MS 图床的身份验证。
|
||||
- 获取方式: 需要在 [SM.MS 官网](https://sm.ms/) 注册并获取。
|
||||
|
||||
- `PICGO_API_KEY`: PicGo API Key
|
||||
- 用途: 用于图片上传到 PicGo 图床的身份验证。
|
||||
- 获取方式: 可在 [PicGo 官网](https://www.picgo.net/settings/api) 的设置页面 API 选项中获取。
|
||||
|
||||
- `CLOUDFLARE_IMGBED_URL`: Cloudflare ImgBed 上传地址
|
||||
- 用途: 指定 Cloudflare ImgBed 图床的上传 API 地址。
|
||||
- 获取方式: 如果您自行搭建了 Cloudflare ImgBed 服务,请填写您的服务部署地址。参考 [Cloudflare-ImgBed 项目](https://github.com/MarSeventh/CloudFlare-ImgBed) 自行搭建。
|
||||
- 注意: URL 必须以 `https://` 开头,并指向 `/upload` 路径 ,例如 `https://cloudflare-imgbed-7b0.pages.dev/upload`。
|
||||
|
||||
- `CLOUDFLARE_IMGBED_AUTH_CODE`: Cloudflare ImgBed 鉴权 Key
|
||||
- 用途: 用于 Cloudflare ImgBed 图床的身份验证。
|
||||
- 说明: 如果您的 Cloudflare ImgBed 服务启用了鉴权,请填写鉴权 Key。若未启用鉴权,则留空即可。
|
||||
- 获取方式: 在 Cloudflare ImgBed 项目的后台设置中获取,或在搭建时自行设置。
|
||||
|
||||
#### 流式输出优化配置
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ class Settings(BaseSettings):
|
||||
UPLOAD_PROVIDER: str = "smms"
|
||||
SMMS_SECRET_TOKEN: str = ""
|
||||
PICGO_API_KEY: str = ""
|
||||
CLOUDFLARE_IMGBED_URL: str = ""
|
||||
CLOUDFLARE_IMGBED_AUTH_CODE: str = ""
|
||||
TEST_MODEL: str = "gemini-1.5-flash"
|
||||
|
||||
# 流式输出优化器配置
|
||||
|
||||
@@ -258,6 +258,119 @@ class PicGoUploader(ImageUploader):
|
||||
original_error=e
|
||||
)
|
||||
|
||||
|
||||
class CloudFlareImgBedUploader(ImageUploader):
|
||||
"""CloudFlare图床上传器"""
|
||||
|
||||
def __init__(self, auth_code: str, api_url: str):
|
||||
"""
|
||||
初始化CloudFlare图床上传器
|
||||
|
||||
Args:
|
||||
auth_code: 认证码
|
||||
api_url: 上传API地址
|
||||
"""
|
||||
self.auth_code = auth_code
|
||||
self.api_url = api_url
|
||||
|
||||
def upload(self, file: bytes, filename: str) -> UploadResponse:
|
||||
"""
|
||||
上传图片到CloudFlare图床
|
||||
|
||||
Args:
|
||||
file: 图片文件二进制数据
|
||||
filename: 文件名
|
||||
|
||||
Returns:
|
||||
UploadResponse: 上传响应对象
|
||||
|
||||
Raises:
|
||||
UploadError: 上传失败时抛出异常
|
||||
"""
|
||||
try:
|
||||
# 准备请求URL(添加认证码参数,如果存在)
|
||||
if self.auth_code:
|
||||
request_url = f"{self.api_url}?authCode={self.auth_code}"
|
||||
else:
|
||||
request_url = self.api_url
|
||||
|
||||
# 准备文件数据
|
||||
files = {
|
||||
"file": (filename, file)
|
||||
}
|
||||
|
||||
# 发送请求
|
||||
response = requests.post(
|
||||
request_url,
|
||||
files=files
|
||||
)
|
||||
|
||||
# 检查响应状态
|
||||
response.raise_for_status()
|
||||
|
||||
# 解析响应
|
||||
result = response.json()
|
||||
|
||||
# 验证响应格式
|
||||
if not result or not isinstance(result, list) or len(result) == 0:
|
||||
raise UploadError(
|
||||
message="Invalid response format",
|
||||
error_type=UploadErrorType.PARSE_ERROR
|
||||
)
|
||||
|
||||
# 获取文件URL
|
||||
file_path = result[0].get("src")
|
||||
if not file_path:
|
||||
raise UploadError(
|
||||
message="Missing file URL in response",
|
||||
error_type=UploadErrorType.PARSE_ERROR
|
||||
)
|
||||
|
||||
# 构建完整URL(如果返回的是相对路径)
|
||||
base_url = self.api_url.split("/upload")[0]
|
||||
full_url = file_path if file_path.startswith(("http://", "https://")) else f"{base_url}{file_path}"
|
||||
|
||||
# 构建图片元数据(注意:CloudFlare-ImgBed不返回所有元数据,所以部分字段为默认值)
|
||||
image_metadata = ImageMetadata(
|
||||
width=0, # CloudFlare-ImgBed不返回宽度
|
||||
height=0, # CloudFlare-ImgBed不返回高度
|
||||
filename=filename,
|
||||
size=0, # CloudFlare-ImgBed不返回大小
|
||||
url=full_url,
|
||||
delete_url=None # CloudFlare-ImgBed不返回删除URL
|
||||
)
|
||||
|
||||
return UploadResponse(
|
||||
success=True,
|
||||
code="success",
|
||||
message="Upload success",
|
||||
data=image_metadata
|
||||
)
|
||||
|
||||
except requests.RequestException as e:
|
||||
# 处理网络请求相关错误
|
||||
raise UploadError(
|
||||
message=f"Upload request failed: {str(e)}",
|
||||
error_type=UploadErrorType.NETWORK_ERROR,
|
||||
original_error=e
|
||||
)
|
||||
except (KeyError, ValueError, TypeError, IndexError) as e:
|
||||
# 处理响应解析错误
|
||||
raise UploadError(
|
||||
message=f"Invalid response format: {str(e)}",
|
||||
error_type=UploadErrorType.PARSE_ERROR,
|
||||
original_error=e
|
||||
)
|
||||
except UploadError:
|
||||
# 重新抛出已经是 UploadError 类型的异常
|
||||
raise
|
||||
except Exception as e:
|
||||
# 处理其他未预期的错误
|
||||
raise UploadError(
|
||||
message=f"Upload failed: {str(e)}",
|
||||
error_type=UploadErrorType.UNKNOWN,
|
||||
original_error=e
|
||||
)
|
||||
|
||||
class ImageUploaderFactory:
|
||||
@staticmethod
|
||||
@@ -272,4 +385,9 @@ class ImageUploaderFactory:
|
||||
elif provider == "picgo":
|
||||
api_url = credentials.get("api_url", "https://www.picgo.net/api/1/upload")
|
||||
return PicGoUploader(credentials["api_key"], api_url)
|
||||
elif provider == "cloudflare_imgbed":
|
||||
return CloudFlareImgBedUploader(
|
||||
credentials["auth_code"],
|
||||
credentials["base_url"]
|
||||
)
|
||||
raise ValueError(f"Unknown provider: {provider}")
|
||||
|
||||
@@ -200,6 +200,8 @@ def _extract_image_data(part: dict) -> str:
|
||||
image_uploader = ImageUploaderFactory.create(provider=settings.UPLOAD_PROVIDER,api_key=settings.SMMS_SECRET_TOKEN)
|
||||
elif settings.UPLOAD_PROVIDER == "picgo":
|
||||
image_uploader = ImageUploaderFactory.create(provider=settings.UPLOAD_PROVIDER,api_key=settings.PICGO_API_KEY)
|
||||
elif settings.UPLOAD_PROVIDER == "cloudflare_imgbed":
|
||||
image_uploader = ImageUploaderFactory.create(provider=settings.UPLOAD_PROVIDER,base_url=settings.CLOUDFLARE_IMGBED_URL,auth_code=settings.CLOUDFLARE_IMGBED_AUTH_CODE)
|
||||
current_date = time.strftime("%Y/%m/%d")
|
||||
filename = f"{current_date}/{uuid.uuid4().hex[:8]}.png"
|
||||
base64_data = part["inlineData"]["data"]
|
||||
|
||||
@@ -96,11 +96,6 @@ class ImageCreateService:
|
||||
for index, generated_image in enumerate(response.generated_images):
|
||||
image_data = generated_image.image.image_bytes
|
||||
image_uploader = None
|
||||
if settings.UPLOAD_PROVIDER == "smms":
|
||||
image_uploader = ImageUploaderFactory.create(provider=settings.UPLOAD_PROVIDER,api_key=settings.SMMS_SECRET_TOKEN)
|
||||
current_date = time.strftime("%Y/%m/%d")
|
||||
filename = f"{current_date}/{uuid.uuid4().hex[:8]}.png"
|
||||
upload_response = image_uploader.upload(image_data,filename)
|
||||
|
||||
if request.response_format == "b64_json":
|
||||
base64_image = base64.b64encode(image_data).decode('utf-8')
|
||||
@@ -109,6 +104,30 @@ class ImageCreateService:
|
||||
"revised_prompt": request.prompt
|
||||
})
|
||||
else:
|
||||
current_date = time.strftime("%Y/%m/%d")
|
||||
filename = f"{current_date}/{uuid.uuid4().hex[:8]}.png"
|
||||
|
||||
if settings.UPLOAD_PROVIDER == "smms":
|
||||
image_uploader = ImageUploaderFactory.create(
|
||||
provider=settings.UPLOAD_PROVIDER,
|
||||
api_key=settings.SMMS_SECRET_TOKEN
|
||||
)
|
||||
elif settings.UPLOAD_PROVIDER == "picgo":
|
||||
image_uploader = ImageUploaderFactory.create(
|
||||
provider=settings.UPLOAD_PROVIDER,
|
||||
api_key=settings.PICGO_API_KEY
|
||||
)
|
||||
elif settings.UPLOAD_PROVIDER == "cloudflare_imgbed":
|
||||
image_uploader = ImageUploaderFactory.create(
|
||||
provider=settings.UPLOAD_PROVIDER,
|
||||
base_url=settings.CLOUDFLARE_IMGBED_URL,
|
||||
auth_code=settings.CLOUDFLARE_IMGBED_AUTH_CODE
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unsupported upload provider: {settings.UPLOAD_PROVIDER}")
|
||||
|
||||
upload_response = image_uploader.upload(image_data, filename)
|
||||
|
||||
images_data.append({
|
||||
"url": f"{upload_response.data.url}",
|
||||
"revised_prompt": request.prompt
|
||||
|
||||
Reference in New Issue
Block a user