示例#1
0
def test_search_any(library, client_mock):
    client_mock.search.return_value = client_mock.SearchResult({
        "responseHeader": {
            "params": {
                "query": "album"
            }
        },
        "response": {
            "docs": [
                {
                    "identifier": "album1",
                    "title": "Album #1",
                    "mediatype": "audio",
                },
                {
                    "identifier": "album2",
                    "title": "Album #2",
                    "mediatype": "etree",
                },
            ],
            "numFound":
            2,
        },
    })
    result = library.search(dict(any=["album"]))
    assert client_mock.search.called_once()
    assert result == models.SearchResult(
        uri="internetarchive:?q=album",
        albums=[
            models.Album(name="Album #1", uri="internetarchive:album1"),
            models.Album(name="Album #2", uri="internetarchive:album2"),
        ],
    )
示例#2
0
    def search(self, query):
        """Search Emby for a term.

        :param query: Search query
        :type query: dict
        :returns: Search results
        :rtype: mopidy.models.SearchResult
        """
        logger.debug('Searching in Emby for {}'.format(query))

        # something to store the results in
        data = []
        tracks = []
        albums = []
        artists = []

        for itemtype, term in query.items():

            for item in term:

                data.extend(self._get_search(itemtype, item))

        # walk through all items and create stuff
        for item in data:

            if item['Type'] == 'Audio':

                track_artists = [
                    models.Artist(name=artist) for artist in item['Artists']
                ]

                tracks.append(
                    models.Track(uri='emby:track:{}'.format(item['ItemId']),
                                 track_no=item.get('IndexNumber'),
                                 name=item.get('Name'),
                                 artists=track_artists,
                                 album=models.Album(name=item.get('Album'),
                                                    artists=track_artists)))

            elif item['Type'] == 'MusicAlbum':
                album_artists = [
                    models.Artist(name=artist) for artist in item['Artists']
                ]

                albums.append(
                    models.Album(uri='emby:album:{}'.format(item['ItemId']),
                                 name=item.get('Name'),
                                 artists=album_artists))

            elif item['Type'] == 'MusicArtist':
                artists.append(
                    models.Artist(uri='emby:artist:{}'.format(item['ItemId']),
                                  name=item.get('Name')))

        return models.SearchResult(uri='emby:search',
                                   tracks=tracks,
                                   artists=artists,
                                   albums=albums)
示例#3
0
    def get_search_tracks(self, artist_ref, album_id):
        tracks = []

        url = self.api_url(
            '/Items?IncludeItemTypes=Audio&Recursive=true&'
            'AlbumIds={}&UserId={}&'.format(
                album_id, self.user_id
            )
        )

        result = self.http.get(url)
        if result:
            raw_tracks = result.get('Items')

        if artist_ref:
            # If the artist was in the query,
            # ensure all tracks belong to that artist
            tracks = [
                models.Track(
                    uri='jellyfin:track:{}'.format(item.get('Id')),
                    track_no=item.get('IndexNumber'),
                    disc_no=track.get('ParentIndexNumber'),
                    name=item.get('Name'),
                    artists=artist_ref,
                    album=models.Album(
                        name=item.get('Album'),
                        artists=artist_ref
                    )
                )
                for item in raw_tracks
                if unidecode(artist_ref[0].name.lower()) in (
                    artist.lower() for artist in item.get('Artists'))
            ]
        else:
            # If the query doesn't contain an artist, return all tracks
            tracks = [
                models.Track(
                    uri='jellyfin:track:{}'.format(item.get('Id')),
                    track_no=item.get('IndexNumber'),
                    name=item.get('Name'),
                    artists=artist_ref,
                    album=models.Album(
                        name=item.get('Album'),
                        artists=artist_ref
                    )
                )
                for item in raw_tracks
            ]

        return tracks
示例#4
0
def test_track_playback_ended_scrobbles_played_track(pylast_mock, frontend):
    frontend.last_start_time = 123
    frontend.lastfm = mock.Mock(spec=pylast.LastFMNetwork)
    artists = [models.Artist(name="ABC"), models.Artist(name="XYZ")]
    album = models.Album(name="The Collection")
    track = models.Track(
        name="One Two Three",
        artists=artists,
        album=album,
        track_no=3,
        length=180432,
        musicbrainz_id="123-456",
    )
    tl_track = models.TlTrack(track=track, tlid=17)

    frontend.track_playback_ended(tl_track, 150000)

    frontend.lastfm.scrobble.assert_called_with(
        "ABC, XYZ",
        "One Two Three",
        "123",
        duration="180",
        album="The Collection",
        track_number="3",
        mbid="123-456",
    )
