discord-haskell 1.12.4 → 1.12.5
raw patch · 15 files changed
+952/−174 lines, 15 filesdep −vectorPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: vector
API changes (from Hackage documentation)
- Discord.Internal.Types.Channel: StickerFormatTypeAPNG :: StickerFormatType
- Discord.Internal.Types.Channel: StickerFormatTypeLOTTIE :: StickerFormatType
- Discord.Internal.Types.Channel: StickerFormatTypePNG :: StickerFormatType
- Discord.Internal.Types.Channel: StickerItem :: StickerId -> Text -> StickerFormatType -> StickerItem
- Discord.Internal.Types.Channel: [stickerItemFormatType] :: StickerItem -> StickerFormatType
- Discord.Internal.Types.Channel: [stickerItemId] :: StickerItem -> StickerId
- Discord.Internal.Types.Channel: [stickerItemName] :: StickerItem -> Text
- Discord.Internal.Types.Channel: data StickerFormatType
- Discord.Internal.Types.Channel: data StickerItem
- Discord.Internal.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Channel.StickerItem
- Discord.Internal.Types.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Channel.StickerItem
- Discord.Internal.Types.Channel: instance Data.Data.Data Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance Discord.Internal.Types.Prelude.InternalDiscordEnum Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance GHC.Classes.Eq Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance GHC.Classes.Eq Discord.Internal.Types.Channel.StickerItem
- Discord.Internal.Types.Channel: instance GHC.Classes.Ord Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance GHC.Classes.Ord Discord.Internal.Types.Channel.StickerItem
- Discord.Internal.Types.Channel: instance GHC.Read.Read Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance GHC.Read.Read Discord.Internal.Types.Channel.StickerItem
- Discord.Internal.Types.Channel: instance GHC.Show.Show Discord.Internal.Types.Channel.StickerFormatType
- Discord.Internal.Types.Channel: instance GHC.Show.Show Discord.Internal.Types.Channel.StickerItem
- Discord.Internal.Types.Components: Emoji :: Maybe EmojiId -> Text -> Maybe [RoleId] -> Maybe User -> Maybe Bool -> Maybe Bool -> Emoji
- Discord.Internal.Types.Components: [emojiAnimated] :: Emoji -> Maybe Bool
- Discord.Internal.Types.Components: [emojiId] :: Emoji -> Maybe EmojiId
- Discord.Internal.Types.Components: [emojiManaged] :: Emoji -> Maybe Bool
- Discord.Internal.Types.Components: [emojiName] :: Emoji -> Text
- Discord.Internal.Types.Components: [emojiRoles] :: Emoji -> Maybe [RoleId]
- Discord.Internal.Types.Components: [emojiUser] :: Emoji -> Maybe User
- Discord.Internal.Types.Components: data Emoji
- Discord.Internal.Types.Components: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Components.Emoji
- Discord.Internal.Types.Components: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Components.Emoji
- Discord.Internal.Types.Components: instance GHC.Classes.Eq Discord.Internal.Types.Components.Emoji
- Discord.Internal.Types.Components: instance GHC.Classes.Ord Discord.Internal.Types.Components.Emoji
- Discord.Internal.Types.Components: instance GHC.Read.Read Discord.Internal.Types.Components.Emoji
- Discord.Internal.Types.Components: instance GHC.Show.Show Discord.Internal.Types.Components.Emoji
- Discord.Internal.Types.Components: mkEmoji :: Text -> Emoji
+ Discord.Internal.Rest.Emoji: CreateGuildStickerOpts :: Text -> Text -> [Text] -> StickerData -> CreateGuildStickerOpts
+ Discord.Internal.Rest.Emoji: EditGuildStickerOpts :: Maybe Text -> Maybe Text -> Maybe [Text] -> EditGuildStickerOpts
+ Discord.Internal.Rest.Emoji: [CreateGuildSticker] :: GuildId -> CreateGuildStickerOpts -> StickerRequest Sticker
+ Discord.Internal.Rest.Emoji: [DeleteGuildSticker] :: GuildId -> StickerId -> StickerRequest ()
+ Discord.Internal.Rest.Emoji: [GetGuildSticker] :: GuildId -> StickerId -> StickerRequest Sticker
+ Discord.Internal.Rest.Emoji: [GetSticker] :: StickerId -> StickerRequest Sticker
+ Discord.Internal.Rest.Emoji: [ListGuildStickers] :: GuildId -> StickerRequest [Sticker]
+ Discord.Internal.Rest.Emoji: [ListNitroStickerPacks] :: StickerRequest [StickerPack]
+ Discord.Internal.Rest.Emoji: [ModifyGuildSticker] :: GuildId -> StickerId -> EditGuildStickerOpts -> StickerRequest Sticker
+ Discord.Internal.Rest.Emoji: [editGuildStickerDescription] :: EditGuildStickerOpts -> Maybe Text
+ Discord.Internal.Rest.Emoji: [editGuildStickerName] :: EditGuildStickerOpts -> Maybe Text
+ Discord.Internal.Rest.Emoji: [editGuildStickerTags] :: EditGuildStickerOpts -> Maybe [Text]
+ Discord.Internal.Rest.Emoji: [guildStickerDescription] :: CreateGuildStickerOpts -> Text
+ Discord.Internal.Rest.Emoji: [guildStickerFile] :: CreateGuildStickerOpts -> StickerData
+ Discord.Internal.Rest.Emoji: [guildStickerName] :: CreateGuildStickerOpts -> Text
+ Discord.Internal.Rest.Emoji: [guildStickerTags] :: CreateGuildStickerOpts -> [Text]
+ Discord.Internal.Rest.Emoji: data CreateGuildStickerOpts
+ Discord.Internal.Rest.Emoji: data EditGuildStickerOpts
+ Discord.Internal.Rest.Emoji: data StickerRequest a
+ Discord.Internal.Rest.Emoji: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Rest.Emoji.CreateGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Rest.Emoji.EditGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Rest.Emoji.StickerData
+ Discord.Internal.Rest.Emoji: instance Discord.Internal.Rest.Prelude.Request (Discord.Internal.Rest.Emoji.StickerRequest a)
+ Discord.Internal.Rest.Emoji: instance GHC.Classes.Eq Discord.Internal.Rest.Emoji.CreateGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Classes.Eq Discord.Internal.Rest.Emoji.EditGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Classes.Eq Discord.Internal.Rest.Emoji.StickerData
+ Discord.Internal.Rest.Emoji: instance GHC.Classes.Ord Discord.Internal.Rest.Emoji.CreateGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Classes.Ord Discord.Internal.Rest.Emoji.EditGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Classes.Ord Discord.Internal.Rest.Emoji.StickerData
+ Discord.Internal.Rest.Emoji: instance GHC.Read.Read Discord.Internal.Rest.Emoji.CreateGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Read.Read Discord.Internal.Rest.Emoji.EditGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Read.Read Discord.Internal.Rest.Emoji.StickerData
+ Discord.Internal.Rest.Emoji: instance GHC.Show.Show Discord.Internal.Rest.Emoji.CreateGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Show.Show Discord.Internal.Rest.Emoji.EditGuildStickerOpts
+ Discord.Internal.Rest.Emoji: instance GHC.Show.Show Discord.Internal.Rest.Emoji.StickerData
+ Discord.Internal.Rest.Guild: [modifyGuildMemberOptsTimeoutUntil] :: ModifyGuildMemberOpts -> Maybe (Maybe UTCTime)
+ Discord.Internal.Rest.Guild: instance Data.Default.Class.Default Discord.Internal.Rest.Guild.ModifyGuildMemberOpts
+ Discord.Internal.Types.Emoji: Emoji :: Maybe EmojiId -> Text -> Maybe [RoleId] -> Maybe User -> Maybe Bool -> Maybe Bool -> Emoji
+ Discord.Internal.Types.Emoji: Sticker :: StickerId -> Maybe Snowflake -> Text -> Maybe Text -> [Text] -> Bool -> StickerFormatType -> Maybe Bool -> Maybe GuildId -> Maybe User -> Maybe Integer -> Sticker
+ Discord.Internal.Types.Emoji: StickerFormatTypeAPNG :: StickerFormatType
+ Discord.Internal.Types.Emoji: StickerFormatTypeLOTTIE :: StickerFormatType
+ Discord.Internal.Types.Emoji: StickerFormatTypePNG :: StickerFormatType
+ Discord.Internal.Types.Emoji: StickerItem :: StickerId -> Text -> StickerFormatType -> StickerItem
+ Discord.Internal.Types.Emoji: StickerPack :: Snowflake -> [Sticker] -> Text -> Snowflake -> Maybe StickerId -> Text -> Maybe Snowflake -> StickerPack
+ Discord.Internal.Types.Emoji: [emojiAnimated] :: Emoji -> Maybe Bool
+ Discord.Internal.Types.Emoji: [emojiId] :: Emoji -> Maybe EmojiId
+ Discord.Internal.Types.Emoji: [emojiManaged] :: Emoji -> Maybe Bool
+ Discord.Internal.Types.Emoji: [emojiName] :: Emoji -> Text
+ Discord.Internal.Types.Emoji: [emojiRoles] :: Emoji -> Maybe [RoleId]
+ Discord.Internal.Types.Emoji: [emojiUser] :: Emoji -> Maybe User
+ Discord.Internal.Types.Emoji: [stickerAvailable] :: Sticker -> Maybe Bool
+ Discord.Internal.Types.Emoji: [stickerDescription] :: Sticker -> Maybe Text
+ Discord.Internal.Types.Emoji: [stickerFormatType] :: Sticker -> StickerFormatType
+ Discord.Internal.Types.Emoji: [stickerGuildId] :: Sticker -> Maybe GuildId
+ Discord.Internal.Types.Emoji: [stickerId] :: Sticker -> StickerId
+ Discord.Internal.Types.Emoji: [stickerIsStandardType] :: Sticker -> Bool
+ Discord.Internal.Types.Emoji: [stickerItemFormatType] :: StickerItem -> StickerFormatType
+ Discord.Internal.Types.Emoji: [stickerItemId] :: StickerItem -> StickerId
+ Discord.Internal.Types.Emoji: [stickerItemName] :: StickerItem -> Text
+ Discord.Internal.Types.Emoji: [stickerName] :: Sticker -> Text
+ Discord.Internal.Types.Emoji: [stickerPackBannerAssetId] :: StickerPack -> Maybe Snowflake
+ Discord.Internal.Types.Emoji: [stickerPackCoverStickerId] :: StickerPack -> Maybe StickerId
+ Discord.Internal.Types.Emoji: [stickerPackDescription] :: StickerPack -> Text
+ Discord.Internal.Types.Emoji: [stickerPackId] :: StickerPack -> Snowflake
+ Discord.Internal.Types.Emoji: [stickerPackName] :: StickerPack -> Text
+ Discord.Internal.Types.Emoji: [stickerPackSKUId] :: StickerPack -> Snowflake
+ Discord.Internal.Types.Emoji: [stickerPackStickers] :: StickerPack -> [Sticker]
+ Discord.Internal.Types.Emoji: [stickerSortValue] :: Sticker -> Maybe Integer
+ Discord.Internal.Types.Emoji: [stickerStickerPackId] :: Sticker -> Maybe Snowflake
+ Discord.Internal.Types.Emoji: [stickerTags] :: Sticker -> [Text]
+ Discord.Internal.Types.Emoji: [stickerUser] :: Sticker -> Maybe User
+ Discord.Internal.Types.Emoji: data Emoji
+ Discord.Internal.Types.Emoji: data Sticker
+ Discord.Internal.Types.Emoji: data StickerFormatType
+ Discord.Internal.Types.Emoji: data StickerItem
+ Discord.Internal.Types.Emoji: data StickerPack
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Emoji.Emoji
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Emoji.Sticker
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Emoji.StickerItem
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.Emoji.StickerPack
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Emoji.Emoji
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.Emoji.StickerItem
+ Discord.Internal.Types.Emoji: instance Data.Data.Data Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance Discord.Internal.Types.Prelude.InternalDiscordEnum Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Eq Discord.Internal.Types.Emoji.Emoji
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Eq Discord.Internal.Types.Emoji.Sticker
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Eq Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Eq Discord.Internal.Types.Emoji.StickerItem
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Eq Discord.Internal.Types.Emoji.StickerPack
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Ord Discord.Internal.Types.Emoji.Emoji
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Ord Discord.Internal.Types.Emoji.Sticker
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Ord Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Ord Discord.Internal.Types.Emoji.StickerItem
+ Discord.Internal.Types.Emoji: instance GHC.Classes.Ord Discord.Internal.Types.Emoji.StickerPack
+ Discord.Internal.Types.Emoji: instance GHC.Read.Read Discord.Internal.Types.Emoji.Emoji
+ Discord.Internal.Types.Emoji: instance GHC.Read.Read Discord.Internal.Types.Emoji.Sticker
+ Discord.Internal.Types.Emoji: instance GHC.Read.Read Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance GHC.Read.Read Discord.Internal.Types.Emoji.StickerItem
+ Discord.Internal.Types.Emoji: instance GHC.Read.Read Discord.Internal.Types.Emoji.StickerPack
+ Discord.Internal.Types.Emoji: instance GHC.Show.Show Discord.Internal.Types.Emoji.Emoji
+ Discord.Internal.Types.Emoji: instance GHC.Show.Show Discord.Internal.Types.Emoji.Sticker
+ Discord.Internal.Types.Emoji: instance GHC.Show.Show Discord.Internal.Types.Emoji.StickerFormatType
+ Discord.Internal.Types.Emoji: instance GHC.Show.Show Discord.Internal.Types.Emoji.StickerItem
+ Discord.Internal.Types.Emoji: instance GHC.Show.Show Discord.Internal.Types.Emoji.StickerPack
+ Discord.Internal.Types.Emoji: mkEmoji :: Text -> Emoji
+ Discord.Internal.Types.Prelude: type ScheduledEventEntityId = Snowflake
+ Discord.Internal.Types.Prelude: type ScheduledEventId = Snowflake
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventDataExternal :: Text -> Text -> ScheduledEventPrivacyLevel -> UTCTime -> UTCTime -> Maybe Text -> Maybe CreateScheduledEventImage -> CreateScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventDataStage :: ChannelId -> Text -> ScheduledEventPrivacyLevel -> UTCTime -> Maybe UTCTime -> Maybe Text -> Maybe CreateScheduledEventImage -> CreateScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventDataVoice :: ChannelId -> Text -> ScheduledEventPrivacyLevel -> UTCTime -> Maybe UTCTime -> Maybe Text -> Maybe CreateScheduledEventImage -> CreateScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventImageURL :: Text -> CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventImageUpload :: CreateScheduledEventImageUploadType -> ByteString -> CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventImageUploadTypeGIF :: CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventImageUploadTypeJPG :: CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: CreateScheduledEventImageUploadTypePNG :: CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: ModifyScheduledEventData :: Maybe (Maybe ChannelId) -> Maybe (Maybe Text) -> Maybe Text -> Maybe ScheduledEventPrivacyLevel -> Maybe UTCTime -> Maybe UTCTime -> Maybe (Maybe Text) -> Maybe ScheduledEventType -> Maybe ScheduledEventStatus -> Maybe CreateScheduledEventImage -> ModifyScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventExternal :: ScheduledEventId -> GuildId -> Text -> Maybe UserId -> Text -> Maybe Text -> UTCTime -> UTCTime -> ScheduledEventPrivacyLevel -> ScheduledEventStatus -> Maybe ScheduledEventEntityId -> Maybe User -> Maybe Integer -> Maybe ScheduledEventImageHash -> ScheduledEvent
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventPrivacyLevelGuildOnly :: ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventStage :: ScheduledEventId -> GuildId -> ChannelId -> Maybe UserId -> Text -> Maybe Text -> UTCTime -> Maybe UTCTime -> ScheduledEventPrivacyLevel -> ScheduledEventStatus -> Maybe ScheduledEventEntityId -> Maybe User -> Maybe Integer -> Maybe ScheduledEventImageHash -> ScheduledEvent
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventStatusActive :: ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventStatusCancelled :: ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventStatusCompleted :: ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventStatusScheduled :: ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventTypeExternal :: ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventTypeStage :: ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventTypeVoice :: ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventUser :: ScheduledEventId -> User -> Maybe GuildMember -> ScheduledEventUser
+ Discord.Internal.Types.ScheduledEvents: ScheduledEventVoice :: ScheduledEventId -> GuildId -> ChannelId -> Maybe UserId -> Text -> Maybe Text -> UTCTime -> Maybe UTCTime -> ScheduledEventPrivacyLevel -> ScheduledEventStatus -> Maybe ScheduledEventEntityId -> Maybe User -> Maybe Integer -> Maybe ScheduledEventImageHash -> ScheduledEvent
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataExternalDescription] :: CreateScheduledEventData -> Maybe Text
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataExternalEndTime] :: CreateScheduledEventData -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataExternalImage] :: CreateScheduledEventData -> Maybe CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataExternalLocation] :: CreateScheduledEventData -> Text
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataExternalName] :: CreateScheduledEventData -> Text
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataExternalPrivacyLevel] :: CreateScheduledEventData -> ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataExternalStartTime] :: CreateScheduledEventData -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataStageChannelId] :: CreateScheduledEventData -> ChannelId
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataStageDescription] :: CreateScheduledEventData -> Maybe Text
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataStageEndTime] :: CreateScheduledEventData -> Maybe UTCTime
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataStageImage] :: CreateScheduledEventData -> Maybe CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataStageName] :: CreateScheduledEventData -> Text
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataStagePrivacyLevel] :: CreateScheduledEventData -> ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataStageStartTime] :: CreateScheduledEventData -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataVoiceChannelId] :: CreateScheduledEventData -> ChannelId
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataVoiceDescription] :: CreateScheduledEventData -> Maybe Text
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataVoiceEndTime] :: CreateScheduledEventData -> Maybe UTCTime
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataVoiceImage] :: CreateScheduledEventData -> Maybe CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataVoiceName] :: CreateScheduledEventData -> Text
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataVoicePrivacyLevel] :: CreateScheduledEventData -> ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: [createScheduleEventDataVoiceStartTime] :: CreateScheduledEventData -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataChannelId] :: ModifyScheduledEventData -> Maybe (Maybe ChannelId)
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataDescription] :: ModifyScheduledEventData -> Maybe (Maybe Text)
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataEndTime] :: ModifyScheduledEventData -> Maybe UTCTime
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataImage] :: ModifyScheduledEventData -> Maybe CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataLocation] :: ModifyScheduledEventData -> Maybe (Maybe Text)
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataName] :: ModifyScheduledEventData -> Maybe Text
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataPrivacyLevel] :: ModifyScheduledEventData -> Maybe ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataStartTime] :: ModifyScheduledEventData -> Maybe UTCTime
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataStatus] :: ModifyScheduledEventData -> Maybe ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: [modifyScheduledEventDataType] :: ModifyScheduledEventData -> Maybe ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalCreatorId] :: ScheduledEvent -> Maybe UserId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalCreator] :: ScheduledEvent -> Maybe User
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalDescription] :: ScheduledEvent -> Maybe Text
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalEndTime] :: ScheduledEvent -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalEntityId] :: ScheduledEvent -> Maybe ScheduledEventEntityId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalGuildId] :: ScheduledEvent -> GuildId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalId] :: ScheduledEvent -> ScheduledEventId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalImage] :: ScheduledEvent -> Maybe ScheduledEventImageHash
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalLocation] :: ScheduledEvent -> Text
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalName] :: ScheduledEvent -> Text
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalPrivacyLevel] :: ScheduledEvent -> ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalStartTime] :: ScheduledEvent -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalStatus] :: ScheduledEvent -> ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventExternalUserCount] :: ScheduledEvent -> Maybe Integer
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageChannelId] :: ScheduledEvent -> ChannelId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageCreatorId] :: ScheduledEvent -> Maybe UserId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageCreator] :: ScheduledEvent -> Maybe User
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageDescription] :: ScheduledEvent -> Maybe Text
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageEndTime] :: ScheduledEvent -> Maybe UTCTime
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageEntityId] :: ScheduledEvent -> Maybe ScheduledEventEntityId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageGuildId] :: ScheduledEvent -> GuildId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageId] :: ScheduledEvent -> ScheduledEventId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageImage] :: ScheduledEvent -> Maybe ScheduledEventImageHash
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageName] :: ScheduledEvent -> Text
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStagePrivacyLevel] :: ScheduledEvent -> ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageStartTime] :: ScheduledEvent -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageStatus] :: ScheduledEvent -> ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventStageUserCount] :: ScheduledEvent -> Maybe Integer
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventUserEvent] :: ScheduledEventUser -> ScheduledEventId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventUserGuildMember] :: ScheduledEventUser -> Maybe GuildMember
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventUserUser] :: ScheduledEventUser -> User
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceChannelId] :: ScheduledEvent -> ChannelId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceCreatorId] :: ScheduledEvent -> Maybe UserId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceCreator] :: ScheduledEvent -> Maybe User
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceDescription] :: ScheduledEvent -> Maybe Text
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceEndTime] :: ScheduledEvent -> Maybe UTCTime
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceEntityId] :: ScheduledEvent -> Maybe ScheduledEventEntityId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceGuildId] :: ScheduledEvent -> GuildId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceId] :: ScheduledEvent -> ScheduledEventId
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceImage] :: ScheduledEvent -> Maybe ScheduledEventImageHash
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceName] :: ScheduledEvent -> Text
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoicePrivacyLevel] :: ScheduledEvent -> ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceStartTime] :: ScheduledEvent -> UTCTime
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceStatus] :: ScheduledEvent -> ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: [scheduledEventVoiceUserCount] :: ScheduledEvent -> Maybe Integer
+ Discord.Internal.Types.ScheduledEvents: data CreateScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: data CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: data CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: data ModifyScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: data ScheduledEvent
+ Discord.Internal.Types.ScheduledEvents: data ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: data ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: data ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: data ScheduledEventUser
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.CreateScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.ModifyScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.ScheduledEvent
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.FromJSON.FromJSON Discord.Internal.Types.ScheduledEvents.ScheduledEventUser
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.ScheduledEvents.CreateScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.ScheduledEvents.ModifyScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.ScheduledEvents.ScheduledEvent
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance Data.Aeson.Types.ToJSON.ToJSON Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: instance Data.Data.Data Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance Data.Data.Data Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance Data.Data.Data Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: instance Data.Default.Class.Default Discord.Internal.Types.ScheduledEvents.ModifyScheduledEventData
+ Discord.Internal.Types.ScheduledEvents: instance Discord.Internal.Types.Prelude.InternalDiscordEnum Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance Discord.Internal.Types.Prelude.InternalDiscordEnum Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance Discord.Internal.Types.Prelude.InternalDiscordEnum Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Eq Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Eq Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Eq Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Eq Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Eq Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Ord Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Ord Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Ord Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Ord Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Classes.Ord Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Read.Read Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Read.Read Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Read.Read Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Read.Read Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Read.Read Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Show.Show Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImage
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Show.Show Discord.Internal.Types.ScheduledEvents.CreateScheduledEventImageUploadType
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Show.Show Discord.Internal.Types.ScheduledEvents.ScheduledEventPrivacyLevel
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Show.Show Discord.Internal.Types.ScheduledEvents.ScheduledEventStatus
+ Discord.Internal.Types.ScheduledEvents: instance GHC.Show.Show Discord.Internal.Types.ScheduledEvents.ScheduledEventType
+ Discord.Internal.Types.ScheduledEvents: type ScheduledEventImageHash = Text
+ Discord.Internal.Types.User: [memberTimeoutEnd] :: GuildMember -> Maybe UTCTime
+ Discord.Types: Sticker :: StickerId -> Maybe Snowflake -> Text -> Maybe Text -> [Text] -> Bool -> StickerFormatType -> Maybe Bool -> Maybe GuildId -> Maybe User -> Maybe Integer -> Sticker
+ Discord.Types: StickerPack :: Snowflake -> [Sticker] -> Text -> Snowflake -> Maybe StickerId -> Text -> Maybe Snowflake -> StickerPack
+ Discord.Types: [memberTimeoutEnd] :: GuildMember -> Maybe UTCTime
+ Discord.Types: [stickerAvailable] :: Sticker -> Maybe Bool
+ Discord.Types: [stickerDescription] :: Sticker -> Maybe Text
+ Discord.Types: [stickerFormatType] :: Sticker -> StickerFormatType
+ Discord.Types: [stickerGuildId] :: Sticker -> Maybe GuildId
+ Discord.Types: [stickerId] :: Sticker -> StickerId
+ Discord.Types: [stickerIsStandardType] :: Sticker -> Bool
+ Discord.Types: [stickerName] :: Sticker -> Text
+ Discord.Types: [stickerPackBannerAssetId] :: StickerPack -> Maybe Snowflake
+ Discord.Types: [stickerPackCoverStickerId] :: StickerPack -> Maybe StickerId
+ Discord.Types: [stickerPackDescription] :: StickerPack -> Text
+ Discord.Types: [stickerPackId] :: StickerPack -> Snowflake
+ Discord.Types: [stickerPackName] :: StickerPack -> Text
+ Discord.Types: [stickerPackSKUId] :: StickerPack -> Snowflake
+ Discord.Types: [stickerPackStickers] :: StickerPack -> [Sticker]
+ Discord.Types: [stickerSortValue] :: Sticker -> Maybe Integer
+ Discord.Types: [stickerStickerPackId] :: Sticker -> Maybe Snowflake
+ Discord.Types: [stickerTags] :: Sticker -> [Text]
+ Discord.Types: [stickerUser] :: Sticker -> Maybe User
+ Discord.Types: data Sticker
+ Discord.Types: data StickerPack
+ Discord.Types: type ScheduledEventEntityId = Snowflake
+ Discord.Types: type ScheduledEventId = Snowflake
- Discord.Internal.Rest.Guild: ModifyGuildMemberOpts :: Maybe Text -> Maybe [RoleId] -> Maybe Bool -> Maybe Bool -> Maybe ChannelId -> ModifyGuildMemberOpts
+ Discord.Internal.Rest.Guild: ModifyGuildMemberOpts :: Maybe Text -> Maybe [RoleId] -> Maybe Bool -> Maybe Bool -> Maybe ChannelId -> Maybe (Maybe UTCTime) -> ModifyGuildMemberOpts
- Discord.Internal.Rest.Guild: [ModifyGuildMember] :: GuildId -> UserId -> ModifyGuildMemberOpts -> GuildRequest ()
+ Discord.Internal.Rest.Guild: [ModifyGuildMember] :: GuildId -> UserId -> ModifyGuildMemberOpts -> GuildRequest GuildMember
- Discord.Internal.Types.User: GuildMember :: Maybe User -> Maybe Text -> Maybe Text -> [RoleId] -> UTCTime -> Maybe UTCTime -> Bool -> Bool -> Bool -> Maybe Text -> GuildMember
+ Discord.Internal.Types.User: GuildMember :: Maybe User -> Maybe Text -> Maybe Text -> [RoleId] -> UTCTime -> Maybe UTCTime -> Bool -> Bool -> Bool -> Maybe Text -> Maybe UTCTime -> GuildMember
- Discord.Types: GuildMember :: Maybe User -> Maybe Text -> Maybe Text -> [RoleId] -> UTCTime -> Maybe UTCTime -> Bool -> Bool -> Bool -> Maybe Text -> GuildMember
+ Discord.Types: GuildMember :: Maybe User -> Maybe Text -> Maybe Text -> [RoleId] -> UTCTime -> Maybe UTCTime -> Bool -> Bool -> Bool -> Maybe Text -> Maybe UTCTime -> GuildMember
Files
- README.md +12/−27
- changelog.md +8/−0
- discord-haskell.cabal +3/−2
- src/Discord/Internal/Rest/Emoji.hs +168/−50
- src/Discord/Internal/Rest/Guild.hs +9/−2
- src/Discord/Internal/Rest/Prelude.hs +1/−1
- src/Discord/Internal/Types.hs +2/−0
- src/Discord/Internal/Types/Channel.hs +4/−41
- src/Discord/Internal/Types/Components.hs +2/−48
- src/Discord/Internal/Types/Emoji.hs +169/−0
- src/Discord/Internal/Types/Events.hs +1/−1
- src/Discord/Internal/Types/Guild.hs +2/−2
- src/Discord/Internal/Types/Prelude.hs +2/−0
- src/Discord/Internal/Types/ScheduledEvents.hs +566/−0
- src/Discord/Internal/Types/User.hs +3/−0
README.md view
@@ -5,6 +5,17 @@ [calamity haskell library](https://github.com/nitros12/calamity) for a more advanced interface. ++#### Documentation++#### [[installing](./docs/installing.md)] [[debugging](./docs/debugging.md)] [[creating-bot](./docs/creating-bot.md)]++#### [[design](./docs/design.md)] [[contributing](./docs/contributing.md)] [[todo](./docs/todo.md)]++#### [[app-commands](./docs/applicationcommands.md)] [[components](./docs/components.md)] [[cache](./docs/cache.md)] [[embeds](./docs/embeds.md)] [[emoji](./docs/emoji.md)] [[intents](./docs/intents.md)] [[voice](./docs/voice.md)]++#### Example+ This is an example bot that replies "pong" to messages that start with "ping". Checkout the [other examples](./examples/) for things like state management. ```haskell@@ -33,7 +44,7 @@ eventHandler :: Event -> DiscordHandler () eventHandler event = case event of- MessageCreate m -> when (isPing m && (not (fromBot 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!")@@ -45,32 +56,6 @@ isPing :: Message -> Bool isPing = ("ping" `isPrefixOf`) . toLower . messageContent ```--### Documentation--### [installing](./docs/installing.md)--### [debugging](./docs/debugging.md)--### [design](./docs/design.md)--### [todo](./docs/todo.md)--### [contributing](./docs/contributing.md)--### [intents](./docs/intents.md)--### [applicationcommands](./docs/applicationcommands.md)--### [components](./docs/components.md)--### [cache](./docs/cache.md)--### [embeds](./docs/embeds.md)--### [emoji](./docs/emoji.md)--### [voice](./docs/voice.md) #### Discord Server
changelog.md view
@@ -6,6 +6,14 @@ ## master +## 1.12.5++[Annwan](https://github.com/aquarial/discord-haskell/pull/109) Add `ScheduledEvent` rest API++[L0neGamer](https://github.com/aquarial/discord-haskell/pull/110) Add stickers API++[L0neGamer](https://github.com/aquarial/discord-haskell/pull/111) Add ModifyGuildMember 'timeout' option+ ## 1.12.4 Library won't crash if something fails to parse. Errors are printed to the log
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.4+version: 1.12.5 description: Functions and data types to write discord bots. Official discord docs <https://discord.com/developers/docs/reference>. .@@ -85,6 +85,8 @@ , Discord.Internal.Types.Interactions , Discord.Internal.Types.Components , Discord.Internal.Types.Color+ , Discord.Internal.Types.Emoji+ , Discord.Internal.Types.ScheduledEvents build-depends: base >= 4 && <5 , aeson@@ -103,7 +105,6 @@ , text , time , unordered-containers- , vector , websockets , wuss , mtl
src/Discord/Internal/Rest/Emoji.hs view
@@ -1,34 +1,35 @@-{-# LANGUAGE GADTs #-} {-# LANGUAGE DataKinds #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE InstanceSigs #-}-{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-} -- | Provides actions for Channel API interactions module Discord.Internal.Rest.Emoji- ( EmojiRequest(..)- , ModifyGuildEmojiOpts(..)- , parseEmojiImage- ) where+ ( EmojiRequest (..),+ ModifyGuildEmojiOpts (..),+ parseEmojiImage,+ StickerRequest (..),+ CreateGuildStickerOpts (..),+ EditGuildStickerOpts (..)+ )+where -import Data.Aeson import Codec.Picture-import Network.HTTP.Req ((/:))-import qualified Network.HTTP.Req as R-import qualified Data.Text as T-import qualified Data.Text.Encoding as TE+import Data.Aeson import qualified Data.ByteString as B import qualified Data.ByteString.Base64 as B64-+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE import Discord.Internal.Rest.Prelude import Discord.Internal.Types+import Network.HTTP.Req ((/:))+import qualified Network.HTTP.Req as R instance Request (EmojiRequest a) where majorRoute = emojiMajorRoute jsonRequest = emojiJsonRequest - -- | Data constructor for requests. See <https://discord.com/developers/docs/resources/ API> data EmojiRequest a where -- | List of emoji objects for the given guild. Requires MANAGE_EMOJIS permission.@@ -43,47 +44,63 @@ DeleteGuildEmoji :: GuildId -> EmojiId -> EmojiRequest () data ModifyGuildEmojiOpts = ModifyGuildEmojiOpts- { modifyGuildEmojiName :: T.Text- , modifyGuildEmojiRoles :: [RoleId]- } deriving (Show, Read, Eq, Ord)+ { modifyGuildEmojiName :: T.Text,+ modifyGuildEmojiRoles :: [RoleId]+ }+ deriving (Show, Read, Eq, Ord) instance ToJSON ModifyGuildEmojiOpts where toJSON (ModifyGuildEmojiOpts name roles) =- object [ "name" .= name, "roles" .= roles ]-+ object ["name" .= name, "roles" .= roles] -data EmojiImageParsed = EmojiImageParsed T.Text+newtype EmojiImageParsed = EmojiImageParsed T.Text deriving (Show, Read, Eq, Ord) parseEmojiImage :: B.ByteString -> Either T.Text EmojiImageParsed parseEmojiImage bs = if B.length bs > 256000- then Left "Cannot create emoji - File is larger than 256kb"- else case (decodeGifImages bs, decodeImage bs) of- (Left e1, Left e2) -> Left ("Could not parse image or gif: " <> T.pack e1- <> " and " <> T.pack e2)- (Right ims, _) -> if all is128 ims- then Right (EmojiImageParsed ("data:text/plain;"- <> "base64,"- <> TE.decodeUtf8 (B64.encode bs)))- else Left "The frames are not all 128x128"- (_, Right im) -> if is128 im- then Right (EmojiImageParsed ("data:text/plain;"- <> "base64,"- <> TE.decodeUtf8 (B64.encode bs)))- else Left "Image is not 128x128"+ then Left "Cannot create emoji - File is larger than 256kb"+ else case (decodeGifImages bs, decodeImage bs) of+ (Left e1, Left e2) ->+ Left+ ( "Could not parse image or gif: " <> T.pack e1+ <> " and "+ <> T.pack e2+ )+ (Right ims, _) ->+ if all is128 ims+ then+ Right+ ( EmojiImageParsed+ ( "data:text/plain;"+ <> "base64,"+ <> TE.decodeUtf8 (B64.encode bs)+ )+ )+ else Left "The frames are not all 128x128"+ (_, Right im) ->+ if is128 im+ then+ Right+ ( EmojiImageParsed+ ( "data:text/plain;"+ <> "base64,"+ <> TE.decodeUtf8 (B64.encode bs)+ )+ )+ else Left "Image is not 128x128" where- is128 im = let i = convertRGB8 im- in imageWidth i == 128 && imageHeight i == 128-+ is128 im =+ let i = convertRGB8 im+ in imageWidth i == 128 && imageHeight i == 128 emojiMajorRoute :: EmojiRequest a -> String emojiMajorRoute c = case c of- (ListGuildEmojis g) -> "emoji " <> show g- (GetGuildEmoji g _) -> "emoji " <> show g+ (ListGuildEmojis g) -> "emoji " <> show g+ (GetGuildEmoji g _) -> "emoji " <> show g (CreateGuildEmoji g _ _) -> "emoji " <> show g (ModifyGuildEmoji g _ _) -> "emoji " <> show g- (DeleteGuildEmoji g _) -> "emoji " <> show g+ (DeleteGuildEmoji g _) -> "emoji " <> show g guilds :: R.Url 'R.Https guilds = baseUrl /: "guilds"@@ -93,13 +110,114 @@ (ListGuildEmojis g) -> Get (guilds // g /: "emojis") mempty (GetGuildEmoji g e) -> Get (guilds // g /: "emojis" // e) mempty (CreateGuildEmoji g name (EmojiImageParsed im)) ->- Post (guilds // g /: "emojis")- (pure (R.ReqBodyJson (object [ "name" .= name- , "image" .= im- -- todo , "roles" .= ...- ])))- mempty- (ModifyGuildEmoji g e o) -> Patch (guilds // g /: "emojis" // e)- (pure (R.ReqBodyJson o))- mempty+ Post+ (guilds // g /: "emojis")+ ( pure+ ( R.ReqBodyJson+ ( object+ [ "name" .= name,+ "image" .= im+ -- todo , "roles" .= ...+ ]+ )+ )+ )+ mempty+ (ModifyGuildEmoji g e o) ->+ Patch+ (guilds // g /: "emojis" // e)+ (pure (R.ReqBodyJson o))+ mempty (DeleteGuildEmoji g e) -> Delete (guilds // g /: "emojis" // e) mempty++data StickerData = StickerDataPNG {stickerData :: B.ByteString} | StickerDataAPNG {stickerData :: B.ByteString} | StickerDataLOTTIE {stickerData :: B.ByteString}+ deriving (Show, Read, Eq, Ord)++instance ToJSON StickerData where+ toJSON sd = String $ "data:image/" <> sdt <> ";base64," <> TE.decodeUtf8 (B64.encode (stickerData sd))+ where+ sdt = case sd of+ StickerDataPNG _ -> "png"+ StickerDataAPNG _ -> "apng"+ StickerDataLOTTIE _ -> "lottie"++data CreateGuildStickerOpts = CreateGuildStickerOpts+ { guildStickerName :: T.Text,+ guildStickerDescription :: T.Text,+ guildStickerTags :: [T.Text],+ guildStickerFile :: StickerData+ }+ deriving (Show, Read, Eq, Ord)++instance ToJSON CreateGuildStickerOpts where+ toJSON CreateGuildStickerOpts {..} =+ object+ [ ("name", toJSON guildStickerName),+ ("description", toJSON guildStickerDescription),+ ("tags", toJSON . T.intercalate "," $ guildStickerTags),+ ("file", toJSON guildStickerFile)+ ]++data EditGuildStickerOpts = EditGuildStickerOpts+ { editGuildStickerName :: Maybe T.Text,+ editGuildStickerDescription :: Maybe T.Text,+ editGuildStickerTags :: Maybe [T.Text]+ }+ deriving (Show, Read, Eq, Ord)++instance ToJSON EditGuildStickerOpts where+ toJSON EditGuildStickerOpts {..} =+ object+ [ (name, value)+ | (name, Just value) <-+ [ ("name", toJSON <$> editGuildStickerName),+ ("description", toJSON <$> editGuildStickerDescription),+ ("tags", toJSON . T.intercalate "," <$> editGuildStickerTags)+ ]+ ]++instance Request (StickerRequest a) where+ majorRoute = stickerMajorRoute+ jsonRequest = stickerJsonRequest++-- | Data constructor for requests. See <https://discord.com/developers/docs/resources/ API>+--+-- Be warned that these are untested due to not having a spare server with +-- boosts. Functionality is at your own risk.+data StickerRequest a where+ -- | Returns a sticker object for the given sticker ID.+ GetSticker :: StickerId -> StickerRequest Sticker+ -- | Returns the list of sticker packs available to Nitro subscribers.+ ListNitroStickerPacks :: StickerRequest [StickerPack]+ -- | Returns an array of sticker objects for the given guild.+ ListGuildStickers :: GuildId -> StickerRequest [Sticker]+ -- | Returns a sticker object for the given guild and sticker ID.+ GetGuildSticker :: GuildId -> StickerId -> StickerRequest Sticker+ -- | Create a new sticker for the guild.+ CreateGuildSticker :: GuildId -> CreateGuildStickerOpts -> StickerRequest Sticker+ -- | Modify a sticker for a guild.+ ModifyGuildSticker :: GuildId -> StickerId -> EditGuildStickerOpts -> StickerRequest Sticker+ -- | Delete a guild sticker+ DeleteGuildSticker :: GuildId -> StickerId -> StickerRequest ()++stickerMajorRoute :: StickerRequest a -> String+stickerMajorRoute = \case+ GetSticker gid -> "sticker " <> show gid+ ListNitroStickerPacks -> "sticker"+ ListGuildStickers gid -> "sticker " <> show gid+ GetGuildSticker gid _ -> "sticker " <> show gid+ CreateGuildSticker gid _ -> "sticker " <> show gid+ ModifyGuildSticker gid _ _ -> "sticker " <> show gid+ DeleteGuildSticker gid _ -> "sticker " <> show gid++stickerJsonRequest :: StickerRequest a -> JsonRequest+stickerJsonRequest = \case+ GetSticker gid -> Get (baseUrl /: "stickers" // gid) mempty+ ListNitroStickerPacks -> Get (baseUrl /: "sticker-packs") mempty+ ListGuildStickers gid -> Get (stickersGuild gid) mempty+ GetGuildSticker gid sid -> Get (stickersGuild gid // sid) mempty+ CreateGuildSticker gid cgso -> Post (stickersGuild gid) (pure $ R.ReqBodyJson $ toJSON cgso) mempty+ ModifyGuildSticker gid sid egso -> Patch (stickersGuild gid // sid) (pure $ R.ReqBodyJson egso) mempty+ DeleteGuildSticker gid sid -> Delete (stickersGuild gid // sid) mempty+ where+ stickersGuild gid = baseUrl /: "guilds" // gid /: "stickers"
src/Discord/Internal/Rest/Guild.hs view
@@ -26,6 +26,7 @@ import Discord.Internal.Rest.Prelude import Discord.Internal.Types+import Data.Default (Default(..)) instance Request (GuildRequest a) where majorRoute = guildMajorRoute@@ -64,7 +65,7 @@ AddGuildMember :: GuildId -> UserId -> AddGuildMemberOpts -> GuildRequest () -- | Modify attributes of a guild 'Member'. Fires a Guild Member Update 'Event'.- ModifyGuildMember :: GuildId -> UserId -> ModifyGuildMemberOpts -> GuildRequest ()+ ModifyGuildMember :: GuildId -> UserId -> ModifyGuildMemberOpts -> GuildRequest GuildMember -- | Modify the nickname of the current user ModifyCurrentUserNick :: GuildId -> T.Text -> GuildRequest () -- | Add a member to a guild role. Requires 'MANAGE_ROLES' permission.@@ -209,15 +210,21 @@ , modifyGuildMemberOptsIsMuted :: Maybe Bool , modifyGuildMemberOptsIsDeafened :: Maybe Bool , modifyGuildMemberOptsMoveToChannel :: Maybe ChannelId+ , modifyGuildMemberOptsTimeoutUntil :: Maybe (Maybe UTCTime) -- ^ If `Just Nothing`, the timeout will be removed. } deriving (Show, Read, Eq, Ord) +instance Default ModifyGuildMemberOpts where+ def = ModifyGuildMemberOpts Nothing Nothing Nothing Nothing Nothing Nothing + instance ToJSON ModifyGuildMemberOpts where toJSON ModifyGuildMemberOpts{..} = object [(name, val) | (name, Just val) <- [("nick", toJSON <$> modifyGuildMemberOptsNickname ), ("roles", toJSON <$> modifyGuildMemberOptsRoles ), ("mute", toJSON <$> modifyGuildMemberOptsIsMuted ), ("deaf", toJSON <$> modifyGuildMemberOptsIsDeafened ),- ("channel_id", toJSON <$> modifyGuildMemberOptsMoveToChannel)]]+ ("channel_id", toJSON <$> modifyGuildMemberOptsMoveToChannel),+ ("communication_disabled_until", toJSON <$> modifyGuildMemberOptsTimeoutUntil)]]+ data CreateGuildChannelOpts = CreateGuildChannelOptsText { createGuildChannelOptsTopic :: Maybe T.Text
src/Discord/Internal/Rest/Prelude.hs view
@@ -34,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.4)"+ agent = "DiscordBot (https://github.com/aquarial/discord-haskell, 1.12.5)" -- Append to an URL infixl 5 //
src/Discord/Internal/Types.hs view
@@ -9,6 +9,7 @@ module Discord.Internal.Types.User, module Discord.Internal.Types.Embed, module Discord.Internal.Types.Components,+ module Discord.Internal.Types.Emoji, module Data.Aeson, module Data.Time.Clock, userFacingEvent,@@ -21,6 +22,7 @@ import Discord.Internal.Types.Color import Discord.Internal.Types.Components import Discord.Internal.Types.Embed+import Discord.Internal.Types.Emoji import Discord.Internal.Types.Events import Discord.Internal.Types.Gateway import Discord.Internal.Types.Guild
src/Discord/Internal/Types/Channel.hs view
@@ -13,13 +13,14 @@ import Data.Text (Text) import Data.Time.Clock import qualified Data.Text as T+import Data.Bits+import Data.Data (Data) import Discord.Internal.Types.Prelude import Discord.Internal.Types.User (User(..), GuildMember) import Discord.Internal.Types.Embed-import Data.Data (Data)-import Data.Bits-import Discord.Internal.Types.Components (ComponentActionRow, Emoji)+import Discord.Internal.Types.Components (ComponentActionRow)+import Discord.Internal.Types.Emoji -- | Guild channels represent an isolated set of users and messages in a Guild (Server) data Channel@@ -592,44 +593,6 @@ , ("me", toJSON <$> pure messageReactionMeIncluded) , ("emoji", toJSON <$> pure messageReactionEmoji) ]]---- TODO: expand stickers and have full objects-data StickerItem = StickerItem- { stickerItemId :: StickerId- , stickerItemName :: T.Text- , stickerItemFormatType :: StickerFormatType- } deriving (Show, Read, Eq, Ord)--instance FromJSON StickerItem where- parseJSON = withObject "StickerItem" $ \o ->- StickerItem <$> o .: "id"- <*> o .: "name"- <*> o .: "format_type"--instance ToJSON StickerItem where- toJSON StickerItem{..} = object [(name, value) | (name, Just value) <-- [ ("id", toJSON <$> pure stickerItemId)- , ("name", toJSON <$> pure stickerItemName)- , ("format_type", toJSON <$> pure stickerItemFormatType)- ]]--data StickerFormatType =- StickerFormatTypePNG- | StickerFormatTypeAPNG- | StickerFormatTypeLOTTIE- deriving (Show, Read, Eq, Ord, Data)--instance InternalDiscordEnum StickerFormatType where- discordTypeStartValue = StickerFormatTypePNG- fromDiscordType StickerFormatTypePNG = 1- fromDiscordType StickerFormatTypeAPNG = 2- fromDiscordType StickerFormatTypeLOTTIE = 3--instance ToJSON StickerFormatType where- toJSON = toJSON . fromDiscordType--instance FromJSON StickerFormatType where- parseJSON = discordTypeParseJSON "StickerFormatType" -- | Represents an attached to a message file. data Attachment = Attachment
src/Discord/Internal/Types/Components.hs view
@@ -17,8 +17,6 @@ mkSelectOption, ComponentTextInput (..), mkComponentTextInput,- Emoji (..),- mkEmoji, ) where @@ -27,8 +25,8 @@ import Data.Foldable (Foldable (toList)) import Data.Scientific (Scientific) import qualified Data.Text as T-import Discord.Internal.Types.Prelude (EmojiId, RoleId, toMaybeJSON)-import Discord.Internal.Types.User (User)+import Discord.Internal.Types.Emoji (Emoji)+import Discord.Internal.Types.Prelude (toMaybeJSON) data ComponentActionRow = ComponentActionRowButton [ComponentButton] | ComponentActionRowSelectMenu ComponentSelectMenu deriving (Show, Read, Eq, Ord)@@ -333,47 +331,3 @@ mkComponentTextInput :: T.Text -> T.Text -> ComponentTextInput mkComponentTextInput cid label = ComponentTextInput cid False label Nothing Nothing True "" ""---- | Represents an emoticon (emoji)-data Emoji = Emoji- { -- | The emoji id- emojiId :: Maybe EmojiId,- -- | The emoji name- emojiName :: T.Text,- -- | Roles the emoji is active for- emojiRoles :: Maybe [RoleId],- -- | User that created this emoji- emojiUser :: Maybe User,- -- | Whether this emoji is managed- emojiManaged :: Maybe Bool,- -- | Whether this emoji is animated- emojiAnimated :: Maybe Bool- }- deriving (Show, Read, Eq, Ord)---- | Make an emoji with only a name-mkEmoji :: T.Text -> Emoji-mkEmoji t = Emoji Nothing t Nothing Nothing Nothing Nothing--instance FromJSON Emoji where- parseJSON = withObject "Emoji" $ \o ->- Emoji <$> o .:? "id"- <*> o .: "name"- <*> o .:? "roles"- <*> o .:? "user"- <*> o .:? "managed"- <*> o .:? "animated"--instance ToJSON Emoji where- toJSON Emoji {..} =- object- [ (name, value)- | (name, Just value) <-- [ ("id", toJSON <$> emojiId),- ("name", toMaybeJSON emojiName),- ("roles", toJSON <$> emojiRoles),- ("user", toJSON <$> emojiUser),- ("managed", toJSON <$> emojiManaged),- ("animated", toJSON <$> emojiAnimated)- ]- ]
+ src/Discord/Internal/Types/Emoji.hs view
@@ -0,0 +1,169 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module Discord.Internal.Types.Emoji where++import Data.Aeson+import Data.Data+import Data.Functor ((<&>))+import Data.Text as T+import Discord.Internal.Types.Prelude+import Discord.Internal.Types.User++-- | Represents an emoticon (emoji)+data Emoji = Emoji+ { -- | The emoji id+ emojiId :: Maybe EmojiId,+ -- | The emoji name+ emojiName :: T.Text,+ -- | Roles the emoji is active for+ emojiRoles :: Maybe [RoleId],+ -- | User that created this emoji+ emojiUser :: Maybe User,+ -- | Whether this emoji is managed+ emojiManaged :: Maybe Bool,+ -- | Whether this emoji is animated+ emojiAnimated :: Maybe Bool+ }+ deriving (Show, Read, Eq, Ord)++-- | Make an emoji with only a name+mkEmoji :: T.Text -> Emoji+mkEmoji t = Emoji Nothing t Nothing Nothing Nothing Nothing++instance FromJSON Emoji where+ parseJSON = withObject "Emoji" $ \o ->+ Emoji <$> o .:? "id"+ <*> o .: "name"+ <*> o .:? "roles"+ <*> o .:? "user"+ <*> o .:? "managed"+ <*> o .:? "animated"++instance ToJSON Emoji where+ toJSON Emoji {..} =+ object+ [ (name, value)+ | (name, Just value) <-+ [ ("id", toJSON <$> emojiId),+ ("name", toMaybeJSON emojiName),+ ("roles", toJSON <$> emojiRoles),+ ("user", toJSON <$> emojiUser),+ ("managed", toJSON <$> emojiManaged),+ ("animated", toJSON <$> emojiAnimated)+ ]+ ]++-- | Represents a pack of standard stickers.+data StickerPack = StickerPack+ { -- | The id of the sticker pack+ stickerPackId :: Snowflake,+ -- | The stickers in the pack+ stickerPackStickers :: [Sticker],+ -- | The name of the sticker pack+ stickerPackName :: T.Text,+ -- | ID of the pack's SKU+ stickerPackSKUId :: Snowflake,+ -- | If of the sticker which is shown as the pack's icon+ stickerPackCoverStickerId :: Maybe StickerId,+ -- | The description of the sticker pack+ stickerPackDescription :: T.Text,+ -- | Id of the sticker pack's banner image+ stickerPackBannerAssetId :: Maybe Snowflake+ }+ deriving (Show, Read, Eq, Ord)++instance FromJSON StickerPack where+ parseJSON = withObject "StickerPack" $ \o ->+ StickerPack <$> o .: "id"+ <*> o .: "stickers"+ <*> o .: "name"+ <*> o .: "sku_id"+ <*> o .:? "cover_sticker_id"+ <*> o .: "description"+ <*> o .:? "banner_asset_id"++-- | A full sticker object+data Sticker = Sticker+ { -- | The sticker's id.+ stickerId :: StickerId,+ -- | For standard stickers, the id of the pack.+ stickerStickerPackId :: Maybe Snowflake,+ -- | The sticker's name.+ stickerName :: T.Text,+ -- | The sticker's description.+ stickerDescription :: Maybe T.Text,+ -- | Autocomplete/suggestion tags for the sticker (max 200 characters total).+ stickerTags :: [T.Text],+ -- | Whether the sticker is standard or guild type.+ stickerIsStandardType :: Bool,+ -- | The sticker's format type.+ stickerFormatType :: StickerFormatType,+ -- | Whether this guild sticker can be used.+ stickerAvailable :: Maybe Bool,+ -- | What guild owns this sticker.+ stickerGuildId :: Maybe GuildId,+ -- | What user uploaded the guild sticker.+ stickerUser :: Maybe User,+ -- | A standard sticker's sort order in its pack.+ stickerSortValue :: Maybe Integer+ }+ deriving (Show, Read, Eq, Ord)++instance FromJSON Sticker where+ parseJSON = withObject "Sticker" $ \o ->+ Sticker <$> o .: "id"+ <*> o .:? "pack_id"+ <*> o .: "name"+ <*> o .:? "description"+ <*> ((o .: "tags") <&> T.splitOn "\n")+ <*> ((o .: "type") <&> (== (1 :: Int)))+ <*> o .: "format_type"+ <*> o .:? "available"+ <*> o .:? "guild_id"+ <*> o .:? "user"+ <*> o .:? "sort_value"++-- | A simplified sticker object.+data StickerItem = StickerItem+ { -- | The sticker's id.+ stickerItemId :: StickerId,+ -- | The sticker's name.+ stickerItemName :: T.Text,+ -- | The sticker's format type.+ stickerItemFormatType :: StickerFormatType+ }+ deriving (Show, Read, Eq, Ord)++instance FromJSON StickerItem where+ parseJSON = withObject "StickerItem" $ \o ->+ StickerItem <$> o .: "id"+ <*> o .: "name"+ <*> o .: "format_type"++instance ToJSON StickerItem where+ toJSON StickerItem {..} =+ object+ [ ("id", toJSON stickerItemId),+ ("name", toJSON stickerItemName),+ ("format_type", toJSON stickerItemFormatType)+ ]++data StickerFormatType+ = StickerFormatTypePNG+ | StickerFormatTypeAPNG+ | StickerFormatTypeLOTTIE+ deriving (Show, Read, Eq, Ord, Data)++instance InternalDiscordEnum StickerFormatType where+ discordTypeStartValue = StickerFormatTypePNG+ fromDiscordType StickerFormatTypePNG = 1+ fromDiscordType StickerFormatTypeAPNG = 2+ fromDiscordType StickerFormatTypeLOTTIE = 3++instance ToJSON StickerFormatType where+ toJSON = toJSON . fromDiscordType++instance FromJSON StickerFormatType where+ parseJSON = discordTypeParseJSON "StickerFormatType"
src/Discord/Internal/Types/Events.hs view
@@ -18,7 +18,7 @@ import Discord.Internal.Types.Guild import Discord.Internal.Types.User (User, GuildMember) import Discord.Internal.Types.Interactions (Interaction)-import Discord.Internal.Types.Components (Emoji)+import Discord.Internal.Types.Emoji (Emoji) -- | Represents possible events sent by discord. Detailed information can be found at https://discord.com/developers/docs/topics/gateway.
src/Discord/Internal/Types/Guild.hs view
@@ -14,9 +14,9 @@ import Discord.Internal.Types.Prelude import Discord.Internal.Types.Color (DiscordColor)-import Discord.Internal.Types.Channel (Channel, StickerItem)+import Discord.Internal.Types.Channel (Channel) import Discord.Internal.Types.User (User, GuildMember)-import Discord.Internal.Types.Components (Emoji)+import Discord.Internal.Types.Emoji (Emoji, StickerItem)
src/Discord/Internal/Types/Prelude.hs view
@@ -70,6 +70,8 @@ type ApplicationId = Snowflake type ApplicationCommandId = Snowflake type InteractionId = Snowflake+type ScheduledEventId = Snowflake+type ScheduledEventEntityId = Snowflake type InteractionToken = T.Text type Shard = (Int, Int)
+ src/Discord/Internal/Types/ScheduledEvents.hs view
@@ -0,0 +1,566 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE DeriveDataTypeable #-}++-- | Structures pertaining to Discord Scheduled Events+module Discord.Internal.Types.ScheduledEvents where++import Data.Aeson ( (.:)+ , (.:!)+ , (.:?)+ , (.=)+ , FromJSON(parseJSON)+ , ToJSON(toJSON)+ , Value(Null, Number, String)+ , object+ , withObject+ , withText+ )+import Data.Aeson.Types ( Parser )+import qualified Data.ByteString as B+import Data.Data ( Data )+import Data.Default ( Default(def) )+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import Data.Time ( UTCTime )+import Discord.Internal.Types.Prelude ( ChannelId+ , GuildId+ , InternalDiscordEnum+ ( discordTypeParseJSON+ , discordTypeStartValue+ , fromDiscordType+ )+ , ScheduledEventEntityId+ , ScheduledEventId+ , UserId+ , toMaybeJSON+ )+import Discord.Internal.Types.User ( GuildMember+ , User+ )++++-- | The ScheduledEvent data structure+data ScheduledEvent+ = ScheduledEventStage+ { scheduledEventStageId :: ScheduledEventId+ , scheduledEventStageGuildId :: GuildId+ , scheduledEventStageChannelId :: ChannelId+ , scheduledEventStageCreatorId :: Maybe UserId+ , scheduledEventStageName :: T.Text+ , scheduledEventStageDescription :: Maybe T.Text+ , scheduledEventStageStartTime :: UTCTime+ , scheduledEventStageEndTime :: Maybe UTCTime+ , scheduledEventStagePrivacyLevel :: ScheduledEventPrivacyLevel+ , scheduledEventStageStatus :: ScheduledEventStatus+ , scheduledEventStageEntityId :: Maybe ScheduledEventEntityId+ , scheduledEventStageCreator :: Maybe User+ , scheduledEventStageUserCount :: Maybe Integer+ , scheduledEventStageImage :: Maybe ScheduledEventImageHash+ }+ | ScheduledEventVoice+ { scheduledEventVoiceId :: ScheduledEventId+ , scheduledEventVoiceGuildId :: GuildId+ , scheduledEventVoiceChannelId :: ChannelId+ , scheduledEventVoiceCreatorId :: Maybe UserId+ , scheduledEventVoiceName :: T.Text+ , scheduledEventVoiceDescription :: Maybe T.Text+ , scheduledEventVoiceStartTime :: UTCTime+ , scheduledEventVoiceEndTime :: Maybe UTCTime+ , scheduledEventVoicePrivacyLevel :: ScheduledEventPrivacyLevel+ , scheduledEventVoiceStatus :: ScheduledEventStatus+ , scheduledEventVoiceEntityId :: Maybe ScheduledEventEntityId+ , scheduledEventVoiceCreator :: Maybe User+ , scheduledEventVoiceUserCount :: Maybe Integer+ , scheduledEventVoiceImage :: Maybe ScheduledEventImageHash+ }+ | ScheduledEventExternal+ { scheduledEventExternalId :: ScheduledEventId+ , scheduledEventExternalGuildId :: GuildId+ , scheduledEventExternalLocation :: T.Text+ , scheduledEventExternalCreatorId :: Maybe UserId+ , scheduledEventExternalName :: T.Text+ , scheduledEventExternalDescription :: Maybe T.Text+ , scheduledEventExternalStartTime :: UTCTime+ , scheduledEventExternalEndTime :: UTCTime+ , scheduledEventExternalPrivacyLevel :: ScheduledEventPrivacyLevel+ , scheduledEventExternalStatus :: ScheduledEventStatus+ , scheduledEventExternalEntityId :: Maybe ScheduledEventEntityId+ , scheduledEventExternalCreator :: Maybe User+ , scheduledEventExternalUserCount :: Maybe Integer+ , scheduledEventExternalImage :: Maybe ScheduledEventImageHash+ }++instance ToJSON ScheduledEvent where+ toJSON ScheduledEventStage {..} = object+ [ (name, value)+ | (name, Just value) <-+ [ ("id" , toMaybeJSON scheduledEventStageId)+ , ("guild_id" , toMaybeJSON scheduledEventStageGuildId)+ , ("channel_id" , toMaybeJSON scheduledEventStageChannelId)+ , ("creator_id" , toJSON <$> scheduledEventStageCreatorId)+ , ("name" , toMaybeJSON scheduledEventStageName)+ , ("description" , toJSON <$> scheduledEventStageDescription)+ , ("scheduled_start_time", toMaybeJSON scheduledEventStageStartTime)+ , ("scheduled_end_time" , toJSON <$> scheduledEventStageEndTime)+ , ("privacy_level" , toMaybeJSON scheduledEventStagePrivacyLevel)+ , ("entity_type" , Just $ Number 1)+ , ("entity_id" , toJSON <$> scheduledEventStageEntityId)+ , ("creator" , toJSON <$> scheduledEventStageCreator)+ , ("user_count" , toJSON <$> scheduledEventStageUserCount)+ , ("image" , toJSON <$> scheduledEventStageImage)+ ]+ ]+ toJSON ScheduledEventVoice {..} = object+ [ (name, value)+ | (name, Just value) <-+ [ ("id" , toMaybeJSON scheduledEventVoiceId)+ , ("guild_id" , toMaybeJSON scheduledEventVoiceGuildId)+ , ("channel_id" , toMaybeJSON scheduledEventVoiceChannelId)+ , ("creator_id" , toJSON <$> scheduledEventVoiceCreatorId)+ , ("name" , toMaybeJSON scheduledEventVoiceName)+ , ("description" , toJSON <$> scheduledEventVoiceDescription)+ , ("scheduled_start_time", toMaybeJSON scheduledEventVoiceStartTime)+ , ("scheduled_end_time" , toJSON <$> scheduledEventVoiceEndTime)+ , ("privacy_level" , toMaybeJSON scheduledEventVoicePrivacyLevel)+ , ("entity_type" , Just $ Number 2)+ , ("entity_id" , toJSON <$> scheduledEventVoiceEntityId)+ , ("creator" , toJSON <$> scheduledEventVoiceCreator)+ , ("user_count" , toJSON <$> scheduledEventVoiceUserCount)+ , ("image" , toJSON <$> scheduledEventVoiceImage)+ ]+ ]+ toJSON ScheduledEventExternal {..} = object+ [ (name, value)+ | (name, Just value) <-+ [ ("id" , toMaybeJSON scheduledEventExternalId)+ , ("guild_id" , toMaybeJSON scheduledEventExternalGuildId)+ , ("creator_id" , toJSON <$> scheduledEventExternalCreatorId)+ , ("name" , toMaybeJSON scheduledEventExternalName)+ , ("description" , toJSON <$> scheduledEventExternalDescription)+ , ("scheduled_start_time", toMaybeJSON scheduledEventExternalStartTime)+ , ("scheduled_end_time" , toMaybeJSON scheduledEventExternalEndTime)+ , ("privacy_level", toMaybeJSON scheduledEventExternalPrivacyLevel)+ , ("entity_type" , Just $ Number 3)+ , ("entity_id" , toJSON <$> scheduledEventExternalEntityId)+ , ("creator" , toJSON <$> scheduledEventExternalCreator)+ , ("user_count" , toJSON <$> scheduledEventExternalUserCount)+ , ("image" , toJSON <$> scheduledEventExternalImage)+ , ( "entity_metadata"+ , Just $ object ["location" .= toJSON scheduledEventExternalLocation]+ )+ ]+ ]+++instance FromJSON ScheduledEvent where+ parseJSON = withObject+ "ScheduledEvent"+ (\v -> do+ setype <- v .: "entity_type" :: Parser Int+ seid <- v .: "id"+ segid <- v .: "guild_id"+ secrid <- v .:? "creator_id"+ sename <- v .: "name"+ sedesc <- v .:? "description"+ sest <- v .: "scheduled_start_time"+ sepl <- v .: "privacy_level" :: Parser ScheduledEventPrivacyLevel+ sestat <- v .: "status" :: Parser ScheduledEventStatus+ seeid <- v .:? "entity_id"+ secrea <- v .:? "creator"+ seuc <- v .:? "user_count"+ seim <- v .:? "image"++ case setype of+ 1 -> do+ sechid <- v .: "channelId"+ seet <- v .:? "scheduled_end_time"+ return $ ScheduledEventStage seid+ segid+ sechid+ secrid+ sename+ sedesc+ sest+ seet+ sepl+ sestat+ seeid+ secrea+ seuc+ seim+ 2 -> do+ sechid <- v .: "channelId"+ seet <- v .:? "scheduled_end_time"+ return $ ScheduledEventVoice seid+ segid+ sechid+ secrid+ sename+ sedesc+ sest+ seet+ sepl+ sestat+ seeid+ secrea+ seuc+ seim+ 3 -> do+ semeta <- v .: "entity_metadata"+ seloc <- withObject "entity_metadata" (.: "location") semeta+ seet <- v .: "scheduled_end_time"+ return $ ScheduledEventExternal seid+ segid+ seloc+ secrid+ sename+ sedesc+ sest+ seet+ sepl+ sestat+ seeid+ secrea+ seuc+ seim+ _ -> error "unreachable"+ )++-- | The privacy level of a scheduled event+data ScheduledEventPrivacyLevel = ScheduledEventPrivacyLevelGuildOnly+ deriving (Show, Read, Eq, Ord, Data)++instance InternalDiscordEnum ScheduledEventPrivacyLevel where+ discordTypeStartValue = ScheduledEventPrivacyLevelGuildOnly+ fromDiscordType ScheduledEventPrivacyLevelGuildOnly = 2++instance ToJSON ScheduledEventPrivacyLevel where+ toJSON = toJSON . fromDiscordType++instance FromJSON ScheduledEventPrivacyLevel where+ parseJSON = discordTypeParseJSON "ScheduledEventPrivacyLevel"++-- | The Status of a Scheduled Event+data ScheduledEventStatus+ = ScheduledEventStatusScheduled+ | ScheduledEventStatusActive+ | ScheduledEventStatusCompleted+ | ScheduledEventStatusCancelled+ deriving (Show, Read, Eq, Ord, Data)++instance InternalDiscordEnum ScheduledEventStatus where+ discordTypeStartValue = ScheduledEventStatusScheduled+ fromDiscordType ScheduledEventStatusScheduled = 1+ fromDiscordType ScheduledEventStatusActive = 2+ fromDiscordType ScheduledEventStatusCompleted = 3+ fromDiscordType ScheduledEventStatusCancelled = 4++instance ToJSON ScheduledEventStatus where+ toJSON = toJSON . fromDiscordType++instance FromJSON ScheduledEventStatus where+ parseJSON = discordTypeParseJSON "ScheduledEventStatus"++-- | The hash of the cover image of a ScheduledEvent+type ScheduledEventImageHash = T.Text++-- | The type of images that can be uploaded+data CreateScheduledEventImageUploadType+ = CreateScheduledEventImageUploadTypeJPG+ | CreateScheduledEventImageUploadTypePNG+ | CreateScheduledEventImageUploadTypeGIF+ deriving (Show, Read, Eq, Ord)++-- | The required information to add a cover image to a Scheduled Event+data CreateScheduledEventImage+ = CreateScheduledEventImageURL T.Text+ | CreateScheduledEventImageUpload CreateScheduledEventImageUploadType B.ByteString+ deriving (Show, Read, Eq, Ord)++instance ToJSON CreateScheduledEventImage where+ toJSON (CreateScheduledEventImageURL u) = String u+ toJSON (CreateScheduledEventImageUpload typ bs) =+ String+ $ "data:"+ <> (case typ of+ CreateScheduledEventImageUploadTypeJPG -> "image/jpeg"+ CreateScheduledEventImageUploadTypePNG -> "image/png"+ CreateScheduledEventImageUploadTypeGIF -> "image/gif"+ )+ <> ";base64,"+ <> T.decodeUtf8 bs++instance FromJSON CreateScheduledEventImage where+ parseJSON =+ withText "CreateScheduledEventImage" (return . CreateScheduledEventImageURL)++-- | Data required to create a Scheduled Event+data CreateScheduledEventData+ = CreateScheduledEventDataStage+ { createScheduleEventDataStageChannelId :: ChannelId+ , createScheduleEventDataStageName :: T.Text+ , createScheduleEventDataStagePrivacyLevel :: ScheduledEventPrivacyLevel+ , createScheduleEventDataStageStartTime :: UTCTime+ , createScheduleEventDataStageEndTime :: Maybe UTCTime+ , createScheduleEventDataStageDescription :: Maybe T.Text+ , createScheduleEventDataStageImage :: Maybe CreateScheduledEventImage+ }+ | CreateScheduledEventDataVoice+ { createScheduleEventDataVoiceChannelId :: ChannelId+ , createScheduleEventDataVoiceName :: T.Text+ , createScheduleEventDataVoicePrivacyLevel :: ScheduledEventPrivacyLevel+ , createScheduleEventDataVoiceStartTime :: UTCTime+ , createScheduleEventDataVoiceEndTime :: Maybe UTCTime+ , createScheduleEventDataVoiceDescription :: Maybe T.Text+ , createScheduleEventDataVoiceImage :: Maybe CreateScheduledEventImage+ }+ | CreateScheduledEventDataExternal+ { createScheduleEventDataExternalLocation :: T.Text+ , createScheduleEventDataExternalName :: T.Text+ , createScheduleEventDataExternalPrivacyLevel :: ScheduledEventPrivacyLevel+ , createScheduleEventDataExternalStartTime :: UTCTime+ , createScheduleEventDataExternalEndTime :: UTCTime+ , createScheduleEventDataExternalDescription :: Maybe T.Text+ , createScheduleEventDataExternalImage :: Maybe CreateScheduledEventImage+ }++instance ToJSON CreateScheduledEventData where+ toJSON CreateScheduledEventDataStage {..} = object+ [ (name, value)+ | (name, Just value) <-+ [ ("channel_id" , toMaybeJSON createScheduleEventDataStageChannelId)+ , ("name" , toMaybeJSON createScheduleEventDataStageName)+ , ("privacy_level", toMaybeJSON createScheduleEventDataStagePrivacyLevel)+ , ( "scheduled_start_time"+ , toMaybeJSON createScheduleEventDataStageStartTime+ )+ , ("scheduled_end_time", toJSON <$> createScheduleEventDataStageEndTime)+ , ("description", toJSON <$> createScheduleEventDataStageDescription)+ , ("entity_type" , Just $ Number 1)+ , ("image" , toJSON <$> createScheduleEventDataStageImage)+ ]+ ]+ toJSON CreateScheduledEventDataVoice {..} = object+ [ (name, value)+ | (name, Just value) <-+ [ ("channel_id" , toMaybeJSON createScheduleEventDataVoiceChannelId)+ , ("name" , toMaybeJSON createScheduleEventDataVoiceName)+ , ("privacy_level", toMaybeJSON createScheduleEventDataVoicePrivacyLevel)+ , ( "scheduled_start_time"+ , toMaybeJSON createScheduleEventDataVoiceStartTime+ )+ , ("scheduled_end_time", toJSON <$> createScheduleEventDataVoiceEndTime)+ , ("description", toJSON <$> createScheduleEventDataVoiceDescription)+ , ("entity_type" , Just $ Number 2)+ , ("image" , toJSON <$> createScheduleEventDataVoiceImage)+ ]+ ]+ toJSON CreateScheduledEventDataExternal {..} = object+ [ (name, value)+ | (name, Just value) <-+ [ ( "entity_metadata"+ , Just $ object ["location" .= createScheduleEventDataExternalLocation]+ )+ , ("name", toMaybeJSON createScheduleEventDataExternalName)+ , ( "privacy_level"+ , toMaybeJSON createScheduleEventDataExternalPrivacyLevel+ )+ , ( "scheduled_start_time"+ , toMaybeJSON createScheduleEventDataExternalStartTime+ )+ , ( "scheduled_end_time"+ , toMaybeJSON createScheduleEventDataExternalEndTime+ )+ , ("description", toJSON <$> createScheduleEventDataExternalDescription)+ , ("entity_type", Just $ Number 2)+ , ("image", toJSON <$> createScheduleEventDataExternalImage)+ ]+ ]++instance FromJSON CreateScheduledEventData where+ parseJSON = withObject+ "CreateScheduledEventData"+ (\v -> do+ t <- v .: "entity_type" :: Parser Int+ csename <- v .: "name"+ csepl <- v .: "privacy_level"+ csest <- v .: "scheduled_start_time"+ csedesc <- v .:? "description"+ cseimg <- v .:? "image"++ case t of+ 1 -> do+ csecid <- v .: "channel_id"+ cseet <- v .:? "scheduled_end_time"+ return $ CreateScheduledEventDataStage csecid+ csename+ csepl+ csest+ cseet+ csedesc+ cseimg+ 2 -> do+ csecid <- v .: "channel_id"+ cseet <- v .:? "scheduled_end_time"+ return $ CreateScheduledEventDataVoice csecid+ csename+ csepl+ csest+ cseet+ csedesc+ cseimg+ 3 -> do+ csemeta <- v .: "entity_metadata"+ cseloc <- withObject "entity_metadata" (.: "location") csemeta+ cseet <- v .: "scheduled_end_time"+ return $ CreateScheduledEventDataVoice cseloc+ csename+ csepl+ csest+ cseet+ csedesc+ cseimg+ _ -> error "unreachable"+ )+++-- | The type of ScheduledEvent, used in 'ModifyScheduledEventData'+data ScheduledEventType+ = ScheduledEventTypeStage+ | ScheduledEventTypeVoice+ | ScheduledEventTypeExternal+ deriving (Show, Read, Ord, Eq, Data)++instance InternalDiscordEnum ScheduledEventType where+ discordTypeStartValue = ScheduledEventTypeStage+ fromDiscordType ScheduledEventTypeStage = 1+ fromDiscordType ScheduledEventTypeVoice = 2+ fromDiscordType ScheduledEventTypeExternal = 3++instance FromJSON ScheduledEventType where+ parseJSON = discordTypeParseJSON "ScheduledEventType"++instance ToJSON ScheduledEventType where+ toJSON = toJSON . fromDiscordType++-- | Data required to issue a Modify Scheduled Event request+-- This isnt fully type-safe, and can allow for boggus requests but I don't+-- know of any sane solution to this+data ModifyScheduledEventData = ModifyScheduledEventData+ { modifyScheduledEventDataChannelId :: Maybe (Maybe ChannelId)+ , modifyScheduledEventDataLocation :: Maybe (Maybe T.Text)+ , modifyScheduledEventDataName :: Maybe T.Text+ , modifyScheduledEventDataPrivacyLevel :: Maybe ScheduledEventPrivacyLevel+ , modifyScheduledEventDataStartTime :: Maybe UTCTime+ , modifyScheduledEventDataEndTime :: Maybe UTCTime+ , modifyScheduledEventDataDescription :: Maybe (Maybe T.Text)+ , modifyScheduledEventDataType :: Maybe ScheduledEventType+ , modifyScheduledEventDataStatus :: Maybe ScheduledEventStatus+ , modifyScheduledEventDataImage :: Maybe CreateScheduledEventImage+ }++instance Default ModifyScheduledEventData where+ def = ModifyScheduledEventData Nothing+ Nothing+ Nothing+ Nothing+ Nothing+ Nothing+ Nothing+ Nothing+ Nothing+ Nothing++instance ToJSON ModifyScheduledEventData where+ toJSON ModifyScheduledEventData {..} = object+ [ (name, value)+ | (name, Just value) <-+ [ ("channel_id", toJSON <$> modifyScheduledEventDataChannelId)+ , ("entity_metadata" , loc)+ , ("name", toJSON <$> modifyScheduledEventDataName)+ , ("scheduled_start_time", toJSON <$> modifyScheduledEventDataStartTime)+ , ("scheduled_end_time", toJSON <$> modifyScheduledEventDataEndTime)+ , ("description", toJSON <$> modifyScheduledEventDataDescription)+ , ("entity_type", toJSON <$> modifyScheduledEventDataType)+ , ("status", toJSON <$> modifyScheduledEventDataStatus)+ , ("image", toJSON <$> modifyScheduledEventDataImage)+ ]+ ]+ where+ loc = case modifyScheduledEventDataLocation of+ Nothing -> Nothing+ Just Nothing -> Just Null+ Just loc' -> Just $ object [("location", toJSON loc')]++instance FromJSON ModifyScheduledEventData where+ parseJSON = withObject+ "ModifyScheduledEventData"+ (\v -> do+ -- The trivial fields+ msename <- v .:? "name"+ msest <- v .:? "scheduled_start_time"+ mseet <- v .:? "scheduled_end_time"+ msetype <- v .:? "entity_type"+ msepl <- v .:? "privacy_level"+ msestat <- v .:? "status"+ mseimg <- v .:? "image"++ -- The not so trivial ones+ msecid' <- v .:! "channel_id"+ mseloc' <- v .:! "entity_metadata"+ msedesc' <- v .:! "description"++ -- Extract the values+ msecid <- case msecid' of+ Nothing -> return Nothing+ Just Null -> return $ Just Nothing+ Just x -> do+ x' <- parseJSON x+ return $ Just x'++ mseloc <- case mseloc' of+ Nothing -> return Nothing+ Just Null -> return $ Just Nothing+ Just x -> do+ x' <- withObject "entity_metadata" (.: "location") x+ return $ Just x'++ msedesc <- case msedesc' of+ Nothing -> return Nothing+ Just Null -> return $ Just Nothing+ Just x -> do+ x' <- parseJSON x+ return $ Just x'++ return $ ModifyScheduledEventData+ { modifyScheduledEventDataChannelId = msecid+ , modifyScheduledEventDataLocation = mseloc+ , modifyScheduledEventDataName = msename+ , modifyScheduledEventDataPrivacyLevel = msepl+ , modifyScheduledEventDataStartTime = msest+ , modifyScheduledEventDataEndTime = mseet+ , modifyScheduledEventDataDescription = msedesc+ , modifyScheduledEventDataType = msetype+ , modifyScheduledEventDataStatus = msestat+ , modifyScheduledEventDataImage = mseimg+ }+ )++-- | An User that subscribed to a Scheduled Event+data ScheduledEventUser = ScheduledEventUser+ { scheduledEventUserEvent :: ScheduledEventId+ , scheduledEventUserUser :: User+ , scheduledEventUserGuildMember :: Maybe GuildMember+ }++instance FromJSON ScheduledEventUser where+ parseJSON = withObject+ "ScheduledEventUser"+ (\v ->+ ScheduledEventUser+ <$> v .: "guild_scheduled_event_id"+ <*> v .: "user"+ <*> v .:? "member"+ )
src/Discord/Internal/Types/User.hs view
@@ -121,6 +121,7 @@ , memberMute :: Bool -- ^ Whether the user is muted , memberPending :: Bool -- ^ Whether the user has passed the guild's membership screening , memberPermissions :: Maybe T.Text -- ^ total permissions of the member+ , memberTimeoutEnd :: Maybe UTCTime -- ^ when the user's timeout will expire and they can communicate again } deriving (Show, Read, Eq, Ord) instance FromJSON GuildMember where@@ -135,6 +136,7 @@ <*> o .: "mute" <*> o .:? "pending" .!= False <*> o .:? "permissions"+ <*> o .:? "communication_disabled_until" instance ToJSON GuildMember where toJSON GuildMember {..} = object [(name, value) | (name, Just value) <-@@ -148,4 +150,5 @@ , ("mute", toJSON <$> pure memberMute) , ("pending", toJSON <$> pure memberPending) , ("permissions", toJSON <$> memberPermissions)+ , ("communication_disabled_until", toJSON <$> memberTimeoutEnd) ] ]