123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- import os
- import platform
- import requests
- import gzip
- import shutil
- from zipfile import ZipFile
- import stat
- import argparse
- import subprocess
- import tempfile
- # 定义常量
- MIHOMO_BASE_URL = 'https://github.com/MetaCubeX/mihomo/releases/download'
- CORE_SERVICE_BASE_URL = 'https://github.com/alroyso/core-service/releases/download'
- MIHOMO_VERSION = 'v1.18.8' # 根据实际版本修改
- CORE_SERVICE_VERSION = 'v1.0.2'
- ASSETS_DIR = './assets/bin'
- SYSTEM = platform.system().lower()
- # ClashName.platform 和 ClashName.arch 是动态生成的
- def get_platform_arch():
- return SYSTEM, platform.machine()
- # 如果目录不存在,创建下载目录
- if not os.path.exists(ASSETS_DIR):
- os.makedirs(ASSETS_DIR)
- def get_download_urls():
- """
- 根据系统生成 mihomo 和 core-service 的下载链接,分别下载 arm64 和 x86_64 架构
- """
- download_urls = []
- # 获取 ClashName 的 platform 和 arch
- platform_name, arch_name = get_platform_arch()
- # 下载 macOS、Linux、Windows 的 arm64 和 x86_64 架构
- if SYSTEM == 'darwin':
- # macOS
- download_urls.append((
- f'mihomo-darwin-arm64-{MIHOMO_VERSION}.gz',
- f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-darwin-arm64-{MIHOMO_VERSION}.gz',
- 'arm64'
- ))
- download_urls.append((
- f'mihomo-darwin-amd64-{MIHOMO_VERSION}.gz',
- f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-darwin-amd64-{MIHOMO_VERSION}.gz',
- 'x86_64'
- ))
- download_urls.append((
- f'ccore-service-darwin-arm64-{CORE_SERVICE_VERSION}.gz',
- f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-darwin-arm64-{CORE_SERVICE_VERSION}.gz',
- 'arm64'
- ))
- download_urls.append((
- f'ccore-service-darwin-amd64-{CORE_SERVICE_VERSION}.gz',
- f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-darwin-amd64-{CORE_SERVICE_VERSION}.gz',
- 'x86_64'
- ))
- elif SYSTEM == 'linux':
- # Linux
- download_urls.append((
- f'mihomo-linux-arm64-{MIHOMO_VERSION}.gz',
- f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-linux-arm64-{MIHOMO_VERSION}.gz',
- 'arm64'
- ))
- download_urls.append((
- f'mihomo-linux-amd64-{MIHOMO_VERSION}.gz',
- f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-linux-amd64-{MIHOMO_VERSION}.gz',
- 'x86_64'
- ))
- download_urls.append((
- f'ccore-service-linux-arm64-{CORE_SERVICE_VERSION}.gz',
- f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-linux-arm64-{CORE_SERVICE_VERSION}.gz',
- 'arm64'
- ))
- download_urls.append((
- f'ccore-service-linux-amd64-{CORE_SERVICE_VERSION}.gz',
- f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-linux-amd64-{CORE_SERVICE_VERSION}.gz',
- 'x86_64'
- ))
- elif SYSTEM == 'windows':
- # Windows
- download_urls.append((
- f'mihomo-windows-arm64-{MIHOMO_VERSION}.zip',
- f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-windows-arm64-{MIHOMO_VERSION}.zip',
- 'arm64'
- ))
- download_urls.append((
- f'mihomo-windows-amd64-{MIHOMO_VERSION}.zip',
- f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-windows-amd64-{MIHOMO_VERSION}.zip',
- 'x86_64'
- ))
- download_urls.append((
- f'ccore-service-windows-arm64-{CORE_SERVICE_VERSION}.zip',
- f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-windows-arm64-{CORE_SERVICE_VERSION}.zip',
- 'arm64'
- ))
- download_urls.append((
- f'ccore-service-windows-amd64-{CORE_SERVICE_VERSION}.zip',
- f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-windows-amd64-{CORE_SERVICE_VERSION}.zip',
- 'x86_64'
- ))
- return download_urls
- def download_file(url, output_path):
- """
- 下载文件
- """
- print(f"正在下载 {url} ...")
- response = requests.get(url, stream=True)
- if response.status_code == 200:
- with open(output_path, 'wb') as file:
- shutil.copyfileobj(response.raw, file)
- print(f"下载完成: {output_path}")
- else:
- print(f"下载失败 {url}, 状态码: {response.status_code}")
- def extract_gz_file(file_path, output_path):
- """
- 解压 .gz 文件
- """
- print(f"正在解压 {file_path} ...")
- with gzip.open(file_path, 'rb') as f_in:
- with open(output_path, 'wb') as f_out:
- shutil.copyfileobj(f_in, f_out)
- print(f"解压到 {output_path}")
- def extract_zip_file(file_path, output_dir):
- """
- 解压 .zip 文件
- """
- print(f"正在解压 {file_path} ...")
- with ZipFile(file_path, 'r') as zip_ref:
- zip_ref.extractall(output_dir)
- print(f"解压到 {output_dir}")
- def merge_binaries(arm_file, x86_file, output_file):
- """
- 使用 lipo 合并 arm64 和 x86_64 的二进制文件
- """
- print(f"正在合并 {arm_file} 和 {x86_file} 到 {output_file}")
- subprocess.run(['lipo', '-create', '-output', output_file, arm_file, x86_file], check=True)
- print(f"成功合并到 {output_file}")
- def add_executable_permission(file_path):
- """
- 添加可执行权限(适用于 macOS 和 Linux)
- """
- print(f"正在添加可执行权限到 {file_path}")
- st = os.stat(file_path)
- os.chmod(file_path, st.st_mode | stat.S_IEXEC)
- print(f"已添加可执行权限到 {file_path}")
- def rename_file(original_path, new_name):
- """
- 重命名文件
- """
- new_path = os.path.join(ASSETS_DIR, new_name)
- shutil.move(original_path, new_path)
- print(f"已重命名 {original_path} 为 {new_path}")
- return new_path
- def main():
- # 获取下载链接和文件名
- download_urls = get_download_urls()
- # 创建临时目录
- with tempfile.TemporaryDirectory() as temp_dir:
- # 存储架构对应的下载路径(仅适用于 macOS 合并)
- downloads = {
- 'mihomo': {'arm64': '', 'x86_64': ''},
- 'core-service': {'arm64': '', 'x86_64': ''}
- }
- for file_name, url, arch in download_urls:
- # 下载文件
- download_path = os.path.join(temp_dir, file_name)
- download_file(url, download_path)
- # 确定服务名称
- if 'core-service' in file_name:
- service_name = 'core-service'
- elif 'mihomo' in file_name:
- service_name = 'mihomo'
- else:
- raise ValueError(f"未知的服务名称: {file_name}")
- # 构建输出路径
- output_file = os.path.join(temp_dir, service_name + '-' + arch)
- # 解压文件
- if file_name.endswith('.gz'):
- extract_gz_file(download_path, output_file)
- elif file_name.endswith('.zip'):
- extract_zip_file(download_path, temp_dir)
- # 如果是 macOS,记录不同架构的文件路径
- if SYSTEM == 'darwin':
- downloads[service_name][arch] = output_file
- # 合并 macOS 下的二进制文件或直接重命名
- if SYSTEM == 'darwin':
- for service in ['mihomo', 'core-service']:
- arm_file = downloads[service]['arm64']
- x86_file = downloads[service]['x86_64']
- if arm_file and x86_file:
- merged_output = os.path.join(temp_dir, service)
- merge_binaries(arm_file, x86_file, merged_output)
- add_executable_permission(merged_output)
-
- # 如果是合并改名,core-{SYSTEM}
- # service-{SYSTEM}
- # 其他平台不变
- new_name = f"core-{SYSTEM}" if service == 'mihomo' else f"service-{SYSTEM}"
- rename_file(merged_output, new_name)
- else:
- # 对于 Linux 和 Windows,直接重命名最新下载的文件
- for service in ['mihomo', 'core-service']:
- latest_file = max(
- [f for f in os.listdir(temp_dir) if service in f],
- key=lambda x: os.path.getmtime(os.path.join(temp_dir, x))
- )
- new_name = f"core-{SYSTEM}-{platform.machine().lower()}" if service == 'mihomo' else f"service-{SYSTEM}-{platform.machine().lower()}"
- if SYSTEM == 'windows':
- new_name += '.exe'
- rename_file(os.path.join(temp_dir, latest_file), new_name)
- if SYSTEM == 'linux':
- add_executable_permission(os.path.join(ASSETS_DIR, new_name))
- if __name__ == "__main__":
- main()
|