fbmessenger-api-0.1.1.1: src/Web/FBMessenger/API/Bot/Responses.hs
-- |
-- Module : Web.FBMessenger.API.Bot.Requests
-- License : BSD3
-- Maintainer : Marcello Seri <marcello.seri@gmail.com>
-- Stability : experimental
-- Portability : unknown
--
-- This module contains types and helpers to parse the responses from the
-- <https://developers.facebook.com/docs/messenger-platform/ Messenger Platform API>.
-- See also 'Web.FBMessenger.API.Bot.SendAPI'.
--
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
module Web.FBMessenger.API.Bot.Responses
( -- * Types
MessageResponse (..)
, SendErrorCode (..)
, SendErrorObject (..)
, SubscriptionResponse (..)
, UserProfileResponse (..)
, WelcomeMessageResponse (..)
-- * Functions
, errorInfo
, extractSendError
) where
import Data.Aeson
import Data.Text (Text)
import GHC.Generics
import Servant.Client (ServantError(..))
import Web.FBMessenger.API.Bot.JsonExt
-- | This object represents the 'subscribed_apps' success response
data SubscriptionResponse = SubscriptionResponse{ subscription_success :: Bool } deriving (Eq, Show, Generic)
instance ToJSON SubscriptionResponse where
toJSON = toJsonDrop 13
instance FromJSON SubscriptionResponse where
parseJSON = parseJsonDrop 13
-- | This object contais the response after a message has been succesfully sent
data MessageResponse = MessageResponse
{ message_response_recipient_id :: Text
, message_response_message_id :: Text
} deriving (Eq, Show, Generic)
instance ToJSON MessageResponse where
toJSON = toJsonDrop 17
instance FromJSON MessageResponse where
parseJSON = parseJsonDrop 17
-- | This objects contains the User Profile informations
data UserProfileResponse = UserProfileResponse
{ usr_first_name :: Text
, usr_last_name :: Text
, usr_profile_pic :: Text
, usr_locale :: Text
, usr_timezone :: Int
, usr_gender :: Text
} deriving (Eq, Show, Generic)
instance ToJSON UserProfileResponse where
toJSON = toJsonDrop 4
instance FromJSON UserProfileResponse where
parseJSON = parseJsonDrop 4
-- | This objects contains informations on the succesful setup of a welcome message
data WelcomeMessageResponse = WelcomeMessageResponse { wmr_result :: Text } deriving (Eq, Show, Generic)
instance ToJSON WelcomeMessageResponse where
toJSON = toJsonDrop 4
instance FromJSON WelcomeMessageResponse where
parseJSON = parseJsonDrop 4
-- | Send API Error response object (see: https://developers.facebook.com/docs/messenger-platform/send-api-reference#errors)
--
-- {
-- "error":{
-- "message":"Invalid parameter",
-- "type":"FacebookApiException",
-- "code":100,
-- "error_data":"No matching user found.",
-- "fbtrace_id":"D2kxCybrKVw"
-- }
--
data SendErrorObject = SendErrorObject { eoMessage :: Text, eoType :: Text, eoCode :: SendErrorCode, eoErrorData :: Text, eoFbtraceId :: Text } deriving (Eq, Show, Generic)
instance ToJSON SendErrorObject where
toJSON SendErrorObject{..} = object [ "error" .= e ]
where e = object [ "message" .= eoMessage
, "type" .= eoType
, "code" .= eoCode
, "error_data" .= eoErrorData
, "fbtrace_id" .= eoFbtraceId ]
instance FromJSON SendErrorObject where
parseJSON = withObject "send error" $ \o ->
let e = o .: "error"
e' field = e >>= (.: field)
in SendErrorObject <$>
e' "message" <*>
e' "type" <*>
e' "code" <*>
e' "error_data" <*>
e' "fbtrace_id"
-- | Send API Error Codes (see: https://developers.facebook.com/docs/messenger-platform/send-api-reference#errors)
--
-- Code Description
-- 2 Send message failure. Internal server error.
-- 10 Application does not have permission to use the Send API
-- 100 No matching user found
-- 613 Calls to this api have exceeded the rate limit.
--
data SendErrorCode = InternalServerError | UnauthorizedApplication | NoMatchingUserFound | RateLimitError deriving (Eq, Show)
instance ToJSON SendErrorCode where
toJSON InternalServerError = Number 2
toJSON UnauthorizedApplication = Number 10
toJSON NoMatchingUserFound = Number 100
toJSON RateLimitError = Number 613
instance FromJSON SendErrorCode where
parseJSON (Number 2) = pure InternalServerError
parseJSON (Number 10) = pure UnauthorizedApplication
parseJSON (Number 100) = pure NoMatchingUserFound
parseJSON (Number 613) = pure RateLimitError
parseJSON _ = fail "Unable to parse SendErrorCode"
-- | Take a Send API error object and return a tuple containing the error code
-- and the error_data (seems to always be the description)
errorInfo :: SendErrorObject -> (SendErrorCode, Text)
errorInfo err = (ecode, edata)
where edata = eoErrorData err
ecode = eoCode err
-- | Extracts a Send API Error object from the 'ServantError' (when possible).
extractSendError :: ServantError -> Maybe SendErrorObject
extractSendError FailureResponse{ responseStatus = _, responseContentType = _
, responseBody = body
} = decode body :: Maybe SendErrorObject
extractSendError _ = Nothing