From 11fa975fb2508be7c0cece679f8f9f7c4daf5a2a Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 20 Mar 2023 01:14:01 +0100 Subject: [PATCH] ticker-serve/export: implement ics export --- ticker-serve/askama.toml | 3 ++ ticker-serve/src/export.rs | 62 +++++++++++++++++++++++++++++++ ticker-serve/src/main.rs | 2 + ticker-serve/templates/export.ics | 24 ++++++++++++ ticker-serve/templates/index.html | 5 +++ 5 files changed, 96 insertions(+) create mode 100644 ticker-serve/askama.toml create mode 100644 ticker-serve/src/export.rs create mode 100644 ticker-serve/templates/export.ics diff --git a/ticker-serve/askama.toml b/ticker-serve/askama.toml new file mode 100644 index 0000000..09b52de --- /dev/null +++ b/ticker-serve/askama.toml @@ -0,0 +1,3 @@ +[[escaper]] +path = "Text" +extensions = ["ics"] diff --git a/ticker-serve/src/export.rs b/ticker-serve/src/export.rs new file mode 100644 index 0000000..b392c06 --- /dev/null +++ b/ticker-serve/src/export.rs @@ -0,0 +1,62 @@ +use askama::{Template, Text}; +use axum::{ + response::{IntoResponse, Response}, + http::{StatusCode, HeaderMap, HeaderName, HeaderValue}, + Extension, +}; + +use diesel::prelude::*; +use chrono::{offset::Local, Duration}; + +use libticker::{ + schema::{self, events::dsl::events}, + model::Event, +}; +use crate::AppState; + +#[derive(Template)] +#[template(path = "export.ics")] +struct IcsTemplate { + events: Vec, +} + +pub async fn ics(Extension(app_state): Extension) -> Response { + export(app_state, |es| ( + IcsTemplate { events: es }, + "text/calendar" + )).await +} + +async fn export(app_state: AppState, f: F) -> Response +where + F: FnOnce(Vec) -> (T, &'static str), + T: Template, +{ + let db = app_state.db.lock().unwrap(); + let today = Local::now().date_naive().and_hms_opt(0, 0, 0).unwrap(); + let limit = Local::now().date_naive().and_hms_opt(0, 0, 0).unwrap() + + Duration::days(app_state.config.upcoming_days.into()); + let es: Vec = events + .filter(schema::events::dtend.ge(&today)) + .or_filter(schema::events::dtstart.ge(&today)) + .filter(schema::events::dtstart.lt(&limit)) + .order_by(schema::events::dtstart.asc()) + .then_order_by(schema::events::dtend.desc()) + .load::(&*db) + .unwrap(); + // .into_iter().collect::>(); + let (template, content_type) = f(es); + match template.render() { + Ok(rendered) => + ( + [(HeaderName::from_static("content-type"), HeaderValue::from_static(content_type))] + .iter().cloned() + .collect::(), + rendered + ).into_response(), + Err(e) => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Failed to render template. Error: {}", e), + ).into_response(), + } +} diff --git a/ticker-serve/src/main.rs b/ticker-serve/src/main.rs index 4180a35..2b318e0 100644 --- a/ticker-serve/src/main.rs +++ b/ticker-serve/src/main.rs @@ -12,6 +12,7 @@ use diesel::{Connection, pg::PgConnection}; use libticker::config::Config; mod index; +mod export; #[derive(Clone)] pub struct AppState { @@ -33,6 +34,7 @@ async fn main() { }; let app = Router::new() .route("/", get(index::index)) + .route("/export.ics", get(export::ics)) .layer(Extension(state)) .nest_service("/static", ServeDir::new("static")); axum::Server::bind(&http_bind) diff --git a/ticker-serve/templates/export.ics b/ticker-serve/templates/export.ics new file mode 100644 index 0000000..1d31137 --- /dev/null +++ b/ticker-serve/templates/export.ics @@ -0,0 +1,24 @@ +BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +X-WR-TIMEZONE;VALUE=TEXT:Europe/Berlin + +{% for e in events -%} +BEGIN:VEVENT +SUMMARY:{{ e.summary }} +DTSTART:{{ e.dtstart.format("%Y%m%dT%H%M%S").to_string() }} +{% if let Some(dtend) = e.dtend -%} +DTEND:{{ dtend.format("%Y%m%dT%H%M%S") }} +{% endif -%} +UID:{{ e.id.replace(char::is_whitespace, "_") }} +{% if let Some(url) = e.url -%} +URL:{{ url }} +{% endif -%} +{% if let Some(location) = e.location -%} +LOCATION:{{ location }} +{% endif -%} +END:VEVENT + +{% endfor -%} +END:VCALENDAR + diff --git a/ticker-serve/templates/index.html b/ticker-serve/templates/index.html index eca822f..660095c 100644 --- a/ticker-serve/templates/index.html +++ b/ticker-serve/templates/index.html @@ -6,6 +6,7 @@ +

Dresden Ticker

@@ -62,6 +63,10 @@ {% endfor %}