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]