use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; use thiserror::Error; pub type LiveResult = Result; #[derive(Debug, Error)] pub enum LiveError { #[error("bad request: {0}")] BadRequest(String), #[error("not found: {0}")] NotFound(String), #[error("forbidden: {0}")] PermissionDenied(String), #[error("conflict: {0}")] Conflict(String), #[error("livekit not configured: {0}")] NotConfigured(String), #[error("livekit api error: {0}")] LiveKitApi(String), #[error("webhook verification failed: {0}")] WebhookVerification(String), #[error("chat layer error: {0}")] ChatLayer(#[from] chatlayer::ChatLayerError), #[error("storage error: {0}")] Storage(#[from] storagelayer::ChatStorageError), #[error("serde error: {0}")] Serde(#[from] serde_json::Error), #[error("reqwest error: {0}")] Reqwest(#[from] reqwest::Error), #[error("jwt error: {0}")] Jwt(#[from] jsonwebtoken::errors::Error), #[error("internal: {0}")] Internal(String), } impl LiveError { fn status(&self) -> StatusCode { match self { Self::BadRequest(_) => StatusCode::BAD_REQUEST, Self::NotFound(_) => StatusCode::NOT_FOUND, Self::PermissionDenied(_) => StatusCode::FORBIDDEN, Self::Conflict(_) => StatusCode::CONFLICT, Self::NotConfigured(_) => StatusCode::SERVICE_UNAVAILABLE, Self::LiveKitApi(_) | Self::WebhookVerification(_) => StatusCode::BAD_GATEWAY, Self::ChatLayer(_) | Self::Storage(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::Serde(_) | Self::Reqwest(_) | Self::Jwt(_) | Self::Internal(_) => { StatusCode::INTERNAL_SERVER_ERROR } } } pub fn error_kind(&self) -> &'static str { match self { Self::BadRequest(_) => "bad_request", Self::NotFound(_) => "not_found", Self::PermissionDenied(_) => "forbidden", Self::Conflict(_) => "conflict", Self::NotConfigured(_) => "not_configured", Self::LiveKitApi(_) => "livekit_api", Self::WebhookVerification(_) => "webhook_verification", Self::ChatLayer(_) => "chat_layer", Self::Storage(_) => "storage", Self::Serde(_) => "serde", Self::Reqwest(_) => "reqwest", Self::Jwt(_) => "jwt", Self::Internal(_) => "internal", } } } impl IntoResponse for LiveError { fn into_response(self) -> Response { let status = self.status(); let (status, body) = match &self { Self::WebhookVerification(_) | Self::NotConfigured(_) => { (StatusCode::OK, serde_json::json!({ "ok": false })) } _ => { let body = serde_json::json!({ "error": { "kind": self.error_kind(), "message": self.to_string() } }); (status, body) } }; (status, axum::Json(body)).into_response() } }