{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Telegram.Bot.API.Types.InputMedia where

import Data.Aeson (ToJSON (..), KeyValue ((.=)))
import Data.Aeson.Text (encodeToLazyText)
import Data.Bool (bool)
import Data.Maybe (catMaybes)
import Data.Functor ((<&>))
import Data.Text (Text, pack)
import GHC.Generics (Generic)
import Servant.Multipart.API
import System.FilePath

import qualified Data.Text.Lazy as TL

import Telegram.Bot.API.Types.Common
import Telegram.Bot.API.Types.MessageEntity
import Telegram.Bot.API.Internal.Utils

-- ** 'InputMedia'

-- | Generic fields for all InputMedia structures
data InputMediaGeneric = InputMediaGeneric
  { InputMediaGeneric -> InputFile
inputMediaGenericMedia :: InputFile -- ^ File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://<file_attach_name>” to upload a new one using multipart/form-data under <file_attach_name> name.
  , InputMediaGeneric -> Maybe Text
inputMediaGenericCaption :: Maybe Text -- ^ Caption of the photo to be sent, 0-1024 characters after entities parsing.
  , InputMediaGeneric -> Maybe Text
inputMediaGenericParseMode :: Maybe Text -- ^ Mode for parsing entities in the photo caption. See formatting options <https:\/\/core.telegram.org\/bots\/api#formatting-options> for more details.
  , InputMediaGeneric -> Maybe [MessageEntity]
inputMediaGenericCaptionEntities :: Maybe [MessageEntity] -- ^ List of special entities that appear in the caption, which can be specified instead of @parse_mode@.
  }
  deriving forall x. Rep InputMediaGeneric x -> InputMediaGeneric
forall x. InputMediaGeneric -> Rep InputMediaGeneric x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep InputMediaGeneric x -> InputMediaGeneric
$cfrom :: forall x. InputMediaGeneric -> Rep InputMediaGeneric x
Generic

instance ToJSON InputMediaGeneric where toJSON :: InputMediaGeneric -> Value
toJSON = forall a (d :: Meta) (f :: * -> *).
(Generic a, GToJSON Zero (Rep a), Rep a ~ D1 d f, Datatype d) =>
a -> Value
gtoJSON

instance ToMultipart Tmp InputMediaGeneric where
  toMultipart :: InputMediaGeneric -> MultipartData Tmp
toMultipart InputMediaGeneric{Maybe [MessageEntity]
Maybe Text
InputFile
inputMediaGenericCaptionEntities :: Maybe [MessageEntity]
inputMediaGenericParseMode :: Maybe Text
inputMediaGenericCaption :: Maybe Text
inputMediaGenericMedia :: InputFile
inputMediaGenericCaptionEntities :: InputMediaGeneric -> Maybe [MessageEntity]
inputMediaGenericParseMode :: InputMediaGeneric -> Maybe Text
inputMediaGenericCaption :: InputMediaGeneric -> Maybe Text
inputMediaGenericMedia :: InputMediaGeneric -> InputFile
..} = Text -> InputFile -> MultipartData Tmp -> MultipartData Tmp
makeFile Text
"media" InputFile
inputMediaGenericMedia (forall tag. [Input] -> [FileData tag] -> MultipartData tag
MultipartData [Input]
fields []) where
    fields :: [Input]
fields = forall a. [Maybe a] -> [a]
catMaybes
      [ Maybe Text
inputMediaGenericCaption forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Text
t -> Text -> Text -> Input
Input Text
"caption" Text
t
      , Maybe Text
inputMediaGenericParseMode forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Text
t -> Text -> Text -> Input
Input Text
"parse_mode" Text
t
      , Maybe [MessageEntity]
inputMediaGenericCaptionEntities forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \[MessageEntity]
t -> Text -> Text -> Input
Input Text
"caption_entities" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText [MessageEntity]
t)
      ]

data InputMediaGenericThumbnail = InputMediaGenericThumbnail
  { InputMediaGenericThumbnail -> InputMediaGeneric
inputMediaGenericGeneric :: InputMediaGeneric
  , InputMediaGenericThumbnail -> Maybe InputFile
inputMediaGenericThumbnail :: Maybe InputFile -- ^ Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's width and height should not exceed 320. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://<file_attach_name>” if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. 
  }

instance ToJSON InputMediaGenericThumbnail where
  toJSON :: InputMediaGenericThumbnail -> Value
toJSON InputMediaGenericThumbnail{Maybe InputFile
InputMediaGeneric
inputMediaGenericThumbnail :: Maybe InputFile
inputMediaGenericGeneric :: InputMediaGeneric
inputMediaGenericThumbnail :: InputMediaGenericThumbnail -> Maybe InputFile
inputMediaGenericGeneric :: InputMediaGenericThumbnail -> InputMediaGeneric
..}
    = Value -> [Pair] -> Value
