from __future__ import annotations from typing import Any, Dict, Optional import requests from django.conf import settings from django.core.exceptions import ImproperlyConfigured class WebEgressError(Exception): def __init__( self, message: str, *, status_code: Optional[int] = None, response_data: Optional[Dict[str, Any]] = None, ): super().__init__(message) self.status_code = status_code self.response_data = response_data or {} class WebEgressClient: def __init__( self, *, base_url: Optional[str] = None, service_token: Optional[str] = None, timeout: Optional[float] = None, ): self.base_url = ( base_url or getattr(settings, "ONLINE_CLASS_WEB_EGRESS_SERVICE_URL", "") ).rstrip("/") self.service_token = ( service_token or getattr(settings, "ONLINE_CLASS_WEB_EGRESS_SERVICE_TOKEN", "") ) self.timeout = timeout or getattr( settings, "ONLINE_CLASS_WEB_EGRESS_TIMEOUT", 20.0 ) if not self.base_url: raise ImproperlyConfigured( "ONLINE_CLASS_WEB_EGRESS_SERVICE_URL must be configured." ) def start_recording(self, payload: Dict[str, Any]) -> Dict[str, Any]: return self._request("POST", "/api/web-egress/start/", json=payload) def stop_recording(self, payload: Dict[str, Any]) -> Dict[str, Any]: return self._request("POST", "/api/web-egress/stop/", json=payload) def get_status(self, *, room_id: str, session_id: int) -> Dict[str, Any]: return self._request( "GET", "/api/web-egress/status/", params={"room_id": room_id, "session_id": session_id}, ) def _request(self, method: str, path: str, **kwargs) -> Dict[str, Any]: headers = kwargs.pop("headers", {}) headers["Content-Type"] = "application/json" if self.service_token: headers["Authorization"] = f"Bearer {self.service_token}" try: response = requests.request( method, f"{self.base_url}{path}", headers=headers, timeout=self.timeout, **kwargs, ) except requests.RequestException as exc: raise WebEgressError("Failed to reach WebEgress service.") from exc data = self._safe_json(response) if response.status_code >= 400: message = ( (data or {}).get("message") or (data or {}).get("detail") or response.text or "WebEgress service request failed." ) raise WebEgressError( message, status_code=response.status_code, response_data=data, ) if data is None: raise WebEgressError("WebEgress service returned an invalid response.") if isinstance(data, dict) and data.get("status") is False: raise WebEgressError( data.get("message") or data.get("detail") or "WebEgress failed.", status_code=response.status_code, response_data=data, ) return data @staticmethod def _safe_json(response: requests.Response) -> Optional[Dict[str, Any]]: try: return response.json() except ValueError: return None