From 4b0fba074bde98d7cbc8621cb05a4f84a973676c Mon Sep 17 00:00:00 2001 From: Price Hiller Date: Thu, 9 Jan 2025 18:51:28 -0600 Subject: [PATCH] feat(waybar): implement custom systemd status --- users/price/dots/.config/waybar/config | 10 +-- .../.config/waybar/scripts/systemd-status.py | 77 +++++++++++++++++++ users/price/dots/.config/waybar/style.css | 6 +- 3 files changed, 85 insertions(+), 8 deletions(-) create mode 100755 users/price/dots/.config/waybar/scripts/systemd-status.py diff --git a/users/price/dots/.config/waybar/config b/users/price/dots/.config/waybar/config index 6d7ad417..b669feb0 100644 --- a/users/price/dots/.config/waybar/config +++ b/users/price/dots/.config/waybar/config @@ -20,7 +20,7 @@ ], "modules-right": [ "privacy", - "systemd-failed-units", + "custom/systemd-failed-units", "tray", "backlight", "network", @@ -225,10 +225,10 @@ "icon-spacing": 2, "icon-size": 14, }, - "systemd-failed-units": { - "format": "✗ Degraded Units: {nr_failed}", - "system": true, - "user": true + "custom/systemd-failed-units": { + "exec": "~/.config/waybar/scripts/systemd-status.py", + "return-type": "json", + "interval": 3 }, "tray": { "icon-size": 14 diff --git a/users/price/dots/.config/waybar/scripts/systemd-status.py b/users/price/dots/.config/waybar/scripts/systemd-status.py new file mode 100755 index 00000000..4b456150 --- /dev/null +++ b/users/price/dots/.config/waybar/scripts/systemd-status.py @@ -0,0 +1,77 @@ +#!/usr/bin/env -S nix shell nixpkgs#python3 nixpkgs#nix-prefetch-git --command python3 + +from enum import Enum +import subprocess +import json +from typing import NotRequired, TypedDict + + +class SystemUnitStatus(str, Enum): + Ok = "ok" + Degraded = "degraded" + + +WaybarJsonRet = TypedDict( + "WaybarJsonRet", + { + "text": str, + "class": SystemUnitStatus, + "alt": NotRequired[str], + "tooltip": NotRequired[str], + "percentage": NotRequired[str], + }, +) + + +class FailedUnit(TypedDict): + unit: str + load: str + active: str + sub: str + description: str + + +def get_failed_units(extra_args: list[str] | None = None) -> list[FailedUnit]: + extra_args = extra_args or [] + args = ["systemctl", "--state=failed", "--output=json"] + args.extend(extra_args) + + units_proc = subprocess.run(args, capture_output=True) + units_proc.check_returncode() + failed_units: list[FailedUnit] = json.loads(units_proc.stdout) + + return failed_units + + +system_failed_units = get_failed_units() +user_failed_units = get_failed_units(["--user"]) +total_units_failed = len(system_failed_units) + len(user_failed_units) + +status: SystemUnitStatus = SystemUnitStatus.Ok +text = "" +failed_units_tooltip: list[str] = [] + +if total_units_failed > 0: + text = f" Degraded Units: {total_units_failed}" + status = SystemUnitStatus.Degraded + failed_units_tooltip.extend( + map( + lambda unit: f"System > {unit["unit"]}", + system_failed_units, + ) + ) + failed_units_tooltip.extend( + map( + lambda unit: f"User > {unit["unit"]}", + user_failed_units, + ) + ) + + +out: WaybarJsonRet = { + "text": text, + "class": status, + "tooltip": "\r\n".join(failed_units_tooltip), +} + +print(json.dumps(out)) diff --git a/users/price/dots/.config/waybar/style.css b/users/price/dots/.config/waybar/style.css index 70ce7442..e2f52c7f 100644 --- a/users/price/dots/.config/waybar/style.css +++ b/users/price/dots/.config/waybar/style.css @@ -72,7 +72,7 @@ tooltip label, #tray, #backlight, #privacy, -#systemd-failed-units, +#custom-systemd-failed-units, #tray menu, #custom-lock { background-color: #16161d; @@ -285,11 +285,11 @@ tooltip { color: #A3D4D5; } -#systemd-failed-units.ok { +#custom-systemd-failed-units.ok { color: #98BB6C; } -#systemd-failed-units.degraded { +#custom-systemd-failed-units.degraded { color: #FF5D62; font-weight: bolder; }