Download of Videos is now possible. Minor styling changes.

This commit is contained in:
Maximilian Wagner
2023-08-03 10:50:16 +02:00
parent 06bb8d22dd
commit c03d0bd6d9
7 changed files with 40 additions and 82 deletions

View File

@@ -1,6 +1,5 @@
import threading
import yt_dlp as ydl
from yt_dlp import DownloadError
import os
import zipfile
from datetime import datetime
@@ -13,15 +12,15 @@ from file_cache import *
# adds thread to queue and starts it
def enqueue_download(url, update=False):
def enqueue_download(url, update=False, ext='mp3'):
# download and processing is happening in background / another thread
t = Thread(target=process_general, args=(url,update))
t = Thread(target=process_general, args=(url, ext, update))
thread_queue.append(t)
t.start()
return
def process_general(url, update=False):
def process_general(url, ext, update=False):
# get current time and put in list to be displayed on /index
current_time = datetime.now().time()
running_downloads.append([url, str(current_time.hour) + ':' + str(current_time.minute)])
@@ -43,7 +42,7 @@ def process_general(url, update=False):
if update:
process_update(parent, query, current_thread)
else:
process_download(url, parent, query, current_thread)
process_download(url, ext, parent, query, current_thread)
try:
running_downloads.pop(0)
@@ -54,7 +53,7 @@ def process_general(url, update=False):
# this is the 'controller' for the download process
def process_download(url, parent, query, current_thread):
def process_download(url, ext, parent, query, current_thread):
# one of the three cases does not throw an exception
# and therefore gets to download and return
# kinda hacky but whatever
@@ -76,12 +75,12 @@ def process_download(url, parent, query, current_thread):
urls.append('https://www.youtube.com/watch?v=' + video['id'])
# start download
download_all(url, parent)
download_all(url, ext, parent)
thread_queue.remove(current_thread)
return
# when downloading: channel: DownloadError, single file: KeyError
except (DownloadError, KeyError):
except (ydl.DownloadError, KeyError):
pass
# if downloading channel
@@ -102,7 +101,7 @@ def process_download(url, parent, query, current_thread):
urls.append('https://www.youtube.com/watch?v=' + video['id'])
# start download
download_all(url, parent)
download_all(url, ext, parent)
thread_queue.remove(current_thread)
return
@@ -119,7 +118,7 @@ def process_download(url, parent, query, current_thread):
urls.append('https://www.youtube.com/watch?v=' + query['id'])
# start download
download_all(url)
download_all(url, ext=ext)
# this is broad on purpose; there has been no exception thrown here _yet_
except Exception as e:
@@ -156,7 +155,7 @@ def process_update(parent, query, current_thread):
return
# when downloading: channel: DownloadError, single file: KeyError
except (DownloadError, KeyError):
except (ydl.DownloadError, KeyError):
pass
# if downloading channel
@@ -196,7 +195,7 @@ def check_already_exists(video_id) -> bool:
return False
def download_all(url, parent=None, ext='mp3'):
def download_all(url, ext, parent=None):
# if no new files to download, there's nothing to do here
if not len(urls) > 0: return
@@ -311,7 +310,7 @@ def yt_download(location, ext='mp3'):
# try to download all new files
try:
ydl.YoutubeDL(opts).download(urls)
except DownloadError:
except ydl.DownloadError:
pass
return

View File

@@ -1,8 +1,9 @@
from flask_wtf import FlaskForm
from wtforms import URLField, SubmitField
from wtforms.validators import URL, DataRequired
from wtforms import URLField, SelectField, SubmitField
from wtforms.validators import URL, DataRequired, AnyOf
class DownloadForm(FlaskForm):
url = URLField('Video, Channel or Playlist', validators=[DataRequired(), URL()], render_kw={'placeholder': 'YouTube Link'})
ext = SelectField('Type', choices=[('mp3', 'Audio'), ('mp4', 'Video')], validators=[AnyOf(('mp3', 'mp4'))])
submit = SubmitField('Go')

View File

