{-# LANGUAGE OverloadedStrings,ScopedTypeVariables #-}
module Vimeta.Core.Config
( Config (..)
, defaultConfig
, configFileName
, readConfig
, writeConfig
) where
import Control.Applicative
import Control.Monad
import Control.Monad.Except
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Aeson hiding (encodeFile)
import Data.Aeson.Types (typeMismatch)
import Data.Text (Text)
import Data.Yaml (decodeFileEither, encodeFile)
import Network.API.TheMovieDB (Key)
import System.Directory (doesFileExist, createDirectoryIfMissing)
import System.Environment.XDG.BaseDir (getUserConfigFile)
import System.FilePath (takeDirectory)
import Vimeta.Core.Tagger
import Prelude
data Config = Config
{ configTMDBKey :: Key
, configFormatMovie :: Text
, configFormatTV :: Text
, configVerbose :: Bool
, configDryRun :: Bool
}
instance FromJSON Config where
parseJSON (Object v) =
Config <$> v .: "tmdb_key"
<*> v .: "cmd_movie"
<*> v .: "cmd_tv"
<*> v .:? "verbose" .!= False
<*> v .:? "dryrun" .!= False
parseJSON x = typeMismatch "configuration" x
instance ToJSON Config where
toJSON c = object [ "tmdb_key" .= configTMDBKey c
, "cmd_movie" .= configFormatMovie c
, "cmd_tv" .= configFormatTV c
]
defaultConfig :: Tagger -> Config
defaultConfig tagger =
Config { configTMDBKey = "your API key goes here"
, configFormatMovie = fmtMovie
, configFormatTV = fmtTV
, configVerbose = False
, configDryRun = False
}
where (fmtMovie, fmtTV) = formatStringsForTagger tagger
configFileName :: IO FilePath
configFileName = getUserConfigFile "vimeta" "config.yml"
readConfig :: (MonadIO m) => ExceptT String m Config
readConfig = do
filename <- liftIO configFileName
exists <- liftIO (doesFileExist filename)
if exists
then decodeConfig filename
else throwError $ missingFile filename
where
decodeConfig :: (MonadIO m) => FilePath -> ExceptT String m Config
decodeConfig fn = do result <- liftIO $ decodeFileEither fn
case result of
Left e -> throwError (show e)
Right a -> return a
missingFile :: FilePath -> String
missingFile fn = "no config file found, use the `config' command " ++
"to create " ++ fn
writeConfig :: (MonadIO m) => Config -> ExceptT String m FilePath
writeConfig c = do
(filename, exists) <- liftIO $ do
fn <- configFileName
ex <- doesFileExist fn
return (fn, ex)
when exists $ throwError (existError filename)
liftIO (createDirectoryIfMissing True (takeDirectory filename))
liftIO (encodeFile filename c)
return filename
where
existError :: FilePath -> String
existError fn = "please remove the existing config file first: " ++ fn