summaryrefslogtreecommitdiff
path: root/Omni/Agent/Telegram/Types.hs
diff options
context:
space:
mode:
authorBen Sima <ben@bensima.com>2025-12-13 00:44:27 -0500
committerBen Sima <ben@bensima.com>2025-12-13 00:44:27 -0500
commit6bbf81f41c318a4200156e58707c807b230a601c (patch)
tree68bb23ec635f6657ba6cb4c6804cfef44d90a4d5 /Omni/Agent/Telegram/Types.hs
parent4ff40843e7a6801b7785bfff7f4e9e8fff4e27d4 (diff)
telegram: add group chat support
- Only respond in groups when @mentioned or replied to - Add ChatType to TelegramMessage (private/group/supergroup/channel) - Add getMe API call to fetch bot username on startup - Add shouldRespondInGroup helper function
Diffstat (limited to 'Omni/Agent/Telegram/Types.hs')
-rw-r--r--Omni/Agent/Telegram/Types.hs47
1 files changed, 47 insertions, 0 deletions
diff --git a/Omni/Agent/Telegram/Types.hs b/Omni/Agent/Telegram/Types.hs
index 2db6a52..d240786 100644
--- a/Omni/Agent/Telegram/Types.hs
+++ b/Omni/Agent/Telegram/Types.hs
@@ -19,6 +19,7 @@ module Omni.Agent.Telegram.Types
TelegramPhoto (..),
TelegramVoice (..),
TelegramReplyMessage (..),
+ ChatType (..),
-- * Parsing
parseUpdate,
@@ -31,6 +32,8 @@ module Omni.Agent.Telegram.Types
-- * Utilities
isPdf,
isSupportedVoiceFormat,
+ isGroupChat,
+ shouldRespondInGroup,
-- * Testing
main,
@@ -81,6 +84,7 @@ test =
TelegramMessage
{ tmUpdateId = 123,
tmChatId = 456,
+ tmChatType = Private,
tmUserId = 789,
tmUserFirstName = "Test",
tmUserLastName = Just "User",
@@ -319,9 +323,28 @@ instance Aeson.FromJSON TelegramReplyMessage where
<*> (v .:? "from_last_name")
<*> (v .:? "text" .!= "")
+data ChatType = Private | Group | Supergroup | Channel
+ deriving (Show, Eq, Generic)
+
+instance Aeson.ToJSON ChatType where
+ toJSON Private = Aeson.String "private"
+ toJSON Group = Aeson.String "group"
+ toJSON Supergroup = Aeson.String "supergroup"
+ toJSON Channel = Aeson.String "channel"
+
+instance Aeson.FromJSON ChatType where
+ parseJSON = Aeson.withText "ChatType" parseChatType
+ where
+ parseChatType "private" = pure Private
+ parseChatType "group" = pure Group
+ parseChatType "supergroup" = pure Supergroup
+ parseChatType "channel" = pure Channel
+ parseChatType _ = pure Private
+
data TelegramMessage = TelegramMessage
{ tmUpdateId :: Int,
tmChatId :: Int,
+ tmChatType :: ChatType,
tmUserId :: Int,
tmUserFirstName :: Text,
tmUserLastName :: Maybe Text,
@@ -338,6 +361,7 @@ instance Aeson.ToJSON TelegramMessage where
Aeson.object
[ "update_id" .= tmUpdateId m,
"chat_id" .= tmChatId m,
+ "chat_type" .= tmChatType m,
"user_id" .= tmUserId m,
"user_first_name" .= tmUserFirstName m,
"user_last_name" .= tmUserLastName m,
@@ -353,6 +377,7 @@ instance Aeson.FromJSON TelegramMessage where
Aeson.withObject "TelegramMessage" <| \v ->
(TelegramMessage </ (v .: "update_id"))
<*> (v .: "chat_id")
+ <*> (v .:? "chat_type" .!= Private)
<*> (v .: "user_id")
<*> (v .: "user_first_name")
<*> (v .:? "user_last_name")
@@ -385,6 +410,12 @@ parseUpdate val = do
chatId <- case KeyMap.lookup "id" chatObj of
Just (Aeson.Number n) -> Just (round n)
_ -> Nothing
+ let chatType = case KeyMap.lookup "type" chatObj of
+ Just (Aeson.String "private") -> Private
+ Just (Aeson.String "group") -> Group
+ Just (Aeson.String "supergroup") -> Supergroup
+ Just (Aeson.String "channel") -> Channel
+ _ -> Private
Aeson.Object fromObj <- KeyMap.lookup "from" msgObj
userId <- case KeyMap.lookup "id" fromObj of
Just (Aeson.Number n) -> Just (round n)
@@ -419,6 +450,7 @@ parseUpdate val = do
TelegramMessage
{ tmUpdateId = updateId,
tmChatId = chatId,
+ tmChatType = chatType,
tmUserId = userId,
tmUserFirstName = firstName,
tmUserLastName = lastName,
@@ -547,3 +579,18 @@ isSupportedVoiceFormat voice =
Just "audio/x-opus+ogg" -> True
Nothing -> True
_ -> False
+
+isGroupChat :: TelegramMessage -> Bool
+isGroupChat msg = tmChatType msg `elem` [Group, Supergroup]
+
+shouldRespondInGroup :: Text -> TelegramMessage -> Bool
+shouldRespondInGroup botUsername msg
+ | not (isGroupChat msg) = True
+ | isMentioned = True
+ | isReplyToBot = True
+ | otherwise = False
+ where
+ msgText = Text.toLower (tmText msg)
+ mention = "@" <> Text.toLower botUsername
+ isMentioned = mention `Text.isInfixOf` msgText
+ isReplyToBot = isJust (tmReplyTo msg)