@@ -1,6 +1,6 @@
from __future__ import unicode_literals
from flask import Blueprint, request, render_template, flash, send_from_directory, current_app
from flask import Blueprint, request, render_template, flash, send_from_directory
from flask_nav3 import Nav
from flask_nav3.elements import Navbar, View
@@ -14,10 +14,9 @@ frontend = Blueprint('frontend', __name__)
nav = Nav()
nav.register_element('frontend_top', Navbar(
View('ytm-ls', '.index'),
View('downloader', '.downloader'),
View('updater', '.updater'),
View('library', '.library')
)
View('Downloader', '.downloader'),
View('Library', '.library')
)
)
@@ -36,11 +35,12 @@ def downloader():
# get url out of form
url = str(form.url.data)
ext = str(form.ext.data)
# check if valid link
# this tool should technically work with other platforms but that is not tested
# since KeyErrors are to be expected in backend.process_download(url), it's blocked here
# you are invited to test and adjust the code for other platforms and open a merge request
# you are invited to test and adjust the code for other platforms
valid_link = True if 'youtube.com' in url or 'youtu.be' in url else False
# if there has been a problem with the form (empty or error) or the link is not valid
@@ -49,7 +49,7 @@ def downloader():
return render_template('downloader.html', form=form, ytLink=valid_link, amount=len(urls))
# kick off download process
enqueue_download(url)
enqueue_download(url, ext=ext)
# show download start confirmation
flash('Download enqueued and will finish in background.')
@@ -75,21 +75,13 @@ def download(file_path):
)
@frontend.route('/update', methods=['GET', 'POST'])
def updater():
downloads = query_db('SELECT name, ROWID FROM playlist')
if not downloads:
flash('Library has no playlists yet. Try downloading some!')
return render_template('updater.html', downloads=downloads)
@frontend.route('/update/<int:url_rowid>')
@frontend.route('/update/<int:url_rowid>', methods=['GET'])
def update(url_rowid):
url = query_db('SELECT url FROM playlist WHERE ROWID = :url_rowid',
{'url_rowid': url_rowid})[0][0]
# kick off download process
enqueue_download(url, True)
enqueue_download(url, update=True)
# show download start confirmation
flash('Update enqueued and will finish in background.')

View File

@@ -2,7 +2,7 @@
{% block content %}
{{ super() }}
<div class="container" style="width: 50%">
<div class="container-fluid" style="width: fit-content(105%)">
<table id="videos" class="table">
<thead>
<tr>
@@ -14,7 +14,7 @@
{% for video in videos %}
<tr>
<td class="text-center">{{ video['name'] }}</td>
<td class="text-center"><a href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Link</a></td>
<td class="text-center"><a class="btn" href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Link</a></td>
</tr>
{% endfor %}
</tbody>

View File

@@ -2,18 +2,15 @@
{% block content %}
{{ super() }}
<div class="container">
<div class="card" style="width: fit-content">
<ul class="list-group list-group-flush">
<li class="list-group-item">
<form method="POST">
{{ form.csrf_token }}
{{ form.url.label }} <br>
{{ form.url }}
{{ form.submit }}
</form>
</li>
</ul>
<div class="container-fluid" style="width: fit-content; align-self: flex-start">
<div class="table-bordered" style="padding: .5cm">
<form method="POST" class="form-group">
{{ form.csrf_token }}
{{ form.url.label(class_="form-text") }} <br>
{{ form.url(class_="form-control") }} <br>
{{ form.ext(class_="form-control") }} <br>
{{ form.submit(class_="btn primary") }}
</form>
</div>
{% if form.errors %}

View File

@@ -2,7 +2,7 @@
{% block content %}
{{ super() }}
<div class="container" style="width: fit-content(105%)">
<div class="container-fluid" style="width: fit-content(105%)">
{% if playlists %}
<div class="card">
<ul class="list-group list-group-flush">
@@ -12,12 +12,14 @@
<thead>
<tr>
<th scope="col" class="text-center">Playlists</th>
<th scope="col" class="text-center">Update</th>
</tr>
</thead>
<tbody>
{% for playlist in playlists %}
<tr>
<td class="text-center"> <a href="/library-playlist?playlist={{ playlist['ROWID'] }}">{{ playlist['name'] }}</a></td>
<td class="text-center"><a class="btn" href="/library-playlist?playlist={{ playlist['ROWID'] }}">{{ playlist['name'] }}</a></td>
<td class="text-center"><a class="btn" href="/update/{{ playlist[1] }}">Start</a></td>
</tr>
{% endfor %}
</tbody>
@@ -46,7 +48,7 @@
{% for video in videos %}
<tr>
<td class="text-center">{{ video['name'] }}</td>
<td class="text-center"><a href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Link</a></td>
<td class="text-center"><a class="btn" href="/download/{{ video['path'] + video['name'] + video['ext'] }}" download>Link</a></td>
</tr>
{% endfor %}
</tbody>

View File

@@ -1,33 +0,0 @@
{%- extends "base.html" %}
{% block content %}
{{ super() }}
<div class="container" style="width: fit-content(105%)">
{% if downloads %}
<div class="card">
<ul class="list-group list-group-flush">
<li class="list-group-item">
<div class="row">
<table id="videos" class="table">
<thead>
<tr>
<th scope="col" class="text-center">Title</th>
<th scope="col" class="text-center">Update</th>
</tr>
</thead>
<tbody>
{% for d in downloads %}
<tr>
<td class="text-center">{{ d[0] }}</td>
<td class="text-center"><a href="/update/{{ d[1] }}">Start</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</li>
</ul>
</div>
{% endif %}
</div>
{%- endblock %}