Matrix protocol in OCaml, Eio specialised
at main 368 lines 11 kB view raw
1(** Push notification operations. *) 2 3(** Push rule kinds *) 4type rule_kind = 5 | Override 6 | Underride 7 | Sender 8 | Room 9 | Content 10 11let rule_kind_to_string = function 12 | Override -> "override" 13 | Underride -> "underride" 14 | Sender -> "sender" 15 | Room -> "room" 16 | Content -> "content" 17 18let rule_kind_of_string = function 19 | "override" -> Ok Override 20 | "underride" -> Ok Underride 21 | "sender" -> Ok Sender 22 | "room" -> Ok Room 23 | "content" -> Ok Content 24 | s -> Error ("Unknown rule kind: " ^ s) 25 26let rule_kind_jsont = 27 Jsont.of_of_string ~kind:"rule_kind" 28 ~enc:rule_kind_to_string 29 rule_kind_of_string 30 31(** Push rule action *) 32type action = 33 | Notify 34 | Dont_notify 35 | Coalesce 36 | Set_tweak of string * Jsont.json 37 38(* For actions, we use a string codec as a simplification *) 39let action_jsont : action Jsont.t = 40 Jsont.string 41 |> Jsont.map 42 ~dec:(function 43 | "notify" -> Notify 44 | "dont_notify" -> Dont_notify 45 | "coalesce" -> Coalesce 46 | _ -> Dont_notify) 47 ~enc:(function 48 | Notify -> "notify" 49 | Dont_notify -> "dont_notify" 50 | Coalesce -> "coalesce" 51 | Set_tweak _ -> "notify") 52 53(** Push rule condition *) 54type condition = { 55 kind : string; 56 key : string option; 57 pattern : string option; 58 is_ : string option; 59} 60 61let condition_jsont = 62 Jsont.Object.( 63 map (fun kind key pattern is_ -> { kind; key; pattern; is_ }) 64 |> mem "kind" Jsont.string ~enc:(fun t -> t.kind) 65 |> opt_mem "key" Jsont.string ~enc:(fun t -> t.key) 66 |> opt_mem "pattern" Jsont.string ~enc:(fun t -> t.pattern) 67 |> opt_mem "is" Jsont.string ~enc:(fun t -> t.is_) 68 |> finish) 69 70(** Push rule *) 71type rule = { 72 rule_id : string; 73 default : bool; 74 enabled : bool; 75 actions : action list; 76 conditions : condition list option; 77 pattern : string option; 78} 79 80let rule_jsont = 81 Jsont.Object.( 82 map (fun rule_id default enabled actions conditions pattern -> 83 { rule_id; default; enabled; actions; conditions; pattern }) 84 |> mem "rule_id" Jsont.string ~enc:(fun t -> t.rule_id) 85 |> mem "default" Jsont.bool ~dec_absent:false ~enc:(fun t -> t.default) 86 |> mem "enabled" Jsont.bool ~dec_absent:true ~enc:(fun t -> t.enabled) 87 |> mem "actions" (Jsont.list action_jsont) ~dec_absent:[] ~enc:(fun t -> t.actions) 88 |> opt_mem "conditions" (Jsont.list condition_jsont) ~enc:(fun t -> t.conditions) 89 |> opt_mem "pattern" Jsont.string ~enc:(fun t -> t.pattern) 90 |> finish) 91 92(** Push ruleset *) 93type ruleset = { 94 override : rule list; 95 underride : rule list; 96 sender : rule list; 97 room : rule list; 98 content : rule list; 99} 100 101let ruleset_jsont = 102 Jsont.Object.( 103 map (fun override underride sender room content -> 104 { override; underride; sender; room; content }) 105 |> mem "override" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.override) 106 |> mem "underride" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.underride) 107 |> mem "sender" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.sender) 108 |> mem "room" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.room) 109 |> mem "content" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.content) 110 |> finish) 111 112type push_rules_response = { 113 global : ruleset; 114} 115 116let push_rules_response_jsont = 117 Jsont.Object.( 118 map (fun global -> { global }) 119 |> mem "global" ruleset_jsont ~enc:(fun t -> t.global) 120 |> finish) 121 122(** Get all push rules. *) 123let get_push_rules client = 124 match Client.get client ~path:"/pushrules/" () with 125 | Error e -> Error e 126 | Ok body -> Client.decode_response push_rules_response_jsont body 127 128(** Get a specific push rule. *) 129let get_push_rule client ~scope ~kind ~rule_id = 130 let kind_str = rule_kind_to_string kind in 131 let path = Printf.sprintf "/pushrules/%s/%s/%s" 132 (Uri.pct_encode scope) 133 (Uri.pct_encode kind_str) 134 (Uri.pct_encode rule_id) 135 in 136 match Client.get client ~path () with 137 | Error e -> Error e 138 | Ok body -> Client.decode_response rule_jsont body 139 140(** Delete a push rule. *) 141let delete_push_rule client ~scope ~kind ~rule_id = 142 let kind_str = rule_kind_to_string kind in 143 let path = Printf.sprintf "/pushrules/%s/%s/%s" 144 (Uri.pct_encode scope) 145 (Uri.pct_encode kind_str) 146 (Uri.pct_encode rule_id) 147 in 148 match Client.delete client ~path () with 149 | Error e -> Error e 150 | Ok _ -> Ok () 151 152(** Add or update a push rule. *) 153type add_rule_request = { 154 actions : action list; 155 conditions : condition list option; 156 pattern : string option; 157} [@@warning "-69"] 158 159let add_rule_request_jsont = 160 Jsont.Object.( 161 map (fun actions conditions pattern -> 162 { actions; conditions; pattern }) 163 |> mem "actions" (Jsont.list action_jsont) ~enc:(fun t -> t.actions) 164 |> opt_mem "conditions" (Jsont.list condition_jsont) ~enc:(fun t -> t.conditions) 165 |> opt_mem "pattern" Jsont.string ~enc:(fun t -> t.pattern) 166 |> finish) 167 168let set_push_rule client ~scope ~kind ~rule_id 169 ~actions ?conditions ?pattern ?before ?after () = 170 let kind_str = rule_kind_to_string kind in 171 let path = Printf.sprintf "/pushrules/%s/%s/%s" 172 (Uri.pct_encode scope) 173 (Uri.pct_encode kind_str) 174 (Uri.pct_encode rule_id) 175 in 176 let query = 177 [] 178 |> (fun q -> match before with Some b -> ("before", b) :: q | None -> q) 179 |> (fun q -> match after with Some a -> ("after", a) :: q | None -> q) 180 in 181 let query = if query = [] then None else Some query in 182 let request = { actions; conditions; pattern } in 183 match Client.encode_body add_rule_request_jsont request with 184 | Error e -> Error e 185 | Ok body -> 186 match Client.put client ~path ~body ?query () with 187 | Error e -> Error e 188 | Ok _ -> Ok () 189 190(** Enable or disable a push rule. *) 191type enabled_request = { 192 enabled : bool; 193} [@@warning "-69"] 194 195let enabled_request_jsont = 196 Jsont.Object.( 197 map (fun enabled -> { enabled }) 198 |> mem "enabled" Jsont.bool ~enc:(fun t -> t.enabled) 199 |> finish) 200 201let set_push_rule_enabled client ~scope ~kind ~rule_id ~enabled = 202 let kind_str = rule_kind_to_string kind in 203 let path = Printf.sprintf "/pushrules/%s/%s/%s/enabled" 204 (Uri.pct_encode scope) 205 (Uri.pct_encode kind_str) 206 (Uri.pct_encode rule_id) 207 in 208 let request = { enabled } in 209 match Client.encode_body enabled_request_jsont request with 210 | Error e -> Error e 211 | Ok body -> 212 match Client.put client ~path ~body () with 213 | Error e -> Error e 214 | Ok _ -> Ok () 215 216(** Set the actions for a push rule. *) 217type actions_request = { 218 actions : action list; 219} [@@warning "-69"] 220 221let actions_request_jsont = 222 Jsont.Object.( 223 map (fun actions -> { actions }) 224 |> mem "actions" (Jsont.list action_jsont) ~enc:(fun t -> t.actions) 225 |> finish) 226 227let set_push_rule_actions client ~scope ~kind ~rule_id ~actions = 228 let kind_str = rule_kind_to_string kind in 229 let path = Printf.sprintf "/pushrules/%s/%s/%s/actions" 230 (Uri.pct_encode scope) 231 (Uri.pct_encode kind_str) 232 (Uri.pct_encode rule_id) 233 in 234 let request = { actions } in 235 match Client.encode_body actions_request_jsont request with 236 | Error e -> Error e 237 | Ok body -> 238 match Client.put client ~path ~body () with 239 | Error e -> Error e 240 | Ok _ -> Ok () 241 242(** Pusher types *) 243type pusher_kind = 244 | Http 245 | Email 246 247let pusher_kind_to_string = function 248 | Http -> "http" 249 | Email -> "email" 250 251let pusher_kind_of_string = function 252 | "http" -> Ok Http 253 | "email" -> Ok Email 254 | s -> Error ("Unknown pusher kind: " ^ s) 255 256let pusher_kind_jsont = 257 Jsont.of_of_string ~kind:"pusher_kind" 258 ~enc:pusher_kind_to_string 259 pusher_kind_of_string 260 261type pusher_data = { 262 url : string option; 263 format : string option; 264} 265 266let pusher_data_jsont = 267 Jsont.Object.( 268 map (fun url format -> { url; format }) 269 |> opt_mem "url" Jsont.string ~enc:(fun t -> t.url) 270 |> opt_mem "format" Jsont.string ~enc:(fun t -> t.format) 271 |> finish) 272 273type pusher = { 274 pushkey : string; 275 kind : pusher_kind; 276 app_id : string; 277 app_display_name : string; 278 device_display_name : string; 279 profile_tag : string option; 280 lang : string; 281 data : pusher_data; 282} 283 284let pusher_jsont = 285 Jsont.Object.( 286 map (fun pushkey kind app_id app_display_name device_display_name 287 profile_tag lang data -> 288 { pushkey; kind; app_id; app_display_name; device_display_name; 289 profile_tag; lang; data }) 290 |> mem "pushkey" Jsont.string ~enc:(fun t -> t.pushkey) 291 |> mem "kind" pusher_kind_jsont ~enc:(fun t -> t.kind) 292 |> mem "app_id" Jsont.string ~enc:(fun t -> t.app_id) 293 |> mem "app_display_name" Jsont.string ~enc:(fun t -> t.app_display_name) 294 |> mem "device_display_name" Jsont.string ~enc:(fun t -> t.device_display_name) 295 |> opt_mem "profile_tag" Jsont.string ~enc:(fun t -> t.profile_tag) 296 |> mem "lang" Jsont.string ~enc:(fun t -> t.lang) 297 |> mem "data" pusher_data_jsont ~enc:(fun t -> t.data) 298 |> finish) 299 300type pushers_response = { 301 pushers : pusher list; 302} 303 304let pushers_response_jsont = 305 Jsont.Object.( 306 map (fun pushers -> { pushers }) 307 |> mem "pushers" (Jsont.list pusher_jsont) ~dec_absent:[] ~enc:(fun t -> t.pushers) 308 |> finish) 309 310(** Get all pushers for the current user. *) 311let get_pushers client = 312 match Client.get client ~path:"/pushers" () with 313 | Error e -> Error e 314 | Ok body -> 315 match Client.decode_response pushers_response_jsont body with 316 | Error e -> Error e 317 | Ok resp -> Ok resp.pushers 318 319(** Set a pusher. *) 320type set_pusher_request = { 321 pushkey : string; 322 kind : pusher_kind; 323 app_id : string; 324 app_display_name : string; 325 device_display_name : string; 326 profile_tag : string option; 327 lang : string; 328 data : pusher_data; 329 append : bool option; 330} [@@warning "-69"] 331 332let set_pusher_request_jsont = 333 Jsont.Object.( 334 map (fun pushkey kind app_id app_display_name device_display_name 335 profile_tag lang data append -> 336 { pushkey; kind; app_id; app_display_name; device_display_name; 337 profile_tag; lang; data; append }) 338 |> mem "pushkey" Jsont.string 339 |> mem "kind" pusher_kind_jsont 340 |> mem "app_id" Jsont.string 341 |> mem "app_display_name" Jsont.string 342 |> mem "device_display_name" Jsont.string 343 |> opt_mem "profile_tag" Jsont.string ~enc:(fun t -> t.profile_tag) 344 |> mem "lang" Jsont.string 345 |> mem "data" pusher_data_jsont 346 |> opt_mem "append" Jsont.bool ~enc:(fun t -> t.append) 347 |> finish) 348 349let set_pusher client ~pushkey ~kind ~app_id ~app_display_name 350 ~device_display_name ?profile_tag ~lang ~data ?append () = 351 let request = { 352 pushkey; kind; app_id; app_display_name; device_display_name; 353 profile_tag; lang; data; append 354 } in 355 match Client.encode_body set_pusher_request_jsont request with 356 | Error e -> Error e 357 | Ok body -> 358 match Client.post client ~path:"/pushers/set" ~body () with 359 | Error e -> Error e 360 | Ok _ -> Ok () 361 362(** Delete a pusher by setting kind to null. *) 363let delete_pusher client ~pushkey ~app_id = 364 (* Use raw json for the special null kind *) 365 let body = Printf.sprintf {|{"pushkey":"%s","kind":null,"app_id":"%s"}|} pushkey app_id in 366 match Client.post client ~path:"/pushers/set" ~body () with 367 | Error e -> Error e 368 | Ok _ -> Ok ()