refactor: restructure project to modern Python layout, separate src, tests, docs, examples

This commit is contained in:
2025-08-07 16:57:41 +08:00
commit 4cb6c4eab7
27 changed files with 2580 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
import json
import os
import subprocess
import requests
from typing import Dict, Optional, Tuple
from ..utils.crypto import encrypt, decrypt
class ConfigManager:
"""配置文件管理器"""
def __init__(self, storage_path: str = "ab", cdn_base_url: str = ""):
self.storage_path = storage_path
self.cdn_base_url = cdn_base_url
def version_to_path(self, version: str) -> str:
"""将版本号转换为存储路径格式"""
# 0.29 -> 0_29
return version.replace('.', '_')
def get_config_path(self, version: str, platform: str) -> str:
"""获取配置文件在对象存储中的路径"""
version_path = self.version_to_path(version)
filename = f"{platform}config.json"
return f"{self.storage_path}/{version_path}/{filename}"
def get_cdn_url(self, version: str, platform: str) -> str:
"""获取配置文件在CDN中的URL"""
if not self.cdn_base_url:
return ""
version_path = self.version_to_path(version)
filename = f"{platform}config.json"
return f"{self.cdn_base_url}/{self.storage_path}/{version_path}/{filename}"
def download_from_storage(self, version: str, platform: str) -> Optional[str]:
"""从对象存储下载并解密配置文件"""
try:
config_path = self.get_config_path(version, platform)
# 使用rclone下载文件
result = subprocess.run(
["rclone", "cat", config_path],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
print(f"警告: 无法从对象存储下载 {config_path}: {result.stderr}")
return None
# 解密文件内容
encrypted_content = result.stdout.strip()
if not encrypted_content:
print(f"警告: 文件 {config_path} 为空")
return None
decrypted_content = decrypt(encrypted_content)
return decrypted_content
except subprocess.TimeoutExpired:
print(f"错误: 下载 {config_path} 超时")
return None
except Exception as e:
print(f"错误: 下载 {config_path} 失败: {str(e)}")
return None
def get_from_cdn(self, version: str, platform: str) -> Optional[str]:
"""从CDN获取配置文件内容"""
try:
cdn_url = self.get_cdn_url(version, platform)
if not cdn_url:
print(f"警告: CDN URL未配置跳过CDN内容获取")
return None
response = requests.get(cdn_url, timeout=10)
response.raise_for_status()
# CDN中的内容应该是解密后的JSON
return response.text
except requests.RequestException as e:
print(f"警告: 无法从CDN获取 {cdn_url}: {str(e)}")
return None
except Exception as e:
print(f"错误: 获取CDN内容失败: {str(e)}")
return None
def parse_config(self, content: str) -> Optional[Dict]:
"""解析配置文件内容"""
try:
return json.loads(content)
except json.JSONDecodeError as e:
print(f"错误: 配置文件格式错误: {str(e)}")
return None
def compare_configs(self, storage_config: Dict, cdn_config: Dict) -> Dict:
"""比较存储配置和CDN配置的差异"""
all_keys = set(storage_config.keys()) | set(cdn_config.keys())
differences = {}
for key in sorted(all_keys):
storage_value = storage_config.get(key, "N/A")
cdn_value = cdn_config.get(key, "N/A")
if storage_value != cdn_value:
differences[key] = {
"storage": storage_value,
"cdn": cdn_value,
"different": True
}
else:
differences[key] = {
"storage": storage_value,
"cdn": cdn_value,
"different": False
}
return differences