validate settings form and userspace archive page_size

This commit is contained in:
simon 2021-10-29 22:37:31 +07:00
parent f24a3dd1f5
commit a4397b5204
5 changed files with 147 additions and 53 deletions

View File

@ -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
)

View File

@ -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()

View File

@ -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

View File

@ -1,20 +1,16 @@
{% extends "home/base.html" %}
{% block content %}
<div class="title-bar">
<h1>Settings</h1>
<h1>User Configurations</h1>
</div>
<form action="/settings/" method="POST" name="settings-update">
<form action="/settings/" method="POST" name="user-update">
{% csrf_token %}
<div class="settings-group">
<h2>Color scheme</h2>
<div class="settings-item">
<p>Current color scheme: <span class="settings-current">{{ config.application.colors }}</span></p>
<i>Select your preferred color scheme between dark and light mode.</i><br>
<select name="application.colors" id="application.colors">
<option value="" disabled selected> -- change color scheme -- </option>
<option value="dark">dark mode</option>
<option value="light">light mode</option>
</select>
{{ user_form.colors }}
</div>
</div>
<div class="settings-group">
@ -22,15 +18,22 @@
<div class="settings-item">
<p>Current page size: <span class="settings-current">{{ config.archive.page_size }}</span></p>
<i>Result of videos showing in archive page</i><br>
<input type="number" name="archive.page_size" id="archive.page_size">
{{ user_form.page_size }}
</div>
</div>
<button type="submit" name="user-settings">Update User Configurations</button>
</form>
<div class="title-bar">
<h1>Application Configurations</h1>
</div>
<form action="/settings/" method="POST" name="application-update">
{% csrf_token %}
<div class="settings-group">
<h2 id="subscriptions">Subscriptions</h2>
<div class="settings-item">
<p>Current channel page size: <span class="settings-current">{{ config.subscriptions.channel_size }}</span></p>
<i>Recent videos to check on check pending, max recommended 50.</i><br>
<input type="number" name="subscriptions.channel_size" id="subscriptions.channel_size">
{{ app_form.subscriptions_channel_size }}
</div>
<div class="settings-item">
<p>Auto scan subscribed channels:</p>
@ -46,22 +49,22 @@
<div class="settings-item">
<p>Current download limit: <span class="settings-current">{{ config.downloads.limit_count }}</span></p>
<i>Limit the number of videos getting downloaded on every run. 0 (zero) to deactivate.</i><br>
<input type="number" name="downloads.limit_count" id="downloads.limit_count">
{{ app_form.downloads_limit_count }}
</div>
<div class="settings-item">
<p>Current download speed limit: <span class="settings-current">{{ config.downloads.limit_speed }}</span></p>
<i>Limit download speed. 0 (zero) to deactivate.</i><br>
<input type="number" name="downloads.limit_speed" id="downloads.limit_speed"><span>KB/sec</span>
{{ app_form.downloads_limit_speed }}
</div>
<div class="settings-item">
<p>Current throttled rate limit: <span class="settings-current">{{ config.downloads.throttledratelimit }}</span></p>
<i>Assume the download is being throttled below this speed and restart. 0 (zero) to deactivate, e.g. 100KB/sec</i><br>
<input type="number" name="downloads.throttledratelimit" id="downloads.throttledratelimit"><span>KB/sec</span>
{{ app_form.downloads_throttledratelimit }}
</div>
<div class="settings-item">
<p>Current scraping sleep interval: <span class="settings-current">{{ config.downloads.sleep_interval }}</p>
<i>Seconds to sleep between calls to YouTube. Might be necessary to avoid throttling. Recommended 3.</i><br>
<input type="number" name="downloads.sleep_interval" id="downloads.sleep_interval">
{{ app_form.downloads_sleep_interval }}
</div>
<div class="settings-item">
<p>External downloader:</p>
@ -82,29 +85,21 @@
<li><span class="settings-current">0</span>: deactivate and download the best quality possible as decided by yt-dlp.</li>
</ul>
<i>Make sure your custom format gets merged into a single file. Check out the <a href="https://github.com/yt-dlp/yt-dlp#format-selection" target="_blank">documentation</a> for valid configurations.</i><br>
<input type="text" name="downloads.format" id="downloads.format">
{{ app_form.downloads_format }}
<br>
</div>
<div class="settings-item">
<p>Current metadata embed setting: <span class="settings-current">{{ config.downloads.add_metadata }}</span></p>
<i>Metadata is not embedded into the downloaded files by default.</i><br>
<select name="downloads.add_metadata" id="downloads.add_metadata"">
<option value="" disabled selected> -- change metadata embed -- </option>
<option value="0">don't embed metadata</option>
<option value="1">embed metadata</option>
</select>
{{ app_form.downloads_add_metadata }}
</div>
<div class="settings-item">
<p>Current thumbnail embed setting: <span class="settings-current">{{ config.downloads.add_thumbnail }}</span></p>
<i>Embed thumbnail into the mediafile.</i><br>
<select name="downloads.add_thumbnail" id="downloads.add_thumbnail"">
<option value="" disabled selected> -- change thumbnail embed -- </option>
<option value="0">don't embed thumbnail</option>
<option value="1">embed thumbnail</option>
</select>
{{ app_form.downloads_add_thumbnail }}
</div>
</div>
<button type="submit">Update Settings</button>
<button type="submit" name="application-settings">Update Application Configurations</button>
</form>
<div class="title-bar">
<h1>Actions</h1>

View File

@ -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)