addJsonFields (forall a. ToJSON a => a -> Value
toJSON InputMediaGeneric
inputMediaGenericGeneric)
      [Key
"thumbnail" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe InputFile
inputMediaGenericThumbnail]

instance ToMultipart Tmp InputMediaGenericThumbnail where
  toMultipart :: InputMediaGenericThumbnail -> MultipartData Tmp
toMultipart = \case
    InputMediaGenericThumbnail InputMediaGeneric
generic Maybe InputFile
Nothing -> forall tag a. ToMultipart tag a => a -> MultipartData tag
toMultipart InputMediaGeneric
generic
    InputMediaGenericThumbnail InputMediaGeneric
generic (Just InputFile
thumbnail) ->
      Text -> InputFile -> MultipartData Tmp -> MultipartData Tmp
makeFile Text
"thumbnail" InputFile
thumbnail (forall tag a. ToMultipart tag a => a -> MultipartData tag
toMultipart InputMediaGeneric
generic)


data InputMedia
  = InputMediaPhoto -- ^ Represents a photo to be sent.
    { InputMedia -> InputMediaGeneric
inputMediaPhotoGeneric :: InputMediaGeneric
    , InputMedia -> Maybe Bool
inputMediaPhotoHasSpoiler :: Maybe Bool -- ^ Pass 'True' if the video needs to be covered with a spoiler animation.
    }
  | InputMediaVideo -- ^ Represents a video to be sent.
    { InputMedia -> InputMediaGenericThumbnail
inputMediaVideoGeneric :: InputMediaGenericThumbnail
    , InputMedia -> Maybe Integer
inputMediaVideoWidth :: Maybe Integer -- ^ Video width
    , InputMedia -> Maybe Integer
inputMediaVideoHeight :: Maybe Integer -- ^ Video height
    , InputMedia -> Maybe Integer
inputMediaVideoDuration :: Maybe Integer -- ^ Video duration in seconds
    , InputMedia -> Maybe Bool
inputMediaVideoSupportsStreaming :: Maybe Bool -- ^ Pass 'True', if the uploaded video is suitable for streaming.
    , InputMedia -> Maybe Bool
inputMediaVideoHasSpoiler :: Maybe Bool -- ^ Pass 'True' if the video needs to be covered with a spoiler animation.
    }
  | InputMediaAnimation -- ^ Represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
    { InputMedia -> InputMediaGenericThumbnail
inputMediaAnimationGeneric :: InputMediaGenericThumbnail
    , InputMedia -> Maybe Integer
inputMediaAnimationWidth :: Maybe Integer -- ^ Animation width
    , InputMedia -> Maybe Integer
inputMediaAnimationHeight :: Maybe Integer -- ^ Animation height
    , InputMedia -> Maybe Integer
inputMediaAnimationDuration :: Maybe Integer -- ^ Animation duration in seconds
    , InputMedia -> Maybe Bool
inputMediaAnimationHasSpoiler :: Maybe Bool -- ^ Pass 'True' if the video needs to be covered with a spoiler animation.
    }
  | InputMediaAudio -- ^ Represents an audio file to be treated as music to be sent.
    { InputMedia -> InputMediaGenericThumbnail
inputMediaAudioGeneric :: InputMediaGenericThumbnail
    , InputMedia -> Maybe Integer
inputMediaAudioDuration :: Maybe Integer -- ^ Duration of the audio in seconds
    , InputMedia -> Maybe Text
inputMediaAudioPerformer :: Maybe Text -- ^ Performer of the audio
    , InputMedia -> Maybe Text
inputMediaAudioTitle :: Maybe Text -- ^ Title of the audio
    }
  | InputMediaDocument -- ^ Represents a general file to be sent.
    { InputMedia -> InputMediaGenericThumbnail
inputMediaDocumentGeneric :: InputMediaGenericThumbnail
    , InputMedia -> Maybe Bool
inputMediaDocumentDisableContentTypeDetection :: Maybe Bool -- ^ Disables automatic server-side content type detection for files uploaded using multipart/form-data. Always True, if the document is sent as part of an album.
    }

instance ToJSON InputMedia where
  toJSON :: InputMedia -> Value
toJSON = \case
    InputMediaPhoto InputMediaGeneric
img Maybe Bool
spoiler ->
      Value -> [Pair] -> Value
addJsonFields (forall a. ToJSON a => a -> Value
toJSON InputMediaGeneric
img) (Text -> [Pair] -> [Pair]
addType Text
"photo" [ Key
"has_spoiler" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Bool
spoiler])
    InputMediaVideo InputMediaGenericThumbnail
