Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add interaction api #7

Merged
merged 6 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions lib/slack.atd
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,46 @@ 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 json
| View_submission <json name="view_submission"> of json
| View_closed <json name="view_closed"> of json
] <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;
}
15 changes: 14 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,19 @@ let process_slack_event (ctx : Context.t) headers body ~event_handler =
event_handler notification.event
)

(** [ process_slack_interaction ] handles slack interactions which are
koonwen marked this conversation as resolved.
Show resolved Hide resolved
similar to slack notifications except that they are specifically
for handling features such as block actions, shortcuts and modals
*)
let process_slack_interaction (ctx : Context.t) headers body ~interaction_handler =
let payload = Uri.query_of_encoded body |> List.assoc "payload" |> List.hd in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

List.hd is a code smell. It's better to use a match and fail with a clear message if the list is empty. It also becomes self documented this way

match interaction_of_string payload with
| exception Yojson.Json_error e -> Lwt.return_error (sprintf "Invalid interaction: %s" e)
| interaction ->
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 interaction

(***************** 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
49 changes: 49 additions & 0 deletions lib_test/mock-slack-interactions/block_action1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"type": "block_actions",
"team": {
"id": "T9TK3CUKW",
"domain": "example"
},
"user": {
"id": "UA8RXUSPL",
"username": "jtorrance",
"team_id": "T9TK3CUKW"
},
"api_app_id": "AABA1ABCD",
"token": "9s8d9as89d8as9d8as989",
"container": {
"type": "message_attachment",
"message_ts": "1548261231.000200",
"attachment_id": 1,
"channel_id": "CBR2V3XEX",
"is_ephemeral": false,
"is_app_unfurl": false
},
"trigger_id": "12321423423.333649436676.d8c1bb837935619ccad0f624c448ffb3",
"channel": {
"id": "CBR2V3XEX",
"name": "review-updates"
},
"message": {
"bot_id": "BAH5CA16Z",
"type": "message",
"text": "This content can't be displayed.",
"user": "UAJ2RU415",
"ts": "1548261231.000200"
},
"response_url": "https://hooks.slack.com/actions/AABA1ABCD/1232321423432/D09sSasdasdAS9091209",
"actions": [
{
"action_id": "WaXA",
"block_id": "=qXel",
"text": {
"type": "plain_text",
"text": "View",
"emoji": true
},
"value": "click_me_123",
"type": "button",
"action_ts": "1548426417.840180"
}
]
}
98 changes: 98 additions & 0 deletions lib_test/mock-slack-interactions/block_action2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"type":"block_actions",
"team":{
"id": "T9TK3CUKW",
"domain": "example"
},
"user":{
"id": "UA8RXUSPL",
"username": "jtorrance",
"name": "jtorrance",
"team_id": "T9TK3CUKW"
},
"api_app_id":"AABA1ABCD",
"token":"9s8d9as89d8as9d8as989",
"container":{
"type":"view",
"view_id":"V0PKB1ZFV"
},
"trigger_id":"24571818370.22717085937.b9c7ca14b87be6b44ff5864edba8306f",
"view":{
"id":"V0PKB1ZFV",
"team_id":"T9TK3CUKW",
"type":"home",
"blocks":[
{
"type":"section",
"block_id":"8ZG",
"text":{
"type":"mrkdwn",
"text":"A stack of blocks for the sample Block Kit Home tab.",
"verbatim":false
}
},
{
"type":"actions",
"block_id":"7fhg",
"elements":[
{
"type":"button",
"action_id":"XRX",
"text":{
"type":"plain_text",
"text":"Action A",
"emoji":true
}
},
{
"type":"button",
"action_id":"GFBew",
"text":{
"type":"plain_text",
"text":"Action B",
"emoji":true
}
}
]
},
{
"type":"section",
"block_id":"6evU",
"text":{
"type":"mrkdwn",
"text":"And now it's slightly more complex.",
"verbatim":false
}
}
],
"private_metadata":"",
"callback_id":"",
"state":{
"values":{}
},
"hash":"1571318366.2468e46f",
"clear_on_close":false,
"notify_on_close":false,
"close":null,
"submit":null,
"previous_view_id":null,
"root_view_id":"V0PKB1ZFV",
"app_id":"AABA1ABCD",
"external_id":"",
"app_installed_team_id":"T9TK3CUKW",
"bot_id":"B0B00B00"
},
"actions":[
{
"type":"button",
"block_id":"7fhg",
"action_id":"XRX",
"text":{
"type":"plain_text",
"text":"Action A",
"emoji":true
},
"action_ts":"1571318425.267782"
}
]
}
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>"
}
}
1 change: 1 addition & 0 deletions lib_test/mock-slack-interactions/message_shortcut.www
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
payload=%7B%22type%22%3A%22message_action%22%2C%22token%22%3A%22XXXXX%22%2C%22action_ts%22%3A%221728360716.833015%22%2C%22team%22%3A%7B%22id%22%3A%22T07MUBTEWGP%22%2C%22domain%22%3A%22testworkspace-jrm5644%22%7D%2C%22user%22%3A%7B%22id%22%3A%22U07NBD2PZ36%22%2C%22username%22%3A%22koonwen.lee%22%2C%22team_id%22%3A%22T07MUBTEWGP%22%2C%22name%22%3A%22koonwen.lee%22%7D%2C%22channel%22%3A%7B%22id%22%3A%22C07N62BSZ9B%22%2C%22name%22%3A%22social%22%7D%2C%22is_enterprise_install%22%3Afalse%2C%22enterprise%22%3Anull%2C%22callback_id%22%3A%22bc_create%22%2C%22trigger_id%22%3A%227846996185716.7742401506567.765fbc775e9236446b5284868c907fc7%22%2C%22response_url%22%3A%22https%3A%5C%2F%5C%2Fhooks.slack.com%5C%2Fapp%5C%2FT07MUBTEWGP%5C%2F7857176821457%5C%2FGjp1XOnzOCKndQZ47NQTT47i%22%2C%22message_ts%22%3A%221728287349.707269%22%2C%22message%22%3A%7B%22user%22%3A%22U07NBD2PZ36%22%2C%22type%22%3A%22message%22%2C%22ts%22%3A%221728287349.707269%22%2C%22client_msg_id%22%3A%22ad1b8ef7-55b2-4915-856e-eb970e7afa42%22%2C%22text%22%3A%22hello+i+need+some+help+this+is+a+long+message+that+will+be+shortened+by+slack+police%22%2C%22team%22%3A%22T07MUBTEWGP%22%2C%22blocks%22%3A%5B%7B%22type%22%3A%22rich_text%22%2C%22block_id%22%3A%22mQ1G5%22%2C%22elements%22%3A%5B%7B%22type%22%3A%22rich_text_section%22%2C%22elements%22%3A%5B%7B%22type%22%3A%22text%22%2C%22text%22%3A%22hello+i+need+some+help+this+is+a+long+message+that+will+be+shortened+by+slack+police%22%7D%5D%7D%5D%7D%5D%7D%7D
13 changes: 13 additions & 0 deletions lib_test/mock-slack-interactions/view_closed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"type": "view_closed",
"team": {
"id": "TXXXXXX",
"domain": "coverbands"
},
"user": {
"id": "UXXXXXX",
"name": "dreamweaver"
},
"api_app_id": "AXXXXXX",
"is_cleared": false
}
34 changes: 34 additions & 0 deletions lib_test/mock-slack-interactions/view_submission.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"type": "view_submission",
"view": {
"id": "VNHU13V36",
"type": "modal",
"private_metadata": "shhh-its-secret",
"callback_id": "modal-with-inputs",
"state": {
"values": {
"multiline": {
"mlvalue": {
"type": "plain_text_input",
"value": "This is my example inputted value"
}
},
"target_channel": {
"target_select": {
"type": "conversations_select",
"selected_conversation": "C123B12DE"
}
}
}
},
"hash": "156663117.cd33ad1f",
"response_urls": [
{
"block_id": "target_channel",
"action_id": "target_select",
"channel_id": "C123B12DE",
"response_url": "https:\/\/hooks.slack.com\/app\/ABC12312\/1234567890\/A100B100C100d100"
}
]
}
}
Loading
Loading