From 9d09dbfd49f3ee276bf9f6aa1e6567749118b867 Mon Sep 17 00:00:00 2001 From: Sean Reifschneider Date: Sat, 6 Jan 2024 18:15:54 -0700 Subject: [PATCH] Fixing _to_ in pyproject --- copy_playlist | 129 ------------------------------------------------ create_playlist | 20 -------- list_playlists | 23 --------- load_liked | 82 ------------------------------ pyproject.toml | 10 ++-- 5 files changed, 5 insertions(+), 259 deletions(-) delete mode 100755 copy_playlist delete mode 100755 create_playlist delete mode 100755 list_playlists delete mode 100755 load_liked diff --git a/copy_playlist b/copy_playlist deleted file mode 100755 index 75c9b32..0000000 --- a/copy_playlist +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python3 - -""" -Copy a Spotify playlist to a YTMusic playlist -""" - -import sys -import json -import time -from argparse import ArgumentParser -from ytmusicapi import YTMusic - - -def lookup_song(yt, track_name, artist_name, album_name): - # for pl in playlists: - # print(f"{pl['playlistId']} {pl['title']}") - - albums = yt.search(query=f"{album_name} by {artist_name}", filter="albums") - for album in albums[:3]: - # print(album) - # print(f"ALBUM: {album['browseId']} - {album['title']} - {album['artists'][0]['name']}") - - try: - for track in yt.get_album(album["browseId"])["tracks"]: - if track["title"] == track_name: - return track - # print(f"{track['videoId']} - {track['title']} - {track['artists'][0]['name']}") - except Exception as e: - print(f"Unable to lookup album ({e}), continuing...") - - songs = yt.search(query=f"{track_name} by {artist_name}", filter="songs") - return songs[0] - - # This would need to do fuzzy matching - for song in songs: - if ( - song["title"] == track_name - and song["artists"][0]["name"] == artist_name - and song["album"]["name"] == album_name - ): - return song - # print(f"SONG: {song['videoId']} - {song['title']} - {song['artists'][0]['name']} - {song['album']['name']}") - - raise ValueError(f"Did not find {track_name} by {artist_name} from {album_name}") - - -def parse_arguments(): - parser = ArgumentParser() - parser.add_argument( - "--track-sleep", - type=float, - default=0.1, - help="Time to sleep between each track that is added (default: 0.1)", - ) - parser.add_argument( - "--dry-run", - action="store_true", - help="Do not add songs to destination playlist (default: False)", - ) - parser.add_argument( - "spotify_playlist_id", type=str, help="ID of the Spotify playlist to copy from" - ) - parser.add_argument( - "ytmusic_playlist_id", type=str, help="ID of the YTMusic playlist to copy to" - ) - - return parser.parse_args() - - -args = parse_arguments() - -src_pl_id = args.spotify_playlist_id -dst_pl_id = args.ytmusic_playlist_id - -yt = YTMusic("oauth.json") - -spotify_pls = json.load(open("playlists.json", "r")) -yt_pl = yt.get_playlist(playlistId=dst_pl_id) -print(f"== Youtube Playlist: {yt_pl['title']}") - -tracks_added_set = set() -duplicate_count = 0 - -for src_pl in spotify_pls["playlists"]: - if str(src_pl.get("id")) != src_pl_id: - continue - - src_pl_name = src_pl["name"] - - print(f"== Spotify Playlist: {src_pl_name}") - - for src_track in src_pl["tracks"]: - src_album_artist = src_track["track"]["album"]["artists"][0]["name"] - src_album_name = src_track["track"]["album"]["name"] - src_track_artist = src_track["track"]["artists"][0]["name"] - src_track_name = src_track["track"]["name"] - - print(f"Spotify: {src_track_name} - {src_track_artist} - {src_album_name}") - dst_track = lookup_song(yt, src_track_name, src_track_artist, src_album_name) - # print(f" Youtube: {dst_track['videoId']} - {dst_track['title']} - {dst_track['artists'][0]['name']}") - print( - f" Youtube: {dst_track['title']} - {dst_track['artists'][0]['name']} - {dst_track['album']}" - ) - - if dst_track["videoId"] in tracks_added_set: - print("(DUPLICATE, this track has already been added)") - duplicate_count += 1 - tracks_added_set.add(dst_track["videoId"]) - - if not args.dry_run: - exception_sleep = 5 - for x in range(10): - try: - yt.add_playlist_items( - playlistId=dst_pl_id, - videoIds=[dst_track["videoId"]], - duplicates=False, - ) - break - except Exception as e: - print(f"ERROR: (Retrying) {e} in {exception_sleep} seconds") - time.sleep(exception_sleep) - exception_sleep *= 2 - - if args.track_sleep: - time.sleep(args.track_sleep) - -print() -print(f"Added {len(tracks_added_set)} tracks, encountered {duplicate_count} duplicates") diff --git a/create_playlist b/create_playlist deleted file mode 100755 index 97c6786..0000000 --- a/create_playlist +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 - -""" -Create a YTMusic playlist -""" - -import sys -from ytmusicapi import YTMusic - - -if len(sys.argv) != 2: - print(f"usage: {sys.argv[0]} ") - sys.exit(1) - -pl_name = sys.argv[1] - -yt = YTMusic("oauth.json") - -id = yt.create_playlist(title=pl_name, description=pl_name) -print(f'Playlist ID: {id}') diff --git a/list_playlists b/list_playlists deleted file mode 100755 index e84580d..0000000 --- a/list_playlists +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python3 - -""" -List the playlists on Spotify and YTMusic -""" - -import json -from ytmusicapi import YTMusic - -yt = YTMusic("oauth.json") - - -spotify_pls = json.load(open("playlists.json", "r")) - -# Liked music -print('== Spotify') -for src_pl in spotify_pls["playlists"]: - print(f"{src_pl.get('id')} - {src_pl['name']:50} ({len(src_pl['tracks'])} tracks)") - -print() -print('== YTMusic') -for pl in yt.get_library_playlists(limit=5000): - print(f"{pl['playlistId']} - {pl['title']:40} ({pl.get('count', '?')} tracks)") diff --git a/load_liked b/load_liked deleted file mode 100755 index 9665cfd..0000000 --- a/load_liked +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python3 - -""" -Load the "Liked Songs" playlist from Spotify into YTMusic. -""" - -import json -from ytmusicapi import YTMusic - -yt = YTMusic("oauth.json") - - -def lookup_song(yt, track_name, artist_name, album_name): - # for pl in playlists: - # print(f"{pl['playlistId']} {pl['title']}") - - albums = yt.search(query=f"{album_name} by {artist_name}", filter="albums") - for album in albums[:3]: - # print(album) - # print(f"ALBUM: {album['browseId']} - {album['title']} - {album['artists'][0]['name']}") - - try: - for track in yt.get_album(album["browseId"])["tracks"]: - if track["title"] == track_name: - return track - # print(f"{track['videoId']} - {track['title']} - {track['artists'][0]['name']}") - except Exception as e: - print(f"Unable to lookup album ({e}), continuing...") - - songs = yt.search(query=f"{track_name} by {artist_name}", filter="songs") - return songs[0] - - # This would need to do fuzzy matching - for song in songs: - if ( - song["title"] == track_name - and song["artists"][0]["name"] == artist_name - and song["album"]["name"] == album_name - ): - return song - # print(f"SONG: {song['videoId']} - {song['title']} - {song['artists'][0]['name']} - {song['album']['name']}") - - raise ValueError(f"Did not find {track_name} by {artist_name} from {album_name}") - - -spotify_pls = json.load(open("playlists.json", "r")) - -error_count = 0 -track_count = 0 - -# Liked music -for src_pl in spotify_pls["playlists"]: - src_pl_name = src_pl["name"] - if src_pl_name != "Liked Songs": - continue - - print(f"== Playlist: {src_pl_name}") - - for src_track in src_pl["tracks"]: - src_album_artist = src_track["track"]["album"]["artists"][0]["name"] - src_album_name = src_track["track"]["album"]["name"] - src_track_artist = src_track["track"]["artists"][0]["name"] - src_track_name = src_track["track"]["name"] - - print(f"Spotify: {src_track_name} - {src_track_artist} - {src_album_name}") - - try: - dst_track = lookup_song(yt, src_track_name, src_track_artist, src_album_name) - except Exception as e: - print(f"ERROR: Unable to look up song on YTMusic: {e}") - error_count += 1 - - # print(f" Youtube: {dst_track['videoId']} - {dst_track['title']} - {dst_track['artists'][0]['name']}") - print( - f" Youtube: {dst_track['title']} - {dst_track['artists'][0]['name']} - {dst_track['album']}" - ) - - yt.rate_song(dst_track["videoId"], "LIKE") - - track_count += 1 - -print(f"Done. Successful Tracks: {track_count} Errors: {error_count}") diff --git a/pyproject.toml b/pyproject.toml index f4ba164..0621467 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [tool.poetry] -name = "spotify_to_ytmusic" +name = "spotify2ytmusic" version = "0.1.0" description = "Copy Spotify playlists to YTMusic/YouTube Music" authors = ["Sean Reifschneider "] @@ -15,7 +15,7 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] -s2yt_load_liked = "spotify_to_ytmusic.cli:load_liked" -s2yt_copy_playlist = "spotify_to_ytmusic.cli:copy_playlist" -s2yt_create_playlist = "spotify_to_ytmusic.cli:create_playlist" -s2yt_list_playlists = "spotify_to_ytmusic.cli:list_playlists" +s2yt_load_liked = "spotify2ytmusic.cli:load_liked" +s2yt_copy_playlist = "spotify2ytmusic.cli:copy_playlist" +s2yt_create_playlist = "spotify2ytmusic.cli:create_playlist" +s2yt_list_playlists = "spotify2ytmusic.cli:list_playlists"