Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ config.yml
config.yaml
.cache*
.session.yml
/logs

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
51 changes: 38 additions & 13 deletions src/spotify_to_tidal/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import traceback
import unicodedata
import math
from pathlib import Path

from .type import spotify as t_spotify

Expand Down Expand Up @@ -261,25 +262,49 @@ async def _run_rate_limiter(semaphore):
return

# Search for each of the tracks on Tidal concurrently
task_description = "Searching Tidal for {}/{} tracks in Spotify playlist '{}'".format(len(tracks_to_search), len(spotify_tracks), playlist_name)
task_description = f"Searching Tidal for {len(tracks_to_search)}/{len(spotify_tracks)} tracks in Spotify playlist '{playlist_name}'"
semaphore = asyncio.Semaphore(config.get('max_concurrency', 10))
rate_limiter_task = asyncio.create_task(_run_rate_limiter(semaphore))
search_results = await atqdm.gather( *[ repeat_on_request_error(tidal_search, t, semaphore, tidal_session) for t in tracks_to_search ], desc=task_description )
search_results = await atqdm.gather(
*[repeat_on_request_error(tidal_search, t, semaphore, tidal_session) for t in tracks_to_search],
desc=task_description
)
rate_limiter_task.cancel()

# Add the search results to the cache
song404 = []
# Organize tracks not found in Tidal by playlist
song404_by_playlist = {}
color = ('\033[91m', '\033[0m')
for idx, spotify_track in enumerate(tracks_to_search):
if search_results[idx]:
track_match_cache.insert( (spotify_track['id'], search_results[idx].id) )
else:
song404.append(f"{spotify_track['id']}: {','.join([a['name'] for a in spotify_track['artists']])} - {spotify_track['name']}")
color = ('\033[91m', '\033[0m')
print(color[0] + "Could not find the track " + song404[-1] + color[1])
file_name = "songs not found.txt"
if not search_results[idx]:
playlist_entries = song404_by_playlist.setdefault(playlist_name, [])
song_info = f"{spotify_track['name']} - {', '.join(a['name'] for a in spotify_track['artists'])}"
playlist_entries.append(song_info)
print(color[0] + "Could not find the track " + song_info + color[1])


# Save missing tracks to file
save_missing_tracks_to_file(song404_by_playlist)


def save_missing_tracks_to_file(song404_by_playlist: dict):
"""Saves the missing tracks organized by playlist to a log file with timestamp."""
if not song404_by_playlist:
return # Exit if there are no missing tracks

# Create the logs directory if it doesn't exist
log_dir = Path("logs")
log_dir.mkdir(exist_ok=True)

# Filename with a timestamp
file_name = log_dir / f"sync_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"

# Write missing tracks to the file, organized by playlist
with open(file_name, "a", encoding="utf-8") as file:
for song in song404:
file.write(f"{song}\n")
for playlist, songs in song404_by_playlist.items():
file.write(f"Playlist {playlist}:\n")
for song in songs:
file.write(f"{song}\n")
file.write("\n")


async def sync_playlist(spotify_session: spotipy.Spotify, tidal_session: tidalapi.Session, spotify_playlist, tidal_playlist: tidalapi.Playlist | None, config: dict):
Expand Down