import os import sqlite3 from datetime import datetime import traceback # Configurable paths via environment variables with fallback defaults DB_PATH = os.getenv('NAVIDROME_DB_PATH', './navidrome.db') OUTPUT_HTML = os.getenv('OUTPUT_HTML_PATH', './public/index.html') def get_all_users(): try: conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute("SELECT name FROM user") users = [row[0] for row in cursor.fetchall()] conn.close() return users except Exception as e: print(f"Error fetching users: {e}") return [] def get_aggregated_scrobbles(user_name): try: conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() cursor.execute(""" SELECT m.title, m.artist, COUNT(*) AS play_count, MAX(s.submission_time) AS last_played FROM scrobbles s JOIN media_file m ON s.media_file_id = m.id JOIN user u ON s.user_id = u.id WHERE u.name = ? GROUP BY m.title, m.artist ORDER BY play_count DESC, last_played DESC, m.artist ASC """, (user_name,)) rows = cursor.fetchall() conn.close() return rows except Exception as e: print(f"Error fetching scrobbles for {user_name}: {e}") return [] def generate_html(): print("Fetching users from Navidrome DB...") users = get_all_users() print(f"Found users: {users}") html_content = """ Music Listening Dashboard - All-Time Top Tracks

All-Time Top Tracks & History

""" for user in users: print(f"Processing scrobbles for {user}...") rows = get_aggregated_scrobbles(user) html_content += f"""

{user}

Unique tracks played: {len(rows)}
""" for title, artist, play_count, last_played in rows: try: dt = datetime.fromtimestamp(int(last_played)).strftime('%Y-%m-%d %H:%M') except: dt = str(last_played) html_content += f"\n" html_content += """
TrackArtistPlaysLast Played
{title}{artist}{play_count}{dt}
""" html_content += """
""" print(f"Writing HTML to {OUTPUT_HTML}...") os.makedirs(os.path.dirname(OUTPUT_HTML), exist_ok=True) with open(OUTPUT_HTML, 'w') as f: f.write(html_content) print("Dashboard HTML generated successfully for all users.") if __name__ == '__main__': try: print("Starting script execution...") generate_html() except Exception as e: print("An error occurred during execution:") traceback.print_exc()