Matrix protocol in OCaml, Eio specialised
at main 257 lines 10 kB view raw
1(** Room preview operations. 2 3 Get information about a room before joining it. *) 4 5(** Room preview information *) 6type room_preview = { 7 room_id : Matrix_proto.Id.Room_id.t; 8 name : string option; 9 topic : string option; 10 avatar_url : string option; 11 canonical_alias : Matrix_proto.Id.Room_alias.t option; 12 join_rule : Matrix_proto.Event.Join_rule.t option; 13 num_joined_members : int; 14 room_type : string option; 15 world_readable : bool; 16 guest_can_join : bool; 17 membership : Matrix_proto.Event.Membership.t option; 18} 19 20(** Summary returned by room summary endpoint (MSC3266) *) 21type room_summary = { 22 room_id : string; 23 membership : Matrix_proto.Event.Membership.t option; 24 is_encrypted : bool option; 25 room_name : string option; 26 topic : string option; 27 avatar_url : string option; 28 canonical_alias : string option; 29 joined_members_count : int option; 30 invited_members_count : int option; 31 room_version : string option; 32 room_type : string option; 33 join_rule : Matrix_proto.Event.Join_rule.t option; 34 guest_can_join : bool option; 35 world_readable : bool option; 36} 37 38let room_summary_jsont = 39 Jsont.Object.( 40 map (fun room_id membership is_encrypted room_name topic avatar_url 41 canonical_alias joined_members_count invited_members_count 42 room_version room_type join_rule guest_can_join world_readable -> 43 { room_id; membership; is_encrypted; room_name; topic; avatar_url; 44 canonical_alias; joined_members_count; invited_members_count; 45 room_version; room_type; join_rule; guest_can_join; world_readable }) 46 |> mem "room_id" Jsont.string ~enc:(fun t -> t.room_id) 47 |> opt_mem "membership" Matrix_proto.Event.Membership.jsont ~enc:(fun t -> t.membership) 48 |> opt_mem "is_encrypted" Jsont.bool ~enc:(fun t -> t.is_encrypted) 49 |> opt_mem "room_name" Jsont.string ~enc:(fun t -> t.room_name) 50 |> opt_mem "topic" Jsont.string ~enc:(fun t -> t.topic) 51 |> opt_mem "avatar_url" Jsont.string ~enc:(fun t -> t.avatar_url) 52 |> opt_mem "canonical_alias" Jsont.string ~enc:(fun t -> t.canonical_alias) 53 |> opt_mem "joined_members_count" Jsont.int ~enc:(fun t -> t.joined_members_count) 54 |> opt_mem "invited_members_count" Jsont.int ~enc:(fun t -> t.invited_members_count) 55 |> opt_mem "room_version" Jsont.string ~enc:(fun t -> t.room_version) 56 |> opt_mem "room_type" Jsont.string ~enc:(fun t -> t.room_type) 57 |> opt_mem "join_rule" Matrix_proto.Event.Join_rule.jsont ~enc:(fun t -> t.join_rule) 58 |> opt_mem "guest_can_join" Jsont.bool ~enc:(fun t -> t.guest_can_join) 59 |> opt_mem "world_readable" Jsont.bool ~enc:(fun t -> t.world_readable) 60 |> finish) 61 62(** Get room summary (MSC3266). 63 64 This is the preferred way to get room information before joining. *) 65let get_summary client ~room_id_or_alias ?via () = 66 let id_str = match room_id_or_alias with 67 | `Room_id id -> Matrix_proto.Id.Room_id.to_string id 68 | `Room_alias alias -> Matrix_proto.Id.Room_alias.to_string alias 69 in 70 let path = Printf.sprintf "/rooms/%s/summary" (Uri.pct_encode id_str) in 71 let query = match via with 72 | Some servers -> Some (List.map (fun s -> ("via", s)) servers) 73 | None -> None 74 in 75 match Client.get client ~path ?query () with 76 | Error e -> Error e 77 | Ok body -> Client.decode_response room_summary_jsont body 78 79(** Public room from directory listing *) 80type public_room = { 81 room_id : Matrix_proto.Id.Room_id.t; 82 name : string option; 83 topic : string option; 84 avatar_url : string option; 85 canonical_alias : Matrix_proto.Id.Room_alias.t option; 86 num_joined_members : int; 87 world_readable : bool; 88 guest_can_join : bool; 89 join_rule : Matrix_proto.Event.Join_rule.t option; 90 room_type : string option; 91} 92 93let public_room_jsont = 94 Jsont.Object.( 95 map (fun room_id name topic avatar_url canonical_alias num_joined_members 96 world_readable guest_can_join join_rule room_type -> 97 { room_id; name; topic; avatar_url; canonical_alias; num_joined_members; 98 world_readable; guest_can_join; join_rule; room_type }) 99 |> mem "room_id" Matrix_proto.Id.Room_id.jsont ~enc:(fun t -> t.room_id) 100 |> opt_mem "name" Jsont.string ~enc:(fun t -> t.name) 101 |> opt_mem "topic" Jsont.string ~enc:(fun t -> t.topic) 102 |> opt_mem "avatar_url" Jsont.string ~enc:(fun t -> t.avatar_url) 103 |> opt_mem "canonical_alias" Matrix_proto.Id.Room_alias.jsont ~enc:(fun t -> t.canonical_alias) 104 |> mem "num_joined_members" Jsont.int ~dec_absent:0 ~enc:(fun t -> t.num_joined_members) 105 |> mem "world_readable" Jsont.bool ~dec_absent:false ~enc:(fun t -> t.world_readable) 106 |> mem "guest_can_join" Jsont.bool ~dec_absent:false ~enc:(fun t -> t.guest_can_join) 107 |> opt_mem "join_rule" Matrix_proto.Event.Join_rule.jsont ~enc:(fun t -> t.join_rule) 108 |> opt_mem "room_type" Jsont.string ~enc:(fun t -> t.room_type) 109 |> finish) 110 111type public_rooms_response = { 112 chunk : public_room list; 113 next_batch : string option; 114 prev_batch : string option; 115 total_room_count_estimate : int option; 116} 117 118let public_rooms_response_jsont = 119 Jsont.Object.( 120 map (fun chunk next_batch prev_batch total_room_count_estimate -> 121 { chunk; next_batch; prev_batch; total_room_count_estimate }) 122 |> mem "chunk" (Jsont.list public_room_jsont) ~dec_absent:[] 123 ~enc:(fun t -> t.chunk) 124 |> opt_mem "next_batch" Jsont.string ~enc:(fun t -> t.next_batch) 125 |> opt_mem "prev_batch" Jsont.string ~enc:(fun t -> t.prev_batch) 126 |> opt_mem "total_room_count_estimate" Jsont.int 127 ~enc:(fun t -> t.total_room_count_estimate) 128 |> finish) 129 130(** Get list of public rooms. 131 132 @param limit Maximum number of rooms to return 133 @param since Pagination token 134 @param server Server to query for rooms *) 135let get_public_rooms client ?limit ?since ?server () = 136 let path = "/publicRooms" in 137 let query = 138 [] 139 |> (fun q -> match limit with Some l -> ("limit", string_of_int l) :: q | None -> q) 140 |> (fun q -> match since with Some s -> ("since", s) :: q | None -> q) 141 |> (fun q -> match server with Some s -> ("server", s) :: q | None -> q) 142 in 143 let query = if query = [] then None else Some query in 144 match Client.get client ~path ?query () with 145 | Error e -> Error e 146 | Ok body -> Client.decode_response public_rooms_response_jsont body 147 148(** Search filter for public rooms *) 149type public_rooms_filter = { 150 generic_search_term : string option; 151 room_types : string list option; 152} 153 154let public_rooms_filter_jsont = 155 Jsont.Object.( 156 map (fun generic_search_term room_types -> 157 { generic_search_term; room_types }) 158 |> opt_mem "generic_search_term" Jsont.string ~enc:(fun t -> t.generic_search_term) 159 |> opt_mem "room_types" (Jsont.list Jsont.string) ~enc:(fun t -> t.room_types) 160 |> finish) 161 162type search_public_rooms_request = { 163 limit : int option; 164 since : string option; 165 filter : public_rooms_filter option; 166 include_all_networks : bool option; 167 third_party_instance_id : string option; 168} [@@warning "-69"] 169 170let search_public_rooms_request_jsont = 171 Jsont.Object.( 172 map (fun limit since filter include_all_networks third_party_instance_id -> 173 { limit; since; filter; include_all_networks; third_party_instance_id }) 174 |> opt_mem "limit" Jsont.int ~enc:(fun t -> t.limit) 175 |> opt_mem "since" Jsont.string ~enc:(fun t -> t.since) 176 |> opt_mem "filter" public_rooms_filter_jsont ~enc:(fun t -> t.filter) 177 |> opt_mem "include_all_networks" Jsont.bool ~enc:(fun t -> t.include_all_networks) 178 |> opt_mem "third_party_instance_id" Jsont.string ~enc:(fun t -> t.third_party_instance_id) 179 |> finish) 180 181(** Search public rooms with filters. 182 183 @param search_term Text to search for 184 @param limit Maximum number of rooms 185 @param since Pagination token 186 @param room_types Filter by room type 187 @param server Server to query *) 188let search_public_rooms client ?search_term ?limit ?since ?room_types ?server () = 189 let path = "/publicRooms" in 190 let query = match server with 191 | Some s -> Some [("server", s)] 192 | None -> None 193 in 194 let filter = match search_term, room_types with 195 | None, None -> None 196 | _ -> Some { generic_search_term = search_term; room_types } 197 in 198 let request = { 199 limit; 200 since; 201 filter; 202 include_all_networks = None; 203 third_party_instance_id = None; 204 } in 205 match Client.encode_body search_public_rooms_request_jsont request with 206 | Error e -> Error e 207 | Ok body -> 208 match Client.post client ~path ~body ?query () with 209 | Error e -> Error e 210 | Ok resp_body -> Client.decode_response public_rooms_response_jsont resp_body 211 212(** Resolve a room alias to a room ID and servers. 213 214 @param room_alias The room alias to resolve *) 215let resolve_alias client ~room_alias = 216 let alias_str = Matrix_proto.Id.Room_alias.to_string room_alias in 217 let path = Printf.sprintf "/directory/room/%s" (Uri.pct_encode alias_str) in 218 let response_jsont = Jsont.Object.( 219 map (fun room_id servers -> (room_id, servers)) 220 |> mem "room_id" Matrix_proto.Id.Room_id.jsont 221 |> mem "servers" (Jsont.list Jsont.string) ~dec_absent:[] 222 |> finish) 223 in 224 match Client.get client ~path () with 225 | Error e -> Error e 226 | Ok body -> Client.decode_response response_jsont body 227 228(** Knock on a room (MSC2403). 229 230 Request to join a room that has knock join rules. 231 232 @param room_id_or_alias The room to knock on 233 @param reason Optional reason for the knock request 234 @param via Servers to try *) 235let knock client ~room_id_or_alias ?reason ?(via = []) () = 236 let id_str = match room_id_or_alias with 237 | `Room_id id -> Matrix_proto.Id.Room_id.to_string id 238 | `Room_alias alias -> Matrix_proto.Id.Room_alias.to_string alias 239 in 240 let path = Printf.sprintf "/knock/%s" (Uri.pct_encode id_str) in 241 let query = if via = [] then None else Some (List.map (fun s -> ("server_name", s)) via) in 242 let request_jsont = Jsont.Object.( 243 map (fun reason -> reason) 244 |> opt_mem "reason" Jsont.string ~enc:Fun.id 245 |> finish) 246 in 247 let response_jsont = Jsont.Object.( 248 map (fun room_id -> room_id) 249 |> mem "room_id" Matrix_proto.Id.Room_id.jsont 250 |> finish) 251 in 252 match Client.encode_body request_jsont reason with 253 | Error e -> Error e 254 | Ok body -> 255 match Client.post client ~path ~body ?query () with 256 | Error e -> Error e 257 | Ok resp_body -> Client.decode_response response_jsont resp_body