import os import time from tkinter import Tk, Frame, Entry, Button, Label, StringVar, messagebox from yt_dlp import YoutubeDL from urllib.parse import urlparse, parse_qs, urlunparse, urlencode from app.widgets.abc import ThreadedTab class MusicDownloadTab(ThreadedTab): def __init__(self, root: Frame | Tk, **kwargs): self.download_url = StringVar() self.status = StringVar() self.download_queue = [] super().__init__(root, **kwargs) def build(self): # Create the main frame for the download interface self.download_frame = Frame(self) self.download_frame.pack(fill="both", expand=True) # Create the input field for the YouTube link self.url_entry = Entry(self.download_frame, textvariable=self.download_url) self.url_entry.pack(fill="x", padx=5, pady=5) # Create the download button self.download_button = Button(self.download_frame, text="Download", command=self.queue_download) self.download_button.pack(padx=5, pady=5) # Create the status label self.status_label = Label(self.download_frame, textvariable=self.status) self.status_label.pack(fill="x", padx=5, pady=5) def queue_download(self): url = self.download_url.get() if url: parsed_url = urlparse(url) query_params = parse_qs(parsed_url.query) if 'list' in query_params: response = messagebox.askyesno("Download Playlist", "Do you want to download the whole playlist?") if not response: query_params.pop('list', None) query_params.pop('index', None) new_query = urlencode(query_params, doseq=True) url = urlunparse(parsed_url._replace(query=new_query)) self.download_queue.append(url) self.status.set("Queued for download") def task(self): if self.download_queue: url = self.download_queue.pop(0) self.download_music(url) time.sleep(1) def download_music(self, url): try: ydl_opts = { 'format': 'bestaudio/best', 'outtmpl': os.path.join("music", '%(title)s.%(ext)s'), 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192', }], } with YoutubeDL(ydl_opts) as ydl: ydl.download([url]) self.status.set("Downloaded successfully") except Exception as e: print(e) self.status.set(f"Error: {str(e)}") time.sleep(1)