85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
#
|
||
# Erminig - Récupération de la dernière version d'un soft sur Github via son API
|
||
# Copyright (C) 2025 L0m1g
|
||
# Sous licence DOUARN - Voir le fichier LICENCE pour les détails
|
||
#
|
||
# Ce fichier fait partie du projet Erminig.
|
||
# Libre comme l’air, stable comme un menhir, et salé comme le beurre.
|
||
#
|
||
|
||
import re
|
||
import requests
|
||
from erminig.config import Config
|
||
from erminig.controllers.evezh.abstract import UpstreamSource
|
||
from erminig.system.retry import retry_on_failure
|
||
|
||
|
||
class GitHubSource(UpstreamSource):
|
||
|
||
@retry_on_failure()
|
||
def get_latest(self):
|
||
repo = self.config["github"]
|
||
file_template = self.config.get("file")
|
||
|
||
latest = self._get_latest_release(repo)
|
||
if not latest:
|
||
latest = self._get_latest_tag(repo)
|
||
if not latest:
|
||
print(f"[{self.name}] Aucune version détectée.")
|
||
return None
|
||
|
||
version = self.normalize_version(latest["tag"])
|
||
url = latest.get("url")
|
||
|
||
if not url and file_template:
|
||
filename = file_template.replace("${version}", version)
|
||
url = f"https://github.com/{repo}/releases/download/{latest['tag']}/{filename}"
|
||
print(f"[{self.name}] Fallback URL : {url}")
|
||
|
||
print(url)
|
||
return {"name": self.name, "version": version, "url": url or ""}
|
||
|
||
def _github_headers(self):
|
||
headers = {}
|
||
if Config.GITHUB_TOKEN:
|
||
headers["Authorization"] = f"token {Config.GITHUB_TOKEN}"
|
||
return headers
|
||
|
||
def _get_latest_release(self, repo):
|
||
r = requests.get(
|
||
f"https://api.github.com/repos/{repo}/releases",
|
||
headers=self._github_headers(),
|
||
)
|
||
r.raise_for_status()
|
||
data = r.json()
|
||
if not data:
|
||
return None
|
||
|
||
release = data[0]
|
||
for asset in release.get("assets", []):
|
||
if asset["browser_download_url"].endswith(".tar.gz"):
|
||
return {
|
||
"tag": release["tag_name"],
|
||
"url": asset["browser_download_url"],
|
||
}
|
||
return {"tag": release["tag_name"]}
|
||
|
||
def _get_latest_tag(self, repo):
|
||
r = requests.get(
|
||
f"https://api.github.com/repos/{repo}/tags", headers=self._github_headers()
|
||
)
|
||
r.raise_for_status()
|
||
tags = r.json()
|
||
if not tags:
|
||
return None
|
||
url = f"https://github.com/{repo}/archive/refs/tags/{tags[0]["name"]}.tar.gz"
|
||
return {"tag": tags[0]["name"], "url": url}
|
||
|
||
def normalize_version(self, tag):
|
||
# Exemples : v2.7.1 → 2.7.1, R_2_7_1 → 2.7.1, expat-2.7.1 → 2.7.1
|
||
tag = tag.strip()
|
||
if tag.lower().startswith(("v", "r_", "r")):
|
||
tag = re.sub(r"^[vVrR_]+", "", tag)
|
||
tag = tag.replace("_", ".")
|
||
match = re.search(r"(\d+\.\d+(?:\.\d+)?)", tag)
|
||
return match.group(1) if match else tag
|