dot

vizie's NixOS desktop: Hyprland, CachyOS kernel and gaming tweaks

56 lines1696 bytesPythonexecutable
1#!/usr/bin/env python3
2"""Prints dunst's most recent notifications as a JSON list for the Eww notifications panel.
3
4Reads `dunstctl history` (newest first) and keeps the last LIMIT entries. Dunst only
5moves a notification into its history once it has left the screen.
6"""
7import html
8import json
9import re
10import subprocess
11import time
12
13LIMIT = 10
14BODY_MAX = 160
15
16
17def plain(text):
18 """Dunst bodies may carry Pango/HTML markup; show them as plain text."""
19 text = re.sub(r"<[^>]+>", "", text or "")
20 return re.sub(r"\s+", " ", html.unescape(text)).strip()
21
22
23def main():
24 try:
25 out = subprocess.run(["dunstctl", "history"], capture_output=True, text=True, timeout=3).stdout
26 history = json.loads(out)["data"][0]
27 except Exception:
28 history = []
29
30 # Dunst timestamps are microseconds on the monotonic clock, not wall-clock time.
31 offset = time.time() - time.monotonic()
32 items = []
33 for n in history[:LIMIT]:
34 def field(name):
35 return (n.get(name) or {}).get("data", "")
36
37 body = plain(field("body"))
38 if len(body) > BODY_MAX:
39 body = body[: BODY_MAX - 1].rstrip() + "…"
40 try:
41 when = time.strftime("%H:%M", time.localtime(offset + int(field("timestamp")) / 1e6))
42 except (TypeError, ValueError):
43 when = ""
44 items.append({
45 "i": len(items), # position in the list, staggers the clear animation
46 "id": field("id"),
47 "app": plain(field("appname")),
48 "summary": plain(field("summary")),
49 "body": body,
50 "time": when,
51 })
52 print(json.dumps(items))
53
54
55if __name__ == "__main__":
56 main()