Skip to content

Commit

Permalink
add interaction api
Browse files Browse the repository at this point in the history
  • Loading branch information
koonwen committed Oct 7, 2024
1 parent e6bc519 commit b97128d
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 1 deletion.
42 changes: 42 additions & 0 deletions lib/slack.atd
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,45 @@ type slack_api_error = [

type 'ok slack_response = ('ok, slack_api_error) http_response
<json adapter.ocaml="Atd_adapters.Slack_response_adapter">

type interaction = [
| Shortcut <json name="shortcut"> of message_actions
| Message_actions <json name="message_action"> of message_actions
(* | Block_actions <json name="block_actions"> of *)
(* | View_submission <json name="view_submission"> of *)
(* | View_closed <json name="view_closed"> of *)
] <ocaml repr="classic"> <json adapter.ocaml="Atdgen_runtime.Json_adapter.Type_field">

type message_actions = {
callback_id: string;
trigger_id: string;
token: string;
team: interaction_team;
?response_url: string nullable;
?message: interaction_message nullable;
?user: interaction_user nullable;
?channel : interaction_channel nullable;
}

type interaction_user = {
id: string;
?name : string nullable;
?username: string nullable;
?team_id: string nullable;
}

type interaction_team = {
id: string;
?domain: string nullable;
}

type interaction_channel = {
id: string;
?name: string nullable;
}

type interaction_message = {
user : string;
ts : string;
text : string;
}
10 changes: 9 additions & 1 deletion lib/utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ open Slack_t
(***************** General Slack Utilities for Handling Event Hooks *****************)

(** [ validate_signature signing_key headers body ] validate the signature
from a Slack event API hook.
from a Slack event API hook.
*)
let validate_signature ?(version = "v0") ?signing_key ~headers body =
match signing_key with
Expand Down Expand Up @@ -47,6 +47,14 @@ let process_slack_event (ctx : Context.t) headers body ~event_handler =
event_handler notification.event
)

let process_slack_interaction (ctx : Context.t) headers body ~interaction_handler =
match interaction_of_string body with
| exception Yojson.Json_error e -> Lwt.return_error (sprintf "Invalid interaction: %s" e)
| Shortcut i | Message_actions i ->
match validate_signature ?signing_key:ctx.secrets.slack_signing_secret ~headers body with
| Error e -> Lwt.return_error (sprintf "signature not validated: %s" e)
| Ok () -> interaction_handler i

(***************** Utilities over Slack API returns *****************)

