5 Commits

Author SHA1 Message Date
Tim Rae
a438cda72b Bump version to 1.0.4 2024-12-04 06:09:12 +09:00
Tim Rae
2f1985a42b Check for null playlists in filter 2024-12-04 05:46:30 +09:00
Tim Rae
bcf2bbca0d Add option to do auth manually on headless server (#88) 2024-10-26 11:12:47 +02:00
Tim Rae
457da1724f Bump version to 1.0.3 2024-10-14 01:25:58 +02:00
Tim Rae
4d7c3b0ef0 Filter out tracks which don't have valid album metadata
Apply a final sanity filter to tracklist to validate assumption in matching
algorithm that the album has certain fields available.

In most situations this filter is not necessary, but occasionally we do
seem to encounter tracks that have no album metadata
2024-10-14 01:25:48 +02:00
5 changed files with 13 additions and 8 deletions

View File

@@ -3,6 +3,7 @@ spotify:
client_secret: your_client_secret
username: your_spotify_username
redirect_uri: http://localhost:8888/callback
open_browser: True # Set to False if using a headless server environment
# uncomment this block if you want to only sync specific playlist IDs

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "spotify_to_tidal"
version = "1.0.2"
version = "1.0.4"
requires-python = ">= 3.10"
dependencies = [

View File

@@ -15,11 +15,12 @@ SPOTIFY_SCOPES = 'playlist-read-private, user-library-read'
def open_spotify_session(config) -> spotipy.Spotify:
credentials_manager = spotipy.SpotifyOAuth(username=config['username'],
scope=SPOTIFY_SCOPES,
client_id=config['client_id'],
client_secret=config['client_secret'],
redirect_uri=config['redirect_uri'],
requests_timeout=2)
scope=SPOTIFY_SCOPES,
client_id=config['client_id'],
client_secret=config['client_secret'],
redirect_uri=config['redirect_uri'],
requests_timeout=2,
open_browser=config.get('open_browser', True))
try:
credentials_manager.get_access_token(as_dict=False)
except spotipy.SpotifyOauthError:

View File

@@ -184,7 +184,8 @@ async def get_tracks_from_spotify_playlist(spotify_session: spotipy.Spotify, spo
print(f"Loading tracks from Spotify playlist '{spotify_playlist['name']}'")
items = await repeat_on_request_error( _fetch_all_from_spotify_in_chunks, lambda offset: _get_tracks_from_spotify_playlist(offset=offset, playlist_id=spotify_playlist["id"]))
track_filter = lambda item: item.get('type', 'track') == 'track' # type may be 'episode' also
return list(filter(track_filter, items))
sanity_filter = lambda item: 'album' in item and 'name' in item['album'] and 'artists' in item['album'] and len(item['album']['artists']) > 0
return list(filter(sanity_filter, filter(track_filter, items)))
def populate_track_match_cache(spotify_tracks_: Sequence[t_spotify.SpotifyTrack], tidal_tracks_: Sequence[tidalapi.Track]):
""" Populate the track match cache with all the existing tracks in Tidal playlist corresponding to Spotify playlist """
@@ -386,7 +387,7 @@ async def get_playlists_from_spotify(spotify_session: spotipy.Spotify, config):
playlists.extend([p for p in extra_result['items']])
# filter out playlists that don't belong to us or are on the exclude list
my_playlist_filter = lambda p: p['owner']['id'] == user_id
my_playlist_filter = lambda p: p and p['owner']['id'] == user_id
exclude_filter = lambda p: not p['id'] in exclude_list
return list(filter( exclude_filter, filter( my_playlist_filter, playlists )))

View File

@@ -24,6 +24,7 @@ def test_open_spotify_session(mocker):
"client_id": "test_client_id",
"client_secret": "test_client_secret",
"redirect_uri": "http://localhost/",
"open_browser": True,
}
# Create a mock SpotifyOAuth instance
@@ -41,6 +42,7 @@ def test_open_spotify_session(mocker):
client_secret="test_client_secret",
redirect_uri="http://localhost/",
requests_timeout=2,
open_browser=True,
)
# Assert that the Spotify instance was created