From 7d0b9df50c6385f4fdda37220cbe46da64aa3294 Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Tue, 19 Aug 2025 18:01:42 +1000 Subject: [PATCH] feat: Add a ton of features to make it better --- current_track.json | 1 + server.log | 3 ++ server.py | 62 +++++++++++++++++++++++++-- song-hook.py | 44 +++++++++++++++++++ templates/assets/css/index.css | 77 ++++++++++++++++++++++++++-------- templates/index.html | 36 +++++++++++++++- 6 files changed, 201 insertions(+), 22 deletions(-) create mode 100644 current_track.json create mode 100644 server.log create mode 100755 song-hook.py diff --git a/current_track.json b/current_track.json new file mode 100644 index 0000000..5399a2c --- /dev/null +++ b/current_track.json @@ -0,0 +1 @@ +{"name": "girls will b girls", "cover": "https://i.scdn.co/image/ab67616d0000b273ea3a18c31fd757d953c7836a"} diff --git a/server.log b/server.log new file mode 100644 index 0000000..9d2e44e --- /dev/null +++ b/server.log @@ -0,0 +1,3 @@ +Changing Song +Song Name: girls will b girls +Playing Song diff --git a/server.py b/server.py index 51a28c0..c6b0e22 100644 --- a/server.py +++ b/server.py @@ -18,9 +18,24 @@ import dotenv dotenv.load_dotenv() +SPEAKER_NAME = os.getenv("SPEAKER_NAME", "Family Room Speakers") + app = Flask(__name__) +def log(message: str): + """ + Log a message to the server log file. + """ + log_path = "server.log" + if not os.path.exists(log_path): + with open(log_path, "w") as f: + f.write("") + + with open(log_path, "a") as f: + f.write(f"{datetime.now().isoformat()} - {message}\n") + print(f"{datetime.now().isoformat()} - {message}") # Also print to console for debugging + def find(name, path): for root, dirs, files in os.walk(path): if name in files: @@ -85,11 +100,21 @@ def restart(): """ # Execute a `pkill spotifyd` command to stop the spotifyd process status = os.system("pkill spotifyd") + + hookPath = os.path.join(os.getcwd(), "song-hook.sh") + + # Clear the server log + log_path = "server.log" + if os.path.exists(log_path): + with open(log_path, "w") as f: + f.write("") + # Start with a new process - os.system("spotifyd -d 'Family Room Speakers'") - - - + output = os.system(f"spotifyd -d '{SPEAKER_NAME}' --onevent {hookPath}") + if output != 0: + log("Failed to restart spotifyd") + else: + log("spotifyd restarted successfully") return redirect('/') @@ -141,6 +166,35 @@ def api_data(): return jsonify(data) +@app.route("/api/v1/logs", methods=["GET"]) +def api_logs(): + """ + Returns the last 100 lines of the server log. + """ + log_path = "server.log" + + # Check if the log file exists + if not os.path.isfile(log_path): + return jsonify({"logs": "Server not running"}), 404 + + lines = [] + try: + with open(log_path, "r") as f: + lines = f.readlines()[-100:] + except Exception as e: + lines = [f"Error reading log file: {e}"] + return jsonify({"logs": "".join(lines)}) + +@app.route("/api/v1/current_track", methods=["GET"]) +def api_current_track(): + # If the current_track.json file exists, read it and return its contents + if os.path.isfile("current_track.json"): + with open("current_track.json", "r") as f: + track_data = json.load(f) + return jsonify(track_data) + else: + return jsonify({"error": "No current track data available"}), 404 + # endregion diff --git a/song-hook.py b/song-hook.py new file mode 100755 index 0000000..362aef1 --- /dev/null +++ b/song-hook.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +import os +from datetime import datetime +# "PLAYER_EVENT": "Player Event", +# "TRACK_ID": "Track ID", +# "TRACK_COVER": "Track Cover", +# "endoftrack": "End of Track", +ENVLOGS = { + "CLIENT_NAME": "Device Connected", + "VOLUME": "Volume Level", + "AUTOPLAY": "Autoplay Status", + "SHUFFLE": "Shuffle Status", + "REPEAT": "Repeat Status", + "TRACK_NAME": "Song Name", +} +PLAYER_EVENTS = { + "start": "Playing Song", + "change": "Changing Song", +} + +LOG_FILE = "/home/nathan/Git/spotifyd-webui/server.log" + +def main(): + with open(LOG_FILE, "a") as f: + # Get PLAYER_EVENT from environment variables + player_event = os.getenv("PLAYER_EVENT", "Unknown Event") + player_event = PLAYER_EVENTS.get(player_event, None) + if player_event: + f.write(player_event + "\n") + for key, value in os.environ.items(): + # Only log specific environment variables using format {ENVLOGS[key]}: value + if key in ENVLOGS: + f.write(f"{ENVLOGS[key]}: {value}\n") + + # Save current name and cover + track_name = os.getenv("TRACK_NAME", None) + track_cover = os.getenv("TRACK_COVER", None) + if track_name and track_cover: + with open("current_track.json", "w") as f: + f.write(f'{{"name": "{track_name}", "cover": "{track_cover}"}}\n') + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/templates/assets/css/index.css b/templates/assets/css/index.css index 4aa9f31..7a75b93 100644 --- a/templates/assets/css/index.css +++ b/templates/assets/css/index.css @@ -8,15 +8,12 @@ h1 { padding: 0; } .centre { - margin-top: 10%; + margin-top: 6%; text-align: center; } -a { - color: #ffffff; - text-decoration: none; -} -a:hover { - text-decoration: underline; + +.spacer { + height: 40px; } /* Mike section styling */ @@ -26,32 +23,78 @@ a:hover { margin-left: auto; margin-right: auto; padding: 20px; - background-color: rgba(50, 50, 50, 0.3); - border-radius: 8px; + background-color: rgba(50, 50, 50, 0.5); + border-radius: 12px; + box-shadow: 0 2px 12px rgba(0,0,0,0.25); + text-align: center; } .mike-section h2 { color: #f0f0f0; margin-top: 0; + font-size: 1.5em; } .mike-section p { line-height: 1.6; margin-bottom: 15px; + font-size: 1.1em; } +.spotify-logo { + width: 90%; + object-fit: cover; + border-radius: 12px; + box-shadow: 0 2px 12px rgba(0,0,0,0.18); + background: #222; + border: 2px solid #444; +} + +#current-track-section { + margin-top: 20px; +} + +#current-track { + font-size: 1.2em; + color: #fff; + margin-top: 8px; + margin-bottom: 0; + font-weight: 500; +} + +#logs-section { + margin-top: 40px; +} + +#server-logs { + font-family: monospace; + font-size: 14px; + background: #222; + color: #eee; + padding: 10px; + border-radius: 5px; + max-height: 400px; + overflow: auto; + text-align: left; + box-shadow: 0 1px 6px rgba(0,0,0,0.12); +} + +/* Button improvements */ .button { display: inline-block; - padding: 10px 20px; - background-color: #ffffff; - color: #000000; + padding: 12px 28px; + background-color: #1db954; + color: #fff; border-radius: 5px; text-decoration: none; - transition: background-color 0.3s ease; - border: 1px solid #ffffff; + transition: background 0.2s, color 0.2s; + border: none; + font-size: 1.1em; + font-weight: 600; + box-shadow: 0 1px 6px rgba(0,0,0,0.10); + margin-top: 18px; } .button:hover { - background-color: #000000; - color: #ffffff; - border: 1px solid #ffffff; + background-color: #14833b; + color: #fff; } \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 4c5e1f8..ff1b653 100644 --- a/templates/index.html +++ b/templates/index.html @@ -17,7 +17,41 @@
- + + +
+ +

Loading...

+
+ +
+

Server Logs

+

+    
+ + \ No newline at end of file