summaryrefslogtreecommitdiff
path: root/app/main.py
blob: 149ef641d17e549cfc83956ccab64e1ea86a8e80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# -*- 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/<file>", 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/<file>", 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")
Copyright 2019--2024 Marius PETER