mirror of
https://github.com/chibicitiberiu/ytsm.git
synced 2024-02-24 05:43:31 +00:00
Fixed user settings page.
This commit is contained in:
parent
076d09e294
commit
10fced57e1
@ -12,8 +12,6 @@ import os
|
|||||||
hidden = Section('hidden')
|
hidden = Section('hidden')
|
||||||
general = Section('general')
|
general = Section('general')
|
||||||
scheduler = Section('scheduler')
|
scheduler = Section('scheduler')
|
||||||
manager = Section('manager')
|
|
||||||
downloader = Section('downloader')
|
|
||||||
|
|
||||||
|
|
||||||
# Hidden settings
|
# Hidden settings
|
||||||
@ -60,7 +58,6 @@ class SchedulerConcurrency(IntegerPreference):
|
|||||||
# User settings
|
# User settings
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class MarkDeletedAsWatched(BooleanPreference):
|
class MarkDeletedAsWatched(BooleanPreference):
|
||||||
section = manager
|
|
||||||
name = 'mark_deleted_as_watched'
|
name = 'mark_deleted_as_watched'
|
||||||
default = True
|
default = True
|
||||||
required = True
|
required = True
|
||||||
@ -68,47 +65,41 @@ class MarkDeletedAsWatched(BooleanPreference):
|
|||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class AutoDeleteWatched(BooleanPreference):
|
class AutoDeleteWatched(BooleanPreference):
|
||||||
section = manager
|
name = 'automatically_delete_watched'
|
||||||
name = 'auto_delete_watched'
|
|
||||||
default = True
|
default = True
|
||||||
required = True
|
required = True
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class AutoDownloadEnabled(BooleanPreference):
|
class AutoDownloadEnabled(BooleanPreference):
|
||||||
section = downloader
|
name = 'auto_download'
|
||||||
name = 'auto_enabled'
|
|
||||||
default = True
|
default = True
|
||||||
required = True
|
required = True
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadGlobalLimit(IntegerPreference):
|
class DownloadGlobalLimit(IntegerPreference):
|
||||||
section = downloader
|
name = 'download_global_limit'
|
||||||
name = 'global_limit'
|
default = -1
|
||||||
default = None
|
|
||||||
required = False
|
required = False
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadGlobalSizeLimit(IntegerPreference):
|
class DownloadGlobalSizeLimit(IntegerPreference):
|
||||||
section = downloader
|
name = 'download_global_size_limit'
|
||||||
name = 'global_size_limit_mb'
|
default = -1
|
||||||
default = None
|
|
||||||
required = False
|
required = False
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadSubscriptionLimit(IntegerPreference):
|
class DownloadSubscriptionLimit(IntegerPreference):
|
||||||
section = downloader
|
name = 'download_subscription_limit'
|
||||||
name = 'limit_per_subscription'
|
|
||||||
default = 5
|
default = 5
|
||||||
required = False
|
required = False
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadMaxAttempts(IntegerPreference):
|
class DownloadMaxAttempts(IntegerPreference):
|
||||||
section = downloader
|
|
||||||
name = 'max_download_attempts'
|
name = 'max_download_attempts'
|
||||||
default = 3
|
default = 3
|
||||||
required = True
|
required = True
|
||||||
@ -116,7 +107,6 @@ class DownloadMaxAttempts(IntegerPreference):
|
|||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadOrder(ChoicePreference):
|
class DownloadOrder(ChoicePreference):
|
||||||
section = downloader
|
|
||||||
name = 'download_order'
|
name = 'download_order'
|
||||||
choices = VIDEO_ORDER_CHOICES
|
choices = VIDEO_ORDER_CHOICES
|
||||||
default = 'playlist'
|
default = 'playlist'
|
||||||
@ -125,7 +115,6 @@ class DownloadOrder(ChoicePreference):
|
|||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadPath(StringPreference):
|
class DownloadPath(StringPreference):
|
||||||
section = downloader
|
|
||||||
name = 'download_path'
|
name = 'download_path'
|
||||||
default = os.path.join(settings.DATA_DIR, 'downloads')
|
default = os.path.join(settings.DATA_DIR, 'downloads')
|
||||||
required = False
|
required = False
|
||||||
@ -133,7 +122,6 @@ class DownloadPath(StringPreference):
|
|||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadFilePattern(StringPreference):
|
class DownloadFilePattern(StringPreference):
|
||||||
section = downloader
|
|
||||||
name = 'download_file_pattern'
|
name = 'download_file_pattern'
|
||||||
default = '${channel}/${playlist}/S01E${playlist_index} - ${title} [${id}]'
|
default = '${channel}/${playlist}/S01E${playlist_index} - ${title} [${id}]'
|
||||||
required = True
|
required = True
|
||||||
@ -141,7 +129,6 @@ class DownloadFilePattern(StringPreference):
|
|||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadFormat(StringPreference):
|
class DownloadFormat(StringPreference):
|
||||||
section = downloader
|
|
||||||
name = 'download_format'
|
name = 'download_format'
|
||||||
default = 'bestvideo+bestaudio'
|
default = 'bestvideo+bestaudio'
|
||||||
required = True
|
required = True
|
||||||
@ -149,39 +136,34 @@ class DownloadFormat(StringPreference):
|
|||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadSubtitles(BooleanPreference):
|
class DownloadSubtitles(BooleanPreference):
|
||||||
section = downloader
|
name = 'download_subtitles'
|
||||||
name = 'subtitles_enabled'
|
|
||||||
default = True
|
default = True
|
||||||
required = True
|
required = True
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadAutogeneratedSubtitles(BooleanPreference):
|
class DownloadAutogeneratedSubtitles(BooleanPreference):
|
||||||
section = downloader
|
name = 'download_autogenerated_subtitles'
|
||||||
name = 'autogenerated_subtitles'
|
|
||||||
default = False
|
default = False
|
||||||
required = True
|
required = True
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadAllSubtitles(BooleanPreference):
|
class DownloadAllSubtitles(BooleanPreference):
|
||||||
section = downloader
|
name = 'download_subtitles_all'
|
||||||
name = 'all_subtitles'
|
|
||||||
default = False
|
default = False
|
||||||
required = False
|
required = False
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadSubtitlesLangs(StringPreference):
|
class DownloadSubtitlesLangs(StringPreference):
|
||||||
section = downloader
|
name = 'download_subtitles_langs'
|
||||||
name = 'subtitles_langs'
|
|
||||||
default = 'en,ro'
|
default = 'en,ro'
|
||||||
required = False
|
required = False
|
||||||
|
|
||||||
|
|
||||||
@user_preferences_registry.register
|
@user_preferences_registry.register
|
||||||
class DownloadSubtitlesFormat(StringPreference):
|
class DownloadSubtitlesFormat(StringPreference):
|
||||||
section = downloader
|
name = 'download_subtitles_format'
|
||||||
name = 'subtitles_format'
|
default = ''
|
||||||
default = False
|
|
||||||
required = False
|
required = False
|
||||||
|
@ -14,9 +14,9 @@ log = logging.getLogger('downloader')
|
|||||||
def __get_subscription_config(sub: Subscription):
|
def __get_subscription_config(sub: Subscription):
|
||||||
user = sub.user
|
user = sub.user
|
||||||
|
|
||||||
enabled = first_non_null(sub.auto_download, user.preferences['download_enabled'])
|
enabled = first_non_null(sub.auto_download, user.preferences['auto_download'])
|
||||||
global_limit = user.preferences['download_global_limit']
|
global_limit = user.preferences['download_global_limit']
|
||||||
limit = first_non_null(sub.download_limit, user.preferences['download_limit_per_subscription'])
|
limit = first_non_null(sub.download_limit, user.preferences['download_subscription_limit'])
|
||||||
order = first_non_null(sub.download_order, user.preferences['download_order'])
|
order = first_non_null(sub.download_order, user.preferences['download_order'])
|
||||||
order = VIDEO_ORDER_MAPPING[order]
|
order = VIDEO_ORDER_MAPPING[order]
|
||||||
|
|
||||||
|
@ -59,9 +59,9 @@ def __build_youtube_dl_params(video: Video):
|
|||||||
'outtmpl': output_path,
|
'outtmpl': output_path,
|
||||||
'writethumbnail': True,
|
'writethumbnail': True,
|
||||||
'writedescription': True,
|
'writedescription': True,
|
||||||
'writesubtitles': user.preferences['subtitles_enabled'],
|
'writesubtitles': user.preferences['download_subtitles'],
|
||||||
'writeautomaticsub': user.preferences['autogenerated_subtitles'],
|
'writeautomaticsub': user.preferences['download_autogenerated_subtitles'],
|
||||||
'allsubtitles': user.preferences['all_subtitles'],
|
'allsubtitles': user.preferences['download_subtitles_all'],
|
||||||
'postprocessors': [
|
'postprocessors': [
|
||||||
{
|
{
|
||||||
'key': 'FFmpegMetadata'
|
'key': 'FFmpegMetadata'
|
||||||
@ -69,12 +69,12 @@ def __build_youtube_dl_params(video: Video):
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
sub_langs = user.preferences['subtitles_langs'].split(',')
|
sub_langs = user.preferences['download_subtitles_langs'].split(',')
|
||||||
sub_langs = [i.strip() for i in sub_langs]
|
sub_langs = [i.strip() for i in sub_langs]
|
||||||
if len(sub_langs) > 0:
|
if len(sub_langs) > 0:
|
||||||
youtube_dl_params['subtitleslangs'] = sub_langs
|
youtube_dl_params['subtitleslangs'] = sub_langs
|
||||||
|
|
||||||
sub_format = user.preferences['subtitles_format']
|
sub_format = user.preferences['download_subtitles_format']
|
||||||
if len(sub_format) > 0:
|
if len(sub_format) > 0:
|
||||||
youtube_dl_params['subtitlesformat'] = sub_format
|
youtube_dl_params['subtitlesformat'] = sub_format
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ def download_video(video: Video, attempt: int = 1):
|
|||||||
_lock.acquire()
|
_lock.acquire()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
max_attempts = user.preferences['download_max_attempts']
|
max_attempts = user.preferences['max_download_attempts']
|
||||||
|
|
||||||
youtube_dl_params, output_path = __build_youtube_dl_params(video)
|
youtube_dl_params, output_path = __build_youtube_dl_params(video)
|
||||||
with youtube_dl.YoutubeDL(youtube_dl_params) as yt:
|
with youtube_dl.YoutubeDL(youtube_dl_params) as yt:
|
||||||
|
@ -73,7 +73,7 @@ def __detect_deleted(subscription: Subscription):
|
|||||||
video.downloaded_path = None
|
video.downloaded_path = None
|
||||||
|
|
||||||
# Mark watched?
|
# Mark watched?
|
||||||
if user.preferences['MarkDeletedAsWatched']:
|
if user.preferences['mark_deleted_as_watched']:
|
||||||
video.watched = True
|
video.watched = True
|
||||||
|
|
||||||
video.save()
|
video.save()
|
||||||
|
@ -30,136 +30,6 @@ VIDEO_ORDER_MAPPING = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class UserSettings(models.Model):
|
|
||||||
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
|
||||||
|
|
||||||
mark_deleted_as_watched = models.BooleanField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='When a downloaded video is deleted from the system, it will be marked as \'watched\'.')
|
|
||||||
|
|
||||||
delete_watched = models.BooleanField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='Videos marked as watched are automatically deleted.')
|
|
||||||
|
|
||||||
auto_download = models.BooleanField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='Enables or disables automatic downloading.')
|
|
||||||
|
|
||||||
download_global_limit = models.IntegerField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='Limits the total number of videos downloaded (-1 = no limit).')
|
|
||||||
|
|
||||||
download_subscription_limit = models.IntegerField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='Limits the number of videos downloaded per subscription (-1 = no limit). '
|
|
||||||
' This setting can be overriden for each individual subscription in the subscription edit dialog.')
|
|
||||||
|
|
||||||
download_order = models.CharField(
|
|
||||||
null=True, blank=True,
|
|
||||||
max_length=100,
|
|
||||||
choices=VIDEO_ORDER_CHOICES,
|
|
||||||
help_text='The order in which videos will be downloaded.'
|
|
||||||
)
|
|
||||||
|
|
||||||
download_path = models.CharField(
|
|
||||||
null=True, blank=True,
|
|
||||||
max_length=1024,
|
|
||||||
help_text='Path on the disk where downloaded videos are stored. '
|
|
||||||
' You can use environment variables using syntax: <code>${env:...}</code>'
|
|
||||||
)
|
|
||||||
|
|
||||||
download_file_pattern = models.CharField(
|
|
||||||
null=True, blank=True,
|
|
||||||
max_length=1024,
|
|
||||||
help_text='A pattern which describes how downloaded files are organized. Extensions are automatically appended.'
|
|
||||||
' You can use the following fields, using the <code>${field}</code> syntax:'
|
|
||||||
' channel, channel_id, playlist, playlist_id, playlist_index, title, id.'
|
|
||||||
' Example: <code>${channel}/${playlist}/S01E${playlist_index} - ${title} [${id}]</code>')
|
|
||||||
|
|
||||||
download_format = models.CharField(
|
|
||||||
null=True, blank=True,
|
|
||||||
max_length=256,
|
|
||||||
help_text='Download format that will be passed to youtube-dl. '
|
|
||||||
' See the <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#format-selection">'
|
|
||||||
' youtube-dl documentation</a> for more details.')
|
|
||||||
|
|
||||||
download_subtitles = models.BooleanField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='Enable downloading subtitles for the videos.'
|
|
||||||
' The flag is passed directly to youtube-dl. You can find more information'
|
|
||||||
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.')
|
|
||||||
|
|
||||||
download_autogenerated_subtitles = models.BooleanField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='Enables downloading the automatically generated subtitle.'
|
|
||||||
' The flag is passed directly to youtube-dl. You can find more information'
|
|
||||||
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.')
|
|
||||||
|
|
||||||
download_subtitles_all = models.BooleanField(
|
|
||||||
null=True, blank=True,
|
|
||||||
help_text='If enabled, all the subtitles in all the available languages will be downloaded.'
|
|
||||||
' The flag is passed directly to youtube-dl. You can find more information'
|
|
||||||
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.')
|
|
||||||
|
|
||||||
download_subtitles_langs = models.CharField(
|
|
||||||
null=True, blank=True,
|
|
||||||
max_length=250,
|
|
||||||
help_text='Comma separated list of languages for which subtitles will be downloaded.'
|
|
||||||
' The flag is passed directly to youtube-dl. You can find more information'
|
|
||||||
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.')
|
|
||||||
|
|
||||||
download_subtitles_format = models.CharField(
|
|
||||||
null=True, blank=True,
|
|
||||||
max_length=100,
|
|
||||||
help_text='Subtitles format preference. Examples: srt/ass/best'
|
|
||||||
' The flag is passed directly to youtube-dl. You can find more information'
|
|
||||||
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.')
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def find_by_user(user: User):
|
|
||||||
result = UserSettings.objects.filter(user=user)
|
|
||||||
if len(result) > 0:
|
|
||||||
return result.first()
|
|
||||||
return None
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.user)
|
|
||||||
|
|
||||||
def to_dict(self):
|
|
||||||
ret = {}
|
|
||||||
|
|
||||||
if self.mark_deleted_as_watched is not None:
|
|
||||||
ret['MarkDeletedAsWatched'] = self.mark_deleted_as_watched
|
|
||||||
if self.delete_watched is not None:
|
|
||||||
ret['DeleteWatched'] = self.delete_watched
|
|
||||||
if self.auto_download is not None:
|
|
||||||
ret['AutoDownload'] = self.auto_download
|
|
||||||
if self.download_global_limit is not None:
|
|
||||||
ret['DownloadGlobalLimit'] = self.download_global_limit
|
|
||||||
if self.download_subscription_limit is not None:
|
|
||||||
ret['DownloadSubscriptionLimit'] = self.download_subscription_limit
|
|
||||||
if self.download_order is not None:
|
|
||||||
ret['DownloadOrder'] = self.download_order
|
|
||||||
if self.download_path is not None:
|
|
||||||
ret['DownloadPath'] = self.download_path
|
|
||||||
if self.download_file_pattern is not None:
|
|
||||||
ret['DownloadFilePattern'] = self.download_file_pattern
|
|
||||||
if self.download_format is not None:
|
|
||||||
ret['DownloadFormat'] = self.download_format
|
|
||||||
if self.download_subtitles is not None:
|
|
||||||
ret['DownloadSubtitles'] = self.download_subtitles
|
|
||||||
if self.download_autogenerated_subtitles is not None:
|
|
||||||
ret['DownloadAutogeneratedSubtitles'] = self.download_autogenerated_subtitles
|
|
||||||
if self.download_subtitles_all is not None:
|
|
||||||
ret['DownloadSubtitlesAll'] = self.download_subtitles_all
|
|
||||||
if self.download_subtitles_langs is not None:
|
|
||||||
ret['DownloadSubtitlesLangs'] = self.download_subtitles_langs
|
|
||||||
if self.download_subtitles_format is not None:
|
|
||||||
ret['DownloadSubtitlesFormat'] = self.download_subtitles_format
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionFolder(models.Model):
|
class SubscriptionFolder(models.Model):
|
||||||
name = models.CharField(null=False, max_length=250)
|
name = models.CharField(null=False, max_length=250)
|
||||||
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)
|
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
@ -138,8 +138,8 @@ class Step3ConfigureView(WizardStepMixin, FormView):
|
|||||||
initial = super().get_initial()
|
initial = super().get_initial()
|
||||||
initial['allow_registrations'] = appconfig.allow_registrations
|
initial['allow_registrations'] = appconfig.allow_registrations
|
||||||
initial['sync_schedule'] = appconfig.sync_schedule
|
initial['sync_schedule'] = appconfig.sync_schedule
|
||||||
initial['auto_download'] = self.request.user.preferences['downloader__auto_enabled']
|
initial['auto_download'] = self.request.user.preferences['auto_download']
|
||||||
initial['download_location'] = self.request.user.preferences['downloader__download_path']
|
initial['download_location'] = self.request.user.preferences['download_path']
|
||||||
return initial
|
return initial
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
@ -153,11 +153,11 @@ class Step3ConfigureView(WizardStepMixin, FormView):
|
|||||||
|
|
||||||
auto_download = form.cleaned_data['auto_download']
|
auto_download = form.cleaned_data['auto_download']
|
||||||
if auto_download is not None:
|
if auto_download is not None:
|
||||||
self.request.user.preferences['downloader__auto_enabled'] = auto_download
|
self.request.user.preferences['auto_download'] = auto_download
|
||||||
|
|
||||||
download_location = form.cleaned_data['download_location']
|
download_location = form.cleaned_data['download_location']
|
||||||
if download_location is not None and len(download_location) > 0:
|
if download_location is not None and len(download_location) > 0:
|
||||||
self.request.user.preferences['downloader__download_path'] = download_location
|
self.request.user.preferences['download_path'] = download_location
|
||||||
|
|
||||||
# Set initialized to true
|
# Set initialized to true
|
||||||
appconfig.initialized = True
|
appconfig.initialized = True
|
||||||
|
@ -2,23 +2,163 @@ from crispy_forms.helper import FormHelper
|
|||||||
from crispy_forms.layout import Layout, HTML, Submit
|
from crispy_forms.layout import Layout, HTML, Submit
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from YtManagerApp.models import UserSettings
|
from YtManagerApp.dynamic_preferences_registry import MarkDeletedAsWatched, AutoDeleteWatched, AutoDownloadEnabled, \
|
||||||
|
DownloadGlobalLimit, DownloadGlobalSizeLimit, DownloadSubscriptionLimit, DownloadMaxAttempts, DownloadOrder, \
|
||||||
|
DownloadPath, DownloadFilePattern, DownloadFormat, DownloadSubtitles, DownloadAutogeneratedSubtitles, \
|
||||||
|
DownloadAllSubtitles, DownloadSubtitlesLangs, DownloadSubtitlesFormat
|
||||||
|
from YtManagerApp.management.appconfig import appconfig
|
||||||
|
from YtManagerApp.models import VIDEO_ORDER_CHOICES
|
||||||
|
|
||||||
|
|
||||||
class SettingsForm(forms.ModelForm):
|
class SettingsForm(forms.Form):
|
||||||
class Meta:
|
|
||||||
model = UserSettings
|
mark_deleted_as_watched = forms.BooleanField(
|
||||||
exclude = ['user']
|
help_text='When a downloaded video is deleted from the system, it will be marked as \'watched\'.',
|
||||||
|
initial=MarkDeletedAsWatched.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
automatically_delete_watched = forms.BooleanField(
|
||||||
|
help_text='Videos marked as watched are automatically deleted.',
|
||||||
|
initial=AutoDeleteWatched.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
auto_download = forms.BooleanField(
|
||||||
|
help_text='Enables or disables automatic downloading.',
|
||||||
|
initial=AutoDownloadEnabled.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
download_global_limit = forms.IntegerField(
|
||||||
|
help_text='Limits the total number of videos downloaded (-1/unset = no limit).',
|
||||||
|
initial=DownloadGlobalLimit.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
download_global_size_limit = forms.IntegerField(
|
||||||
|
help_text='Limits the total amount of space used in MB (-1/unset = no limit).',
|
||||||
|
initial=DownloadGlobalSizeLimit.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
download_subscription_limit = forms.IntegerField(
|
||||||
|
help_text='Limits the number of videos downloaded per subscription (-1/unset = no limit). '
|
||||||
|
' This setting can be overriden for each individual subscription in the subscription edit dialog.',
|
||||||
|
initial=DownloadSubscriptionLimit.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
max_download_attempts = forms.IntegerField(
|
||||||
|
help_text='How many times to attempt downloading a video until giving up.',
|
||||||
|
initial=DownloadMaxAttempts.default,
|
||||||
|
min_value=1,
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
download_order = forms.ChoiceField(
|
||||||
|
help_text='The order in which videos will be downloaded.',
|
||||||
|
choices=VIDEO_ORDER_CHOICES,
|
||||||
|
initial=DownloadOrder.default,
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
download_path = forms.CharField(
|
||||||
|
help_text='Path on the disk where downloaded videos are stored. '
|
||||||
|
'You can use environment variables using syntax: <code>${env:...}</code>',
|
||||||
|
initial=DownloadPath.default,
|
||||||
|
max_length=1024,
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
download_file_pattern = forms.CharField(
|
||||||
|
help_text='A pattern which describes how downloaded files are organized. Extensions are automatically appended.'
|
||||||
|
' You can use the following fields, using the <code>${field}</code> syntax:'
|
||||||
|
' channel, channel_id, playlist, playlist_id, playlist_index, title, id.'
|
||||||
|
' Example: <code>${channel}/${playlist}/S01E${playlist_index} - ${title} [${id}]</code>',
|
||||||
|
initial=DownloadFilePattern.default,
|
||||||
|
max_length=1024,
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
download_format = forms.CharField(
|
||||||
|
help_text='Download format that will be passed to youtube-dl. '
|
||||||
|
' See the <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#format-selection">'
|
||||||
|
' youtube-dl documentation</a> for more details.',
|
||||||
|
initial=DownloadFormat.default,
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
download_subtitles = forms.BooleanField(
|
||||||
|
help_text='Enable downloading subtitles for the videos.'
|
||||||
|
' The flag is passed directly to youtube-dl. You can find more information'
|
||||||
|
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.',
|
||||||
|
initial=DownloadSubtitles.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
download_autogenerated_subtitles = forms.BooleanField(
|
||||||
|
help_text='Enables downloading the automatically generated subtitle.'
|
||||||
|
' The flag is passed directly to youtube-dl. You can find more information'
|
||||||
|
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.',
|
||||||
|
initial=DownloadAutogeneratedSubtitles.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
download_subtitles_all = forms.BooleanField(
|
||||||
|
help_text='If enabled, all the subtitles in all the available languages will be downloaded.'
|
||||||
|
' The flag is passed directly to youtube-dl. You can find more information'
|
||||||
|
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.',
|
||||||
|
initial=DownloadAllSubtitles.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
download_subtitles_langs = forms.CharField(
|
||||||
|
help_text='Comma separated list of languages for which subtitles will be downloaded.'
|
||||||
|
' The flag is passed directly to youtube-dl. You can find more information'
|
||||||
|
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.',
|
||||||
|
initial=DownloadSubtitlesLangs.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
download_subtitles_format = forms.CharField(
|
||||||
|
help_text='Subtitles format preference. Examples: srt/ass/best'
|
||||||
|
' The flag is passed directly to youtube-dl. You can find more information'
|
||||||
|
' <a href="https://github.com/rg3/youtube-dl/blob/master/README.md#subtitle-options">here</a>.',
|
||||||
|
initial=DownloadSubtitlesFormat.default,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
ALL_PROPS = [
|
||||||
|
'mark_deleted_as_watched',
|
||||||
|
'automatically_delete_watched',
|
||||||
|
|
||||||
|
'auto_download',
|
||||||
|
'download_path',
|
||||||
|
'download_file_pattern',
|
||||||
|
'download_format',
|
||||||
|
'download_order',
|
||||||
|
'download_global_limit',
|
||||||
|
'download_global_size_limit',
|
||||||
|
'download_subscription_limit',
|
||||||
|
'max_download_attempts',
|
||||||
|
|
||||||
|
'download_subtitles',
|
||||||
|
'download_subtitles_langs',
|
||||||
|
'download_subtitles_all',
|
||||||
|
'download_autogenerated_subtitles',
|
||||||
|
'download_subtitles_format',
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.helper = FormHelper()
|
self.helper = FormHelper()
|
||||||
self.helper.form_class = 'form-horizontal'
|
self.helper.form_class = 'form-horizontal'
|
||||||
self.helper.label_class = 'col-lg-3'
|
self.helper.label_class = 'col-lg-6'
|
||||||
self.helper.field_class = 'col-lg-9'
|
self.helper.field_class = 'col-lg-6'
|
||||||
self.helper.layout = Layout(
|
self.helper.layout = Layout(
|
||||||
'mark_deleted_as_watched',
|
'mark_deleted_as_watched',
|
||||||
'delete_watched',
|
'automatically_delete_watched',
|
||||||
HTML('<h2>Download settings</h2>'),
|
HTML('<h2>Download settings</h2>'),
|
||||||
'auto_download',
|
'auto_download',
|
||||||
'download_path',
|
'download_path',
|
||||||
@ -26,7 +166,9 @@ class SettingsForm(forms.ModelForm):
|
|||||||
'download_format',
|
'download_format',
|
||||||
'download_order',
|
'download_order',
|
||||||
'download_global_limit',
|
'download_global_limit',
|
||||||
|
'download_global_size_limit',
|
||||||
'download_subscription_limit',
|
'download_subscription_limit',
|
||||||
|
'max_download_attempts',
|
||||||
HTML('<h2>Subtitles download settings</h2>'),
|
HTML('<h2>Subtitles download settings</h2>'),
|
||||||
'download_subtitles',
|
'download_subtitles',
|
||||||
'download_subtitles_langs',
|
'download_subtitles_langs',
|
||||||
@ -36,6 +178,16 @@ class SettingsForm(forms.ModelForm):
|
|||||||
Submit('submit', value='Save')
|
Submit('submit', value='Save')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_initials(user):
|
||||||
|
return {
|
||||||
|
x: user.preferences[x] for x in SettingsForm.ALL_PROPS
|
||||||
|
}
|
||||||
|
|
||||||
|
def save(self, user):
|
||||||
|
for prop in SettingsForm.ALL_PROPS:
|
||||||
|
user.preferences[prop] = self.cleaned_data[prop]
|
||||||
|
|
||||||
|
|
||||||
class AdminSettingsForm(forms.Form):
|
class AdminSettingsForm(forms.Form):
|
||||||
|
|
||||||
@ -78,3 +230,29 @@ class AdminSettingsForm(forms.Form):
|
|||||||
'scheduler_concurrency',
|
'scheduler_concurrency',
|
||||||
Submit('submit', value='Save')
|
Submit('submit', value='Save')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_initials():
|
||||||
|
return {
|
||||||
|
'api_key': appconfig.youtube_api_key,
|
||||||
|
'allow_registrations': appconfig.allow_registrations,
|
||||||
|
'sync_schedule': appconfig.sync_schedule,
|
||||||
|
'scheduler_concurrency': appconfig.concurrency,
|
||||||
|
}
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
api_key = self.cleaned_data['api_key']
|
||||||
|
if api_key is not None and len(api_key) > 0:
|
||||||
|
appconfig.youtube_api_key = api_key
|
||||||
|
|
||||||
|
allow_registrations = self.cleaned_data['allow_registrations']
|
||||||
|
if allow_registrations is not None:
|
||||||
|
appconfig.allow_registrations = allow_registrations
|
||||||
|
|
||||||
|
sync_schedule = self.cleaned_data['sync_schedule']
|
||||||
|
if sync_schedule is not None and len(sync_schedule) > 0:
|
||||||
|
appconfig.sync_schedule = sync_schedule
|
||||||
|
|
||||||
|
concurrency = self.cleaned_data['scheduler_concurrency']
|
||||||
|
if concurrency is not None:
|
||||||
|
appconfig.concurrency = concurrency
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import HttpResponseForbidden
|
from django.http import HttpResponseForbidden
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.views.generic import UpdateView, FormView
|
from django.views.generic import FormView
|
||||||
|
|
||||||
from YtManagerApp.management.appconfig import appconfig
|
|
||||||
from YtManagerApp.models import UserSettings
|
|
||||||
from YtManagerApp.views.forms.settings import SettingsForm, AdminSettingsForm
|
from YtManagerApp.views.forms.settings import SettingsForm, AdminSettingsForm
|
||||||
|
|
||||||
|
|
||||||
class SettingsView(LoginRequiredMixin, UpdateView):
|
class SettingsView(LoginRequiredMixin, FormView):
|
||||||
form_class = SettingsForm
|
form_class = SettingsForm
|
||||||
model = UserSettings
|
|
||||||
template_name = 'YtManagerApp/settings.html'
|
template_name = 'YtManagerApp/settings.html'
|
||||||
success_url = reverse_lazy('home')
|
success_url = reverse_lazy('home')
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_initial(self):
|
||||||
obj, _ = self.model.objects.get_or_create(user=self.request.user)
|
initial = super().get_initial()
|
||||||
return obj
|
initial.update(SettingsForm.get_initials(self.request.user))
|
||||||
|
return initial
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
form.save(self.request.user)
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class AdminSettingsView(LoginRequiredMixin, FormView):
|
class AdminSettingsView(LoginRequiredMixin, FormView):
|
||||||
@ -37,27 +39,9 @@ class AdminSettingsView(LoginRequiredMixin, FormView):
|
|||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
initial = super().get_initial()
|
initial = super().get_initial()
|
||||||
initial['api_key'] = appconfig.youtube_api_key
|
initial.update(AdminSettingsForm.get_initials())
|
||||||
initial['allow_registrations'] = appconfig.allow_registrations
|
|
||||||
initial['sync_schedule'] = appconfig.sync_schedule
|
|
||||||
initial['scheduler_concurrency'] = appconfig.concurrency
|
|
||||||
return initial
|
return initial
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
api_key = form.cleaned_data['api_key']
|
form.save()
|
||||||
if api_key is not None and len(api_key) > 0:
|
|
||||||
appconfig.youtube_api_key = api_key
|
|
||||||
|
|
||||||
allow_registrations = form.cleaned_data['allow_registrations']
|
|
||||||
if allow_registrations is not None:
|
|
||||||
appconfig.allow_registrations = allow_registrations
|
|
||||||
|
|
||||||
sync_schedule = form.cleaned_data['sync_schedule']
|
|
||||||
if sync_schedule is not None and len(sync_schedule) > 0:
|
|
||||||
appconfig.sync_schedule = sync_schedule
|
|
||||||
|
|
||||||
concurrency = form.cleaned_data['scheduler_concurrency']
|
|
||||||
if concurrency is not None:
|
|
||||||
appconfig.concurrency = concurrency
|
|
||||||
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
Loading…
Reference in New Issue
Block a user