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.

165 lines
6.8 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE RecordWildCards #-}
  3. {-# LANGUAGE ScopedTypeVariables #-}
  4. module Main where
  5. import Control.Monad (when, void)
  6. import qualified Data.Text as T
  7. import qualified Data.Text.IO as TIO
  8. import Control.Monad.IO.Unlift (toIO, liftIO, withRunInIO)
  9. import Discord ( def, restCall
  10. , runDiscord, sendCommand
  11. , DiscordHandler
  12. , RunDiscordOpts(..)
  13. )
  14. import Discord.Types ( Event(..), PartialApplication(..)
  15. , GatewaySendable(..)
  16. , UpdateStatusOpts(..)
  17. , UpdateStatusType(..)
  18. , Activity(..), ActivityType(..)
  19. )
  20. import Discord.Interactions ( interactionResponseBasic
  21. , Interaction(..)
  22. , InteractionDataApplicationCommand(..)
  23. )
  24. import qualified Discord.Requests as R
  25. import Commands ( edtResponse, edtCommand
  26. , pingResponse, pingCommand
  27. , remindResponse, remindCommand
  28. , groupCommand, groupResponse
  29. , helpCommand, helpResponse
  30. , Remind(..)
  31. )
  32. import Conf ( Config(..), Group(..), readConfig )
  33. import qualified System.Cron.Schedule as Cron
  34. import qualified Data.Map.Strict as Map
  35. import Commands.EDT (getEdt)
  36. import qualified Control.Concurrent
  37. import qualified Control.Event as E
  38. import UnliftIO.Directory (doesFileExist, removeFile)
  39. import Data.Time (getCurrentTime)
  40. main :: IO ()
  41. main = do
  42. tok <- TIO.readFile "./auth.secret"
  43. conf <- readConfig "./conf.yaml"
  44. eventSystem <- E.initEventSystem
  45. err <- runDiscord $ def { discordToken = tok
  46. , discordOnStart = onDiscordStart conf eventSystem
  47. , discordOnEnd = liftIO $ putStrLn "Ended"
  48. , discordOnEvent = onDiscordEvent conf eventSystem
  49. , discordOnLog =
  50. \s -> TIO.putStrLn s >> TIO.putStrLn ""
  51. }
  52. TIO.putStrLn err
  53. onDiscordStart :: Config -> E.EventSystem -> DiscordHandler ()
  54. onDiscordStart conf eventSystem = do
  55. let
  56. activity :: Activity
  57. activity = def { activityName = "Doing stuff"
  58. , activityType = ActivityTypeGame
  59. , activityUrl = Nothing
  60. }
  61. opts :: UpdateStatusOpts
  62. opts = UpdateStatusOpts { updateStatusOptsSince = Nothing
  63. , updateStatusOptsGame = Just activity
  64. , updateStatusOptsNewStatus = UpdateStatusOnline
  65. , updateStatusOptsAFK = False
  66. }
  67. sendCommand (UpdateStatus opts)
  68. remindDataExist <- liftIO $ doesFileExist "reminds.data"
  69. when remindDataExist $ do
  70. remindfile <- liftIO $ readFile "reminds.data"
  71. let reminddata :: [Remind]
  72. reminddata = map read $ lines remindfile
  73. now <- liftIO getCurrentTime
  74. mapM_ (\r -> do
  75. withRunInIO $ \runInIO ->
  76. if now > rmdWhen r then
  77. void $ E.addEvent eventSystem (rmdWhen r)
  78. ( do
  79. runInIO ( restCall
  80. $ R.CreateMessage (rmdWhere r)
  81. $ "<@"
  82. `T.append` T.pack (show $rmdWho r)
  83. `T.append` "> **Reminder**\n"
  84. `T.append` rmdWhat r
  85. )
  86. return ()
  87. )
  88. else
  89. pure ()
  90. ) reminddata
  91. liftIO $ removeFile "reminds.data"
  92. onDiscordEvent :: Config -> E.EventSystem -> Event -> DiscordHandler ()
  93. onDiscordEvent conf@Config{..} eventSystem (Ready _ _ _ _ _ _ (PartialApplication i _)) = do
  94. mapM_ (maybe ( return () )
  95. ( void
  96. . restCall
  97. . R.CreateGuildApplicationCommand i configServer
  98. )
  99. )
  100. [ pingCommand
  101. , edtCommand conf
  102. , remindCommand
  103. , groupCommand conf
  104. , helpCommand
  105. ]
  106. let glist = Map.toList configGroups
  107. withRunInIO $ \runInIO -> Cron.execSchedule $ do
  108. Cron.addJob ( runInIO
  109. $ pushgroupedt conf "tomorrow" glist
  110. ) configAutoEDTCronDay
  111. Cron.addJob ( runInIO
  112. $ pushgroupedt conf "week" glist
  113. ) configAutoEDTCronWeek
  114. liftIO $ putStrLn "Started"
  115. onDiscordEvent conf@Config{..} eventSystem
  116. ( InteractionCreate InteractionApplicationCommand
  117. { interactionDataApplicationCommand =
  118. InteractionDataApplicationCommandChatInput
  119. { interactionDataApplicationCommandName = name
  120. , interactionDataApplicationCommandOptions = opts
  121. , ..
  122. }
  123. , interactionChannelId = Just channel
  124. , interactionGuildId = Just guild
  125. , interactionUser = user
  126. , ..
  127. }
  128. ) = do
  129. response <- responseIO
  130. void $ restCall
  131. (R.CreateInteractionResponse interactionId interactionToken response)
  132. where
  133. responseIO = case name of
  134. "ping" -> liftIO $ pingResponse conf
  135. "edt" -> liftIO $ edtResponse conf opts
  136. "remind" -> remindResponse opts eventSystem channel user
  137. "group" -> groupResponse conf user guild opts
  138. "help" -> liftIO helpResponse
  139. _ -> return $ interactionResponseBasic $ "Unhandled Command: " `T.append` name
  140. onDiscordEvent _ _ _ = return ()
  141. pushgroupedt :: Config -> T.Text ->[(T.Text, Group)] -> DiscordHandler ()
  142. pushgroupedt conf@Config{..} day glist = do
  143. mapM_ (\(gn, Group{groupChannel = gc}) -> do
  144. edt <- liftIO $ getEdt conf $ Map.fromList [("group", gn), ("day", day )]
  145. liftIO
  146. $ TIO.putStrLn
  147. $ "Putting out time table for group "
  148. `T.append` gn
  149. `T.append` " in "
  150. `T.append` T.pack (show gc)
  151. `T.append` ":\n"
  152. `T.append` edt
  153. restCall $ R.CreateMessage gc (edt `T.append` "\nAutomatic time table")
  154. return ()
  155. ) glist