-- | -- Module : Web.FBMessenger.API.Bot.Requests -- License : BSD3 -- Maintainer : Marcello Seri -- Stability : experimental -- Portability : unknown -- -- This module contains types and helpers to parse the responses from the -- . -- 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