示例#5
0
def _album(obj):
    try:
        name = obj["Album"]
    except KeyError:
        return None
    else:
        return models.Album(name=name, uri=None)
示例#6
0
def album():
    return models.Album(
        uri='podcast+http://www.example.com/everything.xml',
        name='All About Everything',
        artists=[models.Artist(name='John Doe')],
        num_tracks=3
    )
示例#7
0
def mopidy_album_mock(mopidy_artist_mock):
    return models.Album(
        artists=[mopidy_artist_mock],
        date="2001",
        name="DEF 456",
        uri="spotify:album:def",
    )
示例#8
0
def album(obj):
    return models.Album(
        uri=obj["URI"],
        name=obj["DisplayName"],
        artists=list(_artists(obj)),
        num_tracks=obj.get("ItemCount", obj.get("ChildCount")),
    )
示例#9
0
def album(obj):
    return models.Album(
        uri=obj['URI'],
        name=obj['DisplayName'],
        artists=list(_artists(obj)),
        num_tracks=obj.get('ItemCount', obj.get('ChildCount')),
    )
示例#10
0
    def lookup(self, uri):
        pandora_uri = PandoraUri.factory(uri)
        logger.info("Looking up Pandora {} {}...".format(
            pandora_uri.uri_type, pandora_uri.uri))
        if isinstance(pandora_uri, SearchUri):
            # Create the station first so that it can be browsed.
            station_uri = self._create_station_for_token(pandora_uri.token)
            track = self._browse_tracks(station_uri.uri)[0]

            # Recursive call to look up first track in station that was searched for.
            return self.lookup(track.uri)

        track_kwargs = {"uri": uri}
        (album_kwargs, artist_kwargs) = {}, {}

        if isinstance(pandora_uri, TrackUri):
            try:
                track = self.lookup_pandora_track(uri)
            except KeyError:
                logger.exception(f"Failed to lookup Pandora URI '{uri}'.")
                return []
            else:
                if isinstance(pandora_uri, AdItemUri):
                    track_kwargs["name"] = "Advertisement"

                    if not track.title:
                        track.title = "(Title not specified)"
                    artist_kwargs["name"] = track.title

                    if not track.company_name:
                        track.company_name = "(Company name not specified)"
                    album_kwargs["name"] = track.company_name
                else:
                    track_kwargs["name"] = track.song_name
                    track_kwargs["length"] = track.track_length * 1000
                    try:
                        track_kwargs["bitrate"] = int(track.bitrate)
                    except TypeError:
                        # Bitrate not specified for this stream, ignore.
                        pass
                    artist_kwargs["name"] = track.artist_name
                    album_kwargs["name"] = track.album_name
        elif isinstance(pandora_uri, StationUri):
            station = self.backend.api.get_station(pandora_uri.station_id)
            track_kwargs["name"] = station.name
            artist_kwargs["name"] = "Pandora Station"
            album_kwargs["name"] = ", ".join(station.genre)
        else:
            raise ValueError(
                "Unexpected type to perform Pandora track lookup: {}.".format(
                    pandora_uri.uri_type))

        artist_kwargs[
            "uri"] = uri  # Artist lookups should just point back to the track itself.
        track_kwargs["artists"] = [models.Artist(**artist_kwargs)]
        album_kwargs[
            "uri"] = uri  # Album lookups should just point back to the track itself.
        track_kwargs["album"] = models.Album(**album_kwargs)
        return [models.Track(**track_kwargs)]
示例#11
0
    def create_album(self, item):
        """Create album object from Jellyfin item.

        :param track: item
        :type track: dict
        :returns: Album
        :rtype: mopidy.models.Album
        """
        item_type = item.get('Type')
        if item_type == 'Audio':
            return models.Album(name=item.get('Album'),
                                artists=self.create_artists(item),
                                uri=f'jellyfin:album:{item.get("AlbumId")}')
        elif item_type == 'MusicAlbum':
            return models.Album(name=item.get('Name'),
                                artists=self.create_artists(item),
                                uri=f'jellyfin:album:{item.get("Id")}')