(** conversation types of a [Slack channel] *)
Expand Down
1 change: 1 addition & 0 deletions lib_test/dune
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
(deps
(source_tree slack-api-cache)
(source_tree mock-slack-events)
(source_tree mock-slack-interactions)
secrets.json)
(action
(with-stdout-to
Expand Down
16 changes: 16 additions & 0 deletions lib_test/mock-slack-interactions/global_shortcut.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"type": "shortcut",
"token": "XXXXXXXXXXXXX",
"action_ts": "1581106241.371594",
"team": {
"id": "TXXXXXXXX",
"domain": "shortcuts-test"
},
"user": {
"id": "UXXXXXXXXX",
"username": "aman",
"team_id": "TXXXXXXXX"
},
"callback_id": "shortcut_create_task",
"trigger_id": "944799105734.773906753841.38b5894552bdd4a780554ee59d1f3638"
}
25 changes: 25 additions & 0 deletions lib_test/mock-slack-interactions/message_shortcut.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"token": "Nj2rfC2hU8mAfgaJLemZgO7H",
"callback_id": "chirp_message",
"type": "message_action",
"trigger_id": "13345224609.8534564800.6f8ab1f53e13d0cd15f96106292d5536",
"response_url": "https://hooks.slack.com/app-actions/T0MJR11A4/21974584944/yk1S9ndf35Q1flupVG5JbpM6",
"team": {
"id": "T0MJRM1A7",
"domain": "pandamonium"
},
"channel": {
"id": "D0LFFBKLZ",
"name": "cats"
},
"user": {
"id": "U0D15K92L",
"name": "dr_maomao"
},
"message": {
"type": "message",
"user": "U0MJRG1AL",
"ts": "1516229207.000133",
"text": "World's smallest big cat! <https://youtube.com/watch?v=W86cTIoMv2U>"
}
}
25 changes: 25 additions & 0 deletions lib_test/slack_payloads.expected
Original file line number Diff line number Diff line change
Expand Up @@ -724,3 +724,28 @@ listing at cursor #dXNlcjpVMDQ2WE4wTTJSNQ==...
"event_id": "Ev04C7PRDB53",
"event_time": 1669265351
}
===== file mock-slack-interactions/global_shortcut.json =====
{
"type": "shortcut",
"callback_id": "shortcut_create_task",
"trigger_id": "944799105734.773906753841.38b5894552bdd4a780554ee59d1f3638",
"token": "XXXXXXXXXXXXX",
"team": { "id": "TXXXXXXXX", "domain": "shortcuts-test" },
"user": { "id": "UXXXXXXXXX", "username": "aman", "team_id": "TXXXXXXXX" }
}
===== file mock-slack-interactions/message_shortcut.json =====
{
"type": "message_action",
"callback_id": "chirp_message",
"trigger_id": "13345224609.8534564800.6f8ab1f53e13d0cd15f96106292d5536",
"token": "Nj2rfC2hU8mAfgaJLemZgO7H",
"team": { "id": "T0MJRM1A7", "domain": "pandamonium" },
"response_url": "https://hooks.slack.com/app-actions/T0MJR11A4/21974584944/yk1S9ndf35Q1flupVG5JbpM6",
"message": {
"user": "U0MJRG1AL",
"ts": "1516229207.000133",
"text": "World's smallest big cat! <https://youtube.com/watch?v=W86cTIoMv2U>"
},
"user": { "id": "U0D15K92L", "name": "dr_maomao" },
"channel": { "id": "D0LFFBKLZ", "name": "cats" }
}
24 changes: 24 additions & 0 deletions lib_test/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,31 @@ let process_events path =
printf "failed to process slack event %s due to:\n%s\n" path (Printexc.to_string e);
Lwt.return_unit

let mock_slack_interaction_dir = "mock-slack-interactions"

let get_mock_slack_interactions () =
List.map (Filename.concat mock_slack_interaction_dir) (get_sorted_files_from mock_slack_interaction_dir)

let process_interactions path =
Printf.printf "===== file %s =====\n" path;
try
let interaction = Slack_j.interaction_of_string (get_local_file path) in
let json =
interaction |> Slack_j.string_of_interaction |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string
in
printf "%s\n" json;
Lwt.return_unit
with
| Yojson.Json_error e ->
printf "failed to parse slack interaction json %s due to: %s\n" path e;
Lwt.return_unit
| e ->
printf "failed to process slack interaction %s due to:\n%s\n" path (Printexc.to_string e);
Lwt.return_unit

let () =
let slack_events = get_mock_slack_events () in
let slack_interactions = get_mock_slack_interactions () in
Lwt_main.run
(let%lwt () = Lwt_list.iter_s process_send_msg simple_text_msg_cases in
let%lwt () = Lwt_list.iter_s process_send_msg_as_user text_msg_as_user_cases in
Expand All @@ -257,5 +280,6 @@ let () =
let%lwt () = Lwt_list.iter_s process_list_usergroup_users list_usergroup_users_usergroup_id_list in
let%lwt () = Lwt_list.iter_s process_list_users list_users_cursors_list in
let%lwt () = Lwt_list.iter_s process_events slack_events in
let%lwt () = Lwt_list.iter_s process_interactions slack_interactions in
Lwt.return_unit
)

0 comments on commit b97128d

Please sign in to comment.