Matrix protocol in OCaml, Eio specialised
1(** Room directory and alias operations. *)
2
3(* Alias resolution *)
4type alias_info = {
5 room_id : Matrix_proto.Id.Room_id.t;
6 servers : string list;
7}
8
9let alias_info_jsont =
10 Jsont.Object.(
11 map (fun room_id servers -> { room_id; servers })
12 |> mem "room_id" Matrix_proto.Id.Room_id.jsont
13 |> mem "servers" (Jsont.list Jsont.string) ~dec_absent:[]
14 |> finish)
15
16let resolve_alias client ~alias =
17 let alias_str = Matrix_proto.Id.Room_alias.to_string alias in
18 let path = Printf.sprintf "/directory/room/%s" (Uri.pct_encode alias_str) in
19 match Client.get client ~path () with
20 | Error e -> Error e
21 | Ok body -> Client.decode_response alias_info_jsont body
22
23(* Create alias *)
24type create_alias_request = {
25 room_id : Matrix_proto.Id.Room_id.t;
26} [@@warning "-69"]
27
28let create_alias_request_jsont =
29 Jsont.Object.(
30 map (fun room_id -> { room_id })
31 |> mem "room_id" Matrix_proto.Id.Room_id.jsont
32 |> finish)
33
34let create_alias client ~alias ~room_id =
35 let alias_str = Matrix_proto.Id.Room_alias.to_string alias in
36 let path = Printf.sprintf "/directory/room/%s" (Uri.pct_encode alias_str) in
37 let request = { room_id } in
38 match Client.encode_body create_alias_request_jsont request with
39 | Error e -> Error e
40 | Ok body ->
41 match Client.put client ~path ~body () with
42 | Error e -> Error e
43 | Ok _ -> Ok ()
44
45(* Delete alias *)
46let delete_alias client ~alias =
47 let alias_str = Matrix_proto.Id.Room_alias.to_string alias in
48 let path = Printf.sprintf "/directory/room/%s" (Uri.pct_encode alias_str) in
49 match Client.delete client ~path () with
50 | Error e -> Error e
51 | Ok _ -> Ok ()
52
53(* Room visibility *)
54type visibility = [ `Public | `Private ]
55
56type visibility_response = {
57 visibility : string;
58}
59
60let visibility_response_jsont =
61 Jsont.Object.(
62 map (fun visibility -> { visibility })
63 |> mem "visibility" Jsont.string
64 |> finish)
65
66let get_visibility client ~room_id =
67 let room_id_str = Matrix_proto.Id.Room_id.to_string room_id in
68 let path = Printf.sprintf "/directory/list/room/%s" (Uri.pct_encode room_id_str) in
69 match Client.get client ~path () with
70 | Error e -> Error e
71 | Ok body ->
72 match Client.decode_response visibility_response_jsont body with
73 | Error e -> Error e
74 | Ok resp ->
75 match resp.visibility with
76 | "public" -> Ok `Public
77 | _ -> Ok `Private
78
79type set_visibility_request = {
80 visibility : string;
81} [@@warning "-69"]
82
83let set_visibility_request_jsont =
84 Jsont.Object.(
85 map (fun visibility -> { visibility })
86 |> mem "visibility" Jsont.string
87 |> finish)
88
89let set_visibility client ~room_id ~visibility =
90 let room_id_str = Matrix_proto.Id.Room_id.to_string room_id in
91 let path = Printf.sprintf "/directory/list/room/%s" (Uri.pct_encode room_id_str) in
92 let vis_str = match visibility with `Public -> "public" | `Private -> "private" in
93 let request = { visibility = vis_str } in
94 match Client.encode_body set_visibility_request_jsont request with
95 | Error e -> Error e
96 | Ok body ->
97 match Client.put client ~path ~body () with
98 | Error e -> Error e
99 | Ok _ -> Ok ()
100
101(* Room directory search *)
102type search_filter = {
103 generic_search_term : string option;
104 room_types : string list option;
105}
106
107type search_result = {
108 chunk : Rooms.public_room list;
109 next_batch : string option;
110 prev_batch : string option;
111 total_room_count_estimate : int option;
112}
113
114type search_request = {
115 filter : search_filter_request option;
116 limit : int option;
117 since : string option;
118} [@@warning "-69"]
119
120and search_filter_request = {
121 generic_search_term : string option;
122 room_types : string list option;
123} [@@warning "-69"]
124
125let search_filter_request_jsont =
126 Jsont.Object.(
127 map (fun generic_search_term room_types ->
128 { generic_search_term; room_types })
129 |> opt_mem "generic_search_term" Jsont.string ~enc:(fun (t : search_filter_request) -> t.generic_search_term)
130 |> opt_mem "room_types" (Jsont.list Jsont.string) ~enc:(fun (t : search_filter_request) -> t.room_types)
131 |> finish)
132
133let search_request_jsont =
134 Jsont.Object.(
135 map (fun filter limit since -> { filter; limit; since })
136 |> opt_mem "filter" search_filter_request_jsont ~enc:(fun (t : search_request) -> t.filter)
137 |> opt_mem "limit" Jsont.int ~enc:(fun (t : search_request) -> t.limit)
138 |> opt_mem "since" Jsont.string ~enc:(fun (t : search_request) -> t.since)
139 |> finish)
140
141(* Reuse public_room_jsont from Rooms - need to duplicate here *)
142let public_room_jsont : Rooms.public_room Jsont.t =
143 Jsont.Object.(
144 map (fun room_id name topic num_joined_members world_readable guest_can_join avatar_url canonical_alias ->
145 ({ room_id; name; topic; num_joined_members; world_readable; guest_can_join; avatar_url; canonical_alias } : Rooms.public_room))
146 |> mem "room_id" Matrix_proto.Id.Room_id.jsont
147 |> opt_mem "name" Jsont.string ~enc:(fun (t : Rooms.public_room) -> t.name)
148 |> opt_mem "topic" Jsont.string ~enc:(fun (t : Rooms.public_room) -> t.topic)
149 |> mem "num_joined_members" Jsont.int ~dec_absent:0 ~enc:(fun (t : Rooms.public_room) -> t.num_joined_members)
150 |> mem "world_readable" Jsont.bool ~dec_absent:false ~enc:(fun (t : Rooms.public_room) -> t.world_readable)
151 |> mem "guest_can_join" Jsont.bool ~dec_absent:false ~enc:(fun (t : Rooms.public_room) -> t.guest_can_join)
152 |> opt_mem "avatar_url" Jsont.string ~enc:(fun (t : Rooms.public_room) -> t.avatar_url)
153 |> opt_mem "canonical_alias" Jsont.string ~enc:(fun (t : Rooms.public_room) -> t.canonical_alias)
154 |> finish)
155
156let search_result_jsont =
157 Jsont.Object.(
158 map (fun chunk next_batch prev_batch total_room_count_estimate ->
159 { chunk; next_batch; prev_batch; total_room_count_estimate })
160 |> mem "chunk" (Jsont.list public_room_jsont) ~dec_absent:[]
161 |> opt_mem "next_batch" Jsont.string ~enc:(fun t -> t.next_batch)
162 |> opt_mem "prev_batch" Jsont.string ~enc:(fun t -> t.prev_batch)
163 |> opt_mem "total_room_count_estimate" Jsont.int ~enc:(fun t -> t.total_room_count_estimate)
164 |> finish)
165
166let search client ?server ?limit ?since ?(filter : search_filter option) () =
167 let path = "/publicRooms" in
168 let query = match server with
169 | Some s -> Some [("server", s)]
170 | None -> None
171 in
172 let filter_req : search_filter_request option = match filter with
173 | Some f -> Some { generic_search_term = f.generic_search_term; room_types = f.room_types }
174 | None -> None
175 in
176 let request = { filter = filter_req; limit; since } in
177 match Client.encode_body search_request_jsont request with
178 | Error e -> Error e
179 | Ok body ->
180 match Client.post client ~path ?query ~body () with
181 | Error e -> Error e
182 | Ok body -> Client.decode_response search_result_jsont body