servant-smsc-ru-0.1.0.0: src/Servant/API/SMSC/RU/API.hs
{-|
Module : Servant.API.SMSC.RU.API
Description : Contains raw servant API for smsc.ru service
Copyright : (c) Anton Gushcha, 2016
License : MIT
Maintainer : ncrashed@gmail.com
Stability : experimental
Portability : Portable
-}
module Servant.API.SMSC.RU.API(
-- * API
SMSCAPI
-- ** Endpoints
, SendResponse(..)
, PhoneResp(..)
, SendErrorCode(..)
, SendEndpoint
) where
import Control.Monad
import Data.Aeson
import Data.Monoid
import Data.Scientific
import Data.Text
import GHC.Generics
import Servant.API
import Data.ByteString.Lazy (ByteString)
-- | All supported API of smsc.ru service
type SMSCAPI = SendEndpoint
-- | Error type
data SendErrorCode =
SendParametersError
| SendInvalidLoginPass
| SendLowFunds
| SendBlockedDueErrors
| SendInvalidDateFormat
| SendForbiddenMessage
| SendInvalidPhoneFormat
| SendMessageCannotBeDelivered
| SendTooMuchMessages
deriving (Generic, Show, Eq, Bounded, Enum)
-- | Convert from received error code
fromErrorCode :: Word -> Maybe SendErrorCode
fromErrorCode w = case w of
1 -> Just SendParametersError
2 -> Just SendInvalidLoginPass
3 -> Just SendLowFunds
4 -> Just SendBlockedDueErrors
5 -> Just SendInvalidDateFormat
6 -> Just SendForbiddenMessage
7 -> Just SendInvalidPhoneFormat
8 -> Just SendMessageCannotBeDelivered
9 -> Just SendTooMuchMessages
_ -> Nothing
instance FromJSON SendErrorCode where
parseJSON (Number s) = case fromErrorCode =<< toBoundedInteger s of
Nothing -> fail $ "unknown error code " <> show s
Just c -> return c
parseJSON _ = mzero
-- | Additional info about phone number
data PhoneResp = PhoneResp {
phoneNumber :: !Text
, phoneMccmnc :: !Text
, phoneCost :: !Text
, phoneStatus :: !Text
, phoneError :: !Text
} deriving (Generic, Show)
instance FromJSON PhoneResp where
parseJSON (Object o) = PhoneResp
<$> o .: "phone"
<*> o .: "mccmnc"
<*> o .: "cost"
<*> o .: "status"
<*> o .: "error"
parseJSON _ = mzero
-- | Response for 'SendEndpoint'
data SendResponse =
-- | Server returned error payload
SendError {
sendError :: !Text -- ^ Desciption of error
, sendErrorCode :: !SendErrorCode -- ^ Error code
, sendErrorId :: !(Maybe Text) -- ^ ID of failed message
}
-- | Server retunred success payload
| SendSuccess {
sendSuccId :: !(Maybe Word) -- ^ ID of sended message
, sendSuccCnt :: !Word -- ^ Count of messages sended (huge payloads are splitted)
, sendSuccCost :: !(Maybe Text) -- ^ Cost of sending
, sendSuccBalance :: !(Maybe Text) -- ^ Funds of the account left after the call
, sendSuccPhones :: !(Maybe [PhoneResp]) -- ^ Additional info by phone number
}
deriving (Generic, Show)
instance FromJSON SendResponse where
parseJSON (Object o) = do
merr <- o .:? "error"
case merr of
Nothing -> SendSuccess
<$> o .:? "id"
<*> o .: "cnt"
<*> o .:? "cost"
<*> o .:? "balance"
<*> o .:? "phones"
Just err -> SendError err
<$> o .: "error_code"
<*> o .:? "id"
parseJSON _ = mzero
-- | Endpoint for sending sms, this is low-level most general
-- API that is used to built small helper functions.
type SendEndpoint = "sys" :> "send.php"
:> QueryParam "login" Text
:> QueryParam "psw" Text
:> QueryParam "phones" Text
:> QueryParam "mes" Text
-- additional parameters
:> QueryParam "id" Text
:> QueryParam "sender" Text
:> QueryParam "translit" Text
:> QueryParam "tinyurl" Text
:> QueryParam "time" Text
:> QueryParam "tz" Text
:> QueryParam "period" Double
:> QueryParam "freq" Word
:> QueryParam "flash" Word
:> QueryParam "bin" Text
:> QueryParam "push" Word
:> QueryParam "hlr" Word
:> QueryParam "ping" Word
:> QueryParam "mms" Word
:> QueryParam "mail" Word
:> QueryParam "call" Word
:> QueryParam "voice" Text
:> QueryParam "param" Text
:> QueryParam "subj" Text
:> QueryParam "charset" Text
:> QueryParam "cost" Word
:> QueryParam "fmt" Word -- should be always 3
:> QueryParam "list" Text
:> QueryParam "valid" Text
:> QueryParam "maxsms" Word
:> QueryParam "imgcode" Text
:> QueryParam "userip" Text
:> QueryParam "err" Word
:> QueryParam "op" Word
:> QueryParam "pp" Text
:> ReqBody '[OctetStream] ByteString
:> Post '[JSON] SendResponse