Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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