mirror of
https://github.com/chibicitiberiu/ytsm.git
synced 2024-02-24 05:43:31 +00:00
Major refactor of codebase.
This commit is contained in:
@ -3,12 +3,12 @@ from django.http import JsonResponse
|
||||
from django.views.generic import View
|
||||
|
||||
from YtManagerApp.models import Video
|
||||
from YtManagerApp.scheduler.jobs.synchronize_job import SynchronizeJob
|
||||
from YtManagerApp.services import Services
|
||||
|
||||
|
||||
class SyncNowView(LoginRequiredMixin, View):
|
||||
def post(self, *args, **kwargs):
|
||||
SynchronizeJob.schedule_now()
|
||||
Services.subscriptionManager().synchronize_all()
|
||||
return JsonResponse({
|
||||
'success': True
|
||||
})
|
||||
|
@ -36,7 +36,7 @@ class RegisterView(FormView):
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if not Services.appConfig.allow_registrations:
|
||||
if not Services.appConfig().allow_registrations:
|
||||
return HttpResponseForbidden("Registrations are disabled!")
|
||||
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
@ -8,7 +8,6 @@ from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import FormView
|
||||
|
||||
from YtManagerApp.scheduler.jobs.synchronize_job import SynchronizeJob
|
||||
from YtManagerApp.services import Services
|
||||
from YtManagerApp.views.forms.first_time import WelcomeForm, ApiKeyForm, PickAdminUserForm, ServerConfigForm, DoneForm, \
|
||||
UserCreationForm, LoginForm
|
||||
@ -16,7 +15,7 @@ from YtManagerApp.views.forms.first_time import WelcomeForm, ApiKeyForm, PickAdm
|
||||
logger = logging.getLogger("FirstTimeWizard")
|
||||
|
||||
|
||||
class WizardStepMixin:
|
||||
class WizardStepMixin(object):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@ -24,7 +23,7 @@ class WizardStepMixin:
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
# Prevent access if application is already initialized
|
||||
if Services.appConfig.initialized:
|
||||
if Services.appConfig().initialized:
|
||||
logger.debug(f"Attempted to access {request.path}, but first time setup already run. Redirected to home "
|
||||
f"page.")
|
||||
return redirect('home')
|
||||
@ -32,7 +31,7 @@ class WizardStepMixin:
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if Services.appConfig.initialized:
|
||||
if Services.appConfig().initialized:
|
||||
logger.debug(f"Attempted to post {request.path}, but first time setup already run.")
|
||||
return HttpResponseForbidden()
|
||||
return super().post(request, *args, **kwargs)
|
||||
@ -65,14 +64,14 @@ class Step1ApiKeyView(WizardStepMixin, FormView):
|
||||
|
||||
def get_initial(self):
|
||||
initial = super().get_initial()
|
||||
initial['api_key'] = Services.appConfig.youtube_api_key
|
||||
initial['api_key'] = Services.appConfig().youtube_api_key
|
||||
return initial
|
||||
|
||||
def form_valid(self, form):
|
||||
key = form.cleaned_data['api_key']
|
||||
# TODO: validate key
|
||||
if key is not None and len(key) > 0:
|
||||
Services.appConfig.youtube_api_key = key
|
||||
Services.appConfig().youtube_api_key = key
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
@ -149,8 +148,8 @@ class Step3ConfigureView(WizardStepMixin, FormView):
|
||||
|
||||
def get_initial(self):
|
||||
initial = super().get_initial()
|
||||
initial['allow_registrations'] = Services.appConfig.allow_registrations
|
||||
initial['sync_schedule'] = Services.appConfig.sync_schedule
|
||||
initial['allow_registrations'] = Services.appConfig().allow_registrations
|
||||
initial['sync_schedule'] = Services.appConfig().sync_schedule
|
||||
initial['auto_download'] = self.request.user.preferences['auto_download']
|
||||
initial['download_location'] = self.request.user.preferences['download_path']
|
||||
return initial
|
||||
@ -158,11 +157,11 @@ class Step3ConfigureView(WizardStepMixin, FormView):
|
||||
def form_valid(self, form):
|
||||
allow_registrations = form.cleaned_data['allow_registrations']
|
||||
if allow_registrations is not None:
|
||||
Services.appConfig.allow_registrations = allow_registrations
|
||||
Services.appConfig().allow_registrations = allow_registrations
|
||||
|
||||
sync_schedule = form.cleaned_data['sync_schedule']
|
||||
if sync_schedule is not None and len(sync_schedule) > 0:
|
||||
Services.appConfig.sync_schedule = sync_schedule
|
||||
Services.appConfig().sync_schedule = sync_schedule
|
||||
|
||||
auto_download = form.cleaned_data['auto_download']
|
||||
if auto_download is not None:
|
||||
@ -173,11 +172,11 @@ class Step3ConfigureView(WizardStepMixin, FormView):
|
||||
self.request.user.preferences['download_path'] = download_location
|
||||
|
||||
# Set initialized to true
|
||||
Services.appConfig.initialized = True
|
||||
Services.appConfig().initialized = True
|
||||
|
||||
# Start scheduler if not started
|
||||
Services.scheduler.initialize()
|
||||
SynchronizeJob.schedule_global_job()
|
||||
Services.scheduler().initialize()
|
||||
Services.subscriptionManager().schedule_global_synchronize_job()
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
|
@ -234,25 +234,25 @@ class AdminSettingsForm(forms.Form):
|
||||
@staticmethod
|
||||
def get_initials():
|
||||
return {
|
||||
'api_key': Services.appConfig.youtube_api_key,
|
||||
'allow_registrations': Services.appConfig.allow_registrations,
|
||||
'sync_schedule': Services.appConfig.sync_schedule,
|
||||
'scheduler_concurrency': Services.appConfig.concurrency,
|
||||
'api_key': Services.appConfig().youtube_api_key,
|
||||
'allow_registrations': Services.appConfig().allow_registrations,
|
||||
'sync_schedule': Services.appConfig().sync_schedule,
|
||||
'scheduler_concurrency': Services.appConfig().concurrency,
|
||||
}
|
||||
|
||||
def save(self):
|
||||
api_key = self.cleaned_data['api_key']
|
||||
if api_key is not None and len(api_key) > 0:
|
||||
Services.appConfig.youtube_api_key = api_key
|
||||
Services.appConfig().youtube_api_key = api_key
|
||||
|
||||
allow_registrations = self.cleaned_data['allow_registrations']
|
||||
if allow_registrations is not None:
|
||||
Services.appConfig.allow_registrations = allow_registrations
|
||||
Services.appConfig().allow_registrations = allow_registrations
|
||||
|
||||
sync_schedule = self.cleaned_data['sync_schedule']
|
||||
if sync_schedule is not None and len(sync_schedule) > 0:
|
||||
Services.appConfig.sync_schedule = sync_schedule
|
||||
Services.appConfig().sync_schedule = sync_schedule
|
||||
|
||||
concurrency = self.cleaned_data['scheduler_concurrency']
|
||||
if concurrency is not None:
|
||||
Services.appConfig.concurrency = concurrency
|
||||
Services.appConfig().concurrency = concurrency
|
||||
|
@ -1,22 +1,21 @@
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Layout, Field, HTML
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Q
|
||||
from django.http import HttpRequest, HttpResponseBadRequest, JsonResponse
|
||||
from django.shortcuts import render, redirect
|
||||
from django.views.generic import CreateView, UpdateView, DeleteView, FormView
|
||||
from django.views.generic.edit import FormMixin
|
||||
from django.conf import settings
|
||||
from django.core.paginator import Paginator
|
||||
from YtManagerApp.management.videos import get_videos
|
||||
from YtManagerApp.models import Subscription, SubscriptionFolder, VIDEO_ORDER_CHOICES, VIDEO_ORDER_MAPPING
|
||||
from YtManagerApp.services import Services
|
||||
from YtManagerApp.utils import youtube, subscription_file_parser
|
||||
from YtManagerApp.views.controls.modal import ModalMixin
|
||||
|
||||
import logging
|
||||
from YtManagerApp.models import Subscription, SubscriptionFolder, VIDEO_ORDER_CHOICES, VIDEO_ORDER_MAPPING
|
||||
from YtManagerApp.providers.video_provider import InvalidURLError
|
||||
from YtManagerApp.services import Services
|
||||
from YtManagerApp.utils import subscription_file_parser
|
||||
from YtManagerApp.views.controls.modal import ModalMixin
|
||||
|
||||
|
||||
class VideoFilterForm(forms.Form):
|
||||
@ -110,8 +109,7 @@ def __tree_sub_id(sub_id):
|
||||
|
||||
|
||||
def index(request: HttpRequest):
|
||||
|
||||
if not Services.appConfig.initialized:
|
||||
if not Services.appConfig().initialized:
|
||||
return redirect('first_time_0')
|
||||
|
||||
context = {
|
||||
@ -129,7 +127,6 @@ def index(request: HttpRequest):
|
||||
|
||||
@login_required
|
||||
def ajax_get_tree(request: HttpRequest):
|
||||
|
||||
def visit(node):
|
||||
if isinstance(node, SubscriptionFolder):
|
||||
return {
|
||||
@ -157,7 +154,7 @@ def ajax_get_videos(request: HttpRequest):
|
||||
if request.method == 'POST':
|
||||
form = VideoFilterForm(request.POST)
|
||||
if form.is_valid():
|
||||
videos = get_videos(
|
||||
videos = Services.videoManager().get_videos(
|
||||
user=request.user,
|
||||
sort_order=form.cleaned_data['sort'],
|
||||
query=form.cleaned_data['query'],
|
||||
@ -272,7 +269,6 @@ class CreateSubscriptionForm(forms.ModelForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.yt_api = youtube.YoutubeAPI.build_public()
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_tag = False
|
||||
self.helper.layout = Layout(
|
||||
@ -289,16 +285,9 @@ class CreateSubscriptionForm(forms.ModelForm):
|
||||
def clean_playlist_url(self):
|
||||
playlist_url: str = self.cleaned_data['playlist_url']
|
||||
try:
|
||||
parsed_url = self.yt_api.parse_url(playlist_url)
|
||||
except youtube.InvalidURL as e:
|
||||
Services.videoProviderManager().validate_subscription_url(playlist_url)
|
||||
except InvalidURLError as e:
|
||||
raise forms.ValidationError(str(e))
|
||||
|
||||
is_playlist = 'playlist' in parsed_url
|
||||
is_channel = parsed_url['type'] in ('channel', 'user', 'channel_custom')
|
||||
|
||||
if not is_channel and not is_playlist:
|
||||
raise forms.ValidationError('The given URL must link to a channel or a playlist!')
|
||||
|
||||
return playlist_url
|
||||
|
||||
|
||||
@ -308,10 +297,12 @@ class CreateSubscriptionModal(LoginRequiredMixin, ModalMixin, CreateView):
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.user = self.request.user
|
||||
api = youtube.YoutubeAPI.build_public()
|
||||
try:
|
||||
form.instance.fetch_from_url(form.cleaned_data['playlist_url'], api)
|
||||
except youtube.InvalidURL as e:
|
||||
subscription: Subscription = Services.videoProviderManager().fetch_subscription(
|
||||
form.cleaned_data['playlist_url'])
|
||||
form.instance.copy_from(subscription)
|
||||
form.instance.user = self.request.user
|
||||
except InvalidURLError as e:
|
||||
return self.modal_response(form, False, str(e))
|
||||
except ValueError as e:
|
||||
return self.modal_response(form, False, str(e))
|
||||
@ -327,8 +318,9 @@ class CreateSubscriptionModal(LoginRequiredMixin, ModalMixin, CreateView):
|
||||
# except youtube.APIError as e:
|
||||
# return self.modal_response(
|
||||
# form, False, 'An error occurred while communicating with the YouTube API: ' + str(e))
|
||||
|
||||
return super().form_valid(form)
|
||||
response = super().form_valid(form)
|
||||
Services.subscriptionManager().synchronize(form.instance)
|
||||
return response
|
||||
|
||||
|
||||
class UpdateSubscriptionForm(forms.ModelForm):
|
||||
@ -407,7 +399,6 @@ class ImportSubscriptionsForm(forms.Form):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.yt_api = youtube.YoutubeAPI.build_public()
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_tag = False
|
||||
self.helper.layout = Layout(
|
||||
@ -456,28 +447,18 @@ class ImportSubscriptionsModal(LoginRequiredMixin, ModalMixin, FormView):
|
||||
try:
|
||||
url_list = list(subscription_file_parser.parse(file))
|
||||
except subscription_file_parser.FormatNotSupportedError:
|
||||
return super().modal_response(form, success=False,
|
||||
return super().modal_response(form,
|
||||
success=False,
|
||||
error_msg="The file could not be parsed! "
|
||||
"Possible problems: format not supported, file is malformed.")
|
||||
|
||||
print(form.cleaned_data)
|
||||
|
||||
# Create subscriptions
|
||||
api = youtube.YoutubeAPI.build_public()
|
||||
for url in url_list:
|
||||
sub = Subscription()
|
||||
sub.user = self.request.user
|
||||
sub.parent_folder = form.cleaned_data['parent_folder']
|
||||
sub.auto_download = form.cleaned_data['auto_download']
|
||||
sub.download_limit = form.cleaned_data['download_limit']
|
||||
sub.download_order = form.cleaned_data['download_order']
|
||||
sub.automatically_delete_watched = form.cleaned_data["automatically_delete_watched"]
|
||||
try:
|
||||
sub.fetch_from_url(url, api)
|
||||
except Exception as e:
|
||||
logging.error("Import subscription error - error processing URL %s: %s", url, e)
|
||||
continue
|
||||
|
||||
sub.save()
|
||||
Services.subscriptionManager().import_multiple(url_list,
|
||||
form.cleaned_data['parent_folder'],
|
||||
form.cleaned_data['auto_download'],
|
||||
form.cleaned_data['download_limit'],
|
||||
form.cleaned_data['download_order'],
|
||||
form.cleaned_data["automatically_delete_watched"])
|
||||
|
||||
return super().form_valid(form)
|
||||
|
@ -3,7 +3,7 @@ from django.http import HttpResponseForbidden
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import FormView
|
||||
|
||||
from YtManagerApp.scheduler.jobs.synchronize_job import SynchronizeJob
|
||||
from YtManagerApp.services import Services
|
||||
from YtManagerApp.views.forms.settings import SettingsForm, AdminSettingsForm
|
||||
|
||||
|
||||
@ -45,5 +45,5 @@ class AdminSettingsView(LoginRequiredMixin, FormView):
|
||||
|
||||
def form_valid(self, form):
|
||||
form.save()
|
||||
SynchronizeJob.schedule_global_job()
|
||||
Services.subscriptionManager().schedule_global_synchronize_job()
|
||||
return super().form_valid(form)
|
||||
|
@ -1,8 +1,6 @@
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest, StreamingHttpResponse, FileResponse
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.views import View
|
||||
from django.http import HttpRequest, FileResponse
|
||||
from django.views.generic import DetailView
|
||||
|
||||
from YtManagerApp.models import Video
|
||||
|
Reference in New Issue
Block a user