From 09f7e5317b5d0415708cafca8e2b760eb9cb5db3 Mon Sep 17 00:00:00 2001
From: baiiylu <62942942+zsbai@users.noreply.github.com>
Date: Thu, 12 Feb 2026 21:39:14 +0000
Subject: [PATCH] refactor: rewrite in Python (#7)
* refactor: rewrite destVersionForMac in python; remove redundant code & files; new workflow parameter: Force create release using latest WeChat dmg;
* misc: update README file;
---
.github/workflows/destversion.yml | 11 +-
.github/workflows/notify.yml | 18 --
.gitignore | 2 +
README.md | 28 +-
scripts/destVersionForMac.py | 491 ++++++++++++++++++++++++++++++
scripts/destVersionForMac.sh | 221 --------------
scripts/notify.sh | 84 -----
7 files changed, 514 insertions(+), 341 deletions(-)
delete mode 100644 .github/workflows/notify.yml
create mode 100644 scripts/destVersionForMac.py
delete mode 100644 scripts/destVersionForMac.sh
delete mode 100755 scripts/notify.sh
diff --git a/.github/workflows/destversion.yml b/.github/workflows/destversion.yml
index 4697395..453f33f 100644
--- a/.github/workflows/destversion.yml
+++ b/.github/workflows/destversion.yml
@@ -4,15 +4,20 @@ on:
schedule:
- cron: '0 7 * * *'
workflow_dispatch:
+ inputs:
+ force_release:
+ description: 'Force create release (ignore version checks)'
+ type: boolean
+ default: false
jobs:
save_new_wechat:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v2
- # - name: Test Github Action Server Time
- # run: echo `date`
+
- name: Check new version and push
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: bash -x ./scripts/destVersionForMac.sh ${{ github.event.inputs.download_link }}
+ FORCE_RELEASE: ${{ github.event.inputs.force_release }}
+ run: python3 ./scripts/destVersionForMac.py
diff --git a/.github/workflows/notify.yml b/.github/workflows/notify.yml
deleted file mode 100644
index 663bc79..0000000
--- a/.github/workflows/notify.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Wechat Release Notify
-
-on:
- release:
- types: [published]
-
-
-jobs:
- notify_to_tg:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Check new version and push
- env:
- GHTOKEN: ${{ secrets.GHTOKEN }}
- BOTTOKEN: ${{ secrets.BOTTOKEN }}
- CHATIDS: ${{ secrets.CHATIDS }}
- run: bash -x ./scripts/notify.sh
diff --git a/.gitignore b/.gitignore
index 8ab55c2..655b485 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+temp/
+
################################################################################
# This below was automatically created for macOS system
################################################################################
diff --git a/README.md b/README.md
index c7aeb08..69f38f6 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,21 @@
-# Wechat-Versions-For-macOS
-收集 Mac 微信版本并保存
+# Wechat For Macos Version Archive
+收集官网 Mac 微信版本并保存至release。
-## 目录结构
-```shell
-├── README.md # 自述文件
-├── WeChatSetup # 微信安装包临时目录
-│ └── temp # 临时目录
-└── scripts # 脚本目录
- ├── destVersioForMac.sh # 获取安装包及取得版本号与 hash 值的脚本
- └── notify.sh # 新release 时调用通知的脚本
-```
+## 更新日志
+* 2026.2.12:使用python重写脚本,移除冗余文件和代码。在`4.0.5`版本后,之前获取精确版本号的规则失效,目前已修复;未来如果继续出现无法获取精确版本号则会自动采用大版本+build的形式(如`v4.0.0+build.12345`)。
-## 说明
+* 2024.10.1:通过转换dmg为img后解压,获取精确的微信版本号(例如:3.8.9.xx);在此之前,后两位小版本号无法获取,所以通过添加更新日期后缀来区分大版本中的小版本,需在下载前自行判断。
-* 2024.10.1 更新:通过转换dmg为img后解压,获取精确的微信版本号(例如:3.8.9.xx);在此之前,后两位小版本号无法获取,所以通过添加更新日期后缀来区分大版本中的小版本,需在下载前自行判断。
-
-项目使用 Github Action 自动下载微信**官网最新版本安装包**计算 Hash 值并推送至仓库 Release,目前暂无保留App Store安装包的想法。
+项目使用 Github Action 每天自动检测微信**官网新版本更新**,计算 Hash/MD5 值并推送至仓库 Release。
+项目仅抓取官网的Mac安装包,并不包含App Store中的版本。
各版本更新日志可参见官网 [changelog](https://weixin.qq.com/cgi-bin/readtemplate?lang=zh_CN&t=weixin_faq_list&head=true)
+相关项目:
+- [微信 Windows 64 位 3.0 版本存档](https://github.com/tom-snow/wechat-windows-versions)
+- [微信 Windows 32 位 3.0 版本存档](https://github.com/tom-snow/wechat-windows-versions-x86)
+- [微信 Mac 3.0 & 4.0 版本存档](https://github.com/zsbai/wechat-versions)
+
+
*如有问题/侵权,请直接提交 issue 告知。*
diff --git a/scripts/destVersionForMac.py b/scripts/destVersionForMac.py
new file mode 100644
index 0000000..d67770e
--- /dev/null
+++ b/scripts/destVersionForMac.py
@@ -0,0 +1,491 @@
+#!/usr/bin/env python3
+
+import datetime
+import hashlib
+import html.parser
+import os
+import plistlib
+import re
+import shutil
+import subprocess
+import sys
+import time
+import urllib.request
+from pathlib import Path
+
+WEBSITE_URL = "https://mac.weixin.qq.com/?t=mac&lang=zh_CN"
+BASE_DIR = Path.cwd() / "WeChatMac"
+TEMP_DIR = BASE_DIR / "temp"
+
+class DownloadLinkParser(html.parser.HTMLParser):
+ """
+ 从微信 Mac 官方网站的 HTML 中解析下载链接。
+ """
+
+ def __init__(self) -> None:
+ super().__init__()
+ self.link = ""
+
+ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
+ if tag != "a" or self.link:
+ return
+ attrs_dict = {key: value or "" for key, value in attrs}
+ classes = attrs_dict.get("class", "").split()
+ if "download-button" in classes:
+ self.link = attrs_dict.get("href", "").strip()
+
+def run(
+ cmd: list[str], check: bool = True, capture: bool = True
+) -> subprocess.CompletedProcess:
+ """
+ 运行子进程命令的辅助函数,默认捕获输出并检查返回码。
+
+ Args:
+ cmd (list[str]): 要执行的命令列表。
+ check (bool, optional): 是否检查命令返回码。默认为 True。
+ capture (bool, optional): 是否捕获命令输出。默认为 True。
+
+ Returns:
+ subprocess.CompletedProcess: 子进程执行结果。
+ """
+ return subprocess.run(
+ cmd,
+ check=check,
+ text=True,
+ stdout=subprocess.PIPE if capture else None,
+ stderr=subprocess.STDOUT if capture else None,
+ )
+
+def log(message: str) -> None:
+ """
+ 打印日志信息并立即刷新输出缓冲区。
+
+ Args:
+ message (str): 要打印的日志信息。
+ """
+ print(message, flush=True)
+
+def fetch_download_link() -> str:
+ """
+ 从微信 Mac 官方网站获取最新的下载链接
+
+ Raises:
+ RuntimeError: 如果在网站上未找到下载链接
+
+ Returns:
+ str: 下载链接 URL
+ """
+ # Fetch HTML and extract the first download link on the page.
+ with urllib.request.urlopen(WEBSITE_URL, timeout=30) as response:
+ html = response.read().decode("utf-8", errors="replace")
+ parser = DownloadLinkParser()
+ parser.feed(html)
+ if not parser.link:
+ raise RuntimeError("Download link not found on website.")
+ return parser.link
+
+def fetch_head_metadata(url: str) -> dict[str, str]:
+ """
+ 使用 HEAD 请求从直接文件链接读取元数据。
+ Args:
+ url (str): 文件的直接下载链接
+ Returns:
+ dict[str, str]: 从 HEAD 响应中提取的元数据字典,键为小写字符串,值为对应的响应头值
+ """
+
+ # Use HEAD request to read metadata from the direct file link.
+ request = urllib.request.Request(url, method="HEAD")
+ with urllib.request.urlopen(request, timeout=30) as response:
+ return {key.lower(): value.strip() for key, value in response.headers.items()}
+
+def download_with_retry(url: str, dest: Path) -> None:
+ """
+ 下载软件包
+
+ Args:
+ url (str): 文件的直接下载链接
+ dest (Path): 目标文件路径
+ """
+ # Keep temp files under current working directory for debugging.
+ dest.parent.mkdir(parents=True, exist_ok=True)
+ attempts = 2
+ last_error: Exception | None = None
+ for attempt in range(1, attempts + 1):
+ try:
+ run(
+ [
+ "wget",
+ "--quiet",
+ "--tries",
+ "5",
+ "--waitretry",
+ "5",
+ "--retry-connrefused",
+ "--timeout",
+ "30",
+ url,
+ "-O",
+ str(dest),
+ ]
+ )
+ return
+ except Exception as exc:
+ last_error = exc
+ if attempt < attempts:
+ log(f"Download failed (attempt {attempt}). Waiting before retry...")
+ time.sleep(10)
+ if last_error:
+ raise last_error
+
+def mount_dmg(dmg_path: Path) -> str:
+ """
+ 挂载目标 dmg 镜像到本地
+
+ Args:
+ dmg_path (Path): dmg 镜像文件路径
+
+ Raises:
+ RuntimeError: 如果挂载失败或未找到挂载点
+
+ Returns:
+ str: 挂载点路径
+ """
+ # Mount DMG and capture the mount point under /Volumes.
+ result = run(["hdiutil", "attach", str(dmg_path), "-nobrowse"])
+ matches = re.findall(r"(/Volumes/[^\n]+)", result.stdout)
+ if not matches:
+ raise RuntimeError("Failed to mount DMG.")
+ return matches[-1].strip()
+
+def detach_dmg(mount_dir: str) -> None:
+ """
+ 解除挂载对应目录
+
+ Args:
+ mount_dir (str): 挂载点路径
+ """
+ run(["hdiutil", "detach", mount_dir], check=False)
+
+def get_tag_from_plist(mount_dir: str) -> str:
+ """
+ 解析 Info.plist 构建 Tag 标签
+
+ 如果 WeChatBundleVersion 存在则直接使用,否则使用 CFBundleShortVersionString 和 CFBundleVersion 组合的形式。
+
+ Args:
+ mount_dir (str): 挂载路径
+
+ Raises:
+ RuntimeError: 如果 Info.plist 文件未找到
+ RuntimeError: 如果 CFBundleShortVersionString 未找到
+ RuntimeError: 如果 CFBundleVersion 未找到
+
+ Returns:
+ str: 构建标签
+ """
+ # Info.plist lives inside the mounted WeChat.app bundle.
+ info_plist = Path(mount_dir) / "WeChat.app" / "Contents" / "Info.plist"
+ if not info_plist.exists():
+ raise RuntimeError("Info.plist not found in mounted volume.")
+ with info_plist.open("rb") as handle:
+ data = plistlib.load(handle)
+ short_version = str(data.get("CFBundleShortVersionString", "")).strip()
+ build = str(data.get("CFBundleVersion", "")).strip()
+ version = str(data.get("WeChatBundleVersion", "")).strip()
+
+ if not short_version:
+ raise RuntimeError("CFBundleShortVersionString not found.")
+ if not build:
+ raise RuntimeError("CFBundleVersion not found.")
+ if version:
+ tag = version
+ else:
+ tag = f"{short_version}+build.{build}"
+ return tag
+
+def compute_sha256(file_path: Path) -> str:
+ """
+ 计算文件的 sha256
+
+ Args:
+ file_path (Path): 文件路径
+
+ Returns:
+ str: 文件的 sha256 值
+ """
+ digest = hashlib.sha256()
+ with file_path.open("rb") as handle:
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
+ digest.update(chunk)
+ return digest.hexdigest()
+
+def parse_release_body(body: str) -> dict[str, str]:
+ """
+ 从 GitHub release 的 body 文本中解析出键值对信息,返回一个字典。
+
+ Args:
+ body (str): GitHub release 的 body 文本,预期包含多行 "Key: Value" 格式的内容。
+
+ Returns:
+ dict[str, str]: 从 body 中解析出的键值对字典.
+ """
+ info: dict[str, str] = {}
+ for line in body.splitlines():
+ if ":" not in line:
+ continue
+ key, value = line.split(":", 1)
+ info[key.lstrip("- ").strip()] = value.strip()
+ return info
+
+def get_latest_release_info() -> dict[str, str]:
+ """
+ 获取最新 GitHub release 的信息,返回一个包含键值对的字典。
+
+ Returns:
+ dict[str, str]: 包含最新 release 信息的字典
+ """
+ result = run(
+ ["gh", "release", "view", "--json", "body", "--jq", ".body"], check=False
+ )
+ if result.returncode != 0 or not result.stdout:
+ return {}
+ return parse_release_body(result.stdout)
+
+def tag_exists(tag: str) -> bool:
+ """
+ 检查指定的 Git 标签是否已经存在于远程仓库中。
+
+ Args:
+ tag (str): Git 标签名称
+
+ Returns:
+ bool: 指定的 Git 标签是否存在
+ """
+ result = run(["gh", "release", "view", tag, "--json", "tagName"], check=False)
+ return result.returncode == 0
+
+def build_release_notes(
+ tag: str,
+ download_link: str,
+ remote_md5: str,
+ sha256_sum: str,
+ remote_size: str,
+ remote_last_modified: str,
+) -> str:
+ """
+ 构建 Release 发布信息
+
+ Args:
+ tag (str): 构建版本号
+ download_link (str): 下载链接
+ remote_md5 (str): 远端md5的值
+ sha256_sum (str): sha256的值
+ remote_size (str): 文件大小
+ remote_last_modified (str): 最后修改时间
+
+ Returns:
+ str: 最终的发布信息
+ """
+ lines = [
+ "WeChat for Mac automatic release",
+ "",
+ "Download and integrity details are below.",
+ "",
+ "Release details",
+ f"- DestVersion: {tag}",
+ "",
+ "Source and checksums",
+ f"- DownloadFrom: {download_link}",
+ f"- Md5: {remote_md5}",
+ f"- Sha256: {sha256_sum}",
+ ]
+ if remote_size:
+ lines.append(f"- ContentLength: {remote_size}")
+ if remote_last_modified:
+ lines.append(f"- LastModified: {remote_last_modified}")
+ return "\n".join(lines) + "\n"
+
+def write_sha_file(
+ sha_file: Path,
+ tag: str,
+ download_link: str,
+ sha256_sum: str,
+ remote_md5: str,
+ remote_size: str,
+ remote_last_modified: str,
+) -> None:
+ """
+ 写入 SHA 文件
+
+ Args:
+ sha_file (Path): SHA 文件路径
+ tag (str): 构建标签
+ download_link (str): 下载链接
+ sha256_sum (str): sha256的值
+ remote_md5 (str): 远端md5的值
+ remote_size (str): 文件大小
+ remote_last_modified (str): 最后修改时间
+ """
+ timestamp = datetime.datetime.now(datetime.timezone.utc).strftime(
+ "%Y-%m-%d %H:%M:%S"
+ )
+ lines = [
+ f"DestVersion: {tag}",
+ f"Md5: {remote_md5}",
+ f"Sha256: {sha256_sum}",
+ ]
+ if remote_size:
+ lines.append(f"ContentLength: {remote_size}")
+ if remote_last_modified:
+ lines.append(f"LastModified: {remote_last_modified}")
+ lines.extend(
+ [
+ f"UpdateTime: {timestamp} (UTC)",
+ f"DownloadFrom: {download_link}",
+ ]
+ )
+ sha_file.write_text("\n".join(lines) + "\n", encoding="utf-8")
+
+def main() -> int:
+ BASE_DIR.mkdir(parents=True, exist_ok=True)
+ TEMP_DIR.mkdir(parents=True, exist_ok=True)
+
+ mount_dir = ""
+ try:
+ force_release = os.environ.get("FORCE_RELEASE", "").strip().lower() in {
+ "1",
+ "true",
+ "yes",
+ "on",
+ }
+ log(f"Force release: {'true' if force_release else 'false'}")
+
+ # Step 1: resolve download link from website.
+ log("Resolving download link from website...")
+ download_link = fetch_download_link()
+ log(f"Download link: {download_link}")
+
+ # Step 2: read metadata from HEAD response.
+ log("Fetching HEAD metadata...")
+ headers = fetch_head_metadata(download_link)
+ remote_md5 = headers.get("x-cos-meta-md5", "")
+ remote_size = headers.get("content-length", "")
+ remote_last_modified = headers.get("last-modified", "")
+ log(
+ "HEAD metadata: "
+ f"md5={remote_md5 or 'n/a'}, "
+ f"size={remote_size or 'n/a'}, "
+ f"last_modified={remote_last_modified or 'n/a'}"
+ )
+
+ # Step 3: compare with latest release by MD5 to avoid downloads.
+ log("Fetching latest GitHub release info...")
+ latest_info = get_latest_release_info()
+ latest_md5 = latest_info.get("Md5", "")
+ latest_sha256 = latest_info.get("Sha256", "")
+ log(
+ "Latest release: "
+ f"md5={latest_md5 or 'n/a'}, "
+ f"sha256={latest_sha256 or 'n/a'}"
+ )
+
+ if remote_md5 and latest_md5 and remote_md5 == latest_md5:
+ if force_release:
+ log("MD5 matches latest release, but force release is enabled.")
+ else:
+ log("No new version detected by MD5. Skipping download.")
+ return 0
+
+ # Step 4: download DMG with retry.
+ log("Downloading DMG...")
+ dmg_path = TEMP_DIR / "WeChatMac.dmg"
+ download_with_retry(download_link, dmg_path)
+ log(f"Downloaded DMG to {dmg_path}")
+
+ # Step 5: mount DMG and read plist values.
+ log("Mounting DMG and reading Info.plist...")
+ mount_dir = mount_dmg(dmg_path)
+ tag = get_tag_from_plist(mount_dir)
+ detach_dmg(mount_dir)
+ mount_dir = ""
+ log(f"Detected tag: {tag}")
+
+ # Step 6: prepare release assets in workspace.
+ log("Preparing release assets...")
+ version_dir = BASE_DIR / tag
+ version_dir.mkdir(parents=True, exist_ok=True)
+ final_dmg = version_dir / f"WeChatMac-{tag}.dmg"
+ shutil.copy2(dmg_path, final_dmg)
+
+ sha256_sum = compute_sha256(final_dmg)
+ log(f"Computed SHA256: {sha256_sum}")
+ sha_file = version_dir / f"WeChatMac-{tag}.dmg.sha256"
+ write_sha_file(
+ sha_file,
+ tag,
+ download_link,
+ sha256_sum,
+ remote_md5,
+ remote_size,
+ remote_last_modified,
+ )
+
+ if not latest_md5 and latest_sha256 and sha256_sum == latest_sha256:
+ if force_release:
+ log("SHA256 matches latest release, but force release is enabled.")
+ else:
+ log("No new version detected by SHA256. Skipping release.")
+ return 0
+ if not latest_md5:
+ log("Latest release has no MD5, used SHA256 fallback check.")
+
+ if tag_exists(tag):
+ suffix = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%d")
+ tag = f"{tag}_{suffix}"
+ log(f"Release tag: {tag}")
+
+ title = f"Wechat For Mac {tag}"
+ notes_content = build_release_notes(
+ tag,
+ download_link,
+ remote_md5,
+ sha256_sum,
+ remote_size,
+ remote_last_modified,
+ )
+ notes_file = TEMP_DIR / "release_notes.txt"
+ notes_file.write_text(notes_content, encoding="utf-8")
+ log(f"Release notes written to {notes_file}")
+
+ # Step 7: publish release with assets and notes.
+ log("Creating GitHub release...")
+ run(
+ [
+ "gh",
+ "release",
+ "create",
+ tag,
+ str(final_dmg),
+ str(sha_file),
+ "-F",
+ str(notes_file),
+ "-t",
+ title,
+ ]
+ )
+ log("GitHub release created.")
+
+ return 0
+ finally:
+ # Always detach and cleanup to keep workspace tidy.
+ if mount_dir:
+ detach_dmg(mount_dir)
+ shutil.rmtree(BASE_DIR, ignore_errors=True)
+ log("Cleanup completed.")
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except Exception as exc:
+ print(f"Error: {exc}", file=sys.stderr)
+ sys.exit(1)
diff --git a/scripts/destVersionForMac.sh b/scripts/destVersionForMac.sh
deleted file mode 100644
index b40a163..0000000
--- a/scripts/destVersionForMac.sh
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/usr/bin/env bash
-
-set -eo pipefail
-
-# ====================================================
-# 配置变量
-# ====================================================
-TEMP_PATH="WeChatMac/temp"
-WEBSITE_URL="https://mac.weixin.qq.com/?t=mac&lang=zh_CN"
-DOWNLOAD_LINK=""
-
-# ====================================================
-# 函数定义
-# ====================================================
-
-# 打印分隔线
-print_separator() {
- printf '%*s\n' 60 | tr ' ' '#'
-}
-
-# 彩色输出函数
-echo_color() {
- local color="$1"
- shift
- local message="$*"
- case "$color" in
- yellow)
- echo -e "\033[1;33m$message\033[0m"
- ;;
- red)
- echo -e "\033[1;31m$message\033[0m" >&2
- ;;
- green)
- echo -e "\033[1;32m$message\033[0m"
- ;;
- *)
- echo "$message"
- ;;
- esac
-}
-
-# 安装依赖项
-install_depends() {
- print_separator
- echo_color "yellow" "Installing dependencies: wget, curl, git, gh, shasum, pup"
- print_separator
-
- brew install wget curl git gh pup
-}
-
-# 下载 WeChat DMG
-download_wechat() {
- DOWNLOAD_LINK=$(curl -s "$WEBSITE_URL" | pup 'a.download-button:nth-of-type(1) attr{href}')
-
- print_separator
- echo_color "yellow" "Downloading the newest WeChatMac..."
- print_separator
-
- mkdir -p "$TEMP_PATH"
-
- wget -q "$DOWNLOAD_LINK" -O "${TEMP_PATH}/WeChatMac.dmg"
- if [ "$?" -ne 0 ]; then
- echo_color "red" "Download Failed, please check your network!"
- clean_data 1
- fi
-}
-
-# 从 Info.plist 提取版本信息
-get_version() {
- print_separator
- echo_color "yellow" "Extracting version from DMG (macOS)..."
- print_separator
-
- # 挂载 dmg
- MOUNT_DIR=$(hdiutil attach "${TEMP_PATH}/WeChatMac.dmg" -nobrowse | sed -n 's/^.*\(\/Volumes\/.*\)$/\1/p' | tail -n1)
-
- if [ -z "$MOUNT_DIR" ]; then
- echo_color "red" "Failed to mount DMG!"
- clean_data 1
- fi
-
- # 定位 Info.plist
- # INFO_PLIST=$(find "${MOUNT_DIR}" -type f -name "Info.plist" | head -n 1)
- INFO_PLIST="${MOUNT_DIR}/WeChat.app/Contents/Info.plist"
-
- if [ ! -f "$INFO_PLIST" ]; then
- echo_color "red" "Info.plist not found in mounted volume!"
- hdiutil detach "$MOUNT_DIR"
- clean_data 1
- fi
-
- # 使用 grep 和 sed 提取版本号
- VERSION=$(grep -A1 'CFBundleShortVersionString' "$INFO_PLIST" | grep '' | sed -E 's/.*([^<]+)<\/string>.*/\1/')
-
- # 使用 grep 和 sed 提取构建版本号
- BUILD_VERSION=$(grep -A1 'CFBundleVersion' "$INFO_PLIST" | grep '' | sed -E 's/.*([^<]+)<\/string>.*/\1/')
-
- # 卸载 dmg
- hdiutil detach "$MOUNT_DIR"
-
- if [ -z "$VERSION" ]; then
- echo_color "red" "Version information not found in Info.plist!"
- clean_data 1
- fi
-
- echo "Version: $VERSION"
-}
-
-
-# 计算 SHA256
-compute_sha256() {
- local file_path="$1"
- shasum -a 256 "$file_path" | awk '{print $1}'
-}
-
-# 准备提交(复制 DMG 并创建 .sha256 文件)
-prepare_commit() {
- print_separator
- echo_color "yellow" "Preparing to commit new version..."
- print_separator
-
- VERSION_DIR="WeChatMac/$VERSION"
- mkdir -p "$VERSION_DIR"
-
- cp "${TEMP_PATH}/WeChatMac.dmg" "$VERSION_DIR/WeChatMac-$VERSION.dmg"
-
- NOW_SUM256=$(compute_sha256 "$VERSION_DIR/WeChatMac-$VERSION.dmg")
-
- cat > "$VERSION_DIR/WeChatMac-$VERSION.dmg.sha256" <&2 echo -e "\033[1;31mMissing Github Token(GHTOKEN)! Please get a BotToken from 'Github Settings->Developer settings->Personal access tokens' and set it in Repo Secrect\033[0m"
- exit 1
-fi
-
-if [ -z $BOTTOKEN ]; then
- >&2 echo -e "\033[1;31mMissing Bot Token(BOTTOKEN)! Please get a BotToken from @Botfather on Telegram and set it in Repo Secrect\033[0m"
- exit 2
-fi
-
-if [ -z $CHATIDS ]; then
- >&2 echo -e "\033[1;31mMissing ChatIds(CHATIDS)! Please get ChatId from @GroupIDbot on Telegram Chats(Muti chatids split with comma ',') and set it in Repo Environment Values\033[0m"
- exit 2
-fi
-
-function login_gh() {
- printf "#%.0s" {1..60}
- echo
- echo -e "## \033[1;33mLogin to github to use github-cli...\033[0m"
- printf "#%.0s" {1..60}
- echo
-
- echo $GHTOKEN > WeChatSetup/temp/GHTOKEN
- gh auth login --with-token < WeChatSetup/temp/GHTOKEN
- if [ "$?" -ne 0 ]; then
- >&2 echo -e "\033[1;31mLogin Failed, please check your network or token!\033[0m"
- clean_data 1
- fi
- rm -rfv WeChatSetup/temp/GHTOKEN
-}
-
-### https://kodango.com/sed-and-awk-notes-part-5
-## start=${1:-""} means as follows in general
-## if ($1) then
-## start=$1
-## else
-## start=""
-## end
-function join_lines() {
- local delim=${1:-,}
- sed 'H;$!d;${x;s/^\n//;s/\n/\'$delim'/g}'
-}
-
-function clean_data() {
- printf "#%.0s" {1..60}
- echo
- echo -e "## \033[1;33mClean runtime and exit...\033[0m"
- printf "#%.0s" {1..60}
- echo
-
- rm -rfv WeChatSetup/*
- exit $1
-}
-
-function main() {
- temp_path="WeChatSetup/temp"
- mkdir -p ${temp_path}
-
- login_gh
-
- gh release view --json body --jq ".body" > ${temp_path}/release.info
-
- release_info=`awk '!/^$|Sha256/ { $1="*"$1"*";sub("UpdateTime", "CheckTime"); if ( match($2, /https?:\/\/([\w\.\/:])*/) ) $2="[Url]("$2")"; print $0 }' ${temp_path}/release.info | join_lines '%0A' | sed 's/ /%20/g'`
- dest_version=`awk '/DestVersion/ { print $2 }' ${temp_path}/release.info`
- release_info="$release_info%0A%0A*NotifyFrom:*%20[Github](https://github.com/tom-snow/wechat-windows-versions/releases/tag/v$dest_version)"
-
- echo $CHATIDS | sed 's/,/\n/g' > ${temp_path}/chat_ids
- # while IFS="" read -r chatid || [ -n "$chatid" ]
- while IFS="" read -r chatid
- do
- api_link="https://api.telegram.org/bot$BOTTOKEN/sendMessage?chat_id=$chatid&text=*New%20WeChat%20Windows%20Version!!*%0A%0A$release_info&parse_mode=Markdown&disable_web_page_preview=true"
- curl -s -o /dev/null $api_link
- done < ${temp_path}/chat_ids
-
- gh auth logout --hostname github.com | echo "y"
- clean_data 0
-}
-
-main
\ No newline at end of file