feat: add --force-sync command-line argument for one-time playlist sync

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2026-02-04 11:50:02 -07:00
parent a8d940b101
commit a04becb616

40
main.py
View File

@@ -4,6 +4,7 @@ logging.basicConfig(
format='[%(asctime)s] %(levelname)s %(module)s/%(funcName)s - %(message)s', format='[%(asctime)s] %(levelname)s %(module)s/%(funcName)s - %(message)s',
level=logging.DEBUG if DEBUG else logging.INFO) level=logging.DEBUG if DEBUG else logging.INFO)
import argparse
import hashlib import hashlib
import random import random
import string import string
@@ -63,6 +64,9 @@ def delete_playlist_file(playlist_dir, playlist_name):
def main(): def main():
"""Get playlists from a Navidrome server using the Subsonic API.""" """Get playlists from a Navidrome server using the Subsonic API."""
parser = argparse.ArgumentParser(description="Sync Navidrome playlists to Mopidy.")
parser.add_argument('--force-sync', action='store_true', help='Perform a one-time sync of all playlists and exit.')
args = parser.parse_args()
mopidy_playlist_dir = settings.MOPIDY_PLAYLIST_DIR mopidy_playlist_dir = settings.MOPIDY_PLAYLIST_DIR
if not mopidy_playlist_dir: if not mopidy_playlist_dir:
logging.error("MOPIDY_PLAYLIST_DIR must be set in settings.py.") logging.error("MOPIDY_PLAYLIST_DIR must be set in settings.py.")
@@ -100,6 +104,42 @@ def main():
'f': 'json' 'f': 'json'
} }
if args.force_sync:
logging.info("Starting one-time force sync of all playlists...")
api_url = f"{navidrome_url.rstrip('/')}/rest/getPlaylists.view"
try:
response = requests.get(api_url, params=params)
response.raise_for_status()
except requests.exceptions.RequestException as e:
logging.error(f"Error connecting to Navidrome: {e}")
return
data = response.json()
subsonic_response = data.get('subsonic-response')
if not subsonic_response or subsonic_response.get('status') == 'failed':
error = subsonic_response.get('error', {}) if subsonic_response else {}
logging.error(f"API Error during sync: {error.get('message')} (code: {error.get('code')})")
return
playlists = subsonic_response.get('playlists', {}).get('playlist', [])
if not playlists:
logging.info("No playlists found to sync.")
return
logging.info(f"Found {len(playlists)} playlists to sync.")
for playlist in playlists:
playlist_id = playlist.get('id')
playlist_name = playlist.get('name')
logging.info(f"Syncing playlist: '{playlist_name}' ({playlist_id})")
raw_output = run_pls_command(playlist_id)
if raw_output:
transformed_output = transform_m3u_to_m3u8(raw_output)
if transformed_output:
save_playlist_file(mopidy_playlist_dir, playlist_name, transformed_output)
logging.info("Force sync complete.")
return
known_playlists = {} known_playlists = {}
while True: while True: