mirror of
https://github.com/lennart-k/rustical.git
synced 2026-01-30 08:08:23 +00:00
Re-implement calendar export
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1771,7 +1771,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ical"
|
name = "ical"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "git+https://github.com/lennart-k/ical-rs?branch=dev#0a50f3998b8ae104642cceb9d974e99b78838b14"
|
source = "git+https://github.com/lennart-k/ical-rs?branch=dev#8732224dd1514f6dcbccdcf63268a3f223d360e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"chrono-tz",
|
"chrono-tz",
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ use axum::extract::State;
|
|||||||
use axum::{extract::Path, response::Response};
|
use axum::{extract::Path, response::Response};
|
||||||
use headers::{ContentType, HeaderMapExt};
|
use headers::{ContentType, HeaderMapExt};
|
||||||
use http::{HeaderValue, Method, StatusCode, header};
|
use http::{HeaderValue, Method, StatusCode, header};
|
||||||
|
use ical::component::IcalCalendar;
|
||||||
use ical::generator::Emitter;
|
use ical::generator::Emitter;
|
||||||
use ical::property::ContentLine;
|
use ical::property::ContentLine;
|
||||||
use percent_encoding::{CONTROLS, utf8_percent_encode};
|
use percent_encoding::{CONTROLS, utf8_percent_encode};
|
||||||
use rustical_store::{CalendarStore, SubscriptionStore, auth::Principal};
|
use rustical_store::{CalendarStore, SubscriptionStore, auth::Principal};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
@@ -31,79 +31,62 @@ pub async fn route_get<C: CalendarStore, S: SubscriptionStore>(
|
|||||||
return Err(crate::Error::Unauthorized);
|
return Err(crate::Error::Unauthorized);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let mut vtimezones = HashMap::new();
|
let objects = cal_store
|
||||||
// let objects = cal_store.get_objects(&principal, &calendar_id).await?;
|
.get_objects(&principal, &calendar_id)
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, object)| object.into())
|
||||||
|
.collect();
|
||||||
|
|
||||||
todo!()
|
let mut props = vec![];
|
||||||
|
|
||||||
// let mut ical_calendar_builder = IcalCalendarBuilder::version("2.0")
|
if let Some(displayname) = calendar.meta.displayname {
|
||||||
// .gregorian()
|
props.push(ContentLine {
|
||||||
// .prodid("RustiCal");
|
name: "X-WR-CALNAME".to_owned(),
|
||||||
// if let Some(displayname) = calendar.meta.displayname {
|
value: Some(displayname),
|
||||||
// ical_calendar_builder = ical_calendar_builder.set(ContentLine {
|
params: vec![].into(),
|
||||||
// name: "X-WR-CALNAME".to_owned(),
|
});
|
||||||
// value: Some(displayname),
|
}
|
||||||
// params: vec![].into(),
|
if let Some(description) = calendar.meta.description {
|
||||||
// });
|
props.push(ContentLine {
|
||||||
// }
|
name: "X-WR-CALDESC".to_owned(),
|
||||||
// if let Some(description) = calendar.meta.description {
|
value: Some(description),
|
||||||
// ical_calendar_builder = ical_calendar_builder.set(ContentLine {
|
params: vec![].into(),
|
||||||
// name: "X-WR-CALDESC".to_owned(),
|
});
|
||||||
// value: Some(description),
|
}
|
||||||
// params: vec![].into(),
|
if let Some(color) = calendar.meta.color {
|
||||||
// });
|
props.push(ContentLine {
|
||||||
// }
|
name: "X-WR-CALCOLOR".to_owned(),
|
||||||
// if let Some(timezone_id) = calendar.timezone_id {
|
value: Some(color),
|
||||||
// ical_calendar_builder = ical_calendar_builder.set(ContentLine {
|
params: vec![].into(),
|
||||||
// name: "X-WR-TIMEZONE".to_owned(),
|
});
|
||||||
// value: Some(timezone_id),
|
}
|
||||||
// params: vec![].into(),
|
if let Some(timezone_id) = calendar.timezone_id {
|
||||||
// });
|
props.push(ContentLine {
|
||||||
// }
|
name: "X-WR-TIMEZONE".to_owned(),
|
||||||
//
|
value: Some(timezone_id),
|
||||||
// for object in &objects {
|
params: vec![].into(),
|
||||||
// vtimezones.extend(object.get_vtimezones());
|
});
|
||||||
// match object.get_data() {
|
}
|
||||||
// CalendarObjectComponent::Event(EventObject { event, .. }, overrides) => {
|
|
||||||
// ical_calendar_builder = ical_calendar_builder
|
let export_calendar = IcalCalendar::from_objects(objects, props);
|
||||||
// .add_event(event.clone())
|
|
||||||
// .add_events(overrides.iter().map(|ev| ev.event.clone()));
|
let mut resp = Response::builder().status(StatusCode::OK);
|
||||||
// }
|
let hdrs = resp.headers_mut().unwrap();
|
||||||
// CalendarObjectComponent::Todo(todo, overrides) => {
|
hdrs.typed_insert(ContentType::from_str("text/calendar; charset=utf-8").unwrap());
|
||||||
// ical_calendar_builder = ical_calendar_builder
|
|
||||||
// .add_todo(todo.clone())
|
let filename = format!("{}_{}.ics", calendar.principal, calendar.id);
|
||||||
// .add_todos(overrides.iter().cloned());
|
let filename = utf8_percent_encode(&filename, CONTROLS);
|
||||||
// }
|
hdrs.insert(
|
||||||
// CalendarObjectComponent::Journal(journal, overrides) => {
|
header::CONTENT_DISPOSITION,
|
||||||
// ical_calendar_builder = ical_calendar_builder
|
HeaderValue::from_str(&format!(
|
||||||
// .add_journal(journal.clone())
|
"attachement; filename*=UTF-8''{filename}; filename={filename}",
|
||||||
// .add_journals(overrides.iter().cloned());
|
))
|
||||||
// }
|
.unwrap(),
|
||||||
// }
|
);
|
||||||
// }
|
if matches!(method, Method::HEAD) {
|
||||||
//
|
Ok(resp.body(Body::empty()).unwrap())
|
||||||
// ical_calendar_builder = ical_calendar_builder.add_timezones(vtimezones.into_values().cloned());
|
} else {
|
||||||
//
|
Ok(resp.body(Body::new(export_calendar.generate())).unwrap())
|
||||||
// let ical_calendar = ical_calendar_builder
|
}
|
||||||
// .build()
|
|
||||||
// .map_err(|parser_error| Error::IcalError(parser_error.into()))?;
|
|
||||||
//
|
|
||||||
// let mut resp = Response::builder().status(StatusCode::OK);
|
|
||||||
// let hdrs = resp.headers_mut().unwrap();
|
|
||||||
// hdrs.typed_insert(ContentType::from_str("text/calendar; charset=utf-8").unwrap());
|
|
||||||
//
|
|
||||||
// let filename = format!("{}_{}.ics", calendar.principal, calendar.id);
|
|
||||||
// let filename = utf8_percent_encode(&filename, CONTROLS);
|
|
||||||
// hdrs.insert(
|
|
||||||
// header::CONTENT_DISPOSITION,
|
|
||||||
// HeaderValue::from_str(&format!(
|
|
||||||
// "attachement; filename*=UTF-8''{filename}; filename={filename}",
|
|
||||||
// ))
|
|
||||||
// .unwrap(),
|
|
||||||
// );
|
|
||||||
// if matches!(method, Method::HEAD) {
|
|
||||||
// Ok(resp.body(Body::empty()).unwrap())
|
|
||||||
// } else {
|
|
||||||
// Ok(resp.body(Body::new(ical_calendar.generate())).unwrap())
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ pub async fn route_import<C: CalendarStore, S: SubscriptionStore>(
|
|||||||
let description = cal
|
let description = cal
|
||||||
.get_property("X-WR-CALDESC")
|
.get_property("X-WR-CALDESC")
|
||||||
.and_then(|prop| prop.value.clone());
|
.and_then(|prop| prop.value.clone());
|
||||||
|
let color = cal
|
||||||
|
.get_property("X-WR-CALCOLOR")
|
||||||
|
.and_then(|prop| prop.value.clone());
|
||||||
let timezone_id = cal
|
let timezone_id = cal
|
||||||
.get_property("X-WR-TIMEZONE")
|
.get_property("X-WR-TIMEZONE")
|
||||||
.and_then(|prop| prop.value.clone());
|
.and_then(|prop| prop.value.clone());
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ pub async fn route_mkcalendar<C: CalendarStore, S: SubscriptionStore>(
|
|||||||
.ok_or_else(|| rustical_dav::Error::BadRequest("No timezone data provided".to_owned()))?
|
.ok_or_else(|| rustical_dav::Error::BadRequest("No timezone data provided".to_owned()))?
|
||||||
.map_err(|_| rustical_dav::Error::BadRequest("Error parsing timezone".to_owned()))?;
|
.map_err(|_| rustical_dav::Error::BadRequest("Error parsing timezone".to_owned()))?;
|
||||||
|
|
||||||
let timezone = calendar.vtimezones.first().ok_or_else(|| {
|
let timezone = calendar.vtimezones.values().next().ok_or_else(|| {
|
||||||
rustical_dav::Error::BadRequest("No timezone data provided".to_owned())
|
rustical_dav::Error::BadRequest("No timezone data provided".to_owned())
|
||||||
})?;
|
})?;
|
||||||
let timezone: Option<chrono_tz::Tz> = timezone.into();
|
let timezone: Option<chrono_tz::Tz> = timezone.into();
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ impl Resource for CalendarResource {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let timezone = calendar.vtimezones.first().ok_or_else(|| {
|
let timezone = calendar.vtimezones.values().next().ok_or_else(|| {
|
||||||
rustical_dav::Error::BadRequest("No timezone data provided".to_owned())
|
rustical_dav::Error::BadRequest("No timezone data provided".to_owned())
|
||||||
})?;
|
})?;
|
||||||
let timezone: Option<chrono_tz::Tz> = timezone.into();
|
let timezone: Option<chrono_tz::Tz> = timezone.into();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use super::prop::{
|
|||||||
};
|
};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use derive_more::derive::{From, Into};
|
use derive_more::derive::{From, Into};
|
||||||
|
use ical::generator::Emitter;
|
||||||
use rustical_dav::{
|
use rustical_dav::{
|
||||||
extensions::CommonPropertiesExtension,
|
extensions::CommonPropertiesExtension,
|
||||||
privileges::UserPrivilegeSet,
|
privileges::UserPrivilegeSet,
|
||||||
@@ -53,15 +54,18 @@ impl Resource for CalendarObjectResource {
|
|||||||
CalendarObjectProp::Getetag(self.object.get_etag())
|
CalendarObjectProp::Getetag(self.object.get_etag())
|
||||||
}
|
}
|
||||||
CalendarObjectPropName::CalendarData(CalendarData { expand, .. }) => {
|
CalendarObjectPropName::CalendarData(CalendarData { expand, .. }) => {
|
||||||
CalendarObjectProp::CalendarData(if let Some(expand) = expand.as_ref() {
|
CalendarObjectProp::CalendarData(expand.as_ref().map_or_else(
|
||||||
todo!()
|
|| self.object.get_ics().to_owned(),
|
||||||
// self.object.get_inner().expand_recurrence(
|
|expand| {
|
||||||
// Some(expand.start.to_utc()),
|
self.object
|
||||||
// Some(expand.end.to_utc()),
|
.get_inner()
|
||||||
// )
|
.expand_recurrence(
|
||||||
} else {
|
Some(expand.start.to_utc()),
|
||||||
self.object.get_ics().to_owned()
|
Some(expand.end.to_utc()),
|
||||||
})
|
)
|
||||||
|
.generate()
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
CalendarObjectPropName::Getcontenttype => {
|
CalendarObjectPropName::Getcontenttype => {
|
||||||
CalendarObjectProp::Getcontenttype("text/calendar;charset=utf-8")
|
CalendarObjectProp::Getcontenttype("text/calendar;charset=utf-8")
|
||||||
|
|||||||
@@ -102,3 +102,9 @@ impl CalendarObject {
|
|||||||
(&self.inner).into()
|
(&self.inner).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<CalendarObject> for IcalCalendarObject {
|
||||||
|
fn from(value: CalendarObject) -> Self {
|
||||||
|
value.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user