def test_fetch(self, mock_paginated_endpoint_fetch): expected_tracks = [ Track(track_name="Strawberry Fields Forever", artist="The Beatles"), Track(track_name="Badge", artist="Cream"), Track(track_name="Black Dog", artist="Led Zeppelin"), ] mock_paginated_endpoint_fetch.return_value = [ { "recenttracks": { "track": [ { "name": "Strawberry Fields Forever", "artist": { "name": "The Beatles" }, }, { "name": "Badge", "artist": { "name": "Cream" } }, ], "@attr": { "totalPages": "2" }, } }, { "recenttracks": { "track": [{ "name": "Black Dog", "artist": { "name": "Led Zeppelin" } }], "@attr": { "totalPages": "2" }, } }, ] fetched_tracks = recent_tracks.fetch_recent_tracks( user=self.dummy_user, api_key=self.dummy_api_key) self.assertCountEqual(fetched_tracks, expected_tracks)
def filter_out_tracks_in_second_list(track_list_1, track_list_2): """Filters out tracks from track_list_1 that are also in track_list_2""" filtered_tracks = [ track_x for track_x in track_list_1 if not any( Track.are_equivalent(track_x, track_y) for track_y in track_list_2) ] return filtered_tracks
def test_fetch_single_page(self): expected_saved_tracks = [ Track(track_name="Penny Lane", artist="The Beatles", spotify_id="123456789") ] self.mock_spotify.current_user_saved_tracks = MagicMock() mock_saved_tracks_response = { "items": [{ "id": "123456789", "name": "Penny Lane", "artists": [{ "name": "The Beatles" }], }] } self.mock_spotify.current_user_saved_tracks.side_effect = [ mock_saved_tracks_response, { "items": [] }, ] fetched_saved_tracks = get_saved_tracks(self.mock_spotify) self.assertCountEqual(fetched_saved_tracks, expected_saved_tracks)
def test_fetch_multiple_pages(self): expected_saved_tracks = [ Track(track_name="Penny Lane", artist="The Beatles", spotify_id="123456789"), Track( track_name="A Day in the Life", artist="The Beatles", spotify_id="987654321", ), ] self.mock_spotify.current_user_saved_tracks = MagicMock() mock_saved_tracks_response_page_1 = { "items": [{ "id": "123456789", "name": "Penny Lane", "artists": [{ "name": "The Beatles" }], }] } mock_saved_tracks_response_page_2 = { "items": [{ "id": "987654321", "name": "A Day in the Life", "artists": [{ "name": "The Beatles" }], }] } self.mock_spotify.current_user_saved_tracks.side_effect = [ mock_saved_tracks_response_page_1, mock_saved_tracks_response_page_2, { "items": [] }, ] fetched_saved_tracks = get_saved_tracks(self.mock_spotify) self.assertCountEqual(fetched_saved_tracks, expected_saved_tracks)
def build_recommendations_playlist(): """Adds recommendations to the given Spotify user's playlist based on the given Last.fm user's recommendations""" setup_logging("recommendations.log") args = _extract_args() spotify = Spotify(auth=token.get_token( args.spotify_user, args.spotify_client_id_key, args.spotify_client_secret_key, )) recommendations = generate_recommendations( lastfm_user=args.lastfm_user, lastfm_api_key=args.lastfm_api_key, spotify=spotify, recommendation_services=args.recommendation_services, recommendation_period=args.recommendation_period, max_recommendations_per_top_track=args. max_recommendations_per_top_track, blacklisted_artists=args.blacklisted_artists, prefer_unheard_artists=args.prefer_unheard_artists, ) logging.info("Generating recommendations playlist...") tracks_for_playlist = [] while len(tracks_for_playlist) < args.playlist_size and len( recommendations) > 0: # Find and remove the recommendation from the list using a random choice, weighted based on the recommendation's rating value recommendation = choice(recommendations, p=_calculate_rating_weights(recommendations)) recommendations.remove(recommendation) if recommendation.spotify_id is None: # If we didn't get the recommendation directly from Spotify, we need to get the ID from there before we can add to the playlist search_results = search.search_for_tracks( spotify=spotify, query=recommendation.artist + " " + recommendation.track_name, ) if search_results and Track.are_equivalent(recommendation, search_results[0]): recommendation.spotify_id = search_results[0].spotify_id if recommendation.spotify_id is not None and not any( recommendation.artist == item.artist for item in tracks_for_playlist): logging.info("Adding " + str(recommendation)) tracks_for_playlist.append(recommendation) playlist.replace_tracks_in_playlist(spotify, args.playlist_name, tracks_for_playlist) logging.info("Done!")
def fetch_recent_tracks(user, api_key): """Fetches recent tracks for the given user""" logging.info("Fetching recent tracks for " + user) paginated_json_responses = fetch_paginated_response( URL, user, api_key, "recenttracks" ) recent_tracks = [] for json_response in paginated_json_responses: for track in json_response["recenttracks"]["track"]: recent_tracks.append(Track(parse_track_name(track), parse_artist(track))) logging.info("Fetched " + str(len(recent_tracks)) + " recent tracks") logging.debug("Fetched tracks: " + str(recent_tracks)) return recent_tracks
def filter_out_duplicates(tracks): """Filters out duplicate tracks from the given list (i.e. tracks that have the same track name and artist; see Track.are_equivalent)""" logging.info("Filtering out duplicates") logging.debug(str(len(tracks)) + " tracks before removing duplicates") tracks_without_duplicates = [] # We remove duplicates with a list comprehension rather than the traditional hack of using a set, since that # requires the object to be hashable; plus we only want to compare the track name/artist of each track, not # any of the other fields (eg: Spotify ID) which might in fact differ [ tracks_without_duplicates.append(track_x) for track_x in tracks if not any( Track.are_equivalent(track_x, track_y) for track_y in tracks_without_duplicates) ] logging.debug(str(len(tracks)) + " tracks after removing duplicates") return tracks_without_duplicates