use super::{
config::Config as ClusterConfig,
event::Events,
r#impl::{Cluster, ClusterStartError},
scheme::ShardScheme,
};
use crate::{
shard::{LargeThresholdError, ResumeSession, ShardBuilder},
EventTypeFlags,
};
use std::{collections::HashMap, sync::Arc};
use twilight_gateway_queue::{LocalQueue, Queue};
use twilight_http::Client;
use twilight_model::gateway::{
payload::outgoing::{identify::IdentifyProperties, update_presence::UpdatePresencePayload},
Intents,
};
#[derive(Debug)]
pub struct ClusterBuilder(ClusterConfig, ShardBuilder);
impl ClusterBuilder {
pub fn new(token: impl Into<String>, intents: Intents) -> Self {
Self(
ClusterConfig {
shard_scheme: ShardScheme::Auto,
queue: Arc::new(LocalQueue::new()),
resume_sessions: HashMap::new(),
},
ShardBuilder::new(token, intents),
)
}
pub async fn build(mut self) -> Result<(Cluster, Events), ClusterStartError> {
if (self.1).0.gateway_url.is_none() {
let maybe_response = (self.1).0.http_client.gateway().authed().exec().await;
if let Ok(response) = maybe_response {
let gateway_url = response.model().await.ok().map(|info| info.url);
self = self.gateway_url(gateway_url);
}
}
Cluster::new_with_config(self.0, self.1 .0).await
}
#[allow(clippy::missing_const_for_fn)]
pub fn event_types(mut self, event_types: EventTypeFlags) -> Self {
self.1 = self.1.event_types(event_types);
self
}
pub fn gateway_url(mut self, gateway_url: Option<String>) -> Self {
self.1 = self.1.gateway_url(gateway_url);
self
}
pub fn http_client(mut self, http_client: Arc<Client>) -> Self {
self.1 = self.1.http_client(http_client);
self
}
#[allow(clippy::missing_const_for_fn)]
pub fn identify_properties(mut self, identify_properties: IdentifyProperties) -> Self {
self.1 = self.1.identify_properties(identify_properties);
self
}
pub fn large_threshold(mut self, large_threshold: u64) -> Result<Self, LargeThresholdError> {
self.1 = self.1.large_threshold(large_threshold)?;
Ok(self)
}
pub fn presence(mut self, presence: UpdatePresencePayload) -> Self {
self.1 = self.1.presence(presence);
self
}
#[allow(clippy::missing_const_for_fn)]
pub fn shard_scheme(mut self, scheme: ShardScheme) -> Self {
self.0.shard_scheme = scheme;
self
}
pub fn queue(mut self, queue: Arc<dyn Queue>) -> Self {
self.0.queue = Arc::clone(&queue);
self.1 = self.1.queue(queue);
self
}
#[allow(clippy::missing_const_for_fn)]
pub fn resume_sessions(mut self, resume_sessions: HashMap<u64, ResumeSession>) -> Self {
self.0.resume_sessions = resume_sessions;
self
}
}
impl<T: Into<String>> From<(T, Intents)> for ClusterBuilder {
fn from((token, intents): (T, Intents)) -> Self {
Self::new(token, intents)
}
}
#[cfg(test)]
mod tests {
use super::ClusterBuilder;
use crate::Intents;
use static_assertions::assert_impl_all;
use std::fmt::Debug;
assert_impl_all!(ClusterBuilder: Debug, From<(String, Intents)>, Send, Sync);
}