(** Push notification operations. *) (** Push rule kinds *) type rule_kind = | Override | Underride | Sender | Room | Content let rule_kind_to_string = function | Override -> "override" | Underride -> "underride" | Sender -> "sender" | Room -> "room" | Content -> "content" let rule_kind_of_string = function | "override" -> Ok Override | "underride" -> Ok Underride | "sender" -> Ok Sender | "room" -> Ok Room | "content" -> Ok Content | s -> Error ("Unknown rule kind: " ^ s) let rule_kind_jsont = Jsont.of_of_string ~kind:"rule_kind" ~enc:rule_kind_to_string rule_kind_of_string (** Push rule action *) type action = | Notify | Dont_notify | Coalesce | Set_tweak of string * Jsont.json (* For actions, we use a string codec as a simplification *) let action_jsont : action Jsont.t = Jsont.string |> Jsont.map ~dec:(function | "notify" -> Notify | "dont_notify" -> Dont_notify | "coalesce" -> Coalesce | _ -> Dont_notify) ~enc:(function | Notify -> "notify" | Dont_notify -> "dont_notify" | Coalesce -> "coalesce" | Set_tweak _ -> "notify") (** Push rule condition *) type condition = { kind : string; key : string option; pattern : string option; is_ : string option; } let condition_jsont = Jsont.Object.( map (fun kind key pattern is_ -> { kind; key; pattern; is_ }) |> mem "kind" Jsont.string ~enc:(fun t -> t.kind) |> opt_mem "key" Jsont.string ~enc:(fun t -> t.key) |> opt_mem "pattern" Jsont.string ~enc:(fun t -> t.pattern) |> opt_mem "is" Jsont.string ~enc:(fun t -> t.is_) |> finish) (** Push rule *) type rule = { rule_id : string; default : bool; enabled : bool; actions : action list; conditions : condition list option; pattern : string option; } let rule_jsont = Jsont.Object.( map (fun rule_id default enabled actions conditions pattern -> { rule_id; default; enabled; actions; conditions; pattern }) |> mem "rule_id" Jsont.string ~enc:(fun t -> t.rule_id) |> mem "default" Jsont.bool ~dec_absent:false ~enc:(fun t -> t.default) |> mem "enabled" Jsont.bool ~dec_absent:true ~enc:(fun t -> t.enabled) |> mem "actions" (Jsont.list action_jsont) ~dec_absent:[] ~enc:(fun t -> t.actions) |> opt_mem "conditions" (Jsont.list condition_jsont) ~enc:(fun t -> t.conditions) |> opt_mem "pattern" Jsont.string ~enc:(fun t -> t.pattern) |> finish) (** Push ruleset *) type ruleset = { override : rule list; underride : rule list; sender : rule list; room : rule list; content : rule list; } let ruleset_jsont = Jsont.Object.( map (fun override underride sender room content -> { override; underride; sender; room; content }) |> mem "override" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.override) |> mem "underride" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.underride) |> mem "sender" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.sender) |> mem "room" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.room) |> mem "content" (Jsont.list rule_jsont) ~dec_absent:[] ~enc:(fun t -> t.content) |> finish) type push_rules_response = { global : ruleset; } let push_rules_response_jsont = Jsont.Object.( map (fun global -> { global }) |> mem "global" ruleset_jsont ~enc:(fun t -> t.global) |> finish) (** Get all push rules. *) let get_push_rules client = match Client.get client ~path:"/pushrules/" () with | Error e -> Error e | Ok body -> Client.decode_response push_rules_response_jsont body (** Get a specific push rule. *) let get_push_rule client ~scope ~kind ~rule_id = let kind_str = rule_kind_to_string kind in let path = Printf.sprintf "/pushrules/%s/%s/%s" (Uri.pct_encode scope) (Uri.pct_encode kind_str) (Uri.pct_encode rule_id) in match Client.get client ~path () with | Error e -> Error e | Ok body -> Client.decode_response rule_jsont body (** Delete a push rule. *) let delete_push_rule client ~scope ~kind ~rule_id = let kind_str = rule_kind_to_string kind in let path = Printf.sprintf "/pushrules/%s/%s/%s" (Uri.pct_encode scope) (Uri.pct_encode kind_str) (Uri.pct_encode rule_id) in match Client.delete client ~path () with | Error e -> Error e | Ok _ -> Ok () (** Add or update a push rule. *) type add_rule_request = { actions : action list; conditions : condition list option; pattern : string option; } [@@warning "-69"] let add_rule_request_jsont = Jsont.Object.( map (fun actions conditions pattern -> { actions; conditions; pattern }) |> mem "actions" (Jsont.list action_jsont) ~enc:(fun t -> t.actions) |> opt_mem "conditions" (Jsont.list condition_jsont) ~enc:(fun t -> t.conditions) |> opt_mem "pattern" Jsont.string ~enc:(fun t -> t.pattern) |> finish) let set_push_rule client ~scope ~kind ~rule_id ~actions ?conditions ?pattern ?before ?after () = let kind_str = rule_kind_to_string kind in let path = Printf.sprintf "/pushrules/%s/%s/%s" (Uri.pct_encode scope) (Uri.pct_encode kind_str) (Uri.pct_encode rule_id) in let query = [] |> (fun q -> match before with Some b -> ("before", b) :: q | None -> q) |> (fun q -> match after with Some a -> ("after", a) :: q | None -> q) in let query = if query = [] then None else Some query in let request = { actions; conditions; pattern } in match Client.encode_body add_rule_request_jsont request with | Error e -> Error e | Ok body -> match Client.put client ~path ~body ?query () with | Error e -> Error e | Ok _ -> Ok () (** Enable or disable a push rule. *) type enabled_request = { enabled : bool; } [@@warning "-69"] let enabled_request_jsont = Jsont.Object.( map (fun enabled -> { enabled }) |> mem "enabled" Jsont.bool ~enc:(fun t -> t.enabled) |> finish) let set_push_rule_enabled client ~scope ~kind ~rule_id ~enabled = let kind_str = rule_kind_to_string kind in let path = Printf.sprintf "/pushrules/%s/%s/%s/enabled" (Uri.pct_encode scope) (Uri.pct_encode kind_str) (Uri.pct_encode rule_id) in let request = { enabled } in match Client.encode_body enabled_request_jsont request with | Error e -> Error e | Ok body -> match Client.put client ~path ~body () with | Error e -> Error e | Ok _ -> Ok () (** Set the actions for a push rule. *) type actions_request = { actions : action list; } [@@warning "-69"] let actions_request_jsont = Jsont.Object.( map (fun actions -> { actions }) |> mem "actions" (Jsont.list action_jsont) ~enc:(fun t -> t.actions) |> finish) let set_push_rule_actions client ~scope ~kind ~rule_id ~actions = let kind_str = rule_kind_to_string kind in let path = Printf.sprintf "/pushrules/%s/%s/%s/actions" (Uri.pct_encode scope) (Uri.pct_encode kind_str) (Uri.pct_encode rule_id) in let request = { actions } in match Client.encode_body actions_request_jsont request with | Error e -> Error e | Ok body -> match Client.put client ~path ~body () with | Error e -> Error e | Ok _ -> Ok () (** Pusher types *) type pusher_kind = | Http | Email let pusher_kind_to_string = function | Http -> "http" | Email -> "email" let pusher_kind_of_string = function | "http" -> Ok Http | "email" -> Ok Email | s -> Error ("Unknown pusher kind: " ^ s) let pusher_kind_jsont = Jsont.of_of_string ~kind:"pusher_kind" ~enc:pusher_kind_to_string pusher_kind_of_string type pusher_data = { url : string option; format : string option; } let pusher_data_jsont = Jsont.Object.( map (fun url format -> { url; format }) |> opt_mem "url" Jsont.string ~enc:(fun t -> t.url) |> opt_mem "format" Jsont.string ~enc:(fun t -> t.format) |> finish) type pusher = { pushkey : string; kind : pusher_kind; app_id : string; app_display_name : string; device_display_name : string; profile_tag : string option; lang : string; data : pusher_data; } let pusher_jsont = Jsont.Object.( map (fun pushkey kind app_id app_display_name device_display_name profile_tag lang data -> { pushkey; kind; app_id; app_display_name; device_display_name; profile_tag; lang; data }) |> mem "pushkey" Jsont.string ~enc:(fun t -> t.pushkey) |> mem "kind" pusher_kind_jsont ~enc:(fun t -> t.kind) |> mem "app_id" Jsont.string ~enc:(fun t -> t.app_id) |> mem "app_display_name" Jsont.string ~enc:(fun t -> t.app_display_name) |> mem "device_display_name" Jsont.string ~enc:(fun t -> t.device_display_name) |> opt_mem "profile_tag" Jsont.string ~enc:(fun t -> t.profile_tag) |> mem "lang" Jsont.string ~enc:(fun t -> t.lang) |> mem "data" pusher_data_jsont ~enc:(fun t -> t.data) |> finish) type pushers_response = { pushers : pusher list; } let pushers_response_jsont = Jsont.Object.( map (fun pushers -> { pushers }) |> mem "pushers" (Jsont.list pusher_jsont) ~dec_absent:[] ~enc:(fun t -> t.pushers) |> finish) (** Get all pushers for the current user. *) let get_pushers client = match Client.get client ~path:"/pushers" () with | Error e -> Error e | Ok body -> match Client.decode_response pushers_response_jsont body with | Error e -> Error e | Ok resp -> Ok resp.pushers (** Set a pusher. *) type set_pusher_request = { pushkey : string; kind : pusher_kind; app_id : string; app_display_name : string; device_display_name : string; profile_tag : string option; lang : string; data : pusher_data; append : bool option; } [@@warning "-69"] let set_pusher_request_jsont = Jsont.Object.( map (fun pushkey kind app_id app_display_name device_display_name profile_tag lang data append -> { pushkey; kind; app_id; app_display_name; device_display_name; profile_tag; lang; data; append }) |> mem "pushkey" Jsont.string |> mem "kind" pusher_kind_jsont |> mem "app_id" Jsont.string |> mem "app_display_name" Jsont.string |> mem "device_display_name" Jsont.string |> opt_mem "profile_tag" Jsont.string ~enc:(fun t -> t.profile_tag) |> mem "lang" Jsont.string |> mem "data" pusher_data_jsont |> opt_mem "append" Jsont.bool ~enc:(fun t -> t.append) |> finish) let set_pusher client ~pushkey ~kind ~app_id ~app_display_name ~device_display_name ?profile_tag ~lang ~data ?append () = let request = { pushkey; kind; app_id; app_display_name; device_display_name; profile_tag; lang; data; append } in match Client.encode_body set_pusher_request_jsont request with | Error e -> Error e | Ok body -> match Client.post client ~path:"/pushers/set" ~body () with | Error e -> Error e | Ok _ -> Ok () (** Delete a pusher by setting kind to null. *) let delete_pusher client ~pushkey ~app_id = (* Use raw json for the special null kind *) let body = Printf.sprintf {|{"pushkey":"%s","kind":null,"app_id":"%s"}|} pushkey app_id in match Client.post client ~path:"/pushers/set" ~body () with | Error e -> Error e | Ok _ -> Ok ()