packages feed

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 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)