{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}

module Facebook.Monad
  ( FacebookT
  , Auth
  , NoAuth
  , FbTier(..)
  , runFacebookT
  , runNoAuthFacebookT
  , beta_runFacebookT
  , beta_runNoAuthFacebookT
  , getApiVersion
  , getCreds
  , getMCreds
  , getManager
  , getTier
  , withTier
  , addAppSecretProof
  , makeAppSecretProof
  , runResourceInFb
  , mapFacebookT
  , setApiVersion
   -- * Re-export
  , lift
  ) where

import Control.Applicative (Alternative, Applicative)
import Control.Monad (MonadPlus, liftM)
import Control.Monad.Base (MonadBase(..))
import Control.Monad.Fail (MonadFail(..))
import Control.Monad.Fix (MonadFix)
import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Logger (MonadLogger(..))
import Control.Monad.Trans.Class (MonadTrans(lift))
import Control.Monad.Trans.Reader (ReaderT(..), ask, mapReaderT)
import qualified Control.Monad.Trans.Resource as R
import Crypto.Hash.Algorithms (SHA256)
import Crypto.MAC.HMAC (HMAC(..), hmac)
import Data.ByteArray.Encoding (Base(..), convertToBase)
import qualified Data.Text.Encoding as TE
import Data.Typeable (Typeable)
import Facebook.Types
import qualified Network.HTTP.Conduit as H
import qualified Network.HTTP.Types as HT
import UnliftIO
import qualified UnliftIO.Exception as E

