use super::{Client, State};
use crate::ratelimiting::Ratelimiter;
use hyper::header::HeaderMap;
use std::{
sync::{
atomic::{AtomicBool, AtomicU64, Ordering},
Arc,
},
time::Duration,
};
use twilight_model::{channel::message::allowed_mentions::AllowedMentions, id::ApplicationId};
#[derive(Debug)]
pub struct ClientBuilder {
pub(crate) application_id: AtomicU64,
pub(crate) default_allowed_mentions: Option<AllowedMentions>,
pub(crate) proxy: Option<Box<str>>,
pub(crate) ratelimiter: Option<Ratelimiter>,
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 {
#[cfg(feature = "rustls-native-roots")]
let connector = hyper_rustls::HttpsConnector::with_native_roots();
#[cfg(all(feature = "rustls-webpki-roots", not(feature = "rustls-native-roots")))]
let connector = hyper_rustls::HttpsConnector::with_webpki_roots();
#[cfg(all(
feature = "hyper-tls",
not(feature = "rustls-native-roots"),
not(feature = "rustls-webpki-roots")
))]
let connector = hyper_tls::HttpsConnector::new();
let http = hyper::client::Builder::default().build(connector);
Client {
state: Arc::new(State {
http,
default_headers: self.default_headers,
proxy: self.proxy,
ratelimiter: self.ratelimiter,
timeout: self.timeout,
token_invalid: AtomicBool::new(false),
token: self.token,
application_id: self.application_id,
default_allowed_mentions: self.default_allowed_mentions,
use_http: self.use_http,
}),
}
}
pub fn application_id(self, application_id: ApplicationId) -> Self {
self.application_id
.store(application_id.0, Ordering::Relaxed);
self
}
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: impl Into<String>, use_http: bool) -> Self {
self.proxy.replace(proxy_url.into().into_boxed_str());
self.use_http = use_http;
self
}
pub fn ratelimiter(mut self, ratelimiter: impl Into<Option<Ratelimiter>>) -> Self {
self.ratelimiter = ratelimiter.into();
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 fn token(mut self, token: impl Into<String>) -> Self {
let mut token = token.into();
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 {
Self {
application_id: AtomicU64::default(),
default_allowed_mentions: None,
default_headers: None,
proxy: None,
ratelimiter: Some(Ratelimiter::new()),
timeout: Duration::from_secs(10),
token: None,
use_http: false,
}
}
}