summaryrefslogtreecommitdiff
path: root/raveos-center/raveos_center/proton.py
blob: bff9649c7d14c99b6c707de6c5f9897faa57ee88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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)