v0.2.7: 修复Redis连接 + 启动管理后台

- 修复Redis认证 (配置密码)
- 启动Python管理后台 (端口9531, 15个功能开关)
- 统一版本号 0.2.7
- 更新docker-compose.yml (镜像版本/Redis URL/Admin服务)
This commit is contained in:
2026-05-17 02:22:18 +08:00
commit 83cbfaf03f
164 changed files with 25195 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
"""
CloudSearch Transfer — 配置管理 v1.0.0
支持环境变量 + JSON文件 + 数据库多级配置源
"""
import os
import json
from pathlib import Path
from typing import Optional, Dict, Any
from dataclasses import dataclass, field
@dataclass
class PlatformConfig:
"""单个网盘平台的配置"""
enabled: bool = False
cookie: str = "" # Cookie字符串夸克/百度/UC/123
refresh_token: str = "" # OAuth RefreshToken阿里/迅雷)
access_token: str = "" # 运行时AccessToken自动刷新
account_name: str = "" # 账号名(多账号路由)
save_dir: str = "/" # 默认转存目录
share_password: str = "" # 分享密码
banned_keywords: list = field(default_factory=list) # 广告过滤关键词
extra: Dict[str, Any] = field(default_factory=dict) # 扩展字段
@dataclass
class TransferConfig:
"""转存服务配置"""
# HTTP
request_timeout: int = 30 # 请求超时(秒)
max_retries: int = 3 # 最大重试次数
retry_delay: float = 1.0 # 重试延迟(秒)
# 任务轮询
task_poll_interval: float = 0.5 # 轮询间隔(秒)
task_poll_max_attempts: int = 50 # 最大轮询次数
task_poll_max_wait: int = 60 # 最大等待时间(秒)
# 并发控制
max_concurrent_transfers: int = 5 # 最大并发转存数
transfer_queue_size: int = 100 # 转存队列大小
# 广告过滤
ad_filter_enabled: bool = True # 是否启用广告过滤
default_banned_keywords: list = field(default_factory=lambda: [
"公众号", "微信", "扫码", "加群", "QQ群", "广告",
"关注", "免费领取", "点击领取", "全网", "最全",
])
# 分享设置
default_share_period: str = "permanent" # 永久/7d/30d
auto_generate_password: bool = False # 自动生成分享密码
class ConfigManager:
"""统一配置管理器"""
def __init__(self, config_path: Optional[str] = None):
self._config_path = config_path or os.getenv(
"TRANSFER_CONFIG_PATH",
"/data/transfer_config.json"
)
self.platforms: Dict[str, PlatformConfig] = {}
self.transfer: TransferConfig = TransferConfig()
self._load()
def _load(self):
"""加载配置:环境变量 → JSON文件 → 默认值"""
# 1. 从JSON文件加载
if Path(self._config_path).exists():
with open(self._config_path) as f:
data = json.load(f)
self._parse_json(data)
# 2. 环境变量覆盖
self._apply_env_overrides()
def _parse_json(self, data: dict):
"""解析JSON配置"""
# 平台配置
platforms_data = data.get("platforms", {})
for name, cfg in platforms_data.items():
self.platforms[name] = PlatformConfig(
enabled=cfg.get("enabled", False),
cookie=cfg.get("cookie", ""),
refresh_token=cfg.get("refresh_token", ""),
access_token=cfg.get("access_token", ""),
account_name=cfg.get("account_name", name),
save_dir=cfg.get("save_dir", "/"),
share_password=cfg.get("share_password", ""),
banned_keywords=cfg.get("banned_keywords", []),
extra=cfg.get("extra", {}),
)
# 传输配置
transfer_data = data.get("transfer", {})
if transfer_data:
self.transfer = TransferConfig(
request_timeout=transfer_data.get("request_timeout", 30),
max_retries=transfer_data.get("max_retries", 3),
retry_delay=transfer_data.get("retry_delay", 1.0),
task_poll_interval=transfer_data.get("task_poll_interval", 0.5),
task_poll_max_attempts=transfer_data.get("task_poll_max_attempts", 50),
max_concurrent_transfers=transfer_data.get("max_concurrent_transfers", 5),
ad_filter_enabled=transfer_data.get("ad_filter_enabled", True),
)
def _apply_env_overrides(self):
"""环境变量覆盖TRANSFER_<PLATFORM>_COOKIE 等"""
env_map = {
"quark": "QUARK",
"baidu": "BAIDU",
"aliyun": "ALIYUN",
"uc": "UC",
"xunlei": "XUNLEI",
"pan123": "PAN123",
"cloud189": "CLOUD189",
}
for platform, prefix in env_map.items():
cookie = os.getenv(f"TRANSFER_{prefix}_COOKIE")
if cookie:
if platform not in self.platforms:
self.platforms[platform] = PlatformConfig()
self.platforms[platform].cookie = cookie
self.platforms[platform].enabled = True
token = os.getenv(f"TRANSFER_{prefix}_REFRESH_TOKEN")
if token:
if platform not in self.platforms:
self.platforms[platform] = PlatformConfig()
self.platforms[platform].refresh_token = token
self.platforms[platform].enabled = True
def get_platform(self, name: str) -> Optional[PlatformConfig]:
"""获取平台配置"""
config = self.platforms.get(name)
if config and config.enabled:
return config
return None
def get_enabled_platforms(self) -> list:
"""获取所有已启用的平台名"""
return [name for name, cfg in self.platforms.items() if cfg.enabled]
def save(self):
"""保存配置到文件"""
data = {
"platforms": {
name: {
"enabled": cfg.enabled,
"cookie": cfg.cookie[:20] + "..." if cfg.cookie else "",
"refresh_token": cfg.refresh_token[:20] + "..." if cfg.refresh_token else "",
"account_name": cfg.account_name,
"save_dir": cfg.save_dir,
"share_password": cfg.share_password,
"banned_keywords": cfg.banned_keywords,
"extra": cfg.extra,
}
for name, cfg in self.platforms.items()
},
"transfer": {
"request_timeout": self.transfer.request_timeout,
"max_retries": self.transfer.max_retries,
"max_concurrent_transfers": self.transfer.max_concurrent_transfers,
"ad_filter_enabled": self.transfer.ad_filter_enabled,
}
}
Path(self._config_path).parent.mkdir(parents=True, exist_ok=True)
with open(self._config_path, "w") as f:
json.dump(data, f, indent=2, ensure_ascii=False)