module JCDecaux.Vls.Api
( contracts
, stations
, contractStations
, contractStation
, ApiKey(..)
)
where
import JCDecaux.Vls.Types
import Network.HTTP.Conduit (simpleHttp)
import Control.Monad.IO.Class
import Data.Text (Text, pack, unpack, intercalate)
import Data.String (IsString, fromString)
import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Aeson (FromJSON, eitherDecode)
import Data.Monoid ((<>))
import qualified Control.Exception as E
data Error = HttpConnectionError E.SomeException
| JsonError Text
deriving (Show)
type Path = [Text]
type QueryString = [(Text, Text)]
newtype ApiKey = ApiKey Text
instance IsString ApiKey where
fromString = ApiKey . pack
type Result a = Either Error a
contracts :: MonadIO m => ApiKey -> m (Result [Contract])
contracts key = liftIO $ get key ["contracts"] []
stations :: MonadIO m => ApiKey -> m (Result [Station])
stations key = liftIO $ get key ["stations"] []
contractStations :: MonadIO m
=> ApiKey
-> Text
-> m (Result [Station])
contractStations key cn = liftIO $ get key ["stations"] [("contract", cn)]
contractStation :: MonadIO m
=> ApiKey
-> Text
-> Int
-> m (Result Station)
contractStation key cn sn = liftIO $ get key ["stations", pack (show sn)] [("contract", cn)]
get :: (FromJSON a) => ApiKey -> Path -> QueryString -> IO (Result a)
get (ApiKey k) p q = do
(simpleHttp url >>= return . parse)
`E.catches` onException
where
onException = [ E.Handler (\e -> E.throw (e :: E.AsyncException))
, E.Handler (\e -> return . Left $ HttpConnectionError (e :: E.SomeException))
]
parse b =
case eitherDecode b of
Left e -> Left $ JsonError $ pack e <> " in JSON response: " <> pack (LBS.unpack b)
Right d -> Right d
url = unpack $ "https://api.jcdecaux.com/vls/v1/" <> intercalate "/" p <> "?" <> query
query = intercalate "&" $ map (\(n, v) -> n <> "=" <> v) (("apiKey", k):q)