telegram-types (empty) → 0.1.0
raw patch · 28 files changed
+2891/−0 lines, 28 filesdep +aesondep +basedep +bytestringsetup-changed
Dependencies added: aeson, base, bytestring, deriving-aeson, filepath, generic-lens, lens, mime-types, open-union, servant, servant-multipart, telegram-types, text
Files
- LICENSE +30/−0
- README.md +1/−0
- Setup.hs +2/−0
- src/Web/Telegram/Types.hs +116/−0
- src/Web/Telegram/Types/Inline.hs +10/−0
- src/Web/Telegram/Types/Input.hs +33/−0
- src/Web/Telegram/Types/Interaction.hs +68/−0
- src/Web/Telegram/Types/Internal/Common.hs +495/−0
- src/Web/Telegram/Types/Internal/InlineQuery.hs +288/−0
- src/Web/Telegram/Types/Internal/InputFile.hs +110/−0
- src/Web/Telegram/Types/Internal/InputMedia.hs +283/−0
- src/Web/Telegram/Types/Internal/Keyboard.hs +110/−0
- src/Web/Telegram/Types/Internal/Media.hs +237/−0
- src/Web/Telegram/Types/Internal/Passport.hs +147/−0
- src/Web/Telegram/Types/Internal/Sticker.hs +58/−0
- src/Web/Telegram/Types/Internal/Update.hs +125/−0
- src/Web/Telegram/Types/Internal/UpdateType.hs +26/−0
- src/Web/Telegram/Types/Internal/User.hs +45/−0
- src/Web/Telegram/Types/Internal/Utils.hs +19/−0
- src/Web/Telegram/Types/Internal/Utils/Default.hs +87/−0
- src/Web/Telegram/Types/Internal/Utils/Stock.hs +48/−0
- src/Web/Telegram/Types/Lens.hs +408/−0
- src/Web/Telegram/Types/Passport.hs +11/−0
- src/Web/Telegram/Types/Stock.hs +6/−0
- src/Web/Telegram/Types/Update.hs +14/−0
- src/Web/Telegram/Types/UpdateType.hs +6/−0
- telegram-types.cabal +95/−0
- test/Spec.hs +13/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Poscat (c) 2020++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Poscat nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# telegram-types
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Web/Telegram/Types.hs view
@@ -0,0 +1,116 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DerivingVia #-}++module Web.Telegram.Types+ ( -- ** User+ User (..),++ -- ** Message+ Message (..),+ MessageMetadata (..),+ MessageEntity (..),+ MessageContent (..),+ ParseMode (..),++ -- ** Chat+ ChatId (..),+ Chat (..),+ ChatPermissions (..),+ ChatPhoto (..),+ ChatMember (..),++ -- ** Media Types++ -- *** Image+ PhotoSize (..),++ -- *** Audio+ Audio (..),++ -- *** Animation+ Animation (..),++ -- *** Document+ Document (..),++ -- *** Video+ Video (..),++ -- *** Voice+ Voice (..),++ -- *** VideoNote+ VideoNote (..),++ -- *** Contact+ Contact (..),++ -- *** Location+ Location (..),++ -- *** Venue+ Venue (..),++ -- *** PollOption+ PollOption (..),++ -- *** Poll+ Poll (..),+ PollType (..),++ -- *** PollAnswer+ PollAnswer (..),++ -- *** Avatar+ UserProfilePhotos (..),++ -- *** File+ File (..),++ -- ** Stickers+ Sticker (..),+ StickerSet (..),+ MaskPosition (..),++ -- *** Misc+ SuccessfulPayment (..),++ -- *** Utilities+ coe,+ liftUnion,+ QueryR,+ Default (..),+ )+where++import Data.Aeson+import Data.Coerce+import Data.OpenUnion+import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.Common+import Web.Telegram.Types.Internal.Media+import Web.Telegram.Types.Internal.Sticker+import Web.Telegram.Types.Internal.User+import Web.Telegram.Types.Internal.Utils+import Web.Telegram.Types.Internal.InputMedia++data ChatId+ = ChatId Integer+ | ChanId Text+ deriving (Show, Eq, Generic, Default)+ deriving (FromJSON, ToJSON) via UntaggedSum ChatId++instance ToHttpApiData ChatId where+ toQueryParam (ChatId i) = toQueryParam i+ toQueryParam (ChanId t) = t++-- | Alias to coerce+coe :: Coercible a b => a -> b+coe = coerce++-- | Alias to required param+type QueryR = QueryParam' '[Required, Strict]
+ src/Web/Telegram/Types/Inline.hs view
@@ -0,0 +1,10 @@+module Web.Telegram.Types.Inline+ ( InlineQueryResult (..),+ InlineQuery (..),+ ChosenInlineResult (..),+ InputMessageContent (..),+ )+where++import Web.Telegram.Types.Internal.InlineQuery+import Web.Telegram.Types.Internal.InputMedia
+ src/Web/Telegram/Types/Input.hs view
@@ -0,0 +1,33 @@+-- | Sending files+module Web.Telegram.Types.Input+ ( -- * Sending Media+ InputMediaAnimation (..),+ InputMediaAudio (..),+ InputMediaDocument (..),+ InputMediaVideo (..),+ InputMediaPhoto (..),+ InputMedia,++ -- * Uploading Files+ InputFile (..),+ VideoOrPhoto,+ Cert (..),+ Thumb (..),+ Photo (..),+ Doc (..),+ Animation (..),+ Audio (..),+ Voice (..),+ Video (..),+ VideoNote (..),+ Sticker (..),+ PngSticker (..),+ TgsSticker (..),+ Media (..),+ -- Functions+ readInput,+ )+where++import Web.Telegram.Types.Internal.InputFile+import Web.Telegram.Types.Internal.InputMedia
+ src/Web/Telegram/Types/Interaction.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}++-- | User interactions: customized keyboards, clickable buttons, popups and inline displays+module Web.Telegram.Types.Interaction+ ( -- ** queries+ CallbackQuery (..),+ ShippingQuery (..),+ PreCheckoutQuery (..),+ -- ** replys+ ReplyKeyboardMarkup (..),+ KeyboardButton (..),+ KeyboardButtonPollType (..),+ ReplyKeyboardRemove (..),+ InlineKeyboardMarkup (..),+ InlineKeyboardButton (..),+ ForceReply (..),+ LoginUrl (..),+ ReplyMarkup,+ Action (..),+ )+where++import Data.Aeson+import Data.OpenUnion+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.Keyboard+import Web.Telegram.Types.Internal.Utils+import Web.Telegram.Types.Internal.Common++type ReplyMarkup =+ Union+ '[ InlineKeyboardMarkup,+ ReplyKeyboardMarkup,+ ReplyKeyboardRemove,+ ForceReply+ ]++instance ToJSON ReplyMarkup where+ toJSON =+ (\(inlineM :: InlineKeyboardMarkup) -> toJSON inlineM)+ @> (\(replyM :: ReplyKeyboardMarkup) -> toJSON replyM)+ @> (\(replyR :: ReplyKeyboardRemove) -> toJSON replyR)+ @> (\(forceR :: ForceReply) -> toJSON forceR)+ @> typesExhausted++deriving via Serialize ReplyMarkup instance ToHttpApiData ReplyMarkup++data Action+ = Typing+ | UploadPhoto+ | RecordVideo+ | UploadVideo+ | RecordAudio+ | UploadAudio+ | UploadDocument+ | FindLocation+ | RecordVideoNote+ | UploadVideoNote+ deriving (Show, Eq, Ord, Generic, Default)+ deriving (ToJSON, FromJSON) via Snake Action+ deriving (ToHttpApiData) via Serialize Action
+ src/Web/Telegram/Types/Internal/Common.hs view
@@ -0,0 +1,495 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Web.Telegram.Types.Internal.Common where++import Control.Applicative+import Data.Aeson+import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.Keyboard+import Web.Telegram.Types.Internal.Media+import Web.Telegram.Types.Internal.Passport+import Web.Telegram.Types.Internal.Sticker+import Web.Telegram.Types.Internal.User+import Web.Telegram.Types.Internal.Utils++data ChatType+ = Private+ | Group+ | Supergroup+ | Channel+ deriving (Show, Eq, Ord, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via CustomJSON '[SumUntaggedValue, ConstructorTagModifier CamelToSnake] ChatType+ deriving (ToHttpApiData) via Serialize ChatType++-- | https://core.telegram.org/bots/api#chat+data Chat+ = Chat+ { chatId :: Integer,+ chatType :: ChatType,+ title :: Maybe Text,+ username :: Maybe Text,+ firstName :: Maybe Text,+ lastName :: Maybe Text,+ photo :: Maybe ChatPhoto,+ description :: Maybe Text,+ inviteLink :: Maybe Text,+ pinnedMessage :: Maybe Message,+ permissions :: Maybe ChatPermissions,+ slowModeDelay :: Maybe Integer,+ stickerSetName :: Maybe Integer,+ canSetStickerSet :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "chat" Chat+ deriving (ToHttpApiData) via Serialize Chat++data Message+ = Msg+ { metadata :: MessageMetadata,+ content :: MessageContent+ }+ deriving (Show, Eq, Generic, Default)+ deriving (ToHttpApiData) via Serialize Message++instance FromJSON Message where+ parseJSON o = do+ metadata <- parseJSON o+ content <- parseJSON o+ return Msg {..}++instance ToJSON Message where+ toJSON Msg {..} =+ let Object hm1 = toJSON metadata+ Object hm2 = toJSON content+ in Object (hm1 <> hm2)++-- |+data MessageMetadata+ = MMetadata+ { messageId :: Integer,+ from :: Maybe User,+ date :: Integer,+ chat :: Chat,+ forwardFrom :: Maybe User,+ forwardFromChat :: Maybe Chat,+ forwardFromMessageId :: Maybe Integer,+ forwardSignature :: Maybe Text,+ forwardSenderName :: Maybe Text,+ forwardDate :: Maybe Integer,+ replyToMessage :: Maybe Message,+ editDate :: Maybe Integer,+ mediaGroupId :: Maybe Text,+ authorSignature :: Maybe Text,+ replyMarkup :: Maybe InlineKeyboardMarkup+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via CustomJSON '[SumUntaggedValue, FieldLabelModifier CamelToSnake] MessageMetadata+ deriving (ToHttpApiData) via Serialize MessageMetadata++data MessageContent+ = TextM+ { text :: Text,+ entities :: Maybe [MessageEntity]+ }+ | AudioM+ { audio :: Audio,+ caption :: Maybe Text,+ captionEntities :: Maybe [MessageEntity]+ }+ | DocumentM+ { document :: Document,+ caption :: Maybe Text,+ captionEntities :: Maybe [MessageEntity]+ }+ | AnimationM+ { animation :: Animation+ }+ | GameM+ { game :: Game+ }+ | PhotoM+ { photo :: [PhotoSize],+ caption :: Maybe Text,+ captionEntities :: Maybe [MessageEntity]+ }+ | StickerM+ { sticker :: Sticker+ }+ | VideoM+ { video :: Video,+ caption :: Maybe Text,+ captionEntities :: Maybe [MessageEntity]+ }+ | VoiceM+ { voice :: Voice,+ caption :: Maybe Text,+ captionEntities :: Maybe [MessageEntity]+ }+ | VideoNoteM+ { videoNote :: VideoNote+ }+ | ContactM+ { contact :: Contact+ }+ | LocationM+ { location :: Location+ }+ | VenueM+ { venue :: Venue+ }+ | PollM+ { poll :: Poll+ }+ | NewChatMembers+ { newChatMembers :: [User]+ }+ | LeftChatMember+ { leftChatMember :: User+ }+ | NewChatPhoto+ { newChatPhoto :: [PhotoSize]+ }+ | DeleteChatPhoto+ { deleteChatPhoto :: Bool+ }+ | GroupChatCreated+ { groupChatCreated :: Bool+ }+ | SupergroupChatCreated+ { supergroupChatCreated :: Bool+ }+ | ChannelChatCreated+ { channelChatCreated :: Bool+ }+ | MigrateToChatId+ { migrateToChatId :: Integer+ }+ | MigrateFromChatId+ { migrateFromChatId :: Integer+ }+ | PinnedMessage+ { pinnedMessage :: Message+ }+ | InvoiceM+ { invoice :: Invoice+ }+ | SuccessfulPaymentM+ { successfulPayment :: SuccessfulPayment+ }+ | ConnectedWebsite+ { connectedWebsite :: Text+ }+ | PassportData+ { passPortData :: PassportData+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via CustomJSON '[SumUntaggedValue, FieldLabelModifier CamelToSnake] MessageContent+ deriving (ToHttpApiData) via Serialize MessageContent++data MessageEntityType+ = Mention+ | Hashtag+ | Cashtag+ | BotCommand+ | Url+ | Email+ | PhoneNumber+ | Bold+ | Italic+ | Underline+ | Strikethrough+ | Code+ | Pre+ | TextLink+ | TextMention+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via CustomJSON '[SumUntaggedValue, ConstructorTagModifier CamelToSnake] MessageEntityType+ deriving (ToHttpApiData) via Serialize MessageEntityType++data MessageEntity+ = MessageEntity+ { entityType :: MessageEntityType,+ offset :: Integer,+ length :: Integer,+ url :: Maybe Text,+ user :: Maybe User,+ language :: Maybe Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "entity" MessageEntity+ deriving (ToHttpApiData) via Serialize MessageEntity++data CallbackQuery+ = CBQuery+ { callbackId :: Text,+ from :: User,+ message :: Message,+ inlineMessageId :: Maybe Text,+ chatInstance :: Text,+ callbackData :: Maybe Text,+ gameShortName :: Maybe Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "callback" CallbackQuery+ deriving (ToHttpApiData) via Serialize CallbackQuery++data ChatPhoto+ = ChatPhoto+ { smallFileId :: Text,+ smallFileUniqueId :: Text,+ bigFileId :: Text,+ bitFileUniqueId :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ChatPhoto+ deriving (ToHttpApiData) via Serialize ChatPhoto++data ChatMember+ = ChatMember+ { user :: User,+ status :: Text,+ customTitle :: Text,+ untilDate :: Maybe Integer,+ canBeEdited :: Maybe Bool,+ canPostMessages :: Maybe Bool,+ canEditMessages :: Maybe Bool,+ canDeleteMessages :: Maybe Bool,+ canRestrictMembers :: Maybe Bool,+ canPromoteMembers :: Maybe Bool,+ canChangeInfo :: Maybe Bool,+ canInviteUsers :: Maybe Bool,+ canPinMessages :: Maybe Bool,+ isMember :: Maybe Bool,+ canSendMessages :: Maybe Bool,+ canSendMediaMessages :: Maybe Bool,+ canSendPolls :: Maybe Bool,+ canSendOtherMesssages :: Maybe Bool,+ canAddWebPagePreviews :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ChatMember+ deriving (ToHttpApiData) via Serialize ChatMember++data ChatPermissions+ = ChatPermissions+ { canSendMessages :: Maybe Bool,+ canSendMediaMessages :: Maybe Bool,+ canSendPolls :: Maybe Bool,+ canSendOtherMesssages :: Maybe Bool,+ canAddWebPagePreviews :: Maybe Bool,+ canChangeInfo :: Maybe Bool,+ canInviteUsers :: Maybe Bool,+ canPinMessages :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ChatPermissions+ deriving (ToHttpApiData) via Serialize ChatPermissions++data BotCommand+ = BC+ { command :: Text,+ description :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via OmitNothing BotCommand+ deriving (ToHttpApiData) via Serialize BotCommand++data LabeledPrice+ = LabeledPrice+ { label :: Text,+ amount :: Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via OmitNothing LabeledPrice+ deriving (ToHttpApiData) via Serialize LabeledPrice++data Invoice+ = Invoice+ { title :: Text,+ description :: Text,+ startParameter :: Text,+ currency :: Text,+ totalAmount :: Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Invoice+ deriving (ToHttpApiData) via Serialize Invoice++data ShippingAddress+ = ShippingAddress+ { countryCode :: Text,+ state :: Text,+ city :: Text,+ streetLine1 :: Text,+ streetLine2 :: Text,+ postCode :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ShippingAddress+ deriving (ToHttpApiData) via Serialize ShippingAddress++data OrderInfo+ = OrderInfo+ { name :: Maybe Text,+ phoneNumber :: Maybe Text,+ email :: Maybe Text,+ shippingAddress :: ShippingAddress+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake OrderInfo+ deriving (ToHttpApiData) via Serialize OrderInfo++data ShippingOption+ = ShippingOption+ { optionId :: Text,+ title :: Text,+ prices :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "option" ShippingOption+ deriving (ToHttpApiData) via Serialize ShippingOption++data SuccessfulPayment+ = SuccessfulPayment+ { currency :: Text,+ totalAmount :: Integer,+ invoicePayload :: Text,+ shippingOptionId :: Maybe Text,+ orderInfo :: Maybe OrderInfo,+ telegramPaymentChargeId :: Text,+ providerPaymentChargeId :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake SuccessfulPayment+ deriving (ToHttpApiData) via Serialize SuccessfulPayment++data ShippingQuery+ = SQuery+ { queryId :: Text,+ from :: User,+ invoicePayload :: Text,+ shippingAddress :: ShippingAddress+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "query" ShippingQuery+ deriving (ToHttpApiData) via Serialize ShippingQuery++data PreCheckoutQuery+ = PCQuery+ { queryId :: Text,+ from :: User,+ currency :: Text,+ totalAmount :: Integer,+ invoicePayload :: Text,+ shippingOptionId :: Maybe String,+ orderInfo :: Maybe OrderInfo+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "query" PreCheckoutQuery+ deriving (ToHttpApiData) via Serialize PreCheckoutQuery++data Game+ = Game+ { title :: Text,+ description :: Text,+ photo :: [PhotoSize],+ text :: Maybe Text,+ textEntities :: Maybe MessageEntity,+ animation :: Animation+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Game+ deriving (ToHttpApiData) via Serialize Game++data CallbackGame++data GameHighScore+ = GameHighScore+ { position :: Integer,+ user :: User,+ score :: Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via OmitNothing GameHighScore+ deriving (ToHttpApiData) via Serialize GameHighScore++data ResponseParameters+ = ResponseParameters+ { migrateToChatId :: Maybe Integer,+ retryAfter :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ResponseParameters+ deriving (ToHttpApiData) via Serialize ResponseParameters++newtype ReqResult a+ = Ok a+ deriving (Show, Eq, Generic)++instance (FromJSON a) => FromJSON (ReqResult a) where+ parseJSON = withObject "request result" $ \o -> do+ a <- o .: "result"+ a' <- parseJSON a+ return $ Ok a'++data ReqEither a b+ = LLL a+ | RRR b+ deriving (Show, Eq, Generic)++instance (FromJSON a, FromJSON b) => FromJSON (ReqEither a b) where+ parseJSON o = LLL <$> parseJSON o <|> RRR <$> parseJSON o
+ src/Web/Telegram/Types/Internal/InlineQuery.hs view
@@ -0,0 +1,288 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE DuplicateRecordFields #-}++module Web.Telegram.Types.Internal.InlineQuery where++import Data.Aeson+import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.InputMedia+import Web.Telegram.Types.Internal.Keyboard+import Web.Telegram.Types.Internal.Media+import Web.Telegram.Types.Internal.User+import Web.Telegram.Types.Internal.Utils++data InlineQuery+ = IQ+ { queryId :: Text,+ from :: User,+ location :: Maybe Location,+ query :: Text,+ offset :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake' "query" InlineQuery+ deriving (ToHttpApiData) via Serialize InlineQuery++data InlineQueryResult+ = InlineQueryResultArticle+ { resultType :: Text,+ resultId :: Text,+ title :: Text,+ resultInputMessageContent :: InputMessageContent,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ url :: Text,+ hideUrl :: Maybe Bool,+ description :: Maybe Text,+ thumbUrl :: Maybe Text,+ thumbWidth :: Maybe Integer,+ thumbHeight :: Maybe Integer+ }+ | InlineQueryResultPhoto+ { resultType :: Text,+ resultId :: Text,+ photoUrl :: Text,+ thumbUrl' :: Text,+ photoWidth :: Maybe Integer,+ photoHeight :: Maybe Integer,+ resultTitle :: Maybe Text,+ description :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultGif+ { resultType :: Text,+ resultId :: Text,+ gifUrl :: Text,+ gifWidth :: Maybe Integer,+ gifHeight :: Maybe Integer,+ gifDuration :: Maybe Integer,+ thumbUrl' :: Text,+ resultTitle :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultMpeg4Gif+ { resultType :: Text,+ resultId :: Text,+ mpeg4Url :: Text,+ mpeg4Width :: Maybe Integer,+ mpeg4Height :: Maybe Integer,+ mpeg4Duration :: Maybe Integer,+ thumbUrl' :: Text,+ resultTitle :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultVideo+ { resultType :: Text,+ resultId :: Text,+ videoUrl :: Text,+ mimeType :: Text,+ thumbUrl' :: Text,+ title :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ videoWidth :: Maybe Integer,+ videoHeight :: Maybe Integer,+ videoDuration :: Maybe Integer,+ description :: Maybe Text,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultAudio+ { resultType :: Text,+ resultId :: Text,+ audioUrl :: Text,+ title :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ performer :: Maybe Text,+ audioDuration :: Maybe Integer,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultVoice+ { resultType :: Text,+ resultId :: Text,+ voiceUrl :: Text,+ title :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ voiceDuration :: Maybe Integer,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultDocument+ { resultType :: Text,+ resultId :: Text,+ documentUrl :: Text,+ mimeType :: Text,+ title :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ description :: Maybe Text,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent,+ thumbUrl :: Maybe Text,+ thumbWidth :: Maybe Integer,+ thumbHeight :: Maybe Integer+ }+ | InlineQueryResultLocation+ { resultType :: Text,+ resultId :: Text,+ latitude :: Float,+ longitude :: Float,+ title :: Text,+ livePeriod :: Maybe Integer,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent,+ thumbUrl :: Maybe Text,+ thumbWidth :: Maybe Integer,+ thumbHeight :: Maybe Integer+ }+ | InlineQueryResultVenue+ { resultType :: Text,+ resultId :: Text,+ latitude :: Float,+ longitude :: Float,+ title :: Text,+ address :: Text,+ foursquareId :: Text,+ foursquareType :: Maybe Text,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent,+ thumbUrl :: Maybe Text,+ thumbWidth :: Maybe Integer,+ thumbHeight :: Maybe Integer+ }+ | InlineQueryResultContact+ { resultType :: Text,+ resultId :: Text,+ phoneNumber :: Text,+ firstName :: Text,+ lastName :: Maybe Text,+ vcard :: Maybe Text,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent,+ thumbUrl :: Maybe Text,+ thumbWidth :: Maybe Integer,+ thumbHeight :: Maybe Integer+ }+ | InlineQueryResultGame+ { resultType :: Text,+ resultId :: Text,+ gameShortName :: Text,+ replyMarkup :: Maybe InlineKeyboardMarkup+ }+ | InlineQueryResultCachedPhoto+ { resultType :: Text,+ resultId :: Text,+ photoFileId :: Text,+ resultTitle :: Maybe Text,+ description :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultCachedGif+ { resultType :: Text,+ resultId :: Text,+ gifFileId :: Text,+ title :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultCachedMpeg4Gif+ { resultType :: Text,+ resultId :: Text,+ mpeg4FileId :: Text,+ title :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultCachedSticker+ { resultType :: Text,+ resultId :: Text,+ stickerFileId :: Text,+ title :: Text,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultCachedDocument+ { resultType :: Text,+ resultId :: Text,+ title :: Text,+ documentFileId :: Text,+ description :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultCachedVideo+ { resultType :: Text,+ resultId :: Text,+ videoFileId :: Text,+ title :: Text,+ description :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultCachedVoice+ { resultType :: Text,+ resultId :: Text,+ voiceFileId :: Text,+ title :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ | InlineQueryResultCachedAudio+ { resultType :: Text,+ resultId :: Text,+ audioFileId :: Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ replyMarkup :: Maybe InlineKeyboardMarkup,+ inputMessageContent :: Maybe InputMessageContent+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "result" InlineQueryResult+ deriving (ToHttpApiData) via Serialize InlineQueryResult++data ChosenInlineResult+ = ChosenIR+ { resultId :: Text,+ from :: User,+ location :: Maybe Location,+ inlineMessageId :: Maybe Text,+ query :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ChosenInlineResult+ deriving (ToHttpApiData) via Serialize ChosenInlineResult
+ src/Web/Telegram/Types/Internal/InputFile.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++module Web.Telegram.Types.Internal.InputFile where++import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as LBS+import Data.Proxy+import Data.Text (Text, pack)+import Data.Text.Encoding+import GHC.Generics+import GHC.TypeLits+import Network.Mime+import Servant.Multipart+import System.FilePath+import Web.Telegram.Types.Internal.Utils++data InputFile+ = InputFile+ { fileName :: Text,+ mimeType :: Text,+ content :: ByteString+ }+ deriving (Show, Eq, Generic, Default)++readInput :: FilePath -> IO InputFile+readInput fp = do+ content <- LBS.readFile fp+ let fileName = pack $ takeFileName fp+ let mimeType = decodeUtf8 $ defaultMimeLookup fileName+ return InputFile {..}++type Multi = ToMultipart Mem++newtype InputF n = InputF InputFile++instance (KnownSymbol s) => ToMultipart Mem (InputF s) where+ toMultipart (InputF f) =+ MultipartData+ { inputs = [],+ files =+ pure $+ FileData+ { fdInputName = pack $ symbolVal @s Proxy,+ fdFileName = fileName f,+ fdFileCType = mimeType f,+ fdPayload = content f+ }+ }++newtype Cert = Cert InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "certificate"++newtype Thumb = Thumb InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "thumb"++newtype Photo = Photo InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "photo"++newtype Audio = Audio InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "audio"++newtype Doc = Doc InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "document"++newtype Video = Video InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "video"++newtype Animation = Animation InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "animation"++newtype Voice = Voice InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "voice"++newtype VideoNote = VideoNote InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "video_note"++newtype Sticker = Sticker InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "sticker"++newtype PngSticker = PngSticker InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "png_sticker"++newtype TgsSticker = TgsSticker InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "tgs_sticker"++newtype Media = Media InputFile+ deriving (Show, Eq, Generic, Default)+ deriving (Multi) via InputF "media"
+ src/Web/Telegram/Types/Internal/InputMedia.hs view
@@ -0,0 +1,283 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeOperators #-}++module Web.Telegram.Types.Internal.InputMedia where++import Data.Aeson+import Data.Maybe (catMaybes)+import Data.OpenUnion+import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Servant.Multipart+import Web.Telegram.Types.Internal.InputFile+import Web.Telegram.Types.Internal.Utils++data ParseMode+ = MarkdownV2+ | HTML+ | Markdown+ deriving (Show, Eq, Ord, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via OmitNothing ParseMode+ deriving (ToHttpApiData) via Serialize ParseMode++type VideoOrPhoto = Union '[InputMediaPhoto, InputMediaVideo]++instance ToJSON VideoOrPhoto where+ toJSON =+ (\(photo :: InputMediaPhoto) -> toJSON photo)+ @> (\(video :: InputMediaVideo) -> toJSON video)+ @> typesExhausted++instance ToMultipart Mem VideoOrPhoto where+ toMultipart =+ (\(photo :: InputMediaPhoto) -> toMultipart photo)+ @> (\(video :: InputMediaVideo) -> toMultipart video)+ @> typesExhausted++deriving via Serialize VideoOrPhoto instance ToHttpApiData VideoOrPhoto++type InputMedia =+ Union+ '[ InputMediaAnimation,+ InputMediaDocument,+ InputMediaAudio,+ InputMediaVideo,+ InputMediaPhoto+ ]++instance ToJSON InputMedia where+ toJSON =+ (\(anim :: InputMediaAnimation) -> toJSON anim)+ @> (\(doc :: InputMediaDocument) -> toJSON doc)+ @> (\(audio :: InputMediaAudio) -> toJSON audio)+ @> (\(video :: InputMediaVideo) -> toJSON video)+ @> (\(photo :: InputMediaPhoto) -> toJSON photo)+ @> typesExhausted++instance ToMultipart Mem InputMedia where+ toMultipart =+ (\(anim :: InputMediaAnimation) -> toMultipart anim)+ @> (\(doc :: InputMediaDocument) -> toMultipart doc)+ @> (\(audio :: InputMediaAudio) -> toMultipart audio)+ @> (\(video :: InputMediaVideo) -> toMultipart video)+ @> (\(photo :: InputMediaPhoto) -> toMultipart photo)+ @> typesExhausted++deriving via Serialize InputMedia instance ToHttpApiData InputMedia++data InputMediaAnimation+ = InputMediaAnimation+ { media :: Either Text Media,+ thumb :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ width :: Maybe Integer,+ height :: Maybe Integer,+ duration :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving (ToHttpApiData) via Serialize InputMediaAnimation++(.=?) :: ToJSON v => Text -> Maybe v -> Maybe (Text, Value)+k .=? v = (k .=) <$> v++instance ToJSON InputMediaAnimation where+ toJSON InputMediaAnimation {..} =+ let m = case media of+ Left t -> t+ Right (Media m') -> "attach://" <> fileName m'+ in object $+ [ "type" .= ("animation" :: Text),+ "media" .= m+ ]+ <> catMaybes+ [ "thumb" .=? thumb,+ "caption" .=? caption,+ "parse_mode" .=? parseMode,+ "width" .=? width,+ "height" .=? height,+ "duration" .=? duration+ ]++instance ToMultipart Mem InputMediaAnimation where+ toMultipart InputMediaAnimation {..} =+ case media of+ Right m -> toMultipart m+ Left _ -> emptyData++data InputMediaAudio+ = InputMediaAudio+ { media :: Either Text Media,+ thumb :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode,+ duration :: Maybe Integer,+ performer :: Maybe Text,+ title :: Maybe Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving (ToHttpApiData) via Serialize InputMediaAudio++instance ToJSON InputMediaAudio where+ toJSON InputMediaAudio {..} =+ let m = case media of+ Left t -> t+ Right (Media m') -> "attach://" <> fileName m'+ in object $+ [ "type" .= ("audio" :: Text),+ "media" .= m+ ]+ <> catMaybes+ [ "thumb" .=? thumb,+ "caption" .=? caption,+ "parse_mode" .=? parseMode,+ "duration" .=? duration,+ "performer" .=? performer,+ "title" .=? title+ ]++instance ToMultipart Mem InputMediaAudio where+ toMultipart InputMediaAudio {..} =+ case media of+ Right m -> toMultipart m+ Left _ -> emptyData++data InputMediaDocument+ = InputMediaDocument+ { media :: Either Text Media,+ thumb :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode+ }+ deriving (Show, Eq, Generic, Default)+ deriving (ToHttpApiData) via Serialize InputMediaDocument++instance ToJSON InputMediaDocument where+ toJSON InputMediaDocument {..} =+ let m = case media of+ Left t -> t+ Right (Media m') -> "attach://" <> fileName m'+ in object $+ [ "type" .= ("document" :: Text),+ "media" .= m+ ]+ <> catMaybes+ [ "thumb" .=? thumb,+ "caption" .=? caption,+ "parse_mode" .=? parseMode+ ]++instance ToMultipart Mem InputMediaDocument where+ toMultipart InputMediaDocument {..} =+ case media of+ Right m -> toMultipart m+ Left _ -> emptyData++data InputMediaPhoto+ = InputMediaPhoto+ { media :: Either Text Media,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode+ }+ deriving (Show, Eq, Generic, Default)+ deriving (ToHttpApiData) via Serialize InputMediaPhoto++instance ToJSON InputMediaPhoto where+ toJSON InputMediaPhoto {..} =+ let m = case media of+ Left t -> t+ Right (Media m') -> "attach://" <> fileName m'+ in object $+ [ "type" .= ("photo" :: Text),+ "media" .= m+ ]+ <> catMaybes+ [ "caption" .=? caption,+ "parse_mode" .=? parseMode+ ]++instance ToMultipart Mem InputMediaPhoto where+ toMultipart InputMediaPhoto {..} =+ case media of+ Right m -> toMultipart m+ Left _ -> emptyData++data InputMediaVideo+ = InputMediaVideo+ { media :: Either Text Media,+ thumb :: Maybe Text,+ caption :: Maybe Text,+ parseMode :: Maybe ParseMode+ }+ deriving (Show, Eq, Generic, Default)+ deriving (ToHttpApiData) via Serialize InputMediaVideo++instance ToJSON InputMediaVideo where+ toJSON InputMediaVideo {..} =+ let m = case media of+ Left t -> t+ Right (Media m') -> "attach://" <> fileName m'+ in object $+ [ "type" .= ("video" :: Text),+ "media" .= m+ ]+ <> catMaybes+ [ "thumb" .=? thumb,+ "caption" .=? caption,+ "parse_mode" .=? parseMode+ ]++instance ToMultipart Mem InputMediaVideo where+ toMultipart InputMediaVideo {..} =+ case media of+ Right m -> toMultipart m+ Left _ -> emptyData++data InputMessageContent+ = InputTextMessageContent+ { messageText :: Text,+ parseMode :: Maybe ParseMode,+ disableWebPagePreview :: Maybe Bool+ }+ | InputLocationMessageContent+ { latitude :: Float,+ longitude :: Float,+ livePeriod :: Maybe Integer+ }+ | InputVenueMessageContent+ { latitude :: Float,+ longitude :: Float,+ title :: Text,+ address :: Text,+ foursquareId :: Text,+ foursquareType :: Text+ }+ | InputContactMessageContent+ { phoneNumber :: Text,+ firstName :: Text,+ lastName :: Maybe Text,+ vcard :: Maybe Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake InputMessageContent+ deriving (ToHttpApiData) via Serialize InputMessageContent++------++emptyData :: MultipartData a+emptyData = MultipartData [] []
+ src/Web/Telegram/Types/Internal/Keyboard.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE DuplicateRecordFields #-}++module Web.Telegram.Types.Internal.Keyboard where++import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.Media+import Web.Telegram.Types.Internal.Utils++data ReplyKeyboardMarkup+ = ReplyKeyboardMarkup+ { keyboard :: [[KeyboardButton]],+ resizeKeyboard :: Maybe Bool,+ oneTimeKeyboard :: Maybe Bool,+ selective :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ReplyKeyboardMarkup+ deriving (ToHttpApiData) via Serialize ReplyKeyboardMarkup++data KeyboardButton+ = KeyboardButton+ { text :: Text,+ requestContact :: Maybe Bool,+ requestLocation :: Maybe Bool,+ requestPoll :: Maybe KeyboardButtonPollType+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake KeyboardButton+ deriving (ToHttpApiData) via Serialize KeyboardButton++newtype KeyboardButtonPollType+ = KeyboardButtonPollType+ { pollType :: Maybe PollType+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "poll" KeyboardButtonPollType+ deriving (ToHttpApiData) via Serialize KeyboardButtonPollType++data ReplyKeyboardRemove+ = ReplyKeyboardRemove+ { removeKeyboard :: Bool,+ selective :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ReplyKeyboardRemove+ deriving (ToHttpApiData) via Serialize ReplyKeyboardRemove++newtype InlineKeyboardMarkup+ = InlineKeyboardMarkup+ { inlineKeyboard :: [[InlineKeyboardButton]]+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (ToJSON, FromJSON)+ via Snake InlineKeyboardMarkup+ deriving (ToHttpApiData) via Serialize InlineKeyboardMarkup++data InlineKeyboardButton+ = InlineKeyboardButton+ { text :: Text,+ url :: Maybe Text,+ loginUrl :: Maybe LoginUrl,+ callbackData :: Maybe Text,+ switchInlineQuery :: Maybe Text,+ switchInlineQueryCurrentChat :: Maybe Text,+ pay :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake InlineKeyboardButton+ deriving (ToHttpApiData) via Serialize InlineKeyboardButton++data LoginUrl+ = LoginUrl+ { url :: Text,+ forwardText :: Maybe Text,+ botUsername :: Maybe Text,+ requestWriteAccess :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake LoginUrl+ deriving (ToHttpApiData) via Serialize LoginUrl++data ForceReply+ = ForceReply+ { forceReply :: Bool,+ selective :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake ForceReply+ deriving (ToHttpApiData) via Serialize ForceReply
+ src/Web/Telegram/Types/Internal/Media.hs view
@@ -0,0 +1,237 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE DuplicateRecordFields #-}++module Web.Telegram.Types.Internal.Media where++import Data.Aeson+import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.User+import Web.Telegram.Types.Internal.Utils++data PhotoSize+ = PhotoSize+ { fileId :: Text,+ fileUniqueId :: Text,+ width :: Integer,+ height :: Integer,+ fileSize :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake PhotoSize+ deriving (ToHttpApiData) via Serialize PhotoSize++data Audio+ = Audio+ { fileId :: Text,+ fileUniqueId :: Text,+ duration :: Integer,+ performer :: Maybe Text,+ title :: Maybe Text,+ mimeType :: Maybe Text,+ fileSize :: Maybe Integer,+ thumb :: Maybe PhotoSize+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Audio+ deriving (ToHttpApiData) via Serialize Audio++data Document+ = Document+ { fileId :: Text,+ fileUniqueId :: Text,+ thumb :: Maybe PhotoSize,+ fileName :: Maybe Text,+ mimeType :: Maybe Text,+ fileSize :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Document+ deriving (ToHttpApiData) via Serialize Document++data Video+ = Video+ { fileId :: Text,+ fileUniqueId :: Text,+ width :: Integer,+ height :: Integer,+ duration :: Integer,+ thumb :: Maybe PhotoSize,+ mimeType :: Maybe Text,+ fileSize :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Video+ deriving (ToHttpApiData) via Serialize Video++data Animation+ = Animation+ { fileId :: Text,+ fileUniqueId :: Text,+ width :: Integer,+ height :: Integer,+ duration :: Integer,+ thumb :: Maybe PhotoSize,+ fileName :: Maybe Text,+ mimeType :: Maybe Text,+ fileSize :: Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Animation+ deriving (ToHttpApiData) via Serialize Animation++data Voice+ = Voice+ { fileId :: Text,+ fileUniqueId :: Text,+ duration :: Integer,+ mimeType :: Maybe Text,+ fileSize :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Voice+ deriving (ToHttpApiData) via Serialize Voice++data VideoNote+ = VideoNote+ { fileId :: Text,+ fileUniqueId :: Text,+ length :: Integer,+ duration :: Integer,+ thumb :: Maybe PhotoSize,+ fileSize :: Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake VideoNote+ deriving (ToHttpApiData) via Serialize VideoNote++data Contact+ = Contact+ { phoneNumber :: Text,+ firstName :: Text,+ lastName :: Maybe Text,+ userId :: Maybe Integer,+ vcard :: Maybe Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Contact+ deriving (ToHttpApiData) via Serialize Contact++data Location+ = Location+ { longitude :: Float,+ latitude :: Float+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via OmitNothing Location+ deriving (ToHttpApiData) via Serialize Location++data Venue+ = Venue+ { location :: Location,+ title :: Text,+ address :: Text,+ foursquareId :: Maybe Text,+ foursquareType :: Maybe Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Venue+ deriving (ToHttpApiData) via Serialize Venue++data PollOption+ = PollOption+ { text :: Text,+ voterCount :: Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake PollOption+ deriving (ToHttpApiData) via Serialize PollOption++data PollAnswer+ = PollAnswer+ { pollId :: Text,+ user :: User,+ optionIds :: [Integer]+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "poll" PollAnswer+ deriving (ToHttpApiData) via Serialize PollAnswer++data PollType+ = Regular+ | Quiz+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via CustomJSON '[SumUntaggedValue, ConstructorTagModifier CamelToSnake] PollType+ deriving (ToHttpApiData) via Serialize PollType++data Poll+ = Poll+ { pollId :: Text,+ question :: Text,+ options :: [PollOption],+ totalVoterCount :: Integer,+ isClosed :: Bool,+ isAnonymous :: Bool,+ pollType :: PollType,+ allowsMultipleAnswers :: Bool,+ correctOptionId :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "poll" Poll+ deriving (ToHttpApiData) via Serialize Poll++data UserProfilePhotos+ = UserProfilePhotos+ { totalCount :: Integer,+ photos :: [[PhotoSize]]+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake UserProfilePhotos+ deriving (ToHttpApiData) via Serialize UserProfilePhotos++data File+ = File+ { fileId :: Text,+ fileUniqueId :: Text,+ fileSize :: Maybe Integer,+ filePath :: Maybe Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake File+ deriving (ToHttpApiData) via Serialize File
+ src/Web/Telegram/Types/Internal/Passport.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE DuplicateRecordFields #-}++module Web.Telegram.Types.Internal.Passport where++import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.Utils++data PassportData+ = PassportData+ { passportData :: [EncryptedPassportElement],+ credentials :: EncryptedCredentials+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake "passport" PassportData+ deriving (ToHttpApiData) via Serialize PassportData++data PassportFile+ = PassportFile+ { fileId :: Text,+ fileUniqueId :: Text,+ fileSize :: Integer,+ fileDate :: Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (ToJSON, FromJSON)+ via Snake PassportFile+ deriving (ToHttpApiData) via Serialize PassportFile++data EncryptedPassportElement+ = EncryptedPassportElement+ { elementType :: EncryptedPassportElementType,+ elementData :: Maybe Text,+ phoneNumber :: Maybe Text,+ email :: Maybe Text,+ files :: Maybe [PassportFile],+ frontSide :: Maybe PassportFile,+ reverseSide :: Maybe PassportFile,+ selfie :: Maybe PassportFile,+ translation :: Maybe [PassportFile],+ hash :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (ToJSON, FromJSON)+ via PrefixedSnake "element" EncryptedPassportElement++data EncryptedCredentials+ = EncryptedCredentials+ { credentialData :: Text,+ hash :: Text,+ secret :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (ToJSON, FromJSON)+ via PrefixedSnake "credential" EncryptedCredentials++data PassportElementError+ = PassportElementErrorDataField+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fieldName :: Text,+ dataHash :: Text,+ message :: Text+ }+ | PassportElementErrorFrontSide+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fileHash :: Text,+ message :: Text+ }+ | PassportElementErrorReverseSide+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fileHash :: Text,+ message :: Text+ }+ | PassportElementErrorSelfie+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fileHash :: Text,+ message :: Text+ }+ | PassportElementErrorFile+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fileHash :: Text,+ message :: Text+ }+ | PassportElementErrorFiles+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fileHashes :: [Text],+ message :: Text+ }+ | PassportElementErrorTranslationFile+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fileHash :: Text,+ message :: Text+ }+ | PassportElementErrorTranslationFiles+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ fileHashes :: [Text],+ message :: Text+ }+ | PassportElementErrorUnspecified+ { source :: Text,+ errorType :: EncryptedPassportElementType,+ elementHash :: Text,+ message :: Text+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (ToJSON, FromJSON)+ via PrefixedSnake "error" PassportElementError+ deriving (ToHttpApiData) via Serialize PassportElementError++data EncryptedPassportElementType+ = PersonalDetails+ | Passport+ | DriverLicense+ | IdentityCard+ | InternalPassport+ | Address+ | UtilityBill+ | BankStatement+ | RentalAgreement+ | PassportRegistration+ | TemporaryRegistration+ | PhoneNumber+ | Email+ deriving (Show, Eq, Ord, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via CustomJSON '[SumUntaggedValue, ConstructorTagModifier CamelToSnake] EncryptedPassportElementType+ deriving (ToHttpApiData) via Serialize EncryptedPassportElementType
+ src/Web/Telegram/Types/Internal/Sticker.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE DuplicateRecordFields #-}++module Web.Telegram.Types.Internal.Sticker where++import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.Media+import Web.Telegram.Types.Internal.Utils++data Sticker+ = Sticker+ { fileId :: Text,+ fileUniqueId :: Text,+ width :: Integer,+ height :: Integer,+ isAnimated :: Bool,+ thumb :: Maybe PhotoSize,+ emoji :: Maybe Text,+ setName :: Maybe Text,+ maskPosition :: Maybe MaskPosition,+ fileSize :: Maybe Integer+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake Sticker+ deriving (ToHttpApiData) via Serialize Sticker++data StickerSet+ = StickerSet+ { name :: Text,+ title :: Text,+ isAnimated :: Bool,+ containsMasks :: Bool,+ stickers :: [Sticker]+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake StickerSet+ deriving (ToHttpApiData) via Serialize StickerSet++data MaskPosition+ = MaskPosition+ { point :: Text,+ xShift :: Float,+ yShift :: Float,+ scale :: Float+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake MaskPosition+ deriving (ToHttpApiData) via Serialize MaskPosition
+ src/Web/Telegram/Types/Internal/Update.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}++module Web.Telegram.Types.Internal.Update where++import Data.Aeson+import Data.Monoid+import Data.Text (Text)+import Deriving.Aeson+import qualified Web.Telegram.Types.Internal.Common as C+import qualified Web.Telegram.Types.Internal.InlineQuery as IQ+import qualified Web.Telegram.Types.Internal.Media as M+import Web.Telegram.Types.Internal.UpdateType (UpdateType)+import Web.Telegram.Types.Internal.Utils++-- | An incoming update+data Update+ = -- | New incoming message of any kind — text, photo, sticker, etc.+ Message+ { updateId :: Integer,+ message :: C.Message+ }+ | -- | New version of a message that is known to the bot and was edited+ EditedMessage+ { updateId :: Integer,+ message :: C.Message+ }+ | -- | New incoming channel post of any kind — text, photo, sticker, etc.+ ChannelPost+ { updateId :: Integer,+ message :: C.Message+ }+ | -- | New version of a channel post that is known to the bot and was edited+ EditedChannelPost+ { updateId :: Integer,+ message :: C.Message+ }+ | -- | New incoming inline query+ InlineQuery+ { updateId :: Integer,+ iquery :: IQ.InlineQuery+ }+ | -- | The result of an inline query that was chosen by a user and sent to their chat partner. Please see our documentation on the feedback collecting for details on how to enable these updates for your bot+ ChosenInlineResult+ { updateId :: Integer,+ result :: IQ.ChosenInlineResult+ }+ | -- | New incoming callback query+ CallbackQuery+ { updateId :: Integer,+ cbquery :: C.CallbackQuery+ }+ | -- | New incoming shipping query. Only for invoices with flexible price+ ShippingQuery+ { updateId :: Integer,+ squery :: C.ShippingQuery+ }+ | -- | New incoming pre-checkout query. Contains full information about checkout+ PreCheckoutQuery+ { updateId :: Integer,+ pcquery :: C.PreCheckoutQuery+ }+ | -- | New poll state. Bots receive only updates about stopped polls and polls, which are sent by the bot+ PollUpdate+ { updateId :: Integer,+ poll :: M.Poll+ }+ | -- | A user changed their answer in a non-anonymous poll. Bots receive new votes only in polls that were sent by the bot itself.+ PollAnswer+ { updateId :: Integer,+ answer :: M.PollAnswer+ }+ deriving (Show, Eq, Generic, Default)++instance FromJSON Update where+ parseJSON = withObject "Update object" $ \o -> do+ uid <- o .: "update_id"+ let pair (k, c) = do+ m <- o .:? k+ return $ fmap (c uid) m+ l <-+ sequence+ [ pair ("message", Message),+ pair ("edited_message", EditedMessage),+ pair ("channel_post", ChannelPost),+ pair ("edited_channel_post", EditedChannelPost),+ pair ("inline_query", InlineQuery),+ pair ("chosen_inline_result", ChosenInlineResult),+ pair ("callback_query", CallbackQuery),+ pair ("shipping_query", ShippingQuery),+ pair ("pre_checkout_query", PreCheckoutQuery),+ pair ("poll", PollUpdate),+ pair ("poll_answer", PollAnswer)+ ]+ let r = getFirst $ foldMap First l+ case r of+ Nothing -> fail "Empty Message"+ Just r' -> return r'++-- | Contains information about the current status of a webhook.+data WebhookInfo+ = WebhookInfo+ { -- | Webhook URL, may be empty if webhook is not set up+ url :: Text,+ -- | True, if a custom certificate was provided for webhook certificate checks+ hasCustomCertificate :: Bool,+ -- | Number of updates awaiting delivery+ pendingUpdateCount :: Integer,+ -- | Unix time for the most recent error that happened when trying to deliver an update via webhook+ lastErrorDate :: Maybe Integer,+ -- | Error message in human-readable format for the most recent error that happened when trying to deliver an update via webhook+ lastErrorMessage :: Maybe Text,+ -- | Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery+ maxConnections :: Maybe Integer,+ -- | A list of update types the bot is subscribed to. Defaults to all update types+ allowedUpdates :: Maybe [UpdateType]+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via Snake WebhookInfo
+ src/Web/Telegram/Types/Internal/UpdateType.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}++module Web.Telegram.Types.Internal.UpdateType where++import Deriving.Aeson+import Web.Telegram.Types.Internal.Utils++data UpdateType+ = Message+ | EditedMessage+ | ChannelPost+ | EditedChannelPost+ | InlineQuery+ | ChosenInlineResult+ | CallbackQuery+ | ShippingQuery+ | PreCheckoutQuery+ | PollUpdate+ | PollAnswer+ deriving (Show, Eq, Generic, Default, Enum)+ deriving+ (FromJSON, ToJSON)+ via CustomJSON '[SumUntaggedValue, ConstructorTagModifier CamelToSnake] UpdateType
+ src/Web/Telegram/Types/Internal/User.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Web.Telegram.Types.Internal.User+ ( User (..),+ )+where++import Data.Aeson+import Data.Text (Text)+import Deriving.Aeson+import Servant.API+import Web.Telegram.Types.Internal.Utils++-- | A Telegram user or bot.+data User+ = User+ { -- | Unique identifier for this user or bot+ userId :: Integer,+ -- | True, if this user is a bot+ isBot :: Bool,+ -- | User's or bot's first name+ firstName :: Text,+ -- | User's or bot's last name+ lastName :: Maybe Text,+ -- | User's or bot's username+ username :: Maybe Text,+ -- | [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) of the user's language+ languageCode :: Maybe Text,+ -- | True, if the bot can be invited to groups. Returned only in getMe+ canJoinGroups :: Maybe Bool,+ -- | True, if privacy mode is disabled for the bot. Returned only in getMe+ canReadAllGroupMessages :: Maybe Bool,+ -- | True, if the bot supports inline queries. Returned only in getMe.+ supportsInlineQueries :: Maybe Bool+ }+ deriving (Show, Eq, Generic, Default)+ deriving+ (FromJSON, ToJSON)+ via PrefixedSnake' "user" User+ deriving (ToHttpApiData) via Serialize User
+ src/Web/Telegram/Types/Internal/Utils.hs view
@@ -0,0 +1,19 @@+module Web.Telegram.Types.Internal.Utils+ ( module Web.Telegram.Types.Internal.Utils.Default,+ module Web.Telegram.Types.Internal.Utils.Stock,+ Serialize (..),+ )+where++import Data.Aeson+import Data.Aeson.Text+import Data.Text.Lazy+import Servant.API+import Web.Telegram.Types.Internal.Utils.Default+import Web.Telegram.Types.Internal.Utils.Stock++-- | wrapper for serializing+newtype Serialize a = Serialize a++instance (ToJSON a) => ToHttpApiData (Serialize a) where+ toQueryParam (Serialize a) = toStrict $ encodeToLazyText a
+ src/Web/Telegram/Types/Internal/Utils/Default.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}++module Web.Telegram.Types.Internal.Utils.Default where++import Data.ByteString.Lazy (ByteString)+import Data.Dynamic+import Data.Int+import Data.OpenUnion+import Data.Text (Text)+import GHC.Generics++class GDefault f where+ gdef :: f a++instance GDefault U1 where+ gdef = U1++instance (Default a) => GDefault (K1 i a) where+ gdef = K1 def++instance (GDefault a, GDefault b) => GDefault (a :*: b) where+ gdef = gdef :*: gdef++instance (GDefault a) => GDefault (M1 i c a) where+ gdef = M1 gdef++instance (GDefault a, GDefault b) => GDefault (a :+: b) where+ gdef = L1 gdef++-- | A class for types with a default value.+class Default a where+ def :: a+ default def :: (Generic a, GDefault (Rep a)) => a+ def = to gdef++instance Default (Maybe a) where+ def = Nothing++instance Default () where+ def = ()++instance Default Bool where+ def = False++instance Default Int where+ def = 0++instance Default Int8 where+ def = 0++instance Default Int16 where+ def = 0++instance Default Int32 where+ def = 0++instance Default Int64 where+ def = 0++instance Default Integer where+ def = 0++instance Default Float where+ def = 0++instance Default Double where+ def = 0++instance Default Text where+ def = mempty++instance Default ByteString where+ def = mempty++instance Default a => Default (Either a b) where+ def = Left def++instance Default [a] where+ def = mempty++instance (Default a, Typeable a) => Default (Union (a ': as)) where+ def = liftUnion (def :: a)
+ src/Web/Telegram/Types/Internal/Utils/Stock.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++module Web.Telegram.Types.Internal.Utils.Stock+ ( Snake,+ OmitNothing,+ UntaggedSum,+ PrefixedSnake,+ Prefixed,+ PrefixedSnake',+ )+where++import Control.Monad+import Data.Char (isLower)+import Data.List (stripPrefix)+import Data.Maybe+ ( fromMaybe,+ listToMaybe,+ )+import Data.Proxy+import Deriving.Aeson+import GHC.TypeLits++type Snake = CustomJSON '[FieldLabelModifier CamelToSnake, OmitNothingFields]++type OmitNothing = CustomJSON '[OmitNothingFields]++type UntaggedSum = CustomJSON '[SumUntaggedValue, OmitNothingFields]++type PrefixedSnake str = CustomJSON '[FieldLabelModifier (StripPrefix str, CamelToSnake), OmitNothingFields]++type Prefixed str = CustomJSON '[FieldLabelModifier (StripPrefix str), OmitNothingFields]++data StrictStrip t++strictStrip :: String -> String -> Maybe String+strictStrip pre s = do+ t <- stripPrefix pre s+ guard $ maybe False (not . isLower) $ listToMaybe t+ return t++instance KnownSymbol k => StringModifier (StrictStrip k) where+ getStringModifier = fromMaybe <*> strictStrip (symbolVal (Proxy @k))++type PrefixedSnake' str = CustomJSON '[FieldLabelModifier (StrictStrip str, CamelToSnake), OmitNothingFields]
+ src/Web/Telegram/Types/Lens.hs view
@@ -0,0 +1,408 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeApplications #-}++module Web.Telegram.Types.Lens {-# DEPRECATED "Use labels from generics-lens instead" #-} where++import Control.Lens+import Data.Generics.Product++userId :: HasField "userId" s t a b => Lens s t a b+userId = field @"userId"++isBot :: HasField "isBot" s t a b => Lens s t a b+isBot = field @"isBot"++firstName :: HasField "firstName" s t a b => Lens s t a b+firstName = field @"firstName"++lastName :: HasField "lastName" s t a b => Lens s t a b+lastName = field @"lastName"++userName :: HasField "userName" s t a b => Lens s t a b+userName = field @"userName"++languageCode :: HasField "languageCode" s t a b => Lens s t a b+languageCode = field @"languageCode"++canJoinGroups :: HasField "canJoinGroups" s t a b => Lens s t a b+canJoinGroups = field @"canJoinGroups"++canReadAllGroupMessages :: HasField "canReadAllGroupMessages" s t a b => Lens s t a b+canReadAllGroupMessages = field @"canReadAllGroupMessages"++supportsInlineQueries :: HasField "supportsInlineQueries" s t a b => Lens s t a b+supportsInlineQueries = field @"supportsInlineQueries"++metadata :: HasField "metadata" s t a b => Lens s t a b+metadata = field @"metadata"++content :: HasField "content" s t a b => Lens s t a b+content = field @"content"++messageId :: HasField "messageId" s t a b => Lens s t a b+messageId = field @"messageId"++from :: HasField "from" s t a b => Lens s t a b+from = field @"from"++date :: HasField "date" s t a b => Lens s t a b+date = field @"date"++chat :: HasField "chat" s t a b => Lens s t a b+chat = field @"chat"++forwardFrom :: HasField "forwardFrom" s t a b => Lens s t a b+forwardFrom = field @"forwardFrom"++forwardFromChat :: HasField "forwardFromChat" s t a b => Lens s t a b+forwardFromChat = field @"forwardFromChat"++forwardFromMessageId :: HasField "forwardFromMessageId" s t a b => Lens s t a b+forwardFromMessageId = field @"forwardFromMessageId"++forwardSignature :: HasField "forwardSignature" s t a b => Lens s t a b+forwardSignature = field @"forwardSignature"++forwardSenderName :: HasField "forwardSenderName" s t a b => Lens s t a b+forwardSenderName = field @"forwardSenderName"++forwardDate :: HasField "forwardDate" s t a b => Lens s t a b+forwardDate = field @"forwardDate"++replyToMessage :: HasField "replyToMessage" s t a b => Lens s t a b+replyToMessage = field @"replyToMessage"++editDate :: HasField "editDate" s t a b => Lens s t a b+editDate = field @"editDate"++mediaGroupId :: HasField "mediaGroupId" s t a b => Lens s t a b+mediaGroupId = field @"mediaGroupId"++authorSignature :: HasField "authorSignature" s t a b => Lens s t a b+authorSignature = field @"authorSignature"++replyMarkup :: HasField "replyMarkup" s t a b => Lens s t a b+replyMarkup = field @"replyMarkup"++text :: HasField "text" s t a b => Lens s t a b+text = field @"text"++entities :: HasField "entities" s t a b => Lens s t a b+entities = field @"entities"++audio :: HasField "audio" s t a b => Lens s t a b+audio = field @"audio"++document :: HasField "document" s t a b => Lens s t a b+document = field @"document"++animation :: HasField "animation" s t a b => Lens s t a b+animation = field @"animation"++game :: HasField "game" s t a b => Lens s t a b+game = field @"game"++photo :: HasField "photo" s t a b => Lens s t a b+photo = field @"photo"++sticker :: HasField "sticker" s t a b => Lens s t a b+sticker = field @"sticker"++video :: HasField "video" s t a b => Lens s t a b+video = field @"video"++voice :: HasField "voice" s t a b => Lens s t a b+voice = field @"voice"++videoNote :: HasField "videoNote" s t a b => Lens s t a b+videoNote = field @"videoNote"++contact :: HasField "contact" s t a b => Lens s t a b+contact = field @"contact"++location :: HasField "location" s t a b => Lens s t a b+location = field @"location"++venue :: HasField "venue" s t a b => Lens s t a b+venue = field @"venue"++poll :: HasField "poll" s t a b => Lens s t a b+poll = field @"poll"++newChatMembers :: HasField "newChatMembers" s t a b => Lens s t a b+newChatMembers = field @"newChatMembers"++leftChatMember :: HasField "leftChatMember" s t a b => Lens s t a b+leftChatMember = field @"leftChatMember"++newChatPhoto :: HasField "newChatPhoto" s t a b => Lens s t a b+newChatPhoto = field @"newChatPhoto"++deleteChatPhoto :: HasField "deleteChatPhoto" s t a b => Lens s t a b+deleteChatPhoto = field @"deleteChatPhoto"++groupChatCreated :: HasField "groupChatCreated" s t a b => Lens s t a b+groupChatCreated = field @"groupChatCreated"++supergroupChatCreated :: HasField "supergroupChatCreated" s t a b => Lens s t a b+supergroupChatCreated = field @"supergroupChatCreated"++channelChatCreated :: HasField "channelChatCreated" s t a b => Lens s t a b+channelChatCreated = field @"channelChatCreated"++migrateToChatId :: HasField "migrateToChatId" s t a b => Lens s t a b+migrateToChatId = field @"migrateToChatId"++migrateFromChatId :: HasField "migrateFromChatId" s t a b => Lens s t a b+migrateFromChatId = field @"migrateFromChatId"++pinnedMessage :: HasField "pinnedMessage" s t a b => Lens s t a b+pinnedMessage = field @"pinnedMessage"++invoice :: HasField "invoice" s t a b => Lens s t a b+invoice = field @"invoice"++successfulPayment :: HasField "successfulPayment" s t a b => Lens s t a b+successfulPayment = field @"successfulPayment"++connectedWebsite :: HasField "connectedWebsite" s t a b => Lens s t a b+connectedWebsite = field @"connectedWebsite"++passPortData :: HasField "passPortData" s t a b => Lens s t a b+passPortData = field @"passPortData"++caption :: HasField "caption" s t a b => Lens s t a b+caption = field @"caption"++captionEntities :: HasField "captionEntities" s t a b => Lens s t a b+captionEntities = field @"captionEntities"++chatId :: HasField "chatId" s t a b => Lens s t a b+chatId = field @"chatId"++chatType :: HasField "chatType" s t a b => Lens s t a b+chatType = field @"chatType"++title :: HasField "title" s t a b => Lens s t a b+title = field @"title"++username :: HasField "username" s t a b => Lens s t a b+username = field @"username"++description :: HasField "description" s t a b => Lens s t a b+description = field @"description"++inviteLink :: HasField "inviteLink" s t a b => Lens s t a b+inviteLink = field @"inviteLink"++permissions :: HasField "permissions" s t a b => Lens s t a b+permissions = field @"permissions"++slowModeDelay :: HasField "slowModeDelay" s t a b => Lens s t a b+slowModeDelay = field @"slowModeDelay"++stickerSetName :: HasField "stickerSetName" s t a b => Lens s t a b+stickerSetName = field @"stickerSetName"++canSetStickerSet :: HasField "canSetStickerSet" s t a b => Lens s t a b+canSetStickerSet = field @"canSetStickerSet"++canSendMessages :: HasField "canSendMessages" s t a b => Lens s t a b+canSendMessages = field @"canSendMessages"++canSendMediaMessages :: HasField "canSendMediaMessages" s t a b => Lens s t a b+canSendMediaMessages = field @"canSendMediaMessages"++canSendPolls :: HasField "canSendPolls" s t a b => Lens s t a b+canSendPolls = field @"canSendPolls"++canSendOtherMesssages :: HasField "canSendOtherMesssages" s t a b => Lens s t a b+canSendOtherMesssages = field @"canSendOtherMesssages"++canAddWebPagePreviews :: HasField "canAddWebPagePreviews" s t a b => Lens s t a b+canAddWebPagePreviews = field @"canAddWebPagePreviews"++canChangeInfo :: HasField "canChangeInfo" s t a b => Lens s t a b+canChangeInfo = field @"canChangeInfo"++canInviteUsers :: HasField "canInviteUsers" s t a b => Lens s t a b+canInviteUsers = field @"canInviteUsers"++canPinMessages :: HasField "canPinMessages" s t a b => Lens s t a b+canPinMessages = field @"canPinMessages"++smallFileId :: HasField "smallFileId" s t a b => Lens s t a b+smallFileId = field @"smallFileId"++smallFileUniqueId :: HasField "smallFileUniqueId" s t a b => Lens s t a b+smallFileUniqueId = field @"smallFileUniqueId"++bigFileId :: HasField "bigFileId" s t a b => Lens s t a b+bigFileId = field @"bigFileId"++bitFileUniqueId :: HasField "bitFileUniqueId" s t a b => Lens s t a b+bitFileUniqueId = field @"bitFileUniqueId"++user :: HasField "user" s t a b => Lens s t a b+user = field @"user"++status :: HasField "status" s t a b => Lens s t a b+status = field @"status"++customTitle :: HasField "customTitle" s t a b => Lens s t a b+customTitle = field @"customTitle"++untilDate :: HasField "untilDate" s t a b => Lens s t a b+untilDate = field @"untilDate"++canBeEdited :: HasField "canBeEdited" s t a b => Lens s t a b+canBeEdited = field @"canBeEdited"++canPostMessages :: HasField "canPostMessages" s t a b => Lens s t a b+canPostMessages = field @"canPostMessages"++canEditMessages :: HasField "canEditMessages" s t a b => Lens s t a b+canEditMessages = field @"canEditMessages"++canDeleteMessages :: HasField "canDeleteMessages" s t a b => Lens s t a b+canDeleteMessages = field @"canDeleteMessages"++canRestrictMembers :: HasField "canRestrictMembers" s t a b => Lens s t a b+canRestrictMembers = field @"canRestrictMembers"++canPromoteMembers :: HasField "canPromoteMembers" s t a b => Lens s t a b+canPromoteMembers = field @"canPromoteMembers"++isMember :: HasField "isMember" s t a b => Lens s t a b+isMember = field @"isMember"++fileId :: HasField "fileId" s t a b => Lens s t a b+fileId = field @"fileId"++fileUniqueId :: HasField "fileUniqueId" s t a b => Lens s t a b+fileUniqueId = field @"fileUniqueId"++fileSize :: HasField "fileSize" s t a b => Lens s t a b+fileSize = field @"fileSize"++width :: HasField "width" s t a b => Lens s t a b+width = field @"width"++height :: HasField "height" s t a b => Lens s t a b+height = field @"height"++duration :: HasField "duration" s t a b => Lens s t a b+duration = field @"duration"++performer :: HasField "performer" s t a b => Lens s t a b+performer = field @"performer"++mimeType :: HasField "mimeType" s t a b => Lens s t a b+mimeType = field @"mimeType"++thumb :: HasField "thumb" s t a b => Lens s t a b+thumb = field @"thumb"++phoneNumber :: HasField "phoneNumber" s t a b => Lens s t a b+phoneNumber = field @"phoneNumber"++vcard :: HasField "vcard" s t a b => Lens s t a b+vcard = field @"vcard"++longitude :: HasField "longitude" s t a b => Lens s t a b+longitude = field @"longitude"++latitude :: HasField "latitude" s t a b => Lens s t a b+latitude = field @"latitude"++address :: HasField "address" s t a b => Lens s t a b+address = field @"address"++foursquareId :: HasField "foursquareId" s t a b => Lens s t a b+foursquareId = field @"foursquareId"++foursquareType :: HasField "foursquareType" s t a b => Lens s t a b+foursquareType = field @"foursquareType"++voterCount :: HasField "voterCount" s t a b => Lens s t a b+voterCount = field @"voterCount"++pollId :: HasField "pollId" s t a b => Lens s t a b+pollId = field @"pollId"++question :: HasField "question" s t a b => Lens s t a b+question = field @"question"++options :: HasField "options" s t a b => Lens s t a b+options = field @"options"++totalVoterCount :: HasField "totalVoterCount" s t a b => Lens s t a b+totalVoterCount = field @"totalVoterCount"++isClosed :: HasField "isClosed" s t a b => Lens s t a b+isClosed = field @"isClosed"++isAnonymous :: HasField "isAnonymous" s t a b => Lens s t a b+isAnonymous = field @"isAnonymous"++pollType :: HasField "pollType" s t a b => Lens s t a b+pollType = field @"pollType"++allowsMultipleAnswers :: HasField "allowsMultipleAnswers" s t a b => Lens s t a b+allowsMultipleAnswers = field @"allowsMultipleAnswers"++correctOptionId :: HasField "correctOptionId" s t a b => Lens s t a b+correctOptionId = field @"correctOptionId"++optionIds :: HasField "optionIds" s t a b => Lens s t a b+optionIds = field @"optionIds"++totalCount :: HasField "totalCount" s t a b => Lens s t a b+totalCount = field @"totalCount"++photos :: HasField "photos" s t a b => Lens s t a b+photos = field @"photos"++filePath :: HasField "filePath" s t a b => Lens s t a b+filePath = field @"filePath"++isAnimated :: HasField "isAnimated" s t a b => Lens s t a b+isAnimated = field @"isAnimated"++emoji :: HasField "emoji" s t a b => Lens s t a b+emoji = field @"emoji"++setName :: HasField "setName" s t a b => Lens s t a b+setName = field @"setName"++maskPosition :: HasField "maskPosition" s t a b => Lens s t a b+maskPosition = field @"maskPosition"++containsMasks :: HasField "containsMasks" s t a b => Lens s t a b+containsMasks = field @"containsMasks"++stickers :: HasField "stickers" s t a b => Lens s t a b+stickers = field @"stickers"++name :: HasField "name" s t a b => Lens s t a b+name = field @"name"++point :: HasField "point" s t a b => Lens s t a b+point = field @"point"++xShift :: HasField "xShift" s t a b => Lens s t a b+xShift = field @"xShift"++yShift :: HasField "yShift" s t a b => Lens s t a b+yShift = field @"yShift"++scale :: HasField "scale" s t a b => Lens s t a b+scale = field @"scale"++retryAfter :: HasField "retryAfter" s t a b => Lens s t a b+retryAfter = field @"retryAfter"++command :: HasField "command" s t a b => Lens s t a b+command = field @"command"+
+ src/Web/Telegram/Types/Passport.hs view
@@ -0,0 +1,11 @@+module Web.Telegram.Types.Passport+ ( PassportData (..),+ PassportFile (..),+ EncryptedPassportElement (..),+ EncryptedPassportElementType (..),+ EncryptedCredentials (..),+ PassportElementError (..),+ )+where++import Web.Telegram.Types.Internal.Passport
+ src/Web/Telegram/Types/Stock.hs view
@@ -0,0 +1,6 @@+module Web.Telegram.Types.Stock+ ( module Web.Telegram.Types.Internal.Utils.Stock,+ )+where++import Web.Telegram.Types.Internal.Utils.Stock
+ src/Web/Telegram/Types/Update.hs view
@@ -0,0 +1,14 @@+module Web.Telegram.Types.Update+ ( Update (..),+ WebhookInfo (..),++ -- ** Response+ ResponseParameters (..),+ ReqResult (..),+ ReqEither (..),+ BotCommand (..),+ )+where++import Web.Telegram.Types.Internal.Update+import Web.Telegram.Types.Internal.Common
+ src/Web/Telegram/Types/UpdateType.hs view
@@ -0,0 +1,6 @@+module Web.Telegram.Types.UpdateType+ ( module Web.Telegram.Types.Internal.UpdateType,+ )+where++import Web.Telegram.Types.Internal.UpdateType
+ telegram-types.cabal view
@@ -0,0 +1,95 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.33.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: a4fed3a03d8478f0f467cbd86c8dc1ccdb4b4f777198571ebaecc78e4dfeaf38++name: telegram-types+version: 0.1.0+synopsis: Types used in Telegram bot API+description: Defines various datatypes and their serialization methods useful for writing bindings to Telegram bot API.+category: Web+homepage: https://github.com/poscat0x04/telegram-types#readme+bug-reports: https://github.com/poscat0x04/telegram-types/issues+author: Poscat+maintainer: poscat@mail.poscat.moe+copyright: 2020 Poscat+license: BSD3+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md++source-repository head+ type: git+ location: https://github.com/poscat0x04/telegram-types++library+ exposed-modules:+ Web.Telegram.Types+ Web.Telegram.Types.Lens+ Web.Telegram.Types.Stock+ Web.Telegram.Types.Interaction+ Web.Telegram.Types.Inline+ Web.Telegram.Types.Input+ Web.Telegram.Types.Update+ Web.Telegram.Types.UpdateType+ other-modules:+ Web.Telegram.Types.Internal.Common+ Web.Telegram.Types.Internal.InlineQuery+ Web.Telegram.Types.Internal.InputFile+ Web.Telegram.Types.Internal.InputMedia+ Web.Telegram.Types.Internal.Keyboard+ Web.Telegram.Types.Internal.Media+ Web.Telegram.Types.Internal.Passport+ Web.Telegram.Types.Internal.Sticker+ Web.Telegram.Types.Internal.Update+ Web.Telegram.Types.Internal.UpdateType+ Web.Telegram.Types.Internal.User+ Web.Telegram.Types.Internal.Utils+ Web.Telegram.Types.Internal.Utils.Default+ Web.Telegram.Types.Internal.Utils.Stock+ Web.Telegram.Types.Passport+ Paths_telegram_types+ hs-source-dirs:+ src+ build-depends:+ aeson >=1.4.7.1 && <1.5+ , base >=4.7 && <5+ , bytestring >=0.10.10.0 && <0.11+ , deriving-aeson >=0.2.3 && <0.3+ , filepath >=1.4.2.1 && <1.5+ , generic-lens >=1.2.0.1 && <1.3+ , lens >=4.18.1 && <4.19+ , mime-types >=0.1.0.9 && <0.2+ , open-union >=0.4.0.0 && <0.5+ , servant >=0.16.2 && <0.17+ , servant-multipart >=0.11.5 && <0.12+ , text >=1.2.4.0 && <1.3+ default-language: Haskell2010++test-suite telegram-types-test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ other-modules:+ Paths_telegram_types+ hs-source-dirs:+ test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ aeson >=1.4.7.1 && <1.5+ , base >=4.7 && <5+ , bytestring >=0.10.10.0 && <0.11+ , deriving-aeson >=0.2.3 && <0.3+ , filepath >=1.4.2.1 && <1.5+ , generic-lens >=1.2.0.1 && <1.3+ , lens >=4.18.1 && <4.19+ , mime-types >=0.1.0.9 && <0.2+ , open-union >=0.4.0.0 && <0.5+ , servant >=0.16.2 && <0.17+ , servant-multipart >=0.11.5 && <0.12+ , telegram-types+ , text >=1.2.4.0 && <1.3+ default-language: Haskell2010
+ test/Spec.hs view
@@ -0,0 +1,13 @@+module Main where++import Data.Aeson+import qualified Data.ByteString.Lazy as LBS+import Web.Telegram.Types.Input+import Web.Telegram.Types.Update+import Web.Telegram.Types++main :: IO ()+main = do+ f <- LBS.readFile "test/Message1"+ print $ (eitherDecode f :: Either String Update)+ LBS.putStrLn $ encode (def :: InputMedia)