Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying subsonic playlist ID to overwrite #152

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions troi/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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, ))
Expand Down
4 changes: 2 additions & 2 deletions troi/content_resolver/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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:
Expand Down
19 changes: 15 additions & 4 deletions troi/content_resolver/subsonic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime
import logging

from libsonic.errors import DataNotFoundError
import peewee
from tqdm import tqdm

Expand Down Expand Up @@ -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.
"""
Expand All @@ -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)
Loading