diff --git a/src/scrobble/app.py b/src/scrobble/app.py index 2dc472a..752400f 100644 --- a/src/scrobble/app.py +++ b/src/scrobble/app.py @@ -6,7 +6,7 @@ from scrobble.lastfm import get_lastfm_client from scrobble.musicbrainz import CD, UserAgent, init_musicbrainz from scrobble.pushover import send_notification -from scrobble.utils import prepare_tracks +from scrobble.utils import prepare_tracks, choose_tracks import importlib.metadata @@ -19,6 +19,13 @@ APP = typer.Typer() +@APP.command() +def musicbrainz(): + raise NotImplementedError('Scrobbling a MusicBrainz release is not implemented yet.') + +@APP.command() +def discogs(): + raise NotImplementedError('Scrobbling a Discogs release is not implemented yet.') @APP.command() def cd( @@ -38,20 +45,30 @@ def cd( notify: Annotated[bool, typer.Option( help='--notify will send a push notification via Pushover with CD information.' )] = False, - choice: Annotated[bool, typer.Option( - help='--choice will give you a list of options of more than one CD is matched. ' + release_choice: Annotated[bool, typer.Option( + help='--release-choice will give you a list of options of more than one CD is matched. ' 'Otherwise, the app will go with the first match.' )] = True, + track_choice: Annotated[bool, typer.Option( + help='--track-choice will give you a list of tracks in the release to choose to scrobble ' + 'instead of scrobbling the entire release.' + )] = False, ): init_musicbrainz(USERAGENT) - cd = CD.find_cd(barcode, choice) + cd = CD.find_cd(barcode, release_choice) + + if track_choice: + tracks_to_scrobble = choose_tracks(cd.tracks) + else: + tracks_to_scrobble = cd.tracks + + prepped_tracks = prepare_tracks(cd, tracks_to_scrobble, playbackend) - prepped_tracks = prepare_tracks(cd, playbackend) if verbose: print(cd) - for track in cd.tracks: + for track in tracks_to_scrobble: print(track) if not dryrun: diff --git a/src/scrobble/utils.py b/src/scrobble/utils.py index 449ff6a..01ceb88 100644 --- a/src/scrobble/utils.py +++ b/src/scrobble/utils.py @@ -2,9 +2,11 @@ import tomllib from dataclasses import dataclass from datetime import datetime +import subprocess from typing import Optional from scrobble.musicbrainz import CD +from scrobble.musicbrainz import Track @dataclass @@ -63,9 +65,9 @@ def read_api_keys(self, config_path: str) -> dict: return keys -def prepare_tracks(cd: CD, playbackend: str = 'now') -> list[dict]: +def prepare_tracks(cd: CD, tracks: list[Track], playbackend: str = 'now') -> list[dict]: total_run_time: int = 0 - for track in cd.tracks: + for track in tracks: total_run_time += track.track_length if playbackend != 'now': @@ -84,7 +86,7 @@ def prepare_tracks(cd: CD, playbackend: str = 'now') -> list[dict]: elapsed: int = 0 prepped_tracks = [] - for track in cd.tracks: + for track in tracks: elapsed += track.track_length prepped_tracks.append( { @@ -96,3 +98,30 @@ def prepare_tracks(cd: CD, playbackend: str = 'now') -> list[dict]: ) return prepped_tracks + +def find_command(command: str): + try: + command_check = subprocess.check_output( + f'which {command}', + shell=True, + encoding='UTF-8' + ).rstrip() + except subprocess.CalledProcessError: + command_check = None + + return command_check + + +def choose_tracks(tracks: list[Track]) -> list[Track]: + gum_path = find_command('gum') + if gum_path: + track_dict: dict = {str(track): track for track in tracks} + choices = ' '.join(['"'+track_str+'"' for track_str in track_dict.keys()]) + picked_tracks = subprocess.check_output( + f"{gum_path} choose {choices} --no-limit", + shell=True, + encoding='UTF-8').rstrip() + else: + raise NotImplementedError("Haven't implemented basic choosing yet") + + return [track for track in tracks if str(track) in picked_tracks] \ No newline at end of file diff --git a/tests/test__utils.py b/tests/test__utils.py index 537b8a8..9220c09 100644 --- a/tests/test__utils.py +++ b/tests/test__utils.py @@ -1,5 +1,5 @@ import pytest -from scrobble.utils import Config +from scrobble.utils import Config, find_command def test_valid_config_has_lastfm_api(): test_config = Config(config_path='tests/resources/scrobble_complete_valid.toml') @@ -15,4 +15,12 @@ def test_valid_config_lastfm_api_key(): def test_valid_config_lastfm_username(): test_config = Config(config_path='tests/resources/scrobble_complete_valid.toml') - assert test_config.lastfm_username == 'thespeckofme' \ No newline at end of file + assert test_config.lastfm_username == 'thespeckofme' + +def test_find_command_succeeding(): + command_check = find_command('ls') + assert command_check is not None + +def test_find_command_returning_none(): + bad_command_check = find_command('badfakecommand') + assert bad_command_check is None \ No newline at end of file