-- | @FacebookT auth m a@ is this library's monad transformer.
-- Contains information needed to issue commands and queries to
-- Facebook.  The phantom type @auth@ may be either 'Auth' (you
-- have supplied your 'Credentials') or 'NoAuth' (you have not
-- supplied any 'Credentials').
newtype FacebookT auth m a = F
  { FacebookT auth m a -> ReaderT FbData m a
unF :: ReaderT FbData m a -- FbData -> m a
  } deriving ( a -> FacebookT auth m b -> FacebookT auth m a
(a -> b) -> FacebookT auth m a -> FacebookT auth m b
(forall a b. (a -> b) -> FacebookT auth m a -> FacebookT auth m b)
-> (forall a b. a -> FacebookT auth m b -> FacebookT auth m a)
-> Functor (FacebookT auth m)
forall a b. a -> FacebookT auth m b -> FacebookT auth m a
forall a b. (a -> b) -> FacebookT auth m a -> FacebookT auth m b
forall auth (m :: * -> *) a b.
Functor m =>
a -> FacebookT auth m b -> FacebookT auth m a
forall auth (m :: * -> *) a b.
Functor m =>
(a -> b) -> FacebookT auth m a -> FacebookT auth m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> FacebookT auth m b -> FacebookT auth m a
$c<$ :: forall auth (m :: * -> *) a b.
Functor m =>
a -> FacebookT auth m b -> FacebookT auth m a
fmap :: (a -> b) -> FacebookT auth m a -> FacebookT auth m b
$cfmap :: forall auth (m :: * -> *) a b.
Functor m =>
(a -> b) -> FacebookT auth m a -> FacebookT auth m b
Functor
             , Functor (FacebookT auth m)
a -> FacebookT auth m a
Functor (FacebookT auth m)
-> (forall a. a -> FacebookT auth m a)
-> (forall a b.
    FacebookT auth m (a -> b)
    -> FacebookT auth m a -> FacebookT auth m b)
-> (forall a b c.
    (a -> b -> c)
    -> FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m c)
-> (forall a b.
    FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b)
-> (forall a b.
    FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m a)
-> Applicative (FacebookT auth m)
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m a
FacebookT auth m (a -> b)
-> FacebookT auth m a -> FacebookT auth m b
(a -> b -> c)
-> FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m c
forall a. a -> FacebookT auth m a
forall a b.
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m a
forall a b.
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
forall a b.
FacebookT auth m (a -> b)
-> FacebookT auth m a -> FacebookT auth m b
forall a b c.
(a -> b -> c)
-> FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m c
forall auth (m :: * -> *).
Applicative m =>
Functor (FacebookT auth m)
forall auth (m :: * -> *) a.
Applicative m =>
a -> FacebookT auth m a
forall auth (m :: * -> *) a b.
Applicative m =>
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m a
forall auth (m :: * -> *) a b.
Applicative m =>
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
forall auth (m :: * -> *) a b.
Applicative m =>
FacebookT auth m (a -> b)
-> FacebookT auth m a -> FacebookT auth m b
forall auth (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m a
$c<* :: forall auth (m :: * -> *) a b.
Applicative m =>
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m a
*> :: FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
$c*> :: forall auth (m :: * -> *) a b.
Applicative m =>
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
liftA2 :: (a -> b -> c)
-> FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m c
$cliftA2 :: forall auth (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m c
<*> :: FacebookT auth m (a -> b)
-> FacebookT auth m a -> FacebookT auth m b
$c<*> :: forall auth (m :: * -> *) a b.
Applicative m =>
FacebookT auth m (a -> b)
-> FacebookT auth m a -> FacebookT auth m b
pure :: a -> FacebookT auth m a
$cpure :: forall auth (m :: * -> *) a.
Applicative m =>
a -> FacebookT auth m a
$cp1Applicative :: forall auth (m :: * -> *).
Applicative m =>
Functor (FacebookT auth m)
Applicative
             , Applicative (FacebookT auth m)
FacebookT auth m a
Applicative (FacebookT auth m)
-> (forall a. FacebookT auth m a)
-> (forall a.
    FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a)
-> (forall a. FacebookT auth m a -> FacebookT auth m [a])
-> (forall a. FacebookT auth m a -> FacebookT auth m [a])
-> Alternative (FacebookT auth m)
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
FacebookT auth m a -> FacebookT auth m [a]
FacebookT auth m a -> FacebookT auth m [a]
forall a. FacebookT auth m a
forall a. FacebookT auth m a -> FacebookT auth m [a]
forall a.
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
forall auth (m :: * -> *).
Alternative m =>
Applicative (FacebookT auth m)
forall auth (m :: * -> *) a. Alternative m => FacebookT auth m a
forall auth (m :: * -> *) a.
Alternative m =>
FacebookT auth m a -> FacebookT auth m [a]
forall auth (m :: * -> *) a.
Alternative m =>
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
forall (f :: * -> *).
Applicative f
-> (forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
many :: FacebookT auth m a -> FacebookT auth m [a]
$cmany :: forall auth (m :: * -> *) a.
Alternative m =>
FacebookT auth m a -> FacebookT auth m [a]
some :: FacebookT auth m a -> FacebookT auth m [a]
$csome :: forall auth (m :: * -> *) a.
Alternative m =>
FacebookT auth m a -> FacebookT auth m [a]
<|> :: FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
$c<|> :: forall auth (m :: * -> *) a.
Alternative m =>
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
empty :: FacebookT auth m a
$cempty :: forall auth (m :: * -> *) a. Alternative m => FacebookT auth m a
$cp1Alternative :: forall auth (m :: * -> *).
Alternative m =>
Applicative (FacebookT auth m)
Alternative
             , Applicative (FacebookT auth m)
a -> FacebookT auth m a
Applicative (FacebookT auth m)
-> (forall a b.
    FacebookT auth m a
    -> (a -> FacebookT auth m b) -> FacebookT auth m b)
-> (forall a b.
    FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b)
-> (forall a. a -> FacebookT auth m a)
-> Monad (FacebookT auth m)
FacebookT auth m a
-> (a -> FacebookT auth m b) -> FacebookT auth m b
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
forall a. a -> FacebookT auth m a
forall a b.
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
forall a b.
FacebookT auth m a
-> (a -> FacebookT auth m b) -> FacebookT auth m b
forall auth (m :: * -> *).
Monad m =>
Applicative (FacebookT auth m)
forall auth (m :: * -> *) a. Monad m => a -> FacebookT auth m a
forall auth (m :: * -> *) a b.
Monad m =>
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
forall auth (m :: * -> *) a b.
Monad m =>
FacebookT auth m a
-> (a -> FacebookT auth m b) -> FacebookT auth m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> FacebookT auth m a
$creturn :: forall auth (m :: * -> *) a. Monad m => a -> FacebookT auth m a
>> :: FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
$c>> :: forall auth (m :: * -> *) a b.
Monad m =>
FacebookT auth m a -> FacebookT auth m b -> FacebookT auth m b
>>= :: FacebookT auth m a
-> (a -> FacebookT auth m b) -> FacebookT auth m b
$c>>= :: forall auth (m :: * -> *) a b.
Monad m =>
FacebookT auth m a
-> (a -> FacebookT auth m b) -> FacebookT auth m b
$cp1Monad :: forall auth (m :: * -> *).
Monad m =>
Applicative (FacebookT auth m)
Monad
             , Monad (FacebookT auth m)
Monad (FacebookT auth m)
-> (forall a. (a -> FacebookT auth m a) -> FacebookT auth m a)
-> MonadFix (FacebookT auth m)
(a -> FacebookT auth m a) -> FacebookT auth m a
forall a. (a -> FacebookT auth m a) -> FacebookT auth m a
forall auth (m :: * -> *). MonadFix m => Monad (FacebookT auth m)
forall auth (m :: * -> *) a.
MonadFix m =>
(a -> FacebookT auth m a) -> FacebookT auth m a
forall (m :: * -> *).
Monad m -> (forall a. (a -> m a) -> m a) -> MonadFix m
mfix :: (a -> FacebookT auth m a) -> FacebookT auth m a
$cmfix :: forall auth (m :: * -> *) a.
MonadFix m =>
(a -> FacebookT auth m a) -> FacebookT auth m a
$cp1MonadFix :: forall auth (m :: * -> *). MonadFix m => Monad (FacebookT auth m)
MonadFix
             , Monad (FacebookT auth m)
Alternative (FacebookT auth m)
FacebookT auth m a
Alternative (FacebookT auth m)
-> Monad (FacebookT auth m)
-> (forall a. FacebookT auth m a)
-> (forall a.
    FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a)
-> MonadPlus (FacebookT auth m)
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
forall a. FacebookT auth m a
forall a.
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
forall auth (m :: * -> *). MonadPlus m => Monad (FacebookT auth m)
forall auth (m :: * -> *).
MonadPlus m =>
Alternative (FacebookT auth m)
forall auth (m :: * -> *) a. MonadPlus m => FacebookT auth m a
forall auth (m :: * -> *) a.
MonadPlus m =>
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
forall (m :: * -> *).
Alternative m
-> Monad m
-> (forall a. m a)
-> (forall a. m a -> m a -> m a)
-> MonadPlus m
mplus :: FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
$cmplus :: forall auth (m :: * -> *) a.
MonadPlus m =>
FacebookT auth m a -> FacebookT auth m a -> FacebookT auth m a
mzero :: FacebookT auth m a
$cmzero :: forall auth (m :: * -> *) a. MonadPlus m => FacebookT auth m a
$cp2MonadPlus :: forall auth (m :: * -> *). MonadPlus m => Monad (FacebookT auth m)
$cp1MonadPlus :: forall auth (m :: * -> *).
MonadPlus m =>
Alternative (FacebookT auth m)
MonadPlus
             , Monad (FacebookT auth m)
Monad (FacebookT auth m)
-> (forall a. IO a -> FacebookT auth m a)
-> MonadIO (FacebookT auth m)
IO a -> FacebookT auth m a
forall a. IO a -> FacebookT auth m a
forall auth (m :: * -> *). MonadIO m => Monad (FacebookT auth m)
forall auth (m :: * -> *) a.
MonadIO m =>
IO a -> FacebookT auth m a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: IO a -> FacebookT auth m a
$cliftIO :: forall auth (m :: * -> *) a.
MonadIO m =>
IO a -> FacebookT auth m a
$cp1MonadIO :: forall auth (m :: * -> *). MonadIO m => Monad (FacebookT auth m)
MonadIO
             , m a -> FacebookT auth m a
(forall (m :: * -> *) a. Monad m => m a -> FacebookT auth m a)
-> MonadTrans (FacebookT auth)
forall auth (m :: * -> *) a. Monad m => m a -> FacebookT auth m a
forall (m :: * -> *) a. Monad m => m a -> FacebookT auth m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
lift :: m a -> FacebookT auth m a
$clift :: forall auth (m :: * -> *) a. Monad m => m a -> FacebookT auth m a
MonadTrans
             , Monad (FacebookT auth m)
e -> FacebookT auth m a
Monad (FacebookT auth m)
-> (forall e a. Exception e => e -> FacebookT auth m a)
-> MonadThrow (FacebookT auth m)
forall e a. Exception e => e -> FacebookT auth m a
forall auth (m :: * -> *). MonadThrow m => Monad (FacebookT auth m)
forall auth (m :: * -> *) e a.
(MonadThrow m, Exception e) =>
e -> FacebookT auth m a
forall (m :: * -> *).
Monad m -> (forall e a. Exception e => e -> m a) -> MonadThrow m
throwM :: e -> FacebookT auth m a
$cthrowM :: forall auth (m :: * -> *) e a.
(MonadThrow m, Exception e) =>
e -> FacebookT auth m a
$cp1MonadThrow :: forall auth (m :: * -> *). MonadThrow m => Monad (FacebookT auth m)
R.MonadThrow
             , Monad (FacebookT auth m)
Monad (FacebookT auth m)
-> (forall a. String -> FacebookT auth m a)
-> MonadFail (FacebookT auth m)
String -> FacebookT auth m a
forall a. String -> FacebookT auth m a
forall auth (m :: * -> *). MonadFail m => Monad (FacebookT auth m)
forall auth (m :: * -> *) a.
MonadFail m =>
String -> FacebookT auth m a
forall (m :: * -> *).
Monad m -> (forall a. String -> m a) -> MonadFail m
fail :: String -> FacebookT auth m a
$cfail :: forall auth (m :: * -> *) a.
MonadFail m =>
String -> FacebookT auth m a
$cp1MonadFail :: forall auth (m :: * -> *). MonadFail m => Monad (FacebookT auth m)
MonadFail
             )

instance (MonadUnliftIO m) => MonadUnliftIO (FacebookT auth m) where
  withRunInIO :: ((forall a. FacebookT auth m a -> IO a) -> IO b)
-> FacebookT auth m b
withRunInIO (forall a. FacebookT auth m a -> IO a) -> IO b
inner =
    ReaderT FbData m b -> FacebookT auth m b
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F (ReaderT FbData m b -> FacebookT auth m b)
-> ReaderT FbData m b -> FacebookT auth m b
forall a b. (a -> b) -> a -> b
$
    (FbData -> m b) -> ReaderT FbData m b
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((FbData -> m b) -> ReaderT FbData m b)
-> (FbData -> m b) -> ReaderT FbData m b
forall a b. (a -> b) -> a -> b
$ \FbData
r ->
      ((forall a. m a -> IO a) -> IO b) -> m b
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO b) -> m b)
-> ((forall a. m a -> IO a) -> IO b) -> m b
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
run -> (forall a. FacebookT auth m a -> IO a) -> IO b
inner (\FacebookT auth m a
fbT -> m a -> IO a
forall a. m a -> IO a
run (m a -> IO a) -> m a -> IO a
forall a b. (a -> b) -> a -> b
$ ((ReaderT FbData m a -> FbData -> m a)
-> FbData -> ReaderT FbData m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT FbData m a -> FbData -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT) FbData
r (FacebookT auth m a -> ReaderT FbData m a
forall auth (m :: * -> *) a.
FacebookT auth m a -> ReaderT FbData m a
unF FacebookT auth m a
fbT))

deriving instance
         (R.MonadResource m, MonadBase IO m) =>
         R.MonadResource (FacebookT auth m)

instance MonadBase b m => MonadBase b (FacebookT auth m) where
  liftBase :: b α -> FacebookT auth m α
liftBase = m α -> FacebookT auth m α
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m α -> FacebookT auth m α)
-> (b α -> m α) -> b α -> FacebookT auth m α
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b α -> m α
forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase

-- | Since @fb-0.14.8@.
instance MonadLogger m => MonadLogger (FacebookT auth m) where
  monadLoggerLog :: Loc -> LogSource -> LogLevel -> msg -> FacebookT auth m ()
monadLoggerLog Loc
loc LogSource
src LogLevel
lvl msg
msg = m () -> FacebookT auth m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Loc -> LogSource -> LogLevel -> msg -> m ()
forall (m :: * -> *) msg.
(MonadLogger m, ToLogStr msg) =>
Loc -> LogSource -> LogLevel -> msg -> m ()
monadLoggerLog Loc
loc LogSource
src LogLevel
lvl msg
msg)

-- | Phantom type stating that you have provided your
-- 'Credentials' and thus have access to the whole API.
data Auth
  deriving (Typeable)

-- | Phantom type stating that you have /not/ provided your
-- 'Credentials'.  This means that you'll be limited about which
-- APIs you'll be able use.
data NoAuth
  deriving (Typeable)

-- | Internal data kept inside 'FacebookT'.
data FbData = FbData
  { FbData -> Maybe Credentials
fbdCreds :: Maybe Credentials
  , FbData -> Manager
fbdManager :: !H.Manager
  , FbData -> FbTier
fbdTier :: !FbTier
  , FbData -> IORef LogSource
fbdApiVersion :: IORef ApiVersion
  } deriving (Typeable)