def test_search(config, library, results):
    responses.add(responses.GET, re.compile(r'.*/search\b.*'), json=results)
    assert library.search({'any': ['foo']}) == models.SearchResult(
        albums=[
            models.Album(name='Foo', uri='podcast+http://example.com/feed1234')
        ],
        tracks=[
            models.Track(
                name='Bar',
                uri='podcast+http://example.com/feed1234#5678',
                album=models.Album(
                    name='Foo',
                    uri='podcast+http://example.com/feed1234'
                )
            )
        ]
    )
示例#13
0
def web_to_album(web_album):
    artists = [
        web_to_artist(web_artist) for web_artist in web_album['artists']]

    return models.Album(
        uri=web_album['uri'],
        name=web_album['name'],
        artists=artists)
示例#14
0
    def lookup(self, uri):
        pandora_uri = PandoraUri.factory(uri)
        if isinstance(pandora_uri, SearchUri):
            # Create the station first so that it can be browsed.
            station_uri = self._create_station_for_token(pandora_uri.token)
            track = self._browse_tracks(station_uri.uri)[0]

            # Recursive call to look up first track in station that was searched for.
            return self.lookup(track.uri)

        if isinstance(pandora_uri, TrackUri):
            try:
                track = self.lookup_pandora_track(uri)
            except KeyError:
                logger.exception(
                    "Failed to lookup Pandora URI '{}'.".format(uri))
                return []
            else:
                track_kwargs = {'uri': uri}
                (album_kwargs, artist_kwargs) = {}, {}
                # TODO: Album.images has been deprecated in Mopidy 1.2. Remove this code when all frontends have been
                #       updated to make use of the newer LibraryController.get_images()
                images = self.get_images([uri])[uri]
                if len(images) > 0:
                    album_kwargs = {'images': [image.uri for image in images]}

                if isinstance(pandora_uri, AdItemUri):
                    track_kwargs['name'] = 'Advertisement'

                    if not track.title:
                        track.title = '(Title not specified)'
                    artist_kwargs['name'] = track.title

                    if not track.company_name:
                        track.company_name = '(Company name not specified)'
                    album_kwargs['name'] = track.company_name
                else:
                    track_kwargs['name'] = track.song_name
                    track_kwargs['length'] = track.track_length * 1000
                    try:
                        track_kwargs['bitrate'] = int(track.bitrate)
                    except TypeError:
                        # Bitrate not specified for this stream, ignore.
                        pass
                    artist_kwargs['name'] = track.artist_name
                    album_kwargs['name'] = track.album_name
        else:
            raise ValueError(
                'Unexpected type to perform Pandora track lookup: {}.'.format(
                    pandora_uri.uri_type))

        artist_kwargs[
            'uri'] = uri  # Artist lookups should just point back to the track itself.
        track_kwargs['artists'] = [models.Artist(**artist_kwargs)]
        album_kwargs[
            'uri'] = uri  # Album lookups should just point back to the track itself.
        track_kwargs['album'] = models.Album(**album_kwargs)
        return [models.Track(**track_kwargs)]
示例#15
0
    def test_default_get_images_impl_falls_back_to_album_image(self):
        album = models.Album(images=['imageuri'])
        track = models.Track(uri='trackuri', album=album)

        library = dummy_backend.DummyLibraryProvider(backend=None)
        library.dummy_library.append(track)

        expected = {'trackuri': [models.Image(uri='imageuri')]}
        self.assertEqual(library.get_images(['trackuri']), expected)
示例#16
0
    def create_album(self, track):
        """Create album object from track.

        :param track: Track
        :type track: dict
        :returns: Album
        :rtype: mopidy.models.Album
        """
        return models.Album(name=track.get('Album'),
                            artists=self.create_artists(track))
