Show actual collector search activity in request pipeline
This commit is contained in:
@@ -27,6 +27,7 @@ from ..db import (
|
||||
clear_seerr_media_failure,
|
||||
)
|
||||
from ..models import ActionOption, NormalizedState, RequestType, Snapshot, TimelineHop
|
||||
from .collector_search import read_search_status
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -666,6 +667,19 @@ def _build_presentation(
|
||||
fully_available = bool(jellyfin_found and not jellyfin_partial)
|
||||
download_visible = bool(download.get("visible"))
|
||||
download_state = str(download.get("state") or "not_started")
|
||||
search_status = str((arr_details.get("search") or {}).get("state") or "unavailable")
|
||||
search_in_progress = search_status in {"searching", "queued"}
|
||||
search_label = {
|
||||
"searching": "Searching",
|
||||
"queued": "Search queued",
|
||||
"idle": "Not searching",
|
||||
}.get(search_status, "Search unknown")
|
||||
search_target = "episode releases" if snapshot.request_type == RequestType.tv else "a matching release"
|
||||
search_detail = {
|
||||
"searching": f"{collector} is searching for {search_target}.",
|
||||
"queued": f"Search queued — waiting for {collector} to start.",
|
||||
"idle": f"Not currently searching for this {'series' if snapshot.request_type == RequestType.tv else 'movie'}.",
|
||||
}.get(search_status, f"Search status unavailable — unable to check {collector}.")
|
||||
|
||||
if snapshot.state == NormalizedState.requested:
|
||||
status_label = "Waiting for approval"
|
||||
@@ -679,8 +693,8 @@ def _build_presentation(
|
||||
elif jellyfin_partial:
|
||||
status_label = f"Partially available — {available} of {total} episodes collected"
|
||||
meaning = (
|
||||
f"Some of this request is ready to watch. {collector} is still looking for "
|
||||
f"{missing} missing episode{'s' if missing != 1 else ''}."
|
||||
f"Some of this request is ready to watch; {missing} episode{'s' if missing != 1 else ''} "
|
||||
f"{'is' if missing == 1 else 'are'} still missing. {search_detail}"
|
||||
)
|
||||
elif snapshot.state in {NormalizedState.completed, NormalizedState.available}:
|
||||
status_label = "Available to watch"
|
||||
@@ -760,6 +774,10 @@ def _build_presentation(
|
||||
next_title = "Add this request to the library queue"
|
||||
next_description = f"Send the approved request to {collector} so collection can begin."
|
||||
recommended = ["readd_to_arr"]
|
||||
elif search_in_progress and arr_state != "available":
|
||||
next_title = "Wait for the search results" if search_status == "searching" else "Wait for the queued search"
|
||||
next_description = f"{search_detail} This page will update automatically."
|
||||
recommended = []
|
||||
elif "search_auto" in action_ids or "search_releases" in action_ids:
|
||||
if snapshot.request_type == RequestType.tv and missing:
|
||||
target = f"the {missing} missing episode{'s' if missing != 1 else ''}"
|
||||
@@ -806,38 +824,38 @@ def _build_presentation(
|
||||
"state": "complete" if approved else "active",
|
||||
"summary": "Approved for collection" if approved else "Waiting for approval",
|
||||
}
|
||||
library_state_label = None
|
||||
if arr_state == "missing":
|
||||
library_state, library_summary = "attention", "Not yet added to the collector"
|
||||
elif arr_state == "error":
|
||||
library_state, library_summary = "attention", f"Unable to read {collector}"
|
||||
elif partial:
|
||||
library_state, library_summary = "partial", f"{available} of {total} episodes collected"
|
||||
elif arr_state == "available":
|
||||
library_state, library_summary = "complete", "Collection complete"
|
||||
elif arr_state in {"added", "searching"}:
|
||||
library_state = "active" if missing or not available else "complete"
|
||||
library_summary = (
|
||||
f"{missing} episode{'s' if missing != 1 else ''} still missing"
|
||||
if snapshot.request_type == RequestType.tv and missing
|
||||
else "In the library queue"
|
||||
)
|
||||
elif fully_available or (arr_state == "available" and not partial):
|
||||
library_state, library_summary = "complete", "Collection complete — no search needed"
|
||||
elif arr_state in {"added", "searching", "available"}:
|
||||
library_state = "active" if search_in_progress else "attention" if search_status == "unavailable" else "waiting"
|
||||
library_state_label = search_label
|
||||
library_summary = search_detail
|
||||
if download_visible and download_state == "downloading" and not search_in_progress:
|
||||
library_state, library_state_label = "active", "Downloading"
|
||||
library_summary = f"Download in progress. {search_detail}"
|
||||
if partial:
|
||||
library_state = "partial"
|
||||
library_summary = f"{available} of {total} episodes collected. {library_summary}"
|
||||
else:
|
||||
library_state, library_summary = "waiting", "Waiting for collector information"
|
||||
|
||||
if fully_available:
|
||||
search_state, search_summary = "complete", "No further search needed"
|
||||
elif arr_state == "available":
|
||||
elif arr_state == "available" and not partial:
|
||||
search_state, search_summary = "complete", "A release was collected"
|
||||
elif download_visible:
|
||||
elif search_in_progress:
|
||||
search_state, search_summary = "active", search_detail
|
||||
elif download_visible and download_state in {"downloading", "paused", "completed"} and not partial:
|
||||
search_state = "complete"
|
||||
search_summary = "A release was found"
|
||||
elif arr_state in {"added", "searching"} and (missing or snapshot.request_type == RequestType.movie):
|
||||
search_state = "active" if prowlarr_state == "ok" else "attention"
|
||||
search_summary = (
|
||||
f"Ready to search for {missing} missing episode{'s' if missing != 1 else ''}"
|
||||
if snapshot.request_type == RequestType.tv and missing
|
||||
else "Ready to search for a release"
|
||||
)
|
||||
search_state = "waiting" if search_status == "idle" and prowlarr_state == "ok" else "attention"
|
||||
search_summary = search_detail
|
||||
else:
|
||||
search_state, search_summary = "waiting", "Search has not started"
|
||||
|
||||
@@ -917,6 +935,8 @@ def _build_presentation(
|
||||
"id": "library",
|
||||
"label": "Library collection",
|
||||
"state": library_state,
|
||||
"stateLabel": library_state_label or library_state,
|
||||
"searchStatus": search_status,
|
||||
"summary": library_summary,
|
||||
"available": available,
|
||||
"missing": missing,
|
||||
@@ -929,7 +949,7 @@ def _build_presentation(
|
||||
"label": "Release search",
|
||||
"state": search_state,
|
||||
"summary": search_summary,
|
||||
"actionIds": [] if fully_available else [
|
||||
"actionIds": [] if fully_available or search_in_progress else [
|
||||
action_id
|
||||
for action_id in ("search_auto", "search_releases")
|
||||
if action_id in action_ids
|
||||
@@ -1144,6 +1164,9 @@ async def build_snapshot(request_id: str) -> Snapshot:
|
||||
arr_queue = _filter_queue(arr_queue, series_id, RequestType.tv)
|
||||
arr_details["queue"] = arr_queue
|
||||
episodes = await sonarr.get_episodes(series_id)
|
||||
arr_details["search"] = {
|
||||
"state": await read_search_status(sonarr, RequestType.tv, series_id, episodes)
|
||||
}
|
||||
arr_details["availability"] = _episode_availability(episodes)
|
||||
missing_by_season = _missing_episode_numbers_by_season(episodes)
|
||||
if missing_by_season:
|
||||
@@ -1187,8 +1210,6 @@ async def build_snapshot(request_id: str) -> Snapshot:
|
||||
if arr_item:
|
||||
if arr_item.get("hasFile"):
|
||||
arr_state = "available"
|
||||
elif arr_item.get("isAvailable"):
|
||||
arr_state = "searching"
|
||||
else:
|
||||
arr_state = "added"
|
||||
else:
|
||||
@@ -1203,12 +1224,17 @@ async def build_snapshot(request_id: str) -> Snapshot:
|
||||
arr_queue = await radarr.get_queue(int(arr_item["id"]))
|
||||
arr_queue = _filter_queue(arr_queue, int(arr_item["id"]), RequestType.movie)
|
||||
arr_details["queue"] = arr_queue
|
||||
arr_details["search"] = {
|
||||
"state": await read_search_status(radarr, RequestType.movie, int(arr_item["id"]))
|
||||
}
|
||||
except Exception as exc:
|
||||
arr_state = "error"
|
||||
arr_details["error"] = str(exc)
|
||||
|
||||
if arr_state is None:
|
||||
arr_state = "unknown"
|
||||
if arr_state == "added" and (arr_details.get("search") or {}).get("state") == "searching":
|
||||
arr_state = "searching"
|
||||
|
||||
_apply_arr_identity(snapshot, arr_item)
|
||||
timeline.append(TimelineHop(service="Sonarr/Radarr", status=arr_state, details=arr_details))
|
||||
|
||||
Reference in New Issue
Block a user