mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 01:12:24 +00:00
birthday calendar, rename birthday objects, support anniversary field
This commit is contained in:
@@ -49,6 +49,11 @@ impl AddressObject {
|
|||||||
&self.vcf
|
&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> {
|
pub fn get_birthday(&self) -> Option<CalDateTime> {
|
||||||
let prop = self.vcard.get_property("BDAY")?;
|
let prop = self.vcard.get_property("BDAY")?;
|
||||||
CalDateTime::parse_prop(prop, &HashMap::default()).unwrap_or(None)
|
CalDateTime::parse_prop(prop, &HashMap::default()).unwrap_or(None)
|
||||||
@@ -59,6 +64,50 @@ impl AddressObject {
|
|||||||
prop.value.as_ref()
|
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> {
|
pub fn get_birthday_object(&self) -> Result<Option<CalendarObject>, Error> {
|
||||||
Ok(if let Some(birthday) = self.get_birthday() {
|
Ok(if let Some(birthday) = self.get_birthday() {
|
||||||
let fullname = if let Some(name) = self.get_full_name() {
|
let fullname = if let Some(name) = self.get_full_name() {
|
||||||
@@ -70,8 +119,10 @@ impl AddressObject {
|
|||||||
let year = birthday.year();
|
let year = birthday.year();
|
||||||
let birthday_start = birthday.format(LOCAL_DATE);
|
let birthday_start = birthday.format(LOCAL_DATE);
|
||||||
let birthday_end = birthday.succ_opt().unwrap_or(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(
|
Some(CalendarObject::from_ics(
|
||||||
self.get_id().to_owned(),
|
uid.clone(),
|
||||||
format!(
|
format!(
|
||||||
r#"BEGIN:VCALENDAR
|
r#"BEGIN:VCALENDAR
|
||||||
VERSION:2.0
|
VERSION:2.0
|
||||||
@@ -91,11 +142,22 @@ DESCRIPTION:🎂 {fullname} ({year})
|
|||||||
END:VALARM
|
END:VALARM
|
||||||
END:VEVENT
|
END:VEVENT
|
||||||
END:VCALENDAR"#,
|
END:VCALENDAR"#,
|
||||||
uid = self.get_id(),
|
|
||||||
),
|
),
|
||||||
)?)
|
)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::sync::Arc;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
calendar::CalendarObjectType, AddressObject, Addressbook, AddressbookStore, Calendar,
|
calendar::CalendarObjectType, AddressObject, Addressbook, AddressbookStore, Calendar,
|
||||||
@@ -99,14 +99,17 @@ impl<AS: AddressbookStore> CalendarStore for ContactBirthdayStore<AS> {
|
|||||||
principal: &str,
|
principal: &str,
|
||||||
cal_id: &str,
|
cal_id: &str,
|
||||||
) -> Result<Vec<CalendarObject>, Error> {
|
) -> Result<Vec<CalendarObject>, Error> {
|
||||||
let objects: Result<Vec<Option<CalendarObject>>, Error> = self
|
let objects: Result<Vec<HashMap<&'static str, CalendarObject>>, Error> = self
|
||||||
.0
|
.0
|
||||||
.get_objects(principal, cal_id)
|
.get_objects(principal, cal_id)
|
||||||
.await?
|
.await?
|
||||||
.iter()
|
.iter()
|
||||||
.map(AddressObject::get_birthday_object)
|
.map(AddressObject::get_significant_dates)
|
||||||
|
.collect();
|
||||||
|
let objects = objects?
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(HashMap::into_values)
|
||||||
.collect();
|
.collect();
|
||||||
let objects = objects?.into_iter().flatten().collect();
|
|
||||||
|
|
||||||
Ok(objects)
|
Ok(objects)
|
||||||
}
|
}
|
||||||
@@ -117,12 +120,14 @@ impl<AS: AddressbookStore> CalendarStore for ContactBirthdayStore<AS> {
|
|||||||
cal_id: &str,
|
cal_id: &str,
|
||||||
object_id: &str,
|
object_id: &str,
|
||||||
) -> Result<CalendarObject, Error> {
|
) -> Result<CalendarObject, Error> {
|
||||||
Ok(self
|
let (addressobject_id, date_type) = object_id.rsplit_once("-").ok_or(Error::NotFound)?;
|
||||||
.0
|
dbg!(addressobject_id, date_type);
|
||||||
.get_object(principal, cal_id, object_id)
|
self.0
|
||||||
|
.get_object(principal, cal_id, addressobject_id)
|
||||||
.await?
|
.await?
|
||||||
.get_birthday_object()?
|
.get_significant_dates()?
|
||||||
.ok_or(Error::NotFound)?)
|
.remove(date_type)
|
||||||
|
.ok_or(Error::NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put_object(
|
async fn put_object(
|
||||||
|
|||||||
Reference in New Issue
Block a user