From 983ca5f559433f0d8d43c1ec0445638933d9bf1e Mon Sep 17 00:00:00 2001 From: Diogo Castro Date: Fri, 8 Sep 2023 17:53:12 +0100 Subject: [PATCH] [#108] Handle messages with link previews --- src/TzBot/ProcessEvents/Message.hs | 3 + src/TzBot/Slack/API/MessageBlock.hs | 1 + src/TzBot/Slack/Events.hs | 31 ++++-- test/Test/TzBot/Slack/API/Parser.hs | 155 ++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 11 deletions(-) diff --git a/src/TzBot/ProcessEvents/Message.hs b/src/TzBot/ProcessEvents/Message.hs index 7669351..c48556a 100644 --- a/src/TzBot/ProcessEvents/Message.hs +++ b/src/TzBot/ProcessEvents/Message.hs @@ -58,6 +58,9 @@ filterMessageTypeWithLog evt = case meMessageDetails evt of MDUserLeftChannel -> do logInfo [int||Incoming message subtype=channel_leave, ignoring|] pure Nothing + MDMessageUrlUnfurl -> do + logInfo [int||Incoming message with URL preview, ignoring|] + pure Nothing withSenderNotBot :: MessageEvent -> BotM (Maybe User) withSenderNotBot evt = do diff --git a/src/TzBot/Slack/API/MessageBlock.hs b/src/TzBot/Slack/API/MessageBlock.hs index 35cb0a3..183d8f9 100644 --- a/src/TzBot/Slack/API/MessageBlock.hs +++ b/src/TzBot/Slack/API/MessageBlock.hs @@ -29,6 +29,7 @@ module TzBot.Slack.API.MessageBlock , PlainBlockElementLevel1(..) , BlockElementLevel2(..) , ElementText(..) + , ElementLink(..) ) where import TzPrelude diff --git a/src/TzBot/Slack/Events.hs b/src/TzBot/Slack/Events.hs index f7d7dba..254798f 100644 --- a/src/TzBot/Slack/Events.hs +++ b/src/TzBot/Slack/Events.hs @@ -34,6 +34,9 @@ data MessageDetails = MDMessage | MDMessageEdited Message | MDMessageBroadcast -- message copied to channel from thread + | MDMessageUrlUnfurl + -- ^ This event is occurs when a user posts a message with a URL + -- and Slack displays a URL preview. | MDUserJoinedChannel | MDUserLeftChannel deriving stock (Eq, Show, Generic) @@ -52,18 +55,24 @@ instance FromJSON MessageEvent where Just "channel_join" -> (,MDUserJoinedChannel) <$> parseMessage o Just "channel_leave" -> (,MDUserLeftChannel) <$> parseMessage o Just "message_changed" -> do - -- Explanation: when someone posts a message to a thread with channel broadcast, - -- two events come: message and then message_changed, the latter seemingly - -- corresponds to sending this message directly to the channel. - -- These messages lack "edited" field, and they are not really edited. newMsg <- o .: "message" >>= parseMessage - case (mEdited newMsg, mSubType newMsg) of - (True, _) -> do - prevMsg <- o .: "previous_message" >>= parseMessage - pure (newMsg, MDMessageEdited prevMsg) - (False, Just "thread_broadcast") -> - pure (newMsg, MDMessageBroadcast) - _ -> fail "expected edited message" + + messageDetails <- + if + | newMsg.mEdited -> do + prevMsg <- o .: "previous_message" >>= parseMessage + pure $ MDMessageEdited prevMsg + | not newMsg.mEdited && newMsg.mSubType == Just "thread_broadcast" -> + -- Explanation: when someone posts a message to a thread with channel broadcast, + -- two events come: message and then message_changed, the latter seemingly + -- corresponds to sending this message directly to the channel. + -- These messages lack "edited" field, and they are not really edited. + pure MDMessageBroadcast + | not newMsg.mEdited && subtype == Just "message_changed" -> + pure MDMessageUrlUnfurl + | otherwise -> fail "expected edited message" + + pure (newMsg, messageDetails) Just _unknownSubtype -> parseMessageFromTopObject pure MessageEvent {..} diff --git a/test/Test/TzBot/Slack/API/Parser.hs b/test/Test/TzBot/Slack/API/Parser.hs index 31e138d..7109057 100644 --- a/test/Test/TzBot/Slack/API/Parser.hs +++ b/test/Test/TzBot/Slack/API/Parser.hs @@ -7,6 +7,7 @@ module Test.TzBot.Slack.API.Parser , unit_Parse_message_channel_join_events , unit_Parse_message_edited , unit_Parse_message_with_broadcast + , unit_Parse_message_with_unfurled_url ) where import TzPrelude @@ -482,3 +483,157 @@ unit_Parse_message_with_broadcast = , meMessageDetails = MDMessageBroadcast } ) + +-- | These events happen when a user posts a link with a URL +-- and Slack displays a URL preview. +-- +-- https://github.com/serokell/tzbot/issues/108 +unit_Parse_message_with_unfurled_url :: Assertion +unit_Parse_message_with_unfurled_url = do + parseEither @_ @MessageEvent parseJSON [aesonQQ| + { + "channel": "C02N85E82LV", + "channel_type": "channel", + "event_ts": "1694188283.002300", + "hidden": true, + "message": { + "attachments": [ + { + "fallback": "GitHub: GitHub: Let’s build from here", + "from_url": "http://www.github.com/", + "id": 1, + "image_bytes": 309453, + "image_height": 630, + "image_url": "https://github.githubassets.com/images/modules/site/social-cards/campaign-social.png", + "image_width": 1200, + "original_url": "http://www.github.com", + "service_icon": "https://github.com/favicon.ico", + "service_name": "GitHub", + "text": "GitHub is where over 100 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and fea...", + "title": "GitHub: Let’s build from here", + "title_link": "http://www.github.com/" + } + ], + "blocks": [ + { + "block_id": "yLL", + "elements": [ + { + "elements": [ + { + "text": "Hello with link to ", + "type": "text" + }, + { + "text": "github.com", + "type": "link", + "unsafe": true, + "url": "http://www.github.com" + } + ], + "type": "rich_text_section" + } + ], + "type": "rich_text" + } + ], + "client_msg_id": "679a7537-094f-42c3-b629-6d568feafc9e", + "team": "T02NDBHSWSG", + "text": "Hello with link to ", + "ts": "1694188279.128769", + "type": "message", + "user": "U02N85E78QM" + }, + "previous_message": { + "blocks": [ + { + "block_id": "yLL", + "elements": [ + { + "elements": [ + { + "text": "Hello with link to ", + "type": "text" + }, + { + "text": "github.com", + "type": "link", + "unsafe": true, + "url": "http://www.github.com" + } + ], + "type": "rich_text_section" + } + ], + "type": "rich_text" + } + ], + "client_msg_id": "679a7537-094f-42c3-b629-6d568feafc9e", + "team": "T02NDBHSWSG", + "text": "Hello with link to ", + "ts": "1694188279.128769", + "type": "message", + "user": "U02N85E78QM" + }, + "subtype": "message_changed", + "ts": "1694188283.002300", + "type": "message" + } + |] @?= + Right + ( MessageEvent + { meChannel = ChannelId + { unChannelId = "C02N85E82LV" } + , meChannelType = Just CTChannel + , meMessage = Message + { mUser = UserId + { unUserId = "U02N85E78QM" } + , mText = "Hello with link to " + , mMessageId = MessageId + { unMessageId = "1694188279.128769" } + , mTs = read "2023-09-08 15:51:19.128769 UTC" + , mThreadId = Nothing + , mEdited = False + , mSubType = Nothing + , msgBlocks = Just + ( WithUnknown + { unUnknown = Right + [ MessageBlock + { mbElements = + [ BEL1Plain + ( PlainBlockElementLevel1 + { beType = WithUnknown { unUnknown = Right BETRichTextSection } + , beElements = Just + [ WithUnknown + { unUnknown = Right + ( BEL2ElementText + ( ElementText + { etText = "Hello with link to " + , etStyle = Nothing + } + ) + ) + } + , WithUnknown + { unUnknown = Right + ( BEL2ElementLink + ( ElementLink + { elText = "github.com" + , etUrl = "http://www.github.com" + } + ) + ) + } + ] + } + ) + ] + } + ] + } + ) + } + , meTs = read "2023-09-08 15:51:23.0023 UTC" + , meMessageDetails = MDMessageUrlUnfurl + } + )