Skip to content

Commit

Permalink
Podcast endpoints, library, search and player
Browse files Browse the repository at this point in the history
  • Loading branch information
felix-hilden committed Apr 2, 2020
1 parent 863e3a3 commit 1af3152
Show file tree
Hide file tree
Showing 25 changed files with 653 additions and 75 deletions.
12 changes: 11 additions & 1 deletion tekore/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@
----------
.. autoclass:: SpotifyBrowse
:members:
:inherited-members:
Episode API
-----------
.. autoclass:: SpotifyEpisode
:members:
Follow API
----------
Expand Down Expand Up @@ -85,6 +89,12 @@
.. autoclass:: SpotifySearch
:members:
Show API
--------
.. autoclass:: SpotifyShow
:members:
Track API
---------
.. autoclass:: SpotifyTrack
Expand Down
2 changes: 2 additions & 0 deletions tekore/client/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from tekore.client.api.album import SpotifyAlbum
from tekore.client.api.artist import SpotifyArtist
from tekore.client.api.browse import SpotifyBrowse
from tekore.client.api.episode import SpotifyEpisode
from tekore.client.api.follow import SpotifyFollow
from tekore.client.api.library import SpotifyLibrary
from tekore.client.api.personalisation import SpotifyPersonalisation
from tekore.client.api.player import SpotifyPlayer
from tekore.client.api.playlist import SpotifyPlaylist
from tekore.client.api.search import SpotifySearch
from tekore.client.api.show import SpotifyShow
from tekore.client.api.track import SpotifyTrack
from tekore.client.api.user import SpotifyUser
55 changes: 55 additions & 0 deletions tekore/client/api/episode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from tekore.client.process import single, model_list
from tekore.client.chunked import chunked, join_lists
from tekore.client.decor import send_and_process
from tekore.client.base import SpotifyBase
from tekore.serialise import ModelList
from tekore.model import FullEpisode


class SpotifyEpisode(SpotifyBase):
@send_and_process(single(FullEpisode))
def episode(
self,
episode_id: str,
market: str = None
) -> FullEpisode:
"""
Get information for an episode.
Parameters
----------
episode_id
episode ID
market
an ISO 3166-1 alpha-2 country code
Returns
-------
FullEpisode
episode object
"""
return self._get('episodes/' + episode_id, market=market)

@chunked('episode_ids', 1, 50, join_lists)
@send_and_process(model_list(FullEpisode, 'episodes'))
def episodes(
self,
episode_ids: list,
market: str = None
) -> ModelList:
"""
Get information for multiple episodes.
Parameters
----------
episode_ids
the episode IDs, max 50 without chunking
market
an ISO 3166-1 alpha-2 country code
Returns
-------
ModelList
list of episode objects
"""
return self._get('episodes/?ids=' + ','.join(episode_ids), market=market)
84 changes: 83 additions & 1 deletion tekore/client/api/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from tekore.client.chunked import chunked, join_lists, return_none
from tekore.client.decor import send_and_process, maximise_limit
from tekore.client.base import SpotifyBase
from tekore.model import SavedAlbumPaging, SavedTrackPaging
from tekore.model import SavedAlbumPaging, SavedTrackPaging, SavedShowPaging