-- | Which Facebook tier should be used (see
-- <https://developers.facebook.com/support/beta-tier/>).
data FbTier
  = Production
  | Beta
  deriving (FbTier -> FbTier -> Bool
(FbTier -> FbTier -> Bool)
-> (FbTier -> FbTier -> Bool) -> Eq FbTier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FbTier -> FbTier -> Bool
$c/= :: FbTier -> FbTier -> Bool
== :: FbTier -> FbTier -> Bool
$c== :: FbTier -> FbTier -> Bool
Eq, Eq FbTier
Eq FbTier
-> (FbTier -> FbTier -> Ordering)
-> (FbTier -> FbTier -> Bool)
-> (FbTier -> FbTier -> Bool)
-> (FbTier -> FbTier -> Bool)
-> (FbTier -> FbTier -> Bool)
-> (FbTier -> FbTier -> FbTier)
-> (FbTier -> FbTier -> FbTier)
-> Ord FbTier
FbTier -> FbTier -> Bool
FbTier -> FbTier -> Ordering
FbTier -> FbTier -> FbTier
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: FbTier -> FbTier -> FbTier
$cmin :: FbTier -> FbTier -> FbTier
max :: FbTier -> FbTier -> FbTier
$cmax :: FbTier -> FbTier -> FbTier
>= :: FbTier -> FbTier -> Bool
$c>= :: FbTier -> FbTier -> Bool
> :: FbTier -> FbTier -> Bool
$c> :: FbTier -> FbTier -> Bool
<= :: FbTier -> FbTier -> Bool
$c<= :: FbTier -> FbTier -> Bool
< :: FbTier -> FbTier -> Bool
$c< :: FbTier -> FbTier -> Bool
compare :: FbTier -> FbTier -> Ordering
$ccompare :: FbTier -> FbTier -> Ordering
$cp1Ord :: Eq FbTier
Ord, Int -> FbTier -> ShowS
[FbTier] -> ShowS
FbTier -> String
(Int -> FbTier -> ShowS)
-> (FbTier -> String) -> ([FbTier] -> ShowS) -> Show FbTier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FbTier] -> ShowS
$cshowList :: [FbTier] -> ShowS
show :: FbTier -> String
$cshow :: FbTier -> String
showsPrec :: Int -> FbTier -> ShowS
$cshowsPrec :: Int -> FbTier -> ShowS
Show, ReadPrec [FbTier]
ReadPrec FbTier
Int -> ReadS FbTier
ReadS [FbTier]
(Int -> ReadS FbTier)
-> ReadS [FbTier]
-> ReadPrec FbTier
-> ReadPrec [FbTier]
-> Read FbTier
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [FbTier]
$creadListPrec :: ReadPrec [FbTier]
readPrec :: ReadPrec FbTier
$creadPrec :: ReadPrec FbTier
readList :: ReadS [FbTier]
$creadList :: ReadS [FbTier]
readsPrec :: Int -> ReadS FbTier
$creadsPrec :: Int -> ReadS FbTier
Read, Int -> FbTier
FbTier -> Int
FbTier -> [FbTier]
FbTier -> FbTier
FbTier -> FbTier -> [FbTier]
FbTier -> FbTier -> FbTier -> [FbTier]
(FbTier -> FbTier)
-> (FbTier -> FbTier)
-> (Int -> FbTier)
-> (FbTier -> Int)
-> (FbTier -> [FbTier])
-> (FbTier -> FbTier -> [FbTier])
-> (FbTier -> FbTier -> [FbTier])
-> (FbTier -> FbTier -> FbTier -> [FbTier])
-> Enum FbTier
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: FbTier -> FbTier -> FbTier -> [FbTier]
$cenumFromThenTo :: FbTier -> FbTier -> FbTier -> [FbTier]
enumFromTo :: FbTier -> FbTier -> [FbTier]
$cenumFromTo :: FbTier -> FbTier -> [FbTier]
enumFromThen :: FbTier -> FbTier -> [FbTier]
$cenumFromThen :: FbTier -> FbTier -> [FbTier]
enumFrom :: FbTier -> [FbTier]
$cenumFrom :: FbTier -> [FbTier]
fromEnum :: FbTier -> Int
$cfromEnum :: FbTier -> Int
toEnum :: Int -> FbTier
$ctoEnum :: Int -> FbTier
pred :: FbTier -> FbTier
$cpred :: FbTier -> FbTier
succ :: FbTier -> FbTier
$csucc :: FbTier -> FbTier
Enum, Typeable)

