Skip to main content

lavalink_rs/
error.rs

1use crate::model::track::TrackError;
2
3use std::error::Error;
4use std::fmt::{Display, Formatter, Result};
5use std::io::Error as IoError;
6
7use ::http::header::InvalidHeaderValue;
8use ::http::method::InvalidMethod;
9use ::http::uri::InvalidUri;
10use ::http::Error as HttpError;
11use hyper::Error as HyperError;
12use hyper_util::client::legacy::Error as HyperClientError;
13use oneshot::RecvError;
14use tokio::sync::mpsc::error::SendError;
15#[cfg(feature = "_tungstenite")]
16use tokio_tungstenite::tungstenite::error::Error as TungsteniteError;
17#[cfg(feature = "_websockets")]
18use tokio_websockets::error::Error as WebsocketsError;
19
20#[cfg(feature = "python")]
21use pyo3::exceptions::PyException;
22#[cfg(feature = "python")]
23use pyo3::PyErr;
24
25pub type LavalinkResult<T> = std::result::Result<T, LavalinkError>;
26
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28/// Response sent by REST requests when there's an error.
29pub struct ResponseError {
30    pub status: u16,
31    pub timestamp: u64,
32    pub error: String,
33    pub message: String,
34    pub path: String,
35    pub trace: Option<String>,
36}
37
38#[derive(Serialize, Deserialize)]
39#[serde(untagged)]
40pub(crate) enum RequestResult<T> {
41    Ok(T),
42    Err(ResponseError),
43}
44
45impl<T> RequestResult<T> {
46    pub fn to_result(self) -> std::result::Result<T, ResponseError> {
47        match self {
48            Self::Ok(x) => Ok(x),
49            Self::Err(x) => Err(x),
50        }
51    }
52}
53
54#[derive(Debug)]
55#[non_exhaustive]
56/// Every error the library can return.
57pub enum LavalinkError {
58    IoError(IoError),
59    #[cfg(feature = "_tungstenite")]
60    WebsocketError(TungsteniteError),
61    #[cfg(feature = "_websockets")]
62    WebsocketError(WebsocketsError),
63    InvalidHeaderValue(InvalidHeaderValue),
64    HyperError(HyperError),
65    HyperClientError(HyperClientError),
66    HttpError(HttpError),
67    InvalidUri(InvalidUri),
68    InvalidMethod(InvalidMethod),
69    ChannelSendError,
70    ChannelReceiveError(RecvError),
71    SerdeErrorQs(serde_qs::Error),
72    SerdeErrorJson(serde_json::Error),
73
74    ResponseError(ResponseError),
75    NoSessionPresent,
76    TrackError(TrackError),
77    InvalidDataType,
78    Timeout,
79}
80
81impl Error for LavalinkError {}
82
83impl Display for LavalinkError {
84    fn fmt(&self, f: &mut Formatter) -> Result {
85        match self {
86            LavalinkError::WebsocketError(why) => {
87                write!(
88                    f,
89                    "Error while sending payload to the websocket => {:?}",
90                    why
91                )
92            }
93            LavalinkError::IoError(why) => {
94                write!(f, "I/O Error => {:?}", why)
95            }
96            LavalinkError::InvalidHeaderValue(why) => {
97                write!(f, "Invalid Header Value => {:?}", why)
98            }
99            LavalinkError::HttpError(why) => {
100                write!(f, "HttpError => {:?}", why)
101            }
102            LavalinkError::InvalidUri(why) => {
103                write!(f, "Invalid URI => {:?}", why)
104            }
105            LavalinkError::InvalidMethod(why) => {
106                write!(f, "Invalid HTTP request method => {:?}", why)
107            }
108            LavalinkError::HyperError(why) => {
109                write!(f, "Hyper Error => {:?}", why)
110            }
111            LavalinkError::HyperClientError(why) => {
112                write!(f, "Hyper Client Error => {:?}", why)
113            }
114            LavalinkError::ChannelSendError => {
115                write!(f, "The channel receiver is closed.")
116            }
117            LavalinkError::ChannelReceiveError(why) => {
118                write!(f, "Error receiving from player context: {:?}", why)
119            }
120            LavalinkError::SerdeErrorQs(why) => {
121                write!(f, "Error serializing or desesrializing qs => {:?}", why)
122            }
123            LavalinkError::SerdeErrorJson(why) => {
124                write!(f, "Error serializing or desesrializing json => {:?}", why)
125            }
126
127            LavalinkError::NoSessionPresent => {
128                write!(
129                    f,
130                    "Please, call client.create_session() for this method to work correctly."
131                )
132            }
133            LavalinkError::ResponseError(why) => {
134                write!(f, "Error from lavalink server: {:?}", why)
135            }
136            LavalinkError::TrackError(why) => {
137                write!(f, "Error loading tracks: {:?}", why)
138            }
139            LavalinkError::InvalidDataType => {
140                write!(f, "The value type provided does not match the data type id, or no data was ever provided.")
141            }
142            LavalinkError::Timeout => {
143                write!(f, "Timeout reached while waiting for response.")
144            }
145        }
146    }
147}
148
149impl From<IoError> for LavalinkError {
150    fn from(err: IoError) -> LavalinkError {
151        LavalinkError::IoError(err)
152    }
153}
154
155impl From<ResponseError> for LavalinkError {
156    fn from(err: ResponseError) -> LavalinkError {
157        LavalinkError::ResponseError(err)
158    }
159}
160
161impl From<TrackError> for LavalinkError {
162    fn from(err: TrackError) -> LavalinkError {
163        LavalinkError::TrackError(err)
164    }
165}
166
167#[cfg(feature = "_tungstenite")]
168impl From<TungsteniteError> for LavalinkError {
169    fn from(err: TungsteniteError) -> LavalinkError {
170        LavalinkError::WebsocketError(err)
171    }
172}
173
174#[cfg(feature = "_websockets")]
175impl From<WebsocketsError> for LavalinkError {
176    fn from(err: WebsocketsError) -> LavalinkError {
177        LavalinkError::WebsocketError(err)
178    }
179}
180
181impl From<InvalidHeaderValue> for LavalinkError {
182    fn from(err: InvalidHeaderValue) -> LavalinkError {
183        LavalinkError::InvalidHeaderValue(err)
184    }
185}
186
187impl From<HttpError> for LavalinkError {
188    fn from(err: HttpError) -> LavalinkError {
189        LavalinkError::HttpError(err)
190    }
191}
192
193impl From<InvalidUri> for LavalinkError {
194    fn from(err: InvalidUri) -> LavalinkError {
195        LavalinkError::InvalidUri(err)
196    }
197}
198
199impl From<InvalidMethod> for LavalinkError {
200    fn from(err: InvalidMethod) -> LavalinkError {
201        LavalinkError::InvalidMethod(err)
202    }
203}
204
205impl From<HyperError> for LavalinkError {
206    fn from(err: HyperError) -> LavalinkError {
207        LavalinkError::HyperError(err)
208    }
209}
210
211impl From<HyperClientError> for LavalinkError {
212    fn from(err: HyperClientError) -> LavalinkError {
213        LavalinkError::HyperClientError(err)
214    }
215}
216
217impl<T> From<SendError<T>> for LavalinkError {
218    fn from(_: SendError<T>) -> LavalinkError {
219        LavalinkError::ChannelSendError
220    }
221}
222
223impl From<RecvError> for LavalinkError {
224    fn from(err: RecvError) -> LavalinkError {
225        LavalinkError::ChannelReceiveError(err)
226    }
227}
228
229impl From<serde_qs::Error> for LavalinkError {
230    fn from(err: serde_qs::Error) -> Self {
231        LavalinkError::SerdeErrorQs(err)
232    }
233}
234
235impl From<serde_json::Error> for LavalinkError {
236    fn from(err: serde_json::Error) -> Self {
237        LavalinkError::SerdeErrorJson(err)
238    }
239}
240
241#[cfg(feature = "python")]
242impl From<LavalinkError> for PyErr {
243    fn from(err: LavalinkError) -> PyErr {
244        error!("{}", err);
245        PyErr::new::<PyException, _>(format!("{:?}", err))
246    }
247}