happstack-facebook 0.24 → 0.28
raw patch · 9 files changed
+104/−69 lines, 9 files
Files
- Happstack/Facebook/Application.hs +25/−20
- Happstack/Facebook/Common.hs +16/−16
- Happstack/Facebook/Connect.hs +14/−6
- Happstack/Facebook/FacebookT.hs +20/−17
- Happstack/Facebook/Feed.hs +2/−2
- Happstack/Facebook/Formlets.hs +24/−6
- Happstack/Facebook/Notifications.hs +1/−1
- Happstack/Facebook/XdReceiver.hs +1/−0
- happstack-facebook.cabal +1/−1
Happstack/Facebook/Application.hs view
@@ -12,7 +12,7 @@ import qualified Data.ByteString.Lazy.UTF8 as L import Data.Function (on) import Data.List (isPrefixOf, sortBy)-import Data.Maybe (fromJust)+import Data.Maybe (fromJust, mapMaybe) import Data.Time.Clock.POSIX (POSIXTime) import Happstack.Crypto.MD5 (md5, stringMD5) import Happstack.Facebook.Common@@ -20,7 +20,7 @@ import qualified Network.HTTP as HTTP import Network.Browser (Form(..),formToRequest, request, browse) import Network.URI-import Happstack.Server (Method(POST, GET), ServerMonad, withDataFn, lookPairs)+import Happstack.Server (Method(POST, GET), ServerMonad, HasRqData, withDataFn, lookPairs) -- |This data type holds all the informaton that facebook pass along with the request -- http://wiki.developers.facebook.com/index.php/Your_callback_page_and_you@@ -137,6 +137,7 @@ let lookupString k = case lookup k pairs of Nothing -> error ("Could not find required field " ++ k) (Just v) -> v+ read' :: (Show a, Read a) => String -> a read' str = case reads str of [(a,[])] -> a r -> error ("Failed to read " ++ str ++ " got " ++ show r)@@ -194,14 +195,17 @@ }) -- todo: add code to validate the sent fb_sig-withFacebookData :: (Monad m, MonadPlus m, ServerMonad m) => FacebookConfig -> (FacebookData -> m r) -> m r+withFacebookData :: (Functor m, Monad m, MonadPlus m, ServerMonad m, HasRqData m, MonadIO m) => FacebookConfig -> (FacebookData -> m r) -> m r withFacebookData config f = withDataFn (do pairs <- lookPairs- return $ parseFacebookData config pairs)+ let pairs' = mapMaybe (\(k,v) -> case v of+ (Left e) -> Nothing+ (Right c) -> Just (k,c)) pairs+ return $ parseFacebookData config pairs') f -withFacebook :: (Monad m, MonadPlus m, ServerMonad m) => FacebookConfig -> FacebookT (FacebookState FacebookData) m a -> m a+withFacebook :: (Functor m, Monad m, MonadPlus m, ServerMonad m, MonadIO m, HasRqData m) => FacebookConfig -> FacebookT (FacebookState FacebookData) m a -> m a withFacebook config sp = withFacebookData config $ \fbd -> withFacebook' config fbd sp withUserSP :: ( HasFacebookConfig (FacebookT (s d) m)@@ -235,6 +239,7 @@ , HasFacebookData FacebookData (FacebookT (s d) m) , HasFacebookData FacebookData (FacebookT (FacebookStateU d) m) , MonadPlus m+ , Functor m ) => FacebookT (FacebookStateS d) m a -> FacebookT (s d) m a withSessionSP handler =@@ -252,7 +257,7 @@ {--withFacebook' :: (Monad m) => FacebookConfig -> FacebookData -> ServerPartT (FacebookT FacebookState m) a -> ServerPartT m a+withFacebook' :: (Functor m, Monad m) => FacebookConfig -> FacebookData -> ServerPartT (FacebookT FacebookState m) a -> ServerPartT m a withFacebook' config facebookData sp = mapServerPartT doFacebook sp where@@ -292,20 +297,20 @@ return $ parseResponse (Proxy :: Proxy (m method)) res -} {--class (Monad m) => HasFacebookData FacebookData m where+class (Functor m, Monad m) => HasFacebookData FacebookData m where askFacebookData :: m FacebookData -class (Monad m) => HasUser m where+class (Functor m, Monad m) => HasUser m where askUser :: m User -class (Monad m) => HasSessionKey m where+class (Functor m, Monad m) => HasSessionKey m where askSessionKey :: m SessionKey -} {- -class (Monad m) => HasFacebookConfig m where+class (Functor m, Monad m) => HasFacebookConfig m where askFacebookConfig :: m FacebookConfig -}-}@@ -344,7 +349,7 @@ {- -class (Monad m) => HasFacebookData m where+class (Functor m, Monad m) => HasFacebookData m where askFacebookData :: m FacebookData -- |the State that lives in the facebook monad@@ -353,10 +358,10 @@ , fbData :: FacebookData -- user specific information that facebook provides } -instance (Monad m) => HasFacebookConfig (FacebookT FacebookState m) where+instance (Functor m, Monad m) => HasFacebookConfig (FacebookT FacebookState m) where askFacebookConfig = fbConfig <$> ask -instance (Monad m) => HasFacebookData (FacebookT FacebookState m) where+instance (Functor m, Monad m) => HasFacebookData (FacebookT FacebookState m) where askFacebookData = fbData <$> ask data FacebookStateU @@ -365,13 +370,13 @@ , fbuUser :: User } -instance (Monad m) => HasFacebookConfig (FacebookT FacebookStateU m) where+instance (Functor m, Monad m) => HasFacebookConfig (FacebookT FacebookStateU m) where askFacebookConfig = fbuConfig <$> ask -instance (Monad m) => HasFacebookData (FacebookT FacebookStateU m) where+instance (Functor m, Monad m) => HasFacebookData (FacebookT FacebookStateU m) where askFacebookData = fbuData <$> ask -instance (Monad m) => HasUser (FacebookT FacebookStateU m) where+instance (Functor m, Monad m) => HasUser (FacebookT FacebookStateU m) where askUser = fbuUser <$> ask withUser :: (HasFacebookConfig n, HasFacebookData n) => FacebookT FacebookStateU m a -> n (Maybe (m a))@@ -393,16 +398,16 @@ , fbsSessionKey :: SessionKey } -instance (Monad m) => HasFacebookConfig (FacebookT FacebookStateS m) where+instance (Functor m, Monad m) => HasFacebookConfig (FacebookT FacebookStateS m) where askFacebookConfig = fbsConfig <$> ask -instance (Monad m) => HasFacebookData (FacebookT FacebookStateS m) where+instance (Functor m, Monad m) => HasFacebookData (FacebookT FacebookStateS m) where askFacebookData = fbsData <$> ask -instance (Monad m) => HasUser (FacebookT FacebookStateS m) where+instance (Functor m, Monad m) => HasUser (FacebookT FacebookStateS m) where askUser = fbsUser <$> ask -instance (Monad m) => HasSessionKey (FacebookT FacebookStateS m) where+instance (Functor m, Monad m) => HasSessionKey (FacebookT FacebookStateS m) where askSessionKey = fbsSessionKey <$> ask withSession :: (HasUser n, HasFacebookConfig n, HasFacebookData n) => FacebookT FacebookStateS m a -> n (Maybe (m a))
Happstack/Facebook/Common.hs view
@@ -25,7 +25,7 @@ import Happstack.Data (Default(..), Version(..),deriveAll, deriveNewData, deriveSerialize) import Happstack.Facebook.FacebookT import Happstack.State (Proxy(..))-import Happstack.Server -- (Method(..))+import Happstack.Server import HSP (XML,XMLMetaData) import HSX.XMLGenerator(XMLGenT(..)) import Network.Browser (Form(..),formToRequest, request, browse)@@ -100,21 +100,21 @@ data SessionRequired = SessionRequired data None = None -class (Monad m) => FacebookMethod m method where+class (Functor m, Monad m) => FacebookMethod m method where type FacebookResponse method toParams :: method -> m Parameters parseResponse :: Proxy (m method) -> String -> Either String (FacebookResponse method) -class (Monad m) => HasFacebookConfig m where+class (Functor m, Monad m) => HasFacebookConfig m where askFacebookConfig :: m FacebookConfig -class (Monad m) => HasUser m where+class (Functor m, Monad m) => HasUser m where askUser :: m User -class (Monad m) => HasSessionKey m where+class (Functor m, Monad m) => HasSessionKey m where askSessionKey :: m SessionKey -class (Monad m) => HasFacebookData d m where+class (Functor m, Monad m) => HasFacebookData d m where askFacebookData :: m d -- |the State that lives in the facebook monad@@ -123,10 +123,10 @@ , fbData :: d -- user specific information that facebook provides } -instance (Monad m) => HasFacebookConfig (FacebookT (FacebookState d) m) where+instance (Functor m, Monad m) => HasFacebookConfig (FacebookT (FacebookState d) m) where askFacebookConfig = fbConfig <$> askFacebookState -instance (Monad m) => HasFacebookData d (FacebookT (FacebookState d) m) where+instance (Functor m, Monad m) => HasFacebookData d (FacebookT (FacebookState d) m) where askFacebookData = fbData <$> askFacebookState data FacebookStateU d@@ -135,13 +135,13 @@ , fbuUser :: User } -instance (Monad m) => HasFacebookConfig (FacebookT (FacebookStateU d) m) where+instance (Functor m, Monad m) => HasFacebookConfig (FacebookT (FacebookStateU d) m) where askFacebookConfig = fbuConfig <$> askFacebookState -instance (Monad m) => HasFacebookData d (FacebookT (FacebookStateU d) m) where+instance (Functor m, Monad m) => HasFacebookData d (FacebookT (FacebookStateU d) m) where askFacebookData = fbuData <$> askFacebookState -instance (Monad m) => HasUser (FacebookT (FacebookStateU d) m) where+instance (Functor m, Monad m) => HasUser (FacebookT (FacebookStateU d) m) where askUser = fbuUser <$> askFacebookState data FacebookStateS d@@ -152,16 +152,16 @@ } -instance (Monad m) => HasFacebookConfig (FacebookT (FacebookStateS d) m) where+instance (Functor m, Monad m) => HasFacebookConfig (FacebookT (FacebookStateS d) m) where askFacebookConfig = fbsConfig <$> askFacebookState -instance (Monad m) => HasFacebookData d (FacebookT (FacebookStateS d) m) where+instance (Functor m, Monad m) => HasFacebookData d (FacebookT (FacebookStateS d) m) where askFacebookData = fbsData <$> askFacebookState -instance (Monad m) => HasUser (FacebookT (FacebookStateS d) m) where+instance (Functor m, Monad m) => HasUser (FacebookT (FacebookStateS d) m) where askUser = fbsUser <$> askFacebookState -instance (Monad m) => HasSessionKey (FacebookT (FacebookStateS d) m) where+instance (Functor m, Monad m) => HasSessionKey (FacebookT (FacebookStateS d) m) where askSessionKey = fbsSessionKey <$> askFacebookState @@ -395,7 +395,7 @@ toContentType _ = P.pack "text/html; charset=utf-8" toMessage (_,FbXML xml) = L.fromString (renderAsFBML xml) -withFacebook' :: (Monad m) => FacebookConfig -> d -> FacebookT (FacebookState d) m a -> m a+withFacebook' :: (Functor m, Monad m) => FacebookConfig -> d -> FacebookT (FacebookState d) m a -> m a withFacebook' config facebookData m = runReaderT (unFacebookT m) (FacebookState config facebookData) -- |function to read some FacebookConnectData from the Facebook environment
Happstack/Facebook/Connect.hs view
@@ -4,6 +4,7 @@ import Control.Applicative ((<$>)) import Control.Monad(MonadPlus(mzero)) import Control.Monad.Reader (ask, asks, runReaderT)+import Control.Monad.Trans (MonadIO(..)) import qualified Data.ByteString.Lazy.Char8 as L import qualified Data.ByteString.Lazy.UTF8 as L import Data.Char (toLower)@@ -65,9 +66,12 @@ sig' = Just $ stringMD5 (md5 (L.pack (dataStr++(unAppSecret secret)))) withFacebookConnectData :: - ( Monad m+ ( Functor m+ , Monad m , MonadPlus m , ServerMonad m+ , HasRqData m+ , MonadIO m ) => FacebookConfig -> (FacebookConnectData -> m r) -> m r withFacebookConnectData config f = withDataFn buildFBCData f@@ -78,7 +82,7 @@ readTime str = realToFrac (read' str :: Double) lookupString :: String -> RqData (Maybe String) lookupString k = do- cookies <- asks snd+ (_, _, cookies) <- ask return $ fmap cookieValue $ lookup (map toLower (unApiKey (apiKey config) ++k)) cookies buildFBCData :: RqData FacebookConnectData buildFBCData = do@@ -87,7 +91,7 @@ ss <- lookupString "_ss" sig <- lookupString "" user <- lookupString "_user"- cookies <- asks snd+ (_, _, cookies) <- ask let fbcCookies = map (\(k,v) -> (drop ((length (unApiKey (apiKey config)))+1) k, v)) $ filter (isPrefixOf ((unApiKey (apiKey config))++"_") . fst) cookies return $ FacebookConnectData { _fbc_cookies = fbcCookies@@ -100,9 +104,12 @@ } withFacebookConnect :: - ( Monad m+ ( Functor m+ , Monad m , MonadPlus m , ServerMonad m+ , HasRqData m+ , MonadIO m ) => FacebookConfig -> FacebookT (FacebookState FacebookConnectData) m a -> m a withFacebookConnect config sp = withFacebookConnectData config $ \fbd -> withFacebook' config fbd sp @@ -124,6 +131,7 @@ , HasFacebookData FacebookConnectData (FacebookT (s d) m) , HasFacebookData FacebookConnectData (FacebookT (FacebookStateU d) m) , MonadPlus m+ , Functor m ) => FacebookT (FacebookStateS d) m a -> FacebookT (s d) m a withSessionSP handler =@@ -139,13 +147,13 @@ withSession sessionKey handler -- |clear the facebook connect cookies effectively logging the user out-fbcLogout :: (HasFacebookData FacebookConnectData m, HasFacebookConfig m, FilterMonad Response m) => m ()+fbcLogout :: (HasFacebookData FacebookConnectData m, HasFacebookConfig m, FilterMonad Response m, MonadIO m) => m () fbcLogout = do cookies <- fb_sig_cookies config <- askFacebookConfig let clear c = do let key = unApiKey (apiKey config) ++"_"++ c cookie = (mkCookie key "0")- addCookie 0 cookie+ addCookie Expired cookie mapM (clear . fst) cookies return ()
Happstack/Facebook/FacebookT.hs view
@@ -25,7 +25,7 @@ type FacebookTState m askFacebookState :: m (FacebookTState m) -instance (Monad m) => MonadFacebook (FacebookT s m) where+instance (Functor m, Monad m) => MonadFacebook (FacebookT s m) where type FacebookTState (FacebookT s m) = s askFacebookState = FacebookT ask @@ -39,11 +39,14 @@ mapFacebookT :: (m a -> n b) -> FacebookT s m a -> FacebookT s n b mapFacebookT f (FacebookT (ReaderT m)) = FacebookT $ ReaderT $ \s -> f (m s) -instance (Monad m) => Applicative (FacebookT s m) where+liftFacebookT :: m a -> FacebookT s m a+liftFacebookT m = FacebookT (ReaderT (const m))++instance (Functor m, Monad m) => Applicative (FacebookT s m) where pure = FacebookT . return (FacebookT m) <*> (FacebookT n) = FacebookT (m `ap` n) -instance (MonadPlus m) => Alternative (FacebookT s m) where+instance (Functor m, MonadPlus m) => Alternative (FacebookT s m) where empty = unwrapMonad empty f <|> g = unwrapMonad $ (WrapMonad f) <|> (WrapMonad g) @@ -76,7 +79,7 @@ type URL (FacebookT s m) = URL m showURLParams u params = FacebookT $ ReaderT $ const (showURLParams u params) -instance (Monad m) => HSX.XMLGen (FacebookT s m) where+instance (Functor m, Monad m) => HSX.XMLGen (FacebookT s m) where type HSX.XML (FacebookT s m) = XML newtype HSX.Child (FacebookT s m) = FChild { unFChild :: XML } newtype HSX.Attribute (FacebookT s m) = FAttr { unFAttr :: Attribute }@@ -111,23 +114,23 @@ instance (Monad m, Functor m) => IsAttrValue (FacebookT s m) TL.Text where toAttrValue = toAttrValue . TL.unpack -instance (Monad m) => HSX.EmbedAsAttr (FacebookT s m) Attribute where+instance (Monad m, Functor m) => HSX.EmbedAsAttr (FacebookT s m) Attribute where asAttr = return . (:[]) . FAttr -instance (Monad m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String Char) where+instance (Monad m, Functor m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String Char) where asAttr (n := c) = asAttr (n := [c]) -instance (Monad m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String String) where+instance (Monad m, Functor m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String String) where asAttr (n := str) = asAttr $ MkAttr (toName n, pAttrVal str) -instance (Monad m) => HSX.EmbedAsAttr (FacebookT s m) (Attr (String, String) String) where+instance (Monad m, Functor m) => HSX.EmbedAsAttr (FacebookT s m) (Attr (String, String) String) where asAttr (n := str) = asAttr $ MkAttr (toName n, pAttrVal str) -instance (Monad m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String Bool) where+instance (Monad m, Functor m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String Bool) where asAttr (n := True) = asAttr $ MkAttr (toName n, pAttrVal "true") asAttr (n := False) = asAttr $ MkAttr (toName n, pAttrVal "false") -instance (Monad m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String Int) where+instance (Monad m, Functor m) => HSX.EmbedAsAttr (FacebookT s m) (Attr String Int) where asAttr (n := i) = asAttr $ MkAttr (toName n, pAttrVal (show i)) instance (Monad m, Functor m, IsName n) => (EmbedAsAttr (FacebookT s m) (Attr n TL.Text)) where@@ -136,10 +139,10 @@ instance (Monad m, Functor m, IsName n) => (EmbedAsAttr (FacebookT s m) (Attr n T.Text)) where asAttr (n := a) = asAttr $ MkAttr (toName n, pAttrVal $ T.unpack a) -instance (Monad m) => EmbedAsChild (FacebookT s m) Char where+instance (Monad m, Functor m) => EmbedAsChild (FacebookT s m) Char where asChild = XMLGenT . return . (:[]) . FChild . pcdata . (:[]) -instance (Monad m) => EmbedAsChild (FacebookT s m) String where+instance (Monad m, Functor m) => EmbedAsChild (FacebookT s m) String where asChild = XMLGenT . return . (:[]) . FChild . pcdata instance (Monad m, Functor m) => (EmbedAsChild (FacebookT s m) TL.Text) where@@ -148,27 +151,27 @@ instance (Monad m, Functor m) => (EmbedAsChild (FacebookT s m) T.Text) where asChild = asChild . T.unpack -instance (Monad m) => EmbedAsChild (FacebookT s m) XML where+instance (Monad m, Functor m) => EmbedAsChild (FacebookT s m) XML where asChild = XMLGenT . return . (:[]) . FChild -instance (Monad m) => EmbedAsChild (FacebookT s m) () where+instance (Monad m, Functor m) => EmbedAsChild (FacebookT s m) () where asChild () = return [] -instance (Monad m) => AppendChild (FacebookT s m) XML where+instance (Monad m, Functor m) => AppendChild (FacebookT s m) XML where appAll xml children = do chs <- children case xml of CDATA _ _ -> return xml Element n as cs -> return $ Element n as (cs ++ (map unFChild chs)) -instance (Monad m) => SetAttr (FacebookT s m) XML where+instance (Monad m, Functor m) => SetAttr (FacebookT s m) XML where setAll xml hats = do attrs <- hats case xml of CDATA _ _ -> return xml Element n as cs -> return $ Element n (foldr (:) as (map unFAttr attrs)) cs -instance (Monad m) => XMLGenerator (FacebookT s m)+instance (Monad m, Functor m) => XMLGenerator (FacebookT s m) ------------------------------------------------------------------
Happstack/Facebook/Feed.hs view
@@ -42,7 +42,7 @@ = DeactivateTemplateBundleById BundleId deriving (Data, Typeable, Read, Show, Eq, Ord, Ix) -instance (Monad m) => FacebookMethod m DeactivateTemplateBundleById where+instance (Functor m, Monad m) => FacebookMethod m DeactivateTemplateBundleById where type FacebookResponse DeactivateTemplateBundleById = Bool parseResponse _ = parseResponseBool toParams (DeactivateTemplateBundleById (BundleId bid)) =@@ -115,7 +115,7 @@ = RegisterTemplateBundle TemplateBundle deriving (Eq, Ord, Read, Show, Typeable, Data) -instance (Monad m) => FacebookMethod m RegisterTemplateBundle where+instance (Functor m, Monad m) => FacebookMethod m RegisterTemplateBundle where type FacebookResponse RegisterTemplateBundle = BundleId parseResponse _ str = case fromJsonString (undefined :: Integer) str of
Happstack/Facebook/Formlets.hs view
@@ -10,26 +10,28 @@ import Control.Applicative.Error import Control.Monad import Control.Monad.Trans-import Happstack.Server.Extra () -- ServerMonad (XMLGenT m)--- import Happstack.Server.HSX -- ServerMonad (XMLGenT m)+import qualified Data.ByteString.Lazy.UTF8 as LU (toString, fromString)+import Data.Maybe (fromMaybe)+-- import Happstack.Server.Extra () -- ServerMonad (XMLGenT m)+import Happstack.Server.HSX () -- ServerMonad (XMLGenT m) import Happstack.Facebook.Common(FbXML(..)) import HSP import HSP.Formlets import qualified HSX.XMLGenerator as HSX import Happstack.Server as Happstack-import Text.Formlets+import Text.Formlets as F -- ^ turn a formlet into XML+ServerPartT which can be embedded in a larger document formletPart ::- (EmbedAsChild m xml, EmbedAsAttr m (Attr String String), MonadIO m, Functor m, ToMessage b, FilterMonad Response m, WebMonad Response m, MonadPlus m, ServerMonad m) + (EmbedAsChild m xml, EmbedAsAttr m (Attr String String), MonadIO m, Functor m, ToMessage b, FilterMonad Response m, WebMonad Response m, MonadPlus m, ServerMonad m, HasRqData m) => String -- ^ url to POST form results to -> (a -> XMLGenT m b) -- ^ handler used when form validates -> ([ErrorMsg] -> [XMLGenT m (HSX.XML m)] -> XMLGenT m b) -- ^ handler used when form does not validate -> Form xml IO a -- ^ the formlet -> XMLGenT m (HSX.XML m) formletPart action handleSuccess handleFailure form = - withDataFn lookPairs $ \env ->- let (collector, formXML,_) = runFormState (map (second Left) env) form+ withDataFn lookEnv $ \env ->+ let (collector, formXML,_) = runFormState env form in msum [ dir "submit" $ methodSP POST $ XMLGenT $ Happstack.escape . fmap toResponse $ unXMLGenT $ do res <- liftIO collector@@ -43,3 +45,19 @@ <% formXML %> </form> ]++lookEnv :: RqData Env+lookEnv =+ do (query,body,_) <- askRqEnv+ return $ map (\(name, value) ->+ case inputValue value of+ (Left fileContentsPath) ->+ (name, Right $ (File { content = LU.fromString $ fileContentsPath -- this is not really correct, it is expecting the contents of the file not the path to the saved contents. Though perhaps this is better+ , fileName = fromMaybe "" (inputFilename value)+ , F.contentType = F.ContentType { F.ctType = Happstack.ctType (inputContentType value)+ , F.ctSubtype = Happstack.ctSubtype (inputContentType value)+ , F.ctParameters = Happstack.ctParameters (inputContentType value)+ }+ }))+ (Right contents) ->+ (name, Left $ LU.toString contents)) (query ++ body)
Happstack/Facebook/Notifications.hs view
@@ -58,7 +58,7 @@ } deriving (Eq, Ord, Read, Show, Data, Typeable) -instance (Monad m) => FacebookMethod m SendNS where+instance (Functor m, Monad m) => FacebookMethod m SendNS where type FacebookResponse SendNS = [User] parseResponse _ jstr = case fromJsonString [] jstr of
Happstack/Facebook/XdReceiver.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS_GHC -F -pgmFtrhsx #-} module Happstack.Facebook.XdReceiver where
happstack-facebook.cabal view
@@ -1,5 +1,5 @@ Name: happstack-facebook-Version: 0.24+Version: 0.28 License: BSD3 License-file: debian/copyright Author: jeremy@seereason.com