module Vimeta.Core.Config
( Config (..),
defaultConfig,
configFileName,
readConfig,
writeConfig,
)
where
import Control.Monad.Except
import Data.Aeson hiding (encodeFile)
import Data.Aeson.Types (typeMismatch)
import Data.Yaml (decodeFileEither, encodeFile)
import Network.API.TheMovieDB (Key)
import System.Directory
( XdgDirectory (XdgConfig),
createDirectoryIfMissing,
doesFileExist,
getXdgDirectory,
)
import System.FilePath (takeDirectory, (</>))
import Vimeta.Core.Tagger
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 =
getXdgDirectory XdgConfig "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