telegram-api 0.4.1.0 → 0.4.2.0
raw patch · 13 files changed
+208/−109 lines, 13 filesdep ~aesondep ~either
Dependency ranges changed: aeson, either
Files
- CHANGELOG.md +8/−0
- src/Servant/Client/MultipartFormData.hs +1/−11
- src/Web/Telegram/API/Bot.hs +0/−7
- src/Web/Telegram/API/Bot/API.hs +52/−13
- src/Web/Telegram/API/Bot/Data.hs +24/−13
- src/Web/Telegram/API/Bot/JsonExt.hs +3/−7
- src/Web/Telegram/API/Bot/Requests.hs +0/−9
- src/Web/Telegram/API/Bot/Responses.hs +73/−21
- telegram-api.cabal +3/−2
- test/InlineSpec.hs +0/−5
- test/JsonSpec.hs +37/−9
- test/MainSpec.hs +6/−8
- test/Spec.hs +1/−4
CHANGELOG.md view
@@ -1,3 +1,11 @@+## 0.4.2.0++Features:++* Bot-2.1 support+ * Added new methods: `getChat`, `leaveChat`, `getChatAdministrators`, `getChatMember`, `getChatMembersCount`.+ * Added support for edited messages and new mentions from Telegram v.3.9. New fields: `edited_message` in `Update`, `edit_date` in `Message, user in `MessageEntity`. New value `text_mention` for the type field in `MessageEntity`.+ ## 0.4.1.0 Features:
src/Servant/Client/MultipartFormData.hs view
@@ -18,7 +18,6 @@ import Control.Monad.Trans.Except import Data.ByteString.Lazy hiding (pack, filter, map, null, elem) import Data.Proxy-import GHC.TypeLits import Data.String.Conversions import Data.Typeable (Typeable) import Network.HTTP.Client hiding (Proxy, path)@@ -29,18 +28,9 @@ import qualified Network.HTTP.Types as H import qualified Network.HTTP.Types.Header as HTTP import Servant.API-import Servant.API.Verbs import Servant.Common.BaseUrl import Servant.Client import Servant.Common.Req--import Data.ByteString.Lazy (ByteString)-import Data.List-import Data.Text (unpack)-import Network.HTTP.Client (Manager, Response)-import Servant.Client.Experimental.Auth-import Servant.Common.BasicAuth- -- | A type that can be converted to a multipart/form-data value. class ToMultipartFormData a where -- | Convert a Haskell value to a multipart/form-data-friendly intermediate type.@@ -102,7 +92,7 @@ let acceptCT = contentType ct (_status, respBody, respCT, hdrs, _response) <- performRequest' reqToRequest' reqMethod (req { reqAccept = [acceptCT] }) manager reqHost- unless (matches respCT (acceptCT)) $ throwE $ UnsupportedContentType respCT respBody+ unless (matches respCT acceptCT) $ throwE $ UnsupportedContentType respCT respBody case mimeUnrender ct respBody of Left err -> throwE $ DecodeFailure err respCT respBody Right val -> return (hdrs, val)
src/Web/Telegram/API/Bot.hs view
@@ -1,10 +1,3 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TemplateHaskell #-}- -- | This module provides Telegram Bot API module Web.Telegram.API.Bot (
src/Web/Telegram/API/Bot/API.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeOperators #-}@@ -32,7 +31,12 @@ , answerInlineQuery , answerCallbackQuery , kickChatMember+ , leaveChat , unbanChatMember+ , getChat+ , getChatAdministrators+ , getChatMembersCount+ , getChatMember , editMessageText , editMessageCaption , editMessageReplyMarkup@@ -43,23 +47,13 @@ , Token (..) ) where -import Control.Applicative-import Control.Monad.Trans.Either import Control.Monad.Trans.Except (ExceptT, runExceptT)-import Data.Aeson-import Data.Aeson.Types-import Data.Maybe import Data.Proxy import Data.Text (Text)-import qualified Data.Text as T-import GHC.Generics-import GHC.TypeLits import Network.HTTP.Client (Manager) import Servant.API import Servant.Client-import Web.HttpApiData import Servant.Client.MultipartFormData-import Web.Telegram.API.Bot.Data import Web.Telegram.API.Bot.Responses import Web.Telegram.API.Bot.Requests @@ -146,8 +140,7 @@ :> Get '[JSON] UserProfilePhotosResponse :<|> TelegramToken :> "setWebhook" :> QueryParam "url" Text- :> Get '[JSON]- SetWebhookResponse+ :> Get '[JSON] SetWebhookResponse :<|> TelegramToken :> "answerInlineQuery" :> ReqBody '[JSON] AnswerInlineQueryRequest :> Post '[JSON] InlineQueryResponse@@ -158,10 +151,26 @@ :> QueryParam "chat_id" Text :> QueryParam "user_id" Int :> Post '[JSON] KickChatMemberResponse+ :<|> TelegramToken :> "leaveChat"+ :> QueryParam "chat_id" Text+ :> Post '[JSON] LeaveChatResponse :<|> TelegramToken :> "unbanChatMember" :> QueryParam "chat_id" Text :> QueryParam "user_id" Int :> Post '[JSON] UnbanChatMemberResponse+ :<|> TelegramToken :> "getChat"+ :> QueryParam "chat_id" Text+ :> Post '[JSON] GetChatResponse+ :<|> TelegramToken :> "getChatAdministrators"+ :> QueryParam "chat_id" Text+ :> Post '[JSON] GetChatAdministratorsResponse+ :<|> TelegramToken :> "getChatMembersCount"+ :> QueryParam "chat_id" Text+ :> Post '[JSON] GetChatMembersCountResponse+ :<|> TelegramToken :> "getChatMember"+ :> QueryParam "chat_id" Text+ :> QueryParam "user_id" Int+ :> Post '[JSON] GetChatMemberResponse :<|> TelegramToken :> "editMessageText" :> ReqBody '[JSON] EditMessageTextRequest :> Post '[JSON] MessageResponse@@ -203,7 +212,12 @@ answerInlineQuery_ :: Token -> AnswerInlineQueryRequest -> Manager -> BaseUrl -> ExceptT ServantError IO InlineQueryResponse answerCallbackQuery_ :: Token -> AnswerCallbackQueryRequest -> Manager -> BaseUrl -> ExceptT ServantError IO CallbackQueryResponse kickChatMember_ :: Token -> Maybe Text -> Maybe Int -> Manager -> BaseUrl -> ExceptT ServantError IO KickChatMemberResponse+leaveChat_ :: Token -> Maybe Text -> Manager -> BaseUrl -> ExceptT ServantError IO LeaveChatResponse unbanChatMember_ :: Token -> Maybe Text -> Maybe Int -> Manager -> BaseUrl -> ExceptT ServantError IO UnbanChatMemberResponse+getChat_ :: Token -> Maybe Text -> Manager -> BaseUrl -> ExceptT ServantError IO GetChatResponse+getChatAdministrators_ :: Token -> Maybe Text -> Manager -> BaseUrl -> ExceptT ServantError IO GetChatAdministratorsResponse+getChatMembersCount_ :: Token -> Maybe Text -> Manager -> BaseUrl -> ExceptT ServantError IO GetChatMembersCountResponse+getChatMember_ :: Token -> Maybe Text -> Maybe Int -> Manager -> BaseUrl -> ExceptT ServantError IO GetChatMemberResponse editMessageText_ :: Token -> EditMessageTextRequest -> Manager -> BaseUrl -> ExceptT ServantError IO MessageResponse editMessageCaption_ :: Token -> EditMessageCaptionRequest -> Manager -> BaseUrl -> ExceptT ServantError IO MessageResponse editMessageReplyMarkup_ :: Token -> EditMessageReplyMarkupRequest -> Manager -> BaseUrl -> ExceptT ServantError IO MessageResponse@@ -233,7 +247,12 @@ :<|> answerInlineQuery_ :<|> answerCallbackQuery_ :<|> kickChatMember_+ :<|> leaveChat_ :<|> unbanChatMember_+ :<|> getChat_+ :<|> getChatAdministrators_+ :<|> getChatMembersCount_+ :<|> getChatMember_ :<|> editMessageText_ :<|> editMessageCaption_ :<|> editMessageReplyMarkup_ =@@ -355,9 +374,29 @@ kickChatMember :: Token -> Text -> Int -> Manager -> IO (Either ServantError KickChatMemberResponse) kickChatMember token chat_id user_id manager = runExceptT $ kickChatMember_ token (Just chat_id) (Just user_id) manager telegramBaseUrl +-- | Use this method for your bot to leave a group, supergroup or channel. Returns True on success.+leaveChat :: Token -> Text -> Manager -> IO (Either ServantError LeaveChatResponse)+leaveChat token chat_id manager = runExceptT $ leaveChat_ token (Just chat_id) manager telegramBaseUrl+ -- | Use this method to unban a previously kicked user in a supergroup. The user will not return to the group automatically, but will be able to join via link, etc. The bot must be an administrator in the group for this to work. unbanChatMember :: Token -> Text -> Int -> Manager -> IO (Either ServantError UnbanChatMemberResponse) unbanChatMember token chat_id user_id manager = runExceptT $ unbanChatMember_ token (Just chat_id) (Just user_id) manager telegramBaseUrl++-- | Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.)+getChat :: Token -> Text -> Manager -> IO (Either ServantError GetChatResponse)+getChat token chat_id manager = runExceptT $ getChat_ token (Just chat_id) manager telegramBaseUrl++-- | Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned.+getChatAdministrators :: Token -> Text -> Manager -> IO (Either ServantError GetChatAdministratorsResponse)+getChatAdministrators token chat_id manager = runExceptT $ getChatAdministrators_ token (Just chat_id) manager telegramBaseUrl++-- | Use this method to get the number of members in a chat. Returns Int on success.+getChatMembersCount :: Token -> Text -> Manager -> IO (Either ServantError GetChatMembersCountResponse)+getChatMembersCount token chat_id manager = runExceptT $ getChatMembersCount_ token (Just chat_id) manager telegramBaseUrl++-- | Use this method to get information about a member of a chat. Returns a ChatMember object on success.+getChatMember :: Token -> Text -> Int -> Manager -> IO (Either ServantError GetChatMemberResponse)+getChatMember token chat_id user_id manager = runExceptT $ getChatMember_ token (Just chat_id) (Just user_id) manager telegramBaseUrl -- | Use this method to edit text messages sent by the bot or via the bot (for inline bots). On success, if edited message is sent by the bot, the edited `Message` is returned, otherwise True is returned. editMessageText :: Token -> EditMessageTextRequest -> Manager -> IO (Either ServantError MessageResponse)
src/Web/Telegram/API/Bot/Data.hs view
@@ -1,14 +1,12 @@-{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TemplateHaskell #-} -- | This module contains objects which represent data of Telegram Bot API responses module Web.Telegram.API.Bot.Data ( -- * Types User (..)+ , ChatMember (..) , Chat (..) , Message (..) , PhotoSize (..)@@ -17,6 +15,7 @@ , Sticker (..) , Video (..) , Voice (..)+ , Venue (..) , Contact (..) , Location (..) , Update (..)@@ -59,13 +58,9 @@ import Data.Aeson import Data.Aeson.Types-import Data.Maybe-import Data.Proxy import Data.Text (Text)-import qualified Data.Text as T import qualified Data.Char as Char import GHC.Generics-import GHC.TypeLits import Data.List import Web.Telegram.API.Bot.JsonExt @@ -545,9 +540,10 @@ dropCached :: String -> String dropCached name = if isPrefixOf "Cached" name then drop 6 name else name +tagModifier :: String -> String tagModifier "InlineQueryResultMpeg4Gif" = "mpeg4_gif" tagModifier "InlineQueryResultCachedMpeg4Gif" = "mpeg4_gif"-tagModifier x = ((fmap (Char.toLower)) . dropCached . (drop 17)) x+tagModifier x = ((fmap Char.toLower) . dropCached . (drop 17)) x inlineQueryJSONOptions :: Options inlineQueryJSONOptions = defaultOptions {@@ -663,6 +659,7 @@ { update_id :: Int -- ^ The update's unique identifier. Update identifiers start from a certain positive number and increase sequentially. This ID becomes especially handy if you’re using 'setWebhooks', since it allows you to ignore repeated updates or to restore the correct update sequence, should they get out of order. , message :: Maybe Message -- ^ New incoming message of any kind — text, photo, sticker, etc.+ , edited_message :: Maybe Message -- ^ New version of a message that is known to the bot and was edited , inline_query :: Maybe InlineQuery -- ^ New incoming inline query , chosen_inline_result :: Maybe ChosenInlineResult -- ^ The result of a inline query that was chosen by a user and sent to their chat partner , callback_query :: Maybe CallbackQuery -- ^ This object represents an incoming callback query from a callback button in an inline keyboard. If the button that originated the query was attached to a message sent by the bot, the field message will be presented. If the button was attached to a message sent via the bot (in inline mode), the field inline_message_id will be presented.@@ -692,8 +689,20 @@ { total_count :: Int -- ^ Total number of profile pictures the target user has , photos :: [[PhotoSize]] -- ^ Requested profile pictures (in up to 4 sizes each)- } deriving (FromJSON, ToJSON, Show, Generic)+ } deriving (FromJSON, ToJSON, Show, Generic) +data ChatMember = ChatMember+ {+ cm_user :: User -- ^ Information about the user+ , cm_status :: Text -- ^ The member's status in the chat. Can be “creator”, “administrator”, “member”, “left” or “kicked”+ } deriving (Show, Generic)++instance ToJSON ChatMember where+ toJSON = toJsonDrop 3++instance FromJSON ChatMember where+ parseJSON = parseJsonDrop 3+ -- | This object represents a message. data Message = Message {@@ -705,6 +714,7 @@ , forward_from_chat :: Maybe Chat -- ^ For messages forwarded from a channel, information about the original channel , forward_date :: Maybe Int -- ^ For forwarded messages, date the original message was sent in Unix time , reply_to_message :: Maybe Message -- ^ For replies, the original message. Note that the 'Message' object in this field will not contain further 'reply_to_message' fields even if it itself is a reply.+ , edit_date :: Maybe Int -- ^ Date the message was last edited in Unix time , text :: Maybe Text -- ^ For text messages, the actual UTF-8 text of the message , entities :: Maybe [MessageEntity] -- ^ For text messages, special entities like usernames, URLs, bot commands, etc. that appear in the text , audio :: Maybe Audio -- ^ Message is an audio file, information about the file@@ -733,10 +743,11 @@ -- | This object represents one special entity in a text message. For example, hashtags, usernames, URLs, etc. data MessageEntity = MessageEntity {- me_type :: Text -- ^ Type of the entity. One of mention (@username), hashtag, bot_command, url, email, bold (bold text), italic (italic text), code (monowidth string), pre (monowidth block), text_link (for clickable text URLs)- , me_offset :: Int -- ^ Offset in UTF-16 code units to the start of the entity- , me_length :: Int -- ^ Length of the entity in UTF-16 code units- , me_url :: Maybe Text -- ^ For “text_link” only, url that will be opened after user taps on the text+ me_type :: Text -- ^ Type of the entity. Can be mention (@username), hashtag, bot_command, url, email, bold (bold text), italic (italic text), code (monowidth string), pre (monowidth block), text_link (for clickable text URLs), text_mention (for users without usernames)+ , me_offset :: Int -- ^ Offset in UTF-16 code units to the start of the entity+ , me_length :: Int -- ^ Length of the entity in UTF-16 code units+ , me_url :: Maybe Text -- ^ For “text_link” only, url that will be opened after user taps on the text+ , me_user :: Maybe User -- ^ For “text_mention” only, the mentioned user } deriving (Show, Generic) instance ToJSON MessageEntity where
src/Web/Telegram/API/Bot/JsonExt.hs view
@@ -1,10 +1,5 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-} -- | This module contains helper functions to work with JSON module Web.Telegram.API.Bot.JsonExt@@ -16,13 +11,14 @@ import Data.Aeson import Data.Aeson.Types import GHC.Generics-import GHC.TypeLits -- | Method used to drop prefix from field name during serialization+toJsonDrop :: forall a.(GHC.Generics.Generic a, GToJSON (GHC.Generics.Rep a)) => Int -> a -> Value toJsonDrop prefix = genericToJSON defaultOptions { fieldLabelModifier = drop prefix , omitNothingFields = True } -- | Method used to drop prefix from field name during deserialization+parseJsonDrop :: forall a.(Generic a, GFromJSON (Rep a)) => Int -> Value -> Parser a parseJsonDrop prefix = genericParseJSON defaultOptions { fieldLabelModifier = drop prefix }
src/Web/Telegram/API/Bot/Requests.hs view
@@ -1,10 +1,5 @@-{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} -- | This module contains data objects which represents requests to Telegram Bot API@@ -65,18 +60,14 @@ ) where import Data.Aeson-import Data.Aeson.Types import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS import Data.Maybe-import Data.Proxy import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Encoding as T import GHC.Generics-import GHC.TypeLits import Network.HTTP.Client.MultipartFormData-import Network.HTTP.Types.Header (hContentType) import Network.Mime import Servant.Client.MultipartFormData (ToMultipartFormData (..)) import Web.Telegram.API.Bot.JsonExt
src/Web/Telegram/API/Bot/Responses.hs view
@@ -1,38 +1,35 @@-{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE FlexibleContexts #-} -- | This module contains responses from Telegram Bot API module Web.Telegram.API.Bot.Responses ( -- * Types- GetMeResponse (..)- , MessageResponse (..)- , ChatActionResponse (..)- , UpdatesResponse (..)- , FileResponse (..)- , UserProfilePhotosResponse (..)- , SetWebhookResponse (..)- , InlineQueryResponse (..)- , CallbackQueryResponse (..)- , KickChatMemberResponse (..)- , UnbanChatMemberResponse (..)+ GetMeResponse (..)+ , MessageResponse (..)+ , ChatActionResponse (..)+ , UpdatesResponse (..)+ , FileResponse (..)+ , UserProfilePhotosResponse (..)+ , SetWebhookResponse (..)+ , InlineQueryResponse (..)+ , CallbackQueryResponse (..)+ , KickChatMemberResponse (..)+ , LeaveChatResponse (..)+ , UnbanChatMemberResponse (..)+ , GetChatResponse (..)+ , GetChatAdministratorsResponse (..)+ , GetChatMembersCountResponse (..)+ , GetChatMemberResponse (..) ) where import Data.Aeson-import Data.Aeson.Types-import Data.Maybe-import Data.Proxy-import Data.Text (Text)-import qualified Data.Text as T import GHC.Generics-import GHC.TypeLits import Web.Telegram.API.Bot.Data import Web.Telegram.API.Bot.JsonExt +-- TODO: use generic response i.e. `data Response a = Response `+ -- | This object represents 'getMe' response data GetMeResponse = GetMeResponse {@@ -153,6 +150,17 @@ instance FromJSON KickChatMemberResponse where parseJSON = parseJsonDrop 5 +data LeaveChatResponse = LeaveChatResponse+ {+ leave_result :: Bool+ } deriving (Show, Generic)++instance ToJSON LeaveChatResponse where+ toJSON = toJsonDrop 6++instance FromJSON LeaveChatResponse where+ parseJSON = parseJsonDrop 6+ -- | This object represents 'unbanChatMember' response data UnbanChatMemberResponse = UnbanChatMemberResponse {@@ -164,3 +172,47 @@ instance FromJSON UnbanChatMemberResponse where parseJSON = parseJsonDrop 6++data GetChatResponse = GetChatResponse+ {+ chat_result :: Chat+ } deriving (Show, Generic)++instance ToJSON GetChatResponse where+ toJSON = toJsonDrop 5++instance FromJSON GetChatResponse where+ parseJSON = parseJsonDrop 5++data GetChatAdministratorsResponse = GetChatAdministratorsResponse+ {+ ca_result :: [ChatMember]+ } deriving (Show, Generic)++instance ToJSON GetChatAdministratorsResponse where+ toJSON = toJsonDrop 3++instance FromJSON GetChatAdministratorsResponse where+ parseJSON = parseJsonDrop 3++data GetChatMembersCountResponse = GetChatMembersCountResponse+ {+ cmc_result :: Int+ } deriving (Show, Generic)++instance ToJSON GetChatMembersCountResponse where+ toJSON = toJsonDrop 4++instance FromJSON GetChatMembersCountResponse where+ parseJSON = parseJsonDrop 4++data GetChatMemberResponse = GetChatMemberResponse+ {+ gcm_result :: Int+ } deriving (Show, Generic)++instance ToJSON GetChatMemberResponse where+ toJSON = toJsonDrop 4++instance FromJSON GetChatMemberResponse where+ parseJSON = parseJsonDrop 4
telegram-api.cabal view
@@ -1,5 +1,5 @@ name: telegram-api-version: 0.4.1.0+version: 0.4.2.0 synopsis: Telegram Bot API bindings description: High-level bindings to the Telegram Bot API homepage: http://github.com/klappvisor/haskell-telegram-api#readme@@ -47,6 +47,7 @@ , bytestring , string-conversions default-language: Haskell2010+ ghc-options: -O2 -Wall -fno-warn-name-shadowing -fno-warn-unused-binds test-suite telegram-api-test type: exitcode-stdio-1.0@@ -72,7 +73,7 @@ , text , transformers , utf8-string- ghc-options: -threaded -rtsopts -with-rtsopts=-N+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -fno-warn-name-shadowing default-language: Haskell2010 source-repository head
test/InlineSpec.hs view
@@ -1,9 +1,4 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TemplateHaskell #-} module InlineSpec (spec) where
test/JsonSpec.hs view
@@ -1,25 +1,17 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TemplateHaskell #-} module JsonSpec (spec) where -import Control.Monad import Web.Telegram.API.Bot import Test.Hspec-import Data.Text (Text) import qualified Data.Text as T-import System.Environment import Data.Aeson.Encode import Text.JSON.JPath import Data.ByteString.Lazy.UTF8 spec :: Spec spec = do- let getType = \q -> jPath (T.unpack "type") (toString (encode q))+ let getType q = jPath (T.unpack "type") (toString (encode q)) describe "type of serialized inline query result" $ do it "should be article" $ do (getType iq_article) `shouldBe` ["\"article\""]@@ -59,23 +51,59 @@ it "should be photo" $ do (getType cached_photo) `shouldBe` ["\"photo\""] +message_content :: InputMessageContent message_content = InputTextMessageContent "test message content" Nothing Nothing +iq_article :: InlineQueryResult iq_article = inlineQueryResultArticle "" "text article content" message_content++iq_photo :: InlineQueryResult iq_photo = inlineQueryResultPhoto "" "" ""++iq_gif :: InlineQueryResult iq_gif = inlineQueryResultGif "" "" ""++iq_mpeg :: InlineQueryResult iq_mpeg = inlineQueryResultMpeg4Gif "" "" ""++iq_video :: InlineQueryResult iq_video = inlineQueryResultVideo "" "" "video/mpeg" "" ""++iq_audio :: InlineQueryResult iq_audio = inlineQueryResultAudio "" "" ""++iq_contact :: InlineQueryResult iq_contact = inlineQueryResultContact "" "" ""++iq_document :: InlineQueryResult iq_document = inlineQueryResultDocument "" "" "" ""++iq_location :: InlineQueryResult iq_location = inlineQueryResultLocation "" 0.0 0.0 ""++iq_venue :: InlineQueryResult iq_venue = inlineQueryResultVenue "" 0.0 0.0 "" ""++cached_audio :: InlineQueryResult cached_audio = inlineQueryResultCachedAudio "" ""++cached_voice :: InlineQueryResult cached_voice = inlineQueryResultCachedVoice "" "" ""++cached_video :: InlineQueryResult cached_video = inlineQueryResultCachedVideo "" "" ""++cached_doc :: InlineQueryResult cached_doc = inlineQueryResultCachedDocument "" "" ""++cached_sticker :: InlineQueryResult cached_sticker = inlineQueryResultCachedSticker "" ""++cached_mpeg :: InlineQueryResult cached_mpeg = inlineQueryResultCachedMpeg4Gif "" ""++cached_gif :: InlineQueryResult cached_gif = inlineQueryResultCachedGif "" ""++cached_photo :: InlineQueryResult cached_photo = inlineQueryResultCachedPhoto "" ""
test/MainSpec.hs view
@@ -128,21 +128,19 @@ Left FailureResponse { responseStatus = Status { statusMessage = msg } } <- sendAudio token audio manager msg `shouldBe` "Bad Request"- it "should send audio" $ do- -- audio source: https://musopen.org/music/2698/antonio-vivaldi/concerto-for-2-trumpets-in-c-major-rv-537-trumpet-and-organ-arr/- let audio = sendAudioRequest chatId "BQADBAADAQQAAiBOnQHThzc4cz1-IwI"- Right MessageResponse { message_result = Message { audio = Just Audio { audio_title = Just title } } } <-- sendAudio token audio manager- title `shouldBe` "The Nutcracker Suite - Act II, No.12. Pas de Deux variations"- it "should upload audio" $ do+ it "should upload audio and resend it by id" $ do let fileUpload = localFileUpload (testFile "concerto-for-2-trumpets-in-c-major.mp3") audioTitle = "Concerto for 2 Trumpets in C major, RV. 537 (Rondeau arr.) All." audioPerformer = "Michel Rondeau" audio = (uploadAudioRequest chatId fileUpload) { _audio_performer = Just audioPerformer, _audio_title = Just audioTitle }- Right MessageResponse { message_result = Message { audio = Just Audio { audio_title = Just title, audio_performer = Just performer } } } <-+ Right MessageResponse { message_result = Message { audio = Just Audio { audio_file_id = file_id, audio_title = Just title, audio_performer = Just performer } } } <- uploadAudio token audio manager title `shouldBe` audioTitle performer `shouldBe` audioPerformer+ let audio = sendAudioRequest chatId file_id+ Right MessageResponse { message_result = Message { audio = Just Audio { audio_title = Just title' } } } <-+ sendAudio token audio manager+ title' `shouldBe` audioTitle describe "/sendSticker" $ do it "should send sticker" $ do
test/Spec.hs view
@@ -3,15 +3,13 @@ module Main (main) where -import Control.Monad (when) import Data.Maybe (fromMaybe) import Data.Text (Text) import qualified Data.Text as T import qualified MainSpec import qualified JsonSpec import Options.Applicative-import System.Environment (getArgs, withArgs)-import System.Exit (exitSuccess)+import System.Environment (withArgs) import Test.Hspec import qualified Text.PrettyPrint.ANSI.Leijen as PP import Web.Telegram.API.Bot@@ -52,7 +50,6 @@ main :: IO () main = do- args <- getArgs Options{..} <- execParser opts let integration = opt_integration token = fmap (\x -> Token ("bot" <> T.pack x)) opt_token