module Web.API.MapQuest.Geocoding
(runRequest, Creds(..), GeoQuery(..), Coords(..))
where
import Data.List (intersperse)
import Data.Monoid ((<>))
import "mtl" Control.Monad.Reader.Class
import Network.HTTP.Req
import qualified Data.Text as T
import qualified Data.ByteString.Lazy as LBS
import GHC.Generics
import Control.Monad.Catch
import Data.Aeson
import Data.Aeson.Types (Parser, parseMaybe)
import Network.Goggles
apiRootPath :: Url 'Http
apiRootPath = http "www.mapquestapi.com" /: "geocoding" /: "v1" /: "address"
newtype Creds = Creds { apiKey :: T.Text } deriving (Eq, Show)
data MapQuest
instance HasCredentials MapQuest where
type Credentials MapQuest = Creds
instance MonadHttp (WebApiM MapQuest) where
handleHttpException = throwM
request :: (FromJSON a, Floating a) =>
GeoQuery
-> WebApiM MapQuest (Maybe (Coords a))
request q = do
key <- asks (apiKey . credentials)
r <- req GET apiRootPath NoReqBody lbsResponse (opts' key)
return $ decoder1 $ responseBody r where
opts' k =
("key" =: k) <>
("outFormat" =: ("json" :: T.Text)) <>
("location" =: renderGeoQuery q)
runRequest :: (FromJSON a, Floating a) =>
Creds
-> GeoQuery
-> IO (Maybe (Coords a))
runRequest k q = do
h <- createHandle k undefined
evalWebApiIO h (request q)
decoder1 :: (FromJSON a, Floating a) => LBS.ByteString -> Maybe (Coords a)
decoder1 dat = do
r <- decode dat
flip parseMaybe r $ \obj -> do
locp <- decodeLocation obj
decodeLatLong locp
decodeLocation :: FromJSON a => Object -> Parser a
decodeLocation obj = do
(res0 : _) <- obj .: "results"
(loc0 : _) <- res0 .: "locations"
return loc0
decodeLatLong :: (FromJSON a, Floating a) => Object -> Parser (Coords a)
decodeLatLong loc = do
ll <- loc .: "latLng"
Coords <$> ll .: "lat" <*> ll .: "lng"
data Coords a = Coords {
lat :: a
, long :: a
} deriving (Eq, Show, Generic)
data GeoQuery = GQ {
gqStreet :: T.Text
, gqCity :: T.Text
, gqCountry :: T.Text
}
| GQFree T.Text
deriving (Eq, Show)
renderGeoQuery :: GeoQuery -> T.Text
renderGeoQuery q = case q of
(GQ addr city country) -> T.concat $ intersperse ", " [addr, city, country]
(GQFree t) -> t