-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathsetup_fluidd_navi.py
More file actions
126 lines (98 loc) · 3.94 KB
/
setup_fluidd_navi.py
File metadata and controls
126 lines (98 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python3
"""Add a KlipperFleet entry to Fluidd's navigation via Moonraker's database API.
Usage: python3 setup_fluidd_navi.py [--remove] [--moonraker-url URL]
Requires fluidd-core/fluidd#1786 (custom navigation links).
Idempotent: removes any existing KlipperFleet entry before adding the current one.
Reference: https://github.com/fluidd-core/fluidd/pull/1802#issuecomment-4085253599
"""
import argparse
import json
import sys
import urllib.error
import urllib.request
import uuid
MOONRAKER_DEFAULT_URL = "http://localhost:7125"
DB_NAMESPACE = "fluidd"
DB_KEY = "uiSettings.navigation.customLinks"
# Stable UUID v5 derived from the URL namespace and our identifier.
# This ensures the same ID across installs without hardcoding a random UUID.
KLIPPERFLEET_ID = str(uuid.uuid5(uuid.NAMESPACE_URL, "klipperfleet"))
KLIPPERFLEET_LINK = {
"id": KLIPPERFLEET_ID,
"title": "KlipperFleet",
"url": "/klipperfleet.html",
"icon": "mdi-ferry",
"position": 86,
}
def moonraker_request(base_url, method, path, data=None):
"""Make a request to Moonraker's API."""
url = f"{base_url}{path}"
body = json.dumps(data).encode() if data else None
req = urllib.request.Request(url, data=body, method=method)
if body:
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req, timeout=10) as resp:
return json.loads(resp.read())
except urllib.error.URLError:
return None
def get_existing_links(base_url):
"""Fetch existing custom navigation links from Moonraker DB."""
result = moonraker_request(
base_url, "GET",
f"/server/database/item?namespace={DB_NAMESPACE}&key={DB_KEY}"
)
if result and "result" in result:
value = result["result"].get("value", [])
if isinstance(value, list):
return value
return []
def save_links(base_url, links):
"""Save custom navigation links to Moonraker DB."""
result = moonraker_request(
base_url, "POST",
"/server/database/item",
{"namespace": DB_NAMESPACE, "key": DB_KEY, "value": links}
)
return result is not None
def is_klipperfleet(entry):
"""Match KlipperFleet entries by id or title."""
return isinstance(entry, dict) and (
entry.get("id") == KLIPPERFLEET_ID or entry.get("title") == "KlipperFleet"
)
def install(base_url):
"""Add KlipperFleet link to Fluidd navigation."""
links = get_existing_links(base_url)
# Remove any existing KlipperFleet entry, then append
links = [l for l in links if not is_klipperfleet(l)]
links.append(KLIPPERFLEET_LINK)
if save_links(base_url, links):
print("KlipperFleet: Fluidd navigation configured.")
else:
print("KlipperFleet: WARNING: Could not configure Fluidd navigation "
"(Moonraker may not be running or fluidd#1786 not yet available).",
file=sys.stderr)
def remove(base_url):
"""Remove KlipperFleet link from Fluidd navigation."""
links = get_existing_links(base_url)
filtered = [l for l in links if not is_klipperfleet(l)]
if len(filtered) == len(links):
print("KlipperFleet: No Fluidd navigation entry found (skipped).")
return
if save_links(base_url, filtered):
print("KlipperFleet: Fluidd navigation entry removed.")
else:
print("KlipperFleet: WARNING: Could not remove Fluidd navigation entry.",
file=sys.stderr)
def main():
parser = argparse.ArgumentParser(description="Manage KlipperFleet's Fluidd sidebar link")
parser.add_argument("--remove", action="store_true", help="Remove the link instead of adding it")
parser.add_argument("--moonraker-url", default=MOONRAKER_DEFAULT_URL,
help=f"Moonraker base URL (default: {MOONRAKER_DEFAULT_URL})")
args = parser.parse_args()
if args.remove:
remove(args.moonraker_url)
else:
install(args.moonraker_url)
if __name__ == "__main__":
main()