Skip to content

Commit

Permalink
Support browsing "Featured playlists" (Fixes #240)
Browse files Browse the repository at this point in the history
  • Loading branch information
kingosticks committed Dec 21, 2019
1 parent 5b03de0 commit d47f53b
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 17 deletions.
41 changes: 33 additions & 8 deletions mopidy_spotify/browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
from mopidy import models

import spotify
from mopidy_spotify import countries, translator
from mopidy_spotify import countries, playlists, translator

logger = logging.getLogger(__name__)

ROOT_DIR = models.Ref.directory(uri="spotify:directory", name="Spotify")

_TOP_LIST_DIR = models.Ref.directory(uri="spotify:top", name="Top lists")
_YOUR_MUSIC_DIR = models.Ref.directory(uri="spotify:your", name="Your music")
_PLAYLISTS_DIR = models.Ref.directory(uri="spotify:playlists", name="Playlists")

_ROOT_DIR_CONTENTS = [
_TOP_LIST_DIR,
_YOUR_MUSIC_DIR,
_PLAYLISTS_DIR,
]

_TOP_LIST_DIR_CONTENTS = [
Expand All @@ -28,6 +30,10 @@
models.Ref.directory(uri="spotify:your:albums", name="Your albums"),
]

_PLAYLISTS_DIR_CONTENTS = [
models.Ref.directory(uri="spotify:playlists:featured", name="Featured"),
]

_TOPLIST_TYPES = {
"albums": spotify.ToplistType.ALBUMS,
"artists": spotify.ToplistType.ARTISTS,
Expand All @@ -47,8 +53,10 @@ def browse(*, config, session, web_client, uri):
return _TOP_LIST_DIR_CONTENTS
elif uri == _YOUR_MUSIC_DIR.uri:
return _YOUR_MUSIC_DIR_CONTENTS
elif uri.startswith("spotify:user:"):
return _browse_playlist(session, uri, config)
elif uri == _PLAYLISTS_DIR.uri:
return _PLAYLISTS_DIR_CONTENTS
elif uri.startswith("spotify:user:") or uri.startswith("spotify:playlist:"):
return _browse_playlist(session, web_client, uri, config)
elif uri.startswith("spotify:album:"):
return _browse_album(session, uri, config)
elif uri.startswith("spotify:artist:"):
Expand All @@ -70,16 +78,18 @@ def browse(*, config, session, web_client, uri):
parts = uri.replace("spotify:your:", "").split(":")
if len(parts) == 1:
return _browse_your_music(web_client, variant=parts[0])
elif uri.startswith("spotify:playlists:"):
parts = uri.replace("spotify:playlists:", "").split(":")
if len(parts) == 1:
return _browse_playlists(web_client, variant=parts[0])

logger.info(f"Failed to browse {uri!r}: Unknown URI type")
return []


def _browse_playlist(session, uri, config):
sp_playlist = session.get_playlist(uri)
sp_playlist.load(config["timeout"])
return list(
translator.to_track_refs(sp_playlist.tracks, timeout=config["timeout"])
def _browse_playlist(session, web_client, uri, config):
return playlists.playlist_lookup(
session, web_client, uri, config["bitrate"], as_items=True
)


Expand Down Expand Up @@ -212,3 +222,18 @@ def _browse_your_music(web_client, variant):
return list(translator.web_to_album_refs(items))
else:
return []


def _browse_playlists(web_client, variant):
if not web_client.logged_in:
return []

if variant == "featured":
items = (
web_client.get_one(f"browse/{variant}")
.get("playlists", {})
.get("items", [])
)
return list(translator.to_playlist_refs(items))
else:
return []
3 changes: 2 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from mopidy import models

import spotify
from mopidy_spotify import backend, library, utils, web
from mopidy_spotify import backend, library, utils, playlists, web


@pytest.yield_fixture()
Expand Down Expand Up @@ -428,4 +428,5 @@ def backend_listener_mock():

@pytest.fixture
def provider(backend_mock):
playlists._sp_links.clear()
return library.SpotifyLibraryProvider(backend_mock)
41 changes: 33 additions & 8 deletions tests/test_browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ def test_has_a_root_directory(provider):
def test_browse_root_directory(provider):
results = provider.browse("spotify:directory")

assert len(results) == 2
assert len(results) == 3
assert models.Ref.directory(uri="spotify:top", name="Top lists") in results
assert (
models.Ref.directory(uri="spotify:your", name="Your music") in results
)
assert (
models.Ref.directory(uri="spotify:playlists", name="Playlists")
in results
)


def test_browse_top_lists_directory(provider):
Expand Down Expand Up @@ -53,18 +57,25 @@ def test_browse_your_music_directory(provider):
)


def test_browse_playlist(
session_mock, sp_playlist_mock, sp_track_mock, provider
):
session_mock.get_playlist.return_value = sp_playlist_mock
sp_playlist_mock.tracks = [sp_track_mock, sp_track_mock]
def test_browse_playlists_directory(provider):
results = provider.browse("spotify:playlists")

assert len(results) == 1
assert (
models.Ref.directory(uri="spotify:playlists:featured", name="Featured")
in results
)


def test_browse_playlist(web_client_mock, web_playlist_mock, provider):
web_client_mock.get_playlist.return_value = web_playlist_mock

results = provider.browse("spotify:user:alice:playlist:foo")

session_mock.get_playlist.assert_called_once_with(
web_client_mock.get_playlist.assert_called_once_with(
"spotify:user:alice:playlist:foo"
)
assert len(results) == 2
assert len(results) == 1
assert results[0] == models.Ref.track(
uri="spotify:track:abc", name="ABC 123"
)
Expand Down Expand Up @@ -457,3 +468,17 @@ def test_browse_your_music_albums(web_client_mock, web_album_mock, provider):
assert results[0] == models.Ref.album(
uri="spotify:album:def", name="DEF 456"
)


def test_browse_playlists_featured(
web_client_mock, web_playlist_mock, provider
):
web_client_mock.get_one.return_value = {
"playlists": {"items": [web_playlist_mock]}
}

results = provider.browse("spotify:playlists:featured")

assert len(results) == 1
assert results[0].name == "Foo"
assert results[0].uri == "spotify:user:alice:playlist:foo"

0 comments on commit d47f53b

Please sign in to comment.