diff options
| author | Ben Sima <ben@bensima.com> | 2025-12-13 09:14:39 -0500 |
|---|---|---|
| committer | Ben Sima <ben@bensima.com> | 2025-12-13 09:14:39 -0500 |
| commit | ed629a3335c6c5a172322a8d7387f0c6990b0ae5 (patch) | |
| tree | c2c1676ad1593143c12a082f723f46af5a3a67c2 /Omni/Agent/Telegram | |
| parent | 5ba051535138630b333657a6540728a9148c766a (diff) | |
feat: only allow whitelisted users to add bot to groups
When the bot is added to a group, check if the user who added it is
in the whitelist. If not, send a message explaining and leave the group
immediately. This prevents unauthorized users from bypassing DM access
controls by adding the bot to a group.
Diffstat (limited to 'Omni/Agent/Telegram')
| -rw-r--r-- | Omni/Agent/Telegram/Types.hs | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/Omni/Agent/Telegram/Types.hs b/Omni/Agent/Telegram/Types.hs index d240786..aaea65b 100644 --- a/Omni/Agent/Telegram/Types.hs +++ b/Omni/Agent/Telegram/Types.hs @@ -19,10 +19,12 @@ module Omni.Agent.Telegram.Types TelegramPhoto (..), TelegramVoice (..), TelegramReplyMessage (..), + BotAddedToGroup (..), ChatType (..), -- * Parsing parseUpdate, + parseBotAddedToGroup, parseDocument, parseLargestPhoto, parsePhotoSize, @@ -323,6 +325,14 @@ instance Aeson.FromJSON TelegramReplyMessage where <*> (v .:? "from_last_name") <*> (v .:? "text" .!= "") +data BotAddedToGroup = BotAddedToGroup + { bagUpdateId :: Int, + bagChatId :: Int, + bagAddedByUserId :: Int, + bagAddedByFirstName :: Text + } + deriving (Show, Eq, Generic) + data ChatType = Private | Group | Supergroup | Channel deriving (Show, Eq, Generic) @@ -461,6 +471,46 @@ parseUpdate val = do tmReplyTo = replyTo } +parseBotAddedToGroup :: Text -> Aeson.Value -> Maybe BotAddedToGroup +parseBotAddedToGroup botUsername val = do + Aeson.Object obj <- pure val + updateId <- case KeyMap.lookup "update_id" obj of + Just (Aeson.Number n) -> Just (round n) + _ -> Nothing + Aeson.Object msgObj <- KeyMap.lookup "message" obj + Aeson.Object chatObj <- KeyMap.lookup "chat" msgObj + 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 t) -> t + _ -> "private" + guard (chatType == "group" || chatType == "supergroup") + Aeson.Object fromObj <- KeyMap.lookup "from" msgObj + addedByUserId <- case KeyMap.lookup "id" fromObj of + Just (Aeson.Number n) -> Just (round n) + _ -> Nothing + addedByFirstName <- case KeyMap.lookup "first_name" fromObj of + Just (Aeson.String s) -> Just s + _ -> Nothing + Aeson.Array newMembers <- KeyMap.lookup "new_chat_members" msgObj + let botWasAdded = any (isBotUser botUsername) (toList newMembers) + guard botWasAdded + pure + BotAddedToGroup + { bagUpdateId = updateId, + bagChatId = chatId, + bagAddedByUserId = addedByUserId, + bagAddedByFirstName = addedByFirstName + } + where + isBotUser :: Text -> Aeson.Value -> Bool + isBotUser username (Aeson.Object userObj) = + case KeyMap.lookup "username" userObj of + Just (Aeson.String u) -> Text.toLower u == Text.toLower username + _ -> False + isBotUser _ _ = False + parseDocument :: Aeson.Object -> Maybe TelegramDocument parseDocument docObj = do fileId <- case KeyMap.lookup "file_id" docObj of |
