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.
228 lines
8.9 KiB
228 lines
8.9 KiB
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE RecordWildCards #-}
|
|
|
|
module Commands where
|
|
|
|
import Commands.EDT ( getEdt )
|
|
import Commands.Reminds ( Remind(..)
|
|
, registerRemind
|
|
, scheduleRemind
|
|
)
|
|
import Conf ( Config(..)
|
|
, Group(..)
|
|
)
|
|
import Control.Event ( EventSystem
|
|
, addEvent
|
|
)
|
|
import Control.Monad ( when )
|
|
import Control.Monad.IO.Class ( liftIO )
|
|
import qualified Data.Map.Strict as Map
|
|
import Data.Maybe ( fromMaybe )
|
|
import qualified Data.Text as T
|
|
import Data.Time ( addUTCTime
|
|
, getCurrentTime
|
|
)
|
|
import Discord ( DiscordHandler
|
|
, restCall
|
|
)
|
|
import Discord.Interactions ( OptionValue(..)
|
|
, Options(..)
|
|
, Choice(..)
|
|
, CreateApplicationCommand(..)
|
|
, OptionDataValue(..)
|
|
, OptionsData(..)
|
|
, InteractionResponse
|
|
, MemberOrUser(..)
|
|
, LocalizedText(..)
|
|
, createChatInput
|
|
, interactionResponseBasic
|
|
)
|
|
import Discord.Requests ( ChannelRequest(..)
|
|
, GuildRequest(..)
|
|
)
|
|
import Discord.Types ( ChannelId
|
|
, GuildId
|
|
, GuildMember(..)
|
|
, Snowflake
|
|
, UTCTime
|
|
, User(..)
|
|
, RoleId(..)
|
|
, DiscordId,
|
|
)
|
|
import UnliftIO ( withRunInIO )
|
|
|
|
groupNames :: Config -> [T.Text]
|
|
groupNames Config {..} = map fst $ Map.toList configGroups
|
|
|
|
pingCommand :: Maybe CreateApplicationCommand
|
|
pingCommand = createChatInput "ping" "pong"
|
|
|
|
pingResponse :: Config -> IO InteractionResponse
|
|
pingResponse _ = return $ interactionResponseBasic "Pong"
|
|
|
|
edtCommand :: Config -> Maybe CreateApplicationCommand
|
|
edtCommand c =
|
|
createChatInput "edt" "Gets the planning for a group"
|
|
>>= \cac -> return $ cac
|
|
{ createOptions =
|
|
Just $ OptionsValues
|
|
[ OptionValueString
|
|
"group"
|
|
Nothing
|
|
"The group for which the planning is requested"
|
|
Nothing
|
|
True
|
|
(Right $ map (\x -> Choice x Nothing x) $ groupNames c)
|
|
Nothing Nothing
|
|
, OptionValueString
|
|
"day"
|
|
Nothing
|
|
"The day(s) for which the planning is requested (today, tomorrow, week or DD/MM/YYYY)"
|
|
Nothing
|
|
False
|
|
(Left False)
|
|
Nothing Nothing
|
|
]
|
|
}
|
|
|
|
parseOpt :: OptionDataValue -> (T.Text, T.Text)
|
|
parseOpt OptionDataValueString { optionDataValueName = name, optionDataValueString = Right val, ..}
|
|
= (name, val)
|
|
parseOpt _ = ("INVALID Option", "INVALID type")
|
|
|
|
edtResponse
|
|
:: Config
|
|
-> Maybe OptionsData
|
|
-> IO InteractionResponse
|
|
edtResponse conf@Config {..} (Just (OptionsDataValues opts))
|
|
= do
|
|
planning <- getEdt conf parsedOpts
|
|
return $ interactionResponseBasic planning
|
|
where
|
|
parsedOpts :: Map.Map T.Text T.Text
|
|
parsedOpts = Map.fromList $ map parseOpt opts
|
|
edtResponse _ _ = return $ interactionResponseBasic
|
|
"The edt command has mandatory params yet you managed not to give any, WOW"
|
|
|
|
remindCommand :: Maybe CreateApplicationCommand
|
|
remindCommand =
|
|
createChatInput "remind" "reminds you of something later on"
|
|
>>= \cac -> return $ cac
|
|
{ createOptions =
|
|
Just $ OptionsValues
|
|
[ OptionValueString "delay" Nothing "delay" Nothing True (Left False) Nothing Nothing
|
|
, OptionValueString "message" Nothing "message" Nothing True (Left False) Nothing Nothing
|
|
]
|
|
}
|
|
|
|
remindResponse
|
|
:: Maybe OptionsData
|
|
-> EventSystem
|
|
-> Discord.Types.ChannelId
|
|
-> MemberOrUser
|
|
-> DiscordHandler InteractionResponse
|
|
remindResponse (Just (OptionsDataValues opts)) evts ch mou
|
|
= do
|
|
let
|
|
userid = case mou of
|
|
MemberOrUser (Left Discord.Types.GuildMember { memberUser = Just Discord.Types.User { userId = uid } })
|
|
-> uid
|
|
MemberOrUser (Right Discord.Types.User { userId = uid }) -> uid
|
|
_ -> error "Couldnt get user id"
|
|
let d = delay'
|
|
now <- liftIO getCurrentTime
|
|
let
|
|
remindDateTime = case T.last d of
|
|
's' -> addUTCTime (fromInteger $ read $ init $ T.unpack d) now
|
|
'm' -> addUTCTime ((* 60) $ fromInteger $ read $ init $ T.unpack d) now
|
|
'h' ->
|
|
addUTCTime ((* 3600) $ fromInteger $ read $ init $ T.unpack d) now
|
|
'd' ->
|
|
addUTCTime ((* 86400) $ fromInteger $ read $ init $ T.unpack d) now
|
|
_ -> now
|
|
if remindDateTime /= now
|
|
then do
|
|
let rmd = Remind { rmdUser = userid
|
|
, rmdChannel = ch
|
|
, rmdMessage = message
|
|
, rmdDatetime = remindDateTime
|
|
}
|
|
scheduleRemind evts rmd
|
|
liftIO $ registerRemind rmd
|
|
return
|
|
$ interactionResponseBasic
|
|
$ "Reminder registered sucessfully for "
|
|
`T.append` T.pack (show remindDateTime)
|
|
else return $ interactionResponseBasic "couldn't parse your delay :/"
|
|
where
|
|
parsedOpts = Map.fromList $ map parseOpt opts
|
|
delay' =
|
|
fromMaybe (error "delay must exist wtf") $ Map.lookup "delay" parsedOpts
|
|
message = fromMaybe (error "message must exist, wtf")
|
|
$ Map.lookup "message" parsedOpts
|
|
remindResponse _ _ _ _ =
|
|
return
|
|
$ interactionResponseBasic
|
|
"The remind command has mandatory params, yet you managed not to give any, WOW"
|
|
|
|
groupCommand :: Config -> Maybe CreateApplicationCommand
|
|
groupCommand c =
|
|
createChatInput "group" "grab your group" >>= \cac ->
|
|
return $ cac
|
|
{ createOptions = Just $ OptionsValues
|
|
[ OptionValueString
|
|
"group" Nothing
|
|
"Your group" Nothing
|
|
True
|
|
(Right $ map (\x -> Choice x Nothing x) $ groupNames c)
|
|
Nothing Nothing
|
|
]
|
|
}
|
|
|
|
groupResponse
|
|
:: Config
|
|
-> MemberOrUser
|
|
-> Discord.Types.GuildId
|
|
-> Maybe OptionsData
|
|
-> DiscordHandler InteractionResponse
|
|
groupResponse c mou gid (Just (OptionsDataValues opts))
|
|
= do
|
|
let
|
|
uid = case mou of
|
|
MemberOrUser (Left Discord.Types.GuildMember { memberUser = Just Discord.Types.User { userId = uid } })
|
|
-> uid
|
|
MemberOrUser (Right Discord.Types.User { userId = uid }) -> uid
|
|
_ -> -1
|
|
let rid =
|
|
groupRole
|
|
$ fromMaybe (error "group must exist")
|
|
$ Map.lookup group
|
|
$ configGroups c
|
|
restCall $ AddGuildMemberRole gid uid rid
|
|
return
|
|
$ interactionResponseBasic
|
|
$ "You are now part of group "
|
|
`T.append` group
|
|
where
|
|
group =
|
|
fromMaybe (error "required option")
|
|
$ Map.lookup "group"
|
|
$ Map.fromList
|
|
$ map parseOpt opts
|
|
groupResponse _ _ _ _ =
|
|
return
|
|
$ interactionResponseBasic
|
|
"the group command has mandatory params, yet you managed not to give any, WOW"
|
|
|
|
helpCommand :: Maybe CreateApplicationCommand
|
|
helpCommand = createChatInput "help" "help"
|
|
|
|
helpResponse :: IO InteractionResponse
|
|
helpResponse =
|
|
return
|
|
. interactionResponseBasic
|
|
$ "**__Help for Bot IUT__**\n\n"
|
|
`T.append` "`/help` shows this help message\n"
|
|
`T.append` "`/group <group>` join a group\n"
|
|
`T.append` "`/remind <time><s|m|h|d> <message>` reminds you of something in the future\n"
|
|
`T.append` "`/edt <group> [week|today|tomorrow|dd/mm/yyyy]` get the planning for group `group` on `day` (`day` defaults to `week`)"
|