コード例 #1
0
    def find_track(self,
                   query: str,
                   limit: int = 5) -> tuple[bool, list[Track]]:
        self._logger.debug(f"Looking for Spotify track matching '{query}'")
        cache_persist = self._downloader.cache_persisted
        used_cache = False
        tracks = []
        # cache response and use cache if available
        key = f"{self.code}api query {query}"
        query_result = self._downloader.retrieve_object(cache_persist, key)
        if query_result is not None:
            used_cache = True
            query_result = query_result.get_value()
        else:
            query_status, query_result = self._client.query(query, limit)
            self._downloader.store_object(cache_persist, key, query_result)

        # stop if there are results
        if query_result and query_result["tracks"].get("items"):
            for song_hit in query_result["tracks"].get("items"):
                track = Track(
                    origin_code=self.code,
                    track_id=song_hit.get("id"),
                    title=song_hit.get("name"),
                    artists=[
                        artist.get("name")
                        for artist in song_hit.get("artists")
                    ],
                    info=song_hit,
                    query_strings=[],
                )

                tracks.append(track)
        return used_cache, tracks
コード例 #2
0
    def get_playlist_tracks(self, limit: Optional[int] = None) -> List[Track]:
        # build dates for urls
        current_time = datetime.now(tz=self._time_zone)
        current_day = current_time.date()

        url = self.build_url(
            "triplej",
            date_from=current_day - timedelta(days=8),
            date_to=current_day - timedelta(days=1),
        )

        # download track list
        tracks_data = self._downloader.download_json(
            self._downloader.cache_persisted, url)

        result = []
        for index, item in enumerate(tracks_data["items"]):
            title = item["title"]
            track_id = item["arid"]
            original_artists = item["artists"]

            # get primary artist and featured artists
            artist = ""
            featuring = ""
            for raw_artist in original_artists:
                if raw_artist["type"] == "primary":
                    artist = f'{artist}, {raw_artist["name"]}'
                elif raw_artist["type"] == "featured":
                    featuring = f'{artist}, {raw_artist["name"]}'
                else:
                    raise Exception(
                        f"Unrecognised artist {raw_artist['type']}, {artist}, {raw_artist['name']}."
                    )

            artists = [artist.strip(", ")]
            for i in featuring.split(", "):
                featured = i.strip(", ")
                if featured and featured not in artists:
                    artists.append(featured)

            # build track
            result.append(
                Track.create(
                    self.code,
                    track_id,
                    title,
                    artists,
                    {
                        "artists": artists,
                        "source_id": track_id,
                        "source_order": index + 1,
                        "original_track": title,
                        "original_artists": original_artists,
                    },
                ))

        self._logger.info(f"Retrieved {self.title} with {len(result)} tracks.")
        if limit is not None and 0 < limit < len(result):
            result = result[:limit]
        return result
コード例 #3
0
    def is_match(self, query_track: Track, result_track: Track) -> bool:
        query_new = Track.create(
            query_track.origin_code,
            query_track.track_id,
            query_track.title,
            query_track.artists,
            query_track.info,
        )
        query_title = slugify(query_new.title)
        query_artist = slugify(query_new.artists[0])
        query_featured = slugify(", ".join(query_new.artists[1:]))

        result_new = Track.create(
            result_track.origin_code,
            result_track.track_id,
            result_track.title,
            result_track.artists,
            result_track.info,
        )
        result_title = slugify(result_new.title)
        result_artist = slugify(result_new.artists[0])
        result_featured = slugify(", ".join(result_new.artists[1:]))

        match_title = query_title in result_title
        # match_artist = query_artist in result_artist
        match_featuring = query_featured in result_featured
        match_featuring2 = result_featured in query_featured

        equal_title = query_title == result_title
        equal_artist = query_artist == result_artist
        # equal_featuring = query_featured == result_featured

        has_featuring = query_featured and result_featured

        # these are the variations that are valid
        if equal_title and equal_artist and match_featuring and has_featuring:
            return True
        if match_title and equal_artist and match_featuring and not has_featuring:
            return True
        if (equal_title and equal_artist and has_featuring
                and (match_featuring or match_featuring2)):
            return True

        return False
コード例 #4
0
 def get_playlist_tracks(self,
                         playlist_id: str,
                         limit: Optional[int] = None) -> List[Track]:
     self._logger.info(f"Retrieving tracks for Spotify playlist.")
     status, content = self._client.get_playlist_tracks(playlist_id, limit)
     result = []
     for item in content.get("items", []):
         track = item.get("track", {})
         result.append(
             Track(
                 origin_code=self.code,
                 track_id=track.get("id"),
                 title=track.get("name"),
                 artists=[a.get("name") for a in track.get("artists")],
                 info=track,
                 query_strings=[],
             ))
     return result
