Create a Hipster Playlist Using PowerShell

Hipster playlist in Powershell

Hipster cred! I have it, you want it. No way to build it up faster than to be into something before it becomes popular. You may have been wondering how you might be able to pull a random list of fifteen infrequently listened to bands and document the fact that you knew of them before it became all about the money. Well lucky for you we have what you need.

Note: if you see a band in this list and object to their placement, you are functioning at a higher hipster level than this blog accounts for and can add that feather to your fedora.

Setting Up the Spotify API

Before this script will be able to run at all we will need to set up an API(Application Program Interface) at https://developer.spotify.com/my-applications. This will give us the client ID and let us set a redirect URI(Uniform Resource Identifier) for after we authenticate. Seen below is what this screen looks like after I use cutting edge blurring technology to hide my actual IDs.

hipster playlist uri spotify

With this created, you can now generate an access request. The request has to contain the following:

  • Client ID – Identification number generated by Spotify
  • Redirect URI – URI that the browser will go to after you authenticate.
  • Response Type – How you want the Spotify servers to respond to the request
  • Scope – Permissions you are requesting

Opening Your Spotify Hipster Playlist

Here is how our URI request looks. $clientID should be replaced with your client ID after you register your application with Spotify

$clientid = <Your Client ID Here>
$AuthUri = "https://accounts.spotify.com/en/authorize?" +
           "client_id=$clientid" +                                                                                     #Put the client ID from your web application here here
           "&redirect_uri=//www.pdq.com/aa/img/jonathan-lindgren-hipster-220x247-lossy30.gif" +         #Thanks to Jonathan Lindgren (www.jonathanlindgren.com) for use of that awesome gif
           "&scope=playlist-modify-public playlist-modify-private playlist-read-private playlist-read-collaborative" +
           "&response_type=token"

If you copy the above URL into a web browser it will respond with your access token inside the address bar. We could manually copy that over like we are animals, or we can use PowerShell to build our own browser on the fly that will have the token we need in an object. Let’s check in with Kris to see how he might perform such a task.

Add-Type -AssemblyName System.Windows.Forms
$FormProperties = @{
    Size = New-Object System.Drawing.Size(850, 675)
    StartPosition = "CenterScreen"
}
$Form = New-Object System.Windows.Forms.Form -Property $FormProperties
$BrowserProperties = @{
    Dock = "Fill"
}
$Browser = New-Object System.Windows.Forms.WebBrowser -Property $BrowserProperties
$Form.Controls.Add($Browser)
$Browser.Navigate($AuthUri)
$Form.Add_Shown({$Form.Activate()})
$Form.ShowDialog()

Compelling stuff Kris, thanks for stopping by.

Running this will bring you to a login screen for Spotify. Once your credentials are in it will take you to some fantastic artwork by Jonathan Lindgren.

Feel free to bask in its glory, but to move forward with the script you will eventually have to close this browser.

Once you close that browser, your access token will be in $Browser.Url.Fragment. It will take a little work to clean up that data to make it usable. First, you need to use regular expressions to strip everything but the token value. Then, you need to specify the token type and create a header variable.

If ($Browser.url.Fragment -match "access_token=(.*)&token") {$AccessToken = $Matches[1]}

$BearerToken = "Bearer $AccessToken"
$HeaderValue = @{Authorization = $BearerToken}

Now the we have the token the rest of the script is just the same command over and over. Invoke-RestMethod is the PowerShell cmdlet that lets you send HTTPS requests against a web service.

Each time you run the command you specify where you are making the request (URI), what you are doing (method), what you are sending over (body), and your access token (header).

That is it. Just use different variations of that command and it will let you grab your account, build a playlist, grab every genre, and get the three least listened to bands for each one.

Now that we have all the steps lets take a look at the completed script.

### Create uri for generating access request ###

$AuthUri = "https://accounts.spotify.com/en/authorize?" +
            "client_id=$clientid" +                                                                                     #Put the client ID from your web application here here
            "&redirect_uri=//www.pdq.com/aa/img/jonathan-lindgren-hipster-220x247-lossy30.gif" +         #Thanks to Jonathan Lindgren (www.jonathanlindgren.com) for use of that awesome gif
            "&scope=playlist-modify-public playlist-modify-private playlist-read-private playlist-read-collaborative" +
            "&response_type=token"

### Build Browser and request authentication ###

Add-Type -AssemblyName System.Windows.Forms
$FormProperties = @{
    Size = New-Object System.Drawing.Size(850, 675)
    StartPosition = "CenterScreen"
}

