Spotify Driver - adriancooney/polytunes GitHub Wiki

Spotify Driver

To connect Polytunes to Spotify, the process is a little complicated because of it's OAuth. This guide, as it stands, is the most manual way possible of connecting Spotify so apologies for the convoluted process of manually acquiring an OAuth access token. It can only get better from here.

Requirements

To configure the Spotify driver, we have three required variables:

  • SPOTIFY_CLIENT_ID or --spotify-client-id.
  • SPOTIFY_CLIENT_SECRET or --spotify-client-secret.
  • SPOTIFY_REFRESH_TOKEN or --spotify-refresh-token.

Client ID and Secret

To get the client ID and secret, navigate to the Spotify developers portal and create a new application.

Next, we need to add a URL for the OAuth to talk to. Essentially what were doing here is Spotify's OAuth Flow without a server. Since we're only doing this once, we can use RequestB.in. Create a new bin and get it's URL (without the ?inspect suffix!). We add this as a valid Redirect URI in the application:

This tells the Spotify API to post the code required for OAuth to the bin where we can grab it later. Now, we need to begin the OAuth flow. For this tutorial, we'll use HTTPie but you can use Curl or any tool you'd like. Better yet, build something that polytunes can do to automate this! First off, we need to visit the following URL in the browser. Fill in your CLIENT_ID and REQUEST_BIN_URL in the URL.

https://accounts.spotify.com/authorize?client_id=<CLIENT_ID>&redirect_uri=<REQUEST_BIN_URL>&response_type=code&scope=playlist-read-private%20playlist-read-collaborative%20playlist-modify-public%20playlist-modify-private%20user-library-read%20user-library-modify%20user-read-private

Login or authorize the app and you should be redirected to Request Bin's simple OK page with a long URL of following form. Save the <CODE> part of the URL.

http://requestb.in/w5keyyw5?code=<CODE>

Example:

AQB-wsoJYWFvF0n7XDNWtS1rRYjAvuqD3pwTIyoLjYMUM0HCtwUMPpzfyhXeahsfXdDauiHDFY0gEUjbiWnd9PQV9eAXxSvgVb31u3WLVUTRNq9w0jR-hg5zE9IOO_U41gcFfdi-9mku3pl7QnxE2f0_qOcPBok-5Cu_EzFtsWeAl-tMJGfgVJreaM0otdfValZluTTFH_DOssdfsf9YfKL1C0jxwvmoS9X2AHjsrxQRBB429FmPkeC59yDTZLTvZ5hqsnQnZDQ-4xTHY0yzojtmdBLTfWmlv2rdSSpUrgQooz85Clg5egOMYSltqVMd9JlrnxCdrN47F3EQ-Q1QldclSn6XaqvMpyW-G64y7356xpjuEasdcW1J869CGSSPkUetPCsSH9cnuUtzNmKc_lfSqFgp5nCkh5ioUU

Save this code and open your shell. We now need to POST to the Spotify API to get our refresh token. Fill in the following HTTPie command with your details accordingly.

$ http -f POST https://accounts.spotify.com/api/token \
    grant_type=authorization_code \
    code=<CODE> \
    redirect_uri=<REQUEST_BIN_URL> \
    client_id=<CLIENT_ID> \
    client_secret=<CLIENT_SECRET>

This should return the tokens you're looking for:

{
    "access_token": "BQAoW1Xhsdfasdfke_JiTGoDh-oU--jXrBROzHMkhPasdfasdfHfnrQ7WhHuqOOmnUxejVsdfbu4jTkhAg_2VOr4iIntvmOuDQRisl4Dr9NvPV2iI3cyau1QN7qTUA1n-rm6Mg2ThTRR-SjKi4BIE08X15yhgZkuLX2PNy7E14tzKetSL12ymuNdBMD0U7eWL6uMJIHI59AhkKmEQ6C-FaCbLO6asdfasfd8uIclGnzAIkavsldq7a8X0FNHhtwGuX9ZxtHuxee9SVHPm8grk5TRFmxARhEArMmHzdvDukyQ",
    "expires_in": 3600,
    "refresh_token": "AQC3aSDKEEySWDzMzasdfx4RVVCZtTpdQHgrksysswwQrtqdhU53FxGnU_eJWhqfffKa4GR_jXWqdu1ORjJcwX-SUxdQ-0b1dasdnwhHBw1T0-haV9cscZXr2HQwkGo_vK1lvasdfasfdsdf45DWZLc8U",
    "token_type": "Bearer"
}

Now we have the details needed to connect Polytunes to our API. My preferred way of configuring Polytunes is to create a .env file with the configuration (don't forget to fill in the values for anything in between < and >!):

export SPOTIFY_REFRESH_TOKEN=<REFRESH_TOKEN>
export SPOTIFY_CLIENT_ID=<CLIENT_ID>
export SPOTIFY_CLIENT_SECRECT=<CLIENT_SECRET>

Then, whenever I want to interact with Polytunes, I run source .env. You could also add environment variables to your .bashrc or .zshrc or configure Polytunes pass via command line options (see configuring drivers). Now, my Polytunes is automatically configured to talk to my Spotify library:

$ source .env
$ polytunes library -d spotify playlists
[*] Getting Spotify playlists..
    -> 2015 created by adriancooney. (1tKQSuYWtJAgtJ4TYwH2g3)
    -> Library created by adriancooney. (3in3LhDqQdR9LdYoxHI8ga)
    -> House created by adriancooney. (5c2V6EsYWXELjjunNTFpE5)
    -> Groovers created by adriancooney. (3svlOvf9y6dsHt3x6ijZ2q, public)
    -> Laxers created by adriancooney. (5Ezce9OoghtDKOZTdhYgkm, public)
    -> Thumpers created by adriancooney. (4WIVjKPmRDycEBwAaoaUV3, public)
    -> New Music Playlist created by nialler9. (0sLxjSNzBJUn1iIxT1575E)
    -> Internal Affairs (collaborative) created by 1155720466. (1Gvbx5S16cOHgqLvthVdNV, collaborative)
    -> Internet 3.0 (Collaborative) created by 1155720466. (4xAw9Ag79gOlyW9fuy8MFT, collaborative)
    -> Flume Essentials Playlist created by hstreten. (4Z9DdQM7PqG3ykEvVkei2n, public)
    -> What So Not Radio created by whatsonotcertified. (1toiZBu3dcizei848zaohR, public)
⚠️ **GitHub.com Fallback** ⚠️