dotfiles/duskwm/.config/dusk/status_scripts/duskwm_status.py

131 lines
3.7 KiB
Python
Raw Permalink Normal View History

import ast
import logging
2025-06-24 16:57:29 -04:00
import os
import runpy
import subprocess
import sys
import time
from pathlib import Path
from typing import Optional
import psutil
from duskwm_logging import log
2025-06-24 16:57:29 -04:00
# Configs
main_dir = Path(sys.argv[0]).parent.resolve()
debug = ast.literal_eval(os.getenv("STATUS_DEBUG", "False"))
2025-06-24 16:57:29 -04:00
# Scripts by interval
statuses = {
5: [(2, "./scripts/get_volume.py")],
60: [
(0, "./scripts/clock.py"),
(4, "./scripts/get_battery.py"),
(3, "./scripts/get_wifi.py"),
(7, "./scripts/get_uptime.py"),
(1, "./scripts/unread_mail.py"),
],
# 300: [],
3600: [(5, "./scripts/get_publicip.py"), (6, "./scripts/get_weather.py")],
}
def list_statuses():
log.info("Status scripts being processed")
2025-06-24 16:57:29 -04:00
for interval, status in statuses.items():
period = "second" if interval == 1 else "seconds"
log.info(f" Updating every {interval} {period}")
2025-06-24 16:57:29 -04:00
for location, script in status:
log.info(f" {location}: {script}")
2025-06-24 16:57:29 -04:00
def kill_existing_instances():
# Create a temporary lock to ensure firstrun can run
lock_path = "/run/user/1000/duskwm_status.lock"
try:
with open(lock_path, "x") as lock_file:
lock_file.write("Running")
except FileExistsError:
sys.exit(0)
2025-06-24 16:57:29 -04:00
current_pid = os.getpid()
found_existing = False
for proc in psutil.process_iter(["pid", "name", "cmdline"]):
try:
cmdline = proc.info["cmdline"] or []
cmdline_str = " ".join(cmdline)
# Kill uv processes running our script
if "uv run" in cmdline_str and "duskwm_status.py" in cmdline_str:
pid = proc.info["pid"]
if pid != current_pid:
os.kill(pid, 9)
log.warning(f"Killing uv process (PID {pid})")
# Kill python processes running our script
elif "python" in proc.info["name"] and "duskwm_status.py" in cmdline_str:
pid = proc.info["pid"]
if pid != current_pid:
os.kill(pid, 9)
log.warning(f"Killing python process (PID {pid})")
found_existing = True
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
if not found_existing:
log.info("First run detected, sleeping to let system initialize...")
time.sleep(10)
os.remove(lock_path)
2025-06-24 16:57:29 -04:00
def update_status(status: Optional[int], content: Optional[str]):
status = status if status is not None else 99
content = content if content is not None else ""
if debug:
log.setLevel(logging.DEBUG)
log.debug(f"{status:>3} : {content}")
2025-06-24 16:57:29 -04:00
else:
subprocess.run(
[
"duskc",
"--ignore-reply",
"run_command",
"setstatus",
f"{status}",
f"{content}",
]
)
def get_status_data(scriptpath: str) -> Optional[str]:
path = main_dir.joinpath(scriptpath).as_posix()
result = runpy.run_path(path)
content: Optional[str] = result.get("content", None)
return content
# Run at startup
log.info(f"Running in Debug mode: {debug}")
log.info(f"Root script found at: {main_dir}")
2025-06-24 16:57:29 -04:00
kill_existing_instances()
list_statuses()
seconds = 0
while True:
# Run on loop
for interval, scripts in statuses.items():
if seconds % interval == 0:
for status, script in scripts:
# try:
data = get_status_data(script)
# except Exception:
# data = f"Err: {script}"
update_status(status, data)
# Increment count and sleep for loop
seconds += 1
time.sleep(1)