$Form = New-Object System.Windows.Forms.Form -Property $FormProperties
$BrowserProperties = @{
    Dock = "Fill"
}

$Browser = New-Object System.Windows.Forms.WebBrowser -Property $BrowserProperties

$Form.Controls.Add($Browser)
$Browser.Navigate($AuthUri)
$Form.Add_Shown({$Form.Activate()})
$Form.ShowDialog()

### Create access token variable and grab your user account information ###

If ($Browser.url.Fragment -match "access_token=(.*)&token") {$AccessToken = $Matches[1]}

$UserUri = "https://api.spotify.com/v1/me"
$BearerToken = "Bearer $AccessToken"
$HeaderValue = @{Authorization = $BearerToken}
$UserAccount = (Invoke-RestMethod -Uri $UserUri -Method Get -ContentType application\json -Headers $HeaderValue).href

### Build Playlist and get ID ###

$PlaylistUri = $UserAccount + "/playlists"
$NewPlaylist = @{
    name = "Before they are Popular"
    public = "true"
} | ConvertTo-Json

$PlaylistID = Invoke-RestMethod -Uri $PlaylistUri -Method Post -ContentType application/json -Headers $HeaderValue -Body $NewplayList

### Grab all genres seeds and select 5 random ones that have more than 10 bands associated with it ####

$GenreSeedUri = "https://api.spotify.com/v1/recommendations/available-genre-seeds"
$Genres = Invoke-RestMethod -Uri $GenreSeedUri -Headers $HeaderValue | Select-Object -ExpandProperty genres
$GenreList = @()
foreach($Genre in $Genres){
    $GenreUri = "https://api.spotify.com/v1/search?q=genre:$Genre&type=artist&limit=5&market=us"
    $BandCount = (Invoke-RestMethod -Uri $GenreUri -ContentType Application/json -Headers $HeaderValue).artists.total
    if($BandCount -gt 10){
        $GenreList += $Genre
    }
    Write-Output "Generating list for: $Genre"
    Start-Sleep -Milliseconds 100
}

$FinalList = Get-Random -InputObject $GenreList -Count 5

### Grab 3 least popular band per genre ###

$Bands = @()
foreach($Item in $FinalList){
    $BandUri = "https://api.spotify.com/v1/search?q=genre:$($Item)&type=artist&type=artist&limit=5&market=us"
    $BandCount = [System.Math]::Round(((Invoke-RestMethod -Uri $BandUri -ContentType Application/json).artists.total - 3), 0)
    $OffsetUri = "https://api.spotify.com/v1/search?q=genre:$($Item)&type=artist&offset=$($BandCount)&limit=3&market=us"
    $LastThreeBands = (Invoke-RestMethod -Uri $OffsetUri -ContentType Application/json).artists.items | Select-Object name, id
    $Bands += $LastThreeBands
}

### Add top track from bands to playlist ###

Foreach($Band in $Bands){
    $TopTrackUri = "https://api.spotify.com/v1/artists/$($Band.id)/top-tracks?country=us"
    $TopTrack = (Invoke-RestMethod -Uri $TopTrackUri -ContentType Application/json).tracks | Select-Object uri
    if($TopTrack -ne $null){
         $CombinedTopTrack = $TopTrack.uri -join ','
         $AddTrackUri = $UserAccount + "/playlists/" + $PlaylistID.id + "/tracks?position=0&uris=$CombinedTopTrack"
         Invoke-RestMethod -Uri $AddTrackUri -Method Post -ContentType application/json -Headers $HeaderValue
    }
}

### List the 5 Genres used ###

Write-Host "You have created a playlist from the following genres: $FinalList"

Final note, should you want to do something useful with these commands the format would be the same. Just know that I used these commands before they were cool.

4 responses

  • After logging in to Spotify (with the started browser session) I get a HTTP 400 Bad Request. Anyone else has that problem? While re-running the script, I keep getting that error.

    • Unfortunately, we are unable to provide support with a 3rd party product. Although the presented script worked in our environment, we are unable to guarantee it will work with yours. We suggest contacting Spotify directly.

        • Hi Raoul,

          I think I have an idea of what may be going on here. In the bottom section where I put the entire script together I left off the very first line of the script. Try adding “$clientid = ” just below the comment on line one, using your client id from spotify.

          Try that out and let me know if you get the same result.

Respond to Jordan Hammond Cancel response

Your email address will not be published.

Your Name