Skip to content

Commit

Permalink
feat: jira webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
MrExplode committed Oct 24, 2023
1 parent 4742429 commit 8430369
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 6 deletions.
76 changes: 70 additions & 6 deletions src/jira.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@ use actix_web::{
};
use serde::Deserialize;
use serde_json::json;
use webhook::models::Message;

use crate::Clients;
use crate::{types::JiraData, Clients};

const ENV_KEY: &str = "JIRA_TOKEN";

const ISSUE_CREATED: &str = "6684530";
const ISSUE_UPDATED: &str = "16759909";
const ISSUE_DELETED: &str = "16738405";
const UNSPECIFIED_EVENT: &str = "6683903";

#[derive(Deserialize)]
struct Info {
token: String,
}

#[post("/jira")]
async fn handle(info: web::Query<Info>, req_body: String, clients: Data<Arc<Clients>>) -> impl Responder {
async fn handle(info: web::Query<Info>, body: web::Json<JiraData>, clients: Data<Arc<Clients>>) -> impl Responder {
let env_token = match env::var(ENV_KEY) {
Ok(v) => v,
Err(_) => return HttpResponse::InternalServerError().json(json!({"error": "Missing environment value"})),
Expand All @@ -29,10 +35,68 @@ async fn handle(info: web::Query<Info>, req_body: String, clients: Data<Arc<Clie
return HttpResponse::Unauthorized().finish();
}

let _ = clients
.jira_client
.send(|message| message.username("Jira").content(format!("```{}```", req_body).as_str()))
.await;
let d = clients.jira_client.send_message(&message(&body)).await;
match d {
Ok(o) => {
println!("webhook delivery succesful: {}", o);
}
Err(e) => {
println!("geci: {}", e);
}
}

HttpResponse::Accepted().finish()
}

fn message(data: &web::Json<JiraData>) -> Message {
let root_url = root_url(&data.user.self_url);
let event_name = extract_event_name(&data.webhook_event);
let mut msg: Message = Message::new();
msg.username("Jira");
msg.embed(|embed| {
embed
.author(
&data.user.display_name,
None,
data.user.avatar_urls.get("48x48").cloned(),
)
.title(&event_name)
.url(&root_url);

if data.issue.is_some() {
let i = data.issue.as_ref().unwrap();
let f = &i.fields;
embed
.thumbnail(&f.issue_type.icon_url)
.description(
format!(
"[`{}`]({}) **{}**\n```\n{}\n```",
i.key, root_url, f.summary, f.description
)
.as_str(),
)
.field("Type", &f.issue_type.name, false)
.field("Priority", &f.priority.name, false)
.footer(&f.project.name, f.project.avatar_urls.get("48x48").cloned());
}

match data.webhook_event.as_str() {
"jira:issue_created" => embed.color(ISSUE_CREATED),
"jira:issue_updated" => embed.color(ISSUE_UPDATED),
"jira:issue_deleted" => embed.color(ISSUE_DELETED),
_ => embed.color(UNSPECIFIED_EVENT),
}
});
msg
}

fn root_url(url: &str) -> String {
let idx = url.replace("https://", "").find('/').unwrap();
url.chars().take(8 + idx).collect()
}

fn extract_event_name(event: &str) -> String {
let mut chars: Vec<char> = event.replace('_', " ").replace("jira:", "").chars().collect();
chars[0] = chars[0].to_uppercase().next().unwrap();
chars.into_iter().collect()
}
76 changes: 76 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use std::collections::HashMap;

use serde::Deserialize;

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JiraData {
pub timestamp: i64,
pub webhook_event: String,
pub user: JiraUser,
pub issue: Option<JiraIssue>,
pub issue_event_type_name: Option<String>,
}

#[derive(Deserialize)]
pub struct JiraIssue {
#[serde(rename = "self")]
pub self_url: String,
pub id: String,
pub key: String,
pub fields: JiraIssueFields,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JiraIssueFields {
pub creator: JiraUser,
pub project: JiraProject,
pub summary: String,
pub description: String,
pub priority: JiraIssuePriority,
#[serde(rename = "issuetype")]
pub issue_type: JiraIssueType,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JiraIssuePriority {
#[serde(rename = "self")]
pub self_url: String,
pub icon_url: String,
pub name: String,
pub id: String,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JiraIssueType {
#[serde(rename = "self")]
pub self_url: String,
pub id: String,
pub description: String,
pub icon_url: String,
pub name: String,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JiraUser {
#[serde(rename = "self")]
pub self_url: String,
pub account_id: String,
pub avatar_urls: HashMap<String, String>,
pub display_name: String,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JiraProject {
#[serde(rename = "self")]
pub self_url: String,
pub id: String,
pub key: String,
pub name: String,
pub avatar_urls: HashMap<String, String>,
}

0 comments on commit 8430369

Please sign in to comment.