Files
ical2rem/bin/main.ml
2025-09-01 00:00:00 +02:00

45 lines
1.9 KiB
OCaml

open Remind_sync
module Map = MoreLabels.Map.Make (String)
(*
We use a list of events here because there can be multiple events with the same UID, and we want to preserve all of
them. This is important for handling cases where there are multiple events with the same UID but different properties
(e.g., due to updates or recurring events or cancellations).
*)
let ical2rem ical_file =
let ic = open_in ical_file in
let n = in_channel_length ic in
let s = Bytes.create n in
really_input ic s 0 n;
close_in ic;
let cal_or_error = Icalendar.parse (Bytes.unsafe_to_string s) in
match cal_or_error with
| Error e ->
if e = ": not enough input" then
exit 0 (* This is a common error when the file is empty, so we treat it as a non-error case *)
else prerr_endline ("Error parsing iCalendar file: " ^ e)
| Ok (_, components) -> begin
let events_map : Icalendar.event list Map.t =
ListLabels.fold_left ~init:Map.empty components ~f:(fun acc comp ->
match comp with
| `Event ev ->
let uid = Utils.get_uid ev in
let event_list = Map.find_opt uid acc |> Option.value ~default:[] in
Map.add ~key:uid ~data:(ev :: event_list) acc
| _ -> acc (* Ignore non-event components *))
in
(* Now revert all the lists *)
let events_map = Map.map ~f:List.rev events_map in
(* Printf.printf "Events: %d\n\n" (Map.cardinal events_map); *)
Map.iter events_map ~f:(fun ~key:uid ~data:events ->
let rem_or_error = EventPredicates.remind_of_event events in
match rem_or_error with
| Ok rem -> begin Printf.printf "%s\n" (Remind.string_of_rem rem) end
| Error (EventPredicates.Invalid_date s) -> Printf.eprintf "UID: %s Invalid date: %s\n" uid s
| Error Skip -> Printf.eprintf "UID: %s Skipped\n" uid)
end
let () = if !Sys.interactive then () else exit (CommandLine.main ical2rem)