imgt Maybe Integer
width Maybe Integer
height Maybe Integer
duration Maybe Bool
streaming Maybe Bool
spoiler ->
      Value -> [Pair] -> Value
addJsonFields (forall a. ToJSON a => a -> Value
toJSON InputMediaGenericThumbnail
imgt)
                (Text -> [Pair] -> [Pair]
addType Text
"video"
                [ Key
"width" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
width
                , Key
"height" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
height
                , Key
"duration" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
duration
                , Key
"support_streaming" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Bool
streaming
                , Key
"has_spoiler" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Bool
spoiler
                ])
    InputMediaAnimation InputMediaGenericThumbnail
imgt Maybe Integer
width Maybe Integer
height Maybe Integer
duration Maybe Bool
spoiler ->
      Value -> [Pair] -> Value
addJsonFields (forall a. ToJSON a => a -> Value
toJSON InputMediaGenericThumbnail
imgt)
                (Text -> [Pair] -> [Pair]
addType Text
"animation"
                [ Key
"width" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
width
                , Key
"height" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
height
                , Key
"duration" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
duration
                , Key
"has_spoiler" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Bool
spoiler
                ])
    InputMediaAudio InputMediaGenericThumbnail
imgt Maybe Integer
duration Maybe Text
performer Maybe Text
title ->
      Value -> [Pair] -> Value
addJsonFields (forall a. ToJSON a => a -> Value
toJSON InputMediaGenericThumbnail
imgt)
                (Text -> [Pair] -> [Pair]
addType Text
"audio"
                [ Key
"duration" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
duration
                , Key
"performer" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Text
performer
                , Key
"title" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Text
title
                ])
    InputMediaDocument InputMediaGenericThumbnail
imgt Maybe Bool
dctd ->
      Value -> [Pair] -> Value
addJsonFields (forall a. ToJSON a => a -> Value
toJSON InputMediaGenericThumbnail
imgt)
                (Text -> [Pair] -> [Pair]
addType Text
"document" [Key
"disable_content_type_detection" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Bool
dctd])



instance ToMultipart Tmp InputMedia where
  toMultipart :: InputMedia -> MultipartData Tmp
toMultipart = let
    in \case
    InputMediaPhoto InputMediaGeneric
img Maybe Bool
spoiler ->
      forall tag. [Input] -> MultipartData tag -> MultipartData tag
addMultipartFields
      (Text -> Text -> Input
Input Text
"type" Text
"photo"
       forall a. a -> [a] -> [a]
: forall a. [Maybe a] -> [a]
catMaybes
        [ Maybe Bool
spoiler forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
          \Bool
t -> Text -> Text -> Input
Input Text
"has_spoiler" (forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" Bool
t)
        ]) (forall tag a. ToMultipart tag a => a -> MultipartData tag
toMultipart InputMediaGeneric
img)
    InputMediaVideo InputMediaGenericThumbnail
imgt Maybe Integer
width Maybe Integer
height Maybe Integer
duration Maybe Bool
streaming Maybe Bool
spoiler ->
      forall tag. [Input] -> MultipartData tag -> MultipartData tag
addMultipartFields
      (Text -> Text -> Input
Input Text
"type" Text
"video"
      forall a. a -> [a] -> [a]
: forall a. [Maybe a] -> [a]
catMaybes 
      [ Maybe Integer
width forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Integer
t -> Text -> Text -> Input
Input Text
"width" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText Integer
t)
      , Maybe Integer
height forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Integer
t -> Text -> Text -> Input
Input Text
"height" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText Integer
t)
      , Maybe Integer
duration forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Integer
t -> Text -> Text -> Input
Input Text
"duration" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText Integer
t)
      , Maybe Bool
streaming forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Bool
t -> Text -> Text -> Input
Input Text
"support_streaming" (forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" Bool
t)
      , Maybe Bool
spoiler forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Bool
t -> Text -> Text -> Input
Input Text
"has_spoiler" (forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" Bool
t)
      ]) (forall tag a. ToMultipart tag a => a -> MultipartData tag
toMultipart InputMediaGenericThumbnail
imgt)
    InputMediaAnimation InputMediaGenericThumbnail
imgt Maybe Integer
width Maybe Integer
height Maybe Integer
duration Maybe Bool
spoiler ->
      forall tag. [Input] -> MultipartData tag -> MultipartData tag
addMultipartFields
      (Text -> Text -> Input
Input Text
"type" Text
"animation"
      forall a. a -> [a] -> [a]
: forall a. [Maybe a] -> [a]
catMaybes 
      [ Maybe Integer
width forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Integer
t -> Text -> Text -> Input
Input Text
"width" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText Integer
t)
      , Maybe Integer
height forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Integer
t -> Text -> Text -> Input
Input Text
"height" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText Integer
t)
      , Maybe Integer