コード例 #5
0
    def get_playlist_tracks(self, limit: Optional[int] = None) -> List[Track]:
        # get content
        url = self.build_url(api_key=self._api_key)

        # download track list
        tracks_data = self._downloader.download_json(self._downloader.cache_temp, url)

        result = []
        for index, item in enumerate(tracks_data["tracks"]["track"]):
            result.append(
                Track.create(
                    self.code,
                    item.get("url"),
                    item["name"],
                    [item["artist"]["name"]],
                    item,
                )
            )

        self._logger.info(f"Retrieved {self.title} with {len(result)} tracks.")
        if limit is not None and 0 < limit < len(result):
            result = result[:limit]
        return result
コード例 #6
0
    def get_playlist_tracks(self, limit: Optional[int] = None) -> List[Track]:
        # build dates for urls
        current_time = datetime.now(tz=self._time_zone)
        date_from = current_time - timedelta(days=7)
        date_to = current_time

        # download 4zzz programs
        programs = self._downloader.download_json(self._downloader.cache_temp,
                                                  self._url)

        tracks = {}

        # programs
        for program in programs:
            if program.get("archived"):
                continue
            program_name = program["name"]

            # episodes
            episodes_url = f"{program['programRestUrl']}/episodes"
            episodes = self._downloader.download_json(
                self._downloader.cache_temp, episodes_url)
            for episode in episodes or []:
                episode_start = datetime.strptime(
                    episode["start"],
                    "%Y-%m-%d %H:%M:%S").replace(tzinfo=self._time_zone)
                episode_end = datetime.strptime(
                    episode["end"],
                    "%Y-%m-%d %H:%M:%S").replace(tzinfo=self._time_zone)
                if (date_from > episode_start or date_to < episode_start
                        or date_from > episode_end or date_to < episode_end):
                    continue

                # playlist tracks
                playlist_url = f"{episode['episodeRestUrl']}/playlists"
                playlist_raw = self._downloader.download_json(
                    self._downloader.cache_persisted, playlist_url)
                for track in playlist_raw or []:
                    track_type = track["type"]
                    track_artist = track["artist"]
                    track_title = track["title"]
                    track_track = track["track"]

                    if track_type != "track":
                        raise Exception(
                            f"Track type is expected to be 'track', but is {track_type}."
                        )

                    if track_title != track_track:
                        raise Exception(
                            f"Title and track are expected to match, but do not: '{track_title}' != '{track_track}'"
                        )

                    track_key = "-".join([
                        slugify(track_artist, delim="-",
                                ascii=True).decode("utf-8"),
                        slugify(track_track, delim="-",
                                ascii=True).decode("utf-8"),
                    ])

                    item = {
                        "type":
                        track_type,
                        "id":
                        track["id"],
                        "artist":
                        track_artist,
                        "title":
                        track_title,
                        "track":
                        track_track,
                        "release":
                        track["release"],
                        "time":
                        track["time"],
                        "notes":
                        track["notes"],
                        "twitter":
                        track["twitterHandle"],
                        "is_australian":
                        track["contentDescriptors"]["isAustralian"],
                        "is_local":
                        track["contentDescriptors"]["isLocal"],
                        "is_female":
                        track["contentDescriptors"]["isFemale"],
                        "is_indigenous":
                        track["contentDescriptors"]["isIndigenous"],
                        "is_new":
                        track["contentDescriptors"]["isNew"],
                        "wikipedia":
                        track["wikipedia"],
                        "image":
                        track["image"],
                        "video":
                        track["video"],
                        "url":
                        track["url"],
                        "approximate_time":
                        track["approximateTime"],
                        "program_name":
                        program_name,
                        "episode_start":
                        episode_start,
                    }

                    if track_key in tracks:
                        tracks[track_key].append(item)
                    else:
                        tracks[track_key] = [item]

        # find the top 50 most played tracks
        most_played_tracks = sorted([(len(v), k, v)
                                     for k, v in tracks.items() if len(v) > 1],
                                    reverse=True)[:100]

        # build the source playlist tracks
        result = []
        for index, most_played_track in enumerate(most_played_tracks):
            play_count = most_played_track[0]
            track_id = most_played_track[1]
            track_info = most_played_track[2]

            info = self._build_info(track_id, play_count, track_info)

            title = info.get("title")
            artists = [info.get("artist")]
            result.append(
                Track.create(self.code, track_id, title, artists, info))

        self._logger.info(f"Retrieved {self.title} with {len(result)} tracks.")
        if limit is not None and 0 < limit < len(result):
            result = result[:limit]
        return result