module Network.DO.Net.Common where
import Control.Comonad.Env.Class (ComonadEnv, ask)
import Data.Aeson as A hiding (Result)
import qualified Data.Aeson.Types as A
import qualified Data.HashMap.Strict as H
import Data.Maybe
import Data.Proxy
import Data.Text (Text)
import qualified Data.Vector as V
import Network.DO.Types as DO hiding (URI, error)
import Network.REST
import Network.URI (URI, parseURI)
import Prelude as P
rootURI :: String
rootURI = "https://api.digitalocean.com"
apiVersion :: String
apiVersion = "v2"
(</>) :: String -> String -> String
s </> ('/': s') = s ++ s'
s </> s' = s ++ "/" ++ s'
toURI :: String -> URI
toURI s = maybe (P.error $ "cannot parse URI from " ++ s) id $ parseURI s
toList :: (FromJSON a) => Text -> Value -> Result [a]
toList k (Object o) = if H.member "message" o
then error . show $ o H.! "message"
else case H.lookup k o of
Just (Array boxes) ->
Right $ mapMaybe (A.parseMaybe parseJSON) (V.toList boxes)
_ ->
error $ "cannot decode JSON value to a list of " ++ show k
toList k _ =
error $ "cannot decode JSON value to a list of " ++ show k
class Listable a where
listEndpoint :: Proxy a -> String
listField :: Proxy a -> Text
queryList :: (ComonadEnv ToolConfiguration w, Monad m, Listable b, FromJSON b) => Proxy b -> w a -> (RESTT m (Result [b]), w a)
queryList p w = maybe (errMissingToken, w)
(\ t -> let resources = toList (listField p) <$> getJSONWith (authorisation t) (toURI (listEndpoint p))
in (resources, w))
(authToken (ask w))
errMissingToken :: (Monad m) => m (Result a)
errMissingToken = return $ error "no authentication token defined"
fromResponse :: (FromJSON a) => Text -> Either String Value -> Result a
fromResponse key (Right (Object b)) = if H.member "message" b
then error . show $ (b H.! "message")
else case H.lookup key b of
Just val -> either error Right $ A.parseEither parseJSON val
_ -> error $ "cannot decode JSON value to a " ++ show key ++ ": " ++ show b
fromResponse key v =
error $ "cannot decode JSON value to a " ++ show key ++ ": " ++ show v