This is a simple weekly-recommendation-playlist-updater-bot, or something along those lines.
#
Configuration
Some information is required for this script to function (mostly credentials for API’s):
config.ini
1
2
3
4
5
6
7
8
9
10
11
12
[listenbrainz]user=<listenbrainz username>[subsonic]url=<subsonic server url>user=<subsonic username>password=<subsonic password>playlist_id=<subsonic playlist id>[deemix]arl=<your deezer arl>server_url=<url of your deemix instance>
##
1. Fetching the recommendations from listenbrainz
The first step is to actually acquire the “createdfor” playlists from listenbrainz recommendation system, this is done with a simple GET request to https://api.listenbrainz.org/1/user/<username>/playlists/createdfor
defget_createdfor_playlists(username:str)->Sequence[Playlist]:url=urljoin(API,"/1/user/",username,"/playlists/createdfor")response=requests.get(url)ifresponse.status_code!=200:raiseValueError(f"Error fetching playlists for user, api returned status code not 200:\n{response.text}")returnplaylists=response.json()["playlists"]returnmap(lambdajson_playlist:Playlist(json_playlist["playlist"]),playlists)
##
2. Processing the recommendations
Now we can extract everything under the playlists key, giving us a list of all the recommendations playlists, from which we only really need the identifier.
Next step is the extraction of the mbid (musicbrainz ID) from the identifier url, which is easy, we only need to cut the url string at every / and return the last element.
defget_playlist(url:str)->Playlist:mbid=id_from_url(url)url=urljoin(API,"/1/playlist",mbid)response=requests.get(url)ifresponse.status_code!=200:raiseValueError(f"Error fetching playlists for user, api returned status code not 200:\n{response.text}")returnreturnPlaylist(response.json()["playlist"])
##
3. Turning this information in some usable data
Now we just need to get some more information since we only have the song titles and author names.
I’m using the deemix api for this because im lazy but you could also directly use deezer (which is a bit more work since you need to get an API key first, just open deezer an monitor the network traffic while searching).
To execute a search with deemix, send a get request to your-deemix-url/api/search?term=<query>
Almost done, by now we have all the song information we need.
We just need to truncate the playlist on your subsonic server (or not, your choice) and insert the tracks.
def__truncate_playlist(self,playlist_id:str)->bool:url=urljoin(self.server_url,"/rest/getPlaylist")params={"id":playlist_id}response=self.client.get(url,params=params)song_count=response.json().get("subsonic-response",{}).get("playlist",{}).get("songCount",0)ifsong_count==0:returnTrueurl=urljoin(self.server_url,"/rest/updatePlaylist")params={"playlistId":playlist_id,"songIndexToRemove":range(0,song_count)}print(f"Truncating {playlist_id} with {song_count} songs...")response=self.client.get(url,params=params)returnresponse.json().get("subsonic-response",{}).get("status","error")=="ok"
Last but not least we need to insert the songs into the playlist…