libstackexchange 0.3.0.0 → 0.3.1
raw patch · 8 files changed
+180/−22 lines, 8 filesdep +aeson-lensdep +doctestdep +happstack-serverdep ~basenew-component:exe:badges-watchernew-component:exe:rep-watchernew-component:exe:server-side-authenticationPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: aeson-lens, doctest, happstack-server, lens, libstackexchange, mtl
Dependency ranges changed: base
API changes (from Hackage documentation)
- Network.StackExchange.Request: _host :: R r -> Text
- Network.StackExchange.Request: _method :: R r -> Text
- Network.StackExchange.Request: _parse :: R r -> Maybe (ByteString -> r)
- Network.StackExchange.Request: _path :: R r -> Text
- Network.StackExchange.Request: _query :: R r -> Map Text Text
- Network.StackExchange.Request: instance Default (R a n r)
- Network.StackExchange.Request: instance FromJSON (SE a)
- Network.StackExchange.Request: instance Show (SE a)
- Network.StackExchange.Request: unSE :: SE -> Value
- Network.StackExchange.Response: _data :: SEException -> ByteString
- Network.StackExchange.Response: _error :: SEException -> String
- Network.StackExchange.Response: instance Exception SEException
- Network.StackExchange.Response: instance Show SEException
- Network.StackExchange.Response: instance Typeable SEException
+ Network.StackExchange.Request: [_host] :: R r -> Text
+ Network.StackExchange.Request: [_method] :: R r -> Text
+ Network.StackExchange.Request: [_parse] :: R r -> Maybe (ByteString -> r)
+ Network.StackExchange.Request: [_path] :: R r -> Text
+ Network.StackExchange.Request: [_query] :: R r -> Map Text Text
+ Network.StackExchange.Request: [unSE] :: SE -> Value
+ Network.StackExchange.Request: instance Data.Aeson.Types.FromJSON.FromJSON (Network.StackExchange.Request.SE a)
+ Network.StackExchange.Request: instance Data.Default.Class.Default (Network.StackExchange.Request.R a n r)
+ Network.StackExchange.Request: instance GHC.Show.Show (Network.StackExchange.Request.SE a)
+ Network.StackExchange.Response: [_data] :: SEException -> ByteString
+ Network.StackExchange.Response: [_error] :: SEException -> String
+ Network.StackExchange.Response: instance GHC.Exception.Exception Network.StackExchange.Response.SEException
+ Network.StackExchange.Response: instance GHC.Show.Show Network.StackExchange.Response.SEException
- Network.StackExchange.Request: token :: Text -> Request RequireToken n r -> Request Ready n r
+ Network.StackExchange.Request: token :: Text -> Request 'RequireToken n r -> Request 'Ready n r
- Network.StackExchange.Response: askSE :: Request Ready n r -> IO r
+ Network.StackExchange.Response: askSE :: Request 'Ready n r -> IO r
Files
- LICENSE +1/−1
- doctests.hs +8/−0
- examples/badges-watcher.hs +32/−0
- examples/rep-watcher.hs +21/−0
- examples/server-side-authentication.hs +40/−0
- libstackexchange.cabal +73/−17
- src/Network/StackExchange/Request.hs +1/−1
- src/Network/StackExchange/Response.hs +4/−3
LICENSE view
@@ -1,4 +1,4 @@-Copyright (C) 2012 Matvey Aksenov, Dmitry Malikov+Copyright (C) 2012-2013 Matvey Aksenov, Dmitry Malikov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in
+ doctests.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE UnicodeSyntax #-}+module Main where++import Test.DocTest+++main ∷ IO ()+main = doctest ["-isrc", "-XOverloadedStrings", "src/Network/StackExchange/API.hs"]
+ examples/badges-watcher.hs view
@@ -0,0 +1,32 @@+#!/usr/bin/env runhaskell+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE UnicodeSyntax #-}+{-# LANGUAGE ViewPatterns #-}++import Data.Foldable (foldMap)+import Data.Maybe (fromMaybe)+import Data.Monoid++import Control.Lens+import qualified Data.Aeson.Lens as L++import Network.StackExchange+++main ∷ IO ()+main = ask >>= print . foldMap count+++ask ∷ IO [SE Badge]+ask = askSE $ badgesOnUsers [972985] <> site "stackoverflow" <> key "Lhg6xe5d5BvNK*C0S8jijA(("+++count ∷ SE Badge → (Sum Int, Sum Int, Sum Int)+count (view (from se) → x) = (\l → set l (x ^. L.key "award_count" . to (Sum . fromMaybe 0)) mempty) $+ case x ^. L.key "rank" . L.asText of+ Just "bronze" → _1+ Just "silver" → _2+ Just "gold" → _3+ _ → error "badge rank isn't bronze/silver/gold"
+ examples/rep-watcher.hs view
@@ -0,0 +1,21 @@+#!/usr/bin/env runhaskell+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE UnicodeSyntax #-}++import Control.Applicative ((<$>))+import Data.Maybe (catMaybes)+import Data.Monoid ((<>))++import Control.Lens+import qualified Data.Aeson.Lens as L++import Network.StackExchange+++main ∷ IO ()+main = reputation <$> askSE req >>= mapM_ (print . truncate) . catMaybes+ where+ req = usersByIds [972985] <> site "stackoverflow" <> key "Lhg6xe5d5BvNK*C0S8jijA(("+ reputation xs = xs ^.. traverse . from se . L.key "reputation" . L.asDouble
+ examples/server-side-authentication.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE UnicodeSyntax #-}+-- | Simple StackExchange server-side authentication example+-- It consists of two steps.+--+-- * Firstly, after you ran the application, you go to http://appaddress:8000/authenticate-me-please+-- It will redirect you to StackExchange website, asking for confirmation. When you confirm+-- apps access, you will be redirected to @rURI@, it should be http://appaddress:8000/save-token+-- * Secondly, you can check what access token did you receive by asking http://appaddress:8000/show-tokens+--+-- That's it.+module Main where++import Control.Monad+import Data.IORef++import Control.Monad.Trans (liftIO)+import Happstack.Server hiding (host, path)++import Network.StackExchange+++main ∷ IO ()+main = do+ tokens ← newIORef []+ simpleHTTP nullConf $ msum+ [ dir "authenticate-me-please" $ seeOther (render $ explicitUserPermission cID rURI) ""+ , dir "save-token" $ do+ c ← lookText "code"+ liftIO $ askSE (explicitAccessToken cID cSecret c rURI) >>= modifyIORef' tokens . (:)+ ok "Saved."+ , dir "show-tokens" $ liftIO (readIORef tokens) >>= ok . show+ ]+ where+ rURI = undefined++ cID = undefined++ cSecret = undefined
libstackexchange.cabal view
@@ -1,5 +1,5 @@ name: libstackexchange-version: 0.3.0.0+version: 0.3.1 synopsis: StackExchange API interface description: Provides interface for StackExchange v2.1 API homepage: https://github.com/supki/libstackexchange@@ -11,21 +11,77 @@ build-type: Simple cabal-version: >= 1.8 +flag enable-examples+ default: False+flag enable-doctests+ default: False+ library- build-depends: base >= 4.6 && < 5,- bytestring,- containers,- data-default,- attoparsec,- text,- aeson,- http-conduit,- profunctors+ build-depends:+ aeson,+ attoparsec,+ base >= 4.6 && < 5,+ bytestring,+ containers,+ data-default,+ http-conduit,+ profunctors,+ text hs-source-dirs: src- exposed-modules: Network.StackExchange- Network.StackExchange.API- Network.StackExchange.Auth- Network.StackExchange.Request- Network.StackExchange.Response- ghc-options: -Wall- -fno-warn-unused-do-bind+ exposed-modules:+ Network.StackExchange+ Network.StackExchange.API+ Network.StackExchange.Auth+ Network.StackExchange.Request+ Network.StackExchange.Response+ ghc-options:+ -Wall+ -fno-warn-unused-do-bind++test-suite api+ build-depends:+ base >= 4.6,+ doctest >= 0.8,+ http-conduit,+ libstackexchange+ if !flag(enable-doctests)+ buildable: False+ type: exitcode-stdio-1.0+ main-is: doctests.hs+ ghc-options:+ -Wall+ -fno-warn-unused-do-bind++executable rep-watcher+ if !flag(enable-examples)+ buildable: False+ build-depends:+ aeson-lens,+ base >= 4.6,+ lens,+ libstackexchange+ hs-source-dirs: examples+ main-is: rep-watcher.hs++executable badges-watcher+ if !flag(enable-examples)+ buildable: False+ build-depends:+ aeson-lens,+ base >= 4.6,+ lens,+ libstackexchange+ hs-source-dirs: examples+ main-is: badges-watcher.hs++executable server-side-authentication+ if !flag(enable-examples)+ buildable: False+ build-depends:+ base >= 4.6,+ happstack-server,+ lens,+ libstackexchange,+ mtl+ hs-source-dirs: examples+ main-is: server-side-authentication.hs
src/Network/StackExchange/Request.hs view
@@ -157,7 +157,7 @@ -- | Convert token requiring Request into ready one-token ∷ Text → Request RequireToken n r → Request Ready n r+token ∷ Text → Request 'RequireToken n r → Request 'Ready n r token t = unsafeCoerce . mappend (wrap (__query (M.insert "access_token" t))) {-# INLINE token #-}
src/Network/StackExchange/Response.hs view
@@ -37,11 +37,12 @@ -- | Send Request and parse response-askSE ∷ Request Ready n r → IO r+askSE ∷ Request 'Ready n r → IO r askSE q = do let R {_method, _parse} = unwrap q def- r ← C.withManager $ \m → C.parseUrl (render q) >>= \url →- C.responseBody <$> C.httpLbs (url {C.method = toStrict $ encodeUtf8 _method}) m+ m ← C.newManager C.tlsManagerSettings+ url ← C.parseUrlThrow (render q)+ r ← C.responseBody <$> C.httpLbs (url {C.method = toStrict $ encodeUtf8 _method}) m case _parse of Just f → return $ f r Nothing → throwIO $