defaultApiVersion :: ApiVersion
defaultApiVersion :: LogSource
defaultApiVersion = LogSource
"v3.2"

-- | Set the Graph API version.
setApiVersion :: (MonadIO m) => ApiVersion -> FacebookT anyAuth m ()
setApiVersion :: LogSource -> FacebookT anyAuth m ()
setApiVersion LogSource
apiVersion = do
  IORef LogSource
ref <- FbData -> IORef LogSource
fbdApiVersion (FbData -> IORef LogSource)
-> FacebookT anyAuth m FbData
-> FacebookT anyAuth m (IORef LogSource)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` ReaderT FbData m FbData -> FacebookT anyAuth m FbData
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F ReaderT FbData m FbData
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
  IORef LogSource
-> (LogSource -> (LogSource, ())) -> FacebookT anyAuth m ()
forall (m :: * -> *) a b.
MonadIO m =>
IORef a -> (a -> (a, b)) -> m b
atomicModifyIORef' IORef LogSource
ref (\LogSource
_ -> (LogSource
apiVersion, ()))
  () -> FacebookT anyAuth m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- | Run a computation in the 'FacebookT' monad transformer with
-- your credentials.
runFacebookT ::
     (MonadIO m)
  => Credentials -- ^ Your app's credentials.
  -> H.Manager -- ^ Connection manager (see 'H.withManager').
  -> FacebookT Auth m a
  -> m a
runFacebookT :: Credentials -> Manager -> FacebookT Auth m a -> m a
runFacebookT Credentials
creds Manager
manager (F ReaderT FbData m a
act) = do
  IORef LogSource
apiref <- LogSource -> m (IORef LogSource)
forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
newIORef LogSource
defaultApiVersion
  ReaderT FbData m a -> FbData -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT FbData m a
act (Maybe Credentials -> Manager -> FbTier -> IORef LogSource -> FbData
FbData (Credentials -> Maybe Credentials
forall a. a -> Maybe a
Just Credentials
creds) Manager
manager FbTier
Production IORef LogSource
apiref)

addAppSecretProof ::
     Credentials
  -> Maybe (AccessToken anykind)
  -> HT.SimpleQuery
  -> HT.SimpleQuery
addAppSecretProof :: Credentials
-> Maybe (AccessToken anykind) -> SimpleQuery -> SimpleQuery
addAppSecretProof (Credentials LogSource
_ LogSource
_ LogSource
_ Bool
False) Maybe (AccessToken anykind)
_ SimpleQuery
query = SimpleQuery
query
addAppSecretProof Credentials
creds Maybe (AccessToken anykind)
mtoken SimpleQuery
query = Credentials -> Maybe (AccessToken anykind) -> SimpleQuery
forall anyKind.
Credentials -> Maybe (AccessToken anyKind) -> SimpleQuery
makeAppSecretProof Credentials
creds Maybe (AccessToken anykind)
mtoken SimpleQuery -> SimpleQuery -> SimpleQuery
forall a. Semigroup a => a -> a -> a
<> SimpleQuery
query

-- | Make an appsecret_proof in case the given credentials access token is a
-- user access token.
-- See: https://developers.facebook.com/docs/graph-api/securing-requests/#appsecret_proof
makeAppSecretProof ::
     Credentials -- ^ App credentials
  -> Maybe (AccessToken anyKind) -- ^
  -> HT.SimpleQuery
makeAppSecretProof :: Credentials -> Maybe (AccessToken anyKind) -> SimpleQuery
makeAppSecretProof Credentials
creds (Just (UserAccessToken UserId
_ LogSource
accessToken UTCTime
_)) =
  [(LogSource -> ByteString
TE.encodeUtf8 LogSource
"appsecret_proof", ByteString
proof)]
  where
    hmacData :: HMAC SHA256
    hmacData :: HMAC SHA256
hmacData = ByteString -> ByteString -> HMAC SHA256
forall key message a.
(ByteArrayAccess key, ByteArrayAccess message, HashAlgorithm a) =>
key -> message -> HMAC a
hmac (Credentials -> ByteString
appSecretBS Credentials
creds) (LogSource -> ByteString
TE.encodeUtf8 LogSource
accessToken)
    proof :: ByteString
proof = Base -> HMAC SHA256 -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base16 HMAC SHA256
hmacData
makeAppSecretProof Credentials
_ Maybe (AccessToken anyKind)
_ = []

-- | Run a computation in the 'FacebookT' monad without
-- credentials.
runNoAuthFacebookT ::
     (MonadIO m)
  => H.Manager -- ^ Connection manager (see 'H.withManager').
  -> FacebookT NoAuth m a
  -> m a
runNoAuthFacebookT :: Manager -> FacebookT NoAuth m a -> m a
runNoAuthFacebookT Manager
manager (F ReaderT FbData m a
act) = do
  IORef LogSource
apiref <- LogSource -> m (IORef LogSource)
forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
newIORef LogSource
defaultApiVersion
  ReaderT FbData m a -> FbData -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT FbData m a
act (Maybe Credentials -> Manager -> FbTier -> IORef LogSource -> FbData
FbData Maybe Credentials
forall a. Maybe a
Nothing Manager
manager FbTier
Production IORef LogSource
apiref)

-- | Same as 'runFacebookT', but uses Facebook's beta tier (see
-- <https://developers.facebook.com/support/beta-tier/>).
beta_runFacebookT ::
     (MonadIO m) => Credentials -> H.Manager -> FacebookT Auth m a -> m a
beta_runFacebookT :: Credentials -> Manager -> FacebookT Auth m a -> m a
beta_runFacebookT Credentials
creds Manager
manager (F ReaderT FbData m a
act) = do
  IORef LogSource
apiref <- LogSource -> m (IORef LogSource)
forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
newIORef LogSource
defaultApiVersion
  ReaderT FbData m a -> FbData -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT FbData m a
act (Maybe Credentials -> Manager -> FbTier -> IORef LogSource -> FbData
FbData (Credentials -> Maybe Credentials
forall a. a -> Maybe a
Just Credentials
creds) Manager
manager FbTier
Beta IORef LogSource
apiref)

-- | Same as 'runNoAuthFacebookT', but uses Facebook's beta tier
-- (see <https://developers.facebook.com/support/beta-tier/>).
beta_runNoAuthFacebookT ::
     (MonadIO m) => H.Manager -> FacebookT NoAuth m a -> m a
beta_runNoAuthFacebookT :: Manager -> FacebookT NoAuth m a -> m a
beta_runNoAuthFacebookT Manager
manager (F ReaderT FbData m a
act) = do
  IORef LogSource
apiref <- LogSource -> m (IORef LogSource)
forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
newIORef LogSource
defaultApiVersion
  ReaderT FbData m a -> FbData -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT FbData m a
act (Maybe Credentials -> Manager -> FbTier -> IORef LogSource -> FbData
FbData Maybe Credentials
forall a. Maybe a
Nothing Manager
manager FbTier
Beta IORef LogSource
apiref)

-- | Get the user's credentials, fail if they are not available.
getCreds :: (Monad m, MonadIO m) => FacebookT Auth m Credentials
getCreds :: FacebookT Auth m Credentials
getCreds = do
  Maybe Credentials
mCreds <- FacebookT Auth m (Maybe Credentials)
forall (m :: * -> *) anyAuth.
Monad m =>
FacebookT anyAuth m (Maybe Credentials)
getMCreds
  case Maybe Credentials
mCreds of
    Maybe Credentials
Nothing -> FacebookException -> FacebookT Auth m Credentials
forall (m :: * -> *) e a. (MonadIO m, Exception e) => e -> m a
E.throwIO (FacebookException -> FacebookT Auth m Credentials)
-> FacebookException -> FacebookT Auth m Credentials
forall a b. (a -> b) -> a -> b
$ LogSource -> FacebookException
FbLibraryException LogSource
"Couldn't get credentials."
    Just Credentials
creds -> Credentials -> FacebookT Auth m Credentials
forall (m :: * -> *) a. Monad m => a -> m a
return Credentials
creds

-- | Get the user's credentials.
getMCreds :: Monad m => FacebookT anyAuth m (Maybe Credentials)
getMCreds :: FacebookT anyAuth m (Maybe Credentials)
getMCreds = FbData -> Maybe Credentials
fbdCreds (FbData -> Maybe Credentials)
-> FacebookT anyAuth m FbData
-> FacebookT anyAuth m (Maybe Credentials)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` ReaderT FbData m FbData -> FacebookT anyAuth m FbData
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F ReaderT FbData m FbData
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask

