refluxer 0.1.0

Rust API wrapper for Fluxer
Documentation
use serde::{Deserialize, Serialize};

use crate::error::HttpError;
use crate::http::client::HttpClient;
use crate::http::routing::Route;
use crate::model::id::{ChannelId, GuildId};
use crate::model::message::{Embed, Message};
use crate::model::user::User;

#[derive(Debug, Clone, Deserialize)]
pub struct Webhook {
    pub id: String,
    #[serde(default)]
    pub name: Option<String>,
    #[serde(default)]
    pub avatar: Option<String>,
    #[serde(default)]
    pub channel_id: Option<ChannelId>,
    #[serde(default)]
    pub guild_id: Option<GuildId>,
    #[serde(default)]
    pub user: Option<User>,
    #[serde(default)]
    pub token: Option<String>,
}

#[derive(Debug, Default, Serialize)]
pub struct CreateWebhook {
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar: Option<String>,
}

impl CreateWebhook {
    pub fn new(name: impl Into<String>) -> Self {
        Self {
            name: name.into(),
            avatar: None,
        }
    }
}

#[derive(Debug, Default, Serialize)]
pub struct ModifyWebhook {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub channel_id: Option<ChannelId>,
}

impl ModifyWebhook {
    pub fn new() -> Self {
        Self::default()
    }
    pub fn name(mut self, name: impl Into<String>) -> Self {
        self.name = Some(name.into());
        self
    }
    pub fn channel_id(mut self, id: ChannelId) -> Self {
        self.channel_id = Some(id);
        self
    }
}

#[derive(Debug, Default, Serialize)]
pub struct ExecuteWebhook {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub content: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub username: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub avatar_url: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tts: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub embeds: Option<Vec<Embed>>,
}

impl ExecuteWebhook {
    pub fn new() -> Self {
        Self::default()
    }
    pub fn content(mut self, content: impl Into<String>) -> Self {
        self.content = Some(content.into());
        self
    }
    pub fn username(mut self, name: impl Into<String>) -> Self {
        self.username = Some(name.into());
        self
    }
    pub fn avatar_url(mut self, url: impl Into<String>) -> Self {
        self.avatar_url = Some(url.into());
        self
    }
    pub fn tts(mut self, tts: bool) -> Self {
        self.tts = Some(tts);
        self
    }

    pub fn embed(
        mut self,
        build: impl FnOnce(
            crate::http::endpoints::messages::EmbedBuilder,
        ) -> crate::http::endpoints::messages::EmbedBuilder,
    ) -> Self {
        let embed = build(crate::http::endpoints::messages::EmbedBuilder::new()).build();
        self.embeds.get_or_insert_with(Vec::new).push(embed);
        self
    }
}

impl HttpClient {
    pub async fn create_webhook(
        &self,
        channel_id: ChannelId,
        params: &CreateWebhook,
    ) -> Result<Webhook, HttpError> {
        self.request(Route::CreateWebhook { channel_id }, Some(params))
            .await
    }

    pub async fn get_channel_webhooks(
        &self,
        channel_id: ChannelId,
    ) -> Result<Vec<Webhook>, HttpError> {
        self.request_no_body(Route::GetChannelWebhooks { channel_id })
            .await
    }

    pub async fn get_guild_webhooks(&self, guild_id: GuildId) -> Result<Vec<Webhook>, HttpError> {
        self.request_no_body(Route::GetGuildWebhooks { guild_id })
            .await
    }

    pub async fn get_webhook(&self, webhook_id: &str) -> Result<Webhook, HttpError> {
        self.request_no_body(Route::GetWebhook {
            webhook_id: webhook_id.to_string(),
        })
        .await
    }

    pub async fn modify_webhook(
        &self,
        webhook_id: &str,
        params: &ModifyWebhook,
    ) -> Result<Webhook, HttpError> {
        self.request(
            Route::ModifyWebhook {
                webhook_id: webhook_id.to_string(),
            },
            Some(params),
        )
        .await
    }

    pub async fn delete_webhook(&self, webhook_id: &str) -> Result<(), HttpError> {
        self.request_empty(
            Route::DeleteWebhook {
                webhook_id: webhook_id.to_string(),
            },
            None::<&()>,
        )
        .await
    }

    pub async fn execute_webhook(
        &self,
        webhook_id: &str,
        webhook_token: &str,
        params: &ExecuteWebhook,
    ) -> Result<Option<Message>, HttpError> {
        self.request(
            Route::ExecuteWebhook {
                webhook_id: webhook_id.to_string(),
                webhook_token: webhook_token.to_string(),
            },
            Some(params),
        )
        .await
    }

    /// Fetch a webhook using its token instead of a bot/user credential.
    pub async fn get_webhook_with_token(
        &self,
        webhook_id: &str,
        webhook_token: &str,
    ) -> Result<Webhook, HttpError> {
        self.request_no_body(Route::GetWebhookWithToken {
            webhook_id: webhook_id.to_string(),
            webhook_token: webhook_token.to_string(),
        })
        .await
    }

    pub async fn update_webhook_with_token(
        &self,
        webhook_id: &str,
        webhook_token: &str,
        params: &ModifyWebhook,
    ) -> Result<Webhook, HttpError> {
        self.request(
            Route::UpdateWebhookWithToken {
                webhook_id: webhook_id.to_string(),
                webhook_token: webhook_token.to_string(),
            },
            Some(params),
        )
        .await
    }

    pub async fn delete_webhook_with_token(
        &self,
        webhook_id: &str,
        webhook_token: &str,
    ) -> Result<(), HttpError> {
        self.request_empty(
            Route::DeleteWebhookWithToken {
                webhook_id: webhook_id.to_string(),
                webhook_token: webhook_token.to_string(),
            },
            None::<&()>,
        )
        .await
    }

    /// Execute a webhook with a GitHub-formatted payload. The server parses
    /// the GitHub event format and emits a Fluxer-rendered message.
    pub async fn execute_github_webhook(
        &self,
        webhook_id: &str,
        webhook_token: &str,
        body: &impl Serialize,
    ) -> Result<(), HttpError> {
        self.request_empty(
            Route::ExecuteGithubWebhook {
                webhook_id: webhook_id.to_string(),
                webhook_token: webhook_token.to_string(),
            },
            Some(body),
        )
        .await
    }

    pub async fn execute_sentry_webhook(
        &self,
        webhook_id: &str,
        webhook_token: &str,
        body: &impl Serialize,
    ) -> Result<(), HttpError> {
        self.request_empty(
            Route::ExecuteSentryWebhook {
                webhook_id: webhook_id.to_string(),
                webhook_token: webhook_token.to_string(),
            },
            Some(body),
        )
        .await
    }

    pub async fn execute_slack_webhook(
        &self,
        webhook_id: &str,
        webhook_token: &str,
        body: &impl Serialize,
    ) -> Result<(), HttpError> {
        self.request_empty(
            Route::ExecuteSlackWebhook {
                webhook_id: webhook_id.to_string(),
                webhook_token: webhook_token.to_string(),
            },
            Some(body),
        )
        .await
    }
}