use actix_web::{ResponseError, HttpResponse}; use diesel::result::Error as DieselError; use reqwest::StatusCode; use serde::{Serialize, Deserialize}; use std::fmt; #[derive(Serialize, Deserialize)] pub struct Message { pub id: String, pub guild_id: i64, pub channel_id: i64, pub user_id: i64, pub created: i64, pub model: String, pub request: String, pub response: String, pub request_tags: Vec, pub response_tags: Vec, } #[derive(Serialize, Deserialize)] pub struct GetResponse { pub data: T, #[serde(skip_serializing_if = "Option::is_none")] pub metadata: Option } #[derive(Serialize, Deserialize)] pub struct Metadata { pub total: i32, pub limit: i32, pub page: i32, pub pages: i32 } #[derive(Debug, Deserialize, Serialize)] pub struct ServiceError { pub status: u16, pub message: String, } impl ServiceError { pub fn new(error_status_code: u16, error_message: String) -> ServiceError { ServiceError { status: error_status_code, message: error_message, } } } impl fmt::Display for ServiceError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.message.as_str()) } } impl From for ServiceError { fn from(error: DieselError) -> ServiceError { match error { DieselError::DatabaseError(kind, err) => { match kind { diesel::result::DatabaseErrorKind::UniqueViolation => { ServiceError::new(409, err.message().to_string()) }, _ => ServiceError::new(500, err.message().to_string()) } }, DieselError::NotFound => { ServiceError::new(404, "The record was not found".to_string()) }, DieselError::SerializationError(err) => { ServiceError::new(422, err.to_string()) }, err => ServiceError::new(500, format!("Unknown database error: {}", err)), } } } impl From for ServiceError { fn from(error: reqwest::Error) -> ServiceError { ServiceError::new(500, format!("Unknown reqwest error: {}", error)) } } impl From for ServiceError { fn from(error: serde_json::Error) -> ServiceError { ServiceError::new(500, format!("Unknown serde_json error: {}", error)) } } impl From for ServiceError { fn from(error: serenity::Error) -> ServiceError { ServiceError::new(500, format!("Unknown serenity error: {}", error)) } } impl From for ServiceError { fn from(error: argon2::password_hash::Error) -> ServiceError { ServiceError::new(500, format!("Unknown argon2 error: {}", error)) } } impl From for ServiceError { fn from(error: jsonwebtoken::errors::Error) -> ServiceError { ServiceError::new(500, format!("Unknown jsonwebtoken error: {}", error)) } } impl From for ServiceError { fn from(error: redis::RedisError) -> ServiceError { ServiceError::new(500, format!("Unknown redis error: {}", error)) } } impl From for ServiceError { fn from(error: s3::error::S3Error) -> ServiceError { match error { s3::error::S3Error::Http(code, message) => { ServiceError::new(code, message) }, _ => ServiceError::new(500, format!("Unknown s3 error: {}", error)) } } } impl From for ServiceError { fn from(error: s3::creds::error::CredentialsError) -> ServiceError { ServiceError::new(500, format!("Unknown credentials error: {}", error)) } } impl ResponseError for ServiceError { fn error_response(&self) -> HttpResponse { let status_code = match StatusCode::from_u16(self.status) { Ok(status_code) => status_code, Err(_) => StatusCode::INTERNAL_SERVER_ERROR, }; let error_message = match status_code.as_u16() < 500 { true => self.message.clone(), false => "Internal server error".to_string(), }; HttpResponse::build(status_code).json(serde_json::json!({ "status": status_code.as_u16(), "message": error_message })) } }