import yaml import sys import asyncio from typing import List, Dict, Any from spotify_to_tidal import auth as _auth from spotify_to_tidal import sync as _sync from spotify_to_tidal.tidalapi_patch import get_all_playlists def print_menu(playlists: List[Dict[str, Any]]): print("\n" + "="*50) print(f"🎵 Spotify Playlists Found ({len(playlists)} total) 🎵") print("="*50) for i, p in enumerate(playlists): track_count = p.get('tracks', {}).get('total', 'Unknown') print(f"[{i+1:2d}] {p['name']:<35} ({track_count:>3} tracks) | ID: {p['id']}") print("="*50) print("Enter the numbers of the playlists you want to sync, separated by commas (e.g., 1, 4, 12).") print("Enter 'ALL' to sync all playlists.") print("Enter 'Q' to quit.") async def main_async(): # 1. Load config try: with open('config.yml', 'r') as f: config = yaml.safe_load(f) except Exception as e: sys.exit(f"Failed to load config.yml: {e}") # 2. Authenticate print("Authenticating with Spotify...") spotify_session = _auth.open_spotify_session(config['spotify']) print("Authenticating with Tidal...") tidal_session = _auth.open_tidal_session() if not tidal_session.check_login(): sys.exit("Could not connect to Tidal") # 3. Fetch all Spotify user playlists print("\nFetching Spotify playlists...") spotify_playlists = await _sync.get_playlists_from_spotify(spotify_session, config) if not spotify_playlists: print("No Spotify playlists found!") return # 4. Interactive menu loop while True: print_menu(spotify_playlists) choice = input("\nYour choice: ").strip().lower() if choice == 'q': print("Exiting...") return selected_playlists = [] if choice == 'all': selected_playlists = spotify_playlists print(f"Selected ALL {len(selected_playlists)} playlists for synchronization.") break else: try: # Parse comma-separated indices indices = [int(x.strip()) - 1 for x in choice.split(',')] for idx in indices: if 0 <= idx < len(spotify_playlists): selected_playlists.append(spotify_playlists[idx]) else: print(f"Warning: Number {idx + 1} is out of range, ignoring.") if not selected_playlists: print("No valid playlists selected. Please try again.") continue print(f"Selected {len(selected_playlists)} playlists for synchronization.") for p in selected_playlists: print(f" - {p['name']}") confirm = input("Proceed? (Y/n): ").strip().lower() if confirm in ('', 'y', 'yes'): break except ValueError: print("Invalid input. Please enter numbers separated by commas (e.g. 1, 2, 3) or 'ALL'.") # 5. Execute the sync for the selected playlists if not selected_playlists: return print("\n=== Starting Synchronization ===") tidal_playlists = {p.name: p for p in await get_all_playlists(tidal_session.user)} mappings_to_sync = [] for sp_playlist in selected_playlists: mappings_to_sync.append(_sync.pick_tidal_playlist_for_spotify_playlist(sp_playlist, tidal_playlists)) for index, (sp_playlist, td_playlist) in enumerate(mappings_to_sync): print(f"\n[{index+1}/{len(mappings_to_sync)}] Syncing playlist: {sp_playlist['name']}") await _sync.sync_playlist(spotify_session, tidal_session, sp_playlist, td_playlist, config) print("\n=== Synchronization Complete ===") # Optionally sync favorites if enabled in config if config.get('sync_favorites_default', True): fav_confirm = input("\nWould you like to sync your 'Liked Songs' as well? (Y/n): ").strip().lower() if fav_confirm in ('', 'y', 'yes'): await _sync.sync_favorites(spotify_session, tidal_session, config) def main(): asyncio.run(main_async()) if __name__ == "__main__": main()