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.

167 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. liftIO $ removeFile "reminds.data"
  75. mapM_ (\r -> do
  76. withRunInIO $ \runInIO ->
  77. if now > rmdWhen r then
  78. void $ E.addEvent eventSystem (rmdWhen r)
  79. ( do
  80. runInIO ( restCall
  81. $ R.CreateMessage (rmdWhere r)
  82. $ "<@"
  83. `T.append` T.pack (show $rmdWho r)
  84. `T.append` "> **Reminder**\n"
  85. `T.append` rmdWhat r
  86. )
  87. appendFile "reminds.data" $ show r
  88. return ()
  89. )
  90. else
  91. pure ()
  92. ) reminddata
  93. onDiscordEvent :: Config -> E.EventSystem -> Event -> DiscordHandler ()
  94. onDiscordEvent conf@Config{..} eventSystem (Ready _ _ _ _ _ _ (PartialApplication i _)) = do
  95. mapM_ (maybe ( return () )
  96. ( void
  97. . restCall
  98. . R.CreateGuildApplicationCommand i configServer
  99. )
  100. )
  101. [ pingCommand
  102. , edtCommand conf
  103. , remindCommand
  104. , groupCommand conf
  105. , helpCommand
  106. ]
  107. let glist = Map.toList configGroups
  108. withRunInIO $ \runInIO -> Cron.execSchedule $ do
  109. Cron.addJob ( runInIO
  110. $ pushgroupedt conf "tomorrow" glist
  111. ) configAutoEDTCronDay
  112. Cron.addJob ( runInIO
  113. $ pushgroupedt conf "week" glist
  114. ) configAutoEDTCronWeek
  115. liftIO $ putStrLn "Started"
  116. onDiscordEvent conf@Config{..} eventSystem
  117. ( InteractionCreate InteractionApplicationCommand
  118. { interactionDataApplicationCommand =
  119. InteractionDataApplicationCommandChatInput
  120. { interactionDataApplicationCommandName = name
  121. , interactionDataApplicationCommandOptions = opts
  122. , ..
  123. }
  124. , interactionChannelId = Just channel
  125. , interactionGuildId = Just guild
  126. , interactionUser = user
  127. , ..
  128. }
  129. ) = do
  130. response <- responseIO
  131. void $ restCall
  132. (R.CreateInteractionResponse interactionId interactionToken response)
  133. where
  134. responseIO = case name of
  135. "ping" -> liftIO $ pingResponse conf
  136. "edt" -> liftIO $ edtResponse conf opts
  137. "remind" -> remindResponse opts eventSystem channel user
  138. "group" -> groupResponse conf user guild opts
  139. "help" -> liftIO helpResponse
  140. _ -> return $ interactionResponseBasic $ "Unhandled Command: " `T.append` name
  141. onDiscordEvent _ _ _ = return ()
  142. pushgroupedt :: Config -> T.Text ->[(T.Text, Group)] -> DiscordHandler ()
  143. pushgroupedt conf@Config{..} day glist = do
  144. mapM_ (\(gn, Group{groupChannel = gc}) -> do
  145. edt <- liftIO $ getEdt conf $ Map.fromList [("group", gn), ("day", day )]
  146. liftIO
  147. $ TIO.putStrLn
  148. $ "Putting out time table for group "
  149. `T.append` gn
  150. `T.append` " in "
  151. `T.append` T.pack (show gc)
  152. `T.append` ":\n"
  153. `T.append` edt
  154. restCall $ R.CreateMessage gc (edt `T.append` "\nAutomatic time table")
  155. return ()
  156. ) glist