def volume(to, up, down): """Control the active device's volume level.""" num_options = (bool(up) + bool(down) + bool(to)) if num_options != 1: raise InvalidVolumeInput if to: new_volume = to else: from cli.commands.status import status raw_status = status.callback(raw=True, verbose=-1) current_volume = raw_status['device']['volume_percent'] new_volume = current_volume + up - down if new_volume > 100: new_volume = 100 elif new_volume < 0: new_volume = 0 try: Spotify.request( 'me/player/volume?volume_percent={}'.format(new_volume), method='PUT') except SpotifyAPIError as e: if e.status == 403: raise DeviceOperationRestricted else: raise e click.echo('Volume set to {}%'.format(new_volume)) return
def previous(verbose=0, quiet=False): """Play the previous song in the queue.""" Spotify.request('me/player/previous', method='POST') if not quiet: from cli.commands.status import status status.callback(verbose=verbose) return
def play(verbose=0, quiet=False): """Resume playback.""" try: Spotify.request('me/player/play', method='PUT') except SpotifyAPIError as e: if e.status == 403: pass else: raise e if not quiet: from cli.commands.status import status status.callback(verbose=verbose, override={'is_playing': True}) return
def status(verbose): """Show who's logged in.""" user_data = Spotify.request('me', method='GET') click.echo('Logged in as {}'.format(user_data['display_name'])) if verbose: click.echo('Credentials stored in {}'.format(CREDS_PATH)) return
def login(): """Authorize spotify-cli to access the Spotify API.""" url = AUTH_URL + '&state=' + str(uuid1()) try: import webbrowser webbrowser.open(url) except: pass print('Go to the following link in your browser:\n\n\t{}\n'.format(url)) auth_code = input('Enter verification code: ') print('\nObtaining access token...') Spotify.refresh(auth_code) print('Credentials saved to {}'.format(CREDS_PATH)) return
def status(verbose=0, raw=False, override={}): """Describe the current playback session.""" res = Spotify.request('me/player', method='GET') if raw: if verbose >= 0: click.echo(res) return res if not res: raise NoPlaybackError # raw data = {} data['is_podcast'] = res['currently_playing_type'] == 'episode' if data['is_podcast']: raise PodcastNotSupported data['is_shuffle'] = res['shuffle_state'] data['is_repeat'] = False if res['repeat_state'] == 'off' else res[ 'repeat_state'] data['is_playing'] = res['is_playing'] data['device'] = { 'name': res['device']['name'], 'type': res['device']['type'], 'volume': res['device']['volume_percent'], } item = res['item'] data['music'] = { # note: playback context not available if private session or unnamed playlist 'context': res['context'], 'song': { 'name': item['name'], 'url': item['external_urls']['spotify'], 'api': item['href'], 'track_number': item['track_number'], 'progress': format_duration_ms(res['progress_ms']), 'duration': format_duration_ms(item['duration_ms']), }, 'album': { 'name': item['album']['name'], 'url': item['album']['external_urls']['spotify'], 'api': item['album']['href'], 'release_date': item['album']['release_date'], }, 'artist': { 'name': ', '.join([artist['name'] for artist in item['artists']]), 'urls': [artist['external_urls']['spotify'] for artist in item['artists']], }, } music = data['music'] # parsed if override: data.update(override) playback_status = 'Playing' if data['is_playing'] else 'Paused' playback_options = [] if data['is_repeat']: playback_options.append('repeat') if data['is_shuffle']: playback_options.append('shuffle') playback_str = '' if data['is_playing']: playback_options_str = '{}'.format( 'on {}'.format(' and '.join(playback_options) + ', ') if playback_options else '') playback_str = "({}{}% volume)".format(playback_options_str, data['device']['volume']) # output if not verbose: click.echo('{}: {}{}\n' ' {} - {}'.format( playback_status, ' ' if not data['is_playing'] else '', music['song']['name'], music['artist']['name'], music['album']['name'])) if verbose >= 1: click.echo('Song {} ({} / {})\n' 'Artist {}\n' 'Album {}\n' 'Status {} {}'.format(music['song']['name'], music['song']['progress'], music['song']['duration'], music['artist']['name'], music['album']['name'], playback_status, playback_str)) if verbose >= 2: click.echo('\n' 'Device {} ({})\n' 'URL: {}'.format(data['device']['name'], data['device']['type'], music['song']['url'])) return
def devices(verbose=False, switch_to='', raw=False): """Manage active devices. Only devices with an active Spotify session will be recognized. """ res = Spotify.request('me/player/devices', method='GET') if raw: if verbose: click.echo(res) return res if not res: raise NoPlaybackError # parsed devices_list = sorted(res['devices'], key=lambda x: (x['is_active'], x['type'], x['name'])) for device in devices_list: device['formatted_name'] = '{} - {}'.format(device['name'], device['type']) # output if not switch_to: if not verbose: output_list = map( lambda x: '* ' + x['name'] if x['is_active'] else ' ' + x['name'], sorted(devices_list, key=lambda x: x['name'])) click.echo('\n'.join(output_list)) else: output_list = map( lambda x: '* ' + x['formatted_name'] if x['is_active'] else ' ' + x['formatted_name'], sorted(devices_list, key=lambda x: x['formatted_name'])) click.echo('\n'.join(output_list)) return # switch-to handler matched_devices = [ x for x in devices_list if switch_to.lower() in x['formatted_name'].lower() ] num_matched = len(matched_devices) if num_matched != 1: if num_matched == 0: click.echo('"{}" not found.'.format(switch_to)) message = 'Please select a valid device.\n' choices = devices_list else: click.echo('{} devices matched "{}".'.format( num_matched, switch_to)) message = 'Please select the device to activate.\n' choices = matched_devices choices = map( lambda x: { 'value': x['formatted_name'], 'name': x['formatted_name'] + ('' if not x['is_active'] else ' (active)'), }, sorted(choices, key=lambda x: (x['is_active'], x['formatted_name']))) # interactive prompt from PyInquirer import prompt questions = [{ 'type': 'list', 'name': 'formatted_name', 'message': message, 'choices': choices, }] choice = prompt(questions) if not choice: return matched_devices = [ x for x in devices_list if choice['formatted_name'] == x['formatted_name'] ] to_activate = matched_devices[0] if to_activate['is_active']: click.echo(to_activate['formatted_name'] + ' is already active.') return post_data = { 'device_ids': [to_activate['id']], } Spotify.request('me/player', method='PUT', data=post_data) print('Switched to ' + to_activate['formatted_name']) return