delete source page, start of youtube-dl wrapper
This commit is contained in:
parent
c87adf86d5
commit
060691202b
|
@ -36,7 +36,7 @@ $form-error-text-colour: $colour-near-white;
|
|||
$form-help-text-colour: $colour-light-blue;
|
||||
$form-delete-button-background-colour: $colour-red;
|
||||
|
||||
$collection-no-items-text-colour: $colour-light-blue;
|
||||
$collection-no-items-text-colour: $colour-near-black;
|
||||
$collection-background-hover-colour: $colour-orange;
|
||||
$collection-text-hover-colour: $colour-near-white;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class ValidateSourceForm(forms.Form):
|
||||
|
@ -10,6 +11,14 @@ class ValidateSourceForm(forms.Form):
|
|||
widget=forms.HiddenInput()
|
||||
)
|
||||
source_url = forms.URLField(
|
||||
label='Source URL',
|
||||
label=_('Source URL'),
|
||||
required=True
|
||||
)
|
||||
|
||||
|
||||
class ConfirmDeleteSourceForm(forms.Form):
|
||||
|
||||
delete_media = forms.BooleanField(
|
||||
label=_('Also delete downloaded media'),
|
||||
required=False
|
||||
)
|
||||
|
|
|
@ -66,7 +66,7 @@ class Source(models.Model):
|
|||
}
|
||||
|
||||
URLS = {
|
||||
SOURCE_TYPE_YOUTUBE_CHANNEL: 'https://www.youtube.com/{key}',
|
||||
SOURCE_TYPE_YOUTUBE_CHANNEL: 'https://www.youtube.com/c/{key}',
|
||||
SOURCE_TYPE_YOUTUBE_PLAYLIST: 'https://www.youtube.com/playlist?list={key}',
|
||||
}
|
||||
|
||||
|
@ -172,11 +172,15 @@ class Source(models.Model):
|
|||
@property
|
||||
def icon(self):
|
||||
return self.ICONS.get(self.source_type)
|
||||
|
||||
|
||||
@classmethod
|
||||
def create_url(obj, source_type, key):
|
||||
url = obj.URLS.get(source_type)
|
||||
return url.format(key=key)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
url = self.URLS.get(self.source_type)
|
||||
return url.format(key=self.key)
|
||||
return Source.create_url(self.source_type, self.key)
|
||||
|
||||
@property
|
||||
def directory_path(self):
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block headtitle %}Delete source - {{ source.name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row no-margin-bottom">
|
||||
<div class="col s12">
|
||||
<h1>Delete source <strong>{{ source.name }}</strong></h1>
|
||||
<p>
|
||||
Are you sure you want to delete this source? Deleting a source is permanent.
|
||||
By default, deleting a source does not delete any saved media files. You can
|
||||
tick the "also delete downloaded media" checkbox to also remove save
|
||||
media when you delete the source. Deleting a source cannot be undone.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form method="post" action="{% url 'sync:delete-source' pk=source.pk %}" class="col s12 simpleform">
|
||||
{% csrf_token %}
|
||||
{% include 'simpleform.html' with form=form %}
|
||||
<div class="row no-margin-bottom padding-top">
|
||||
<div class="col s12">
|
||||
<button class="btn" type="submit" name="action">Really delete source <i class="fas fa-trash-alt"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -80,7 +80,7 @@
|
|||
<a href="{% url 'sync:update-source' pk=source.pk %}" class="btn">Edit source <i class="fas fa-pen-square"></i></a>
|
||||
</div>
|
||||
<div class="col s12 l6 margin-bottom">
|
||||
<a href="" class="btn delete-button">Delete source <i class="fas fa-trash-alt"></i></a>
|
||||
<a href="{% url 'sync:delete-source' pk=source.pk %}" class="btn delete-button">Delete source <i class="fas fa-trash-alt"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.urls import path
|
||||
from .views import (DashboardView, SourcesView, ValidateSourceView, AddSourceView,
|
||||
SourceView, UpdateSourceView, MediaView, TasksView, LogsView)
|
||||
SourceView, UpdateSourceView, DeleteSourceView, MediaView,
|
||||
TasksView, LogsView)
|
||||
|
||||
|
||||
app_name = 'sync'
|
||||
|
@ -36,9 +37,13 @@ urlpatterns = [
|
|||
UpdateSourceView.as_view(),
|
||||
name='update-source'),
|
||||
|
||||
# Media URLs
|
||||
path('source-delete/<uuid:pk>',
|
||||
DeleteSourceView.as_view(),
|
||||
name='delete-source'),
|
||||
|
||||
path('media',
|
||||
# Media URLs (note /media/ is the static media URL, don't use that)
|
||||
|
||||
path('mediafiles',
|
||||
MediaView.as_view(),
|
||||
name='media'),
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
from django.conf import settings
|
||||
from django.http import Http404
|
||||
from django.views.generic import TemplateView, ListView, DetailView
|
||||
from django.views.generic.edit import FormView, CreateView, UpdateView
|
||||
from django.views.generic.edit import (FormView, FormMixin, CreateView, UpdateView,
|
||||
DeleteView)
|
||||
from django.urls import reverse_lazy
|
||||
from django.forms import ValidationError
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from common.utils import append_uri_params
|
||||
from .models import Source
|
||||
from .forms import ValidateSourceForm
|
||||
from .forms import ValidateSourceForm, ConfirmDeleteSourceForm
|
||||
from .utils import validate_url
|
||||
from . import youtube
|
||||
|
||||
|
||||
class DashboardView(TemplateView):
|
||||
|
@ -155,7 +157,7 @@ class ValidateSourceView(FormView):
|
|||
ValidationError(self.errors['invalid_source'])
|
||||
)
|
||||
source_url = form.cleaned_data['source_url']
|
||||
validation_url = self.validation_urls.get(self.source_type)
|
||||
validation_url = self.validation_urls.get(source_type)
|
||||
try:
|
||||
self.key = validate_url(source_url, validation_url)
|
||||
except ValidationError as e:
|
||||
|
@ -246,6 +248,30 @@ class UpdateSourceView(UpdateView):
|
|||
return append_uri_params(url, {'message': 'source-updated'})
|
||||
|
||||
|
||||
class DeleteSourceView(DeleteView, FormMixin):
|
||||
'''
|
||||
Confirm the deletion of a source with an option to delete all the media
|
||||
associated with the source from disk when the source is deleted.
|
||||
'''
|
||||
|
||||
template_name = 'sync/source-delete.html'
|
||||
model = Source
|
||||
form_class = ConfirmDeleteSourceForm
|
||||
context_object_name = 'source'
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
delete_media_val = request.POST.get('delete_media', False)
|
||||
delete_media = True if delete_media_val is not False else False
|
||||
if delete_media:
|
||||
# TODO: delete media files from disk linked to this source
|
||||
pass
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
url = reverse_lazy('sync:sources')
|
||||
return append_uri_params(url, {'message': 'source-deleted'})
|
||||
|
||||
|
||||
class MediaView(TemplateView):
|
||||
'''
|
||||
A bare list of media added with their states.
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
'''
|
||||
Wrapper for the youtube-dl library. Used so if there are any library interface
|
||||
updates we only need to udpate them in one place.
|
||||
'''
|
||||
|
||||
|
||||
from django.conf import settings
|
||||
import youtube_dl
|
||||
|
||||
|
||||
_defaults = getattr(settings, 'YOUTUBE_DEFAULTS', {})
|
||||
|
||||
|
||||
class YouTubeError(youtube_dl.utils.DownloadError):
|
||||
'''
|
||||
Generic wrapped error for all errors that could be raised by youtube-dl.
|
||||
'''
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def extract_info(url):
|
||||
'''
|
||||
Extracts information from a YouTube URL and returns it as a dict. For a channel
|
||||
or playlist this returns a dict of all the videos on the channel or playlist
|
||||
as well as associated metadata.
|
||||
'''
|
||||
opts = _defaults.update({
|
||||
'skip_download': True,
|
||||
'forcejson': True,
|
||||
'simulate': True,
|
||||
'extract_flat': 'in_playlist',
|
||||
'playlist_items': 1,
|
||||
})
|
||||
response = {}
|
||||
with youtube_dl.YoutubeDL(opts) as y:
|
||||
try:
|
||||
response = y.extract_info(url, download=False)
|
||||
except youtube_dl.utils.DownloadError as e:
|
||||
raise YouTubeError(f'Failed to extract_info for "{url}": {e}') from e
|
||||
return response
|
|
@ -119,6 +119,11 @@ DJANGO_SIMPLE_TASK_WORKERS = 2
|
|||
SOURCES_PER_PAGE = 25
|
||||
|
||||
|
||||
YOUTUBE_DEFAULTS = {
|
||||
'age_limit': 99,
|
||||
}
|
||||
|
||||
|
||||
try:
|
||||
from .local_settings import *
|
||||
except ImportError as e:
|
||||
|
|
Loading…
Reference in New Issue