calamity-0.8.0.0: Calamity/HTTP/Guild.hs
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
-- | Guild endpoints
module Calamity.HTTP.Guild (
GuildRequest (..),
CreateGuildData (..),
ModifyGuildData (..),
ChannelCreateData (..),
ChannelPosition (..),
ListMembersOptions (..),
AddGuildMemberData (..),
ModifyGuildMemberData,
modifyGuildMemberNick,
modifyGuildMemberRoles,
modifyGuildMemberMute,
modifyGuildMemberDeaf,
modifyGuildMemberChannelID,
CreateGuildBanData (..),
ModifyGuildRoleData,
modifyGuildRoleName,
modifyGuildRolePermissions,
modifyGuildRoleColour,
modifyGuildRoleHoist,
modifyGuildRoleMentionable,
ModifyGuildRolePositionsData (..),
) where
import Calamity.HTTP.Internal.Request
import Calamity.HTTP.Internal.Route
import Calamity.Internal.IntColour
import Calamity.Internal.Utils (CalamityToJSON (..), CalamityToJSON' (..), (.=), (.?=))
import Calamity.Types.Model.Channel
import Calamity.Types.Model.Guild
import Calamity.Types.Model.User
import Calamity.Types.Model.Voice
import Calamity.Types.Snowflake
import Data.Aeson qualified as Aeson
import Data.Aeson.KeyMap qualified as K
import Data.Colour (Colour)
import Data.Default.Class
import Data.Text (Text)
import Network.HTTP.Req
import Optics
data CreateGuildData = CreateGuildData
{ name :: Text
, region :: Text
, icon :: Text
, verificationLevel :: Integer -- TODO: enums for these
, defaultMessageNotifications :: Integer
, explicitContentFilter :: Integer
, roles :: [Role]
, channels :: [Partial Channel]
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON CreateGuildData
instance CalamityToJSON' CreateGuildData where
toPairs CreateGuildData {..} =
[ "name" .= name
, "region" .= region
, "icon" .= icon
, "verification_level" .= verificationLevel
, "default_message_notifications" .= defaultMessageNotifications
, "explicit_content_filter" .= explicitContentFilter
, "roles" .= roles
, "channels" .= channels
]
data ModifyGuildData = ModifyGuildData
{ name :: Maybe Text
, region :: Maybe Text
, icon :: Maybe Text
, verificationLevel :: Maybe Integer -- TODO: enums for these
, defaultMessageNotifications :: Maybe Integer
, explicitContentFilter :: Maybe Integer
, afkChannelID :: Maybe (Snowflake GuildChannel)
, afkTimeout :: Maybe Integer
, ownerID :: Maybe (Snowflake User)
, splash :: Maybe Text
, banner :: Maybe Text
, systemChannelID :: Maybe (Snowflake GuildChannel)
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON ModifyGuildData
instance Default ModifyGuildData where
def =
ModifyGuildData
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
Nothing
-- TODO: Make this work properly, a la modifyguildmember
instance CalamityToJSON' ModifyGuildData where
toPairs ModifyGuildData {..} =
[ "name" .?= name
, "region" .?= region
, "icon" .?= icon
, "verification_level" .?= verificationLevel
, "default_message_notifications" .?= defaultMessageNotifications
, "explicit_content_filter" .?= explicitContentFilter
, "afk_timeout" .?= afkTimeout
, "owner_id" .?= ownerID
, "splash" .?= splash
, "banner" .?= banner
, "system_channel_id" .?= systemChannelID
]
data ChannelCreateData = ChannelCreateData
{ name :: Text
, type_ :: Maybe ChannelType
, topic :: Maybe Text
, bitrate :: Maybe Integer
, userLimit :: Maybe Integer
, rateLimitPerUser :: Maybe Integer
, position :: Maybe Integer
, permissionOverwrites :: Maybe [Overwrite]
, parentID :: Maybe (Snowflake Category)
, nsfw :: Maybe Bool
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON ChannelCreateData
instance CalamityToJSON' ChannelCreateData where
toPairs ChannelCreateData {..} =
[ "name" .= name
, "type" .?= type_
, "topic" .?= topic
, "bitrate" .?= bitrate
, "user_limit" .?= userLimit
, "rate_limit_per_user" .?= rateLimitPerUser
, "position" .?= position
, "permission_overwrites" .?= permissionOverwrites
, "parent_id" .?= parentID
, "nsfw" .?= nsfw
]
data ChannelPosition = ChannelPosition
{ id :: Snowflake GuildChannel
, position :: Maybe Integer
, lockPermissions :: Maybe Bool
, parentID :: Snowflake GuildChannel
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON ChannelPosition
instance CalamityToJSON' ChannelPosition where
toPairs ChannelPosition {..} =
[ "id" .= id
, "position" .= position
, "lock_permissions" .= lockPermissions
, "parent_id" .= parentID
]
data ListMembersOptions = ListMembersOptions
{ limit :: Maybe Integer
, after :: Maybe (Snowflake User)
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON ListMembersOptions
instance Default ListMembersOptions where
def = ListMembersOptions Nothing Nothing
instance CalamityToJSON' ListMembersOptions where
toPairs ListMembersOptions {..} =
[ "limit" .?= limit
, "after" .?= after
]
data SearchMembersOptions = SearchMembersOptions
{ limit :: Maybe Integer
, query :: Text
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON SearchMembersOptions
instance CalamityToJSON' SearchMembersOptions where
toPairs SearchMembersOptions {..} =
[ "limit" .?= limit
, "query" .= query
]
data AddGuildMemberData = AddGuildMemberData
{ accessToken :: Text
, nick :: Maybe Text
, roles :: Maybe [Snowflake Role]
, mute :: Maybe Bool
, deaf :: Maybe Bool
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON AddGuildMemberData
instance CalamityToJSON' AddGuildMemberData where
toPairs AddGuildMemberData {..} =
[ "access_token" .= accessToken
, "nick" .?= nick
, "roles" .?= roles
, "mute" .?= mute
, "deaf" .?= deaf
]
{- | Parameters to the Modify Guild Member endpoint.
Use the provided methods (@modifyGuildMemberX@) to create a value with the
field set, use the Semigroup instance to combine modifications.
==== Examples
>>> encode $ modifyGuildMemberNick (Just "test") <> modifyGuildMemberDeaf Nothing
"{\"nick\":\"test\",\"deaf\":null}"
-}
newtype ModifyGuildMemberData = ModifyGuildMemberData Aeson.Object
deriving stock (Show)
deriving newtype (Aeson.ToJSON, Semigroup, Monoid)
modifyGuildMemberNick :: Maybe Text -> ModifyGuildMemberData
modifyGuildMemberNick v = ModifyGuildMemberData $ K.fromList [("nick", Aeson.toJSON v)]
modifyGuildMemberRoles :: Maybe [Snowflake Role] -> ModifyGuildMemberData
modifyGuildMemberRoles v = ModifyGuildMemberData $ K.fromList [("roles", Aeson.toJSON v)]
modifyGuildMemberMute :: Maybe Bool -> ModifyGuildMemberData
modifyGuildMemberMute v = ModifyGuildMemberData $ K.fromList [("mute", Aeson.toJSON v)]
modifyGuildMemberDeaf :: Maybe Bool -> ModifyGuildMemberData
modifyGuildMemberDeaf v = ModifyGuildMemberData $ K.fromList [("deaf", Aeson.toJSON v)]
modifyGuildMemberChannelID :: Maybe (Snowflake VoiceChannel) -> ModifyGuildMemberData
modifyGuildMemberChannelID v = ModifyGuildMemberData $ K.fromList [("channel_id", Aeson.toJSON v)]
data GetGuildBansOptions = GetGuildBansOptions
{ limit :: Maybe Int
, before :: Maybe Int
, after :: Maybe Int
}
deriving (Show)
instance Default GetGuildBansOptions where
def = GetGuildBansOptions Nothing Nothing Nothing
data CreateGuildBanData = CreateGuildBanData
{ deleteMessageDays :: Maybe Integer
, reason :: Maybe Text
}
deriving (Show)
instance Default CreateGuildBanData where
def = CreateGuildBanData Nothing Nothing
{- | Parameters to the Modify Guild Role endpoint.
Use the provided methods (@modifyGuildRoleX@) to create a value with the
field set, use the Semigroup instance to combine parameters.
==== Examples
>>> encode $ modifyGuildRoleName (Just "test") <> modifyGuildRolePermissions Nothing
"{\"name\":\"test\",\"permissions\":null}"
-}
newtype ModifyGuildRoleData = ModifyGuildRoleData Aeson.Object
deriving stock (Show)
deriving newtype (Aeson.ToJSON, Semigroup, Monoid)
modifyGuildRoleName :: Maybe Text -> ModifyGuildRoleData
modifyGuildRoleName v = ModifyGuildRoleData $ K.fromList [("name", Aeson.toJSON v)]
modifyGuildRolePermissions :: Maybe Permissions -> ModifyGuildRoleData
modifyGuildRolePermissions v = ModifyGuildRoleData $ K.fromList [("permissions", Aeson.toJSON v)]
modifyGuildRoleColour :: Maybe (Colour Double) -> ModifyGuildRoleData
modifyGuildRoleColour v = ModifyGuildRoleData $ K.fromList [("colour", Aeson.toJSON (IntColour <$> v))]
modifyGuildRoleHoist :: Maybe Bool -> ModifyGuildRoleData
modifyGuildRoleHoist v = ModifyGuildRoleData $ K.fromList [("hoist", Aeson.toJSON v)]
modifyGuildRoleMentionable :: Maybe Bool -> ModifyGuildRoleData
modifyGuildRoleMentionable v = ModifyGuildRoleData $ K.fromList [("mentionable", Aeson.toJSON v)]
data ModifyGuildRolePositionsData = ModifyGuildRolePositionsData
{ id :: Snowflake Role
, position :: Maybe Integer
}
deriving (Show)
deriving (Aeson.ToJSON) via CalamityToJSON ModifyGuildRolePositionsData
instance CalamityToJSON' ModifyGuildRolePositionsData where
toPairs ModifyGuildRolePositionsData {..} =
[ "id" .= id
, "postition" .?= position
]
data GuildRequest a where
CreateGuild :: CreateGuildData -> GuildRequest Guild
GetGuild :: HasID Guild g => g -> GuildRequest Guild
ModifyGuild :: HasID Guild g => g -> ModifyGuildData -> GuildRequest Guild
DeleteGuild :: HasID Guild g => g -> GuildRequest ()
GetGuildChannels :: HasID Guild g => g -> GuildRequest [Channel]
CreateGuildChannel :: HasID Guild g => g -> ChannelCreateData -> GuildRequest Channel
ModifyGuildChannelPositions :: HasID Guild g => g -> [ChannelPosition] -> GuildRequest ()
GetGuildMember :: (HasID Guild g, HasID User u) => g -> u -> GuildRequest Member
ListGuildMembers :: HasID Guild g => g -> ListMembersOptions -> GuildRequest [Member]
SearchGuildMembers :: HasID Guild g => g -> SearchMembersOptions -> GuildRequest [Member]
AddGuildMember :: (HasID Guild g, HasID User u) => g -> u -> AddGuildMemberData -> GuildRequest (Maybe Member)
ModifyGuildMember :: (HasID Guild g, HasID User u) => g -> u -> ModifyGuildMemberData -> GuildRequest ()
ModifyCurrentUserNick :: HasID Guild g => g -> Maybe Text -> GuildRequest ()
AddGuildMemberRole :: (HasID Guild g, HasID User u, HasID Role r) => g -> u -> r -> GuildRequest ()
RemoveGuildMemberRole :: (HasID Guild g, HasID User u, HasID Role r) => g -> u -> r -> GuildRequest ()
RemoveGuildMember :: (HasID Guild g, HasID User u) => g -> u -> GuildRequest ()
GetGuildBans :: HasID Guild g => g -> GetGuildBansOptions -> GuildRequest [BanData]
GetGuildBan :: (HasID Guild g, HasID User u) => g -> u -> GuildRequest BanData
CreateGuildBan :: (HasID Guild g, HasID User u) => g -> u -> CreateGuildBanData -> GuildRequest ()
RemoveGuildBan :: (HasID Guild g, HasID User u) => g -> u -> GuildRequest ()
GetGuildRoles :: HasID Guild g => g -> GuildRequest [Role]
CreateGuildRole :: HasID Guild g => g -> ModifyGuildRoleData -> GuildRequest Role
ModifyGuildRolePositions :: HasID Guild g => g -> ModifyGuildRolePositionsData -> GuildRequest [Role]
ModifyGuildRole :: (HasID Guild g, HasID Role r) => g -> r -> ModifyGuildRoleData -> GuildRequest Role
DeleteGuildRole :: (HasID Guild g, HasID Role r) => g -> r -> GuildRequest ()
GetGuildPruneCount :: HasID Guild g => g -> Integer -> GuildRequest Integer
BeginGuildPrune :: HasID Guild g => g -> Integer -> Bool -> GuildRequest (Maybe Integer)
GetGuildVoiceRegions :: HasID Guild g => g -> GuildRequest [VoiceRegion]
GetGuildInvites :: HasID Guild g => g -> GuildRequest [Invite]
baseRoute :: Snowflake Guild -> RouteBuilder _
baseRoute id =
mkRouteBuilder // S "guilds" // ID @Guild
& giveID id
instance Request (GuildRequest a) where
type Result (GuildRequest a) = a
route (CreateGuild _) =
mkRouteBuilder // S "guilds"
& buildRoute
route (GetGuild (getID -> gid)) =
baseRoute gid
& buildRoute
route (ModifyGuild (getID -> gid) _) =
baseRoute gid
& buildRoute
route (DeleteGuild (getID -> gid)) =
baseRoute gid
& buildRoute
route (GetGuildChannels (getID -> gid)) =
baseRoute gid // S "channels"
& buildRoute
route (CreateGuildChannel (getID -> gid) _) =
baseRoute gid // S "channels"
& buildRoute
route (ModifyGuildChannelPositions (getID -> gid) _) =
baseRoute gid // S "channels"
& buildRoute
route (GetGuildMember (getID -> gid) (getID @User -> uid)) =
baseRoute gid // S "members" // ID @User
& giveID uid
& buildRoute
route (ListGuildMembers (getID -> gid) _) =
baseRoute gid // S "members"
& buildRoute
route (SearchGuildMembers (getID -> gid) _) =
baseRoute gid // S "members" // S "search"
& buildRoute
route (AddGuildMember (getID -> gid) (getID @User -> uid) _) =
baseRoute gid // S "members" // ID @User
& giveID uid
& buildRoute
route (ModifyGuildMember (getID -> gid) (getID @User -> uid) _) =
baseRoute gid // S "members" // ID @User
& giveID uid
& buildRoute
route (ModifyCurrentUserNick (getID -> gid) _) =
baseRoute gid // S "members" // S "@me" // S "nick"
& buildRoute
route (AddGuildMemberRole (getID -> gid) (getID @User -> uid) (getID @Role -> rid)) =
baseRoute gid // S "members" // ID @User // S "roles" // ID @Role
& giveID uid
& giveID rid
& buildRoute
route (RemoveGuildMemberRole (getID -> gid) (getID @User -> uid) (getID @Role -> rid)) =
baseRoute gid // S "members" // ID @User // S "roles" // ID @Role
& giveID uid
& giveID rid
& buildRoute
route (RemoveGuildMember (getID -> gid) (getID @User -> uid)) =
baseRoute gid // S "members" // ID @User
& giveID uid
& buildRoute
route (GetGuildBans (getID -> gid) _) =
baseRoute gid // S "bans"
& buildRoute
route (GetGuildBan (getID -> gid) (getID @User -> uid)) =
baseRoute gid // S "bans" // ID @User
& giveID uid
& buildRoute
route (CreateGuildBan (getID -> gid) (getID @User -> uid) _) =
baseRoute gid // S "bans" // ID @User
& giveID uid
& buildRoute
route (RemoveGuildBan (getID -> gid) (getID @User -> uid)) =
baseRoute gid // S "bans" // ID @User
& giveID uid
& buildRoute
route (GetGuildRoles (getID -> gid)) =
baseRoute gid // S "roles"
& buildRoute
route (CreateGuildRole (getID -> gid) _) =
baseRoute gid // S "roles"
& buildRoute
route (ModifyGuildRolePositions (getID -> gid) _) =
baseRoute gid // S "roles"
& buildRoute
route (ModifyGuildRole (getID -> gid) (getID @Role -> rid) _) =
baseRoute gid // S "roles" // ID @Role
& giveID rid
& buildRoute
route (DeleteGuildRole (getID -> gid) (getID @Role -> rid)) =
baseRoute gid // S "roles" // ID @Role
& giveID rid
& buildRoute
route (GetGuildPruneCount (getID -> gid) _) =
baseRoute gid // S "prune"
& buildRoute
route (BeginGuildPrune (getID -> gid) _ _) =
baseRoute gid // S "prune"
& buildRoute
route (GetGuildVoiceRegions (getID -> gid)) =
baseRoute gid // S "regions"
& buildRoute
route (GetGuildInvites (getID -> gid)) =
baseRoute gid // S "invites"
& buildRoute
action (CreateGuild o) = postWith' (ReqBodyJson o)
action (GetGuild _) = getWith
action (ModifyGuild _ o) = patchWith' (ReqBodyJson o)
action (DeleteGuild _) = deleteWith
action (GetGuildChannels _) = getWith
action (CreateGuildChannel _ o) = postWith' (ReqBodyJson o)
action (ModifyGuildChannelPositions _ o) = postWith' (ReqBodyJson o)
action (GetGuildMember _ _) = getWith
action (ListGuildMembers _ ListMembersOptions {limit, after}) =
getWithP
("limit" =:? limit <> "after" =:? (fromSnowflake <$> after))
action (SearchGuildMembers _ SearchMembersOptions {limit, query}) =
getWithP
("limit" =:? limit <> "query" =: query)
action (AddGuildMember _ _ o) = putWith' (ReqBodyJson o)
action (ModifyGuildMember _ _ o) = patchWith' (ReqBodyJson o)
action (ModifyCurrentUserNick _ nick) = patchWith' (ReqBodyJson $ Aeson.object ["nick" Aeson..= nick])
action AddGuildMemberRole {} = putEmpty
action RemoveGuildMemberRole {} = deleteWith
action (RemoveGuildMember _ _) = deleteWith
action (GetGuildBans _ GetGuildBansOptions {limit, before, after}) =
getWithP
("limit" =:? limit <> "before" =:? before <> "after" =:? after)
action (GetGuildBan _ _) = getWith
action (CreateGuildBan _ _ CreateGuildBanData {deleteMessageDays}) =
putEmptyP
("delete_message_days" =:? deleteMessageDays)
action (RemoveGuildBan _ _) = deleteWith
action (GetGuildRoles _) = getWith
action (CreateGuildRole _ o) = postWith' (ReqBodyJson o)
action (ModifyGuildRolePositions _ o) = patchWith' (ReqBodyJson o)
action (ModifyGuildRole _ _ o) = patchWith' (ReqBodyJson o)
action (DeleteGuildRole _ _) = deleteWith
action (GetGuildPruneCount _ d) = getWithP ("days" =: d)
action (BeginGuildPrune _ d r) = postEmptyP ("days" =: d <> "compute_prune_count" =: r)
action (GetGuildVoiceRegions _) = getWith
action (GetGuildInvites _) = getWith
-- this is a bit of a hack
-- TODO: add something to allow for contextual parsing
modifyResponse _ = Prelude.id
$(makeFieldLabelsNoPrefix ''CreateGuildData)
$(makeFieldLabelsNoPrefix ''ModifyGuildData)
$(makeFieldLabelsNoPrefix ''ChannelCreateData)
$(makeFieldLabelsNoPrefix ''ChannelPosition)
$(makeFieldLabelsNoPrefix ''ListMembersOptions)
$(makeFieldLabelsNoPrefix ''AddGuildMemberData)
$(makeFieldLabelsNoPrefix ''ModifyGuildRolePositionsData)
$(makeFieldLabelsNoPrefix ''CreateGuildBanData)