import jsonfile import youtube MUSIC_FILE = "music.json" def load_videos() -> tuple[dict, list[str]]: data = jsonfile.load(MUSIC_FILE) return data, data.setdefault("videos", []) def find_index(videos: list[str], identifier: str) -> int | None: return next((index for index, video in enumerate(videos) if youtube.video_id(video) == identifier), None) def list_songs(arguments) -> None: _, videos = load_videos() if not videos: print("The playlist is empty.") return for number, video in enumerate(videos, start=1): identifier = youtube.video_id(video) or "?" title = youtube.video_title(identifier) if arguments.titles else None print(f"{number:>3}. {identifier} {title or video}") def add_songs(arguments) -> None: data, videos = load_videos() added = 0 for text in arguments.songs: identifier = youtube.video_id(text) if not identifier: print(f"Skipped {text}: not a YouTube link or video ID.") continue if find_index(videos, identifier) is not None: print(f"Skipped {identifier}: already in the playlist.") continue videos.append(youtube.watch_url(identifier)) added += 1 print(f"Added {youtube.video_title(identifier) or identifier}") if added: jsonfile.save(MUSIC_FILE, data) def remove_song(arguments) -> None: data, videos = load_videos() identifier = youtube.video_id(arguments.song) index = find_index(videos, identifier) if identifier else None if index is None: print(f"{arguments.song} is not in the playlist.") return videos.pop(index) jsonfile.save(MUSIC_FILE, data) print(f"Removed {identifier}") def register(subparsers) -> None: parser = subparsers.add_parser("music", help="Manage the music playlist") actions = parser.add_subparsers(dest="action", required=True) list_parser = actions.add_parser("list", help="List songs in the playlist") list_parser.add_argument("--titles", action="store_true", help="Look up song titles on YouTube") list_parser.set_defaults(handler=list_songs) add_parser = actions.add_parser("add", help="Add songs by YouTube link or video ID") add_parser.add_argument("songs", nargs="+", help="YouTube links or video IDs") add_parser.set_defaults(handler=add_songs) remove_parser = actions.add_parser("remove", help="Remove a song by YouTube link or video ID") remove_parser.add_argument("song", help="YouTube link or video ID") remove_parser.set_defaults(handler=remove_song)