stoat-rs 0.2.5

Stoat API Wrapper
Documentation
use crate::{
    HttpClient, Identifiable, Result,
    builders::{EditMessageBuilder, SendMessageBuilder},
    types::StoatConfig,
};
use async_trait::async_trait;
use stoat_models::v0::{Message, OptionsUnreact};

#[async_trait]
pub trait MessageExt {
    fn reply(&self, http: impl AsRef<HttpClient>, mention: bool) -> SendMessageBuilder;
    fn edit(&self, http: impl AsRef<HttpClient>) -> EditMessageBuilder;
    async fn delete(&self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
    async fn clear_reactions(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
    async fn pin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
    async fn unpin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()>;
    async fn react(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()>;
    async fn unreact(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()>;
    async fn remove_reaction(
        &mut self,
        http: impl AsRef<HttpClient> + Send,
        emoji: &str,
        options: &OptionsUnreact,
    ) -> Result<()>;

    fn jump_link(&self, config: impl AsRef<StoatConfig>) -> String;
}

#[async_trait]
impl MessageExt for Message {
    fn reply(&self, http: impl AsRef<HttpClient>, mention: bool) -> SendMessageBuilder {
        let mut builder = SendMessageBuilder::new(http.as_ref().clone(), self.channel.clone());
        builder.reply(self.id.clone(), mention);
        builder
    }

    fn edit(&self, http: impl AsRef<HttpClient>) -> EditMessageBuilder {
        EditMessageBuilder::new(http.as_ref().clone(), self.channel.clone(), self.id.clone())
    }

    async fn delete(&self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
        http.as_ref().delete_message(&self.channel, &self.id).await
    }

    async fn clear_reactions(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
        http.as_ref()
            .clear_reactions(&self.channel, &self.id)
            .await?;

        self.reactions.clear();

        Ok(())
    }

    async fn pin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
        http.as_ref().pin_message(&self.channel, &self.id).await?;

        self.pinned = Some(true);

        Ok(())
    }

    async fn unpin_message(&mut self, http: impl AsRef<HttpClient> + Send) -> Result<()> {
        http.as_ref().unpin_message(&self.channel, &self.id).await?;

        self.pinned = None;

        Ok(())
    }

    async fn react(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()> {
        http.as_ref()
            .react_message(&self.channel, &self.id, emoji)
            .await?;

        if let Some(user_id) = http.as_ref().user_id.clone() {
            self.reactions
                .entry(emoji.to_string())
                .or_default()
                .insert(user_id);
        };

        Ok(())
    }

    async fn unreact(&mut self, http: impl AsRef<HttpClient> + Send, emoji: &str) -> Result<()> {
        http.as_ref()
            .unreact_message(
                &self.channel,
                &self.id,
                emoji,
                &OptionsUnreact {
                    user_id: None,
                    remove_all: None,
                },
            )
            .await?;

        if let Some(user_id) = &http.as_ref().user_id {
            if let Some(users) = self.reactions.get_mut(emoji) {
                users.remove(user_id);
            };
        };

        Ok(())
    }

    async fn remove_reaction(
        &mut self,
        http: impl AsRef<HttpClient> + Send,
        emoji: &str,
        options: &OptionsUnreact,
    ) -> Result<()> {
        http.as_ref()
            .unreact_message(&self.channel, &self.id, emoji, options)
            .await?;

        if options.remove_all == Some(true) {
            self.reactions.remove(emoji);
        } else if let Some(user_id) = &options.user_id {
            if let Some(users) = self.reactions.get_mut(emoji) {
                users.remove(user_id);
            };
        } else if let Some(user_id) = &http.as_ref().user_id {
            if let Some(users) = self.reactions.get_mut(emoji) {
                users.remove(user_id);
            };
        };

        Ok(())
    }

    fn jump_link(&self, config: impl AsRef<StoatConfig>) -> String {
        format!(
            "{}/channel/{}/{}",
            &config.as_ref().app,
            &self.channel,
            &self.id
        )
    }
}

impl Identifiable for Message {
    fn id(&self) -> &str {
        &self.id
    }
}