From c7f2f3614f1f997442c5d5f9d672ba3d76f768b6 Mon Sep 17 00:00:00 2001 From: Zomatree Date: Fri, 30 Dec 2022 18:08:43 +0000 Subject: [PATCH] star event --- .../routes/webhooks/webhook_execute_github.rs | 238 ++++++++++++++++-- 1 file changed, 222 insertions(+), 16 deletions(-) diff --git a/crates/delta/src/routes/webhooks/webhook_execute_github.rs b/crates/delta/src/routes/webhooks/webhook_execute_github.rs index 4ed393de..4d5276be 100644 --- a/crates/delta/src/routes/webhooks/webhook_execute_github.rs +++ b/crates/delta/src/routes/webhooks/webhook_execute_github.rs @@ -1,20 +1,185 @@ 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 rocket::{Request, request::FromRequest, http::Status}; +use rocket_okapi::{request::{OpenApiFromRequest, RequestHeaderInput}, okapi::openapi3::{Parameter, ParameterValue, MediaType}, gen::OpenApiGenerator}; +use schemars::schema::{SchemaObject, StringValidation}; use serde::{Deserialize, Serialize}; use serde_json::Value; use ulid::Ulid; +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GithubUser { + name: Option, + email: Option, + login: String, + id: u32, + node_id: String, + avatar_url: String, + gravatar_id: String, + url: String, + html_url: String, + followers_url: String, + following_url: String, + gists_url: String, + starred_url: String, + subscriptions_url: String, + organizations_url: String, + repos_url: String, + events_url: String, + received_events_url: String, +} -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GithubRepositorySecurityAndAnalysisStatus { + status: String +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GithubRepositorySecurityAndAnalysis { + advanced_security: GithubRepositorySecurityAndAnalysisStatus, + secret_scanning: GithubRepositorySecurityAndAnalysisStatus, + secret_scanning_push_protection: GithubRepositorySecurityAndAnalysisStatus +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GithubRepositoryLicense { + key: Option, + name: Option, + spdx_id: Option, + url: Option, + node_id: Option, +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GithubRepositoryCodeOfConduct { + key: String, + name: String, + url: String, + body: Option, + html_url: Option +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GithubRepositoryPermissions { + admin: Option, + maintain: Option, + push: Option, + triage: Option, + pull: Option +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GithubRepository { + id: u32, + node_id: String, + name: String, + full_name: String, + owner: GithubUser, + private: bool, + html_url: String, + description: Option, + fork: bool, + url: String, + archive_url: String, + assignees_url: String, + blobs_url: String, + branches_url: String, + collaborators_url: String, + comments_url: String, + commits_url: String, + compare_url: String, + contents_url: String, + contributors_url: String, + deployments_url: String, + downloads_url: String, + events_url: String, + forks_url: String, + git_commits_url: String, + git_refs_url: String, + git_tags_url: String, + git_url: Option, + issue_comment_url: String, + issue_events_url: String, + issues_url: String, + keys_url: String, + labels_url: String, + languages_url: String, + merges_url: String, + milestones_url: String, + notifications_url: String, + pulls_url: String, + releases_url: String, + ssh_url: String, + stargazers_url: String, + statuses_url: String, + subscribers_url: String, + subscription_url: String, + tags_url: String, + teams_url: String, + trees_url: String, + clone_url: Option, + mirror_url: Option, + hooks_url: String, + svn_url: Option, + homepage: Option, + language: Option, + forks_count: Option, + stargazers_count: Option, + watchers_count: Option, + size: Option, + default_branch: Option, + open_issues_count: Option, + is_template: Option, + topics: Option>, + has_issues: Option, + has_projects: Option, + has_wiki: Option, + has_pages: Option, + has_downloads: Option, + has_discussions: Option, + archived: Option, + disabled: Option, + visibility: Option, + pushed_at: Option, + created_at: Option, + updated_at: Option, + permissions: GithubRepositoryPermissions, + role_name: Option, + temp_clone_token: Option, + delete_branch_on_merge: Option, + subscribers_count: Option, + network_count: Option, + code_of_conduct: GithubRepositoryCodeOfConduct, + license: Option, + forks: Option, + open_issues: Option, + watchers: Option, + allow_forking: Option, + web_commit_signoff_required: Option, + security_and_analysis: Option +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "lowercase")] -pub enum Event { +pub enum BaseEvent { Star { - action: String, - sender: Value + starred_at: Option, } } -struct EventHeader<'r>(pub &'r str); +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct Event { + action: String, + sender: GithubUser, + repository: GithubRepository, + organization: Option, + installation: Option, + + #[serde(flatten)] + event: BaseEvent +} + +#[derive(Debug, JsonSchema)] +pub struct EventHeader<'r>(pub &'r str); #[async_trait] impl<'r> FromRequest<'r> for EventHeader<'r> { @@ -30,6 +195,39 @@ impl<'r> FromRequest<'r> for EventHeader<'r> { } } +impl<'r> OpenApiFromRequest<'r> for EventHeader<'r> { + fn from_request_input( + _gen: &mut OpenApiGenerator, + _name: String, + _required: bool, + ) -> rocket_okapi::Result { + let mut content = schemars::Map::new(); + content.insert("X-Github-Event".to_string(), MediaType { + schema: Some(SchemaObject { + string: Some(Box::new(StringValidation::default())), + ..Default::default() + }), + example: None, + examples: None, + encoding: schemars::Map::new(), + extensions: schemars::Map::new(), + }); + + Ok(RequestHeaderInput::Parameter( + Parameter { + name: "X-Github-Event".to_string(), + location: "header".to_string(), + required: true, + description: Some("The name of the github event".to_string()), + deprecated: false, + allow_empty_value: false, + value: ParameterValue::Content { content }, + extensions: schemars::Map::new() + } + )) + } +} + /// # executes a webhook specific to github /// /// executes a webhook specific to github and sends a message containg the relavent info about the event @@ -44,16 +242,26 @@ pub async fn req(db: &Db, target: Ref, token: String, event: EventHeader<'_>, da let channel = db.fetch_channel(&webhook.channel).await?; - let body = format!(r#"{{"{}": {data}}}"#r, event.0); + let body = format!(r#"{{"{}": {data}}}"#, &event.0); + + log::info!("{body}"); let Ok(event) = serde_json::from_str::(&body) else { return Err(Error::InvalidOperation) }; - let sendable_embed = match event { - Event::Star { action, sender } => SendableEmbed { - title: Some(format!("{action} star")), - ..Default::default() + let sendable_embed = match event.event { + BaseEvent::Star { .. } => { + if event.action != "created" { return Ok(()) }; + + SendableEmbed { + title: Some(event.sender.login), + description: Some(format!("[[{}] New star added]({})", event.repository.full_name, event.repository.html_url)), + colour: Some("#202224".to_string()), + icon_url: Some(event.sender.avatar_url), + url: Some(event.sender.html_url), + ..Default::default() + } }, }; @@ -61,15 +269,13 @@ pub async fn req(db: &Db, target: Ref, token: String, event: EventHeader<'_>, da let embed = sendable_embed.into_embed(db, message_id.clone()).await?; - let message = Message { + let mut message = Message { id: message_id, - channel: webhook.channel, + channel: webhook.channel.clone(), embeds: Some(vec![embed]), webhook: Some(webhook.id.clone()), ..Default::default() }; - message.create(db, &channel, Some(MessageAuthor::Webhook(&webhook))).await; - - Ok(()) + message.create(db, &channel, Some(MessageAuthor::Webhook(&webhook))).await }