mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-09-12 21:54:16 -04:00
Migrate more config pages to Starlette
Continues the migration to Starlette/Uvicorn by converting the General, Folders, Switches, Special, and Categories config pages. This commit: - Refactors CherryPy class-based handlers into Starlette function-based routes. - Updates form actions and methods in templates to align with the new routing. - Standardizes API responses using `sabnzbd.api.report` for consistency. - Updates Uvicorn and other related web dependencies.
This commit is contained in:
9 files changed
+76
-72
No files matched your search
@@ -17,7 +17,6 @@
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
# Trick to show a better message on older Python
|
||||
# releases that don't support walrus operator
|
||||
if Python_39_is_required_to_run_SABnzbd := sys.hexversion < 0x03090000:
|
||||
|
||||
@@ -9,12 +9,12 @@ setuptools==82.0.1
|
||||
markdown==3.10.2
|
||||
|
||||
# Required on 32bit Windows, exclude it based on Python-version
|
||||
importlib_metadata==8.5.0; python_version < '3.10'
|
||||
importlib_resources==6.4.5; python_version < '3.10'
|
||||
zipp==3.21.0; python_version < '3.10'
|
||||
importlib_metadata==8.7.0; python_version < '3.10'
|
||||
importlib_resources==6.5.2; python_version < '3.10'
|
||||
zipp==3.23.0; python_version < '3.10'
|
||||
|
||||
# orjson does not support 32bit Windows, also exclude based on Python-version
|
||||
orjson==3.10.12; python_version > '3.8'
|
||||
orjson==3.11.3; python_version > '3.8'
|
||||
|
||||
# For the Windows build
|
||||
pefile==2024.8.26; sys_platform == 'win32'
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<h5 class="darkred"><strong>$T('explain-relFolder'):</strong> <span class="path">$defdir</span></h5>
|
||||
<!--#for $cur, $slot in enumerate($slotinfo)#-->
|
||||
<!--#set $cansort = $slot.name != '*' and $slot.name != ''#-->
|
||||
<form action="save" method="post" <!--#if $cansort#-->class="sorting-row"<!--#end if#-->>
|
||||
<form action="categories/save" method="get" class="fullform" <!--#if $cansort#-->class="sorting-row"<!--#end if#-->>
|
||||
<table class="catTable">
|
||||
<!--#if $cur == 0#-->
|
||||
<tr>
|
||||
@@ -108,7 +108,7 @@
|
||||
jQuery(document).ready(function() {
|
||||
jQuery('.delCat').click(function() {
|
||||
var theForm = jQuery(this).closest("form");
|
||||
theForm.attr("action", "delete").submit();
|
||||
theForm.attr("action", "categories/delete").submit();
|
||||
});
|
||||
|
||||
// Add autocomplete and file-browser
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<input type="checkbox" id="advanced-settings-button" name="advanced-settings-button"> $T('button-advanced')
|
||||
</label>
|
||||
</div>
|
||||
<form action="folders/save" method="post" name="fullform" class="fullform" autocomplete="off">
|
||||
<form action="folders/save" method="get" name="fullform" class="fullform" autocomplete="off">
|
||||
<input type="hidden" id="apikey" name="apikey" value="$apikey" />
|
||||
<input type="hidden" name="output" value="json" />
|
||||
<input type="hidden" id="ajax" name="ajax" value="1" />
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<input type="checkbox" id="advanced-settings-button" name="advanced-settings-button"> $T('button-advanced')
|
||||
</label>
|
||||
</div>
|
||||
<form action="general/save" method="post" name="fullform" class="fullform" autocomplete="off">
|
||||
<form action="general/save" method="get" name="fullform" class="fullform" autocomplete="off">
|
||||
<input type="hidden" id="apikey" name="apikey" value="$apikey" />
|
||||
<input type="hidden" id="ajax" name="ajax" value="1" />
|
||||
<input type="hidden" name="output" value="json" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
<form action="saveSpecial" method="post" autocomplete="off">
|
||||
<form action="special/save" method="get" name="fullform" class="fullform" autocomplete="off">
|
||||
<input type="hidden" id="apikey" name="apikey" value="$apikey" />
|
||||
<div class="padTable">
|
||||
<h4 class="darkred nomargin">$T('explain-special')</h4>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<input type="checkbox" id="advanced-settings-button" name="advanced-settings-button"> $T('button-advanced')
|
||||
</label>
|
||||
</div>
|
||||
<form action="switches/save" method="post" name="fullform" class="fullform" autocomplete="off">
|
||||
<form action="switches/save" method="get" name="fullform" class="fullform" autocomplete="off">
|
||||
<input type="hidden" id="apikey" name="apikey" value="$apikey" />
|
||||
<input type="hidden" id="ajax" name="ajax" value="1" />
|
||||
<input type="hidden" name="output" value="json" />
|
||||
|
||||
+4
-4
@@ -33,11 +33,11 @@ babelfish==0.6.1
|
||||
rebulk==3.2.0
|
||||
|
||||
# New for starlette/uvicorn
|
||||
starlette==0.47.3
|
||||
anyio==4.10.0
|
||||
starlette==0.48.0
|
||||
anyio==4.11.0
|
||||
sniffio==1.3.1
|
||||
uvicorn==0.35.0
|
||||
click==8.1.7
|
||||
uvicorn==0.37.0
|
||||
click==8.3.0
|
||||
h11==0.16.0
|
||||
python-multipart==0.0.20
|
||||
httptools==0.6.4
|
||||
|
||||
+62
-57
@@ -136,7 +136,6 @@ def secured_expose(
|
||||
|
||||
@functools.wraps(wrap_func)
|
||||
async def internal_wrap(*args, **kwargs):
|
||||
# All good, cool!
|
||||
return await wrap_func(*args, **kwargs)
|
||||
|
||||
return internal_wrap
|
||||
@@ -963,7 +962,7 @@ async def config_general_save(request: Request):
|
||||
# Handle general options
|
||||
for kw in GENERAL_LIST:
|
||||
if msg := config.get_config("misc", kw).set(request.query_params.get(kw)):
|
||||
return badParameterResponse(msg, ajax=request.query_params.get("ajax"))
|
||||
return sabnzbd.api.report(request.query_params, error=msg)
|
||||
|
||||
# Handle special options
|
||||
cfg.password.set(request.query_params.get("password"))
|
||||
@@ -972,13 +971,7 @@ async def config_general_save(request: Request):
|
||||
change_web_dir(web_dir)
|
||||
|
||||
config.save_config()
|
||||
|
||||
# Update CherryPy authentication
|
||||
set_auth(cherrypy.config)
|
||||
if request.query_params.get("ajax"):
|
||||
return sabnzbd.api.report(data={"success": True, "restart_req": sabnzbd.RESTART_REQ})
|
||||
else:
|
||||
raise Raiser("/config")
|
||||
return sabnzbd.api.report(request.query_params, data={"success": True, "restart_req": sabnzbd.RESTART_REQ})
|
||||
|
||||
|
||||
@secured_expose(route="/config/general/uploadConfig", check_api_key=True, check_configlock=True)
|
||||
@@ -1706,64 +1699,76 @@ class ConfigScheduling:
|
||||
|
||||
|
||||
##############################################################################
|
||||
class ConfigCats:
|
||||
def __init__(self, root):
|
||||
self.__root = root
|
||||
# Page definitions - Config - Categories
|
||||
##############################################################################
|
||||
|
||||
@secured_expose(check_configlock=True)
|
||||
def index(request: Request):
|
||||
conf = build_header(sabnzbd.WEB_DIR_CONFIG)
|
||||
@secured_expose(route="/config/categories", check_configlock=True)
|
||||
async def index_config_categories(request: Request):
|
||||
conf = build_header(sabnzbd.WEB_DIR_CONFIG)
|
||||
|
||||
conf["scripts"] = list_scripts(default=True)
|
||||
conf["defdir"] = cfg.complete_dir.get_clipped_path()
|
||||
conf["scripts"] = list_scripts(default=True)
|
||||
conf["defdir"] = cfg.complete_dir.get_clipped_path()
|
||||
|
||||
categories = config.get_ordered_categories()
|
||||
new_cat_order = max(cat["order"] for cat in categories) + 1
|
||||
categories = config.get_ordered_categories()
|
||||
new_cat_order = max(cat["order"] for cat in categories) + 1
|
||||
|
||||
# Add empty line to add new categories
|
||||
empty = {
|
||||
"name": "",
|
||||
"order": str(new_cat_order),
|
||||
"pp": "-1",
|
||||
"script": "",
|
||||
"dir": "",
|
||||
"newzbin": "",
|
||||
"priority": DEFAULT_PRIORITY,
|
||||
}
|
||||
categories.insert(1, empty)
|
||||
conf["slotinfo"] = categories
|
||||
# Add empty line to add new categories
|
||||
empty = {
|
||||
"name": "",
|
||||
"order": str(new_cat_order),
|
||||
"pp": "-1",
|
||||
"script": "",
|
||||
"dir": "",
|
||||
"newzbin": "",
|
||||
"priority": DEFAULT_PRIORITY,
|
||||
}
|
||||
categories.insert(1, empty)
|
||||
conf["slotinfo"] = categories
|
||||
|
||||
return template_filtered_response(
|
||||
file=os.path.join(sabnzbd.WEB_DIR_CONFIG, "config_cat.tmpl"),
|
||||
search_list=conf,
|
||||
)
|
||||
return template_filtered_response(
|
||||
file=os.path.join(sabnzbd.WEB_DIR_CONFIG, "config_cat.tmpl"),
|
||||
search_list=conf,
|
||||
)
|
||||
|
||||
@secured_expose(check_api_key=True, check_configlock=True)
|
||||
def delete(request: Request):
|
||||
kwargs["section"] = "categories"
|
||||
kwargs["keyword"] = request.query_params.get("name")
|
||||
del_from_section(kwargs)
|
||||
raise Raiser(self.__root)
|
||||
|
||||
@secured_expose(check_api_key=True, check_configlock=True)
|
||||
def save(request: Request):
|
||||
name = request.query_params.get("name", "*")
|
||||
newname = request.query_params.get("newname", "")
|
||||
if name == "*":
|
||||
newname = name
|
||||
@secured_expose(route="/config/categories/delete", check_api_key=True, check_configlock=True)
|
||||
async def config_categories_delete(request: Request):
|
||||
kw = {
|
||||
"section": "categories",
|
||||
"keyword": request.query_params.get("name"),
|
||||
}
|
||||
del_from_section(kw)
|
||||
# Keep API response pattern consistent
|
||||
return sabnzbd.api.report(request.query_params)
|
||||
|
||||
if newname:
|
||||
# Check if this cat-dir is not sub-folder of incomplete
|
||||
if same_directory(cfg.download_dir.get_path(), real_path(cfg.complete_dir.get_path(), kwargs["dir"])):
|
||||
return T("Category folder cannot be a subfolder of the Temporary Download Folder.")
|
||||
|
||||
# Delete current one and replace with new one
|
||||
if name:
|
||||
config.delete("categories", name)
|
||||
config.ConfigCat(newname.lower(), kwargs)
|
||||
@secured_expose(route="/config/categories/save", check_api_key=True, check_configlock=True)
|
||||
async def config_categories_save(request: Request):
|
||||
name = request.query_params.get("name", "*")
|
||||
newname = request.query_params.get("newname", "")
|
||||
if name == "*":
|
||||
newname = name
|
||||
|
||||
config.save_config()
|
||||
raise Raiser(self.__root)
|
||||
if newname:
|
||||
# Build params dict for category configuration
|
||||
cat_params = dict(request.query_params)
|
||||
# Validate directory not under incomplete
|
||||
if same_directory(
|
||||
cfg.download_dir.get_path(),
|
||||
real_path(cfg.complete_dir.get_path(), cat_params.get("dir", "")),
|
||||
):
|
||||
return sabnzbd.api.report(
|
||||
request.query_params,
|
||||
error=T("Category folder cannot be a subfolder of the Temporary Download Folder."),
|
||||
)
|
||||
|
||||
# Delete current one and replace with new one
|
||||
if name:
|
||||
config.delete("categories", name)
|
||||
config.ConfigCat(newname.lower(), cat_params)
|
||||
|
||||
config.save_config()
|
||||
return sabnzbd.api.report(request.query_params)
|
||||
|
||||
|
||||
##############################################################################
|
||||
|
||||
Reference in new issue
Block a user