yogeshwaran01 / spotify-playlist-to-youtube-playlist

From Spotify's Groove to YouTube's Show: Spot2Tube
https://dev.to/yogeshwaran01/from-spotify-to-youtube-how-i-built-a-python-script-to-convert-playlists-2h89
MIT License
47 stars 5 forks source link

[Feature] [Performance] track changes in Spotify playlist instead of re-adding #12

Open Rexadev opened 1 year ago

Rexadev commented 1 year ago
import os
import json

# ... (existing code)

@click.command()
@click.option("-s", "--spotify_playlist_id", help="Spotify playlist ID")
@click.option("-y", "--youtube_playlist_id", help="YouTube playlist ID")
@click.option(
    "--only-link",
    "-l",
    default=False,
    help="just only link of playlist, logs not appear",
    is_flag=True,
)
@click.option(
    "--cache-folder",
    default="cache",
    help="Folder path to store cached data",
)
def sync(
    spotify_playlist_id: str,
    youtube_playlist_id: str,
    only_link: bool,
    cache_folder: str,
):
    """Sync your YouTube playlist with Spotify Playlist"""

    # ... (existing code)

    # New Code: Create a cache folder if it doesn't exist
    if not os.path.exists(cache_folder):
        os.makedirs(cache_folder)

    # New Code: Check if there's a cached list for the given Spotify playlist ID
    cached_list_path = os.path.join(cache_folder, f"{spotify_playlist_id}.json")
    if os.path.exists(cached_list_path):
        with open(cached_list_path, "r") as file:
            cached_list = json.load(file)
    else:
        cached_list = []

    # ... (existing code)

    # New Code: Create a list to store songs from Spotify for comparison
    new_list = []

    # ... (existing code)

    for track in spotify_playlist.tracks:
        video = youtube.search_video(track)
        new_list.append(video.video_id)

    # ... (existing code)

    # New Code: Compare new list with cached list and update YouTube playlist accordingly
    songs_to_be_added = list(set(new_list) - set(cached_list))
    songs_to_be_removed = list(set(cached_list) - set(new_list))

    for song in songs_to_be_added:
        youtube.add_song_playlist(playlist["youtube_playlist_id"], song)

    for song in songs_to_be_removed:
        youtube.remove_song_playlist(playlist["youtube_playlist_id"], song)

    # New Code: Cache the new list for future syncing
    with open(cached_list_path, "w") as file:
        json.dump(new_list, file)

    t = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # ... (existing code)

# ... (existing code)
from pytube import Search
from pytube.contrib.search import logger

from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

logger.disabled = True

class YouTubeClient:
    def __init__(self) -> None:
        flow = InstalledAppFlow.from_client_secrets_file(
            "client_secret.json",
            scopes=["https://www.googleapis.com/auth/youtube.force-ssl"],
        )

        creds = flow.run_local_server()

        self.youtube = build("youtube", "v3", credentials=creds)

    # ... (existing code)

    def update_playlist_items(self, playlist_id: str, new_video_ids: list):
        # Get the current video IDs in the playlist
        current_video_ids = []
        next_page_token = None

        while True:
            request = self.youtube.playlistItems().list(
                part="snippet",
                playlistId=playlist_id,
                maxResults=50,
                pageToken=next_page_token,
            )

            response = request.execute()

            current_video_ids.extend(
                [item["snippet"]["resourceId"]["videoId"] for item in response["items"]]
            )

            next_page_token = response.get("nextPageToken")

            if not next_page_token:
                break

        # Calculate the videos to be added and removed
        videos_to_add = list(set(new_video_ids) - set(current_video_ids))
        videos_to_remove = list(set(current_video_ids) - set(new_video_ids))

        # Add new videos to the playlist
        for video_id in videos_to_add:
            self.add_song_playlist(playlist_id, video_id)

        # Remove videos from the playlist
        for video_id in videos_to_remove:
            self.remove_song_playlist(playlist_id, video_id)

    # ... (existing code)
Rexadev commented 1 year ago

@yogeshwaran01