I'm a big fan of Spotify's generated daily and genre-specific mixes in general. They're great to just have a nice list of music going without thinking too much what to play next, and I've discovered plenty of great new-to-me songs through them.
That said, I've come to absolutely loathe their inconsistency and disruption in the list handling.
One too many times I had a list I enjoyed replaced the next day with a near-identical duplicate of another, already existing list. And one too many times I had a horribly timed refreshing of a list mess up the whole vibe of it. Obviously, after repeat-listening a certain song or band for the last hours, it must clearly mean I've had enough of it, so let's make sure it won't be on the refreshed list anymore. @#%$@&!
Copying manually some songs to a dedicated playlist is an option, sure, but I don't really want to make it a chore to enjoy music.
To the rescue: smuffy!
smuffy waits for the user to select both a target playlist (any playlist the user owns) and a starting point (right now, a certain song in the play history, or simply the entire play history). Once done, smuffy adds all past songs from the starting point and all future songs from here on forward to the target playlist, preserving any generated mix in a dedicated playlist.
But it doesn't even need to be for that, got some upcoming event you want to have a memory of all the music played there? Tadaa - smuffy!
smuffy itself is just running in the background, and all interaction happens through a web UI it provides. There, you can select one of your existing playlists and start the whole process by pressing play.
On start, smuffy retrieves the selected playlist's content via /playlists/{playlist_id}
and keeps a copy of the relevant information around. It then periodically
- retrieves the list of last played songs via
/me/player/recently-played - compares the recently played songs against the ones already contained in the playlist
- collects the new songs in a list
- calls
/playlists/{playlist_id}/tracksto add them straight to the actual playlist - waits for a user-defined number of minutes to start over with that.
This will run for as long as you let it, i.e., until pressing stop on the web UI, which puts smuffy back in idle state, waiting for a new start signal - maybe you changed your mood and need a new playlist to record to.
- No authentication outside the Spotify API, once you're authenticated with Spotify, anyone with access to smuffy can use it
- Spotify limits the play history to 50 songs, so you can't copy your entire life
- Spotify adds only fully played songs to the list of recently played songs, so skipped songs will be ignored (which is kinda good though)
- By design, duplicate songs aren't added to the playlist, so recording the full, raw play history as-is isn't possible (this may be an option in the future)
- There's no playlist management implemented (nor planned at this point), so creating playlists, deleting songs or other rearrangements need to be done in Spotify
You'll need to set up your own Spotify app in their developer portal, and create an .env file with the information needed, if you wanna give it a try.
Note that Spotify enforces HTTPS for callback URLs other than localhost.
go build./smuffyNOTE: THERE IS NO USER AUTHENTICATION IN PLACE, SO YOU SHOULD NEVER RUN THIS PUBLICLY ACCESSIBLE IN ITS CURRENT STATE!
Go to your browser and visit http://localhost:58071
All configuration is currently done via .env file which is loaded on startup.
Following entries are supported and understood. Bold entries are mandatory, and the tool won't work without them.
SPOTIFY_ID=<string>to define your own Spotify app's IDSPOTIFY_SECRET=<string>same for the app's secret tokenSPOTIFY_REDIRECT_URL=<string>one of the app's defined callback urls, defaults to http://localhost:58071/callbackPLAYLIST_REQUEST_INTERVAL_MINUTES=<int>time interval to update the playlist with the last played songs, defaults to 10 minutesCACHE_AUTH_TOKEN=<int>set to1if Spotify auth token should be cached in a.cachefile to reuse it next time the tool is started, comment it out to request auth on every start