packages feed

hyperpublic 0.0.0 → 0.1.0

raw patch · 8 files changed

+190/−79 lines, 8 filesdep +containersdep +textdep +vectornew-component:exe:hyperpublic-examplePVP ok

version bump matches the API change (PVP)

Dependencies added: containers, text, vector

API changes (from Hackage documentation)

+ Web.Hyperpublic.Categories: find :: HpAuth -> IO Value
+ Web.Hyperpublic.Categories: show :: HpAuth -> ByteString -> IO Value
+ Web.Hyperpublic.Places: create :: HpAuth -> SimpleQuery -> IO Value

Files

Examples.hs view
@@ -13,10 +13,12 @@ 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 =@@ -34,6 +36,7 @@     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
README.md view
@@ -1,3 +1,18 @@ A thin Haskell wrapper for the [Hyperpublic](http://hyperpublic.com/) API. See-the documentation on the-[Hackage page](http://hackage.haskell.org/package/hyperpublic).+the [Hackage page](http://hackage.haskell.org/package/hyperpublic) for library+documentation and examples.++A Note on Version Numbers+-------------------------++This package adheres to the following convention regarding version+numbers:++    x.y.z+++ `x` -- Major digit, denotes structural changes to the library's exposed+  modules. Application code will probably require updates.++ `y` -- Minor digit, denotes feature additions.  Application code will not+  require updates.++ `z` -- Bugfix digit, denotes bug fixes. Application code will not require+  updates.
Web/Hyperpublic.hs view
@@ -1,20 +1,17 @@-{-# 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/>.+-- | A thin wrapper for the Hyperpublic API, which uses @http-enumerator@ to+-- fetch results and @aeson@ to return them as JSON. Full documentation for the+-- Hyperpublic API 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+.+-- The exposed functions of these modules follow a simple pattern: each takes+-- an 'HpAuth' record as well as either a 'ByteString' (for @show@ methods on+-- the API) or a 'Network.HTTP.Types.SimpleQuery' (for @find@ or @create@+-- methods on the API). ----- Examples (included in the distribution as @Examples.hs@):+-- Some basic usage examples follow. (This code is included in the distribution+-- as @Examples.hs@. Call @cabal-install@ with @-f example@ and it will build+-- an executable called @hyperpublic-example@.) Usage questions may be posted+-- on the Hyperpublic API Developers mailing list at+-- <http://groups.google.com/group/hyperpublic-api-developers>. -- -- >{-# LANGUAGE OverloadedStrings #-} -- >@@ -31,10 +28,12 @@ -- >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 =@@ -53,6 +52,7 @@ -- >  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@@ -67,59 +67,13 @@ -- >    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 )+import Data.ByteString ( ByteString )  -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/Categories.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Wrappers for calling the methods of the Hyperpublic Categories endpoint.+module Web.Hyperpublic.Categories+( show+, find+) where++import Prelude hiding ( show )++import Data.Aeson ( Value )+import Data.ByteString ( ByteString+                       , append )+import Data.ByteString.Char8 ()++import Network.HTTP.Types ( StdMethod (..) )++import Web.Hyperpublic+import Web.Hyperpublic.Internal+++-- | Call the show method of the Categories endpoint. API documentation at+-- <http://developer.hyperpublic.com/categories/show-category/>+show :: HpAuth      -- ^ API authorization+     -> ByteString  -- ^ The id of the category to be returned+     -> IO Value    -- ^ JSON output+show auth hpId = callApi auth GET ("/categories/" `append` hpId) []++-- | Call the find method of the Categories endpoint, which simply lists the+-- full category hierarchy. (The endpoint does not currently support more+-- specific queries.) API documentation at+-- <http://developer.hyperpublic.com/categories/all-categories/>+find :: HpAuth       -- ^ API authorization+     -> IO Value     -- ^ JSON output+find auth = callApi auth GET "/categories" []
+ Web/Hyperpublic/Internal.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE OverloadedStrings #-}++module Web.Hyperpublic.Internal+( 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+                          , StdMethod (..)+                          , renderStdMethod+                          , simpleQueryToQuery )++import Web.Hyperpublic+++callApi :: HpAuth -> StdMethod -> ByteString -> SimpleQuery -> IO Value+callApi auth mthd urlPath query = do+    let query' = [ ("client_id", clientId auth)+                 , ("client_secret", clientSecret auth) ] +++                 filter cleanQuery query+    rsp <- withManager (httpLbsRedirect $ request mthd urlPath query')+    eitherToIO $ Right rsp >>= readResponse >>= eitherResult . parse json+  where+    cleanQuery (k, _) = k /= "client_id" && k /= "client_secret"++request :: StdMethod -> ByteString -> SimpleQuery -> Request m+request mthd urlPath query = def+    { method = renderStdMethod mthd+    , 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 $ show (statusCode rsp) ++ ": " ++ unpack strictBody++eitherToIO :: Either String a -> IO a+eitherToIO (Right a) = return a+eitherToIO (Left str) = fail str
Web/Hyperpublic/Offers.hs view
@@ -1,29 +1,36 @@ {-# LANGUAGE OverloadedStrings #-} --- | See the usage examples in the "Web.Hyperpublic" documentation.+-- | Wrappers for calling the methods of the Hyperpublic Geo Deals and Events+-- endpoint. module Web.Hyperpublic.Offers-where+( show+, find+) where +import Prelude hiding ( show )+ import Data.Aeson ( Value ) import Data.ByteString ( ByteString                        , append ) import Data.ByteString.Char8 () -import Network.HTTP.Types ( SimpleQuery )+import Network.HTTP.Types ( SimpleQuery+                          , StdMethod (..) )  import Web.Hyperpublic+import Web.Hyperpublic.Internal   -- | 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+     -> ByteString  -- ^ The id of the offer to be returned      -> IO Value    -- ^ JSON output-show auth hpId = callApi auth ("/offers/" `append` hpId) []+show auth hpId = callApi auth GET ("/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+find auth query = callApi auth GET "/offers" query
Web/Hyperpublic/Places.hs view
@@ -1,17 +1,24 @@ {-# LANGUAGE OverloadedStrings #-} --- | See the usage examples in the "Web.Hyperpublic" documentation.+-- | Wrappers for calling the methods of the Hyperpublic Places+ endpoint. module Web.Hyperpublic.Places-where+( show+, find+, create+) where +import Prelude hiding ( show )+ import Data.Aeson ( Value ) import Data.ByteString ( ByteString                        , append ) import Data.ByteString.Char8 () -import Network.HTTP.Types ( SimpleQuery )+import Network.HTTP.Types ( SimpleQuery+                          , StdMethod (..) )  import Web.Hyperpublic+import Web.Hyperpublic.Internal   -- | Call the show method of the Places+ endpoint. API documentation at@@ -19,11 +26,18 @@ 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) []+show auth hpId = callApi auth GET ("/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+find auth query = callApi auth GET "/places" query++-- | Call the create method of the Places+ endpoint. API documentation at+-- <http://developer.hyperpublic.com/places/create-a-place/>+create :: HpAuth       -- ^ API authorization+       -> SimpleQuery  -- ^ Query parameters+       -> IO Value     -- ^ JSON output+create auth query = callApi auth POST "/places" query
hyperpublic.cabal view
@@ -1,5 +1,5 @@ name: hyperpublic-version: 0.0.0+version: 0.1.0 cabal-version: >= 1.6 build-type: Simple license: PublicDomain@@ -10,11 +10,16 @@ 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.+  A thin wrapper for the Hyperpublic API, which uses @http-enumerator@ to fetch+  results and @aeson@ to return them as JSON. category: Web extra-source-files: README.md, Examples.hs +flag example+  description: Build Examples.hs into the hyperpublic-example executable.+  default: False+  manual: True+ library   -- Very conservative lower bounds here. Notify me when you find wider   -- compatibility boundaries and I'll update them here.@@ -26,9 +31,30 @@     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+    Web.Hyperpublic,+    Web.Hyperpublic.Places,+    Web.Hyperpublic.Offers,+    Web.Hyperpublic.Categories+  other-modules:+    Web.Hyperpublic.Internal   extensions: OverloadedStrings   ghc-options: -Wall++executable hyperpublic-example+  build-depends:+    aeson >= 0.3.2.12 && < 0.4,+    base >= 4.0 && < 5.0,+    bytestring >= 0.9.2.0 && < 0.9.99,+    containers >= 0.4.1.0 && < 0.5,+    text >= 0.11.1.6 && < 0.12,+    vector >= 0.9 && < 0.9.99+  other-modules:+    Web.Hyperpublic, Web.Hyperpublic.Places, Web.Hyperpublic.Offers+  main-is: Examples.hs+  if flag(example)+    buildable: True+  else+    buildable: False  source-repository head   type: git