{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Telegram.Bot.API.InlineMode.InlineQueryResult where import Data.Aeson ( FromJSON (..), ToJSON (..), KeyValue ((.=)), Value (..) , withObject, (.:), (.:?) ) import Data.Aeson.Types (Parser) import Data.Hashable (Hashable) import Data.Text (Text) import GHC.Generics (Generic) import Telegram.Bot.API.Internal.Utils import Telegram.Bot.API.Types import Telegram.Bot.API.InlineMode.InputMessageContent import Telegram.Bot.API.Internal.TH (makeDefault) import qualified Data.Text as Text newtype InlineQueryResultId = InlineQueryResultId Text deriving (Eq, Show, Generic, ToJSON, FromJSON, Hashable) data InlineQueryResultGeneric = InlineQueryResultGeneric { inlineQueryResultId :: InlineQueryResultId -- ^ Unique identifier for this result, 1-64 Bytes , inlineQueryResultTitle :: Maybe Text -- ^ Title of the result (only valid for "Article", "Photo", "Gif", "Mpeg4Gif", "Video", "Audio", "Voice", "Document", "Location", "Venue", "CachedPhoto", "CachedGif", "CachedMpeg4Gif", "CachedDocument", "CachedVideo", "CachedVoice" types of results) , inlineQueryResultCaption :: Maybe Text -- ^ Caption of the media to be sent, 0-1024 characters after entities parsing. , inlineQueryResultParseMode :: Maybe Text -- ^ Mode for parsing entities in the photo caption. See formatting options for more details. , inlineQueryResultCaptionEntities :: Maybe [MessageEntity] -- ^ List of special entities that appear in the caption, which can be specified instead of @parse_mode@. , inlineQueryResultReplyMarkup :: Maybe InlineKeyboardMarkup -- ^ Inline keyboard attached to the message. , inlineQueryResultInputMessageContent :: Maybe InputMessageContent -- ^ Content of the message to be sent instead of the media. , inlineQueryResultDescription :: Maybe Text -- ^ Short description of the result. } deriving (Generic, Show) instance ToJSON InlineQueryResultGeneric where toJSON = gtoJSON instance FromJSON InlineQueryResultGeneric where parseJSON = gparseJSON data InlineQueryResultGenericThumbnail = InlineQueryResultGenericThumbnail { inlineQueryResultGenericGeneric :: InlineQueryResultGeneric , inlineQueryResultGenericThumbnailUrl :: Maybe Text -- ^ URL of the thumbnail for the media. , inlineQueryResultGenericThumbnailMimeType :: Maybe Text -- ^ MIME type of the thumbnail, must be one of @image/jpeg@, @image/gif@, or @video/mp4@. Defaults to @image/jpeg@. , inlineQueryResultGenericThumbnailWidth :: Maybe Integer -- ^ Media width. , inlineQueryResultGenericThumbnailHeight :: Maybe Integer -- ^ Media height. } deriving (Generic, Show) instance ToJSON InlineQueryResultGenericThumbnail where toJSON InlineQueryResultGenericThumbnail{..} = addJsonFields (toJSON inlineQueryResultGenericGeneric) [ "thumbnail_url" .= inlineQueryResultGenericThumbnailUrl , "thumbnail_mime_type" .= inlineQueryResultGenericThumbnailMimeType , "thumbnail_width" .= inlineQueryResultGenericThumbnailWidth , "thumbnail_height" .= inlineQueryResultGenericThumbnailHeight ] instance FromJSON InlineQueryResultGenericThumbnail where parseJSON = withObject "InlineQueryResult" \o -> InlineQueryResultGenericThumbnail <$> parseJSON (Object o) <*> o .: "thumbnail_url" <*> o .: "thumbnail_mime_type" <*> o .: "thumbnail_width" <*> o .: "thumbnail_height" -- | This object represents one result of an inline query data InlineQueryResult = InlineQueryResultArticle { inlineQueryResultArticleGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultArticleUrl :: Maybe Text -- ^ URL of the result. , inlineQueryResultArticleHideUrl :: Maybe Bool -- ^ 'True' if you don't want the URL to be shown in the message. } | InlineQueryResultPhoto { inlineQueryResultPhotoGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultPhotoPhotoUrl :: Text -- ^ A valid URL of the photo. Photo must be in **JPEG** format. Photo size must not exceed 5MB. , inlineQueryResultPhotoPhotoWidth :: Maybe Integer -- ^ Width of the photo. , inlineQueryResultPhotoPhotoHeight :: Maybe Integer -- ^ Height of the photo. } | InlineQueryResultGif { inlineQueryResultGifGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultGifGifUrl :: Text -- ^ A valid URL for the GIF file. File size must not exceed 1MB. , inlineQueryResultGifGifWidth :: Maybe Integer -- ^ Width of the GIF. , inlineQueryResultGifGifHeight :: Maybe Integer -- ^ Height of the GIF. , inlineQueryResultGifGifDuration :: Maybe Integer -- ^ Duration of the GIF in seconds. } | InlineQueryResultMpeg4Gif { inlineQueryResultMpeg4GifGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultMpeg4GifMpeg4Url :: Text -- ^ A valid URL for the MPEG4 file. File size must not exceed 1MB. , inlineQueryResultMpeg4GifMpeg4Width :: Maybe Integer -- ^ Video width. , inlineQueryResultMpeg4GifMpeg4Height :: Maybe Integer -- ^ Video height. , inlineQueryResultMpeg4GifMpeg4Duration :: Maybe Integer -- ^ Video duration in seconds. } | InlineQueryResultVideo { inlineQueryResultVideoGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultVideoVideoUrl :: Text -- ^ A valid URL for the embedded video player or video file. , inlineQueryResultVideoMimeType :: Text -- ^ MIME type of the content of the video URL, @text/html@ or @video/mp4@. , inlineQueryResultVideoVideoWidth :: Maybe Integer -- ^ Video width. , inlineQueryResultVideoVideoHeight :: Maybe Integer -- ^ Video height. , inlineQueryResultVideoVideoDuration :: Maybe Integer -- ^ Video duration in seconds. } | InlineQueryResultAudio { inlineQueryResultAudioGeneric :: InlineQueryResultGeneric , inlineQueryResultAudioAudioUrl :: Text -- ^ A valid URL for the audio file. , inlineQueryResultAudioPerformer :: Maybe Text -- ^ Performer. , inlineQueryResultAudioAudioDuration :: Maybe Integer -- ^ Audio duration in seconds. } | InlineQueryResultVoice { inlineQueryResultVoiceGeneric :: InlineQueryResultGeneric , inlineQueryResultVoiceVoiceUrl :: Text -- ^ A valid URL for the voice recording. , inlineQueryResultVoiceVoiceDuration :: Maybe Integer -- ^ Recording duration in seconds. } | InlineQueryResultDocument { inlineQueryResultDocumentGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultDocumentDocumentUrl :: Text -- ^ A valid URL for the file. , inlineQueryResultDocumentMimeType :: Text -- ^ MIME type of the content of the file, either @application/pdf@ or @application/zip@. } | InlineQueryResultLocation { inlineQueryResultLocationGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultLocationLatitude :: Float -- ^ Location latitude in degrees. , inlineQueryResultLocationLongitude :: Float -- ^ Location longitude in degrees. , inlineQueryResultLocationHorizontalAccuracy :: Maybe Float -- ^ The radius of uncertainty for the location, measured in meters; 0-1500. , inlineQueryResultLocationLivePeriod :: Maybe Seconds -- ^ Period in seconds for which the location can be updated, should be between 60 and 86400. , inlineQueryResultLocationHeading :: Maybe Int -- ^ For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. , inlineQueryResultLocationProximityAlertRadius :: Maybe Int -- ^ For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. } | InlineQueryResultVenue { inlineQueryResultVenueGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultVenueLatitude :: Float -- ^ Latitude of the venue location in degrees. , inlineQueryResultVenueLongitude :: Float -- ^ Longitude of the venue location in degrees. , inlineQueryResultVenueAddress :: Text -- ^ Address of the venue. , inlineQueryResultVenueFoursquareId :: Maybe Text -- ^ Foursquare identifier of the venue if known. , inlineQueryResultVenueFoursquareType :: Maybe Text -- ^ Foursquare type of the venue, if known. (For example, @arts_entertainment/default@, @arts_entertainment/aquarium@ or @food/icecream@.) , inlineQueryResultVenueGooglePlaceId :: Maybe Text -- ^ Google Places identifier of the venue. , inlineQueryResultVenueGooglePlaceType :: Maybe Text -- ^ Google Places type of the venue. (See supported types .) } | InlineQueryResultContact { inlineQueryResultContactGeneric :: InlineQueryResultGenericThumbnail , inlineQueryResultContactPhoneNumber :: Text -- ^ Contact's phone number. , inlineQueryResultContactFirstName :: Text -- ^ Contact's first name. , inlineQueryResultContactLastName :: Maybe Text -- ^ Contact's last name. , inlineQueryResultContactVcard :: Maybe Text -- ^ Additional data about the contact in the form of a vCard , 0-2048 bytes. } | InlineQueryResultGame { inlineQueryResultGameGeneric :: InlineQueryResultGeneric , inlineQueryResultGameGameShortName :: Text -- ^ Short name of the game. } | InlineQueryResultCachedPhoto { inlineQueryResultCachedPhotoGeneric :: InlineQueryResultGeneric , inlineQueryResultCachedPhotoPhotoFileId :: FileId -- ^ A valid file identifier of the photo. } | InlineQueryResultCachedGif { inlineQueryResultCachedGifGeneric :: InlineQueryResultGeneric , iinlineQueryResultCachedGifGifFileId :: FileId -- ^ A valid file identifier for the GIF file. } | InlineQueryResultCachedMpeg4Gif { inlineQueryResultCachedMpeg4GifGeneric :: InlineQueryResultGeneric , inlineQueryResultCachedMpeg4GifMpeg4FileId :: FileId -- ^ A valid file identifier for the MPEG4 file. } | InlineQueryResultCachedSticker { inlineQueryResultCachedStickerGeneric :: InlineQueryResultGeneric , inlineQueryResultCachedStickerStickerFileId :: FileId -- ^ A valid file identifier of the sticker. } | InlineQueryResultCachedDocument { inlineQueryResultCachedDocumentGeneric :: InlineQueryResultGeneric , inlineQueryResultCachedDocumentDocumentFileId :: FileId -- ^ A valid file identifier for the file. } | InlineQueryResultCachedVideo { inlineQueryResultCachedVideoGeneric :: InlineQueryResultGeneric , inlineQueryResultCachedVideoVideoFileId :: FileId -- ^ A valid file identifier for the video file. } | InlineQueryResultCachedVoice { inlineQueryResultCachedVoiceGeneric :: InlineQueryResultGeneric , inlineQueryResultCachedVoiceVoiceFileId :: FileId -- ^ A valid file identifier for the voice message. } | InlineQueryResultCachedAudio { inlineQueryResultCachedAudioGeneric :: InlineQueryResultGeneric , inlineQueryResultCachedAudioAudioFileId :: FileId -- ^ A valid file identifier for the audio file. } deriving (Generic, Show) instance ToJSON InlineQueryResult where toJSON = \case InlineQueryResultArticle g url hideUrl -> addJsonFields (toJSON g) (addType "article" [ "url" .= url , "hide_url" .= hideUrl ]) InlineQueryResultPhoto g photoUrl photoWidth photoHeight -> addJsonFields (toJSON g) (addType "photo" [ "photo_url" .= photoUrl , "photo_width" .= photoWidth , "photo_height" .= photoHeight ]) InlineQueryResultGif g gifUrl gifWidth gifHeight gifDuration -> addJsonFields (toJSON g) (addType "gif" [ "gif_url" .= gifUrl , "gif_width" .= gifWidth , "gif_height" .= gifHeight , "gif_duration" .= gifDuration ]) InlineQueryResultMpeg4Gif g mpeg4Url mpeg4Width mpeg4Height mpeg4Duration -> addJsonFields (toJSON g) (addType "mpeg4_gif" [ "mpeg4_url" .= mpeg4Url , "mpeg4_width" .= mpeg4Width , "mpeg4_height" .= mpeg4Height , "mpeg4_duration" .= mpeg4Duration ]) InlineQueryResultVideo g videoUrl mimeType videoWidth videoHeight videoDuration -> addJsonFields (toJSON g) (addType "video" [ "video_url" .= videoUrl , "mime_type" .= mimeType , "video_width" .= videoWidth , "video_height" .= videoHeight , "video_duration" .= videoDuration ]) InlineQueryResultAudio g audioUrl performer audioDuration -> addJsonFields (toJSON g) (addType "audio" [ "audio_url" .= audioUrl , "performer" .= performer , "audio_duration" .= audioDuration ]) InlineQueryResultVoice g voiceUrl voiceDuration -> addJsonFields (toJSON g) (addType "voice" [ "voice_url" .= voiceUrl , "voice_duration" .= voiceDuration ]) InlineQueryResultDocument g documentUrl mimeType -> addJsonFields (toJSON g) (addType "document" [ "document_url" .= documentUrl , "mime_type" .= mimeType ]) InlineQueryResultLocation g latitude longitude horizontalAccuracy livePeriod heading proximityAlertRadius -> addJsonFields (toJSON g) (addType "location" [ "latitude" .= latitude , "longitude" .= longitude , "horizontal_accuracy" .= horizontalAccuracy , "live_period" .= livePeriod , "heading" .= heading , "proximity_alert_radius" .= proximityAlertRadius ]) InlineQueryResultVenue g latitude longitude address foursquareId foursquareType googlePlaceId googlePlaceType -> addJsonFields (toJSON g) (addType "venue" [ "latitude" .= latitude , "longitude" .= longitude , "address" .= address , "foursquare_id" .= foursquareId , "foursquare_type" .= foursquareType , "google_place_id" .= googlePlaceId , "google_place_type" .= googlePlaceType ]) InlineQueryResultContact g phoneNumber firstName lastName vcard -> addJsonFields (toJSON g) (addType "contact" [ "phone_number" .= phoneNumber , "first_name" .= firstName , "last_name" .= lastName , "vcard" .= vcard ]) InlineQueryResultGame g gameShortName -> addJsonFields (toJSON g) (addType "game" [ "game_short_name" .= gameShortName ]) InlineQueryResultCachedPhoto g photoFileId -> addJsonFields (toJSON g) (addType "photo" [ "photo_file_id" .= photoFileId ]) InlineQueryResultCachedGif g gifFileId -> addJsonFields (toJSON g) (addType "gif" [ "gif_file_id" .= gifFileId ]) InlineQueryResultCachedMpeg4Gif g mpeg4FileId -> addJsonFields (toJSON g) (addType "mpeg4_gif" [ "mpeg4_file_id" .= mpeg4FileId ]) InlineQueryResultCachedSticker g stickerFileId -> addJsonFields (toJSON g) (addType "sticker" [ "sticker_file_id" .= stickerFileId ]) InlineQueryResultCachedDocument g documentFileId -> addJsonFields (toJSON g) (addType "document" [ "document_file_id" .= documentFileId ]) InlineQueryResultCachedVideo g videoFileId -> addJsonFields (toJSON g) (addType "video" [ "video_file_id" .= videoFileId ]) InlineQueryResultCachedVoice g voiceFileId -> addJsonFields (toJSON g) (addType "voice" [ "voice_file_id" .= voiceFileId ]) InlineQueryResultCachedAudio g audioFileId -> addJsonFields (toJSON g) (addType "audio" [ "audio_file_id" .= audioFileId ]) instance FromJSON InlineQueryResult where parseJSON = withObject "InlineQueryResult" \o -> (o .: "type" :: Parser Text) >>= \case "article" -> InlineQueryResultArticle <$> parseJSON (Object o) <*> o .: "url" <*> o .: "hide_url" "photo" -> parseFileId o "photo_file_id" >>= \case Nothing -> InlineQueryResultPhoto <$> parseJSON (Object o) -- generic thumbnail <*> o .: "photo_url" <*> o .: "photo_width" <*> o .: "photo_height" Just fileId -> InlineQueryResultCachedPhoto <$> parseJSON (Object o) <*> pure fileId "gif" -> parseFileId o "gif_file_id" >>= \case Nothing -> InlineQueryResultGif <$> parseJSON (Object o) -- generic thumbnail <*> o .: "gif_url" <*> o .: "gif_width" <*> o .: "gif_height" <*> o .: "gif_duration" Just fileId -> InlineQueryResultCachedGif <$> parseJSON (Object o) <*> pure fileId "mpeg4_gif" -> parseFileId o "mpeg4_file_id" >>= \case Nothing -> InlineQueryResultMpeg4Gif <$> parseJSON (Object o) -- generic thumbnail <*> o .: "mpeg4_url" <*> o .: "mpeg4_width" <*> o .: "mpeg4_height" <*> o .: "mpeg4_duration" Just fileId -> InlineQueryResultCachedMpeg4Gif <$> parseJSON (Object o) <*> pure fileId "video" -> parseFileId o "video_file_id" >>= \case Nothing -> InlineQueryResultVideo <$> parseJSON (Object o) <*> o .: "video_url" <*> o .: "mime_type" <*> o .: "video_width" <*> o .: "video_height" <*> o .: "video_duration" Just fileId -> InlineQueryResultCachedVideo <$> parseJSON (Object o) <*> pure fileId "audio" -> parseFileId o "audio_file_id" >>= \case Nothing -> InlineQueryResultAudio <$> parseJSON (Object o) <*> o .: "audio_url" <*> o .: "performer" <*> o .: "duration" Just fileId -> InlineQueryResultCachedAudio <$> parseJSON (Object o) <*> pure fileId "voice" -> parseFileId o "voice_file_id" >>= \case Nothing -> InlineQueryResultVoice <$> parseJSON (Object o) <*> o .: "voice_url" <*> o .: "voice_duration" Just fileId -> InlineQueryResultCachedVoice <$> parseJSON (Object o) <*> pure fileId "document" -> parseFileId o "document_file_id" >>= \case Nothing -> InlineQueryResultDocument <$> parseJSON (Object o) <*> o .: "document_url" <*> o .: "mime_type" Just fileId -> InlineQueryResultCachedDocument <$> parseJSON (Object o) <*> pure fileId "location" -> InlineQueryResultLocation <$> parseJSON (Object o) <*> o .: "latitude" <*> o .: "longitude" <*> o .: "horizontal_accuracy" <*> o .: "live_period" <*> o .: "heading" <*> o .: "proximity_alert_radius" "venue" -> InlineQueryResultVenue <$> parseJSON (Object o) <*> o .: "latitude" <*> o .: "longitude" <*> o .: "address" <*> o .: "foursquare_id" <*> o .: "foursquare_type" <*> o .: "google_place_id" <*> o .: "google_place_type" "contact" -> InlineQueryResultContact <$> parseJSON (Object o) <*> o .: "phone_number" <*> o .: "first_name" <*> o .: "last_name" <*> o .: "vcard" "game" -> InlineQueryResultGame <$> parseJSON (Object o) <*> o .: "game_short_name" t -> fail $ Text.unpack ("Unknown type: " <> t) where parseFileId o fileField = o .:? fileField :: Parser (Maybe FileId) defInlineQueryResultArticle :: InlineQueryResultGenericThumbnail -> InlineQueryResult defInlineQueryResultArticle g = InlineQueryResultArticle g Nothing Nothing defInlineQueryResultPhotoUrl :: InlineQueryResultGenericThumbnail -> Text -> InlineQueryResult defInlineQueryResultPhotoUrl g photoUrl = InlineQueryResultPhoto g photoUrl Nothing Nothing defInlineQueryResultGif :: InlineQueryResultGenericThumbnail -> Text -> InlineQueryResult defInlineQueryResultGif g gifUrl = InlineQueryResultGif g gifUrl Nothing Nothing Nothing defInlineQueryResultMpeg4Gif :: InlineQueryResultGenericThumbnail -> Text -> InlineQueryResult defInlineQueryResultMpeg4Gif g mpeg4Url = InlineQueryResultMpeg4Gif g mpeg4Url Nothing Nothing Nothing defInlineQueryResultVideo :: InlineQueryResultGenericThumbnail -> Text -> Text -> InlineQueryResult defInlineQueryResultVideo g videoUrl mimeType = InlineQueryResultVideo g videoUrl mimeType Nothing Nothing Nothing defInlineQueryResultAudio :: InlineQueryResultGeneric -> Text -> InlineQueryResult defInlineQueryResultAudio g audioUrl = InlineQueryResultAudio g audioUrl Nothing Nothing defInlineQueryResultVoice :: InlineQueryResultGeneric -> Text -> InlineQueryResult defInlineQueryResultVoice g voiceUrl = InlineQueryResultVoice g voiceUrl Nothing defInlineQueryResultDocument :: InlineQueryResultGenericThumbnail -> Text -> Text -> InlineQueryResult defInlineQueryResultDocument = InlineQueryResultDocument defInlineQueryResultLocation :: InlineQueryResultGenericThumbnail -> Float -> Float -> InlineQueryResult defInlineQueryResultLocation g lat lon = InlineQueryResultLocation g lat lon Nothing Nothing Nothing Nothing defInlineQueryResultVenue :: InlineQueryResultGenericThumbnail -> Float -> Float -> Text -> InlineQueryResult defInlineQueryResultVenue g lat lon address = InlineQueryResultVenue g lat lon address Nothing Nothing Nothing Nothing defInlineQueryResultContact :: InlineQueryResultGenericThumbnail -> Text -> Text -> InlineQueryResult defInlineQueryResultContact g phoneNumber firstName = InlineQueryResultContact g phoneNumber firstName Nothing Nothing -- | This object represents a button to be shown above inline query results. You must use exactly one of the optional fields. data InlineQueryResultsButton = InlineQueryResultsButton { inlineQueryResultsButtonText :: Text , inlineQueryResultsButtonWebApp :: Maybe WebAppInfo , inlineQueryResultsButtonStartParameter :: Maybe Text -- ^ [Deep-linking](https://core.telegram.org/bots/features#deep-linking) parameter for the /start message sent to the bot when a user presses the button. 1-64 characters, only @A-Z@, @a-z@, @0-9@, @_@ and @-@ are allowed. -- -- Example: An inline bot that sends YouTube videos can ask the user to connect the bot to their YouTube account to adapt search results accordingly. To do this, it displays a 'Connect your YouTube account' button above the results, or even before showing any. The user presses the button, switches to a private chat with the bot and, in doing so, passes a start parameter that instructs the bot to return an OAuth link. Once done, the bot can offer a [switch_inline](https://core.telegram.org/bots/api#inlinekeyboardmarkup) button so that the user can easily return to the chat where they wanted to use the bot's inline capabilities. } deriving Generic instance ToJSON InlineQueryResultsButton where toJSON = gtoJSON instance FromJSON InlineQueryResultsButton where parseJSON = gparseJSON foldMap makeDefault [ ''InlineQueryResultGeneric , ''InlineQueryResultGenericThumbnail ]