diff --git a/librespot/core.py b/librespot/core.py index 0f67119..76720e7 100644 --- a/librespot/core.py +++ b/librespot/core.py @@ -11,8 +11,8 @@ from librespot.audio.storage import ChannelManager from librespot.cache import CacheManager from librespot.crypto import CipherPair, DiffieHellman, Packet from librespot.mercury import MercuryClient, MercuryRequests, RawMercuryRequest -from librespot.metadata import AlbumId, ArtistId, EpisodeId, ShowId, TrackId -from librespot.proto import Authentication_pb2 as Authentication, ClientToken_pb2 as ClientToken, Connect_pb2 as Connect, Connectivity_pb2 as Connectivity, Keyexchange_pb2 as Keyexchange, Metadata_pb2 as Metadata +from librespot.metadata import AlbumId, ArtistId, EpisodeId, ShowId, TrackId, PlaylistId +from librespot.proto import Authentication_pb2 as Authentication, ClientToken_pb2 as ClientToken, Connect_pb2 as Connect, Connectivity_pb2 as Connectivity, Keyexchange_pb2 as Keyexchange, Metadata_pb2 as Metadata, Playlist4External_pb2 as Playlist4External from librespot.proto.ExplicitContentPubsub_pb2 import UserAttributesUpdate from librespot.structure import Closeable, MessageListener, RequestListener, SubListener import base64 @@ -154,6 +154,18 @@ class ApiClient(Closeable): proto.ParseFromString(body) return proto + def get_playlist(self, _id: PlaylistId) -> Playlist4External.SelectedListContent: + response = self.send("GET", + "/playlist/v2/playlist/{}".format(_id.id()), None, + None) + ApiClient.StatusCodeException.check_status(response) + body = response.content + if body is None: + raise IOError() + proto = Playlist4External.SelectedListContent() + proto.ParseFromString(body) + return proto + def set_client_token(self, client_token): self.__client_token_str = client_token diff --git a/librespot/metadata.py b/librespot/metadata.py index fe64342..413117f 100644 --- a/librespot/metadata.py +++ b/librespot/metadata.py @@ -62,6 +62,29 @@ class PlayableId: raise NotImplementedError +class PlaylistId(SpotifyId): + base62 = Base62.create_instance_with_inverted_character_set() + pattern = re.compile(r"spotify:playlist:(.{22})") + __id: str + + def __init__(self, _id: str): + self.__id = _id + + @staticmethod + def from_uri(uri: str) -> PlaylistId: + matcher = PlaylistId.pattern.search(uri) + if matcher is not None: + playlist_id = matcher.group(1) + return PlaylistId(playlist_id) + raise TypeError("Not a Spotify playlist ID: {}.".format(uri)) + + def id(self) -> str: + return self.__id + + def to_spotify_uri(self) -> str: + return "spotify:playlist:" + self.__id + + class UnsupportedId(PlayableId): uri: str