#! /usr/bin/env python3 import argparse import sys import logging import spotipy import subprocess from pathlib import Path from spotipy.oauth2 import SpotifyOAuth from rich.console import Console SPOTIFY_CLIENT_ID = "bb39d914c6884316ac09cf0c928d975b" logger = logging.getLogger(__name__) def main() -> int: # Handle program arguments ap = argparse.ArgumentParser( prog="spotify-now-playing", description="Display the currently playing Spotify track", ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) args = ap.parse_args() # Configure logging logging.basicConfig( level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s", ) # Call `ewp-secrets` to read the Spotify client secret secrets_proc = subprocess.run( [ (Path(__file__).parent / "ewp-secrets").as_posix(), "load", "-n", "spotify", "-k", "client-secret", ], capture_output=True, ) # If the secret manager failed, exit if secrets_proc.returncode != 0: print("Failed to load Spotify Client Secret", file=sys.stderr) print( "Please run `ewp-secrets store -n spotify -k client-secret` and pass it the secret from:", file=sys.stderr, ) print( f"https://developer.spotify.com/dashboard/{SPOTIFY_CLIENT_ID}/settings", file=sys.stderr, ) return 1 # Connect to Spotify cache_path = Path("~/.cache/spotipy/spotify-now-playing.oauth").expanduser() cache_path.parent.mkdir(parents=True, exist_ok=True) oauth = SpotifyOAuth( client_id=SPOTIFY_CLIENT_ID, client_secret=secrets_proc.stdout.decode().strip(), redirect_uri="http://localhost:8933", scope="user-read-playback-state,user-read-currently-playing", cache_path=cache_path.as_posix(), open_browser=True ) spotify = spotipy.Spotify(auth_manager=oauth) # Read the currently playing track current_track = spotify.current_user_playing_track() # If nothing is playing if not current_track: print("Nothing is currently playing") return 1 # Pretty printing :) console = Console(highlight=False) # Display basic info console.print(f"[bold]{current_track['item']['name']}[/bold] by [bold]{' & '.join([artist['name'] for artist in current_track['item']['artists']])}[/bold]") console.print(f"Album: [bold]{current_track['item']['album']['name']}[/bold] ({current_track['item']['album']['album_type'].capitalize()}, {current_track['item']['album']['release_date'][:4]})") console.print(f"Popularity: [bold]{current_track['item']['popularity']}%[/bold]") # Get this track's audio features audio_features = spotify.audio_features([current_track['item']['id']])[0] console.print(f"Tempo: [bold]{audio_features['tempo']} BPM[/bold] ({audio_features['time_signature']}/4)") key = { -1: "???", 0: "C", 1: "C♯/D♭", 2: "D", 3: "D♯/E♭", 4: "E", 5: "F", 6: "F♯/G♭", 7: "G", 8: "G♯/A♭", 9: "A", 10: "A♯/B♭", 11: "B" }[audio_features['key']] console.print(f"Key: [bold]{key} {'Major' if audio_features['mode'] == 1 else 'Minor'}[/bold]") console.print(f"Energy: [bold]{int(audio_features['energy'] * 100)}%[/bold]") return 0 if __name__ == "__main__": sys.exit(main())