示例#17
0
    def get_albums(self, query):
        raw_artist = [""]
        raw_albums = []

        # Check query for artist name
        if 'artist' in query:
            raw_artist = query.get('artist')
        elif 'albumartist' in query:
            raw_artist = query.get('albumartist')
        else:
            return []

        # URL encode artist string
        artist = quote(raw_artist[0].encode('utf8')).replace('/', '-')
        artist_ref = [models.Artist(name=raw_artist[0])]
        url = self.api_url(
            '/Artists/{}?UserId={}'.format(
                artist, self.user_id)
        )

        # Pull out artist_id
        artist_data = self.http.get(url)
        artist_id = artist_data.get('Id')

        # Get album list
        if self.albumartistsort:
            url = self.api_url(
                '/Items?AlbumArtistIds={}&UserId={}&'
                'IncludeItemTypes=MusicAlbum&Recursive=true'.format(
                    artist_id, self.user_id
                )
            )
        else:
            url = self.api_url(
                '/Items?ArtistIds={}&UserId={}&'
                'IncludeItemTypes=MusicAlbum&Recursive=true'.format(
                    artist_id, self.user_id
                )
            )

        result = self.http.get(url)
        if result:
            raw_albums = result.get('Items')

        albums = [
            models.Album(
                uri='jellyfin:album:{}'.format(item.get('Id')),
                name=item.get('Name'),
                artists=artist_ref
            )
            for item in raw_albums
        ]

        return albums
示例#18
0
def to_album(qobuz_album):
    if qobuz_album is None:
        return

    artist = to_artist(qobuz_album.artist)

    return models.Album(
        uri="qobuz:album:" + str(qobuz_album.id),
        name=qobuz_album.title,
        artists=[artist],
    )
示例#19
0
 def compose_bt_track(self, uri=BTPlayerUri.BT_SONG):
     # Old behaviour -> Use real track data on lookup
     # Since track data are immutable, it is hacky to change the data on track changes
     # New behaviour -> Use track structure with the device name and info
     if not self.bt_player.is_connected():
         return None
     dev_name = unicode(self.bt_player.get_device_name())
     bt_info = {'name': dev_name,
                'artists': [models.Artist(name='Bluetooth Player')],
                'album': models.Album(name=dev_name, uri=BTPlayerUri.BT_DEVICE),
                'uri': uri}
     return models.Track(**bt_info)
示例#20
0
def web_to_album(web_album):
    ref = web_to_album_ref(web_album)
    if ref is None:
        return

    artists = [
        web_to_artist(web_artist)
        for web_artist in web_album.get("artists", [])
    ]
    artists = [a for a in artists if a]

    return models.Album(uri=ref.uri, name=ref.name, artists=artists)
示例#21
0
 def translate_track_data(bt_track_data, uri):
     if bt_track_data:
         mp_track_data = {
             'uri': uri,
             'name': unicode(bt_track_data.get('Title', '')),
             'artists': [models.Artist(name=unicode(bt_track_data.get('Artist')))],
             'album': models.Album(name=unicode(bt_track_data.get('Album'))),
             'length': int(bt_track_data.get('Duration')) if bt_track_data.get('Duration') != 0xFFFFFFFF else None,
             'genre': unicode(bt_track_data.get('Genre'))}
         return models.Track(**mp_track_data)
     else:
         return {}
示例#22
0
    def lookup(self, uri):
        if not uri.startswith("transistor:"):
            return []

        if uri == "transistor:noise":
            return [models.Track(name="Random Noise", uri=uri)]

        split_uri = uri.split(":")

        if len(split_uri) == 4:
            if split_uri[1] == "radios":
                bank_radios = self.lib.data["radio_banks"][split_uri[2]]
                for rad in bank_radios:
                    if rad["position"] == int(split_uri[3]):
                        return [
                            models.Track(
                                name=rad["name"],
                                uri=uri,
                                artists=[models.Artist(name=rad["name"])],
                                album=models.Album(name=split_uri[2]),
                            )
                        ]

            if split_uri[1] == "podcasts":
                for podcast in self.lib.data["podcasts"]:
                    if podcast["position"] == int(split_uri[2]):
                        for ep in podcast["episodes"]:
                            if split_uri[3] == ep["title"]:
                                return [
                                    models.Track(
                                        name=ep["title"],
                                        uri=uri,
                                        artists=[
                                            models.Artist(name=podcast["name"])
                                        ],
                                        album=models.Album(name=""),
                                    )
                                ]

        return []
