You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.6 KiB

3 years ago
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE LambdaCase #-}
  3. module Conf ( Group(..) , Config(..) , readConfig ) where
  4. import qualified Data.Text as T
  5. import qualified Discord.Types as D
  6. import Data.Yaml ( Object
  7. , decodeFileThrow
  8. , (.:)
  9. , parseMaybe
  10. , Parser
  11. , withObject
  12. , FromJSON
  13. , Value (Object, Number, String)
  14. , parseJSON
  15. )
  16. import qualified Data.HashMap.Strict as H
  17. import qualified Data.Map.Strict as Map
  18. import Data.Maybe (fromMaybe)
  19. import Control.Monad (mzero)
  20. import Data.Word (Word64)
  21. import Data.Scientific (Scientific, floatingOrInteger)
  22. import Data.Either (fromRight)
  23. data Group = Group
  24. { groupChannel :: D.Snowflake
  25. , groupRole :: D.Snowflake
  26. , groupAde :: T.Text
  27. }
  28. deriving (Show, Eq, Read)
  29. hmToGroup :: H.HashMap T.Text Value -> Group
  30. hmToGroup hm = Group
  31. { groupChannel = scitosno
  32. . valueNum "channel"
  33. . errorRequired "channel"
  34. $ H.lookup "channel" hm
  35. , groupRole = scitosno
  36. . valueNum "role"
  37. . errorRequired "role"
  38. $ H.lookup "role" hm
  39. , groupAde = valueText "edturl"
  40. . errorRequired "edturl"
  41. $ H.lookup "edturl" hm
  42. }
  43. data Config = Config
  44. { configServer :: D.Snowflake
  45. , configGroups :: Map.Map T.Text Group
  46. , configAutoEDTCronDay :: T.Text
  47. , configAutoEDTCronWeek :: T.Text
  48. }
  49. deriving (Show, Eq, Read)
  50. readConfig :: FilePath -> IO Config
  51. readConfig fp = do
  52. conf_yml <- decodeFileThrow fp :: IO Object
  53. -- print conf_yml
  54. return $ ymlToConf conf_yml
  55. ymlToConf :: Object -> Config
  56. ymlToConf v = Config
  57. { configServer = server
  58. , configGroups = groups
  59. , configAutoEDTCronDay = autoEdtCronDay
  60. , configAutoEDTCronWeek = autoEdtCronWeek
  61. }
  62. where
  63. server' = errorRequired "server" $ H.lookup "server" v
  64. server = scitosno $ valueNum "server" server'
  65. groups = parseGroups groupsObject
  66. groupsObject = H.lookup "groups" v
  67. parseGroups (Just (Object o)) = let groupList' :: H.HashMap T.Text Group
  68. groupList' = fmap ( hmToGroup
  69. . (\case
  70. Object u -> u
  71. _ -> error "groups are objects")
  72. ) o
  73. in Map.fromList $ H.toList groupList'
  74. parseGroups _ = error "Wrong format for groups"
  75. autoEdtCronDay =
  76. valueText "autoEdtCronDay"
  77. $ fromMaybe "0 15 * * 0-4"
  78. $ H.lookup "autoEdtCronDay" v
  79. autoEdtCronWeek =
  80. valueText "autoEdtCronWeek"
  81. $ fromMaybe "30 9 * * 0"
  82. $ H.lookup "autoEdtCronWeek" v
  83. errorRequired :: [Char] -> Maybe a -> a
  84. errorRequired name = fromMaybe (error $ "required field: " ++ name)
  85. valueText :: [Char] -> Value -> T.Text
  86. valueText _ (String t) = t
  87. valueText name _ = error $ name ++ " should be a string"
  88. valueNum :: [Char] -> Value -> Scientific
  89. valueNum _ (Number n) = n
  90. valueNum name _ = error $ name ++ " should be an integer"
  91. scitosno :: Scientific -> D.Snowflake
  92. scitosno = D.Snowflake
  93. . (fromInteger :: Integer -> Word64)
  94. . fromRight (error "Cant read that as an int")
  95. . floatingOrInteger