twilight_http/client/
builder.rs1#[cfg(not(target_os = "wasi"))]
2use super::Token;
3use crate::Client;
4#[cfg(not(target_os = "wasi"))]
5use crate::client::connector;
6use http::header::HeaderMap;
7#[cfg(not(target_os = "wasi"))]
8use hyper_util::rt::TokioExecutor;
9use std::{
10 sync::{Arc, atomic::AtomicBool},
11 time::Duration,
12};
13#[cfg(not(target_os = "wasi"))]
14use twilight_http_ratelimiting::RateLimiter;
15use twilight_model::channel::message::AllowedMentions;
16
17#[derive(Debug)]
19#[must_use = "has no effect if not built into a Client"]
20#[cfg(not(target_os = "wasi"))]
21pub struct ClientBuilder {
22 pub(crate) default_allowed_mentions: Option<AllowedMentions>,
23 pub(crate) proxy: Option<Box<str>>,
24 ratelimiter: Option<RateLimiter>,
25 remember_invalid_token: bool,
26 pub(crate) default_headers: Option<HeaderMap>,
27 pub(crate) timeout: Duration,
28 pub(super) token: Option<Token>,
29 pub(crate) use_http: bool,
30}
31
32#[derive(Debug)]
34#[must_use = "has no effect if not built into a Client"]
35#[cfg(target_os = "wasi")]
36pub struct ClientBuilder {
37 pub(crate) default_allowed_mentions: Option<AllowedMentions>,
38}
39
40impl ClientBuilder {
41 pub fn new() -> Self {
43 Self::default()
44 }
45
46 #[cfg(not(target_os = "wasi"))]
48 pub fn build(self) -> Client {
49 let connector = connector::create();
50
51 let http =
52 hyper_util::client::legacy::Client::builder(TokioExecutor::new()).build(connector);
53
54 let token_invalidated = if self.remember_invalid_token {
55 Some(Arc::new(AtomicBool::new(false)))
56 } else {
57 None
58 };
59
60 Client {
61 http,
62 default_headers: self.default_headers,
63 proxy: self.proxy,
64 ratelimiter: self.ratelimiter,
65 timeout: self.timeout,
66 token_invalidated,
67 token: self.token,
68 default_allowed_mentions: self.default_allowed_mentions,
69 use_http: self.use_http,
70 }
71 }
72
73 #[cfg(target_os = "wasi")]
75 pub fn build(self) -> Client {
76 Client {
77 default_allowed_mentions: self.default_allowed_mentions,
78 }
79 }
80
81 pub fn default_allowed_mentions(mut self, allowed_mentions: AllowedMentions) -> Self {
84 self.default_allowed_mentions.replace(allowed_mentions);
85
86 self
87 }
88
89 #[cfg(not(target_os = "wasi"))]
110 pub fn proxy(mut self, proxy_url: String, use_http: bool) -> Self {
111 self.proxy.replace(proxy_url.into_boxed_str());
112 self.use_http = use_http;
113
114 self
115 }
116
117 #[allow(clippy::missing_const_for_fn)]
125 #[cfg(not(target_os = "wasi"))]
126 pub fn ratelimiter(mut self, ratelimiter: Option<RateLimiter>) -> Self {
127 self.ratelimiter = ratelimiter;
128
129 self
130 }
131
132 #[cfg(not(target_os = "wasi"))]
136 pub const fn timeout(mut self, duration: Duration) -> Self {
137 self.timeout = duration;
138
139 self
140 }
141
142 #[cfg(not(target_os = "wasi"))]
144 pub fn default_headers(mut self, headers: HeaderMap) -> Self {
145 self.default_headers.replace(headers);
146
147 self
148 }
149
150 #[cfg(not(target_os = "wasi"))]
158 pub const fn remember_invalid_token(mut self, remember: bool) -> Self {
159 self.remember_invalid_token = remember;
160
161 self
162 }
163
164 #[cfg(not(target_os = "wasi"))]
166 pub fn token(mut self, mut token: String) -> Self {
167 let is_bot = token.starts_with("Bot ");
168 let is_bearer = token.starts_with("Bearer ");
169
170 if !is_bot && !is_bearer {
173 token.insert_str(0, "Bot ");
174 }
175
176 self.token.replace(Token::new(token.into_boxed_str()));
177
178 self
179 }
180}
181
182impl Default for ClientBuilder {
183 #[cfg(not(target_os = "wasi"))]
184 fn default() -> Self {
185 Self {
186 default_allowed_mentions: None,
187 default_headers: None,
188 proxy: None,
189 ratelimiter: (!cfg!(test)).then(RateLimiter::default),
190 remember_invalid_token: true,
191 timeout: Duration::from_secs(10),
192 token: None,
193 use_http: false,
194 }
195 }
196
197 #[cfg(target_os = "wasi")]
198 fn default() -> Self {
199 Self {
200 default_allowed_mentions: None,
201 }
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use super::ClientBuilder;
208 use static_assertions::assert_impl_all;
209 use std::fmt::Debug;
210
211 assert_impl_all!(ClientBuilder: Debug, Default, Send, Sync);
212
213 #[test]
214 fn client_debug() {
215 assert!(
216 format!("{:?}", ClientBuilder::new().token("Bot foo".to_owned()))
217 .contains("token: Some(<redacted>)")
218 );
219 assert!(format!("{:?}", ClientBuilder::new()).contains("token: None"));
220 }
221}