python-tidal icon indicating copy to clipboard operation
python-tidal copied to clipboard

Is there anyway to modify playlists?

Open tcm151 opened this issue 5 years ago • 11 comments

tcm151 avatar Dec 13 '19 19:12 tcm151

Not right now, shouldn't be too difficult to add it though.

morguldir avatar Dec 13 '19 23:12 morguldir

Following on this, is there any way to add a playlist to a user? Or duplicate it?

bjesus avatar Jan 04 '20 18:01 bjesus

Here is a short script for the time in between the versions that shows how to edit playlists. Create a playlist, add a song, delete the song and delete the playlist again. Should also work with multiple songs.

import tidalapi
from time import sleep

session = tidalapi.Session()
uname = "[email protected]"
pw="password"

try:
    session.login(uname,pw)
except:
    print("Couldn't login to Tidal!")
    sleep(3)
    exit()

uid = session.user.id

# Create new playlist
result = session.request('POST','users/%s/playlists' % uid ,data={'title': 'testauto'})
print(result)

# Get playlist name
playlists = session.get_user_playlists(uid)

for i,ps in enumerate(playlists,1):
    print("[" +str(i)+ "] "+ps.name)

selection1 = int(input("Wähle Playlist Nummer : "))-1
playlist_id = playlists[selection1].id
print(playlist_id)

# Add Tracks to playlist
track_id_list = ["33500418"]
to_index = 0
etag = session.request('GET','playlists/%s' % playlist_id).headers['ETag']
headers = {'if-none-match' : etag}
data = {
    'trackIds' : ",".join(track_id_list),
    'toIndex' : to_index
        }
result = session.request('POST', 'playlists/%s/tracks' % playlist_id, data = data ,headers = headers)
sleep(10)

# Delete track from Playlist
track_index_list=["0"]
etag = session.request('GET','playlists/%s/tracks' % playlist_id).headers['ETag']
headers = {'if-none-match' : etag}
track_index_string = ",".join(track_index_list)
result = session.request('DELETE','playlists/%s/tracks/%s'%(playlist_id,track_index_string),headers=headers)

# Delete Playlist
etag = session.request('GET','playlists/%s' % playlist_id).headers['ETag']
headers = {'if-none-match' : etag}
result = session.request('DELETE', 'playlists/%s' % playlist_id, headers = headers)
print( result )

Husky22 avatar Mar 24 '20 12:03 Husky22

Thanks @Husky22 for this! Was hoping for a more API-ish way to do this, but I guess meanwhile this can work too.

bjesus avatar Mar 24 '20 21:03 bjesus

Well I was working on integrating it into the api but as long as 0.7 isn't available I don't mind finishing it. But it's actually straight forward to integrate it into tidalapi. If it helps you i can update my fork tomorrow to provide you a more API-ish experience.

Husky22 avatar Mar 24 '20 21:03 Husky22

Please don't do this just for me 😅 I'll use the the above code example you posted and wait patiently for the 0.7 release. Thank you!

bjesus avatar Mar 25 '20 08:03 bjesus

Hi, could you execute code for adding songs to a playlist? I'm trying it but it doesn't work for me...

EDIT: oops! now I found the problem! The session.request() method doesn't have the headers parameter, but I just had to add it and pass it to the requests.request() call inside it. Now it works! 👏

By the way, how did you discover these endpoints? :)

You can ignore the rest of this message.


I was getting this error: TypeError: request() got an unexpected keyword argument 'headers'

If I removed the headers argument I got: requests.exceptions.HTTPError: 412 Client Error: Precondition Failed for url

fmaylinch avatar Apr 03 '20 16:04 fmaylinch

I took inspiration from the C# Tidal API OpenTidl. But how to get to these endpoints in general, I don't really know. The Node.js TidalAPI gives some hints on how to decrypt HTTPS traffic with Fiddler: https://github.com/lucaslg26/TidalAPI#obtain-the-tidal-token-needed-to-use-this-api I think this would be the way by observing the traffic of the original tidal app.

Husky22 avatar Apr 03 '20 17:04 Husky22

Thank you @Husky22 !

By the way, I implemented that method to add tracks to a playlist. I also fixed the Favorites.playlists() because it doesn't work. Maybe they removed that alternative path in /favorites, so maybe you just want to remove that method from Favorites.

Does it make sense to make a pull request? When do you think you're going to release the 0.7 version?

fmaylinch avatar Apr 03 '20 17:04 fmaylinch

Not very certain about when it will be released, but hopefully within the next months, so i think people can wait. I don't want to spend time looking at a pull request when it's just going to get removed either way. If you add tests so i can just git pull and run the tests i guess you can submit a PR, but i don't think it's worth the time for you either.

morguldir avatar Apr 11 '20 20:04 morguldir

Here's the script I used to add these methods. Serves my purposes for the moment; hope it helps.


class FavoritesExtended(Favorites):
    def add_playlist(self, playlist_name: str) -> str:

        url = (
            "https://listen.tidal.com/v1/users/"
            + str(self._session.user.id)
            + "/playlists"
        )

        r = requests.post(
            url,
            data={"title": playlist_name, "description": ""},
            headers={"x-tidal-sessionid": self._session.session_id},
        )
        r.raise_for_status()

        return r.json()["uuid"]

    def add_track_to_playlist(self, playlist_id: str, track_id: str) -> Response:

        url = urljoin(
            self._session._config.api_location, "playlists/%s/tracks" % playlist_id
        )

        return requests.request(
            "POST",
            url,
            data={"trackIds": track_id, "toIndex": 1},
            headers={
                "x-tidal-sessionid": self._session.session_id,
                "if-none-match": "*",
            },
            params={
                "sessionId": self._session.session_id,
                "countryCode": self._session.country_code,
                "limit": "999",
            },
        )

    def _remove_playlist(self, playlist_id: str) -> Response:

        playlist_url = "https://listen.tidal.com/v1/playlists/" + playlist_id

        return requests.delete(
            playlist_url, headers={"x-tidal-sessionid": self._session.session_id}
        )

cwe5590 avatar Dec 20 '20 17:12 cwe5590