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.

263 lines
8.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
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE RecordWildCards #-}
  3. module Commands where
  4. import Discord ( restCall, DiscordHandler )
  5. import Discord.Types ( ChannelId
  6. , User(..)
  7. , GuildMember(..)
  8. , GuildId, UTCTime, Snowflake
  9. )
  10. import Discord.Interactions ( interactionResponseBasic
  11. , createApplicationCommandChatInput
  12. , MemberOrUser(..)
  13. , InteractionDataApplicationCommandOptions(..)
  14. , InteractionDataApplicationCommandOptionValue(..)
  15. , Choice(..)
  16. , ApplicationCommandOptionValue(..)
  17. , ApplicationCommandOptions(..)
  18. , InteractionResponse
  19. , CreateApplicationCommand(..)
  20. )
  21. import Discord.Requests ( ChannelRequest(..)
  22. , GuildRequest(..)
  23. )
  24. import Control.Event ( EventSystem, addEvent )
  25. import Control.Monad ( when )
  26. import Control.Monad.IO.Class ( liftIO )
  27. import qualified Data.Map.Strict as Map
  28. import Data.Maybe ( fromMaybe )
  29. import Data.Time ( getCurrentTime, addUTCTime )
  30. import qualified Data.Text as T
  31. import UnliftIO ( withRunInIO )
  32. import Commands.EDT ( getEdt )
  33. import Conf ( Config(..), Group(..) )
  34. groupNames :: Config -> [T.Text]
  35. groupNames Config{..} = map fst $ Map.toList configGroups
  36. pingCommand :: Maybe CreateApplicationCommand
  37. pingCommand =
  38. createApplicationCommandChatInput
  39. "ping"
  40. "pong"
  41. pingResponse :: Config -> IO InteractionResponse
  42. pingResponse _ = return $ interactionResponseBasic "Pong"
  43. edtCommand :: Config -> Maybe CreateApplicationCommand
  44. edtCommand c =
  45. createApplicationCommandChatInput "edt" "Gets the planning for a group"
  46. >>=
  47. \cac ->
  48. return
  49. $ cac
  50. { createApplicationCommandOptions =
  51. Just
  52. $ ApplicationCommandOptionsValues
  53. [ ApplicationCommandOptionValueString
  54. "group"
  55. "The group for which the planning is requested"
  56. True (Right $ map (\x -> Choice x x) $ groupNames c)
  57. , ApplicationCommandOptionValueString
  58. "day"
  59. ("The day(s) for which the planning is requested "
  60. `T.append` "(today, tomorrow, week or DD/MM/YYYY)")
  61. False
  62. (Left False)
  63. ]
  64. }
  65. parseOpt :: InteractionDataApplicationCommandOptionValue -> (T.Text, T.Text)
  66. parseOpt InteractionDataApplicationCommandOptionValueString
  67. { interactionDataApplicationCommandOptionValueName = name
  68. , interactionDataApplicationCommandOptionValueStringValue =
  69. Right val
  70. , ..
  71. } =
  72. (name, val)
  73. parseOpt _ = ("INVALID Option", "INVALID type")
  74. edtResponse :: Config
  75. -> Maybe InteractionDataApplicationCommandOptions
  76. -> IO InteractionResponse
  77. edtResponse conf@Config{..} (Just (InteractionDataApplicationCommandOptionsValues opts)) = do
  78. planning <- getEdt conf parsedOpts
  79. return $ interactionResponseBasic planning
  80. where
  81. parsedOpts :: Map.Map T.Text T.Text
  82. parsedOpts = Map.fromList $ map parseOpt opts
  83. edtResponse _ _ =
  84. return $ interactionResponseBasic
  85. "The edt command has mandatory params yet you managed not to give any, WOW"
  86. remindCommand :: Maybe CreateApplicationCommand
  87. remindCommand =
  88. createApplicationCommandChatInput "remind" "reminds you of something later on"
  89. >>=
  90. \cac ->
  91. return
  92. $ cac
  93. { createApplicationCommandOptions =
  94. Just
  95. $ ApplicationCommandOptionsValues
  96. [ ApplicationCommandOptionValueString "delay" "delay" True (Left False)
  97. , ApplicationCommandOptionValueString "message" "message" True (Left False)
  98. ]
  99. }
  100. data Remind = Remind { rmdWhen :: UTCTime
  101. , rmdWhat :: T.Text
  102. , rmdWhere :: Snowflake
  103. , rmdWho :: Snowflake
  104. }
  105. deriving (Read, Show, Eq)
  106. remindResponse :: Maybe InteractionDataApplicationCommandOptions
  107. -> EventSystem
  108. -> ChannelId
  109. -> MemberOrUser
  110. -> DiscordHandler InteractionResponse
  111. remindResponse (Just (InteractionDataApplicationCommandOptionsValues opts)) evts ch mou = do
  112. let userid = case mou of
  113. MemberOrUser (Left GuildMember{memberUser = Just User{userId = uid}}) -> uid
  114. MemberOrUser (Right User{userId = uid}) -> uid
  115. _ -> error "Couldnt get user id"
  116. let d = delay'
  117. now <- liftIO getCurrentTime
  118. let remindDateTime =
  119. case T.last d of
  120. 's' -> addUTCTime ( fromInteger
  121. $ read
  122. $ init
  123. $ T.unpack d
  124. ) now
  125. 'm' -> addUTCTime ( (*60)
  126. $ fromInteger
  127. $ read
  128. $ init
  129. $ T.unpack d
  130. ) now
  131. 'h' -> addUTCTime ( (*3600)
  132. $ fromInteger
  133. $ read
  134. $ init
  135. $ T.unpack d
  136. ) now
  137. 'd' -> addUTCTime ( (*86400)
  138. $ fromInteger
  139. $ read
  140. $ init
  141. $ T.unpack d
  142. ) now
  143. _ -> now
  144. if remindDateTime /= now
  145. then
  146. ( do
  147. withRunInIO $ \runInIO ->
  148. addEvent evts remindDateTime
  149. ( do
  150. runInIO ( restCall
  151. $ CreateMessage ch
  152. $ "<@"
  153. `T.append` T.pack (show userid)
  154. `T.append` "> **Reminder**\n"
  155. `T.append` message
  156. )
  157. return ()
  158. )
  159. liftIO $ appendFile "reminds.data" $ show (Remind remindDateTime message ch userid) ++ "\n"
  160. return
  161. $ interactionResponseBasic
  162. $ "Reminder registered sucessfully for "
  163. `T.append` T.pack (show remindDateTime)
  164. )
  165. else
  166. return $ interactionResponseBasic "couldn't parse your delay :/"
  167. where
  168. parsedOpts = Map.fromList $ map parseOpt opts
  169. delay' =
  170. fromMaybe (error "delay must exist wtf")
  171. $ Map.lookup "delay" parsedOpts
  172. message =
  173. fromMaybe (error "message must exist, wtf")
  174. $ Map.lookup "message" parsedOpts
  175. remindResponse _ _ _ _= return $ interactionResponseBasic
  176. "The remind command has mandatory params, yet you managed not to give any, WOW"
  177. groupCommand :: Config -> Maybe CreateApplicationCommand
  178. groupCommand c =
  179. createApplicationCommandChatInput "group" "grab your group"
  180. >>=
  181. \cac ->
  182. return
  183. $ cac
  184. { createApplicationCommandOptions =
  185. Just
  186. $ ApplicationCommandOptionsValues
  187. [ ApplicationCommandOptionValueString
  188. "group"
  189. "Your group"
  190. True
  191. (Right $ map (\x -> Choice x x) $ groupNames c)
  192. ]
  193. }
  194. groupResponse :: Config
  195. -> MemberOrUser
  196. -> GuildId
  197. -> Maybe InteractionDataApplicationCommandOptions
  198. -> DiscordHandler InteractionResponse
  199. groupResponse c
  200. mou
  201. gid
  202. (Just (InteractionDataApplicationCommandOptionsValues opts)) =
  203. do
  204. let uid = case mou of
  205. MemberOrUser (Left GuildMember{memberUser = Just User{userId = uid}}) -> uid
  206. MemberOrUser (Right User{userId = uid}) -> uid
  207. _ -> -1
  208. let rid =
  209. groupRole
  210. $ fromMaybe (error "group must exist")
  211. $ Map.lookup group
  212. $ configGroups c
  213. restCall $ AddGuildMemberRole gid uid rid
  214. return $ interactionResponseBasic $
  215. "You are now part of group " `T.append` group
  216. where
  217. group =
  218. fromMaybe (error "required option")
  219. $ Map.lookup "group"
  220. $ Map.fromList
  221. $ map parseOpt opts
  222. groupResponse _ _ _ _ =
  223. return $ interactionResponseBasic
  224. "the group command has mandatory params, yet you managed not to give any, WOW"
  225. helpCommand :: Maybe CreateApplicationCommand
  226. helpCommand =
  227. createApplicationCommandChatInput
  228. "help"
  229. "help"
  230. helpResponse :: IO InteractionResponse
  231. helpResponse = return . interactionResponseBasic
  232. $ "**__Help for Bot IUT__**\n\n"
  233. `T.append` "`/help` shows this help message\n"
  234. `T.append` "`/group <group>` join a group\n"
  235. `T.append` "`/remind <time><s|m|h|d> <message>` reminds you of something in the future\n"
  236. `T.append` "`/edt <group> [week|today|tomorrow|dd/mm/yyyy]` get the planning for group `group` on `day` (`day` defaults to `week`)"