"""从 GitHub Releases 下载 dws CLI 到项目 tools/ 目录""" import os import sys import json import platform import zipfile import io import shutil try: from urllib.request import urlopen, Request except ImportError: print("需要 Python 3") sys.exit(1) SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PROJECT_ROOT = os.path.dirname(SCRIPT_DIR) TOOLS_DIR = os.path.join(PROJECT_ROOT, "tools") REPO = "DingTalk-Real-AI/dingtalk-workspace-cli" API_URL = f"https://api.github.com/repos/{REPO}/releases/latest" def get_asset_name(): """根据当前平台返回对应的 release asset 文件名""" system = platform.system().lower() # windows / darwin / linux machine = platform.machine().lower() # amd64 / arm64 / x86_64 if machine in ("x86_64", "amd64"): arch = "amd64" elif machine in ("aarch64", "arm64"): arch = "arm64" else: print(f"不支持的架构: {machine}") sys.exit(1) if system == "windows": return f"dws-windows-{arch}.zip" elif system == "darwin": return f"dws-darwin-{arch}.tar.gz" elif system == "linux": return f"dws-linux-{arch}.tar.gz" else: print(f"不支持的操作系统: {system}") sys.exit(1) def download_and_extract(asset_name, download_url): """下载并解压 dws 到 tools/ 目录""" os.makedirs(TOOLS_DIR, exist_ok=True) print(f"下载 {asset_name} ...") req = Request(download_url, headers={"Accept": "application/octet-stream", "User-Agent": "feishu-docs-summary/setup"}) with urlopen(req) as resp: data = resp.read() ext = ".exe" if platform.system() == "Windows" else "" target = os.path.join(TOOLS_DIR, f"dws{ext}") if asset_name.endswith(".zip"): with zipfile.ZipFile(io.BytesIO(data)) as zf: # 找到 dws 可执行文件 for name in zf.namelist(): basename = os.path.basename(name) if basename == "dws" or basename == "dws.exe": with zf.open(name) as src, open(target, "wb") as dst: dst.write(src.read()) break else: print("zip 中未找到 dws 可执行文件") sys.exit(1) elif asset_name.endswith(".tar.gz"): import tarfile with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as tf: for member in tf.getmembers(): if os.path.basename(member.name) == "dws": src = tf.extractfile(member) with open(target, "wb") as dst: dst.write(src.read()) break else: print("tar.gz 中未找到 dws 可执行文件") sys.exit(1) # Unix 系统加执行权限 if platform.system() != "Windows": os.chmod(target, 0o755) size_kb = os.path.getsize(target) / 1024 print(f"已保存到: {target} ({size_kb:.0f} KB)") return target def main(): # 检查是否已存在 ext = ".exe" if platform.system() == "Windows" else "" existing = os.path.join(TOOLS_DIR, f"dws{ext}") if os.path.isfile(existing): print(f"dws 已存在: {existing}") print("如需更新,请先删除该文件后重新运行此脚本") return # 获取最新 release 信息 print(f"查询最新版本: {API_URL}") req = Request(API_URL, headers={"Accept": "application/vnd.github.v3+json", "User-Agent": "feishu-docs-summary/setup"}) with urlopen(req) as resp: release = json.loads(resp.read()) tag = release["tag_name"] print(f"最新版本: {tag}") # 检查 rate limit remaining = resp.headers.get("X-RateLimit-Remaining", "?") print(f"GitHub API 剩余请求: {remaining}") asset_name = get_asset_name() print(f"目标平台: {asset_name}") # 找到下载链接 download_url = None for asset in release.get("assets", []): if asset["name"] == asset_name: download_url = asset["browser_download_url"] break if not download_url: print(f"未找到对应平台的 release: {asset_name}") sys.exit(1) path = download_and_extract(asset_name, download_url) print("\n安装完成!验证:") print(f" {path} version") print(f" {path} auth") if __name__ == "__main__": main()