Explain remote service responses in plain English
Magent CI/CD / verify (push) Successful in 10m20s
Magent CI/CD / deploy-prod (push) Skipped
Magent CI/CD / deploy-beta (push) Successful in 15s

This commit is contained in:
2026-08-31 22:28:56 +12:00
parent 906a777b95
commit ae6cee5d0b
4 changed files with 369 additions and 16 deletions
+57 -7
View File
@@ -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