use crate::{client::connector, Client};
use hyper::header::HeaderMap;
use std::{
sync::{atomic::AtomicBool, Arc},
time::Duration,
};
use twilight_http_ratelimiting::{InMemoryRatelimiter, Ratelimiter};
use twilight_model::channel::message::AllowedMentions;
#[derive(Debug)]
#[must_use = "has no effect if not built into a Client"]
pub struct ClientBuilder {
pub(crate) default_allowed_mentions: Option<AllowedMentions>,
pub(crate) proxy: Option<Box<str>>,
pub(crate) ratelimiter: Option<Box<dyn Ratelimiter>>,
remember_invalid_token: bool,
pub(crate) default_headers: Option<HeaderMap>,
pub(crate) timeout: Duration,
pub(crate) token: Option<Box<str>>,
pub(crate) use_http: bool,
}
impl ClientBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn build(self) -> Client {
let connector = connector::create();
let http = hyper::Client::builder().build(connector);
let token_invalidated = if self.remember_invalid_token {
Some(Arc::new(AtomicBool::new(false)))
} else {
None
};
Client {
http,
default_headers: self.default_headers,
proxy: self.proxy,
ratelimiter: self.ratelimiter,
timeout: self.timeout,
token_invalidated,
token: self.token,
default_allowed_mentions: self.default_allowed_mentions,
use_http: self.use_http,
}
}
pub fn default_allowed_mentions(mut self, allowed_mentions: AllowedMentions) -> Self {
self.default_allowed_mentions.replace(allowed_mentions);
self
}
pub fn proxy(mut self, proxy_url: String, use_http: bool) -> Self {
self.proxy.replace(proxy_url.into_boxed_str());
self.use_http = use_http;
self
}
#[allow(clippy::missing_const_for_fn)]
pub fn ratelimiter(mut self, ratelimiter: Option<Box<dyn Ratelimiter>>) -> Self {
self.ratelimiter = ratelimiter;
self
}
pub const fn timeout(mut self, duration: Duration) -> Self {
self.timeout = duration;
self
}
pub fn default_headers(mut self, headers: HeaderMap) -> Self {
self.default_headers.replace(headers);
self
}
pub const fn remember_invalid_token(mut self, remember: bool) -> Self {
self.remember_invalid_token = remember;
self
}
pub fn token(mut self, mut token: String) -> Self {
let is_bot = token.starts_with("Bot ");
let is_bearer = token.starts_with("Bearer ");
if !is_bot && !is_bearer {
token.insert_str(0, "Bot ");
}
self.token.replace(token.into_boxed_str());
self
}
}
impl Default for ClientBuilder {
fn default() -> Self {
#[allow(clippy::box_default)]
Self {
default_allowed_mentions: None,
default_headers: None,
proxy: None,
ratelimiter: Some(Box::new(InMemoryRatelimiter::default())),
remember_invalid_token: true,
timeout: Duration::from_secs(10),
token: None,
use_http: false,
}
}
}
#[cfg(test)]
mod tests {
use super::ClientBuilder;
use static_assertions::assert_impl_all;
use std::fmt::Debug;
assert_impl_all!(ClientBuilder: Debug, Default, Send, Sync);
}