(* * Copyright (C) 2020, 2021 Alban Gruin * * ucs is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ucs is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with ucs. If not, see . *) open CalendarLib module StringSet = Set.Make (String) let to_date = Printer.Calendar.sprint "%Y%m%dT%H%M%S" let current_date () = to_date @@ Calendar.now () let ics_split_line = let max_line_length = 73 in let rec aux accu str = String.( let l = length str in if l > max_line_length then let b = sub str 0 max_line_length and e = sub str max_line_length (l - max_line_length) in aux (accu ^ b ^ "\r\n ") e else accu ^ str) in aux "" module Event = struct type t = { start: Calendar.t; stop: Calendar.t; summary: string; location: string; groups: string list; } let make start stop summary location groups = {start; stop; summary; location; groups} let to_string date event id = ["BEGIN:VEVENT"; "UID:" ^ date ^ "." ^ (string_of_int id) ^ "@ucs.pa1ch.fr"; "DTSTART:" ^ to_date event.start; "DTEND:" ^ to_date event.stop; "DTSTAMP:" ^ date; "SUMMARY:" ^ event.summary; "COMMENT:" ^ String.concat ", " event.groups; "LOCATION:" ^ event.location; "END:VEVENT\n"] |> List.map ics_split_line |> String.concat "\n" let has_groups groups event = List.fold_left (fun found group -> found || List.exists ((=) group) groups) false event.groups let get_groups event = event.groups end type t = Event.t list let make events = events let filter_groups groups = List.filter (Event.has_groups groups) let gen_vtimezone tz = if tz <> "" then ["BEGIN:VTIMEZONE"; "TZID:" ^ tz; "END:VTIMEZONE\n"] |> List.map ics_split_line |> String.concat "\n" else "" let get_all_groups events = let add_groups_to_set set event = List.fold_left (fun set elt -> StringSet.add elt set) set @@ Event.get_groups event in List.fold_left add_groups_to_set StringSet.empty events |> StringSet.to_seq let to_string tz events = let date = current_date () in let vtimezone = gen_vtimezone tz in let rec gen_events id str = function | [] -> str | event :: l -> gen_events (id + 1) (str ^ Event.to_string date event id) l in "BEGIN:VCALENDAR\n\ VERSION:2.0\n\ PRODID:-//ucs//\n" ^ vtimezone ^ gen_events 0 "" events ^ "END:VCALENDAR\n"