From 0b057a4d2e523b74be94bb125c26d97206690482 Mon Sep 17 00:00:00 2001 From: Malted Date: Thu, 14 Mar 2024 21:00:13 +0000 Subject: [PATCH] Add team member emails --- src/defs.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++------- src/main.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++ src/slack.rs | 27 +++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 src/slack.rs diff --git a/src/defs.rs b/src/defs.rs index 51c2003..12a61d9 100644 --- a/src/defs.rs +++ b/src/defs.rs @@ -3,18 +3,29 @@ use serde_json::Value; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct TeamMember { - name: String, + pub name: String, bio: Option, department: String, role: String, bio_hackfoundation: Option, pronouns: Option, + pub slack_id: Option, slack_display_name: Option, avatar: Option, // 72^2 px if from Slack; ..=512^2 if overriden in Airtable + avatar_id: Option, + email: Option, } impl TeamMember { pub fn from_json(json: &Value) -> Self { // Title Case names are from Airtable, _snake_case names are from Slack. + + let avatar_object = json + .get("Override Avatar") + .and_then(|s| s.as_array()) + .and_then(|s| s.get(0)) + .and_then(|s| s.get("thumbnails")) + .and_then(|s| s.get("large")); + Self { name: json["Name"].as_str().unwrap().into(), bio: json["Bio"].as_str().map(|s| s.into()), @@ -24,19 +35,50 @@ impl TeamMember { pronouns: json .get("_pronouns") .and_then(|s| s.as_str().map(|s| s.to_string())), + slack_id: json + .get("Slack ID") + .and_then(|s| s.as_str().map(|s| s.to_string())), slack_display_name: json .get("_slack_display_name") .map(|s| s.as_str().unwrap().to_string()), - avatar: json - .get("Override Avatar") - .and_then(|s| s.as_array()) - .and_then(|s| s.get(0)) - .and_then(|s| s.get("thumbnails")) - .and_then(|s| s.get("large")) + avatar: avatar_object .and_then(|s| s.get("url")) .map(|s| s.as_str().unwrap().to_string()) .or(json.get("_avatar").map(|s| s.as_str().unwrap().to_string())), + avatar_id: avatar_object + .and_then(|s| s.get("id")) + .map(|s| s.as_str().unwrap().to_string()) + .or(Some(String::new())), + email: json["Email"].as_str().map(|s| s.into()), + } + } + + pub fn differences(&self, other: &Self) -> Vec<&str> { + let mut diffs = vec![]; + + if self.name != other.name { + diffs.push("name") } + if self.bio != other.bio { + diffs.push("bio") + } + if self.department != other.department { + diffs.push("department") + } + if self.role != other.role { + diffs.push("role") + } + if self.bio_hackfoundation != other.bio_hackfoundation { + diffs.push("alternate bio") + } + if self.avatar_id != other.avatar_id { + diffs.push("avatar") + } + if self.email != other.email { + diffs.push("email") + } + + diffs } } diff --git a/src/main.rs b/src/main.rs index f3c2518..188484e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use std::env::var; use std::sync::Arc; mod defs; use defs::{Team, TeamFetchError, TeamMember}; +mod slack; impl Team { fn from_raw_airtable(refreshed_at: u64, input: Value) -> Self { @@ -142,6 +143,54 @@ fn notify_team_change(team: &State>>, token: String) -> Json { + let current_team = team.read(); + + for current_member in (*current_team.current).iter() { + if let Some(other_member) = t.current.iter().find(|m| m.name == current_member.name) + { + let changed_fields = current_member.differences(other_member); + if !changed_fields.is_empty() { + if let Some(ref sid) = current_member.slack_id { + if slack::send_slack_message( + sid, + &format!( + "The following fields have changed for you: {}", + changed_fields.join(", ") + ), + ) + .is_err() + { + log::error!( + "failed to send row change slack notification to {}", + current_member.name + ); + } + } + } + } + } + + // for changed_member in team.read().changed_members(&t) { + // if let Some(ref sid) = changed_member.slack_id { + // let other_member = other + // .current + // .iter() + // .find(|m| m.name == changed_member.name) + // .unwrap_or_else(|| { + // log::warn!("Member {} not found in other team", member.name); + // member + // }); + + // let changed = changed_member.clone().differences(t); + // if slack::send_slack_message(sid, "test1").is_err() { + // log::error!( + // "failed to send row change slack notification to {}", + // changed_member.name + // ); + // } + // } + // } + *team.write() = t; Json(String::from("success!")) } diff --git a/src/slack.rs b/src/slack.rs new file mode 100644 index 0000000..22353b5 --- /dev/null +++ b/src/slack.rs @@ -0,0 +1,27 @@ +pub fn send_slack_message(slack_id: &str, message: &str) -> Result<(), reqwest::Error> { + let client = reqwest::blocking::Client::new(); + + let res = client + .post("https://slack.com/api/chat.postMessage") + .header( + "Authorization", + format!("Bearer {}", std::env::var("SLACK_TOKEN").unwrap()), + ) + .header("Content-Type", "application/json") + .json(&serde_json::json!({ + "channel": slack_id, + "text": message, + })) + .send(); + + if let Err(err) = res { + return Err(err); + } + + let res = res.unwrap(); + + let text = res.text(); + println!("{:?}", text); + + Ok(()) +}