Explain remote service responses in plain English
This commit is contained in:
@@ -2,10 +2,60 @@ from typing import Any, Dict, Optional
|
||||
import httpx
|
||||
import logging
|
||||
import time
|
||||
from .base import ApiClient
|
||||
from .base import ApiClient, _operation_error_message
|
||||
from ..services.operation_progress import finish_remote_call, start_remote_call
|
||||
|
||||
|
||||
def _torrent_state_text(state: Any) -> str:
|
||||
normalized = str(state or "").strip().lower()
|
||||
if "pause" in normalized:
|
||||
return "paused"
|
||||
if "stall" in normalized:
|
||||
return "stalled"
|
||||
if normalized.startswith("queued"):
|
||||
return "waiting in the queue"
|
||||
if "downloading" in normalized or normalized in {"forcedl", "metadl", "checkingdl"}:
|
||||
return "downloading"
|
||||
if "upload" in normalized or normalized in {"stalledup", "forcedup"}:
|
||||
return "finished and seeding"
|
||||
if normalized in {"completed", "missingfiles"}:
|
||||
return "finished" if normalized == "completed" else "missing files"
|
||||
if "error" in normalized:
|
||||
return "in an error state"
|
||||
return "present"
|
||||
|
||||
|
||||
def _torrent_result_message(result: Any) -> str:
|
||||
torrents = result if isinstance(result, list) else []
|
||||
if not torrents:
|
||||
return "qBittorrent found no matching downloads."
|
||||
first = next((item for item in torrents if isinstance(item, dict)), {})
|
||||
if len(torrents) == 1:
|
||||
name = str(first.get("name") or "the matching download").strip()
|
||||
progress = first.get("progress")
|
||||
progress_text = (
|
||||
f" and {max(0, min(100, round(progress * 100)))}% complete"
|
||||
if isinstance(progress, (int, float))
|
||||
else ""
|
||||
)
|
||||
return f'qBittorrent found "{name}"; it is {_torrent_state_text(first.get("state"))}{progress_text}.'
|
||||
active = sum(
|
||||
1
|
||||
for item in torrents
|
||||
if isinstance(item, dict) and _torrent_state_text(item.get("state")) == "downloading"
|
||||
)
|
||||
return f"qBittorrent found {len(torrents)} matching downloads; {active} are actively downloading."
|
||||
|
||||
|
||||
def _torrent_action_message(path: str) -> str:
|
||||
normalized_path = path.lower()
|
||||
if normalized_path.endswith("/resume") or normalized_path.endswith("/start"):
|
||||
return "qBittorrent accepted the request to resume the download."
|
||||
if normalized_path.endswith("/add"):
|
||||
return "qBittorrent accepted the release and added it to the download queue."
|
||||
return "qBittorrent accepted the requested download action."
|
||||
|
||||
|
||||
class QBittorrentClient(ApiClient):
|
||||
def __init__(self, base_url: Optional[str], username: Optional[str], password: Optional[str]):
|
||||
super().__init__(base_url, None)
|
||||
@@ -46,7 +96,7 @@ class QBittorrentClient(ApiClient):
|
||||
operation_event_id,
|
||||
success=True,
|
||||
status_code=response.status_code,
|
||||
message=f"qBittorrent returned the current download state in {duration_ms / 1000:.1f}s.",
|
||||
message=_torrent_result_message(result),
|
||||
)
|
||||
return result
|
||||
except Exception as exc:
|
||||
@@ -56,7 +106,7 @@ class QBittorrentClient(ApiClient):
|
||||
operation_event_id,
|
||||
success=False,
|
||||
status_code=status_code,
|
||||
message=f"qBittorrent returned an error after {duration_ms / 1000:.1f}s.",
|
||||
message=_operation_error_message("qBittorrent", status_code),
|
||||
)
|
||||
raise
|
||||
|
||||
@@ -76,7 +126,7 @@ class QBittorrentClient(ApiClient):
|
||||
operation_event_id,
|
||||
success=True,
|
||||
status_code=response.status_code,
|
||||
message=f"qBittorrent responded in {duration_ms / 1000:.1f}s.",
|
||||
message=f"Connected to qBittorrent{f' version {result}' if result else ''}.",
|
||||
)
|
||||
return result
|
||||
except Exception as exc:
|
||||
@@ -86,7 +136,7 @@ class QBittorrentClient(ApiClient):
|
||||
operation_event_id,
|
||||
success=False,
|
||||
status_code=status_code,
|
||||
message=f"qBittorrent returned an error after {duration_ms / 1000:.1f}s.",
|
||||
message=_operation_error_message("qBittorrent", status_code),
|
||||
)
|
||||
raise
|
||||
|
||||
@@ -105,7 +155,7 @@ class QBittorrentClient(ApiClient):
|
||||
operation_event_id,
|
||||
success=True,
|
||||
status_code=response.status_code,
|
||||
message=f"qBittorrent accepted the action in {duration_ms / 1000:.1f}s.",
|
||||
message=_torrent_action_message(path),
|
||||
)
|
||||
except Exception as exc:
|
||||
duration_ms = round((time.perf_counter() - started_at) * 1000, 2)
|
||||
@@ -114,7 +164,7 @@ class QBittorrentClient(ApiClient):
|
||||
operation_event_id,
|
||||
success=False,
|
||||
status_code=status_code,
|
||||
message=f"qBittorrent returned an error after {duration_ms / 1000:.1f}s.",
|
||||
message=_operation_error_message("qBittorrent", status_code),
|
||||
)
|
||||
raise
|
||||
|
||||
|
||||
Reference in New Issue
Block a user