diff options
Diffstat (limited to 'raveos-center/raveos_center/proton.py')
| -rw-r--r-- | raveos-center/raveos_center/proton.py | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/proton.py b/raveos-center/raveos_center/proton.py new file mode 100644 index 0000000..bff9649 --- /dev/null +++ b/raveos-center/raveos_center/proton.py @@ -0,0 +1,125 @@ +import hashlib +import json +import re +import shutil +import tarfile +import tempfile +import urllib.request +from pathlib import Path + +from raveos_center import VERZIO + +KIADAS = "https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest" +STEAM_HELYEK = [ + Path.home() / ".steam" / "root", + Path.home() / ".local" / "share" / "Steam", + Path.home() / ".var" / "app" / "com.valvesoftware.Steam" / "data" / "Steam", +] +NEV_MINTA = re.compile(r"^GE-Proton([0-9]+)-([0-9]+)(-x86_64)?$") +FEJLEC = {"User-Agent": f"RaveOS-Center/{VERZIO}"} + + +def celmappak(): + lista = [] + latott = set() + for hely in STEAM_HELYEK: + if not hely.is_dir(): + continue + valodi = hely.resolve() + if valodi in latott: + continue + latott.add(valodi) + lista.append(valodi / "compatibilitytools.d") + return lista + + +def _sorrend(nevek): + return sorted(nevek, key=lambda n: [int(x) for x in NEV_MINTA.match(n).groups()[:2]], reverse=True) + + +def _mappaban(mappa): + if not mappa.is_dir(): + return [] + return _sorrend(p.name for p in mappa.iterdir() if p.is_dir() and not p.is_symlink() and NEV_MINTA.match(p.name)) + + +def telepitett(): + nevek = set() + for mappa in celmappak(): + nevek.update(_mappaban(mappa)) + return _sorrend(nevek) + + +def regiek(): + return [(mappa, nev) for mappa in celmappak() for nev in _mappaban(mappa)[1:]] + + +def _lekeres(url, ido=30): + return urllib.request.urlopen(urllib.request.Request(url, headers=FEJLEC), timeout=ido) + + +def legujabb(): + with _lekeres(KIADAS) as valasz: + adat = json.load(valasz) + nev = adat.get("tag_name", "") + if not NEV_MINTA.match(nev): + raise RuntimeError("ismeretlen kiadásnév") + eszkozok = {e["name"]: e for e in adat.get("assets", [])} + for mappa in (f"{nev}-x86_64", nev): + tar = eszkozok.get(f"{mappa}.tar.gz") + osszeg = eszkozok.get(f"{mappa}.sha512sum") + if tar and osszeg: + return { + "nev": mappa, + "url": tar["browser_download_url"], + "meret": tar.get("size", 0), + "osszeg_url": osszeg["browser_download_url"], + } + raise RuntimeError("a kiadásból hiányzik a csomag vagy az ellenőrzőösszeg") + + +def telepit(kiadas, haladas): + mappak = celmappak() + if not mappak: + raise RuntimeError("nem található Steam, előbb indítsd el egyszer a Steamet") + with _lekeres(kiadas["osszeg_url"]) as valasz: + vart = valasz.read().decode().split()[0].lower() + if not re.fullmatch(r"[0-9a-f]{128}", vart): + raise RuntimeError("érvénytelen ellenőrzőösszeg") + mappak[0].mkdir(parents=True, exist_ok=True) + with tempfile.NamedTemporaryFile(dir=mappak[0], suffix=".tar.gz") as ideiglenes: + hasito = hashlib.sha512() + letoltve = 0 + with _lekeres(kiadas["url"], 60) as valasz: + while darab := valasz.read(1 << 20): + ideiglenes.write(darab) + hasito.update(darab) + letoltve += len(darab) + if kiadas["meret"]: + haladas(min(90, int(letoltve * 90 / kiadas["meret"]))) + ideiglenes.flush() + if hasito.hexdigest() != vart: + raise RuntimeError("a letöltött fájl ellenőrzőösszege nem egyezik") + for mappa in mappak: + mappa.mkdir(parents=True, exist_ok=True) + cel = mappa / kiadas["nev"] + if cel.is_symlink() or cel.is_file(): + cel.unlink() + elif cel.exists(): + shutil.rmtree(cel) + with tarfile.open(ideiglenes.name, "r:gz") as tar: + tagok = tar.getmembers() + if any(t.name != kiadas["nev"] and not t.name.startswith(kiadas["nev"] + "/") for t in tagok): + raise RuntimeError("váratlan tartalom a csomagban") + tar.extractall(mappa, members=tagok, filter="data") + haladas(100) + return kiadas["nev"] + + +def torol(nev, mappak=None): + if not NEV_MINTA.match(nev): + raise ValueError("érvénytelen név") + for mappa in mappak or celmappak(): + cel = mappa / nev + if cel.is_dir() and not cel.is_symlink(): + shutil.rmtree(cel) |