mirror of
https://github.com/markbeep/AudioBookRequest.git
synced 2026-01-05 21:20:15 -06:00
correctly handle missing/incorrect prowlarr settings
This commit is contained in:
@@ -6,6 +6,7 @@ from typing import Any, Literal, Optional
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from aiohttp import ClientResponse, ClientSession
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.internal.indexers.abstract import SessionContainer
|
||||
@@ -246,37 +247,75 @@ async def query_prowlarr(
|
||||
return sources
|
||||
|
||||
|
||||
class IndexerResponse(BaseModel):
|
||||
indexers: dict[int, Indexer] = {}
|
||||
state: Literal["ok", "missingUrlKey", "failedFetch"]
|
||||
error: Optional[str] = None
|
||||
|
||||
@property
|
||||
def json_string(self) -> str:
|
||||
return json.dumps(
|
||||
{id: indexer.model_dump() for id, indexer in self.indexers.items()}
|
||||
)
|
||||
|
||||
@property
|
||||
def ok(self) -> bool:
|
||||
return self.state == "ok"
|
||||
|
||||
|
||||
async def get_indexers(
|
||||
session: Session, client_session: ClientSession
|
||||
) -> dict[int, Indexer]:
|
||||
) -> IndexerResponse:
|
||||
"""Fetch the list of all indexers from Prowlarr."""
|
||||
base_url = prowlarr_config.get_base_url(session)
|
||||
api_key = prowlarr_config.get_api_key(session)
|
||||
assert base_url is not None and api_key is not None
|
||||
source_ttl = prowlarr_config.get_source_ttl(session)
|
||||
|
||||
if not base_url or not api_key:
|
||||
logger.warning("Prowlarr base url or api key not set, skipping indexer fetch")
|
||||
return IndexerResponse(
|
||||
state="failedFetch",
|
||||
error="Missing Prowlarr base url or api key",
|
||||
)
|
||||
|
||||
indexers = prowlarr_indexer_cache.get_all(source_ttl).values()
|
||||
if len(indexers) > 0:
|
||||
return {indexer.id: indexer for indexer in indexers}
|
||||
return IndexerResponse(
|
||||
indexers={indexer.id: indexer for indexer in indexers},
|
||||
state="ok",
|
||||
)
|
||||
|
||||
url = posixpath.join(base_url, "api/v1/indexer")
|
||||
logger.info("Fetching indexers from Prowlarr: %s", url)
|
||||
|
||||
async with client_session.get(
|
||||
url,
|
||||
headers={"X-Api-Key": api_key},
|
||||
) as response:
|
||||
if not response.ok:
|
||||
logger.error("Failed to fetch indexers: %s", response)
|
||||
return {}
|
||||
try:
|
||||
async with client_session.get(
|
||||
url,
|
||||
headers={"X-Api-Key": api_key},
|
||||
) as response:
|
||||
if not response.ok:
|
||||
logger.error("Failed to fetch indexers: %s", response)
|
||||
return IndexerResponse(
|
||||
state="failedFetch",
|
||||
error=f"{response.status}: {response.reason}",
|
||||
)
|
||||
|
||||
json_response = await response.json()
|
||||
json_response = await response.json()
|
||||
|
||||
for indexer in json_response:
|
||||
indexer_obj = Indexer.model_validate(indexer)
|
||||
prowlarr_indexer_cache.set(indexer_obj, str(indexer_obj.id))
|
||||
for indexer in json_response:
|
||||
indexer_obj = Indexer.model_validate(indexer)
|
||||
prowlarr_indexer_cache.set(indexer_obj, str(indexer_obj.id))
|
||||
|
||||
return {
|
||||
indexer.id: indexer
|
||||
for indexer in prowlarr_indexer_cache.get_all(source_ttl).values()
|
||||
}
|
||||
return IndexerResponse(
|
||||
indexers={
|
||||
indexer.id: indexer
|
||||
for indexer in prowlarr_indexer_cache.get_all(source_ttl).values()
|
||||
},
|
||||
state="ok",
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("Failed to access Prowlarr to fetch indexers: %s", e)
|
||||
return IndexerResponse(
|
||||
state="failedFetch",
|
||||
error=str(e),
|
||||
)
|
||||
|
||||
@@ -223,7 +223,6 @@ async def read_prowlarr(
|
||||
prowlarr_api_key = prowlarr_config.get_api_key(session)
|
||||
selected = set(prowlarr_config.get_categories(session))
|
||||
indexers = await get_indexers(session, client_session)
|
||||
indexers = {id: indexer.model_dump() for id, indexer in indexers.items()}
|
||||
selected_indexers = set(prowlarr_config.get_indexers(session))
|
||||
|
||||
return template_response(
|
||||
@@ -236,7 +235,7 @@ async def read_prowlarr(
|
||||
"prowlarr_api_key": prowlarr_api_key,
|
||||
"indexer_categories": indexer_categories,
|
||||
"selected_categories": selected,
|
||||
"indexers": json.dumps(indexers),
|
||||
"indexers": indexers,
|
||||
"selected_indexers": selected_indexers,
|
||||
"prowlarr_misconfigured": True if prowlarr_misconfigured else False,
|
||||
},
|
||||
@@ -252,6 +251,7 @@ def update_prowlarr_api_key(
|
||||
],
|
||||
):
|
||||
prowlarr_config.set_api_key(session, api_key)
|
||||
flush_prowlarr_cache()
|
||||
return Response(status_code=204, headers={"HX-Refresh": "true"})
|
||||
|
||||
|
||||
@@ -264,6 +264,7 @@ def update_prowlarr_base_url(
|
||||
],
|
||||
):
|
||||
prowlarr_config.set_base_url(session, base_url)
|
||||
flush_prowlarr_cache()
|
||||
return Response(status_code=204, headers={"HX-Refresh": "true"})
|
||||
|
||||
|
||||
@@ -306,7 +307,6 @@ async def update_selected_indexers(
|
||||
prowlarr_config.set_indexers(session, indexer_ids)
|
||||
|
||||
indexers = await get_indexers(session, client_session)
|
||||
indexers = {id: indexer.model_dump() for id, indexer in indexers.items()}
|
||||
selected_indexers = set(prowlarr_config.get_indexers(session))
|
||||
flush_prowlarr_cache()
|
||||
|
||||
@@ -315,9 +315,9 @@ async def update_selected_indexers(
|
||||
request,
|
||||
admin_user,
|
||||
{
|
||||
"indexers": json.dumps(indexers),
|
||||
"indexers": indexers,
|
||||
"selected_indexers": selected_indexers,
|
||||
"success": "Categories updated",
|
||||
"success": "Indexers updated",
|
||||
},
|
||||
block_name="indexer",
|
||||
)
|
||||
|
||||
@@ -110,18 +110,30 @@
|
||||
<form
|
||||
id="indexer-select"
|
||||
class="flex flex-col gap-1"
|
||||
x-data="{ selectedIndexers: [{{ selected_indexers|join(',') }}].sort(), indexers: {{ indexers }}, dirty: false }"
|
||||
x-data="{ selectedIndexers: [{{ selected_indexers|join(',') }}].sort(), indexers: {{ indexers.json_string }}, dirty: false }"
|
||||
hx-put="{{base_url}}/settings/prowlarr/indexers"
|
||||
hx-disabled-elt="#indexer-submit-button"
|
||||
hx-target="this"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
{% if success %}
|
||||
<script>
|
||||
toast("{{success|safe}}", "success");
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<label for="indexers">Indexers</label>
|
||||
<p class="text-xs opacity-60">
|
||||
Select the indexers to use with Prowlarr. If none are selected, all
|
||||
indexers will be used.
|
||||
indexers will be used. {% if not indexers.ok %}
|
||||
<span class="text-error font-semibold">
|
||||
<br />
|
||||
No indexers found. {{ indexers.error or "" }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
{% if indexers.ok %}
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<template x-for="indexerId in selectedIndexers">
|
||||
<div
|
||||
@@ -139,8 +151,10 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<select name="group" class="select w-full">
|
||||
<!-- prettier-ignore -->
|
||||
<select name="group" class="select w-full" {% if not indexers.ok %}disabled{% endif %}>
|
||||
<template x-for="indexerId in Object.keys(indexers)">
|
||||
<template x-if="!selectedIndexers.includes(indexerId)">
|
||||
<option
|
||||
|
||||
Reference in New Issue
Block a user