{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module Telegram.Bot.API.Methods.SendAudio where

import Control.Monad.IO.Class (liftIO)
import Data.Aeson (ToJSON (..))
import Data.Aeson.Text (encodeToLazyText)
import Data.Bool
import Data.Maybe (catMaybes)
import Data.Functor ((<&>))
import Data.Proxy
import Data.Text
import GHC.Generics (Generic)
import Servant.API
import Servant.Multipart.API
import Servant.Multipart.Client
import Servant.Client hiding (Response)

import qualified Data.Text.Lazy as TL

import Telegram.Bot.API.Internal.Utils
import Telegram.Bot.API.MakingRequests
import Telegram.Bot.API.Types
import Telegram.Bot.API.Types.ParseMode
import Telegram.Bot.API.Internal.TH

-- ** 'sendAudio'

-- | Request parameters for 'sendAudio'.
data SendAudioRequest = SendAudioRequest
  { SendAudioRequest -> Maybe BusinessConnectionId
sendAudioBusinessConnectionId :: Maybe BusinessConnectionId -- ^ Unique identifier of the business connection on behalf of which the message will be sent.
  , SendAudioRequest -> SomeChatId
sendAudioChatId :: SomeChatId -- ^ Unique identifier for the target chat or username of the target channel (in the format @channelusername).
  , SendAudioRequest -> Maybe MessageThreadId
sendAudioMessageThreadId :: Maybe MessageThreadId -- ^ Unique identifier for the target message thread (topic) of the forum; for forum supergroups only.
  , SendAudioRequest -> InputFile
sendAudioAudio :: InputFile -- ^ Audio to send. Pass a file_id as String to send an audio that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a audio from the Internet, or upload a new audio using multipart/form-data. More info on Sending Files »
  , SendAudioRequest -> Maybe Int
sendAudioDuration :: Maybe Int -- ^ Duration of sent audio in seconds
  , SendAudioRequest -> Maybe Text
sendAudioPerformer :: Maybe Text -- ^ Performer
  , SendAudioRequest -> Maybe Text
sendAudioTitle :: Maybe Text -- ^ Track name
  , SendAudioRequest -> Maybe InputFile
sendAudioThumbnail :: 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>. More info on Sending Files »
  , SendAudioRequest -> Maybe Text
sendAudioCaption :: Maybe Text -- ^ Audio caption (may also be used when resending audios by file_id), 0-1024 characters after entities parsing
  , SendAudioRequest -> Maybe ParseMode
sendAudioParseMode :: Maybe ParseMode  -- ^ Send 'MarkdownV2', 'HTML' or 'Markdown' (legacy), if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message.
  , SendAudioRequest -> Maybe [MessageEntity]
sendAudioCaptionEntities :: Maybe [MessageEntity] -- ^ A JSON-serialized list of special entities that appear in the caption, which can be specified instead of parse_mode
  , SendAudioRequest -> Maybe Bool
sendAudioDisableNotification :: Maybe Bool -- ^ Sends the message silently. Users will receive a notification with no sound.
  , SendAudioRequest -> Maybe Bool
sendAudioProtectContent :: Maybe Bool -- ^ Protects the contents of the sent message from forwarding and saving
  , SendAudioRequest -> Maybe Text
sendAudioMessageEffectId :: Maybe Text -- ^ Unique identifier of the message effect to be added to the message; for private chats only.
  , SendAudioRequest -> Maybe MessageId
sendAudioReplyToMessageId :: Maybe MessageId -- ^ If the message is a reply, ID of the original message
  , SendAudioRequest -> Maybe ReplyParameters
sendAudioReplyParameters :: Maybe ReplyParameters -- ^ Description of the message to reply to.
  , SendAudioRequest -> Maybe InlineKeyboardMarkup
sendAudioReplyMarkup :: Maybe InlineKeyboardMarkup -- ^ Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
  }
  deriving (forall x. SendAudioRequest -> Rep SendAudioRequest x)
-> (forall x. Rep SendAudioRequest x -> SendAudioRequest)
-> Generic SendAudioRequest
forall x. Rep SendAudioRequest x -> SendAudioRequest
forall x. SendAudioRequest -> Rep SendAudioRequest x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SendAudioRequest -> Rep SendAudioRequest x
from :: forall x. SendAudioRequest -> Rep SendAudioRequest x
$cto :: forall x. Rep SendAudioRequest x -> SendAudioRequest
to :: forall x. Rep SendAudioRequest x -> SendAudioRequest
Generic

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

instance ToMultipart Tmp SendAudioRequest where
  toMultipart :: SendAudioRequest -> MultipartData Tmp
toMultipart SendAudioRequest{Maybe Bool
Maybe Int
Maybe [MessageEntity]
Maybe Text
Maybe BusinessConnectionId
Maybe MessageThreadId
Maybe MessageId
Maybe ParseMode
Maybe InlineKeyboardMarkup
Maybe ReplyParameters
Maybe InputFile
SomeChatId
InputFile
sendAudioBusinessConnectionId :: SendAudioRequest -> Maybe BusinessConnectionId
sendAudioChatId :: SendAudioRequest -> SomeChatId
sendAudioMessageThreadId :: SendAudioRequest -> Maybe MessageThreadId
sendAudioAudio :: SendAudioRequest -> InputFile
sendAudioDuration :: SendAudioRequest -> Maybe Int
sendAudioPerformer :: SendAudioRequest -> Maybe Text
sendAudioTitle :: SendAudioRequest -> Maybe Text
sendAudioThumbnail :: SendAudioRequest -> Maybe InputFile
sendAudioCaption :: SendAudioRequest -> Maybe Text
sendAudioParseMode :: SendAudioRequest -> Maybe ParseMode
sendAudioCaptionEntities :: SendAudioRequest -> Maybe [MessageEntity]
sendAudioDisableNotification :: SendAudioRequest -> Maybe Bool
sendAudioProtectContent :: SendAudioRequest -> Maybe Bool
sendAudioMessageEffectId :: SendAudioRequest -> Maybe Text
sendAudioReplyToMessageId :: SendAudioRequest -> Maybe MessageId
sendAudioReplyParameters :: SendAudioRequest -> Maybe ReplyParameters
sendAudioReplyMarkup :: SendAudioRequest -> Maybe InlineKeyboardMarkup
sendAudioBusinessConnectionId :: Maybe BusinessConnectionId
sendAudioChatId :: SomeChatId
sendAudioMessageThreadId :: Maybe MessageThreadId
sendAudioAudio :: InputFile
sendAudioDuration :: Maybe Int
sendAudioPerformer :: Maybe Text
sendAudioTitle :: Maybe Text
sendAudioThumbnail :: Maybe InputFile
sendAudioCaption :: Maybe Text
sendAudioParseMode :: Maybe ParseMode
sendAudioCaptionEntities :: Maybe [MessageEntity]
sendAudioDisableNotification :: Maybe Bool
sendAudioProtectContent :: Maybe Bool
sendAudioMessageEffectId :: Maybe Text
sendAudioReplyToMessageId :: Maybe MessageId
sendAudioReplyParameters :: Maybe ReplyParameters
sendAudioReplyMarkup :: Maybe InlineKeyboardMarkup
..} =
    (MultipartData Tmp -> MultipartData Tmp)
-> (InputFile -> MultipartData Tmp -> MultipartData Tmp)
-> Maybe InputFile
-> MultipartData Tmp
-> MultipartData Tmp
forall b a. b -> (a -> b) -> Maybe a -> b
maybe MultipartData Tmp -> MultipartData Tmp
forall a. a -> a
id (Text -> InputFile -> MultipartData Tmp -> MultipartData Tmp
makeFile Text
"Thumbnail") Maybe InputFile
sendAudioThumbnail (MultipartData Tmp -> MultipartData Tmp)
-> MultipartData Tmp -> MultipartData Tmp
forall a b. (a -> b) -> a -> b
$
    Text -> InputFile -> MultipartData Tmp -> MultipartData Tmp
makeFile Text
"audio" InputFile
sendAudioAudio (MultipartData Tmp -> MultipartData Tmp)
-> MultipartData Tmp -> MultipartData Tmp
forall a b. (a -> b) -> a -> b
$
    [Input] -> [FileData Tmp] -> MultipartData Tmp
forall tag. [Input] -> [FileData tag] -> MultipartData tag
MultipartData [Input]
fields [] where
    fields :: [Input]
fields =
      [ Text -> Text -> Input
Input Text
"chat_id" (Text -> Input) -> Text -> Input
forall a b. (a -> b) -> a -> b
$ case SomeChatId
sendAudioChatId of
          SomeChatId (ChatId Integer
chat_id) -> Integer -> Text
forall a. Show a => a -> Text
showText Integer
chat_id
          SomeChatUsername Text
txt -> Text
txt
      ] [Input] -> [Input] -> [Input]
forall a. Semigroup a => a -> a -> a
<> [Maybe Input] -> [Input]
forall a. [Maybe a] -> [a]
catMaybes
      [ Maybe MessageThreadId
sendAudioMessageThreadId Maybe MessageThreadId -> (MessageThreadId -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \MessageThreadId
t -> Text -> Text -> Input
Input Text
"message_thread_id" (MessageThreadId -> Text
forall a. Show a => a -> Text
showText MessageThreadId
t)
      , Maybe Text
sendAudioCaption Maybe Text -> (Text -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Text
t -> Text -> Text -> Input
Input Text
"caption" Text
t
      , Maybe ParseMode
sendAudioParseMode Maybe ParseMode -> (ParseMode -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \ParseMode
t -> Text -> Text -> Input
Input Text
"parse_mode" (Text -> Text
TL.toStrict (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
TL.replace Text
"\"" Text
"" (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ ParseMode -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText ParseMode
t)
      , Maybe [MessageEntity]
sendAudioCaptionEntities Maybe [MessageEntity] -> ([MessageEntity] -> Input) -> Maybe Input
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 (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ [MessageEntity] -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText [MessageEntity]
t)
      , Maybe Int
sendAudioDuration Maybe Int -> (Int -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Int
t -> Text -> Text -> Input
Input Text
"duration" (Text -> Text
TL.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Int -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText Int
t)
      , Maybe Text
sendAudioPerformer Maybe Text -> (Text -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Text
t -> Text -> Text -> Input
Input Text
"performer" Text
t
      , Maybe Text
sendAudioTitle Maybe Text -> (Text -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Text
t -> Text -> Text -> Input
Input Text
"title" (Text -> Text
TL.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText Text
t)
      , Maybe Bool
sendAudioDisableNotification Maybe Bool -> (Bool -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Bool
t -> Text -> Text -> Input
Input Text
"disable_notification" (Text -> Text -> Bool -> Text
forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" Bool
t)
      , Maybe Bool
sendAudioProtectContent Maybe Bool -> (Bool -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \Bool
t -> Text -> Text -> Input
Input Text
"protect_content" (Text -> Text -> Bool -> Text
forall a. a -> a -> Bool -> a
bool Text
"false" Text
"true" Bool
t)
      , Maybe MessageId
sendAudioReplyToMessageId Maybe MessageId -> (MessageId -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \MessageId
t -> Text -> Text -> Input
Input Text
"reply_to_message_id" (Text -> Text
TL.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ MessageId -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText MessageId
t)
      , Maybe ReplyParameters
sendAudioReplyParameters Maybe ReplyParameters -> (ReplyParameters -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \ReplyParameters
t -> Text -> Text -> Input
Input Text
"reply_parameters" (Text -> Text
TL.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ ReplyParameters -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText ReplyParameters
t)
      , Maybe InlineKeyboardMarkup
sendAudioReplyMarkup Maybe InlineKeyboardMarkup
-> (InlineKeyboardMarkup -> Input) -> Maybe Input
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&>
        \InlineKeyboardMarkup
t -> Text -> Text -> Input
Input Text
"reply_markup" (Text -> Text
TL.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ InlineKeyboardMarkup -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText InlineKeyboardMarkup
t)
      ]

type SendAudioContent
  = "sendAudio"
  :> MultipartForm Tmp SendAudioRequest
  :> Post '[JSON] (Response Message)

type SendAudioLink
  = "sendAudio"
  :> ReqBody '[JSON] SendAudioRequest
  :> Post '[JSON] (Response Message)

-- | Use this method to send audio files, if
--   you want Telegram clients to display them
--   in the music player. Your audio must be in
--   the .MP3 or .M4A format. On success, the sent
--   Message is returned. Bots can currently send
--   audio files of up to 50 MB in size, this limit
--   may be changed in the future.
--
--   For sending voice messages, use the sendVoice method instead.
sendAudio :: SendAudioRequest ->  ClientM (Response Message)
sendAudio :: SendAudioRequest -> ClientM (Response Message)
sendAudio SendAudioRequest
r = case (SendAudioRequest -> InputFile
sendAudioAudio SendAudioRequest
r, SendAudioRequest -> Maybe InputFile
sendAudioThumbnail SendAudioRequest
r) of
  (InputFile{}, Maybe InputFile
_) -> do
    ByteString
boundary <- IO ByteString -> ClientM ByteString
forall a. IO a -> ClientM a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ByteString
genBoundary
    Proxy SendAudioContent -> Client ClientM SendAudioContent
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @SendAudioContent) (ByteString
boundary, SendAudioRequest
r)
  (InputFile
_, Just InputFile{}) -> do
    ByteString
boundary <- IO ByteString -> ClientM ByteString
forall a. IO a -> ClientM a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ByteString
genBoundary
    Proxy SendAudioContent -> Client ClientM SendAudioContent
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @SendAudioContent) (ByteString
boundary, SendAudioRequest
r)
  (InputFile, Maybe InputFile)
_ ->  Proxy SendAudioLink -> Client ClientM SendAudioLink
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @SendAudioLink) SendAudioRequest
r

makeDefault ''SendAudioRequest