{-# LANGUAGE OverloadedStrings #-}
module System.Cached.JSON (
getCachedJSON,
getCachedJSONQuery,
lookupKey
)
where
import Control.Monad
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as B
import Data.Time.Clock (diffUTCTime, getCurrentTime, NominalDiffTime)
import Network.HTTP.Query
import System.Directory
import System.Environment.XDG.BaseDir
import System.FilePath
getCachedJSON :: (FromJSON a, ToJSON a)
=> String
-> FilePath
-> String
-> NominalDiffTime
-> IO a
getCachedJSON :: forall a.
(FromJSON a, ToJSON a) =>
String -> String -> String -> NominalDiffTime -> IO a
getCachedJSON String
prog String
jsonfile String
url =
String -> String -> IO a -> NominalDiffTime -> IO a
forall a.
(FromJSON a, ToJSON a) =>
String -> String -> IO a -> NominalDiffTime -> IO a
getCachedJSONQuery String
prog String
jsonfile (String -> Query -> IO a
forall (m :: * -> *) a.
(MonadIO m, FromJSON a) =>
String -> Query -> m a
webAPIQuery String
url [])
getCachedJSONQuery :: (FromJSON a, ToJSON a)
=> String
-> FilePath
-> IO a
-> NominalDiffTime
-> IO a
getCachedJSONQuery :: forall a.
(FromJSON a, ToJSON a) =>
String -> String -> IO a -> NominalDiffTime -> IO a
getCachedJSONQuery String
prog String
jsonfile IO a
webquery NominalDiffTime
minutes = do
file <- String -> String -> IO String
getUserCacheFile String
prog String
jsonfile
exists <- doesFileExist file
unless exists $ do
putStrLn $ "Creating " ++ file ++ " ..."
createDirectoryIfMissing True (takeDirectory file)
recent <- do
if exists
then do
size <- getFileSize file
if size == 0
then return False
else do
ts <- getModificationTime file
t <- getCurrentTime
return $ diffUTCTime t ts < (minutes * 60)
else return False
if recent
then do
eObj <- eitherDecode <$> B.readFile file
case eObj of
Left String
err -> String -> IO a
forall a. HasCallStack => String -> a
error String
err
Right a
obj -> a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
obj
else do
obj <- webquery
B.writeFile file $ encode obj
return obj