discord-haskell 1.12.0 → 1.12.1
raw patch · 16 files changed
+916/−318 lines, 16 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Discord.Internal.Types.Events: PresenceInfo :: UserId -> [RoleId] -> GuildId -> Text -> PresenceInfo
- Discord.Internal.Types.Events: [presenceGuildId] :: PresenceInfo -> GuildId
- Discord.Internal.Types.Events: [presenceRoles] :: PresenceInfo -> [RoleId]
- Discord.Internal.Types.Events: [presenceStatus] :: PresenceInfo -> Text
- Discord.Internal.Types.Events: [presenceUserId] :: PresenceInfo -> UserId
- Discord.Internal.Types.Events: data PresenceInfo
- Discord.Internal.Types.Events: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Events.PresenceInfo
- Discord.Internal.Types.Events: instance GHC.Classes.Eq Discord.Internal.Types.Events.PresenceInfo
- Discord.Internal.Types.Events: instance GHC.Classes.Ord Discord.Internal.Types.Events.PresenceInfo
- Discord.Internal.Types.Events: instance GHC.Read.Read Discord.Internal.Types.Events.PresenceInfo
- Discord.Internal.Types.Events: instance GHC.Show.Show Discord.Internal.Types.Events.PresenceInfo
- Discord.Internal.Types.Gateway: Activity :: Text -> ActivityType -> Maybe Text -> Activity
- Discord.Internal.Types.Gateway: ActivityTypeCompeting :: ActivityType
- Discord.Internal.Types.Gateway: ActivityTypeGame :: ActivityType
- Discord.Internal.Types.Gateway: ActivityTypeListening :: ActivityType
- Discord.Internal.Types.Gateway: ActivityTypeStreaming :: ActivityType
- Discord.Internal.Types.Gateway: [activityName] :: Activity -> Text
- Discord.Internal.Types.Gateway: [activityType] :: Activity -> ActivityType
- Discord.Internal.Types.Gateway: [activityUrl] :: Activity -> Maybe Text
- Discord.Internal.Types.Gateway: activityTypeId :: ActivityType -> Int
- Discord.Internal.Types.Gateway: data Activity
- Discord.Internal.Types.Gateway: data ActivityType
- Discord.Internal.Types.Gateway: instance GHC.Classes.Eq Discord.Internal.Types.Gateway.Activity
- Discord.Internal.Types.Gateway: instance GHC.Classes.Eq Discord.Internal.Types.Gateway.ActivityType
- Discord.Internal.Types.Gateway: instance GHC.Classes.Ord Discord.Internal.Types.Gateway.Activity
- Discord.Internal.Types.Gateway: instance GHC.Classes.Ord Discord.Internal.Types.Gateway.ActivityType
- Discord.Internal.Types.Gateway: instance GHC.Read.Read Discord.Internal.Types.Gateway.Activity
- Discord.Internal.Types.Gateway: instance GHC.Read.Read Discord.Internal.Types.Gateway.ActivityType
- Discord.Internal.Types.Gateway: instance GHC.Show.Show Discord.Internal.Types.Gateway.Activity
- Discord.Internal.Types.Gateway: instance GHC.Show.Show Discord.Internal.Types.Gateway.ActivityType
- Discord.Internal.Types.Guild: GuildInfo :: UTCTime -> Bool -> Integer -> [GuildMember] -> [Channel] -> GuildInfo
- Discord.Internal.Types.Guild: [guildRegion] :: Guild -> Maybe Text
- Discord.Internal.Types.Guild: data GuildInfo
- Discord.Internal.Types.Guild: data GuildUnavailable
- Discord.Internal.Types.Guild: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Guild.GuildInfo
- Discord.Internal.Types.Guild: instance GHC.Classes.Eq Discord.Internal.Types.Guild.GuildInfo
- Discord.Internal.Types.Guild: instance GHC.Classes.Ord Discord.Internal.Types.Guild.GuildInfo
- Discord.Internal.Types.Guild: instance GHC.Read.Read Discord.Internal.Types.Guild.GuildInfo
- Discord.Internal.Types.Guild: instance GHC.Show.Show Discord.Internal.Types.Guild.GuildInfo
- Discord.Types: GuildInfo :: UTCTime -> Bool -> Integer -> [GuildMember] -> [Channel] -> GuildInfo
- Discord.Types: [guildRegion] :: Guild -> Maybe Text
- Discord.Types: [presenceRoles] :: PresenceInfo -> [RoleId]
- Discord.Types: activityTypeId :: ActivityType -> Int
- Discord.Types: data GuildInfo
- Discord.Types: data GuildUnavailable
+ Discord.Internal.Rest.Channel: ListThreads :: [Channel] -> [ThreadMember] -> Bool -> ListThreads
+ Discord.Internal.Rest.Channel: StartThreadNoMessageOpts :: StartThreadOpts -> Integer -> Maybe Bool -> StartThreadNoMessageOpts
+ Discord.Internal.Rest.Channel: StartThreadOpts :: Text -> Maybe Integer -> Maybe Integer -> StartThreadOpts
+ Discord.Internal.Rest.Channel: [AddThreadMember] :: ChannelId -> UserId -> ChannelRequest ()
+ Discord.Internal.Rest.Channel: [GetThreadMember] :: ChannelId -> UserId -> ChannelRequest ThreadMember
+ Discord.Internal.Rest.Channel: [JoinThread] :: ChannelId -> ChannelRequest ()
+ Discord.Internal.Rest.Channel: [LeaveThread] :: ChannelId -> ChannelRequest ()
+ Discord.Internal.Rest.Channel: [ListJoinedPrivateArchivedThreads] :: ChannelId -> (Maybe UTCTime, Maybe Integer) -> ChannelRequest ListThreads
+ Discord.Internal.Rest.Channel: [ListPrivateArchivedThreads] :: ChannelId -> (Maybe UTCTime, Maybe Integer) -> ChannelRequest ListThreads
+ Discord.Internal.Rest.Channel: [ListPublicArchivedThreads] :: ChannelId -> (Maybe UTCTime, Maybe Integer) -> ChannelRequest ListThreads
+ Discord.Internal.Rest.Channel: [ListThreadMembers] :: ChannelId -> ChannelRequest [ThreadMember]
+ Discord.Internal.Rest.Channel: [RemoveThreadMember] :: ChannelId -> UserId -> ChannelRequest ()
+ Discord.Internal.Rest.Channel: [StartThreadFromMessage] :: ChannelId -> MessageId -> StartThreadOpts -> ChannelRequest Channel
+ Discord.Internal.Rest.Channel: [StartThreadNoMessage] :: ChannelId -> StartThreadNoMessageOpts -> ChannelRequest Channel
+ Discord.Internal.Rest.Channel: [listThreadsHasMore] :: ListThreads -> Bool
+ Discord.Internal.Rest.Channel: [listThreadsMembers] :: ListThreads -> [ThreadMember]
+ Discord.Internal.Rest.Channel: [listThreadsThreads] :: ListThreads -> [Channel]
+ Discord.Internal.Rest.Channel: [startThreadAutoArchive] :: StartThreadOpts -> Maybe Integer
+ Discord.Internal.Rest.Channel: [startThreadName] :: StartThreadOpts -> Text
+ Discord.Internal.Rest.Channel: [startThreadNoMessageBaseOpts] :: StartThreadNoMessageOpts -> StartThreadOpts
+ Discord.Internal.Rest.Channel: [startThreadNoMessageInvitable] :: StartThreadNoMessageOpts -> Maybe Bool
+ Discord.Internal.Rest.Channel: [startThreadNoMessageType] :: StartThreadNoMessageOpts -> Integer
+ Discord.Internal.Rest.Channel: [startThreadRateLimit] :: StartThreadOpts -> Maybe Integer
+ Discord.Internal.Rest.Channel: data ListThreads
+ Discord.Internal.Rest.Channel: data StartThreadNoMessageOpts
+ Discord.Internal.Rest.Channel: data StartThreadOpts
+ Discord.Internal.Rest.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Rest.Channel.ListThreads
+ Discord.Internal.Rest.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Rest.Channel.ListThreads
+ Discord.Internal.Rest.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Rest.Channel.StartThreadNoMessageOpts
+ Discord.Internal.Rest.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Rest.Channel.StartThreadOpts
+ Discord.Internal.Rest.Channel: instance GHC.Classes.Eq Discord.Internal.Rest.Channel.ListThreads
+ Discord.Internal.Rest.Channel: instance GHC.Classes.Eq Discord.Internal.Rest.Channel.StartThreadNoMessageOpts
+ Discord.Internal.Rest.Channel: instance GHC.Classes.Eq Discord.Internal.Rest.Channel.StartThreadOpts
+ Discord.Internal.Rest.Channel: instance GHC.Classes.Ord Discord.Internal.Rest.Channel.ListThreads
+ Discord.Internal.Rest.Channel: instance GHC.Classes.Ord Discord.Internal.Rest.Channel.StartThreadNoMessageOpts
+ Discord.Internal.Rest.Channel: instance GHC.Classes.Ord Discord.Internal.Rest.Channel.StartThreadOpts
+ Discord.Internal.Rest.Channel: instance GHC.Read.Read Discord.Internal.Rest.Channel.ListThreads
+ Discord.Internal.Rest.Channel: instance GHC.Read.Read Discord.Internal.Rest.Channel.StartThreadNoMessageOpts
+ Discord.Internal.Rest.Channel: instance GHC.Read.Read Discord.Internal.Rest.Channel.StartThreadOpts
+ Discord.Internal.Rest.Channel: instance GHC.Show.Show Discord.Internal.Rest.Channel.ListThreads
+ Discord.Internal.Rest.Channel: instance GHC.Show.Show Discord.Internal.Rest.Channel.StartThreadNoMessageOpts
+ Discord.Internal.Rest.Channel: instance GHC.Show.Show Discord.Internal.Rest.Channel.StartThreadOpts
+ Discord.Internal.Rest.Prelude: apiVersion :: Text
+ Discord.Internal.Types.ApplicationCommands: instance GHC.Classes.Ord a => GHC.Classes.Ord (Discord.Internal.Types.ApplicationCommands.Choice a)
+ Discord.Internal.Types.Channel: ChannelNewsThread :: ChannelId -> GuildId -> Maybe Text -> Maybe Integer -> Maybe MessageId -> Maybe ParentId -> Maybe ThreadMetadata -> Maybe ThreadMember -> Channel
+ Discord.Internal.Types.Channel: ChannelPrivateThread :: ChannelId -> GuildId -> Maybe Text -> Maybe Integer -> Maybe MessageId -> Maybe ParentId -> Maybe ThreadMetadata -> Maybe ThreadMember -> Channel
+ Discord.Internal.Types.Channel: ChannelPublicThread :: ChannelId -> GuildId -> Maybe Text -> Maybe Integer -> Maybe MessageId -> Maybe ParentId -> Maybe ThreadMetadata -> Maybe ThreadMember -> Channel
+ Discord.Internal.Types.Channel: ThreadListSyncFields :: GuildId -> Maybe [ChannelId] -> [Channel] -> [ThreadMember] -> ThreadListSyncFields
+ Discord.Internal.Types.Channel: ThreadMember :: Maybe ChannelId -> Maybe UserId -> UTCTime -> Integer -> ThreadMember
+ Discord.Internal.Types.Channel: ThreadMembersUpdateFields :: ChannelId -> GuildId -> Integer -> Maybe [ThreadMember] -> Maybe [UserId] -> ThreadMembersUpdateFields
+ Discord.Internal.Types.Channel: ThreadMetadata :: Bool -> Integer -> UTCTime -> Bool -> Maybe Bool -> Maybe UTCTime -> ThreadMetadata
+ Discord.Internal.Types.Channel: [channelThreadMember] :: Channel -> Maybe ThreadMember
+ Discord.Internal.Types.Channel: [channelThreadMetadata] :: Channel -> Maybe ThreadMetadata
+ Discord.Internal.Types.Channel: [channelThreadName] :: Channel -> Maybe Text
+ Discord.Internal.Types.Channel: [channelUserRateLimitThread] :: Channel -> Maybe Integer
+ Discord.Internal.Types.Channel: [threadListSyncFieldsChannelIds] :: ThreadListSyncFields -> Maybe [ChannelId]
+ Discord.Internal.Types.Channel: [threadListSyncFieldsGuildId] :: ThreadListSyncFields -> GuildId
+ Discord.Internal.Types.Channel: [threadListSyncFieldsThreadMembers] :: ThreadListSyncFields -> [ThreadMember]
+ Discord.Internal.Types.Channel: [threadListSyncFieldsThreads] :: ThreadListSyncFields -> [Channel]
+ Discord.Internal.Types.Channel: [threadMemberFlags] :: ThreadMember -> Integer
+ Discord.Internal.Types.Channel: [threadMemberJoinTime] :: ThreadMember -> UTCTime
+ Discord.Internal.Types.Channel: [threadMemberThreadId] :: ThreadMember -> Maybe ChannelId
+ Discord.Internal.Types.Channel: [threadMemberUserId] :: ThreadMember -> Maybe UserId
+ Discord.Internal.Types.Channel: [threadMembersUpdateFieldsAddedMembers] :: ThreadMembersUpdateFields -> Maybe [ThreadMember]
+ Discord.Internal.Types.Channel: [threadMembersUpdateFieldsGuildId] :: ThreadMembersUpdateFields -> GuildId
+ Discord.Internal.Types.Channel: [threadMembersUpdateFieldsMemberCount] :: ThreadMembersUpdateFields -> Integer
+ Discord.Internal.Types.Channel: [threadMembersUpdateFieldsRemovedMembers] :: ThreadMembersUpdateFields -> Maybe [UserId]
+ Discord.Internal.Types.Channel: [threadMembersUpdateFieldsThreadId] :: ThreadMembersUpdateFields -> ChannelId
+ Discord.Internal.Types.Channel: [threadMetadataArchiveTime] :: ThreadMetadata -> UTCTime
+ Discord.Internal.Types.Channel: [threadMetadataArchived] :: ThreadMetadata -> Bool
+ Discord.Internal.Types.Channel: [threadMetadataAutoArchive] :: ThreadMetadata -> Integer
+ Discord.Internal.Types.Channel: [threadMetadataCreateTime] :: ThreadMetadata -> Maybe UTCTime
+ Discord.Internal.Types.Channel: [threadMetadataInvitable] :: ThreadMetadata -> Maybe Bool
+ Discord.Internal.Types.Channel: [threadMetadataLocked] :: ThreadMetadata -> Bool
+ Discord.Internal.Types.Channel: data ThreadListSyncFields
+ Discord.Internal.Types.Channel: data ThreadMember
+ Discord.Internal.Types.Channel: data ThreadMembersUpdateFields
+ Discord.Internal.Types.Channel: data ThreadMetadata
+ Discord.Internal.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Channel.ThreadListSyncFields
+ Discord.Internal.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Channel.ThreadMember
+ Discord.Internal.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Channel.ThreadMembersUpdateFields
+ Discord.Internal.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Channel.ThreadMetadata
+ Discord.Internal.Types.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Channel.ThreadMember
+ Discord.Internal.Types.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Channel.ThreadMetadata
+ Discord.Internal.Types.Channel: instance GHC.Classes.Eq Discord.Internal.Types.Channel.ThreadListSyncFields
+ Discord.Internal.Types.Channel: instance GHC.Classes.Eq Discord.Internal.Types.Channel.ThreadMember
+ Discord.Internal.Types.Channel: instance GHC.Classes.Eq Discord.Internal.Types.Channel.ThreadMembersUpdateFields
+ Discord.Internal.Types.Channel: instance GHC.Classes.Eq Discord.Internal.Types.Channel.ThreadMetadata
+ Discord.Internal.Types.Channel: instance GHC.Classes.Ord Discord.Internal.Types.Channel.ThreadListSyncFields
+ Discord.Internal.Types.Channel: instance GHC.Classes.Ord Discord.Internal.Types.Channel.ThreadMember
+ Discord.Internal.Types.Channel: instance GHC.Classes.Ord Discord.Internal.Types.Channel.ThreadMembersUpdateFields
+ Discord.Internal.Types.Channel: instance GHC.Classes.Ord Discord.Internal.Types.Channel.ThreadMetadata
+ Discord.Internal.Types.Channel: instance GHC.Read.Read Discord.Internal.Types.Channel.ThreadListSyncFields
+ Discord.Internal.Types.Channel: instance GHC.Read.Read Discord.Internal.Types.Channel.ThreadMember
+ Discord.Internal.Types.Channel: instance GHC.Read.Read Discord.Internal.Types.Channel.ThreadMembersUpdateFields
+ Discord.Internal.Types.Channel: instance GHC.Read.Read Discord.Internal.Types.Channel.ThreadMetadata
+ Discord.Internal.Types.Channel: instance GHC.Show.Show Discord.Internal.Types.Channel.ThreadListSyncFields
+ Discord.Internal.Types.Channel: instance GHC.Show.Show Discord.Internal.Types.Channel.ThreadMember
+ Discord.Internal.Types.Channel: instance GHC.Show.Show Discord.Internal.Types.Channel.ThreadMembersUpdateFields
+ Discord.Internal.Types.Channel: instance GHC.Show.Show Discord.Internal.Types.Channel.ThreadMetadata
+ Discord.Internal.Types.Components: ComponentTextInput :: Text -> Bool -> Text -> Maybe Integer -> Maybe Integer -> Bool -> Text -> Text -> ComponentTextInput
+ Discord.Internal.Types.Components: [componentTextInputCustomId] :: ComponentTextInput -> Text
+ Discord.Internal.Types.Components: [componentTextInputIsParagraph] :: ComponentTextInput -> Bool
+ Discord.Internal.Types.Components: [componentTextInputLabel] :: ComponentTextInput -> Text
+ Discord.Internal.Types.Components: [componentTextInputMaxLength] :: ComponentTextInput -> Maybe Integer
+ Discord.Internal.Types.Components: [componentTextInputMinLength] :: ComponentTextInput -> Maybe Integer
+ Discord.Internal.Types.Components: [componentTextInputPlaceholder] :: ComponentTextInput -> Text
+ Discord.Internal.Types.Components: [componentTextInputRequired] :: ComponentTextInput -> Bool
+ Discord.Internal.Types.Components: [componentTextInputValue] :: ComponentTextInput -> Text
+ Discord.Internal.Types.Components: data ComponentTextInput
+ Discord.Internal.Types.Components: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Components.ComponentTextInput
+ Discord.Internal.Types.Components: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Components.ComponentTextInput
+ Discord.Internal.Types.Components: instance GHC.Classes.Eq Discord.Internal.Types.Components.ComponentTextInput
+ Discord.Internal.Types.Components: instance GHC.Classes.Ord Discord.Internal.Types.Components.ComponentTextInput
+ Discord.Internal.Types.Components: instance GHC.Read.Read Discord.Internal.Types.Components.ComponentTextInput
+ Discord.Internal.Types.Components: instance GHC.Show.Show Discord.Internal.Types.Components.ComponentTextInput
+ Discord.Internal.Types.Components: mkComponentTextInput :: Text -> Text -> ComponentTextInput
+ Discord.Internal.Types.Events: InternalThreadCreate :: Channel -> EventInternalParse
+ Discord.Internal.Types.Events: InternalThreadDelete :: Channel -> EventInternalParse
+ Discord.Internal.Types.Events: InternalThreadListSync :: ThreadListSyncFields -> EventInternalParse
+ Discord.Internal.Types.Events: InternalThreadMembersUpdate :: ThreadMembersUpdateFields -> EventInternalParse
+ Discord.Internal.Types.Events: InternalThreadUpdate :: Channel -> EventInternalParse
+ Discord.Internal.Types.Events: ThreadCreate :: Channel -> Event
+ Discord.Internal.Types.Events: ThreadDelete :: Channel -> Event
+ Discord.Internal.Types.Events: ThreadListSync :: ThreadListSyncFields -> Event
+ Discord.Internal.Types.Events: ThreadMembersUpdate :: ThreadMembersUpdateFields -> Event
+ Discord.Internal.Types.Events: ThreadUpdate :: Channel -> Event
+ Discord.Internal.Types.Gateway: [gatewayIntentMessageContent] :: GatewayIntent -> Bool
+ Discord.Internal.Types.Guild: Activity :: Text -> ActivityType -> Maybe Text -> Integer -> Maybe ActivityTimestamps -> Maybe ApplicationId -> Maybe Text -> Maybe Text -> Maybe Emoji -> Maybe ActivityParty -> Maybe Bool -> Maybe Integer -> Maybe [ActivityButton] -> Activity
+ Discord.Internal.Types.Guild: ActivityButton :: Text -> Text -> ActivityButton
+ Discord.Internal.Types.Guild: ActivityParty :: Maybe Text -> Maybe (Integer, Integer) -> ActivityParty
+ Discord.Internal.Types.Guild: ActivityTimestamps :: Maybe Integer -> Maybe Integer -> ActivityTimestamps
+ Discord.Internal.Types.Guild: ActivityTypeCompeting :: ActivityType
+ Discord.Internal.Types.Guild: ActivityTypeCustom :: ActivityType
+ Discord.Internal.Types.Guild: ActivityTypeGame :: ActivityType
+ Discord.Internal.Types.Guild: ActivityTypeListening :: ActivityType
+ Discord.Internal.Types.Guild: ActivityTypeStreaming :: ActivityType
+ Discord.Internal.Types.Guild: ActivityTypeWatching :: ActivityType
+ Discord.Internal.Types.Guild: PresenceInfo :: UserId -> Maybe [Activity] -> Maybe GuildId -> Text -> PresenceInfo
+ Discord.Internal.Types.Guild: [activityApplicationId] :: Activity -> Maybe ApplicationId
+ Discord.Internal.Types.Guild: [activityButtonLabel] :: ActivityButton -> Text
+ Discord.Internal.Types.Guild: [activityButtonUrl] :: ActivityButton -> Text
+ Discord.Internal.Types.Guild: [activityButtons] :: Activity -> Maybe [ActivityButton]
+ Discord.Internal.Types.Guild: [activityCreatedAt] :: Activity -> Integer
+ Discord.Internal.Types.Guild: [activityDetails] :: Activity -> Maybe Text
+ Discord.Internal.Types.Guild: [activityEmoji] :: Activity -> Maybe Emoji
+ Discord.Internal.Types.Guild: [activityFlags] :: Activity -> Maybe Integer
+ Discord.Internal.Types.Guild: [activityInstance] :: Activity -> Maybe Bool
+ Discord.Internal.Types.Guild: [activityName] :: Activity -> Text
+ Discord.Internal.Types.Guild: [activityPartyId] :: ActivityParty -> Maybe Text
+ Discord.Internal.Types.Guild: [activityPartySize] :: ActivityParty -> Maybe (Integer, Integer)
+ Discord.Internal.Types.Guild: [activityParty] :: Activity -> Maybe ActivityParty
+ Discord.Internal.Types.Guild: [activityState] :: Activity -> Maybe Text
+ Discord.Internal.Types.Guild: [activityTimeStamps] :: Activity -> Maybe ActivityTimestamps
+ Discord.Internal.Types.Guild: [activityTimestampsEnd] :: ActivityTimestamps -> Maybe Integer
+ Discord.Internal.Types.Guild: [activityTimestampsStart] :: ActivityTimestamps -> Maybe Integer
+ Discord.Internal.Types.Guild: [activityType] :: Activity -> ActivityType
+ Discord.Internal.Types.Guild: [activityUrl] :: Activity -> Maybe Text
+ Discord.Internal.Types.Guild: [guildApproxMemberCount] :: Guild -> Maybe Integer
+ Discord.Internal.Types.Guild: [guildApproxPresenceCount] :: Guild -> Maybe Integer
+ Discord.Internal.Types.Guild: [guildBanner] :: Guild -> Maybe Text
+ Discord.Internal.Types.Guild: [guildDescription] :: Guild -> Maybe Text
+ Discord.Internal.Types.Guild: [guildDiscoverySplash] :: Guild -> Maybe Text
+ Discord.Internal.Types.Guild: [guildIconHash] :: Guild -> Maybe Text
+ Discord.Internal.Types.Guild: [guildMaxMembers] :: Guild -> Maybe Integer
+ Discord.Internal.Types.Guild: [guildMaxPresences] :: Guild -> Maybe Integer
+ Discord.Internal.Types.Guild: [guildMaxVideoUsers] :: Guild -> Maybe Integer
+ Discord.Internal.Types.Guild: [guildNSFWLevel] :: Guild -> Integer
+ Discord.Internal.Types.Guild: [guildOwner] :: Guild -> Maybe Bool
+ Discord.Internal.Types.Guild: [guildPreferredLocale] :: Guild -> Text
+ Discord.Internal.Types.Guild: [guildPremiumBar] :: Guild -> Bool
+ Discord.Internal.Types.Guild: [guildPremiumTier] :: Guild -> Integer
+ Discord.Internal.Types.Guild: [guildPresences] :: Guild -> Maybe [PresenceInfo]
+ Discord.Internal.Types.Guild: [guildPublicUpdatesChannel] :: Guild -> Maybe ChannelId
+ Discord.Internal.Types.Guild: [guildRulesChannelId] :: Guild -> Maybe ChannelId
+ Discord.Internal.Types.Guild: [guildStickers] :: Guild -> Maybe [StickerItem]
+ Discord.Internal.Types.Guild: [guildSubscriptionCount] :: Guild -> Maybe Integer
+ Discord.Internal.Types.Guild: [guildSystemChannelFlags] :: Guild -> Integer
+ Discord.Internal.Types.Guild: [guildSystemChannelId] :: Guild -> Maybe ChannelId
+ Discord.Internal.Types.Guild: [guildThreads] :: Guild -> Maybe [Channel]
+ Discord.Internal.Types.Guild: [guildUnavailable] :: Guild -> Maybe Bool
+ Discord.Internal.Types.Guild: [guildVanityURL] :: Guild -> Maybe Text
+ Discord.Internal.Types.Guild: [presenceActivities] :: PresenceInfo -> Maybe [Activity]
+ Discord.Internal.Types.Guild: [presenceGuildId] :: PresenceInfo -> Maybe GuildId
+ Discord.Internal.Types.Guild: [presenceStatus] :: PresenceInfo -> Text
+ Discord.Internal.Types.Guild: [presenceUserId] :: PresenceInfo -> UserId
+ Discord.Internal.Types.Guild: data Activity
+ Discord.Internal.Types.Guild: data ActivityButton
+ Discord.Internal.Types.Guild: data ActivityParty
+ Discord.Internal.Types.Guild: data ActivityTimestamps
+ Discord.Internal.Types.Guild: data ActivityType
+ Discord.Internal.Types.Guild: data PresenceInfo
+ Discord.Internal.Types.Guild: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Guild.Activity
+ Discord.Internal.Types.Guild: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Guild.ActivityButton
+ Discord.Internal.Types.Guild: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Guild.ActivityParty
+ Discord.Internal.Types.Guild: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Guild.ActivityTimestamps
+ Discord.Internal.Types.Guild: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Guild.ActivityType
+ Discord.Internal.Types.Guild: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Guild.PresenceInfo
+ Discord.Internal.Types.Guild: instance Data.Data.Data Discord.Internal.Types.Guild.ActivityType
+ Discord.Internal.Types.Guild: instance Data.Default.Class.Default Discord.Internal.Types.Guild.Activity
+ Discord.Internal.Types.Guild: instance Discord.Internal.Types.Prelude.InternalDiscordEnum Discord.Internal.Types.Guild.ActivityType
+ Discord.Internal.Types.Guild: instance GHC.Classes.Eq Discord.Internal.Types.Guild.Activity
+ Discord.Internal.Types.Guild: instance GHC.Classes.Eq Discord.Internal.Types.Guild.ActivityButton
+ Discord.Internal.Types.Guild: instance GHC.Classes.Eq Discord.Internal.Types.Guild.ActivityParty
+ Discord.Internal.Types.Guild: instance GHC.Classes.Eq Discord.Internal.Types.Guild.ActivityTimestamps
+ Discord.Internal.Types.Guild: instance GHC.Classes.Eq Discord.Internal.Types.Guild.ActivityType
+ Discord.Internal.Types.Guild: instance GHC.Classes.Eq Discord.Internal.Types.Guild.PresenceInfo
+ Discord.Internal.Types.Guild: instance GHC.Classes.Ord Discord.Internal.Types.Guild.Activity
+ Discord.Internal.Types.Guild: instance GHC.Classes.Ord Discord.Internal.Types.Guild.ActivityButton
+ Discord.Internal.Types.Guild: instance GHC.Classes.Ord Discord.Internal.Types.Guild.ActivityParty
+ Discord.Internal.Types.Guild: instance GHC.Classes.Ord Discord.Internal.Types.Guild.ActivityTimestamps
+ Discord.Internal.Types.Guild: instance GHC.Classes.Ord Discord.Internal.Types.Guild.ActivityType
+ Discord.Internal.Types.Guild: instance GHC.Classes.Ord Discord.Internal.Types.Guild.PresenceInfo
+ Discord.Internal.Types.Guild: instance GHC.Read.Read Discord.Internal.Types.Guild.Activity
+ Discord.Internal.Types.Guild: instance GHC.Read.Read Discord.Internal.Types.Guild.ActivityButton
+ Discord.Internal.Types.Guild: instance GHC.Read.Read Discord.Internal.Types.Guild.ActivityParty
+ Discord.Internal.Types.Guild: instance GHC.Read.Read Discord.Internal.Types.Guild.ActivityTimestamps
+ Discord.Internal.Types.Guild: instance GHC.Read.Read Discord.Internal.Types.Guild.ActivityType
+ Discord.Internal.Types.Guild: instance GHC.Read.Read Discord.Internal.Types.Guild.PresenceInfo
+ Discord.Internal.Types.Guild: instance GHC.Show.Show Discord.Internal.Types.Guild.Activity
+ Discord.Internal.Types.Guild: instance GHC.Show.Show Discord.Internal.Types.Guild.ActivityButton
+ Discord.Internal.Types.Guild: instance GHC.Show.Show Discord.Internal.Types.Guild.ActivityParty
+ Discord.Internal.Types.Guild: instance GHC.Show.Show Discord.Internal.Types.Guild.ActivityTimestamps
+ Discord.Internal.Types.Guild: instance GHC.Show.Show Discord.Internal.Types.Guild.ActivityType
+ Discord.Internal.Types.Guild: instance GHC.Show.Show Discord.Internal.Types.Guild.PresenceInfo
+ Discord.Internal.Types.Guild: newtype GuildUnavailable
+ Discord.Internal.Types.Interactions: InteractionModalSubmit :: InteractionId -> ApplicationId -> InteractionDataModal -> Maybe GuildId -> Maybe ChannelId -> MemberOrUser -> InteractionToken -> Int -> Text -> Maybe Text -> Interaction
+ Discord.Internal.Types.Interactions: InteractionResponseModal :: InteractionResponseModalData -> InteractionResponse
+ Discord.Internal.Types.Interactions: InteractionResponseModalData :: Text -> Text -> [ComponentTextInput] -> InteractionResponseModalData
+ Discord.Internal.Types.Interactions: [interactionDataModal] :: Interaction -> InteractionDataModal
+ Discord.Internal.Types.Interactions: [interactionResponseModalComponents] :: InteractionResponseModalData -> [ComponentTextInput]
+ Discord.Internal.Types.Interactions: [interactionResponseModalCustomId] :: InteractionResponseModalData -> Text
+ Discord.Internal.Types.Interactions: [interactionResponseModalTitle] :: InteractionResponseModalData -> Text
+ Discord.Internal.Types.Interactions: [resolvedDataAttachments] :: ResolvedData -> Maybe Value
+ Discord.Internal.Types.Interactions: [resolvedDataMessages] :: ResolvedData -> Maybe Value
+ Discord.Internal.Types.Interactions: data InteractionResponseModalData
+ Discord.Internal.Types.Interactions: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Interactions.InteractionDataModal
+ Discord.Internal.Types.Interactions: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Interactions.InteractionResponseModalData
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Eq Discord.Internal.Types.Interactions.InteractionDataModal
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Eq Discord.Internal.Types.Interactions.InteractionResponse
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Eq Discord.Internal.Types.Interactions.InteractionResponseModalData
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.Interaction
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionDataApplicationCommand
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionDataApplicationCommandOptionSubcommand
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionDataApplicationCommandOptionSubcommandOrGroup
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionDataApplicationCommandOptionValue
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionDataApplicationCommandOptions
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionDataComponent
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionDataModal
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionResponse
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionResponseAutocomplete
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionResponseMessage
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionResponseMessageFlag
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionResponseMessageFlags
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.InteractionResponseModalData
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.MemberOrUser
+ Discord.Internal.Types.Interactions: instance GHC.Classes.Ord Discord.Internal.Types.Interactions.ResolvedData
+ Discord.Internal.Types.Interactions: instance GHC.Read.Read Discord.Internal.Types.Interactions.InteractionDataModal
+ Discord.Internal.Types.Interactions: instance GHC.Read.Read Discord.Internal.Types.Interactions.InteractionResponse
+ Discord.Internal.Types.Interactions: instance GHC.Read.Read Discord.Internal.Types.Interactions.InteractionResponseAutocomplete
+ Discord.Internal.Types.Interactions: instance GHC.Read.Read Discord.Internal.Types.Interactions.InteractionResponseMessage
+ Discord.Internal.Types.Interactions: instance GHC.Read.Read Discord.Internal.Types.Interactions.InteractionResponseModalData
+ Discord.Internal.Types.Interactions: instance GHC.Show.Show Discord.Internal.Types.Interactions.InteractionDataModal
+ Discord.Internal.Types.Interactions: instance GHC.Show.Show Discord.Internal.Types.Interactions.InteractionResponse
+ Discord.Internal.Types.Interactions: instance GHC.Show.Show Discord.Internal.Types.Interactions.InteractionResponseModalData
+ Discord.Types: ActivityButton :: Text -> Text -> ActivityButton
+ Discord.Types: ActivityParty :: Maybe Text -> Maybe (Integer, Integer) -> ActivityParty
+ Discord.Types: ActivityTimestamps :: Maybe Integer -> Maybe Integer -> ActivityTimestamps
+ Discord.Types: ActivityTypeCustom :: ActivityType
+ Discord.Types: ActivityTypeWatching :: ActivityType
+ Discord.Types: ChannelNewsThread :: ChannelId -> GuildId -> Maybe Text -> Maybe Integer -> Maybe MessageId -> Maybe ParentId -> Maybe ThreadMetadata -> Maybe ThreadMember -> Channel
+ Discord.Types: ChannelPrivateThread :: ChannelId -> GuildId -> Maybe Text -> Maybe Integer -> Maybe MessageId -> Maybe ParentId -> Maybe ThreadMetadata -> Maybe ThreadMember -> Channel
+ Discord.Types: ChannelPublicThread :: ChannelId -> GuildId -> Maybe Text -> Maybe Integer -> Maybe MessageId -> Maybe ParentId -> Maybe ThreadMetadata -> Maybe ThreadMember -> Channel
+ Discord.Types: ComponentTextInput :: Text -> Bool -> Text -> Maybe Integer -> Maybe Integer -> Bool -> Text -> Text -> ComponentTextInput
+ Discord.Types: ThreadCreate :: Channel -> Event
+ Discord.Types: ThreadDelete :: Channel -> Event
+ Discord.Types: ThreadListSync :: ThreadListSyncFields -> Event
+ Discord.Types: ThreadListSyncFields :: GuildId -> Maybe [ChannelId] -> [Channel] -> [ThreadMember] -> ThreadListSyncFields
+ Discord.Types: ThreadMember :: Maybe ChannelId -> Maybe UserId -> UTCTime -> Integer -> ThreadMember
+ Discord.Types: ThreadMembersUpdate :: ThreadMembersUpdateFields -> Event
+ Discord.Types: ThreadMembersUpdateFields :: ChannelId -> GuildId -> Integer -> Maybe [ThreadMember] -> Maybe [UserId] -> ThreadMembersUpdateFields
+ Discord.Types: ThreadMetadata :: Bool -> Integer -> UTCTime -> Bool -> Maybe Bool -> Maybe UTCTime -> ThreadMetadata
+ Discord.Types: ThreadUpdate :: Channel -> Event
+ Discord.Types: [activityApplicationId] :: Activity -> Maybe ApplicationId
+ Discord.Types: [activityButtonLabel] :: ActivityButton -> Text
+ Discord.Types: [activityButtonUrl] :: ActivityButton -> Text
+ Discord.Types: [activityButtons] :: Activity -> Maybe [ActivityButton]
+ Discord.Types: [activityCreatedAt] :: Activity -> Integer
+ Discord.Types: [activityDetails] :: Activity -> Maybe Text
+ Discord.Types: [activityEmoji] :: Activity -> Maybe Emoji
+ Discord.Types: [activityFlags] :: Activity -> Maybe Integer
+ Discord.Types: [activityInstance] :: Activity -> Maybe Bool
+ Discord.Types: [activityPartyId] :: ActivityParty -> Maybe Text
+ Discord.Types: [activityPartySize] :: ActivityParty -> Maybe (Integer, Integer)
+ Discord.Types: [activityParty] :: Activity -> Maybe ActivityParty
+ Discord.Types: [activityState] :: Activity -> Maybe Text
+ Discord.Types: [activityTimeStamps] :: Activity -> Maybe ActivityTimestamps
+ Discord.Types: [activityTimestampsEnd] :: ActivityTimestamps -> Maybe Integer
+ Discord.Types: [activityTimestampsStart] :: ActivityTimestamps -> Maybe Integer
+ Discord.Types: [channelThreadMember] :: Channel -> Maybe ThreadMember
+ Discord.Types: [channelThreadMetadata] :: Channel -> Maybe ThreadMetadata
+ Discord.Types: [channelThreadName] :: Channel -> Maybe Text
+ Discord.Types: [channelUserRateLimitThread] :: Channel -> Maybe Integer
+ Discord.Types: [componentTextInputCustomId] :: ComponentTextInput -> Text
+ Discord.Types: [componentTextInputIsParagraph] :: ComponentTextInput -> Bool
+ Discord.Types: [componentTextInputLabel] :: ComponentTextInput -> Text
+ Discord.Types: [componentTextInputMaxLength] :: ComponentTextInput -> Maybe Integer
+ Discord.Types: [componentTextInputMinLength] :: ComponentTextInput -> Maybe Integer
+ Discord.Types: [componentTextInputPlaceholder] :: ComponentTextInput -> Text
+ Discord.Types: [componentTextInputRequired] :: ComponentTextInput -> Bool
+ Discord.Types: [componentTextInputValue] :: ComponentTextInput -> Text
+ Discord.Types: [gatewayIntentMessageContent] :: GatewayIntent -> Bool
+ Discord.Types: [guildApproxMemberCount] :: Guild -> Maybe Integer
+ Discord.Types: [guildApproxPresenceCount] :: Guild -> Maybe Integer
+ Discord.Types: [guildBanner] :: Guild -> Maybe Text
+ Discord.Types: [guildDescription] :: Guild -> Maybe Text
+ Discord.Types: [guildDiscoverySplash] :: Guild -> Maybe Text
+ Discord.Types: [guildIconHash] :: Guild -> Maybe Text
+ Discord.Types: [guildMaxMembers] :: Guild -> Maybe Integer
+ Discord.Types: [guildMaxPresences] :: Guild -> Maybe Integer
+ Discord.Types: [guildMaxVideoUsers] :: Guild -> Maybe Integer
+ Discord.Types: [guildNSFWLevel] :: Guild -> Integer
+ Discord.Types: [guildOwner] :: Guild -> Maybe Bool
+ Discord.Types: [guildPreferredLocale] :: Guild -> Text
+ Discord.Types: [guildPremiumBar] :: Guild -> Bool
+ Discord.Types: [guildPremiumTier] :: Guild -> Integer
+ Discord.Types: [guildPresences] :: Guild -> Maybe [PresenceInfo]
+ Discord.Types: [guildPublicUpdatesChannel] :: Guild -> Maybe ChannelId
+ Discord.Types: [guildRulesChannelId] :: Guild -> Maybe ChannelId
+ Discord.Types: [guildStickers] :: Guild -> Maybe [StickerItem]
+ Discord.Types: [guildSubscriptionCount] :: Guild -> Maybe Integer
+ Discord.Types: [guildSystemChannelFlags] :: Guild -> Integer
+ Discord.Types: [guildSystemChannelId] :: Guild -> Maybe ChannelId
+ Discord.Types: [guildThreads] :: Guild -> Maybe [Channel]
+ Discord.Types: [guildUnavailable] :: Guild -> Maybe Bool
+ Discord.Types: [guildVanityURL] :: Guild -> Maybe Text
+ Discord.Types: [presenceActivities] :: PresenceInfo -> Maybe [Activity]
+ Discord.Types: [threadListSyncFieldsChannelIds] :: ThreadListSyncFields -> Maybe [ChannelId]
+ Discord.Types: [threadListSyncFieldsGuildId] :: ThreadListSyncFields -> GuildId
+ Discord.Types: [threadListSyncFieldsThreadMembers] :: ThreadListSyncFields -> [ThreadMember]
+ Discord.Types: [threadListSyncFieldsThreads] :: ThreadListSyncFields -> [Channel]
+ Discord.Types: [threadMemberFlags] :: ThreadMember -> Integer
+ Discord.Types: [threadMemberJoinTime] :: ThreadMember -> UTCTime
+ Discord.Types: [threadMemberThreadId] :: ThreadMember -> Maybe ChannelId
+ Discord.Types: [threadMemberUserId] :: ThreadMember -> Maybe UserId
+ Discord.Types: [threadMembersUpdateFieldsAddedMembers] :: ThreadMembersUpdateFields -> Maybe [ThreadMember]
+ Discord.Types: [threadMembersUpdateFieldsGuildId] :: ThreadMembersUpdateFields -> GuildId
+ Discord.Types: [threadMembersUpdateFieldsMemberCount] :: ThreadMembersUpdateFields -> Integer
+ Discord.Types: [threadMembersUpdateFieldsRemovedMembers] :: ThreadMembersUpdateFields -> Maybe [UserId]
+ Discord.Types: [threadMembersUpdateFieldsThreadId] :: ThreadMembersUpdateFields -> ChannelId
+ Discord.Types: [threadMetadataArchiveTime] :: ThreadMetadata -> UTCTime
+ Discord.Types: [threadMetadataArchived] :: ThreadMetadata -> Bool
+ Discord.Types: [threadMetadataAutoArchive] :: ThreadMetadata -> Integer
+ Discord.Types: [threadMetadataCreateTime] :: ThreadMetadata -> Maybe UTCTime
+ Discord.Types: [threadMetadataInvitable] :: ThreadMetadata -> Maybe Bool
+ Discord.Types: [threadMetadataLocked] :: ThreadMetadata -> Bool
+ Discord.Types: data ActivityButton
+ Discord.Types: data ActivityParty
+ Discord.Types: data ActivityTimestamps
+ Discord.Types: data ComponentTextInput
+ Discord.Types: data ThreadListSyncFields
+ Discord.Types: data ThreadMember
+ Discord.Types: data ThreadMembersUpdateFields
+ Discord.Types: data ThreadMetadata
+ Discord.Types: mkComponentTextInput :: Text -> Text -> ComponentTextInput
+ Discord.Types: newtype GuildUnavailable
- Discord: Cache :: User -> Map ChannelId Channel -> Map GuildId (Guild, GuildInfo) -> Map ChannelId Channel -> PartialApplication -> Cache
+ Discord: Cache :: User -> Map ChannelId Channel -> Map GuildId Guild -> Map ChannelId Channel -> PartialApplication -> Cache
- Discord: [cacheGuilds] :: Cache -> Map GuildId (Guild, GuildInfo)
+ Discord: [cacheGuilds] :: Cache -> Map GuildId Guild
- Discord.Internal.Gateway: Cache :: User -> Map ChannelId Channel -> Map GuildId (Guild, GuildInfo) -> Map ChannelId Channel -> PartialApplication -> Cache
+ Discord.Internal.Gateway: Cache :: User -> Map ChannelId Channel -> Map GuildId Guild -> Map ChannelId Channel -> PartialApplication -> Cache
- Discord.Internal.Gateway: [cacheGuilds] :: Cache -> Map GuildId (Guild, GuildInfo)
+ Discord.Internal.Gateway: [cacheGuilds] :: Cache -> Map GuildId Guild
- Discord.Internal.Gateway.Cache: Cache :: User -> Map ChannelId Channel -> Map GuildId (Guild, GuildInfo) -> Map ChannelId Channel -> PartialApplication -> Cache
+ Discord.Internal.Gateway.Cache: Cache :: User -> Map ChannelId Channel -> Map GuildId Guild -> Map ChannelId Channel -> PartialApplication -> Cache
- Discord.Internal.Gateway.Cache: [cacheGuilds] :: Cache -> Map GuildId (Guild, GuildInfo)
+ Discord.Internal.Gateway.Cache: [cacheGuilds] :: Cache -> Map GuildId Guild
- Discord.Internal.Types.Components: ComponentButton :: Text -> Bool -> ButtonStyle -> Text -> Maybe Emoji -> ComponentButton
+ Discord.Internal.Types.Components: ComponentButton :: Text -> Bool -> ButtonStyle -> Maybe Text -> Maybe Emoji -> ComponentButton
- Discord.Internal.Types.Components: ComponentButtonUrl :: Text -> Bool -> Text -> Maybe Emoji -> ComponentButton
+ Discord.Internal.Types.Components: ComponentButtonUrl :: Text -> Bool -> Maybe Text -> Maybe Emoji -> ComponentButton
- Discord.Internal.Types.Components: [componentButtonLabel] :: ComponentButton -> Text
+ Discord.Internal.Types.Components: [componentButtonLabel] :: ComponentButton -> Maybe Text
- Discord.Internal.Types.Events: GuildCreate :: Guild -> GuildInfo -> Event
+ Discord.Internal.Types.Events: GuildCreate :: Guild -> Event
- Discord.Internal.Types.Events: InternalGuildCreate :: Guild -> GuildInfo -> EventInternalParse
+ Discord.Internal.Types.Events: InternalGuildCreate :: Guild -> EventInternalParse
- Discord.Internal.Types.Gateway: GatewayIntent :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GatewayIntent
+ Discord.Internal.Types.Gateway: GatewayIntent :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GatewayIntent
- Discord.Internal.Types.Guild: Guild :: GuildId -> Text -> Maybe Text -> Maybe Text -> UserId -> Maybe Text -> Maybe Text -> Maybe ChannelId -> Integer -> Maybe Bool -> Maybe ChannelId -> Integer -> Integer -> Integer -> [Role] -> [Emoji] -> [Text] -> !Integer -> Maybe Snowflake -> Guild
+ Discord.Internal.Types.Guild: Guild :: GuildId -> Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Bool -> UserId -> Maybe Text -> Maybe ChannelId -> Integer -> Maybe Bool -> Maybe ChannelId -> Integer -> Integer -> Integer -> [Role] -> [Emoji] -> [Text] -> !Integer -> Maybe ApplicationId -> Maybe ChannelId -> Integer -> Maybe ChannelId -> Maybe UTCTime -> Maybe Bool -> Maybe Bool -> Maybe Integer -> Maybe [GuildMember] -> Maybe [Channel] -> Maybe [Channel] -> Maybe [PresenceInfo] -> Maybe Integer -> Maybe Integer -> Maybe Text -> Maybe Text -> Maybe Text -> Integer -> Maybe Integer -> Text -> Maybe ChannelId -> Maybe Integer -> Maybe Integer -> Maybe Integer -> Integer -> Maybe [StickerItem] -> Bool -> Guild
- Discord.Internal.Types.Guild: [guildApplicationId] :: Guild -> Maybe Snowflake
+ Discord.Internal.Types.Guild: [guildApplicationId] :: Guild -> Maybe ApplicationId
- Discord.Internal.Types.Guild: [guildChannels] :: GuildInfo -> [Channel]
+ Discord.Internal.Types.Guild: [guildChannels] :: Guild -> Maybe [Channel]
- Discord.Internal.Types.Guild: [guildJoinedAt] :: GuildInfo -> UTCTime
+ Discord.Internal.Types.Guild: [guildJoinedAt] :: Guild -> Maybe UTCTime
- Discord.Internal.Types.Guild: [guildLarge] :: GuildInfo -> Bool
+ Discord.Internal.Types.Guild: [guildLarge] :: Guild -> Maybe Bool
- Discord.Internal.Types.Guild: [guildMemberCount] :: GuildInfo -> Integer
+ Discord.Internal.Types.Guild: [guildMemberCount] :: Guild -> Maybe Integer
- Discord.Internal.Types.Guild: [guildMembers] :: GuildInfo -> [GuildMember]
+ Discord.Internal.Types.Guild: [guildMembers] :: Guild -> Maybe [GuildMember]
- Discord.Internal.Types.Interactions: ResolvedData :: Maybe Value -> Maybe Value -> Maybe Value -> Maybe Value -> ResolvedData
+ Discord.Internal.Types.Interactions: ResolvedData :: Maybe Value -> Maybe Value -> Maybe Value -> Maybe Value -> Maybe Value -> Maybe Value -> ResolvedData
- Discord.Types: Activity :: Text -> ActivityType -> Maybe Text -> Activity
+ Discord.Types: Activity :: Text -> ActivityType -> Maybe Text -> Integer -> Maybe ActivityTimestamps -> Maybe ApplicationId -> Maybe Text -> Maybe Text -> Maybe Emoji -> Maybe ActivityParty -> Maybe Bool -> Maybe Integer -> Maybe [ActivityButton] -> Activity
- Discord.Types: ComponentButton :: Text -> Bool -> ButtonStyle -> Text -> Maybe Emoji -> ComponentButton
+ Discord.Types: ComponentButton :: Text -> Bool -> ButtonStyle -> Maybe Text -> Maybe Emoji -> ComponentButton
- Discord.Types: ComponentButtonUrl :: Text -> Bool -> Text -> Maybe Emoji -> ComponentButton
+ Discord.Types: ComponentButtonUrl :: Text -> Bool -> Maybe Text -> Maybe Emoji -> ComponentButton
- Discord.Types: GatewayIntent :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GatewayIntent
+ Discord.Types: GatewayIntent :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> GatewayIntent
- Discord.Types: Guild :: GuildId -> Text -> Maybe Text -> Maybe Text -> UserId -> Maybe Text -> Maybe Text -> Maybe ChannelId -> Integer -> Maybe Bool -> Maybe ChannelId -> Integer -> Integer -> Integer -> [Role] -> [Emoji] -> [Text] -> !Integer -> Maybe Snowflake -> Guild
+ Discord.Types: Guild :: GuildId -> Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Bool -> UserId -> Maybe Text -> Maybe ChannelId -> Integer -> Maybe Bool -> Maybe ChannelId -> Integer -> Integer -> Integer -> [Role] -> [Emoji] -> [Text] -> !Integer -> Maybe ApplicationId -> Maybe ChannelId -> Integer -> Maybe ChannelId -> Maybe UTCTime -> Maybe Bool -> Maybe Bool -> Maybe Integer -> Maybe [GuildMember] -> Maybe [Channel] -> Maybe [Channel] -> Maybe [PresenceInfo] -> Maybe Integer -> Maybe Integer -> Maybe Text -> Maybe Text -> Maybe Text -> Integer -> Maybe Integer -> Text -> Maybe ChannelId -> Maybe Integer -> Maybe Integer -> Maybe Integer -> Integer -> Maybe [StickerItem] -> Bool -> Guild
- Discord.Types: GuildCreate :: Guild -> GuildInfo -> Event
+ Discord.Types: GuildCreate :: Guild -> Event
- Discord.Types: PresenceInfo :: UserId -> [RoleId] -> GuildId -> Text -> PresenceInfo
+ Discord.Types: PresenceInfo :: UserId -> Maybe [Activity] -> Maybe GuildId -> Text -> PresenceInfo
- Discord.Types: [componentButtonLabel] :: ComponentButton -> Text
+ Discord.Types: [componentButtonLabel] :: ComponentButton -> Maybe Text
- Discord.Types: [guildApplicationId] :: Guild -> Maybe Snowflake
+ Discord.Types: [guildApplicationId] :: Guild -> Maybe ApplicationId
- Discord.Types: [guildChannels] :: GuildInfo -> [Channel]
+ Discord.Types: [guildChannels] :: Guild -> Maybe [Channel]
- Discord.Types: [guildJoinedAt] :: GuildInfo -> UTCTime
+ Discord.Types: [guildJoinedAt] :: Guild -> Maybe UTCTime
- Discord.Types: [guildLarge] :: GuildInfo -> Bool
+ Discord.Types: [guildLarge] :: Guild -> Maybe Bool
- Discord.Types: [guildMemberCount] :: GuildInfo -> Integer
+ Discord.Types: [guildMemberCount] :: Guild -> Maybe Integer
- Discord.Types: [guildMembers] :: GuildInfo -> [GuildMember]
+ Discord.Types: [guildMembers] :: Guild -> Maybe [GuildMember]
- Discord.Types: [presenceGuildId] :: PresenceInfo -> GuildId
+ Discord.Types: [presenceGuildId] :: PresenceInfo -> Maybe GuildId
Files
- README.md +33/−52
- changelog.md +6/−0
- discord-haskell.cabal +1/−1
- examples/ping-pong.hs +4/−4
- src/Discord/Internal/Gateway/Cache.hs +5/−5
- src/Discord/Internal/Gateway/EventLoop.hs +2/−1
- src/Discord/Internal/Rest/Channel.hs +195/−56
- src/Discord/Internal/Rest/Prelude.hs +7/−3
- src/Discord/Internal/Types.hs +6/−1
- src/Discord/Internal/Types/ApplicationCommands.hs +3/−3
- src/Discord/Internal/Types/Channel.hs +179/−8
- src/Discord/Internal/Types/Components.hs +87/−26
- src/Discord/Internal/Types/Events.hs +81/−82
- src/Discord/Internal/Types/Gateway.hs +5/−20
- src/Discord/Internal/Types/Guild.hs +202/−40
- src/Discord/Internal/Types/Interactions.hs +100/−16
README.md view
@@ -1,38 +1,32 @@-# discord-haskell [](https://github.com/aquarial/discord-haskell/actions/) [](https://hackage.haskell.org/package/discord-haskell) [](https://discord.gg/eaRAGgX3bK)+# discord-haskell [](https://github.com/aquarial/discord-haskell/actions/) [](https://hackage.haskell.org/package/discord-haskell) [](https://discord.gg/eaRAGgX3bK) -## About -Build that discord bot in Haskell! Also checkout the [calamity haskell library](https://github.com/nitros12/calamity)-for a more advanced interface than `discord-haskell`.+Build that discord bot in Haskell! Also checkout the+[calamity haskell library](https://github.com/nitros12/calamity)+for a more advanced interface. -### Documentation + #### Local Documentation -Find docs on features, metadata, and parts is found in [./docs/README.md#Documentation](./docs/README.md#Documentation)+Documentation on specific features and metadata is in [the local documentation folder](./docs/README.md#Documentation) #### Discord Server -Current project discord server: <https://discord.gg/eaRAGgX3bK>--Ask questions, get updates, request features, etc+Ask questions, get updates, request features, etc in the project discord server: <https://discord.gg/eaRAGgX3bK> #### Official Discord Documentation -The [official discord documentation](https://discord.com/developers/docs/intro)-lists the rest requests, gateway events, and gateway sendables. The library-matches very closely. +This api closley matches the [official discord documentation](https://discord.com/developers/docs/intro),+which lists the rest requests, gateway events, and gateway sendables. -For example: -[Get Channel](https://discord.com/developers/docs/resources/channel#get-channel)-and discord-haskell has a rest request ADT including -`[GetChannel :: ChannelId -> ChannelRequest Channel]`. Similar matching exists for gateway `Event`s.+You can use the docs to check the name of something you want to do. For example: +the docs list a [Get Channel](https://discord.com/developers/docs/resources/channel#get-channel) API path,+which translates to discord-haskell's rest request ADT for `GetChannel` of type `ChannelId -> ChannelRequest Channel`. #### Open an Issue -If something goes wrong: check the error message, (optional: check log file), make sure you have the most recent version, ask on discord, or open a github issue.--## Implementation and Progress+If something goes wrong: check the error message (optional: check [the debugging logs](./docs/debugging.md)), make sure you have the most recent version, ask on discord, or open a github issue. ### Quickstart @@ -40,12 +34,13 @@ ```haskell {-# LANGUAGE OverloadedStrings #-} -- allows "string literals" to be Text-import Control.Monad (when, void)-import Data.Text (isPrefixOf, toLower, Text)+import Control.Monad (when, void)+import UnliftIO.Concurrent+import Data.Text (isPrefixOf, toLower, Text) import qualified Data.Text.IO as TIO-import UnliftIO.Concurrent-import Discord-import Discord.Types++import Discord+import Discord.Types import qualified Discord.Requests as R -- | Replies "pong" to every message that starts with "ping"@@ -53,16 +48,14 @@ pingpongExample = do userFacingError <- runDiscord $ def { discordToken = "Bot ZZZZZZZZZZZZZZZZZZZ"- , discordOnEvent = eventHandler- , discordOnLog = \s -> TIO.putStrLn s- , discordForkThreadForEvents = True }+ , discordOnEvent = eventHandler } TIO.putStrLn userFacingError -- userFacingError is an unrecoverable error -- put normal 'cleanup' code in discordOnEnd (see examples) eventHandler :: Event -> DiscordHandler () eventHandler event = case event of- MessageCreate m -> when (not (fromBot m) && isPing m) $ do+ MessageCreate m -> when (isPing m && (not (fromBot m)) $ do void $ restCall (R.CreateReaction (messageChannelId m, messageId m) "eyes") threadDelay (2 * 10^6) void $ restCall (R.CreateMessage (messageChannelId m) "Pong!")@@ -75,32 +68,11 @@ isPing = ("ping" `isPrefixOf`) . toLower . messageContent ``` -```cabal--- ping-pong.cabal--executable haskell-bot- main-is: src/Main.hs- default-language: Haskell2010- ghc-options: -threaded- build-depends: base- , text- , unliftio- , discord-haskell-```--### Biggest TODOs--- [ ] Add slash commands [issue](https://github.com/aquarial/discord-haskell/issues/59)-- [ ] APIv9 [issue](https://github.com/aquarial/discord-haskell/issues/72)-- [ ] Event type includes roles and other cached info-- [ ] higher level bot interface? easier to add state and stuff-- [x] rewrite eventloop [issue](https://github.com/aquarial/discord-haskell/issues/70)- ### Installing discord-haskell is on hosted on hackage at https://hackage.haskell.org/package/discord-haskell, -In `stack.yaml`+Add the following to your `stack.yaml` (if using stack) ```yaml extra-deps:@@ -108,7 +80,7 @@ - discord-haskell-VERSION ``` -In `project.cabal`+And add this to the `project.cabal` ```cabal executable haskell-bot@@ -117,7 +89,8 @@ ghc-options: -threaded build-depends: base , text- , discord-haskell+ , discord-haskell + -- == VERSION (if using cabal) ``` For a more complete example with various options go to @@ -127,5 +100,13 @@ [Creating your first Bot](https://github.com/aquarial/discord-haskell/wiki/Creating-your-first-Bot) for some help setting up your bot token +++### Rough Roadmap++- [ ] Add slash commands [issue](https://github.com/aquarial/discord-haskell/issues/59)+- [ ] APIv9 [issue](https://github.com/aquarial/discord-haskell/issues/72)+- [ ] Event type includes roles and other cached info+- [ ] higher level bot interface? easier to add state and stuff
changelog.md view
@@ -6,6 +6,12 @@ ## master +## 1.12.1++[L0neGamer](https://github.com/aquarial/discord-haskell/pull/103) Add threads, switch api to V10, Update Guild data fields++[L0neGamer](https://github.com/aquarial/discord-haskell/pull/104) Add model interaction and components+ ## 1.12.0 [L0neGamer](https://github.com/aquarial/discord-haskell/pull/96) breaking changes and fixes to application commands, interactions, and components, and updates elsewhere
discord-haskell.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.0 name: discord-haskell -- library version is also noted at src/Discord/Rest/Prelude.hs-version: 1.12.0+version: 1.12.1 description: Functions and data types to write discord bots. Official discord docs <https://discord.com/developers/docs/reference>. .
examples/ping-pong.hs view
@@ -36,6 +36,7 @@ , discordOnEnd = liftIO $ putStrLn "Ended" , discordOnEvent = eventHandler , discordOnLog = \s -> TIO.putStrLn s >> TIO.putStrLn ""+ , discordGatewayIntent = def {gatewayIntentMembers = True, gatewayIntentPrecenses =True} } -- only reached on an unrecoverable error@@ -46,10 +47,9 @@ -- Use place to execute commands you know you want to complete startHandler :: DiscordHandler () startHandler = do- let activity = Activity { activityName = "ping-pong"- , activityType = ActivityTypeGame- , activityUrl = Nothing- }+ let activity = def { activityName = "ping-pong"+ , activityType = ActivityTypeGame+ } let opts = UpdateStatusOpts { updateStatusOptsSince = Nothing , updateStatusOptsGame = Just activity , updateStatusOptsNewStatus = UpdateStatusOnline
src/Discord/Internal/Gateway/Cache.hs view
@@ -16,7 +16,7 @@ data Cache = Cache { cacheCurrentUser :: User , cacheDMChannels :: M.Map ChannelId Channel- , cacheGuilds :: M.Map GuildId (Guild, GuildInfo)+ , cacheGuilds :: M.Map GuildId Guild , cacheChannels :: M.Map ChannelId Channel , cacheApplication :: PartialApplication } deriving (Show)@@ -54,10 +54,10 @@ adjustCache :: Cache -> EventInternalParse -> Cache adjustCache minfo event = case event of- InternalGuildCreate guild info ->- let newChans = map (setChanGuildID (guildId guild)) $ guildChannels info- g = M.insert (guildId guild) (guild, info { guildChannels = newChans }) (cacheGuilds minfo)- c = M.unionWith (\a _ -> a)+ InternalGuildCreate guild ->+ let newChans = maybe [] (map (setChanGuildID (guildId guild))) (guildChannels guild)+ g = M.insert (guildId guild) (guild { guildChannels = Just newChans }) (cacheGuilds minfo)+ c = M.unionWith const (M.fromList [ (channelId ch, ch) | ch <- newChans ]) (cacheChannels minfo) in minfo { cacheGuilds = g, cacheChannels = c }
src/Discord/Internal/Gateway/EventLoop.hs view
@@ -24,6 +24,7 @@ receiveData, sendTextData, sendClose) import Discord.Internal.Types+import Discord.Internal.Rest.Prelude (apiVersion) data GatewayHandle = GatewayHandle@@ -102,7 +103,7 @@ LoopClosed -> pure Nothing startconnectionpls :: GatewaySendableInternal -> IO LoopState- startconnectionpls first = runSecureClient "gateway.discord.gg" 443 "/?v=8&encoding=json" $ \conn -> do+ startconnectionpls first = runSecureClient "gateway.discord.gg" 443 ("/?v=" <> T.unpack apiVersion <>"&encoding=json") $ \conn -> do msg <- getPayload conn log case msg of Right (Hello interval) -> do
src/Discord/Internal/Rest/Channel.hs view
@@ -16,6 +16,9 @@ , ChannelPermissionsOpts(..) , GroupDMAddRecipientOpts(..) , ChannelPermissionsOptsType(..)+ , StartThreadOpts(..)+ , StartThreadNoMessageOpts(..)+ , ListThreads(..) ) where @@ -41,60 +44,91 @@ -- | Data constructor for requests. See <https://discord.com/developers/docs/resources/ API> data ChannelRequest a where -- | Gets a channel by its id.- GetChannel :: ChannelId -> ChannelRequest Channel+ GetChannel :: ChannelId -> ChannelRequest Channel -- | Edits channels options.- ModifyChannel :: ChannelId -> ModifyChannelOpts -> ChannelRequest Channel+ ModifyChannel :: ChannelId -> ModifyChannelOpts -> ChannelRequest Channel -- | Deletes a channel if its id doesn't equal to the id of guild.- DeleteChannel :: ChannelId -> ChannelRequest Channel+ DeleteChannel :: ChannelId -> ChannelRequest Channel -- | Gets a messages from a channel with limit of 100 per request.- GetChannelMessages :: ChannelId -> (Int, MessageTiming) -> ChannelRequest [Message]+ GetChannelMessages :: ChannelId -> (Int, MessageTiming) -> ChannelRequest [Message] -- | Gets a message in a channel by its id.- GetChannelMessage :: (ChannelId, MessageId) -> ChannelRequest Message+ GetChannelMessage :: (ChannelId, MessageId) -> ChannelRequest Message -- | Sends a message to a channel.- CreateMessage :: ChannelId -> T.Text -> ChannelRequest Message+ CreateMessage :: ChannelId -> T.Text -> ChannelRequest Message -- | Sends a message with a file to a channel.- CreateMessageUploadFile :: ChannelId -> T.Text -> B.ByteString -> ChannelRequest Message+ CreateMessageUploadFile :: ChannelId -> T.Text -> B.ByteString -> ChannelRequest Message -- | Sends a message with granular controls.- CreateMessageDetailed :: ChannelId -> MessageDetailedOpts -> ChannelRequest Message+ CreateMessageDetailed :: ChannelId -> MessageDetailedOpts -> ChannelRequest Message -- | Add an emoji reaction to a message. ID must be present for custom emoji- CreateReaction :: (ChannelId, MessageId) -> T.Text -> ChannelRequest ()+ CreateReaction :: (ChannelId, MessageId) -> T.Text -> ChannelRequest () -- | Remove a Reaction this bot added- DeleteOwnReaction :: (ChannelId, MessageId) -> T.Text -> ChannelRequest ()+ DeleteOwnReaction :: (ChannelId, MessageId) -> T.Text -> ChannelRequest () -- | Remove a Reaction someone else added- DeleteUserReaction :: (ChannelId, MessageId) -> UserId -> T.Text -> ChannelRequest ()+ DeleteUserReaction :: (ChannelId, MessageId) -> UserId -> T.Text -> ChannelRequest () -- | Deletes all reactions of a single emoji on a message- DeleteSingleReaction :: (ChannelId, MessageId) -> T.Text -> ChannelRequest ()+ DeleteSingleReaction :: (ChannelId, MessageId) -> T.Text -> ChannelRequest () -- | List of users that reacted with this emoji- GetReactions :: (ChannelId, MessageId) -> T.Text -> (Int, ReactionTiming) -> ChannelRequest [User]+ GetReactions :: (ChannelId, MessageId) -> T.Text -> (Int, ReactionTiming) -> ChannelRequest [User] -- | Delete all reactions on a message- DeleteAllReactions :: (ChannelId, MessageId) -> ChannelRequest ()+ DeleteAllReactions :: (ChannelId, MessageId) -> ChannelRequest () -- | Edits a message content.- EditMessage :: (ChannelId, MessageId) -> T.Text -> Maybe CreateEmbed- -> ChannelRequest Message+ EditMessage :: (ChannelId, MessageId) -> T.Text -> Maybe CreateEmbed+ -> ChannelRequest Message -- | Deletes a message.- DeleteMessage :: (ChannelId, MessageId) -> ChannelRequest ()+ DeleteMessage :: (ChannelId, MessageId) -> ChannelRequest () -- | Deletes a group of messages.- BulkDeleteMessage :: (ChannelId, [MessageId]) -> ChannelRequest ()+ BulkDeleteMessage :: (ChannelId, [MessageId]) -> ChannelRequest () -- | Edits a permission overrides for a channel.- EditChannelPermissions :: ChannelId -> OverwriteId -> ChannelPermissionsOpts -> ChannelRequest ()+ EditChannelPermissions :: ChannelId -> OverwriteId -> ChannelPermissionsOpts -> ChannelRequest () -- | Gets all instant invites to a channel.- GetChannelInvites :: ChannelId -> ChannelRequest Object+ GetChannelInvites :: ChannelId -> ChannelRequest Object -- | Creates an instant invite to a channel.- CreateChannelInvite :: ChannelId -> ChannelInviteOpts -> ChannelRequest Invite+ CreateChannelInvite :: ChannelId -> ChannelInviteOpts -> ChannelRequest Invite -- | Deletes a permission override from a channel.- DeleteChannelPermission :: ChannelId -> OverwriteId -> ChannelRequest ()+ DeleteChannelPermission :: ChannelId -> OverwriteId -> ChannelRequest () -- | Sends a typing indicator a channel which lasts 10 seconds.- TriggerTypingIndicator :: ChannelId -> ChannelRequest ()+ TriggerTypingIndicator :: ChannelId -> ChannelRequest () -- | Gets all pinned messages of a channel.- GetPinnedMessages :: ChannelId -> ChannelRequest [Message]+ GetPinnedMessages :: ChannelId -> ChannelRequest [Message] -- | Pins a message.- AddPinnedMessage :: (ChannelId, MessageId) -> ChannelRequest ()+ AddPinnedMessage :: (ChannelId, MessageId) -> ChannelRequest () -- | Unpins a message.- DeletePinnedMessage :: (ChannelId, MessageId) -> ChannelRequest ()+ DeletePinnedMessage :: (ChannelId, MessageId) -> ChannelRequest () -- | Adds a recipient to a Group DM using their access token- GroupDMAddRecipient :: ChannelId -> GroupDMAddRecipientOpts -> ChannelRequest ()+ GroupDMAddRecipient :: ChannelId -> GroupDMAddRecipientOpts -> ChannelRequest () -- | Removes a recipient from a Group DM- GroupDMRemoveRecipient :: ChannelId -> UserId -> ChannelRequest ()+ GroupDMRemoveRecipient :: ChannelId -> UserId -> ChannelRequest ()+ -- | Start a thread from a message+ StartThreadFromMessage :: ChannelId -> MessageId -> StartThreadOpts -> ChannelRequest Channel+ -- | Start a thread without a message+ StartThreadNoMessage :: ChannelId -> StartThreadNoMessageOpts -> ChannelRequest Channel+ -- | Join a thread+ JoinThread :: ChannelId -> ChannelRequest ()+ -- | Add a thread member+ AddThreadMember :: ChannelId -> UserId -> ChannelRequest ()+ -- | Leave a thread+ LeaveThread :: ChannelId -> ChannelRequest ()+ -- | Remove a thread member+ RemoveThreadMember :: ChannelId -> UserId -> ChannelRequest ()+ -- | Get a thread member+ GetThreadMember :: ChannelId -> UserId -> ChannelRequest ThreadMember+ -- | List the thread members+ ListThreadMembers :: ChannelId -> ChannelRequest [ThreadMember]+ -- | List public archived threads in the given channel. Optionally before a + -- given time, and optional maximum number of threads. Returns the threads, + -- thread members, and whether there are more to collect.+ -- Requires the READ_MESSAGE_HISTORY permission.+ ListPublicArchivedThreads :: ChannelId -> (Maybe UTCTime, Maybe Integer) -> ChannelRequest ListThreads+ -- | List private archived threads in the given channel. Optionally before a + -- given time, and optional maximum number of threads. Returns the threads, + -- thread members, and whether there are more to collect.+ -- Requires both the READ_MESSAGE_HISTORY and MANAGE_THREADS permissions.+ ListPrivateArchivedThreads :: ChannelId -> (Maybe UTCTime, Maybe Integer) -> ChannelRequest ListThreads+ -- | List joined private archived threads in the given channel. Optionally + -- before a given time, and optional maximum number of threads. Returns the + -- threads, thread members, and whether there are more to collect.+ -- Requires both the READ_MESSAGE_HISTORY and MANAGE_THREADS permissions.+ ListJoinedPrivateArchivedThreads :: ChannelId -> (Maybe UTCTime, Maybe Integer) -> ChannelRequest ListThreads -- | Data constructor for CreateMessageDetailed requests.@@ -107,7 +141,7 @@ , messageDetailedReference :: Maybe MessageReference , messageDetailedComponents :: Maybe [ComponentActionRow] , messageDetailedStickerIds :: Maybe [StickerId]- } deriving (Show, Eq, Ord, Read)+ } deriving (Show, Read, Eq, Ord) instance Default MessageDetailedOpts where def = MessageDetailedOpts { messageDetailedContent = ""@@ -208,35 +242,95 @@ , groupDMAddRecipientGDMJoinAccessToken :: T.Text } deriving (Show, Read, Eq, Ord) +data StartThreadOpts = StartThreadOpts + { startThreadName :: T.Text+ , startThreadAutoArchive :: Maybe Integer -- ^ can be one of 60, 1440, 4320, 10080+ , startThreadRateLimit :: Maybe Integer+ } deriving (Show, Read, Eq, Ord)++instance ToJSON StartThreadOpts where+ toJSON StartThreadOpts{..} = object [ (name, value) | (name, Just value) <- + [ ("name", toJSON <$> pure startThreadName)+ , ("auto_archive_duration", toJSON <$> startThreadAutoArchive)+ , ("rate_limit_per_user", toJSON <$> startThreadRateLimit)+ ]+ ]++data StartThreadNoMessageOpts = StartThreadNoMessageOpts+ { startThreadNoMessageBaseOpts :: StartThreadOpts+ , startThreadNoMessageType :: Integer -- ^ 10, 11, or 12 (https://discord.com/developers/docs/resources/channel#channel-object-channel-types)+ , startThreadNoMessageInvitable :: Maybe Bool+ } deriving (Show, Read, Eq, Ord)++instance ToJSON StartThreadNoMessageOpts where+ toJSON StartThreadNoMessageOpts{..} = object [ (name, value) | (name, Just value) <- + [ ("name", toJSON <$> pure (startThreadName startThreadNoMessageBaseOpts))+ , ("auto_archive_duration", toJSON <$> (startThreadAutoArchive startThreadNoMessageBaseOpts))+ , ("rate_limit_per_user", toJSON <$> (startThreadRateLimit startThreadNoMessageBaseOpts))+ , ("type", toJSON <$> pure startThreadNoMessageType)+ , ("invitable", toJSON <$> startThreadNoMessageInvitable)+ ]+ ]++data ListThreads = ListThreads + { listThreadsThreads :: [Channel]+ , listThreadsMembers :: [ThreadMember]+ , listThreadsHasMore :: Bool -- ^ whether there is more data to retrieve+ } deriving (Show, Read, Eq, Ord)++instance ToJSON ListThreads where+ toJSON ListThreads{..} = object + [ ("threads", toJSON listThreadsThreads)+ , ("members", toJSON listThreadsMembers)+ , ("has_more", toJSON listThreadsHasMore)+ ]++instance FromJSON ListThreads where+ parseJSON = withObject "ListThreads" $ \o ->+ ListThreads <$> o .: "threads"+ <*> o .: "members"+ <*> o .: "has_more"+ channelMajorRoute :: ChannelRequest a -> String channelMajorRoute c = case c of- (GetChannel chan) -> "get_chan " <> show chan- (ModifyChannel chan _) -> "mod_chan " <> show chan- (DeleteChannel chan) -> "mod_chan " <> show chan- (GetChannelMessages chan _) -> "msg " <> show chan- (GetChannelMessage (chan, _)) -> "get_msg " <> show chan- (CreateMessage chan _) -> "msg " <> show chan- (CreateMessageUploadFile chan _ _) -> "msg " <> show chan- (CreateMessageDetailed chan _) -> "msg " <> show chan- (CreateReaction (chan, _) _) -> "add_react " <> show chan- (DeleteOwnReaction (chan, _) _) -> "react " <> show chan- (DeleteUserReaction (chan, _) _ _) -> "react " <> show chan- (DeleteSingleReaction (chan, _) _) -> "react " <> show chan- (GetReactions (chan, _) _ _) -> "react " <> show chan- (DeleteAllReactions (chan, _)) -> "react " <> show chan- (EditMessage (chan, _) _ _) -> "get_msg " <> show chan- (DeleteMessage (chan, _)) -> "get_msg " <> show chan- (BulkDeleteMessage (chan, _)) -> "del_msgs " <> show chan- (EditChannelPermissions chan _ _) -> "perms " <> show chan- (GetChannelInvites chan) -> "invites " <> show chan- (CreateChannelInvite chan _) -> "invites " <> show chan- (DeleteChannelPermission chan _) -> "perms " <> show chan- (TriggerTypingIndicator chan) -> "tti " <> show chan- (GetPinnedMessages chan) -> "pins " <> show chan- (AddPinnedMessage (chan, _)) -> "pin " <> show chan- (DeletePinnedMessage (chan, _)) -> "pin " <> show chan- (GroupDMAddRecipient chan _) -> "groupdm " <> show chan- (GroupDMRemoveRecipient chan _) -> "groupdm " <> show chan+ (GetChannel chan) -> "get_chan " <> show chan+ (ModifyChannel chan _) -> "mod_chan " <> show chan+ (DeleteChannel chan) -> "mod_chan " <> show chan+ (GetChannelMessages chan _) -> "msg " <> show chan+ (GetChannelMessage (chan, _)) -> "get_msg " <> show chan+ (CreateMessage chan _) -> "msg " <> show chan+ (CreateMessageUploadFile chan _ _) -> "msg " <> show chan+ (CreateMessageDetailed chan _) -> "msg " <> show chan+ (CreateReaction (chan, _) _) -> "add_react " <> show chan+ (DeleteOwnReaction (chan, _) _) -> "react " <> show chan+ (DeleteUserReaction (chan, _) _ _) -> "react " <> show chan+ (DeleteSingleReaction (chan, _) _) -> "react " <> show chan+ (GetReactions (chan, _) _ _) -> "react " <> show chan+ (DeleteAllReactions (chan, _)) -> "react " <> show chan+ (EditMessage (chan, _) _ _) -> "get_msg " <> show chan+ (DeleteMessage (chan, _)) -> "get_msg " <> show chan+ (BulkDeleteMessage (chan, _)) -> "del_msgs " <> show chan+ (EditChannelPermissions chan _ _) -> "perms " <> show chan+ (GetChannelInvites chan) -> "invites " <> show chan+ (CreateChannelInvite chan _) -> "invites " <> show chan+ (DeleteChannelPermission chan _) -> "perms " <> show chan+ (TriggerTypingIndicator chan) -> "tti " <> show chan+ (GetPinnedMessages chan) -> "pins " <> show chan+ (AddPinnedMessage (chan, _)) -> "pin " <> show chan+ (DeletePinnedMessage (chan, _)) -> "pin " <> show chan+ (GroupDMAddRecipient chan _) -> "groupdm " <> show chan+ (GroupDMRemoveRecipient chan _) -> "groupdm " <> show chan+ (StartThreadFromMessage chan _ _) -> "thread " <> show chan+ (StartThreadNoMessage chan _) -> "thread " <> show chan+ (JoinThread chan) -> "thread " <> show chan+ (AddThreadMember chan _) -> "thread " <> show chan+ (LeaveThread chan) -> "thread " <> show chan+ (RemoveThreadMember chan _) -> "thread " <> show chan+ (GetThreadMember chan _) -> "thread " <> show chan+ (ListThreadMembers chan) -> "thread " <> show chan+ (ListPublicArchivedThreads chan _) -> "thread " <> show chan+ (ListPrivateArchivedThreads chan _) -> "thread " <> show chan+ (ListJoinedPrivateArchivedThreads chan _) -> "thread " <> show chan cleanupEmoji :: T.Text -> T.Text cleanupEmoji emoji =@@ -380,3 +474,48 @@ (GroupDMRemoveRecipient chan userid) -> Delete (channels // chan // chan /: "recipients" // userid) mempty + (StartThreadFromMessage chan mid sto) ->+ Post (channels // chan /: "messages" // mid /: "threads")+ (pure $ R.ReqBodyJson $ toJSON sto)+ mempty++ (StartThreadNoMessage chan sto) ->+ Post (channels // chan /: "messages" /: "threads")+ (pure $ R.ReqBodyJson $ toJSON sto)+ mempty++ (JoinThread chan) ->+ Put (channels // chan /: "thread-members" /: "@me")+ R.NoReqBody mempty++ (AddThreadMember chan uid) ->+ Put (channels // chan /: "thread-members" // uid)+ R.NoReqBody mempty++ (LeaveThread chan) ->+ Delete (channels // chan /: "thread-members" /: "@me")+ mempty++ (RemoveThreadMember chan uid) ->+ Delete (channels // chan /: "thread-members" // uid)+ mempty++ (GetThreadMember chan uid) ->+ Get (channels // chan /: "thread-members" // uid)+ mempty++ (ListThreadMembers chan) ->+ Get (channels // chan /: "thread-members")+ mempty++ (ListPublicArchivedThreads chan (time, lim)) ->+ Get (channels // chan /: "threads" /: "archived" /: "public")+ (maybe mempty ("limit" R.=:) lim <> maybe mempty ("before" R.=:) time)++ (ListPrivateArchivedThreads chan (time, lim)) ->+ Get (channels // chan /: "threads" /: "archived" /: "private")+ (maybe mempty ("limit" R.=:) lim <> maybe mempty ("before" R.=:) time)++ (ListJoinedPrivateArchivedThreads chan (time, lim)) ->+ Get (channels // chan /: "users" /: "@me" /: "threads" /: "archived" /: "private")+ (maybe mempty ("limit" R.=:) lim <> maybe mempty ("before" R.=:) time)
src/Discord/Internal/Rest/Prelude.hs view
@@ -17,10 +17,14 @@ import Discord.Internal.Types +-- | The api version to use.+apiVersion :: T.Text+apiVersion = "10"+ -- | The base url (Req) for API requests baseUrl :: R.Url 'R.Https-baseUrl = R.https "discord.com" R./: "api" R./: apiVersion- where apiVersion = "v8"+baseUrl = R.https "discord.com" R./: "api" R./: apiVersion'+ where apiVersion' = "v" <> apiVersion -- | Discord requires HTTP headers for authentication. authHeader :: Auth -> R.Option 'R.Https@@ -30,7 +34,7 @@ where -- | https://discord.com/developers/docs/reference#user-agent -- Second place where the library version is noted- agent = "DiscordBot (https://github.com/aquarial/discord-haskell, 1.12.0)"+ agent = "DiscordBot (https://github.com/aquarial/discord-haskell, 1.12.1)" -- Append to an URL infixl 5 //
src/Discord/Internal/Types.hs view
@@ -34,8 +34,13 @@ InternalChannelCreate a -> ChannelCreate a InternalChannelUpdate a -> ChannelUpdate a InternalChannelDelete a -> ChannelDelete a+ InternalThreadCreate a -> ThreadCreate a+ InternalThreadUpdate a -> ThreadUpdate a+ InternalThreadDelete a -> ThreadDelete a+ InternalThreadListSync a -> ThreadListSync a+ InternalThreadMembersUpdate a -> ThreadMembersUpdate a InternalChannelPinsUpdate a b -> ChannelPinsUpdate a b- InternalGuildCreate a b -> GuildCreate a b+ InternalGuildCreate a -> GuildCreate a InternalGuildUpdate a -> GuildUpdate a InternalGuildDelete a -> GuildDelete a InternalGuildBanAdd a b -> GuildBanAdd a b
src/Discord/Internal/Types/ApplicationCommands.hs view
@@ -538,7 +538,7 @@ ] data Choice a = Choice {choiceName :: T.Text, choiceValue :: a}- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance Functor Choice where fmap f (Choice s a) = Choice s (f a)@@ -632,7 +632,7 @@ -- | The permissions for the command in the guild. guildApplicationCommandPermissionsPermissions :: [ApplicationCommandPermissions] }- deriving (Show, Eq, Ord, Read)+ deriving (Show, Read, Eq, Ord) instance FromJSON GuildApplicationCommandPermissions where parseJSON =@@ -668,7 +668,7 @@ -- | Whether to allow or not. applicationCommandPermissionsPermission :: Bool }- deriving (Show, Eq, Ord, Read)+ deriving (Show, Read, Eq, Ord) instance FromJSON ApplicationCommandPermissions where parseJSON =
src/Discord/Internal/Types/Channel.hs view
@@ -28,7 +28,7 @@ { channelId :: ChannelId -- ^ The id of the channel (Will be equal to -- the guild if it's the "general" channel). , channelGuild :: GuildId -- ^ The id of the guild.- , channelName :: T.Text -- ^ The name of the guild (2 - 1000 characters).+ , channelName :: T.Text -- ^ The name of the channel (2 - 1000 characters). , channelPosition :: Integer -- ^ The storing position of the channel. , channelPermissions :: [Overwrite] -- ^ An array of permission 'Overwrite's , channelUserRateLimit :: Integer -- ^ Seconds before a user can speak again@@ -94,6 +94,39 @@ , channelStageId :: StageId , channelStageTopic :: Text }+ | ChannelNewsThread+ { channelId :: ChannelId -- ^ The id of the thread+ , channelGuild :: GuildId -- ^ The id of the guild.+ , channelThreadName :: Maybe T.Text -- ^ The name of the channel (2 - 1000 characters).+ , channelUserRateLimitThread :: Maybe Integer -- ^ Seconds before a user can speak again+ , channelLastMessage :: Maybe MessageId -- ^ The id of the last message sent in the+ -- channel+ , channelParentId :: Maybe ParentId -- ^ The id of the parent channel (category)+ , channelThreadMetadata :: Maybe ThreadMetadata -- ^ Metadata about this thread+ , channelThreadMember :: Maybe ThreadMember -- ^ Used to indicate if the user has joined the thread+ }+ | ChannelPublicThread+ { channelId :: ChannelId -- ^ The id of the thread+ , channelGuild :: GuildId -- ^ The id of the guild.+ , channelThreadName :: Maybe T.Text -- ^ The name of the channel (2 - 1000 characters).+ , channelUserRateLimitThread :: Maybe Integer -- ^ Seconds before a user can speak again+ , channelLastMessage :: Maybe MessageId -- ^ The id of the last message sent in the+ -- channel+ , channelParentId :: Maybe ParentId -- ^ The id of the parent channel (category)+ , channelThreadMetadata :: Maybe ThreadMetadata -- ^ Metadata about this thread+ , channelThreadMember :: Maybe ThreadMember -- ^ Used to indicate if the user has joined the thread+ }+ | ChannelPrivateThread+ { channelId :: ChannelId -- ^ The id of the thread+ , channelGuild :: GuildId -- ^ The id of the guild.+ , channelThreadName :: Maybe T.Text -- ^ The name of the channel (2 - 1000 characters).+ , channelUserRateLimitThread :: Maybe Integer -- ^ Seconds before a user can speak again+ , channelLastMessage :: Maybe MessageId -- ^ The id of the last message sent in the+ -- channel+ , channelParentId :: Maybe ParentId -- ^ The id of the parent channel (category)+ , channelThreadMetadata :: Maybe ThreadMetadata -- ^ Metadata about this thread+ , channelThreadMember :: Maybe ThreadMember -- ^ Used to indicate if the user has joined the thread+ } | ChannelUnknownType { channelId :: ChannelId , channelJSON :: Text@@ -155,6 +188,30 @@ <*> o .:? "nsfw" .!= False <*> o .: "permission_overwrites" <*> o .:? "parent_id"+ 10 -> ChannelNewsThread <$> o.: "id"+ <*> o .:? "guild_id" .!= 0+ <*> o .:? "name"+ <*> o .:? "rate_limit_per_user"+ <*> o .:? "last_message_id"+ <*> o .:? "parent_id"+ <*> o .:? "thread_metadata"+ <*> o .:? "member"+ 11 -> ChannelPublicThread <$> o.: "id"+ <*> o .:? "guild_id" .!= 0+ <*> o .:? "name"+ <*> o .:? "rate_limit_per_user"+ <*> o .:? "last_message_id"+ <*> o .:? "parent_id"+ <*> o .:? "thread_metadata"+ <*> o .:? "member"+ 12 -> ChannelPrivateThread <$> o.: "id"+ <*> o .:? "guild_id" .!= 0+ <*> o .:? "name"+ <*> o .:? "rate_limit_per_user"+ <*> o .:? "last_message_id"+ <*> o .:? "parent_id"+ <*> o .:? "thread_metadata"+ <*> o .:? "member" 13 -> ChannelStage <$> o .: "id" <*> o .:? "guild_id" .!= 0@@ -225,6 +282,36 @@ , ("channel_id", toJSON <$> pure channelStageId) , ("topic", toJSON <$> pure channelStageTopic) ] ]+ toJSON ChannelNewsThread{..} = object [(name,value) | (name, Just value) <-+ [ ("id", toJSON <$> pure channelId)+ , ("guild_id", toJSON <$> pure channelGuild)+ , ("name", toJSON <$> channelThreadName)+ , ("rate_limit_per_user", toJSON <$> channelUserRateLimitThread)+ , ("last_message_id", toJSON <$> channelLastMessage)+ , ("parent_id", toJSON <$> pure channelParentId)+ , ("thread_metadata", toJSON <$> channelThreadMetadata)+ , ("member", toJSON <$> channelThreadMember)+ ] ]+ toJSON ChannelPublicThread{..} = object [(name,value) | (name, Just value) <-+ [ ("id", toJSON <$> pure channelId)+ , ("guild_id", toJSON <$> pure channelGuild)+ , ("name", toJSON <$> channelThreadName)+ , ("rate_limit_per_user", toJSON <$> channelUserRateLimitThread)+ , ("last_message_id", toJSON <$> channelLastMessage)+ , ("parent_id", toJSON <$> pure channelParentId)+ , ("thread_metadata", toJSON <$> channelThreadMetadata)+ , ("member", toJSON <$> channelThreadMember)+ ] ]+ toJSON ChannelPrivateThread{..} = object [(name,value) | (name, Just value) <-+ [ ("id", toJSON <$> pure channelId)+ , ("guild_id", toJSON <$> pure channelGuild)+ , ("name", toJSON <$> channelThreadName)+ , ("rate_limit_per_user", toJSON <$> channelUserRateLimitThread)+ , ("last_message_id", toJSON <$> channelLastMessage)+ , ("parent_id", toJSON <$> pure channelParentId)+ , ("thread_metadata", toJSON <$> channelThreadMetadata)+ , ("member", toJSON <$> channelThreadMember)+ ] ] toJSON ChannelUnknownType{..} = object [(name,value) | (name, Just value) <- [ ("id", toJSON <$> pure channelId) , ("json", toJSON <$> pure channelJSON)@@ -233,11 +320,14 @@ -- | If the channel is part of a guild (has a guild id field) channelIsInGuild :: Channel -> Bool channelIsInGuild c = case c of- ChannelGuildCategory{..} -> True- ChannelText{..} -> True- ChannelVoice{..} -> True- ChannelNews{..} -> True- ChannelStorePage{..} -> True+ ChannelGuildCategory{} -> True+ ChannelText{} -> True+ ChannelVoice{} -> True+ ChannelNews{} -> True+ ChannelStorePage{} -> True+ ChannelNewsThread{} -> True+ ChannelPublicThread{} -> True+ ChannelPrivateThread{} -> True _ -> False -- | Permission overwrites for a channel.@@ -263,6 +353,87 @@ , ("deny", toJSON overwriteDeny) ] +-- | Metadata for threads.+data ThreadMetadata = ThreadMetadata+ { threadMetadataArchived :: Bool -- ^ Is the thread archived?+ , threadMetadataAutoArchive :: Integer -- ^ How long after activity should the thread auto archive+ , threadMetadataArchiveTime :: UTCTime -- ^ When was the last time the archive status changed?+ , threadMetadataLocked :: Bool -- ^ Is the thread locked? (only MANAGE_THREADS users can unarchive)+ , threadMetadataInvitable :: Maybe Bool -- ^ Can non-mods add other non-mods? (private threads only)+ , threadMetadataCreateTime :: Maybe UTCTime -- ^ When was the thread created?+ } deriving (Show, Read, Eq, Ord)++instance FromJSON ThreadMetadata where+ parseJSON = withObject "ThreadMetadata" $ \o ->+ ThreadMetadata <$> o .: "archived"+ <*> o .: "auto_archive_duration"+ <*> o .: "archive_timestamp"+ <*> o .: "locked"+ <*> o .:? "invitable"+ <*> o .:? "create_timestamp"++instance ToJSON ThreadMetadata where+ toJSON ThreadMetadata{..} = object [(name,value) | (name, Just value) <-+ [ ("archived", toJSON <$> pure threadMetadataArchived)+ , ("auto_archive_duration", toJSON <$> pure threadMetadataAutoArchive)+ , ("archive_timestamp", toJSON <$> pure threadMetadataArchiveTime)+ , ("locked", toJSON <$> pure threadMetadataLocked)+ , ("invitable", toJSON <$> threadMetadataInvitable)+ , ("create_timestamp", toJSON <$> pure threadMetadataCreateTime)+ ] ]++data ThreadMember = ThreadMember+ { threadMemberThreadId :: Maybe ChannelId -- ^ id of the thread+ , threadMemberUserId :: Maybe UserId -- ^ id of the user+ , threadMemberJoinTime :: UTCTime -- ^ time the current user last joined the thread+ , threadMemberFlags :: Integer -- ^ user-thread settings+ } deriving (Show, Read, Eq, Ord)++instance FromJSON ThreadMember where+ parseJSON = withObject "ThreadMember" $ \o ->+ ThreadMember <$> o .:? "id"+ <*> o .:? "user_id"+ <*> o .: "join_timestamp"+ <*> o .: "flags"++instance ToJSON ThreadMember where+ toJSON ThreadMember{..} = object [(name,value) | (name, Just value) <-+ [ ("id", toJSON <$> threadMemberThreadId)+ , ("user_id", toJSON <$> threadMemberUserId)+ , ("join_timestamp", toJSON <$> pure threadMemberJoinTime)+ , ("flags", toJSON <$> pure threadMemberFlags)+ ] ]++data ThreadListSyncFields = ThreadListSyncFields + { threadListSyncFieldsGuildId :: GuildId+ , threadListSyncFieldsChannelIds :: Maybe [ChannelId]+ , threadListSyncFieldsThreads :: [Channel]+ , threadListSyncFieldsThreadMembers :: [ThreadMember]+ } deriving (Show, Read, Eq, Ord)++instance FromJSON ThreadListSyncFields where+ parseJSON = withObject "ThreadListSyncFields" $ \o ->+ ThreadListSyncFields <$> o .: "guild_id"+ <*> o .:? "channel_ids"+ <*> o .: "threads"+ <*> o .: "members"++data ThreadMembersUpdateFields = ThreadMembersUpdateFields + { threadMembersUpdateFieldsThreadId :: ChannelId+ , threadMembersUpdateFieldsGuildId :: GuildId+ , threadMembersUpdateFieldsMemberCount :: Integer+ , threadMembersUpdateFieldsAddedMembers :: Maybe [ThreadMember]+ , threadMembersUpdateFieldsRemovedMembers :: Maybe [UserId]+ } deriving (Show, Read, Eq, Ord)++instance FromJSON ThreadMembersUpdateFields where+ parseJSON = withObject "ThreadMembersUpdateFields" $ \o ->+ ThreadMembersUpdateFields <$> o .: "id"+ <*> o .: "guild_id"+ <*> o .: "member_count"+ <*> o .:? "added_members"+ <*> o .:? "removed_member_ids"+ -- | Represents information about a message in a Discord channel. data Message = Message { messageId :: MessageId -- ^ The id of the message@@ -300,7 +471,7 @@ , messageThread :: Maybe Channel -- ^ the thread that was started from this message, includes thread member object , messageComponents :: Maybe [ComponentActionRow] -- ^ sent if the message contains components like buttons, action rows, or other interactive components , messageStickerItems :: Maybe [StickerItem] -- ^ sent if the message contains stickers- } deriving (Show, Eq, Ord, Read)+ } deriving (Show, Read, Eq, Ord) instance FromJSON Message where parseJSON = withObject "Message" $ \o ->@@ -675,7 +846,7 @@ , messageInteractionType :: Integer -- ^ Type of the interaction (liekly always application command) , messageInteractionName :: T.Text -- ^ Name of the interaction , messageInteractionUser :: User -- ^ User who invoked the interaction- } deriving (Show, Eq, Ord, Read)+ } deriving (Show, Read, Eq, Ord) instance ToJSON MessageInteraction where toJSON MessageInteraction{..} = object [(name,value) | (name, Just value) <-
src/Discord/Internal/Types/Components.hs view
@@ -15,6 +15,8 @@ mkSelectMenu, SelectOption (..), mkSelectOption,+ ComponentTextInput (..),+ mkComponentTextInput, Emoji (..), mkEmoji, )@@ -29,28 +31,32 @@ import Discord.Internal.Types.User (User) data ComponentActionRow = ComponentActionRowButton [ComponentButton] | ComponentActionRowSelectMenu ComponentSelectMenu- deriving (Show, Eq, Ord, Read)+ deriving (Show, Read, Eq, Ord) instance FromJSON ComponentActionRow where parseJSON = withObject "ComponentActionRow" ( \cs -> do- a <- cs .: "components" :: Parser Array- let a' = toList a- case a' of- [] -> return $ ComponentActionRowButton []- (c : _) ->- withObject- "ComponentActionRow item"- ( \v -> do- t <- v .: "type" :: Parser Int- case t of- 2 -> ComponentActionRowButton <$> mapM parseJSON a'- 3 -> ComponentActionRowSelectMenu <$> parseJSON c- _ -> fail $ "unknown component type: " ++ show t- )- c+ t <- cs .: "type" :: Parser Int+ case t of+ 1 -> do+ a <- cs .: "components" :: Parser Array+ let a' = toList a+ case a' of+ [] -> return $ ComponentActionRowButton []+ (c : _) ->+ withObject+ "ComponentActionRow item"+ ( \v -> do+ t' <- v .: "type" :: Parser Int+ case t' of+ 2 -> ComponentActionRowButton <$> mapM parseJSON a'+ 3 -> ComponentActionRowSelectMenu <$> parseJSON c+ _ -> fail $ "unknown component type: " ++ show t+ )+ c+ _ -> fail $ "expected action row type (1), got: " ++ show t ) instance ToJSON ComponentActionRow where@@ -69,7 +75,7 @@ -- | What is the style of the button componentButtonStyle :: ButtonStyle, -- | What is the user-facing label of the button- componentButtonLabel :: T.Text,+ componentButtonLabel :: Maybe T.Text, -- | What emoji is displayed on the button componentButtonEmoji :: Maybe Emoji }@@ -80,15 +86,15 @@ -- | Whether the button is disabled componentButtonDisabled :: Bool, -- | What is the user-facing label of the button- componentButtonLabel :: T.Text,+ componentButtonLabel :: Maybe T.Text, -- | What emoji is displayed on the button componentButtonEmoji :: Maybe Emoji }- deriving (Show, Eq, Ord, Read)+ deriving (Show, Read, Eq, Ord) -- | Takes the label and the custom id of the button that is to be generated. mkButton :: T.Text -> T.Text -> ComponentButton-mkButton label customId = ComponentButton customId False ButtonStyleSecondary label Nothing+mkButton label customId = ComponentButton customId False ButtonStyleSecondary (Just label) Nothing instance FromJSON ComponentButton where parseJSON =@@ -99,7 +105,7 @@ case t of 2 -> do disabled <- v .:? "disabled" .!= False- label <- v .: "label"+ label <- v .:? "label" partialEmoji <- v .:? "emoji" style <- v .: "style" :: Parser Scientific case style of@@ -126,7 +132,7 @@ | (name, Just value) <- [ ("type", Just $ Number 2), ("style", Just $ Number 5),- ("label", toMaybeJSON componentButtonLabel),+ ("label", toJSON <$> componentButtonLabel), ("disabled", toMaybeJSON componentButtonDisabled), ("url", toMaybeJSON componentButtonUrl), ("emoji", toJSON <$> componentButtonEmoji)@@ -138,7 +144,7 @@ | (name, Just value) <- [ ("type", Just $ Number 2), ("style", Just $ toJSON componentButtonStyle),- ("label", toMaybeJSON componentButtonLabel),+ ("label", toJSON <$> componentButtonLabel), ("disabled", toMaybeJSON componentButtonDisabled), ("custom_id", toMaybeJSON componentButtonCustomId), ("emoji", toJSON <$> componentButtonEmoji)@@ -155,7 +161,7 @@ ButtonStyleSuccess | -- | Red button ButtonStyleDanger- deriving (Show, Eq, Ord, Read)+ deriving (Show, Read, Eq, Ord) instance FromJSON ButtonStyle where parseJSON =@@ -192,7 +198,7 @@ -- | Maximum number of values to select (def 1, max 25) componentSelectMenuMaxValues :: Maybe Integer }- deriving (Show, Eq, Ord, Read)+ deriving (Show, Read, Eq, Ord) -- | Takes the custom id and the options of the select menu that is to be -- generated.@@ -246,7 +252,7 @@ -- | Use this value by default selectOptionDefault :: Maybe Bool }- deriving (Show, Eq, Ord, Read)+ deriving (Show, Read, Eq, Ord) -- | Make a select option from the given label and value. mkSelectOption :: T.Text -> T.Text -> SelectOption@@ -272,6 +278,61 @@ ("default", toJSON <$> selectOptionDefault) ] ]++data ComponentTextInput = ComponentTextInput+ { -- | Dev identifier+ componentTextInputCustomId :: T.Text,+ -- | What style to use (short or paragraph)+ componentTextInputIsParagraph :: Bool,+ -- | The label for this component+ componentTextInputLabel :: T.Text,+ -- | The minimum input length for a text input (0-4000)+ componentTextInputMinLength :: Maybe Integer,+ -- | The maximum input length for a text input (1-4000)+ componentTextInputMaxLength :: Maybe Integer,+ -- | Whether this component is required to be filled+ componentTextInputRequired :: Bool,+ -- | The prefilled value for this component (max 4000)+ componentTextInputValue :: T.Text,+ -- | Placeholder text if empty (max 4000)+ componentTextInputPlaceholder :: T.Text+ }+ deriving (Show, Read, Eq, Ord)++instance ToJSON ComponentTextInput where+ toJSON ComponentTextInput {..} =+ object+ [ (name, value)+ | (name, Just value) <-+ [ ("type", Just $ Number 4),+ ("custom_id", toMaybeJSON componentTextInputCustomId),+ ("style", toMaybeJSON (1 + fromEnum componentTextInputIsParagraph)),+ ("label", toMaybeJSON componentTextInputLabel),+ ("min_length", toJSON <$> componentTextInputMinLength),+ ("max_length", toJSON <$> componentTextInputMaxLength),+ ("required", toMaybeJSON componentTextInputRequired),+ ("value", toMaybeJSON componentTextInputValue),+ ("placeholder", toMaybeJSON componentTextInputPlaceholder)+ ]+ ]++instance FromJSON ComponentTextInput where+ parseJSON = withObject "ComponentTextInput" $ \o -> do+ t <- o .: "type" :: Parser Int+ case t of+ 4 ->+ ComponentTextInput <$> o .: "custom_id"+ <*> fmap (== (2 :: Int)) (o .:? "style" .!= 1)+ <*> o .:? "label" .!= ""+ <*> o .:? "min_length"+ <*> o .:? "max_length"+ <*> o .:? "required" .!= False+ <*> o .:? "value" .!= ""+ <*> o .:? "placeholder" .!= ""+ _ -> fail "expected text input, found other type of component"++mkComponentTextInput :: T.Text -> T.Text -> ComponentTextInput+mkComponentTextInput cid label = ComponentTextInput cid False label Nothing Nothing True "" "" -- | Represents an emoticon (emoji) data Emoji = Emoji
src/Discord/Internal/Types/Events.hs view
@@ -15,7 +15,7 @@ import Discord.Internal.Types.Prelude import Discord.Internal.Types.Channel-import Discord.Internal.Types.Guild (Role, GuildInfo, GuildUnavailable, Guild)+import Discord.Internal.Types.Guild import Discord.Internal.Types.User (User, GuildMember) import Discord.Internal.Types.Interactions (Interaction) import Discord.Internal.Types.Components (Emoji)@@ -23,79 +23,89 @@ -- | Represents possible events sent by discord. Detailed information can be found at https://discord.com/developers/docs/topics/gateway. data Event =- Ready Int User [Channel] [GuildUnavailable] T.Text (Maybe Shard) PartialApplication- | Resumed [T.Text]- | ChannelCreate Channel- | ChannelUpdate Channel- | ChannelDelete Channel- | ChannelPinsUpdate ChannelId (Maybe UTCTime)- | GuildCreate Guild GuildInfo- | GuildUpdate Guild- | GuildDelete GuildUnavailable- | GuildBanAdd GuildId User- | GuildBanRemove GuildId User- | GuildEmojiUpdate GuildId [Emoji]- | GuildIntegrationsUpdate GuildId- | GuildMemberAdd GuildId GuildMember- | GuildMemberRemove GuildId User- | GuildMemberUpdate GuildId [RoleId] User (Maybe T.Text)- | GuildMemberChunk GuildId [GuildMember]- | GuildRoleCreate GuildId Role- | GuildRoleUpdate GuildId Role- | GuildRoleDelete GuildId RoleId- | MessageCreate Message- | MessageUpdate ChannelId MessageId- | MessageDelete ChannelId MessageId- | MessageDeleteBulk ChannelId [MessageId]- | MessageReactionAdd ReactionInfo- | MessageReactionRemove ReactionInfo- | MessageReactionRemoveAll ChannelId MessageId+ Ready Int User [Channel] [GuildUnavailable] T.Text (Maybe Shard) PartialApplication+ | Resumed [T.Text]+ | ChannelCreate Channel+ | ChannelUpdate Channel+ | ChannelDelete Channel+ | ThreadCreate Channel+ | ThreadUpdate Channel+ | ThreadDelete Channel+ | ThreadListSync ThreadListSyncFields + | ThreadMembersUpdate ThreadMembersUpdateFields + | ChannelPinsUpdate ChannelId (Maybe UTCTime)+ | GuildCreate Guild+ | GuildUpdate Guild+ | GuildDelete GuildUnavailable+ | GuildBanAdd GuildId User+ | GuildBanRemove GuildId User+ | GuildEmojiUpdate GuildId [Emoji]+ | GuildIntegrationsUpdate GuildId+ | GuildMemberAdd GuildId GuildMember+ | GuildMemberRemove GuildId User+ | GuildMemberUpdate GuildId [RoleId] User (Maybe T.Text)+ | GuildMemberChunk GuildId [GuildMember]+ | GuildRoleCreate GuildId Role+ | GuildRoleUpdate GuildId Role+ | GuildRoleDelete GuildId RoleId+ | MessageCreate Message+ | MessageUpdate ChannelId MessageId+ | MessageDelete ChannelId MessageId+ | MessageDeleteBulk ChannelId [MessageId]+ | MessageReactionAdd ReactionInfo+ | MessageReactionRemove ReactionInfo+ | MessageReactionRemoveAll ChannelId MessageId | MessageReactionRemoveEmoji ReactionRemoveInfo- | PresenceUpdate PresenceInfo- | TypingStart TypingInfo- | UserUpdate User- | InteractionCreate Interaction+ | PresenceUpdate PresenceInfo+ | TypingStart TypingInfo+ | UserUpdate User+ | InteractionCreate Interaction -- | VoiceStateUpdate -- | VoiceServerUpdate- | UnknownEvent T.Text Object+ | UnknownEvent T.Text Object deriving (Show, Eq) data EventInternalParse =- InternalReady Int User [Channel] [GuildUnavailable] T.Text (Maybe Shard) PartialApplication- | InternalResumed [T.Text]- | InternalChannelCreate Channel- | InternalChannelUpdate Channel- | InternalChannelDelete Channel- | InternalChannelPinsUpdate ChannelId (Maybe UTCTime)- | InternalGuildCreate Guild GuildInfo- | InternalGuildUpdate Guild- | InternalGuildDelete GuildUnavailable- | InternalGuildBanAdd GuildId User- | InternalGuildBanRemove GuildId User- | InternalGuildEmojiUpdate GuildId [Emoji]- | InternalGuildIntegrationsUpdate GuildId- | InternalGuildMemberAdd GuildId GuildMember- | InternalGuildMemberRemove GuildId User- | InternalGuildMemberUpdate GuildId [RoleId] User (Maybe T.Text)- | InternalGuildMemberChunk GuildId [GuildMember]- | InternalGuildRoleCreate GuildId Role- | InternalGuildRoleUpdate GuildId Role- | InternalGuildRoleDelete GuildId RoleId- | InternalMessageCreate Message- | InternalMessageUpdate ChannelId MessageId- | InternalMessageDelete ChannelId MessageId- | InternalMessageDeleteBulk ChannelId [MessageId]- | InternalMessageReactionAdd ReactionInfo- | InternalMessageReactionRemove ReactionInfo- | InternalMessageReactionRemoveAll ChannelId MessageId+ InternalReady Int User [Channel] [GuildUnavailable] T.Text (Maybe Shard) PartialApplication+ | InternalResumed [T.Text]+ | InternalChannelCreate Channel+ | InternalChannelUpdate Channel+ | InternalChannelDelete Channel+ | InternalThreadCreate Channel+ | InternalThreadUpdate Channel+ | InternalThreadDelete Channel+ | InternalThreadListSync ThreadListSyncFields + | InternalThreadMembersUpdate ThreadMembersUpdateFields + | InternalChannelPinsUpdate ChannelId (Maybe UTCTime)+ | InternalGuildCreate Guild+ | InternalGuildUpdate Guild+ | InternalGuildDelete GuildUnavailable+ | InternalGuildBanAdd GuildId User+ | InternalGuildBanRemove GuildId User+ | InternalGuildEmojiUpdate GuildId [Emoji]+ | InternalGuildIntegrationsUpdate GuildId+ | InternalGuildMemberAdd GuildId GuildMember+ | InternalGuildMemberRemove GuildId User+ | InternalGuildMemberUpdate GuildId [RoleId] User (Maybe T.Text)+ | InternalGuildMemberChunk GuildId [GuildMember]+ | InternalGuildRoleCreate GuildId Role+ | InternalGuildRoleUpdate GuildId Role+ | InternalGuildRoleDelete GuildId RoleId+ | InternalMessageCreate Message+ | InternalMessageUpdate ChannelId MessageId+ | InternalMessageDelete ChannelId MessageId+ | InternalMessageDeleteBulk ChannelId [MessageId]+ | InternalMessageReactionAdd ReactionInfo+ | InternalMessageReactionRemove ReactionInfo+ | InternalMessageReactionRemoveAll ChannelId MessageId | InternalMessageReactionRemoveEmoji ReactionRemoveInfo- | InternalPresenceUpdate PresenceInfo- | InternalTypingStart TypingInfo- | InternalUserUpdate User- | InternalInteractionCreate Interaction+ | InternalPresenceUpdate PresenceInfo+ | InternalTypingStart TypingInfo+ | InternalUserUpdate User+ | InternalInteractionCreate Interaction -- -- | InternalVoiceStateUpdate -- -- | InternalVoiceServerUpdate- | InternalUnknownEvent T.Text Object+ | InternalUnknownEvent T.Text Object deriving (Show, Eq, Read) data PartialApplication = PartialApplication@@ -136,22 +146,6 @@ <*> o .: "message_id" <*> o .: "emoji" -data PresenceInfo = PresenceInfo- { presenceUserId :: UserId- , presenceRoles :: [RoleId]- -- , presenceGame :: Maybe Activity- , presenceGuildId :: GuildId- , presenceStatus :: T.Text- } deriving (Show, Read, Eq, Ord)--instance FromJSON PresenceInfo where- parseJSON = withObject "PresenceInfo" $ \o ->- PresenceInfo <$> (o .: "user" >>= (.: "id"))- <*> o .: "roles"- -- <*> o .: "game"- <*> o .: "guild_id"- <*> o .: "status"- data TypingInfo = TypingInfo { typingUserId :: UserId , typingChannelId :: ChannelId@@ -187,11 +181,16 @@ "CHANNEL_CREATE" -> InternalChannelCreate <$> reparse o "CHANNEL_UPDATE" -> InternalChannelUpdate <$> reparse o "CHANNEL_DELETE" -> InternalChannelDelete <$> reparse o+ "THREAD_CREATE" -> InternalThreadCreate <$> reparse o+ "THREAD_UPDATE" -> InternalThreadUpdate <$> reparse o+ "THREAD_DELETE" -> InternalThreadDelete <$> reparse o+ "THREAD_LIST_SYNC" -> InternalThreadListSync <$> reparse o+ "THREAD_MEMBERS_UPDATE" -> InternalThreadMembersUpdate <$> reparse o "CHANNEL_PINS_UPDATE" -> do id <- o .: "channel_id" stamp <- o .:? "last_pin_timestamp" let utc = stamp >>= parseISO8601 pure (InternalChannelPinsUpdate id utc)- "GUILD_CREATE" -> InternalGuildCreate <$> reparse o <*> reparse o+ "GUILD_CREATE" -> InternalGuildCreate <$> reparse o "GUILD_UPDATE" -> InternalGuildUpdate <$> reparse o "GUILD_DELETE" -> InternalGuildDelete <$> reparse o "GUILD_BAN_ADD" -> InternalGuildBanAdd <$> o .: "guild_id" <*> o .: "user"
src/Discord/Internal/Types/Gateway.hs view
@@ -20,6 +20,7 @@ import Discord.Internal.Types.Prelude import Discord.Internal.Types.Events+import Discord.Internal.Types.Guild (Activity (..)) -- | Sent by gateway data GatewayReceivable@@ -57,6 +58,7 @@ , gatewayIntentDirectMessageChanges :: Bool , gatewayIntentDirectMessageReactions :: Bool , gatewayIntentDirectMessageTyping :: Bool+ , gatewayIntentMessageContent :: Bool } deriving (Show, Read, Eq, Ord) instance Default GatewayIntent where@@ -75,6 +77,7 @@ , gatewayIntentDirectMessageChanges = True , gatewayIntentDirectMessageReactions = True , gatewayIntentDirectMessageTyping = True+ , gatewayIntentMessageContent = True } compileGatewayIntent :: GatewayIntent -> Int@@ -95,6 +98,7 @@ , (2 ^ 12, gatewayIntentDirectMessageChanges) , (2 ^ 13, gatewayIntentDirectMessageReactions) , (2 ^ 14, gatewayIntentDirectMessageTyping)+ , (2 ^ 15, gatewayIntentMessageContent) ] ] @@ -127,25 +131,6 @@ } deriving (Show, Read, Eq, Ord) -data Activity = Activity- { activityName :: T.Text- , activityType :: ActivityType- , activityUrl :: Maybe T.Text- }- deriving (Show, Read, Eq, Ord)--data ActivityType = ActivityTypeGame- | ActivityTypeStreaming- | ActivityTypeListening- | ActivityTypeCompeting- deriving (Show, Read, Eq, Ord)--activityTypeId :: ActivityType -> Int-activityTypeId a = case a of ActivityTypeGame -> 0- ActivityTypeStreaming -> 1- ActivityTypeListening -> 2- ActivityTypeCompeting -> 5- data UpdateStatusType = UpdateStatusOnline | UpdateStatusDoNotDisturb | UpdateStatusAwayFromKeyboard@@ -228,7 +213,7 @@ , "status" .= statusString status , "game" .= (game <&> \a -> object [ "name" .= activityName a- , "type" .= activityTypeId (activityType a)+ , "type" .= fromDiscordType (activityType a) , "url" .= activityUrl a ]) ]
src/Discord/Internal/Types/Guild.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE DeriveDataTypeable #-} -- | Types relating to Discord Guilds (servers) module Discord.Internal.Types.Guild where@@ -8,10 +9,12 @@ import Data.Aeson import qualified Data.Text as T+import Data.Data (Data)+import Data.Default (Default(..)) import Discord.Internal.Types.Prelude import Discord.Internal.Types.Color (DiscordColor)-import Discord.Internal.Types.Channel (Channel)+import Discord.Internal.Types.Channel (Channel, StickerItem) import Discord.Internal.Types.User (User, GuildMember) import Discord.Internal.Types.Components (Emoji) @@ -22,25 +25,57 @@ -- -- https://discord.com/developers/docs/resources/guild#guild-object data Guild = Guild- { guildId :: GuildId -- ^ Gulid id- , guildName :: T.Text -- ^ Guild name (2 - 100 chars)- , guildIcon :: Maybe T.Text -- ^ Icon hash- , guildSplash :: Maybe T.Text -- ^ Splash hash- , guildOwnerId :: UserId -- ^ Guild owner id- , guildPermissions :: Maybe T.Text- , guildRegion :: Maybe T.Text -- ^ Guild voice region- , guildAfkId :: Maybe ChannelId -- ^ Id of afk channel- , guildAfkTimeout :: Integer -- ^ Afk timeout in seconds- , guildWidgetEnabled :: Maybe Bool -- ^ Id of embedded channel- , guildWidgetChannelId :: Maybe ChannelId -- ^ Id of embedded channel- , guildVerificationLevel :: Integer -- ^ Level of verification- , guildNotification :: Integer -- ^ Level of default notifications- , guildExplicitFilterLevel :: Integer- , guildRoles :: [Role] -- ^ Array of 'Role' objects- , guildEmojis :: [Emoji] -- ^ Array of 'Emoji' objects- , guildFeatures :: [T.Text]- , guildMultiFactAuth :: !Integer- , guildApplicationId :: Maybe Snowflake+ { guildId :: GuildId -- ^ Gulid id+ , guildName :: T.Text -- ^ Guild name (2 - 100 chars)+ , guildIcon :: Maybe T.Text -- ^ Icon hash+ , guildIconHash :: Maybe T.Text -- ^ Icon hash, when returned in template object+ , guildSplash :: Maybe T.Text -- ^ Splash hash+ , guildDiscoverySplash :: Maybe T.Text -- ^ Discovery splash hash+ , guildOwner :: Maybe Bool -- ^ True is user is the owner of the guild+ , guildOwnerId :: UserId -- ^ Guild owner id+ , guildPermissions :: Maybe T.Text -- ^ Total permissions for the user in the guild+ , guildAfkId :: Maybe ChannelId -- ^ Id of afk channel+ , guildAfkTimeout :: Integer -- ^ Afk timeout in seconds+ , guildWidgetEnabled :: Maybe Bool -- ^ Id of embedded channel+ , guildWidgetChannelId :: Maybe ChannelId -- ^ Id of embedded channel+ , guildVerificationLevel :: Integer -- ^ Level of verification+ , guildNotification :: Integer -- ^ Level of default notifications+ , guildExplicitFilterLevel :: Integer -- ^ Whose media gets scanned+ , guildRoles :: [Role] -- ^ Array of 'Role' objects+ , guildEmojis :: [Emoji] -- ^ Array of 'Emoji' objects+ , guildFeatures :: [T.Text] -- ^ Array of guild feature strings+ , guildMultiFactAuth :: !Integer -- ^ MFA level for the guild+ , guildApplicationId :: Maybe ApplicationId -- ^ Application id of the guild if bot created+ , guildSystemChannelId :: Maybe ChannelId -- ^ Channel where guild notices such as welcome messages and boost events+ , guildSystemChannelFlags :: Integer -- ^ Flags on the system channel+ , guildRulesChannelId :: Maybe ChannelId -- ^ Id of channel with rules/guidelines+ , guildJoinedAt :: Maybe UTCTime -- ^ When this guild was joined at+ , guildLarge :: Maybe Bool -- ^ True if this guild is considered large+ , guildUnavailable :: Maybe Bool -- ^ True if the guild is unavailable due to outage+ , guildMemberCount :: Maybe Integer -- ^ Total number of members in the guild+ -- voice_states+ , guildMembers :: Maybe [GuildMember] -- ^ Users in the guild+ , guildChannels :: Maybe [Channel] -- ^ Channels in the guild+ , guildThreads :: Maybe [Channel] -- ^ All active threads in the guild that the current user has permission to view+ , guildPresences :: Maybe [PresenceInfo] -- ^ Presences of the members in the guild+ , guildMaxPresences :: Maybe Integer -- ^ Maximum number of prescences in the guild+ , guildMaxMembers :: Maybe Integer -- ^ Maximum number of members in the guild+ , guildVanityURL :: Maybe T.Text -- ^ Vanity url code for the guild+ , guildDescription :: Maybe T.Text -- ^ Description of a commmunity guild+ , guildBanner :: Maybe T.Text -- ^ Banner hash+ , guildPremiumTier :: Integer -- ^ Premium tier (boost level)+ , guildSubscriptionCount :: Maybe Integer -- ^ Number of boosts the guild has+ , guildPreferredLocale :: T.Text -- ^ Preferred locale of a community server+ , guildPublicUpdatesChannel :: Maybe ChannelId -- ^ Id of channel where admins and mods get updates+ , guildMaxVideoUsers :: Maybe Integer -- ^ Maximum number of users in video channel+ , guildApproxMemberCount :: Maybe Integer -- ^ Approximate number of members in the guild+ , guildApproxPresenceCount :: Maybe Integer -- ^ Approximate number of non-offline members in the guild+ -- welcome_screen+ , guildNSFWLevel :: Integer -- ^ Guild NSFW level+ -- stage_instances+ , guildStickers :: Maybe [StickerItem] -- ^ Custom guild stickers+ -- guild_scheduled_events+ , guildPremiumBar :: Bool -- ^ Whether the guild has the boost progress bar enabled } deriving (Show, Read, Eq, Ord) instance FromJSON Guild where@@ -48,10 +83,12 @@ Guild <$> o .: "id" <*> o .: "name" <*> o .:? "icon"+ <*> o .:? "icon_hash" <*> o .:? "splash"+ <*> o .:? "discovery_splash"+ <*> o .:? "owner" <*> o .: "owner_id" <*> o .:? "permissions"- <*> o .:? "region" <*> o .:? "afk_channel_id" <*> o .: "afk_timeout" <*> o .:? "widget_enabled"@@ -64,8 +101,37 @@ <*> o .: "features" <*> o .: "mfa_level" <*> o .:? "application_id"+ <*> o .:? "system_channel_id"+ <*> o .: "system_channel_flags"+ <*> o .:? "rules_channel_id"+ <*> o .:? "joined_at"+ <*> o .:? "large"+ <*> o .:? "unavailable"+ <*> o .:? "member_count"+ -- voice_states+ <*> o .:? "members"+ <*> o .:? "channels"+ <*> o .:? "threads"+ <*> o .:? "presences"+ <*> o .:? "max_presences"+ <*> o .:? "max_members"+ <*> o .:? "vanity_url_code"+ <*> o .:? "description"+ <*> o .:? "banner"+ <*> o .: "premium_tier"+ <*> o .:? "premium_subscription_count"+ <*> o .: "preferred_locale"+ <*> o .:? "public_updates_channel_id"+ <*> o .:? "max_video_channel_users"+ <*> o .:? "approximate_member_count"+ <*> o .:? "approximate_presence_count"+ -- welcome_screen+ <*> o .: "nsfw_level"+ -- stage_instances+ <*> o .:? "stickers"+ <*> o .: "premium_progress_bar_enabled" -data GuildUnavailable = GuildUnavailable+newtype GuildUnavailable = GuildUnavailable { idOnceAvailable :: GuildId } deriving (Show, Read, Eq, Ord) @@ -73,24 +139,120 @@ parseJSON = withObject "GuildUnavailable" $ \o -> GuildUnavailable <$> o .: "id" -data GuildInfo = GuildInfo- { guildJoinedAt :: UTCTime- , guildLarge :: Bool- , guildMemberCount :: Integer- -- , guildVoiceStates :: [VoiceState] -- (without guildid) todo have to add voice state data type- , guildMembers :: [GuildMember]- , guildChannels :: [Channel] -- ^ Channels in the guild (sent in GuildCreate)- -- , guildPresences :: [Presence]- } deriving (Show, Read, Eq, Ord)+data PresenceInfo = PresenceInfo+ { presenceUserId :: UserId+ -- , presenceRoles :: [RoleId]+ , presenceActivities :: Maybe [Activity]+ , presenceGuildId :: Maybe GuildId+ , presenceStatus :: T.Text+ } deriving (Show, Read, Eq, Ord) -instance FromJSON GuildInfo where- parseJSON = withObject "GuildInfo" $ \o ->- GuildInfo <$> o .: "joined_at"- <*> o .: "large"- <*> o .: "member_count"- -- <*> o .: "voice_states"- <*> o .: "members"- <*> o .: "channels"+instance FromJSON PresenceInfo where+ parseJSON = withObject "PresenceInfo" $ \o ->+ PresenceInfo <$> (o .: "user" >>= (.: "id"))+ <*> o .: "activities"+ <*> o .:? "guild_id"+ <*> o .: "status"++-- | Object for a single activity+--+-- https://discord.com/developers/docs/topics/gateway#activity-object+--+-- When setting a bot's activity, only the name, url, and type are sent - and+-- it seems that not many types are permitted either.+data Activity = + Activity+ { activityName :: T.Text -- ^ Name of activity+ , activityType :: ActivityType -- ^ Type of activity+ , activityUrl :: Maybe T.Text -- ^ URL of the activity (only verified when streaming)+ , activityCreatedAt :: Integer -- ^ unix time in milliseconds+ , activityTimeStamps :: Maybe ActivityTimestamps -- ^ Start and end times+ , activityApplicationId :: Maybe ApplicationId -- ^ Application of the activity+ , activityDetails :: Maybe T.Text -- ^ Details of Activity+ , activityState :: Maybe T.Text -- ^ State of the user's party+ , activityEmoji :: Maybe Emoji -- ^ Simplified emoji object+ , activityParty :: Maybe ActivityParty -- ^ Info for the current player's party+ -- assets+ -- secrets+ , activityInstance :: Maybe Bool -- ^ Whether or not the activity is an instanced game session+ , activityFlags :: Maybe Integer -- ^ The flags https://discord.com/developers/docs/topics/gateway#activity-object-activity-flags+ , activityButtons :: Maybe [ActivityButton] -- ^ Custom buttons shown in Rich Presence+ }+ deriving (Show, Read, Eq, Ord)++instance Default Activity where+ def = Activity "discord-haskell" ActivityTypeGame Nothing 0 Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing++instance FromJSON Activity where+ parseJSON = withObject "Activity" $ \o -> do+ Activity <$> o .: "name"+ <*> o .: "type"+ <*> o .:? "url"+ <*> o .: "created_at"+ <*> o .:? "timestamps"+ <*> o .:? "application_id"+ <*> o .:? "details"+ <*> o .:? "state"+ <*> o .:? "emoji"+ <*> o .:? "party"+ -- assets+ -- secrets+ <*> o .:? "instance"+ <*> o .:? "flags"+ <*> o .:? "buttons"++data ActivityTimestamps = ActivityTimestamps+ { activityTimestampsStart :: Maybe Integer -- ^ unix time in milliseconds+ , activityTimestampsEnd :: Maybe Integer -- ^ unix time in milliseconds+ } deriving (Show, Read, Eq, Ord)++instance FromJSON ActivityTimestamps where+ parseJSON = withObject "ActivityTimestamps" $ \o ->+ ActivityTimestamps <$> o .:? "start"+ <*> o .:? "end"++data ActivityParty = ActivityParty+ { activityPartyId :: Maybe T.Text+ , activityPartySize :: Maybe (Integer, Integer)+ } deriving (Show, Read, Eq, Ord)++instance FromJSON ActivityParty where+ parseJSON = withObject "ActivityParty" $ \o ->+ ActivityParty <$> o .:? "id"+ <*> o .:? "size"++data ActivityButton = ActivityButton+ { activityButtonLabel :: T.Text+ , activityButtonUrl :: T.Text+ } deriving (Show, Read, Eq, Ord)++instance FromJSON ActivityButton where+ parseJSON = withObject "ActivityButton" $ \o ->+ ActivityButton <$> o .: "label"+ <*> o .: "url"++-- | To see what these look like, go to here: +-- https://discord.com/developers/docs/topics/gateway#activity-object-activity-types+data ActivityType = + ActivityTypeGame+ | ActivityTypeStreaming+ | ActivityTypeListening+ | ActivityTypeWatching+ | ActivityTypeCustom+ | ActivityTypeCompeting+ deriving (Show, Read, Eq, Ord, Data)++instance InternalDiscordEnum ActivityType where+ discordTypeStartValue = ActivityTypeGame+ fromDiscordType ActivityTypeGame = 0+ fromDiscordType ActivityTypeStreaming = 1+ fromDiscordType ActivityTypeListening = 2+ fromDiscordType ActivityTypeWatching = 3+ fromDiscordType ActivityTypeCustom = 4+ fromDiscordType ActivityTypeCompeting = 5++instance FromJSON ActivityType where+ parseJSON = discordTypeParseJSON "ActivityType" data PartialGuild = PartialGuild { partialGuildId :: GuildId
src/Discord/Internal/Types/Interactions.hs view
@@ -25,10 +25,12 @@ interactionResponseMessageBasic, InteractionResponseMessageFlags (..), InteractionResponseMessageFlag (..),+ InteractionResponseModalData (..), ) where import Control.Applicative (Alternative ((<|>)))+import Control.Monad (join) import Data.Aeson import Data.Aeson.Types (Parser) import Data.Bits (Bits (shift, (.|.)))@@ -37,7 +39,7 @@ import qualified Data.Text as T import Discord.Internal.Types.ApplicationCommands (Choice) import Discord.Internal.Types.Channel (AllowedMentions, Attachment, Message)-import Discord.Internal.Types.Components (ComponentActionRow)+import Discord.Internal.Types.Components (ComponentActionRow, ComponentTextInput) import Discord.Internal.Types.Embed (CreateEmbed, createEmbed) import Discord.Internal.Types.Prelude (ApplicationCommandId, ApplicationId, ChannelId, GuildId, InteractionId, InteractionToken, MessageId, RoleId, Snowflake, UserId) import Discord.Internal.Types.User (GuildMember, User)@@ -122,7 +124,29 @@ -- | The invoking guild's preferred locale. interactionGuildLocale :: Maybe T.Text }- deriving (Show, Eq, Read)+ | InteractionModalSubmit+ { -- | The id of this interaction.+ interactionId :: InteractionId,+ -- | The id of the application that this interaction belongs to.+ interactionApplicationId :: ApplicationId,+ -- | The data for this interaction.+ interactionDataModal :: InteractionDataModal,+ -- | What guild this interaction comes from.+ interactionGuildId :: Maybe GuildId,+ -- | What channel this interaction comes from.+ interactionChannelId :: Maybe ChannelId,+ -- | What user/member this interaction comes from.+ interactionUser :: MemberOrUser,+ -- | The unique token that represents this interaction.+ interactionToken :: InteractionToken,+ -- | What version of interaction is this (always 1).+ interactionVersion :: Int,+ -- | The invoking user's preferred locale.+ interactionLocale :: T.Text,+ -- | The invoking guild's preferred locale.+ interactionGuildLocale :: Maybe T.Text+ }+ deriving (Show, Read, Eq, Ord) instance FromJSON Interaction where parseJSON =@@ -170,10 +194,21 @@ <*> return version <*> v .: "locale" <*> return glocale+ 5 ->+ InteractionModalSubmit iid aid+ <$> v .: "data"+ <*> return gid+ <*> return cid+ <*> parseJSON (Object v)+ <*> return tok+ <*> return version+ <*> v .: "locale"+ <*> return glocale _ -> fail "unknown interaction type" ) -newtype MemberOrUser = MemberOrUser (Either GuildMember User) deriving (Show, Eq, Read)+newtype MemberOrUser = MemberOrUser (Either GuildMember User)+ deriving (Show, Read, Eq, Ord) instance {-# OVERLAPPING #-} FromJSON MemberOrUser where parseJSON =@@ -193,7 +228,7 @@ -- | Values for the select menu. interactionDataComponentValues :: [T.Text] }- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance FromJSON InteractionDataComponent where parseJSON =@@ -241,7 +276,7 @@ -- | The options of the application command. interactionDataApplicationCommandOptions :: Maybe InteractionDataApplicationCommandOptions }- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance FromJSON InteractionDataApplicationCommand where parseJSON =@@ -269,7 +304,7 @@ data InteractionDataApplicationCommandOptions = InteractionDataApplicationCommandOptionsSubcommands [InteractionDataApplicationCommandOptionSubcommandOrGroup] | InteractionDataApplicationCommandOptionsValues [InteractionDataApplicationCommandOptionValue]- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance FromJSON InteractionDataApplicationCommandOptions where parseJSON =@@ -299,7 +334,7 @@ interactionDataApplicationCommandOptionSubcommandGroupFocused :: Bool } | InteractionDataApplicationCommandOptionSubcommandOrGroupSubcommand InteractionDataApplicationCommandOptionSubcommand- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance FromJSON InteractionDataApplicationCommandOptionSubcommandOrGroup where parseJSON =@@ -323,7 +358,7 @@ interactionDataApplicationCommandOptionSubcommandOptions :: [InteractionDataApplicationCommandOptionValue], interactionDataApplicationCommandOptionSubcommandFocused :: Bool }- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance FromJSON InteractionDataApplicationCommandOptionSubcommand where parseJSON =@@ -374,7 +409,7 @@ { interactionDataApplicationCommandOptionValueName :: T.Text, interactionDataApplicationCommandOptionValueNumberValue :: Either T.Text Scientific }- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance FromJSON InteractionDataApplicationCommandOptionValue where parseJSON =@@ -412,6 +447,30 @@ _ -> fail $ "unexpected interaction data application command option value type: " ++ show t ) +data InteractionDataModal = InteractionDataModal+ { -- | The unique id of the component (up to 100 characters).+ interactionDataModalCustomId :: T.Text,+ -- | Components from the modal.+ interactionDataModalComponents :: [ComponentTextInput]+ }+ deriving (Show, Read, Eq, Ord)++instance FromJSON InteractionDataModal where+ parseJSON =+ withObject+ "InteractionDataModal"+ ( \v ->+ InteractionDataModal <$> v .: "custom_id"+ <*> ((v .: "components") >>= (join <$>) . mapM getTextInput)+ )+ where+ getTextInput :: Value -> Parser [ComponentTextInput]+ getTextInput = withObject "InteractionDataModal.TextInput" $ \o -> do+ t <- o .: "type" :: Parser Int+ case t of+ 1 -> o .: "components"+ _ -> fail $ "expected action row type (1), got: " ++ show t+ parseValue :: (FromJSON a) => Object -> Bool -> Parser (Either T.Text a) parseValue o True = Left <$> o .: "value" parseValue o False = Right <$> o .: "value"@@ -429,9 +488,11 @@ { resolvedDataUsers :: Maybe Value, resolvedDataMembers :: Maybe Value, resolvedDataRoles :: Maybe Value,- resolvedDataChannels :: Maybe Value+ resolvedDataChannels :: Maybe Value,+ resolvedDataMessages :: Maybe Value,+ resolvedDataAttachments :: Maybe Value }- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance ToJSON ResolvedData where toJSON ResolvedData {..} =@@ -441,7 +502,9 @@ [ ("users", resolvedDataUsers), ("members", resolvedDataMembers), ("roles", resolvedDataRoles),- ("channels", resolvedDataChannels)+ ("channels", resolvedDataChannels),+ ("messages", resolvedDataMessages),+ ("attachments", resolvedDataAttachments) ] ] @@ -455,6 +518,8 @@ <*> v .:? "members" <*> v .:? "roles" <*> v .:? "channels"+ <*> v .:? "messages"+ <*> v .:? "attachments" ) -- | The data to respond to an interaction with. Unless specified otherwise, you@@ -473,6 +538,9 @@ InteractionResponseUpdateMessage InteractionResponseMessage | -- | respond to an autocomplete interaction with suggested choices InteractionResponseAutocompleteResult InteractionResponseAutocomplete+ | -- | respond with a popup modal+ InteractionResponseModal InteractionResponseModalData+ deriving (Show, Read, Eq, Ord) -- | A basic interaction response, sending back the given text. interactionResponseBasic :: T.Text -> InteractionResponse@@ -485,9 +553,10 @@ toJSON (InteractionResponseChannelMessage ms) = object [("type", Number 4), ("data", toJSON ms)] toJSON (InteractionResponseUpdateMessage ms) = object [("type", Number 7), ("data", toJSON ms)] toJSON (InteractionResponseAutocompleteResult ms) = object [("type", Number 8), ("data", toJSON ms)]+ toJSON (InteractionResponseModal ms) = object [("type", Number 9), ("data", toJSON ms)] data InteractionResponseAutocomplete = InteractionResponseAutocompleteString [Choice T.Text] | InteractionResponseAutocompleteInteger [Choice Integer] | InteractionResponseAutocompleteNumber [Choice Scientific]- deriving (Show, Eq)+ deriving (Show, Read, Eq, Ord) instance ToJSON InteractionResponseAutocomplete where toJSON (InteractionResponseAutocompleteString cs) = object [("choices", toJSON cs)]@@ -504,7 +573,7 @@ interactionResponseMessageComponents :: Maybe [ComponentActionRow], interactionResponseMessageAttachments :: Maybe [Attachment] }- deriving (Show, Eq)+ deriving (Show, Read, Eq, Ord) -- | A basic interaction response, sending back the given text. This is -- effectively a helper function.@@ -531,10 +600,10 @@ -- Currently the only flag is EPHERMERAL, which means only the user can see the -- message. data InteractionResponseMessageFlag = InteractionResponseMessageFlagEphermeral- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) newtype InteractionResponseMessageFlags = InteractionResponseMessageFlags [InteractionResponseMessageFlag]- deriving (Show, Read, Eq)+ deriving (Show, Read, Eq, Ord) instance Enum InteractionResponseMessageFlag where fromEnum InteractionResponseMessageFlagEphermeral = 1 `shift` 6@@ -544,3 +613,18 @@ instance ToJSON InteractionResponseMessageFlags where toJSON (InteractionResponseMessageFlags fs) = Number $ fromInteger $ fromIntegral $ foldr (.|.) 0 (fromEnum <$> fs)++data InteractionResponseModalData = InteractionResponseModalData+ { interactionResponseModalCustomId :: T.Text,+ interactionResponseModalTitle :: T.Text,+ interactionResponseModalComponents :: [ComponentTextInput]+ }+ deriving (Show, Read, Eq, Ord)++instance ToJSON InteractionResponseModalData where+ toJSON InteractionResponseModalData {..} =+ object+ [ ("custom_id", toJSON interactionResponseModalCustomId),+ ("title", toJSON interactionResponseModalTitle),+ ("components", toJSON $ map (\ti -> object [("type", Number 1), ("components", toJSON [ti])]) interactionResponseModalComponents)+ ]