blob: 5afff39e6a1fdd3a8ee663dc7f8122062a2fd42b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
(*
* Copyright (C) 2020 -- 2022 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 <http://www.gnu.org/licenses/>.
*)
open CalendarLib
module StringSet = Set.Make (String)
let rng_bound = int_of_float (2. ** 30.) - 1
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 option;
groups: string list;
}
let make start stop summary location groups =
{start; stop; summary; location; groups}
let to_string date event id =
let summary, location = match event.location with
| None -> "[PAS DE SALLE] " ^ event.summary, ""
| Some location -> event.summary, location in
let attendees =
List.map (fun group -> "ATTENDEE:" ^ group) event.groups
|> String.concat "\r\n" in
["BEGIN:VEVENT";
"UID:" ^ date ^ "." ^ (string_of_int id) ^ "@ucs.pa1ch.fr";
"DTSTART:" ^ to_date event.start;
"DTEND:" ^ to_date event.stop;
"DTSTAMP:" ^ date;
"SUMMARY:" ^ summary;
attendees;
"LOCATION:" ^ location;
"END:VEVENT\r\n"]
|> List.map ics_split_line
|> String.concat "\r\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 filter_groups groups =
List.filter (Event.has_groups groups)
let gen_vtimezone tz =
if tz <> "" then
["BEGIN:VTIMEZONE";
"TZID:" ^ tz;
"END:VTIMEZONE\r\n"]
|> List.map ics_split_line
|> String.concat "\r\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\r\n\
VERSION:2.0\r\n\
PRODID:-//ucs//\r\n"
^ vtimezone
^ gen_events (Random.int rng_bound) "" events
^ "END:VCALENDAR\r\n"
|