This repository has been archived by the owner on Dec 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.rs
128 lines (112 loc) · 4.08 KB
/
errors.rs
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
use std::{fmt, result};
use chrono::{NaiveDateTime, Local, DateTime, Utc};
/// Represents an error that occurred while using the library.
#[derive(Debug)]
pub enum Error {
Gateway(String),
Http(String),
InvalidToken(TokenContext),
NoPermission(TokenContext),
RateLimited(RlContext),
Json(JsonContext),
Other(String),
}
/// Provides context when an error related to the
/// token is emitted.
#[derive(Debug)]
pub struct TokenContext {
/// The endpoint on which this error occurred
pub endpoint: String,
/// The token used to send the request
pub token: String,
}
/// Context for errors emitted when the bot is
/// being rate limited.
#[derive(Debug)]
pub struct RlContext {
/// The endpoint for which the rate-limit has been hit
pub endpoint: String,
/// Date when the rate-limit will be removed
pub until: NaiveDateTime,
/// Whether this error was generated by the library preventing
/// you from getting rate-limited or if it was sent by discord
/// because of a real rate-limit
pub prevented: bool,
}
/// Errors spawned in the [json](automate::encode::json) module.
#[derive(Debug)]
pub struct JsonContext {
pub message: String,
#[cfg(feature = "backtrace")]
pub backtrace: String,
}
impl Error {
pub fn new<S>(msg: S) -> Error where S: ToString {
Error::Other(msg.to_string())
}
pub fn err<S, T>(msg: S) -> Result<T, Error> where S: ToString {
Err(Error::Other(msg.to_string()))
}
pub(crate) fn gateway<S, T>(msg: S) -> Result<T, Error> where S: ToString {
Err(Error::Gateway(msg.to_string()))
}
pub(crate) fn http<S, T>(msg: S) -> Result<T, Error> where S: ToString {
Err(Error::Http(msg.to_string()))
}
pub(crate) fn invalid_token<T>(endpoint: &str, token: &str) -> Result<T, Error> {
Err(Error::InvalidToken(TokenContext {
endpoint: endpoint.to_owned(),
token: token.to_owned(),
}))
}
pub(crate) fn no_permission<T>(endpoint: &str, token: &str) -> Result<T, Error> {
Err(Error::NoPermission(TokenContext {
endpoint: endpoint.to_owned(),
token: token.to_owned(),
}))
}
pub(crate) fn rate_limited<T>(endpoint: &str, until: NaiveDateTime, prevented: bool) -> Result<T, Error> {
Err(Error::RateLimited(RlContext {
endpoint: endpoint.to_owned(),
until,
prevented,
}))
}
pub(crate) fn json<S, T>(message: S) -> Result<T, Error> where S: ToString {
Err(Error::Json(JsonContext {
message: message.to_string(),
#[cfg(feature = "backtrace")]
backtrace: format!("{:#?}", backtrace::Backtrace::new()),
}))
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
match self {
Error::Gateway(s) => write!(f, "{}", s),
Error::Http(s) => write!(f, "{}", s),
Error::InvalidToken(ctx) => write!(f, "Invalid token `{}`", ctx.token),
Error::NoPermission(ctx) => write!(f, "Token `{}` does not have the permission to call `{}`", ctx.token, ctx.endpoint),
Error::RateLimited(ctx) => {
let datetime: DateTime<Utc> = DateTime::from_utc(ctx.until, Utc);
let local = datetime.with_timezone(&Local);
if ctx.prevented {
write!(f, "Cancelled to avoid reaching rate limit for endpoint `̀{}` wait until {}", ctx.endpoint, local)
} else {
write!(f, "Reached rate limit for endpoint `̀{}` until {}", ctx.endpoint, local)
}
},
Error::Json(s) => {
#[cfg(feature = "backtrace")] write!(f, "{}\n{}", s.message, s.backtrace)?;
#[cfg(not(feature = "backtrace"))] write!(f, "{}", s.message)?;
Ok(())
},
Error::Other(s) => write!(f, "{}", s),
}
}
}
impl<T: std::error::Error> From<T> for Error {
fn from(err: T) -> Self {
Error::new(err.to_string())
}
}