Skip to content

Commit

Permalink
Introduce chat.update bindings (#112)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jade Lovelace committed Nov 28, 2022
1 parent ffeccec commit 0d6c5f7
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nix-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ jobs:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Run all nix checks
run: |
nix build --keep-going ".#checks.x86_64-linux.all"
nix build --print-build-logs --keep-going ".#checks.x86_64-linux.all"
3 changes: 3 additions & 0 deletions slack-web.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ extra-source-files:
tests/golden/Conversation/*.golden
tests/golden/UsersConversationsResponse/*.json
tests/golden/UsersConversationsResponse/*.golden
tests/golden/UpdateRsp/*.json
tests/golden/UpdateRsp/*.golden

category: Web

Expand Down Expand Up @@ -174,6 +176,7 @@ test-suite tests
Web.Slack.PagerSpec
Web.Slack.MessageParserSpec
Web.Slack.ConversationSpec
Web.Slack.ChatSpec
Web.Slack.UsersConversationsSpec
Web.Slack.Experimental.RequestVerificationSpec
Web.Slack.Experimental.Events.TypesSpec
Expand Down
22 changes: 22 additions & 0 deletions src/Web/Slack.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Web.Slack
apiTest,
authTest,
chatPostMessage,
chatUpdate,
conversationsList,
conversationsListAll,
conversationsHistory,
Expand Down Expand Up @@ -85,6 +86,10 @@ type Api =
:> AuthProtect "token"
:> ReqBody '[FormUrlEncoded] Chat.PostMsgReq
:> Post '[JSON] (ResponseJSON Chat.PostMsgRsp)
:<|> "chat.update"
:> AuthProtect "token"
:> ReqBody '[FormUrlEncoded] Chat.UpdateReq
:> Post '[JSON] (ResponseJSON Chat.UpdateRsp)
:<|> "users.list"
:> AuthProtect "token"
:> Post '[JSON] (ResponseJSON User.ListRsp)
Expand Down Expand Up @@ -213,6 +218,22 @@ chatPostMessage_ ::
Chat.PostMsgReq ->
ClientM (ResponseJSON Chat.PostMsgRsp)

-- | Updates a message.
--
-- <https://api.slack.com/methods/chat.update>
chatUpdate ::
SlackConfig ->
Chat.UpdateReq ->
IO (Response Chat.UpdateRsp)
chatUpdate = flip $ \updateReq -> do
authR <- mkSlackAuthenticateReq
run (chatUpdate_ authR updateReq) . slackConfigManager

chatUpdate_ ::
AuthenticatedRequest (AuthProtect "token") ->
Chat.UpdateReq ->
ClientM (ResponseJSON Chat.UpdateRsp)

-- |
--
-- This method returns a list of all users in the team.
Expand Down Expand Up @@ -299,6 +320,7 @@ apiTest_
:<|> conversationsHistory_
:<|> conversationsReplies_
:<|> chatPostMessage_
:<|> chatUpdate_
:<|> usersList_
:<|> userLookupByEmail_ =
client (Proxy :: Proxy Api)
Expand Down
86 changes: 59 additions & 27 deletions src/Web/Slack/Chat.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,21 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

----------------------------------------------------------------------

----------------------------------------------------------------------

-- |
-- Module: Web.Slack.Chat
-- Description:
module Web.Slack.Chat
( PostMsg (..),
PostMsgReq (..),
mkPostMsgReq,
PostMsgRsp (..),
UpdateReq (..),
mkUpdateReq,
UpdateRsp (..),
)
where

-- FIXME: Web.Slack.Prelude

-- aeson

-- base

-- deepseq
import Control.DeepSeq (NFData)
import Data.Aeson.TH
-- http-api-data

-- slack-web

-- text
import Data.Text (Text)
import GHC.Generics (Generic)
import Web.FormUrlEncoded
import Web.Slack.Conversation (ConversationId)
import Web.Slack.Prelude
import Web.Slack.Util
import Prelude

data PostMsg = PostMsg
{ postMsgText :: Text
Expand All @@ -59,7 +40,9 @@ $(deriveJSON (jsonOpts "postMsg") ''PostMsg)

data PostMsgReq = PostMsgReq
{ postMsgReqChannel :: Text
, postMsgReqText :: Text
, postMsgReqText :: Maybe Text
-- ^ One of 'postMsgReqText', 'postMsgReqAttachments', or 'postMsgReqBlocks'
-- is required.
, postMsgReqParse :: Maybe Text
, postMsgReqLinkNames :: Maybe Bool
, postMsgReqAttachments :: Maybe Text
Expand Down Expand Up @@ -90,7 +73,7 @@ mkPostMsgReq ::
mkPostMsgReq channel text =
PostMsgReq
{ postMsgReqChannel = channel
, postMsgReqText = text
, postMsgReqText = Just text
, postMsgReqParse = Nothing
, postMsgReqLinkNames = Nothing
, postMsgReqAttachments = Nothing
Expand All @@ -106,11 +89,60 @@ mkPostMsgReq channel text =
}

data PostMsgRsp = PostMsgRsp
{ postMsgRspTs :: String
{ postMsgRspTs :: Text
, postMsgRspMessage :: PostMsg
}
deriving stock (Eq, Generic, Show)

instance NFData PostMsgRsp

$(deriveFromJSON (jsonOpts "postMsgRsp") ''PostMsgRsp)

-- | <https://api.slack.com/methods/chat.update>
data UpdateReq = UpdateReq
{ updateReqChannel :: ConversationId
, updateReqTs :: Text
-- ^ \"Timestamp of the message to be updated.\"
, updateReqAsUser :: Maybe Bool
-- ^ \"Pass true to update the message as the authed user. Bot users in this context are considered authed users.\"
, updateReqAttachments :: Maybe Text
-- ^ \"A JSON-based array of structured attachments, presented as a URL-encoded string. This field is required when not presenting text. If you don't include this field, the message's previous attachments will be retained. To remove previous attachments, include an empty array for this field.\"
, updateReqLinkNames :: Maybe Bool
, updateReqMetadata :: Maybe Text
, updateReqParse :: Maybe Text
, updateReqReplyBroadcast :: Maybe Bool
-- ^ \"Broadcast an existing thread reply to make it visible to everyone in the channel or conversation.\"
, updateReqText :: Maybe Text
-- ^ \"New text for the message, using the default formatting rules. It's not required when presenting blocks or attachments.\"
}
deriving stock (Eq, Generic, Show)

instance ToForm UpdateReq where
toForm = genericToForm (formOpts "updateReq")

mkUpdateReq :: ConversationId -> Text -> UpdateReq
mkUpdateReq channel ts =
UpdateReq
{ updateReqChannel = channel
, updateReqTs = ts
, updateReqAsUser = Nothing
, updateReqAttachments = Nothing
, updateReqLinkNames = Nothing
, updateReqMetadata = Nothing
, updateReqParse = Nothing
, updateReqReplyBroadcast = Nothing
, updateReqText = Nothing
}

data UpdateRsp = UpdateRsp
{ updateRspChannel :: ConversationId
, updateRspTs :: Text
, updateRspText :: Text
-- FIXME(jadel): this does look suspiciously like the same schema as
-- MessageEvent based on the example I received, but Slack hasn't documented
-- what it actually is, so let's not try to parse it for now.
-- , message :: MessageEvent
}
deriving stock (Eq, Generic, Show)

$(deriveFromJSON (jsonOpts "updateRsp") ''UpdateRsp)
11 changes: 11 additions & 0 deletions tests/Web/Slack/ChatSpec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Web.Slack.ChatSpec (spec) where

import JSONGolden
import TestImport
import Web.Slack.Chat (UpdateRsp)

spec :: Spec
spec = describe "Chat methods" do
describe "chat.update" do
describe "Response FromJSON" do
mapM_ (oneGoldenTest @UpdateRsp) ["sample", "actual"]
78 changes: 78 additions & 0 deletions tests/golden/SlackWebhookEvent/shared_message_no_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"token": "aaaa",
"team_id": "T043DB835ML",
"api_app_id": "A0442TUPHGR",
"event": {
"type": "message",
"text": "",
"user": "U043H11ES4V",
"ts": "1668537593.598469",
"team": "T043DB835ML",
"attachments": [
{
"from_url": "https://jadeapptesting.slack.com/archives/C043KSKGJUB/p1665615886364019",
"ts": "1665615886.364019",
"author_id": "U043H11ES4V",
"channel_id": "C043KSKGJUB",
"channel_team": "T043DB835ML",
"channel_name": "testing-slack-app",
"is_msg_unfurl": true,
"message_blocks": [
{
"team": "T043DB835ML",
"channel": "C043KSKGJUB",
"ts": "1665615886.364019",
"message": {
"blocks": [
{
"type": "rich_text",
"block_id": "TNHa4",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "blahblahblahblahblah"
}
]
}
]
}
]
}
}
],
"color": "D0D0D0",
"is_share": true,
"fallback": "[October 12th, 2022 4:04 PM] jadel: blahblahblahblahblah",
"text": "blahblahblahblahblah",
"author_name": "jadel",
"author_link": "https://jadeapptesting.slack.com/team/U043H11ES4V",
"author_icon": "https://secure.gravatar.com/avatar/dcd5bc53dcfaca62ddc3f5726d07ba13.jpg?s=48&d=https%3A%2F%2Fa.slack-edge.com%2Fdf10d%2Fimg%2Favatars%2Fava_0019-48.png",
"author_subname": "jadel",
"mrkdwn_in": [
"text"
],
"footer": "Posted in #testing-slack-app"
}
],
"channel": "C043YJGBY49",
"event_ts": "1668537593.598469",
"channel_type": "channel"
},
"type": "event_callback",
"event_id": "Ev04BEN3QMSM",
"event_time": 1668537593,
"authorizations": [
{
"enterprise_id": null,
"team_id": "T043DB835ML",
"user_id": "U0442US8QGH",
"is_bot": true,
"is_enterprise_install": false
}
],
"is_ext_shared_channel": false,
"event_context": "aaaa"
}
6 changes: 6 additions & 0 deletions tests/golden/UpdateRsp/actual.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
UpdateRsp
{ updateRspChannel = ConversationId
{ unConversationId = "D0442US94JD" }
, updateRspTs = "1668717810.728689"
, updateRspText = "blahblahblah"
}
48 changes: 48 additions & 0 deletions tests/golden/UpdateRsp/actual.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"ok": true,
"channel": "D0442US94JD",
"ts": "1668717810.728689",
"text": "blahblahblah",
"message": {
"bot_id": "B0439P161B9",
"type": "message",
"text": "blahblahblah",
"user": "U0442US8QGH",
"app_id": "A0442TUPHGR",
"blocks": [
{
"type": "rich_text",
"block_id": "j1Bvn",
"elements": [
{
"type": "rich_text_section",
"elements": [
{
"type": "text",
"text": "blahblahblah"
}
]
}
]
}
],
"team": "T043DB835ML",
"bot_profile": {
"id": "B0439P161B9",
"app_id": "A0442TUPHGR",
"name": "Slacklinker dev",
"icons": {
"image_36": "https://a.slack-edge.com/80588/img/plugins/app/bot_36.png",
"image_48": "https://a.slack-edge.com/80588/img/plugins/app/bot_48.png",
"image_72": "https://a.slack-edge.com/80588/img/plugins/app/service_72.png"
},
"deleted": false,
"updated": 1663960005,
"team_id": "T043DB835ML"
},
"edited": {
"user": "B0439P161B9",
"ts": "1668721589.000000"
}
}
}
6 changes: 6 additions & 0 deletions tests/golden/UpdateRsp/sample.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
UpdateRsp
{ updateRspChannel = ConversationId
{ unConversationId = "C024BE91L" }
, updateRspTs = "1401383885.000061"
, updateRspText = "Updated text you carefully authored"
}
10 changes: 10 additions & 0 deletions tests/golden/UpdateRsp/sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"ok": true,
"channel": "C024BE91L",
"ts": "1401383885.000061",
"text": "Updated text you carefully authored",
"message": {
"text": "Updated text you carefully authored",
"user": "U34567890"
}
}

0 comments on commit 0d6c5f7

Please sign in to comment.