-- | Get the Graph API version.
getApiVersion :: MonadIO m => FacebookT anyAuth m ApiVersion
getApiVersion :: FacebookT anyAuth m LogSource
getApiVersion = do
  IORef LogSource
ref <- FbData -> IORef LogSource
fbdApiVersion (FbData -> IORef LogSource)
-> FacebookT anyAuth m FbData
-> FacebookT anyAuth m (IORef LogSource)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` ReaderT FbData m FbData -> FacebookT anyAuth m FbData
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F ReaderT FbData m FbData
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
  LogSource
apiVersion <- IORef LogSource -> FacebookT anyAuth m LogSource
forall (m :: * -> *) a. MonadIO m => IORef a -> m a
readIORef IORef LogSource
ref
  LogSource -> FacebookT anyAuth m LogSource
forall (f :: * -> *) a. Applicative f => a -> f a
pure LogSource
apiVersion

-- | Get the 'H.Manager'.
getManager :: Monad m => FacebookT anyAuth m H.Manager
getManager :: FacebookT anyAuth m Manager
getManager = FbData -> Manager
fbdManager (FbData -> Manager)
-> FacebookT anyAuth m FbData -> FacebookT anyAuth m Manager
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` ReaderT FbData m FbData -> FacebookT anyAuth m FbData
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F ReaderT FbData m FbData
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask

