diff --git a/app/YtManagerApp/dynamic_preferences_registry.py b/app/YtManagerApp/dynamic_preferences_registry.py
index d8a3235..7b1609f 100644
--- a/app/YtManagerApp/dynamic_preferences_registry.py
+++ b/app/YtManagerApp/dynamic_preferences_registry.py
@@ -12,8 +12,6 @@ import os
hidden = Section('hidden')
general = Section('general')
scheduler = Section('scheduler')
-manager = Section('manager')
-downloader = Section('downloader')
# Hidden settings
@@ -60,7 +58,6 @@ class SchedulerConcurrency(IntegerPreference):
# User settings
@user_preferences_registry.register
class MarkDeletedAsWatched(BooleanPreference):
- section = manager
name = 'mark_deleted_as_watched'
default = True
required = True
@@ -68,47 +65,41 @@ class MarkDeletedAsWatched(BooleanPreference):
@user_preferences_registry.register
class AutoDeleteWatched(BooleanPreference):
- section = manager
- name = 'auto_delete_watched'
+ name = 'automatically_delete_watched'
default = True
required = True
@user_preferences_registry.register
class AutoDownloadEnabled(BooleanPreference):
- section = downloader
- name = 'auto_enabled'
+ name = 'auto_download'
default = True
required = True
@user_preferences_registry.register
class DownloadGlobalLimit(IntegerPreference):
- section = downloader
- name = 'global_limit'
- default = None
+ name = 'download_global_limit'
+ default = -1
required = False
@user_preferences_registry.register
class DownloadGlobalSizeLimit(IntegerPreference):
- section = downloader
- name = 'global_size_limit_mb'
- default = None
+ name = 'download_global_size_limit'
+ default = -1
required = False
@user_preferences_registry.register
class DownloadSubscriptionLimit(IntegerPreference):
- section = downloader
- name = 'limit_per_subscription'
+ name = 'download_subscription_limit'
default = 5
required = False
@user_preferences_registry.register
class DownloadMaxAttempts(IntegerPreference):
- section = downloader
name = 'max_download_attempts'
default = 3
required = True
@@ -116,7 +107,6 @@ class DownloadMaxAttempts(IntegerPreference):
@user_preferences_registry.register
class DownloadOrder(ChoicePreference):
- section = downloader
name = 'download_order'
choices = VIDEO_ORDER_CHOICES
default = 'playlist'
@@ -125,7 +115,6 @@ class DownloadOrder(ChoicePreference):
@user_preferences_registry.register
class DownloadPath(StringPreference):
- section = downloader
name = 'download_path'
default = os.path.join(settings.DATA_DIR, 'downloads')
required = False
@@ -133,7 +122,6 @@ class DownloadPath(StringPreference):
@user_preferences_registry.register
class DownloadFilePattern(StringPreference):
- section = downloader
name = 'download_file_pattern'
default = '${channel}/${playlist}/S01E${playlist_index} - ${title} [${id}]'
required = True
@@ -141,7 +129,6 @@ class DownloadFilePattern(StringPreference):
@user_preferences_registry.register
class DownloadFormat(StringPreference):
- section = downloader
name = 'download_format'
default = 'bestvideo+bestaudio'
required = True
@@ -149,39 +136,34 @@ class DownloadFormat(StringPreference):
@user_preferences_registry.register
class DownloadSubtitles(BooleanPreference):
- section = downloader
- name = 'subtitles_enabled'
+ name = 'download_subtitles'
default = True
required = True
@user_preferences_registry.register
class DownloadAutogeneratedSubtitles(BooleanPreference):
- section = downloader
- name = 'autogenerated_subtitles'
+ name = 'download_autogenerated_subtitles'
default = False
required = True
@user_preferences_registry.register
class DownloadAllSubtitles(BooleanPreference):
- section = downloader
- name = 'all_subtitles'
+ name = 'download_subtitles_all'
default = False
required = False
@user_preferences_registry.register
class DownloadSubtitlesLangs(StringPreference):
- section = downloader
- name = 'subtitles_langs'
+ name = 'download_subtitles_langs'
default = 'en,ro'
required = False
@user_preferences_registry.register
class DownloadSubtitlesFormat(StringPreference):
- section = downloader
- name = 'subtitles_format'
- default = False
+ name = 'download_subtitles_format'
+ default = ''
required = False
diff --git a/app/YtManagerApp/management/downloader.py b/app/YtManagerApp/management/downloader.py
index 70c7f38..4259630 100644
--- a/app/YtManagerApp/management/downloader.py
+++ b/app/YtManagerApp/management/downloader.py
@@ -14,9 +14,9 @@ log = logging.getLogger('downloader')
def __get_subscription_config(sub: Subscription):
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']
- 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 = VIDEO_ORDER_MAPPING[order]
diff --git a/app/YtManagerApp/management/jobs/download_video.py b/app/YtManagerApp/management/jobs/download_video.py
index b35771b..96f9cd3 100644
--- a/app/YtManagerApp/management/jobs/download_video.py
+++ b/app/YtManagerApp/management/jobs/download_video.py
@@ -59,9 +59,9 @@ def __build_youtube_dl_params(video: Video):
'outtmpl': output_path,
'writethumbnail': True,
'writedescription': True,
- 'writesubtitles': user.preferences['subtitles_enabled'],
- 'writeautomaticsub': user.preferences['autogenerated_subtitles'],
- 'allsubtitles': user.preferences['all_subtitles'],
+ 'writesubtitles': user.preferences['download_subtitles'],
+ 'writeautomaticsub': user.preferences['download_autogenerated_subtitles'],
+ 'allsubtitles': user.preferences['download_subtitles_all'],
'postprocessors': [
{
'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]
if len(sub_langs) > 0:
youtube_dl_params['subtitleslangs'] = sub_langs
- sub_format = user.preferences['subtitles_format']
+ sub_format = user.preferences['download_subtitles_format']
if len(sub_format) > 0:
youtube_dl_params['subtitlesformat'] = sub_format
@@ -93,7 +93,7 @@ def download_video(video: Video, attempt: int = 1):
_lock.acquire()
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)
with youtube_dl.YoutubeDL(youtube_dl_params) as yt:
diff --git a/app/YtManagerApp/management/jobs/synchronize.py b/app/YtManagerApp/management/jobs/synchronize.py
index bd6814c..11e49d4 100644
--- a/app/YtManagerApp/management/jobs/synchronize.py
+++ b/app/YtManagerApp/management/jobs/synchronize.py
@@ -73,7 +73,7 @@ def __detect_deleted(subscription: Subscription):
video.downloaded_path = None
# Mark watched?
- if user.preferences['MarkDeletedAsWatched']:
+ if user.preferences['mark_deleted_as_watched']:
video.watched = True
video.save()
diff --git a/app/YtManagerApp/models.py b/app/YtManagerApp/models.py
index c500f36..979bee2 100644
--- a/app/YtManagerApp/models.py
+++ b/app/YtManagerApp/models.py
@@ -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: ${env:...}
'
- )
-
- 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 ${field}
syntax:'
- ' channel, channel_id, playlist, playlist_id, playlist_index, title, id.'
- ' Example: ${channel}/${playlist}/S01E${playlist_index} - ${title} [${id}]
')
-
- download_format = models.CharField(
- null=True, blank=True,
- max_length=256,
- help_text='Download format that will be passed to youtube-dl. '
- ' See the '
- ' youtube-dl documentation 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'
- ' here.')
-
- 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'
- ' here.')
-
- 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'
- ' here.')
-
- 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'
- ' here.')
-
- 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'
- ' here.')
-
- @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):
name = models.CharField(null=False, max_length=250)
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)
diff --git a/app/YtManagerApp/views/first_time.py b/app/YtManagerApp/views/first_time.py
index 9b20dd8..e597f73 100644
--- a/app/YtManagerApp/views/first_time.py
+++ b/app/YtManagerApp/views/first_time.py
@@ -138,8 +138,8 @@ class Step3ConfigureView(WizardStepMixin, FormView):
initial = super().get_initial()
initial['allow_registrations'] = appconfig.allow_registrations
initial['sync_schedule'] = appconfig.sync_schedule
- initial['auto_download'] = self.request.user.preferences['downloader__auto_enabled']
- initial['download_location'] = self.request.user.preferences['downloader__download_path']
+ initial['auto_download'] = self.request.user.preferences['auto_download']
+ initial['download_location'] = self.request.user.preferences['download_path']
return initial
def form_valid(self, form):
@@ -153,11 +153,11 @@ class Step3ConfigureView(WizardStepMixin, FormView):
auto_download = form.cleaned_data['auto_download']
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']
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
appconfig.initialized = True
diff --git a/app/YtManagerApp/views/forms/settings.py b/app/YtManagerApp/views/forms/settings.py
index b22e096..8700a25 100644
--- a/app/YtManagerApp/views/forms/settings.py
+++ b/app/YtManagerApp/views/forms/settings.py
@@ -2,23 +2,163 @@ from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, HTML, Submit
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 Meta:
- model = UserSettings
- exclude = ['user']
+class SettingsForm(forms.Form):
+
+ mark_deleted_as_watched = forms.BooleanField(
+ 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: ${env:...}
',
+ 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 ${field}
syntax:'
+ ' channel, channel_id, playlist, playlist_id, playlist_index, title, id.'
+ ' Example: ${channel}/${playlist}/S01E${playlist_index} - ${title} [${id}]
',
+ 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 '
+ ' youtube-dl documentation 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'
+ ' here.',
+ 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'
+ ' here.',
+ 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'
+ ' here.',
+ 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'
+ ' here.',
+ 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'
+ ' here.',
+ 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):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'form-horizontal'
- self.helper.label_class = 'col-lg-3'
- self.helper.field_class = 'col-lg-9'
+ self.helper.label_class = 'col-lg-6'
+ self.helper.field_class = 'col-lg-6'
self.helper.layout = Layout(
'mark_deleted_as_watched',
- 'delete_watched',
+ 'automatically_delete_watched',
HTML('