{-# LANGUAGE OverlappingInstances #-} module Network.IRC.Config (loadBotConfig) where import qualified Data.Configurator as CF import qualified Data.Configurator.Types as CFT import qualified Data.Ratio as R import ClassyPrelude import Data.Configurator.Types (Configured (..), ConfigError (..), KeyError (..)) import Prelude (read) import Network.IRC import Network.IRC.Configuration import Network.IRC.Handlers instance Configurable CFT.Value where fromValue (String a) = Just $ CFT.String a fromValue (Number a) = Just $ CFT.Number (a R.% 1) fromValue (Boolean a) = Just $ CFT.Bool a fromValue (List a) = Just $ CFT.List (mapMaybe fromValue a) toValue (CFT.String a) = toValue a toValue (CFT.Number r) = toValue (R.numerator r `div` R.denominator r) toValue (CFT.Bool a) = toValue a toValue (CFT.List vs) = toValue vs fromConfiguratorConfig :: CFT.Config -> IO Configuration fromConfiguratorConfig config = fromMap . foldl' (\m (k, v) -> insertMap k (toValue v) m) mempty . mapToList <$> CF.getMap config loadBotConfig :: String -> IO BotConfig loadBotConfig configFile = do eConfig <- try $ CF.load [CF.Required configFile] case eConfig of Left (ParseError _ msg) -> error $ "Error while loading config: " ++ msg Right config -> do eBotConfig <- try $ do handlers :: [Text] <- CF.require config "msghandlers" let handlerInfo = foldl' (\m h -> insertMap h mempty m) mempty handlers let handlerMakers = foldl' (\m maker -> insertMap (msgHandlerName maker) maker m) mempty . filter (\MsgHandlerMaker { .. } -> msgHandlerName `member` handlerInfo) $ allMsgHandlerMakers botConfig <- newBotConfig <$> CF.require config "server" <*> CF.require config "port" <*> CF.require config "channel" <*> (Nick <$> CF.require config "nick") <*> CF.require config "timeout" <*> (read <$> CF.require config "loglevel") configMap <- fromConfiguratorConfig config return botConfig { msgHandlerInfo = handlerInfo , msgHandlerMakers = handlerMakers , config = configMap } case eBotConfig of Left (KeyError k) -> error $ "Error while reading key from config: " ++ unpack k Right botConf -> return botConf