1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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
}
}