diff --git a/Cargo.lock b/Cargo.lock index 79fc94c..6fb4169 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -920,6 +920,12 @@ dependencies = [ "cc", ] +[[package]] +name = "ics" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ebec52f461ade2d19e7b594ecbcd0723ba0ab0eefa8aae2281b78ff461a91fa" + [[package]] name = "idna" version = "0.3.0" @@ -1773,6 +1779,7 @@ dependencies = [ "argon2", "chrono", "env_logger", + "ics", "log", "rocket", "rocket_dyn_templates", diff --git a/Cargo.toml b/Cargo.toml index e661384..708477d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,4 @@ serde = { version = "1.0", features = [ "derive" ]} serde_json = "1.0" chrono = { version = "0.4", features = ["serde"]} tera = { version = "1.18", features = ["date-locale"]} +ics = "0.5" diff --git a/src/model/planned_event.rs b/src/model/planned_event.rs index a32af38..afe8152 100644 --- a/src/model/planned_event.rs +++ b/src/model/planned_event.rs @@ -1,4 +1,10 @@ +use std::io::Write; + use chrono::NaiveDate; +use ics::{ + properties::{DtStart, Summary}, + Event, ICalendar, +}; use serde::Serialize; use sqlx::{FromRow, SqlitePool}; @@ -207,25 +213,22 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM planned_even } pub async fn get_ics_feed(db: &SqlitePool) -> String { - let mut res = String::new(); - res.push_str("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//rudernlinz.at//Trips//DE\r\nX-WR-CALNAME:Ruderausfahrten\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Vienna\r\nTZURL:http://tzurl.org/zoneinfo-outlook/Europe/Vienna\r\nX-LIC-LOCATION:Europe/Vienna\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE"); + let mut calendar = ICalendar::new("2.0", "ics-rs"); let events = PlannedEvent::all(db).await; for event in events { - res.push_str("\r\nBEGIN:VEVENT"); - res.push_str(&format!("\r\nUID:{}@rudernlinz.at", event.id)); - res.push_str(&format!( - "\r\nDTSTART;TZID=Europe/Vienna:{}T{}00", + let mut vevent = Event::new(format!("{}@rudernlinz.at", event.id), "19900101T180000"); + vevent.push(DtStart::new(format!( + "TZID=Europe/Vienna:{}T{}00", event.day.replace('-', ""), event.planned_starting_time.replace(':', "") - )); - res.push_str(&format!("\r\nDTSTAMP;TZID=Europe/Vienna:19900101T180000")); - res.push_str(&format!("\r\nSUMMARY:{}", event.name)); - res.push_str("\r\nEND:VEVENT"); + ))); + vevent.push(Summary::new(event.name)); + calendar.add_event(vevent); } - - res.push_str("\r\nEND:VCALENDAR"); - res + let mut buf = Vec::new(); + write!(&mut buf, "{}", calendar).unwrap(); + String::from_utf8(buf).unwrap() } }