packages feed

hyperpublic (empty) → 0.0.0

raw patch · 7 files changed

+277/−0 lines, 7 filesdep +aesondep +attoparsecdep +basesetup-changed

Dependencies added: aeson, attoparsec, base, bytestring, http-enumerator, http-types

Files

+ Examples.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE OverloadedStrings #-}++module Main where++import Data.Aeson+import Data.ByteString.Char8 ()+import qualified Data.Map as M+import Data.Maybe+import Data.Text+import qualified Data.Vector as V++import Web.Hyperpublic+import qualified Web.Hyperpublic.Places as Places+import qualified Web.Hyperpublic.Offers as Offers++-- Sequence the two examples.+main :: IO ()+main = placeNamesNearHq >> offerDescr++-- Find places near Hyperpublic HQ and print the name of each.+placeNamesNearHq :: IO ()+placeNamesNearHq =+    let json = Places.find auth [( "address"+                                 , "416 W 13th St, New York, NY 10014" )]+    in json >>= putStrLn . show . getNames+  where+    getNames (Array arr) = mapMaybe getName $ V.toList arr+    getName (Object obj) = getTextField obj "display_name"++-- Find the offer with id 4e90567c297a200001008db9 and print its description.+offerDescr :: IO ()+offerDescr =+    let json = Offers.show auth "4e90567c297a200001008db9"+    in json >>= putStrLn . show . getDescr+  where+    getDescr (Object obj) = maybe "" id $ getTextField obj "description"++-- Create an authorization record. Get your own credentials at+-- http://www.hyperpublic.com/registerapi+auth :: HpAuth+auth = HpAuth { clientId = "8UufhI6bCKQXKMBn7AUWO67Yq6C8RkfD0BGouTke"+              , clientSecret = "zdoROY5XRN0clIWsEJyKzHedSK4irYee8jpnOXaP" }++-- Extract a text field from an 'Data.Aeson.Object'.+getTextField :: Object -> Text -> Maybe Text+getTextField obj txt = M.lookup txt obj >>= resultToMaybe . fromJSON+  where+    resultToMaybe (Success a) = Just a+    resultToMaybe (Error _) = Nothing
+ README.md view
@@ -0,0 +1,3 @@+A thin Haskell wrapper for the [Hyperpublic](http://hyperpublic.com/) API. See+the documentation on the+[Hackage page](http://hackage.haskell.org/package/hyperpublic).
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Web/Hyperpublic.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK prune #-}++-- | A thin wrapper for the Hyperpublic API, which uses+-- "Network.HTTP.Enumerator" to fetch results and "Data.Aeson" to return them+-- as JSON. The "Web.Hyperpublic.Places" and "Web.Hyperpublic.Offers" modules+-- wrap @find@ and @show@ methods of the Places++-- (<http://www.hyperpublic.com/placesplus>) and Geo Deals and Events+-- (<http://www.hyperpublic.com/deals>) endpoints, respectively. The next+-- release of this package will also wrap the @create@ method of Places+. Full+-- API documentation can be found at <http://developer.hyperpublic.com/>.+--+-- "Web.Hyperpublic.Places" and "Web.Hyperpublic.Offers" export the functions+-- @find@ and @show@, where each works similarly across the two modules. The+-- next release of this package will also wrap the @create@ method of Places+.+--+-- Examples (included in the distribution as @Examples.hs@):+--+-- >{-# LANGUAGE OverloadedStrings #-}+-- >+-- >module Main where+-- >+-- >import Data.Aeson+-- >import Data.ByteString.Char8 ()+-- >import qualified Data.Map as M+-- >import Data.Maybe+-- >import Data.Text+-- >import qualified Data.Vector as V+-- >+-- >import Web.Hyperpublic+-- >import qualified Web.Hyperpublic.Places as Places+-- >import qualified Web.Hyperpublic.Offers as Offers+-- >+-- >-- Sequence the two examples.+-- >main :: IO ()+-- >main = placeNamesNearHq >> offerDescr+-- >+-- >-- Find places near Hyperpublic HQ and print the name of each.+-- >placeNamesNearHq :: IO ()+-- >placeNamesNearHq =+-- >    let json = Places.find auth [( "address"+-- >                                 , "416 W 13th St, New York, NY 10014" )]+-- >    in json >>= putStrLn . show . getNames+-- >  where+-- >    getNames (Array arr) = mapMaybe getName $ V.toList arr+-- >    getName (Object obj) = getTextField obj "display_name"+-- >+-- >-- Find the offer with id 4e90567c297a200001008db9 and print its description.+-- >offerDescr :: IO ()+-- >offerDescr =+-- >    let json = Offers.show auth "4e90567c297a200001008db9"+-- >    in json >>= putStrLn . show . getDescr+-- >  where+-- >    getDescr (Object obj) = maybe "" id $ getTextField obj "description"+-- >+-- >-- Create an authorization record. Get your own credentials at+-- >-- http://www.hyperpublic.com/registerapi+-- >auth :: HpAuth+-- >auth = HpAuth { clientId = "8UufhI6bCKQXKMBn7AUWO67Yq6C8RkfD0BGouTke"+-- >              , clientSecret = "zdoROY5XRN0clIWsEJyKzHedSK4irYee8jpnOXaP" }+-- >+-- >-- Extract a text field from an 'Data.Aeson.Object'.+-- >getTextField :: Object -> Text -> Maybe Text+-- >getTextField obj txt = M.lookup txt obj >>= resultToMaybe . fromJSON+-- >  where+-- >    resultToMaybe (Success a) = Just a+-- >    resultToMaybe (Error _) = Nothing+module Web.Hyperpublic+( HpAuth (..)+, callApi+) where++import Data.Aeson ( Value+                  , json )+import Data.Attoparsec ( eitherResult+                       , parse )+import Data.ByteString ( ByteString+                       , append )+import Data.ByteString.Char8 ( unpack )+import qualified Data.ByteString.Lazy as Lazy++import Network.HTTP.Enumerator ( Request (..)+                               , Response (..)+                               , def+                               , httpLbsRedirect+                               , withManager )+import Network.HTTP.Types ( SimpleQuery+                          , simpleQueryToQuery )+++callApi :: HpAuth -> ByteString -> SimpleQuery -> IO Value+callApi auth urlPath query = do+    let query' = [ ("client_id", clientId auth)+                 , ("client_secret", clientSecret auth) ] +++                 filter cleanQuery query+    rsp <- withManager (httpLbsRedirect $ request urlPath query')+    eitherToIO $ Right rsp >>= readResponse >>= eitherResult . parse json+  where+    cleanQuery (k, _) = k /= "client_id" && k /= "client_secret"++-- | A record for passing around API authorization credentials.+data HpAuth = HpAuth+    { clientId :: ByteString+    , clientSecret :: ByteString+    } deriving (Show)+++request :: ByteString -> SimpleQuery -> Request m+request urlPath query = def+    { host = "api.hyperpublic.com"+    , path = "/api/v1" `append` urlPath+    , queryString = simpleQueryToQuery query+    , port = 443+    , secure = True }++readResponse :: Response -> Either String ByteString+readResponse rsp =+    let strictBody = foldr1 append $ Lazy.toChunks $ responseBody rsp+    in if statusCode rsp == 200+      then Right strictBody+      else Left $ unpack strictBody++eitherToIO :: Either String a -> IO a+eitherToIO (Right a) = return a+eitherToIO (Left str) = fail str
+ Web/Hyperpublic/Offers.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE OverloadedStrings #-}++-- | See the usage examples in the "Web.Hyperpublic" documentation.+module Web.Hyperpublic.Offers+where++import Data.Aeson ( Value )+import Data.ByteString ( ByteString+                       , append )+import Data.ByteString.Char8 ()++import Network.HTTP.Types ( SimpleQuery )++import Web.Hyperpublic+++-- | Call the show method of the Geo Deals and Events endpoint. API+-- documentation at <http://developer.hyperpublic.com/offers/show-an-offer/>+show :: HpAuth      -- ^ API authorization+     -> ByteString  -- ^ The id of the place to be returned+     -> IO Value    -- ^ JSON output+show auth hpId = callApi auth ("/offers/" `append` hpId) []++-- | Call the find method of the Geo Deals and Events endpoint. API+-- documentation at <http://developer.hyperpublic.com/offers/find-offers/>+find :: HpAuth       -- ^ API authorization+     -> SimpleQuery  -- ^ Query parameters+     -> IO Value     -- ^ JSON output+find auth query = callApi auth "/offers" query
+ Web/Hyperpublic/Places.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE OverloadedStrings #-}++-- | See the usage examples in the "Web.Hyperpublic" documentation.+module Web.Hyperpublic.Places+where++import Data.Aeson ( Value )+import Data.ByteString ( ByteString+                       , append )+import Data.ByteString.Char8 ()++import Network.HTTP.Types ( SimpleQuery )++import Web.Hyperpublic+++-- | Call the show method of the Places+ endpoint. API documentation at+-- <http://developer.hyperpublic.com/places/show-a-place/>+show :: HpAuth      -- ^ API authorization+     -> ByteString  -- ^ The id of the place to be returned+     -> IO Value    -- ^ JSON output+show auth hpId = callApi auth ("/places/" `append` hpId) []++-- | Call the find method of the Places+ endpoint. API documentation at+-- <http://developer.hyperpublic.com/offers/find-offers/>+find :: HpAuth       -- ^ API authorization+     -> SimpleQuery  -- ^ Query parameters+     -> IO Value     -- ^ JSON output+find auth query = callApi auth "/places" query
+ hyperpublic.cabal view
@@ -0,0 +1,40 @@+name: hyperpublic+version: 0.0.0+cabal-version: >= 1.6+build-type: Simple+license: PublicDomain+author: Mike S. Craig+maintainer: mkscrg@gmail.com+stability: experimental+homepage: https://github.com/mkscrg/hyperpublic-haskell+bug-reports: https://github.com/mkscrg/hyperpublic-haskell/issues+synopsis: A thin wrapper for the Hyperpublic API+description:+  A thin wrapper for the Hyperpublic API, which uses "Network.HTTP.Enumerator"+  to fetch results and "Data.Aeson" to return them as JSON.+category: Web+extra-source-files: README.md, Examples.hs++library+  -- Very conservative lower bounds here. Notify me when you find wider+  -- compatibility boundaries and I'll update them here.+  build-depends:+    aeson >= 0.3.2.12 && < 0.4,+    attoparsec >= 0.9.1.2 && < 0.9.99,+    base >= 4.0 && < 5.0,+    bytestring >= 0.9.2.0 && < 0.9.99,+    http-enumerator >= 0.7.1.3 && < 0.8,+    http-types >= 0.6.5.1 && < 0.7+  exposed-modules:+    Web.Hyperpublic, Web.Hyperpublic.Places, Web.Hyperpublic.Offers+  extensions: OverloadedStrings+  ghc-options: -Wall++source-repository head+  type: git+  location: git://github.com/mkscrg/hyperpublic-haskell.git++source-repository this+  type: git+  location: git://github.com/mkscrg/hyperpublic-haskell.git+  tag: 0.0.0