# -*- mode: python; -*- """ routes.py module ---------------- This Python module contains the logic supporting: 1. Navigating between website pages 2. Interpreting user requests to the server 3. Dispatching requested content back to the user Python dependencies: - flask: provides web application features - forms: provides secure user form submission - sqlalchemy: provides communication with database on server. Personal imports: These are used to avoid cluttering this file with placeholder data for posts' content. """ import os import time import glob from datetime import datetime from concurrent.futures import ThreadPoolExecutor from flask import ( Blueprint, render_template, send_from_directory, request, redirect, flash, url_for, jsonify, abort, ) from flask_login import login_required, current_user import youtube_dl from .models import db, Download from .forms import DownloadToRemote, ManageRemote main = Blueprint("main", __name__) executor = ThreadPoolExecutor(4) @main.route("/") @main.route("/index") @login_required def home(): """Prompt for video URL.""" # https://www.youtube.com/watch?v=86khmc6y1yE&list=RDGMEMYH9CUrFO7CfLJpaD7UR85w&index=13 download_history = Download.query.order_by(Download.primary_key.desc()).all() downloaded_files = [ file for file in os.listdir("downloads") if file.endswith((".mp3", ".m4a")) ] pending_files = [file for file in os.listdir("downloads") if file.endswith(".part")] return render_template( "home.html", user=current_user, form_download_remote=DownloadToRemote(), form_manage_remote=ManageRemote(), downloaded_files=downloaded_files, pending_files=pending_files, download_history=download_history, ) @main.route("/download-remote", methods=["POST"]) @login_required def download_remote(): """Download audio from URL onto server.""" form = DownloadToRemote() if form.validate_on_submit(): url = request.form["url"] ydl_opts = { "format": "bestaudio/best", "outtmpl": os.path.join( os.getcwd(), "downloads", "%(title)s.%(ext)s", ), "noplaylist": True, "postprocessors": [ { "key": "FFmpegExtractAudio", "preferredcodec": "mp3", "preferredquality": "192", } ], } executor.submit(youtube_dl.YoutubeDL(ydl_opts).download, [url]) with youtube_dl.YoutubeDL(ydl_opts) as ydl: # time.sleep(1) info = ydl.extract_info(url, download=False) title = info.get("title") new_download = Download( title=title, url=url, user_id=current_user.primary_key, ) db.session.add(new_download) db.session.commit() flash(f"Successfully started downloading {title}.") return redirect("/index") flash(f"Couldn't download {title}.") return redirect("/index") @main.route("/manage-remote/", methods=["POST"]) @login_required def manage_remote(): """Manage all files downloaded on remote device. The value of the submit button pressed is checked, then the appropriate redirection is performed. """ form = ManageRemote() if form.validate_on_submit(): file_name = request.form.get("file_name") if form.download_local.data: return redirect(url_for("main.download_local", file=file_name)) elif form.remove_remote.data: return redirect(url_for("main.remove_remote", file=file_name)) flash("Couldn't manage remote file.", "error") return redirect("/index") @main.route("/download-local/", methods=["GET", "POST"]) @login_required def download_local(file): """Download file from remote to local device.""" downloads = os.path.join(os.getcwd(), "downloads") return send_from_directory(downloads, file, as_attachment=True) @main.route("/remove-remote/", methods=["GET", "POST"]) @login_required def remove_remote(file): """Remove file from remote device.""" file_to_remove = os.path.join(os.getcwd(), "downloads", file) os.remove(file_to_remove) flash(f"Successfully removed file {file}.") return redirect("/index")