module Facebook.Graph
( getObject
, postObject
, deleteObject
, searchObjects
, ( #= )
, SimpleType(..)
, Place(..)
, Location(..)
, GeoCoordinates(..)
, Tag(..)
) where
#if __GLASGOW_HASKELL__ <= 784
import Control.Applicative
#endif
import Control.Monad (mzero)
import Data.ByteString.Char8 (ByteString)
import Data.Int (Int8, Int16, Int32, Int64)
import Data.List (intersperse)
import Data.Text (Text)
import Data.Typeable (Typeable)
import Data.Word (Word, Word8, Word16, Word32, Word64)
#if MIN_VERSION_time(1,5,0)
import Data.Time (defaultTimeLocale)
#else
import System.Locale (defaultTimeLocale)
#endif
import qualified Control.Monad.Trans.Resource as R
import qualified Data.Aeson as A
#if MIN_VERSION_aeson(1,0,0)
import Data.Aeson.Text (encodeToTextBuilder)
#else
import Data.Aeson.Encode (encodeToTextBuilder)
#endif
import qualified Data.ByteString.Char8 as B
import qualified Data.Text.Encoding as TE
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as TLB
import qualified Data.Time as TI
import qualified Network.HTTP.Conduit as H
import qualified Network.HTTP.Types as HT
import Facebook.Auth
import Facebook.Base
import Facebook.Monad
import Facebook.Types
import Facebook.Pager
getObject
:: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m, A.FromJSON a)
=> Text
-> [Argument]
-> Maybe (AccessToken anyKind)
-> FacebookT anyAuth m a
getObject path query mtoken =
runResourceInFb $ asJson =<< fbhttp =<< fbreq path mtoken query
postObject
:: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m, A.FromJSON a)
=> Text
-> [Argument]
-> AccessToken anyKind
-> FacebookT Auth m a
postObject = methodObject HT.methodPost
deleteObject
:: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m, A.FromJSON a)
=> Text
-> [Argument]
-> AccessToken anyKind
-> FacebookT Auth m a
deleteObject = methodObject HT.methodDelete
methodObject
:: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m, A.FromJSON a)
=> HT.Method
-> Text
-> [Argument]
-> AccessToken anyKind
-> FacebookT Auth m a
methodObject method path query token =
runResourceInFb $
do req <- fbreq path (Just token) query
asJson =<<
fbhttp
req
{ H.method = method
}
searchObjects
:: (R.MonadResource m, R.MonadUnliftIO m, R.MonadThrow m, A.FromJSON a)
=> Text
-> Text
-> [Argument]
-> Maybe UserAccessToken
-> FacebookT anyAuth m (Pager a)
searchObjects objectType keyword query = getObject "/search" query'
where
query' = ("q" #= keyword) : ("type" #= objectType) : query
( #= )
:: SimpleType a
=> ByteString -> a -> Argument
p #= v = (p, encodeFbParam v)
class SimpleType a where
encodeFbParam :: a -> B.ByteString
instance SimpleType Bool where
encodeFbParam b =
if b
then "1"
else "0"
instance SimpleType TI.Day where
encodeFbParam = B.pack . TI.formatTime defaultTimeLocale "%Y-%m-%d"
instance SimpleType TI.UTCTime where
encodeFbParam = B.pack . TI.formatTime defaultTimeLocale "%Y%m%dT%H%MZ"
instance SimpleType TI.ZonedTime where
encodeFbParam = encodeFbParam . TI.zonedTimeToUTC
instance SimpleType Float where
encodeFbParam = showBS
instance SimpleType Double where
encodeFbParam = showBS
instance SimpleType Int where
encodeFbParam = showBS
instance SimpleType Word where
encodeFbParam = showBS
instance SimpleType Int8 where
encodeFbParam = showBS
instance SimpleType Word8 where
encodeFbParam = showBS
instance SimpleType Int16 where
encodeFbParam = showBS
instance SimpleType Word16 where
encodeFbParam = showBS
instance SimpleType Int32 where
encodeFbParam = showBS
instance SimpleType Word32 where
encodeFbParam = showBS
instance SimpleType Int64 where
encodeFbParam = showBS
instance SimpleType Word64 where
encodeFbParam = showBS
instance SimpleType Text where
encodeFbParam = TE.encodeUtf8
instance SimpleType ByteString where
encodeFbParam = id
instance SimpleType Id where
encodeFbParam = TE.encodeUtf8 . idCode
instance SimpleType Permission where
encodeFbParam = encodeFbParam . unPermission
instance SimpleType a =>
SimpleType [a] where
encodeFbParam = B.concat . intersperse "," . map encodeFbParam
showBS
:: Show a
=> a -> B.ByteString
showBS = B.pack . show
data Place = Place
{ placeId :: Id
, placeName :: Maybe Text
, placeLocation :: Maybe Location
} deriving (Eq, Ord, Show, Read, Typeable)
instance A.FromJSON Place where
parseJSON (A.Object v) =
Place <$> v A..: "id" <*> v A..:? "name" <*> v A..:? "location"
parseJSON _ = mzero
data Location = Location
{ locationStreet :: Maybe Text
, locationCity :: Maybe Text
, locationState :: Maybe Text
, locationCountry :: Maybe Text
, locationZip :: Maybe Text
, locationCoords :: Maybe GeoCoordinates
} deriving (Eq, Ord, Show, Read, Typeable)
instance A.FromJSON Location where
parseJSON obj@(A.Object v) =
Location <$> v A..:? "street" <*> v A..:? "city" <*> v A..:? "state" <*>
v A..:? "country" <*>
v A..:? "zip" <*>
A.parseJSON obj
parseJSON _ = mzero
data GeoCoordinates = GeoCoordinates
{ latitude :: !Double
, longitude :: !Double
} deriving (Eq, Ord, Show, Read, Typeable)
instance A.FromJSON GeoCoordinates where
parseJSON (A.Object v) =
GeoCoordinates <$> v A..: "latitude" <*> v A..: "longitude"
parseJSON _ = mzero
instance SimpleType GeoCoordinates where
encodeFbParam c =
let obj =
A.object ["latitude" A..= latitude c, "longitude" A..= longitude c]
toBS = TE.encodeUtf8 . TL.toStrict . TLB.toLazyText . encodeToTextBuilder
in toBS obj
data Tag = Tag
{ tagId :: Id
, tagName :: Text
} deriving (Eq, Ord, Show, Read, Typeable)
instance A.FromJSON Tag where
parseJSON (A.Object v) = Tag <$> v A..: "id" <*> v A..: "name"
parseJSON _ = mzero