diff --git a/app/Dockerfile b/app/Dockerfile new file mode 100644 index 0000000..7b33ec1 --- /dev/null +++ b/app/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.11-slim + +# Instala dependencias del sistema +RUN apt-get update && apt-get install -y ffmpeg curl + +# Instala yt-dlp +RUN curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux -o /usr/local/bin/yt-dlp && \ +#RUN curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp && \ +chmod a+rx /usr/local/bin/yt-dlp + +# Crea carpetas necesarias +WORKDIR /app +COPY . /app +RUN pip install -r requirements.txt + +CMD ["python", "main.py"] diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..5eb5b49 --- /dev/null +++ b/app/main.py @@ -0,0 +1,104 @@ +from flask import Flask, render_template, request, send_file +import subprocess +import os +import uuid +import shutil + +app = Flask(__name__) +BASE_DOWNLOADS_DIR = "downloads" + +os.makedirs(BASE_DOWNLOADS_DIR, exist_ok=True) + +@app.route("/", methods=["GET", "POST"]) +def index(): + if request.method == "POST": + url = request.form.get("url") + mode = request.form.get("mode") # 'audio' o 'video' + download_type = request.form.get("type") # 'single' o 'playlist' + + if not url: + return render_template("index.html", error="URL obligatoria") + + + # Modo single o playlist + if download_type == "single": + folder_id = str(uuid.uuid4()) + folder_path = os.path.join(BASE_DOWNLOADS_DIR, folder_id) + os.makedirs(folder_path, exist_ok=True) + + filename_template = "%(title)s.%(ext)s" + output_path = os.path.join(folder_path, filename_template) + + cmd = ["yt-dlp", "-o", output_path] + + if mode == "audio": + cmd += ["-x", "--audio-format", "mp3"] + + cmd.append(url) + + try: + subprocess.run(cmd, check=True) + + # Buscar el archivo descargado (único archivo en carpeta) + files = os.listdir(folder_path) + if not files: + return render_template("index.html", error="No se pudo descargar el archivo.") + + downloaded_file_path = os.path.join(folder_path, files[0]) + return send_file(downloaded_file_path, as_attachment=True, download_name=files[0]) + + except subprocess.CalledProcessError: + return render_template("index.html", error="Error al descargar el vídeo.") + + elif download_type == "playlist": + folder_id = str(uuid.uuid4()) + folder_path = os.path.join(BASE_DOWNLOADS_DIR, folder_id) + os.makedirs(folder_path, exist_ok=True) + + # Obtener título real de la playlist + try: + result = subprocess.run( + ["yt-dlp", "--flat-playlist", "--print", "%(playlist_title)s", url], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + check=True, + text=True + ) + #playlist_title = result.stdout.strip() + playlist_title = result.stdout.strip().splitlines()[0] + # Limpiar el nombre para que sea válido como nombre de archivo + playlist_title_clean = "".join(c for c in playlist_title if c.isalnum() or c in " _-").strip().replace(" ", "_") + print(f"Título original: {playlist_title}") + print(f"Título limpio: {playlist_title_clean}") + except subprocess.CalledProcessError: + return render_template("index.html", error="Error al obtener el título de la playlist.") + + output_path = os.path.join(folder_path, "%(title)s.%(ext)s") + cmd = ["yt-dlp", "-o", output_path] + + if mode == "audio": + cmd += ["-x", "--audio-format", "mp3"] + + cmd.append(url) + + try: + subprocess.run(cmd, check=True) + + # Comprimir en ZIP + zip_path = shutil.make_archive(folder_path, 'zip', folder_path) + zip_filename = f"{playlist_title_clean}.zip" + + # Enviar al navegador + return send_file(zip_path, as_attachment=True, download_name=zip_filename, mimetype='application/zip') + + except subprocess.CalledProcessError: + return render_template("index.html", error="Error al descargar la lista.") + + else: + return render_template("index.html", error="Tipo de descarga no válido.") + + return render_template("index.html") + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) + diff --git a/app/main.py.bak b/app/main.py.bak new file mode 100644 index 0000000..96200ee --- /dev/null +++ b/app/main.py.bak @@ -0,0 +1,87 @@ +from flask import Flask, render_template, request, send_file +import subprocess +import os +import uuid +import shutil + +app = Flask(__name__) +BASE_DOWNLOADS_DIR = "downloads" + +os.makedirs(BASE_DOWNLOADS_DIR, exist_ok=True) + +@app.route("/", methods=["GET", "POST"]) +def index(): + if request.method == "POST": + url = request.form.get("url") + mode = request.form.get("mode") # 'audio' o 'video' + download_type = request.form.get("type") # 'single' o 'playlist' + + if not url: + return render_template("index.html", error="URL obligatoria") + + # Modo single o playlist + if download_type == "single": + unique_id = str(uuid.uuid4()) + filename_template = f"{unique_id}.%(ext)s" + output_path = os.path.join(BASE_DOWNLOADS_DIR, filename_template) + + cmd = ["yt-dlp", "-o", output_path] + + if mode == "audio": + cmd += ["-x", "--audio-format", "mp3"] + + cmd.append(url) + + try: + subprocess.run(cmd, check=True) + + # Encuentra el archivo resultante + downloaded_file = None + for file in os.listdir(BASE_DOWNLOADS_DIR): + if file.startswith(unique_id): + downloaded_file = os.path.join(BASE_DOWNLOADS_DIR, file) + break + + if not downloaded_file: + return render_template("index.html", error="No se encontró el archivo descargado.") + + # Enviar al navegador y luego borrar + return send_file(downloaded_file, as_attachment=True, download_name=os.path.basename(downloaded_file), mimetype='application/octet-stream') + + except subprocess.CalledProcessError: + return render_template("index.html", error="Error al descargar el archivo.") + + elif download_type == "playlist": + folder_id = str(uuid.uuid4()) + folder_path = os.path.join(BASE_DOWNLOADS_DIR, folder_id) + os.makedirs(folder_path, exist_ok=True) + + output_path = os.path.join(folder_path, "%(title)s.%(ext)s") + cmd = ["yt-dlp", "-o", output_path] + + if mode == "audio": + cmd += ["-x", "--audio-format", "mp3"] + + cmd.append(url) + + try: + subprocess.run(cmd, check=True) + + # Comprimir en ZIP + zip_path = shutil.make_archive(folder_path, 'zip', folder_path) + + # Enviar al navegador + # return send_file(zip_path, as_attachment=True, download_name="descarga_playlist.zip", mimetype='application/zip') + return send_file(zip_path, as_attachment=True, download_name="%(playlist_title).zip", mimetype='application/zip') + + except subprocess.CalledProcessError: + return render_template("index.html", error="Error al descargar la lista.") + + else: + return render_template("index.html", error="Tipo de descarga no válido.") + + return render_template("index.html") + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) + diff --git a/app/requirements.txt b/app/requirements.txt new file mode 100644 index 0000000..e3e9a71 --- /dev/null +++ b/app/requirements.txt @@ -0,0 +1 @@ +Flask diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..8603143 --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,108 @@ + + +
+ +Los archivos descargados se guardan en la carpeta downloads/.