Move yearly recurrence out of Event and into scheduler

This commit is contained in:
Matteo Settenvini 2022-08-03 19:31:06 +02:00
parent f98c82ae7f
commit e6288cfde1
Signed by: matteo
GPG Key ID: 8576CC1AD97D42DF
3 changed files with 40 additions and 26 deletions

View File

@ -25,7 +25,12 @@ struct CsvRecord {
dinner: String, dinner: String,
} }
pub async fn with(api_client: &ApiClient, calendar: &str, csv_file: &Path) -> Result<()> { pub async fn with(
api_client: &ApiClient,
calendar: &str,
csv_file: &Path,
yearly_recurring_events: bool,
) -> Result<()> {
let mut csv = csv::Reader::from_path(csv_file)?; let mut csv = csv::Reader::from_path(csv_file)?;
let records = csv.deserialize::<CsvRecord>().flatten().collect::<Vec<_>>(); let records = csv.deserialize::<CsvRecord>().flatten().collect::<Vec<_>>();
@ -51,7 +56,7 @@ pub async fn with(api_client: &ApiClient, calendar: &str, csv_file: &Path) -> Re
}) })
.flatten(); .flatten();
publish_events(&api_client, calendar, events).await?; publish_events(&api_client, calendar, events, yearly_recurring_events).await?;
Ok(()) Ok(())
} }
@ -111,6 +116,7 @@ async fn publish_events<'a, EventsIter>(
api_client: &ApiClient, api_client: &ApiClient,
calendar: &str, calendar: &str,
events: EventsIter, events: EventsIter,
yearly_recurring_events: bool,
) -> Result<()> ) -> Result<()>
where where
EventsIter: Iterator<Item = Event>, EventsIter: Iterator<Item = Event>,
@ -134,9 +140,28 @@ where
&ev.ends_at.date(), &ev.ends_at.date(),
&ev.recipe.name &ev.recipe.name
); );
let cal = icalendar::Calendar::new()
.push::<icalendar::Event>(ev.into()) let end_time = ev.ends_at;
.done(); let mut event: icalendar::Event = ev.into();
if yearly_recurring_events {
use chrono::Datelike;
use icalendar::Component;
const DAY_NAMES: [&str; 7] = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
event.add_property(
"RRULE",
&format!(
"FREQ=YEARLY;BYDAY={weekday};BYWEEKNO={weekno}",
weekday = DAY_NAMES
.get(end_time.weekday().num_days_from_monday() as usize)
.unwrap(),
weekno = end_time.iso_week().week(),
),
);
}
let cal = icalendar::Calendar::new().push(event).done();
let cal_as_string = (&cal.to_string()) let cal_as_string = (&cal.to_string())
.replacen( .replacen(

View File

@ -3,7 +3,7 @@
use { use {
crate::recipe::Recipe, crate::recipe::Recipe,
chrono::{/*Datelike, */ NaiveDate, NaiveDateTime, NaiveTime, Utc}, chrono::{NaiveDate, NaiveDateTime, NaiveTime, Utc},
icalendar::Event as CalEvent, icalendar::Event as CalEvent,
std::rc::Rc, std::rc::Rc,
}; };
@ -47,8 +47,6 @@ impl Event {
impl From<Event> for CalEvent { impl From<Event> for CalEvent {
fn from(ev: Event) -> Self { fn from(ev: Event) -> Self {
use icalendar::Component; use icalendar::Component;
// const DAY_NAMES: [&str; 7] = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"];
let start_time = ev.ends_at - ev.recipe.total_time(); let start_time = ev.ends_at - ev.recipe.total_time();
let cal_event = CalEvent::new() let cal_event = CalEvent::new()
@ -59,23 +57,6 @@ impl From<Event> for CalEvent {
.timestamp(Utc::now()) .timestamp(Utc::now())
.starts(start_time) .starts(start_time)
.ends(ev.ends_at) .ends(ev.ends_at)
/* FIXME
.add_property(
// TODO make configurable yearly repetition, for now this suits my personal uses
"RRULE",
&format!(
"FREQ=YEARLY;BYDAY={weekday};BYWEEKNO={weekno}",
weekday = DAY_NAMES
.get(start_time.weekday().num_days_from_monday() as usize)
.unwrap(),
weekno = start_time.iso_week().week(),
),
)*/
.add_property(
// TODO make configurable yearly repetition, for now this suits my personal uses
"RRULE",
"FREQ=YEARLY",
)
.done(); .done();
cal_event cal_event

View File

@ -69,6 +69,7 @@ fn setup_args() -> ArgMatches {
.arg(server_arg.clone()) .arg(server_arg.clone())
.arg(arg!(<calendar_name> "")) .arg(arg!(<calendar_name> ""))
.arg(arg!(<csv_file> "").value_parser(clap::value_parser!(PathBuf))) .arg(arg!(<csv_file> "").value_parser(clap::value_parser!(PathBuf)))
.arg(arg!(-y --yearly "Setup yearly recurring events (preserving the day of the week)"))
) )
.subcommand( .subcommand(
Command::new("purge") Command::new("purge")
@ -118,7 +119,14 @@ async fn parse_args(args: &ArgMatches) -> Result<()> {
let calendar_name = sub_matches let calendar_name = sub_matches
.get_one::<String>("calendar_name") .get_one::<String>("calendar_name")
.expect("<calendar_name> is a mandatory parameter, it cannot be missing"); .expect("<calendar_name> is a mandatory parameter, it cannot be missing");
commands::schedule_csv::with(&api_client, calendar_name.as_str(), &csv_file).await let yearly_recurring_events = sub_matches.contains_id("yearly");
commands::schedule_csv::with(
&api_client,
calendar_name.as_str(),
&csv_file,
yearly_recurring_events,
)
.await
} }
Some(("purge", sub_matches)) => { Some(("purge", sub_matches)) => {
let api_client = get_api_client(&sub_matches, &configuration)?; let api_client = get_api_client(&sub_matches, &configuration)?;