use std::error::Error;
use std::sync::Arc;
use twilight_model::id::Id;
use twilight_model::id::marker::ChannelMarker;
use crate::aliases::DiscordClient;
use crate::cache::Cache;
use crate::commands::CommandNode;
use crate::commands::prefixed::prefixes::Prefixes;
use crate::errors::ErrorHandlerWithoutType;
use crate::state::StateBound;
use crate::wrappers::TwilightError;
use crate::wrappers::actions::message_create::MessageCreate;
use crate::wrappers::types::users::User;
#[derive(Clone)]
pub struct Handle<State>
where
State: StateBound,
{
pub(crate) client: DiscordClient,
pub commands: Arc<Vec<CommandNode<State>>>,
pub(crate) prefixes: Option<Arc<dyn Prefixes<State>>>,
pub(crate) on_errors: Vec<Arc<dyn ErrorHandlerWithoutType<State>>>,
pub cache: Option<Arc<dyn Cache>>,
}
#[derive(Debug, thiserror::Error)]
pub enum HandleError {
#[error("An error occurred while calling the Discord API: {0}")]
Twilight(#[from] TwilightError),
#[error("The cache backend returned an error: {0}")]
Cache(#[from] Box<dyn Error + Send + Sync>),
}
impl<State> Handle<State>
where
State: StateBound,
{
pub fn send(&self, channel_id: Id<ChannelMarker>, content: impl Into<String>) -> MessageCreate {
MessageCreate::new(self.client.clone(), channel_id, content)
}
pub async fn fetch_user(&self, user_id: u64) -> Result<User, HandleError> {
let user: User = self
.client
.user(Id::new(user_id))
.await
.map_err(TwilightError::Twilight)?
.model()
.await
.map_err(TwilightError::TwilightParsing)?
.into();
if let Some(cache) = &self.cache {
cache.set_user(user.clone()).await?;
}
Ok(user)
}
pub async fn get_or_fetch_user(&self, user_id: u64) -> Result<User, HandleError> {
if let Some(cache) = &self.cache {
let user = cache.get_user_by_id(user_id).await?;
if let Some(user) = user {
return Ok(user);
}
}
self.fetch_user(user_id).await
}
}