Update scd.py
这个提交包含在:
@@ -26,15 +26,129 @@ DEFAULT_MIRROR = "https://scl.ecuil.com/run/plugins/"
|
||||
# 配置文件路径
|
||||
CONFIG_FILE = os.path.join(os.path.expanduser("~"), ".scd_config.json")
|
||||
|
||||
# 多语言支持
|
||||
LANGUAGES = {
|
||||
"en": {
|
||||
"installing_plugin": "Installing plugin: {}",
|
||||
"downloading_from": "Downloading from: {}",
|
||||
"plugin_installed": "Plugin {} installed successfully!",
|
||||
"install_failed": "Failed to install plugin {}",
|
||||
"installing_from_file": "Installing plugins from file: {}",
|
||||
"file_not_found": "File {} not found",
|
||||
"no_plugins_in_file": "No plugins found in file",
|
||||
"all_plugins_installed": "All plugins installed!",
|
||||
"reading_file_failed": "Failed to read file: {}",
|
||||
"updating_plugin": "Updating plugin: {}",
|
||||
"updating_scd": "Updating scd...",
|
||||
"local_version": "Local version: {}",
|
||||
"remote_version": "Remote version: {}",
|
||||
"found_new_version": "Found new version, downloading...",
|
||||
"unsupported_os": "Unsupported operating system",
|
||||
"update_failed": "Failed to download update",
|
||||
"scd_updated": "scd updated successfully!",
|
||||
"run_new_scd": "Please run the new scd{}",
|
||||
"already_latest": "{} is already up to date",
|
||||
"listing_local_plugins": "Listing local plugins...",
|
||||
"installed_plugins": "Installed plugins:",
|
||||
"no_plugins_installed": "No plugins installed",
|
||||
"plugins_dir_not_found": "Plugins directory not found",
|
||||
"listing_web_plugins": "Listing web plugins...",
|
||||
"fetching_plugins_from": "Fetching plugins from: {}",
|
||||
"available_plugins": "Available plugins:",
|
||||
"no_available_plugins": "No available plugins",
|
||||
"invalid_api_response": "Invalid API response",
|
||||
"install_required_packages": "Error: Please install required packages: pip install requests",
|
||||
"fetch_failed": "Failed to fetch plugins list: {}",
|
||||
"check_network": "Please check your network connection or mirror URL",
|
||||
"available_mirrors": "Available mirrors:",
|
||||
"adding_mirror": "Mirror {} added and set as current mirror",
|
||||
"mirror_exists": "Mirror {} already exists",
|
||||
"scd_info": "SCL Plugin Downloader (scd)",
|
||||
"version": "Version: 1.0.0",
|
||||
"current_mirror": "Current mirror: {}",
|
||||
"available_mirrors_count": "Available mirrors: {}",
|
||||
"cpu_cores": "CPU cores: {}",
|
||||
"download_threads": "Download threads: {}",
|
||||
"loading_config_failed": "Failed to load config file: {}",
|
||||
"saving_config_failed": "Failed to save config file: {}",
|
||||
"downloading_file": "Downloading: {}",
|
||||
"download_failed": "Failed to download file: {}",
|
||||
"error": "Error: {}",
|
||||
"warning_fallback": "Warning: Using fallback download method. Install requests and tqdm for better progress bars.",
|
||||
"language_set": "Language set to: {}",
|
||||
"language_not_supported": "Language not supported. Available languages: en, zh",
|
||||
"setting_language": "Setting language to: {}",
|
||||
"current_language": "Current language: {}"
|
||||
},
|
||||
"zh": {
|
||||
"installing_plugin": "正在安装插件: {}",
|
||||
"downloading_from": "从以下地址下载: {}",
|
||||
"plugin_installed": "插件 {} 安装成功!",
|
||||
"install_failed": "安装插件 {} 失败",
|
||||
"installing_from_file": "从文件安装插件: {}",
|
||||
"file_not_found": "文件 {} 不存在",
|
||||
"no_plugins_in_file": "文件中未找到插件",
|
||||
"all_plugins_installed": "所有插件安装完成!",
|
||||
"reading_file_failed": "读取文件失败: {}",
|
||||
"updating_plugin": "正在更新插件: {}",
|
||||
"updating_scd": "正在更新 scd...",
|
||||
"local_version": "本地版本: {}",
|
||||
"remote_version": "远程版本: {}",
|
||||
"found_new_version": "发现新版本,正在下载...",
|
||||
"unsupported_os": "不支持的操作系统",
|
||||
"update_failed": "下载更新失败",
|
||||
"scd_updated": "scd 更新成功!",
|
||||
"run_new_scd": "请运行新的 scd{}",
|
||||
"already_latest": "{} 已是最新版本,无需更新",
|
||||
"listing_local_plugins": "正在列出本地插件...",
|
||||
"installed_plugins": "已安装的插件:",
|
||||
"no_plugins_installed": "没有安装插件",
|
||||
"plugins_dir_not_found": "未找到插件目录",
|
||||
"listing_web_plugins": "正在列出网络插件...",
|
||||
"fetching_plugins_from": "从以下地址获取插件: {}",
|
||||
"available_plugins": "可用的插件:",
|
||||
"no_available_plugins": "没有可用的插件",
|
||||
"invalid_api_response": "API 响应无效",
|
||||
"install_required_packages": "错误: 请安装必要的包: pip install requests",
|
||||
"fetch_failed": "获取插件列表失败: {}",
|
||||
"check_network": "请检查网络连接或镜像 URL",
|
||||
"available_mirrors": "可用的镜像源:",
|
||||
"adding_mirror": "镜像 {} 已添加并设为当前镜像",
|
||||
"mirror_exists": "镜像 {} 已存在",
|
||||
"scd_info": "SCL 插件下载器 (scd)",
|
||||
"version": "版本: 1.0.0",
|
||||
"current_mirror": "当前镜像: {}",
|
||||
"available_mirrors_count": "可用镜像: {}",
|
||||
"cpu_cores": "CPU 核心数: {}",
|
||||
"download_threads": "下载线程数: {}",
|
||||
"loading_config_failed": "加载配置文件失败: {}",
|
||||
"saving_config_failed": "保存配置文件失败: {}",
|
||||
"downloading_file": "下载中: {}",
|
||||
"download_failed": "下载文件失败: {}",
|
||||
"error": "错误: {}",
|
||||
"warning_fallback": "警告: 使用后备下载方法。安装 requests 和 tqdm 以获得更好的进度条。",
|
||||
"language_set": "语言已设置为: {}",
|
||||
"language_not_supported": "不支持的语言。可用语言: en, zh",
|
||||
"setting_language": "正在设置语言为: {}",
|
||||
"current_language": "当前语言: {}"
|
||||
}
|
||||
}
|
||||
|
||||
class SCDownloader:
|
||||
def __init__(self):
|
||||
self.config = self.load_config()
|
||||
self.mirrors = self.config.get("mirrors", [DEFAULT_MIRROR])
|
||||
self.current_mirror = self.config.get("current_mirror", DEFAULT_MIRROR)
|
||||
self.language = self.config.get("language", "zh") # 默认中文
|
||||
# 获取 CPU 核心数,用于多线程下载
|
||||
self.cpu_cores = os.cpu_count() or 4
|
||||
self.threads = max(1, self.cpu_cores // 2)
|
||||
|
||||
def _(self, key, *args):
|
||||
"""获取翻译文本"""
|
||||
lang = self.language if self.language in LANGUAGES else "zh"
|
||||
return LANGUAGES[lang].get(key, key).format(*args)
|
||||
|
||||
def load_config(self):
|
||||
"""加载配置文件"""
|
||||
if os.path.exists(CONFIG_FILE):
|
||||
@@ -42,19 +156,20 @@ class SCDownloader:
|
||||
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"加载配置文件失败: {e}")
|
||||
return {"mirrors": [DEFAULT_MIRROR], "current_mirror": DEFAULT_MIRROR}
|
||||
print(self._("loading_config_failed", e))
|
||||
return {"mirrors": [DEFAULT_MIRROR], "current_mirror": DEFAULT_MIRROR, "language": "zh"}
|
||||
|
||||
def save_config(self):
|
||||
"""保存配置文件"""
|
||||
self.config["mirrors"] = self.mirrors
|
||||
self.config["current_mirror"] = self.current_mirror
|
||||
self.config["language"] = self.language
|
||||
try:
|
||||
os.makedirs(os.path.dirname(CONFIG_FILE), exist_ok=True)
|
||||
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(self.config, f, indent=2)
|
||||
except Exception as e:
|
||||
print(f"保存配置文件失败: {e}")
|
||||
print(self._("saving_config_failed", e))
|
||||
|
||||
def add_mirror(self, mirror_url):
|
||||
"""添加镜像源"""
|
||||
@@ -62,9 +177,19 @@ class SCDownloader:
|
||||
self.mirrors.append(mirror_url)
|
||||
self.current_mirror = mirror_url
|
||||
self.save_config()
|
||||
print(f"镜像 {mirror_url} 已添加并设为当前镜像")
|
||||
print(self._("adding_mirror", mirror_url))
|
||||
else:
|
||||
print(f"镜像 {mirror_url} 已存在")
|
||||
print(self._("mirror_exists", mirror_url))
|
||||
|
||||
def set_language(self, lang):
|
||||
"""设置语言"""
|
||||
if lang in LANGUAGES:
|
||||
print(self._("setting_language", lang))
|
||||
self.language = lang
|
||||
self.save_config()
|
||||
print(self._("language_set", lang))
|
||||
else:
|
||||
print(self._("language_not_supported"))
|
||||
|
||||
def download_file(self, url, output_path, show_progress=True):
|
||||
"""下载文件并显示进度(模范 PIP 风格)"""
|
||||
@@ -95,7 +220,7 @@ class SCDownloader:
|
||||
return True
|
||||
except ImportError:
|
||||
# 如果没有 requests 和 tqdm,使用 urllib 作为后备
|
||||
print("警告: 使用后备下载方法。安装 requests 和 tqdm 以获得更好的进度条。")
|
||||
print(self._("warning_fallback"))
|
||||
|
||||
def progress_hook(count, block_size, total_size):
|
||||
if total_size > 0:
|
||||
@@ -117,15 +242,15 @@ class SCDownloader:
|
||||
sys.stdout.flush()
|
||||
return True
|
||||
except urllib.error.URLError as e:
|
||||
print(f"\n下载文件失败: {e}")
|
||||
print(f"\n{self._('download_failed', e)}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"\n错误: {e}")
|
||||
print(f"\n{self._('error', e)}")
|
||||
return False
|
||||
|
||||
def install_plugin(self, plugin_name):
|
||||
"""安装插件"""
|
||||
print(f"正在安装插件: {plugin_name}")
|
||||
print(self._("installing_plugin", plugin_name))
|
||||
|
||||
# 构建插件下载 URL
|
||||
plugin_url = f"{self.current_mirror}{plugin_name}.py"
|
||||
@@ -135,20 +260,20 @@ class SCDownloader:
|
||||
os.makedirs("plugins", exist_ok=True)
|
||||
|
||||
# 下载插件
|
||||
print(f"从以下地址下载: {plugin_url}")
|
||||
print(self._("downloading_from", plugin_url))
|
||||
if self.download_file(plugin_url, plugin_path):
|
||||
print(f"插件 {plugin_name} 安装成功!")
|
||||
print(self._("plugin_installed", plugin_name))
|
||||
return True
|
||||
else:
|
||||
print(f"安装插件 {plugin_name} 失败")
|
||||
print(self._("install_failed", plugin_name))
|
||||
return False
|
||||
|
||||
def install_from_file(self, file_path):
|
||||
"""从文件安装多个插件"""
|
||||
print(f"从文件安装插件: {file_path}")
|
||||
print(self._("installing_from_file", file_path))
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
print(f"文件 {file_path} 不存在")
|
||||
print(self._("file_not_found", file_path))
|
||||
return False
|
||||
|
||||
try:
|
||||
@@ -156,7 +281,7 @@ class SCDownloader:
|
||||
plugins = [line.strip() for line in f if line.strip() and not line.strip().startswith("#")]
|
||||
|
||||
if not plugins:
|
||||
print("文件中未找到插件")
|
||||
print(self._("no_plugins_in_file"))
|
||||
return False
|
||||
|
||||
# 使用线程池下载插件
|
||||
@@ -168,12 +293,12 @@ class SCDownloader:
|
||||
try:
|
||||
future.result()
|
||||
except Exception as e:
|
||||
print(f"安装 {plugin} 时出错: {e}")
|
||||
print(f"{self._('error', e)}")
|
||||
|
||||
print("所有插件安装完成!")
|
||||
print(self._("all_plugins_installed"))
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"读取文件失败: {e}")
|
||||
print(self._("reading_file_failed", e))
|
||||
return False
|
||||
|
||||
def get_plugin_version(self, plugin_name):
|
||||
@@ -203,7 +328,7 @@ class SCDownloader:
|
||||
version_data = response.json()
|
||||
return version_data.get("version", "0.0.0")
|
||||
except Exception as e:
|
||||
print(f"获取远程版本信息失败: {e}")
|
||||
print(self._("error", e))
|
||||
return "0.0.0"
|
||||
|
||||
def compare_versions(self, v1, v2):
|
||||
@@ -250,26 +375,26 @@ class SCDownloader:
|
||||
version_data = response.json()
|
||||
return version_data.get("v", "0.0.0")
|
||||
except Exception as e:
|
||||
print(f"获取远程版本信息失败: {e}")
|
||||
print(self._("error", e))
|
||||
return "0.0.0"
|
||||
|
||||
def update_plugin(self, plugin_name):
|
||||
"""更新插件"""
|
||||
if plugin_name == "scd":
|
||||
# 更新 scd 本身
|
||||
print("正在更新 scd...")
|
||||
print(self._("updating_scd"))
|
||||
|
||||
# 获取本地版本
|
||||
local_version = self.get_scd_version()
|
||||
print(f"本地版本: {local_version}")
|
||||
print(self._("local_version", local_version))
|
||||
|
||||
# 获取远程版本
|
||||
remote_version = self.get_remote_scd_version()
|
||||
print(f"远程版本: {remote_version}")
|
||||
print(self._("remote_version", remote_version))
|
||||
|
||||
# 比较版本
|
||||
if self.compare_versions(local_version, remote_version) < 0:
|
||||
print("发现新版本,正在下载...")
|
||||
print(self._("found_new_version"))
|
||||
|
||||
# 根据操作系统类型选择下载文件
|
||||
import platform
|
||||
@@ -282,7 +407,7 @@ class SCDownloader:
|
||||
scd_url = "https://scl.ecuil.com/scd"
|
||||
scd_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "scd")
|
||||
else:
|
||||
print("不支持的操作系统")
|
||||
print(self._("unsupported_os"))
|
||||
return False
|
||||
|
||||
# 下载更新
|
||||
@@ -293,55 +418,55 @@ class SCDownloader:
|
||||
import os
|
||||
os.chmod(scd_path, 0o755)
|
||||
except Exception as e:
|
||||
print(f"设置可执行权限失败: {e}")
|
||||
print(self._("error", e))
|
||||
|
||||
print("scd 更新成功!")
|
||||
print(f"请运行新的 scd{'文件' if system == 'Windows' else '可执行文件'}")
|
||||
print(self._("scd_updated"))
|
||||
print(self._("run_new_scd", "文件" if system == "Windows" else "可执行文件"))
|
||||
return True
|
||||
else:
|
||||
print("下载更新失败")
|
||||
print(self._("update_failed"))
|
||||
return False
|
||||
else:
|
||||
print("scd 已是最新版本,无需更新")
|
||||
print(self._("already_latest", "scd"))
|
||||
return True
|
||||
else:
|
||||
# 更新普通插件
|
||||
print(f"正在更新插件: {plugin_name}")
|
||||
print(self._("updating_plugin", plugin_name))
|
||||
|
||||
# 获取本地版本
|
||||
local_version = self.get_plugin_version(plugin_name)
|
||||
print(f"本地版本: {local_version}")
|
||||
print(self._("local_version", local_version))
|
||||
|
||||
# 获取远程版本
|
||||
remote_version = self.get_remote_plugin_version(plugin_name)
|
||||
print(f"远程版本: {remote_version}")
|
||||
print(self._("remote_version", remote_version))
|
||||
|
||||
# 比较版本
|
||||
if self.compare_versions(local_version, remote_version) < 0:
|
||||
print("发现新版本,正在下载...")
|
||||
print(self._("found_new_version"))
|
||||
return self.install_plugin(plugin_name)
|
||||
else:
|
||||
print("插件已是最新版本,无需更新")
|
||||
print(self._("already_latest", f"插件 {plugin_name}"))
|
||||
return True
|
||||
|
||||
def list_plugins(self, mode="local"):
|
||||
"""列出可用插件"""
|
||||
if mode == "local":
|
||||
print("正在列出本地插件...")
|
||||
print(self._("listing_local_plugins"))
|
||||
plugins_dir = "plugins"
|
||||
if os.path.exists(plugins_dir):
|
||||
plugins = [f[:-3] for f in os.listdir(plugins_dir) if f.endswith(".py")]
|
||||
if plugins:
|
||||
print("已安装的插件:")
|
||||
print(self._("installed_plugins"))
|
||||
for plugin in plugins:
|
||||
print(f" - {plugin}")
|
||||
else:
|
||||
print("没有安装插件")
|
||||
print(self._("no_plugins_installed"))
|
||||
else:
|
||||
print("未找到插件目录")
|
||||
print(self._("plugins_dir_not_found"))
|
||||
elif mode == "web":
|
||||
print("正在列出网络插件...")
|
||||
print(f"从以下地址获取插件: {self.current_mirror}")
|
||||
print(self._("listing_web_plugins"))
|
||||
print(self._("fetching_plugins_from", self.current_mirror))
|
||||
try:
|
||||
# 尝试从 API 获取插件列表
|
||||
import requests
|
||||
@@ -353,22 +478,22 @@ class SCDownloader:
|
||||
if plugins_data.get("status") == "success" and "plugins" in plugins_data:
|
||||
plugins = plugins_data["plugins"]
|
||||
if plugins:
|
||||
print("可用的插件:")
|
||||
print(self._("available_plugins"))
|
||||
for plugin in plugins:
|
||||
print(f" - {plugin}")
|
||||
else:
|
||||
print("没有可用的插件")
|
||||
print(self._("no_available_plugins"))
|
||||
else:
|
||||
print("API 响应无效")
|
||||
print(self._("invalid_api_response"))
|
||||
except ImportError:
|
||||
print("错误: 请安装必要的包: pip install requests")
|
||||
print(self._("install_required_packages"))
|
||||
except Exception as e:
|
||||
print(f"获取插件列表失败: {e}")
|
||||
print("请检查网络连接或镜像 URL")
|
||||
print(self._("fetch_failed", e))
|
||||
print(self._("check_network"))
|
||||
|
||||
def show_mirrors(self):
|
||||
"""显示可用镜像源"""
|
||||
print("可用的镜像源:")
|
||||
print(self._("available_mirrors"))
|
||||
for i, mirror in enumerate(self.mirrors):
|
||||
marker = "*" if mirror == self.current_mirror else " "
|
||||
print(f"{marker} [{i+1}] {mirror}")
|
||||
@@ -395,12 +520,19 @@ class SCDownloader:
|
||||
else:
|
||||
self.list_plugins()
|
||||
elif args.command == "info":
|
||||
print("SCL 插件下载器 (scd)")
|
||||
print(f"版本: 1.0.0")
|
||||
print(f"当前镜像: {self.current_mirror}")
|
||||
print(f"可用镜像: {len(self.mirrors)}")
|
||||
print(f"CPU 核心数: {self.cpu_cores}")
|
||||
print(f"下载线程数: {self.threads}")
|
||||
print(self._("scd_info"))
|
||||
print(self._("version"))
|
||||
print(self._("current_mirror", self.current_mirror))
|
||||
print(self._("available_mirrors_count", len(self.mirrors)))
|
||||
print(self._("cpu_cores", self.cpu_cores))
|
||||
print(self._("download_threads", self.threads))
|
||||
print(self._("current_language", self.language))
|
||||
elif args.command == "language":
|
||||
if args.lang:
|
||||
self.set_language(args.lang)
|
||||
else:
|
||||
print(self._("current_language", self.language))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="SCL 插件下载器")
|
||||
@@ -427,6 +559,10 @@ def main():
|
||||
# info 命令
|
||||
subparsers.add_parser("info", help="显示 scd 信息")
|
||||
|
||||
# language 命令
|
||||
language_parser = subparsers.add_parser("language", help="管理语言设置")
|
||||
language_parser.add_argument("lang", nargs="?", choices=["en", "zh"], help="要设置的语言: en 或 zh")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 处理 -t 参数
|
||||
@@ -440,5 +576,6 @@ def main():
|
||||
downloader = SCDownloader()
|
||||
downloader.run(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
在新工单中引用
屏蔽一个用户