use async_tungstenite::tungstenite::Error as TungsteniteError;
use std::{error::Error, fmt, result::Result as StdResult};
pub type Result<T> = StdResult<T, PandaError>;
#[derive(Debug)]
pub enum PandaError {
AuthenticationFailed,
CantConnectToGateway,
ConnectionClosed,
UnknownPayloadReceived,
UnknownOpcodeSent,
InvalidDecodeSent,
InvalidPayloadFormat(&'static str),
UnexpectedPayloadReceived,
WrongCompression,
HttpNoResponse,
HttpImproperlyFormatted,
HttpUnauthorized,
HttpForbidden,
HttpInvalidParameters,
UnsuccessfulConnectionClose,
InvalidShard,
ShardingRequired,
InvalidApiGatewayVersion,
SerdeError(serde_json::Error),
TungsteniteError(TungsteniteError),
RuntimeError,
}
impl fmt::Display for PandaError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AuthenticationFailed => write!(f, "Authentication failed"),
Self::CantConnectToGateway => write!(f, "'Discord' couldn't connect to gateway"),
Self::ConnectionClosed => write!(f, "Connection closed unexpectedly"),
Self::UnknownPayloadReceived => write!(f, "Unknown payload format received"),
Self::InvalidPayloadFormat(p) => write!(f, "Invalid payload format received: {}", p),
Self::UnexpectedPayloadReceived => write!(f, "Unexpected payload received"),
Self::WrongCompression => write!(f, "Wrong zlib compression"),
Self::HttpNoResponse => write!(f, "Discord HTTP API didn't response"),
Self::HttpImproperlyFormatted => write!(f, "Invalid format of request body"),
Self::HttpUnauthorized => write!(f, "The client token is invalid"),
Self::HttpForbidden => write!(f, "The client did not have permission to the resource"),
Self::HttpInvalidParameters => write!(f, "The request had invalid parameters"),
Self::UnsuccessfulConnectionClose => write!(f, "The gateway couldn't close succesfully the connection"),
Self::InvalidShard => write!(f, "You sent an invalid shard"),
Self::ShardingRequired => write!(f, "The SessionData would have handled too many guilds - you are required to shard your connection in order to connect."),
Self::InvalidApiGatewayVersion => write!(f, "panda needs to update the gateway version"),
Self::SerdeError(e) => write!(f, "Serde Error: {}", e),
Self::TungsteniteError(e) => write!(f, "Tungstenite Error: {}", e),
Self::UnknownOpcodeSent => write!(f, "panda sent an invalid Opcode, please report the bug"),
Self::InvalidDecodeSent => write!(f, "panda sent an invalid payload, please report the bug"),
Self::RuntimeError => write!(f, "runtime error")
}
}
}
impl Error for PandaError {}
impl From<serde_json::Error> for PandaError {
fn from(error: serde_json::Error) -> Self {
if error.is_data() {
return PandaError::InvalidPayloadFormat("");
}
PandaError::SerdeError(error)
}
}
impl From<TungsteniteError> for PandaError {
fn from(error: TungsteniteError) -> Self {
match error {
TungsteniteError::ConnectionClosed => PandaError::ConnectionClosed,
_ => PandaError::TungsteniteError(error),
}
}
}
impl From<isahc::Error> for PandaError {
fn from(_error: isahc::Error) -> Self {
PandaError::HttpNoResponse
}
}
#[cfg(feature = "tokio-runtime")]
impl From<tokio::task::JoinError> for PandaError {
fn from(_error: tokio::task::JoinError) -> Self {
PandaError::RuntimeError
}
}