add github webhook support

This commit is contained in:
Zomatree
2022-11-27 06:52:44 +00:00
parent 5cb2320760
commit c826d8cf07
3 changed files with 78 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ mod webhook_delete;
mod webhook_edit;
mod webhook_execute;
mod webhook_fetch;
mod webhook_execute_github;
pub fn routes() -> (Vec<Route>, OpenApi) {
openapi_get_routes_spec![
@@ -12,5 +13,6 @@ pub fn routes() -> (Vec<Route>, OpenApi) {
webhook_edit::req,
webhook_execute::req,
webhook_fetch::req,
webhook_execute_github::req
]
}

View File

@@ -0,0 +1,75 @@
use revolt_quark::{Db, Ref, Result, Error, models::{Webhook, Message, message::SendableEmbed}, types::push::MessageAuthor};
use rocket::{serde::{json::Json, DeserializeOwned}, Request, request::FromRequest, http::Status};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use ulid::Ulid;
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Event {
Star {
action: String,
sender: Value
}
}
struct EventHeader<'r>(pub &'r str);
#[async_trait]
impl<'r> FromRequest<'r> for EventHeader<'r> {
type Error = Error;
async fn from_request(request: &'r Request<'_>) -> rocket::request::Outcome<Self,Self::Error> {
let headers = request.headers();
let Some(event) = headers.get_one("X-GitHub-Event") else {
return rocket::request::Outcome::Failure((Status::BadRequest, Error::InvalidOperation))
};
rocket::request::Outcome::Success(Self(event))
}
}
/// # executes a webhook specific to github
///
/// executes a webhook specific to github and sends a message containg the relavent info about the event
#[openapi(tag = "Webhooks")]
#[post("/<target>/<token>/github", data="<data>")]
pub async fn req(db: &Db, target: Ref, token: String, event: EventHeader<'_>, data: String) -> Result<()> {
let webhook = target.as_webhook(db).await?;
(webhook.token == token)
.then_some(())
.ok_or(Error::InvalidCredentials)?;
let channel = db.fetch_channel(&webhook.channel).await?;
let body = format!(r#"{{"{}": {data}}}"#r, event.0);
let Ok(event) = serde_json::from_str::<Event>(&body) else {
return Err(Error::InvalidOperation)
};
let sendable_embed = match event {
Event::Star { action, sender } => SendableEmbed {
title: Some(format!("{action} star")),
..Default::default()
},
};
let message_id = Ulid::new().to_string();
let embed = sendable_embed.into_embed(db, message_id.clone()).await?;
let message = Message {
id: message_id,
channel: webhook.channel,
embeds: Some(vec![embed]),
webhook: Some(webhook.id.clone()),
..Default::default()
};
message.create(db, &channel, Some(MessageAuthor::Webhook(&webhook))).await;
Ok(())
}

View File

@@ -30,7 +30,7 @@ pub struct Reply {
}
/// Representation of a text embed before it is sent.
#[derive(Validate, Serialize, Deserialize, JsonSchema, Clone, Debug)]
#[derive(Validate, Serialize, Deserialize, JsonSchema, Clone, Debug, Default)]
pub struct SendableEmbed {
#[validate(length(min = 1, max = 128))]
pub icon_url: Option<String>,