# /usr/bin/env python # -*- coding: utf-8 -*- # -*- encoding: utf-8 -*- """ Clase que controla los eventos del downloader además de las descargas de los videos y audios """ # __author__=jjr4p from io import BytesIO from PIL import ImageTk from PIL.Image import open as opp from tkinter import Toplevel, NORMAL, DISABLED, END, INSERT, TclError, IntVar from tkinter import messagebox as msg from tkinter import ttk from tkinter import filedialog import pafy import requests import os import threading import platform class Controlador: def setVista(self, vista): """ Define la vista que será controlada """ self.vista = vista self.recurso = None def cargarurl(self): """ Método encargado de llamar al método cargarInfo en un hilo distinto """ self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) if platform.system() == 'Windows': self.vista.config(cursor="wait") if "facebook" in self.vista.url.get(): self.t = threading.Thread(target=self.cargarFB) self.t.start() else: try: self.recursoPL = pafy.get_playlist(self.vista.url.get()) self.t = threading.Thread(target=self.cargarPlayList) self.t.start() except ValueError as e: try: self.recurso = pafy.new(self.vista.url.get()) self.t = threading.Thread(target=self.cargarInfo) self.t.start() except ValueError as e: mensaje = "La url es inválida o no se encuentra conectado " mensaje += "a internet, intentelo nuevamente." msg.showerror("Error", mensaje) self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def cargarInfo(self): self.vista.notebook.select(self.vista.tab1) """ Método encargado de obtener información dela url ingresada """ info = "" info += "■Título: " + self.recurso.title+"\n" info += "■Duración: " + self.recurso.duration+"\n" info += "■Autor: " + self.recurso.author+"\n" try: info += "■Categoría: " + self.recurso.category+"\n" except: info += "■Categoría: No disponible\n" pass info += "■Likes: " + str(self.recurso.likes)+"\n" info += "■Dislikes: " + str(self.recurso.dislikes)+"\n" mejor = self.recurso.getbest() info += "■Mejor resolución: " + mejor.resolution+"\n" info += "■Mejor formato: " + mejor.extension if self.recurso.bigthumb != '': response = requests.get(self.recurso.bigthumb) img_data = response.content img = ImageTk.PhotoImage(opp(BytesIO(img_data))) self.vista.imagen.config(text="", image=img) self.vista.imagen.image = img self.vista.text.config(state=NORMAL) self.vista.text.delete(1.0, END) self.vista.text.insert(INSERT, info) self.vista.text.config(state=DISABLED) self.cargarLista() self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def cargarLista(self): """ Método encargado de obtener los formatos disponibles del video que se busca """ self.streams = self.recurso.streams self.vista.listbox.delete(0, END) i = 0 texto_a_insertar = "{}) Resolución: {}, Extensión: {}, Tamaño: {}" for s in self.streams: i += 1 tamanio = str("%.2f MB." % (s.get_filesize()/(1024**2))) self.vista.listbox.insert(END, texto_a_insertar.format( i, s.resolution, s.extension, tamanio)) def descargaVideo(self): """ Método encargado de llamar al método __descargaVideo, según lo seleccionado por el usuario además que se ejecuta en un hilo distinto """ index = self.vista.listbox.curselection() if len(index) > 0: self.seleccion = self.streams[index[0]] self.size = self.seleccion.get_filesize() self.mostrarDialogo() t = threading.Thread(target=self.__descargarVideo) t.start() self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) else: msg.showerror("Error", "Se debe seleccionar un video de la lista.") def __descargarVideo(self): """ Método que descarga el video seleccionado y muestra la carga """ self.d = True try: file = self.seleccion.download( quiet=True, filepath=self.vista.path.get(), callback=self.callback) except Exception as e: raise e msg.showerror("Error", "El archivo ya existe.") self.top.destroy() self.d = False msg.showinfo("Mensaje", "Archivo descargado correctamente") self.vista.text.config(state=NORMAL) self.vista.text.delete(1.0, END) self.vista.text.config(state=DISABLED) self.vista.listbox.delete(0, END) self.vista.url.set("") self.vista.imagen.config(text="No disponible", image='') self.vista.imagen.image = '' self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.config(cursor='') self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def descargaAudio(self): """ Método encargado de llamar al método __descargaAudio, que descarga la mejor resolución de audio, además que se ejecuta en un hilo distinto """ if self.recurso != None: t = threading.Thread(target=self.__descargaAudio) t.start() self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) self.mostrarDialogo() def __descargaAudio(self): """ Método que descarga el video seleccionado y muestra la carga """ self.bestaudio = self.recurso.getbestaudio(preftype='m4a') if self.bestaudio != None: self.d = True self.fileaudio = self.bestaudio.title+".m4a" self.size = self.bestaudio.get_filesize() try: self.bestaudio.download( quiet=True, callback=self.callback, filepath=self.vista.path.get()) msg.showinfo("Mensaje", "Archivo descargado correctamente.") except Exception as e: msg.showerror("Error", "El archivo ya existe.") self.top.destroy() self.d = False self.vista.text.config(state=NORMAL) self.vista.text.delete(1.0, END) self.vista.text.config(state=DISABLED) self.vista.listbox.delete(0, END) self.vista.url.set("") self.vista.imagen.config(text="No disponible", image='') self.vista.imagen.image = '' self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.config(cursor='') self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def mostrarDialogo(self): """ Método que muestra la GUI de descarga del archivo """ self.top = Toplevel(self.vista) self.top.resizable(0, 0) self.top.iconbitmap('descarga.ico') geometry = "400x150+" geometry = "400x250+" geometry += str(int(self.vista.ancho/2)-150)+"+" geometry += str(int(self.vista.alto/2)-50) self.top.geometry(geometry) self.top.title("Descarga en progreso...") self.label = Label(self.top, text="Descargando: ", font=("Arial", 13)) self.label.place(x=5, y=15) self.label2 = Label(self.top, text="Tiempo: ", font=("Arial", 13)) self.label2.place(x=130, y=15) self.label3 = Label(self.top, text="Vel.: ", font=("Arial", 13)) self.label3.place(x=250, y=15) self.progress = IntVar() self.progress.set(0) self.progressbar = ttk.Progressbar(self.top, variable=self.progress) self.progressbar.place(x=30, y=60, width=320) self.bcancelar = ttk.Button(self.top, text="Cancelar") self.bcancelar.place(x=150, y= 100) self.top.iconbitmap('descarga.ico') self.progress = IntVar() self.progress.set(0) self.progressbar = ttk.Progressbar(self.top, variable=self.progress) self.label = ttk.Label(self.top, text="Descargando: ", font=("Arial", 14)) self.label.place(x=5, y=15) self.label2 = ttk.Label(self.top, text="Tiempo restante: ", font=("Arial", 14)) self.label2.place(x=5, y=65) self.label3 = ttk.Label(self.top, text="Velocidad: ", font=("Arial", 14)) self.label3.place(x=5, y=115) self.progressbar.place(x=30, y=160, width=320) if platform.system() == 'Windows': self.vista.config(cursor="wait") self.bcancelar = ttk.Button(self.top, text="cancelar", command=self.cancelar) self.bcancelar.place(x=150,y=200) self.top.transient(self.vista) self.top.config(bg="#4C4C4D") def iniciar(self): """ Método que muestra la GUI """ self.vista.mainloop() def cancelar(self): pass def borrarurl(self): """ Método borra la url ingresada """ self.vista.url.set("") def callback(self, total, recvd, ratio, rate, eta): """ Método que controla la descarga del archivo """ carga = int(ratio*100) self.progressbar.step(carga - self.progress.get()) self.progress.set(carga) self.label.config(text="Descarga: "+str(carga)+" %") self.label2.config(text="Tiempo restante: "+str("%.0f" % (eta))+" segundos") self.label3.config(text="Velocidad: "+str("%.2f" % (rate/1024))+" Mb/s") def cambiaPath(self): """ Método para cambiar la carpeta destino """ path = filedialog.askdirectory() if path != None and path != '': self.vista.path.set(path) def copia(self, event): """ Método que pega la url del portapapeles """ self.vista.url.set(self.vista.clipboard_get()) def cargarPlayList(self): self.vista.notebook.select(self.vista.tabPL) self.disponibles = self.recursoPL['items'] self.vista.listPL.delete(0, END) i = 0 texto_a_insertar = "{}) Título: {}, Duración: {}" for s in self.disponibles: i += 1 insertar = texto_a_insertar.format(i, s['pafy'].title[:40]+"...", s['pafy'].duration) try: self.vista.listPL.insert(END,insertar) except TclError as e: pass self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="") def cargarInfoDesdePL(self): index = self.vista.listPL.curselection() if len(index) > 0: if platform.system() == 'Windows': self.vista.config(cursor="wait") self.recurso = self.recursoPL['items'][index[0]]['pafy'] self.vista.button.config(state=DISABLED) self.vista.bvideo.config(state=DISABLED) self.vista.baudio.config(state=DISABLED) self.vista.bborrar.config(state=DISABLED) self.t = threading.Thread(target=self.cargarInfo) self.t.start() else: msg.showerror("Error", "Se debe seleccionar un video de la lista.") def cargarFB(self): try: rpta = msg.askyesno("Pregunta", "No se puede obtener información "+ "de un video de facebook, desea continuar con la descarga?") if rpta: path = filedialog.asksaveasfilename() os.popen("facebook-dl.py {} hd {}".format(self.vista.url.get(),path)) msg.showinfo("Mensaje", "Archivo descargado correctamente.") except: msg.showerror("Error", "El video no es público, o la url es inválida.") self.vista.button.config(state=NORMAL) self.vista.bvideo.config(state=NORMAL) self.vista.baudio.config(state=NORMAL) self.vista.bborrar.config(state=NORMAL) self.vista.config(cursor="")