mod error;
mod events;
mod implementations;
mod internal;
pub mod traits;
use async_trait::async_trait;
use disruption_types::{
channel::ChannelApiType,
channel::MessageApiType,
entities::{EmojiApiType, GuildApiType, GuildMemberApiType, RoleApiType, UserApiType},
gateway::Event,
interactions::InteractionApiType,
payloads::ReadyPayloadData,
};
pub use error::{Error, RestError, Result};
pub use implementations::*;
pub use disruption_gateway::*;
use events::*;
use implementations::channel::Message;
use internal::RestClient;
#[async_trait]
pub trait Handler {
async fn on_message(&mut self, _message: Message) {}
async fn on_guild_create(&mut self, _guild: GuildApiType) {}
async fn on_guild_update(&mut self, _guild: GuildApiType) {}
async fn on_guild_delete(&mut self, _guild_id: String, _unavailable: bool) {}
async fn on_guild_member_add(&mut self, _guild_id: String, _member: GuildMemberApiType) {}
async fn on_guild_member_remove(&mut self, _guild_id: String, _user: UserApiType) {}
async fn on_guild_member_update(&mut self, _guild_id: String, _member: GuildMemberApiType) {}
async fn on_guild_role_create(&mut self, _guild_id: String, _role: RoleApiType) {}
async fn on_guild_role_update(&mut self, _guild_id: String, _role: RoleApiType) {}
async fn on_guild_role_delete(&mut self, _guild_id: String, _role_id: String) {}
async fn on_interaction(&mut self, _interaction: InteractionApiType) {}
async fn on_message_update(&mut self, _message: MessageApiType) {}
async fn on_message_delete(
&mut self,
_message_id: String,
_channel_id: String,
_guild_id: Option<String>,
) {
}
async fn on_message_reaction_add(
&mut self,
_user_id: String,
_channel_id: String,
_message_id: String,
_guild_id: Option<String>,
_emoji: EmojiApiType,
) {
}
async fn on_message_reaction_remove(
&mut self,
_user_id: String,
_channel_id: String,
_message_id: String,
_guild_id: Option<String>,
_emoji: EmojiApiType,
) {
}
async fn on_channel_create(&mut self, _channel: ChannelApiType) {}
async fn on_channel_update(&mut self, _channel: ChannelApiType) {}
}
pub struct Client<'a> {
token: String,
gateway: Option<Gateway>,
handler: &'a mut (dyn Handler + Send),
rest_client: Option<RestClient>,
}
impl<'a> Client<'a> {
pub fn new(handler: &'a mut (dyn Handler + Send), token: impl ToString) -> Self {
Self {
token: token.to_string(),
handler,
gateway: None,
rest_client: None,
}
}
pub async fn connect(&mut self) -> Result<()> {
self.gateway = Some(Gateway::connect(&self.token).await?);
Ok(())
}
pub async fn start(&mut self) -> Result<()> {
let Some(gateway) = &self.gateway else {
return Err(Error::Internal(
"Gateway not connected. Call connect() before start()".to_string(),
));
};
let receiver = gateway.receiver().await.clone();
loop {
let payload = receiver.recv().await?;
let Some(Ok(event)) = payload.t.map(|event| Event::try_from(event.as_str())) else {
continue;
};
match event {
Event::READY => {
let Some(d) = payload.d else {
continue;
};
let data: ReadyPayloadData = serde_json::from_value(d)?;
self.handle_ready(data).await;
}
Event::GUILD_CREATE => {
let Some(d) = payload.d else {
continue;
};
let guild: GuildApiType = serde_json::from_value(d)?;
self.handler.on_guild_create(guild).await;
}
Event::GUILD_UPDATE => {
let Some(d) = payload.d else {
continue;
};
let guild: GuildApiType = serde_json::from_value(d)?;
self.handler.on_guild_update(guild).await;
}
Event::GUILD_DELETE => {
let Some(d) = payload.d else {
continue;
};
let event: GuildDeleteEvent = serde_json::from_value(d)?;
self.handler
.on_guild_delete(event.id, event.unavailable)
.await;
}
Event::GUILD_MEMBER_ADD => {
let Some(d) = payload.d else {
continue;
};
let event: GuildMemberAddEvent = serde_json::from_value(d)?;
self.handler
.on_guild_member_add(event.guild_id, event.member)
.await;
}
Event::GUILD_MEMBER_REMOVE => {
let Some(d) = payload.d else {
continue;
};
let event: GuildMemberRemoveEvent = serde_json::from_value(d)?;
self.handler
.on_guild_member_remove(event.guild_id, event.user)
.await;
}
Event::GUILD_MEMBER_UPDATE => {
let Some(d) = payload.d else {
continue;
};
let event: GuildMemberUpdateEvent = serde_json::from_value(d)?;
self.handler
.on_guild_member_update(event.guild_id, event.member)
.await;
}
Event::GUILD_ROLE_CREATE => {
let Some(d) = payload.d else {
continue;
};
let event: GuildRoleCreateEvent = serde_json::from_value(d)?;
self.handler
.on_guild_role_create(event.guild_id, event.role)
.await;
}
Event::GUILD_ROLE_UPDATE => {
let Some(d) = payload.d else {
continue;
};
let event: GuildRoleUpdateEvent = serde_json::from_value(d)?;
self.handler
.on_guild_role_update(event.guild_id, event.role)
.await;
}
Event::GUILD_ROLE_DELETE => {
let Some(d) = payload.d else {
continue;
};
let event: GuildRoleDeleteEvent = serde_json::from_value(d)?;
self.handler
.on_guild_role_delete(event.guild_id, event.role_id)
.await;
}
Event::INTERACTION_CREATE => {
let Some(d) = payload.d else {
continue;
};
let interaction: InteractionApiType = serde_json::from_value(d)?;
self.handler.on_interaction(interaction).await;
}
Event::MESSAGE_CREATE => {
let (Some(d), Some(rest_client)) = (payload.d, &self.rest_client) else {
continue;
};
let message: MessageApiType = serde_json::from_value(d)?;
let message = Message::new(rest_client.clone(), message).await;
self.handler.on_message(message).await;
}
Event::MESSAGE_UPDATE => {
let Some(d) = payload.d else {
continue;
};
let message: MessageApiType = serde_json::from_value(d)?;
self.handler.on_message_update(message).await;
}
Event::MESSAGE_DELETE => {
let Some(d) = payload.d else {
continue;
};
let event: MessageDeleteEvent = serde_json::from_value(d)?;
self.handler
.on_message_delete(event.id, event.channel_id, event.guild_id)
.await;
}
Event::MESSAGE_REACTION_ADD => {
let Some(d) = payload.d else {
continue;
};
let event: MessageReactionAddEvent = serde_json::from_value(d)?;
self.handler
.on_message_reaction_add(
event.user_id,
event.channel_id,
event.message_id,
event.guild_id,
event.emoji,
)
.await;
}
Event::MESSAGE_REACTION_REMOVE => {
let Some(d) = payload.d else {
continue;
};
let event: MessageReactionRemoveEvent = serde_json::from_value(d)?;
self.handler
.on_message_reaction_remove(
event.user_id,
event.channel_id,
event.message_id,
event.guild_id,
event.emoji,
)
.await;
}
Event::CHANNEL_CREATE => {
let Some(d) = payload.d else {
continue;
};
let channel: ChannelApiType = serde_json::from_value(d)?;
self.handler.on_channel_create(channel).await;
}
Event::CHANNEL_UPDATE => {
let Some(d) = payload.d else {
continue;
};
let channel: ChannelApiType = serde_json::from_value(d)?;
self.handler.on_channel_update(channel).await;
}
_ => {
continue;
}
}
}
}
async fn handle_ready(&mut self, data: ReadyPayloadData) {
if let Some(gateway) = &self.gateway {
gateway.set_session_id(data.session_id.clone()).await;
}
self.rest_client = Some(RestClient::new(&self.token, data.v));
}
}