示例#23
0
    def test_successful_translation(self, web_track_mock):
        track = translator.web_to_track(web_track_mock)

        assert track.uri == 'spotify:track:abc'
        assert track.name == 'ABC 123'
        assert list(track.artists) == [
            models.Artist(uri='spotify:artist:abba', name='ABBA')
        ]
        assert track.album == models.Album(uri='spotify:album:def',
                                           name='DEF 456')
        assert track.track_no == 7
        assert track.disc_no == 1
        assert track.length == 174300
示例#24
0
    def test_successful_translation(self, web_track_mock):
        track = translator.web_to_track(web_track_mock)

        artists = [models.Artist(uri="spotify:artist:abba", name="ABBA")]

        assert track.uri == "spotify:track:abc"
        assert track.name == "ABC 123"
        assert list(track.artists) == artists
        assert track.album == models.Album(uri="spotify:album:def",
                                           name="DEF 456",
                                           artists=artists)
        assert track.track_no == 7
        assert track.disc_no == 1
        assert track.length == 174300
示例#25
0
 def _build_user_albums(self, user):
     return [
         models.Album(
             uri='lastfm:user-album:{0}'.format(
                 self._generate_uri_tail(user.name,
                                         limit=self.limit,
                                         period=period)
             ),
             name=self._generate_name(user.name,
                                     limit=self.limit,
                                     period=period),
         )
         for period in self.ALL_PERIODS
     ]
示例#26
0
def web_to_album(web_album):
    ref = web_to_album_ref(web_album)
    if ref is None:
        return

    artists = [
        web_to_artist(web_artist) for web_artist in web_album.get("artists", [])
    ]
    artists = [a for a in artists if a]

    # Note: date can by YYYY-MM-DD, YYYY-MM or YYYY.
    date = web_album.get("release_date", "").split("-")[0] or None

    return models.Album(uri=ref.uri, name=ref.name, artists=artists, date=date)
示例#27
0
 def tracks(self, newest_first=False):
     album = models.Album(uri=self.uri,
                          name=self.__channel.findtext('title'),
                          artists=self.__artists(self.__channel),
                          num_tracks=len(self.__items))
     genre = self.__genre(self.__channel)
     items = enumerate(self.__items, start=1)
     for index, item in (reversed(list(items)) if newest_first else items):
         yield models.Track(uri=self.getitemuri(self.__guid(item)),
                            name=item.findtext('title'),
                            album=album,
                            artists=(self.__artists(item) or album.artists),
                            genre=genre,
                            date=self.__date(item),
                            length=self.__length(item),
                            comment=item.findtext('description'),
                            track_no=index)
def test_album(album=translator.album):
    model = models.Album(name="foo", uri="internetarchive:foo")
    assert model == album({"identifier": "foo"})
    assert model.replace(name="Foo") == album({
        "identifier": "foo",
        "title": "Foo"
    })
    assert model.replace(artists=[models.Artist(name="bar")]) == album({
        "identifier":
        "foo",
        "creator":
        "bar"
    })
    assert model.replace(date="1970-01-01") == album({
        "identifier": "foo",
        "date": "1970-01-01"
    })
示例#29
0
def to_album(sp_album):
    if not sp_album.is_loaded:
        return

    if sp_album.artist is not None and sp_album.artist.is_loaded:
        artists = [to_artist(sp_album.artist)]
    else:
        artists = []

    if sp_album.year is not None and sp_album.year != 0:
        date = f"{sp_album.year}"
    else:
        date = None

    return models.Album(
        uri=sp_album.link.uri, name=sp_album.name, artists=artists, date=date
    )
示例#30
0
    def test_successful_translation(self, sp_track_mock):
        track = translator.to_track(sp_track_mock, bitrate=320)

        assert track.uri == 'spotify:track:abc'
        assert track.name == 'ABC 123'
        assert list(track.artists) == [
            models.Artist(uri='spotify:artist:abba', name='ABBA')
        ]
        assert track.album == models.Album(
            uri='spotify:album:def',
            name='DEF 456',
            artists=[models.Artist(uri='spotify:artist:abba', name='ABBA')],
            date='2001')
        assert track.track_no == 7
        assert track.disc_no == 1
        assert track.date == '2001'
        assert track.length == 174300
        assert track.bitrate == 320