diff --git a/bin/eventPredicates.ml b/bin/eventPredicates.ml index 2021d01..4de96df 100644 --- a/bin/eventPredicates.ml +++ b/bin/eventPredicates.ml @@ -50,7 +50,7 @@ open Utils snippet: 'REM Mon Wed FROM 2025-09-01 UNTIL 2025-10-31 AT 09:00 MSG Standup' priorita: Subito - - id: P06 + - id: P06 ✅ pattern: Ricorrenza giornaliera semplice ics: "RRULE:FREQ=DAILY;[UNTIL|COUNT]" remind_support: nativo @@ -226,9 +226,6 @@ let collect_exdates rem ev : (Remind.rem, error) result = let exdates = Utils.get_exdates ev in Ok { rem with Remind.exdate = exdates } -let expand_recurrence rem _ev : (Remind.rem, error) result = - if List.length rem.Remind.recurring > 0 then skip else Ok rem - let yearly_simple_date rem ev : (Remind.rem, error) result = match ev.rrule with | Some (_, (`Yearly, None, None, [])) -> @@ -292,11 +289,12 @@ RRULE: (`Weekly, (Some `Until (`Utc (2026-07-01 09:00:00 +00:00))), None, []) *) match ev.rrule with | Some (_, (`Yearly, None, None, [])) -> Ok rem (* handled in yearly_simple_date *) - | Some (_, (`Weekly, count_or_until, interval, recurs)) -> + | Some (_, ((`Weekly as freq), count_or_until, interval, recurs)) + | Some (_, ((`Daily as freq), count_or_until, interval, recurs)) -> begin if List.length rem.recurring > 0 || List.length rem.exdate > 0 then ( Printf.eprintf "Warning: skipping complex recurrence with EXDATE/RDATE/overrides, not supported\t\t\tUID: %s\n" (Utils.get_uid ev); - debug_print_of_recurrence_and_skip ev (`Weekly, count_or_until, interval, recurs)) + debug_print_of_recurrence_and_skip ev (freq, count_or_until, interval, recurs)) else let days = ListLabels.filter_map recurs ~f:(function @@ -310,21 +308,21 @@ RRULE: (`Weekly, (Some `Until (`Utc (2026-07-01 09:00:00 +00:00))), None, []) | `Weekday `Monday -> Some `Monday | _ -> None) in - Ok { rem with Remind.weekly = Some { count_or_until; interval; byday = days; week_start } } + match freq with + | `Daily -> Ok { rem with Remind.weekly = None; Remind.daily = Some { count_or_until; interval; week_start } } + | `Weekly -> + Ok + { + rem with + Remind.daily = None; + Remind.weekly = Some { count_or_until; interval; byday = days; week_start }; + } end | Some (_, recurs) -> debug_print_of_recurrence_and_skip ev recurs | None -> Ok rem let all_collectors : collector list = - [ - collect_uuid; - collect_summary; - collect_start_end_duration; - collect_exdates; - expand_recurrence; - yearly_simple_date; - simple_recurrence; - ] + [ collect_uuid; collect_summary; collect_start_end_duration; collect_exdates; yearly_simple_date; simple_recurrence ] let remind_of_event (source : string) (ev : Icalendar.event list) : (Remind.rem, error) result = let () = if List.length ev = 0 then failwith "No events provided" in diff --git a/bin/remind.ml b/bin/remind.ml index afc51d3..8b2bbc6 100644 --- a/bin/remind.ml +++ b/bin/remind.ml @@ -10,6 +10,13 @@ type simple_weekly = { } (** A simple weekly REM command *) +type simple_daily = { + count_or_until : Icalendar.count_or_until option; + interval : int option; (** Optional interval for daily recurrence, default is 1 *) + week_start : week_first_day option; (** First day of the week for weekly recurrence *) +} +(** A simple daily REM command *) + type rem = { source : string; (** Source file or identifier for the reminder *) original_uuid : string; (** Original UID from the iCalendar event *) @@ -20,6 +27,7 @@ type rem = { duration : Timedesc.Span.t option; (** Optional duration for timed events *) yearly : (int * int) option; (** Optional simple yearly recurrence (month, day) *) weekly : simple_weekly option; (** Optional simple weekly recurrence *) + daily : simple_daily option; (** Optional simple daily recurrence *) recurring : Icalendar.event list; (** List of events that are part of the same recurring series: these are only the overrides, not the master event *) @@ -38,6 +46,7 @@ let empty = duration = None; yearly = None; weekly = None; + daily = None; recurring = []; exdate = []; } @@ -49,11 +58,15 @@ let add_info b uuid = Buffer.add_string b (spf "INFO \"UID: %s\" " uuid) let add_date b date = Buffer.add_string b (Timedesc.Date.to_rfc3339 date) let add_weekday b wd = Buffer.add_string b (spf "%s " (string_of_weekday wd)) -let add_interval b w = +let add_interval b (w : simple_weekly) = let n = Option.value ~default:1 w.interval in Buffer.add_string b (spf "*%d " (n * 7)) -let add_until b rem w = +let add_interval_daily b (d : simple_daily) = + let n = Option.value ~default:1 d.interval in + Buffer.add_string b (spf "*%d " n) + +let add_until b rem (w : simple_weekly) = match w.count_or_until with | None -> () | Some (`Until d) -> @@ -71,6 +84,17 @@ let add_until b rem w = let until = Timedesc.Date.add ~days:((count * 7 * iv) - sub) rem.date in Buffer.add_string b (spf "UNTIL %s " (Timedesc.Date.to_rfc3339 until)) +let add_until_daily b rem (d : simple_daily) = + match d.count_or_until with + | None -> () + | Some (`Until dt) -> + let ts = timedesc_of_utc_or_timestamp_local dt in + Buffer.add_string b (spf "UNTIL %s " (Timedesc.Date.to_rfc3339 (Timedesc.date ts))) + | Some (`Count count) -> + let iv = Option.value ~default:1 d.interval in + let until = Timedesc.Date.add ~days:((count - 1) * iv) rem.date in + Buffer.add_string b (spf "UNTIL %s " (Timedesc.Date.to_rfc3339 until)) + let add_at b = function | Some t -> Buffer.add_string b (spf " AT %s" (string_of_time t)) | None -> () @@ -87,7 +111,20 @@ let add_msg b summary = Buffer.add_string b (spf " MSG %s\n" summary) (* ── rendering ────────────────────────────────────────────────── *) -let render_weekly rem w = +let render_daily rem (d : simple_daily) = + let b = Buffer.create 256 in + add_rem b; + add_info b rem.original_uuid; + add_date b rem.date; + Buffer.add_char b ' '; + add_interval_daily b d; + add_until_daily b rem d; + add_at b rem.time; + add_duration b rem.duration; + add_msg b rem.summary; + Buffer.contents b + +let render_weekly rem (w : simple_weekly) = let b = Buffer.create 256 in List.iter (fun wd -> @@ -125,9 +162,12 @@ let render_yearly month day summary = (* ── dispatcher ───────────────────────────────────────────────── *) let string_of_rem rem = - match rem.weekly with - | Some w -> render_weekly rem w + match rem.daily with + | Some d -> render_daily rem d | None -> ( - match rem.yearly with - | Some (month, day) -> render_yearly month day rem.summary - | None -> render_single rem) + match rem.weekly with + | Some w -> render_weekly rem w + | None -> ( + match rem.yearly with + | Some (month, day) -> render_yearly month day rem.summary + | None -> render_single rem))