aur-0.2.0: Linux/Arch/Aur/Rpc.hs
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module : Linux.Arch.Aur.Rpc
-- Copyright : (c) Colin Woodbury, 2014
-- License : GPL3
-- Maintainer: Colin Woodbury <colingw@gmail.com>
module Linux.Arch.Aur.Rpc
( -- * Queries
info
, multiinfo
, search
, msearch
-- * As JSON
, info'
, multiinfo'
, search'
, msearch'
-- * Pretty JSON
, pretty) where
import Linux.Arch.Aur.Types
import Control.Applicative ((<$>))
import Control.Monad.Trans (MonadIO, liftIO)
import Control.Lens
import Data.Aeson (Value(..), FromJSON, Result(..), fromJSON)
import Data.Aeson.Lens (AsValue, key, nth)
import Data.Aeson.Encode.Pretty
import Data.Maybe (catMaybes)
import Data.Text
import Data.Text.Lazy.Encoding
import Network.Wreq
import qualified Data.Text.Lazy as TL
import qualified Data.Vector as V
---
rpcUrl :: String
rpcUrl = "https://aur.archlinux.org/rpc.php?"
apiVersion :: Text
apiVersion = "3"
-- | Returns all information about one package.
info :: (MonadIO m, Functor m) => Text -> m (Maybe AurInfo)
info p = (>>= extract) <$> info' p
-- | `info` call as Haskellised JSON.
info' :: (MonadIO m, Functor m) => Text -> m (Maybe Value)
info' pkg = (>>= (^? nth 0)) <$> multiinfo' [pkg]
-- | Like `info`, but can handle requests for multiple packages at once.
-- More efficient than using `info` multiple times.
multiinfo :: (MonadIO m, Functor m) => [Text] -> m [AurInfo]
multiinfo p = mapArray <$> multiinfo' p
-- | `multiinfo` call as Haskellised JSON.
multiinfo' :: MonadIO m => [Text] -> m (Maybe Value)
multiinfo' pkgs = rpc "multiinfo" pkgs "arg[]"
-- | Yields any matches to the input as `AurInfo`, but
-- doesn't include dependency information.
search :: (MonadIO m, Functor m) => Text -> m [AurInfo]
search s = mapArray <$> search' s
-- | `search` call as Haskellised JSON.
search' :: MonadIO m => Text -> m (Maybe Value)
search' query = rpc "search" [query] "arg"
-- | Search the AUR by Maintainer name.
msearch :: (MonadIO m, Functor m) => Text -> m [AurInfo]
msearch m = mapArray <$> msearch' m
-- | `msearch` call as Haskellised JSON.
msearch' :: MonadIO m => Text -> m (Maybe Value)
msearch' maintainer = rpc "msearch" [maintainer] "arg"
-- | Call the RPC.
-- Doesn't fail elegantly when there is a connection failure.
rpc :: MonadIO m => Text -> [Text] -> Text -> m (Maybe Value)
rpc method args argLabel = liftIO (rpcResults <$> getWith opts rpcUrl)
where opts = defaults & param "type" .~ [method]
& param argLabel .~ args
& param "v" .~ [apiVersion]
rpcResults :: AsValue r => Response r -> Maybe Value
rpcResults r = r ^? responseBody . key "results"
-- | Conversion of JSON to nicely formatted Text.
pretty :: Value -> Text
pretty = TL.toStrict . decodeUtf8 . encodePretty
--------------------
-- UTILITY FUNCTIONS
--------------------
extract :: FromJSON a => Value -> Maybe a
extract = f . fromJSON
where f (Success x) = Just x
f _ = Nothing
-- There must be a better way to do this.
mapArray :: FromJSON a => Maybe Value -> [a]
mapArray (Just (Array v)) = catMaybes . V.toList . V.map extract $ v
mapArray _ = []