import re from ytmusicapi import YTMusic ytmusic = YTMusic() def extract_playlist_id(url: str) -> str: """Extract playlist ID from a YouTube Music playlist URL.""" match = re.search(r"[?&]list=([A-Za-z0-9_-]+)", url) if not match: raise ValueError("Invalid YouTube Music playlist URL") return match.group(1) def get_playlist_tracks(playlist_url: str) -> tuple[str, str | None, list[dict]]: """Fetch playlist info and tracks from a public YouTube Music playlist. Returns (playlist_name, playlist_image_url, tracks). Each track dict has: title, artist, album, youtube_id, image_url. """ playlist_id = extract_playlist_id(playlist_url) playlist = ytmusic.get_playlist(playlist_id, limit=None) name = playlist.get("title", playlist_id) image_url = None thumbnails = playlist.get("thumbnails") if thumbnails: image_url = thumbnails[-1].get("url") tracks = [] for item in playlist.get("tracks", []): artists = item.get("artists") or [] artist_name = ", ".join(a.get("name", "") for a in artists if a.get("name")) album_name = None album = item.get("album") if album: album_name = album.get("name") thumb_url = None thumbs = item.get("thumbnails") if thumbs: thumb_url = thumbs[-1].get("url") tracks.append({ "title": item.get("title", "Unknown"), "artist": artist_name or "Unknown", "album": album_name, "youtube_id": item.get("videoId"), "image_url": thumb_url, }) return name, image_url, tracks def search_track(query: str) -> list[dict]: """Search YouTube Music for tracks matching the query. Returns a list of result dicts with: title, artist, album, youtube_id, image_url. """ results = ytmusic.search(query, filter="songs", limit=10) tracks = [] for item in results: artists = item.get("artists") or [] artist_name = ", ".join(a.get("name", "") for a in artists if a.get("name")) album_name = None album = item.get("album") if album: album_name = album.get("name") thumb_url = None thumbs = item.get("thumbnails") if thumbs: thumb_url = thumbs[-1].get("url") tracks.append({ "title": item.get("title", "Unknown"), "artist": artist_name or "Unknown", "album": album_name, "youtube_id": item.get("videoId"), "image_url": thumb_url, }) return tracks