matabas/backend/ICAFocus.hs
2023-08-10 00:55:07 +02:00

82 lines
2.6 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
module ICAFocus where
import qualified Network.HTTP.Client as H
import qualified Network.HTTP.Client.TLS as H
import Network.HTTP.Types.Status
import Data.Aeson
import Data.Aeson.Types
import Data.Aeson.KeyMap
import Data.Text
import Text.Read
import Data.ByteString.Lazy
import GHC.Generics
newtype ImageLink = ImageLink { getLink :: String }
deriving (Show)
newtype ImageData = ImageData { getData :: ByteString }
instance Show ImageData where
show _ = "ImageData { ... }"
data ICAFocusItem a = ICAFocusItem
{ name :: Text
, image :: a
, pricePerUnit :: Float
, pricePerKg :: Float
}
deriving (Show, Functor)
type ICAFocusData = ICAFocusItem ImageLink
type ICAFocusProduct = ICAFocusItem ImageData
instance FromJSON ICAFocusData where
parseJSON (Object v) = do
productMap <- (v .: "entities") >>= (.: "product") :: Parser Object
product <- case elems productMap of
[Object x] -> pure x
[] -> fail "No products"
_ -> fail "Too many products"
name <- product .: "name"
pricePerUnitStr <- product .: "price" >>= (.: "current") >>= (.: "amount") :: Parser String
pricePerUnit <- case readEither pricePerUnitStr of
Right x -> pure x
Left e -> fail e
pricePerKgStr <- product .: "price" >>= (.: "unit") >>= (.: "current") >>= (.: "amount") :: Parser String
pricePerKg <- case readEither pricePerKgStr of
Right x -> pure x
Left e -> fail e
imageLink <- product .: "image" >>= (.: "src")
pure $ ICAFocusItem name (ImageLink imageLink) pricePerUnit pricePerKg
loadProductData :: Int -> IO (Either String ICAFocusData)
loadProductData product_id = do
httpman <- H.newManager H.tlsManagerSettings
req <- H.parseRequest $ "https://handlaprivatkund.ica.se/stores/1004247/api/v4/products/bop?retailerProductId=" ++ show product_id
resp <- H.httpLbs req httpman
if H.responseStatus resp == status200
then pure $ eitherDecode $ H.responseBody resp
else pure $ Left "Error status code"
loadProductImage :: ICAFocusData -> IO (Either String ICAFocusProduct)
loadProductImage x = do
httpman <- H.newManager H.tlsManagerSettings
req <- H.parseRequest $ (getLink . image) x
resp <- H.httpLbs req httpman
if H.responseStatus resp == status200
then do
let imageData = H.responseBody resp
pure $ Right $ (const (ImageData imageData)) <$> x
else pure $ Left "Error status code"
loadProduct :: Int -> IO (Either String ICAFocusProduct)
loadProduct product_id = do
prod <- loadProductData product_id
case prod of
Right x -> loadProductImage x
Left e -> pure $ Left e