Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: JohnConnor en 17 Marzo 2016, 05:24 am



Título: Jason's ogg 2.1 YouTube Downloader C#
Publicado por: JohnConnor en 17 Marzo 2016, 05:24 am
Buenas, les traigo un mini proyecto en fase de pruebas para que lo chequeen.
Jason es un downloader de audio de Youtube, tambien organiza y lista las canciones permitiendo cambiar su ubicacion, calidad, nombre, etc.

Esta programado en C# y utiliza la libreria DevExpress. Para funcionar requiere "Microsoft .Net Framework" y cualquier reproductor OGG. (yo recomiendo VLC)  .

(http://vbspong.hol.es/jason21-1.png)
(http://vbspong.hol.es/jason21-2.png)
(http://vbspong.hol.es/jason21-3.png)
(http://vbspong.hol.es/jason21-4.png)

NOTA: Jason no crackea ni proporciona audio/video protegido por derechos de autor (los mismos son bloqueados)

Links descargas:
(proyecto visual studio, portable y  ejecutabbe)

(http://static1.squarespace.com/static/53cfd7ebe4b07647985da19f/t/543efe51e4b01fa79711a842/1413414482099/download-now-button.png) (http://foro.code-makers.es/viewtopic.php?f=21&t=65)


el que quiera participar del proyecto lo puede hacer aca: http://foro.code-makers.es/viewtopic.php?f=21&t=65   ;-)


Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.Web;
  11. using System.Net;
  12. using System.IO;
  13. using System.Diagnostics;
  14. using System.Text.RegularExpressions;
  15. using System.Media;
  16. using System.Globalization;
  17.  
  18. namespace Jason21
  19. {
  20.    public partial class Form1 : Form
  21.    {
  22.        List<string> Canciones = new List<string>();
  23.        List<string> urlCanciones = new List<string>();
  24.        List<string> mArchivos = new List<string>();
  25.        public bool PrimerCheck = true;
  26.        public string input;
  27.        public string[] parts1;
  28.        public string[] parts2;
  29.        public string[] parts3;
  30.        public string Titulo;
  31.        public string[] ImgP;
  32.        public string[] ImgTP;
  33.        public string[] ImgTP2;
  34.        public string[] ImgT;
  35.        public string[] videoID;
  36.  
  37.        // v1.1 Reformas
  38.        public int intentoDescarga;
  39.        public int maxIntentos;
  40.        public string ultimaURL;
  41.        public int uU = 0;
  42.  
  43.        // v2.0 Reformas
  44.        public string urlADS;
  45.  
  46.        //v2.1 Reformas
  47.        public string archivo_Configuracion;
  48.        public string CarpetaDescargas;
  49.        public float megaBytesGlobal;
  50.        public int sDescargas = 0;
  51.        public bool Cancelar_Busqueda = false;
  52.        public string ultimaPestana = "controlBuscar";
  53.        public int tDescargas = 0;
  54.        public int fDescargas = 0;
  55.        public Form1()
  56.        {
  57.            InitializeComponent();
  58.            webBrowser1.ScriptErrorsSuppressed = true;
  59.            webBrowser2.ScriptErrorsSuppressed = true;
  60.            listBox1.MouseDoubleClick += new MouseEventHandler(listBox1_DoubleClick);
  61.            lista_Biblioteca.MouseDoubleClick += new MouseEventHandler(lista_Biblioteca_DoubleClick);
  62.            // Control_Pestanas.SelectedPageChanged += new TabControlCancelEventHandler(Control_Pestanas_Selecting);
  63.  
  64.        }
  65.  
  66.        private void Form1_Load(object sender, EventArgs e)
  67.        {
  68.            archivo_Configuracion = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\JasonConfig.config");
  69.            CheckConfig();
  70.            ListarCanciones();
  71.            intentoDescarga = 2;
  72.            boton_CancelarBusqueda.Enabled = false;
  73.            Application.DoEvents();
  74.            ListarCanciones();
  75.            Application.DoEvents();
  76.            webBrowser2.Navigate("http://jason.esy.es/");
  77.        }
  78.  
  79.  
  80.  
  81.  
  82.  
  83.        private void boton_Buscar_Click(object sender, EventArgs e)
  84.        {
  85.            boton_Buscar.Enabled = false;
  86.            boton_CancelarBusqueda.Enabled = true;
  87.            Canciones.Clear();
  88.            urlCanciones.Clear();
  89.            listBox1.Items.Clear();
  90.            Cancelar_Busqueda = false;
  91.            for (int i = 1; i <= (int)input_pagBusqueda.Value; i++)
  92.            {
  93.                if (Cancelar_Busqueda)
  94.                {
  95.                    i = 100;
  96.                }
  97.                else
  98.                {
  99.                    Buscar_Agregar(inputText_Buscar.Text, i);
  100.                }
  101.            }
  102.        }
  103.  
  104.        public void Buscar_Agregar(string Busqueda, int Pagina)
  105.        {
  106.            Control_Pestanas.SelectedPageIndex= 0;
  107.            webBrowser1.Navigate("https://www.youtube.com/results?search_query=" + Busqueda + "&page=" + Pagina);
  108.            while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
  109.            {
  110.                Application.DoEvents();
  111.            }
  112.            HtmlElementCollection theElementCollection = default(HtmlElementCollection);
  113.            theElementCollection = webBrowser1.Document.GetElementsByTagName("a");
  114.            foreach (HtmlElement curElement in theElementCollection)
  115.            {
  116.                if (curElement.GetAttribute("classname") == "yt-uix-sessionlink yt-uix-tile-link yt-ui-ellipsis yt-ui-ellipsis-2       spf-link ")
  117.                {
  118.                    bool esLista = curElement.GetAttribute("href").Contains("list");
  119.                    if (!esLista)
  120.                    {
  121.                        listBox1.Items.Add(curElement.GetAttribute("InnerText"));
  122.                        urlCanciones.Add(curElement.GetAttribute("href"));
  123.                    }
  124.                }
  125.            }
  126.        }
  127.  
  128.        private void boton_CancelarBusqueda_Click(object sender, EventArgs e)
  129.        {
  130.            boton_CancelarBusqueda.Enabled = false;
  131.            boton_Buscar.Enabled = true;
  132.            Cancelar_Busqueda = true;
  133.        }
  134.  
  135.  
  136.        private void listBox1_DoubleClick(object sender, MouseEventArgs e)
  137.        {
  138.            if (sDescargas <= 3)
  139.            {
  140.                ConvertirCancion(sender, e);
  141.            }
  142.            else
  143.            {
  144.                MessageBox.Show("The free version does not allow many downloads.");
  145.            }
  146.        }
  147.        public void ConvertirCancion(object sender, MouseEventArgs e)
  148.        {
  149.            int index = this.listBox1.IndexFromPoint(e.Location);
  150.            int urlB = listBox1.SelectedIndex;
  151.            label_ArchivosDescargados.Text = tDescargas.ToString();
  152.            if (index != System.Windows.Forms.ListBox.NoMatches)
  153.            {
  154.                tabControl1.SelectedIndex = 1;
  155.                lista_Descargas.Items.Add(listBox1.SelectedItem);
  156.                label_EstadoDescarga.Text = "It becoming! please, be patient...";
  157.                label_LocacionDescarga.Text = urlCanciones[urlB];
  158.                webBrowser1.Navigate(urlCanciones[listBox1.SelectedIndex]);
  159.                while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
  160.                {
  161.                    Application.DoEvents();
  162.                }
  163.                try
  164.                {
  165.                    input = webBrowser1.DocumentText;
  166.                    parts1 = input.Split(new string[] { "type=audio" }, StringSplitOptions.None);
  167.                    maxIntentos = parts1.Count();
  168.                    parts2 = parts1[intentoDescarga].Split(new string[] { "url=" }, StringSplitOptions.None);
  169.                    parts3 = parts2[1].Split(new string[] { "\\" }, StringSplitOptions.None);
  170.                    Titulo = webBrowser1.Document.Title.Replace(" - YouTube", "");
  171.                    label_EstadoDescarga.Text = "Successful conversion";
  172.                    label_NombreDescarga.Text = Titulo + ".ogg";
  173.                    videoID = urlCanciones[listBox1.SelectedIndex].Split(new string[] { "=" }, StringSplitOptions.None);
  174.                    webBrowser1.Navigate("about:blank");
  175.                    Application.DoEvents();
  176.                    DescargarCancion();
  177.                }
  178.                catch
  179.                {
  180.                    fDescargas ++;
  181.                    label_DescargasFallidas.Text = fDescargas.ToString();
  182.                    label_EstadoDescarga.Text = "Error becoming  file - try again later.";
  183.                    label_NombreDescarga.Text = Titulo + ".ogg\"";
  184.                    webBrowser1.Navigate("about:blank");
  185.                }
  186.            }
  187.        }
  188.  
  189.        public void DescargarCancion()
  190.        {
  191.            label_EstadoDescarga.Text = "Downloading...";
  192.            WebClient Client = new WebClient();
  193.            Client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
  194.            Client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
  195.            Client.DownloadFileAsync(new Uri((HttpUtility.UrlDecode(parts3[0]))), (CarpetaDescargas + "/" + Titulo + ".ogg").Replace("?", ""));
  196.            Application.DoEvents();
  197.            sDescargas++;
  198.        }
  199.  
  200.        public void FalloDescarga()
  201.        {
  202.            fDescargas++;
  203.            sDescargas--;
  204.            label_DescargasFallidas.Text = fDescargas.ToString();
  205.            label_NombreDescarga.Text = intentoDescarga.ToString() + " - Error : \"" + Titulo + ".ogg\"  is protected by copyright.";
  206.            File.Delete(CarpetaDescargas + "/" + Titulo + ".ogg");
  207.            Application.DoEvents();
  208.            /* System.Threading.Thread.Sleep(2000);
  209.             this.intentoDescarga += 1;
  210.             if (intentoDescarga > 1)
  211.             {
  212.                 ConvertirCancion(null, null);
  213.             }
  214.             if (intentoDescarga > maxIntentos - 2)
  215.             {
  216.                 intentoDescarga = 1;
  217.             }
  218.             */
  219.        }
  220.        void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
  221.        {
  222.            int Porciento = ((int)e.BytesReceived * 100) / ((int)e.TotalBytesToReceive);
  223.            label_ArchivosDescargando.Text = sDescargas.ToString();
  224.            try
  225.            {
  226.                progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
  227.                progressBar1.Value = (int)e.BytesReceived / 100;
  228.                double megaBytesT = ((double)e.TotalBytesToReceive / 1024) / (1024);
  229.                double megaBytesR = ((double)e.BytesReceived / 1024) / (1024);
  230.            }
  231.            catch
  232.            {
  233.                label_EstadoDescarga.Text = " Downloading - " + Titulo;
  234.            }
  235.  
  236.            try
  237.            {
  238.  
  239.                progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
  240.                progressBar1.Value = (int)e.BytesReceived / 100;
  241.                double megaBytesT = ((double)e.TotalBytesToReceive / 1024) / (1024);
  242.                megaBytesGlobal = (float)megaBytesT;
  243.                double megaBytesR = ((double)e.BytesReceived / 1024) / (1024);
  244.                if (megaBytesT <= (float)0.5)
  245.                {
  246.                    FalloDescarga();
  247.                }
  248.                else
  249.                {
  250.                    label_EstadoDescarga.Text = " Downloading  " + Porciento + " %";
  251.                    label_MBr.Text = megaBytesR.ToString().Substring(0, 4) + "Mb.";
  252.                    label_MBt.Text = megaBytesT.ToString().Substring(0, 4) + "Mb.";
  253.                }
  254.            }
  255.            catch
  256.            {
  257.                Application.DoEvents();
  258.            }
  259.        }
  260.  
  261.        void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
  262.        {
  263.  
  264.            if (e.Error != null)
  265.            {
  266.                FalloDescarga();
  267.            }
  268.            else
  269.            {
  270.                string Cancion = CarpetaDescargas + "\\" + Titulo + ".ogg";
  271.                if (megaBytesGlobal <= (float)0.5)
  272.                {
  273.                    label_EstadoDescarga.Text = "Unknow error";
  274.                }
  275.                else
  276.                {
  277.                    sDescargas--;
  278.                    tDescargas++;
  279.                    label_ArchivosDescargando.Text = sDescargas.ToString();
  280.                    label_ArchivosDescargados.Text = tDescargas.ToString();
  281.                    label_EstadoDescarga.Text = "Download completed";
  282.                }
  283.  
  284.                if (checkBox_AbrirFinal.Checked)
  285.                {
  286.                    Process.Start(CarpetaDescargas); //, string.Format("/select,\"{0}\"", Titulo + ".ogg"));
  287.                    Application.DoEvents();
  288.                    SendKeys.Send(Titulo);
  289.                }
  290.  
  291.  
  292.                if (checkBox_PlayFinal.Checked)
  293.                {
  294.  
  295.                    Process.Start(Cancion);
  296.                    Application.DoEvents();
  297.                }
  298.            }
  299.        }
  300.  
  301.        public void ListarCanciones()
  302.        {
  303.            if (!PrimerCheck)
  304.            {
  305.                mArchivos.Clear();
  306.                lista_Biblioteca.Items.Clear();
  307.            }
  308.            string[] archivos = Directory.GetFiles(CarpetaDescargas, "*.*", SearchOption.TopDirectoryOnly);
  309.            if (archivos.Length >= 1)
  310.            {
  311.                foreach (string nombre in archivos)
  312.                {
  313.                    bool esOGG = nombre.Contains(".ogg");
  314.                    bool esMP3 = nombre.Contains(".mp3");
  315.                    bool filtro = nombre.ToLower().Contains(textBox_Library_Filter.Text.ToLower());
  316.                    if (esOGG && filtro || esMP3 && filtro)
  317.                    {
  318.  
  319.                        mArchivos.Add(nombre);
  320.                        lista_Biblioteca.Items.Add(nombre.Replace(CarpetaDescargas + "\\", "") + "                                    -                                  Location:  " + nombre);
  321.  
  322.                    }
  323.                }
  324.            }
  325.            PrimerCheck = false;
  326.        }
  327.  
  328.        public void CheckConfig()
  329.        {
  330.            bool abrirFinal = archivo_Configuracion.Contains("openonfinish=true");
  331.            bool playFinal = archivo_Configuracion.Contains("playonfinish=true");
  332.            bool usarMyMusic = archivo_Configuracion.Contains("usemymusic=true");
  333.            if (abrirFinal)
  334.            {
  335.                usar_MyMusic.Checked = true;
  336.            }
  337.            else
  338.            {
  339.                usar_MyMusic.Checked = false;
  340.            }
  341.            if (playFinal)
  342.            {
  343.                usar_OtraCarpeta.Checked = true;
  344.            }
  345.            else
  346.            {
  347.                usar_OtraCarpeta.Checked = false;
  348.            }
  349.            if (usarMyMusic)
  350.            {
  351.                usar_MyMusic.Checked = true;
  352.                usar_OtraCarpeta.Checked = false;
  353.                elegir_Carpeta.Enabled = false;
  354.                CarpetaDescargas = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  355.                textBox_PathChoice.Text = CarpetaDescargas;
  356.                textBox_PathChoice.Enabled = false;
  357.            }
  358.            else if (!usarMyMusic)
  359.            {
  360.                usar_MyMusic.Checked = false;
  361.                usar_OtraCarpeta.Checked = true;
  362.                elegir_Carpeta.Enabled = true;
  363.                CarpetaDescargas = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config");
  364.                textBox_PathChoice.Text = CarpetaDescargas;
  365.            }
  366.        }
  367.  
  368.  
  369.  
  370.        // FIN FIN FIN FIN
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.        private void checkEdit8_CheckedChanged(object sender, EventArgs e)
  388.        {
  389.  
  390.        }
  391.  
  392.        private void groupControl4_Paint(object sender, PaintEventArgs e)
  393.        {
  394.  
  395.        }
  396.  
  397.        private void comboBox_Filter_Library_type_SelectedIndexChanged(object sender, EventArgs e)
  398.        {
  399.  
  400.        }
  401.  
  402.        private void checkBox_AbrirFinal_CheckedChanged(object sender, EventArgs e)
  403.        {
  404.            if (checkBox_AbrirFinal.Checked)
  405.            {
  406.                archivo_Configuracion = archivo_Configuracion.Replace("openonfinish=false", "openonfinish=true");
  407.            }
  408.            else if (!checkBox_AbrirFinal.Checked)
  409.            {
  410.                archivo_Configuracion = archivo_Configuracion.Replace("openonfinish=true", "openonfinish=false");
  411.            }
  412.        }
  413.  
  414.        private void checkBox_PlayFinal_CheckedChanged(object sender, EventArgs e)
  415.        {
  416.            if (checkBox_PlayFinal.Checked)
  417.            {
  418.                archivo_Configuracion = archivo_Configuracion.Replace("playonfinish=false", "playonfinish=true");
  419.            }
  420.            else if (!checkBox_PlayFinal.Checked)
  421.            {
  422.                archivo_Configuracion = archivo_Configuracion.Replace("playonfinish=true", "playonfinish=false");
  423.            }
  424.        }
  425.  
  426.        private void usar_MyMusic_CheckedChanged(object sender, EventArgs e)
  427.        {
  428.            if (usar_MyMusic.Checked && archivo_Configuracion.Contains("usemymusic=false"))
  429.            {
  430.                archivo_Configuracion = archivo_Configuracion.Replace("usemymusic=false", "usemymusic=true");
  431.                usar_OtraCarpeta.Checked = false;
  432.                textBox_PathChoice.Enabled = false;
  433.                elegir_Carpeta.Enabled = false;
  434.                CarpetaDescargas = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  435.                textBox_PathChoice.Text = CarpetaDescargas;
  436.                using (StreamWriter ArchivoDownpath = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config"))
  437.                {
  438.                    ArchivoDownpath.Write("");
  439.                }
  440.            }
  441.        }
  442.  
  443.        private void usar_OtraCarpeta_CheckedChanged(object sender, EventArgs e)
  444.        {
  445.            if (usar_OtraCarpeta.Checked && archivo_Configuracion.Contains("usemymusic=true"))
  446.            {
  447.                archivo_Configuracion = archivo_Configuracion.Replace("usemymusic=true", "usemymusic=false");
  448.                usar_MyMusic.Checked = false;
  449.                textBox_PathChoice.Enabled = true;
  450.                elegir_Carpeta.Enabled = true;
  451.            }
  452.        }
  453.  
  454.        private void boton_AplicarConfig_Click(object sender, EventArgs e)
  455.        {
  456.            using (StreamWriter ArchivoConfig = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\JasonConfig.config"))
  457.            {
  458.                ArchivoConfig.Write(archivo_Configuracion);
  459.            }
  460.            if (usar_MyMusic.Checked)
  461.            {
  462.                Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  463.            }
  464.            else
  465.            {
  466.                CarpetaDescargas = textBox_PathChoice.Text;
  467.            }
  468.            //continuar
  469.            using (StreamWriter ArchivoDownpath = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config"))
  470.            {
  471.                ArchivoDownpath.Write(CarpetaDescargas);
  472.            }
  473.        }
  474.  
  475.        private void boton_Reset_Click(object sender, EventArgs e)
  476.        {
  477.            using (StreamWriter ArchivoConfig = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\JasonConfig.config"))
  478.            {
  479.                ArchivoConfig.Write("openonfinish=true;playonfinish=false;usemymusic=true;otherpath:();");
  480.                archivo_Configuracion = ("openonfinish=true;playonfinish=false;usemymusic=true;otherpath:();");
  481.                CarpetaDescargas = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  482.            }
  483.  
  484.            CheckConfig();
  485.  
  486.            using (StreamWriter ArchivoDownpath = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config"))
  487.            {
  488.                ArchivoDownpath.Write("");
  489.            }
  490.        }
  491.  
  492.        private void elegir_Carpeta_Click(object sender, EventArgs e)
  493.        {
  494.            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
  495.            {
  496.                textBox_PathChoice.Text = folderBrowserDialog1.SelectedPath;
  497.            }
  498.        }
  499.  
  500.        private void simpleButton3_Click(object sender, EventArgs e)
  501.        {
  502.            lista_Descargas.CheckedItems.OfType<string>().ToList().ForEach(lista_Descargas.Items.Remove);
  503.        }
  504.  
  505.        private void simpleButton4_Click(object sender, EventArgs e)
  506.        {
  507.            lista_Descargas.Items.Clear();
  508.        }
  509.  
  510.        private void link_AbrirCarpeta_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
  511.        {
  512.            Process.Start(CarpetaDescargas);
  513.        }
  514.  
  515.  
  516.        private void lista_Biblioteca_DoubleClick(object sender, EventArgs e)
  517.        {
  518.            try {
  519.                Process.Start(mArchivos[lista_Biblioteca.SelectedIndex]);
  520.            } catch
  521.            {
  522.                Process.Start(mArchivos[lista_Biblioteca.SelectedIndex]);
  523.            }
  524.        }
  525.        private void lista_Descargas_DoubleClick(object sender, EventArgs e)
  526.        {
  527.            try
  528.            {
  529.                textBox_Library_Filter.Text = lista_Biblioteca.SelectedItem.ToString();
  530.            }
  531.            catch
  532.            {
  533.                textBox_Library_Filter.Text = lista_Biblioteca.SelectedItem.ToString();
  534.            }
  535.        }
  536.  
  537.  
  538.        private void textBox_Library_Filter_TextChanged(object sender, EventArgs e)
  539.        {
  540.            ListarCanciones();
  541.        }
  542.  
  543.        private void control_Biblioteca_Paint(object sender, PaintEventArgs e)
  544.        {
  545.            // ListarCanciones();
  546.            if (ultimaPestana != "controlBiblioteca")
  547.            {
  548.                ListarCanciones();
  549.            } else
  550.            {
  551.                Application.DoEvents();
  552.            }
  553.  
  554.        }
  555.  
  556.        private void lista_Biblioteca_SelectedIndexChanged(object sender, EventArgs e)
  557.        {
  558.  
  559.        }
  560.  
  561.        private void label13_Click(object sender, EventArgs e)
  562.        {
  563.  
  564.        }
  565.  
  566.        private void lista_Descargas_SelectedIndexChanged(object sender, EventArgs e)
  567.        {
  568.  
  569.        }
  570.    }
  571. }
  572.  



Bueno, eso es todo! Saludos


Título: Re: Jason's ogg 2.1 YouTube Downloader C#
Publicado por: .:UND3R:. en 17 Marzo 2016, 05:44 am
Buenas, les traigo un mini proyecto en fase de pruebas para que lo chequeen.
Jason es un downloader de audio de Youtube, tambien organiza y lista las canciones permitiendo cambiar su ubicacion, calidad, nombre, etc.

Esta programado en C# y utiliza la libreria DevExpress. Para funcionar requiere "Microsoft .Net Framework" y cualquier reproductor OGG. (yo recomiendo VLC)  .

(http://vbspong.hol.es/jason21-1.png)
(http://vbspong.hol.es/jason21-2.png)
(http://vbspong.hol.es/jason21-3.png)
(http://vbspong.hol.es/jason21-4.png)

NOTA: Jason no crackea ni proporciona audio/video protegido por derechos de autor (los mismos son bloqueados)

Links descargas:
(proyecto visual studio, portable y  ejecutabbe)

(http://static1.squarespace.com/static/53cfd7ebe4b07647985da19f/t/543efe51e4b01fa79711a842/1413414482099/download-now-button.png) (http://foro.code-makers.es/viewtopic.php?f=21&t=65)


el que quiera participar del proyecto lo puede hacer aca: http://foro.code-makers.es/viewtopic.php?f=21&t=65   ;-)


Código
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.Web;
  11. using System.Net;
  12. using System.IO;
  13. using System.Diagnostics;
  14. using System.Text.RegularExpressions;
  15. using System.Media;
  16. using System.Globalization;
  17.  
  18. namespace Jason21
  19. {
  20.    public partial class Form1 : Form
  21.    {
  22.        List<string> Canciones = new List<string>();
  23.        List<string> urlCanciones = new List<string>();
  24.        List<string> mArchivos = new List<string>();
  25.        public bool PrimerCheck = true;
  26.        public string input;
  27.        public string[] parts1;
  28.        public string[] parts2;
  29.        public string[] parts3;
  30.        public string Titulo;
  31.        public string[] ImgP;
  32.        public string[] ImgTP;
  33.        public string[] ImgTP2;
  34.        public string[] ImgT;
  35.        public string[] videoID;
  36.  
  37.        // v1.1 Reformas
  38.        public int intentoDescarga;
  39.        public int maxIntentos;
  40.        public string ultimaURL;
  41.        public int uU = 0;
  42.  
  43.        // v2.0 Reformas
  44.        public string urlADS;
  45.  
  46.        //v2.1 Reformas
  47.        public string archivo_Configuracion;
  48.        public string CarpetaDescargas;
  49.        public float megaBytesGlobal;
  50.        public int sDescargas = 0;
  51.        public bool Cancelar_Busqueda = false;
  52.        public string ultimaPestana = "controlBuscar";
  53.        public int tDescargas = 0;
  54.        public int fDescargas = 0;
  55.        public Form1()
  56.        {
  57.            InitializeComponent();
  58.            webBrowser1.ScriptErrorsSuppressed = true;
  59.            webBrowser2.ScriptErrorsSuppressed = true;
  60.            listBox1.MouseDoubleClick += new MouseEventHandler(listBox1_DoubleClick);
  61.            lista_Biblioteca.MouseDoubleClick += new MouseEventHandler(lista_Biblioteca_DoubleClick);
  62.            // Control_Pestanas.SelectedPageChanged += new TabControlCancelEventHandler(Control_Pestanas_Selecting);
  63.  
  64.        }
  65.  
  66.        private void Form1_Load(object sender, EventArgs e)
  67.        {
  68.            archivo_Configuracion = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\JasonConfig.config");
  69.            CheckConfig();
  70.            ListarCanciones();
  71.            intentoDescarga = 2;
  72.            boton_CancelarBusqueda.Enabled = false;
  73.            Application.DoEvents();
  74.            ListarCanciones();
  75.            Application.DoEvents();
  76.            webBrowser2.Navigate("http://jason.esy.es/");
  77.        }
  78.  
  79.  
  80.  
  81.  
  82.  
  83.        private void boton_Buscar_Click(object sender, EventArgs e)
  84.        {
  85.            boton_Buscar.Enabled = false;
  86.            boton_CancelarBusqueda.Enabled = true;
  87.            Canciones.Clear();
  88.            urlCanciones.Clear();
  89.            listBox1.Items.Clear();
  90.            Cancelar_Busqueda = false;
  91.            for (int i = 1; i <= (int)input_pagBusqueda.Value; i++)
  92.            {
  93.                if (Cancelar_Busqueda)
  94.                {
  95.                    i = 100;
  96.                }
  97.                else
  98.                {
  99.                    Buscar_Agregar(inputText_Buscar.Text, i);
  100.                }
  101.            }
  102.        }
  103.  
  104.        public void Buscar_Agregar(string Busqueda, int Pagina)
  105.        {
  106.            Control_Pestanas.SelectedPageIndex= 0;
  107.            webBrowser1.Navigate("https://www.youtube.com/results?search_query=" + Busqueda + "&page=" + Pagina);
  108.            while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
  109.            {
  110.                Application.DoEvents();
  111.            }
  112.            HtmlElementCollection theElementCollection = default(HtmlElementCollection);
  113.            theElementCollection = webBrowser1.Document.GetElementsByTagName("a");
  114.            foreach (HtmlElement curElement in theElementCollection)
  115.            {
  116.                if (curElement.GetAttribute("classname") == "yt-uix-sessionlink yt-uix-tile-link yt-ui-ellipsis yt-ui-ellipsis-2       spf-link ")
  117.                {
  118.                    bool esLista = curElement.GetAttribute("href").Contains("list");
  119.                    if (!esLista)
  120.                    {
  121.                        listBox1.Items.Add(curElement.GetAttribute("InnerText"));
  122.                        urlCanciones.Add(curElement.GetAttribute("href"));
  123.                    }
  124.                }
  125.            }
  126.        }
  127.  
  128.        private void boton_CancelarBusqueda_Click(object sender, EventArgs e)
  129.        {
  130.            boton_CancelarBusqueda.Enabled = false;
  131.            boton_Buscar.Enabled = true;
  132.            Cancelar_Busqueda = true;
  133.        }
  134.  
  135.  
  136.        private void listBox1_DoubleClick(object sender, MouseEventArgs e)
  137.        {
  138.            if (sDescargas <= 3)
  139.            {
  140.                ConvertirCancion(sender, e);
  141.            }
  142.            else
  143.            {
  144.                MessageBox.Show("The free version does not allow many downloads.");
  145.            }
  146.        }
  147.        public void ConvertirCancion(object sender, MouseEventArgs e)
  148.        {
  149.            int index = this.listBox1.IndexFromPoint(e.Location);
  150.            int urlB = listBox1.SelectedIndex;
  151.            label_ArchivosDescargados.Text = tDescargas.ToString();
  152.            if (index != System.Windows.Forms.ListBox.NoMatches)
  153.            {
  154.                tabControl1.SelectedIndex = 1;
  155.                lista_Descargas.Items.Add(listBox1.SelectedItem);
  156.                label_EstadoDescarga.Text = "It becoming! please, be patient...";
  157.                label_LocacionDescarga.Text = urlCanciones[urlB];
  158.                webBrowser1.Navigate(urlCanciones[listBox1.SelectedIndex]);
  159.                while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
  160.                {
  161.                    Application.DoEvents();
  162.                }
  163.                try
  164.                {
  165.                    input = webBrowser1.DocumentText;
  166.                    parts1 = input.Split(new string[] { "type=audio" }, StringSplitOptions.None);
  167.                    maxIntentos = parts1.Count();
  168.                    parts2 = parts1[intentoDescarga].Split(new string[] { "url=" }, StringSplitOptions.None);
  169.                    parts3 = parts2[1].Split(new string[] { "\\" }, StringSplitOptions.None);
  170.                    Titulo = webBrowser1.Document.Title.Replace(" - YouTube", "");
  171.                    label_EstadoDescarga.Text = "Successful conversion";
  172.                    label_NombreDescarga.Text = Titulo + ".ogg";
  173.                    videoID = urlCanciones[listBox1.SelectedIndex].Split(new string[] { "=" }, StringSplitOptions.None);
  174.                    webBrowser1.Navigate("about:blank");
  175.                    Application.DoEvents();
  176.                    DescargarCancion();
  177.                }
  178.                catch
  179.                {
  180.                    fDescargas ++;
  181.                    label_DescargasFallidas.Text = fDescargas.ToString();
  182.                    label_EstadoDescarga.Text = "Error becoming  file - try again later.";
  183.                    label_NombreDescarga.Text = Titulo + ".ogg\"";
  184.                    webBrowser1.Navigate("about:blank");
  185.                }
  186.            }
  187.        }
  188.  
  189.        public void DescargarCancion()
  190.        {
  191.            label_EstadoDescarga.Text = "Downloading...";
  192.            WebClient Client = new WebClient();
  193.            Client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
  194.            Client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
  195.            Client.DownloadFileAsync(new Uri((HttpUtility.UrlDecode(parts3[0]))), (CarpetaDescargas + "/" + Titulo + ".ogg").Replace("?", ""));
  196.            Application.DoEvents();
  197.            sDescargas++;
  198.        }
  199.  
  200.        public void FalloDescarga()
  201.        {
  202.            fDescargas++;
  203.            sDescargas--;
  204.            label_DescargasFallidas.Text = fDescargas.ToString();
  205.            label_NombreDescarga.Text = intentoDescarga.ToString() + " - Error : \"" + Titulo + ".ogg\"  is protected by copyright.";
  206.            File.Delete(CarpetaDescargas + "/" + Titulo + ".ogg");
  207.            Application.DoEvents();
  208.            /* System.Threading.Thread.Sleep(2000);
  209.             this.intentoDescarga += 1;
  210.             if (intentoDescarga > 1)
  211.             {
  212.                 ConvertirCancion(null, null);
  213.             }
  214.             if (intentoDescarga > maxIntentos - 2)
  215.             {
  216.                 intentoDescarga = 1;
  217.             }
  218.             */
  219.        }
  220.        void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
  221.        {
  222.            int Porciento = ((int)e.BytesReceived * 100) / ((int)e.TotalBytesToReceive);
  223.            label_ArchivosDescargando.Text = sDescargas.ToString();
  224.            try
  225.            {
  226.                progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
  227.                progressBar1.Value = (int)e.BytesReceived / 100;
  228.                double megaBytesT = ((double)e.TotalBytesToReceive / 1024) / (1024);
  229.                double megaBytesR = ((double)e.BytesReceived / 1024) / (1024);
  230.            }
  231.            catch
  232.            {
  233.                label_EstadoDescarga.Text = " Downloading - " + Titulo;
  234.            }
  235.  
  236.            try
  237.            {
  238.  
  239.                progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
  240.                progressBar1.Value = (int)e.BytesReceived / 100;
  241.                double megaBytesT = ((double)e.TotalBytesToReceive / 1024) / (1024);
  242.                megaBytesGlobal = (float)megaBytesT;
  243.                double megaBytesR = ((double)e.BytesReceived / 1024) / (1024);
  244.                if (megaBytesT <= (float)0.5)
  245.                {
  246.                    FalloDescarga();
  247.                }
  248.                else
  249.                {
  250.                    label_EstadoDescarga.Text = " Downloading  " + Porciento + " %";
  251.                    label_MBr.Text = megaBytesR.ToString().Substring(0, 4) + "Mb.";
  252.                    label_MBt.Text = megaBytesT.ToString().Substring(0, 4) + "Mb.";
  253.                }
  254.            }
  255.            catch
  256.            {
  257.                Application.DoEvents();
  258.            }
  259.        }
  260.  
  261.        void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
  262.        {
  263.  
  264.            if (e.Error != null)
  265.            {
  266.                FalloDescarga();
  267.            }
  268.            else
  269.            {
  270.                string Cancion = CarpetaDescargas + "\\" + Titulo + ".ogg";
  271.                if (megaBytesGlobal <= (float)0.5)
  272.                {
  273.                    label_EstadoDescarga.Text = "Unknow error";
  274.                }
  275.                else
  276.                {
  277.                    sDescargas--;
  278.                    tDescargas++;
  279.                    label_ArchivosDescargando.Text = sDescargas.ToString();
  280.                    label_ArchivosDescargados.Text = tDescargas.ToString();
  281.                    label_EstadoDescarga.Text = "Download completed";
  282.                }
  283.  
  284.                if (checkBox_AbrirFinal.Checked)
  285.                {
  286.                    Process.Start(CarpetaDescargas); //, string.Format("/select,\"{0}\"", Titulo + ".ogg"));
  287.                    Application.DoEvents();
  288.                    SendKeys.Send(Titulo);
  289.                }
  290.  
  291.  
  292.                if (checkBox_PlayFinal.Checked)
  293.                {
  294.  
  295.                    Process.Start(Cancion);
  296.                    Application.DoEvents();
  297.                }
  298.            }
  299.        }
  300.  
  301.        public void ListarCanciones()
  302.        {
  303.            if (!PrimerCheck)
  304.            {
  305.                mArchivos.Clear();
  306.                lista_Biblioteca.Items.Clear();
  307.            }
  308.            string[] archivos = Directory.GetFiles(CarpetaDescargas, "*.*", SearchOption.TopDirectoryOnly);
  309.            if (archivos.Length >= 1)
  310.            {
  311.                foreach (string nombre in archivos)
  312.                {
  313.                    bool esOGG = nombre.Contains(".ogg");
  314.                    bool esMP3 = nombre.Contains(".mp3");
  315.                    bool filtro = nombre.ToLower().Contains(textBox_Library_Filter.Text.ToLower());
  316.                    if (esOGG && filtro || esMP3 && filtro)
  317.                    {
  318.  
  319.                        mArchivos.Add(nombre);
  320.                        lista_Biblioteca.Items.Add(nombre.Replace(CarpetaDescargas + "\\", "") + "                                    -                                  Location:  " + nombre);
  321.  
  322.                    }
  323.                }
  324.            }
  325.            PrimerCheck = false;
  326.        }
  327.  
  328.        public void CheckConfig()
  329.        {
  330.            bool abrirFinal = archivo_Configuracion.Contains("openonfinish=true");
  331.            bool playFinal = archivo_Configuracion.Contains("playonfinish=true");
  332.            bool usarMyMusic = archivo_Configuracion.Contains("usemymusic=true");
  333.            if (abrirFinal)
  334.            {
  335.                usar_MyMusic.Checked = true;
  336.            }
  337.            else
  338.            {
  339.                usar_MyMusic.Checked = false;
  340.            }
  341.            if (playFinal)
  342.            {
  343.                usar_OtraCarpeta.Checked = true;
  344.            }
  345.            else
  346.            {
  347.                usar_OtraCarpeta.Checked = false;
  348.            }
  349.            if (usarMyMusic)
  350.            {
  351.                usar_MyMusic.Checked = true;
  352.                usar_OtraCarpeta.Checked = false;
  353.                elegir_Carpeta.Enabled = false;
  354.                CarpetaDescargas = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  355.                textBox_PathChoice.Text = CarpetaDescargas;
  356.                textBox_PathChoice.Enabled = false;
  357.            }
  358.            else if (!usarMyMusic)
  359.            {
  360.                usar_MyMusic.Checked = false;
  361.                usar_OtraCarpeta.Checked = true;
  362.                elegir_Carpeta.Enabled = true;
  363.                CarpetaDescargas = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config");
  364.                textBox_PathChoice.Text = CarpetaDescargas;
  365.            }
  366.        }
  367.  
  368.  
  369.  
  370.        // FIN FIN FIN FIN
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.        private void checkEdit8_CheckedChanged(object sender, EventArgs e)
  388.        {
  389.  
  390.        }
  391.  
  392.        private void groupControl4_Paint(object sender, PaintEventArgs e)
  393.        {
  394.  
  395.        }
  396.  
  397.        private void comboBox_Filter_Library_type_SelectedIndexChanged(object sender, EventArgs e)
  398.        {
  399.  
  400.        }
  401.  
  402.        private void checkBox_AbrirFinal_CheckedChanged(object sender, EventArgs e)
  403.        {
  404.            if (checkBox_AbrirFinal.Checked)
  405.            {
  406.                archivo_Configuracion = archivo_Configuracion.Replace("openonfinish=false", "openonfinish=true");
  407.            }
  408.            else if (!checkBox_AbrirFinal.Checked)
  409.            {
  410.                archivo_Configuracion = archivo_Configuracion.Replace("openonfinish=true", "openonfinish=false");
  411.            }
  412.        }
  413.  
  414.        private void checkBox_PlayFinal_CheckedChanged(object sender, EventArgs e)
  415.        {
  416.            if (checkBox_PlayFinal.Checked)
  417.            {
  418.                archivo_Configuracion = archivo_Configuracion.Replace("playonfinish=false", "playonfinish=true");
  419.            }
  420.            else if (!checkBox_PlayFinal.Checked)
  421.            {
  422.                archivo_Configuracion = archivo_Configuracion.Replace("playonfinish=true", "playonfinish=false");
  423.            }
  424.        }
  425.  
  426.        private void usar_MyMusic_CheckedChanged(object sender, EventArgs e)
  427.        {
  428.            if (usar_MyMusic.Checked && archivo_Configuracion.Contains("usemymusic=false"))
  429.            {
  430.                archivo_Configuracion = archivo_Configuracion.Replace("usemymusic=false", "usemymusic=true");
  431.                usar_OtraCarpeta.Checked = false;
  432.                textBox_PathChoice.Enabled = false;
  433.                elegir_Carpeta.Enabled = false;
  434.                CarpetaDescargas = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  435.                textBox_PathChoice.Text = CarpetaDescargas;
  436.                using (StreamWriter ArchivoDownpath = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config"))
  437.                {
  438.                    ArchivoDownpath.Write("");
  439.                }
  440.            }
  441.        }
  442.  
  443.        private void usar_OtraCarpeta_CheckedChanged(object sender, EventArgs e)
  444.        {
  445.            if (usar_OtraCarpeta.Checked && archivo_Configuracion.Contains("usemymusic=true"))
  446.            {
  447.                archivo_Configuracion = archivo_Configuracion.Replace("usemymusic=true", "usemymusic=false");
  448.                usar_MyMusic.Checked = false;
  449.                textBox_PathChoice.Enabled = true;
  450.                elegir_Carpeta.Enabled = true;
  451.            }
  452.        }
  453.  
  454.        private void boton_AplicarConfig_Click(object sender, EventArgs e)
  455.        {
  456.            using (StreamWriter ArchivoConfig = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\JasonConfig.config"))
  457.            {
  458.                ArchivoConfig.Write(archivo_Configuracion);
  459.            }
  460.            if (usar_MyMusic.Checked)
  461.            {
  462.                Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  463.            }
  464.            else
  465.            {
  466.                CarpetaDescargas = textBox_PathChoice.Text;
  467.            }
  468.            //continuar
  469.            using (StreamWriter ArchivoDownpath = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config"))
  470.            {
  471.                ArchivoDownpath.Write(CarpetaDescargas);
  472.            }
  473.        }
  474.  
  475.        private void boton_Reset_Click(object sender, EventArgs e)
  476.        {
  477.            using (StreamWriter ArchivoConfig = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\JasonConfig.config"))
  478.            {
  479.                ArchivoConfig.Write("openonfinish=true;playonfinish=false;usemymusic=true;otherpath:();");
  480.                archivo_Configuracion = ("openonfinish=true;playonfinish=false;usemymusic=true;otherpath:();");
  481.                CarpetaDescargas = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
  482.            }
  483.  
  484.            CheckConfig();
  485.  
  486.            using (StreamWriter ArchivoDownpath = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\Jason\Downpath.config"))
  487.            {
  488.                ArchivoDownpath.Write("");
  489.            }
  490.        }
  491.  
  492.        private void elegir_Carpeta_Click(object sender, EventArgs e)
  493.        {
  494.            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
  495.            {
  496.                textBox_PathChoice.Text = folderBrowserDialog1.SelectedPath;
  497.            }
  498.        }
  499.  
  500.        private void simpleButton3_Click(object sender, EventArgs e)
  501.        {
  502.            lista_Descargas.CheckedItems.OfType<string>().ToList().ForEach(lista_Descargas.Items.Remove);
  503.        }
  504.  
  505.        private void simpleButton4_Click(object sender, EventArgs e)
  506.        {
  507.            lista_Descargas.Items.Clear();
  508.        }
  509.  
  510.        private void link_AbrirCarpeta_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
  511.        {
  512.            Process.Start(CarpetaDescargas);
  513.        }
  514.  
  515.  
  516.        private void lista_Biblioteca_DoubleClick(object sender, EventArgs e)
  517.        {
  518.            try {
  519.                Process.Start(mArchivos[lista_Biblioteca.SelectedIndex]);
  520.            } catch
  521.            {
  522.                Process.Start(mArchivos[lista_Biblioteca.SelectedIndex]);
  523.            }
  524.        }
  525.        private void lista_Descargas_DoubleClick(object sender, EventArgs e)
  526.        {
  527.            try
  528.            {
  529.                textBox_Library_Filter.Text = lista_Biblioteca.SelectedItem.ToString();
  530.            }
  531.            catch
  532.            {
  533.                textBox_Library_Filter.Text = lista_Biblioteca.SelectedItem.ToString();
  534.            }
  535.        }
  536.  
  537.  
  538.        private void textBox_Library_Filter_TextChanged(object sender, EventArgs e)
  539.        {
  540.            ListarCanciones();
  541.        }
  542.  
  543.        private void control_Biblioteca_Paint(object sender, PaintEventArgs e)
  544.        {
  545.            // ListarCanciones();
  546.            if (ultimaPestana != "controlBiblioteca")
  547.            {
  548.                ListarCanciones();
  549.            } else
  550.            {
  551.                Application.DoEvents();
  552.            }
  553.  
  554.        }
  555.  
  556.        private void lista_Biblioteca_SelectedIndexChanged(object sender, EventArgs e)
  557.        {
  558.  
  559.        }
  560.  
  561.        private void label13_Click(object sender, EventArgs e)
  562.        {
  563.  
  564.        }
  565.  
  566.        private void lista_Descargas_SelectedIndexChanged(object sender, EventArgs e)
  567.        {
  568.  
  569.        }
  570.    }
  571. }
  572.  



Bueno, eso es todo! Saludos

 ;-) ;-) ;-)

Excelente proyecto, no puede estar más que mejor, te felicito. Nada mejor que dejes el source, pues ayuda mucho a aquellos que desean entender el como desarrollaste ciertas cosas, me quito el sombrero, te felicito.


Título: Re: Jason's ogg 2.1 YouTube Downloader C#
Publicado por: Eleкtro en 19 Marzo 2016, 20:01 pm
Genial herramienta.

¿Has pensado en añadir una característica para poder descargar los videos también? (a la mayor calidad posible disponible en Youtube), sería muy util para descargar videoclips musicales.

Saludos!