aboutsummaryrefslogtreecommitdiff
path: root/lib/Web
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2017-06-07 16:24:05 +0300
committerIgor Pashev <pashev.igor@gmail.com>2017-06-07 16:35:08 +0300
commit6f6e3d8ec76c59d6f403725e9b2a22b8f6680714 (patch)
tree45382bc0e03032ffa09b7b63afdc45e243e60f4f /lib/Web
downloadopenweathermap-6f6e3d8ec76c59d6f403725e9b2a22b8f6680714.tar.gz
Initial version 0.0.00.0.0
Diffstat (limited to 'lib/Web')
-rw-r--r--lib/Web/OpenWeatherMap/API.hs45
-rw-r--r--lib/Web/OpenWeatherMap/Client.hs49
-rw-r--r--lib/Web/OpenWeatherMap/Types/Clouds.hs16
-rw-r--r--lib/Web/OpenWeatherMap/Types/Coord.hs17
-rw-r--r--lib/Web/OpenWeatherMap/Types/CurrentWeather.hs35
-rw-r--r--lib/Web/OpenWeatherMap/Types/Main.hs23
-rw-r--r--lib/Web/OpenWeatherMap/Types/Sys.hs19
-rw-r--r--lib/Web/OpenWeatherMap/Types/Weather.hs19
-rw-r--r--lib/Web/OpenWeatherMap/Types/Wind.hs17
9 files changed, 240 insertions, 0 deletions
diff --git a/lib/Web/OpenWeatherMap/API.hs b/lib/Web/OpenWeatherMap/API.hs
new file mode 100644
index 0000000..0c1e282
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/API.hs
@@ -0,0 +1,45 @@
+{-|
+Direct API functions.
+For API key (a.k.a appid) refer to <http://openweathermap.org/appid>.
+-}
+
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+
+module Web.OpenWeatherMap.API (
+ weatherByName,
+ weatherByCoord
+) where
+
+import Data.Proxy (Proxy(..))
+
+import Servant.API ((:>), (:<|>)(..), JSON, Get, QueryParam)
+import Servant.Client (client)
+import Servant.Common.Req (ClientM)
+
+import Web.OpenWeatherMap.Types.CurrentWeather (CurrentWeather)
+
+
+type GetCurrentWeather = AppId :> Get '[JSON] CurrentWeather
+type AppId = QueryParam "appid" String
+
+type API
+ = "weather" :> QueryParam "q" String :> GetCurrentWeather
+ :<|> "weather" :> QueryParam "lat" Double :> QueryParam "lon" Double
+ :> GetCurrentWeather
+
+-- | Request current weather in the city.
+weatherByName
+ :: Maybe String -- ^ City name, e. g. \"Moscow\" or \"Moscow,ru\".
+ -> Maybe String -- ^ API key.
+ -> ClientM CurrentWeather
+
+-- | Request current weather at the geographic coordinates (in decimal degrees).
+weatherByCoord
+ :: Maybe Double -- ^ Latitude, e. g. 55.7522200 for Moscow.
+ -> Maybe Double -- ^ Longitude, e. g. 37.6155600 for Moscow.
+ -> Maybe String -- ^ API key.
+ -> ClientM CurrentWeather
+
+weatherByName :<|> weatherByCoord = client (Proxy :: Proxy API)
+
diff --git a/lib/Web/OpenWeatherMap/Client.hs b/lib/Web/OpenWeatherMap/Client.hs
new file mode 100644
index 0000000..7804ef2
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Client.hs
@@ -0,0 +1,49 @@
+{-|
+High-level client functions perfoming requests to OpenWeatherMap API.
+-}
+module Web.OpenWeatherMap.Client (
+ Location(..),
+ getWeather
+) where
+
+import Network.HTTP.Client (newManager, defaultManagerSettings)
+import Servant.Client (ClientEnv(..), runClientM, ServantError)
+import Servant.Common.BaseUrl (BaseUrl(..), Scheme(..))
+import Servant.Common.Req (ClientM)
+
+import Web.OpenWeatherMap.Types.CurrentWeather (CurrentWeather)
+import qualified Web.OpenWeatherMap.API as API
+
+
+-- | Various way to specify location.
+data Location
+ = Name String -- ^ City name.
+ | Coord Double Double -- ^ Geographic coordinates: latitude and longitude.
+
+
+-- | Make a request to OpenWeatherMap API
+-- and return current weather in given location.
+getWeather
+ :: String -- ^ API key.
+ -> Location
+ -> IO (Either ServantError CurrentWeather)
+getWeather appid loc =
+ defaultEnv >>= runClientM (api loc appid)
+
+api
+ :: Location
+ -> String -- ^ API key.
+ -> ClientM CurrentWeather
+api (Name city) = API.weatherByName (Just city) . Just
+api (Coord lat lon) = API.weatherByCoord (Just lat) (Just lon) . Just
+
+defaultEnv :: IO ClientEnv
+defaultEnv = do
+ manager <- newManager defaultManagerSettings
+ return $ ClientEnv manager baseUrl
+
+-- XXX openweathermap.org does not support HTTPS,
+-- XXX appid is passed in clear text. Oops.
+baseUrl :: BaseUrl
+baseUrl = BaseUrl Http "api.openweathermap.org" 80 "/data/2.5"
+
diff --git a/lib/Web/OpenWeatherMap/Types/Clouds.hs b/lib/Web/OpenWeatherMap/Types/Clouds.hs
new file mode 100644
index 0000000..78a6e97
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Types/Clouds.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Web.OpenWeatherMap.Types.Clouds (
+ Clouds(..)
+) where
+
+import GHC.Generics (Generic)
+
+import Data.Aeson (FromJSON)
+
+
+data Clouds = Clouds
+ { all :: Double
+ } deriving (Show, Generic, FromJSON)
+
diff --git a/lib/Web/OpenWeatherMap/Types/Coord.hs b/lib/Web/OpenWeatherMap/Types/Coord.hs
new file mode 100644
index 0000000..d9a9f21
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Types/Coord.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Web.OpenWeatherMap.Types.Coord (
+ Coord(..)
+) where
+
+import GHC.Generics (Generic)
+
+import Data.Aeson (FromJSON)
+
+
+data Coord = Coord
+ { lon :: Double
+ , lat :: Double
+ } deriving (Show, Generic, FromJSON)
+
diff --git a/lib/Web/OpenWeatherMap/Types/CurrentWeather.hs b/lib/Web/OpenWeatherMap/Types/CurrentWeather.hs
new file mode 100644
index 0000000..26572a7
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Types/CurrentWeather.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Web.OpenWeatherMap.Types.CurrentWeather (
+ CurrentWeather(..)
+) where
+
+import Prelude hiding (id)
+import GHC.Generics (Generic)
+
+import Data.Aeson (FromJSON)
+
+import Web.OpenWeatherMap.Types.Clouds (Clouds)
+import Web.OpenWeatherMap.Types.Coord (Coord)
+import Web.OpenWeatherMap.Types.Main (Main)
+import Web.OpenWeatherMap.Types.Sys (Sys)
+import Web.OpenWeatherMap.Types.Weather (Weather)
+import Web.OpenWeatherMap.Types.Wind (Wind)
+
+-- | Response to requests for current weather.
+-- Refer to <https://openweathermap.org/current>.
+data CurrentWeather = CurrentWeather
+ { coord :: Coord
+ , weather :: [Weather]
+ , base :: String
+ , main :: Main
+ , wind :: Wind
+ , clouds :: Clouds
+ , dt :: Int
+ , sys :: Sys
+ , id :: Int
+ , name :: String
+ , cod :: Int
+ } deriving (Show, Generic, FromJSON)
+
diff --git a/lib/Web/OpenWeatherMap/Types/Main.hs b/lib/Web/OpenWeatherMap/Types/Main.hs
new file mode 100644
index 0000000..21b1951
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Types/Main.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Web.OpenWeatherMap.Types.Main (
+ Main(..)
+) where
+
+import GHC.Generics (Generic)
+
+import Data.Aeson (FromJSON)
+
+
+{-# ANN module "HLint: ignore Use camelCase" #-}
+data Main = Main
+ { temp :: Double
+ , pressure :: Double
+ , humidity :: Double
+ , temp_min :: Double
+ , temp_max :: Double
+ , sea_level :: Maybe Double
+ , grnd_level :: Maybe Double
+ } deriving (Show, Generic, FromJSON)
+
diff --git a/lib/Web/OpenWeatherMap/Types/Sys.hs b/lib/Web/OpenWeatherMap/Types/Sys.hs
new file mode 100644
index 0000000..03b223c
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Types/Sys.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Web.OpenWeatherMap.Types.Sys (
+ Sys(..)
+) where
+
+import GHC.Generics (Generic)
+
+import Data.Aeson (FromJSON)
+
+
+data Sys = Sys
+ { message :: Double
+ , country :: Maybe String
+ , sunrise :: Int
+ , sunset :: Int
+ } deriving (Show, Generic, FromJSON)
+
diff --git a/lib/Web/OpenWeatherMap/Types/Weather.hs b/lib/Web/OpenWeatherMap/Types/Weather.hs
new file mode 100644
index 0000000..090fe0f
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Types/Weather.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Web.OpenWeatherMap.Types.Weather (
+ Weather(..)
+) where
+
+import GHC.Generics (Generic)
+
+import Data.Aeson (FromJSON)
+
+
+data Weather = Weather
+ { id :: Int
+ , main :: String
+ , description :: String
+ , icon :: String
+ } deriving (Show, Generic, FromJSON)
+
diff --git a/lib/Web/OpenWeatherMap/Types/Wind.hs b/lib/Web/OpenWeatherMap/Types/Wind.hs
new file mode 100644
index 0000000..8481e62
--- /dev/null
+++ b/lib/Web/OpenWeatherMap/Types/Wind.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Web.OpenWeatherMap.Types.Wind (
+ Wind(..)
+) where
+
+import GHC.Generics (Generic)
+
+import Data.Aeson (FromJSON)
+
+
+data Wind = Wind
+ { speed :: Double
+ , deg :: Double
+ } deriving (Show, Generic, FromJSON)
+