diff --git a/cache/boltcache.go b/cache/boltcache.go index cc3d242..a307ab0 100644 --- a/cache/boltcache.go +++ b/cache/boltcache.go @@ -380,9 +380,13 @@ func (c *BoltCache) StoreChannels(channels []channel.Channel) { b := tx.Bucket([]byte("channels")) for _, ch := range channels { + var guildId uint64 + if ch.GuildId != nil { + guildId = *ch.GuildId + } cwg := channelWithGuild{ CachedChannel: ch.ToCachedChannel(), - guildId: ch.GuildId, + guildId: guildId, } if encoded, err := json.Marshal(cwg); err == nil { @@ -732,7 +736,11 @@ func (c *BoltCache) StoreVoiceStates(states []guild.VoiceState) { for _, state := range states { if encoded, err := json.Marshal(state.ToCachedVoiceState()); err == nil { - if err := b.Put(memberToBytes(state.UserId, state.GuildId), encoded); err != nil { + guildId := uint64(0) + if state.GuildId != nil { + guildId = *state.GuildId + } + if err := b.Put(memberToBytes(state.UserId, guildId), encoded); err != nil { return err } } else { @@ -766,7 +774,7 @@ func (c *BoltCache) GetVoiceState(userId, guildId uint64) (guild.VoiceState, boo u = user.User{Id: userId} } - m = member.Member{User: u} + m = member.Member{User: &u} } state := cached.ToVoiceState(guildId, m) @@ -805,7 +813,7 @@ func (c *BoltCache) GetGuildVoiceStates(guildId uint64) []guild.VoiceState { u = user.User{Id: stateUserId} } - m = member.Member{User: u} + m = member.Member{User: &u} } states = append(states, cached.ToVoiceState(guildId, m)) diff --git a/cache/memorycache.go b/cache/memorycache.go index 0bf1cf2..d2f7fa8 100644 --- a/cache/memorycache.go +++ b/cache/memorycache.go @@ -300,19 +300,21 @@ func (c *MemoryCache) StoreChannels(ctx context.Context, channels []channel.Chan // Add to guild object c.guildLock.Lock() - if guild, found := c.guilds[channel.GuildId]; found { - // Check to see if channel already exists - var channelExists bool - for _, userId := range guild.Channels { - if userId == channel.Id { - channelExists = true - break + if channel.GuildId != nil { + if guild, found := c.guilds[*channel.GuildId]; found { + // Check to see if channel already exists + var channelExists bool + for _, userId := range guild.Channels { + if userId == channel.Id { + channelExists = true + break + } } - } - if !channelExists { - guild.Channels = append(guild.Channels, channel.Id) - c.guilds[channel.GuildId] = guild + if !channelExists { + guild.Channels = append(guild.Channels, channel.Id) + c.guilds[*channel.GuildId] = guild + } } } c.guildLock.Unlock() @@ -677,11 +679,15 @@ func (c *MemoryCache) StoreVoiceStates(ctx context.Context, states []guild.Voice defer c.voiceStateLock.Unlock() for _, state := range states { - if c.voiceStates[state.GuildId] == nil { - c.voiceStates[state.GuildId] = make(map[uint64]guild.CachedVoiceState) + if state.GuildId == nil { + continue + } + guildId := *state.GuildId + if c.voiceStates[guildId] == nil { + c.voiceStates[guildId] = make(map[uint64]guild.CachedVoiceState) } - c.voiceStates[state.GuildId][state.UserId] = state.ToCachedVoiceState() + c.voiceStates[guildId][state.UserId] = state.ToCachedVoiceState() } } @@ -702,11 +708,8 @@ func (c *MemoryCache) GetVoiceState(ctx context.Context, userId, guildId uint64) // get member m, err := c.GetMember(ctx, guildId, userId) if err == ErrNotFound { - m = member.Member{ - User: user.User{ - Id: userId, - }, - } + u := user.User{Id: userId} + m = member.Member{User: &u} } else if err != nil { return guild.VoiceState{}, err } @@ -730,11 +733,8 @@ func (c *MemoryCache) GetGuildVoiceStates(ctx context.Context, guildId uint64) ( // get member m, err := c.GetMember(ctx, guildId, userId) if err == ErrNotFound { - m = member.Member{ - User: user.User{ - Id: userId, - }, - } + u := user.User{Id: userId} + m = member.Member{User: &u} } else if err != nil { return nil, err } diff --git a/cache/pgcache.go b/cache/pgcache.go index 4fa9c89..fe3537b 100644 --- a/cache/pgcache.go +++ b/cache/pgcache.go @@ -255,7 +255,11 @@ func (c *PgCache) StoreGuilds(ctx context.Context, guilds []guild.Guild) error { return err } - batch.Queue(`INSERT INTO channels("channel_id", "guild_id", "data") VALUES($1, $2, $3) ON CONFLICT("channel_id") DO UPDATE SET "data" = $3;`, channel.Id, channel.GuildId, string(encoded)) + var chGuildId uint64 + if channel.GuildId != nil { + chGuildId = *channel.GuildId + } + batch.Queue(`INSERT INTO channels("channel_id", "guild_id", "data") VALUES($1, $2, $3) ON CONFLICT("channel_id") DO UPDATE SET "data" = $3;`, channel.Id, chGuildId, string(encoded)) } } @@ -316,7 +320,8 @@ func (c *PgCache) StoreGuild(ctx context.Context, g guild.Guild) error { } for i, channel := range g.Channels { - channel.GuildId = g.Id + gId := g.Id + channel.GuildId = &gId g.Channels[i] = channel } @@ -362,10 +367,10 @@ func (c *PgCache) GetGuildChannels(ctx context.Context, guildId uint64) ([]chann } rows, err := c.Query(ctx, queryGetGuildChannels, guildId) - defer rows.Close() if err != nil { return nil, err } + defer rows.Close() var channels []channel.Channel for rows.Next() { @@ -615,7 +620,11 @@ func (c *PgCache) StoreChannel(ctx context.Context, ch channel.Channel) error { return err } - _, err = c.Exec(ctx, queryInsertChannel, ch.Id, ch.GuildId, string(encoded)) + var guildId uint64 + if ch.GuildId != nil { + guildId = *ch.GuildId + } + _, err = c.Exec(ctx, queryInsertChannel, ch.Id, guildId, string(encoded)) return err } @@ -632,7 +641,11 @@ func (c *PgCache) StoreChannels(ctx context.Context, channels []channel.Channel) return err } - batch.Queue(queryInsertChannel, ch.Id, ch.GuildId, string(encoded)) + var chGuildId uint64 + if ch.GuildId != nil { + chGuildId = *ch.GuildId + } + batch.Queue(queryInsertChannel, ch.Id, chGuildId, string(encoded)) } br := c.SendBatch(ctx, batch) @@ -664,7 +677,11 @@ func (c *PgCache) ReplaceChannels(ctx context.Context, guildId uint64, channels return err } - if _, err := tx.Exec(ctx, queryInsertChannel, ch.Id, ch.GuildId, string(encoded)); err != nil { + var txGuildId uint64 + if ch.GuildId != nil { + txGuildId = *ch.GuildId + } + if _, err := tx.Exec(ctx, queryInsertChannel, ch.Id, txGuildId, string(encoded)); err != nil { return err } } diff --git a/command/commandhandler.go b/command/commandhandler.go index 82acb53..f998855 100644 --- a/command/commandhandler.go +++ b/command/commandhandler.go @@ -59,12 +59,12 @@ func (h *CommandHandler) commandListener(s *gateway.Shard, e *events.MessageCrea } for _, cmd := range h.commands { - match := strings.ToLower(cmd.Name) == strings.ToLower(root) + match := strings.EqualFold(cmd.Name, root) // check aliases if !match { for _, alias := range cmd.Aliases { - if strings.ToLower(cmd.Name) == strings.ToLower(alias) { + if strings.EqualFold(cmd.Name, alias) { match = true break } @@ -76,12 +76,12 @@ func (h *CommandHandler) commandListener(s *gateway.Shard, e *events.MessageCrea argloop: for i, arg := range args { for _, sub := range cmd.SubCommands { - subMatch := strings.ToLower(arg) == strings.ToLower(sub.Name) + subMatch := strings.EqualFold(arg, sub.Name) // check aliases if !subMatch { for _, alias := range sub.Aliases { - if strings.ToLower(arg) == strings.ToLower(alias) { + if strings.EqualFold(arg, alias) { subMatch = true break } diff --git a/examples/avatar/avatar.go b/examples/avatar/avatar.go index c8b51bc..0e7ecf3 100644 --- a/examples/avatar/avatar.go +++ b/examples/avatar/avatar.go @@ -1,25 +1,19 @@ package main import ( + "context" "fmt" - "net/http" "github.com/TicketsBot-cloud/gdl/cache" "github.com/TicketsBot-cloud/gdl/command" "github.com/TicketsBot-cloud/gdl/gateway" - "github.com/TicketsBot-cloud/gdl/rest" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" "github.com/sirupsen/logrus" ) func main() { - cacheFactory := cache.BoltCacheFactory(cache.CacheOptions{ + cacheFactory := cache.MemoryCacheFactory(cache.CacheOptions{ Users: true, - }, cache.BoltOptions{ - ClearOnRestart: false, - Path: "bolt.db", - FileMode: 600, - Options: nil, }) shardOptions := gateway.ShardOptions{ @@ -55,27 +49,14 @@ func registerCommands(sm *gateway.ShardManager) { func onCommand(ctx command.CommandContext) { if len(ctx.Mentions) == 0 { - _, _ = ctx.Shard.CreateMessage(ctx.ChannelId, "You need to mention a user") + _, _ = ctx.Shard.CreateMessage(context.Background(), ctx.ChannelId, "You need to mention a user") return } for _, mention := range ctx.Mentions { - res, err := http.Get(mention.AvatarUrl(2048)) + _, err := ctx.Shard.CreateMessage(context.Background(), ctx.ChannelId, fmt.Sprintf("%s's avatar is: %s", mention.Username, mention.AvatarUrl(2048))) if err != nil { logrus.Warn(err.Error()) - continue } - defer res.Body.Close() - - data := rest.CreateMessageData{ - Content: fmt.Sprintf("%s's avatar is:", mention.Username), - File: &rest.File{ - Name: "avatar.png", - ContentType: res.Header.Get("Content-Type"), - Reader: res.Body, - }, - } - - ctx.Shard.CreateMessageComplex(ctx.ChannelId, data) } } diff --git a/examples/starboard/starboard.go b/examples/starboard/starboard.go index fbb6134..cfeafee 100644 --- a/examples/starboard/starboard.go +++ b/examples/starboard/starboard.go @@ -1,6 +1,8 @@ package main import ( + "context" + "github.com/TicketsBot-cloud/gdl/cache" "github.com/TicketsBot-cloud/gdl/gateway" "github.com/TicketsBot-cloud/gdl/gateway/payloads/events" @@ -16,14 +18,9 @@ const ( ) func main() { - cacheFactory := cache.BoltCacheFactory(cache.CacheOptions{ + cacheFactory := cache.MemoryCacheFactory(cache.CacheOptions{ Guilds: true, Users: true, - }, cache.BoltOptions{ - ClearOnRestart: false, - Path: "bolt.db", - FileMode: 600, - Options: nil, }) shardOptions := gateway.ShardOptions{ @@ -47,12 +44,12 @@ func main() { func reactListener(s *gateway.Shard, e *events.MessageReactionAdd) { // check the new reaction is a star - if e.Emoji.Name != "⭐" { + if *e.Emoji.Name != "⭐" { return } // get people who have reacted with a star so we can check if we've met the threshold - reactors, err := s.GetReactions(e.ChannelId, e.MessageId, "⭐", rest.GetReactionsData{}) + reactors, err := s.GetReactions(context.Background(), e.ChannelId, e.MessageId, "⭐", rest.GetReactionsData{}) if err != nil { logrus.Warn(err) return @@ -60,7 +57,7 @@ func reactListener(s *gateway.Shard, e *events.MessageReactionAdd) { if len(reactors) >= StarThreshold { // get the message object so we can get the content & sender - msg, err := s.GetChannelMessage(e.ChannelId, e.MessageId) + msg, err := s.GetChannelMessage(context.Background(), e.ChannelId, e.MessageId) if err != nil { logrus.Warn(err) return @@ -72,7 +69,7 @@ func reactListener(s *gateway.Shard, e *events.MessageReactionAdd) { SetAuthor(msg.Author.Username, "", msg.Author.AvatarUrl(256)). SetDescription(msg.Content) - if _, err := s.CreateMessageEmbed(StarboardChannelId, embed); err != nil { + if _, err := s.CreateMessageEmbed(context.Background(), StarboardChannelId, embed); err != nil { logrus.Warn(err) return } diff --git a/gateway/cachelisteners.go b/gateway/cachelisteners.go index 90eef89..b80acb5 100644 --- a/gateway/cachelisteners.go +++ b/gateway/cachelisteners.go @@ -78,7 +78,7 @@ func guildMemberRemoveListener(s *Shard, e *events.GuildMemberRemove) { func guildMemberUpdateListener(s *Shard, e *events.GuildMemberUpdate) { s.Cache.StoreMember(context.Background(), member.Member{ - User: e.User, + User: &e.User, Nick: e.Nick, Roles: e.Roles, PremiumSince: e.PremiumSince, diff --git a/gateway/payloads/events/eventbus.go b/gateway/eventbus.go similarity index 83% rename from gateway/payloads/events/eventbus.go rename to gateway/eventbus.go index 0d106c4..a5d7fc4 100644 --- a/gateway/payloads/events/eventbus.go +++ b/gateway/eventbus.go @@ -1,12 +1,11 @@ -package events +package gateway type EventBus struct { Listeners []interface{} } func NewEventBus() *EventBus { - return &EventBus{ - } + return &EventBus{} } func (e *EventBus) RegisterListener(fn interface{}) { diff --git a/gateway/payloads/events/applicationcommandpermissionsupdate.go b/gateway/payloads/events/applicationcommandpermissionsupdate.go new file mode 100644 index 0000000..c2b6e03 --- /dev/null +++ b/gateway/payloads/events/applicationcommandpermissionsupdate.go @@ -0,0 +1,7 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/interaction" + +type ApplicationCommandPermissionsUpdate struct { + interaction.GuildApplicationCommandPermissions +} diff --git a/gateway/payloads/events/automoderation.go b/gateway/payloads/events/automoderation.go new file mode 100644 index 0000000..dd7db07 --- /dev/null +++ b/gateway/payloads/events/automoderation.go @@ -0,0 +1,29 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/automoderation" + +type AutoModerationRuleCreate struct { + automoderation.Rule +} + +type AutoModerationRuleUpdate struct { + automoderation.Rule +} + +type AutoModerationRuleDelete struct { + automoderation.Rule +} + +type AutoModerationActionExecution struct { + GuildId uint64 `json:"guild_id,string"` + Action automoderation.Action `json:"action"` + RuleId uint64 `json:"rule_id,string"` + RuleTriggerType automoderation.TriggerType `json:"rule_trigger_type"` + UserId uint64 `json:"user_id,string"` + ChannelId *uint64 `json:"channel_id,string"` + MessageId *uint64 `json:"message_id,string"` + AlertSystemMessageId *uint64 `json:"alert_system_message_id,string"` + Content *string `json:"content"` + MatchedKeyword *string `json:"matched_keyword"` + MatchedContent *string `json:"matched_content"` +} diff --git a/gateway/payloads/events/channelinfo.go b/gateway/payloads/events/channelinfo.go new file mode 100644 index 0000000..da3701c --- /dev/null +++ b/gateway/payloads/events/channelinfo.go @@ -0,0 +1,8 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/channel" + +type ChannelInfo struct { + GuildId uint64 `json:"guild_id,string"` + Channels []channel.ChannelInfoEntry `json:"channels"` +} diff --git a/gateway/payloads/events/channelpinsupdate.go b/gateway/payloads/events/channelpinsupdate.go index b81be14..afc31e8 100644 --- a/gateway/payloads/events/channelpinsupdate.go +++ b/gateway/payloads/events/channelpinsupdate.go @@ -1,11 +1,9 @@ package events -import ( - "time" -) +import "time" type ChannelPinsUpdate struct { - GuildId uint64 `json:"guild_id,string"` - ChannelId uint64 `json:"channel_id,string"` - LastPinTimestamp time.Time `json:"last_pin_timestamp"` + GuildId *uint64 `json:"guild_id,string"` + ChannelId uint64 `json:"channel_id,string"` + LastPinTimestamp *time.Time `json:"last_pin_timestamp"` } diff --git a/gateway/payloads/events/eventtype.go b/gateway/payloads/events/eventtype.go index 9b580a8..534b979 100644 --- a/gateway/payloads/events/eventtype.go +++ b/gateway/payloads/events/eventtype.go @@ -3,33 +3,72 @@ package events type EventType string const ( - READY EventType = "READY" - RESUMED EventType = "RESUMED" - RECONNECT EventType = "RECONNECT" - INVALID_SESSION EventType = "INVALID_SESSION" - CHANNEL_CREATE EventType = "CHANNEL_CREATE" - CHANNEL_UPDATE EventType = "CHANNEL_UPDATE" - CHANNEL_DELETE EventType = "CHANNEL_DELETE" - CHANNEL_PINS_UPDATE EventType = "CHANNEL_PINS_UPDATE" - ENTITLEMENT_CREATE EventType = "ENTITLEMENT_CREATE" - ENTITLEMENT_UPDATE EventType = "ENTITLEMENT_UPDATE" - ENTITLEMENT_DELETE EventType = "ENTITLEMENT_DELETE" - GUILD_CREATE EventType = "GUILD_CREATE" - GUILD_UPDATE EventType = "GUILD_UPDATE" - GUILD_DELETE EventType = "GUILD_DELETE" - GUILD_BAN_ADD EventType = "GUILD_BAN_ADD" - GUILD_BAN_REMOVE EventType = "GUILD_BAN_REMOVE" - GUILD_EMOJIS_UPDATE EventType = "GUILD_EMOJIS_UPDATE" - GUILD_INTEGRATIONS_UPDATE EventType = "GUILD_INTEGRATIONS_UPDATE" - GUILD_MEMBER_ADD EventType = "GUILD_MEMBER_ADD" - GUILD_MEMBER_REMOVE EventType = "GUILD_MEMBER_REMOVE" - GUILD_MEMBER_UPDATE EventType = "GUILD_MEMBER_UPDATE" - GUILD_MEMBERS_CHUNK EventType = "GUILD_MEMBERS_CHUNK" - GUILD_ROLE_CREATE EventType = "GUILD_ROLE_CREATE" - GUILD_ROLE_UPDATE EventType = "GUILD_ROLE_UPDATE" - GUILD_ROLE_DELETE EventType = "GUILD_ROLE_DELETE" - INVITE_CREATE EventType = "INVITE_CREATE" - INVITE_DELETE EventType = "INVITE_DELETE" + READY EventType = "READY" + RESUMED EventType = "RESUMED" + RECONNECT EventType = "RECONNECT" + INVALID_SESSION EventType = "INVALID_SESSION" + + APPLICATION_COMMAND_PERMISSIONS_UPDATE EventType = "APPLICATION_COMMAND_PERMISSIONS_UPDATE" + + AUTO_MODERATION_RULE_CREATE EventType = "AUTO_MODERATION_RULE_CREATE" + AUTO_MODERATION_RULE_UPDATE EventType = "AUTO_MODERATION_RULE_UPDATE" + AUTO_MODERATION_RULE_DELETE EventType = "AUTO_MODERATION_RULE_DELETE" + AUTO_MODERATION_ACTION_EXECUTION EventType = "AUTO_MODERATION_ACTION_EXECUTION" + + CHANNEL_CREATE EventType = "CHANNEL_CREATE" + CHANNEL_UPDATE EventType = "CHANNEL_UPDATE" + CHANNEL_DELETE EventType = "CHANNEL_DELETE" + CHANNEL_INFO EventType = "CHANNEL_INFO" + CHANNEL_PINS_UPDATE EventType = "CHANNEL_PINS_UPDATE" + + THREAD_CREATE EventType = "THREAD_CREATE" + THREAD_UPDATE EventType = "THREAD_UPDATE" + THREAD_DELETE EventType = "THREAD_DELETE" + THREAD_LIST_SYNC EventType = "THREAD_LIST_SYNC" + THREAD_MEMBER_UPDATE EventType = "THREAD_MEMBER_UPDATE" + THREAD_MEMBERS_UPDATE EventType = "THREAD_MEMBERS_UPDATE" + + ENTITLEMENT_CREATE EventType = "ENTITLEMENT_CREATE" + ENTITLEMENT_UPDATE EventType = "ENTITLEMENT_UPDATE" + ENTITLEMENT_DELETE EventType = "ENTITLEMENT_DELETE" + + GUILD_CREATE EventType = "GUILD_CREATE" + GUILD_UPDATE EventType = "GUILD_UPDATE" + GUILD_DELETE EventType = "GUILD_DELETE" + GUILD_AUDIT_LOG_ENTRY_CREATE EventType = "GUILD_AUDIT_LOG_ENTRY_CREATE" + GUILD_BAN_ADD EventType = "GUILD_BAN_ADD" + GUILD_BAN_REMOVE EventType = "GUILD_BAN_REMOVE" + GUILD_EMOJIS_UPDATE EventType = "GUILD_EMOJIS_UPDATE" + GUILD_STICKERS_UPDATE EventType = "GUILD_STICKERS_UPDATE" + GUILD_INTEGRATIONS_UPDATE EventType = "GUILD_INTEGRATIONS_UPDATE" + GUILD_MEMBER_ADD EventType = "GUILD_MEMBER_ADD" + GUILD_MEMBER_REMOVE EventType = "GUILD_MEMBER_REMOVE" + GUILD_MEMBER_UPDATE EventType = "GUILD_MEMBER_UPDATE" + GUILD_MEMBERS_CHUNK EventType = "GUILD_MEMBERS_CHUNK" + GUILD_ROLE_CREATE EventType = "GUILD_ROLE_CREATE" + GUILD_ROLE_UPDATE EventType = "GUILD_ROLE_UPDATE" + GUILD_ROLE_DELETE EventType = "GUILD_ROLE_DELETE" + GUILD_SCHEDULED_EVENT_CREATE EventType = "GUILD_SCHEDULED_EVENT_CREATE" + GUILD_SCHEDULED_EVENT_UPDATE EventType = "GUILD_SCHEDULED_EVENT_UPDATE" + GUILD_SCHEDULED_EVENT_DELETE EventType = "GUILD_SCHEDULED_EVENT_DELETE" + GUILD_SCHEDULED_EVENT_USER_ADD EventType = "GUILD_SCHEDULED_EVENT_USER_ADD" + GUILD_SCHEDULED_EVENT_USER_REMOVE EventType = "GUILD_SCHEDULED_EVENT_USER_REMOVE" + GUILD_SOUNDBOARD_SOUND_CREATE EventType = "GUILD_SOUNDBOARD_SOUND_CREATE" + GUILD_SOUNDBOARD_SOUND_UPDATE EventType = "GUILD_SOUNDBOARD_SOUND_UPDATE" + GUILD_SOUNDBOARD_SOUND_DELETE EventType = "GUILD_SOUNDBOARD_SOUND_DELETE" + GUILD_SOUNDBOARD_SOUNDS_UPDATE EventType = "GUILD_SOUNDBOARD_SOUNDS_UPDATE" + + SOUNDBOARD_SOUNDS EventType = "SOUNDBOARD_SOUNDS" + + INTEGRATION_CREATE EventType = "INTEGRATION_CREATE" + INTEGRATION_UPDATE EventType = "INTEGRATION_UPDATE" + INTEGRATION_DELETE EventType = "INTEGRATION_DELETE" + + INTERACTION_CREATE EventType = "INTERACTION_CREATE" + + INVITE_CREATE EventType = "INVITE_CREATE" + INVITE_DELETE EventType = "INVITE_DELETE" + MESSAGE_CREATE EventType = "MESSAGE_CREATE" MESSAGE_UPDATE EventType = "MESSAGE_UPDATE" MESSAGE_DELETE EventType = "MESSAGE_DELETE" @@ -38,16 +77,28 @@ const ( MESSAGE_REACTION_REMOVE EventType = "MESSAGE_REACTION_REMOVE" MESSAGE_REACTION_REMOVE_ALL EventType = "MESSAGE_REACTION_REMOVE_ALL" MESSAGE_REACTION_REMOVE_EMOJI EventType = "MESSAGE_REACTION_REMOVE_EMOJI" - PRESENCE_UPDATE EventType = "PRESENCE_UPDATE" - THREAD_CREATE EventType = "THREAD_CREATE" - THREAD_UPDATE EventType = "THREAD_UPDATE" - THREAD_DELETE EventType = "THREAD_DELETE" - THREAD_LIST_SYNC EventType = "THREAD_LIST_SYNC" - THREAD_MEMBER_UPDATE EventType = "THREAD_MEMBER_UPDATE" - THREAD_MEMBERS_UPDATE EventType = "THREAD_MEMBERS_UPDATE" - TYPING_START EventType = "TYPING_START" - USER_UPDATE EventType = "USER_UPDATE" - VOICE_STATE_UPDATE EventType = "VOICE_STATE_UPDATE" - VOICE_SERVER_UPDATE EventType = "VOICE_SERVER_UPDATE" - WEBHOOKS_UPDATE EventType = "WEBHOOKS_UPDATE" + MESSAGE_POLL_VOTE_ADD EventType = "MESSAGE_POLL_VOTE_ADD" + MESSAGE_POLL_VOTE_REMOVE EventType = "MESSAGE_POLL_VOTE_REMOVE" + + PRESENCE_UPDATE EventType = "PRESENCE_UPDATE" + + STAGE_INSTANCE_CREATE EventType = "STAGE_INSTANCE_CREATE" + STAGE_INSTANCE_UPDATE EventType = "STAGE_INSTANCE_UPDATE" + STAGE_INSTANCE_DELETE EventType = "STAGE_INSTANCE_DELETE" + + SUBSCRIPTION_CREATE EventType = "SUBSCRIPTION_CREATE" + SUBSCRIPTION_UPDATE EventType = "SUBSCRIPTION_UPDATE" + SUBSCRIPTION_DELETE EventType = "SUBSCRIPTION_DELETE" + + TYPING_START EventType = "TYPING_START" + + USER_UPDATE EventType = "USER_UPDATE" + + VOICE_CHANNEL_EFFECT_SEND EventType = "VOICE_CHANNEL_EFFECT_SEND" + VOICE_CHANNEL_START_TIME_UPDATE EventType = "VOICE_CHANNEL_START_TIME_UPDATE" + VOICE_CHANNEL_STATUS_UPDATE EventType = "VOICE_CHANNEL_STATUS_UPDATE" + VOICE_STATE_UPDATE EventType = "VOICE_STATE_UPDATE" + VOICE_SERVER_UPDATE EventType = "VOICE_SERVER_UPDATE" + + WEBHOOKS_UPDATE EventType = "WEBHOOKS_UPDATE" ) diff --git a/gateway/payloads/events/eventtypes.go b/gateway/payloads/events/eventtypes.go deleted file mode 100644 index 62d8d62..0000000 --- a/gateway/payloads/events/eventtypes.go +++ /dev/null @@ -1,103 +0,0 @@ -package events - -import "reflect" - -type Event interface { - Ready | - Resumed | - Reconnect | - InvalidSession | - ChannelCreate | - ChannelUpdate | - ChannelDelete | - ChannelPinsUpdate | - EntitlementCreate | - EntitlementUpdate | - EntitlementDelete | - GuildCreate | - GuildUpdate | - GuildDelete | - GuildBanAdd | - GuildBanRemove | - GuildEmojisUpdate | - GuildIntegrationsUpdate | - GuildMemberAdd | - GuildMemberRemove | - GuildMemberUpdate | - GuildMembersChunk | - GuildRoleCreate | - GuildRoleUpdate | - GuildRoleDelete | - InviteCreate | - InviteDelete | - MessageCreate | - MessageUpdate | - MessageDelete | - MessageDeleteBulk | - MessageReactionAdd | - MessageReactionRemove | - MessageReactionRemoveAll | - MessageReactionRemoveEmoji | - PresenceUpdate | - ThreadCreate | - ThreadUpdate | - ThreadDelete | - ThreadListSync | - ThreadMembersUpdate | - ThreadMemberUpdate | - TypingStart | - UserUpdate | - VoiceServerUpdate | - VoiceStateUpdate | - WebhooksUpdate -} - -var EventTypes = map[EventType]reflect.Type{ - READY: reflect.TypeOf(Ready{}), - RESUMED: reflect.TypeOf(Resumed{}), - RECONNECT: reflect.TypeOf(Reconnect{}), - INVALID_SESSION: reflect.TypeOf(InvalidSession{}), - CHANNEL_CREATE: reflect.TypeOf(ChannelCreate{}), - CHANNEL_UPDATE: reflect.TypeOf(ChannelUpdate{}), - CHANNEL_DELETE: reflect.TypeOf(ChannelDelete{}), - CHANNEL_PINS_UPDATE: reflect.TypeOf(ChannelPinsUpdate{}), - ENTITLEMENT_CREATE: reflect.TypeOf(EntitlementCreate{}), - ENTITLEMENT_UPDATE: reflect.TypeOf(EntitlementUpdate{}), - ENTITLEMENT_DELETE: reflect.TypeOf(EntitlementDelete{}), - GUILD_CREATE: reflect.TypeOf(GuildCreate{}), - GUILD_UPDATE: reflect.TypeOf(GuildUpdate{}), - GUILD_DELETE: reflect.TypeOf(GuildDelete{}), - GUILD_BAN_ADD: reflect.TypeOf(GuildBanAdd{}), - GUILD_BAN_REMOVE: reflect.TypeOf(GuildBanRemove{}), - GUILD_EMOJIS_UPDATE: reflect.TypeOf(GuildEmojisUpdate{}), - GUILD_INTEGRATIONS_UPDATE: reflect.TypeOf(GuildIntegrationsUpdate{}), - GUILD_MEMBER_ADD: reflect.TypeOf(GuildMemberAdd{}), - GUILD_MEMBER_REMOVE: reflect.TypeOf(GuildMemberRemove{}), - GUILD_MEMBER_UPDATE: reflect.TypeOf(GuildMemberUpdate{}), - GUILD_MEMBERS_CHUNK: reflect.TypeOf(GuildMembersChunk{}), - GUILD_ROLE_CREATE: reflect.TypeOf(GuildRoleCreate{}), - GUILD_ROLE_UPDATE: reflect.TypeOf(GuildRoleUpdate{}), - GUILD_ROLE_DELETE: reflect.TypeOf(GuildRoleDelete{}), - INVITE_CREATE: reflect.TypeOf(InviteCreate{}), - INVITE_DELETE: reflect.TypeOf(InviteDelete{}), - MESSAGE_CREATE: reflect.TypeOf(MessageCreate{}), - MESSAGE_UPDATE: reflect.TypeOf(MessageUpdate{}), - MESSAGE_DELETE: reflect.TypeOf(MessageDelete{}), - MESSAGE_DELETE_BULK: reflect.TypeOf(MessageDeleteBulk{}), - MESSAGE_REACTION_ADD: reflect.TypeOf(MessageReactionAdd{}), - MESSAGE_REACTION_REMOVE: reflect.TypeOf(MessageReactionRemove{}), - MESSAGE_REACTION_REMOVE_ALL: reflect.TypeOf(MessageReactionRemoveAll{}), - MESSAGE_REACTION_REMOVE_EMOJI: reflect.TypeOf(MessageReactionRemoveEmoji{}), - PRESENCE_UPDATE: reflect.TypeOf(PresenceUpdate{}), - THREAD_CREATE: reflect.TypeOf(ThreadCreate{}), - THREAD_UPDATE: reflect.TypeOf(ThreadUpdate{}), - THREAD_DELETE: reflect.TypeOf(ThreadDelete{}), - THREAD_LIST_SYNC: reflect.TypeOf(ThreadListSync{}), - THREAD_MEMBER_UPDATE: reflect.TypeOf(ThreadMemberUpdate{}), - THREAD_MEMBERS_UPDATE: reflect.TypeOf(ThreadMembersUpdate{}), - TYPING_START: reflect.TypeOf(TypingStart{}), - USER_UPDATE: reflect.TypeOf(UserUpdate{}), - VOICE_STATE_UPDATE: reflect.TypeOf(VoiceStateUpdate{}), - VOICE_SERVER_UPDATE: reflect.TypeOf(VoiceStateUpdate{}), - WEBHOOKS_UPDATE: reflect.TypeOf(WebhooksUpdate{}), -} diff --git a/gateway/payloads/events/guildauditlogentrycreate.go b/gateway/payloads/events/guildauditlogentrycreate.go new file mode 100644 index 0000000..8bca275 --- /dev/null +++ b/gateway/payloads/events/guildauditlogentrycreate.go @@ -0,0 +1,8 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/auditlog" + +type GuildAuditLogEntryCreate struct { + auditlog.AuditLogEntry + GuildId uint64 `json:"guild_id,string"` +} diff --git a/gateway/payloads/events/guildmemberschunk.go b/gateway/payloads/events/guildmemberschunk.go index 68f1443..95d43c3 100644 --- a/gateway/payloads/events/guildmemberschunk.go +++ b/gateway/payloads/events/guildmemberschunk.go @@ -7,8 +7,11 @@ import ( ) type GuildMembersChunk struct { - GuildId uint64 `json:"guild_id,string"` - Members []member.Member `json:"member"` - NotFound utils.Uint64StringSlice `json:"not_found"` - Presences []user.Presence `json:"presences"` + GuildId uint64 `json:"guild_id,string"` + Members []member.Member `json:"members"` + ChunkIndex int `json:"chunk_index"` + ChunkCount int `json:"chunk_count"` + NotFound utils.Uint64StringSlice `json:"not_found"` + Presences []user.Presence `json:"presences"` + Nonce string `json:"nonce"` } diff --git a/gateway/payloads/events/guildmemberupdate.go b/gateway/payloads/events/guildmemberupdate.go index 4f95253..445da47 100644 --- a/gateway/payloads/events/guildmemberupdate.go +++ b/gateway/payloads/events/guildmemberupdate.go @@ -8,9 +8,17 @@ import ( ) type GuildMemberUpdate struct { - GuildId uint64 `json:"guild_id,string"` - Roles utils.Uint64StringSlice `json:"roles"` - User user.User `json:"user"` - Nick string `json:"nick"` - PremiumSince *time.Time `json:"premium_since"` // When the user started boosting the guild + GuildId uint64 `json:"guild_id,string"` + Roles utils.Uint64StringSlice `json:"roles"` + User user.User `json:"user"` + Nick *string `json:"nick"` + Avatar *string `json:"avatar"` + Banner *string `json:"banner"` + JoinedAt *time.Time `json:"joined_at"` + PremiumSince *time.Time `json:"premium_since"` + Deaf *bool `json:"deaf"` + Mute *bool `json:"mute"` + Pending *bool `json:"pending"` + CommunicationDisabledUntil *time.Time `json:"communication_disabled_until"` + Collectibles *user.UserCollectibles `json:"collectibles,omitempty"` } diff --git a/gateway/payloads/events/guildrolecreate.go b/gateway/payloads/events/guildrolecreate.go index c6fad49..0830c0c 100644 --- a/gateway/payloads/events/guildrolecreate.go +++ b/gateway/payloads/events/guildrolecreate.go @@ -6,5 +6,5 @@ import ( type GuildRoleCreate struct { GuildId uint64 `json:"guild_id,string"` - Role guild.Role ` json:"role"` + Role guild.Role `json:"role"` } diff --git a/gateway/payloads/events/guildroleupdate.go b/gateway/payloads/events/guildroleupdate.go index d077f52..b37a594 100644 --- a/gateway/payloads/events/guildroleupdate.go +++ b/gateway/payloads/events/guildroleupdate.go @@ -6,5 +6,5 @@ import ( type GuildRoleUpdate struct { GuildId uint64 `json:"guild_id,string"` - Role guild.Role ` json:"role"` + Role guild.Role `json:"role"` } diff --git a/gateway/payloads/events/guildscheduledevents.go b/gateway/payloads/events/guildscheduledevents.go new file mode 100644 index 0000000..e7ba6ec --- /dev/null +++ b/gateway/payloads/events/guildscheduledevents.go @@ -0,0 +1,27 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/guild/scheduledevent" + +type GuildScheduledEventCreate struct { + scheduledevent.GuildScheduledEvent +} + +type GuildScheduledEventUpdate struct { + scheduledevent.GuildScheduledEvent +} + +type GuildScheduledEventDelete struct { + scheduledevent.GuildScheduledEvent +} + +type GuildScheduledEventUserAdd struct { + GuildScheduledEventId uint64 `json:"guild_scheduled_event_id,string"` + UserId uint64 `json:"user_id,string"` + GuildId uint64 `json:"guild_id,string"` +} + +type GuildScheduledEventUserRemove struct { + GuildScheduledEventId uint64 `json:"guild_scheduled_event_id,string"` + UserId uint64 `json:"user_id,string"` + GuildId uint64 `json:"guild_id,string"` +} diff --git a/gateway/payloads/events/guildsoundboard.go b/gateway/payloads/events/guildsoundboard.go new file mode 100644 index 0000000..fbdfd12 --- /dev/null +++ b/gateway/payloads/events/guildsoundboard.go @@ -0,0 +1,26 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/guild/soundboard" + +type GuildSoundboardSoundCreate struct { + soundboard.SoundboardSound +} + +type GuildSoundboardSoundUpdate struct { + soundboard.SoundboardSound +} + +type GuildSoundboardSoundDelete struct { + SoundId uint64 `json:"sound_id,string"` + GuildId uint64 `json:"guild_id,string"` +} + +type GuildSoundboardSoundsUpdate struct { + GuildId uint64 `json:"guild_id,string"` + SoundboardSounds []soundboard.SoundboardSound `json:"soundboard_sounds"` +} + +type SoundboardSounds struct { + GuildId uint64 `json:"guild_id,string"` + SoundboardSounds []soundboard.SoundboardSound `json:"soundboard_sounds"` +} diff --git a/gateway/payloads/events/guildstickersupdate.go b/gateway/payloads/events/guildstickersupdate.go new file mode 100644 index 0000000..1e13238 --- /dev/null +++ b/gateway/payloads/events/guildstickersupdate.go @@ -0,0 +1,8 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/guild/sticker" + +type GuildStickersUpdate struct { + GuildId uint64 `json:"guild_id,string"` + Stickers []sticker.Sticker `json:"stickers"` +} diff --git a/gateway/payloads/events/integrations.go b/gateway/payloads/events/integrations.go new file mode 100644 index 0000000..9976214 --- /dev/null +++ b/gateway/payloads/events/integrations.go @@ -0,0 +1,19 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/integration" + +type IntegrationCreate struct { + integration.Integration + GuildId uint64 `json:"guild_id,string"` +} + +type IntegrationUpdate struct { + integration.Integration + GuildId uint64 `json:"guild_id,string"` +} + +type IntegrationDelete struct { + Id uint64 `json:"id,string"` + GuildId uint64 `json:"guild_id,string"` + ApplicationId *uint64 `json:"application_id,string"` +} diff --git a/gateway/payloads/events/invitecreate.go b/gateway/payloads/events/invitecreate.go index dc069d1..6757369 100644 --- a/gateway/payloads/events/invitecreate.go +++ b/gateway/payloads/events/invitecreate.go @@ -1,14 +1,22 @@ package events -import "time" +import ( + "time" + + "github.com/TicketsBot-cloud/gdl/objects/user" +) type InviteCreate struct { - ChannelId uint64 `json:"channel_id,string"` - Code string `json:"code"` - CreatedAt time.Time `json:"created_at"` - GuildId uint64 `json:"guild_id,string"` - MaxAge int `json:"max_age"` // How long the invite is valid for, in seconds - MaxUses int `json:"max_uses"` - Temporary bool `json:"temporary"` - Uses int `json:"uses"` // Will always be 0 + ChannelId uint64 `json:"channel_id,string"` + Code string `json:"code"` + CreatedAt time.Time `json:"created_at"` + GuildId *uint64 `json:"guild_id,string"` + Inviter *user.User `json:"inviter"` + MaxAge int `json:"max_age"` + MaxUses int `json:"max_uses"` + TargetType *int `json:"target_type"` + TargetUser *user.User `json:"target_user"` + Temporary bool `json:"temporary"` + Uses int `json:"uses"` + ExpiresAt *time.Time `json:"expires_at"` } diff --git a/gateway/payloads/events/invitedelete.go b/gateway/payloads/events/invitedelete.go index 9a504c8..cc4a268 100644 --- a/gateway/payloads/events/invitedelete.go +++ b/gateway/payloads/events/invitedelete.go @@ -1,7 +1,7 @@ package events type InviteDelete struct { - ChannelId uint64 `json:"channel_id,string"` - GuildId uint64 `json:"guild_id,string"` - Code string `json:"code"` + ChannelId uint64 `json:"channel_id,string"` + GuildId *uint64 `json:"guild_id,string"` + Code string `json:"code"` } diff --git a/gateway/payloads/events/messagedelete.go b/gateway/payloads/events/messagedelete.go index 75cb07d..e575b0b 100644 --- a/gateway/payloads/events/messagedelete.go +++ b/gateway/payloads/events/messagedelete.go @@ -1,7 +1,7 @@ package events type MessageDelete struct { - Id uint64 `json:"id,string"` - ChannelId uint64 `json:"channel_id,string"` - GuildId uint64 `json:"guild_id,string"` + Id uint64 `json:"id,string"` + ChannelId uint64 `json:"channel_id,string"` + GuildId *uint64 `json:"guild_id,string"` } diff --git a/gateway/payloads/events/messagedeletebulk.go b/gateway/payloads/events/messagedeletebulk.go index 2f30c65..e4fdee0 100644 --- a/gateway/payloads/events/messagedeletebulk.go +++ b/gateway/payloads/events/messagedeletebulk.go @@ -3,7 +3,7 @@ package events import "github.com/TicketsBot-cloud/gdl/utils" type MessageDeleteBulk struct { - Id utils.Uint64StringSlice `json:"ids"` + Ids utils.Uint64StringSlice `json:"ids"` ChannelId uint64 `json:"channel_id,string"` - GuildId uint64 `json:"guild_id,string"` + GuildId *uint64 `json:"guild_id,string"` } diff --git a/gateway/payloads/events/messagepollvote.go b/gateway/payloads/events/messagepollvote.go new file mode 100644 index 0000000..7707876 --- /dev/null +++ b/gateway/payloads/events/messagepollvote.go @@ -0,0 +1,17 @@ +package events + +type MessagePollVoteAdd struct { + UserId uint64 `json:"user_id,string"` + ChannelId uint64 `json:"channel_id,string"` + MessageId uint64 `json:"message_id,string"` + GuildId *uint64 `json:"guild_id,string"` + AnswerId uint8 `json:"answer_id"` +} + +type MessagePollVoteRemove struct { + UserId uint64 `json:"user_id,string"` + ChannelId uint64 `json:"channel_id,string"` + MessageId uint64 `json:"message_id,string"` + GuildId *uint64 `json:"guild_id,string"` + AnswerId uint8 `json:"answer_id"` +} diff --git a/gateway/payloads/events/messagereactionadd.go b/gateway/payloads/events/messagereactionadd.go index 8d1fd35..d930dcc 100644 --- a/gateway/payloads/events/messagereactionadd.go +++ b/gateway/payloads/events/messagereactionadd.go @@ -6,10 +6,14 @@ import ( ) type MessageReactionAdd struct { - UserId uint64 `json:"user_id,string"` - ChannelId uint64 `json:"channel_id,string"` - MessageId uint64 `json:"message_id,string"` - GuildId uint64 `json:"guild_id,string"` - Member *member.Member `json:"member"` - Emoji emoji.Emoji `json:"emoji"` // Partial emoji object; https://discord.com/developers/docs/resources/emoji#emoji-object-gateway-reaction-standard-emoji-example + UserId uint64 `json:"user_id,string"` + ChannelId uint64 `json:"channel_id,string"` + MessageId uint64 `json:"message_id,string"` + GuildId *uint64 `json:"guild_id,string"` + MessageAuthorId *uint64 `json:"message_author_id,string"` + Member *member.Member `json:"member"` + Emoji emoji.Emoji `json:"emoji"` + Burst bool `json:"burst"` + BurstColors []string `json:"burst_colors"` + Type int `json:"type"` } diff --git a/gateway/payloads/events/messagereactionremove.go b/gateway/payloads/events/messagereactionremove.go index 7a07871..d47b665 100644 --- a/gateway/payloads/events/messagereactionremove.go +++ b/gateway/payloads/events/messagereactionremove.go @@ -1,14 +1,14 @@ package events -import ( - "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" -) +import "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" // Sent when a user removes a reaction from a message. type MessageReactionRemove struct { UserId uint64 `json:"user_id,string"` ChannelId uint64 `json:"channel_id,string"` MessageId uint64 `json:"message_id,string"` - GuildId uint64 `json:"guild_id,string"` - Emoji emoji.Emoji `json:"emoji,string"` // Partial emoji object; https://discord.com/developers/docs/resources/emoji#emoji-object-gateway-reaction-standard-emoji-example + GuildId *uint64 `json:"guild_id,string"` + Emoji emoji.Emoji `json:"emoji"` + Burst bool `json:"burst"` + Type int `json:"type"` } diff --git a/gateway/payloads/events/messagereactionremoveemoji.go b/gateway/payloads/events/messagereactionremoveemoji.go index f697ce8..8fda8c9 100644 --- a/gateway/payloads/events/messagereactionremoveemoji.go +++ b/gateway/payloads/events/messagereactionremoveemoji.go @@ -1,13 +1,11 @@ package events -import ( - "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" -) +import "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" // Sent when a bot removes all instances of a given emoji from the reactions of a message. type MessageReactionRemoveEmoji struct { ChannelId uint64 `json:"channel_id,string"` - GuildId uint64 `json:"guild_id,string"` + GuildId *uint64 `json:"guild_id,string"` MessageId uint64 `json:"message_id,string"` - Emoji emoji.Emoji `json:"emoji,string"` // Partial emoji object; https://discord.com/developers/docs/resources/emoji#emoji-object-gateway-reaction-standard-emoji-example + Emoji emoji.Emoji `json:"emoji"` } diff --git a/gateway/payloads/events/ready.go b/gateway/payloads/events/ready.go index 6f944ec..941bff4 100644 --- a/gateway/payloads/events/ready.go +++ b/gateway/payloads/events/ready.go @@ -1,15 +1,17 @@ package events import ( + "github.com/TicketsBot-cloud/gdl/objects/application" "github.com/TicketsBot-cloud/gdl/objects/guild" "github.com/TicketsBot-cloud/gdl/objects/user" ) type Ready struct { - GatewayVersion int `json:"v"` - User user.User `json:"user"` - PrivateChannels []uint64 `json:"private_channels,string"` // Note: This slice will always be empty - Guilds []guild.Guild `json:"guilds"` - SessionId string `json:"session_id"` - Shard []int `json:"shard"` // Slice of [shard_id, num_shards] + GatewayVersion int `json:"v"` + User user.User `json:"user"` + Guilds []guild.Guild `json:"guilds"` + SessionId string `json:"session_id"` + ResumeGatewayUrl string `json:"resume_gateway_url"` + Shard []int `json:"shard"` + Application application.PartialApplication `json:"application"` } diff --git a/gateway/payloads/events/registry.go b/gateway/payloads/events/registry.go new file mode 100644 index 0000000..5f592a3 --- /dev/null +++ b/gateway/payloads/events/registry.go @@ -0,0 +1,183 @@ +package events + +import "reflect" + +type Event interface { + Ready | + Resumed | + Reconnect | + InvalidSession | + ApplicationCommandPermissionsUpdate | + AutoModerationRuleCreate | + AutoModerationRuleUpdate | + AutoModerationRuleDelete | + AutoModerationActionExecution | + ChannelCreate | + ChannelUpdate | + ChannelDelete | + ChannelInfo | + ChannelPinsUpdate | + ThreadCreate | + ThreadUpdate | + ThreadDelete | + ThreadListSync | + ThreadMembersUpdate | + ThreadMemberUpdate | + EntitlementCreate | + EntitlementUpdate | + EntitlementDelete | + GuildCreate | + GuildUpdate | + GuildDelete | + GuildAuditLogEntryCreate | + GuildBanAdd | + GuildBanRemove | + GuildEmojisUpdate | + GuildStickersUpdate | + GuildIntegrationsUpdate | + GuildMemberAdd | + GuildMemberRemove | + GuildMemberUpdate | + GuildMembersChunk | + GuildRoleCreate | + GuildRoleUpdate | + GuildRoleDelete | + GuildScheduledEventCreate | + GuildScheduledEventUpdate | + GuildScheduledEventDelete | + GuildScheduledEventUserAdd | + GuildScheduledEventUserRemove | + GuildSoundboardSoundCreate | + GuildSoundboardSoundUpdate | + GuildSoundboardSoundDelete | + GuildSoundboardSoundsUpdate | + SoundboardSounds | + IntegrationCreate | + IntegrationUpdate | + IntegrationDelete | + InviteCreate | + InviteDelete | + MessageCreate | + MessageUpdate | + MessageDelete | + MessageDeleteBulk | + MessageReactionAdd | + MessageReactionRemove | + MessageReactionRemoveAll | + MessageReactionRemoveEmoji | + MessagePollVoteAdd | + MessagePollVoteRemove | + PresenceUpdate | + StageInstanceCreate | + StageInstanceUpdate | + StageInstanceDelete | + SubscriptionCreate | + SubscriptionUpdate | + SubscriptionDelete | + TypingStart | + UserUpdate | + VoiceChannelEffectSend | + VoiceChannelStartTimeUpdate | + VoiceChannelStatusUpdate | + VoiceServerUpdate | + VoiceStateUpdate | + WebhooksUpdate +} + +var EventTypes = map[EventType]reflect.Type{ + READY: reflect.TypeOf(Ready{}), + RESUMED: reflect.TypeOf(Resumed{}), + RECONNECT: reflect.TypeOf(Reconnect{}), + INVALID_SESSION: reflect.TypeOf(InvalidSession{}), + + APPLICATION_COMMAND_PERMISSIONS_UPDATE: reflect.TypeOf(ApplicationCommandPermissionsUpdate{}), + + AUTO_MODERATION_RULE_CREATE: reflect.TypeOf(AutoModerationRuleCreate{}), + AUTO_MODERATION_RULE_UPDATE: reflect.TypeOf(AutoModerationRuleUpdate{}), + AUTO_MODERATION_RULE_DELETE: reflect.TypeOf(AutoModerationRuleDelete{}), + AUTO_MODERATION_ACTION_EXECUTION: reflect.TypeOf(AutoModerationActionExecution{}), + + CHANNEL_CREATE: reflect.TypeOf(ChannelCreate{}), + CHANNEL_UPDATE: reflect.TypeOf(ChannelUpdate{}), + CHANNEL_DELETE: reflect.TypeOf(ChannelDelete{}), + CHANNEL_INFO: reflect.TypeOf(ChannelInfo{}), + CHANNEL_PINS_UPDATE: reflect.TypeOf(ChannelPinsUpdate{}), + + THREAD_CREATE: reflect.TypeOf(ThreadCreate{}), + THREAD_UPDATE: reflect.TypeOf(ThreadUpdate{}), + THREAD_DELETE: reflect.TypeOf(ThreadDelete{}), + THREAD_LIST_SYNC: reflect.TypeOf(ThreadListSync{}), + THREAD_MEMBER_UPDATE: reflect.TypeOf(ThreadMemberUpdate{}), + THREAD_MEMBERS_UPDATE: reflect.TypeOf(ThreadMembersUpdate{}), + + ENTITLEMENT_CREATE: reflect.TypeOf(EntitlementCreate{}), + ENTITLEMENT_UPDATE: reflect.TypeOf(EntitlementUpdate{}), + ENTITLEMENT_DELETE: reflect.TypeOf(EntitlementDelete{}), + + GUILD_CREATE: reflect.TypeOf(GuildCreate{}), + GUILD_UPDATE: reflect.TypeOf(GuildUpdate{}), + GUILD_DELETE: reflect.TypeOf(GuildDelete{}), + GUILD_AUDIT_LOG_ENTRY_CREATE: reflect.TypeOf(GuildAuditLogEntryCreate{}), + GUILD_BAN_ADD: reflect.TypeOf(GuildBanAdd{}), + GUILD_BAN_REMOVE: reflect.TypeOf(GuildBanRemove{}), + GUILD_EMOJIS_UPDATE: reflect.TypeOf(GuildEmojisUpdate{}), + GUILD_STICKERS_UPDATE: reflect.TypeOf(GuildStickersUpdate{}), + GUILD_INTEGRATIONS_UPDATE: reflect.TypeOf(GuildIntegrationsUpdate{}), + GUILD_MEMBER_ADD: reflect.TypeOf(GuildMemberAdd{}), + GUILD_MEMBER_REMOVE: reflect.TypeOf(GuildMemberRemove{}), + GUILD_MEMBER_UPDATE: reflect.TypeOf(GuildMemberUpdate{}), + GUILD_MEMBERS_CHUNK: reflect.TypeOf(GuildMembersChunk{}), + GUILD_ROLE_CREATE: reflect.TypeOf(GuildRoleCreate{}), + GUILD_ROLE_UPDATE: reflect.TypeOf(GuildRoleUpdate{}), + GUILD_ROLE_DELETE: reflect.TypeOf(GuildRoleDelete{}), + GUILD_SCHEDULED_EVENT_CREATE: reflect.TypeOf(GuildScheduledEventCreate{}), + GUILD_SCHEDULED_EVENT_UPDATE: reflect.TypeOf(GuildScheduledEventUpdate{}), + GUILD_SCHEDULED_EVENT_DELETE: reflect.TypeOf(GuildScheduledEventDelete{}), + GUILD_SCHEDULED_EVENT_USER_ADD: reflect.TypeOf(GuildScheduledEventUserAdd{}), + GUILD_SCHEDULED_EVENT_USER_REMOVE: reflect.TypeOf(GuildScheduledEventUserRemove{}), + GUILD_SOUNDBOARD_SOUND_CREATE: reflect.TypeOf(GuildSoundboardSoundCreate{}), + GUILD_SOUNDBOARD_SOUND_UPDATE: reflect.TypeOf(GuildSoundboardSoundUpdate{}), + GUILD_SOUNDBOARD_SOUND_DELETE: reflect.TypeOf(GuildSoundboardSoundDelete{}), + GUILD_SOUNDBOARD_SOUNDS_UPDATE: reflect.TypeOf(GuildSoundboardSoundsUpdate{}), + SOUNDBOARD_SOUNDS: reflect.TypeOf(SoundboardSounds{}), + + INTEGRATION_CREATE: reflect.TypeOf(IntegrationCreate{}), + INTEGRATION_UPDATE: reflect.TypeOf(IntegrationUpdate{}), + INTEGRATION_DELETE: reflect.TypeOf(IntegrationDelete{}), + + INVITE_CREATE: reflect.TypeOf(InviteCreate{}), + INVITE_DELETE: reflect.TypeOf(InviteDelete{}), + + MESSAGE_CREATE: reflect.TypeOf(MessageCreate{}), + MESSAGE_UPDATE: reflect.TypeOf(MessageUpdate{}), + MESSAGE_DELETE: reflect.TypeOf(MessageDelete{}), + MESSAGE_DELETE_BULK: reflect.TypeOf(MessageDeleteBulk{}), + MESSAGE_REACTION_ADD: reflect.TypeOf(MessageReactionAdd{}), + MESSAGE_REACTION_REMOVE: reflect.TypeOf(MessageReactionRemove{}), + MESSAGE_REACTION_REMOVE_ALL: reflect.TypeOf(MessageReactionRemoveAll{}), + MESSAGE_REACTION_REMOVE_EMOJI: reflect.TypeOf(MessageReactionRemoveEmoji{}), + MESSAGE_POLL_VOTE_ADD: reflect.TypeOf(MessagePollVoteAdd{}), + MESSAGE_POLL_VOTE_REMOVE: reflect.TypeOf(MessagePollVoteRemove{}), + + PRESENCE_UPDATE: reflect.TypeOf(PresenceUpdate{}), + + STAGE_INSTANCE_CREATE: reflect.TypeOf(StageInstanceCreate{}), + STAGE_INSTANCE_UPDATE: reflect.TypeOf(StageInstanceUpdate{}), + STAGE_INSTANCE_DELETE: reflect.TypeOf(StageInstanceDelete{}), + + SUBSCRIPTION_CREATE: reflect.TypeOf(SubscriptionCreate{}), + SUBSCRIPTION_UPDATE: reflect.TypeOf(SubscriptionUpdate{}), + SUBSCRIPTION_DELETE: reflect.TypeOf(SubscriptionDelete{}), + + TYPING_START: reflect.TypeOf(TypingStart{}), + + USER_UPDATE: reflect.TypeOf(UserUpdate{}), + + VOICE_CHANNEL_EFFECT_SEND: reflect.TypeOf(VoiceChannelEffectSend{}), + VOICE_CHANNEL_START_TIME_UPDATE: reflect.TypeOf(VoiceChannelStartTimeUpdate{}), + VOICE_CHANNEL_STATUS_UPDATE: reflect.TypeOf(VoiceChannelStatusUpdate{}), + VOICE_STATE_UPDATE: reflect.TypeOf(VoiceStateUpdate{}), + VOICE_SERVER_UPDATE: reflect.TypeOf(VoiceServerUpdate{}), + + WEBHOOKS_UPDATE: reflect.TypeOf(WebhooksUpdate{}), +} diff --git a/gateway/payloads/events/stageinstances.go b/gateway/payloads/events/stageinstances.go new file mode 100644 index 0000000..88494de --- /dev/null +++ b/gateway/payloads/events/stageinstances.go @@ -0,0 +1,15 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/guild/stage" + +type StageInstanceCreate struct { + stage.StageInstance +} + +type StageInstanceUpdate struct { + stage.StageInstance +} + +type StageInstanceDelete struct { + stage.StageInstance +} diff --git a/gateway/payloads/events/subscriptions.go b/gateway/payloads/events/subscriptions.go new file mode 100644 index 0000000..2501c47 --- /dev/null +++ b/gateway/payloads/events/subscriptions.go @@ -0,0 +1,15 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/subscription" + +type SubscriptionCreate struct { + subscription.Subscription +} + +type SubscriptionUpdate struct { + subscription.Subscription +} + +type SubscriptionDelete struct { + subscription.Subscription +} diff --git a/gateway/payloads/events/threadcreate.go b/gateway/payloads/events/threadcreate.go index 7cb9548..8b85097 100644 --- a/gateway/payloads/events/threadcreate.go +++ b/gateway/payloads/events/threadcreate.go @@ -1,9 +1,8 @@ package events -import ( - "github.com/TicketsBot-cloud/gdl/objects/channel" -) +import "github.com/TicketsBot-cloud/gdl/objects/channel" type ThreadCreate struct { channel.Channel + NewlyCreated bool `json:"newly_created"` } diff --git a/gateway/payloads/events/threaddelete.go b/gateway/payloads/events/threaddelete.go index d1f5753..5ff6cd4 100644 --- a/gateway/payloads/events/threaddelete.go +++ b/gateway/payloads/events/threaddelete.go @@ -1,9 +1,10 @@ package events -import ( - "github.com/TicketsBot-cloud/gdl/objects/channel" -) +import "github.com/TicketsBot-cloud/gdl/objects/channel" type ThreadDelete struct { - channel.Channel + Id uint64 `json:"id,string"` + GuildId uint64 `json:"guild_id,string"` + ParentId uint64 `json:"parent_id,string"` + Type channel.ChannelType `json:"type"` } diff --git a/gateway/payloads/events/threadmembersupdate.go b/gateway/payloads/events/threadmembersupdate.go index 3287d29..1198cf8 100644 --- a/gateway/payloads/events/threadmembersupdate.go +++ b/gateway/payloads/events/threadmembersupdate.go @@ -8,7 +8,7 @@ import ( type ThreadMembersUpdate struct { ThreadId uint64 `json:"id,string"` GuildId uint64 `json:"guild_id,string"` - MemberCount uint64 `json:"member_count"` + MemberCount int `json:"member_count"` AddedMembers []channel.ThreadMember `json:"added_members"` RemovedMemberIds utils.Uint64StringSlice `json:"removed_member_ids"` } diff --git a/gateway/payloads/events/threadmemberupdate.go b/gateway/payloads/events/threadmemberupdate.go index 5bd444e..b1f1c71 100644 --- a/gateway/payloads/events/threadmemberupdate.go +++ b/gateway/payloads/events/threadmemberupdate.go @@ -1,9 +1,8 @@ package events -import ( - "github.com/TicketsBot-cloud/gdl/objects/channel" -) +import "github.com/TicketsBot-cloud/gdl/objects/channel" type ThreadMemberUpdate struct { channel.ThreadMember + GuildId uint64 `json:"guild_id,string"` } diff --git a/gateway/payloads/events/voicechanneleffectsend.go b/gateway/payloads/events/voicechanneleffectsend.go new file mode 100644 index 0000000..71d5437 --- /dev/null +++ b/gateway/payloads/events/voicechanneleffectsend.go @@ -0,0 +1,14 @@ +package events + +import "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" + +type VoiceChannelEffectSend struct { + ChannelId uint64 `json:"channel_id,string"` + GuildId uint64 `json:"guild_id,string"` + UserId uint64 `json:"user_id,string"` + Emoji *emoji.Emoji `json:"emoji"` + AnimationType *int `json:"animation_type"` + AnimationId uint `json:"animation_id"` + SoundId *uint64 `json:"sound_id,string"` + SoundVolume *float64 `json:"sound_volume"` +} diff --git a/gateway/payloads/events/voicechannelstarttimeupdate.go b/gateway/payloads/events/voicechannelstarttimeupdate.go new file mode 100644 index 0000000..f278ce4 --- /dev/null +++ b/gateway/payloads/events/voicechannelstarttimeupdate.go @@ -0,0 +1,7 @@ +package events + +type VoiceChannelStartTimeUpdate struct { + Id uint64 `json:"id,string"` + GuildId uint64 `json:"guild_id,string"` + VoiceStartTime *int64 `json:"voice_start_time"` +} diff --git a/gateway/payloads/events/voicechannelstatusupdate.go b/gateway/payloads/events/voicechannelstatusupdate.go new file mode 100644 index 0000000..579f8ef --- /dev/null +++ b/gateway/payloads/events/voicechannelstatusupdate.go @@ -0,0 +1,7 @@ +package events + +type VoiceChannelStatusUpdate struct { + Id uint64 `json:"id,string"` + GuildId uint64 `json:"guild_id,string"` + Status *string `json:"status"` +} diff --git a/gateway/payloads/events/voiceserverupdate.go b/gateway/payloads/events/voiceserverupdate.go index 9f8d59b..88a83ac 100644 --- a/gateway/payloads/events/voiceserverupdate.go +++ b/gateway/payloads/events/voiceserverupdate.go @@ -1,7 +1,7 @@ package events type VoiceServerUpdate struct { - Token string `json:"token"` - GuildId uint64 `json:"guild_id,string"` - Endpoint string `json:"endpoint"` + Token string `json:"token"` + GuildId uint64 `json:"guild_id,string"` + Endpoint *string `json:"endpoint"` } diff --git a/gateway/payloads/heartbeatack.go b/gateway/payloads/heartbeatack.go index 83b1737..c66e141 100644 --- a/gateway/payloads/heartbeatack.go +++ b/gateway/payloads/heartbeatack.go @@ -5,13 +5,14 @@ import ( ) type HeartbeatAck struct { - Opcode int `json:"op"` + Opcode int `json:"op"` SequenceNumber int `json:"d"` } func NewHeartbeackAck(raw []byte) (Hello, error) { var payload Hello - err := json.Unmarshal(raw, &payload); if err != nil { + err := json.Unmarshal(raw, &payload) + if err != nil { return Hello{}, err } diff --git a/gateway/payloads/payload.go b/gateway/payloads/payload.go index 4558ee1..153a53f 100644 --- a/gateway/payloads/payload.go +++ b/gateway/payloads/payload.go @@ -5,10 +5,10 @@ import ( ) type Payload struct { - Opcode int `json:"op"` + Opcode int `json:"op"` Data json.RawMessage `json:"d"` - SequenceNumber *int `json:"s"` - EventName string `json:"t"` + SequenceNumber *int `json:"s"` + EventName string `json:"t"` } func NewPayload(raw []byte) (Payload, error) { diff --git a/gateway/restwrapper.go b/gateway/restwrapper.go index d32b6ee..97f4440 100644 --- a/gateway/restwrapper.go +++ b/gateway/restwrapper.go @@ -187,7 +187,7 @@ func (s *Shard) GetThreadMember(ctx context.Context, channelId, userId uint64) ( } func (s *Shard) ListThreadMembers(ctx context.Context, channelId uint64) ([]channel.ThreadMember, error) { - return rest.ListThreadMembers(ctx, s.Token, s.ShardManager.RateLimiter, channelId) + return rest.ListThreadMembers(ctx, s.Token, s.ShardManager.RateLimiter, channelId, rest.ListThreadMembersData{}) } func (s *Shard) ListActiveThreads(ctx context.Context, guildId uint64) (rest.ThreadsResponse, error) { @@ -218,7 +218,7 @@ func (s *Shard) CreatePublicThread(ctx context.Context, channelId uint64, name s data := rest.StartThreadWithoutMessageData{ Name: name, AutoArchiveDuration: autoArchiveDuration, - Type: channel.ChannelTypeGuildPublicThread, + Type: channel.ChannelTypePublicThread, } return rest.StartThreadWithoutMessage(ctx, s.Token, s.ShardManager.RateLimiter, channelId, data) @@ -228,7 +228,7 @@ func (s *Shard) CreatePrivateThread(ctx context.Context, channelId uint64, name data := rest.StartThreadWithoutMessageData{ Name: name, AutoArchiveDuration: autoArchiveDuration, - Type: channel.ChannelTypeGuildPrivateThread, + Type: channel.ChannelTypePrivateThread, Invitable: invitable, } @@ -395,7 +395,7 @@ func (s *Shard) SearchGuildMembers(ctx context.Context, guildId uint64, data res var users []user.User for _, m := range members { - users = append(users, m.User) + users = append(users, *m.User) } if err := s.Cache.StoreUsers(ctx, users); err != nil { @@ -419,7 +419,7 @@ func (s *Shard) ListGuildMembers(ctx context.Context, guildId uint64, data rest. var users []user.User for _, m := range members { - users = append(users, m.User) + users = append(users, *m.User) } if err := s.Cache.StoreUsers(ctx, users); err != nil { @@ -511,7 +511,10 @@ func (s *Shard) GetGuildPruneCount(ctx context.Context, guildId uint64, days int // computePruneCount = whether 'pruned' is returned, discouraged for large guilds func (s *Shard) BeginGuildPrune(ctx context.Context, guildId uint64, days int, computePruneCount bool) error { - return rest.BeginGuildPrune(ctx, s.Token, s.ShardManager.RateLimiter, guildId, days, computePruneCount) + return rest.BeginGuildPrune(ctx, s.Token, s.ShardManager.RateLimiter, guildId, rest.BeginGuildPruneData{ + Days: days, + ComputePruneCount: computePruneCount, + }) } func (s *Shard) GetGuildVoiceRegions(ctx context.Context, guildId uint64) ([]guild.VoiceRegion, error) { @@ -556,7 +559,7 @@ func (s *Shard) GetGuildVanityUrl(ctx context.Context, guildId uint64) (invite.I } func (s *Shard) GetInvite(ctx context.Context, inviteCode string, withCounts bool) (invite.Invite, error) { - return rest.GetInvite(ctx, s.Token, s.ShardManager.RateLimiter, inviteCode, withCounts) + return rest.GetInvite(ctx, s.Token, s.ShardManager.RateLimiter, inviteCode, withCounts, nil) } func (s *Shard) DeleteInvite(ctx context.Context, inviteCode string) (invite.Invite, error) { @@ -668,7 +671,7 @@ func (s *Shard) GetGuildAuditLog(ctx context.Context, guildId uint64, data rest. } func (s *Shard) GetGlobalCommands(ctx context.Context, applicationId uint64) ([]interaction.ApplicationCommand, error) { - return rest.GetGlobalCommands(ctx, s.Token, s.ShardManager.RateLimiter, applicationId) + return rest.GetGlobalCommands(ctx, s.Token, s.ShardManager.RateLimiter, applicationId, false) } func (s *Shard) CreateGlobalCommand(ctx context.Context, applicationId uint64, data rest.CreateCommandData) (interaction.ApplicationCommand, error) { @@ -688,7 +691,7 @@ func (s *Shard) DeleteGlobalCommand(ctx context.Context, applicationId, commandI } func (s *Shard) GetGuildCommands(ctx context.Context, applicationId, guildId uint64) ([]interaction.ApplicationCommand, error) { - return rest.GetGuildCommands(ctx, s.Token, s.ShardManager.RateLimiter, applicationId, guildId) + return rest.GetGuildCommands(ctx, s.Token, s.ShardManager.RateLimiter, applicationId, guildId, false) } func (s *Shard) CreateGuildCommand(ctx context.Context, applicationId, guildId uint64, data rest.CreateCommandData) (interaction.ApplicationCommand, error) { @@ -722,3 +725,7 @@ func (s *Shard) EditCommandPermissions(ctx context.Context, applicationId, guild func (s *Shard) EditBulkCommandPermissions(ctx context.Context, applicationId, guildId uint64, data []rest.CommandWithPermissionsData) ([]rest.CommandWithPermissionsData, error) { return rest.EditBulkCommandPermissions(ctx, s.Token, s.ShardManager.RateLimiter, applicationId, guildId, data) } + +func (s *Shard) SearchGuildMessages(ctx context.Context, guildId uint64, data rest.SearchGuildMessagesData) (rest.SearchGuildMessagesResponse, error) { + return rest.SearchGuildMessages(ctx, s.Token, s.ShardManager.RateLimiter, guildId, data) +} diff --git a/gateway/shardmanager.go b/gateway/shardmanager.go index a998230..a8565a8 100644 --- a/gateway/shardmanager.go +++ b/gateway/shardmanager.go @@ -5,7 +5,6 @@ import ( "os/signal" "syscall" - "github.com/TicketsBot-cloud/gdl/gateway/payloads/events" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" "github.com/TicketsBot-cloud/gdl/rest/request" ) @@ -18,7 +17,7 @@ type ShardManager struct { ShardOptions ShardOptions Shards map[int]*Shard - EventBus *events.EventBus + EventBus *EventBus } func NewShardManager(token string, shardOptions ShardOptions) *ShardManager { @@ -30,7 +29,7 @@ func NewShardManager(token string, shardOptions ShardOptions) *ShardManager { Token: token, RateLimiter: ratelimit.NewRateLimiter(shardOptions.RateLimitStore, shardOptions.LargeShardingBuckets), ShardOptions: shardOptions, - EventBus: events.NewEventBus(), + EventBus: NewEventBus(), } manager.Shards = make(map[int]*Shard) @@ -67,6 +66,6 @@ func (sm *ShardManager) ShardForGuild(guildId uint64) *Shard { func (sm *ShardManager) WaitForInterrupt() { ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) <-ch } diff --git a/gateway/state.go b/gateway/state.go index 6f10c0c..b7ad062 100644 --- a/gateway/state.go +++ b/gateway/state.go @@ -2,7 +2,7 @@ package gateway type State int -const( +const ( CONNECTED State = iota CONNECTING DISCONNECTING diff --git a/gateway/wrappedreader.go b/gateway/wrappedreader.go index 505e652..c917e3f 100644 --- a/gateway/wrappedreader.go +++ b/gateway/wrappedreader.go @@ -4,7 +4,6 @@ import ( "errors" "github.com/tatsuworks/czlib" "io" - "io/ioutil" "sync" ) @@ -12,7 +11,7 @@ type wrappedReader struct { io.ReadCloser sync.RWMutex closeChan chan struct{} - isClosed bool + isClosed bool } func (r *wrappedReader) Close() error { @@ -43,7 +42,7 @@ func (r *wrappedReader) Read() ([]byte, error) { case <-r.closeChan: return nil, errors.New("reader was closed") default: - return ioutil.ReadAll(r.ReadCloser) + return io.ReadAll(r.ReadCloser) } } diff --git a/objects/application/activityinstance.go b/objects/application/activityinstance.go new file mode 100644 index 0000000..d70851a --- /dev/null +++ b/objects/application/activityinstance.go @@ -0,0 +1,16 @@ +package application + +type ActivityLocation struct { + Id string `json:"id"` + Kind string `json:"kind"` + ChannelId uint64 `json:"channel_id,string"` + GuildId *uint64 `json:"guild_id,string,omitempty"` +} + +type ActivityInstance struct { + ApplicationId uint64 `json:"application_id,string"` + InstanceId string `json:"instance_id"` + LaunchId string `json:"launch_id"` + Location ActivityLocation `json:"location"` + Users []uint64 `json:"users"` +} diff --git a/objects/application/application.go b/objects/application/application.go index 92a14a1..f0bad13 100644 --- a/objects/application/application.go +++ b/objects/application/application.go @@ -6,32 +6,56 @@ import ( ) type Application struct { - Id uint64 `json:"id,string"` - Name string `json:"name"` - Icon *string `json:"icon"` - Description string `json:"description"` - RpcOrigins []string `json:"rpc_origins,omitempty"` - BotPublic bool `json:"bot_public"` - BotRequireCodeGrant bool `json:"bot_require_code_grant"` - Bot *user.User `json:"bot,omitempty"` - TermsOfServiceUrl *string `json:"terms_of_service_url,omitempty"` - PrivacyPolicyUrl *string `json:"privacy_policy_url,omitempty"` - Owner *user.User `json:"owner,omitempty"` - VerifyKey string `json:"verify_key"` - Team *Team `json:"team"` - GuildId *uint64 `json:"guild_id,string,omitempty"` - Guild *guild.Guild `json:"guild,omitempty"` - PrimarySkuId *uint64 `json:"primary_sku_id,string,omitempty"` - Slug *string `json:"slug,omitempty"` - CoverImage *string `json:"cover_image,omitempty"` - Flags *Flag `json:"flags,omitempty"` - ApproximateGuildCount *int `json:"approximate_guild_count,omitempty"` - RedirectUris []string `json:"redirect_uris,omitempty"` - InteractionsEndpointUrl *string `json:"interactions_endpoint_url,omitempty"` - RoleConnectionsVerificationUrl *string `json:"role_connections_verification_url,omitempty"` - Tags []string `json:"tags,omitempty"` - InstallParams *InstallParams `json:"install_params,omitempty"` - CustomInstallUrl *string `json:"custom_install_url,omitempty"` + Id uint64 `json:"id,string"` + Name string `json:"name"` + Icon *string `json:"icon"` + Description string `json:"description"` + RpcOrigins []string `json:"rpc_origins,omitempty"` + BotPublic bool `json:"bot_public"` + BotRequireCodeGrant bool `json:"bot_require_code_grant"` + Bot *user.User `json:"bot,omitempty"` + TermsOfServiceUrl *string `json:"terms_of_service_url,omitempty"` + PrivacyPolicyUrl *string `json:"privacy_policy_url,omitempty"` + Owner *user.User `json:"owner,omitempty"` + VerifyKey string `json:"verify_key"` + Team *Team `json:"team"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + Guild *guild.Guild `json:"guild,omitempty"` + PrimarySkuId *uint64 `json:"primary_sku_id,string,omitempty"` + Slug *string `json:"slug,omitempty"` + CoverImage *string `json:"cover_image,omitempty"` + Flags *Flag `json:"flags,omitempty"` + ApproximateGuildCount *int `json:"approximate_guild_count,omitempty"` + ApproximateUserInstallCount *int `json:"approximate_user_install_count,omitempty"` + RedirectUris []string `json:"redirect_uris,omitempty"` + InteractionsEndpointUrl *string `json:"interactions_endpoint_url,omitempty"` + RoleConnectionsVerificationUrl *string `json:"role_connections_verification_url,omitempty"` + EventWebhooksUrl *string `json:"event_webhooks_url,omitempty"` + EventWebhooksStatus ApplicationEventWebhookStatus `json:"event_webhooks_status,omitempty"` + EventWebhooksTypes []string `json:"event_webhooks_types,omitempty"` + Tags []string `json:"tags,omitempty"` + InstallParams *InstallParams `json:"install_params,omitempty"` + IntegrationTypesConfig map[ApplicationIntegrationType]ApplicationIntegrationTypeConfig `json:"integration_types_config,omitempty"` + CustomInstallUrl *string `json:"custom_install_url,omitempty"` +} + +type ApplicationEventWebhookStatus int + +const ( + ApplicationEventWebhookStatusDisabled ApplicationEventWebhookStatus = iota + 1 + ApplicationEventWebhookStatusEnabled + ApplicationEventWebhookStatusDisabledByDiscord +) + +type ApplicationIntegrationType int + +const ( + ApplicationIntegrationTypeGuildInstall ApplicationIntegrationType = iota + ApplicationIntegrationTypeUserInstall +) + +type ApplicationIntegrationTypeConfig struct { + OAuth2InstallParams *InstallParams `json:"oauth2_install_params,omitempty"` } type Flag uint64 @@ -46,7 +70,7 @@ const ( FlagEmbedded Flag = 1 << 17 FlagGatewayMessageContent Flag = 1 << 18 FlagGatewayMessageContentLimited Flag = 1 << 19 - FlagApplicationCommandBadge Flag = 1 << 20 + FlagApplicationCommandBadge Flag = 1 << 23 ) func (f Flag) Has(flag Flag) bool { @@ -62,3 +86,8 @@ func BuildFlags(flags ...Flag) Flag { return built } + +type PartialApplication struct { + Id uint64 `json:"id,string"` + Flags int `json:"flags"` +} diff --git a/objects/application/team.go b/objects/application/team.go index 5c7b8d8..a317ee4 100644 --- a/objects/application/team.go +++ b/objects/application/team.go @@ -24,9 +24,10 @@ type ( ) const ( - TeamMembershipStateInvited TeamMembershipState = 1 - TeamMembershipStateAccepted TeamMembershipState = 2 + TeamMembershipStateInvited TeamMembershipState = iota + 1 + TeamMembershipStateAccepted + TeamMemberRoleOwner TeamMemberRole = "owner" TeamMemberRoleAdmin TeamMemberRole = "admin" TeamMemberRoleDeveloper TeamMemberRole = "developer" TeamMemberRoleReadOnly TeamMemberRole = "read_only" diff --git a/objects/auditlog/auditentryinfo.go b/objects/auditlog/auditentryinfo.go index 0397da6..66c557e 100644 --- a/objects/auditlog/auditentryinfo.go +++ b/objects/auditlog/auditentryinfo.go @@ -2,12 +2,17 @@ package auditlog // https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object-optional-audit-entry-info type AuditEntryInfo struct { - DeleteMemberDays int `json:"delete_member_days,string"` // MEMBER_PRUNE - MembersRemoved int `json:"members_removed,string"` // MEMBER_PRUNE - ChannelId uint64 `json:"channel_id,string"` // MEMBER_MOVE & MESSAGE_PIN & MESSAGE_UNPIN & MESSAGE_DELETE - MessageId uint64 `json:"message_id,string"` // MESSAGE_PIN & MESSAGE_UNPIN - Id uint64 `json:"id,string"` // MESSAGE_DELETE & MESSAGE_BULK_DELETE & MEMBER_DISCONNECT & MEMBER_MOVE - Count int `json:"count,string"` // CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE - Type EntityType `json:"type"` // CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE - RoleName string `json:"role_name"` //CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE + ApplicationId *uint64 `json:"application_id,string,omitempty"` // APPLICATION_COMMAND_PERMISSION_UPDATE + AutoModerationRuleName string `json:"auto_moderation_rule_name,omitempty"` // AUTO_MODERATION_* + AutoModerationRuleTriggerType string `json:"auto_moderation_rule_trigger_type,omitempty"` // AUTO_MODERATION_* + ChannelId *uint64 `json:"channel_id,string,omitempty"` // MEMBER_MOVE & MESSAGE_PIN & MESSAGE_UNPIN & MESSAGE_DELETE & STAGE_INSTANCE_* + Count string `json:"count,omitempty"` // MESSAGE_DELETE & MESSAGE_BULK_DELETE & MEMBER_DISCONNECT & MEMBER_MOVE + DeleteMemberDays string `json:"delete_member_days,omitempty"` // MEMBER_PRUNE + Id *uint64 `json:"id,string,omitempty"` // MESSAGE_DELETE & MESSAGE_BULK_DELETE & MEMBER_DISCONNECT & MEMBER_MOVE + IntegrationType string `json:"integration_type,omitempty"` // MEMBER_KICK & MEMBER_ROLE_UPDATE + MembersRemoved string `json:"members_removed,omitempty"` // MEMBER_PRUNE + MessageId *uint64 `json:"message_id,string,omitempty"` // MESSAGE_PIN & MESSAGE_UNPIN + RoleName string `json:"role_name,omitempty"` // CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE + Type EntityType `json:"type,omitempty"` // CHANNEL_OVERWRITE_CREATE & CHANNEL_OVERWRITE_UPDATE & CHANNEL_OVERWRITE_DELETE + Status string `json:"status,omitempty"` // VOICE_CHANNEL_STATUS_UPDATE } diff --git a/objects/auditlog/auditlog.go b/objects/auditlog/auditlog.go index d0f2a11..b078394 100644 --- a/objects/auditlog/auditlog.go +++ b/objects/auditlog/auditlog.go @@ -1,14 +1,22 @@ package auditlog import ( + "github.com/TicketsBot-cloud/gdl/objects/automoderation" + "github.com/TicketsBot-cloud/gdl/objects/channel" "github.com/TicketsBot-cloud/gdl/objects/guild" + "github.com/TicketsBot-cloud/gdl/objects/guild/scheduledevent" "github.com/TicketsBot-cloud/gdl/objects/integration" + "github.com/TicketsBot-cloud/gdl/objects/interaction" "github.com/TicketsBot-cloud/gdl/objects/user" ) type AuditLog struct { - Webhooks []guild.Webhook `json:"webhooks"` - Users []user.User `json:"users"` - Entries []AuditLogEntry `json:"audit_log_entries"` - Integrations []integration.Integration `json:"integrations"` + ApplicationCommands []interaction.ApplicationCommand `json:"application_commands"` + AutoModerationRules []automoderation.Rule `json:"auto_moderation_rules"` + Entries []AuditLogEntry `json:"audit_log_entries"` + GuildScheduledEvents []scheduledevent.GuildScheduledEvent `json:"guild_scheduled_events"` + Integrations []integration.Integration `json:"integrations"` + Threads []channel.Channel `json:"threads"` + Users []user.User `json:"users"` + Webhooks []guild.Webhook `json:"webhooks"` } diff --git a/objects/auditlog/auditlogchange.go b/objects/auditlog/auditlogchange.go index fa3edb5..0dffe82 100644 --- a/objects/auditlog/auditlogchange.go +++ b/objects/auditlog/auditlogchange.go @@ -2,7 +2,7 @@ package auditlog // https://discord.com/developers/docs/resources/audit-log#audit-log-change-object-audit-log-change-key type AuditLogChange struct { - NewValue interface{} `json:"new_value"` - OldValue interface{} `json:"old_value"` + NewValue interface{} `json:"new_value,omitempty"` + OldValue interface{} `json:"old_value,omitempty"` Key ChangeKey `json:"key"` } diff --git a/objects/auditlog/auditlogentry.go b/objects/auditlog/auditlogentry.go index f70e15f..0295741 100644 --- a/objects/auditlog/auditlogentry.go +++ b/objects/auditlog/auditlogentry.go @@ -1,11 +1,11 @@ package auditlog type AuditLogEntry struct { - TargetId uint64 `json:"target_id,string"` - Changes []AuditLogChange `json:"changes"` - UserId uint64 `json:"user_id,string"` + TargetId *string `json:"target_id"` + Changes []AuditLogChange `json:"changes,omitempty"` + UserId *uint64 `json:"user_id,string,omitempty"` Id uint64 `json:"id,string"` ActionType AuditLogEvent `json:"action_type"` - Options AuditEntryInfo `json:"options"` - Reason *string `json:"reason"` + Options *AuditEntryInfo `json:"options,omitempty"` + Reason *string `json:"reason,omitempty"` } diff --git a/objects/auditlog/auditlogevent.go b/objects/auditlog/auditlogevent.go index 546c857..2c0de74 100644 --- a/objects/auditlog/auditlogevent.go +++ b/objects/auditlog/auditlogevent.go @@ -3,39 +3,127 @@ package auditlog type AuditLogEvent int const ( - EventGuildUpdate AuditLogEvent = 1 - EventChannelCreate AuditLogEvent = 10 - EventChannelUpdate AuditLogEvent = 11 - EventChannelDelete AuditLogEvent = 12 - EventChannelOverwriteCreate AuditLogEvent = 13 - EventChannelOverwriteUpdate AuditLogEvent = 14 - EventChannelOverwriteDelete AuditLogEvent = 15 - EventMemberKick AuditLogEvent = 20 - EventMemberPrune AuditLogEvent = 21 - EventMemberBanAdd AuditLogEvent = 22 - EventMemberBanRemove AuditLogEvent = 23 - EventMemberUpdate AuditLogEvent = 24 - EventMemberRoleUpdate AuditLogEvent = 25 - EventMemberMove AuditLogEvent = 26 - EventMemberDisconnect AuditLogEvent = 27 - EventBotAdd AuditLogEvent = 28 - EventRoleCreate AuditLogEvent = 30 - EventRoleUpdate AuditLogEvent = 31 - EventRoleDelete AuditLogEvent = 32 - EventInviteCreate AuditLogEvent = 40 - EventInviteUpdate AuditLogEvent = 41 - EventInviteDelete AuditLogEvent = 42 - EventWebhookCreate AuditLogEvent = 50 - EventWebhookUpdate AuditLogEvent = 51 - EventWebhookDelete AuditLogEvent = 52 - EventEmojiCreate AuditLogEvent = 60 - EventEmojiUpdate AuditLogEvent = 61 - EventEmojiDelete AuditLogEvent = 62 - EventMessageDelete AuditLogEvent = 72 - EventMessageBulkDelete AuditLogEvent = 73 - EventMessagePin AuditLogEvent = 74 - EventMessageUnpin AuditLogEvent = 75 - EventMessageIntegrationCreate AuditLogEvent = 80 - EventMessageIntegrationUpdate AuditLogEvent = 81 - EventMessageIntegrationDelete AuditLogEvent = 82 + AuditLogEventGuildUpdate AuditLogEvent = 1 +) + +const ( + AuditLogEventChannelCreate AuditLogEvent = iota + 10 + AuditLogEventChannelUpdate + AuditLogEventChannelDelete + AuditLogEventChannelOverwriteCreate + AuditLogEventChannelOverwriteUpdate + AuditLogEventChannelOverwriteDelete +) + +const ( + AuditLogEventMemberKick AuditLogEvent = iota + 20 + AuditLogEventMemberPrune + AuditLogEventMemberBanAdd + AuditLogEventMemberBanRemove + AuditLogEventMemberUpdate + AuditLogEventMemberRoleUpdate + AuditLogEventMemberMove + AuditLogEventMemberDisconnect + AuditLogEventBotAdd +) + +const ( + AuditLogEventRoleCreate AuditLogEvent = iota + 30 + AuditLogEventRoleUpdate + AuditLogEventRoleDelete +) + +const ( + AuditLogEventInviteCreate AuditLogEvent = iota + 40 + AuditLogEventInviteUpdate + AuditLogEventInviteDelete +) + +const ( + AuditLogEventWebhookCreate AuditLogEvent = iota + 50 + AuditLogEventWebhookUpdate + AuditLogEventWebhookDelete +) + +const ( + AuditLogEventEmojiCreate AuditLogEvent = iota + 60 + AuditLogEventEmojiUpdate + AuditLogEventEmojiDelete +) + +const ( + AuditLogEventMessageDelete AuditLogEvent = iota + 72 + AuditLogEventMessageBulkDelete + AuditLogEventMessagePin + AuditLogEventMessageUnpin +) + +const ( + AuditLogEventIntegrationCreate AuditLogEvent = iota + 80 + AuditLogEventIntegrationUpdate + AuditLogEventIntegrationDelete + AuditLogEventStageInstanceCreate + AuditLogEventStageInstanceUpdate + AuditLogEventStageInstanceDelete +) + +const ( + AuditLogEventStickerCreate AuditLogEvent = iota + 90 + AuditLogEventStickerUpdate + AuditLogEventStickerDelete +) + +const ( + AuditLogEventGuildScheduledEventCreate AuditLogEvent = iota + 100 + AuditLogEventGuildScheduledEventUpdate + AuditLogEventGuildScheduledEventDelete +) + +const ( + AuditLogEventThreadCreate AuditLogEvent = iota + 110 + AuditLogEventThreadUpdate + AuditLogEventThreadDelete +) + +const ( + AuditLogEventApplicationCommandPermissionUpdate AuditLogEvent = 121 +) + +const ( + AuditLogEventSoundboardSoundCreate AuditLogEvent = iota + 130 + AuditLogEventSoundboardSoundUpdate + AuditLogEventSoundboardSoundDelete +) + +const ( + AuditLogEventAutoModerationRuleCreate AuditLogEvent = iota + 140 + AuditLogEventAutoModerationRuleUpdate + AuditLogEventAutoModerationRuleDelete + AuditLogEventAutoModerationBlockMessage + AuditLogEventAutoModerationFlagToChannel + AuditLogEventAutoModerationUserCommunicationDisabled + AuditLogEventAutoModerationQuarantineUser +) + +const ( + AuditLogEventCreatorMonetizationRequestCreated AuditLogEvent = iota + 150 + AuditLogEventCreatorMonetizationTermsAccepted +) + +const ( + AuditLogEventOnboardingPromptCreate AuditLogEvent = iota + 163 + AuditLogEventOnboardingPromptUpdate + AuditLogEventOnboardingPromptDelete + AuditLogEventOnboardingCreate + AuditLogEventOnboardingUpdate +) + +const ( + AuditLogEventHomeSettingsCreate AuditLogEvent = iota + 190 + AuditLogEventHomeSettingsUpdate +) + +const ( + AuditLogEventVoiceChannelStatusUpdate AuditLogEvent = iota + 192 + AuditLogEventVoiceChannelStatusDelete ) diff --git a/objects/auditlog/changekey.go b/objects/auditlog/changekey.go index 32969e2..14e4176 100644 --- a/objects/auditlog/changekey.go +++ b/objects/auditlog/changekey.go @@ -63,4 +63,37 @@ const ( ChangeKeyEnableEmoticons ChangeKey = "enable_emoticons" ChangeKeyExpireBehaviour ChangeKey = "expire_behaviour" ChangeKeyExpireGracePeriod ChangeKey = "expire_grace_period" + + // guild + ChangeKeyDiscoverySplashHash ChangeKey = "discovery_splash_hash" + ChangeKeyBanner ChangeKey = "banner_hash" + ChangeKeyRulesChannelId ChangeKey = "rules_channel_id" + ChangeKeyPublicUpdatesChannelId ChangeKey = "public_updates_channel_id" + ChangeKeyPreferredLocale ChangeKey = "preferred_locale" + ChangeKeyPremiumProgressBarEnabled ChangeKey = "premium_progress_bar_enabled" + + // channel + ChangeKeyDefaultAutoArchiveDuration ChangeKey = "default_auto_archive_duration" + ChangeKeyForumTags ChangeKey = "available_tags" + ChangeKeyDefaultReactionEmoji ChangeKey = "default_reaction_emoji" + ChangeKeyDefaultSortOrder ChangeKey = "default_sort_order" + ChangeKeyDefaultForumLayout ChangeKey = "default_forum_layout" + + // role + ChangeKeyUnicodeEmoji ChangeKey = "unicode_emoji" + ChangeKeyIconEmoji ChangeKey = "icon_emoji" + + // thread + ChangeKeyArchived ChangeKey = "archived" + ChangeKeyAutoArchiveDuration ChangeKey = "auto_archive_duration" + ChangeKeyLocked ChangeKey = "locked" + + // soundboard + ChangeKeySoundId ChangeKey = "sound_id" + ChangeKeyVolume ChangeKey = "volume" + ChangeKeyEmojiName ChangeKey = "emoji_name" + ChangeKeyEmojiId ChangeKey = "emoji_id" + + // command permissions + ChangeKeyCommandId ChangeKey = "command_id" ) diff --git a/objects/auditlog/entitytype.go b/objects/auditlog/entitytype.go index 143249a..1ca5650 100644 --- a/objects/auditlog/entitytype.go +++ b/objects/auditlog/entitytype.go @@ -3,6 +3,6 @@ package auditlog type EntityType string const ( - EntityTypeMember EntityType = "member" - EntityTypeRole EntityType = "role" + EntityTypeRole EntityType = "0" + EntityTypeMember EntityType = "1" ) diff --git a/objects/automoderation/automoderation.go b/objects/automoderation/automoderation.go new file mode 100644 index 0000000..cad9030 --- /dev/null +++ b/objects/automoderation/automoderation.go @@ -0,0 +1,72 @@ +package automoderation + +import "github.com/TicketsBot-cloud/gdl/utils" + +type EventType int + +const ( + EventTypeMessageSend EventType = iota + 1 + EventTypeMemberUpdate +) + +type TriggerType int + +const ( + TriggerTypeKeyword TriggerType = iota + 1 + _ + TriggerTypeSpam + TriggerTypeKeywordPreset + TriggerTypeMentionSpam + TriggerTypeMemberProfile +) + +type KeywordPresetType int + +const ( + KeywordPresetTypeProfanity KeywordPresetType = iota + 1 + KeywordPresetTypeSexualContent + KeywordPresetTypeSlurs +) + +type ActionType int + +const ( + ActionTypeBlockMessage ActionType = iota + 1 + ActionTypeSendAlertMessage + ActionTypeTimeout + ActionTypeBlockMemberInteraction +) + +type TriggerMetadata struct { + KeywordFilter []string `json:"keyword_filter"` + RegexPatterns []string `json:"regex_patterns"` + Presets []KeywordPresetType `json:"presets"` + AllowList []string `json:"allow_list"` + MentionTotalLimit int `json:"mention_total_limit"` + MentionRaidProtectionEnabled bool `json:"mention_raid_protection_enabled"` +} + +type ActionMetadata struct { + ChannelId *uint64 `json:"channel_id,string,omitempty"` + DurationSeconds *int `json:"duration_seconds,omitempty"` + CustomMessage *string `json:"custom_message,omitempty"` +} + +type Action struct { + Type ActionType `json:"type"` + Metadata *ActionMetadata `json:"metadata,omitempty"` +} + +type Rule struct { + Id uint64 `json:"id,string"` + GuildId uint64 `json:"guild_id,string"` + Name string `json:"name"` + CreatorId uint64 `json:"creator_id,string"` + EventType EventType `json:"event_type"` + TriggerType TriggerType `json:"trigger_type"` + TriggerMetadata TriggerMetadata `json:"trigger_metadata"` + Actions []Action `json:"actions"` + Enabled bool `json:"enabled"` + ExemptRoles utils.Uint64StringSlice `json:"exempt_roles"` + ExemptChannels utils.Uint64StringSlice `json:"exempt_channels"` +} diff --git a/objects/channel/attachment.go b/objects/channel/attachment.go index 14aa849..dd90faa 100644 --- a/objects/channel/attachment.go +++ b/objects/channel/attachment.go @@ -1,11 +1,40 @@ package channel +import ( + "encoding/json" + "time" + + "github.com/TicketsBot-cloud/gdl/objects/user" +) + +type AttachmentFlag int + +const ( + AttachmentFlagIsClip AttachmentFlag = 1 << 0 + AttachmentFlagIsThumbnail AttachmentFlag = 1 << 1 + AttachmentFlagIsRemix AttachmentFlag = 1 << 2 + AttachmentFlagIsSpoiler AttachmentFlag = 1 << 3 + AttachmentFlagIsAnimated AttachmentFlag = 1 << 5 +) + type Attachment struct { - Id uint64 `json:",string"` - Filename string `json:"filename"` - Size int `json:"size"` - Url string `json:"url"` - ProxyUrl string `json:"proxy_url"` - Height int `json:"height"` - Width int `json:"width"` + Id uint64 `json:"id,string"` + Filename string `json:"filename"` + Title *string `json:"title,omitempty"` + Description *string `json:"description,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size int `json:"size"` + Url string `json:"url"` + ProxyUrl string `json:"proxy_url"` + Height *int `json:"height,omitempty"` + Width *int `json:"width,omitempty"` + Placeholder *string `json:"placeholder,omitempty"` + PlaceholderVersion *int `json:"placeholder_version,omitempty"` + Ephemeral *bool `json:"ephemeral,omitempty"` + DurationSecs *float64 `json:"duration_secs,omitempty"` + Waveform *string `json:"waveform,omitempty"` + Flags *AttachmentFlag `json:"flags,omitempty"` + ClipParticipants []user.User `json:"clip_participants,omitempty"` + ClipCreatedAt *time.Time `json:"clip_created_at,omitempty"` + Application json.RawMessage `json:"application,omitempty"` } diff --git a/objects/channel/cachedchannel.go b/objects/channel/cachedchannel.go index d8d3022..f540b21 100644 --- a/objects/channel/cachedchannel.go +++ b/objects/channel/cachedchannel.go @@ -9,27 +9,27 @@ import ( type CachedChannel struct { GuildId uint64 `json:"-"` Type ChannelType `json:"type"` - Position int `json:"position"` + Position *int `json:"position,omitempty"` PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - Name string `json:"name"` - Topic string `json:"topic"` + Name *string `json:"name,omitempty"` + Topic *string `json:"topic,omitempty"` Nsfw bool `json:"nsfw"` LastMessageId objects.NullableSnowflake `json:"last_message_id"` Bitrate int `json:"bitrate"` UserLimit int `json:"user_limit"` RateLimitPerUser int `json:"rate_limit_per_user"` - Icon string `json:"icon"` - OwnerId uint64 `json:"owner_id,string"` - ApplicationId uint64 `json:"application_id"` + Icon *string `json:"icon,omitempty"` + OwnerId *uint64 `json:"owner_id,string,omitempty"` + ApplicationId *uint64 `json:"application_id,string,omitempty"` ParentId objects.NullableSnowflake `json:"parent_id,omitempty"` - LastPinTimestamp time.Time `json:"last_pin_timestamp"` + LastPinTimestamp *time.Time `json:"last_pin_timestamp,omitempty"` } func (c *CachedChannel) ToChannel(channelId, guildId uint64) Channel { return Channel{ Id: channelId, Type: c.Type, - GuildId: guildId, + GuildId: &guildId, Position: c.Position, PermissionOverwrites: c.PermissionOverwrites, Name: c.Name, @@ -39,7 +39,6 @@ func (c *CachedChannel) ToChannel(channelId, guildId uint64) Channel { Bitrate: c.Bitrate, UserLimit: c.UserLimit, RateLimitPerUser: c.RateLimitPerUser, - Recipients: nil, Icon: c.Icon, OwnerId: c.OwnerId, ApplicationId: c.ApplicationId, diff --git a/objects/channel/channel.go b/objects/channel/channel.go index 57d249c..74a054b 100644 --- a/objects/channel/channel.go +++ b/objects/channel/channel.go @@ -6,33 +6,45 @@ import ( "github.com/TicketsBot-cloud/gdl/objects" "github.com/TicketsBot-cloud/gdl/objects/user" + "github.com/TicketsBot-cloud/gdl/utils" ) type Channel struct { - Id uint64 `json:"id,string"` - Type ChannelType `json:"type"` - GuildId uint64 `json:"guild_id,string"` - Position int `json:"position"` - PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - Name string `json:"name"` - Topic string `json:"topic"` - Nsfw bool `json:"nsfw"` - LastMessageId objects.NullableSnowflake `json:"last_message_id"` - Bitrate int `json:"bitrate"` - UserLimit int `json:"user_limit"` - RateLimitPerUser int `json:"rate_limit_per_user"` - Recipients []user.User `json:"recipients"` - Icon string `json:"icon"` - OwnerId uint64 `json:"owner_id,string"` // Owner of a group DM - ApplicationId uint64 `json:"application_id,string"` - ParentId objects.NullableSnowflake `json:"parent_id,omitempty"` - LastPinTimestamp time.Time `json:"last_pin_timestamp"` - RtcRegion *string `json:"rtc_region"` - VideoQualityMode VideoQualityMode `json:"video_quality_mode"` - MessageCount uint64 `json:"message_count"` - MemberCount uint64 `json:"member_count"` - ThreadMetadata *ThreadMetadata `json:"thread_metadata,omitempty"` - Member ThreadMember `json:"member"` + Id uint64 `json:"id,string"` + Type ChannelType `json:"type"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + Position *int `json:"position,omitempty"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites,omitempty"` + Name *string `json:"name,omitempty"` + Topic *string `json:"topic,omitempty"` + Nsfw bool `json:"nsfw,omitempty"` + LastMessageId objects.NullableSnowflake `json:"last_message_id"` + Bitrate int `json:"bitrate,omitempty"` + UserLimit int `json:"user_limit,omitempty"` + RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` + Recipients []user.User `json:"recipients,omitempty"` + Icon *string `json:"icon,omitempty"` + OwnerId *uint64 `json:"owner_id,string,omitempty"` + ApplicationId *uint64 `json:"application_id,string,omitempty"` + Managed *bool `json:"managed,omitempty"` + ParentId objects.NullableSnowflake `json:"parent_id,omitempty"` + LastPinTimestamp *time.Time `json:"last_pin_timestamp,omitempty"` + RtcRegion *string `json:"rtc_region,omitempty"` + VideoQualityMode VideoQualityMode `json:"video_quality_mode,omitempty"` + MessageCount int `json:"message_count,omitempty"` + MemberCount int `json:"member_count,omitempty"` + ThreadMetadata *ThreadMetadata `json:"thread_metadata,omitempty"` + Member *ThreadMember `json:"member,omitempty"` + DefaultAutoArchiveDuration *int `json:"default_auto_archive_duration,omitempty"` + Permissions *string `json:"permissions,omitempty"` + Flags *int `json:"flags,omitempty"` + TotalMessageSent *int `json:"total_message_sent,omitempty"` + AvailableTags []ForumTag `json:"available_tags,omitempty"` + AppliedTags utils.Uint64StringSlice `json:"applied_tags,omitempty"` + DefaultReactionEmoji *DefaultReaction `json:"default_reaction_emoji,omitempty"` + DefaultThreadRateLimitPerUser *int `json:"default_thread_rate_limit_per_user,omitempty"` + DefaultSortOrder *int `json:"default_sort_order,omitempty"` + DefaultForumLayout *int `json:"default_forum_layout,omitempty"` } func (c *Channel) Mention() string { @@ -40,8 +52,13 @@ func (c *Channel) Mention() string { } func (c *Channel) ToCachedChannel() CachedChannel { + var guildId uint64 + if c.GuildId != nil { + guildId = *c.GuildId + } + return CachedChannel{ - GuildId: c.GuildId, + GuildId: guildId, Type: c.Type, Position: c.Position, PermissionOverwrites: c.PermissionOverwrites, @@ -62,15 +79,14 @@ func (c *Channel) ToCachedChannel() CachedChannel { func (c *Channel) ToPartialChannel() PartialChannel { return PartialChannel{ - Id: c.Id, - Type: c.Type, - GuildId: c.GuildId, - Position: c.Position, - Name: c.Name, - Topic: c.Topic, - Nsfw: c.Nsfw, - LastMessageId: c.LastMessageId, - ParentId: c.ParentId, - LastPinTimestamp: c.LastPinTimestamp, + Id: c.Id, + Type: c.Type, + Name: c.Name, } } + +type ChannelInfoEntry struct { + Id uint64 `json:"id,string"` + Status *string `json:"status,omitempty"` + VoiceStartTime *int64 `json:"voice_start_time,omitempty"` +} diff --git a/objects/channel/channeltype.go b/objects/channel/channeltype.go index 82d6ec6..675428f 100644 --- a/objects/channel/channeltype.go +++ b/objects/channel/channeltype.go @@ -8,12 +8,15 @@ const ( ChannelTypeGuildVoice ChannelTypeGroupDM ChannelTypeGuildCategory - ChannelTypeGuildNews - ChannelTypeGuildStore - ChannelTypeGuildNewsThread ChannelType = iota + 3 - ChannelTypeGuildPublicThread - ChannelTypeGuildPrivateThread + ChannelTypeGuildAnnouncement +) + +const ( + ChannelTypeAnnouncementThread ChannelType = iota + 10 + ChannelTypePublicThread + ChannelTypePrivateThread ChannelTypeGuildStageVoice ChannelTypeGuildDirectory ChannelTypeGuildForum + ChannelTypeGuildMedia ) diff --git a/objects/channel/embed/embed.go b/objects/channel/embed/embed.go index 5f42336..c3eb410 100644 --- a/objects/channel/embed/embed.go +++ b/objects/channel/embed/embed.go @@ -3,11 +3,12 @@ package embed import "time" type Embed struct { - Title string `json:"title,omitempty"` - Description string `json:"description,omitempty"` - Url string `json:"url,omitempty"` - Timestamp *time.Time `json:"timestamp,omitempty"` - Color int `json:"color,omitempty"` + Title string `json:"title,omitempty"` + Type *string `json:"type,omitempty"` + Description string `json:"description,omitempty"` + Url string `json:"url,omitempty"` + Timestamp *time.Time `json:"timestamp,omitempty"` + Color int `json:"color,omitempty"` Footer *EmbedFooter `json:"footer,omitempty"` Image *EmbedImage `json:"image,omitempty"` Thumbnail *EmbedThumbnail `json:"thumbnail,omitempty"` diff --git a/objects/channel/embed/embedimage.go b/objects/channel/embed/embedimage.go index 0c9b6a3..72ff2ea 100644 --- a/objects/channel/embed/embedimage.go +++ b/objects/channel/embed/embedimage.go @@ -2,7 +2,7 @@ package embed type EmbedImage struct { Url string `json:"url"` - ProxyUrl string `json:"proxy_url"` - Height int `json:"height"` - Width int `json:"width"` + ProxyUrl string `json:"proxy_url,omitempty"` + Height int `json:"height,omitempty"` + Width int `json:"width,omitempty"` } diff --git a/objects/channel/embed/embedprovider.go b/objects/channel/embed/embedprovider.go index 6e386ff..d42c0eb 100644 --- a/objects/channel/embed/embedprovider.go +++ b/objects/channel/embed/embedprovider.go @@ -1,6 +1,6 @@ package embed type EmbedProvider struct { - Name string `json:"name"` - Url string `json:"name"` + Name string `json:"name,omitempty"` + Url string `json:"url,omitempty"` } diff --git a/objects/channel/embed/embedthumbnail.go b/objects/channel/embed/embedthumbnail.go index bcb9c40..c487a24 100644 --- a/objects/channel/embed/embedthumbnail.go +++ b/objects/channel/embed/embedthumbnail.go @@ -2,7 +2,7 @@ package embed type EmbedThumbnail struct { Url string `json:"url"` - ProxyUrl string `json:"proxy_url"` - Height int `json:"height"` - Width int `json:"width"` + ProxyUrl string `json:"proxy_url,omitempty"` + Height int `json:"height,omitempty"` + Width int `json:"width,omitempty"` } diff --git a/objects/channel/embed/embedvideo.go b/objects/channel/embed/embedvideo.go index c67f805..973a544 100644 --- a/objects/channel/embed/embedvideo.go +++ b/objects/channel/embed/embedvideo.go @@ -1,7 +1,8 @@ package embed type EmbedVideo struct { - Url string `json:"url"` - Height int `json:"height"` - Width int `json:"width"` + Url string `json:"url,omitempty"` + ProxyUrl string `json:"proxy_url,omitempty"` + Height int `json:"height,omitempty"` + Width int `json:"width,omitempty"` } diff --git a/objects/channel/forumtag.go b/objects/channel/forumtag.go new file mode 100644 index 0000000..2186f60 --- /dev/null +++ b/objects/channel/forumtag.go @@ -0,0 +1,14 @@ +package channel + +type ForumTag struct { + Id uint64 `json:"id,string"` + Name string `json:"name"` + Moderated bool `json:"moderated"` + EmojiId *uint64 `json:"emoji_id,string,omitempty"` + EmojiName *string `json:"emoji_name,omitempty"` +} + +type DefaultReaction struct { + EmojiId *uint64 `json:"emoji_id,string,omitempty"` + EmojiName *string `json:"emoji_name,omitempty"` +} diff --git a/objects/channel/message/allowedmention.go b/objects/channel/message/allowedmention.go index c643a84..e97bf4c 100644 --- a/objects/channel/message/allowedmention.go +++ b/objects/channel/message/allowedmention.go @@ -11,5 +11,5 @@ type AllowedMention struct { // Helper var MentionEveryone = AllowedMention{ - Parse: []AllowedMentionType{EVERYONE}, + Parse: []AllowedMentionType{AllowedMentionTypeEveryone}, } diff --git a/objects/channel/message/allowedmentiontype.go b/objects/channel/message/allowedmentiontype.go index 74d0128..528e615 100644 --- a/objects/channel/message/allowedmentiontype.go +++ b/objects/channel/message/allowedmentiontype.go @@ -2,8 +2,8 @@ package message type AllowedMentionType string -const( - EVERYONE AllowedMentionType = "everyone" - USERS AllowedMentionType = "users" - ROLES AllowedMentionType = "roles" +const ( + AllowedMentionTypeRoles AllowedMentionType = "roles" + AllowedMentionTypeUsers AllowedMentionType = "users" + AllowedMentionTypeEveryone AllowedMentionType = "everyone" ) diff --git a/objects/channel/message/message.go b/objects/channel/message/message.go index 021b6a6..8977d33 100644 --- a/objects/channel/message/message.go +++ b/objects/channel/message/message.go @@ -1,45 +1,77 @@ package message import ( + "encoding/json" "regexp" "strconv" "time" "github.com/TicketsBot-cloud/gdl/objects/channel" "github.com/TicketsBot-cloud/gdl/objects/channel/embed" + "github.com/TicketsBot-cloud/gdl/objects/guild/sticker" "github.com/TicketsBot-cloud/gdl/objects/interaction/component" "github.com/TicketsBot-cloud/gdl/objects/member" "github.com/TicketsBot-cloud/gdl/objects/user" "github.com/TicketsBot-cloud/gdl/utils" ) +type BaseThemeType int + +const ( + BaseThemeUnset BaseThemeType = 0 + BaseThemeDark BaseThemeType = 1 + BaseThemeLight BaseThemeType = 2 + BaseThemeDarker BaseThemeType = 3 + BaseThemeMidnight BaseThemeType = 4 +) + +type SharedClientTheme struct { + Colors []string `json:"colors"` + GradientAngle int `json:"gradient_angle"` + BaseMix int `json:"base_mix"` + BaseTheme *BaseThemeType `json:"base_theme,omitempty"` +} + type Message struct { - Id uint64 `json:"id,string"` - ChannelId uint64 `json:"channel_id,string"` - GuildId uint64 `json:"guild_id,string"` - Author user.User `json:"author"` - Member member.Member `json:"member"` - Content string `json:"content"` - Timestamp time.Time `json:"timestamp"` - EditedTimestamp *time.Time `json:"edited_timestamp,omitempty"` - Tts bool `json:"tts"` - MentionEveryone bool `json:"mention_everyone"` - Mentions []MessageMentionedUser `json:"mentions,omitempty"` // The user objects in the mentions array will only have the partial member field present in MESSAGE_CREATE and MESSAGE_UPDATE events from text-based guild channels - MentionRoles utils.Uint64StringSlice `json:"mention_roles"` - VisibleMentionedChannels []ChannelMention `json:"mention_channels,omitempty"` // Not all channel mentions in a message will appear in mention_channels. Only textual channels that are visible to everyone in a lurkable guild will ever be included. Only crossposted messages (via Channel Following) currently include mention_channels at all. If no mentions in the message meet these requirements, this field will not be sent. - Attachments []channel.Attachment `json:"attachments,omitempty"` - Embeds []embed.Embed `json:"embeds,omitempty"` - Reactions []Reaction `json:"reactions,omitempty"` - Nonce interface{} `json:"nonce,omitempty"` - Pinned bool `json:"pinned"` - WebhookId uint64 `json:"webhook_id,string"` // if the message is generated by a webhook, this is the webhook's id - Type MessageType `json:"type"` - Activity MessageActivity `json:"activity"` - Application MessageApplication `json:"application"` - MessageReference MessageReference `json:"message_reference"` // reference data sent with crossposted messages - Flags int `json:"flags"` - ReferencedMessage *MessageReference `json:"referenced_message,omitempty"` - Components []component.Component `json:"components,omitempty"` + Id uint64 `json:"id,string"` + ChannelId uint64 `json:"channel_id,string"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + Author user.User `json:"author"` + Member *member.Member `json:"member,omitempty"` + Content string `json:"content"` + Timestamp time.Time `json:"timestamp"` + EditedTimestamp *time.Time `json:"edited_timestamp,omitempty"` + Tts bool `json:"tts"` + MentionEveryone bool `json:"mention_everyone"` + Mentions []MessageMentionedUser `json:"mentions,omitempty"` // The user objects in the mentions array will only have the partial member field present in MESSAGE_CREATE and MESSAGE_UPDATE events from text-based guild channels + MentionRoles utils.Uint64StringSlice `json:"mention_roles"` + MentionChannels []ChannelMention `json:"mention_channels,omitempty"` // Not all channel mentions in a message will appear in mention_channels. Only textual channels that are visible to everyone in a lurkable guild will ever be included. + Attachments []channel.Attachment `json:"attachments,omitempty"` + Embeds []embed.Embed `json:"embeds,omitempty"` + Reactions []Reaction `json:"reactions,omitempty"` + Nonce interface{} `json:"nonce,omitempty"` + Pinned bool `json:"pinned"` + WebhookId *uint64 `json:"webhook_id,string,omitempty"` + Type MessageType `json:"type"` + Activity *MessageActivity `json:"activity,omitempty"` + Application *MessageApplication `json:"application,omitempty"` + ApplicationId *uint64 `json:"application_id,string,omitempty"` + Flags MessageFlag `json:"flags,omitempty"` + MessageReference *MessageReference `json:"message_reference,omitempty"` + MessageSnapshots []MessageSnapshot `json:"message_snapshots,omitempty"` + ReferencedMessage *Message `json:"referenced_message,omitempty"` + InteractionMetadata *MessageInteractionMetadata `json:"interaction_metadata,omitempty"` + Interaction *MessageInteraction `json:"interaction,omitempty"` // Deprecated: use InteractionMetadata + Thread *channel.Channel `json:"thread,omitempty"` + Components []component.Component `json:"components,omitempty"` + StickerItems []StickerItem `json:"sticker_items,omitempty"` + Stickers []sticker.Sticker `json:"stickers,omitempty"` + Position *int `json:"position,omitempty"` + RoleSubscriptionData *RoleSubscriptionData `json:"role_subscription_data,omitempty"` + Poll *Poll `json:"poll,omitempty"` + Call *MessageCall `json:"call,omitempty"` + Resolved json.RawMessage `json:"resolved,omitempty"` + SharedClientTheme *SharedClientTheme `json:"shared_client_theme,omitempty"` } var channelMentionRegex = regexp.MustCompile(`<#(\d+)>`) diff --git a/objects/channel/message/messageactivity.go b/objects/channel/message/messageactivity.go index e83cb0f..8a41d98 100644 --- a/objects/channel/message/messageactivity.go +++ b/objects/channel/message/messageactivity.go @@ -2,5 +2,5 @@ package message type MessageActivity struct { Type MessageActivityType `json:"type"` - PartyId string `json:"party_id"` + PartyId *string `json:"party_id,omitempty"` } diff --git a/objects/channel/message/messageactivitytype.go b/objects/channel/message/messageactivitytype.go index d1645b0..b42dd0b 100644 --- a/objects/channel/message/messageactivitytype.go +++ b/objects/channel/message/messageactivitytype.go @@ -3,8 +3,9 @@ package message type MessageActivityType int const ( - MessageActivityJoin MessageActivityType = iota - MessageActivitySpectate - MessageActivityListen - MessageActivityJoinRequest + MessageActivityTypeJoin MessageActivityType = iota + 1 + MessageActivityTypeSpectate + MessageActivityTypeListen + _ + MessageActivityTypeJoinRequest ) diff --git a/objects/channel/message/messageapplication.go b/objects/channel/message/messageapplication.go index 6ebb857..84836d4 100644 --- a/objects/channel/message/messageapplication.go +++ b/objects/channel/message/messageapplication.go @@ -1,9 +1,9 @@ package message type MessageApplication struct { - Id uint64 `json:",string"` - CoverImage string - Description string - Icon string - Name string + Id uint64 `json:"id,string"` + CoverImage *string `json:"cover_image,omitempty"` + Description string `json:"description"` + Icon *string `json:"icon,omitempty"` + Name string `json:"name"` } diff --git a/objects/channel/message/messagecall.go b/objects/channel/message/messagecall.go new file mode 100644 index 0000000..116bd79 --- /dev/null +++ b/objects/channel/message/messagecall.go @@ -0,0 +1,12 @@ +package message + +import ( + "time" + + "github.com/TicketsBot-cloud/gdl/utils" +) + +type MessageCall struct { + Participants utils.Uint64StringSlice `json:"participants"` + EndedTimestamp *time.Time `json:"ended_timestamp,omitempty"` +} diff --git a/objects/channel/message/messageflags.go b/objects/channel/message/messageflags.go index dc5601f..1c47749 100644 --- a/objects/channel/message/messageflags.go +++ b/objects/channel/message/messageflags.go @@ -5,13 +5,20 @@ type MessageFlag uint const ( FlagCrossposted MessageFlag = 1 << iota FlagIsCrosspost - FlagSupressEmbeds + FlagSuppressEmbeds FlagSourceMessageDeleted FlagUrgent - _ // 1 << 5 not documented + FlagHasThread FlagEphemeral FlagLoading - FlagComponentsV2 MessageFlag = 1 << 15 + FlagFailedToMentionSomeRolesInThread +) + +const ( + FlagSuppressNotifications MessageFlag = 1 << (iota + 12) + FlagIsVoiceMessage + FlagHasSnapshot + FlagIsComponentsV2 ) func SumFlags(flags ...MessageFlag) (sum uint) { diff --git a/objects/channel/message/messageinteraction.go b/objects/channel/message/messageinteraction.go new file mode 100644 index 0000000..7e91152 --- /dev/null +++ b/objects/channel/message/messageinteraction.go @@ -0,0 +1,27 @@ +package message + +import ( + "github.com/TicketsBot-cloud/gdl/objects/member" + "github.com/TicketsBot-cloud/gdl/objects/user" +) + +// MessageInteraction is deprecated in favour of InteractionMetadata +type MessageInteraction struct { + Id uint64 `json:"id,string"` + Type int `json:"type"` + Name string `json:"name"` + User user.User `json:"user"` + Member *member.Member `json:"member,omitempty"` +} + +type MessageInteractionMetadata struct { + Id uint64 `json:"id,string"` + Type int `json:"type"` + User user.User `json:"user"` + AuthorizingIntegrationOwners map[string]string `json:"authorizing_integration_owners"` + OriginalResponseMessageId *uint64 `json:"original_response_message_id,string,omitempty"` + TargetUser *user.User `json:"target_user,omitempty"` + TargetMessageId *uint64 `json:"target_message_id,string,omitempty"` + InteractedMessageId *uint64 `json:"interacted_message_id,string,omitempty"` + TriggeringInteractionMetadata *MessageInteractionMetadata `json:"triggering_interaction_metadata,omitempty"` +} diff --git a/objects/channel/message/messagementioneduser.go b/objects/channel/message/messagementioneduser.go index 43c7b95..6af5d5d 100644 --- a/objects/channel/message/messagementioneduser.go +++ b/objects/channel/message/messagementioneduser.go @@ -8,5 +8,5 @@ import ( // Mentions is an array of users with partial member type MessageMentionedUser struct { user.User - Member member.Member + Member *member.Member `json:"member,omitempty"` } diff --git a/objects/channel/message/messagereference.go b/objects/channel/message/messagereference.go index 091323d..4d1b471 100644 --- a/objects/channel/message/messagereference.go +++ b/objects/channel/message/messagereference.go @@ -1,8 +1,9 @@ package message type MessageReference struct { - MessageId uint64 `json:"message_id,string"` - ChannelId uint64 `json:"channel_id,string"` - GuildId uint64 `json:"guild_id,string"` - FailIfNotExists bool `json:"fail_if_not_exists"` + Type *int `json:"type,omitempty"` + MessageId *uint64 `json:"message_id,string,omitempty"` + ChannelId *uint64 `json:"channel_id,string,omitempty"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + FailIfNotExists *bool `json:"fail_if_not_exists,omitempty"` } diff --git a/objects/channel/message/messagesnapshot.go b/objects/channel/message/messagesnapshot.go new file mode 100644 index 0000000..0226722 --- /dev/null +++ b/objects/channel/message/messagesnapshot.go @@ -0,0 +1,5 @@ +package message + +type MessageSnapshot struct { + Message Message `json:"message"` +} diff --git a/objects/channel/message/messagetype.go b/objects/channel/message/messagetype.go index 6de99ba..363d438 100644 --- a/objects/channel/message/messagetype.go +++ b/objects/channel/message/messagetype.go @@ -16,7 +16,10 @@ const ( MessageTypeUserPremiumGuildSubscriptionTier2 MessageTypeUserPremiumGuildSubscriptionTier3 MessageTypeChannelFollowAdd - MessageTypeGuildDiscoveryDisqualified +) + +const ( + MessageTypeGuildDiscoveryDisqualified MessageType = iota + 14 MessageTypeGuildDiscoveryRequalified MessageTypeGuildDiscoveryGracePeriodInitialWarning MessageTypeGuildDiscoveryGracePeriodFinalWarning @@ -25,4 +28,31 @@ const ( MessageTypeApplicationCommand MessageTypeThreadStarterMessage MessageTypeGuildInviteReminder + MessageTypeContextMenuCommand + MessageTypeAutoModerationAction + MessageTypeRoleSubscriptionPurchase + MessageTypeInteractionPremiumUpsell + MessageTypeStageStart + MessageTypeStageEnd + MessageTypeStageSpeaker +) + +const ( + MessageTypeStageTopic MessageType = iota + 31 + MessageTypeGuildApplicationPremiumSubscription +) + +const ( + MessageTypeGuildIncidentAlertModeEnabled MessageType = iota + 36 + MessageTypeGuildIncidentAlertModeDisabled + MessageTypeGuildIncidentReportRaid + MessageTypeGuildIncidentReportFalseAlarm +) + +const ( + MessageTypePurchaseNotification MessageType = iota + 44 +) + +const ( + MessageTypePollResult MessageType = iota + 46 ) diff --git a/objects/channel/message/poll.go b/objects/channel/message/poll.go new file mode 100644 index 0000000..7aba905 --- /dev/null +++ b/objects/channel/message/poll.go @@ -0,0 +1,37 @@ +package message + +import ( + "time" + + "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" +) + +type Poll struct { + Question PollMedia `json:"question"` + Answers []PollAnswer `json:"answers"` + Expiry *time.Time `json:"expiry"` + AllowMultiselect bool `json:"allow_multiselect"` + LayoutType int `json:"layout_type"` + Results *PollResults `json:"results,omitempty"` +} + +type PollMedia struct { + Text *string `json:"text,omitempty"` + Emoji *emoji.Emoji `json:"emoji,omitempty"` +} + +type PollAnswer struct { + AnswerId int `json:"answer_id,omitempty"` + PollMedia PollMedia `json:"poll_media"` +} + +type PollResults struct { + IsFinalized bool `json:"is_finalized"` + AnswerCounts []PollAnswerCount `json:"answer_counts"` +} + +type PollAnswerCount struct { + Id int `json:"id"` + Count int `json:"count"` + MeVoted bool `json:"me_voted"` +} diff --git a/objects/channel/message/reaction.go b/objects/channel/message/reaction.go index 8a9c76d..74f4172 100644 --- a/objects/channel/message/reaction.go +++ b/objects/channel/message/reaction.go @@ -2,8 +2,16 @@ package message import "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" +type ReactionCountDetails struct { + Burst int `json:"burst"` + Normal int `json:"normal"` +} + type Reaction struct { - Count int - Me bool - Emoji emoji.Emoji + Count int `json:"count"` + CountDetails ReactionCountDetails `json:"count_details"` + Me bool `json:"me"` + MeBurst bool `json:"me_burst"` + Emoji emoji.Emoji `json:"emoji"` + BurstColors []string `json:"burst_colors"` } diff --git a/objects/channel/message/rolesubscriptiondata.go b/objects/channel/message/rolesubscriptiondata.go new file mode 100644 index 0000000..e8c444b --- /dev/null +++ b/objects/channel/message/rolesubscriptiondata.go @@ -0,0 +1,8 @@ +package message + +type RoleSubscriptionData struct { + RoleSubscriptionListingId uint64 `json:"role_subscription_listing_id,string"` + TierName string `json:"tier_name"` + TotalMonthsSubscribed int `json:"total_months_subscribed"` + IsRenewal bool `json:"is_renewal"` +} diff --git a/objects/channel/message/stickeritem.go b/objects/channel/message/stickeritem.go new file mode 100644 index 0000000..a48c9f8 --- /dev/null +++ b/objects/channel/message/stickeritem.go @@ -0,0 +1,9 @@ +package message + +import "github.com/TicketsBot-cloud/gdl/objects/guild/sticker" + +type StickerItem struct { + Id uint64 `json:"id,string"` + Name string `json:"name"` + FormatType sticker.StickerFormatType `json:"format_type"` +} diff --git a/objects/channel/message/timestamp.go b/objects/channel/message/timestamp.go index b091c42..48c44ad 100644 --- a/objects/channel/message/timestamp.go +++ b/objects/channel/message/timestamp.go @@ -8,7 +8,7 @@ import ( type TimestampStyle string const ( - TimestampStyleShortTime TimestampStyle = "s" + TimestampStyleShortTime TimestampStyle = "t" TimestampStyleLongTime TimestampStyle = "T" TimestampStyleShortDate TimestampStyle = "d" TimestampStyleLongDate TimestampStyle = "D" @@ -23,4 +23,4 @@ func BuildTimestamp(timestamp time.Time, style TimestampStyle) string { func BuildTimestampFromUnixSecs(timestamp int64, style TimestampStyle) string { return fmt.Sprintf("", timestamp, style) -} \ No newline at end of file +} diff --git a/objects/channel/partialchannel.go b/objects/channel/partialchannel.go index 365a674..2bd10fc 100644 --- a/objects/channel/partialchannel.go +++ b/objects/channel/partialchannel.go @@ -1,20 +1,7 @@ package channel -import ( - "time" - - "github.com/TicketsBot-cloud/gdl/objects" -) - type PartialChannel struct { - Id uint64 `json:"id,string"` - Type ChannelType `json:"type"` - GuildId uint64 `json:"guild_id,string"` - Position int `json:"position"` - Name string `json:"name"` - Topic string `json:"topic"` - Nsfw bool `json:"nsfw"` - LastMessageId objects.NullableSnowflake `json:"last_message_id"` - ParentId objects.NullableSnowflake `json:"parent_id,omitempty"` - LastPinTimestamp time.Time `json:"last_pin_timestamp"` + Id uint64 `json:"id,string"` + Type ChannelType `json:"type"` + Name *string `json:"name,omitempty"` } diff --git a/objects/channel/permissionoverwrite.go b/objects/channel/permissionoverwrite.go index 41dc7ba..be80778 100644 --- a/objects/channel/permissionoverwrite.go +++ b/objects/channel/permissionoverwrite.go @@ -1,7 +1,7 @@ package channel type PermissionOverwrite struct { - Id uint64 `json:"id,string,omitempty"` + Id uint64 `json:"id,string"` Type PermissionOverwriteType `json:"type"` Allow uint64 `json:"allow,string"` Deny uint64 `json:"deny,string"` diff --git a/objects/channel/permissionoverwritetype.go b/objects/channel/permissionoverwritetype.go index c6a4e3a..8d700dc 100644 --- a/objects/channel/permissionoverwritetype.go +++ b/objects/channel/permissionoverwritetype.go @@ -3,6 +3,6 @@ package channel type PermissionOverwriteType int const ( - PermissionTypeRole PermissionOverwriteType = iota - PermissionTypeMember + PermissionOverwriteTypeRole PermissionOverwriteType = iota + PermissionOverwriteTypeMember ) diff --git a/objects/channel/thread.go b/objects/channel/thread.go index 48f68ee..63b1a39 100644 --- a/objects/channel/thread.go +++ b/objects/channel/thread.go @@ -1,6 +1,10 @@ package channel -import "time" +import ( + "time" + + "github.com/TicketsBot-cloud/gdl/objects/member" +) type ThreadMetadata struct { Archived bool `json:"archived"` @@ -12,8 +16,9 @@ type ThreadMetadata struct { } type ThreadMember struct { - ThreadId uint64 `json:"id,string"` - UserId uint64 `json:"user_id,string"` - JoinTimestamp time.Time `json:"join_timestamp"` - Flags uint `json:"flags"` + ThreadId *uint64 `json:"id,string,omitempty"` + UserId *uint64 `json:"user_id,string,omitempty"` + JoinTimestamp time.Time `json:"join_timestamp"` + Flags uint `json:"flags"` + Member *member.Member `json:"member,omitempty"` } diff --git a/objects/entitlement/entitlement.go b/objects/entitlement/entitlement.go index 1b889ba..c56b300 100644 --- a/objects/entitlement/entitlement.go +++ b/objects/entitlement/entitlement.go @@ -18,12 +18,12 @@ type Entitlement struct { type EntitlementType uint16 const ( - TypePurchase EntitlementType = iota + 1 - TypePremiumSubscription - TypeDeveloperGift - TypeTestModePurchase - TypeFreePurchase - TypeUserGift - TypePremiumPurchase - TypeApplicationSubscription + EntitlementTypePurchase EntitlementType = iota + 1 + EntitlementTypePremiumSubscription + EntitlementTypeDeveloperGift + EntitlementTypeTestModePurchase + EntitlementTypeFreePurchase + EntitlementTypeUserGift + EntitlementTypePremiumPurchase + EntitlementTypeApplicationSubscription ) diff --git a/objects/guild/ban.go b/objects/guild/ban.go index b9cd06f..5088d1d 100644 --- a/objects/guild/ban.go +++ b/objects/guild/ban.go @@ -5,6 +5,6 @@ import ( ) type Ban struct { - Reason string `json:"reason,omitempty"` + Reason *string `json:"reason"` User user.User `json:"user"` } diff --git a/objects/guild/cachedguild.go b/objects/guild/cachedguild.go index e5450e0..780d81b 100644 --- a/objects/guild/cachedguild.go +++ b/objects/guild/cachedguild.go @@ -9,12 +9,12 @@ import ( type CachedGuild struct { Id uint64 `json:"id"` Name string `json:"name"` - Icon string `json:"icon"` - Splash string `json:"splash"` + Icon *string `json:"icon"` + Splash *string `json:"splash"` Owner bool `json:"owner"` OwnerId uint64 `json:"owner_id"` Permissions uint64 `json:"permissions"` - Region string `json:"region"` + Region *string `json:"region,omitempty"` AfkChannelId objects.NullableSnowflake `json:"afk_channel_id"` AfkTimeout int `json:"afk_timeout"` VerificationLevel int `json:"verification_level"` @@ -25,27 +25,27 @@ type CachedGuild struct { Features []GuildFeature `json:"features"` MfaLevel int `json:"mfa_level"` ApplicationId objects.NullableSnowflake `json:"application_id"` - WidgetEnabled bool `json:"widget_enabled"` - WidgetChannelId objects.NullableSnowflake `json:"widget_channel_id"` + WidgetEnabled *bool `json:"widget_enabled,omitempty"` + WidgetChannelId objects.NullableSnowflake `json:"widget_channel_id,omitempty"` SystemChannelId objects.NullableSnowflake `json:"system_channel_id"` SystemChannelFlags uint16 `json:"system_channel_flags"` RulesChannelId objects.NullableSnowflake `json:"rules_channel_id,omitempty"` JoinedAt time.Time `json:"joined_at"` Large bool `json:"large"` - Unavailable *bool `json:"unavailable"` + Unavailable *bool `json:"unavailable,omitempty"` MemberCount int `json:"member_count"` Channels []uint64 `json:"-"` Presences []uint64 `json:"-"` - MaxPresences int `json:"max_presences"` - MaxMembers int `json:"max_members"` - VanityUrlCode string `json:"vanity_url_code"` - Description string `json:"description"` - Banner string `json:"banner"` + MaxPresences *int `json:"max_presences,omitempty"` + MaxMembers *int `json:"max_members,omitempty"` + VanityUrlCode *string `json:"vanity_url_code"` + Description *string `json:"description"` + Banner *string `json:"banner"` PremiumTier PremiumTier `json:"premium_tier"` - PremiumSubscriptionCount int `json:"premium_subscription_count"` + PremiumSubscriptionCount *int `json:"premium_subscription_count,omitempty"` PreferredLocale string `json:"preferred_locale"` PublicUpdatesChannelId objects.NullableSnowflake `json:"public_updates_channel_id"` - MaxVideoChannelUsers int `json:"max_video_channel_users"` + MaxVideoChannelUsers *int `json:"max_video_channel_users,omitempty"` } func (g *CachedGuild) ToGuild(guildId uint64) Guild { @@ -66,7 +66,7 @@ func (g *CachedGuild) ToGuild(guildId uint64) Guild { Features: g.Features, MfaLevel: g.MfaLevel, ApplicationId: g.ApplicationId, - WidgetEnabled: bool(g.WidgetEnabled), + WidgetEnabled: g.WidgetEnabled, WidgetChannelId: g.WidgetChannelId, SystemChannelId: g.SystemChannelId, SystemChannelFlags: g.SystemChannelFlags, diff --git a/objects/guild/cachedvoicestate.go b/objects/guild/cachedvoicestate.go index 8e40b04..2f33f55 100644 --- a/objects/guild/cachedvoicestate.go +++ b/objects/guild/cachedvoicestate.go @@ -1,8 +1,6 @@ package guild -import ( - "github.com/TicketsBot-cloud/gdl/objects/member" -) +import "github.com/TicketsBot-cloud/gdl/objects/member" type CachedVoiceState struct { ChannelId uint64 `json:"channel_id"` @@ -15,11 +13,17 @@ type CachedVoiceState struct { } func (s *CachedVoiceState) ToVoiceState(guildId uint64, m member.Member) VoiceState { + channelId := s.ChannelId + var userId uint64 + if m.User != nil { + userId = m.User.Id + } + return VoiceState{ - GuildId: guildId, - ChannelId: s.ChannelId, - UserId: m.User.Id, - Member: m, + GuildId: &guildId, + ChannelId: &channelId, + UserId: userId, + Member: &m, SessionId: s.SessionId, Deaf: s.Deaf, Mute: s.Mute, diff --git a/objects/guild/defaultmessagenotificationlevel.go b/objects/guild/defaultmessagenotificationlevel.go index aff300c..0edd318 100644 --- a/objects/guild/defaultmessagenotificationlevel.go +++ b/objects/guild/defaultmessagenotificationlevel.go @@ -3,6 +3,6 @@ package guild type DefaultMessageNotificationLevel int const ( - DefaultMessageNotificationLevelAllMessages DefaultMessageNotificationLevel = 0 - DefaultMessageNotificationLevelOnlyMengions DefaultMessageNotificationLevel = 1 + DefaultMessageNotificationLevelAllMessages DefaultMessageNotificationLevel = iota + DefaultMessageNotificationLevelOnlyMentions ) diff --git a/objects/guild/emoji/cachedemoji.go b/objects/guild/emoji/cachedemoji.go index 05ef8ba..b045d6b 100644 --- a/objects/guild/emoji/cachedemoji.go +++ b/objects/guild/emoji/cachedemoji.go @@ -7,7 +7,7 @@ import ( type CachedEmoji struct { GuildId uint64 `json:"-"` - Name string `json:"name"` + Name *string `json:"name,omitempty"` Roles []uint64 `json:"roles"` User uint64 `json:"user"` RequireColons bool `json:"require_colons"` @@ -15,12 +15,12 @@ type CachedEmoji struct { Animated bool `json:"animated"` } -func (e *CachedEmoji) ToEmoji(emojiId uint64, user user.User) Emoji { +func (e *CachedEmoji) ToEmoji(emojiId uint64, u user.User) Emoji { return Emoji{ Id: objects.NewNullableSnowflake(emojiId), Name: e.Name, Roles: e.Roles, - User: user, + User: &u, RequireColons: e.RequireColons, Managed: e.Managed, Animated: e.Animated, diff --git a/objects/guild/emoji/emoji.go b/objects/guild/emoji/emoji.go index 5ab94a0..e4cb553 100644 --- a/objects/guild/emoji/emoji.go +++ b/objects/guild/emoji/emoji.go @@ -9,20 +9,26 @@ import ( // https://discord.com/developers/docs/resources/emoji#emoji-object type Emoji struct { Id objects.NullableSnowflake `json:"id"` - Name string `json:"name"` // if this is not a custom emote, Name will be the unicode emoji, and Id will be 0 + Name *string `json:"name,omitempty"` // null when custom emoji data is not available; unicode emoji string for standard emoji Roles utils.Uint64StringSlice `json:"roles,omitempty"` - User user.User `json:"user"` - RequireColons bool `json:"require_colons"` - Managed bool `json:"managed"` - Animated bool `json:"animated"` + User *user.User `json:"user,omitempty"` + RequireColons bool `json:"require_colons,omitempty"` + Managed bool `json:"managed,omitempty"` + Animated bool `json:"animated,omitempty"` + Available *bool `json:"available,omitempty"` } func (e *Emoji) ToCachedEmoji(guildId uint64) CachedEmoji { + var userId uint64 + if e.User != nil { + userId = e.User.Id + } + return CachedEmoji{ GuildId: guildId, Name: e.Name, Roles: e.Roles, - User: e.User.Id, + User: userId, RequireColons: e.RequireColons, Managed: e.Managed, Animated: e.Animated, diff --git a/objects/guild/explicitcontentfilterlevel.go b/objects/guild/explicitcontentfilterlevel.go index c4c81b0..34302f1 100644 --- a/objects/guild/explicitcontentfilterlevel.go +++ b/objects/guild/explicitcontentfilterlevel.go @@ -3,7 +3,7 @@ package guild type ExplicitContentFilterLevel int const ( - DISABLED ExplicitContentFilterLevel = 0 - MEMBERS_WITHOUT_ROLES ExplicitContentFilterLevel = 1 - ALL_MEMBERS ExplicitContentFilterLevel = 2 + ExplicitContentFilterLevelDisabled ExplicitContentFilterLevel = iota + ExplicitContentFilterLevelMembersWithoutRoles + ExplicitContentFilterLevelAllMembers ) diff --git a/objects/guild/guild.go b/objects/guild/guild.go index bf107c9..8f0337c 100644 --- a/objects/guild/guild.go +++ b/objects/guild/guild.go @@ -8,20 +8,25 @@ import ( "github.com/TicketsBot-cloud/gdl/objects" "github.com/TicketsBot-cloud/gdl/objects/channel" "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" + "github.com/TicketsBot-cloud/gdl/objects/guild/sticker" "github.com/TicketsBot-cloud/gdl/objects/member" ) type Guild struct { Id uint64 `json:"id,string"` Name string `json:"name"` - Icon string `json:"icon"` - Splash string `json:"splash"` - Owner bool `json:"owner"` + Icon *string `json:"icon"` + IconHash *string `json:"icon_hash,omitempty"` + Splash *string `json:"splash"` + DiscoverySplash *string `json:"discovery_splash"` + Owner bool `json:"owner,omitempty"` OwnerId uint64 `json:"owner_id,string"` - Permissions uint64 `json:"permissions,string"` - Region string `json:"region"` + Permissions uint64 `json:"permissions,string,omitempty"` + Region *string `json:"region,omitempty"` AfkChannelId objects.NullableSnowflake `json:"afk_channel_id"` AfkTimeout int `json:"afk_timeout"` + WidgetEnabled *bool `json:"widget_enabled,omitempty"` + WidgetChannelId objects.NullableSnowflake `json:"widget_channel_id,omitempty"` VerificationLevel int `json:"verification_level"` DefaultMessageNotifications int `json:"default_message_notifications"` ExplicitContentFilter int `json:"explicit_content_filter"` @@ -30,46 +35,56 @@ type Guild struct { Features []GuildFeature `json:"features"` MfaLevel int `json:"mfa_level"` ApplicationId objects.NullableSnowflake `json:"application_id"` - WidgetEnabled bool `json:"widget_enabled"` - WidgetChannelId objects.NullableSnowflake `json:"widget_channel_id"` SystemChannelId objects.NullableSnowflake `json:"system_channel_id"` SystemChannelFlags uint16 `json:"system_channel_flags"` RulesChannelId objects.NullableSnowflake `json:"rules_channel_id,omitempty"` - JoinedAt time.Time `json:"joined_at"` - Large bool `json:"large"` - Unavailable *bool `json:"unavailable"` - MemberCount int `json:"member_count"` - VoiceStates []VoiceState `json:"voice_state"` - Members []member.Member `json:"members"` - Channels []channel.Channel `json:"channels"` - Threads []channel.Channel `json:"threads"` - MaxPresences int `json:"max_presences"` - MaxMembers int `json:"max_members"` - VanityUrlCode string `json:"vanity_url_code"` - Description string `json:"description"` - Banner string `json:"banner"` + JoinedAt time.Time `json:"joined_at,omitempty"` + Large bool `json:"large,omitempty"` + Unavailable *bool `json:"unavailable,omitempty"` + MemberCount int `json:"member_count,omitempty"` + VoiceStates []VoiceState `json:"voice_states,omitempty"` + Members []member.Member `json:"members,omitempty"` + Channels []channel.Channel `json:"channels,omitempty"` + Threads []channel.Channel `json:"threads,omitempty"` + MaxPresences *int `json:"max_presences,omitempty"` + MaxMembers *int `json:"max_members,omitempty"` + VanityUrlCode *string `json:"vanity_url_code"` + Description *string `json:"description"` + Banner *string `json:"banner"` PremiumTier PremiumTier `json:"premium_tier"` - PremiumSubscriptionCount int `json:"premium_subscription_count"` + PremiumSubscriptionCount *int `json:"premium_subscription_count,omitempty"` PreferredLocale string `json:"preferred_locale"` PublicUpdatesChannelId objects.NullableSnowflake `json:"public_updates_channel_id"` - MaxVideoChannelUsers int `json:"max_video_channel_users"` - ApproximateMemberCount int `json:"approximate_member_count"` // Returned on GET /guild/:id - ApproximatePresenceCount int `json:"approximate_presence_count"` // Returned on GET /guild/:id - WelcomeScreen WelcomeScreen `json:"welcome_screen"` - Nsfw bool `json:"nsfw"` + MaxVideoChannelUsers *int `json:"max_video_channel_users,omitempty"` + MaxStageVideoChannelUsers *int `json:"max_stage_video_channel_users,omitempty"` + ApproximateMemberCount int `json:"approximate_member_count,omitempty"` + ApproximatePresenceCount int `json:"approximate_presence_count,omitempty"` + WelcomeScreen *WelcomeScreen `json:"welcome_screen,omitempty"` + NsfwLevel int `json:"nsfw_level"` + Stickers []sticker.Sticker `json:"stickers,omitempty"` + PremiumProgressBarEnabled bool `json:"premium_progress_bar_enabled"` + SafetyAlertsChannelId objects.NullableSnowflake `json:"safety_alerts_channel_id"` + IncidentsData *IncidentsData `json:"incidents_data,omitempty"` +} + +type IncidentsData struct { + InvitesDisabledUntil *time.Time `json:"invites_disabled_until,omitempty"` + DmsDisabledUntil *time.Time `json:"dms_disabled_until,omitempty"` + DmSpamDetectedAt *time.Time `json:"dm_spam_detected_at,omitempty"` + RaidDetectedAt *time.Time `json:"raid_detected_at,omitempty"` } func (g *Guild) IconUrl() string { - if g.Icon == "" { + if g.Icon == nil || *g.Icon == "" { return "" } extension := "png" - if strings.HasPrefix(g.Icon, "a_") { + if strings.HasPrefix(*g.Icon, "a_") { extension = "gif" } - return fmt.Sprintf("https://cdn.discordapp.com/icons/%d/%s.%s", g.Id, g.Icon, extension) + return fmt.Sprintf("https://cdn.discordapp.com/icons/%d/%s.%s", g.Id, *g.Icon, extension) } func (g *Guild) ToCachedGuild() (cached CachedGuild) { diff --git a/objects/guild/guildembed.go b/objects/guild/guildembed.go index 97ba327..2dbb69f 100644 --- a/objects/guild/guildembed.go +++ b/objects/guild/guildembed.go @@ -1,6 +1,9 @@ package guild +import "github.com/TicketsBot-cloud/gdl/objects" + +// GuildEmbed represents the settings for a guild's widget (also known as GuildWidgetSettings). type GuildEmbed struct { - Enabled bool `json:"enabled"` - ChannelId uint64 `json:"channel_id,string"` + Enabled bool `json:"enabled"` + ChannelId objects.NullableSnowflake `json:"channel_id"` } diff --git a/objects/guild/guildfeature.go b/objects/guild/guildfeature.go index 334ad16..13d8576 100644 --- a/objects/guild/guildfeature.go +++ b/objects/guild/guildfeature.go @@ -3,16 +3,36 @@ package guild type GuildFeature string const ( - GuildFeatureInviteSplash GuildFeature = "INVITE_SPLASH" - GuildFeatureVipRegions GuildFeature = "VIP_REGIONS" // guild has access to set 384kbps bitrate in voice (previously VIP voice servers) - GuildFeatureVanityUrl GuildFeature = "VANITY_URL" - GuildFeatureVerified GuildFeature = "VERIFIED" - GuildFeaturePartnered GuildFeature = "PARTNERED" - GuildFeaturePublic GuildFeature = "PUBLIC" - GuildFeatureCommerce GuildFeature = "COMMERCE" - GuildFeatureNews GuildFeature = "NEWS" - GuildFeatureDiscoverable GuildFeature = "DISCOVERABLE" - GuildFeatureFeaturable GuildFeature = "FEATURABLE" - GuildFeatureBanner GuildFeature = "BANNER" - GuildFeaturePublicDisabled GuildFeature = "PUBLIC_DISABLED" + GuildFeatureAnimatedBanner GuildFeature = "ANIMATED_BANNER" + GuildFeatureAnimatedIcon GuildFeature = "ANIMATED_ICON" + GuildFeatureApplicationCommandPermissionsV2 GuildFeature = "APPLICATION_COMMAND_PERMISSIONS_V2" + GuildFeatureAutoModeration GuildFeature = "AUTO_MODERATION" + GuildFeatureBanner GuildFeature = "BANNER" + GuildFeatureCommunity GuildFeature = "COMMUNITY" + GuildFeatureCreatorMonetizableProvisional GuildFeature = "CREATOR_MONETIZABLE_PROVISIONAL" + GuildFeatureCreatorStorePage GuildFeature = "CREATOR_STORE_PAGE" + GuildFeatureDeveloperSupportServer GuildFeature = "DEVELOPER_SUPPORT_SERVER" + GuildFeatureDiscoverable GuildFeature = "DISCOVERABLE" + GuildFeatureFeaturable GuildFeature = "FEATURABLE" + GuildFeatureEnhancedRoleColors GuildFeature = "ENHANCED_ROLE_COLORS" + GuildFeatureGuestsEnabled GuildFeature = "GUESTS_ENABLED" + GuildFeatureGuildTags GuildFeature = "GUILD_TAGS" + GuildFeatureInvitesDisabled GuildFeature = "INVITES_DISABLED" + GuildFeatureInviteSplash GuildFeature = "INVITE_SPLASH" + GuildFeatureMemberVerificationGateEnabled GuildFeature = "MEMBER_VERIFICATION_GATE_ENABLED" + GuildFeatureMoreSoundboard GuildFeature = "MORE_SOUNDBOARD" + GuildFeatureMoreStickers GuildFeature = "MORE_STICKERS" + GuildFeatureNews GuildFeature = "NEWS" + GuildFeaturePartnered GuildFeature = "PARTNERED" + GuildFeaturePreviewEnabled GuildFeature = "PREVIEW_ENABLED" + GuildFeatureRaidAlertsDisabled GuildFeature = "RAID_ALERTS_DISABLED" + GuildFeatureRoleIcons GuildFeature = "ROLE_ICONS" + GuildFeatureRoleSubscriptionsAvailableForPurchase GuildFeature = "ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE" + GuildFeatureRoleSubscriptionsEnabled GuildFeature = "ROLE_SUBSCRIPTIONS_ENABLED" + GuildFeatureSoundboard GuildFeature = "SOUNDBOARD" + GuildFeatureTicketedEventsEnabled GuildFeature = "TICKETED_EVENTS_ENABLED" + GuildFeatureVanityUrl GuildFeature = "VANITY_URL" + GuildFeatureVerified GuildFeature = "VERIFIED" + GuildFeatureVipRegions GuildFeature = "VIP_REGIONS" + GuildFeatureWelcomeScreenEnabled GuildFeature = "WELCOME_SCREEN_ENABLED" ) diff --git a/objects/guild/guildpreview.go b/objects/guild/guildpreview.go index 6742949..bb97191 100644 --- a/objects/guild/guildpreview.go +++ b/objects/guild/guildpreview.go @@ -1,16 +1,20 @@ package guild -import "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" +import ( + "github.com/TicketsBot-cloud/gdl/objects/guild/emoji" + "github.com/TicketsBot-cloud/gdl/objects/guild/sticker" +) type GuildPreview struct { - Id uint64 `json:"id,string"` - Name string `json:"name"` - Icon string `json:"icon"` - Splash string `json:"splash"` - DiscoverySplash string `json:"discovery_splash"` - Emojis []emoji.Emoji `json:"emojis"` - Features []GuildFeature `json:"features"` - ApproximateMemberCount int `json:"approximate_member_count"` - ApproximatePresenceCount int `json:"approximate_presence_count"` - Description string `json:"description"` + Id uint64 `json:"id,string"` + Name string `json:"name"` + Icon *string `json:"icon"` + Splash *string `json:"splash"` + DiscoverySplash *string `json:"discovery_splash"` + Emojis []emoji.Emoji `json:"emojis"` + Features []GuildFeature `json:"features"` + ApproximateMemberCount int `json:"approximate_member_count"` + ApproximatePresenceCount int `json:"approximate_presence_count"` + Description *string `json:"description"` + Stickers []sticker.Sticker `json:"stickers"` } diff --git a/objects/guild/guildwidget.go b/objects/guild/guildwidget.go index d17aade..fae90a2 100644 --- a/objects/guild/guildwidget.go +++ b/objects/guild/guildwidget.go @@ -8,7 +8,7 @@ import ( type GuildWidget struct { Id uint64 `json:"id,string"` Name string `json:"name"` - InstantInvite string `json:"instant_invite"` + InstantInvite *string `json:"instant_invite"` Channels []channel.Channel `json:"channels"` Members []member.Member `json:"members"` PresenceCount int `json:"presence_count"` diff --git a/objects/guild/role.go b/objects/guild/role.go index d603340..108784b 100644 --- a/objects/guild/role.go +++ b/objects/guild/role.go @@ -1,24 +1,37 @@ package guild -import ( - "fmt" -) +import "fmt" + +type RoleColors struct { + PrimaryColor int `json:"primary_color"` + SecondaryColor *int `json:"secondary_color,omitempty"` + TertiaryColor *int `json:"tertiary_color,omitempty"` +} type Role struct { - Id uint64 `json:"id,string"` - Name string `json:"name"` - Color int `json:"color"` - Hoist bool `json:"hoist"` - Position int `json:"position"` - Permissions uint64 `json:"permissions,string"` - Managed bool `json:"managed"` - Mentionable bool `json:"mentionable"` - Tags RoleTags `json:"tags"` + Id uint64 `json:"id,string"` + Name string `json:"name"` + Color int `json:"color"` + Colors RoleColors `json:"colors"` + Hoist bool `json:"hoist"` + Icon *string `json:"icon"` + UnicodeEmoji *string `json:"unicode_emoji"` + Position int `json:"position"` + Permissions uint64 `json:"permissions,string"` + Managed bool `json:"managed"` + Mentionable bool `json:"mentionable"` + Flags int `json:"flags"` + Tags RoleTags `json:"tags"` } type RoleTags struct { BotId *uint64 `json:"bot_id,string,omitempty"` IntegrationId *uint64 `json:"integration_id,string,omitempty"` + // PremiumSubscriber, AvailableForPurchase, GuildConnections: key present (even as null) = tag applies + PremiumSubscriber *bool `json:"premium_subscriber,omitempty"` + SubscriptionListingId *uint64 `json:"subscription_listing_id,string,omitempty"` + AvailableForPurchase *bool `json:"available_for_purchase,omitempty"` + GuildConnections *bool `json:"guild_connections,omitempty"` } func (r *Role) Mention() string { diff --git a/objects/guild/scheduledevent/scheduledevent.go b/objects/guild/scheduledevent/scheduledevent.go new file mode 100644 index 0000000..ae5ed9f --- /dev/null +++ b/objects/guild/scheduledevent/scheduledevent.go @@ -0,0 +1,110 @@ +package scheduledevent + +import ( + "time" + + "github.com/TicketsBot-cloud/gdl/objects/user" +) + +type PrivacyLevel int + +const ( + PrivacyLevelGuildOnly PrivacyLevel = 2 +) + +type EntityType int + +const ( + EntityTypeStageInstance EntityType = iota + 1 + EntityTypeVoice + EntityTypeExternal +) + +type Status int + +const ( + StatusScheduled Status = iota + 1 + StatusActive + StatusCompleted + StatusCanceled +) + +type RecurrenceFrequency int + +const ( + RecurrenceFrequencyYearly RecurrenceFrequency = iota + RecurrenceFrequencyMonthly + RecurrenceFrequencyWeekly + RecurrenceFrequencyDaily +) + +type RecurrenceWeekday int + +const ( + RecurrenceWeekdayMonday RecurrenceWeekday = iota + RecurrenceWeekdayTuesday + RecurrenceWeekdayWednesday + RecurrenceWeekdayThursday + RecurrenceWeekdayFriday + RecurrenceWeekdaySaturday + RecurrenceWeekdaySunday +) + +type RecurrenceMonth int + +const ( + RecurrenceMonthJanuary RecurrenceMonth = iota + 1 + RecurrenceMonthFebruary + RecurrenceMonthMarch + RecurrenceMonthApril + RecurrenceMonthMay + RecurrenceMonthJune + RecurrenceMonthJuly + RecurrenceMonthAugust + RecurrenceMonthSeptember + RecurrenceMonthOctober + RecurrenceMonthNovember + RecurrenceMonthDecember +) + +type RecurrenceNWeekday struct { + N int `json:"n"` + Day RecurrenceWeekday `json:"day"` +} + +type RecurrenceRule struct { + Start time.Time `json:"start"` + End *time.Time `json:"end,omitempty"` + Frequency RecurrenceFrequency `json:"frequency"` + Interval int `json:"interval"` + ByWeekday []RecurrenceWeekday `json:"by_weekday,omitempty"` + ByNWeekday []RecurrenceNWeekday `json:"by_n_weekday,omitempty"` + ByMonth []RecurrenceMonth `json:"by_month,omitempty"` + ByMonthDay []int `json:"by_month_day,omitempty"` + ByYearDay []int `json:"by_year_day,omitempty"` + Count *int `json:"count,omitempty"` +} + +type EntityMetadata struct { + Location *string `json:"location,omitempty"` +} + +type GuildScheduledEvent struct { + Id uint64 `json:"id,string"` + GuildId uint64 `json:"guild_id,string"` + ChannelId *uint64 `json:"channel_id,string,omitempty"` + CreatorId *uint64 `json:"creator_id,string,omitempty"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + ScheduledStartTime time.Time `json:"scheduled_start_time"` + ScheduledEndTime *time.Time `json:"scheduled_end_time,omitempty"` + PrivacyLevel PrivacyLevel `json:"privacy_level"` + Status Status `json:"status"` + EntityType EntityType `json:"entity_type"` + EntityId *uint64 `json:"entity_id,string,omitempty"` + EntityMetadata *EntityMetadata `json:"entity_metadata,omitempty"` + Creator *user.User `json:"creator,omitempty"` + UserCount *int `json:"user_count,omitempty"` + Image *string `json:"image,omitempty"` + RecurrenceRule *RecurrenceRule `json:"recurrence_rule,omitempty"` +} diff --git a/objects/guild/soundboard/soundboard.go b/objects/guild/soundboard/soundboard.go new file mode 100644 index 0000000..17275c4 --- /dev/null +++ b/objects/guild/soundboard/soundboard.go @@ -0,0 +1,14 @@ +package soundboard + +import "github.com/TicketsBot-cloud/gdl/objects/user" + +type SoundboardSound struct { + SoundId uint64 `json:"sound_id,string"` + Name string `json:"name"` + Volume float64 `json:"volume"` + EmojiId *uint64 `json:"emoji_id,string"` + EmojiName *string `json:"emoji_name,omitempty"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + Available bool `json:"available"` + User *user.User `json:"user,omitempty"` +} diff --git a/objects/guild/stage/stage.go b/objects/guild/stage/stage.go new file mode 100644 index 0000000..f24ab10 --- /dev/null +++ b/objects/guild/stage/stage.go @@ -0,0 +1,20 @@ +package stage + +import "github.com/TicketsBot-cloud/gdl/objects" + +type StagePrivacyLevel int + +const ( + StagePrivacyLevelPublic StagePrivacyLevel = iota + 1 // Deprecated + StagePrivacyLevelGuildOnly +) + +type StageInstance struct { + Id uint64 `json:"id,string"` + GuildId uint64 `json:"guild_id,string"` + ChannelId uint64 `json:"channel_id,string"` + Topic string `json:"topic"` + PrivacyLevel StagePrivacyLevel `json:"privacy_level"` + DiscoverableDisabled bool `json:"discoverable_disabled,omitempty"` + GuildScheduledEventId objects.NullableSnowflake `json:"guild_scheduled_event_id"` +} diff --git a/objects/guild/sticker/sticker.go b/objects/guild/sticker/sticker.go new file mode 100644 index 0000000..b1f3957 --- /dev/null +++ b/objects/guild/sticker/sticker.go @@ -0,0 +1,33 @@ +package sticker + +import "github.com/TicketsBot-cloud/gdl/objects/user" + +type StickerType int + +const ( + StickerTypeStandard StickerType = iota + 1 + StickerTypeGuild +) + +type StickerFormatType int + +const ( + StickerFormatTypePNG StickerFormatType = iota + 1 + StickerFormatTypeAPNG + StickerFormatTypeLottie + StickerFormatTypeGIF +) + +type Sticker struct { + Id uint64 `json:"id,string"` + PackId *uint64 `json:"pack_id,string,omitempty"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Tags string `json:"tags"` + Type StickerType `json:"type"` + FormatType StickerFormatType `json:"format_type"` + Available *bool `json:"available,omitempty"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + User *user.User `json:"user,omitempty"` + SortValue *int `json:"sort_value,omitempty"` +} diff --git a/objects/guild/verificationlevel.go b/objects/guild/verificationlevel.go index 4216ed7..0a393ac 100644 --- a/objects/guild/verificationlevel.go +++ b/objects/guild/verificationlevel.go @@ -3,9 +3,9 @@ package guild type VerificationLevel int const ( - NONE VerificationLevel = 0 - LOW VerificationLevel = 1 - MEDIUM VerificationLevel = 2 - HIGH VerificationLevel = 3 - VERY_HIGH VerificationLevel = 4 + VerificationLevelNone VerificationLevel = iota + VerificationLevelLow + VerificationLevelMedium + VerificationLevelHigh + VerificationLevelVeryHigh ) diff --git a/objects/guild/voiceregion.go b/objects/guild/voiceregion.go index 3bf8c78..7995fd0 100644 --- a/objects/guild/voiceregion.go +++ b/objects/guild/voiceregion.go @@ -3,7 +3,6 @@ package guild type VoiceRegion struct { Id string `json:"id"` Name string `json:"name"` - Vip bool `json:"vip"` Optimal bool `json:"optimal"` Deprecated bool `json:"deprecated"` Custom bool `json:"custom"` diff --git a/objects/guild/voicestate.go b/objects/guild/voicestate.go index a29fdf0..f1a07fd 100644 --- a/objects/guild/voicestate.go +++ b/objects/guild/voicestate.go @@ -1,23 +1,35 @@ package guild -import "github.com/TicketsBot-cloud/gdl/objects/member" +import ( + "time" + + "github.com/TicketsBot-cloud/gdl/objects/member" +) type VoiceState struct { - GuildId uint64 `json:"guild_id,string"` - ChannelId uint64 `json:"channel_id,string"` - UserId uint64 `json:"user_id,string"` - Member member.Member `json:"member"` - SessionId string `json:"session_id"` - Deaf bool `json:"deaf"` - Mute bool `json:"mute"` - SelfDeaf bool `json:"self_deaf"` - SelfMute bool `json:"self_mute"` - Suppress bool `json:"suppress"` + GuildId *uint64 `json:"guild_id,string"` + ChannelId *uint64 `json:"channel_id,string"` + UserId uint64 `json:"user_id,string"` + Member *member.Member `json:"member,omitempty"` + SessionId string `json:"session_id"` + Deaf bool `json:"deaf"` + Mute bool `json:"mute"` + SelfDeaf bool `json:"self_deaf"` + SelfMute bool `json:"self_mute"` + SelfStream bool `json:"self_stream"` + SelfVideo bool `json:"self_video"` + Suppress bool `json:"suppress"` + RequestToSpeakTimestamp *time.Time `json:"request_to_speak_timestamp"` } func (s *VoiceState) ToCachedVoiceState() CachedVoiceState { + var channelId uint64 + if s.ChannelId != nil { + channelId = *s.ChannelId + } + return CachedVoiceState{ - ChannelId: s.ChannelId, + ChannelId: channelId, SessionId: s.SessionId, Deaf: s.Deaf, Mute: s.Mute, diff --git a/objects/guild/webhook.go b/objects/guild/webhook.go index e7d2280..5e57fe3 100644 --- a/objects/guild/webhook.go +++ b/objects/guild/webhook.go @@ -2,17 +2,28 @@ package guild import ( "github.com/TicketsBot-cloud/gdl/objects" + "github.com/TicketsBot-cloud/gdl/objects/channel" "github.com/TicketsBot-cloud/gdl/objects/user" ) type Webhook struct { Id uint64 `json:"id,string"` Type WebhookType `json:"type"` - GuildId uint64 `json:"guild_id,string,omitempty"` - ChannelId uint64 `json:"channel_id,string"` - User user.User `json:"user"` - Name string `json:"name,omitempty"` - Avatar string `json:"avatar,omitempty"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + ChannelId objects.NullableSnowflake `json:"channel_id"` + User *user.User `json:"user,omitempty"` + Name *string `json:"name"` + Avatar *string `json:"avatar"` Token string `json:"token,omitempty"` ApplicationId objects.NullableSnowflake `json:"application_id"` + SourceGuild *WebhookSourceGuild `json:"source_guild,omitempty"` + SourceChannel *channel.PartialChannel `json:"source_channel,omitempty"` + Url *string `json:"url,omitempty"` +} + +// WebhookSourceGuild is the partial guild object returned for Channel Follower webhooks. +type WebhookSourceGuild struct { + Id uint64 `json:"id,string"` + Name string `json:"name"` + Icon *string `json:"icon"` } diff --git a/objects/guild/webhooktype.go b/objects/guild/webhooktype.go index 4b24392..27ae972 100644 --- a/objects/guild/webhooktype.go +++ b/objects/guild/webhooktype.go @@ -3,6 +3,7 @@ package guild type WebhookType int const ( - WebhookTypeIncoming WebhookType = 1 - WebhookTypeChannelFollower WebhookType = 2 + WebhookTypeIncoming WebhookType = iota + 1 + WebhookTypeChannelFollower + WebhookTypeApplication ) diff --git a/objects/guild/welcomescreen.go b/objects/guild/welcomescreen.go index 695e260..8fb5330 100644 --- a/objects/guild/welcomescreen.go +++ b/objects/guild/welcomescreen.go @@ -3,7 +3,7 @@ package guild import "github.com/TicketsBot-cloud/gdl/objects" type WelcomeScreen struct { - Description string `json:"description"` + Description *string `json:"description"` WelcomeChannels []WelcomeScreenChannel `json:"welcome_channels"` } diff --git a/objects/integration/connection.go b/objects/integration/connection.go index 83a46fb..62ea645 100644 --- a/objects/integration/connection.go +++ b/objects/integration/connection.go @@ -1,20 +1,21 @@ package integration -type Visibility int +type ConnectionVisibility int const ( - VisibilityNone Visibility = 0 - VisibilityEveryone Visibility = 1 + ConnectionVisibilityNone ConnectionVisibility = iota + ConnectionVisibilityEveryone ) type Connection struct { - Id string `json:"id"` - Name string `json:"name"` - Type string `json:"type"` // youtube, twitch, etc. - Revoked bool `json:"revoked"` - Integrations []Integration `json:"integrations"` - Verified bool `json:"verified"` - FriendSync bool `json:"friend_sync"` - ShowActivity bool `json:"show_activity"` - Visibility Visibility `json:"visibility"` + Id string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` // twitch, youtube, spotify, etc. + Revoked *bool `json:"revoked,omitempty"` + Integrations []Integration `json:"integrations,omitempty"` + Verified bool `json:"verified"` + FriendSync bool `json:"friend_sync"` + ShowActivity bool `json:"show_activity"` + TwoWayLink bool `json:"two_way_link"` + Visibility ConnectionVisibility `json:"visibility"` } diff --git a/objects/integration/integrationexpirebehaviour.go b/objects/integration/integrationexpirebehaviour.go index b1eb94e..514d729 100644 --- a/objects/integration/integrationexpirebehaviour.go +++ b/objects/integration/integrationexpirebehaviour.go @@ -3,6 +3,6 @@ package integration type IntegrationExpireBehaviour int const ( - RemoveRole IntegrationExpireBehaviour = 0 - Kick IntegrationExpireBehaviour = 1 + IntegrationExpireBehaviourRemoveRole IntegrationExpireBehaviour = iota + IntegrationExpireBehaviourKick ) diff --git a/objects/integration/integrations.go b/objects/integration/integrations.go index b024813..7d9792e 100644 --- a/objects/integration/integrations.go +++ b/objects/integration/integrations.go @@ -8,16 +8,28 @@ import ( ) type Integration struct { - Id uint64 `json:"id,string"` - Name string `json:"name"` - Type string `json:"type"` // twitch, youtube, etc. - Enabled bool `json:"enabled"` - Syncing bool `json:"syncing"` - RoleId uint64 `json:"role_id,string"` - EnableEmoticons bool `json:"enable_emoticons"` - ExpireBehaviour IntegrationExpireBehaviour `json:"expire_behavior"` - ExpireGracePeriod int `json:"expire_grace_period"` - User user.User `json:"user"` - Account guild.Account `json:"account"` - SyncedAt time.Time `json:"synced_at"` + Id uint64 `json:"id,string"` + Name string `json:"name"` + Type string `json:"type"` // twitch, youtube, discord, etc. + Enabled bool `json:"enabled"` + Syncing *bool `json:"syncing,omitempty"` + RoleId *uint64 `json:"role_id,string,omitempty"` + EnableEmoticons *bool `json:"enable_emoticons,omitempty"` + ExpireBehaviour *IntegrationExpireBehaviour `json:"expire_behavior,omitempty"` + ExpireGracePeriod *int `json:"expire_grace_period,omitempty"` + User *user.User `json:"user,omitempty"` + Account guild.Account `json:"account"` + SyncedAt *time.Time `json:"synced_at,omitempty"` + SubscriberCount *int `json:"subscriber_count,omitempty"` + Revoked *bool `json:"revoked,omitempty"` + Application *IntegrationApplication `json:"application,omitempty"` + Scopes []string `json:"scopes,omitempty"` +} + +type IntegrationApplication struct { + Id uint64 `json:"id,string"` + Name string `json:"name"` + Icon *string `json:"icon"` + Description string `json:"description"` + Bot *user.User `json:"bot,omitempty"` } diff --git a/objects/interaction/applicationcommand.go b/objects/interaction/applicationcommand.go index 5d57449..68807a4 100644 --- a/objects/interaction/applicationcommand.go +++ b/objects/interaction/applicationcommand.go @@ -1,14 +1,23 @@ package interaction +import "github.com/TicketsBot-cloud/gdl/objects/application" + type ApplicationCommand struct { - Id uint64 `json:"id,string,omitempty"` - Type ApplicationCommandType `json:"application_command_type"` - ApplicationId uint64 `json:"application_id,string,omitempty"` - Name string `json:"name"` - Description string `json:"description"` - Options []ApplicationCommandOption `json:"options"` - DefaultPermission bool `json:"default_permission,omitempty"` - Contexts []InteractionContextType `json:"contexts,omitempty"` + Id uint64 `json:"id,string,omitempty"` + Type ApplicationCommandType `json:"type"` + ApplicationId uint64 `json:"application_id,string,omitempty"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + Name string `json:"name"` + NameLocalizations map[string]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[string]string `json:"description_localizations,omitempty"` + Options []ApplicationCommandOption `json:"options,omitempty"` + DefaultMemberPermissions *string `json:"default_member_permissions,omitempty"` + Nsfw bool `json:"nsfw,omitempty"` + IntegrationTypes []application.ApplicationIntegrationType `json:"integration_types,omitempty"` + Contexts []InteractionContextType `json:"contexts,omitempty"` + Version uint64 `json:"version,string,omitempty"` + Handler *ApplicationCommandHandlerType `json:"handler,omitempty"` } type ApplicationCommandType uint8 @@ -17,4 +26,12 @@ const ( ApplicationCommandTypeChatInput ApplicationCommandType = iota + 1 ApplicationCommandTypeUser ApplicationCommandTypeMessage + ApplicationCommandTypePrimaryEntryPoint +) + +type ApplicationCommandHandlerType uint8 + +const ( + ApplicationCommandHandlerTypeAppHandler ApplicationCommandHandlerType = iota + 1 + ApplicationCommandHandlerTypeDiscordLaunchActivity ) diff --git a/objects/interaction/applicationcommandoption.go b/objects/interaction/applicationcommandoption.go index 4448792..4ca01b8 100644 --- a/objects/interaction/applicationcommandoption.go +++ b/objects/interaction/applicationcommandoption.go @@ -3,41 +3,48 @@ package interaction import "github.com/TicketsBot-cloud/gdl/objects/channel" type ApplicationCommandInteractionDataOption struct { + Type ApplicationCommandOptionType `json:"type"` Name string `json:"name"` Value interface{} `json:"value,omitempty"` Options []ApplicationCommandInteractionDataOption `json:"options,omitempty"` - Focused bool `json:"focused"` + Focused bool `json:"focused,omitempty"` } type ApplicationCommandOption struct { - Type ApplicationCommandOptionType `json:"type"` - Name string `json:"name"` - Description string `json:"description"` - Default bool `json:"default"` - Required bool `json:"required"` - Choices []ApplicationCommandOptionChoice `json:"choices,omitempty"` - Autocomplete bool `json:"autocomplete"` - Options []ApplicationCommandOption `json:"options,omitempty"` - ChannelTypes []channel.ChannelType `json:"channel_types,omitempty"` + Type ApplicationCommandOptionType `json:"type"` + Name string `json:"name"` + NameLocalizations map[string]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[string]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` + Choices []ApplicationCommandOptionChoice `json:"choices,omitempty"` + Autocomplete bool `json:"autocomplete,omitempty"` + Options []ApplicationCommandOption `json:"options,omitempty"` + ChannelTypes []channel.ChannelType `json:"channel_types,omitempty"` + MinValue *float64 `json:"min_value,omitempty"` + MaxValue *float64 `json:"max_value,omitempty"` + MinLength *int `json:"min_length,omitempty"` + MaxLength *int `json:"max_length,omitempty"` } type ApplicationCommandOptionType uint8 const ( - OptionTypeSubCommand ApplicationCommandOptionType = iota + 1 - OptionTypeSubCommandGroup - OptionTypeString - OptionTypeInteger - OptionTypeBoolean - OptionTypeUser - OptionTypeChannel - OptionTypeRole - OptionTypeMentionable - OptionTypeNumber - OptionTypeAttachment + ApplicationCommandOptionTypeSubCommand ApplicationCommandOptionType = iota + 1 + ApplicationCommandOptionTypeSubCommandGroup + ApplicationCommandOptionTypeString + ApplicationCommandOptionTypeInteger + ApplicationCommandOptionTypeBoolean + ApplicationCommandOptionTypeUser + ApplicationCommandOptionTypeChannel + ApplicationCommandOptionTypeRole + ApplicationCommandOptionTypeMentionable + ApplicationCommandOptionTypeNumber + ApplicationCommandOptionTypeAttachment ) type ApplicationCommandOptionChoice struct { - Name string `json:"name"` - Value interface{} `json:"value"` // string, int or double + Name string `json:"name"` + NameLocalizations map[string]string `json:"name_localizations,omitempty"` + Value interface{} `json:"value"` // string, int or double } diff --git a/objects/interaction/applicationcommandpermissions.go b/objects/interaction/applicationcommandpermissions.go index da7bf83..14fc5b0 100644 --- a/objects/interaction/applicationcommandpermissions.go +++ b/objects/interaction/applicationcommandpermissions.go @@ -5,6 +5,7 @@ type ApplicationCommandPermissionType uint8 const ( ApplicationCommandPermissionTypeRole ApplicationCommandPermissionType = iota + 1 ApplicationCommandPermissionTypeUser + ApplicationCommandPermissionTypeChannel ) type ApplicationCommandPermissions struct { @@ -12,3 +13,10 @@ type ApplicationCommandPermissions struct { Type ApplicationCommandPermissionType `json:"type"` Permission bool `json:"permission"` } + +type GuildApplicationCommandPermissions struct { + Id uint64 `json:"id,string"` + ApplicationId uint64 `json:"application_id,string"` + GuildId uint64 `json:"guild_id,string"` + Permissions []ApplicationCommandPermissions `json:"permissions"` +} diff --git a/objects/interaction/component/component.go b/objects/interaction/component/component.go index f2523a8..e57a60c 100644 --- a/objects/interaction/component/component.go +++ b/objects/interaction/component/component.go @@ -11,7 +11,7 @@ type ComponentType uint8 const ( ComponentActionRow ComponentType = iota + 1 ComponentButton - ComponentSelectMenu + ComponentStringSelect ComponentInputText ComponentUserSelect ComponentRoleSelect @@ -23,10 +23,16 @@ const ( ComponentMediaGallery ComponentFile ComponentSeparator - ComponentContainer ComponentType = iota + 3 // 14 +) + +const ( + ComponentContainer ComponentType = iota + 17 ComponentLabel ComponentFileUpload - ComponentRadioGroup ComponentType = iota + 4 // 21 +) + +const ( + ComponentRadioGroup ComponentType = iota + 21 ComponentCheckboxGroup ComponentCheckbox ) @@ -134,7 +140,7 @@ func (c *Component) UnmarshalJSON(data []byte) error { var parsed Button err = json.Unmarshal(data, &parsed) c.ComponentData = parsed - case ComponentSelectMenu: + case ComponentStringSelect: var parsed SelectMenu err = json.Unmarshal(data, &parsed) c.ComponentData = parsed diff --git a/objects/interaction/component/component_channel_select.go b/objects/interaction/component/component_channel_select.go index 61a2814..27c8602 100644 --- a/objects/interaction/component/component_channel_select.go +++ b/objects/interaction/component/component_channel_select.go @@ -2,16 +2,20 @@ package component import ( "encoding/json" + + "github.com/TicketsBot-cloud/gdl/objects/channel" ) type ChannelSelect struct { - CustomId string `json:"custom_id"` - Options []SelectOption `json:"options"` - Placeholder string `json:"placeholder,omitempty"` - MinValues *int `json:"min_values,omitempty"` - MaxValues *int `json:"max_values,omitempty"` - Disabled *bool `json:"disabled"` - Required *bool `json:"required,omitempty"` + Id *int `json:"id,omitempty"` + CustomId string `json:"custom_id"` + ChannelTypes []channel.ChannelType `json:"channel_types,omitempty"` + Placeholder string `json:"placeholder,omitempty"` + DefaultValues []SelectDefaultValue `json:"default_values,omitempty"` + MinValues *int `json:"min_values,omitempty"` + MaxValues *int `json:"max_values,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + Required *bool `json:"required,omitempty"` } func (i ChannelSelect) Type() ComponentType { diff --git a/objects/interaction/component/component_checkbox.go b/objects/interaction/component/component_checkbox.go index 6e3ec76..80a5b58 100644 --- a/objects/interaction/component/component_checkbox.go +++ b/objects/interaction/component/component_checkbox.go @@ -3,8 +3,11 @@ package component import "encoding/json" type Checkbox struct { - CustomId string `json:"custom_id"` - Default bool `json:"default,omitempty"` + Id *int `json:"id,omitempty"` + CustomId string `json:"custom_id"` + Label string `json:"label"` + Description *string `json:"description,omitempty"` + Default bool `json:"default,omitempty"` } func (c Checkbox) Type() ComponentType { diff --git a/objects/interaction/component/component_checkbox_group.go b/objects/interaction/component/component_checkbox_group.go index 156a11f..6e21519 100644 --- a/objects/interaction/component/component_checkbox_group.go +++ b/objects/interaction/component/component_checkbox_group.go @@ -3,11 +3,12 @@ package component import "encoding/json" type CheckboxGroup struct { - CustomId string `json:"custom_id"` - Options []CheckboxGroupOption `json:"options"` - MinValues *int `json:"min_values,omitempty"` - MaxValues *int `json:"max_values,omitempty"` - Required *bool `json:"required,omitempty"` + Id *int `json:"id,omitempty"` + CustomId string `json:"custom_id"` + Options []CheckboxGroupOption `json:"options"` + MinValues *int `json:"min_values,omitempty"` + MaxValues *int `json:"max_values,omitempty"` + Required *bool `json:"required,omitempty"` } type CheckboxGroupOption struct { diff --git a/objects/interaction/component/component_container.go b/objects/interaction/component/component_container.go index d88405f..5c97478 100644 --- a/objects/interaction/component/component_container.go +++ b/objects/interaction/component/component_container.go @@ -5,6 +5,7 @@ import ( ) type Container struct { + Id *int `json:"id,omitempty"` Components []Component `json:"components"` AccentColor *int `json:"accent_color,omitempty"` Spoiler *bool `json:"spoiler,omitempty"` diff --git a/objects/interaction/component/component_file.go b/objects/interaction/component/component_file.go index 9196741..35454d4 100644 --- a/objects/interaction/component/component_file.go +++ b/objects/interaction/component/component_file.go @@ -5,6 +5,7 @@ import ( ) type File struct { + Id *int `json:"id,omitempty"` File UnfurledMediaItem `json:"file"` Spoiler *bool `json:"spoiler,omitempty"` } diff --git a/objects/interaction/component/component_file_upload.go b/objects/interaction/component/component_file_upload.go index fa164cd..3f5da32 100644 --- a/objects/interaction/component/component_file_upload.go +++ b/objects/interaction/component/component_file_upload.go @@ -3,6 +3,7 @@ package component import "encoding/json" type FileUpload struct { + Id *int `json:"id,omitempty"` CustomId string `json:"custom_id"` MinValues *int `json:"min_values,omitempty"` MaxValues *int `json:"max_values,omitempty"` diff --git a/objects/interaction/component/component_label.go b/objects/interaction/component/component_label.go index ccd15c0..d0a3f33 100644 --- a/objects/interaction/component/component_label.go +++ b/objects/interaction/component/component_label.go @@ -5,9 +5,10 @@ import ( ) type Label struct { + Id *int `json:"id,omitempty"` Label string `json:"label"` Description *string `json:"description,omitempty"` - Component Component `json:"component"` // This can only be string select or text input + Component Component `json:"component"` } func (i Label) Type() ComponentType { diff --git a/objects/interaction/component/component_media_gallery.go b/objects/interaction/component/component_media_gallery.go index 25a99b7..6fc8108 100644 --- a/objects/interaction/component/component_media_gallery.go +++ b/objects/interaction/component/component_media_gallery.go @@ -5,11 +5,12 @@ import ( ) type MediaGallery struct { + Id *int `json:"id,omitempty"` Items []MediaGalleryItem `json:"items"` } type MediaGalleryItem struct { - Media UnfurledMediaItem `json:"media,omitempty"` + Media UnfurledMediaItem `json:"media"` Description *string `json:"description,omitempty"` Spoiler *bool `json:"spoiler,omitempty"` } diff --git a/objects/interaction/component/component_mentionable_select.go b/objects/interaction/component/component_mentionable_select.go index 0d910bc..3a6f404 100644 --- a/objects/interaction/component/component_mentionable_select.go +++ b/objects/interaction/component/component_mentionable_select.go @@ -5,13 +5,14 @@ import ( ) type MentionableSelect struct { - CustomId string `json:"custom_id"` - Options []SelectOption `json:"options"` - Placeholder string `json:"placeholder,omitempty"` - MinValues *int `json:"min_values,omitempty"` - MaxValues *int `json:"max_values,omitempty"` - Disabled *bool `json:"disabled"` - Required *bool `json:"required,omitempty"` + Id *int `json:"id,omitempty"` + CustomId string `json:"custom_id"` + Placeholder string `json:"placeholder,omitempty"` + DefaultValues []SelectDefaultValue `json:"default_values,omitempty"` + MinValues *int `json:"min_values,omitempty"` + MaxValues *int `json:"max_values,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + Required *bool `json:"required,omitempty"` } func (i MentionableSelect) Type() ComponentType { diff --git a/objects/interaction/component/component_radio_group.go b/objects/interaction/component/component_radio_group.go index 7461cd6..a35f92a 100644 --- a/objects/interaction/component/component_radio_group.go +++ b/objects/interaction/component/component_radio_group.go @@ -3,6 +3,7 @@ package component import "encoding/json" type RadioGroup struct { + Id *int `json:"id,omitempty"` CustomId string `json:"custom_id"` Options []RadioGroupOption `json:"options"` Required *bool `json:"required,omitempty"` diff --git a/objects/interaction/component/component_role_select.go b/objects/interaction/component/component_role_select.go index 5e0a2d7..1dd6b91 100644 --- a/objects/interaction/component/component_role_select.go +++ b/objects/interaction/component/component_role_select.go @@ -5,13 +5,14 @@ import ( ) type RoleSelect struct { - CustomId string `json:"custom_id"` - Options []SelectOption `json:"options"` - Placeholder string `json:"placeholder,omitempty"` - MinValues *int `json:"min_values,omitempty"` - MaxValues *int `json:"max_values,omitempty"` - Disabled *bool `json:"disabled"` - Required *bool `json:"required,omitempty"` + Id *int `json:"id,omitempty"` + CustomId string `json:"custom_id"` + Placeholder string `json:"placeholder,omitempty"` + DefaultValues []SelectDefaultValue `json:"default_values,omitempty"` + MinValues *int `json:"min_values,omitempty"` + MaxValues *int `json:"max_values,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + Required *bool `json:"required,omitempty"` } func (i RoleSelect) Type() ComponentType { diff --git a/objects/interaction/component/component_section.go b/objects/interaction/component/component_section.go index 2fea6d4..43187ed 100644 --- a/objects/interaction/component/component_section.go +++ b/objects/interaction/component/component_section.go @@ -5,8 +5,9 @@ import ( ) type Section struct { + Id *int `json:"id,omitempty"` Components []Component `json:"components"` - Accessory Component `json:"accessory,omitempty"` + Accessory Component `json:"accessory"` } func (i Section) Type() ComponentType { diff --git a/objects/interaction/component/component_separator.go b/objects/interaction/component/component_separator.go index 40b9d20..7b3553d 100644 --- a/objects/interaction/component/component_separator.go +++ b/objects/interaction/component/component_separator.go @@ -5,6 +5,7 @@ import ( ) type Separator struct { + Id *int `json:"id,omitempty"` Divider *bool `json:"divider,omitempty"` Spacing *int `json:"spacing,omitempty"` } diff --git a/objects/interaction/component/component_text_display.go b/objects/interaction/component/component_text_display.go index f1cd1ef..45a61dc 100644 --- a/objects/interaction/component/component_text_display.go +++ b/objects/interaction/component/component_text_display.go @@ -5,6 +5,7 @@ import ( ) type TextDisplay struct { + Id *int `json:"id,omitempty"` Content string `json:"content"` } diff --git a/objects/interaction/component/component_thumbnail.go b/objects/interaction/component/component_thumbnail.go index 84ca046..bc526b5 100644 --- a/objects/interaction/component/component_thumbnail.go +++ b/objects/interaction/component/component_thumbnail.go @@ -5,17 +5,18 @@ import ( ) type Thumbnail struct { - Media UnfurledMediaItem `json:"media,omitempty"` + Id *int `json:"id,omitempty"` + Media UnfurledMediaItem `json:"media"` Description *string `json:"description,omitempty"` Spoiler *bool `json:"spoiler,omitempty"` } type UnfurledMediaItem struct { - Url string `json:"url"` - ProxyUrl string `json:"proxy_url"` - Height int `json:"height"` - Width int `json:"width"` - ContentType string `json:"content_type"` + Url string `json:"url"` + ProxyUrl *string `json:"proxy_url,omitempty"` + Height *int `json:"height,omitempty"` + Width *int `json:"width,omitempty"` + ContentType *string `json:"content_type,omitempty"` } func (i Thumbnail) Type() ComponentType { diff --git a/objects/interaction/component/component_user_select.go b/objects/interaction/component/component_user_select.go index c73a6a9..f9aa0d7 100644 --- a/objects/interaction/component/component_user_select.go +++ b/objects/interaction/component/component_user_select.go @@ -5,12 +5,14 @@ import ( ) type UserSelect struct { - CustomId string `json:"custom_id"` - Placeholder string `json:"placeholder,omitempty"` - MinValues *int `json:"min_values,omitempty"` - MaxValues *int `json:"max_values,omitempty"` - Disabled bool `json:"disabled"` - Required *bool `json:"required,omitempty"` + Id *int `json:"id,omitempty"` + CustomId string `json:"custom_id"` + Placeholder string `json:"placeholder,omitempty"` + DefaultValues []SelectDefaultValue `json:"default_values,omitempty"` + MinValues *int `json:"min_values,omitempty"` + MaxValues *int `json:"max_values,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Required *bool `json:"required,omitempty"` } func (i UserSelect) Type() ComponentType { diff --git a/objects/interaction/component/componentactionrow.go b/objects/interaction/component/componentactionrow.go index 2b1ef5f..4959a6f 100644 --- a/objects/interaction/component/componentactionrow.go +++ b/objects/interaction/component/componentactionrow.go @@ -3,7 +3,8 @@ package component import "encoding/json" type ActionRow struct { - Components []Component + Id *int `json:"id,omitempty"` + Components []Component `json:"components"` } func (a ActionRow) Type() ComponentType { @@ -17,14 +18,14 @@ func (a ActionRow) MarshalJSON() ([]byte, error) { Type ComponentType `json:"type"` WrappedActionRow }{ - Type: ComponentButton, + Type: ComponentActionRow, WrappedActionRow: WrappedActionRow(a), }) } func BuildActionRow(components ...Component) Component { return Component{ - Type: ComponentActionRow, + Type: ComponentActionRow, ComponentData: ActionRow{ Components: components, }, diff --git a/objects/interaction/component/componentbutton.go b/objects/interaction/component/componentbutton.go index 014e832..c2699b1 100644 --- a/objects/interaction/component/componentbutton.go +++ b/objects/interaction/component/componentbutton.go @@ -7,13 +7,14 @@ import ( ) type Button struct { - Label string `json:"label"` + Id *int `json:"id,omitempty"` + Label string `json:"label,omitempty"` CustomId string `json:"custom_id,omitempty"` Style ButtonStyle `json:"style"` Emoji *emoji.Emoji `json:"emoji,omitempty"` SkuId *uint64 `json:"sku_id,string,omitempty"` Url *string `json:"url,omitempty"` - Disabled bool `json:"disabled"` + Disabled bool `json:"disabled,omitempty"` } func (b Button) Type() ComponentType { diff --git a/objects/interaction/component/inputtext.go b/objects/interaction/component/inputtext.go index 6713e19..e099b3a 100644 --- a/objects/interaction/component/inputtext.go +++ b/objects/interaction/component/inputtext.go @@ -5,6 +5,7 @@ import ( ) type InputText struct { + Id *int `json:"id,omitempty"` Style TextStyleTypes `json:"style"` CustomId string `json:"custom_id"` Label *string `json:"label,omitempty"` diff --git a/objects/interaction/component/selectmenu.go b/objects/interaction/component/selectmenu.go index ee17a61..4dced2b 100644 --- a/objects/interaction/component/selectmenu.go +++ b/objects/interaction/component/selectmenu.go @@ -7,12 +7,13 @@ import ( ) type SelectMenu struct { + Id *int `json:"id,omitempty"` CustomId string `json:"custom_id"` Options []SelectOption `json:"options"` Placeholder string `json:"placeholder,omitempty"` MinValues *int `json:"min_values,omitempty"` MaxValues *int `json:"max_values,omitempty"` - Disabled bool `json:"disabled"` + Disabled bool `json:"disabled,omitempty"` Required *bool `json:"required,omitempty"` } @@ -21,11 +22,24 @@ type SelectOption struct { Value string `json:"value"` Description *string `json:"description,omitempty"` Emoji *emoji.Emoji `json:"emoji,omitempty"` - Default bool `json:"default"` + Default bool `json:"default,omitempty"` +} + +type SelectDefaultValueType string + +const ( + SelectDefaultValueTypeRole SelectDefaultValueType = "role" + SelectDefaultValueTypeUser SelectDefaultValueType = "user" + SelectDefaultValueTypeChannel SelectDefaultValueType = "channel" +) + +type SelectDefaultValue struct { + Id uint64 `json:"id,string"` + Type SelectDefaultValueType `json:"type"` } func (s SelectMenu) Type() ComponentType { - return ComponentSelectMenu + return ComponentStringSelect } func (s SelectMenu) MarshalJSON() ([]byte, error) { @@ -35,14 +49,14 @@ func (s SelectMenu) MarshalJSON() ([]byte, error) { Type ComponentType `json:"type"` WrappedSelectMenu }{ - Type: ComponentSelectMenu, + Type: ComponentStringSelect, WrappedSelectMenu: WrappedSelectMenu(s), }) } func BuildSelectMenu(data SelectMenu) Component { return Component{ - Type: ComponentSelectMenu, + Type: ComponentStringSelect, ComponentData: data, } } diff --git a/objects/interaction/componentinteractiondata.go b/objects/interaction/componentinteractiondata.go index 6ad8abd..89636df 100644 --- a/objects/interaction/componentinteractiondata.go +++ b/objects/interaction/componentinteractiondata.go @@ -58,7 +58,7 @@ type SelectMenuInteractionData struct { } func (d SelectMenuInteractionData) Type() component.ComponentType { - return component.ComponentSelectMenu + return component.ComponentStringSelect } type FileUploadInteractionData struct { @@ -118,7 +118,7 @@ func (d *MessageComponentInteractionData) UnmarshalJSON(data []byte) error { var parsed ButtonInteractionData err = json.Unmarshal(data, &parsed) d.IMessageComponentInteractionData = parsed - case component.ComponentSelectMenu: + case component.ComponentStringSelect: var parsed SelectMenuInteractionData err = json.Unmarshal(data, &parsed) d.IMessageComponentInteractionData = parsed diff --git a/objects/interaction/interaction.go b/objects/interaction/interaction.go index 77e169e..a1ab54b 100644 --- a/objects/interaction/interaction.go +++ b/objects/interaction/interaction.go @@ -19,18 +19,21 @@ type Interaction struct { type InteractionMetadata struct { Interaction - Id uint64 `json:"id,string"` - ApplicationId uint64 `json:"application_id,string"` - GuildId objects.NullableSnowflake `json:"guild_id"` - ChannelId uint64 `json:"channel_id,string"` - Channel channel.PartialChannel `json:"channel"` - Member *member.Member `json:"member"` - User *user.User `json:"user"` - Token string `json:"token"` - AppPermissions uint64 `json:"app_permissions,string"` - Locale string `json:"locale"` - GuildLocale string `json:"guild_locale"` - Entitlements []entitlement.Entitlement `json:"entitlements"` + Id uint64 `json:"id,string"` + ApplicationId uint64 `json:"application_id,string"` + GuildId objects.NullableSnowflake `json:"guild_id"` + ChannelId uint64 `json:"channel_id,string"` + Channel channel.PartialChannel `json:"channel"` + Member *member.Member `json:"member"` + User *user.User `json:"user"` + Token string `json:"token"` + AppPermissions uint64 `json:"app_permissions,string"` + Locale *string `json:"locale,omitempty"` + GuildLocale *string `json:"guild_locale,omitempty"` + Entitlements []entitlement.Entitlement `json:"entitlements"` + AuthorizingIntegrationOwners map[string]string `json:"authorizing_integration_owners"` + Context *InteractionContextType `json:"context,omitempty"` + AttachmentSizeLimit int `json:"attachment_size_limit"` } type InteractionType uint8 @@ -58,9 +61,10 @@ type ApplicationCommandInteractionData struct { Id uint64 `json:"id,string"` Name string `json:"name"` Type ApplicationCommandType `json:"type"` - Resolved ResolvedData `json:"resolved"` - Options []ApplicationCommandInteractionDataOption `json:"options"` - TargetId uint64 `json:"target_id,string"` + Resolved *ResolvedData `json:"resolved,omitempty"` + Options []ApplicationCommandInteractionDataOption `json:"options,omitempty"` + GuildId *uint64 `json:"guild_id,string,omitempty"` + TargetId *uint64 `json:"target_id,string,omitempty"` } type MessageComponentInteraction struct { diff --git a/objects/interaction/interactioncontext.go b/objects/interaction/interactioncontext.go index 9d3f469..3af3188 100644 --- a/objects/interaction/interactioncontext.go +++ b/objects/interaction/interactioncontext.go @@ -3,7 +3,7 @@ package interaction type InteractionContextType int8 const ( - InteractionContextGuild InteractionContextType = 0 - InteractionContextBotDM InteractionContextType = 1 - InteractionContextPrivateChannel InteractionContextType = 2 + InteractionContextGuild InteractionContextType = iota + InteractionContextBotDM + InteractionContextPrivateChannel ) diff --git a/objects/interaction/resolved.go b/objects/interaction/resolved.go index c2c5926..62d2746 100644 --- a/objects/interaction/resolved.go +++ b/objects/interaction/resolved.go @@ -10,10 +10,10 @@ import ( ) type ResolvedData struct { - Users map[objects.Snowflake]user.User `json:"users"` - Members map[objects.Snowflake]member.Member `json:"members"` - Roles map[objects.Snowflake]guild.Role `json:"roles"` - Channels map[objects.Snowflake]channel.Channel `json:"channels"` - Messages map[objects.Snowflake]message.Message `json:"messages"` - Attachments map[objects.Snowflake]channel.Attachment `json:"attachments"` + Users map[objects.Snowflake]user.User `json:"users,omitempty"` + Members map[objects.Snowflake]member.Member `json:"members,omitempty"` + Roles map[objects.Snowflake]guild.Role `json:"roles,omitempty"` + Channels map[objects.Snowflake]channel.Channel `json:"channels,omitempty"` + Messages map[objects.Snowflake]message.Message `json:"messages,omitempty"` + Attachments map[objects.Snowflake]channel.Attachment `json:"attachments,omitempty"` } diff --git a/objects/interaction/response.go b/objects/interaction/response.go index ef09337..ac1e4ca 100644 --- a/objects/interaction/response.go +++ b/objects/interaction/response.go @@ -54,7 +54,7 @@ type ResponseAckWithSource struct { func NewResponseAckWithSource(flags uint) ResponseAckWithSource { return ResponseAckWithSource{ Response: Response{ - Type: ResponseTypeACKWithSource, + Type: ResponseTypeDeferredChannelMessageWithSource, }, Data: struct { Flags uint `json:"flags"` @@ -74,7 +74,7 @@ type ResponseDeferredMessageUpdate struct { func NewResponseDeferredMessageUpdate() ResponseDeferredMessageUpdate { return ResponseDeferredMessageUpdate{ Response: Response{ - Type: ResponseTypeDeferredMessageUpdate, + Type: ResponseTypeDeferredUpdateMessage, }, } } diff --git a/objects/interaction/responsetype.go b/objects/interaction/responsetype.go index 319bc6e..3400953 100644 --- a/objects/interaction/responsetype.go +++ b/objects/interaction/responsetype.go @@ -3,14 +3,13 @@ package interaction type ResponseType uint8 const ( - ResponseTypePong ResponseType = iota + 1 - _ - _ - ResponseTypeChannelMessageWithSource - ResponseTypeACKWithSource - ResponseTypeDeferredMessageUpdate - ResponseTypeUpdateMessage - ResponseTypeApplicationCommandAutoCompleteResult - ResponseTypeModal - ResponseTypePremiumRequired + ResponseTypePong ResponseType = 1 + ResponseTypeChannelMessageWithSource ResponseType = 4 + ResponseTypeDeferredChannelMessageWithSource ResponseType = 5 + ResponseTypeDeferredUpdateMessage ResponseType = 6 + ResponseTypeUpdateMessage ResponseType = 7 + ResponseTypeApplicationCommandAutoCompleteResult ResponseType = 8 + ResponseTypeModal ResponseType = 9 + ResponseTypePremiumRequired ResponseType = 10 // Deprecated + ResponseTypeLaunchActivity ResponseType = 12 ) diff --git a/objects/invite/invite.go b/objects/invite/invite.go index 9a78217..b51df8e 100644 --- a/objects/invite/invite.go +++ b/objects/invite/invite.go @@ -3,26 +3,43 @@ package invite import ( "time" + "github.com/TicketsBot-cloud/gdl/objects/application" "github.com/TicketsBot-cloud/gdl/objects/channel" "github.com/TicketsBot-cloud/gdl/objects/guild" + "github.com/TicketsBot-cloud/gdl/objects/guild/scheduledevent" "github.com/TicketsBot-cloud/gdl/objects/user" ) -type TargetUserType int +type InviteType int const ( - STREAM TargetUserType = 1 + InviteTypeGuild InviteType = iota + InviteTypeGroupDm + InviteTypeFriend +) + +type InviteTargetType int + +const ( + InviteTargetTypeStream InviteTargetType = iota + 1 + InviteTargetTypeEmbeddedApplication ) type Invite struct { - Code string `json:"code"` - Guild guild.Guild `json:"guild"` - Channel channel.Channel `json:"channel"` - Inviter user.User `json:"inviter"` - TargetUser user.User `json:"target_user"` - TargetUserType TargetUserType `json:"target_user_type"` - ApproximatePresenceCount int `json:"approximate_presence_count"` - ApproximateMemberCount int `json:"approximate_member_count"` + Type InviteType `json:"type"` + Code string `json:"code"` + Guild *guild.Guild `json:"guild,omitempty"` + Channel *channel.PartialChannel `json:"channel,omitempty"` + Inviter *user.User `json:"inviter,omitempty"` + TargetType InviteTargetType `json:"target_type,omitempty"` + TargetUser *user.User `json:"target_user,omitempty"` + TargetApplication *application.Application `json:"target_application,omitempty"` + ApproximatePresenceCount int `json:"approximate_presence_count,omitempty"` + ApproximateMemberCount int `json:"approximate_member_count,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` + GuildScheduledEvent *scheduledevent.GuildScheduledEvent `json:"guild_scheduled_event,omitempty"` + Flags *int `json:"flags,omitempty"` + Roles []guild.Role `json:"roles,omitempty"` } type InviteMetadata struct { diff --git a/objects/member/cachedmember.go b/objects/member/cachedmember.go index 5b5f956..e7b82a2 100644 --- a/objects/member/cachedmember.go +++ b/objects/member/cachedmember.go @@ -7,20 +7,20 @@ import ( ) type CachedMember struct { - Nick string `json:"nick"` + Nick *string `json:"nick"` Roles []uint64 `json:"roles"` JoinedAt time.Time `json:"joined_at"` - PremiumSince *time.Time `json:"premium_since"` // when the user started boosting the guild + PremiumSince *time.Time `json:"premium_since"` Deaf bool `json:"deaf"` Mute bool `json:"mute"` } -func (m *CachedMember) ToMember(user user.User) Member { +func (m *CachedMember) ToMember(u user.User) Member { return Member{ - User: user, + User: &u, Nick: m.Nick, Roles: m.Roles, - JoinedAt: m.JoinedAt, + JoinedAt: &m.JoinedAt, PremiumSince: m.PremiumSince, Deaf: m.Deaf, Mute: m.Mute, diff --git a/objects/member/member.go b/objects/member/member.go index 3be6383..3460385 100644 --- a/objects/member/member.go +++ b/objects/member/member.go @@ -8,14 +8,21 @@ import ( ) type Member struct { - User user.User `json:"user"` - Nick string `json:"nick"` - Roles utils.Uint64StringSlice `json:"roles"` - JoinedAt time.Time `json:"joined_at"` - PremiumSince *time.Time `json:"premium_since"` // when the user started boosting the guild - Deaf bool `json:"deaf"` - Mute bool `json:"mute"` - Permissions uint64 `json:"permissions,string"` + User *user.User `json:"user"` + Nick *string `json:"nick"` + Avatar *string `json:"avatar"` + Banner *string `json:"banner"` + Roles utils.Uint64StringSlice `json:"roles"` + JoinedAt *time.Time `json:"joined_at"` + PremiumSince *time.Time `json:"premium_since"` + Deaf bool `json:"deaf"` + Mute bool `json:"mute"` + Flags int `json:"flags"` + Pending *bool `json:"pending,omitempty"` + Permissions uint64 `json:"permissions,string,omitempty"` + CommunicationDisabledUntil *time.Time `json:"communication_disabled_until,omitempty"` + AvatarDecorationData *user.AvatarDecorationData `json:"avatar_decoration_data,omitempty"` + Collectibles *user.UserCollectibles `json:"collectibles,omitempty"` } func (m *Member) HasRole(roleId uint64) bool { @@ -28,10 +35,15 @@ func (m *Member) HasRole(roleId uint64) bool { } func (m *Member) ToCachedMember() CachedMember { + var joinedAt time.Time + if m.JoinedAt != nil { + joinedAt = *m.JoinedAt + } + return CachedMember{ Nick: m.Nick, Roles: m.Roles, - JoinedAt: m.JoinedAt, + JoinedAt: joinedAt, PremiumSince: m.PremiumSince, Deaf: m.Deaf, Mute: m.Mute, diff --git a/objects/sku/sku.go b/objects/sku/sku.go new file mode 100644 index 0000000..e4e684d --- /dev/null +++ b/objects/sku/sku.go @@ -0,0 +1,29 @@ +package sku + +type SKUType int + +const ( + _ SKUType = iota + 1 + SKUTypeDurable + SKUTypeConsumable + _ + SKUTypeSubscription + SKUTypeSubscriptionGroup +) + +type SKUFlag uint32 + +const ( + SKUFlagAvailable SKUFlag = 1 << 2 + SKUFlagGuildSubscription SKUFlag = 1 << 7 + SKUFlagUserSubscription SKUFlag = 1 << 8 +) + +type SKU struct { + Id uint64 `json:"id,string"` + Type SKUType `json:"type"` + ApplicationId uint64 `json:"application_id,string"` + Name string `json:"name"` + Slug string `json:"slug"` + Flags SKUFlag `json:"flags"` +} diff --git a/objects/subscription/subscription.go b/objects/subscription/subscription.go new file mode 100644 index 0000000..0aa9bb3 --- /dev/null +++ b/objects/subscription/subscription.go @@ -0,0 +1,28 @@ +package subscription + +import ( + "time" + + "github.com/TicketsBot-cloud/gdl/utils" +) + +type SubscriptionStatus int + +const ( + SubscriptionStatusActive SubscriptionStatus = iota + SubscriptionStatusEnding + SubscriptionStatusInactive +) + +type Subscription struct { + Id uint64 `json:"id,string"` + UserId uint64 `json:"user_id,string"` + SkuIds utils.Uint64StringSlice `json:"sku_ids"` + EntitlementIds utils.Uint64StringSlice `json:"entitlement_ids"` + RenewalSkuIds utils.Uint64StringSlice `json:"renewal_sku_ids,omitempty"` + CurrentPeriodStart time.Time `json:"current_period_start"` + CurrentPeriodEnd time.Time `json:"current_period_end"` + Status SubscriptionStatus `json:"status"` + CanceledAt *time.Time `json:"canceled_at,omitempty"` + Country *string `json:"country,omitempty"` +} diff --git a/objects/user/activity.go b/objects/user/activity.go index 9e096c0..4f29806 100644 --- a/objects/user/activity.go +++ b/objects/user/activity.go @@ -3,15 +3,22 @@ package user type Activity struct { Name string `json:"name"` Type ActivityType `json:"type"` - Url string `json:"url,omitempty"` + Url *string `json:"url,omitempty"` + CreatedAt int `json:"created_at,omitempty"` Timestamps *Timestamps `json:"timestamps,omitempty"` ApplicationId uint64 `json:"application_id,string,omitempty"` - Details string `json:"details,omitempty"` - State string `json:"state,omitempty"` + Details *string `json:"details,omitempty"` + State *string `json:"state,omitempty"` // TODO: Figure out how to handle emoji w/o import cycle - Party *Party `json:"party,omitempty"` - Assets *Asset `json:"assets,omitempty"` - Secret *Secret `json:"secret,omitempty"` - Instance bool `json:"instance,omitempty"` - Flags int `json:"flags,omitempty"` // TODO: Wrap this + Party *Party `json:"party,omitempty"` + Assets *Asset `json:"assets,omitempty"` + Secrets *Secret `json:"secrets,omitempty"` + Instance *bool `json:"instance,omitempty"` + Flags int `json:"flags,omitempty"` + Buttons []ActivityButton `json:"buttons,omitempty"` +} + +type ActivityButton struct { + Label string `json:"label"` + Url string `json:"url"` } diff --git a/objects/user/asset.go b/objects/user/asset.go index 9b96f6e..df648cb 100644 --- a/objects/user/asset.go +++ b/objects/user/asset.go @@ -1,8 +1,11 @@ package user type Asset struct { - LargeImage string `json:"large_image,omitempty"` - LargeText string `json:"large_text,omitempty"` - SmallImage string `json:"small_image,omitempty"` - SmallText string `json:"small_text,omitempty"` + InviteCoverImage string `json:"invite_cover_image,omitempty"` + LargeImage string `json:"large_image,omitempty"` + LargeText string `json:"large_text,omitempty"` + LargeUrl string `json:"large_url,omitempty"` + SmallImage string `json:"small_image,omitempty"` + SmallText string `json:"small_text,omitempty"` + SmallUrl string `json:"small_url,omitempty"` } diff --git a/objects/user/avatar.go b/objects/user/avatar.go index 94ad3e8..8d590db 100644 --- a/objects/user/avatar.go +++ b/objects/user/avatar.go @@ -7,7 +7,7 @@ import ( type Avatar struct { Animated bool - data []uint64 + data []uint64 } func (a *Avatar) String() string { @@ -67,5 +67,3 @@ func (a *Avatar) UnmarshalJSON(data []byte) error { return nil } - - diff --git a/objects/user/clientstatus.go b/objects/user/clientstatus.go index 1340ab9..1c2cbcf 100644 --- a/objects/user/clientstatus.go +++ b/objects/user/clientstatus.go @@ -1,7 +1,7 @@ package user type ClientStatus struct { - Desktop ClientStatusType `json:"desktop"` - Mobile ClientStatusType `json:"mobile"` - Web ClientStatusType `json:"web"` + Desktop ClientStatusType `json:"desktop,omitempty"` + Mobile ClientStatusType `json:"mobile,omitempty"` + Web ClientStatusType `json:"web,omitempty"` } diff --git a/objects/user/clientstatustype.go b/objects/user/clientstatustype.go index 105c016..356b947 100644 --- a/objects/user/clientstatustype.go +++ b/objects/user/clientstatustype.go @@ -4,8 +4,8 @@ type ClientStatusType string const ( ClientStatusTypeOnline ClientStatusType = "online" - ClientStatusTypeIdle ClientStatusType = "idle" ClientStatusTypeDoNotDisturb ClientStatusType = "dnd" + ClientStatusTypeIdle ClientStatusType = "idle" ClientStatusTypeInvisible ClientStatusType = "invisible" ClientStatusTypeOffline ClientStatusType = "offline" ) diff --git a/objects/user/presence.go b/objects/user/presence.go index 939f1d0..5c26991 100644 --- a/objects/user/presence.go +++ b/objects/user/presence.go @@ -8,12 +8,11 @@ import ( type Presence struct { User User `json:"user"` - Roles utils.Uint64StringSlice `json:"roles"` - Game Activity `json:"name"` - GuildId uint64 `json:"guild_id,string"` + GuildId *uint64 `json:"guild_id,string,omitempty"` Status string `json:"status"` Activities []Activity `json:"activities"` ClientStatus ClientStatus `json:"client_status"` - PremiumSince *time.Time `json:"premium_since"` - Nick string `json:"nick"` + Roles utils.Uint64StringSlice `json:"roles,omitempty"` + PremiumSince *time.Time `json:"premium_since,omitempty"` + Nick *string `json:"nick,omitempty"` } diff --git a/objects/user/updatestatus.go b/objects/user/updatestatus.go index 8f34f7e..179c71b 100644 --- a/objects/user/updatestatus.go +++ b/objects/user/updatestatus.go @@ -1,17 +1,19 @@ package user type UpdateStatus struct { - Since int `json:"since"` // time since client went idle (unix epoch millis) - Game Activity `json:"game,omitempty"` - Status ClientStatusType `json:"status"` - Afk bool `json:"afk"` + Since *int `json:"since"` // unix time in ms when client went idle, null if not idle + Activities []Activity `json:"activities"` + Status ClientStatusType `json:"status"` + Afk bool `json:"afk"` } func BuildStatus(activityType ActivityType, status string) UpdateStatus { return UpdateStatus{ - Game: Activity{ - Name: status, - Type: activityType, + Activities: []Activity{ + { + Name: status, + Type: activityType, + }, }, Status: ClientStatusTypeOnline, } diff --git a/objects/user/user.go b/objects/user/user.go index 0c8d3ed..aa466ff 100644 --- a/objects/user/user.go +++ b/objects/user/user.go @@ -1,13 +1,82 @@ package user -import "fmt" +import ( + "fmt" + + "github.com/TicketsBot-cloud/gdl/objects" +) + +type UserFlag int + +const ( + UserFlagStaff UserFlag = 1 << 0 + UserFlagPartner UserFlag = 1 << 1 + UserFlagHypesquad UserFlag = 1 << 2 + UserFlagBugHunterLevel1 UserFlag = 1 << 3 + UserFlagHypesquadOnlineHouse1 UserFlag = 1 << 6 + UserFlagHypesquadOnlineHouse2 UserFlag = 1 << 7 + UserFlagHypesquadOnlineHouse3 UserFlag = 1 << 8 + UserFlagPremiumEarlySupporter UserFlag = 1 << 9 + UserFlagTeamPseudoUser UserFlag = 1 << 10 + UserFlagBugHunterLevel2 UserFlag = 1 << 14 + UserFlagVerifiedBot UserFlag = 1 << 16 + UserFlagVerifiedDeveloper UserFlag = 1 << 17 + UserFlagCertifiedModerator UserFlag = 1 << 18 + UserFlagBotHttpInteractions UserFlag = 1 << 19 +) + +type PremiumType int + +const ( + PremiumTypeNone PremiumType = 0 + PremiumTypeNitroClassic PremiumType = 1 + PremiumTypeNitro PremiumType = 2 + PremiumTypeNitroBasic PremiumType = 3 +) + +type AvatarDecorationData struct { + Asset string `json:"asset"` + SkuId uint64 `json:"sku_id,string"` +} + +type UserNameplate struct { + SkuId uint64 `json:"sku_id,string"` + Asset string `json:"asset"` + Label string `json:"label"` + Palette string `json:"palette"` +} + +type UserCollectibles struct { + Nameplate *UserNameplate `json:"nameplate,omitempty"` +} + +type UserPrimaryGuild struct { + IdentityGuildId objects.NullableSnowflake `json:"identity_guild_id"` + IdentityEnabled *bool `json:"identity_enabled,omitempty"` + Tag *string `json:"tag,omitempty"` + Badge *string `json:"badge,omitempty"` +} type User struct { - Id uint64 `json:"id,string"` - Username string `json:"username"` - GlobalName *string `json:"global_name"` - Avatar Avatar `json:"avatar"` - Bot bool `json:"bot"` + Id uint64 `json:"id,string"` + Username string `json:"username"` + Discriminator Discriminator `json:"discriminator"` + GlobalName *string `json:"global_name"` + Avatar Avatar `json:"avatar"` + Bot bool `json:"bot,omitempty"` + System *bool `json:"system,omitempty"` + MfaEnabled *bool `json:"mfa_enabled,omitempty"` + Banner *string `json:"banner,omitempty"` + AccentColor *int `json:"accent_color,omitempty"` + Locale *string `json:"locale,omitempty"` + Verified *bool `json:"verified,omitempty"` + Email *string `json:"email,omitempty"` + Flags *UserFlag `json:"flags,omitempty"` + PremiumType *PremiumType `json:"premium_type,omitempty"` + PublicFlags *UserFlag `json:"public_flags,omitempty"` + AvatarDecorationData *AvatarDecorationData `json:"avatar_decoration_data,omitempty"` + Collectibles *UserCollectibles `json:"collectibles,omitempty"` + PrimaryGuild *UserPrimaryGuild `json:"primary_guild,omitempty"` } // shortcut, ignores errors diff --git a/permission/permission.go b/permission/permission.go index 9d7e2f2..9056968 100644 --- a/permission/permission.go +++ b/permission/permission.go @@ -33,7 +33,7 @@ const ( ManageNicknames ManageRoles // Manage permissions ManageWebhooks - ManageEmojis + ManageGuildExpressions UseApplicationCommands RequestToSpeak ManageEvents @@ -134,8 +134,8 @@ func (p Permission) String() string { return "Manage Roles" case ManageWebhooks: return "Manage Webhooks" - case ManageEmojis: - return "Manage Emojis" + case ManageGuildExpressions: + return "Manage Guild Expressions" case UseApplicationCommands: return "Use Application Commands" case RequestToSpeak: @@ -174,6 +174,8 @@ func (p Permission) String() string { return "Use External Apps" case PinMessages: return "Pin Messages" + case BypassSlowmode: + return "Bypass Slowmode" default: return "Unknown Permission" } @@ -210,7 +212,7 @@ var AllPermissions = []Permission{ ManageNicknames, ManageRoles, ManageWebhooks, - ManageEmojis, + ManageGuildExpressions, UseApplicationCommands, RequestToSpeak, ManageEvents, @@ -230,4 +232,5 @@ var AllPermissions = []Permission{ SendPolls, UseExternalApps, PinMessages, + BypassSlowmode, } diff --git a/permission/permissioncalculator.go b/permission/permissioncalculator.go index 2330a12..52e2cbc 100644 --- a/permission/permissioncalculator.go +++ b/permission/permissioncalculator.go @@ -146,7 +146,7 @@ func GetChannelMemberPermissions(ctx context.Context, shard *gateway.Shard, user } for _, overwrite := range ch.PermissionOverwrites { - if overwrite.Type == channel.PermissionTypeMember && overwrite.Id == userId { + if overwrite.Type == channel.PermissionOverwriteTypeMember && overwrite.Id == userId { initialPermissions &= ^overwrite.Deny initialPermissions |= overwrite.Allow } @@ -177,7 +177,7 @@ func GetChannelTotalRolePermissions(ctx context.Context, shard *gateway.Shard, g for _, role := range roles { if memberRole == role.Id { for _, overwrite := range ch.PermissionOverwrites { - if overwrite.Type == channel.PermissionTypeRole && overwrite.Id == role.Id { + if overwrite.Type == channel.PermissionOverwriteTypeRole && overwrite.Id == role.Id { allow |= overwrite.Allow deny |= overwrite.Deny break @@ -217,7 +217,7 @@ func GetChannelBasePermissions(ctx context.Context, shard *gateway.Shard, guildI } for _, overwrite := range ch.PermissionOverwrites { - if overwrite.Type == channel.PermissionTypeRole && overwrite.Id == publicRole.Id { + if overwrite.Type == channel.PermissionOverwriteTypeRole && overwrite.Id == publicRole.Id { initialPermissions &= ^overwrite.Deny initialPermissions |= overwrite.Allow break diff --git a/rest/application.go b/rest/application.go index d6094b7..cf63451 100644 --- a/rest/application.go +++ b/rest/application.go @@ -2,6 +2,7 @@ package rest import ( "context" + "fmt" "github.com/TicketsBot-cloud/gdl/objects/application" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" @@ -23,15 +24,19 @@ func GetCurrentApplication(ctx context.Context, token string, rateLimiter *ratel } type EditCurrentApplicationData struct { - CustomInstallUrl *string `json:"custom_install_url,omitempty"` - Description *string `json:"description,omitempty"` - RoleConnectionsVerificationUrl *string `json:"role_connections_verification_url,omitempty"` - InstallParams *application.InstallParams `json:"install_params,omitempty"` - Flags *application.Flag `json:"flags,omitempty"` - // TODO: icon - // TODO: cover_image - InteractionsEndpointUrl *string `json:"interactions_endpoint_url,omitempty"` - Tags []string `json:"tags,omitempty"` + CustomInstallUrl *string `json:"custom_install_url,omitempty"` + Description *string `json:"description,omitempty"` + RoleConnectionsVerificationUrl *string `json:"role_connections_verification_url,omitempty"` + InstallParams *application.InstallParams `json:"install_params,omitempty"` + IntegrationTypesConfig map[application.ApplicationIntegrationType]application.ApplicationIntegrationTypeConfig `json:"integration_types_config,omitempty"` + Flags *application.Flag `json:"flags,omitempty"` + Icon *string `json:"icon,omitempty"` + CoverImage *string `json:"cover_image,omitempty"` + InteractionsEndpointUrl *string `json:"interactions_endpoint_url,omitempty"` + Tags []string `json:"tags,omitempty"` + EventWebhooksUrl *string `json:"event_webhooks_url,omitempty"` + EventWebhooksStatus *application.ApplicationEventWebhookStatus `json:"event_webhooks_status,omitempty"` + EventWebhooksTypes []string `json:"event_webhooks_types,omitempty"` } func EditCurrentApplication(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, data EditCurrentApplicationData) (application.Application, error) { @@ -47,3 +52,17 @@ func EditCurrentApplication(ctx context.Context, token string, rateLimiter *rate err, _ := endpoint.Request(ctx, token, data, &app) return app, err } + +func GetActivityInstance(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId uint64, instanceId string) (application.ActivityInstance, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/activity-instances/%s", applicationId, instanceId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteGetActivityInstance, applicationId), + RateLimiter: rateLimiter, + } + + var instance application.ActivityInstance + err, _ := endpoint.Request(ctx, token, nil, &instance) + return instance, err +} diff --git a/rest/auditlog.go b/rest/auditlog.go index 4a5ddfd..a8e47dd 100644 --- a/rest/auditlog.go +++ b/rest/auditlog.go @@ -15,7 +15,8 @@ type GetGuildAuditLogData struct { UserId uint64 ActionType auditlog.AuditLogEvent Before uint64 // audit log entry ID - Limit int + After uint64 // audit log entry ID + Limit int // 1-100, omitted if 0 } func (d *GetGuildAuditLogData) Query() string { @@ -33,10 +34,13 @@ func (d *GetGuildAuditLogData) Query() string { query.Set("before", strconv.FormatUint(d.Before, 10)) } - if d.Limit > 100 || d.Limit < 1 { - d.Limit = 50 + if d.After != 0 { + query.Set("after", strconv.FormatUint(d.After, 10)) + } + + if d.Limit >= 1 && d.Limit <= 100 { + query.Set("limit", strconv.Itoa(d.Limit)) } - query.Set("limit", strconv.Itoa(d.Limit)) return query.Encode() } diff --git a/rest/automoderation.go b/rest/automoderation.go new file mode 100644 index 0000000..1ebbbe0 --- /dev/null +++ b/rest/automoderation.go @@ -0,0 +1,110 @@ +package rest + +import ( + "context" + "fmt" + + "github.com/TicketsBot-cloud/gdl/objects/automoderation" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" + "github.com/TicketsBot-cloud/gdl/utils" +) + +type CreateAutoModerationRuleData struct { + Name string `json:"name"` + EventType automoderation.EventType `json:"event_type"` + TriggerType automoderation.TriggerType `json:"trigger_type"` + TriggerMetadata *automoderation.TriggerMetadata `json:"trigger_metadata,omitempty"` + Actions []automoderation.Action `json:"actions"` + Enabled *bool `json:"enabled,omitempty"` + ExemptRoles utils.Uint64StringSlice `json:"exempt_roles,omitempty"` + ExemptChannels utils.Uint64StringSlice `json:"exempt_channels,omitempty"` +} + +type ModifyAutoModerationRuleData struct { + Name *string `json:"name,omitempty"` + EventType *automoderation.EventType `json:"event_type,omitempty"` + TriggerMetadata *automoderation.TriggerMetadata `json:"trigger_metadata,omitempty"` + Actions []automoderation.Action `json:"actions,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + ExemptRoles utils.Uint64StringSlice `json:"exempt_roles,omitempty"` + ExemptChannels utils.Uint64StringSlice `json:"exempt_channels,omitempty"` +} + +func ListAutoModerationRules(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) ([]automoderation.Rule, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/auto-moderation/rules", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteListAutoModerationRules, guildId), + RateLimiter: rateLimiter, + } + + var rules []automoderation.Rule + if err, _ := endpoint.Request(ctx, token, nil, &rules); err != nil { + return nil, err + } + + return rules, nil +} + +func GetAutoModerationRule(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, ruleId uint64) (automoderation.Rule, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/auto-moderation/rules/%d", guildId, ruleId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetAutoModerationRule, guildId), + RateLimiter: rateLimiter, + } + + var rule automoderation.Rule + err, _ := endpoint.Request(ctx, token, nil, &rule) + return rule, err +} + +func CreateAutoModerationRule(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data CreateAutoModerationRuleData) (automoderation.Rule, error) { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/auto-moderation/rules", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteCreateAutoModerationRule, guildId), + RateLimiter: rateLimiter, + } + + var rule automoderation.Rule + if err, _ := endpoint.Request(ctx, token, data, &rule); err != nil { + return automoderation.Rule{}, err + } + + return rule, nil +} + +func ModifyAutoModerationRule(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, ruleId uint64, data ModifyAutoModerationRuleData) (automoderation.Rule, error) { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/auto-moderation/rules/%d", guildId, ruleId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyAutoModerationRule, guildId), + RateLimiter: rateLimiter, + } + + var rule automoderation.Rule + if err, _ := endpoint.Request(ctx, token, data, &rule); err != nil { + return automoderation.Rule{}, err + } + + return rule, nil +} + +func DeleteAutoModerationRule(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, ruleId uint64) error { + endpoint := request.Endpoint{ + RequestType: request.DELETE, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/auto-moderation/rules/%d", guildId, ruleId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteAutoModerationRule, guildId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, nil, nil) + return err +} diff --git a/rest/channel.go b/rest/channel.go index b0eb44f..e27fdcb 100644 --- a/rest/channel.go +++ b/rest/channel.go @@ -36,15 +36,20 @@ func GetChannel(ctx context.Context, token string, rateLimiter *ratelimit.Rateli } type ModifyChannelData struct { - Name string `json:"name,omitempty"` - Position int `json:"position,omitempty"` - Topic string `json:"topic,omitempty"` - Nsfw bool `json:"nsfw,omitempty"` - RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` - Bitrate int `json:"bitrate,omitempty"` - UserLimit int `json:"user_limit,omitempty"` - PermissionOverwrites []channel.PermissionOverwrite `json:"permission_overwrites,omitempty"` - ParentId uint64 `json:"parent_id,string,omitempty"` + Name string `json:"name,omitempty"` + Position int `json:"position,omitempty"` + Topic string `json:"topic,omitempty"` + Nsfw bool `json:"nsfw,omitempty"` + RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` + Bitrate int `json:"bitrate,omitempty"` + UserLimit int `json:"user_limit,omitempty"` + PermissionOverwrites []channel.PermissionOverwrite `json:"permission_overwrites,omitempty"` + ParentId uint64 `json:"parent_id,string,omitempty"` + DefaultAutoArchiveDuration *uint16 `json:"default_auto_archive_duration,omitempty"` + Flags *int `json:"flags,omitempty"` + DefaultThreadRateLimitPerUser *int `json:"default_thread_rate_limit_per_user,omitempty"` + DefaultSortOrder *int `json:"default_sort_order,omitempty"` + DefaultForumLayout *int `json:"default_forum_layout,omitempty"` *ThreadMetadataModifyData } @@ -323,19 +328,36 @@ func DeleteAllReactionsEmoji(ctx context.Context, token string, rateLimiter *rat } type EditMessageData struct { - Content string `json:"content"` - Embeds []*embed.Embed `json:"embeds"` - Flags uint `json:"flags"` // https://discord.com/developers/docs/resources/channel#message-object-message-flags TODO: Helper function - Components []component.Component `json:"components"` + Content string `json:"content,omitempty"` + Embeds []*embed.Embed `json:"embeds,omitempty"` + Flags uint `json:"flags,omitempty"` + AllowedMentions *message.AllowedMention `json:"allowed_mentions,omitempty"` + Components []component.Component `json:"components,omitempty"` + Attachments []request.Attachment `json:"attachments,omitempty"` +} + +func (d EditMessageData) GetAttachments() []request.Attachment { + return d.Attachments } func EditMessage(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId, messageId uint64, data EditMessageData) (message.Message, error) { - endpoint := request.Endpoint{ - RequestType: request.PATCH, - ContentType: request.ApplicationJson, - Endpoint: fmt.Sprintf("/channels/%d/messages/%d", channelId, messageId), - Route: ratelimit.NewChannelRoute(ratelimit.RouteEditMessage, channelId), - RateLimiter: rateLimiter, + var endpoint request.Endpoint + if len(data.Attachments) == 0 { + endpoint = request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/channels/%d/messages/%d", channelId, messageId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteEditMessage, channelId), + RateLimiter: rateLimiter, + } + } else { + endpoint = request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.MultipartFormData, + Endpoint: fmt.Sprintf("/channels/%d/messages/%d", channelId, messageId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteEditMessage, channelId), + RateLimiter: rateLimiter, + } } var message message.Message @@ -409,12 +431,13 @@ func GetChannelInvites(ctx context.Context, token string, rateLimiter *ratelimit } type CreateInviteData struct { - MaxAge int `json:"max_age"` // seconds, 0 = never - MaxUses int `json:"max_uses"` // 0 = unlimited - Temporary bool `json:"temporary"` - Unique bool `json:"unique"` - TargetUser uint64 `json:"target_user,string,omitempty"` - TargetUserType int `json:"target_user_type,omitempty"` + MaxAge int `json:"max_age"` // seconds, 0 = never + MaxUses int `json:"max_uses"` // 0 = unlimited + Temporary bool `json:"temporary"` + Unique bool `json:"unique"` + TargetType int `json:"target_type,omitempty"` + TargetUserId *uint64 `json:"target_user_id,string,omitempty"` + TargetApplicationId *uint64 `json:"target_application_id,string,omitempty"` } func CreateChannelInvite(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64, data CreateInviteData) (invite.Invite, error) { @@ -437,7 +460,7 @@ func CreateChannelInvite(ctx context.Context, token string, rateLimiter *ratelim func DeleteChannelPermissions(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId, overwriteId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/channels/%d/permissions/%d", channelId, overwriteId), Route: ratelimit.NewChannelRoute(ratelimit.RouteDeleteChannelPermission, channelId), RateLimiter: rateLimiter, @@ -447,6 +470,23 @@ func DeleteChannelPermissions(ctx context.Context, token string, rateLimiter *ra return err } +func FollowAnnouncementChannel(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId, webhookChannelId uint64) error { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/channels/%d/followers", channelId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteFollowNewsChannel, channelId), + RateLimiter: rateLimiter, + } + + body := map[string]interface{}{ + "webhook_channel_id": strconv.FormatUint(webhookChannelId, 10), + } + + err, _ := endpoint.Request(ctx, token, body, nil) + return err +} + func TriggerTypingIndicator(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64) error { endpoint := request.Endpoint{ RequestType: request.POST, @@ -568,11 +608,35 @@ func GetThreadMember(ctx context.Context, token string, rateLimiter *ratelimit.R return } -func ListThreadMembers(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64) (members []channel.ThreadMember, err error) { +type ListThreadMembersData struct { + WithMember bool // include guild member data for each thread member + After uint64 // get thread members after this user ID + Limit int // max 100 +} + +func (d *ListThreadMembersData) Query() string { + query := url.Values{} + + if d.WithMember { + query.Set("with_member", "true") + } + + if d.After != 0 { + query.Set("after", strconv.FormatUint(d.After, 10)) + } + + if d.Limit > 0 { + query.Set("limit", strconv.Itoa(d.Limit)) + } + + return query.Encode() +} + +func ListThreadMembers(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64, data ListThreadMembersData) (members []channel.ThreadMember, err error) { endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/channels/%d/thread-members", channelId), + Endpoint: fmt.Sprintf("/channels/%d/thread-members?%s", channelId, data.Query()), Route: ratelimit.NewChannelRoute(ratelimit.RouteListThreadMembers, channelId), RateLimiter: rateLimiter, } @@ -583,7 +647,8 @@ func ListThreadMembers(ctx context.Context, token string, rateLimiter *ratelimit type StartThreadWithMessageData struct { Name string `json:"name"` - AutoArchiveDuration uint16 `json:"auto_archive_duration"` + AutoArchiveDuration uint16 `json:"auto_archive_duration,omitempty"` + RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` } func StartThreadWithMessage(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId, messageId uint64, data StartThreadWithMessageData) (ch channel.Channel, err error) { @@ -601,9 +666,10 @@ func StartThreadWithMessage(ctx context.Context, token string, rateLimiter *rate type StartThreadWithoutMessageData struct { Name string `json:"name"` - AutoArchiveDuration uint16 `json:"auto_archive_duration"` - Type channel.ChannelType `json:"type"` - Invitable bool `json:"invitable"` + AutoArchiveDuration uint16 `json:"auto_archive_duration,omitempty"` + Type channel.ChannelType `json:"type,omitempty"` + Invitable bool `json:"invitable,omitempty"` + RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` } func StartThreadWithoutMessage(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64, data StartThreadWithoutMessageData) (ch channel.Channel, err error) { @@ -647,7 +713,7 @@ func (d *ListThreadsData) Query() string { query := url.Values{} if !d.Before.IsZero() { - query.Set("before", d.Before.String()) + query.Set("before", d.Before.UTC().Format(time.RFC3339)) } if d.Limit > 0 { @@ -687,7 +753,7 @@ func ListJoinedPrivateArchivedThreads(ctx context.Context, token string, rateLim endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/channels/%d/usrs/@methreads/archived/private?%s", channelId, data.Query()), + Endpoint: fmt.Sprintf("/channels/%d/users/@me/threads/archived/private?%s", channelId, data.Query()), Route: ratelimit.NewChannelRoute(ratelimit.RouteGetArchivedPrivateThreads, channelId), RateLimiter: rateLimiter, } diff --git a/rest/emojis.go b/rest/emojis.go index d027d4b..be8a490 100644 --- a/rest/emojis.go +++ b/rest/emojis.go @@ -79,7 +79,7 @@ func CreateGuildEmoji(ctx context.Context, token string, rateLimiter *ratelimit. func ModifyGuildEmoji(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, emojiId uint64, data CreateEmojiData) (emoji.Emoji, error) { endpoint := request.Endpoint{ RequestType: request.PATCH, - ContentType: request.Nil, + ContentType: request.ApplicationJson, Endpoint: fmt.Sprintf("/guilds/%d/emojis/%d", guildId, emojiId), Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyGuildEmoji, guildId), RateLimiter: rateLimiter, @@ -110,3 +110,95 @@ func DeleteGuildEmoji(ctx context.Context, token string, rateLimiter *ratelimit. err, _ := endpoint.Request(ctx, token, nil, nil) return err } + +type ListApplicationEmojisResponse struct { + Items []emoji.Emoji `json:"items"` +} + +func ListApplicationEmojis(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId uint64) ([]emoji.Emoji, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/emojis", applicationId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteListApplicationEmojis, applicationId), + RateLimiter: rateLimiter, + } + + var res ListApplicationEmojisResponse + err, _ := endpoint.Request(ctx, token, nil, &res) + return res.Items, err +} + +func GetApplicationEmoji(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, emojiId uint64) (emoji.Emoji, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/emojis/%d", applicationId, emojiId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteGetApplicationEmoji, applicationId), + RateLimiter: rateLimiter, + } + + var e emoji.Emoji + err, _ := endpoint.Request(ctx, token, nil, &e) + return e, err +} + +type CreateApplicationEmojiData struct { + Name string `json:"name"` + Image Image `json:"-"` +} + +func CreateApplicationEmoji(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId uint64, data CreateApplicationEmojiData) (emoji.Emoji, error) { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/applications/%d/emojis", applicationId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteCreateApplicationEmoji, applicationId), + RateLimiter: rateLimiter, + } + + var e emoji.Emoji + imageData, err := data.Image.Encode() + if err != nil { + return e, err + } + + body := map[string]interface{}{ + "name": data.Name, + "image": imageData, + } + + err, _ = endpoint.Request(ctx, token, body, &e) + return e, err +} + +func ModifyApplicationEmoji(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, emojiId uint64, name string) (emoji.Emoji, error) { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/applications/%d/emojis/%d", applicationId, emojiId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteModifyApplicationEmoji, applicationId), + RateLimiter: rateLimiter, + } + + body := map[string]interface{}{ + "name": name, + } + + var e emoji.Emoji + err, _ := endpoint.Request(ctx, token, body, &e) + return e, err +} + +func DeleteApplicationEmoji(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, emojiId uint64) error { + endpoint := request.Endpoint{ + RequestType: request.DELETE, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/emojis/%d", applicationId, emojiId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteDeleteApplicationEmoji, applicationId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, nil, nil) + return err +} diff --git a/rest/entitlement.go b/rest/entitlement.go index eb7f958..d17d042 100644 --- a/rest/entitlement.go +++ b/rest/entitlement.go @@ -4,7 +4,7 @@ import ( "context" "fmt" "net/url" - strconv "strconv" + "strconv" "github.com/TicketsBot-cloud/gdl/objects/entitlement" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" @@ -12,13 +12,14 @@ import ( ) type EntitlementQueryOptions struct { - UserId *uint64 - SkuIds []uint64 - Before *uint64 - After *uint64 - Limit *int - GuildId *uint64 - ExcludedEnded *bool + UserId *uint64 + SkuIds []uint64 + Before *uint64 + After *uint64 + Limit *int + GuildId *uint64 + ExcludeEnded *bool + ExcludeDeleted *bool } func (o *EntitlementQueryOptions) Query() string { @@ -31,13 +32,11 @@ func (o *EntitlementQueryOptions) Query() string { if len(o.SkuIds) > 0 { var encoded string for i, id := range o.SkuIds { - encoded += strconv.FormatUint(id, 10) + "," - - if i == len(o.SkuIds)-1 { - encoded = encoded[:len(encoded)-1] + encoded += strconv.FormatUint(id, 10) + if i < len(o.SkuIds)-1 { + encoded += "," } } - query.Add("sku_ids", encoded) } @@ -57,8 +56,12 @@ func (o *EntitlementQueryOptions) Query() string { query.Add("guild_id", strconv.FormatUint(*o.GuildId, 10)) } - if o.ExcludedEnded != nil { - query.Add("excluded_ended", strconv.FormatBool(*o.ExcludedEnded)) + if o.ExcludeEnded != nil { + query.Add("exclude_ended", strconv.FormatBool(*o.ExcludeEnded)) + } + + if o.ExcludeDeleted != nil { + query.Add("exclude_deleted", strconv.FormatBool(*o.ExcludeDeleted)) } return query.Encode() @@ -81,20 +84,31 @@ func ListEntitlements(ctx context.Context, token string, rateLimiter *ratelimit. return entitlements, nil } +func GetEntitlement(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, entitlementId uint64) (entitlement.Entitlement, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/entitlements/%d", applicationId, entitlementId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteGetEntitlement, applicationId), + RateLimiter: rateLimiter, + } + + var e entitlement.Entitlement + err, _ := endpoint.Request(ctx, token, nil, &e) + return e, err +} + func ConsumeEntitlement(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, entitlementId uint64) error { endpoint := request.Endpoint{ RequestType: request.POST, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/applications/%d/entitlements/%d/consume", applicationId, entitlementId), Route: ratelimit.NewApplicationRoute(ratelimit.RouteConsumeEntitlement, applicationId), RateLimiter: rateLimiter, } - if err, _ := endpoint.Request(ctx, token, nil, nil); err != nil { - return err - } - - return nil + err, _ := endpoint.Request(ctx, token, nil, nil) + return err } type CreateTestEntitlementData struct { @@ -119,21 +133,21 @@ func CreateTestEntitlement(ctx context.Context, token string, rateLimiter *ratel RateLimiter: rateLimiter, } - var createdEntitlement entitlement.Entitlement - if err, _ := endpoint.Request(ctx, token, data, &createdEntitlement); err != nil { + var e entitlement.Entitlement + if err, _ := endpoint.Request(ctx, token, data, &e); err != nil { return entitlement.Entitlement{}, err } - return createdEntitlement, nil + return e, nil } -func DeleteTestEntitlement(ctx context.Context, token string, rateLimtier *ratelimit.Ratelimiter, applicationId, entitlementId uint64) error { +func DeleteTestEntitlement(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, entitlementId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, ContentType: request.Nil, Endpoint: fmt.Sprintf("/applications/%d/entitlements/%d", applicationId, entitlementId), Route: ratelimit.NewApplicationRoute(ratelimit.RouteDeleteTestEntitlement, applicationId), - RateLimiter: rateLimtier, + RateLimiter: rateLimiter, } err, _ := endpoint.Request(ctx, token, nil, nil) diff --git a/rest/guild.go b/rest/guild.go index 98f73d4..d0942ce 100644 --- a/rest/guild.go +++ b/rest/guild.go @@ -5,8 +5,10 @@ import ( "fmt" "net/url" "strconv" + "time" "github.com/TicketsBot-cloud/gdl/objects/channel" + "github.com/TicketsBot-cloud/gdl/objects/channel/message" "github.com/TicketsBot-cloud/gdl/objects/guild" "github.com/TicketsBot-cloud/gdl/objects/integration" "github.com/TicketsBot-cloud/gdl/objects/invite" @@ -74,21 +76,27 @@ func GetGuildPreview(ctx context.Context, token string, rateLimiter *ratelimit.R } type ModifyGuildData struct { - Name string `json:"name"` - Region string `json:"region"` // voice region ID TODO: Helper function - VerificationLevel guild.VerificationLevel `json:"verification_level"` - DefaultMessageNotifications guild.DefaultMessageNotificationLevel `json:"default_message_notifications"` - ExplicitContentFilter guild.ExplicitContentFilterLevel `json:"explicit_content_filter"` - AfkChannelId uint64 `json:"afk_channel_id,string"` - AfkTimeout int `json:"afk_timeout"` - Icon string `json:"icon"` - OwnerId uint64 `json:"owner_id"` - Splash string `json:"splash"` - Banner string `json:"banner"` - SystemChannelId uint64 `json:"system_channel_id"` - RulesChannelId uint64 `json:"rules_channel_id"` - PublicUpdatesChannelId uint64 `json:"public_updates_channel_id"` - PreferredLocale string `json:"preferred_locale"` + Name string `json:"name,omitempty"` + Region *string `json:"region,omitempty"` // voice region ID, deprecated + VerificationLevel *guild.VerificationLevel `json:"verification_level,omitempty"` + DefaultMessageNotifications *guild.DefaultMessageNotificationLevel `json:"default_message_notifications,omitempty"` + ExplicitContentFilter *guild.ExplicitContentFilterLevel `json:"explicit_content_filter,omitempty"` + AfkChannelId *uint64 `json:"afk_channel_id,string,omitempty"` + AfkTimeout *int `json:"afk_timeout,omitempty"` + Icon *string `json:"icon,omitempty"` + OwnerId *uint64 `json:"owner_id,string,omitempty"` + Splash *string `json:"splash,omitempty"` + DiscoverySplash *string `json:"discovery_splash,omitempty"` + Banner *string `json:"banner,omitempty"` + SystemChannelId *uint64 `json:"system_channel_id,string,omitempty"` + SystemChannelFlags *int `json:"system_channel_flags,omitempty"` + RulesChannelId *uint64 `json:"rules_channel_id,string,omitempty"` + PublicUpdatesChannelId *uint64 `json:"public_updates_channel_id,string,omitempty"` + PreferredLocale *string `json:"preferred_locale,omitempty"` + Features []string `json:"features,omitempty"` + Description *string `json:"description,omitempty"` + PremiumProgressBarEnabled *bool `json:"premium_progress_bar_enabled,omitempty"` + SafetyAlertsChannelId *uint64 `json:"safety_alerts_channel_id,string,omitempty"` } func ModifyGuild(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data ModifyGuildData) (guild.Guild, error) { @@ -108,7 +116,7 @@ func ModifyGuild(ctx context.Context, token string, rateLimiter *ratelimit.Ratel func DeleteGuild(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/guilds/%d", guildId), Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteGuild, guildId), RateLimiter: rateLimiter, @@ -133,16 +141,24 @@ func GetGuildChannels(ctx context.Context, token string, rateLimiter *ratelimit. } type CreateChannelData struct { - Name string `json:"name"` - Type channel.ChannelType `json:"type"` - Topic string `json:"topic,omitempty"` - Bitrate int `json:"bitrate,omitempty"` - UserLimit int `json:"user_limit,omitempty"` - RateLimitPerUser int `json:"rate_limit_per_user"` - Position int `json:"position,omitempty"` - PermissionOverwrites []channel.PermissionOverwrite `json:"permission_overwrites"` - ParentId uint64 `json:"parent_id,string,omitempty"` - Nsfw bool `json:"nsfw,omitempty"` + Name string `json:"name"` + Type channel.ChannelType `json:"type,omitempty"` + Topic *string `json:"topic,omitempty"` + Bitrate *int `json:"bitrate,omitempty"` + UserLimit *int `json:"user_limit,omitempty"` + RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` + Position *int `json:"position,omitempty"` + PermissionOverwrites []channel.PermissionOverwrite `json:"permission_overwrites,omitempty"` + ParentId *uint64 `json:"parent_id,string,omitempty"` + Nsfw *bool `json:"nsfw,omitempty"` + RtcRegion *string `json:"rtc_region,omitempty"` + VideoQualityMode *int `json:"video_quality_mode,omitempty"` + DefaultAutoArchiveDuration *int `json:"default_auto_archive_duration,omitempty"` + DefaultReactionEmoji *channel.DefaultReaction `json:"default_reaction_emoji,omitempty"` + AvailableTags []channel.ForumTag `json:"available_tags,omitempty"` + DefaultSortOrder *int `json:"default_sort_order,omitempty"` + DefaultForumLayout *int `json:"default_forum_layout,omitempty"` + DefaultThreadRateLimitPerUser *int `json:"default_thread_rate_limit_per_user,omitempty"` } func CreateGuildChannel(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data CreateChannelData) (channel.Channel, error) { @@ -160,8 +176,10 @@ func CreateGuildChannel(ctx context.Context, token string, rateLimiter *ratelimi } type Position struct { - ChannelId uint64 `json:"id,string"` - Position int `json:"position"` + ChannelId uint64 `json:"id,string"` + Position int `json:"position"` + LockPermissions *bool `json:"lock_permissions,omitempty"` + ParentId *uint64 `json:"parent_id,string,omitempty"` } func ModifyGuildChannelPositions(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, positions []Position) error { @@ -256,11 +274,13 @@ func ListGuildMembers(ctx context.Context, token string, rateLimiter *ratelimit. } type ModifyGuildMemberData struct { - Nick string `json:"nick,omitempty"` - Roles *utils.Uint64StringSlice `json:"roles,omitempty"` - Mute *bool `json:"mute,omitempty"` - Deaf *bool `json:"deaf,omitempty"` - ChannelId uint64 `json:"channel_id,string,omitempty"` // id of channel to move user to (if they are connected to voice) + Nick *string `json:"nick,omitempty"` + Roles *utils.Uint64StringSlice `json:"roles,omitempty"` + Mute *bool `json:"mute,omitempty"` + Deaf *bool `json:"deaf,omitempty"` + ChannelId *uint64 `json:"channel_id,string,omitempty"` // id of channel to move user to (if they are connected to voice) + CommunicationDisabledUntil *time.Time `json:"communication_disabled_until,omitempty"` + Flags *int `json:"flags,omitempty"` } func ModifyGuildMember(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId uint64, data ModifyGuildMemberData) error { @@ -296,7 +316,7 @@ func ModifyCurrentUserNick(ctx context.Context, token string, rateLimiter *ratel func AddGuildMemberRole(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId, roleId uint64) error { endpoint := request.Endpoint{ RequestType: request.PUT, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/guilds/%d/members/%d/roles/%d", guildId, userId, roleId), Route: ratelimit.NewGuildRoute(ratelimit.RouteAddGuildMemberRole, guildId), RateLimiter: rateLimiter, @@ -309,7 +329,7 @@ func AddGuildMemberRole(ctx context.Context, token string, rateLimiter *ratelimi func RemoveGuildMemberRole(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId, roleId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/guilds/%d/members/%d/roles/%d", guildId, userId, roleId), Route: ratelimit.NewGuildRoute(ratelimit.RouteRemoveGuildMemberRole, guildId), RateLimiter: rateLimiter, @@ -322,7 +342,7 @@ func RemoveGuildMemberRole(ctx context.Context, token string, rateLimiter *ratel func RemoveGuildMember(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/guilds/%d/members/%d", guildId, userId), Route: ratelimit.NewGuildRoute(ratelimit.RouteRemoveGuildMember, guildId), RateLimiter: rateLimiter, @@ -385,7 +405,7 @@ func GetGuildBan(ctx context.Context, token string, rateLimiter *ratelimit.Ratel } type CreateGuildBanData struct { - DeleteMessageDays int `json:"delete_message_days,omitempty"` // 1 - 7 + DeleteMessageSeconds int `json:"delete_message_seconds,omitempty"` // 0 - 604800 (7 days) } func CreateGuildBan(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId uint64, data CreateGuildBanData) error { @@ -429,11 +449,13 @@ func GetGuildRoles(ctx context.Context, token string, rateLimiter *ratelimit.Rat } type GuildRoleData struct { - Name string `json:"name,omitempty"` - Permissions *uint64 `json:"permissions,omitempty,string"` - Color *int `json:"color,omitempty"` - Hoist *bool `json:"hoist,omitempty"` - Mentionable *bool `json:"mentionable,omitempty"` + Name string `json:"name,omitempty"` + Permissions *uint64 `json:"permissions,string,omitempty"` + Color *int `json:"color,omitempty"` + Hoist *bool `json:"hoist,omitempty"` + Icon *string `json:"icon,omitempty"` + UnicodeEmoji *string `json:"unicode_emoji,omitempty"` + Mentionable *bool `json:"mentionable,omitempty"` } func CreateGuildRole(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data GuildRoleData) (guild.Role, error) { @@ -481,7 +503,7 @@ func ModifyGuildRole(ctx context.Context, token string, rateLimiter *ratelimit.R func DeleteGuildRole(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, roleId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/guilds/%d/roles/%d", guildId, roleId), Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteGuildRole, guildId), RateLimiter: rateLimiter, @@ -509,17 +531,23 @@ func GetGuildPruneCount(ctx context.Context, token string, rateLimiter *ratelimi return res["pruned"], err } +type BeginGuildPruneData struct { + Days int `json:"days,omitempty"` + ComputePruneCount bool `json:"compute_prune_count"` + IncludeRoles []uint64 `json:"include_roles,omitempty"` +} + // computePruneCount = whether 'pruned' is returned, discouraged for large guilds -func BeginGuildPrune(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, days int, computePruneCount bool) error { +func BeginGuildPrune(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data BeginGuildPruneData) error { endpoint := request.Endpoint{ RequestType: request.POST, ContentType: request.ApplicationJson, - Endpoint: fmt.Sprintf("/guilds/%d/prune?days=%d&compute_prune_count=%t", guildId, days, computePruneCount), + Endpoint: fmt.Sprintf("/guilds/%d/prune", guildId), Route: ratelimit.NewGuildRoute(ratelimit.RouteBeginGuildPrune, guildId), RateLimiter: rateLimiter, } - err, _ := endpoint.Request(ctx, token, nil, nil) + err, _ := endpoint.Request(ctx, token, data, nil) return err } @@ -605,7 +633,7 @@ func ModifyGuildIntegration(ctx context.Context, token string, rateLimiter *rate func DeleteGuildIntegration(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, integrationId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/guilds/%d/integrations/%d", guildId, integrationId), Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteGuildIntegration, guildId), RateLimiter: rateLimiter, @@ -618,7 +646,7 @@ func DeleteGuildIntegration(ctx context.Context, token string, rateLimiter *rate func SyncGuildIntegration(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, integrationId uint64) error { endpoint := request.Endpoint{ RequestType: request.POST, - ContentType: request.ApplicationJson, + ContentType: request.Nil, Endpoint: fmt.Sprintf("/guilds/%d/integrations/%d/sync", guildId, integrationId), Route: ratelimit.NewGuildRoute(ratelimit.RouteSyncGuildIntegration, guildId), RateLimiter: rateLimiter, @@ -628,24 +656,24 @@ func SyncGuildIntegration(ctx context.Context, token string, rateLimiter *rateli return err } -func GetGuildWidget(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) (widget guild.GuildWidget, err error) { +func GetGuildWidgetSettings(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) (settings guild.GuildEmbed, err error) { endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/guilds/%d/widget.json", guildId), - Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildWidget, guildId), + Endpoint: fmt.Sprintf("/guilds/%d/widget", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildWidgetSettings, guildId), RateLimiter: rateLimiter, } - err, _ = endpoint.Request(ctx, token, nil, &widget) + err, _ = endpoint.Request(ctx, token, nil, &settings) return } -func ModifyGuildEmbed(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data guild.GuildEmbed) (widget guild.GuildEmbed, err error) { +func ModifyGuildWidget(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data guild.GuildEmbed) (widget guild.GuildEmbed, err error) { endpoint := request.Endpoint{ RequestType: request.PATCH, ContentType: request.ApplicationJson, - Endpoint: fmt.Sprintf("/guilds/%d/embed", guildId), + Endpoint: fmt.Sprintf("/guilds/%d/widget", guildId), Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyGuildWidget, guildId), RateLimiter: rateLimiter, } @@ -654,6 +682,24 @@ func ModifyGuildEmbed(ctx context.Context, token string, rateLimiter *ratelimit. return } +// Deprecated: Use ModifyGuildWidget instead. +func ModifyGuildEmbed(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data guild.GuildEmbed) (widget guild.GuildEmbed, err error) { + return ModifyGuildWidget(ctx, token, rateLimiter, guildId, data) +} + +func GetGuildWidget(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) (widget guild.GuildWidget, err error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/widget.json", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildWidget, guildId), + RateLimiter: rateLimiter, + } + + err, _ = endpoint.Request(ctx, token, nil, &widget) + return +} + // returns invite object with only "code" and "uses" fields func GetGuildVanityURL(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) (invite invite.Invite, err error) { endpoint := request.Endpoint{ @@ -667,3 +713,201 @@ func GetGuildVanityURL(ctx context.Context, token string, rateLimiter *ratelimit err, _ = endpoint.Request(ctx, token, nil, &invite) return } + +type AddGuildMemberData struct { + AccessToken string `json:"access_token"` + Nick *string `json:"nick,omitempty"` + Roles utils.Uint64StringSlice `json:"roles,omitempty"` + Mute *bool `json:"mute,omitempty"` + Deaf *bool `json:"deaf,omitempty"` +} + +// Returns nil if the user was already a member of the guild (HTTP 204). +func AddGuildMember(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId uint64, data AddGuildMemberData) (*member.Member, error) { + endpoint := request.Endpoint{ + RequestType: request.PUT, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/members/%d", guildId, userId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteAddGuildMember, guildId), + RateLimiter: rateLimiter, + } + + var m member.Member + if err, res := endpoint.Request(ctx, token, data, &m); err != nil { + return nil, err + } else if res != nil && res.StatusCode == 204 { + return nil, nil + } + + return &m, nil +} + +func GetGuildWelcomeScreen(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) (guild.WelcomeScreen, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/welcome-screen", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildWelcomeScreen, guildId), + RateLimiter: rateLimiter, + } + + var screen guild.WelcomeScreen + err, _ := endpoint.Request(ctx, token, nil, &screen) + return screen, err +} + +type ModifyGuildWelcomeScreenData struct { + Enabled *bool `json:"enabled,omitempty"` + WelcomeChannels []guild.WelcomeScreenChannel `json:"welcome_channels,omitempty"` + Description *string `json:"description,omitempty"` +} + +func ModifyGuildWelcomeScreen(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data ModifyGuildWelcomeScreenData) (guild.WelcomeScreen, error) { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/welcome-screen", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyGuildWelcomeScreen, guildId), + RateLimiter: rateLimiter, + } + + var screen guild.WelcomeScreen + if err, _ := endpoint.Request(ctx, token, data, &screen); err != nil { + return guild.WelcomeScreen{}, err + } + + return screen, nil +} + +// All fields are optional +type SearchGuildMessagesData struct { + Limit int // 1-25, default 25 + Offset int // max 9975 + MaxId uint64 // Get messages before this message ID + MinId uint64 // Get messages after this message ID + Slop int // Max words to skip between tokens (max 100, default 2) + Content string // Filter by content (max 1024 chars) + ChannelIds []uint64 // Filter by channels (max 500) + AuthorTypes []string // Filter by author type: "user", "bot", "webhook" (prefix with "-" to negate) + AuthorIds []uint64 // Filter by authors (max 100) + Mentions []uint64 // Filter by mentioned users (max 100) + MentionsRoleIds []uint64 // Filter by mentioned roles (max 100) + MentionEveryone *bool // Filter by @everyone mention + RepliedToUserIds []uint64 // Filter by replied-to users (max 100) + RepliedToMessageIds []uint64 // Filter by replied-to messages (max 100) + Pinned *bool // Filter by pinned status + Has []string // Filter by content type: "image", "sound", "video", "file", "sticker", "embed", "link", "poll", "snapshot" + EmbedTypes []string // Filter by embed type: "image", "video", "gif", "sound", "article" + EmbedProviders []string // Filter by embed provider (max 100) + LinkHostnames []string // Filter by link hostname (max 100) + AttachmentFilenames []string // Filter by attachment filename (max 100) + AttachmentExtensions []string // Filter by attachment extension (max 100) + SortBy string // "timestamp" or "relevance" + SortOrder string // "asc" or "desc" + IncludeNsfw *bool // Whether to include age-restricted channels (default false) +} + +func (d *SearchGuildMessagesData) Encode() string { + q := url.Values{} + + if d.Limit != 0 { + q.Set("limit", strconv.Itoa(d.Limit)) + } + if d.Offset != 0 { + q.Set("offset", strconv.Itoa(d.Offset)) + } + if d.MaxId != 0 { + q.Set("max_id", strconv.FormatUint(d.MaxId, 10)) + } + if d.MinId != 0 { + q.Set("min_id", strconv.FormatUint(d.MinId, 10)) + } + if d.Slop != 0 { + q.Set("slop", strconv.Itoa(d.Slop)) + } + if d.Content != "" { + q.Set("content", d.Content) + } + for _, id := range d.ChannelIds { + q.Add("channel_id", strconv.FormatUint(id, 10)) + } + for _, t := range d.AuthorTypes { + q.Add("author_type", t) + } + for _, id := range d.AuthorIds { + q.Add("author_id", strconv.FormatUint(id, 10)) + } + for _, id := range d.Mentions { + q.Add("mentions", strconv.FormatUint(id, 10)) + } + for _, id := range d.MentionsRoleIds { + q.Add("mentions_role_id", strconv.FormatUint(id, 10)) + } + if d.MentionEveryone != nil { + q.Set("mention_everyone", strconv.FormatBool(*d.MentionEveryone)) + } + for _, id := range d.RepliedToUserIds { + q.Add("replied_to_user_id", strconv.FormatUint(id, 10)) + } + for _, id := range d.RepliedToMessageIds { + q.Add("replied_to_message_id", strconv.FormatUint(id, 10)) + } + if d.Pinned != nil { + q.Set("pinned", strconv.FormatBool(*d.Pinned)) + } + for _, h := range d.Has { + q.Add("has", h) + } + for _, t := range d.EmbedTypes { + q.Add("embed_type", t) + } + for _, p := range d.EmbedProviders { + q.Add("embed_provider", p) + } + for _, h := range d.LinkHostnames { + q.Add("link_hostname", h) + } + for _, f := range d.AttachmentFilenames { + q.Add("attachment_filename", f) + } + for _, e := range d.AttachmentExtensions { + q.Add("attachment_extension", e) + } + if d.SortBy != "" { + q.Set("sort_by", d.SortBy) + } + if d.SortOrder != "" { + q.Set("sort_order", d.SortOrder) + } + if d.IncludeNsfw != nil { + q.Set("include_nsfw", strconv.FormatBool(*d.IncludeNsfw)) + } + + return q.Encode() +} + +type SearchGuildMessagesResponse struct { + DoingDeepHistoricalIndex bool `json:"doing_deep_historical_index"` + DocumentsIndexed *int `json:"documents_indexed,omitempty"` + TotalResults int `json:"total_results"` + Messages [][]message.Message `json:"messages"` + Threads []channel.Channel `json:"threads,omitempty"` + Members []channel.ThreadMember `json:"members,omitempty"` +} + +func SearchGuildMessages(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data SearchGuildMessagesData) (SearchGuildMessagesResponse, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/messages/search?%s", guildId, data.Encode()), + Route: ratelimit.NewGuildRoute(ratelimit.RouteSearchGuildMessages, guildId), + RateLimiter: rateLimiter, + } + + var res SearchGuildMessagesResponse + if err, _ := endpoint.Request(ctx, token, nil, &res); err != nil { + return SearchGuildMessagesResponse{}, err + } + + return res, nil +} diff --git a/rest/image.go b/rest/image.go index a2bbf38..e8d7ff5 100644 --- a/rest/image.go +++ b/rest/image.go @@ -4,7 +4,6 @@ import ( "encoding/base64" "fmt" "io" - "io/ioutil" "github.com/TicketsBot-cloud/gdl/rest/request" ) @@ -15,7 +14,7 @@ type Image struct { } func (i *Image) Encode() (string, error) { - content, err := ioutil.ReadAll(i.ImageReader) + content, err := io.ReadAll(i.ImageReader) if err != nil { return "", err } diff --git a/rest/interaction.go b/rest/interaction.go index f12625f..b977ca9 100644 --- a/rest/interaction.go +++ b/rest/interaction.go @@ -4,17 +4,18 @@ import ( "context" "fmt" + "github.com/TicketsBot-cloud/gdl/objects/application" "github.com/TicketsBot-cloud/gdl/objects/channel/message" "github.com/TicketsBot-cloud/gdl/objects/interaction" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" "github.com/TicketsBot-cloud/gdl/rest/request" ) -func GetGlobalCommands(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId uint64) (commands []interaction.ApplicationCommand, err error) { +func GetGlobalCommands(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId uint64, withLocalizations bool) (commands []interaction.ApplicationCommand, err error) { endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/applications/%d/commands", applicationId), + Endpoint: fmt.Sprintf("/applications/%d/commands?with_localizations=%t", applicationId, withLocalizations), Route: ratelimit.NewApplicationRoute(ratelimit.RouteGetGlobalCommands, applicationId), RateLimiter: rateLimiter, } @@ -23,13 +24,32 @@ func GetGlobalCommands(ctx context.Context, token string, rateLimiter *ratelimit return } +func GetGlobalCommand(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, commandId uint64) (command interaction.ApplicationCommand, err error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/commands/%d", applicationId, commandId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteGetGlobalCommand, applicationId), + RateLimiter: rateLimiter, + } + + err, _ = endpoint.Request(ctx, token, nil, &command) + return +} + type CreateCommandData struct { - Id uint64 `json:"id,omitempty"` // Optional: Use to rename without changing ID - Name string `json:"name"` - Description string `json:"description"` - Options []interaction.ApplicationCommandOption `json:"options"` - Type interaction.ApplicationCommandType `json:"type"` - Contexts []interaction.InteractionContextType `json:"contexts,omitempty"` + Id uint64 `json:"id,string,omitempty"` // Use in bulk overwrite to update an existing command by ID + Name string `json:"name"` + NameLocalizations map[string]string `json:"name_localizations,omitempty"` + Description string `json:"description,omitempty"` + DescriptionLocalizations map[string]string `json:"description_localizations,omitempty"` + Options []interaction.ApplicationCommandOption `json:"options,omitempty"` + DefaultMemberPermissions *string `json:"default_member_permissions,omitempty"` + IntegrationTypes []application.ApplicationIntegrationType `json:"integration_types,omitempty"` + Contexts []interaction.InteractionContextType `json:"contexts,omitempty"` + Type interaction.ApplicationCommandType `json:"type,omitempty"` + Nsfw *bool `json:"nsfw,omitempty"` + Handler *interaction.ApplicationCommandHandlerType `json:"handler,omitempty"` } func CreateGlobalCommand(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId uint64, data CreateCommandData) (command interaction.ApplicationCommand, err error) { @@ -84,11 +104,11 @@ func DeleteGlobalCommand(ctx context.Context, token string, rateLimiter *ratelim return } -func GetGuildCommands(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, guildId uint64) (commands []interaction.ApplicationCommand, err error) { +func GetGuildCommands(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, guildId uint64, withLocalizations bool) (commands []interaction.ApplicationCommand, err error) { endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/applications/%d/guilds/%d/commands", applicationId, guildId), + Endpoint: fmt.Sprintf("/applications/%d/guilds/%d/commands?with_localizations=%t", applicationId, guildId, withLocalizations), Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildCommands, applicationId), RateLimiter: rateLimiter, } @@ -97,6 +117,19 @@ func GetGuildCommands(ctx context.Context, token string, rateLimiter *ratelimit. return } +func GetGuildCommand(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, guildId, commandId uint64) (command interaction.ApplicationCommand, err error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/guilds/%d/commands/%d", applicationId, guildId, commandId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildCommand, applicationId), + RateLimiter: rateLimiter, + } + + err, _ = endpoint.Request(ctx, token, nil, &command) + return +} + func CreateGuildCommand(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId, guildId uint64, data CreateCommandData) (command interaction.ApplicationCommand, err error) { endpoint := request.Endpoint{ RequestType: request.POST, @@ -239,7 +272,7 @@ func DeleteOriginalInteractionResponse(ctx context.Context, token string, rateLi RequestType: request.DELETE, ContentType: request.Nil, Endpoint: fmt.Sprintf("/webhooks/%d/%s/messages/@original", applicationId, token), - Route: ratelimit.NewWebhookRoute(ratelimit.RouteEditOriginalInteractionResponse, applicationId), + Route: ratelimit.NewWebhookRoute(ratelimit.RouteDeleteOriginalInteractionResponse, applicationId), RateLimiter: rateLimiter, } diff --git a/rest/invite.go b/rest/invite.go index 311ad92..690abe8 100644 --- a/rest/invite.go +++ b/rest/invite.go @@ -9,11 +9,16 @@ import ( "github.com/TicketsBot-cloud/gdl/rest/request" ) -func GetInvite(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, inviteCode string, withCounts bool) (invite.Invite, error) { +func GetInvite(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, inviteCode string, withCounts bool, guildScheduledEventId *uint64) (invite.Invite, error) { + url := fmt.Sprintf("/invites/%s?with_counts=%v", inviteCode, withCounts) + if guildScheduledEventId != nil { + url += fmt.Sprintf("&guild_scheduled_event_id=%d", *guildScheduledEventId) + } + endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/invites/%s?with_counts=%v", inviteCode, withCounts), + Endpoint: url, Route: ratelimit.NewGuildRoute(ratelimit.RouteGetInvite, 0), // No ratelimit RateLimiter: rateLimiter, } @@ -27,7 +32,7 @@ func DeleteInvite(ctx context.Context, token string, rateLimiter *ratelimit.Rate endpoint := request.Endpoint{ RequestType: request.DELETE, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/invites/%s", inviteCode), + Endpoint: "/invites/" + inviteCode, Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteInvite, 0), // No ratelimit RateLimiter: rateLimiter, } diff --git a/rest/oauth.go b/rest/oauth.go index 89be734..1922953 100644 --- a/rest/oauth.go +++ b/rest/oauth.go @@ -6,7 +6,10 @@ import ( "encoding/json" "errors" "fmt" + "time" + "github.com/TicketsBot-cloud/gdl/objects/application" + "github.com/TicketsBot-cloud/gdl/objects/user" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" "github.com/TicketsBot-cloud/gdl/rest/request" ) @@ -40,6 +43,7 @@ type ( const ( GrantTypeAuthorizationCode GrantType = "authorization_code" GrantTypeRefreshToken GrantType = "refresh_token" + GrantTypeClientCredentials GrantType = "client_credentials" TokenTypeHintAccessToken TokenTypeHint = "access_token" TokenTypeHintRefreshToken TokenTypeHint = "refresh_token" @@ -106,6 +110,29 @@ func RevokeToken(ctx context.Context, rateLimiter *ratelimit.Ratelimiter, client return convertToOauthError(err) } +// AuthorizationInformation is returned by GET /oauth2/@me (bearer token only). +type AuthorizationInformation struct { + Application application.Application `json:"application"` + Scopes []string `json:"scopes"` + Expires time.Time `json:"expires"` + User *user.User `json:"user,omitempty"` +} + +// GetCurrentAuthorizationInformation requires a bearer token, not a bot token. +func GetCurrentAuthorizationInformation(ctx context.Context, bearerToken string, rateLimiter *ratelimit.Ratelimiter) (AuthorizationInformation, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: "/oauth2/@me", + Route: ratelimit.NewOtherRoute(ratelimit.RouteGetCurrentAuthorizationInformation, 0), + RateLimiter: rateLimiter, + } + + var info AuthorizationInformation + err, _ := endpoint.Request(ctx, "Bearer "+bearerToken, nil, &info) + return info, err +} + func convertToOauthError(err error) error { var restError request.RestError if errors.As(err, &restError) { diff --git a/rest/poll.go b/rest/poll.go new file mode 100644 index 0000000..27147cf --- /dev/null +++ b/rest/poll.go @@ -0,0 +1,70 @@ +package rest + +import ( + "context" + "fmt" + "net/url" + "strconv" + + "github.com/TicketsBot-cloud/gdl/objects/channel/message" + "github.com/TicketsBot-cloud/gdl/objects/user" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" +) + +type GetPollAnswerVotersData struct { + After *uint64 + Limit *int +} + +func (d *GetPollAnswerVotersData) Query() string { + query := url.Values{} + + if d.After != nil { + query.Add("after", strconv.FormatUint(*d.After, 10)) + } + + if d.Limit != nil { + query.Add("limit", strconv.Itoa(*d.Limit)) + } + + return query.Encode() +} + +type pollAnswerVotersResponse struct { + Users []user.User `json:"users"` +} + +func GetPollAnswerVoters(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId, messageId uint64, answerId int, data GetPollAnswerVotersData) ([]user.User, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/channels/%d/polls/%d/answers/%d?%s", channelId, messageId, answerId, data.Query()), + Route: ratelimit.NewChannelRoute(ratelimit.RouteGetPollAnswerVoters, channelId), + RateLimiter: rateLimiter, + } + + var res pollAnswerVotersResponse + if err, _ := endpoint.Request(ctx, token, nil, &res); err != nil { + return nil, err + } + + return res.Users, nil +} + +func EndPoll(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId, messageId uint64) (message.Message, error) { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/channels/%d/polls/%d/expire", channelId, messageId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteEndPoll, channelId), + RateLimiter: rateLimiter, + } + + var msg message.Message + if err, _ := endpoint.Request(ctx, token, nil, &msg); err != nil { + return message.Message{}, err + } + + return msg, nil +} diff --git a/rest/ratelimit/memorystore.go b/rest/ratelimit/memorystore.go index 10ff8aa..d66b148 100644 --- a/rest/ratelimit/memorystore.go +++ b/rest/ratelimit/memorystore.go @@ -43,7 +43,7 @@ func (s *MemoryStore) getTTLAndDecrease(route Route) (time.Duration, error) { if found { remaining := item.Data.(int) - ttl := item.ExpireAt.Sub(time.Now()) + ttl := time.Until(item.ExpireAt) if remaining > 0 { s.Cache.SetWithTTL(key, remaining-1, ttl) @@ -59,7 +59,7 @@ func (s *MemoryStore) getTTLAndDecrease(route Route) (time.Duration, error) { func (s *MemoryStore) getGlobalTTL() (time.Duration, error) { s.globalLock.RLock() defer s.globalLock.RUnlock() - return s.globalResetAfter.Sub(time.Now()), nil + return time.Until(s.globalResetAfter), nil } func (s *MemoryStore) UpdateRateLimit(route Route, remaining int, resetAfter time.Duration) error { diff --git a/rest/ratelimit/ratelimiter.go b/rest/ratelimit/ratelimiter.go index b1d5f46..20c3973 100644 --- a/rest/ratelimit/ratelimiter.go +++ b/rest/ratelimit/ratelimiter.go @@ -5,8 +5,6 @@ import ( "time" ) -// Big thanks to https://github.com/spencersharkey for sharing his ratelimiter with me - type Ratelimiter struct { sync.Mutex Store RateLimitStore diff --git a/rest/ratelimit/redisstore.go b/rest/ratelimit/redisstore.go index 0a83da1..df5f579 100644 --- a/rest/ratelimit/redisstore.go +++ b/rest/ratelimit/redisstore.go @@ -19,8 +19,7 @@ func NewRedisStore(client *redis.Client, keyPrefix string) *RedisStore { Client: client, keyPrefix: keyPrefix, ContextBuilder: func() context.Context { - ctx, _ := context.WithTimeout(context.Background(), time.Second*5) - return ctx + return context.Background() }, } } diff --git a/rest/ratelimit/routes.go b/rest/ratelimit/routes.go index fec1b68..dc747a7 100644 --- a/rest/ratelimit/routes.go +++ b/rest/ratelimit/routes.go @@ -98,6 +98,13 @@ const ( RouteModifyGuildEmoji RouteDeleteGuildEmoji + // /applications/:id/emojis + RouteListApplicationEmojis + RouteGetApplicationEmoji + RouteCreateApplicationEmoji + RouteModifyApplicationEmoji + RouteDeleteApplicationEmoji + // /guilds/:id/... RouteCreateGuild RouteGetGuild @@ -156,6 +163,7 @@ const ( RouteGetUser RouteModifyCurrentUser RouteGetCurrentUserGuilds + RouteGetCurrentUserGuildMember RouteLeaveGuild RouteGetUserDMs RouteCreateDM @@ -165,6 +173,12 @@ const ( // /voice/regions RouteListVoiceRegions + // /guilds/:id/voice-states + RouteGetCurrentUserVoiceState + RouteGetUserVoiceState + RouteModifyCurrentUserVoiceState + RouteModifyUserVoiceState + // /channels/:id/webhooks RouteCreateWebhook RouteGetChannelWebhooks @@ -180,10 +194,13 @@ const ( RouteDeleteWebhook RouteDeleteWebhookWithToken RouteExecuteWebhook + RouteGetWebhookMessage RouteEditWebhookMessage + RouteDeleteWebhookMessage // /applications/:id/... RouteGetGlobalCommands + RouteGetGlobalCommand RouteCreateGlobalCommand RouteModifyGlobalCommand RouteModifyGlobalCommands @@ -191,6 +208,7 @@ const ( // /applications/:id/guild/... RouteGetGuildCommands + RouteGetGuildCommand RouteCreateGuildCommand RouteModifyGuildCommand RouteModifyGuildCommands @@ -214,9 +232,11 @@ const ( // /applications/@me RouteGetCurrentApplication RouteEditCurrentApplication + RouteGetActivityInstance ///applications/:id/entitlements RouteListEntitlements + RouteGetEntitlement RouteConsumeEntitlement RouteCreateTestEntitlement RouteDeleteTestEntitlement @@ -224,4 +244,63 @@ const ( // /oauth2/ RouteOauth2TokenExchange RouteOauth2TokenRevoke + RouteGetCurrentAuthorizationInformation + + // Auto Moderation + RouteListAutoModerationRules + RouteGetAutoModerationRule + RouteCreateAutoModerationRule + RouteModifyAutoModerationRule + RouteDeleteAutoModerationRule + + // Guild Scheduled Events + RouteListGuildScheduledEvents + RouteGetGuildScheduledEvent + RouteCreateGuildScheduledEvent + RouteModifyGuildScheduledEvent + RouteDeleteGuildScheduledEvent + RouteGetGuildScheduledEventUsers + + // Stage Instances + RouteCreateStageInstance + RouteGetStageInstance + RouteModifyStageInstance + RouteDeleteStageInstance + + // Soundboard + RouteSendSoundboardSound + RouteGetDefaultSoundboardSounds + RouteListGuildSoundboardSounds + RouteGetGuildSoundboardSound + RouteCreateGuildSoundboardSound + RouteModifyGuildSoundboardSound + RouteDeleteGuildSoundboardSound + + // Polls + RouteGetPollAnswerVoters + RouteEndPoll + + // SKUs + RouteListSKUs + + // Subscriptions + RouteListSKUSubscriptions + RouteGetSKUSubscription + + // Stickers + RouteGetSticker + RouteGetStickerPacks + RouteGetStickerPack + RouteListGuildStickers + RouteGetGuildSticker + RouteCreateGuildSticker + RouteModifyGuildSticker + RouteDeleteGuildSticker + + // Guild Welcome Screen + RouteGetGuildWelcomeScreen + RouteModifyGuildWelcomeScreen + + // Guild Message Search + RouteSearchGuildMessages ) diff --git a/rest/request/endpoint.go b/rest/request/endpoint.go index 235b70d..7ed58c9 100644 --- a/rest/request/endpoint.go +++ b/rest/request/endpoint.go @@ -107,19 +107,20 @@ func (e *Endpoint) Request(ctx context.Context, token string, body any, response // Encode body var encoded []byte - if e.ContentType == ApplicationJson { + switch e.ContentType { + case ApplicationJson: raw, err := json.Marshal(&body) if err != nil { return err, nil } encoded = raw - } else if e.ContentType == ApplicationFormUrlEncoded { + case ApplicationFormUrlEncoded: str, err := qs.Marshal(body) if err != nil { return err, nil } encoded = []byte(str) - } else if e.ContentType == MultipartFormData { + case MultipartFormData: data, ok := body.(MultipartPayload) if !ok { return errors.New("Content-Type MultipartFormData specified but EncodeMultipartFormData was missing"), nil diff --git a/rest/request/multipart.go b/rest/request/multipart.go index 921c9fd..ca751f9 100644 --- a/rest/request/multipart.go +++ b/rest/request/multipart.go @@ -58,5 +58,5 @@ func EncodeMultipartFormData(payload MultipartPayload) ([]byte, string, error) { } } - return []byte(string(body.Bytes()) + "\r\n--" + writer.Boundary() + "--"), writer.Boundary(), nil + return []byte(body.String() + "\r\n--" + writer.Boundary() + "--"), writer.Boundary(), nil } diff --git a/rest/scheduledevent.go b/rest/scheduledevent.go new file mode 100644 index 0000000..baf3c8d --- /dev/null +++ b/rest/scheduledevent.go @@ -0,0 +1,172 @@ +package rest + +import ( + "context" + "fmt" + "net/url" + "strconv" + "time" + + "github.com/TicketsBot-cloud/gdl/objects/guild/scheduledevent" + "github.com/TicketsBot-cloud/gdl/objects/member" + "github.com/TicketsBot-cloud/gdl/objects/user" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" +) + +type CreateGuildScheduledEventData struct { + ChannelId *uint64 `json:"channel_id,string,omitempty"` + EntityMetadata *scheduledevent.EntityMetadata `json:"entity_metadata,omitempty"` + Name string `json:"name"` + PrivacyLevel scheduledevent.PrivacyLevel `json:"privacy_level"` + ScheduledStartTime time.Time `json:"scheduled_start_time"` + ScheduledEndTime *time.Time `json:"scheduled_end_time,omitempty"` + Description *string `json:"description,omitempty"` + EntityType scheduledevent.EntityType `json:"entity_type"` + Image *string `json:"image,omitempty"` + RecurrenceRule *scheduledevent.RecurrenceRule `json:"recurrence_rule,omitempty"` +} + +type ModifyGuildScheduledEventData struct { + ChannelId *uint64 `json:"channel_id,string,omitempty"` + EntityMetadata *scheduledevent.EntityMetadata `json:"entity_metadata,omitempty"` + Name *string `json:"name,omitempty"` + PrivacyLevel *scheduledevent.PrivacyLevel `json:"privacy_level,omitempty"` + ScheduledStartTime *time.Time `json:"scheduled_start_time,omitempty"` + ScheduledEndTime *time.Time `json:"scheduled_end_time,omitempty"` + Description *string `json:"description,omitempty"` + EntityType *scheduledevent.EntityType `json:"entity_type,omitempty"` + Status *scheduledevent.Status `json:"status,omitempty"` + Image *string `json:"image,omitempty"` + RecurrenceRule *scheduledevent.RecurrenceRule `json:"recurrence_rule,omitempty"` +} + +type GetGuildScheduledEventUsersData struct { + Limit *int + WithMember *bool + Before *uint64 + After *uint64 +} + +func (d *GetGuildScheduledEventUsersData) Query() string { + query := url.Values{} + + if d.Limit != nil { + query.Add("limit", strconv.Itoa(*d.Limit)) + } + + if d.WithMember != nil { + query.Add("with_member", strconv.FormatBool(*d.WithMember)) + } + + if d.Before != nil { + query.Add("before", strconv.FormatUint(*d.Before, 10)) + } + + if d.After != nil { + query.Add("after", strconv.FormatUint(*d.After, 10)) + } + + return query.Encode() +} + +type GuildScheduledEventUser struct { + GuildScheduledEventId uint64 `json:"guild_scheduled_event_id,string"` + User user.User `json:"user"` + Member *member.Member `json:"member,omitempty"` +} + +func ListGuildScheduledEvents(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, withUserCount bool) ([]scheduledevent.GuildScheduledEvent, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/scheduled-events?with_user_count=%s", guildId, strconv.FormatBool(withUserCount)), + Route: ratelimit.NewGuildRoute(ratelimit.RouteListGuildScheduledEvents, guildId), + RateLimiter: rateLimiter, + } + + var events []scheduledevent.GuildScheduledEvent + if err, _ := endpoint.Request(ctx, token, nil, &events); err != nil { + return nil, err + } + + return events, nil +} + +func GetGuildScheduledEvent(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, eventId uint64, withUserCount bool) (scheduledevent.GuildScheduledEvent, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/scheduled-events/%d?with_user_count=%s", guildId, eventId, strconv.FormatBool(withUserCount)), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildScheduledEvent, guildId), + RateLimiter: rateLimiter, + } + + var event scheduledevent.GuildScheduledEvent + err, _ := endpoint.Request(ctx, token, nil, &event) + return event, err +} + +func CreateGuildScheduledEvent(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data CreateGuildScheduledEventData) (scheduledevent.GuildScheduledEvent, error) { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/scheduled-events", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteCreateGuildScheduledEvent, guildId), + RateLimiter: rateLimiter, + } + + var event scheduledevent.GuildScheduledEvent + if err, _ := endpoint.Request(ctx, token, data, &event); err != nil { + return scheduledevent.GuildScheduledEvent{}, err + } + + return event, nil +} + +func ModifyGuildScheduledEvent(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, eventId uint64, data ModifyGuildScheduledEventData) (scheduledevent.GuildScheduledEvent, error) { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/scheduled-events/%d", guildId, eventId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyGuildScheduledEvent, guildId), + RateLimiter: rateLimiter, + } + + var event scheduledevent.GuildScheduledEvent + if err, _ := endpoint.Request(ctx, token, data, &event); err != nil { + return scheduledevent.GuildScheduledEvent{}, err + } + + return event, nil +} + +func DeleteGuildScheduledEvent(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, eventId uint64) error { + endpoint := request.Endpoint{ + RequestType: request.DELETE, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/scheduled-events/%d", guildId, eventId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteGuildScheduledEvent, guildId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, nil, nil) + return err +} + +func GetGuildScheduledEventUsers(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, eventId uint64, data GetGuildScheduledEventUsersData) ([]GuildScheduledEventUser, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/scheduled-events/%d/users?%s", guildId, eventId, data.Query()), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildScheduledEventUsers, guildId), + RateLimiter: rateLimiter, + } + + var users []GuildScheduledEventUser + if err, _ := endpoint.Request(ctx, token, nil, &users); err != nil { + return nil, err + } + + return users, nil +} diff --git a/rest/sku.go b/rest/sku.go new file mode 100644 index 0000000..241cd09 --- /dev/null +++ b/rest/sku.go @@ -0,0 +1,27 @@ +package rest + +import ( + "context" + "fmt" + + "github.com/TicketsBot-cloud/gdl/objects/sku" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" +) + +func ListSKUs(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, applicationId uint64) ([]sku.SKU, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/applications/%d/skus", applicationId), + Route: ratelimit.NewApplicationRoute(ratelimit.RouteListSKUs, applicationId), + RateLimiter: rateLimiter, + } + + var skus []sku.SKU + if err, _ := endpoint.Request(ctx, token, nil, &skus); err != nil { + return nil, err + } + + return skus, nil +} diff --git a/rest/soundboard.go b/rest/soundboard.go new file mode 100644 index 0000000..ebb59bc --- /dev/null +++ b/rest/soundboard.go @@ -0,0 +1,138 @@ +package rest + +import ( + "context" + "fmt" + + "github.com/TicketsBot-cloud/gdl/objects/guild/soundboard" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" +) + +type SendSoundboardSoundData struct { + SoundId uint64 `json:"sound_id,string"` + SourceGuildId *uint64 `json:"source_guild_id,string,omitempty"` +} + +type CreateGuildSoundboardSoundData struct { + Name string `json:"name"` + Sound string `json:"sound"` + Volume *float64 `json:"volume,omitempty"` + EmojiId *uint64 `json:"emoji_id,string,omitempty"` + EmojiName *string `json:"emoji_name,omitempty"` +} + +type ModifyGuildSoundboardSoundData struct { + Name *string `json:"name,omitempty"` + Volume *float64 `json:"volume,omitempty"` + EmojiId *uint64 `json:"emoji_id,string,omitempty"` + EmojiName *string `json:"emoji_name,omitempty"` +} + +func SendSoundboardSound(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64, data SendSoundboardSoundData) error { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/channels/%d/send-soundboard-sound", channelId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteSendSoundboardSound, channelId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, data, nil) + return err +} + +func GetDefaultSoundboardSounds(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter) ([]soundboard.SoundboardSound, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: "/soundboard-default-sounds", + Route: ratelimit.NewOtherRoute(ratelimit.RouteGetDefaultSoundboardSounds, 0), + RateLimiter: rateLimiter, + } + + var sounds []soundboard.SoundboardSound + if err, _ := endpoint.Request(ctx, token, nil, &sounds); err != nil { + return nil, err + } + + return sounds, nil +} + +func ListGuildSoundboardSounds(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) ([]soundboard.SoundboardSound, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/soundboard-sounds", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteListGuildSoundboardSounds, guildId), + RateLimiter: rateLimiter, + } + + var sounds []soundboard.SoundboardSound + if err, _ := endpoint.Request(ctx, token, nil, &sounds); err != nil { + return nil, err + } + + return sounds, nil +} + +func GetGuildSoundboardSound(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, soundId uint64) (soundboard.SoundboardSound, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/soundboard-sounds/%d", guildId, soundId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildSoundboardSound, guildId), + RateLimiter: rateLimiter, + } + + var sound soundboard.SoundboardSound + err, _ := endpoint.Request(ctx, token, nil, &sound) + return sound, err +} + +func CreateGuildSoundboardSound(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data CreateGuildSoundboardSoundData) (soundboard.SoundboardSound, error) { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/soundboard-sounds", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteCreateGuildSoundboardSound, guildId), + RateLimiter: rateLimiter, + } + + var sound soundboard.SoundboardSound + if err, _ := endpoint.Request(ctx, token, data, &sound); err != nil { + return soundboard.SoundboardSound{}, err + } + + return sound, nil +} + +func ModifyGuildSoundboardSound(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, soundId uint64, data ModifyGuildSoundboardSoundData) (soundboard.SoundboardSound, error) { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/soundboard-sounds/%d", guildId, soundId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyGuildSoundboardSound, guildId), + RateLimiter: rateLimiter, + } + + var sound soundboard.SoundboardSound + if err, _ := endpoint.Request(ctx, token, data, &sound); err != nil { + return soundboard.SoundboardSound{}, err + } + + return sound, nil +} + +func DeleteGuildSoundboardSound(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, soundId uint64) error { + endpoint := request.Endpoint{ + RequestType: request.DELETE, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/soundboard-sounds/%d", guildId, soundId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteGuildSoundboardSound, guildId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, nil, nil) + return err +} diff --git a/rest/stage.go b/rest/stage.go new file mode 100644 index 0000000..08227a0 --- /dev/null +++ b/rest/stage.go @@ -0,0 +1,84 @@ +package rest + +import ( + "context" + "fmt" + + "github.com/TicketsBot-cloud/gdl/objects/guild/stage" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" +) + +type CreateStageInstanceData struct { + ChannelId uint64 `json:"channel_id,string"` + Topic string `json:"topic"` + PrivacyLevel *stage.StagePrivacyLevel `json:"privacy_level,omitempty"` + SendStartNotification *bool `json:"send_start_notification,omitempty"` + GuildScheduledEventId *uint64 `json:"guild_scheduled_event_id,string,omitempty"` +} + +type ModifyStageInstanceData struct { + Topic *string `json:"topic,omitempty"` + PrivacyLevel *stage.StagePrivacyLevel `json:"privacy_level,omitempty"` +} + +func CreateStageInstance(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, data CreateStageInstanceData) (stage.StageInstance, error) { + endpoint := request.Endpoint{ + RequestType: request.POST, + ContentType: request.ApplicationJson, + Endpoint: "/stage-instances", + Route: ratelimit.NewChannelRoute(ratelimit.RouteCreateStageInstance, data.ChannelId), + RateLimiter: rateLimiter, + } + + var instance stage.StageInstance + if err, _ := endpoint.Request(ctx, token, data, &instance); err != nil { + return stage.StageInstance{}, err + } + + return instance, nil +} + +func GetStageInstance(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64) (stage.StageInstance, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/stage-instances/%d", channelId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteGetStageInstance, channelId), + RateLimiter: rateLimiter, + } + + var instance stage.StageInstance + err, _ := endpoint.Request(ctx, token, nil, &instance) + return instance, err +} + +func ModifyStageInstance(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64, data ModifyStageInstanceData) (stage.StageInstance, error) { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/stage-instances/%d", channelId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteModifyStageInstance, channelId), + RateLimiter: rateLimiter, + } + + var instance stage.StageInstance + if err, _ := endpoint.Request(ctx, token, data, &instance); err != nil { + return stage.StageInstance{}, err + } + + return instance, nil +} + +func DeleteStageInstance(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, channelId uint64) error { + endpoint := request.Endpoint{ + RequestType: request.DELETE, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/stage-instances/%d", channelId), + Route: ratelimit.NewChannelRoute(ratelimit.RouteDeleteStageInstance, channelId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, nil, nil) + return err +} diff --git a/rest/sticker.go b/rest/sticker.go new file mode 100644 index 0000000..7b65050 --- /dev/null +++ b/rest/sticker.go @@ -0,0 +1,136 @@ +package rest + +import ( + "context" + "fmt" + + "github.com/TicketsBot-cloud/gdl/objects/guild/sticker" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" +) + +type ModifyGuildStickerData struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Tags *string `json:"tags,omitempty"` +} + +type StickerPack struct { + Id uint64 `json:"id,string"` + Stickers []sticker.Sticker `json:"stickers"` + Name string `json:"name"` + SkuId uint64 `json:"sku_id,string"` + CoverStickerId *uint64 `json:"cover_sticker_id,string,omitempty"` + Description string `json:"description"` + BannerAssetId *uint64 `json:"banner_asset_id,string,omitempty"` +} + +func GetSticker(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, stickerId uint64) (sticker.Sticker, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/stickers/%d", stickerId), + Route: ratelimit.NewOtherRoute(ratelimit.RouteGetSticker, stickerId), + RateLimiter: rateLimiter, + } + + var s sticker.Sticker + err, _ := endpoint.Request(ctx, token, nil, &s) + return s, err +} + +type stickerPacksResponse struct { + StickerPacks []StickerPack `json:"sticker_packs"` +} + +func GetStickerPacks(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter) ([]StickerPack, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: "/sticker-packs", + Route: ratelimit.NewOtherRoute(ratelimit.RouteGetStickerPacks, 0), + RateLimiter: rateLimiter, + } + + var res stickerPacksResponse + if err, _ := endpoint.Request(ctx, token, nil, &res); err != nil { + return nil, err + } + + return res.StickerPacks, nil +} + +func GetStickerPack(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, packId uint64) (StickerPack, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/sticker-packs/%d", packId), + Route: ratelimit.NewOtherRoute(ratelimit.RouteGetStickerPack, packId), + RateLimiter: rateLimiter, + } + + var pack StickerPack + err, _ := endpoint.Request(ctx, token, nil, &pack) + return pack, err +} + +func ListGuildStickers(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) ([]sticker.Sticker, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/stickers", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteListGuildStickers, guildId), + RateLimiter: rateLimiter, + } + + var stickers []sticker.Sticker + if err, _ := endpoint.Request(ctx, token, nil, &stickers); err != nil { + return nil, err + } + + return stickers, nil +} + +func GetGuildSticker(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, stickerId uint64) (sticker.Sticker, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/stickers/%d", guildId, stickerId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetGuildSticker, guildId), + RateLimiter: rateLimiter, + } + + var s sticker.Sticker + err, _ := endpoint.Request(ctx, token, nil, &s) + return s, err +} + +func ModifyGuildSticker(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, stickerId uint64, data ModifyGuildStickerData) (sticker.Sticker, error) { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/stickers/%d", guildId, stickerId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyGuildSticker, guildId), + RateLimiter: rateLimiter, + } + + var s sticker.Sticker + if err, _ := endpoint.Request(ctx, token, data, &s); err != nil { + return sticker.Sticker{}, err + } + + return s, nil +} + +func DeleteGuildSticker(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, stickerId uint64) error { + endpoint := request.Endpoint{ + RequestType: request.DELETE, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/stickers/%d", guildId, stickerId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteDeleteGuildSticker, guildId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, nil, nil) + return err +} diff --git a/rest/subscription.go b/rest/subscription.go new file mode 100644 index 0000000..8c2e25b --- /dev/null +++ b/rest/subscription.go @@ -0,0 +1,72 @@ +package rest + +import ( + "context" + "fmt" + "net/url" + "strconv" + + "github.com/TicketsBot-cloud/gdl/objects/subscription" + "github.com/TicketsBot-cloud/gdl/rest/ratelimit" + "github.com/TicketsBot-cloud/gdl/rest/request" +) + +type ListSKUSubscriptionsData struct { + Before *uint64 + After *uint64 + Limit *int + UserId *uint64 +} + +func (d *ListSKUSubscriptionsData) Query() string { + query := url.Values{} + + if d.Before != nil { + query.Add("before", strconv.FormatUint(*d.Before, 10)) + } + + if d.After != nil { + query.Add("after", strconv.FormatUint(*d.After, 10)) + } + + if d.Limit != nil { + query.Add("limit", strconv.Itoa(*d.Limit)) + } + + if d.UserId != nil { + query.Add("user_id", strconv.FormatUint(*d.UserId, 10)) + } + + return query.Encode() +} + +func ListSKUSubscriptions(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, skuId uint64, data ListSKUSubscriptionsData) ([]subscription.Subscription, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/skus/%d/subscriptions?%s", skuId, data.Query()), + Route: ratelimit.NewOtherRoute(ratelimit.RouteListSKUSubscriptions, skuId), + RateLimiter: rateLimiter, + } + + var subscriptions []subscription.Subscription + if err, _ := endpoint.Request(ctx, token, nil, &subscriptions); err != nil { + return nil, err + } + + return subscriptions, nil +} + +func GetSKUSubscription(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, skuId, subscriptionId uint64) (subscription.Subscription, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/skus/%d/subscriptions/%d", skuId, subscriptionId), + Route: ratelimit.NewOtherRoute(ratelimit.RouteGetSKUSubscription, skuId), + RateLimiter: rateLimiter, + } + + var sub subscription.Subscription + err, _ := endpoint.Request(ctx, token, nil, &sub) + return sub, err +} diff --git a/rest/user.go b/rest/user.go index ac5be0f..e742a5b 100644 --- a/rest/user.go +++ b/rest/user.go @@ -9,6 +9,7 @@ import ( "github.com/TicketsBot-cloud/gdl/objects/channel" "github.com/TicketsBot-cloud/gdl/objects/guild" "github.com/TicketsBot-cloud/gdl/objects/integration" + "github.com/TicketsBot-cloud/gdl/objects/member" "github.com/TicketsBot-cloud/gdl/objects/user" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" "github.com/TicketsBot-cloud/gdl/rest/request" @@ -43,8 +44,9 @@ func GetUser(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimit } type ModifyUserData struct { - Username string `json:"username,omitempty"` - Avatar string `json:"avatar,omitempty"` + Username string `json:"username,omitempty"` + Avatar *string `json:"avatar,omitempty"` + Banner *string `json:"banner,omitempty"` } func ModifyCurrentUser(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, data ModifyUserData) (user.User, error) { @@ -62,9 +64,10 @@ func ModifyCurrentUser(ctx context.Context, token string, rateLimiter *ratelimit } type CurrentUserGuildsData struct { - Before uint64 - After uint64 - Limit int + Before uint64 + After uint64 + Limit int // 1-200, omitted if 0 + WithCounts bool } func (d *CurrentUserGuildsData) Query() string { @@ -78,10 +81,13 @@ func (d *CurrentUserGuildsData) Query() string { query.Set("after", strconv.FormatUint(d.After, 10)) } - if d.Limit > 200 || d.Limit < 1 { - d.Limit = 200 + if d.Limit >= 1 && d.Limit <= 200 { + query.Set("limit", strconv.Itoa(d.Limit)) + } + + if d.WithCounts { + query.Set("with_counts", "true") } - query.Set("limit", strconv.Itoa(d.Limit)) return query.Encode() } @@ -100,6 +106,20 @@ func GetCurrentUserGuilds(ctx context.Context, token string, rateLimiter *rateli return guilds, err } +func GetCurrentUserGuildMember(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) (member.Member, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/users/@me/guilds/%d/member", guildId), + Route: ratelimit.NewOtherRoute(ratelimit.RouteGetCurrentUserGuildMember, 0), + RateLimiter: rateLimiter, + } + + var m member.Member + err, _ := endpoint.Request(ctx, token, nil, &m) + return m, err +} + func LeaveGuild(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) error { endpoint := request.Endpoint{ RequestType: request.DELETE, @@ -117,7 +137,7 @@ func CreateDM(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimi endpoint := request.Endpoint{ RequestType: request.POST, ContentType: request.ApplicationJson, - Endpoint: fmt.Sprintf("/users/@me/channels"), + Endpoint: "/users/@me/channels", Route: ratelimit.NewOtherRoute(ratelimit.RouteCreateDM, recipientId), RateLimiter: rateLimiter, } @@ -135,7 +155,7 @@ func GetUserConnections(ctx context.Context, token string, rateLimiter *ratelimi endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/users/@me/connections"), + Endpoint: "/users/@me/connections", Route: ratelimit.NewOtherRoute(ratelimit.RouteGetUserConnections, 0), RateLimiter: rateLimiter, } diff --git a/rest/voice.go b/rest/voice.go index 0dea5dd..e53bd62 100644 --- a/rest/voice.go +++ b/rest/voice.go @@ -3,6 +3,7 @@ package rest import ( "context" "fmt" + "time" "github.com/TicketsBot-cloud/gdl/objects/guild" "github.com/TicketsBot-cloud/gdl/rest/ratelimit" @@ -13,7 +14,7 @@ func ListVoiceRegions(ctx context.Context, token string) ([]guild.VoiceRegion, e endpoint := request.Endpoint{ RequestType: request.GET, ContentType: request.Nil, - Endpoint: fmt.Sprintf("/voice/regions"), + Endpoint: "/voice/regions", Route: ratelimit.NewOtherRoute(ratelimit.RouteListVoiceRegions, 0), } @@ -21,3 +22,68 @@ func ListVoiceRegions(ctx context.Context, token string) ([]guild.VoiceRegion, e err, _ := endpoint.Request(ctx, token, nil, &voiceRegions) return voiceRegions, err } + +func GetCurrentUserVoiceState(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64) (guild.VoiceState, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/voice-states/@me", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetCurrentUserVoiceState, guildId), + RateLimiter: rateLimiter, + } + + var state guild.VoiceState + err, _ := endpoint.Request(ctx, token, nil, &state) + return state, err +} + +func GetUserVoiceState(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId uint64) (guild.VoiceState, error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/guilds/%d/voice-states/%d", guildId, userId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteGetUserVoiceState, guildId), + RateLimiter: rateLimiter, + } + + var state guild.VoiceState + err, _ := endpoint.Request(ctx, token, nil, &state) + return state, err +} + +type ModifyCurrentUserVoiceStateData struct { + ChannelId *uint64 `json:"channel_id,string,omitempty"` + Suppress *bool `json:"suppress,omitempty"` + RequestToSpeakTimestamp *time.Time `json:"request_to_speak_timestamp,omitempty"` +} + +func ModifyCurrentUserVoiceState(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId uint64, data ModifyCurrentUserVoiceStateData) error { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/voice-states/@me", guildId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyCurrentUserVoiceState, guildId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, data, nil) + return err +} + +type ModifyUserVoiceStateData struct { + ChannelId *uint64 `json:"channel_id,string,omitempty"` + Suppress *bool `json:"suppress,omitempty"` +} + +func ModifyUserVoiceState(ctx context.Context, token string, rateLimiter *ratelimit.Ratelimiter, guildId, userId uint64, data ModifyUserVoiceStateData) error { + endpoint := request.Endpoint{ + RequestType: request.PATCH, + ContentType: request.ApplicationJson, + Endpoint: fmt.Sprintf("/guilds/%d/voice-states/%d", guildId, userId), + Route: ratelimit.NewGuildRoute(ratelimit.RouteModifyUserVoiceState, guildId), + RateLimiter: rateLimiter, + } + + err, _ := endpoint.Request(ctx, token, data, nil) + return err +} diff --git a/rest/webhook.go b/rest/webhook.go index 2e88d2f..09e27dc 100644 --- a/rest/webhook.go +++ b/rest/webhook.go @@ -151,12 +151,13 @@ type WebhookBody struct { Content string `json:"content,omitempty"` Username string `json:"username,omitempty"` AvatarUrl string `json:"avatar_url,omitempty"` - Tts bool `json:"tts"` + Tts bool `json:"tts,omitempty"` Flags uint `json:"flags,omitempty"` Embeds []*embed.Embed `json:"embeds,omitempty"` AllowedMentions message.AllowedMention `json:"allowed_mentions,omitempty"` Components []component.Component `json:"components,omitempty"` Attachments []request.Attachment `json:"attachments,omitempty"` + ThreadId *uint64 `json:"thread_id,string,omitempty"` ThreadName string `json:"thread_name,omitempty"` } @@ -210,12 +211,25 @@ func (d WebhookEditBody) GetAttachments() []request.Attachment { return d.Attachments } +func GetWebhookMessage(ctx context.Context, webhookToken string, rateLimiter *ratelimit.Ratelimiter, webhookId, messageId uint64) (msg message.Message, err error) { + endpoint := request.Endpoint{ + RequestType: request.GET, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/webhooks/%d/%s/messages/%d", webhookId, webhookToken, messageId), + Route: ratelimit.NewWebhookRoute(ratelimit.RouteGetWebhookMessage, webhookId), + RateLimiter: rateLimiter, + } + + err, _ = endpoint.Request(ctx, "", nil, &msg) + return +} + func EditWebhookMessage(ctx context.Context, webhookToken string, rateLimiter *ratelimit.Ratelimiter, webhookId, messageId uint64, data WebhookEditBody) (msg message.Message, err error) { var endpoint request.Endpoint if len(data.Attachments) == 0 { endpoint = request.Endpoint{ - RequestType: request.POST, + RequestType: request.PATCH, ContentType: request.ApplicationJson, Endpoint: fmt.Sprintf("/webhooks/%d/%s/messages/%d", webhookId, webhookToken, messageId), Route: ratelimit.NewWebhookRoute(ratelimit.RouteEditWebhookMessage, webhookId), @@ -223,7 +237,7 @@ func EditWebhookMessage(ctx context.Context, webhookToken string, rateLimiter *r } } else { endpoint = request.Endpoint{ - RequestType: request.POST, + RequestType: request.PATCH, ContentType: request.MultipartFormData, Endpoint: fmt.Sprintf("/webhooks/%d/%s/messages/%d", webhookId, webhookToken, messageId), Route: ratelimit.NewWebhookRoute(ratelimit.RouteEditWebhookMessage, webhookId), @@ -234,3 +248,16 @@ func EditWebhookMessage(ctx context.Context, webhookToken string, rateLimiter *r err, _ = endpoint.Request(ctx, "", data, &msg) return } + +func DeleteWebhookMessage(ctx context.Context, webhookToken string, rateLimiter *ratelimit.Ratelimiter, webhookId, messageId uint64) (err error) { + endpoint := request.Endpoint{ + RequestType: request.DELETE, + ContentType: request.Nil, + Endpoint: fmt.Sprintf("/webhooks/%d/%s/messages/%d", webhookId, webhookToken, messageId), + Route: ratelimit.NewWebhookRoute(ratelimit.RouteDeleteWebhookMessage, webhookId), + RateLimiter: rateLimiter, + } + + err, _ = endpoint.Request(ctx, "", nil, nil) + return +} diff --git a/test/interactiondeserialization_test.go b/test/interactiondeserialization_test.go index dc0c60f..37f3bf1 100644 --- a/test/interactiondeserialization_test.go +++ b/test/interactiondeserialization_test.go @@ -28,7 +28,7 @@ func TestDeserializeSelectMenuInteraction(t *testing.T) { return } - MustMatch(t, "interaction type", i.Data.Type(), component.ComponentSelectMenu) + MustMatch(t, "interaction type", i.Data.Type(), component.ComponentStringSelect) data := i.Data.AsSelectMenu() MustMatch(t, "custom id", data.CustomId, "class_select_1") diff --git a/utils/reflectionutils.go b/utils/reflectionutils.go index db8a8da..00521d5 100644 --- a/utils/reflectionutils.go +++ b/utils/reflectionutils.go @@ -33,4 +33,3 @@ func IsZero(v reflect.Value) bool { return result } - diff --git a/utils/uintstringslice.go b/utils/uintstringslice.go index 1da3ab0..a4f36b0 100644 --- a/utils/uintstringslice.go +++ b/utils/uintstringslice.go @@ -43,4 +43,3 @@ func (slice *Uint64StringSlice) UnmarshalJSON(b []byte) error { } return nil } -