获取指定 GitHub 仓库 Release 中首个符合是否预发布要求,且匹配所有关键字的资源下载链接和文件名。 https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#list-releases
(
repo: str, keywords: list[str], prerelease: bool = True
)
| 219 | |
| 220 | |
| 221 | def get_latest_release_url( |
| 222 | repo: str, keywords: list[str], prerelease: bool = True |
| 223 | ) -> tuple[str | None, str | None, str | None]: |
| 224 | """ |
| 225 | 获取指定 GitHub 仓库 Release 中首个符合是否预发布要求,且匹配所有关键字的资源下载链接和文件名。 |
| 226 | |
| 227 | https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#list-releases |
| 228 | """ |
| 229 | api_url = f"https://api.github.com/repos/{repo}/releases" |
| 230 | token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN") |
| 231 | |
| 232 | try: |
| 233 | print(Console.info(t("inf_get_latest_release", repo=repo))) |
| 234 | |
| 235 | req = urllib.request.Request(api_url) |
| 236 | if token: |
| 237 | req.add_header("Authorization", f"Bearer {token}") |
| 238 | req.add_header("Accept", "application/vnd.github+json") |
| 239 | req.add_header("User-Agent", "MaaEnd-setup") |
| 240 | req.add_header("X-GitHub-Api-Version", "2022-11-28") |
| 241 | |
| 242 | with urllib.request.urlopen(req, timeout=TIMEOUT) as res: |
| 243 | tags = json.loads(res.read().decode()) |
| 244 | assert isinstance(tags, list) |
| 245 | if not tags: |
| 246 | raise ValueError("No releases found (GitHub API)") |
| 247 | |
| 248 | for tag in tags: |
| 249 | assert isinstance(tag, dict) |
| 250 | if ( |
| 251 | not prerelease |
| 252 | and tag.get("prerelease", False) |
| 253 | or tag.get("draft", False) |
| 254 | ): |
| 255 | continue |
| 256 | assets = tag.get("assets", []) |
| 257 | assert isinstance(assets, list) |
| 258 | |
| 259 | for asset in assets: |
| 260 | assert isinstance(asset, dict) |
| 261 | name = asset["name"].lower() |
| 262 | if all(k.lower() in name for k in keywords): |
| 263 | print(Console.ok(t("inf_matched_asset", name=asset["name"]))) |
| 264 | tag_name = tag.get("tag_name") or tag.get("name") |
| 265 | return asset["browser_download_url"], asset["name"], tag_name |
| 266 | |
| 267 | raise ValueError("No matching asset found in the latest release (GitHub API)") |
| 268 | except Exception as e: |
| 269 | print(Console.err(t("err_get_release_failed", error_type=type(e).__name__, error=e))) |
| 270 | |
| 271 | return None, None, None |
| 272 | |
| 273 | |
| 274 | def read_versions_file(path: Path) -> dict[str, str]: |