1 {-# LANGUAGE ViewPatterns #-}
2 -- |Implementations shared across two or more modules.
3 module Cryptsy
.API
.Public
.Internal
where
6 import Control
.Exception
(try)
9 import Data
.Aeson
(Value
(Object
), withObject
, json
')
10 import Data
.Aeson
.Types
(Parser
, parseEither
)
13 import Control
.Monad
.Trans
.Either (EitherT
(..), hoistEither
, left
, right
)
14 import Data
.Either.Combinators
(mapLeft
)
17 import Network
.HTTP
.Client
18 ( parseUrl
, responseBody
, responseCookieJar
, withManager
22 import Network
.HTTP
.Client
.TLS
(tlsManagerSettings
)
25 import Pipes
.Attoparsec
(parse
)
28 import Pipes
.HTTP
(withHTTP
)
31 import Data
.Text
(Text
, pack
)
34 import Control
.Monad
.Trans
.State
.Strict
(evalStateT
)
36 -- unordered-containers
37 import qualified Data
.HashMap
.Strict
as HM
(lookup)
40 import Cryptsy
.API
.Public
.Types
.Error
41 import Cryptsy
.API
.Public
.Types
.Monad
43 -- |generates public API URL
44 pubURL
:: String -- ^ method value
45 -> String -- ^ complete URL
46 pubURL
= ("http://pubapi.cryptsy.com/api.php?method=" ++)
47 {-# INLINABLE pubURL #-}
53 -- |key in JSON object for return data
55 dataKey
= pack dataStr
57 -- |key in JSON object for error message
59 errMsgKey
= pack
"error"
61 -- |common request implementation
62 pubCryptsy
:: String -- ^ URL
63 -> (Value
-> Parser a
)
65 pubCryptsy apiurl parser
= EitherT
. withManager tlsManagerSettings
66 $ \manager
-> runEitherT
$ do
67 req
<- hoistEither
. mapLeft
(BadURL apiurl
) $ parseUrl apiurl
68 (parseResult
, _cookieJar
) <- EitherT
69 . fmap (mapLeft
(FailReadResponse req
))
70 . try $ withHTTP req manager
$ \resp
-> do
71 pr
<- evalStateT
(parse json
') $ responseBody resp
-- discard lo
72 return (pr
, responseCookieJar resp
)
73 value <- case parseResult
of
74 Left pe
-> left
$ FailParseResponse pe
77 Object
(HM
.lookup dataKey
-> Just d
) -> right d
78 Object
(HM
.lookup errMsgKey
-> Just errMsg
) ->
79 left
$ ErrorResponse errMsg
80 _
-> left
$ UnsuccessfulResponse
value
81 hoistEither
. mapLeft
(FailParseReturn dat
) $ parseEither parser dat
82 {-# INLINABLE pubCryptsy #-}
84 -- |unpacked 'marketsKey'
86 marketsStr
= "markets"
88 -- |failure message when 'marketsKey' is missing
90 missingMsg
= "Missing '" ++ marketsStr
++ "' key."
92 -- |key in JSON object for market data
94 marketsKey
= pack marketsStr
96 -- |Apply a parser on the 'marketsKey' of an object. If not an object or the
97 -- key is missing, fail.
98 onMarkets
:: (Value
-> Parser a
) -> Value
-> Parser a
99 onMarkets parser
= withObject marketsStr
$
100 maybe (fail missingMsg
) parser
. HM
.lookup marketsKey
101 {-# INLINABLE onMarkets #-}