("en", new HTMLEnglish())
9 | };
10 |
11 | public virtual string GetName() { return ""; }
12 | public virtual string GetIndex() { return ""; }
13 | public virtual string GetProgress(string mensaje) { return ""; }
14 | public virtual string CloseWithJS() { return ""; }
15 | public virtual string GetHelp() { return ""; }
16 | public virtual string GetListSelection(string options) { return ""; }
17 | public virtual string GetClosed() { return ""; }
18 | public virtual string GetHelpImageName() { return ""; }
19 | public virtual string GetTXTInvalidURL() { return ""; }
20 | public virtual string GetTXTErrorDownloadingURL() { return ""; }
21 | public virtual string GetTXTM3U8Unsupported() { return ""; }
22 | public virtual string GetTXTFFMPEGFail() { return ""; }
23 | public virtual string GetTXTFail() { return ""; }
24 |
25 |
26 | public string GetLanguageList() {
27 | string txt = "Change language: ";
28 | for (int i = 0; i < HTML.availableLanguages.Length; i++) {
29 | txt += "" + HTML.availableLanguages[i].Value.GetName() + " ";
30 | }
31 | return txt;
32 | }
33 |
34 | public virtual string GetProgress() {
35 | return GetProgress("");
36 | }
37 |
38 | public virtual string GetAllcss() {
39 | //RESET.css
40 | return "html, body, div, span, applet, object, iframe," +
41 | "h1, h2, h3, h4, h5, h6, p, blockquote, pre," +
42 | "a, abbr, acronym, address, big, cite, code," +
43 | "del, dfn, em, img, ins, kbd, q, s, samp," +
44 | "small, strike, strong, sub, sup, tt, var," +
45 | "b, u, i, center,\ndl, dt, dd, ol, ul, li," +
46 | "fieldset, form, label, legend," +
47 | "table, caption, tbody, tfoot, thead, tr, th, td," +
48 | "article, aside, canvas, details, embed," +
49 | "figure, figcaption, footer, header, hgroup," +
50 | "menu, nav, output, ruby, section, summary," +
51 | "time, mark, audio, video {" +
52 | "margin: 0;" +
53 | "padding: 0;" +
54 | "border: 0;" +
55 | "font-size: 100%;" +
56 | "vertical-align: baseline;" +
57 | "}" +
58 | "article, aside, details, figcaption, figure," +
59 | "footer, header, hgroup, menu, nav, section {" +
60 | "display: block;" +
61 | "}" +
62 | "body {" +
63 | "line-height: 1;" +
64 | "}" +
65 | "ol, ul {" +
66 | "list-style: none;" +
67 | "}" +
68 | "blockquote, q {" +
69 | "quotes: none;" +
70 | "}" +
71 | "blockquote:before, blockquote:after," +
72 | "q:before, q:after {" +
73 | "content: '';" +
74 | "content: none;" +
75 | "}" +
76 | "table {" +
77 | "border-collapse: collapse;" +
78 | "border-spacing: 0;" +
79 | "}" +
80 |
81 | //All.css
82 | "body {" +
83 | "background-color: #6E9500;" +
84 | "font-family: Tahoma;" +
85 | "}" +
86 | "a {" +
87 | "color: #0FF;" +
88 | "}" +
89 | "a:hover {" +
90 | "color: #FFF;" +
91 | "}" +
92 | "#cerrarAplicacion > a:hover {" +
93 | "background-color: #FF0000;" +
94 | "}" +
95 | "#cerrarAplicacion > a {" +
96 | "background: none repeat scroll 0 0 #9C0000;" +
97 | "border: 1px double #FFFFFF;" +
98 | "border-radius: 10px;" +
99 | "color: #FFFFFF;" +
100 | "margin: 5px;" +
101 | "padding: 10px;" +
102 | "position: fixed;" +
103 | "right: 0;" +
104 | "text-decoration: none;" +
105 | "top: 0;" +
106 | "}" +
107 | "#menu {" +
108 | "background-color: #1A1A1A;" +
109 | "box-shadow: 0 0 15px 0 #000000;" +
110 | "color: #FFFFFF;" +
111 | "height: 100%;" +
112 | "padding: 30px 0;" +
113 | "position: fixed;" +
114 | "text-align: center;" +
115 | "width: 230px;" +
116 | "}" +
117 | "#menu a {" +
118 | "color: #B2F100;" +
119 | "display: block;" +
120 | "font-size: 16px;" +
121 | "font-weight: bold;" +
122 | "line-height: 20px;" +
123 | "padding: 10px 0;" +
124 | "text-decoration: none;" +
125 | "}" +
126 | "#menu a:hover {" +
127 | "background-color: #EEEEEE;" +
128 | "box-shadow: 0 0 9px #929292 inset;" +
129 | "color: #333333;" +
130 | "}" +
131 | "#menu .titulo_menu {" +
132 | "background-color: #990000;" +
133 | "color: #FFFFFF;" +
134 | "font-size: 18px;" +
135 | "font-weight: normal;" +
136 | "line-height: 18px;" +
137 | "margin-bottom: 35px;" +
138 | "padding: 20px;" +
139 | "}" +
140 | "#menu .titulo_menu:hover {" +
141 | "background-color: #FFFFFF;" +
142 | "box-shadow: none;" +
143 | "color: #000000;" +
144 | "}" +
145 | "#contenido {" +
146 | "color: #FFFFFF;" +
147 | "display: inline-block;" +
148 | "margin: 25px 20px 0 270px;" +
149 | "padding: 0 0 50px;" +
150 | "}" +
151 | "#descargando {" +
152 | "width: 100%;" +
153 | "}" +
154 | "#descargando .n{" +
155 | "width: 18%;" +
156 | "}" +
157 | "#descargando .u{" +
158 | "width: 27%;" +
159 | "}" +
160 | "#descargando .p{" +
161 | "width: 27%;" +
162 | "}" +
163 | "#descargando .t{" +
164 | "width: 19%;" +
165 | "}" +
166 | "#descargando .q{" +
167 | "width: 9%;" +
168 | "}" +
169 | "#descargando .q a {" +
170 | "background-color: #FF0000;" +
171 | "border: 1px solid #FFFFFF;" +
172 | "border-radius: 10px;" +
173 | "color: #FFFFFF;" +
174 | "display: inline-block;" +
175 | "padding: 4px;" +
176 | "text-decoration: none;" +
177 | "}" +
178 | "#descargando .q a:hover {" +
179 | "background-color: #FFFFFF;" +
180 | "color: #F00;" +
181 | "border-color: #F00;" +
182 | "}" +
183 | ".tabla{" +
184 | "display: table;" +
185 | "margin: 15px 0 50px;" +
186 | "position: relative;" +
187 | "table-layout: fixed;" +
188 | "word-break: break-all;" +
189 | "word-wrap: break-word;" +
190 | "}" +
191 | ".tabla > .elemento:nth-child(odd) {" +
192 | "background-color: #B6CCAF;" +
193 | "}" +
194 | ".tabla > .elemento:nth-child(even) {" +
195 | "background-color: #CBE1A4;" +
196 | "}" +
197 | ".tabla > .elemento {" +
198 | "border-bottom: 1px solid #000000;" +
199 | "color: #000000;" +
200 | "display: table-row;" +
201 | "line-height: 22px;" +
202 | "}" +
203 | ".tabla > .titulos:first-child {" +
204 | "background-color: #24302A;" +
205 | "color: #ECFFC9;" +
206 | "font-weight: bold;" +
207 | "}" +
208 | ".tabla > .elemento > div {" +
209 | "display: table-cell;" +
210 | "font-size: 14px;" +
211 | "line-height: 14px;" +
212 | "padding: 5px 10px;" +
213 | "}" +
214 | ".progressBar {" +
215 | "background-color: #000000;" +
216 | "border-radius: 10px;" +
217 | "box-shadow: 0 -9px 10px -5px #858585 inset;" +
218 | "display: inline-block;" +
219 | "height: 10px;" +
220 | "margin: 0 8px 0 0;" +
221 | "padding: 1px;" +
222 | "width: calc(100% - 60px);" +
223 | "}" +
224 | ".progressBar > div {" +
225 | "background-color: #FFC8C8;" +
226 | "box-shadow: 0 -2px 4px 2px #FF0000 inset;" +
227 | "border-radius: 10px;" +
228 | "height: 10px;" +
229 | "}" +
230 | "ol {" +
231 | "list-style: decimal outside none;" +
232 | "}" +
233 | "li {" +
234 | "margin-bottom: 1em;" +
235 | "}" +
236 | ".img_ayuda{" +
237 | "background-color: #C2C2C2;" +
238 | "border: 1px solid #FFFFFF;" +
239 | "padding: 10px;" +
240 | "width: 80%" +
241 | "}";
242 | }
243 |
244 | }
245 | }
246 |
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/HTMLEnglish.cs:
--------------------------------------------------------------------------------
1 | // Translation by veso266
2 |
3 | using System;
4 |
5 | namespace M3U8downloader {
6 | public class HTMLEnglish : HTML {
7 | public override string GetName() {
8 | return "English";
9 | }
10 |
11 | public override string GetIndex() {
12 | return "" +
13 | "" +
14 | "M3U8-Downloader V" + MainClass.version + " " +
15 | " " +
16 | "" +
17 | "" +
18 | "" +
19 | "" +
22 | "" +
30 | "" +
31 | "New Download:" +
32 | "
" +
45 | "Downloads in progress:" +
46 | "
" +
47 | GetProgress() +
48 | "
" +
49 | "
" +
50 | "" +
61 | "" +
62 | "";
63 | }
64 |
65 | public override string GetProgress(string mensaje) {
66 | String resp = "" +
67 | "
Name
" +
68 | "
URL
" +
69 | "
Progress
" +
70 | "
Time left
" +
71 | "
Remove
" +
72 | "
";
73 | for (int i = 0; i < MainClass.descargasEnProceso.Count; i++) {
74 | if (MainClass.descargasEnProceso[i].fallado != "") {
75 | resp += "" +
76 | "
" + MainClass.descargasEnProceso[i].nombre + "
" +
77 | "
" + MainClass.descargasEnProceso[i].url + "
" +
78 | "
" + MainClass.descargasEnProceso[i].fallado + "
" +
79 | "
" +
80 | "
" +
81 | "
";
82 | } else {
83 | resp += "" +
84 | "
" + MainClass.descargasEnProceso[i].nombre + "
" +
85 | "
" + MainClass.descargasEnProceso[i].url + "
" +
86 | "
" + MainClass.descargasEnProceso[i].porcentajeInt + "%
" +
87 | "
" + MainClass.descargasEnProceso[i].horaRestanteString + "
" +
88 | "
" +
89 | "
";
90 | }
91 | }
92 |
93 | if (mensaje != "") {
94 | resp += "";
95 | }
96 |
97 | return resp;
98 | }
99 |
100 | public override string CloseWithJS() {
101 | return "You can close this window/tab." +
102 | "";
107 | }
108 |
109 | public override string GetHelp() {
110 | return "" +
111 | "" +
112 | "M3U8-Downloader V" + MainClass.version + " " +
113 | " " +
114 | "" +
115 | "" +
116 | "" +
117 | "" +
120 | "" +
126 | "" +
127 | "
" +
128 | "
" +
129 | "Program Version." +
130 | " In the case of the image it is version 0.3. " +
131 | "If we want to check for updates, it will be understood as a superior version of one that has a value greater than the current number, with version 2.0, for example greater than 1.5 and higher than version 0.3. " +
132 | "Link to the section of the program versions. " +
133 | "Clicking on the link a page with the list of all published versions where you can download the latest or any of the earlier versions will open. " +
134 | "In this form you add new Downloads. " +
135 | "If you want to manually add a download, enter the URL of the file m3u8 in the URL field and type the name you want to have the video in the Name field. The name of the video must have the file extension, to be a valid name such asvideo.mp4 or Chapter 15.mp4 . The name can be left blank. Once completed the form when clickingAdd start downloading the video. " +
136 | "File name as it appears in the folder that contains it. " +
137 | "URL of the file you are downloading. " +
138 | "Download Progress. " +
139 | "After completing each download folder containing the video opens. Until then, you should not move or delete the file. " +
140 | "Time remaining to complete the download. " +
141 | "The time is calculated from the percentage downloaded and elapsed time so it is only approximate. " +
142 | "Remove the download list. " +
143 | "If the download is not yet completed it will stop downloading and be removed from the list, leaving the incomplete file in the download folder. " +
144 | "If the download is completed it will be removed from the list automatically " +
145 | "Close the Program. " +
146 | "To close the program you must click the button. In doing so, a question is displayed. If you accept, all incomplete downloads in progress will be discontinued and then the program will close. Otherwise the program will not be closed. Once done it will load a new page that will indicate that the program has been successfully closed. If you close the console (black window) instead of clicking on the close button it will stop the discharges in open process, so to stop them it would be necessary to close the process in question. " +
147 | " " +
148 | "
Back " +
149 | "
" +
150 | "" +
151 | "";
152 | }
153 |
154 | public override string GetListSelection(string options) {
155 | return "Found several download options A greater BANDWIDTH and/or resolution, higher image quality Please click on the option you want to download: " + options;
156 | }
157 |
158 | public override string GetClosed() {
159 | return "You have closed the program Now you can close the console.";
160 | }
161 |
162 | public override string GetHelpImageName() {
163 | return "M3U8downloader.ayuda_img.png";
164 | }
165 |
166 | public override string GetTXTInvalidURL() {
167 | return "Invalid URL";
168 | }
169 |
170 | public override string GetTXTErrorDownloadingURL() {
171 | return "Error downloading the URL";
172 | }
173 |
174 | public override string GetTXTM3U8Unsupported() {
175 | return "M3U8 not supported";
176 | }
177 |
178 | public override string GetTXTFFMPEGFail() {
179 | return "FFMPEG failed";
180 | }
181 |
182 | public override string GetTXTFail() {
183 | return "Error";
184 | }
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/HTMLSpanish.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace M3U8downloader
4 | {
5 | public class HTMLSpanish : HTML
6 | {
7 | public override string GetName() {
8 | return "Español";
9 | }
10 |
11 | public override string GetIndex(){
12 | return "" +
13 | "" +
14 | "M3U8-Downloader V" + MainClass.version + " " +
15 | " " +
16 | "" +
17 | "" +
18 | "" +
19 | "" +
22 | "" +
30 | "" +
31 | "Nueva descarga:" +
32 | "
" +
45 | "Descargas en progreso:" +
46 | "
" +
47 | GetProgress() +
48 | "
" +
49 | "
" +
50 | "" +
61 | "" +
62 | "";
63 | }
64 |
65 | public override string GetProgress(string mensaje){
66 | String resp = "" +
67 | "
Nombre
" +
68 | "
URL
" +
69 | "
Progreso
" +
70 | "
Tiempo restante
" +
71 | "
Quitar
" +
72 | "
";
73 | for (int i=0; i" +
76 | "" + MainClass.descargasEnProceso [i].nombre + "
" +
77 | "" + MainClass.descargasEnProceso [i].url + "
" +
78 | ""+MainClass.descargasEnProceso [i].fallado+"
" +
79 | "
" +
80 | "" +
81 | "";
82 | } else {
83 | resp += "" +
84 | "
" + MainClass.descargasEnProceso [i].nombre + "
" +
85 | "
" + MainClass.descargasEnProceso [i].url + "
" +
86 | "
" + MainClass.descargasEnProceso [i].porcentajeInt + "%
" +
87 | "
" + MainClass.descargasEnProceso [i].horaRestanteString + "
" +
88 | "
" +
89 | "
";
90 | }
91 | }
92 |
93 | if(mensaje != ""){
94 | resp += "";
95 | }
96 |
97 | return resp;
98 | }
99 |
100 | public override string CloseWithJS(){
101 | return "Puedes cerrar esta ventana/pestaña."+
102 | "";
107 | }
108 |
109 | public override string GetHelp(){
110 | return "" +
111 | "" +
112 | "M3U8-Downloader V" + MainClass.version + " " +
113 | " " +
114 | "" +
115 | "" +
116 | "" +
117 | "" +
120 | "" +
126 | "" +
127 | "
" +
128 | "
" +
129 | "Versión del programa." +
130 | " En el caso de la imagen se trata de la versión 0.3. " +
131 | "Si queremos buscar actualizaciones, se entenderá como una versión superior aquella que tenga un número mayor que el actual, siendo por ejemplo la versión 2.0 superior a la 1.5 y a su vez superior a la versión 0.3. " +
132 | "Enlace a la sección de versiones del programa en Descargavideos. " +
133 | "Al hacer clic en el enlace se abrirá una página con el listado de versiones publicadas donde podrás descargar la más reciente o cualquiera de las versiones anteriores. " +
134 | "Formulario para agregar nuevas descargas. " +
135 | "En caso de querer agregar manualmente una descarga, introduce la URL del archivo m3u8 en el campo URL y escribe el nombre que quieres que tenga el vídeo en el campo Nombre. El nombre del vídeo debe tener la extensión del archivo, siendo un nombre válido por ejemplo video.mp4 o capítulo 15.mp4 . El nombre puede dejarse en blanco. Una vez completado el formulario al clicar Agregar comenzará la descarga del vídeo. " +
136 | "Nombre del archivo tal y como figura en la carpeta que lo contiene. " +
137 | "URL del archivo que se está descargando. " +
138 | "Progreso de la descarga. " +
139 | "Una vez completada cada descarga se abrirá la carpeta que contiene el vídeo. Hasta entonces, no debe moverse o borrarse el archivo. " +
140 | "Tiempo restante para completar la descarga. " +
141 | "El tiempo es calculado a partir del porcentaje descargado y el tiempo transcurrido por lo que únicamente es aproximado. " +
142 | "Quitar la descarga de la lista. " +
143 | "En caso de que la descarga no esté finalizada detendrá la descarga y la quitará de la lista, dejando el archivo incompleto en la carpeta de descargas. " +
144 | "En caso de que la descarga esté finalizada, únicamente la quitará de la lista. " +
145 | "Cerrar el programa. " +
146 | "Para cerrar el programa se debe de hacer clic en el botón. Al hacerlo, se mostrará una pregunta. En caso de que aceptemos, todas las descargas incompletas en curso se interrumpirán y después se cerrará el programa. De lo contrario no se cerrará el programa. Una vez hecho esto cargará una nueva página en la que indicará que el programa se ha cerrado con éxito. En caso de cerrar la consola (la ventana negra) en lugar de clicar en el botón de cerrar dejará las descargas en proceso abiertas, por lo que para detenerlas sería necesario cerrar el proceso en cuestión. " +
147 | " " +
148 | "
atras " +
149 | "
" +
150 | "" +
151 | "";
152 | }
153 |
154 | public override string GetListSelection(string options){
155 | return "Se han encontrado varias opciones de descarga A mayor BANDWIDTH Y/O RESOLUTION, mayor calidad de imagen Por favor, clica en la opción que quieras descargar: "+options;
156 | }
157 |
158 | public override string GetClosed(){
159 | return "Has cerrado el programa Ahora puedes cerrar la consola.";
160 | }
161 |
162 | public override string GetHelpImageName() {
163 | return "M3U8downloader.ayuda_img.png";
164 | }
165 |
166 | public override string GetTXTInvalidURL() {
167 | return "URL inválida";
168 | }
169 |
170 | public override string GetTXTErrorDownloadingURL() {
171 | return "Error al descargar la URL";
172 | }
173 |
174 | public override string GetTXTM3U8Unsupported() {
175 | return "M3U8 no soportado";
176 | }
177 |
178 | public override string GetTXTFFMPEGFail() {
179 | return "FFMPEG ha fallado";
180 | }
181 |
182 | public override string GetTXTFail() {
183 | return "Fallo";
184 | }
185 | }
186 | }
187 |
188 |
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/M3U8-downloader.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 9.0.21022
7 | 2.0
8 | {4B78A828-6021-4F83-A159-B78972AF24BB}
9 | Exe
10 | M3U8downloader
11 | M3U8-downloader
12 | v3.5
13 | 0.4
14 |
15 |
16 |
17 |
18 | 3.5
19 | publish\
20 | true
21 | Disk
22 | false
23 | Foreground
24 | 7
25 | Days
26 | false
27 | false
28 | true
29 | 0
30 | 1.0.0.%2a
31 | false
32 | false
33 | true
34 |
35 |
36 | True
37 | full
38 | False
39 | bin\Debug
40 | DEBUG;
41 | prompt
42 | 4
43 | x86
44 | True
45 |
46 |
47 | none
48 | False
49 | bin\Release
50 | prompt
51 | 4
52 | x86
53 | True
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | False
82 | .NET Framework 3.5 SP1
83 | true
84 |
85 |
86 |
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/MainClass.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Text.RegularExpressions;
4 | using System.IO;
5 | using System.Collections.Generic;
6 | using System.Threading;
7 | using System.Diagnostics;
8 | using System.Net;
9 | using System.Globalization;
10 |
11 | namespace M3U8downloader
12 | {
13 |
14 | public static class MainClass
15 | {
16 | public static string ffmpegfile = "";
17 | public static string m3u8downloaderPath = "";
18 | public static string relativePath = "";
19 | public static bool desdeServidor = false;
20 |
21 | public static string version = "0.5.2";
22 |
23 | public static int puerto = 25430;
24 |
25 | public static List descargasEnProceso = new List();
26 | public static int TempDescargasEnProcesoCantidad = 0;
27 |
28 |
29 | public static void Main (string[] cmdLine)
30 | {
31 | Console.Title = "M3U8-Downloader V" + version + " - http://www.descargavideos.TV";
32 | Console.WriteLine ("M3U8-Downloader V" + version + " - http://www.descargavideos.TV");
33 | Console.WriteLine ("");
34 |
35 | MainClass.m3u8downloaderPath = AppDomain.CurrentDomain.BaseDirectory;
36 | MainClass.relativePath = Directory.GetCurrentDirectory();
37 |
38 | if (File.Exists (MainClass.m3u8downloaderPath + "\\ffmpeg\\ffmpeg.exe")) {
39 | MainClass.ffmpegfile = MainClass.m3u8downloaderPath + "\\ffmpeg\\ffmpeg.exe";
40 | } else if (File.Exists (MainClass.m3u8downloaderPath + "\\ffmpeg.exe")) {
41 | MainClass.ffmpegfile = MainClass.m3u8downloaderPath + "\\ffmpeg.exe";
42 | }
43 | if (MainClass.ffmpegfile == "") {
44 | //No tsmuxer files
45 | Console.WriteLine ("Por favor descarga ffmpeg y coloca el archivo ffmpeg.exe dentro de la siguiente carpeta:");
46 | Console.WriteLine (MainClass.m3u8downloaderPath);
47 | Console.WriteLine ("");
48 | Console.WriteLine ("Descargalo aqui:");
49 | Console.WriteLine ("http://www.ffmpeg.org/download.html");
50 | Console.WriteLine ("");
51 | Console.WriteLine ("Tambien puedes encontrar el archivo en el ZIP de M3U8-Downloader");
52 | Console.WriteLine ("Pulsa cualquier tecla para continuar...");
53 | Console.ReadKey();
54 | return;
55 | }
56 |
57 |
58 |
59 | //Todo http aqui
60 | if (cmdLine.Length == 0) {
61 | desdeServidor = true;
62 | operaDesdeServidor ();
63 | return;
64 | }
65 |
66 |
67 |
68 | //Desde consola
69 | Descargador myDownloader = new Descargador ();
70 | if (cmdLine.Length == 2) {
71 | myDownloader.Comienza (cmdLine [0], cmdLine [1]);
72 | } else if (cmdLine.Length == 3) {
73 | myDownloader.Comienza (cmdLine [0], cmdLine [1], cmdLine [2]);
74 | } else {
75 | //incorrect start parameters
76 | Console.WriteLine ("Uso: M3U8-Downloader ");
77 | Console.WriteLine ("Ejemplo: M3U8-Downloader http://web.com/video.m3u8 C:\\video.mp4");
78 | Console.WriteLine ("");
79 | Console.WriteLine ("Uso: M3U8-Downloader ");
80 | Console.WriteLine ("Ejemplo: M3U8-Downloader http://web.com/video.m3u8 00112233445566778899AABBCCDDEEFF C:\\video.mp4");
81 | return;
82 | }
83 | }
84 |
85 | public static NetworkServer myServer;
86 |
87 | public static HTML html = new HTMLSpanish(); // default
88 |
89 | //Manejo desde HTTP. Todo desde aqui. Una vez terminada la funcion acabara el programa
90 | public static void operaDesdeServidor() {
91 | SelectLanguage(CultureInfo.InstalledUICulture.TwoLetterISOLanguageName);
92 |
93 | //create server and listen from port 25430
94 | Console.WriteLine ("Para usar el programa abre en un navegador la siguiente URL:");
95 | Console.WriteLine ("http://127.0.0.1:"+puerto+"/");
96 | Console.WriteLine ("");
97 |
98 |
99 | myServer = new NetworkServer ();
100 |
101 | if (!myServer.Abre (puerto)) {
102 | Console.WriteLine ("No se ha podido abrir servidor.");
103 | Console.WriteLine ("Es posible que ya tengas el programa abierto.");
104 | Console.WriteLine ("");
105 |
106 | return;
107 | }
108 |
109 | //Abre navegador
110 | Process.Start("http://127.0.0.1:"+puerto+"/");
111 |
112 | while(true) {
113 | RespuestaHTTP GETurl = myServer.Escucha();
114 |
115 | if (!GETurl.correcto) {
116 | myServer.CierraCliente ();
117 | continue;
118 | }
119 |
120 | string path = GETurl.path;
121 |
122 | string accion = GETurl.getParametro ("accion");
123 |
124 | string nombre = GETurl.getParametro ("nombre");
125 | string url = GETurl.getParametro ("url");
126 | string headers = GETurl.getParametro ("headers");
127 |
128 | if (accion == "" || accion == "descargar") {
129 | if (url != "") {
130 | string cerrarVentana = GETurl.getParametro ("cerrarVentana");
131 | if(cerrarVentana == "" || cerrarVentana == "1"){
132 | myServer.Envia(html.CloseWithJS());
133 | }
134 | //else if(cerrarVentana == "0" || true){
135 | else{
136 | myServer.EnviaLocation ("/");
137 | }
138 | var t = new Thread(() => lanzaDescarga(url, headers, nombre));
139 | t.Start();
140 | continue;
141 | }
142 | }
143 |
144 | if(path == "/ayuda"){
145 | myServer.Envia (html.GetHelp());
146 | continue;
147 | }
148 |
149 | if(path == "/ayuda/ayuda_prev.png"){
150 | byte[] imgBytes = GetILocalFileBytes.Get(html.GetHelpImageName());
151 | myServer.EnviaRaw ("image/png", imgBytes);
152 | continue;
153 | }
154 |
155 | if(path == "/all.css"){
156 | myServer.Envia (html.GetAllcss());
157 | continue;
158 | }
159 |
160 | if (path.IndexOf("/lang/") == 0) {
161 | SelectLanguage(path.Substring("/lang/".Length));
162 | myServer.EnviaLocation ("/");
163 | continue;
164 | }
165 |
166 | if (path == "/" && accion == "") {
167 | myServer.Envia (html.GetIndex());
168 | continue;
169 | }
170 |
171 | if (accion == "seleccionarlista" && GETurl.existeParametro("urlm3u8")) {
172 | //Mostrar un alert en caso de que se agregue una nueva descarga para conseguir el focus de la pestaña
173 | String opciones = desglosaListaM3U8(GETurl.getParametro("urlm3u8"));
174 | if (opciones != "") {
175 | myServer.Envia (html.GetListSelection (opciones));
176 | } else {
177 | myServer.Envia("No se ha podido descargar la lista m3u8.");
178 | }
179 | continue;
180 | }
181 |
182 | if (accion == "progreso") {
183 | //Mostrar un alert en caso de que se agregue una nueva descarga para conseguir el focus de la pestaña
184 | if(descargasEnProceso.Count > TempDescargasEnProcesoCantidad){
185 | myServer.Envia (html.GetProgress("Descarga agregada"));
186 | TempDescargasEnProcesoCantidad = descargasEnProceso.Count;
187 | }
188 | else{
189 | myServer.Envia (html.GetProgress());
190 | }
191 | continue;
192 | }
193 |
194 | if (accion == "cancelarDescarga") {
195 | int elem = Convert.ToInt32(GETurl.getParametro ("elem"));
196 | if(elem >= 0 && elem < descargasEnProceso.Count){
197 | borraDescarga(descargasEnProceso[elem]);
198 | }
199 | myServer.EnviaLocation("/");
200 | continue;
201 | }
202 |
203 | if (accion == "cerrarPrograma") {
204 | for(int i=0; i< descargasEnProceso.Count; i++){
205 | descargasEnProceso[i].Cancelar();
206 | }
207 | myServer.Envia(html.GetClosed());
208 |
209 | myServer.Cierra();
210 |
211 | return;
212 | }
213 |
214 |
215 | myServer.Envia ("Na que hacer");
216 | }
217 | }
218 |
219 | public static void SelectLanguage(string twoLetterLang) {
220 | for (int i = 0; i < HTML.availableLanguages.Length; i++) {
221 | if (twoLetterLang == HTML.availableLanguages[i].Key) {
222 | html = HTML.availableLanguages[i].Value;
223 | return;
224 | }
225 | }
226 | }
227 |
228 | public static string desglosaListaM3U8(string url){
229 | if (url.IndexOf ("http://") != 0 && url.IndexOf ("https://") != 0) {
230 | Console.WriteLine ("URL invalida. La URL debe comenzar por \"http://\" o \"https://\"");
231 | return "";
232 | }
233 |
234 | string m3u8List = "";
235 | try {
236 | WebClient webClient = new WebClient ();
237 | m3u8List = webClient.DownloadString (url);
238 | } catch (Exception e) {
239 | Console.WriteLine ("No se pudo descargar la URL: \"" + url + "\"");
240 | return "";
241 | }
242 |
243 | string pattern = "\n([^#\n\r$]+)";
244 | MatchCollection matchesURL = Regex.Matches (m3u8List, pattern);
245 | pattern = "\n#EXT-X-STREAM-INF:(.*?(RESOLUTION|BANDWIDTH)=(.*?)[,\r\n].*?)*";
246 | MatchCollection matchesDESC = Regex.Matches (m3u8List, pattern);
247 | //myServer.Envia(Utilidades.print_r_regex(matchesDESC));
248 |
249 | string resp = "";
250 |
251 | if (matchesURL.Count > 0) {
252 | string extra = "";
253 | if (matchesURL[0].Groups[1].Captures[0].Value.IndexOf ("http") != 0) {
254 | //no es una url completa. completar a partir de la url original. dependiendo de si es relativo o absoluto.
255 | if (matchesURL[0].Groups[1].Captures[0].Value.IndexOf ("/") == 0) {
256 | //absoluto
257 | extra = url.Substring (0, url.IndexOf ("/")) + "/";
258 | } else {
259 | //relativo
260 | extra = url.Substring (0, url.LastIndexOf ("/", url.IndexOf("?")>=0?url.IndexOf("?"):url.Length-1)) + "/";
261 | }
262 | }
263 |
264 | resp = "";
265 |
266 | if(matchesDESC.Count == matchesURL.Count){
267 | for(int i=0; i";
273 | }
274 | }
275 | else{
276 | for(int i=0; i" + extra + matchesURL[i].Groups[1].Captures[0].Value + " ";
278 | }
279 | }
280 | }
281 | else{
282 | resp = "No se ha encontrado nada. Forzar descarga (poner enlace con parametro get que sea forzar = 1. poner en Descargador.cs el detectar ese get, en caso de estar saltar comprobacion)";
283 | }
284 |
285 |
286 | return resp;
287 | }
288 |
289 | public static void borraDescarga(Descargador cual){
290 | cual.Cancelar();
291 | descargasEnProceso.Remove(cual);
292 |
293 | TempDescargasEnProcesoCantidad = descargasEnProceso.Count;
294 | }
295 |
296 | public static void lanzaDescarga(string url, string nombre){
297 | lanzaDescarga (url, "", nombre);
298 | }
299 | public static void lanzaDescarga(string url, string headers, string nombre){
300 | Descargador miDescargador = new Descargador ();
301 |
302 | if (nombre == "") {
303 | nombre = "video.mp4";
304 | }
305 | for (int j=1; File.Exists(nombre); j++) {
306 | nombre = "video" + j + ".mp4";
307 | }
308 |
309 | if (miDescargador.Comienza (url, headers, nombre)) {
310 | //Abrir carpeta que tiene el video
311 | //string myDocspath = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
312 | string windir = Environment.GetEnvironmentVariable ("WINDIR");
313 | System.Diagnostics.Process prc = new System.Diagnostics.Process ();
314 | prc.StartInfo.FileName = windir + @"\explorer.exe";
315 | prc.StartInfo.Arguments = MainClass.relativePath;
316 | prc.Start ();
317 | }
318 | }
319 | }
320 | }
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/NetworkHelper.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.17929
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 | using System;
11 | using System.IO;
12 |
13 |
14 | namespace M3U8downloader
15 | {
16 | public class NetworkHelper
17 | {
18 | public NetworkHelper ()
19 | {
20 | }
21 |
22 | public static void CopyTo(Stream source, Stream destination)
23 | {
24 | // TODO: Argument validation
25 | byte[] buffer = new byte[16384]; // For example...
26 | int bytesRead;
27 | while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
28 | {
29 | destination.Write(buffer, 0, bytesRead);
30 | }
31 | }
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/NetworkServer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Sockets;
3 | using System.Net;
4 | using System.IO;
5 | using System.Text.RegularExpressions;
6 |
7 | namespace M3U8downloader
8 | {
9 | public class NetworkServer
10 | {
11 | TcpListener listener;
12 | TcpClient client;
13 | NetworkStream stream;
14 | StreamReader reader;
15 | StreamWriter writer;
16 |
17 | public NetworkServer (){}
18 |
19 | public bool Abre(int puerto){
20 | try{
21 | Console.WriteLine ("Abriendo servidor en \"127.0.0.1:" + puerto + "\"...");
22 | listener = new TcpListener (IPAddress.Loopback, puerto);
23 | listener.Start ();
24 |
25 | Console.WriteLine ("Servidor abierto.");
26 | return true;
27 | }
28 | catch(Exception e){
29 | Console.WriteLine ("h0");
30 | Console.WriteLine (e);
31 | return false;
32 | }
33 | }
34 |
35 | public RespuestaHTTP Escucha ()
36 | {
37 |
38 | try{
39 |
40 | client = listener.AcceptTcpClient ();
41 | DDebug.WriteLine ("Conexion establecida");
42 |
43 | stream = client.GetStream ();
44 | reader = new StreamReader (stream);
45 | writer = new StreamWriter (stream);
46 | stream.ReadTimeout = 30000;
47 |
48 | // limpiar stream
49 | string entrada = "";
50 | while (entrada.Length < 4 || entrada.Substring(entrada.Length - 4, 4) != "\r\n\r\n") {
51 | entrada += (char) reader.Read();
52 | }
53 | DDebug.WriteLine(entrada);
54 | stream.Flush();
55 |
56 | string GETurl = entrada.Substring(0, entrada.IndexOf("\r\n"));
57 |
58 | if(GETurl != null){
59 | string pattern = " (.*?) HTTP";
60 | MatchCollection matches = Regex.Matches (GETurl, pattern);
61 |
62 | string url="";
63 |
64 | if (matches.Count > 0) {
65 | GroupCollection gc = matches[0].Groups;
66 | CaptureCollection cc = gc[1].Captures;
67 | url = cc[0].Value;
68 | }
69 | DDebug.WriteLine (url);
70 |
71 |
72 | pattern = "\\?(&?([^=^&]+?)=([^&]*))*";
73 | matches = Regex.Matches (url, pattern);
74 | //Utilidades.print_r_regex(matches);
75 | if (matches.Count > 0) {
76 | GroupCollection gc = matches[0].Groups;
77 | CaptureCollection variables = gc[2].Captures;
78 | CaptureCollection valores = gc[3].Captures;
79 |
80 | ParametroGet[] parametros = new ParametroGet[variables.Count];
81 | for(int i = 0; i < variables.Count; i++){
82 | parametros[i] = new ParametroGet(
83 | Uri.UnescapeDataString(variables[i].Value).Replace("+", " "),
84 | Uri.UnescapeDataString(valores[i].Value).Replace("+", " "));
85 | }
86 | return new RespuestaHTTP (url, parametros);
87 | }
88 | return new RespuestaHTTP (url);
89 | }
90 | return new RespuestaHTTP (false);
91 |
92 | }
93 | catch(Exception e){
94 | Console.WriteLine ("h1");
95 | Console.WriteLine (e);
96 | CierraCliente ();
97 | return new RespuestaHTTP (false);
98 | }
99 | }
100 |
101 | public bool Envia (String que)
102 | {
103 | try {
104 | DDebug.WriteLine ("Enviando desde Envia");
105 |
106 | writer.WriteLine ("HTTP/1.1 200 OK");
107 | writer.WriteLine ("Connection: Close");
108 | writer.WriteLine ("Content-Type: text/html; charset=utf-8");
109 |
110 | writer.WriteLine ("");
111 | writer.Write (que);
112 | writer.Flush();
113 |
114 | CierraCliente ();
115 | return true;
116 | } catch (Exception e) {
117 | Console.WriteLine ("h2");
118 | Console.WriteLine (e);
119 | return false;
120 | }
121 | }
122 |
123 | public bool EnviaRaw(String contentType, byte[] contenido){
124 | try {
125 | DDebug.WriteLine ("Enviando desde EnviaRaw");
126 |
127 | writer.WriteLine ("HTTP/1.1 200 OK");
128 | writer.WriteLine ("Connection: Close");
129 | writer.WriteLine ("Content-Type: "+contentType);
130 |
131 | writer.WriteLine ("");
132 | writer.Flush();
133 | stream.Write(contenido, 0, contenido.Length);
134 |
135 | CierraCliente ();
136 | return true;
137 | } catch (Exception e) {
138 | Console.WriteLine ("h10");
139 | Console.WriteLine (e);
140 | return false;
141 | }
142 | }
143 |
144 | public bool EnviaLocation (String que)
145 | {
146 | try {
147 | DDebug.WriteLine ("EnviaLocation");
148 |
149 | writer.WriteLine ("HTTP/1.1 302 OK");
150 | writer.WriteLine ("Location: " + que);
151 | writer.WriteLine ("Content-Length: 0");
152 |
153 | writer.WriteLine ("");
154 | writer.Flush();
155 |
156 | CierraCliente ();
157 | return true;
158 | } catch (Exception e) {
159 | Console.WriteLine("h3");
160 | Console.WriteLine (e);
161 | return false;
162 | }
163 | }
164 |
165 | public void CierraCliente ()
166 | {
167 | try{
168 | DDebug.WriteLine ("CierraCliente");
169 |
170 | this.writer.Close ();
171 | this.stream.Close ();
172 | DDebug.WriteLine("Cliente cerrado.");
173 | }
174 | catch(Exception e){
175 | Console.WriteLine("h4");
176 | Console.WriteLine (e);
177 | }
178 | }
179 |
180 | public void Cierra ()
181 | {
182 | try{
183 | DDebug.WriteLine ("Cierra");
184 |
185 | CierraCliente();
186 | this.listener.Stop ();
187 | Console.WriteLine("Servidor cerrado.");
188 | }
189 | catch(Exception e){
190 | Console.WriteLine("h5");
191 | Console.WriteLine (e);
192 | }
193 | }
194 | }
195 |
196 | public class RespuestaHTTP
197 | {
198 | public String url;
199 | public String path;
200 | public ParametroGet[] parametros;
201 | bool _correcto;
202 | public bool correcto{
203 | get{
204 | return _correcto;
205 | }
206 | set{ }
207 | }
208 |
209 | public RespuestaHTTP (String url)
210 | {
211 | this._correcto = true;
212 |
213 | this.setURL(url);
214 | }
215 |
216 | public RespuestaHTTP (bool correcto)
217 | {
218 | this.correcto = correcto;
219 | }
220 |
221 | public RespuestaHTTP (String url, ParametroGet[] parametros)
222 | {
223 | this.setURL(url);
224 | this.parametros = parametros;
225 | this._correcto = true;
226 | }
227 |
228 | void setURL(String url){
229 | this.url = url;
230 |
231 | String pattern = "[^\\?]*";
232 | MatchCollection matches = Regex.Matches (url, pattern);
233 | //Utilidades.print_r_regex(matches);
234 |
235 | this.path = matches[0].Groups[0].Captures[0].Value;
236 | }
237 |
238 | public bool tieneParametros(){
239 | return parametros != null;
240 | }
241 |
242 | public bool existeParametro(String variable){
243 | if (!tieneParametros())
244 | return false;
245 |
246 | for(int i = 0; i < parametros.Length; i++){
247 | if (parametros[i].variable == variable)
248 | return true;
249 | }
250 | return false;
251 | }
252 |
253 | public String getParametro(String variable){
254 | if (!tieneParametros())
255 | return "";
256 |
257 | for (int i = 0; i < parametros.Length; i++) {
258 | if (parametros [i].variable == variable)
259 | return parametros [i].valor;
260 | }
261 | return "";
262 | }
263 | }
264 |
265 | public class ParametroGet{
266 | String _variable;
267 | String _valor;
268 |
269 | public String variable{
270 | get{
271 | return _variable;
272 | }
273 | set{ }
274 | }
275 | public String valor{
276 | get{
277 | return _valor;
278 | }
279 | set{ }
280 | }
281 |
282 |
283 | public ParametroGet (String variable, String valor)
284 | {
285 | this._variable = variable;
286 | this._valor = valor;
287 | }
288 | }
289 | }
290 |
291 |
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/Utilidades.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.RegularExpressions;
3 |
4 | namespace M3U8downloader
5 | {
6 | public class Utilidades
7 | {
8 | public static int UnixTimestamp()
9 | {
10 | return (int)(DateTime.Now - new DateTime(1970, 1, 1).ToLocalTime()).TotalSeconds;
11 | }
12 |
13 | //Tan solo para ver si el pregmatch tira lo que quiero
14 | public static string print_r_regex(MatchCollection mc){
15 | string resp = "";
16 | if(mc.Count > 0)
17 | {
18 | resp += "Printing matches...";
19 | for(int i =0; i < mc.Count; i++)
20 | {
21 | resp += "\n";
22 | resp += "Match["+i+"]: " + mc[i].Value + "\n";
23 | resp += "Printing groups for this match...\n";
24 | GroupCollection gc = mc[i].Groups;
25 | for(int j =0; j < gc.Count; j++)
26 | {
27 | resp += "\tGroup["+j+"]: "+ gc[j].Value + "\n";
28 | resp += "\tPrinting captures for this group...\n";
29 | CaptureCollection cc = gc[j].Captures;
30 | for(int k =0; k < cc.Count; k++)
31 | {
32 | resp += "\t\tCapture["+k+"]: "+ cc[k].Value + "\n";
33 | }
34 | }
35 | }
36 | }
37 | return resp;
38 | }
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/ayuda_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestrf/M3U8-Downloader/1d2f0ac5a94ec39fec846f1ce20e7ba9f8cd862b/Project files/M3U8-downloader/ayuda_img.png
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/bin/Debug/ffmpeg/ffmpeg.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestrf/M3U8-Downloader/1d2f0ac5a94ec39fec846f1ce20e7ba9f8cd862b/Project files/M3U8-downloader/bin/Debug/ffmpeg/ffmpeg.exe
--------------------------------------------------------------------------------
/Project files/M3U8-downloader/bin/Release/ffmpeg/ffmpeg.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/forestrf/M3U8-Downloader/1d2f0ac5a94ec39fec846f1ce20e7ba9f8cd862b/Project files/M3U8-downloader/bin/Release/ffmpeg/ffmpeg.exe
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | M3U8-Downloader
2 | ===============
3 |
4 | Programa para facilitar la descarga de enlaces M3U8
5 |
--------------------------------------------------------------------------------