diff options
Diffstat (limited to 'raveos-center/raveos_center/rendszerinfo.py')
| -rw-r--r-- | raveos-center/raveos_center/rendszerinfo.py | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/rendszerinfo.py b/raveos-center/raveos_center/rendszerinfo.py new file mode 100644 index 0000000..b526670 --- /dev/null +++ b/raveos-center/raveos_center/rendszerinfo.py @@ -0,0 +1,240 @@ +import json +import os +import platform +import re +import shutil +import subprocess +import threading +import time +from pathlib import Path + + +def _futtat(parancs, ido=60): + try: + kimenet = subprocess.run(parancs, capture_output=True, text=True, timeout=ido) + except (OSError, subprocess.TimeoutExpired): + return None + return kimenet + + +def os_release(): + adat = {} + try: + for sor in Path("/etc/os-release").read_text().splitlines(): + if "=" in sor: + k, _, v = sor.partition("=") + adat[k] = v.strip().strip('"') + except OSError: + pass + return adat + + +def raveos_verzio(): + adat = os_release() + nev = adat.get("NAME", "RaveOS") + verzio = adat.get("VERSION_ID") or adat.get("BUILD_ID") or "" + return f"{nev} {verzio}".strip() + + +def kernel(): + return platform.release() + + +def asztal(): + nev = os.environ.get("XDG_CURRENT_DESKTOP") or os.environ.get("DESKTOP_SESSION") or "ismeretlen" + nev = nev.split(":")[-1] + tipus = os.environ.get("XDG_SESSION_TYPE", "") + return f"{nev} ({tipus.capitalize()})" if tipus else nev + + +def cpu(): + try: + for sor in Path("/proc/cpuinfo").read_text().splitlines(): + if sor.startswith("model name"): + nev = sor.split(":", 1)[1].strip() + return re.sub(r"\s+", " ", re.sub(r"\((R|TM)\)|CPU|Processor", "", nev)).strip() + except OSError: + pass + return platform.processor() or "ismeretlen" + + +def gpuk(): + lista = [] + kimenet = _futtat(["lspci", "-mm"]) + if not kimenet or kimenet.returncode != 0: + return lista + for sor in kimenet.stdout.splitlines(): + mezok = re.findall(r'"([^"]*)"', sor) + if len(mezok) >= 3 and re.search(r"VGA|3D|Display", mezok[0]): + gyarto = mezok[1].replace("Advanced Micro Devices, Inc. ", "").replace(" Corporation", "") + gyarto = gyarto.replace("[AMD/ATI]", "AMD").strip() + nev = mezok[2] + talalat = re.search(r"\[([^\]]+)\]", nev) + lista.append(f"{gyarto} {talalat.group(1) if talalat else nev}".strip()) + return lista + + +def gpu_driverek(): + driverek = [] + for kartya in sorted(Path("/sys/class/drm").glob("card[0-9]")): + try: + nev = (kartya / "device" / "driver").resolve().name + except OSError: + continue + if nev and nev not in driverek: + driverek.append(nev) + return driverek + + +def memoria(): + try: + for sor in Path("/proc/meminfo").read_text().splitlines(): + if sor.startswith("MemTotal:"): + kb = int(sor.split()[1]) + return f"{kb / 1024 / 1024:.1f} GB" + except (OSError, ValueError): + pass + return "ismeretlen" + + +def fajlrendszer(hely="/"): + kimenet = _futtat(["findmnt", "-no", "FSTYPE", hely]) + if kimenet and kimenet.returncode == 0 and kimenet.stdout.strip(): + return kimenet.stdout.strip().splitlines()[0] + try: + for sor in reversed(Path("/proc/mounts").read_text().splitlines()): + mezok = sor.split() + if len(mezok) > 2 and mezok[1] == hely: + return mezok[2] + except OSError: + pass + return "ismeretlen" + + +def uzemido(): + try: + mp = int(float(Path("/proc/uptime").read_text().split()[0])) + except (OSError, ValueError): + return "ismeretlen" + nap, mp = divmod(mp, 86400) + ora, mp = divmod(mp, 3600) + perc = mp // 60 + if nap: + return f"{nap} nap {ora} óra" + if ora: + return f"{ora} óra {perc} perc" + return f"{perc} perc" + + +def lemez(hely="/"): + hasznalat = shutil.disk_usage(hely) + return hasznalat.used, hasznalat.total + + +UJRAINDITOS = re.compile( + r"^(linux|linux-[a-z0-9-]+|nvidia.*|mesa|lib32-mesa|amd-ucode|intel-ucode|systemd|glibc|dbus|dbus-broker)$" +) + +_frissites_zar = threading.Lock() +_frissites_tar = {"ido": 0.0, "lista": None} +FRISSITES_TAR_IDO = 600 + + +def _pacman_meretek(nevek): + db = os.environ.get("CHECKUPDATES_DB") or f"{os.environ.get('TMPDIR', '/tmp')}/checkup-db-{os.getuid()}" + kimenet = _futtat( + ["pacman", "-Sup", "--dbpath", db, "--logfile", "/dev/null", "--print-format", "%n %s"], ido=60 + ) + meretek = {} + if kimenet and kimenet.returncode == 0: + for sor in kimenet.stdout.splitlines(): + r = sor.split() + if len(r) == 2 and r[1].isdigit(): + meretek[r[0]] = int(r[1]) + return {n: meretek.get(n) for n in nevek} + + +def _meret_szoveg(szoveg): + talalat = re.match(r"([\d.,]+)\s*([kMG]?B)", szoveg.replace("\xa0", " ")) + if not talalat: + return None + szam = float(talalat.group(1).replace(",", ".")) + return int(szam * {"B": 1, "kB": 1e3, "MB": 1e6, "GB": 1e9}[talalat.group(2)]) + + +def _frissitesek_lekerdez(): + csomagok = [] + if not shutil.which("checkupdates"): + raise RuntimeError("a checkupdates nem elérhető (pacman-contrib)") + pac = _futtat(["checkupdates", "--nocolor"], ido=180) + if not pac or pac.returncode not in (0, 2): + raise RuntimeError("a pacman frissítések ellenőrzése nem sikerült") + if pac.returncode == 0: + for sor in pac.stdout.splitlines(): + r = sor.split() + if len(r) >= 4: + csomagok.append({"nev": r[0], "forras": "pacman", "regi": r[1], "uj": r[3], "meret": None}) + meretek = _pacman_meretek([c["nev"] for c in csomagok]) + for c in csomagok: + c["meret"] = meretek.get(c["nev"]) + if shutil.which("yay"): + aur = _futtat(["yay", "-Qua", "--color", "never"], ido=180) + if aur and aur.returncode in (0, 1): + for sor in aur.stdout.splitlines(): + r = sor.split() + if len(r) >= 4 and r[2] == "->": + csomagok.append({"nev": r[0], "forras": "aur", "regi": r[1], "uj": r[3], "meret": None}) + if shutil.which("flatpak"): + fp = _futtat( + ["flatpak", "remote-ls", "--updates", "--columns=application,version,download-size"], ido=180 + ) + if fp and fp.returncode == 0: + for sor in fp.stdout.splitlines(): + r = sor.split("\t") + if r and r[0] and r[0] != "Application ID": + csomagok.append({ + "nev": r[0], + "forras": "flatpak", + "regi": "", + "uj": r[1] if len(r) > 1 else "", + "meret": _meret_szoveg(r[2]) if len(r) > 2 else None, + }) + for c in csomagok: + c["ujrainditas"] = c["forras"] == "pacman" and bool(UJRAINDITOS.match(c["nev"])) + return csomagok + + +def frissitesek(friss=False): + with _frissites_zar: + tar = _frissites_tar + if not friss and tar["lista"] is not None and time.monotonic() - tar["ido"] < FRISSITES_TAR_IDO: + return [dict(c) for c in tar["lista"]] + lista = _frissitesek_lekerdez() + tar["lista"] = lista + tar["ido"] = time.monotonic() + tar["mikor"] = time.time() + return [dict(c) for c in lista] + + +def frissites_ellenorizve(): + return _frissites_tar.get("mikor") + + +def snapper_elerheto(): + return bool(shutil.which("snapper")) and Path("/etc/snapper/configs/root").exists() + + +def utolso_snapshot(): + if not shutil.which("snapper"): + return None + kimenet = _futtat(["snapper", "--jsonout", "-c", "root", "list"], ido=30) + if not kimenet or kimenet.returncode != 0: + return None + try: + lista = json.loads(kimenet.stdout).get("root", []) + except ValueError: + return None + lista = [s for s in lista if s.get("number", 0) != 0] + if not lista: + return {} + return lista[-1] |