2026-04-22 11:53:00 +08:00
|
|
|
|
from urllib.parse import quote, urlparse, urlunparse
|
2026-02-02 12:54:43 +08:00
|
|
|
|
from config import Config
|
|
|
|
|
|
|
|
|
|
|
|
def get_proxied_url(url):
|
|
|
|
|
|
"""
|
|
|
|
|
|
如果启用了代理,则返回经过代理包装的 URL。
|
|
|
|
|
|
否则返回原 URL。
|
|
|
|
|
|
"""
|
|
|
|
|
|
if Config.USE_PROXY and url:
|
|
|
|
|
|
return f"{Config.PROXY_URL}{quote(url)}"
|
|
|
|
|
|
return url
|
2026-04-22 11:53:00 +08:00
|
|
|
|
|
|
|
|
|
|
def get_backup_api_url(url):
|
|
|
|
|
|
"""
|
|
|
|
|
|
将已有接口地址切换到备用 AI Base URL,并保留原始路径。
|
|
|
|
|
|
"""
|
|
|
|
|
|
if not url or not Config.AI_BACKUP_BASE_URL:
|
|
|
|
|
|
return url
|
|
|
|
|
|
|
|
|
|
|
|
source = urlparse(url)
|
|
|
|
|
|
backup = urlparse(Config.AI_BACKUP_BASE_URL)
|
|
|
|
|
|
if not backup.scheme or not backup.netloc:
|
|
|
|
|
|
return url
|
|
|
|
|
|
|
|
|
|
|
|
return urlunparse((
|
|
|
|
|
|
backup.scheme,
|
|
|
|
|
|
backup.netloc,
|
|
|
|
|
|
source.path,
|
|
|
|
|
|
source.params,
|
|
|
|
|
|
source.query,
|
|
|
|
|
|
source.fragment,
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
def get_backup_api_key(api_key):
|
|
|
|
|
|
"""
|
|
|
|
|
|
返回内置主 Key 对应的备用 Key;自定义 Key 默认沿用原值。
|
|
|
|
|
|
"""
|
|
|
|
|
|
fallback_map = {
|
|
|
|
|
|
Config.TRIAL_KEY: Config.TRIAL_BACKUP_KEY,
|
|
|
|
|
|
Config.PREMIUM_KEY: Config.PREMIUM_BACKUP_KEY,
|
|
|
|
|
|
Config.VIDEO_KEY: Config.VIDEO_BACKUP_KEY,
|
|
|
|
|
|
Config.GEMINI_FLASH_IMAGE_PREMIUM_KEY: Config.GEMINI_FLASH_IMAGE_PREMIUM_BACKUP_KEY,
|
|
|
|
|
|
}
|
|
|
|
|
|
return fallback_map.get(api_key, api_key)
|
|
|
|
|
|
|
|
|
|
|
|
def get_api_candidates(url, api_key):
|
|
|
|
|
|
"""
|
|
|
|
|
|
生成主线路与备用线路候选。
|
|
|
|
|
|
"""
|
|
|
|
|
|
candidates = [{"url": url, "api_key": api_key, "label": "primary"}]
|
|
|
|
|
|
backup_url = get_backup_api_url(url)
|
|
|
|
|
|
backup_key = get_backup_api_key(api_key)
|
|
|
|
|
|
|
|
|
|
|
|
if backup_url and backup_url != url:
|
|
|
|
|
|
candidates.append({"url": backup_url, "api_key": backup_key, "label": "backup"})
|
|
|
|
|
|
|
|
|
|
|
|
return candidates
|
|
|
|
|
|
|
|
|
|
|
|
def should_switch_to_backup(status_code):
|
|
|
|
|
|
"""
|
|
|
|
|
|
遇到鉴权、限流或服务端异常时,尝试切换备用线路。
|
|
|
|
|
|
"""
|
|
|
|
|
|
return status_code in (401, 403, 408, 429) or status_code >= 500
|