mirror of
https://github.com/tubearchivist/tubearchivist-frontend.git
synced 2024-11-22 20:00:15 +00:00
validate settings form and userspace archive page_size
This commit is contained in:
parent
f24a3dd1f5
commit
a4397b5204
62
tubearchivist/home/forms.py
Normal file
62
tubearchivist/home/forms.py
Normal 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
|
||||||
|
)
|
@ -86,11 +86,23 @@ class AppConfig:
|
|||||||
elif to_write.isdigit():
|
elif to_write.isdigit():
|
||||||
to_write = int(to_write)
|
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
|
config[config_dict][config_value] = to_write
|
||||||
|
|
||||||
RedisArchivist().set_message("config", config, expire=False)
|
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):
|
def load_new_defaults(self):
|
||||||
"""check config.json for missing defaults"""
|
"""check config.json for missing defaults"""
|
||||||
default_config = self.get_config_file()
|
default_config = self.get_config_file()
|
||||||
|
@ -12,6 +12,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
from home.src.config import AppConfig
|
from home.src.config import AppConfig
|
||||||
|
from home.src.helper import RedisArchivist
|
||||||
from home.src.thumbnails import ThumbManager
|
from home.src.thumbnails import ThumbManager
|
||||||
|
|
||||||
|
|
||||||
@ -181,13 +182,23 @@ class Pagination:
|
|||||||
figure out the pagination based on page size and total_hits
|
figure out the pagination based on page size and total_hits
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, page_get, search_get=False):
|
def __init__(self, page_get, user_id, search_get=False):
|
||||||
config = AppConfig().config
|
self.user_id = user_id
|
||||||
self.page_size = config["archive"]["page_size"]
|
self.page_size = self.get_page_size()
|
||||||
self.page_get = page_get
|
self.page_get = page_get
|
||||||
self.search_get = search_get
|
self.search_get = search_get
|
||||||
self.pagination = self.first_guess()
|
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):
|
def first_guess(self):
|
||||||
"""build first guess before api call"""
|
"""build first guess before api call"""
|
||||||
page_get = self.page_get
|
page_get = self.page_get
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
{% extends "home/base.html" %}
|
{% extends "home/base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="title-bar">
|
<div class="title-bar">
|
||||||
<h1>Settings</h1>
|
<h1>User Configurations</h1>
|
||||||
</div>
|
</div>
|
||||||
<form action="/settings/" method="POST" name="settings-update">
|
<form action="/settings/" method="POST" name="user-update">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="settings-group">
|
<div class="settings-group">
|
||||||
<h2>Color scheme</h2>
|
<h2>Color scheme</h2>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current color scheme: <span class="settings-current">{{ config.application.colors }}</span></p>
|
<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>
|
<i>Select your preferred color scheme between dark and light mode.</i><br>
|
||||||
<select name="application.colors" id="application.colors">
|
{{ user_form.colors }}
|
||||||
<option value="" disabled selected> -- change color scheme -- </option>
|
|
||||||
<option value="dark">dark mode</option>
|
|
||||||
<option value="light">light mode</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-group">
|
<div class="settings-group">
|
||||||
@ -22,15 +18,22 @@
|
|||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current page size: <span class="settings-current">{{ config.archive.page_size }}</span></p>
|
<p>Current page size: <span class="settings-current">{{ config.archive.page_size }}</span></p>
|
||||||
<i>Result of videos showing in archive page</i><br>
|
<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>
|
||||||
</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">
|
<div class="settings-group">
|
||||||
<h2 id="subscriptions">Subscriptions</h2>
|
<h2 id="subscriptions">Subscriptions</h2>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current channel page size: <span class="settings-current">{{ config.subscriptions.channel_size }}</span></p>
|
<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>
|
<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>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Auto scan subscribed channels:</p>
|
<p>Auto scan subscribed channels:</p>
|
||||||
@ -46,22 +49,22 @@
|
|||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current download limit: <span class="settings-current">{{ config.downloads.limit_count }}</span></p>
|
<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>
|
<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>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current download speed limit: <span class="settings-current">{{ config.downloads.limit_speed }}</span></p>
|
<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>
|
<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>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current throttled rate limit: <span class="settings-current">{{ config.downloads.throttledratelimit }}</span></p>
|
<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>
|
<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>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current scraping sleep interval: <span class="settings-current">{{ config.downloads.sleep_interval }}</p>
|
<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>
|
<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>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>External downloader:</p>
|
<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>
|
<li><span class="settings-current">0</span>: deactivate and download the best quality possible as decided by yt-dlp.</li>
|
||||||
</ul>
|
</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>
|
<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>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current metadata embed setting: <span class="settings-current">{{ config.downloads.add_metadata }}</span></p>
|
<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>
|
<i>Metadata is not embedded into the downloaded files by default.</i><br>
|
||||||
<select name="downloads.add_metadata" id="downloads.add_metadata"">
|
{{ app_form.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>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p>Current thumbnail embed setting: <span class="settings-current">{{ config.downloads.add_thumbnail }}</span></p>
|
<p>Current thumbnail embed setting: <span class="settings-current">{{ config.downloads.add_thumbnail }}</span></p>
|
||||||
<i>Embed thumbnail into the mediafile.</i><br>
|
<i>Embed thumbnail into the mediafile.</i><br>
|
||||||
<select name="downloads.add_thumbnail" id="downloads.add_thumbnail"">
|
{{ app_form.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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">Update Settings</button>
|
<button type="submit" name="application-settings">Update Application Configurations</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="title-bar">
|
<div class="title-bar">
|
||||||
<h1>Actions</h1>
|
<h1>Actions</h1>
|
||||||
|
@ -11,7 +11,6 @@ from time import sleep
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth import login
|
from django.contrib.auth import login
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
from django.forms.widgets import PasswordInput, TextInput
|
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
from django.utils.http import urlencode
|
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.helper import RedisArchivist, RedisQueue, process_url_list
|
||||||
from home.src.index import WatchState, YoutubeChannel, YoutubeVideo
|
from home.src.index import WatchState, YoutubeChannel, YoutubeVideo
|
||||||
from home.src.searching import Pagination, SearchForm, SearchHandler
|
from home.src.searching import Pagination, SearchForm, SearchHandler
|
||||||
|
from home.forms import (
|
||||||
|
ApplicationSettingsForm,
|
||||||
|
CustomAuthForm,
|
||||||
|
UserSettingsForm
|
||||||
|
)
|
||||||
from home.tasks import (
|
from home.tasks import (
|
||||||
download_pending,
|
download_pending,
|
||||||
download_single,
|
download_single,
|
||||||
@ -44,7 +48,8 @@ class HomeView(View):
|
|||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
"""return home search results"""
|
"""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
|
# handle search
|
||||||
search_get = request.GET.get("search", False)
|
search_get = request.GET.get("search", False)
|
||||||
if search_get:
|
if search_get:
|
||||||
@ -53,7 +58,9 @@ class HomeView(View):
|
|||||||
search_encoded = False
|
search_encoded = False
|
||||||
# define page size
|
# define page size
|
||||||
page_get = int(request.GET.get("page", 0))
|
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"
|
url = self.ES_URL + "/ta_video/_search"
|
||||||
data = self.build_data(
|
data = self.build_data(
|
||||||
@ -157,17 +164,6 @@ class HomeView(View):
|
|||||||
return redirect(search_url, permanent=True)
|
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):
|
class LoginView(View):
|
||||||
"""resolves to /login/
|
"""resolves to /login/
|
||||||
Greeting and login page
|
Greeting and login page
|
||||||
@ -222,10 +218,11 @@ class DownloadView(View):
|
|||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
"""handle get requests"""
|
"""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))
|
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"
|
url = view_config["es_url"] + "/ta_download/_search"
|
||||||
data = self.build_data(
|
data = self.build_data(
|
||||||
@ -370,7 +367,7 @@ class ChannelIdView(View):
|
|||||||
def get_channel_videos(self, request, channel_id_detail, view_config):
|
def get_channel_videos(self, request, channel_id_detail, view_config):
|
||||||
"""get channel from video index"""
|
"""get channel from video index"""
|
||||||
page_get = int(request.GET.get("page", 0))
|
page_get = int(request.GET.get("page", 0))
|
||||||
pagination_handler = Pagination(page_get)
|
pagination_handler = Pagination(page_get, request.user.id)
|
||||||
# get data
|
# get data
|
||||||
url = view_config["es_url"] + "/ta_video/_search"
|
url = view_config["es_url"] + "/ta_video/_search"
|
||||||
data = self.build_data(
|
data = self.build_data(
|
||||||
@ -465,7 +462,7 @@ class ChannelView(View):
|
|||||||
user_id = request.user.id
|
user_id = request.user.id
|
||||||
view_config = self.read_config(user_id=user_id)
|
view_config = self.read_config(user_id=user_id)
|
||||||
page_get = int(request.GET.get("page", 0))
|
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_size = pagination_handler.pagination["page_size"]
|
||||||
page_from = pagination_handler.pagination["page_from"]
|
page_from = pagination_handler.pagination["page_from"]
|
||||||
# get
|
# get
|
||||||
@ -610,18 +607,35 @@ class SettingsView(View):
|
|||||||
config = AppConfig().config
|
config = AppConfig().config
|
||||||
colors = config["application"]["colors"]
|
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)
|
return render(request, "home/settings.html", context)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def post(request):
|
def post(request):
|
||||||
"""handle form post to update settings"""
|
"""handle form post to update settings"""
|
||||||
form_post = dict(request.POST)
|
|
||||||
del form_post["csrfmiddlewaretoken"]
|
form_response = forms.Form(request.POST)
|
||||||
print(form_post)
|
if form_response.is_valid():
|
||||||
config_handler = AppConfig()
|
form_post = dict(request.POST)
|
||||||
config_handler.update_config(form_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)
|
return redirect("settings", permanent=True)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user