diff --git a/troi/cli.py b/troi/cli.py index a247c123..9af266c4 100755 --- a/troi/cli.py +++ b/troi/cli.py @@ -183,12 +183,13 @@ def info_cmd(patch): @click.option("-d", "--db_file", help="Database file for the local collection", required=False, is_flag=False) @click.option('-t', '--threshold', default=.80, help="Minimum match percentage for metadata matches. Must be 0.0 - 1.0") @click.option('-u', '--upload-to-subsonic', required=False, is_flag=True, help="upload playlist via subsonic API") +@click.option('-i', '--subsonic-id', required=False, help="overwrite existing subsonic playlist with the given ID") @click.option('-m', '--save-to-m3u', required=False, help="save to specified m3u playlist") @click.option('-j', '--save-to-jspf', required=False, help="save to specified JSPF playlist") @click.option('-y', '--dont-ask', required=False, is_flag=True, help="save playlist without asking user") @click.option('-q', '--quiet', 'quiet', help="Do no print out anything", required=False, is_flag=True) @click.argument('jspf_playlist') -def resolve(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, quiet, jspf_playlist): +def resolve(db_file, threshold, upload_to_subsonic, subsonic_id, save_to_m3u, save_to_jspf, dont_ask, quiet, jspf_playlist): """ Resolve a global JSPF playlist with MusicBrainz MBIDs to files in the local collection""" set_log_level(quiet) db_file = db_file_check(db_file) @@ -197,20 +198,21 @@ def resolve(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, d lbrl = ListenBrainzRadioLocal(quiet) playlist = read_jspf_playlist(jspf_playlist) lbrl.resolve_playlist(threshold, playlist) - output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask) + output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, subsonic_id) @cli.command(name="lb-radio", context_settings=dict(ignore_unknown_options=True, )) @click.option("-d", "--db_file", help="Database file for the local collection", required=False, is_flag=False) @click.option('-t', '--threshold', default=.80, help="Minimum match percentage for metadata matches. Must be 0.0 - 1.0") @click.option('-u', '--upload-to-subsonic', required=False, is_flag=True, help="upload playlist via subsonic API") +@click.option('-i', '--subsonic-id', required=False, help="overwrite existing subsonic playlist with the given ID") @click.option('-m', '--save-to-m3u', required=False, help="save to specified m3u playlist") @click.option('-j', '--save-to-jspf', required=False, help="save to specified JSPF playlist") @click.option('-y', '--dont-ask', required=False, is_flag=True, help="save playlist without asking user") @click.option('-q', '--quiet', 'quiet', help="Do no print out anything", required=False, is_flag=True) @click.argument('mode') @click.argument('prompt') -def lb_radio(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, quiet, mode, prompt): +def lb_radio(db_file, threshold, upload_to_subsonic, subsonic_id, save_to_m3u, save_to_jspf, dont_ask, quiet, mode, prompt): """Use LB Radio to create a playlist from a prompt, using a local music collection""" set_log_level(quiet) db_file = db_file_check(db_file) @@ -224,19 +226,20 @@ def lb_radio(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, db.metadata_sanity_check(include_subsonic=upload_to_subsonic) return - output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask) + output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, subsonic_id) @cli.command("weekly-jams", context_settings=dict(ignore_unknown_options=True, )) @click.option("-d", "--db_file", help="Database file for the local collection", required=False, is_flag=False) @click.option('-t', '--threshold', default=.80, help="Minimum match percentage for metadata matches. Must be 0.0 - 1.0") @click.option('-u', '--upload-to-subsonic', required=False, is_flag=True, help="upload playlist via subsonic API") +@click.option('-i', '--subsonic-id', required=False, help="overwrite existing subsonic playlist with the given ID") @click.option('-m', '--save-to-m3u', required=False, help="save to specified m3u playlist") @click.option('-j', '--save-to-jspf', required=False, help="save to specified JSPF playlist") @click.option('-y', '--dont-ask', required=False, is_flag=True, help="save playlist without asking user") @click.option('-q', '--quiet', 'quiet', help="Do no print out anything", required=False, is_flag=True) @click.argument('user_name') -def periodic_jams(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, quiet, user_name): +def periodic_jams(db_file, threshold, upload_to_subsonic, subsonic_id, save_to_m3u, save_to_jspf, dont_ask, quiet, user_name): "Generate a weekly jams playlist for your local collection" set_log_level(quiet) db_file = db_file_check(db_file) @@ -251,7 +254,7 @@ def periodic_jams(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_j db.metadata_sanity_check(include_subsonic=upload_to_subsonic) return - output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask) + output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, subsonic_id) @cli.command(context_settings=dict(ignore_unknown_options=True, )) diff --git a/troi/content_resolver/cli.py b/troi/content_resolver/cli.py index bb612b65..38eefd26 100755 --- a/troi/content_resolver/cli.py +++ b/troi/content_resolver/cli.py @@ -26,7 +26,7 @@ DEFAULT_CHUNKSIZE = 100 -def output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask): +def output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, subsonic_id=None): try: recording = playlist.playlists[0].recordings[0] except (KeyError, IndexError): @@ -43,7 +43,7 @@ def output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, if dont_ask or ask_yes_no_question("Upload via subsonic? (Y/n)"): logger.info("uploading playlist") - db.upload_playlist(playlist) + db.upload_playlist(playlist, subsonic_id) return if save_to_m3u or save_to_jspf: diff --git a/troi/content_resolver/subsonic.py b/troi/content_resolver/subsonic.py index 4f712f92..1d953baf 100755 --- a/troi/content_resolver/subsonic.py +++ b/troi/content_resolver/subsonic.py @@ -1,6 +1,7 @@ import datetime import logging +from libsonic.errors import DataNotFoundError import peewee from tqdm import tqdm @@ -235,9 +236,7 @@ def update_recordings(self, recordings): # , subsonic_id = excluded.subsonic_id # , last_updated = excluded.last_updated""", recordings) - - - def upload_playlist(self, playlist): + def upload_playlist(self, playlist, playlist_id=None): """ Given a Troi playlist, upload the playlist to the subsonic API. """ @@ -253,4 +252,16 @@ def upload_playlist(self, playlist): except KeyError: continue - conn.createPlaylist(name=playlist.playlists[0].name, songIds=song_ids) + if playlist_id: + try: + remote_playlist = conn.getPlaylist(pid=playlist_id) + conn.updatePlaylist( + lid=playlist_id, + name=playlist.playlists[0].name, + songIdsToAdd=song_ids, + songIndexesToRemove=list(range(0, len(remote_playlist["playlist"]) - 1)), + ) + except DataNotFoundError: + conn.createPlaylist(name=playlist.playlists[0].name, songIds=song_ids) + else: + conn.createPlaylist(name=playlist.playlists[0].name, songIds=song_ids)