birthday calendar, rename birthday objects, support anniversary field

This commit is contained in:
Lennart
2025-01-21 13:38:46 +01:00
parent 7a678f5150
commit ec6dbf50f6
2 changed files with 78 additions and 11 deletions

View File

@@ -49,6 +49,11 @@ impl AddressObject {
&self.vcf
}
pub fn get_anniversary(&self) -> Option<CalDateTime> {
let prop = self.vcard.get_property("ANNIVERSARY")?;
CalDateTime::parse_prop(prop, &HashMap::default()).unwrap_or(None)
}
pub fn get_birthday(&self) -> Option<CalDateTime> {
let prop = self.vcard.get_property("BDAY")?;
CalDateTime::parse_prop(prop, &HashMap::default()).unwrap_or(None)
@@ -59,6 +64,50 @@ impl AddressObject {
prop.value.as_ref()
}
pub fn get_anniversary_object(&self) -> Result<Option<CalendarObject>, Error> {
Ok(if let Some(anniversary) = self.get_anniversary() {
let fullname = if let Some(name) = self.get_full_name() {
name
} else {
return Ok(None);
};
let anniversary = anniversary.date();
let year = anniversary.year();
let anniversary_start = anniversary.format(LOCAL_DATE);
let anniversary_end = anniversary
.succ_opt()
.unwrap_or(anniversary)
.format(LOCAL_DATE);
let uid = format!("{}-anniversary", self.get_id());
Some(CalendarObject::from_ics(
uid.clone(),
format!(
r#"BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//github.com/lennart-k/rustical birthday calendar//EN
BEGIN:VEVENT
DTSTART;VALUE=DATE:{anniversary_start}
DTEND;VALUE=DATE:{anniversary_end}
UID:{uid}
RRULE:FREQ=YEARLY
SUMMARY:💍 {fullname} ({year})
TRANSP:TRANSPARENT
BEGIN:VALARM
TRIGGER;VALUE=DURATION:-PT0M
ACTION:DISPLAY
DESCRIPTION:💍 {fullname} ({year})
END:VALARM
END:VEVENT
END:VCALENDAR"#,
),
)?)
} else {
None
})
}
pub fn get_birthday_object(&self) -> Result<Option<CalendarObject>, Error> {
Ok(if let Some(birthday) = self.get_birthday() {
let fullname = if let Some(name) = self.get_full_name() {
@@ -70,8 +119,10 @@ impl AddressObject {
let year = birthday.year();
let birthday_start = birthday.format(LOCAL_DATE);
let birthday_end = birthday.succ_opt().unwrap_or(birthday).format(LOCAL_DATE);
let uid = format!("{}-birthday", self.get_id());
Some(CalendarObject::from_ics(
self.get_id().to_owned(),
uid.clone(),
format!(
r#"BEGIN:VCALENDAR
VERSION:2.0
@@ -91,11 +142,22 @@ DESCRIPTION:🎂 {fullname} ({year})
END:VALARM
END:VEVENT
END:VCALENDAR"#,
uid = self.get_id(),
),
)?)
} else {
None
})
}
/// Get significant dates associated with this address object
pub fn get_significant_dates(&self) -> Result<HashMap<&'static str, CalendarObject>, Error> {
let mut out = HashMap::new();
if let Some(birthday) = self.get_birthday_object()? {
out.insert("birthday", birthday);
}
if let Some(anniversary) = self.get_anniversary_object()? {
out.insert("anniversary", anniversary);
}
Ok(out)
}
}

View File

@@ -1,4 +1,4 @@
use std::sync::Arc;
use std::{collections::HashMap, sync::Arc};
use crate::{
calendar::CalendarObjectType, AddressObject, Addressbook, AddressbookStore, Calendar,
@@ -99,14 +99,17 @@ impl<AS: AddressbookStore> CalendarStore for ContactBirthdayStore<AS> {
principal: &str,
cal_id: &str,
) -> Result<Vec<CalendarObject>, Error> {
let objects: Result<Vec<Option<CalendarObject>>, Error> = self
let objects: Result<Vec<HashMap<&'static str, CalendarObject>>, Error> = self
.0
.get_objects(principal, cal_id)
.await?
.iter()
.map(AddressObject::get_birthday_object)
.map(AddressObject::get_significant_dates)
.collect();
let objects = objects?
.into_iter()
.flat_map(HashMap::into_values)
.collect();
let objects = objects?.into_iter().flatten().collect();
Ok(objects)
}
@@ -117,12 +120,14 @@ impl<AS: AddressbookStore> CalendarStore for ContactBirthdayStore<AS> {
cal_id: &str,
object_id: &str,
) -> Result<CalendarObject, Error> {
Ok(self
.0
.get_object(principal, cal_id, object_id)
let (addressobject_id, date_type) = object_id.rsplit_once("-").ok_or(Error::NotFound)?;
dbg!(addressobject_id, date_type);
self.0
.get_object(principal, cal_id, addressobject_id)
.await?
.get_birthday_object()?
.ok_or(Error::NotFound)?)
.get_significant_dates()?
.remove(date_type)
.ok_or(Error::NotFound)
}
async fn put_object(