-- | Get the 'FbTier'.
getTier :: Monad m => FacebookT anyAuth m FbTier
getTier :: FacebookT anyAuth m FbTier
getTier = FbData -> FbTier
fbdTier (FbData -> FbTier)
-> FacebookT anyAuth m FbData -> FacebookT anyAuth m FbTier
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` ReaderT FbData m FbData -> FacebookT anyAuth m FbData
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F ReaderT FbData m FbData
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask

-- | Run a pure function that depends on the 'FbTier' being used.
withTier :: Monad m => (FbTier -> a) -> FacebookT anyAuth m a
withTier :: (FbTier -> a) -> FacebookT anyAuth m a
withTier = ((FbTier -> a)
 -> FacebookT anyAuth m FbTier -> FacebookT anyAuth m a)
-> FacebookT anyAuth m FbTier
-> (FbTier -> a)
-> FacebookT anyAuth m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip (FbTier -> a)
-> FacebookT anyAuth m FbTier -> FacebookT anyAuth m a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM FacebookT anyAuth m FbTier
forall (m :: * -> *) anyAuth. Monad m => FacebookT anyAuth m FbTier
getTier

-- | Run a 'ResourceT' inside a 'FacebookT'.
runResourceInFb ::
     (R.MonadResource m, MonadUnliftIO m)
  => FacebookT anyAuth (R.ResourceT m) a
  -> FacebookT anyAuth m a
runResourceInFb :: FacebookT anyAuth (ResourceT m) a -> FacebookT anyAuth m a
runResourceInFb (F ReaderT FbData (ResourceT m) a
inner) = ReaderT FbData m a -> FacebookT anyAuth m a
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F (ReaderT FbData m a -> FacebookT anyAuth m a)
-> ReaderT FbData m a -> FacebookT anyAuth m a
forall a b. (a -> b) -> a -> b
$ ReaderT FbData m FbData
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask ReaderT FbData m FbData
-> (FbData -> ReaderT FbData m a) -> ReaderT FbData m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m a -> ReaderT FbData m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ReaderT FbData m a)
-> (FbData -> m a) -> FbData -> ReaderT FbData m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ResourceT m a -> m a
forall (m :: * -> *) a. MonadUnliftIO m => ResourceT m a -> m a
R.runResourceT (ResourceT m a -> m a)
-> (FbData -> ResourceT m a) -> FbData -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReaderT FbData (ResourceT m) a -> FbData -> ResourceT m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT FbData (ResourceT m) a
inner

-- | Transform the computation inside a 'FacebookT'.
mapFacebookT :: (m a -> n b) -> FacebookT anyAuth m a -> FacebookT anyAuth n b
mapFacebookT :: (m a -> n b) -> FacebookT anyAuth m a -> FacebookT anyAuth n b
mapFacebookT m a -> n b
f = ReaderT FbData n b -> FacebookT anyAuth n b
forall auth (m :: * -> *) a.
ReaderT FbData m a -> FacebookT auth m a
F (ReaderT FbData n b -> FacebookT anyAuth n b)
-> (FacebookT anyAuth m a -> ReaderT FbData n b)
-> FacebookT anyAuth m a
-> FacebookT anyAuth n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (m a -> n b) -> ReaderT FbData m a -> ReaderT FbData n b
forall (m :: * -> *) a (n :: * -> *) b r.
(m a -> n b) -> ReaderT r m a -> ReaderT r n b
mapReaderT m a -> n b
f (ReaderT FbData m a -> ReaderT FbData n b)
-> (FacebookT anyAuth m a -> ReaderT FbData m a)
-> FacebookT anyAuth m a
-> ReaderT FbData n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FacebookT anyAuth m a -> ReaderT FbData m a
forall auth (m :: * -> *) a.
FacebookT auth m a -> ReaderT FbData m a
unF