duration forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Integer
t -> Text -> Text -> Input
Input Text
"duration" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText Integer
t)
      , Maybe Bool
spoiler forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Bool
t -> Text -> Text -> Input
Input Text
"has_spoiler" (forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" Bool
t)
      ]) (forall tag a. ToMultipart tag a => a -> MultipartData tag
toMultipart InputMediaGenericThumbnail
imgt)
    InputMediaAudio InputMediaGenericThumbnail
imgt Maybe Integer
duration Maybe Text
performer Maybe Text
title ->
      forall tag. [Input] -> MultipartData tag -> MultipartData tag
addMultipartFields
      (Text -> Text -> Input
Input Text
"type" Text
"audio"
      forall a. a -> [a] -> [a]
: forall a. [Maybe a] -> [a]
catMaybes 
      [ Maybe Integer
duration forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Integer
t -> Text -> Text -> Input
Input Text
"duration" (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText Integer
t)
      , Maybe Text
performer forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Text
t -> Text -> Text -> Input
Input Text
"performer" Text
t
      , Maybe Text
title forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Text
t -> Text -> Text -> Input
Input Text
"title" Text
t
      ]) (forall tag a. ToMultipart tag a => a -> MultipartData tag
toMultipart InputMediaGenericThumbnail
imgt)
    InputMediaDocument InputMediaGenericThumbnail
imgt Maybe Bool
dctd ->
      forall tag. [Input] -> MultipartData tag -> MultipartData tag
addMultipartFields
      (Text -> Text -> Input
Input Text
"type" Text
"document"
      forall a. a -> [a] -> [a]
: forall a. [Maybe a] -> [a]
catMaybes 
      [ Maybe Bool
dctd forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> 
         \Bool
t -> Text -> Text -> Input
Input Text
"disable_content_type_detection" (forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" Bool
t)
      ]) (forall tag a. ToMultipart tag a => a -> MultipartData tag
toMultipart InputMediaGenericThumbnail
imgt)

type ContentType = Text

data InputFile
  = InputFileId FileId
  | FileUrl Text
  | InputFile FilePath ContentType
  deriving (forall x. Rep InputFile x -> InputFile
forall x. InputFile -> Rep InputFile x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep InputFile x -> InputFile
$cfrom :: forall x. InputFile -> Rep InputFile x
Generic, Int -> InputFile -> ShowS
[InputFile] -> ShowS
InputFile -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [InputFile] -> ShowS
$cshowList :: [InputFile] -> ShowS
show :: InputFile -> String
$cshow :: InputFile -> String
showsPrec :: Int -> InputFile -> ShowS
$cshowsPrec :: Int -> InputFile -> ShowS
Show)

instance ToJSON InputFile where
  toJSON :: InputFile -> Value
toJSON (InputFileId FileId
i) = forall a. ToJSON a => a -> Value
toJSON FileId
i
  toJSON (FileUrl Text
t) = forall a. ToJSON a => a -> Value
toJSON Text
t
  toJSON (InputFile String
f Text
_) = forall a. ToJSON a => a -> Value
toJSON (Text
"attach://" forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (ShowS
takeFileName String
f))


-- | Multipart file helper
makeFile :: Text -> InputFile ->  MultipartData Tmp ->  MultipartData Tmp
makeFile :: Text -> InputFile -> MultipartData Tmp -> MultipartData Tmp
makeFile Text
name (InputFile String
path Text
ct) (MultipartData [Input]
fields [FileData Tmp]
files) = 
  forall tag. [Input] -> [FileData tag] -> MultipartData tag
MultipartData 
    (Text -> Text -> Input
Input Text
name (Text
"attach://" forall a. Semigroup a => a -> a -> a
<> Text
name) forall a. a -> [a] -> [a]
: [Input]
fields) 
    (forall tag.
Text -> Text -> Text -> MultipartResult tag -> FileData tag
FileData Text
name (String -> Text
pack forall a b. (a -> b) -> a -> b
$ ShowS
takeFileName String
path) Text
ct String
path forall a. a -> [a] -> [a]
: [FileData Tmp]
files)

makeFile Text
name InputFile
file (MultipartData [Input]
fields [FileData Tmp]
files) = 
  forall tag. [Input] -> [FileData tag] -> MultipartData tag
MultipartData 
    (Text -> Text -> Input
Input Text
name (Text -> Text
TL.toStrict forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Text
encodeToLazyText InputFile
file) forall a. a -> [a] -> [a]
: [Input]
fields) 
    [FileData Tmp]
files