From fe23acafdf9649b7c01cf8ee1cd91752fca8c0c4 Mon Sep 17 00:00:00 2001 From: tommal Date: Sun, 30 Nov 2025 15:21:34 +0100 Subject: [PATCH] Script per l'importazione delle stazioni radio --- readme | 3 + shortwave_to_navidrome.py | 134 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 readme create mode 100644 shortwave_to_navidrome.py diff --git a/readme b/readme new file mode 100644 index 0000000..da22114 --- /dev/null +++ b/readme @@ -0,0 +1,3 @@ +sqlite3 -header -csv ~/snap/shortwave/114/.local/share/Shortwave/Shortwave.db "SELECT * FROM library;" > ~/my_shortwave_stations.csv + + diff --git a/shortwave_to_navidrome.py b/shortwave_to_navidrome.py new file mode 100644 index 0000000..5a19e59 --- /dev/null +++ b/shortwave_to_navidrome.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +""" +Import Shortwave radio stations into Navidrome via Subsonic API +""" + +import sqlite3 +import json +import requests +import hashlib +import random +import string +from urllib.parse import urljoin + +# ============= CONFIGURATION ============= +# Edit these values for your setup +NAVIDROME_URL = "http://192.168.1.105:4533" # Your Navidrome URL +USERNAME = "tommal" # Your Navidrome username +PASSWORD = "tommal" # Your Navidrome password +SHORTWAVE_DB = "/home/tommal/snap/shortwave/114/.local/share/Shortwave/Shortwave.db" +# ========================================= + + +def generate_token(password, salt): + """Generate authentication token for Subsonic API""" + token_str = password + salt + return hashlib.md5(token_str.encode()).hexdigest() + + +def create_radio_station(base_url, username, token, salt, name, stream_url, homepage_url=""): + """Create internet radio station in Navidrome""" + url = urljoin(base_url, "/rest/createInternetRadioStation") + + params = { + 'u': username, + 't': token, + 's': salt, + 'v': '1.16.1', + 'c': 'ShortwaveImport', + 'f': 'json', + 'name': name, + 'streamUrl': stream_url, + 'homepageUrl': homepage_url + } + + try: + response = requests.get(url, params=params, timeout=10) + response.raise_for_status() + result = response.json() + + if result.get('subsonic-response', {}).get('status') == 'ok': + return True, "Success" + else: + error = result.get('subsonic-response', {}).get('error', {}) + return False, f"Error: {error.get('message', 'Unknown error')}" + except Exception as e: + return False, str(e) + + +def main(): + # Generate salt and token + salt = ''.join(random.choices(string.ascii_letters + string.digits, k=16)) + token = generate_token(PASSWORD, salt) + + print(f"Connecting to Shortwave database: {SHORTWAVE_DB}") + + # Connect to Shortwave database + conn = sqlite3.connect(SHORTWAVE_DB) + cursor = conn.cursor() + + # Get all stations from library + cursor.execute("SELECT uuid, data FROM library") + stations = cursor.fetchall() + + print(f"\nFound {len(stations)} stations in Shortwave library") + print(f"Importing to Navidrome at {NAVIDROME_URL}...\n") + + success_count = 0 + failed_count = 0 + + for uuid, data_json in stations: + try: + # Parse JSON data + data = json.loads(data_json) + + name = data.get('name', '').strip() + # Prefer url_resolved over url + stream_url = data.get('url_resolved') or data.get('url', '') + homepage = data.get('homepage', '') + + if not name or not stream_url: + print(f"⚠️ Skipping station with missing data (UUID: {uuid})") + failed_count += 1 + continue + + print(f"Importing: {name}") + print(f" URL: {stream_url}") + + success, message = create_radio_station( + NAVIDROME_URL, + USERNAME, + token, + salt, + name, + stream_url, + homepage + ) + + if success: + print(f" ✓ Success\n") + success_count += 1 + else: + print(f" ✗ Failed: {message}\n") + failed_count += 1 + + except json.JSONDecodeError: + print(f"⚠️ Skipping station with invalid JSON (UUID: {uuid})") + failed_count += 1 + except Exception as e: + print(f"⚠️ Error processing station {uuid}: {e}") + failed_count += 1 + + conn.close() + + # Summary + print("=" * 50) + print(f"Import complete!") + print(f" ✓ Successfully imported: {success_count}") + print(f" ✗ Failed: {failed_count}") + print(f" Total: {len(stations)}") + print("=" * 50) + + +if __name__ == "__main__": + main()