diff --git a/tubearchivist/home/forms.py b/tubearchivist/home/forms.py new file mode 100644 index 0000000..142d7ce --- /dev/null +++ b/tubearchivist/home/forms.py @@ -0,0 +1,62 @@ +"""functionality: +- hold all form classes used in the views +""" + +from django import forms +from django.contrib.auth.forms import AuthenticationForm +from django.forms.widgets import PasswordInput, TextInput + + +class CustomAuthForm(AuthenticationForm): + """better styled login form""" + + username = forms.CharField( + widget=TextInput(attrs={"placeholder": "Username"}), label=False + ) + password = forms.CharField( + widget=PasswordInput(attrs={"placeholder": "Password"}), label=False + ) + + +class UserSettingsForm(forms.Form): + """user configurations values""" + + CHOICES = [ + ("", "-- change color scheme --"), + ("dark", "Dark"), + ("light", "Light"), + ] + + colors = forms.ChoiceField( + widget=forms.Select, choices=CHOICES, required=False + ) + page_size = forms.IntegerField(required=False) + + +class ApplicationSettingsForm(forms.Form): + """handle all application settings""" + + METADATA_CHOICES = [ + ("", "-- change metadata embed --"), + ("0", "don't embed metadata"), + ("1", "embed metadata"), + ] + + THUMBNAIL_CHOICES = [ + ("", "-- change thumbnail embed --"), + ("0", "don't embed thumbnail"), + ("1", "embed thumbnail"), + ] + + subscriptions_channel_size = forms.IntegerField(required=False) + downloads_limit_count = forms.IntegerField(required=False) + downloads_limit_speed = forms.IntegerField(required=False) + downloads_throttledratelimit = forms.IntegerField(required=False) + downloads_sleep_interval = forms.IntegerField(required=False) + downloads_format = forms.CharField(required=False) + downloads_add_metadata = forms.ChoiceField( + widget=forms.Select, choices=METADATA_CHOICES, required=False + ) + downloads_add_thumbnail = forms.ChoiceField( + widget=forms.Select, choices=THUMBNAIL_CHOICES, required=False + ) diff --git a/tubearchivist/home/src/config.py b/tubearchivist/home/src/config.py index 6e304f5..32402fd 100644 --- a/tubearchivist/home/src/config.py +++ b/tubearchivist/home/src/config.py @@ -86,11 +86,23 @@ class AppConfig: elif to_write.isdigit(): to_write = int(to_write) - config_dict, config_value = key.split(".") + config_dict, config_value = key.split("_", maxsplit=1) config[config_dict][config_value] = to_write RedisArchivist().set_message("config", config, expire=False) + @staticmethod + def set_user_config(form_post, user_id): + """set values in redis for user settings""" + for key, value in form_post.items(): + to_write = value[0] + if len(to_write): + if to_write.isdigit(): + to_write = int(to_write) + message = {"status": to_write} + redis_key = f"{user_id}:{key}" + RedisArchivist().set_message(redis_key, message, expire=False) + def load_new_defaults(self): """check config.json for missing defaults""" default_config = self.get_config_file() diff --git a/tubearchivist/home/src/searching.py b/tubearchivist/home/src/searching.py index 2d8dee4..14e8c5a 100644 --- a/tubearchivist/home/src/searching.py +++ b/tubearchivist/home/src/searching.py @@ -12,6 +12,7 @@ from datetime import datetime import requests from home.src.config import AppConfig +from home.src.helper import RedisArchivist from home.src.thumbnails import ThumbManager @@ -181,13 +182,23 @@ class Pagination: figure out the pagination based on page size and total_hits """ - def __init__(self, page_get, search_get=False): - config = AppConfig().config - self.page_size = config["archive"]["page_size"] + def __init__(self, page_get, user_id, search_get=False): + self.user_id = user_id + self.page_size = self.get_page_size() self.page_get = page_get self.search_get = search_get self.pagination = self.first_guess() + def get_page_size(self): + """get default or user modified page_size""" + key = f"{self.user_id}:page_size" + page_size = RedisArchivist().get_message(key)["status"] + if not page_size: + config = AppConfig().config + page_size = config["archive"]["page_size"] + + return page_size + def first_guess(self): """build first guess before api call""" page_get = self.page_get diff --git a/tubearchivist/home/templates/home/settings.html b/tubearchivist/home/templates/home/settings.html index 9dab509..306424b 100644 --- a/tubearchivist/home/templates/home/settings.html +++ b/tubearchivist/home/templates/home/settings.html @@ -1,20 +1,16 @@ {% extends "home/base.html" %} {% block content %}
-

Settings

+

User Configurations

-
+ {% csrf_token %}

Color scheme

Current color scheme: {{ config.application.colors }}

Select your preferred color scheme between dark and light mode.
- + {{ user_form.colors }}
@@ -22,15 +18,22 @@

Current page size: {{ config.archive.page_size }}

Result of videos showing in archive page
- + {{ user_form.page_size }}
+ +
+
+

Application Configurations

+
+
+ {% csrf_token %}

Subscriptions

Current channel page size: {{ config.subscriptions.channel_size }}

Recent videos to check on check pending, max recommended 50.
- + {{ app_form.subscriptions_channel_size }}

Auto scan subscribed channels:

@@ -46,22 +49,22 @@

Current download limit: {{ config.downloads.limit_count }}

Limit the number of videos getting downloaded on every run. 0 (zero) to deactivate.
- + {{ app_form.downloads_limit_count }}

Current download speed limit: {{ config.downloads.limit_speed }}

Limit download speed. 0 (zero) to deactivate.
- KB/sec + {{ app_form.downloads_limit_speed }}

Current throttled rate limit: {{ config.downloads.throttledratelimit }}

Assume the download is being throttled below this speed and restart. 0 (zero) to deactivate, e.g. 100KB/sec
- KB/sec + {{ app_form.downloads_throttledratelimit }}

Current scraping sleep interval: {{ config.downloads.sleep_interval }}

Seconds to sleep between calls to YouTube. Might be necessary to avoid throttling. Recommended 3.
- + {{ app_form.downloads_sleep_interval }}

External downloader:

@@ -82,29 +85,21 @@
  • 0: deactivate and download the best quality possible as decided by yt-dlp.
  • Make sure your custom format gets merged into a single file. Check out the documentation for valid configurations.
    - + {{ app_form.downloads_format }}

    Current metadata embed setting: {{ config.downloads.add_metadata }}

    Metadata is not embedded into the downloaded files by default.
    - + {{ app_form.downloads_add_metadata }}

    Current thumbnail embed setting: {{ config.downloads.add_thumbnail }}

    Embed thumbnail into the mediafile.
    - + {{ app_form.downloads_add_thumbnail }}
    - +

    Actions

    diff --git a/tubearchivist/home/views.py b/tubearchivist/home/views.py index 119803c..b08fe6a 100644 --- a/tubearchivist/home/views.py +++ b/tubearchivist/home/views.py @@ -11,7 +11,6 @@ from time import sleep from django import forms from django.contrib.auth import login from django.contrib.auth.forms import AuthenticationForm -from django.forms.widgets import PasswordInput, TextInput from django.http import JsonResponse from django.shortcuts import redirect, render from django.utils.http import urlencode @@ -21,6 +20,11 @@ from home.src.download import ChannelSubscription, PendingList from home.src.helper import RedisArchivist, RedisQueue, process_url_list from home.src.index import WatchState, YoutubeChannel, YoutubeVideo from home.src.searching import Pagination, SearchForm, SearchHandler +from home.forms import ( + ApplicationSettingsForm, + CustomAuthForm, + UserSettingsForm +) from home.tasks import ( download_pending, download_single, @@ -44,7 +48,8 @@ class HomeView(View): def get(self, request): """return home search results""" - view_config = self.read_config(user_id=request.user.id) + user_id = request.user.id + view_config = self.read_config(user_id) # handle search search_get = request.GET.get("search", False) if search_get: @@ -53,7 +58,9 @@ class HomeView(View): search_encoded = False # define page size page_get = int(request.GET.get("page", 0)) - pagination_handler = Pagination(page_get, search_encoded) + pagination_handler = Pagination( + page_get, user_id, search_get=search_encoded + ) url = self.ES_URL + "/ta_video/_search" data = self.build_data( @@ -157,17 +164,6 @@ class HomeView(View): return redirect(search_url, permanent=True) -class CustomAuthForm(AuthenticationForm): - """better styled login form""" - - username = forms.CharField( - widget=TextInput(attrs={"placeholder": "Username"}), label=False - ) - password = forms.CharField( - widget=PasswordInput(attrs={"placeholder": "Password"}), label=False - ) - - class LoginView(View): """resolves to /login/ Greeting and login page @@ -222,10 +218,11 @@ class DownloadView(View): def get(self, request): """handle get requests""" - view_config = self.read_config(user_id=request.user.id) + user_id = request.user.id + view_config = self.read_config(user_id) page_get = int(request.GET.get("page", 0)) - pagination_handler = Pagination(page_get) + pagination_handler = Pagination(page_get, user_id) url = view_config["es_url"] + "/ta_download/_search" data = self.build_data( @@ -370,7 +367,7 @@ class ChannelIdView(View): def get_channel_videos(self, request, channel_id_detail, view_config): """get channel from video index""" page_get = int(request.GET.get("page", 0)) - pagination_handler = Pagination(page_get) + pagination_handler = Pagination(page_get, request.user.id) # get data url = view_config["es_url"] + "/ta_video/_search" data = self.build_data( @@ -465,7 +462,7 @@ class ChannelView(View): user_id = request.user.id view_config = self.read_config(user_id=user_id) page_get = int(request.GET.get("page", 0)) - pagination_handler = Pagination(page_get) + pagination_handler = Pagination(page_get, user_id) page_size = pagination_handler.pagination["page_size"] page_from = pagination_handler.pagination["page_from"] # get @@ -610,18 +607,35 @@ class SettingsView(View): config = AppConfig().config colors = config["application"]["colors"] - context = {"title": "Settings", "config": config, "colors": colors} + user_form = UserSettingsForm() + app_form = ApplicationSettingsForm() + + context = { + "title": "Settings", + "config": config, + "colors": colors, + "user_form": user_form, + "app_form": app_form, + } return render(request, "home/settings.html", context) @staticmethod def post(request): """handle form post to update settings""" - form_post = dict(request.POST) - del form_post["csrfmiddlewaretoken"] - print(form_post) - config_handler = AppConfig() - config_handler.update_config(form_post) + + form_response = forms.Form(request.POST) + if form_response.is_valid(): + form_post = dict(request.POST) + print(form_post) + del form_post["csrfmiddlewaretoken"] + config_handler = AppConfig() + if "application-settings" in form_post: + del form_post["application-settings"] + config_handler.update_config(form_post) + elif "user-settings" in form_post: + del form_post["user-settings"] + config_handler.set_user_config(form_post, request.user.id) return redirect("settings", permanent=True)