diff options
| -rw-r--r-- | Cargo.lock | 28 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/main.rs | 54 |
3 files changed, 83 insertions, 1 deletions
@@ -1,6 +1,15 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -207,11 +216,13 @@ dependencies = [ name = "google-calendar-rsvp" version = "0.0.1" dependencies = [ + "base64", "exitcode", "google-calendar3", "home", "hyper", "hyper-rustls", + "regex", "serde_json", "tokio", "yup-oauth2", @@ -606,6 +617,23 @@ dependencies = [ ] [[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] name = "ring" version = "0.16.20" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4,11 +4,13 @@ version = "0.0.1" edition = "2018" [dependencies] +base64 = "0.13.0" exitcode = "1.1.2" google-calendar3 = "2.0.4+20210327" home = "0.5.3" hyper = "0.14.7" hyper-rustls = "0.22.1" +regex = "1.5.4" serde_json = "1.0.64" tokio = { version = "1.6.0", features = ["rt-multi-thread"] } yup-oauth2 = "5.1.0" diff --git a/src/main.rs b/src/main.rs index db82151..9f4ad6a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,10 @@ +use base64; use google_calendar3::api::{Event, EventAttendee}; use google_calendar3::CalendarHub; use home; use hyper; use hyper_rustls; +use regex::Regex; use tokio; use yup_oauth2 as oauth2; @@ -10,6 +12,7 @@ use std::env; use std::fmt; use std::fs; use std::process; +use std::str; #[derive(Debug)] @@ -71,7 +74,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { } for event_id in &event_ids { - rsvp(event_id, &action).await; + rsvp( + &event_id_from_base64(event_id), + &action, + ).await; } Ok(()) @@ -145,3 +151,49 @@ fn secret_from_file() -> oauth2::ApplicationSecret { None => todo!(), } } + +fn event_id_from_base64(event_id: &str) -> String { + // Base64-matching regex from Xuanyuanzhiyuan + // (https://stackoverflow.com/users/1076906/xuanyuanzhiyuan) on Stack + // Overflow: + // https://stackoverflow.com/questions/8571501/how-to-check-whether-a-string-is-base64-encoded-or-not/8571649#8571649 + let re = Regex::new( + "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$", + ).unwrap(); + + if !re.is_match(event_id) { + return event_id.to_owned(); + } + + let decoded = &base64::decode(event_id).unwrap(); + let id_email_pair = str::from_utf8(decoded).unwrap(); + let values = id_email_pair.split(" ").collect::<Vec<_>>(); + let id = values.first().unwrap().to_string(); + + id +} + + +#[cfg(test)] +mod tests { + use crate::*; + + #[test] + fn test_event_id_from_base64_event_id() { + let expected = "1g4j1h67ndq7kddrb2bptp2cua_20210521T120000Z"; + + let id = event_id_from_base64(expected); + + assert_eq!(expected, id); + } + + #[test] + fn test_event_id_from_base64_eid() { + let expected = "1g4j1h67ndq7kddrb2bptp2cua"; + let encoded = base64::encode(format!("{} rory.mercury@example.com", expected)); + + let id = event_id_from_base64(&encoded); + + assert_eq!(expected, id); + } +} |
