{-# LANGUAGE CPP                        #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}
module Telegram.Bot.API.MakingRequests where

import           Data.Aeson                      (FromJSON (..), ToJSON (..))
#if defined(MIN_VERSION_GLASGOW_HASKELL)
#if MIN_VERSION_GLASGOW_HASKELL(8,6,2,0)
#else
import           Data.Monoid                     ((<>))
#endif
#endif
import           Data.String                     (IsString)
import           Data.Text                       (Text)
import qualified Data.Text                       as Text
import           GHC.Generics                    (Generic)
import           Network.HTTP.Client             (newManager)
import           Network.HTTP.Client.TLS         (tlsManagerSettings)
import           Servant.Client                  hiding (Response)
import           Web.HttpApiData                 (FromHttpApiData,
                                                  ToHttpApiData (..))

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

botBaseUrl :: Token -> BaseUrl
botBaseUrl :: Token -> BaseUrl
botBaseUrl Token
token = Scheme -> String -> Int -> String -> BaseUrl
BaseUrl Scheme
Https String
"api.telegram.org" Int
443
  (Text -> String
Text.unpack (Text
"/bot" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Token -> Text
forall a. ToHttpApiData a => a -> Text
toUrlPiece Token
token))

botBaseUrlTest :: Token -> BaseUrl
botBaseUrlTest :: Token -> BaseUrl
botBaseUrlTest Token
token = Scheme -> String -> Int -> String -> BaseUrl
BaseUrl Scheme
Https String
"api.telegram.org" Int
443
  (Text -> String
Text.unpack (Text
"/bot" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Token -> Text
forall a. ToHttpApiData a => a -> Text
toUrlPiece Token
token Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/test"))

defaultTelegramClientEnv :: Token -> IO ClientEnv
defaultTelegramClientEnv :: Token -> IO ClientEnv
defaultTelegramClientEnv Token
token = Manager -> BaseUrl -> ClientEnv
mkClientEnv
  (Manager -> BaseUrl -> ClientEnv)
-> IO Manager -> IO (BaseUrl -> ClientEnv)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ManagerSettings -> IO Manager
newManager ManagerSettings
tlsManagerSettings
  IO (BaseUrl -> ClientEnv) -> IO BaseUrl -> IO ClientEnv
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BaseUrl -> IO BaseUrl
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Token -> BaseUrl
botBaseUrl Token
token)

defaultTelegramClientEnvTest :: Token -> IO ClientEnv
defaultTelegramClientEnvTest :: Token -> IO ClientEnv
defaultTelegramClientEnvTest Token
token = Manager -> BaseUrl -> ClientEnv
mkClientEnv
  (Manager -> BaseUrl -> ClientEnv)
-> IO Manager -> IO (BaseUrl -> ClientEnv)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ManagerSettings -> IO Manager
newManager ManagerSettings
tlsManagerSettings
  IO (BaseUrl -> ClientEnv) -> IO BaseUrl -> IO ClientEnv
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BaseUrl -> IO BaseUrl
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Token -> BaseUrl
botBaseUrlTest Token
token)

defaultRunBot :: Token -> ClientM a -> IO (Either ClientError a)
defaultRunBot :: forall a. Token -> ClientM a -> IO (Either ClientError a)
defaultRunBot Token
token ClientM a
bot = do
  ClientEnv
env <- Token -> IO ClientEnv
defaultTelegramClientEnv Token
token
  ClientM a -> ClientEnv -> IO (Either ClientError a)
forall a. ClientM a -> ClientEnv -> IO (Either ClientError a)
runClientM ClientM a
bot ClientEnv
env

defaultRunBotTest :: Token -> ClientM a -> IO (Either ClientError a)
defaultRunBotTest :: forall a. Token -> ClientM a -> IO (Either ClientError a)
defaultRunBotTest Token
token ClientM a
bot = do
  ClientEnv
env <- Token -> IO ClientEnv
defaultTelegramClientEnvTest Token
token
  ClientM a -> ClientEnv -> IO (Either ClientError a)
forall a. ClientM a -> ClientEnv -> IO (Either ClientError a)
runClientM ClientM a
bot ClientEnv
env

data Response a = Response
  { forall a. Response a -> Bool
responseOk          :: Bool
  , forall a. Response a -> Maybe Text
responseDescription :: Maybe Text
  , forall a. Response a -> a
responseResult      :: a
  , forall a. Response a -> Maybe Integer
responseErrorCode   :: Maybe Integer
  , forall a. Response a -> Maybe ResponseParameters
responseParameters  :: Maybe ResponseParameters
  } deriving (Int -> Response a -> ShowS
[Response a] -> ShowS
Response a -> String
(Int -> Response a -> ShowS)
-> (Response a -> String)
-> ([Response a] -> ShowS)
-> Show (Response a)
forall a. Show a => Int -> Response a -> ShowS
forall a. Show a => [Response a] -> ShowS
forall a. Show a => Response a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Response a -> ShowS
showsPrec :: Int -> Response a -> ShowS
$cshow :: forall a. Show a => Response a -> String
show :: Response a -> String
$cshowList :: forall a. Show a => [Response a] -> ShowS
showList :: [Response a] -> ShowS
Show, (forall x. Response a -> Rep (Response a) x)
-> (forall x. Rep (Response a) x -> Response a)
-> Generic (Response a)
forall x. Rep (Response a) x -> Response a
forall x. Response a -> Rep (Response a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Response a) x -> Response a
forall a x. Response a -> Rep (Response a) x
$cfrom :: forall a x. Response a -> Rep (Response a) x
from :: forall x. Response a -> Rep (Response a) x
$cto :: forall a x. Rep (Response a) x -> Response a
to :: forall x. Rep (Response a) x -> Response a
Generic)

instance ToJSON   a => ToJSON   (Response a) where toJSON :: Response a -> Value
toJSON = Response a -> Value
forall a (d :: Meta) (f :: * -> *).
(Generic a, GToJSON Zero (Rep a), Rep a ~ D1 d f, Datatype d) =>
a -> Value
gtoJSON
instance FromJSON a => FromJSON (Response a) where parseJSON :: Value -> Parser (Response a)
parseJSON = Value -> Parser (Response a)
forall a (d :: Meta) (f :: * -> *).
(Generic a, GFromJSON Zero (Rep a), Rep a ~ D1 d f, Datatype d) =>
Value -> Parser a
gparseJSON

newtype Token = Token Text
  deriving (Token -> Token -> Bool
(Token -> Token -> Bool) -> (Token -> Token -> Bool) -> Eq Token
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Token -> Token -> Bool
== :: Token -> Token -> Bool
$c/= :: Token -> Token -> Bool
/= :: Token -> Token -> Bool
Eq, Int -> Token -> ShowS
[Token] -> ShowS
Token -> String
(Int -> Token -> ShowS)
-> (Token -> String) -> ([Token] -> ShowS) -> Show Token
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Token -> ShowS
showsPrec :: Int -> Token -> ShowS
$cshow :: Token -> String
show :: Token -> String
$cshowList :: [Token] -> ShowS
showList :: [Token] -> ShowS
Show, Token -> Text
Token -> ByteString
Token -> Builder
(Token -> Text)
-> (Token -> Builder)
-> (Token -> ByteString)
-> (Token -> Text)
-> (Token -> Builder)
-> ToHttpApiData Token
forall a.
(a -> Text)
-> (a -> Builder)
-> (a -> ByteString)
-> (a -> Text)
-> (a -> Builder)
-> ToHttpApiData a
$ctoUrlPiece :: Token -> Text
toUrlPiece :: Token -> Text
$ctoEncodedUrlPiece :: Token -> Builder
toEncodedUrlPiece :: Token -> Builder
$ctoHeader :: Token -> ByteString
toHeader :: Token -> ByteString
$ctoQueryParam :: Token -> Text
toQueryParam :: Token -> Text
$ctoEncodedQueryParam :: Token -> Builder
toEncodedQueryParam :: Token -> Builder
ToHttpApiData, Text -> Either Text Token
ByteString -> Either Text Token
(Text -> Either Text Token)
-> (ByteString -> Either Text Token)
-> (Text -> Either Text Token)
-> FromHttpApiData Token
forall a.
(Text -> Either Text a)
-> (ByteString -> Either Text a)
-> (Text -> Either Text a)
-> FromHttpApiData a
$cparseUrlPiece :: Text -> Either Text Token
parseUrlPiece :: Text -> Either Text Token
$cparseHeader :: ByteString -> Either Text Token
parseHeader :: ByteString -> Either Text Token
$cparseQueryParam :: Text -> Either Text Token
parseQueryParam :: Text -> Either Text Token
FromHttpApiData, [Token] -> Value
[Token] -> Encoding
Token -> Bool
Token -> Value
Token -> Encoding
(Token -> Value)
-> (Token -> Encoding)
-> ([Token] -> Value)
-> ([Token] -> Encoding)
-> (Token -> Bool)
-> ToJSON Token
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: Token -> Value
toJSON :: Token -> Value
$ctoEncoding :: Token -> Encoding
toEncoding :: Token -> Encoding
$ctoJSONList :: [Token] -> Value
toJSONList :: [Token] -> Value
$ctoEncodingList :: [Token] -> Encoding
toEncodingList :: [Token] -> Encoding
$comitField :: Token -> Bool
omitField :: Token -> Bool
ToJSON, Maybe Token
Value -> Parser [Token]
Value -> Parser Token
(Value -> Parser Token)
-> (Value -> Parser [Token]) -> Maybe Token -> FromJSON Token
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser Token
parseJSON :: Value -> Parser Token
$cparseJSONList :: Value -> Parser [Token]
parseJSONList :: Value -> Parser [Token]
$comittedField :: Maybe Token
omittedField :: Maybe Token
FromJSON, String -> Token
(String -> Token) -> IsString Token
forall a. (String -> a) -> IsString a
$cfromString :: String -> Token
fromString :: String -> Token
IsString)