class SpotifyLibrary(SpotifyBase):
Expand Down Expand Up @@ -165,3 +165,85 @@ def saved_tracks_delete(self, track_ids: list) -> None:
list of track IDs, max 50 without chunking
"""
return self._delete('me/tracks/?ids=' + ','.join(track_ids))

@send_and_process(single(SavedShowPaging))
@maximise_limit(50)
def saved_shows(
self,
market: str = None,
limit: int = 20,
offset: int = 0
) -> SavedShowPaging:
"""
Get a list of the shows saved in the current user's Your Music library.
Requires the user-library-read scope.
Parameters
----------
market
an ISO 3166-1 alpha-2 country code or 'from_token'
limit
the number of items to return (1..50)
offset
the index of the first item to return
Returns
-------
SavedShowPaging
paging object containing saved shows
"""
return self._get('me/shows', market=market, limit=limit, offset=offset)

@chunked('show_ids', 1, 50, join_lists)
@send_and_process(nothing)
def saved_shows_contains(self, show_ids: list) -> List[bool]:
"""
Check if user has saved shows.
Requires the user-library-read scope.
Parameters
----------
show_ids
list of show IDs, max 50 without chunking
Returns
-------
list
list of booleans in the same order the show IDs were given
"""
return self._get('me/shows/contains?ids=' + ','.join(show_ids))

@chunked('show_ids', 1, 50, return_none)
@send_and_process(nothing)
def saved_shows_add(self, show_ids: list) -> None:
"""
Save shows for current user.
Requires the user-library-modify scope.
Parameters
----------
show_ids
list of show IDs, max 50 without chunking
"""
return self._put('me/shows/?ids=' + ','.join(show_ids))

@chunked('show_ids', 1, 50, return_none)
@send_and_process(nothing)
def saved_shows_delete(self, show_ids: list, market: str = None) -> None:
"""
Remove shows for current user.
Requires the user-library-modify scope.
Parameters
----------
show_ids
list of show IDs, max 50 without chunking
market
an ISO 3166-1 alpha-2 country code, only remove shows that are
available in the specified market, overrided by token's country
"""
return self._delete('me/shows/?ids=' + ','.join(show_ids), market=market)
6 changes: 3 additions & 3 deletions tekore/client/api/player/modify.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,16 @@ def playback_start_context(
@send_and_process(nothing)
def playback_queue_add(self, uri: str, device_id: str = None) -> None:
"""
Add a track to a user's queue.
Add a track or an episode to a user's queue.
Requires the user-modify-playback-state scope.
Parameters
----------
uri
resource to add, currently only tracks are supported
resource to add, track or episode
device_id
devide to add the track on
devide to extend the queue on
"""
return self._post('me/player/queue', uri=uri, device_id=device_id)

Expand Down
34 changes: 27 additions & 7 deletions tekore/client/api/player/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,67 @@ class SpotifyPlayerView(SpotifyBase):
@send_and_process(single(CurrentlyPlayingContext))
def playback(
self,
market: str = None
market: str = None,
additional_types: List[str] = None
) -> CurrentlyPlayingContext:
"""
Get information about user's current playback.
Requires the user-read-playback-state or
the user-read-currently-playing scope.
Requires the user-read-playback-state scope.
Parameters
----------
market
an ISO 3166-1 alpha-2 country code or 'from_token'
additional_types
item types to return, valid types are 'track' and 'episode',
types not specified are returned as None values
Returns
-------
CurrentlyPlayingContext
information about current playback
"""
return self._get('me/player', market=market)
if additional_types is not None:
additional_types = ','.join(additional_types)
return self._get(
'me/player',
market=market,
additional_types=additional_types
)

@send_and_process(single(CurrentlyPlaying))
def playback_currently_playing(
self,
market: str = None
market: str = None,
additional_types: List[str] = None
) -> CurrentlyPlaying:
"""
Get user's currently playing track.
Requires the user-read-playback-state scope.
Requires the user-read-playback-state or
the user-read-currently-playing scope.
Parameters
----------
market
an ISO 3166-1 alpha-2 country code or 'from_token'
additional_types
item types to return, valid types are 'track' and 'episode',
types not specified are returned as None values
Returns
-------
CurrentlyPlaying
information about the current track playing
"""
return self._get('me/player/currently-playing', market=market)
if additional_types is not None:
additional_types = ','.join(additional_types)
return self._get(
'me/player/currently-playing',
market=market,
additional_types=additional_types
)

@send_and_process(single(PlayHistoryPaging))
@maximise_limit(50)
Expand Down
16 changes: 10 additions & 6 deletions tekore/client/api/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@
FullTrackPaging,
SimpleAlbumPaging,
SimplePlaylistPaging,
SimpleEpisodePaging,
SimpleShowPaging,
)

paging_type = {
'artist': FullArtistOffsetPaging,
'album': SimpleAlbumPaging,
'playlist': SimplePlaylistPaging,
'track': FullTrackPaging,
'artists': FullArtistOffsetPaging,
'albums': SimpleAlbumPaging,
'episodes': SimpleEpisodePaging,
'playlists': SimplePlaylistPaging,
'shows': SimpleShowPaging,
'tracks': FullTrackPaging,
}


def search_result(json: dict):
"""
Unpack search result dicts into respective paging type constructors.
"""
return tuple(paging_type[key[:-1]](**json[key]) for key in json.keys())
return tuple(paging_type[key](**json[key]) for key in json.keys())


class SpotifySearch(SpotifyBase):
Expand All @@ -46,7 +50,7 @@ def search(
search query
types
resources to search for, tuple of strings containing
artist, album, track and/or playlist
artist, album, track, playlist, show and/or episode
market
an ISO 3166-1 alpha-2 country code or 'from_token'
limit
Expand Down
Loading

0 comments on commit 1af3152

Please sign in to comment.