#!/usr/bin/env python # Helper script to backup playlists and copy new ones over import argparse import subprocess import os import shutil from pathlib import Path import sys import shlex def usage(): print("Usage: {} [--video]".format(sys.argv[0])) sys.exit(1) def run_command(command, capture_output=False, text=True): try: result = subprocess.run(command, shell=True, check=True, capture_output=capture_output, text=text) return result.stdout if capture_output else None except subprocess.CalledProcessError as e: print(f"Command '{command}' failed with exit code {e.returncode}") sys.exit(e.returncode) def main(): parser = argparse.ArgumentParser(description="Synchronize Beat Saber playlists and optionally videos.", add_help=False) parser.add_argument('-v', '--video', action='store_true', help='Enable video synchronization') parser.add_argument('-h', '--help', action='store_true', help='Show help message and exit') args = parser.parse_args() if args.help: usage() COPY_VIDEOS = args.video # Define paths REMOTE_PLAYLISTS = "BSManager/BSInstances/1.39.1/Playlists/" REMOTE_PLAYLISTS_WIN = "BSManager\\BSInstances\\1.39.1\\Playlists" # For Windows SSH commands LOCAL_ARCHIVE_DIR = Path.home() / "archive" / "beatsaber-playlists" LOCAL_ARCHIVE_SUBDIR = LOCAL_ARCHIVE_DIR / "archive" LOCAL_BPLIST_DIR = Path.cwd() # Ensure archive subdirectory exists LOCAL_ARCHIVE_SUBDIR.mkdir(parents=True, exist_ok=True) # Check for local *.bplist files and sync to remote using scp bplist_files = list(LOCAL_BPLIST_DIR.glob("*.bplist")) if bplist_files: print("Starting synchronization of .bplist files to remote using scp...") # Build file string with proper quoting using shlex.quote, so wildcard expansion isn't needed files_str = " ".join(shlex.quote(str(file)) for file in bplist_files) scp_sync_upload = f"scp {files_str} winroar:\"{REMOTE_PLAYLISTS}\"" run_command(scp_sync_upload) # Remove local *.bplist files after successful transfer for f in bplist_files: f.unlink() print(f"Removed local file: {f.name}") # Fetch list of remote *.bplist files print("Fetching list of remote .bplist files...") ssh_command = f'ssh winroar "cd {REMOTE_PLAYLISTS_WIN} && dir /b *.bplist"' remote_bplist = run_command(ssh_command, capture_output=True) remote_bplist_files = set(remote_bplist.strip().split('\n')) if remote_bplist else set() # Fetch list of local archive *.bplist files print("Fetching list of local archived .bplist files...") local_archive_files = set(f.name for f in LOCAL_ARCHIVE_DIR.glob("*.bplist")) # Determine deleted files (present locally but not remotely) deleted_files = local_archive_files - remote_bplist_files if deleted_files: print("Identifying deleted playlists...") for file in deleted_files: local_file = LOCAL_ARCHIVE_DIR / file destination_file = LOCAL_ARCHIVE_SUBDIR / file if local_file.exists(): if destination_file.exists(): destination_file.unlink() # Remove existing file to allow overwrite print(f"Overwriting existing archived file: {file}") shutil.move(str(local_file), str(destination_file)) print(f"Archived deleted playlist: {file}") else: print("No deleted playlists found.") # Sync remote *.bplist to local archive directory print("Downloading current remote .bplist files to local archive...") scp_sync_download = ( f"scp winroar:\"{REMOTE_PLAYLISTS}*.bplist\" \"{LOCAL_ARCHIVE_DIR}/\"" ) run_command(scp_sync_download) print("Download complete.") # Optional video synchronization if COPY_VIDEOS: print("Starting video synchronization with scp...") # Define remote and local video paths REMOTE_VIDEOS = "/Users/pleb/Videos/Beat Saber/" LOCAL_DOWNLOADS = Path.home() / "Downloads" / "Beat Saber" # Ensure local downloads directory exists LOCAL_DOWNLOADS.mkdir(parents=True, exist_ok=True) # Construct scp command to copy videos from remote to local Downloads folder scp_sync_videos = ( f"scp -r winroar:\"{REMOTE_VIDEOS}\" \"{LOCAL_DOWNLOADS}\"" ) run_command(scp_sync_videos) print("Video files synchronized successfully.") input("Press [Enter] to delete videos on winroar.") # Delete videos on remote after confirmation ssh_delete_command = f'ssh winroar \'rm -rf "{REMOTE_VIDEOS}"\'' run_command(ssh_delete_command) print("Remote video directory deleted.") if __name__ == "__main__": main()