import yt_dlp from pathlib import Path from config import settings def is_playlist(query: str) -> bool: return "playlist" in query or "list=" in query def is_youtube_url(query: str) -> bool: return query.startswith("http") def duration_range_filter(min_seconds, max_seconds): def _filter(info, *, incomplete): duration = info.get('duration') if duration: if duration < min_seconds: return f"Skipping: {info.get('title')} is shorter than {min_seconds//60} minutes" if duration > max_seconds: return f"Skipping: {info.get('title')} is longer than {max_seconds//60} minutes" return _filter def download_song(query: str): Path(settings.MUSIC_DIR).mkdir(parents=True, exist_ok=True) if is_youtube_url(query): yt_query = query noplaylist = False elif is_playlist(query): yt_query = query noplaylist = False else: yt_query = f"ytsearch10:{query}" # Always search for 10 results for any artist/song query noplaylist = True ydl_opts = { 'format': 'bestaudio/best', 'outtmpl': f"{settings.MUSIC_DIR}/%(title)s.%(ext)s", 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', }, { 'key': 'FFmpegMetadata', }], 'match_filter': duration_range_filter(2 * 60, 9 * 60), # 2 to 9 minutes 'noplaylist': noplaylist, 'quiet': False, 'verbose': True, } print("yt-dlp options:", ydl_opts) with yt_dlp.YoutubeDL(ydl_opts) as ydl: result = ydl.download([yt_query]) return {"downloaded": "Check music folder for downloaded files"}