diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 32090e36..3cc9868f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,13 +1,13 @@ version: 2 updates: -- package-ecosystem: gomod - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 - target-branch: development -- package-ecosystem: gomod - directory: "/example" - schedule: - interval: daily - open-pull-requests-limit: 10 + - package-ecosystem: gomod + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + target-branch: development + - package-ecosystem: gomod + directory: "/example" + schedule: + interval: daily + open-pull-requests-limit: 10 diff --git a/api/action_row.go b/api/action_row.go new file mode 100644 index 00000000..3b1bd0d4 --- /dev/null +++ b/api/action_row.go @@ -0,0 +1,15 @@ +package api + +// NewActionRow creates a new ActionRow holding th provided Component(s) +func NewActionRow(components ...Component) *ActionRow { + return &ActionRow{ + ComponentImpl: newComponentImpl(ComponentTypeActionRow), + Components: components, + } +} + +// ActionRow holds up to 5 Component(s) in a row +type ActionRow struct { + ComponentImpl + Components []Component `json:"components"` +} diff --git a/api/button.go b/api/button.go new file mode 100644 index 00000000..641ea2c5 --- /dev/null +++ b/api/button.go @@ -0,0 +1,62 @@ +package api + +// ButtonStyle defines how the Button looks like (https://discord.com/assets/7bb017ce52cfd6575e21c058feb3883b.png) +type ButtonStyle int + +// Supported ButtonStyle(s) +const ( + ButtonStylePrimary = iota + 1 + ButtonStyleSecondary + ButtonStyleSuccess + ButtonStyleDanger + ButtonStyleLink +) + +// NewButton creates a new Button with the provided parameters. Link Button(s) need a url and other Button(s) need a customID +func NewButton(style ButtonStyle, label *string, customID string, url string, emote *Emote, disabled bool) *Button { + return &Button{ + ComponentImpl: newComponentImpl(ComponentTypeButton), + Style: style, + CustomID: customID, + URL: url, + Label: label, + Emote: emote, + Disabled: disabled, + } +} + +// NewPrimaryButton creates a new Button with ButtonStylePrimary & the provided parameters +func NewPrimaryButton(label string, customID string, emote *Emote, disabled bool) *Button { + return NewButton(ButtonStylePrimary, &label, customID, "", emote, disabled) +} + +// NewSecondaryButton creates a new Button with ButtonStyleSecondary & the provided parameters +func NewSecondaryButton(label string, customID string, emote *Emote, disabled bool) *Button { + return NewButton(ButtonStyleSecondary, &label, customID, "", emote, disabled) +} + +// NewSuccessButton creates a new Button with ButtonStyleSuccess & the provided parameters +func NewSuccessButton(label string, customID string, emote *Emote, disabled bool) *Button { + return NewButton(ButtonStyleSuccess, &label, customID, "", emote, disabled) +} + +// NewDangerButton creates a new Button with ButtonStyleDanger & the provided parameters +func NewDangerButton(label string, customID string, emote *Emote, disabled bool) *Button { + return NewButton(ButtonStyleDanger, &label, customID, "", emote, disabled) +} + +// NewLinkButton creates a new link Button with ButtonStyleLink & the provided parameters +func NewLinkButton(label string, url string, emote *Emote, disabled bool) *Button { + return NewButton(ButtonStyleLink, &label, "", url, emote, disabled) +} + +// Button can be attacked to all messages & be clicked by a User. If clicked it fires a events.ButtonClickEvent with the declared customID +type Button struct { + ComponentImpl + Style ButtonStyle `json:"style,omitempty"` + Label *string `json:"label,omitempty"` + Emote *Emote `json:"emoji,omitempty"` + CustomID string `json:"custom_id,omitempty"` + URL string `json:"url,omitempty"` + Disabled bool `json:"disabled,omitempty"` +} diff --git a/api/component.go b/api/component.go new file mode 100644 index 00000000..bddaa23c --- /dev/null +++ b/api/component.go @@ -0,0 +1,41 @@ +package api + +// ComponentType defines different Component(s) +type ComponentType int + +// Supported ComponentType(s) +const ( + ComponentTypeActionRow = iota + 1 + ComponentTypeButton +) + +// Component is a general interface each Component needs to implement +type Component interface { + Type() ComponentType +} + +func newComponentImpl(componentType ComponentType) ComponentImpl { + return ComponentImpl{ComponentType: componentType} +} + +// ComponentImpl is used to embed in each different ComponentType +type ComponentImpl struct { + ComponentType ComponentType `json:"type"` +} + +// Type returns the ComponentType of this Component +func (t ComponentImpl) Type() ComponentType { + return t.ComponentType +} + +// UnmarshalComponent is used for easier unmarshalling of different Component(s) +type UnmarshalComponent struct { + ComponentType ComponentType `json:"type"` + Style ButtonStyle `json:"style"` + Label *string `json:"label"` + Emote *Emote `json:"emoji"` + CustomID string `json:"custom_id"` + URL string `json:"url"` + Disabled bool `json:"disabled"` + Components []*UnmarshalComponent `json:"components"` +} diff --git a/api/emote.go b/api/emote.go index 5df8157f..e77ef2d8 100644 --- a/api/emote.go +++ b/api/emote.go @@ -1,12 +1,27 @@ package api -// An Emote allows you to interact with custom emojis in discord. +// NewEmote creates a new custom Emote with the given parameters +func NewEmote(name string, emoteID Snowflake) *Emote { + return &Emote{Name: name, ID: emoteID, Animated: false} +} + +// NewAnimatedEmote creates a new animated custom Emote with the given parameters +func NewAnimatedEmote(name string, emoteID Snowflake) *Emote { + return &Emote{Name: name, ID: emoteID, Animated: true} +} + +// NewEmoji creates a new emoji with the given unicode +func NewEmoji(name string) *Emote { + return &Emote{Name: name} +} + +// Emote allows you to interact with emojis & emotes type Emote struct { Disgo Disgo - ID Snowflake - GuildID Snowflake - Name string - Animated bool + GuildID Snowflake `json:"guild_id,omitempty"` + Name string `json:"name,omitempty"` + ID Snowflake `json:"id,omitempty"` + Animated bool `json:"animated,omitempty"` } // Guild returns the Guild of the Emote from the Cache diff --git a/api/endpoints/api_route.go b/api/endpoints/api_route.go deleted file mode 100644 index 887d0d13..00000000 --- a/api/endpoints/api_route.go +++ /dev/null @@ -1,47 +0,0 @@ -package endpoints - -// APIRoute is a basic struct containing Method and URL -type APIRoute struct { - Route - method Method -} - -// Compile returns a CompiledAPIRoute -func (r APIRoute) Compile(args ...interface{}) (*CompiledAPIRoute, error) { - compiledRoute, err := r.Route.Compile(args...) - if err != nil { - return nil, err - } - return &CompiledAPIRoute{ - CompiledRoute: compiledRoute, - method: r.method, - }, nil -} - -// Method returns the request method used by the route -func (r APIRoute) Method() Method { - return r.method -} - -// NewAPIRoute generates a new discord api route struct -func NewAPIRoute(method Method, url string) APIRoute { - return APIRoute{ - Route: Route{ - baseRoute: API, - route: url, - paramCount: countParams(url), - }, - method: method, - } -} - -// CompiledAPIRoute is APIRoute compiled with all URL args -type CompiledAPIRoute struct { - *CompiledRoute - method Method -} - -// Method returns the request method used by the route -func (r CompiledAPIRoute) Method() Method { - return r.method -} diff --git a/api/endpoints/cdn_route.go b/api/endpoints/cdn_route.go deleted file mode 100644 index 7df913d3..00000000 --- a/api/endpoints/cdn_route.go +++ /dev/null @@ -1,66 +0,0 @@ -package endpoints - -import ( - "errors" -) - -// FileExtension is the type of an image on Discord's CDN -type FileExtension string - -// The available FileExtension(s) -const ( - PNG FileExtension = "png" - JPEG FileExtension = "jpg" - WEBP FileExtension = "webp" - GIF FileExtension = "gif" - BLANK FileExtension = "" -) - -func (f FileExtension) String() string { - return string(f) -} - -// CDNRoute is a route for interacting with images hosted on discord's CDN -type CDNRoute struct { - Route - supportedFileExtensions []FileExtension -} - -// NewCDNRoute generates a new discord cdn route struct -func NewCDNRoute(url string, supportedFileExtensions ...FileExtension) CDNRoute { - return CDNRoute{ - Route: Route{ - baseRoute: CDN, - route: url, - paramCount: countParams(url), - }, - supportedFileExtensions: supportedFileExtensions, - } -} - -// Compile builds a full request URL based on provided arguments -func (r CDNRoute) Compile(fileExtension FileExtension, args ...interface{}) (*CompiledCDNRoute, error) { - supported := false - for _, supportedFileExtension := range r.supportedFileExtensions { - if supportedFileExtension == fileExtension { - supported = true - } - } - if !supported { - return nil, errors.New("provided file extension: " + fileExtension.String() + " is not supported by discord on this endpoint!") - } - compiledRoute, err := r.Route.Compile(args...) - if err != nil { - return nil, err - } - compiledRoute.route += fileExtension.String() - compiledCDNRoute := &CompiledCDNRoute{ - CompiledRoute: compiledRoute, - } - return compiledCDNRoute, nil -} - -// CompiledCDNRoute is CDNRoute compiled with all URL args -type CompiledCDNRoute struct { - *CompiledRoute -} diff --git a/api/endpoints/custom_route.go b/api/endpoints/custom_route.go deleted file mode 100644 index 64b26672..00000000 --- a/api/endpoints/custom_route.go +++ /dev/null @@ -1,30 +0,0 @@ -package endpoints - -// CustomRoute is APIRoute but custom for you -type CustomRoute struct { - APIRoute -} - -// Compile returns a CompiledAPIRoute -func (r CustomRoute) Compile(args ...interface{}) (*CompiledAPIRoute, error) { - compiledRoute, err := r.Route.Compile(args...) - if err != nil { - return nil, err - } - return &CompiledAPIRoute{ - CompiledRoute: compiledRoute, - method: r.method, - }, nil -} - -// NewCustomRoute generates a new custom route struct -func NewCustomRoute(method Method, url string) APIRoute { - return APIRoute{ - Route: Route{ - baseRoute: "", - route: url, - paramCount: countParams(url), - }, - method: method, - } -} diff --git a/api/endpoints/endpoints.go b/api/endpoints/endpoints.go deleted file mode 100644 index d335c1f5..00000000 --- a/api/endpoints/endpoints.go +++ /dev/null @@ -1,209 +0,0 @@ -package endpoints - -// Discord Endpoint Constants -const ( - APIVersion = "8" - Base = "https://discord.com/" - CDN = "https://cdn.discordapp.com" - API = Base + "api/v" + APIVersion -) - -// Misc -var ( - GetGateway = NewAPIRoute(GET, "/gateway") - GetGatewayBot = NewAPIRoute(GET, "/gateway/bot") - GetBotApplication = NewAPIRoute(GET, "/oauth2/applications/@me") -) - -// Interactions -var ( - GetGlobalCommands = NewAPIRoute(GET, "/applications/{application.id}/commands") - GetGlobalCommand = NewAPIRoute(GET, "/applications/{application.id}/command/{command.id}") - CreateGlobalCommand = NewAPIRoute(POST, "/applications/{application.id}/commands") - SetGlobalCommands = NewAPIRoute(PUT, "/applications/{application.id}/commands") - EditGlobalCommand = NewAPIRoute(PATCH, "/applications/{application.id}/commands/{command.id}") - DeleteGlobalCommand = NewAPIRoute(DELETE, "/applications/{application.id}/commands") - - GetGuildCommands = NewAPIRoute(GET, "/applications/{application.id}/guilds/{guild.id}/commands") - GetGuildCommand = NewAPIRoute(GET, "/applications/{application.id}/guilds/{guild.id}/command/{command.id}") - CreateGuildCommand = NewAPIRoute(POST, "/applications/{application.id}/guilds/{guild.id}/commands") - SetGuildCommands = NewAPIRoute(PUT, "/applications/{application.id}/guilds/{guild.id}/commands") - EditGuildCommand = NewAPIRoute(PATCH, "/applications/{application.id}/guilds/{guild.id}/commands/{command.id}") - DeleteGuildCommand = NewAPIRoute(DELETE, "/applications/{application.id}/guilds/{guild.id}/commands") - - GetGuildCommandPermissions = NewAPIRoute(GET, "/applications/{application.id}/guilds/{guild.id}/commands/permissions") - GetGuildCommandPermission = NewAPIRoute(GET, "/applications/{application.id}/guilds/{guild.id}/commands/{command.id}/permissions") - SetGuildCommandsPermissions = NewAPIRoute(PUT, "/applications/{application.id}/guilds/{guild.id}/commands/permissions") - SetGuildCommandPermissions = NewAPIRoute(PUT, "/applications/{application.id}/guilds/{guild.id}/commands/{command.id}/permissions") - - CreateInteractionResponse = NewAPIRoute(POST, "/interactions/{interaction.id}/{interaction.token}/callback") - EditInteractionResponse = NewAPIRoute(PATCH, "/webhooks/{application.id}/{interaction.token}/messages/@original") - DeleteInteractionResponse = NewAPIRoute(DELETE, "/webhooks/{application.id}/{interaction.token}/messages/@original") - - CreateFollowupMessage = NewAPIRoute(POST, "/webhooks/{application.id}/{interaction.token}") - EditFollowupMessage = NewAPIRoute(PATCH, "/webhooks/{application.id}/{interaction.token}/messages/{message.id}") - DeleteFollowupMessage = NewAPIRoute(DELETE, "/webhooks/{application.id}/{interaction.token}/messages/{message.id}") -) - -// Users -var ( - GetUser = NewAPIRoute(GET, "/users/{user.id}") - GetSelfUser = NewAPIRoute(GET, "/users/@me") - UpdateSelfUser = NewAPIRoute(PATCH, "/users/@me") - GetGuilds = NewAPIRoute(GET, "/users/@me/guilds") - LeaveGuild = NewAPIRoute(DELETE, "/users/@me/guilds/{guild.id}") - GetDMChannels = NewAPIRoute(GET, "/users/@me/channels") - CreateDMChannel = NewAPIRoute(POST, "/users/@me/channels") -) - -// Guilds -var ( - GetGuild = NewAPIRoute(GET, "/guilds/{guild.id}") - CreateGuild = NewAPIRoute(POST, "/guilds") - UpdateGuild = NewAPIRoute(PATCH, "/guilds/{guild.id}") - DeleteGuild = NewAPIRoute(DELETE, "/guilds/{guild.id}") - GetVanityURL = NewAPIRoute(GET, "/guilds/{guild.id}/vanity-url") - - CreateChannel = NewAPIRoute(POST, "/guilds/{guild.id}/channels") - GetChannels = NewAPIRoute(GET, "/guilds/{guild.id}/channels") - UpdateChannels = NewAPIRoute(PATCH, "/guilds/{guild.id}/channels") - - GetBans = NewAPIRoute(GET, "/guilds/{guild.id}/bans") - GetBan = NewAPIRoute(GET, "/guilds/{guild.id}/bans/{user.id}") - CreateBan = NewAPIRoute(POST, "/guilds/{guild.id}/bans/{user.id}") - DeleteBan = NewAPIRoute(DELETE, "/guilds/{guild.id}/bans/{user.id}") - - GetMember = NewAPIRoute(GET, "/guilds/{guild.id}/members/{user.id}") - GetMembers = NewAPIRoute(GET, "/guilds/{guild.id}/members") - AddMember = NewAPIRoute(PUT, "/guilds/{guild.id}/members/{user.id}") - UpdateMember = NewAPIRoute(PATCH, "/guilds/{guild.id}/members/{user.id}") - RemoveMember = NewAPIRoute(DELETE, "/guilds/{guild.id}/members/{user.id}") - RemoveMemberReason = NewAPIRoute(DELETE, "/guilds/{guild.id}/members/{user.id}?reason={reason}") - AddMemberRole = NewAPIRoute(PUT, "/guilds/{guild.id}/members/{user.id}/roles/{role.id}") - RemoveMemberRole = NewAPIRoute(DELETE, "/guilds/{guild.id}/members/{user.id}/roles/{role.id}") - - UpdateSelfNick = NewAPIRoute(PATCH, "/guilds/{guild.id}/members/@me/nick") - - PrunableCount = NewAPIRoute(GET, "/guilds/{guild.id}/prune") - PruneMembers = NewAPIRoute(POST, "/guilds/{guild.id}/prune") - - GetGuildWebhooks = NewAPIRoute(GET, "/guilds/{guild.id}/webhooks") - - GetAuditLogs = NewAPIRoute(GET, "/guilds/{guild.id}/audit-logs") - - GetVoiceRegions = NewAPIRoute(GET, "/guilds/{guild.id}/regions") - - GetIntegrations = NewAPIRoute(GET, "/guilds/{guild.id}/integrations") - CreateIntegration = NewAPIRoute(POST, "/guilds/{guild.id}/integrations") - UpdateIntegration = NewAPIRoute(PATCH, "/guilds/{guild.id}/integrations/{integration.id}") - DeleteIntegration = NewAPIRoute(DELETE, "/guilds/{guild.id}/integrations/{integration.id}") - SyncIntegration = NewAPIRoute(POST, "/guilds/{guild.id}/integrations/{integration.id}/sync") -) - -// Roles -var ( - GetRoles = NewAPIRoute(GET, "/guilds/{guild.id}/roles") - GetRole = NewAPIRoute(GET, "/guilds/{guild.id}/roles/{role.id}") - CreateRole = NewAPIRoute(POST, "/guilds/{guild.id}/roles") - UpdateRoles = NewAPIRoute(PATCH, "/guilds/{guild.id}/roles") - UpdateRole = NewAPIRoute(PATCH, "/guilds/{guild.id}/roles/{role.id}") - UpdateRolePositions = NewAPIRoute(PATCH, "/guilds/{guild.id}/roles") - DelteRole = NewAPIRoute(DELETE, "/guilds/{guild.id}/roles/{role.id}") -) - -// Channels -var ( - GetChannel = NewAPIRoute(GET, "/channels/{channel.id}") - UpdateChannel = NewAPIRoute(PATCH, "/channels/{channel.id}") - DeleteChannel = NewAPIRoute(DELETE, "/channels/{channel.id}") - - GetWebhooks = NewAPIRoute(GET, "/channels/{channel.id}/webhooks") - CreateWebhook = NewAPIRoute(POST, "/channels/{channel.id}/webhooks") - - GetPermissionOverrides = NewAPIRoute(GET, "/channels/{channel.id}/permissions") - GetPermissionOverride = NewAPIRoute(GET, "/channels/{channel.id}/permissions/{overwrite.id}") - CreatePermissionOverride = NewAPIRoute(PUT, "/channels/{channel.id}/permissions/{overwrite.id}") - UpdatePermissionOverride = NewAPIRoute(PUT, "/channels/{channel.id}/permissions/{overwrite.id}") - DeletePermissionOverride = NewAPIRoute(DELETE, "/channels/{channel.id}/permissions/{overwrite.id}") - - SendTyping = NewAPIRoute(POST, "/channels/{channel.id}/typing") -) - -// Messages -var ( - GetMessages = NewAPIRoute(GET, "/channels/{channel.id}/messages") - GetMessage = NewAPIRoute(GET, "/channels/{channel.id}/messages/{message.id}") - CreateMessage = NewAPIRoute(POST, "/channels/{channel.id}/messages") - UpdateMessage = NewAPIRoute(PATCH, "/channels/{channel.id}/messages/{message.id}") - DeleteMessage = NewAPIRoute(DELETE, "/channels/{channel.id}/messages/{message.id}") - BulkDeleteMessage = NewAPIRoute(POST, "/channels/{channel.id}/messages/bulk-delete") - - GetPinnedMessages = NewAPIRoute(GET, "/channels/{channel.id}/pins") - AddPinnedMessage = NewAPIRoute(PUT, "/channels/{channel.id}/pins/{message.id}") - RemovePinnedMessage = NewAPIRoute(DELETE, "/channels/{channel.id}/pins/{message.id}") - - CrosspostMessage = NewAPIRoute(POST, "/channels/{channel.id}/messages/{message.id}/crosspost") - - GetReactions = NewAPIRoute(GET, "/channels/{channel.id}/messages/{message.id}/reactions/{emoji}") - AddReaction = NewAPIRoute(PUT, "/channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me") - RemoveOwnReaction = NewAPIRoute(DELETE, "/channels/{channel.id}/messages/{message.id}/reactions/{emoji}/@me") - RemoveUserReaction = NewAPIRoute(DELETE, "/channels/{channel.id}/messages/{message.id}/reactions/{emoji}/{user.id}") - RemoveAllReactions = NewAPIRoute(DELETE, "/channels/{channel.id}/messages/{message.id}/reactions") - RemoveAllReactionsEmoji = NewAPIRoute(DELETE, "/channels/{channel.id}/messages/{message.id}/reactions/{emoji}") -) - -// Emotes -var ( - GetEmotes = NewAPIRoute(GET, "/guilds/{guild.id}/emojis") - Getemote = NewAPIRoute(GET, "/guilds/{guild.id}/emojis/{emoji.id}") - CreateEmote = NewAPIRoute(POST, "/guilds/{guild.id}/emojis") - UpdateEmote = NewAPIRoute(PATCH, "/guilds/{guild.id}/emojis/{emote.id}") - DeleteEmote = NewAPIRoute(DELETE, "/guilds/{guild.id}/emojis/{emote.id}") -) - -// Webhooks -var ( - GetWebhook = NewAPIRoute(GET, "/webhooks/{webhook.id}") - GetWebhookWithToken = NewAPIRoute(GET, "/webhooks/{webhook.id}/{token}") - UpdateWebhok = NewAPIRoute(PATCH, "/webhooks/{webhook.id}") - UpdateWebhokWithToken = NewAPIRoute(PATCH, "/webhooks/{webhook.id}/{token}") - DeleteWebhook = NewAPIRoute(DELETE, "/webhooks/{webhook.id}") - DeleteWebhookWithToken = NewAPIRoute(DELETE, "/webhooks/{webhook.id}/{token}") - - CreateWebhookMessage = NewAPIRoute(POST, "/webhooks/{webhook.id}") - CreateWebhookMessageSlack = NewAPIRoute(POST, "/webhooks/{webhook.id}/slack") - CreateWebhookMessageGithub = NewAPIRoute(POST, "/webhooks/{webhook.id}/github") - UpdateWebhookMessage = NewAPIRoute(POST, "/webhooks/{webhook.id}/{token}/messages/{message.id}") - DeleteWebhookMessage = NewAPIRoute(POST, "/webhooks/{webhook.id}/{token}/messages/{message.id}") -) - -// Invites -var ( - GetInvite = NewAPIRoute(GET, "/invites/{code}") - CreateInvite = NewAPIRoute(POST, "/channels/{channel.id}/invites") - DeleteInvite = NewAPIRoute(DELETE, "/invites/{code}") - - GetGuildInvite = NewAPIRoute(GET, "/guilds/{guild.id}/invites") - GetChannelInvites = NewAPIRoute(GET, "/channels/{channel.id}/invites") -) - -// CDN -var ( - Emote = NewCDNRoute("/emojis/{emote.id}.", PNG, GIF) - GuildIcon = NewCDNRoute("/icons/{guild.id}/{icon.hash}.", PNG, JPEG, WEBP, GIF) - GuildSplash = NewCDNRoute("/splashes/{guild.id}/guild.splash.", PNG, JPEG, WEBP) - GuildDiscoverySplash = NewCDNRoute("/discovery-splashes/{guild.id}/guild.discovery.splash.", PNG, JPEG, WEBP) - GuildBanner = NewCDNRoute("/banners/{guild.id}/guild.banner.", PNG, JPEG, WEBP) - DefaultUserAvatar = NewCDNRoute("/embed/avatars/{user.discriminator%5}.", PNG) - UserAvatar = NewCDNRoute("/avatars/{user.id}/user.avatar.", PNG, JPEG, WEBP, GIF) - ApplicationIcon = NewCDNRoute("/app-icons/{application.id}/icon.", PNG, JPEG, WEBP) - ApplicationAsset = NewCDNRoute("/app-assets/{application.id}/{asset.id}.", PNG, JPEG, WEBP) - AchievementIcon = NewCDNRoute("/app-assets/{application.id}/achievements/{achievement.id}/icons/{icon.hash}.", PNG, JPEG, WEBP) - TeamIcon = NewCDNRoute("/team-icons/{team.id}/team.icon.", PNG, JPEG, WEBP) - Attachments = NewCDNRoute("/attachments/{channel.id}/{attachment.id}/{file.name}", BLANK) -) - -// Other -var ( - InviteURL = NewRoute("https://discord.gg/{code}") -) diff --git a/api/endpoints/methods.go b/api/endpoints/methods.go deleted file mode 100644 index 658e8aab..00000000 --- a/api/endpoints/methods.go +++ /dev/null @@ -1,17 +0,0 @@ -package endpoints - -// Method is a HTTP request Method -type Method string - -// HTTP Methods used by Discord -const ( - DELETE Method = "DELETE" - GET Method = "GET" - POST Method = "POST" - PUT Method = "PUT" - PATCH Method = "PATCH" -) - -func (m Method) String() string { - return string(m) -} diff --git a/api/endpoints/route.go b/api/endpoints/route.go deleted file mode 100644 index 771a8e58..00000000 --- a/api/endpoints/route.go +++ /dev/null @@ -1,56 +0,0 @@ -package endpoints - -import ( - "errors" - "fmt" - "strconv" - "strings" -) - -// Route the base struct for routes used in disgo -type Route struct { - baseRoute string - route string - paramCount int -} - -// Compile builds a full request URL based on provided arguments -func (r Route) Compile(args ...interface{}) (*CompiledRoute, error) { - if len(args) != r.paramCount { - return nil, errors.New("invalid amount of arguments received. expected: " + strconv.Itoa(len(args)) + ", received: " + strconv.Itoa(r.paramCount)) - } - route := r.route - if len(args) > 0 { - for _, arg := range args { - start := strings.Index(route, "{") - end := strings.Index(route, "}") - route = route[:start] + fmt.Sprint(arg) + route[end+1:] - } - } - - return &CompiledRoute{route: r.baseRoute + route}, nil -} - -// NewRoute generates a Route when given a URL -func NewRoute(url string) Route { - return Route{ - baseRoute: "", - route: url, - paramCount: countParams(url), - } -} - -func countParams(url string) int { - paramCount := strings.Count(url, "{") - return paramCount -} - -// CompiledRoute is Route compiled with all URL args -type CompiledRoute struct { - route string -} - -// Route returns the full request url -func (r CompiledRoute) Route() string { - return r.route -} diff --git a/api/endpoints/route_test.go b/api/endpoints/route_test.go deleted file mode 100644 index 052238ff..00000000 --- a/api/endpoints/route_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package endpoints - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestAPIRoute_Compile(t *testing.T) { - compiledRoute, err := AddReaction.Compile("test1", "test2", "test3") - assert.NoError(t, err) - assert.Equal(t, API+"/channels/test1/messages/test2/reactions/test3/@me", compiledRoute.Route()) -} - -func TestCDNRoute_Compile(t *testing.T) { - compiledRoute, err := Emote.Compile(PNG, "test1") - assert.NoError(t, err) - assert.Equal(t, CDN+"/emojis/test1.png", compiledRoute.Route()) - - compiledRoute, err = Emote.Compile(GIF, "test1") - assert.NoError(t, err) - assert.Equal(t, CDN+"/emojis/test1.gif", compiledRoute.Route()) -} - -func TestCustomRoute_Compile(t *testing.T) { - testAPI := NewCustomRoute(GET, "https://test.de/{test}") - - compiledRoute, err := testAPI.Compile("test") - assert.NoError(t, err) - assert.Equal(t, "https://test.de/test", compiledRoute.Route()) -} diff --git a/api/entity_builder.go b/api/entity_builder.go index c97a6379..41c179a2 100644 --- a/api/entity_builder.go +++ b/api/entity_builder.go @@ -15,13 +15,14 @@ var ( type EntityBuilder interface { Disgo() Disgo - CreateInteraction(interaction *Interaction, updateCache CacheStrategy) *Interaction + CreateButtonInteraction(fullInteraction *FullInteraction, c chan *InteractionResponse, updateCache CacheStrategy) *ButtonInteraction + CreateCommandInteraction(fullInteraction *FullInteraction, c chan *InteractionResponse, updateCache CacheStrategy) *CommandInteraction CreateGlobalCommand(command *Command, updateCache CacheStrategy) *Command CreateUser(user *User, updateCache CacheStrategy) *User - CreateMessage(message *Message, updateCache CacheStrategy) *Message + CreateMessage(message *FullMessage, updateCache CacheStrategy) *Message CreateGuild(guild *Guild, updateCache CacheStrategy) *Guild CreateMember(guildID Snowflake, member *Member, updateCache CacheStrategy) *Member diff --git a/api/events/application_command_events.go b/api/events/application_command_events.go index 3b427c71..ba6101f1 100644 --- a/api/events/application_command_events.go +++ b/api/events/application_command_events.go @@ -4,8 +4,8 @@ import ( "github.com/DisgoOrg/disgo/api" ) -// GenericApplicationCommandEvent is called upon receiving either ApplicationCommandCreateEvent, ApplicationCommandUpdateEvent or ApplicationCommandDeleteEvent -type GenericApplicationCommandEvent struct { +// GenericCommandEvent is called upon receiving either CommandCreateEvent, CommandUpdateEvent or CommandDeleteEvent +type GenericCommandEvent struct { GenericEvent CommandID api.Snowflake Command *api.Command @@ -13,25 +13,25 @@ type GenericApplicationCommandEvent struct { } // Guild returns the api.Guild the api.Event got called or nil for global api.Command(s) -func (e GenericApplicationCommandEvent) Guild() *api.Guild { +func (e GenericCommandEvent) Guild() *api.Guild { if e.GuildID == nil { return nil } return e.Disgo().Cache().Guild(*e.GuildID) } -// ApplicationCommandCreateEvent indicates that a new api.Command got created(this can come from any bot!) -type ApplicationCommandCreateEvent struct { - GenericApplicationCommandEvent +// CommandCreateEvent indicates that a new api.Command got created(this can come from any bot!) +type CommandCreateEvent struct { + GenericCommandEvent } -// ApplicationCommandUpdateEvent indicates that a api.Command got updated(this can come from any bot!) -type ApplicationCommandUpdateEvent struct { - GenericApplicationCommandEvent +// CommandUpdateEvent indicates that a api.Command got updated(this can come from any bot!) +type CommandUpdateEvent struct { + GenericCommandEvent OldCommand *api.Command } -// ApplicationCommandDeleteEvent indicates that a api.Command got deleted(this can come from any bot!) -type ApplicationCommandDeleteEvent struct { - GenericApplicationCommandEvent +// CommandDeleteEvent indicates that a api.Command got deleted(this can come from any bot!) +type CommandDeleteEvent struct { + GenericCommandEvent } diff --git a/api/events/interaction_events.go b/api/events/interaction_events.go index 28da43fb..1e18049f 100644 --- a/api/events/interaction_events.go +++ b/api/events/interaction_events.go @@ -1,8 +1,6 @@ package events import ( - "errors" - "github.com/DisgoOrg/disgo/api" ) @@ -12,21 +10,59 @@ type GenericInteractionEvent struct { Interaction *api.Interaction } -// SlashCommandEvent indicates that a slash api.Command was ran in a api.Guild -type SlashCommandEvent struct { +// Reply replies to the api.Interaction with the provided api.InteractionResponse +func (e *GenericInteractionEvent) Reply(response *api.InteractionResponse) error { + return e.Interaction.Reply(response) +} + +// EditOriginal edits the original api.InteractionResponse +func (e *GenericInteractionEvent) EditOriginal(followupMessage *api.FollowupMessage) (*api.Message, error) { + return e.Interaction.EditOriginal(followupMessage) +} + +// DeleteOriginal deletes the original api.InteractionResponse +func (e *GenericInteractionEvent) DeleteOriginal() error { + return e.Interaction.DeleteOriginal() +} + +// SendFollowup used to send a api.FollowupMessage to an api.Interaction +func (e *GenericInteractionEvent) SendFollowup(followupMessage *api.FollowupMessage) (*api.Message, error) { + return e.Interaction.SendFollowup(followupMessage) +} + +// EditFollowup used to edit a api.FollowupMessage from an api.Interaction +func (e *GenericInteractionEvent) EditFollowup(messageID api.Snowflake, followupMessage *api.FollowupMessage) (*api.Message, error) { + return e.Interaction.EditFollowup(messageID, followupMessage) +} + +// DeleteFollowup used to delete a api.FollowupMessage from an api.Interaction +func (e *GenericInteractionEvent) DeleteFollowup(messageID api.Snowflake) error { + return e.Interaction.DeleteFollowup(messageID) +} + +// CommandEvent indicates that a slash api.Command was ran +type CommandEvent struct { GenericInteractionEvent - ResponseChannel chan *api.InteractionResponse - FromWebhook bool + CommandInteraction *api.CommandInteraction CommandID api.Snowflake CommandName string SubCommandName *string SubCommandGroupName *string Options []*api.Option - Replied bool +} + +// DeferReply replies to the api.CommandInteraction with api.InteractionResponseTypeDeferredChannelMessageWithSource and shows a loading state +func (e *CommandEvent) DeferReply(ephemeral bool) error { + return e.CommandInteraction.DeferReply(ephemeral) +} + +// ReplyCreate replies to the api.CommandInteraction with api.InteractionResponseTypeDeferredChannelMessageWithSource & api.InteractionResponseData +func (e *CommandEvent) ReplyCreate(data *api.InteractionResponseData) error { + return e.CommandInteraction.ReplyCreate(data) } // CommandPath returns the api.Command path -func (e SlashCommandEvent) CommandPath() string { +func (e CommandEvent) CommandPath() string { path := e.CommandName if e.SubCommandName != nil { path += "/" + *e.SubCommandName @@ -38,7 +74,7 @@ func (e SlashCommandEvent) CommandPath() string { } // Option returns an Option by name -func (e SlashCommandEvent) Option(name string) *api.Option { +func (e CommandEvent) Option(name string) *api.Option { options := e.OptionN(name) if len(options) == 0 { return nil @@ -47,7 +83,7 @@ func (e SlashCommandEvent) Option(name string) *api.Option { } // OptionN returns Option(s) by name -func (e SlashCommandEvent) OptionN(name string) []*api.Option { +func (e CommandEvent) OptionN(name string) []*api.Option { options := make([]*api.Option, 0) for _, option := range e.Options { if option.Name == name { @@ -58,7 +94,7 @@ func (e SlashCommandEvent) OptionN(name string) []*api.Option { } // OptionsT returns Option(s) by api.CommandOptionType -func (e SlashCommandEvent) OptionsT(optionType api.CommandOptionType) []*api.Option { +func (e CommandEvent) OptionsT(optionType api.CommandOptionType) []*api.Option { options := make([]*api.Option, 0) for _, option := range e.Options { if option.Type == optionType { @@ -68,31 +104,33 @@ func (e SlashCommandEvent) OptionsT(optionType api.CommandOptionType) []*api.Opt return options } -// Acknowledge replies to the api.Interaction with api.InteractionResponseTypeDeferredChannelMessageWithSource -func (e *SlashCommandEvent) Acknowledge(ephemeral bool) error { - var data *api.InteractionResponseData - if ephemeral { - data = &api.InteractionResponseData{ - Flags: api.MessageFlagEphemeral, - } - } - return e.Reply(&api.InteractionResponse{ - Type: api.InteractionResponseTypeDeferredChannelMessageWithSource, - Data: data, - }) +// ButtonClickEvent indicates that a api.Button was clicked +type ButtonClickEvent struct { + GenericInteractionEvent + ButtonInteraction *api.ButtonInteraction } -// Reply replies to the api.Interaction with the provided api.InteractionResponse -func (e *SlashCommandEvent) Reply(response *api.InteractionResponse) error { - if e.Replied { - return errors.New("you already replied to this interaction") - } - e.Replied = true +// DeferEdit replies to the api.ButtonInteraction with api.InteractionResponseTypeDeferredUpdateMessage and cancels the loading state +func (e *ButtonClickEvent) DeferEdit() error { + return e.ButtonInteraction.DeferEdit() +} - if e.FromWebhook { - e.ResponseChannel <- response - return nil - } +// ReplyEdit replies to the api.ButtonInteraction with api.InteractionResponseTypeUpdateMessage & api.InteractionResponseData which edits the original api.Message +func (e *ButtonClickEvent) ReplyEdit(data *api.InteractionResponseData) error { + return e.ButtonInteraction.ReplyEdit(data) +} + +// CustomID returns the customID from the called api.Button +func (e *ButtonClickEvent) CustomID() string { + return e.ButtonInteraction.Data.CustomID +} + +// ComponentType returns the api.ComponentType from the called api.Button +func (e *ButtonClickEvent) ComponentType() string { + return e.ButtonInteraction.Data.CustomID +} - return e.Interaction.Disgo.RestClient().SendInteractionResponse(e.Interaction.ID, e.Interaction.Token, response) +// Message returns the api.Message the api.Button is called from +func (e *ButtonClickEvent) Message() *api.Message { + return e.ButtonInteraction.Message } diff --git a/api/events/listener_adapter.go b/api/events/listener_adapter.go index 7c0f6978..75ded836 100644 --- a/api/events/listener_adapter.go +++ b/api/events/listener_adapter.go @@ -16,10 +16,10 @@ type ListenerAdapter struct { OnReadyEvent func(event *ReadyEvent) // api.Command Events - OnGenericApplicationCommandEvent func(event *GenericApplicationCommandEvent) - OnApplicationCommandCreate func(event *ApplicationCommandCreateEvent) - OnApplicationCommandUpdate func(event *ApplicationCommandUpdateEvent) - OnApplicationCommandDelete func(event *ApplicationCommandDeleteEvent) + OnGenericCommandEvent func(event *GenericCommandEvent) + OnCommandCreate func(event *CommandCreateEvent) + OnCommandUpdate func(event *CommandUpdateEvent) + OnCommandDelete func(event *CommandDeleteEvent) // api.Channel Events OnGenericChannelEvent func(event *GenericChannelEvent) @@ -123,7 +123,8 @@ type ListenerAdapter struct { // api.Interaction Events OnGenericInteractionEvent func(event *GenericInteractionEvent) - OnSlashCommand func(event *SlashCommandEvent) + OnCommand func(event *CommandEvent) + OnButtonClick func(event *ButtonClickEvent) // api.Message Events OnGenericMessageEvent func(event *GenericMessageEvent) @@ -180,20 +181,20 @@ func (l ListenerAdapter) OnEvent(event interface{}) { } // api.Command Events - case GenericApplicationCommandEvent: - if listener := l.OnGenericApplicationCommandEvent; listener != nil { + case GenericCommandEvent: + if listener := l.OnGenericCommandEvent; listener != nil { listener(&e) } - case ApplicationCommandCreateEvent: - if listener := l.OnApplicationCommandCreate; listener != nil { + case CommandCreateEvent: + if listener := l.OnCommandCreate; listener != nil { listener(&e) } - case ApplicationCommandUpdateEvent: - if listener := l.OnApplicationCommandUpdate; listener != nil { + case CommandUpdateEvent: + if listener := l.OnCommandUpdate; listener != nil { listener(&e) } - case ApplicationCommandDeleteEvent: - if listener := l.OnApplicationCommandDelete; listener != nil { + case CommandDeleteEvent: + if listener := l.OnCommandDelete; listener != nil { listener(&e) } @@ -506,8 +507,12 @@ func (l ListenerAdapter) OnEvent(event interface{}) { if listener := l.OnGenericInteractionEvent; listener != nil { listener(&e) } - case SlashCommandEvent: - if listener := l.OnSlashCommand; listener != nil { + case CommandEvent: + if listener := l.OnCommand; listener != nil { + listener(&e) + } + case ButtonClickEvent: + if listener := l.OnButtonClick; listener != nil { listener(&e) } diff --git a/api/gateway.go b/api/gateway.go index cc11abd9..e0835ee7 100644 --- a/api/gateway.go +++ b/api/gateway.go @@ -62,9 +62,9 @@ const ( GatewayEventResumed GatewayEventType = "RESUMED" GatewayEventReconnect GatewayEventType = "RECONNECT" GatewayEventInvalidSession GatewayEventType = "INVALID_SESSION" - GatewayEventApplicationCommandCreate GatewayEventType = "APPLICATION_COMMAND_CREATE" - GatewayEventApplicationCommandUpdate GatewayEventType = "APPLICATION_COMMAND_UPDATE" - GatewayEventApplicationCommandDelete GatewayEventType = "APPLICATION_COMMAND_DELETE" + GatewayEventCommandCreate GatewayEventType = "APPLICATION_COMMAND_CREATE" + GatewayEventCommandUpdate GatewayEventType = "APPLICATION_COMMAND_UPDATE" + GatewayEventCommandDelete GatewayEventType = "APPLICATION_COMMAND_DELETE" GatewayEventChannelCreate GatewayEventType = "CHANNEL_CREATE" GatewayEventChannelUpdate GatewayEventType = "CHANNEL_UPDATE" GatewayEventChannelDelete GatewayEventType = "CHANNEL_DELETE" diff --git a/api/guild.go b/api/guild.go index 393d9a83..d56cc3fa 100644 --- a/api/guild.go +++ b/api/guild.go @@ -4,7 +4,7 @@ import ( "strings" "time" - "github.com/DisgoOrg/disgo/api/endpoints" + "github.com/DisgoOrg/restclient" ) // PremiumTier tells you the boost level of a guild @@ -187,16 +187,16 @@ func (g *Guild) AddMember(userID Snowflake, addGuildMemberData *AddGuildMemberDa } // IconURL returns the Icon of a guild_events -func (g *Guild) IconURL() *string { +func (g *Guild) IconURL(size int) *string { if g.Icon == nil { return nil } animated := strings.HasPrefix(*g.Icon, "a_") - format := endpoints.PNG + format := restclient.PNG if animated { - format = endpoints.GIF + format = restclient.GIF } - route, err := endpoints.GuildIcon.Compile(format, g.ID.String(), *g.Icon) + route, err := restclient.GuildIcon.Compile(nil, format, size, g.ID.String(), *g.Icon) if err != nil { return nil } diff --git a/api/interaction.go b/api/interaction.go index af0a5a60..ca5b4222 100644 --- a/api/interaction.go +++ b/api/interaction.go @@ -1,26 +1,53 @@ package api +import ( + "encoding/json" + "errors" +) + // InteractionType is the type of Interaction type InteractionType int -// Constants for InteractionType +// Supported InteractionType(s) const ( InteractionTypePing InteractionType = iota + 1 - InteractionTypeApplicationCommand + InteractionTypeCommand + InteractionTypeComponent ) -// An Interaction is the slash command object you receive when a user uses one of your commands +// Interaction holds the general parameters of each Interaction type Interaction struct { - Disgo Disgo - ID Snowflake `json:"id"` - Type InteractionType `json:"type"` - Data *InteractionData `json:"data,omitempty"` - GuildID *Snowflake `json:"guild_id,omitempty"` - ChannelID *Snowflake `json:"channel_id,omitempty"` - Member *Member `json:"member,omitempty"` - User *User `json:"User,omitempty"` - Token string `json:"token"` - Version int `json:"version"` + Disgo Disgo + ResponseChannel chan *InteractionResponse + Replied bool + ID Snowflake `json:"id"` + Type InteractionType `json:"type"` + GuildID *Snowflake `json:"guild_id,omitempty"` + ChannelID *Snowflake `json:"channel_id,omitempty"` + Member *Member `json:"member,omitempty"` + User *User `json:"User,omitempty"` + Token string `json:"token"` + Version int `json:"version"` +} + +// Reply replies to the api.Interaction with the provided api.InteractionResponse +func (i *Interaction) Reply(response *InteractionResponse) error { + if i.Replied { + return errors.New("you already replied to this interaction") + } + i.Replied = true + + if i.FromWebhook() { + i.ResponseChannel <- response + return nil + } + + return i.Disgo.RestClient().SendInteractionResponse(i.ID, i.Token, response) +} + +// FromWebhook returns is the Interaction was made via http +func (i *Interaction) FromWebhook() bool { + return i.ResponseChannel != nil } // Guild returns the api.Guild from the api.Cache @@ -88,14 +115,71 @@ func (i *Interaction) DeleteFollowup(messageID Snowflake) error { return i.Disgo.RestClient().DeleteFollowupMessage(i.Disgo.ApplicationID(), i.Token, messageID) } -// InteractionData is the command data payload -type InteractionData struct { +// FullInteraction is used for easier unmarshalling of different Interaction(s) +type FullInteraction struct { + ID Snowflake `json:"id"` + Type InteractionType `json:"type"` + GuildID *Snowflake `json:"guild_id,omitempty"` + ChannelID *Snowflake `json:"channel_id,omitempty"` + FullMessage *FullMessage `json:"message,omitempty"` + Member *Member `json:"member,omitempty"` + User *User `json:"User,omitempty"` + Token string `json:"token"` + Version int `json:"version"` + Data json.RawMessage `json:"data,omitempty"` +} + +// CommandInteraction is a specific Interaction when using Command(s) +type CommandInteraction struct { + *Interaction + Data *CommandInteractionData `json:"data,omitempty"` +} + +// DeferReply replies to the api.CommandInteraction with api.InteractionResponseTypeDeferredChannelMessageWithSource and shows a loading state +func (i *CommandInteraction) DeferReply(ephemeral bool) error { + var data *InteractionResponseData + if ephemeral { + data = &InteractionResponseData{Flags: MessageFlagEphemeral} + } + return i.Reply(&InteractionResponse{Type: InteractionResponseTypeDeferredChannelMessageWithSource, Data: data}) +} + +// ReplyCreate replies to the api.CommandInteraction with api.InteractionResponseTypeDeferredChannelMessageWithSource & api.InteractionResponseData +func (i *CommandInteraction) ReplyCreate(data *InteractionResponseData) error { + return i.Reply(&InteractionResponse{Type: InteractionResponseTypeChannelMessageWithSource, Data: data}) +} + +// ButtonInteraction is a specific Interaction when CLicked on Button(s) +type ButtonInteraction struct { + *Interaction + Message *Message `json:"message,omitempty"` + Data *ButtonInteractionData `json:"data,omitempty"` +} + +// DeferEdit replies to the api.ButtonInteraction with api.InteractionResponseTypeDeferredUpdateMessage and cancels the loading state +func (i *ButtonInteraction) DeferEdit() error { + return i.Reply(&InteractionResponse{Type: InteractionResponseTypeDeferredUpdateMessage}) +} + +// ReplyEdit replies to the api.ButtonInteraction with api.InteractionResponseTypeUpdateMessage & api.InteractionResponseData which edits the original api.Message +func (i *ButtonInteraction) ReplyEdit(data *InteractionResponseData) error { + return i.Reply(&InteractionResponse{Type: InteractionResponseTypeUpdateMessage, Data: data}) +} + +// CommandInteractionData is the command data payload +type CommandInteractionData struct { ID Snowflake `json:"id"` Name string `json:"name"` - Resolved *Resolved `json:"resolved"` + Resolved *Resolved `json:"resolved,omitempty"` Options []*OptionData `json:"options,omitempty"` } +// ButtonInteractionData is the command data payload +type ButtonInteractionData struct { + CustomID string `json:"custom_id"` + ComponentType ComponentType `json:"component_type"` +} + // Resolved contains resolved mention data type Resolved struct { Users map[Snowflake]*User `json:"users,omitempty"` diff --git a/api/interaction_followup.go b/api/interaction_followup.go index 570c44ef..6c4462da 100644 --- a/api/interaction_followup.go +++ b/api/interaction_followup.go @@ -4,9 +4,10 @@ import "fmt" // FollowupMessage is used to add additional messages to an Interaction after you've responded initially type FollowupMessage struct { - Content *string `json:"content,omitempty"` - TTS *bool `json:"tts,omitempty"` + TTS bool `json:"tts,omitempty"` + Content string `json:"content,omitempty"` Embeds []*Embed `json:"embeds,omitempty"` + Components []Component `json:"components,omitempty"` AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` Flags MessageFlags `json:"flags,omitempty"` } @@ -19,28 +20,44 @@ type FollowupMessageBuilder struct { // NewFollowupMessageBuilder returns a new FollowupMessageBuilder func NewFollowupMessageBuilder() *FollowupMessageBuilder { return &FollowupMessageBuilder{ - FollowupMessage{ + FollowupMessage: FollowupMessage{ AllowedMentions: &DefaultInteractionAllowedMentions, }, } } +// NewFollowupMessageBuilderByMessage returns a new FollowupMessageBuilder and takes an existing Message +func NewFollowupMessageBuilderByMessage(message *Message) *FollowupMessageBuilder { + msg := FollowupMessage{ + TTS: message.TTS, + Embeds: message.Embeds, + Components: message.Components, + AllowedMentions: &DefaultInteractionAllowedMentions, + Flags: message.Flags, + } + if message.Content != nil { + msg.Content = *message.Content + } + return &FollowupMessageBuilder{ + FollowupMessage: msg, + } +} + // SetTTS sets if the FollowupMessage is a tts message func (b *FollowupMessageBuilder) SetTTS(tts bool) *FollowupMessageBuilder { - b.TTS = &tts + b.TTS = tts return b } // SetContent sets the content of the FollowupMessage func (b *FollowupMessageBuilder) SetContent(content string) *FollowupMessageBuilder { - b.Content = &content + b.Content = content return b } // SetContentf sets the content of the FollowupMessage with format func (b *FollowupMessageBuilder) SetContentf(content string, a ...interface{}) *FollowupMessageBuilder { - contentf := fmt.Sprintf(content, a...) - b.Content = &contentf + b.Content = fmt.Sprintf(content, a...) return b } @@ -70,6 +87,18 @@ func (b *FollowupMessageBuilder) RemoveEmbed(index int) *FollowupMessageBuilder return b } +// SetComponents sets the Component(s) of the FollowupMessage +func (b *FollowupMessageBuilder) SetComponents(components ...Component) *FollowupMessageBuilder { + b.Components = components + return b +} + +// AddComponents adds the Component(s) to the FollowupMessage +func (b *FollowupMessageBuilder) AddComponents(components ...Component) *FollowupMessageBuilder { + b.Components = append(b.Components, components...) + return b +} + // SetAllowedMentions sets the allowed mentions of the FollowupMessage func (b *FollowupMessageBuilder) SetAllowedMentions(allowedMentions *AllowedMentions) *FollowupMessageBuilder { b.AllowedMentions = allowedMentions @@ -90,13 +119,9 @@ func (b *FollowupMessageBuilder) SetFlags(flags MessageFlags) *FollowupMessageBu // SetEphemeral adds/removes MessageFlagEphemeral to the message flags func (b *FollowupMessageBuilder) SetEphemeral(ephemeral bool) *FollowupMessageBuilder { if ephemeral { - if !b.Flags.Has(MessageFlagEphemeral) { - b.Flags = b.Flags.Add(MessageFlagEphemeral) - } + b.Flags &= MessageFlagEphemeral } else { - if b.Flags.Has(MessageFlagEphemeral) { - b.Flags = b.Flags.Remove(MessageFlagEphemeral) - } + b.Flags |= MessageFlagEphemeral } return b } diff --git a/api/interaction_response.go b/api/interaction_response.go index 990efe29..65a214d6 100644 --- a/api/interaction_response.go +++ b/api/interaction_response.go @@ -12,6 +12,8 @@ const ( _ InteractionResponseTypeChannelMessageWithSource InteractionResponseTypeDeferredChannelMessageWithSource + InteractionResponseTypeDeferredUpdateMessage + InteractionResponseTypeUpdateMessage ) // InteractionResponse is how you answer interactions. If an answer is not sent within 3 seconds of receiving it, the interaction is failed, and you will be unable to respond to it. @@ -22,9 +24,10 @@ type InteractionResponse struct { // The InteractionResponseData is used to specify the message_events options when creating an InteractionResponse type InteractionResponseData struct { - TTS *bool `json:"tts,omitempty"` + TTS bool `json:"tts,omitempty"` Content *string `json:"content,omitempty"` Embeds []*Embed `json:"embeds,omitempty"` + Components []Component `json:"components,omitempty"` AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` Flags MessageFlags `json:"flags,omitempty"` } @@ -37,8 +40,7 @@ type InteractionResponseBuilder struct { // NewInteractionResponseBuilder returns a new InteractionResponseBuilder func NewInteractionResponseBuilder() *InteractionResponseBuilder { return &InteractionResponseBuilder{ - InteractionResponse{ - Type: InteractionResponseTypeChannelMessageWithSource, + InteractionResponse: InteractionResponse{ Data: &InteractionResponseData{ AllowedMentions: &DefaultInteractionAllowedMentions, }, @@ -46,67 +48,71 @@ func NewInteractionResponseBuilder() *InteractionResponseBuilder { } } -// SetType sets the InteractionResponseType of the InteractionResponse -func (b *InteractionResponseBuilder) SetType(responseType InteractionResponseType) *InteractionResponseBuilder { - b.Type = responseType - return b +// NewInteractionResponseBuilderByMessage returns a new InteractionResponseBuilder and takes an existing Message +func NewInteractionResponseBuilderByMessage(message *Message) *InteractionResponseBuilder { + rs := &InteractionResponseData{ + TTS: message.TTS, + Embeds: message.Embeds, + Components: message.Components, + AllowedMentions: &DefaultInteractionAllowedMentions, + Flags: message.Flags, + } + if message.Content != nil { + rs.Content = message.Content + } + return &InteractionResponseBuilder{ + InteractionResponse: InteractionResponse{ + Data: rs, + }, + } } -// SetData sets the InteractionResponseData of the InteractionResponse -func (b *InteractionResponseBuilder) SetData(data *InteractionResponseData) *InteractionResponseBuilder { - b.Data = data +// SetType sets if the InteractionResponseType of this InteractionResponse +func (b *InteractionResponseBuilder) SetType(responseType InteractionResponseType) *InteractionResponseBuilder { + b.Type = responseType return b } // SetTTS sets if the InteractionResponse is a tts message func (b *InteractionResponseBuilder) SetTTS(tts bool) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } - b.Data.TTS = &tts + b.Data.TTS = tts return b } // SetContent sets the content of the InteractionResponse func (b *InteractionResponseBuilder) SetContent(content string) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } b.Data.Content = &content return b } // SetContentf sets the content of the InteractionResponse with format func (b *InteractionResponseBuilder) SetContentf(content string, a ...interface{}) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } contentf := fmt.Sprintf(content, a...) b.Data.Content = &contentf return b } +// ClearContent sets the content of the InteractionResponse to nil +func (b *InteractionResponseBuilder) ClearContent() *InteractionResponseBuilder { + b.Data.Content = nil + return b +} + // SetEmbeds sets the embeds of the InteractionResponse func (b *InteractionResponseBuilder) SetEmbeds(embeds ...*Embed) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } b.Data.Embeds = embeds return b } // AddEmbeds adds multiple embeds to the InteractionResponse func (b *InteractionResponseBuilder) AddEmbeds(embeds ...*Embed) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } b.Data.Embeds = append(b.Data.Embeds, embeds...) return b } // ClearEmbeds removes all of the embeds from the InteractionResponse func (b *InteractionResponseBuilder) ClearEmbeds() *InteractionResponseBuilder { - if b.Data != nil { + if b != nil { b.Data.Embeds = []*Embed{} } return b @@ -114,17 +120,42 @@ func (b *InteractionResponseBuilder) ClearEmbeds() *InteractionResponseBuilder { // RemoveEmbed removes an embed from the InteractionResponse func (b *InteractionResponseBuilder) RemoveEmbed(i int) *InteractionResponseBuilder { - if b.Data != nil && len(b.Data.Embeds) > i { + if b != nil && len(b.Data.Embeds) > i { b.Data.Embeds = append(b.Data.Embeds[:i], b.Data.Embeds[i+1:]...) } return b } +// SetComponents sets the Component(s) of the InteractionResponse +func (b *InteractionResponseBuilder) SetComponents(components ...Component) *InteractionResponseBuilder { + b.Data.Components = components + return b +} + +// AddComponents adds the Component(s) to the InteractionResponse +func (b *InteractionResponseBuilder) AddComponents(components ...Component) *InteractionResponseBuilder { + b.Data.Components = append(b.Data.Components, components...) + return b +} + +// ClearComponents removes all of the Component(s) of the InteractionResponse +func (b *InteractionResponseBuilder) ClearComponents() *InteractionResponseBuilder { + if b != nil { + b.Data.Components = []Component{} + } + return b +} + +// RemoveComponent removes a Component from the InteractionResponse +func (b *InteractionResponseBuilder) RemoveComponent(i int) *InteractionResponseBuilder { + if b != nil && len(b.Data.Components) > i { + b.Data.Components = append(b.Data.Components[:i], b.Data.Components[i+1:]...) + } + return b +} + // SetAllowedMentions sets the allowed mentions of the InteractionResponse func (b *InteractionResponseBuilder) SetAllowedMentions(allowedMentions *AllowedMentions) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } b.Data.AllowedMentions = allowedMentions return b } @@ -136,26 +167,17 @@ func (b *InteractionResponseBuilder) SetAllowedMentionsEmpty() *InteractionRespo // SetFlags sets the message flags of the InteractionResponse func (b *InteractionResponseBuilder) SetFlags(flags MessageFlags) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } b.Data.Flags = flags return b } // SetEphemeral adds/removes MessageFlagEphemeral to the message flags func (b *InteractionResponseBuilder) SetEphemeral(ephemeral bool) *InteractionResponseBuilder { - if b.Data == nil { - b.Data = &InteractionResponseData{} - } if ephemeral { - if !b.Data.Flags.Has(MessageFlagEphemeral) { - b.Data.Flags = b.Data.Flags.Add(MessageFlagEphemeral) - } + b.Data.Flags &= MessageFlagEphemeral + } else { - if b.Data.Flags.Has(MessageFlagEphemeral) { - b.Data.Flags = b.Data.Flags.Remove(MessageFlagEphemeral) - } + b.Data.Flags |= MessageFlagEphemeral } return b } @@ -164,3 +186,8 @@ func (b *InteractionResponseBuilder) SetEphemeral(ephemeral bool) *InteractionRe func (b *InteractionResponseBuilder) Build() *InteractionResponse { return &b.InteractionResponse } + +// BuildData returns your built InteractionResponseData +func (b *InteractionResponseBuilder) BuildData() *InteractionResponseData { + return b.Data +} diff --git a/api/invite.go b/api/invite.go index d12396b8..ee579990 100644 --- a/api/invite.go +++ b/api/invite.go @@ -3,7 +3,7 @@ package api import ( "time" - "github.com/DisgoOrg/disgo/api/endpoints" + "github.com/DisgoOrg/restclient" ) // ExpandedInvite is a full Invite struct @@ -31,7 +31,7 @@ type Invite struct { // URL returns the invite url in format like https://discord.gg/{code} func (i Invite) URL() string { - url, err := endpoints.InviteURL.Compile(i.Code) + url, err := restclient.InviteURL.Compile(nil, i.Code) if err != nil { return "" } diff --git a/api/message.go b/api/message.go index 5a1d4916..1e2a8cd5 100644 --- a/api/message.go +++ b/api/message.go @@ -30,7 +30,7 @@ const ( MessageTypeGuildDiscoveryFinalWarning _ MessageTypeReply - MessageTypeApplicationCommand + MessageTypeCommand ) // The MessageFlags of a Message @@ -88,15 +88,15 @@ func (f MessageFlags) Missing(bit MessageFlags) bool { // Constants for MessageFlags const ( - MessageFlagNone MessageFlags = 0 - MessageFlagCrossposted MessageFlags = 1 << (iota - 1) + MessageFlagCrossposted MessageFlags = 1 << iota MessageFlagIsCrosspost MessageFlagSuppressEmbeds MessageFlagSourceMessageDeleted MessageFlagUrgent _ MessageFlagEphemeral - MessageFlagLoading // Message is an interaction of type 5, awaiting further response + MessageFlagLoading // Message is an interaction of type 5, awaiting further response + MessageFlagNone MessageFlags = 0 ) //MessageAttachment is used for files sent in a Message @@ -166,6 +166,7 @@ type Message struct { Attachments []*MessageAttachment `json:"attachments"` TTS bool `json:"tts"` Embeds []*Embed `json:"embeds,omitempty"` + Components []Component `json:"components,omitempty"` CreatedAt time.Time `json:"timestamp"` Mentions []interface{} `json:"mentions"` MentionEveryone bool `json:"mention_everyone"` @@ -178,7 +179,7 @@ type Message struct { Content *string `json:"content,omitempty"` ChannelID Snowflake `json:"channel_id"` Type MessageType `json:"type"` - Flags *MessageFlags `json:"flags"` + Flags MessageFlags `json:"flags"` MessageReference *MessageReference `json:"message_reference,omitempty"` Interaction *MessageInteraction `json:"message_interaction,omitempty"` WebhookID *Snowflake `json:"webhook_id,omitempty"` @@ -186,7 +187,13 @@ type Message struct { Application *MessageApplication `json:"application,omitempty"` Stickers []*MessageSticker `json:"stickers,omitempty"` ReferencedMessage *Message `json:"referenced_message,omitempty"` - LastUpdated *time.Time + LastUpdated *time.Time `json:"last_updated,omitempty"` +} + +// FullMessage is used for easier unmarshalling of Component(s) in Message(s) +type FullMessage struct { + *Message + UnmarshalComponents []*UnmarshalComponent `json:"components,omitempty"` } // MessageReference is a reference to another message @@ -265,20 +272,12 @@ type MessageReaction struct { // MessageUpdate is used to edit a Message type MessageUpdate struct { Content *string `json:"content,omitempty"` + Components []Component `json:"components,omitempty"` Embed *Embed `json:"embed,omitempty"` Flags *MessageFlags `json:"flags,omitempty"` AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` } -// MessageCreate is the struct to create a new Message with -type MessageCreate struct { - Content *string `json:"content,omitempty"` - TTS *bool `json:"tts,omitempty"` - Embed *Embed `json:"embed,omitempty"` - AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` - MessageReference *MessageReference `json:"message_reference,omitempty"` -} - // MessageBulkDelete is used to bulk delete Message(s) type MessageBulkDelete struct { Messages []Snowflake `json:"messages"` diff --git a/api/message_builder.go b/api/message_builder.go index 2d28e544..909ee399 100644 --- a/api/message_builder.go +++ b/api/message_builder.go @@ -2,6 +2,17 @@ package api import "fmt" +// MessageCreate is the struct to create a new Message with +type MessageCreate struct { + Nonce string `json:"nonce,omitempty"` + Content string `json:"content,omitempty"` + Components []Component `json:"components,omitempty"` + TTS bool `json:"tts,omitempty"` + Embed *Embed `json:"embed,omitempty"` + AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` + MessageReference *MessageReference `json:"message_reference,omitempty"` +} + // MessageBuilder helper to build Message(s) easier type MessageBuilder struct { MessageCreate @@ -11,11 +22,30 @@ type MessageBuilder struct { func NewMessageBuilder() *MessageBuilder { return &MessageBuilder{ MessageCreate: MessageCreate{ + Nonce: "test nonce", AllowedMentions: &DefaultMessageAllowedMentions, }, } } +// NewMessageBuilderByMessage returns a new MessageBuilder and takes an existing Message +func NewMessageBuilderByMessage(message *Message) *MessageBuilder { + msg := MessageCreate{ + TTS: message.TTS, + Components: message.Components, + AllowedMentions: &DefaultInteractionAllowedMentions, + } + if message.Content != nil { + msg.Content = *message.Content + } + if len(message.Embeds) > 0 { + msg.Embed = message.Embeds[0] + } + return &MessageBuilder{ + MessageCreate: msg, + } +} + // NewMessageBuilderWithEmbed creates a new MessageBuilder with an Embed to be built later func NewMessageBuilderWithEmbed(embed *Embed) *MessageBuilder { return NewMessageBuilder().SetEmbed(embed) @@ -28,20 +58,19 @@ func NewMessageBuilderWithContent(content string) *MessageBuilder { // SetContent sets content of the Message func (b *MessageBuilder) SetContent(content string) *MessageBuilder { - b.Content = &content + b.Content = content return b } // SetContentf sets content of the Message func (b *MessageBuilder) SetContentf(content string, a ...interface{}) *MessageBuilder { - contentf := fmt.Sprintf(content, a...) - b.Content = &contentf + b.Content = fmt.Sprintf(content, a...) return b } // SetTTS sets the text to speech of the Message func (b *MessageBuilder) SetTTS(tts bool) *MessageBuilder { - b.TTS = &tts + b.TTS = tts return b } @@ -51,6 +80,34 @@ func (b *MessageBuilder) SetEmbed(embed *Embed) *MessageBuilder { return b } +// SetComponents sets the Component(s) of the Message +func (b *MessageBuilder) SetComponents(components ...Component) *MessageBuilder { + b.Components = components + return b +} + +// AddComponents adds the Component(s) to the Message +func (b *MessageBuilder) AddComponents(components ...Component) *MessageBuilder { + b.Components = append(b.Components, components...) + return b +} + +// ClearComponents removes all of the Component(s) of the Message +func (b *MessageBuilder) ClearComponents() *MessageBuilder { + if b != nil { + b.Components = []Component{} + } + return b +} + +// RemoveComponent removes a Component from the Message +func (b *MessageBuilder) RemoveComponent(i int) *MessageBuilder { + if b != nil && len(b.Components) > i { + b.Components = append(b.Components[:i], b.Components[i+1:]...) + } + return b +} + // SetAllowedMentions sets the AllowedMentions of the Message func (b *MessageBuilder) SetAllowedMentions(allowedMentions *AllowedMentions) *MessageBuilder { b.AllowedMentions = allowedMentions diff --git a/api/permissions.go b/api/permissions.go index 48b64be6..86346afb 100644 --- a/api/permissions.go +++ b/api/permissions.go @@ -133,7 +133,7 @@ const ( PermissionManageRoles PermissionManageWebhooks PermissionManageEmojis - PermissionUseSlashCommands + PermissionUseCommands ) // Constants for the different bit offsets of general permissions diff --git a/api/restclient.go b/api/restclient.go index 3eaba0d0..19cbdff5 100644 --- a/api/restclient.go +++ b/api/restclient.go @@ -3,7 +3,7 @@ package api import ( "errors" - "github.com/DisgoOrg/disgo/api/endpoints" + "github.com/DisgoOrg/restclient" ) // Errors when connecting to discord @@ -12,7 +12,7 @@ var ( ErrUnauthorized = errors.New("not authorized for this endpoint") ErrBadRequest = errors.New("bad request please check your request") ErrRatelimited = errors.New("too many requests") - ErrTooMuchApplicationCommands = errors.New("you can provide a max of 100 application commands") + ErrTooMuchCommands = errors.New("you can provide a max of 100 application commands") ) // ErrorResponse contains custom errors from discord @@ -23,12 +23,10 @@ type ErrorResponse struct { // RestClient is a manager for all of disgo's HTTP requests type RestClient interface { + restclient.RestClient Close() Disgo() Disgo - UserAgent() string - Request(route *endpoints.CompiledAPIRoute, rqBody interface{}, rsBody interface{}) error - SendMessage(channelID Snowflake, message *MessageCreate) (*Message, error) EditMessage(channelID Snowflake, messageID Snowflake, message *MessageUpdate) (*Message, error) DeleteMessage(channelID Snowflake, messageID Snowflake) error diff --git a/api/user.go b/api/user.go index 7c996c24..26200d64 100644 --- a/api/user.go +++ b/api/user.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - "github.com/DisgoOrg/disgo/api/endpoints" + "github.com/DisgoOrg/restclient" ) // User is a struct for interacting with discord's users @@ -27,20 +27,20 @@ type User struct { } // AvatarURL returns the Avatar URL of the User -func (u *User) AvatarURL() string { +func (u *User) AvatarURL(size int) string { if u.Avatar == nil { discrim, _ := strconv.Atoi(u.Discriminator) - route, err := endpoints.DefaultUserAvatar.Compile(endpoints.PNG, discrim%5) + route, err := restclient.DefaultUserAvatar.Compile(nil, restclient.PNG, size, discrim%5) if err != nil { return "" } return route.Route() } - format := endpoints.PNG + format := restclient.PNG if strings.HasPrefix(*u.Avatar, "a_") { - format = endpoints.GIF + format = restclient.GIF } - route, err := endpoints.UserAvatar.Compile(format, u.ID.String(), *u.Avatar) + route, err := restclient.UserAvatar.Compile(nil, format, size, u.ID.String(), *u.Avatar) if err != nil { return "" } diff --git a/example/examplebot.go b/example/examplebot.go index 051922b4..3cf4dacc 100644 --- a/example/examplebot.go +++ b/example/examplebot.go @@ -21,9 +21,10 @@ const red = 16711680 const orange = 16562691 const green = 65280 -const guildID = "817327181659111454" -const adminRoleID = "817327279583264788" -const testRoleID = "825156597935243304" +var guildID = api.Snowflake(os.Getenv("guild_id")) +var adminRoleID = api.Snowflake(os.Getenv("admin_role_id")) +var testRoleID = api.Snowflake(os.Getenv("test_role_id")) +var emoteID = api.Snowflake(os.Getenv("test_emote_id")) var logger = logrus.New() var client = http.DefaultClient @@ -34,13 +35,16 @@ func main() { dgo, err := disgo.NewBuilder(os.Getenv("token")). SetLogger(logger). + SetRawGatewayEventsEnabled(true). SetHTTPClient(client). SetGatewayIntents(api.GatewayIntentsGuilds | api.GatewayIntentsGuildMessages | api.GatewayIntentsGuildMembers). SetMemberCachePolicy(api.MemberCachePolicyAll). AddEventListeners(&events.ListenerAdapter{ + OnRawGateway: rawGatewayEventListener, OnGuildAvailable: guildAvailListener, OnGuildMessageCreate: messageListener, - OnSlashCommand: slashCommandListener, + OnCommand: commandListener, + OnButtonClick: buttonClickListener, }). Build() if err != nil { @@ -52,7 +56,7 @@ func main() { { Name: "eval", Description: "runs some go code", - DefaultPermission: ptrBool(false), + DefaultPermission: ptrBool(true), Options: []*api.CommandOption{ { Type: api.CommandOptionTypeString, @@ -65,12 +69,12 @@ func main() { { Name: "test", Description: "test test test test test test", - DefaultPermission: ptrBool(false), + DefaultPermission: ptrBool(true), }, { Name: "say", Description: "says what you say", - DefaultPermission: ptrBool(false), + DefaultPermission: ptrBool(true), Options: []*api.CommandOption{ { Type: api.CommandOptionTypeString, @@ -83,7 +87,7 @@ func main() { { Name: "addrole", Description: "This command adds a role to a member", - DefaultPermission: ptrBool(false), + DefaultPermission: ptrBool(true), Options: []*api.CommandOption{ { Type: api.CommandOptionTypeUser, @@ -102,7 +106,7 @@ func main() { { Name: "removerole", Description: "This command removes a role from a member", - DefaultPermission: ptrBool(false), + DefaultPermission: ptrBool(true), Options: []*api.CommandOption{ { Type: api.CommandOptionTypeUser, @@ -168,11 +172,44 @@ func guildAvailListener(event *events.GuildAvailableEvent) { logger.Printf("guild loaded: %s", event.Guild.ID) } -func slashCommandListener(event *events.SlashCommandEvent) { +func rawGatewayEventListener(event *events.RawGatewayEvent) { + if event.Type == api.GatewayEventInteractionCreate { + println(string(event.RawPayload)) + } +} + +func buttonClickListener(event *events.ButtonClickEvent) { + switch event.CustomID() { + case "test": + if err := event.ReplyEdit(api.NewInteractionResponseBuilder(). + SetContent("test2"). + SetComponents(api.NewActionRow( + api.NewPrimaryButton("test2", "test2", api.NewEmoji("✔"), false), + api.NewLinkButton("KittyBot", "https://kittybot.de", api.NewEmote("kittybot", emoteID), false), + )). + BuildData(), + ); err != nil { + logger.Errorf("error sending interaction response: %s", err) + } + + case "test2": + if err := event.ReplyEdit(api.NewInteractionResponseBuilder(). + SetContent("test"). + SetComponents(api.NewActionRow( + api.NewPrimaryButton("test", "test", api.NewEmoji("❌"), false), + api.NewLinkButton("KittyBot", "https://kittybot.de", api.NewEmote("kittybot", emoteID), false), + )). + BuildData(), + ); err != nil { + logger.Errorf("error sending interaction response: %s", err) + } + } +} + +func commandListener(event *events.CommandEvent) { switch event.CommandName { case "eval": go func() { - start := time.Now() code := event.Option("code").String() embed := api.NewEmbedBuilder(). SetColor(orange). @@ -180,21 +217,20 @@ func slashCommandListener(event *events.SlashCommandEvent) { AddField("Time", "...", true). AddField("Code", "```go\n"+code+"\n```", false). AddField("Output", "```\n...\n```", false) + _ = event.ReplyCreate(api.NewInteractionResponseBuilder().SetEmbeds(embed.Build()).BuildData()) - _ = event.Reply(api.NewInteractionResponseBuilder().SetEmbeds(embed.Build()).Build()) - - vars := map[string]interface{}{ + start := time.Now() + output, err := gval.Evaluate(code, map[string]interface{}{ "disgo": event.Disgo(), "dgo": event.Disgo(), "event": event, - } - output, err := gval.Evaluate(code, vars) + }) elapsed := time.Since(start) embed.SetField(1, "Time", strconv.Itoa(int(elapsed.Milliseconds()))+"ms", true) if err != nil { - _, _ = event.Interaction.EditOriginal(api.NewFollowupMessageBuilder(). + _, err = event.Interaction.EditOriginal(api.NewFollowupMessageBuilder(). SetEmbeds(embed. SetColor(red). SetField(0, "Status", "Failed", true). @@ -203,9 +239,12 @@ func slashCommandListener(event *events.SlashCommandEvent) { ). Build(), ) + if err != nil { + logger.Errorf("error sending interaction response: %s", err) + } return } - _, _ = event.Interaction.EditOriginal(api.NewFollowupMessageBuilder(). + _, err = event.Interaction.EditOriginal(api.NewFollowupMessageBuilder(). SetEmbeds(embed. SetColor(green). SetField(0, "Status", "Success", true). @@ -214,6 +253,9 @@ func slashCommandListener(event *events.SlashCommandEvent) { ). Build(), ) + if err != nil { + logger.Errorf("error sending interaction response: %s", err) + } }() case "say": @@ -224,32 +266,18 @@ func slashCommandListener(event *events.SlashCommandEvent) { ) case "test": - go func() { - _ = event.Acknowledge(true) - - time.Sleep(2 * time.Second) - _, _ = event.Interaction.EditOriginal(api.NewFollowupMessageBuilder(). - SetEmbeds(api.NewEmbedBuilder(). - SetDescription("finished with thinking"). - Build(), - ).Build(), - ) - - time.Sleep(1 * time.Second) - _, _ = event.Interaction.SendFollowup(api.NewFollowupMessageBuilder(). - SetEmbeds(api.NewEmbedBuilder(). - SetDescription("followup 1"). - Build(), - ).Build(), - ) - - time.Sleep(1 * time.Second) - _, _ = event.Interaction.SendFollowup(api.NewFollowupMessageBuilder(). - SetEphemeral(true). - SetContent("followup 2 only you can see"). - Build(), - ) - }() + if err := event.Reply(api.NewInteractionResponseBuilder(). + SetContent("test1"). + SetEmbeds(api.NewEmbedBuilder().SetDescription("this message should have some buttons").Build()). + SetComponents( + api.NewActionRow( + api.NewPrimaryButton("test", "test", api.NewEmoji("❌"), false), + ), + ). + Build(), + ); err != nil { + logger.Errorf("error sending interaction response: %s", err) + } case "addrole": user := event.Option("member").User() diff --git a/example/go.sum b/example/go.sum index c78d4f6d..c7226593 100644 --- a/example/go.sum +++ b/example/go.sum @@ -1,5 +1,13 @@ github.com/DisgoOrg/log v1.0.3 h1:IjmZQQu/kuBIui22EdXmxzQGYwcPCJEkXa0Fe6W9fJk= github.com/DisgoOrg/log v1.0.3/go.mod h1:KFGKhBQr37d6rxZ7p2bmc8BEmDH8DZbtgdlJDSCsE7I= +github.com/DisgoOrg/restclient v1.1.1 h1:xjDPlbS5yXSnQuL7cxgcm9Zyo0FWT4yDVkpn9gvC+dI= +github.com/DisgoOrg/restclient v1.1.1/go.mod h1:PIhyYsT52w5T6m4LT+HTdKqY6NOIqo71Ai0rgaq9ZtM= +github.com/DisgoOrg/restclient v1.1.2 h1:KxpWL3t587EFjfwELVsWVrEeoBIQCcKXCTEBffCDKrI= +github.com/DisgoOrg/restclient v1.1.2/go.mod h1:PIhyYsT52w5T6m4LT+HTdKqY6NOIqo71Ai0rgaq9ZtM= +github.com/DisgoOrg/restclient v1.1.3 h1:ZspV/tSwzCSffIZMRctS+ryzKmgNrKEqKMH6UQW819A= +github.com/DisgoOrg/restclient v1.1.3/go.mod h1:PIhyYsT52w5T6m4LT+HTdKqY6NOIqo71Ai0rgaq9ZtM= +github.com/DisgoOrg/restclient v1.1.4 h1:mjl6bRfq8Lj2n0zpMV4hcozVF1AQioG1huiJSs5ZSjY= +github.com/DisgoOrg/restclient v1.1.4/go.mod h1:PIhyYsT52w5T6m4LT+HTdKqY6NOIqo71Ai0rgaq9ZtM= github.com/PaesslerAG/gval v1.1.0 h1:k3RuxeZDO3eejD4cMPSt+74tUSvTnbGvLx0df4mdwFc= github.com/PaesslerAG/gval v1.1.0/go.mod h1:y/nm5yEyTeX6av0OfKJNp9rBNj2XrGhAf5+v24IBN1I= github.com/PaesslerAG/jsonpath v0.1.0 h1:gADYeifvlqK3R3i2cR5B4DGgxLXIPb3TRTH1mGi0jPI= diff --git a/go.mod b/go.mod index 460f2c3c..3820e206 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.16 require ( github.com/DisgoOrg/log v1.0.3 + github.com/DisgoOrg/restclient v1.1.4 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.4.2 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 7fd0a7b8..6bb9bf7b 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/DisgoOrg/log v1.0.3 h1:IjmZQQu/kuBIui22EdXmxzQGYwcPCJEkXa0Fe6W9fJk= github.com/DisgoOrg/log v1.0.3/go.mod h1:KFGKhBQr37d6rxZ7p2bmc8BEmDH8DZbtgdlJDSCsE7I= +github.com/DisgoOrg/restclient v1.1.4 h1:mjl6bRfq8Lj2n0zpMV4hcozVF1AQioG1huiJSs5ZSjY= +github.com/DisgoOrg/restclient v1.1.4/go.mod h1:PIhyYsT52w5T6m4LT+HTdKqY6NOIqo71Ai0rgaq9ZtM= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= diff --git a/internal/disgo_builder_impl.go b/internal/disgo_builder_impl.go index 760cb3d7..853d54ab 100644 --- a/internal/disgo_builder_impl.go +++ b/internal/disgo_builder_impl.go @@ -60,8 +60,8 @@ func (b *DisgoBuilderImpl) SetHTTPClient(httpClient *http.Client) api.DisgoBuild } // SetGatewayIntents sets the api.GatewayIntents to connect to discord -func (b *DisgoBuilderImpl) SetGatewayIntents(GatewayIntents api.GatewayIntents) api.DisgoBuilder { - b.gatewayIntents = GatewayIntents +func (b *DisgoBuilderImpl) SetGatewayIntents(gatewayIntents api.GatewayIntents) api.DisgoBuilder { + b.gatewayIntents = gatewayIntents return b } diff --git a/internal/entity_builder_impl.go b/internal/entity_builder_impl.go index 7bfa746e..3ad9c0bb 100644 --- a/internal/entity_builder_impl.go +++ b/internal/entity_builder_impl.go @@ -1,6 +1,8 @@ package internal import ( + "encoding/json" + "github.com/DisgoOrg/disgo/api" ) @@ -14,22 +16,51 @@ type EntityBuilderImpl struct { } // Disgo returns the api.Disgo client -func (b EntityBuilderImpl) Disgo() api.Disgo { +func (b *EntityBuilderImpl) Disgo() api.Disgo { return b.disgo } -// CreateInteraction returns a new api.Interaction entity -func (b EntityBuilderImpl) CreateInteraction(interaction *api.Interaction, updateCache api.CacheStrategy) *api.Interaction { - interaction.Disgo = b.disgo - if interaction.Member != nil { - interaction.Member = b.CreateMember(*interaction.GuildID, interaction.Member, api.CacheStrategyYes) +func (b EntityBuilderImpl) createInteraction(fullInteraction *api.FullInteraction, c chan *api.InteractionResponse, updateCache api.CacheStrategy) *api.Interaction { + interaction := &api.Interaction{ + Disgo: b.disgo, + ResponseChannel: c, + Replied: false, + ID: fullInteraction.ID, + Type: fullInteraction.Type, + GuildID: fullInteraction.GuildID, + ChannelID: fullInteraction.ChannelID, + Token: fullInteraction.Token, + Version: fullInteraction.Version, + } + + if fullInteraction.Member != nil { + interaction.Member = b.CreateMember(*fullInteraction.GuildID, fullInteraction.Member, api.CacheStrategyYes) } - if interaction.User != nil { - interaction.User = b.CreateUser(interaction.User, updateCache) + if fullInteraction.User != nil { + interaction.User = b.CreateUser(fullInteraction.User, updateCache) } + return interaction +} + +// CreateButtonInteraction creates a api.ButtonInteraction from the full interaction response +func (b *EntityBuilderImpl) CreateButtonInteraction(fullInteraction *api.FullInteraction, c chan *api.InteractionResponse, updateCache api.CacheStrategy) *api.ButtonInteraction { + var data *api.ButtonInteractionData + _ = json.Unmarshal(fullInteraction.Data, &data) - if interaction.Data != nil && interaction.Data.Resolved != nil { - resolved := interaction.Data.Resolved + return &api.ButtonInteraction{ + Interaction: b.createInteraction(fullInteraction, c, updateCache), + Message: b.CreateMessage(fullInteraction.FullMessage, updateCache), + Data: data, + } +} + +// CreateCommandInteraction creates a api.CommandInteraction from the full interaction response +func (b *EntityBuilderImpl) CreateCommandInteraction(fullInteraction *api.FullInteraction, c chan *api.InteractionResponse, updateCache api.CacheStrategy) *api.CommandInteraction { + var data *api.CommandInteractionData + _ = json.Unmarshal(fullInteraction.Data, &data) + + if data.Resolved != nil { + resolved := data.Resolved if resolved.Users != nil { for _, user := range resolved.Users { user = b.CreateUser(user, updateCache) @@ -38,12 +69,12 @@ func (b EntityBuilderImpl) CreateInteraction(interaction *api.Interaction, updat if resolved.Members != nil { for id, member := range resolved.Members { member.User = resolved.Users[id] - member = b.CreateMember(*interaction.GuildID, member, updateCache) + member = b.CreateMember(member.GuildID, member, updateCache) } } if resolved.Roles != nil { for _, role := range resolved.Roles { - role = b.CreateRole(*interaction.GuildID, role, updateCache) + role = b.CreateRole(role.GuildID, role, updateCache) } } // TODO how do we cache partial channels? @@ -54,11 +85,15 @@ func (b EntityBuilderImpl) CreateInteraction(interaction *api.Interaction, updat } }*/ } - return interaction + + return &api.CommandInteraction{ + Interaction: b.createInteraction(fullInteraction, c, updateCache), + Data: data, + } } // CreateGlobalCommand returns a new api.Command entity -func (b EntityBuilderImpl) CreateGlobalCommand(command *api.Command, updateCache api.CacheStrategy) *api.Command { +func (b *EntityBuilderImpl) CreateGlobalCommand(command *api.Command, updateCache api.CacheStrategy) *api.Command { command.Disgo = b.Disgo() if updateCache(b.Disgo()) { return b.Disgo().Cache().CacheGlobalCommand(command) @@ -67,7 +102,7 @@ func (b EntityBuilderImpl) CreateGlobalCommand(command *api.Command, updateCache } // CreateUser returns a new api.User entity -func (b EntityBuilderImpl) CreateUser(user *api.User, updateCache api.CacheStrategy) *api.User { +func (b *EntityBuilderImpl) CreateUser(user *api.User, updateCache api.CacheStrategy) *api.User { user.Disgo = b.Disgo() if updateCache(b.Disgo()) { return b.Disgo().Cache().CacheUser(user) @@ -75,15 +110,58 @@ func (b EntityBuilderImpl) CreateUser(user *api.User, updateCache api.CacheStrat return user } +func (b *EntityBuilderImpl) createComponent(unmarshalComponent *api.UnmarshalComponent, updateCache api.CacheStrategy) api.Component { + switch unmarshalComponent.ComponentType { + case api.ComponentTypeActionRow: + components := make([]api.Component, len(unmarshalComponent.Components)) + for i, unmarshalC := range unmarshalComponent.Components { + components[i] = b.createComponent(unmarshalC, updateCache) + } + return &api.ActionRow{ + ComponentImpl: api.ComponentImpl{ + ComponentType: api.ComponentTypeActionRow, + }, + Components: components, + } + + case api.ComponentTypeButton: + return &api.Button{ + ComponentImpl: api.ComponentImpl{ + ComponentType: api.ComponentTypeButton, + }, + Style: unmarshalComponent.Style, + Label: unmarshalComponent.Label, + Emote: b.CreateEmote("", unmarshalComponent.Emote, updateCache), + CustomID: unmarshalComponent.CustomID, + URL: unmarshalComponent.URL, + Disabled: unmarshalComponent.Disabled, + } + + default: + b.Disgo().Logger().Errorf("unexpected component type %d received", unmarshalComponent.ComponentType) + return nil + } +} + // CreateMessage returns a new api.Message entity -func (b EntityBuilderImpl) CreateMessage(message *api.Message, updateCache api.CacheStrategy) *api.Message { +func (b *EntityBuilderImpl) CreateMessage(fullMessage *api.FullMessage, updateCache api.CacheStrategy) *api.Message { + message := fullMessage.Message message.Disgo = b.Disgo() + if message.Member != nil { + message.Member.User = message.Author message.Member = b.CreateMember(*message.GuildID, message.Member, updateCache) } if message.Author != nil { message.Author = b.CreateUser(message.Author, updateCache) } + + if fullMessage.UnmarshalComponents != nil { + for _, component := range fullMessage.UnmarshalComponents { + message.Components = append(message.Components, b.createComponent(component, updateCache)) + } + } + // TODO: should we cache mentioned users, members, etc? if updateCache(b.Disgo()) { return b.Disgo().Cache().CacheMessage(message) @@ -92,7 +170,7 @@ func (b EntityBuilderImpl) CreateMessage(message *api.Message, updateCache api.C } // CreateGuild returns a new api.Guild entity -func (b EntityBuilderImpl) CreateGuild(guild *api.Guild, updateCache api.CacheStrategy) *api.Guild { +func (b *EntityBuilderImpl) CreateGuild(guild *api.Guild, updateCache api.CacheStrategy) *api.Guild { guild.Disgo = b.Disgo() if updateCache(b.Disgo()) { return b.Disgo().Cache().CacheGuild(guild) @@ -101,7 +179,7 @@ func (b EntityBuilderImpl) CreateGuild(guild *api.Guild, updateCache api.CacheSt } // CreateMember returns a new api.Member entity -func (b EntityBuilderImpl) CreateMember(guildID api.Snowflake, member *api.Member, updateCache api.CacheStrategy) *api.Member { +func (b *EntityBuilderImpl) CreateMember(guildID api.Snowflake, member *api.Member, updateCache api.CacheStrategy) *api.Member { member.Disgo = b.Disgo() member.GuildID = guildID member.User = b.CreateUser(member.User, updateCache) @@ -112,7 +190,7 @@ func (b EntityBuilderImpl) CreateMember(guildID api.Snowflake, member *api.Membe } // CreateVoiceState returns a new api.VoiceState entity -func (b EntityBuilderImpl) CreateVoiceState(guildID api.Snowflake, voiceState *api.VoiceState, updateCache api.CacheStrategy) *api.VoiceState { +func (b *EntityBuilderImpl) CreateVoiceState(guildID api.Snowflake, voiceState *api.VoiceState, updateCache api.CacheStrategy) *api.VoiceState { voiceState.Disgo = b.Disgo() voiceState.GuildID = guildID b.Disgo().Logger().Infof("voiceState: %+v", voiceState) @@ -124,7 +202,7 @@ func (b EntityBuilderImpl) CreateVoiceState(guildID api.Snowflake, voiceState *a } // CreateGuildCommand returns a new api.Command entity -func (b EntityBuilderImpl) CreateGuildCommand(guildID api.Snowflake, command *api.Command, updateCache api.CacheStrategy) *api.Command { +func (b *EntityBuilderImpl) CreateGuildCommand(guildID api.Snowflake, command *api.Command, updateCache api.CacheStrategy) *api.Command { command.Disgo = b.Disgo() command.GuildID = &guildID if updateCache(b.Disgo()) { @@ -134,7 +212,7 @@ func (b EntityBuilderImpl) CreateGuildCommand(guildID api.Snowflake, command *ap } // CreateGuildCommandPermissions returns a new api.GuildCommandPermissions entity -func (b EntityBuilderImpl) CreateGuildCommandPermissions(guildCommandPermissions *api.GuildCommandPermissions, updateCache api.CacheStrategy) *api.GuildCommandPermissions { +func (b *EntityBuilderImpl) CreateGuildCommandPermissions(guildCommandPermissions *api.GuildCommandPermissions, updateCache api.CacheStrategy) *api.GuildCommandPermissions { guildCommandPermissions.Disgo = b.Disgo() if updateCache(b.Disgo()) && b.Disgo().Cache().CacheFlags().Has(api.CacheFlagCommandPermissions) { if cmd := b.Disgo().Cache().Command(guildCommandPermissions.ID); cmd != nil { @@ -145,7 +223,7 @@ func (b EntityBuilderImpl) CreateGuildCommandPermissions(guildCommandPermissions } // CreateRole returns a new api.Role entity -func (b EntityBuilderImpl) CreateRole(guildID api.Snowflake, role *api.Role, updateCache api.CacheStrategy) *api.Role { +func (b *EntityBuilderImpl) CreateRole(guildID api.Snowflake, role *api.Role, updateCache api.CacheStrategy) *api.Role { role.Disgo = b.Disgo() role.GuildID = guildID if updateCache(b.Disgo()) { @@ -155,7 +233,7 @@ func (b EntityBuilderImpl) CreateRole(guildID api.Snowflake, role *api.Role, upd } // CreateTextChannel returns a new api.TextChannel entity -func (b EntityBuilderImpl) CreateTextChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.TextChannel { +func (b *EntityBuilderImpl) CreateTextChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.TextChannel { channel.Disgo = b.Disgo() textChannel := &api.TextChannel{ MessageChannel: api.MessageChannel{ @@ -172,7 +250,7 @@ func (b EntityBuilderImpl) CreateTextChannel(channel *api.Channel, updateCache a } // CreateVoiceChannel returns a new api.VoiceChannel entity -func (b EntityBuilderImpl) CreateVoiceChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.VoiceChannel { +func (b *EntityBuilderImpl) CreateVoiceChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.VoiceChannel { channel.Disgo = b.Disgo() voiceChannel := &api.VoiceChannel{ GuildChannel: api.GuildChannel{ @@ -186,7 +264,7 @@ func (b EntityBuilderImpl) CreateVoiceChannel(channel *api.Channel, updateCache } // CreateStoreChannel returns a new api.StoreChannel entity -func (b EntityBuilderImpl) CreateStoreChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.StoreChannel { +func (b *EntityBuilderImpl) CreateStoreChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.StoreChannel { channel.Disgo = b.Disgo() storeChannel := &api.StoreChannel{ GuildChannel: api.GuildChannel{ @@ -200,7 +278,7 @@ func (b EntityBuilderImpl) CreateStoreChannel(channel *api.Channel, updateCache } // CreateCategory returns a new api.Category entity -func (b EntityBuilderImpl) CreateCategory(channel *api.Channel, updateCache api.CacheStrategy) *api.Category { +func (b *EntityBuilderImpl) CreateCategory(channel *api.Channel, updateCache api.CacheStrategy) *api.Category { channel.Disgo = b.Disgo() category := &api.Category{ GuildChannel: api.GuildChannel{ @@ -214,7 +292,7 @@ func (b EntityBuilderImpl) CreateCategory(channel *api.Channel, updateCache api. } // CreateDMChannel returns a new api.DMChannel entity -func (b EntityBuilderImpl) CreateDMChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.DMChannel { +func (b *EntityBuilderImpl) CreateDMChannel(channel *api.Channel, updateCache api.CacheStrategy) *api.DMChannel { channel.Disgo = b.Disgo() dmChannel := &api.DMChannel{ MessageChannel: api.MessageChannel{ @@ -228,7 +306,7 @@ func (b EntityBuilderImpl) CreateDMChannel(channel *api.Channel, updateCache api } // CreateEmote returns a new api.Emote entity -func (b EntityBuilderImpl) CreateEmote(guildID api.Snowflake, emote *api.Emote, updateCache api.CacheStrategy) *api.Emote { +func (b *EntityBuilderImpl) CreateEmote(guildID api.Snowflake, emote *api.Emote, updateCache api.CacheStrategy) *api.Emote { emote.Disgo = b.Disgo() emote.GuildID = guildID if updateCache(b.Disgo()) { diff --git a/internal/gateway_impl.go b/internal/gateway_impl.go index 1f5478db..8ba97913 100644 --- a/internal/gateway_impl.go +++ b/internal/gateway_impl.go @@ -14,7 +14,7 @@ import ( "github.com/gorilla/websocket" "github.com/DisgoOrg/disgo/api" - "github.com/DisgoOrg/disgo/api/endpoints" + "github.com/DisgoOrg/restclient" ) func newGatewayImpl(disgo api.Disgo) api.Gateway { @@ -73,17 +73,17 @@ func (g *GatewayImpl) Open() error { if g.url == nil { g.Disgo().Logger().Debug("gateway url empty, fetching...") gatewayRs := api.GatewayRs{} - compiledRoute, err := endpoints.GetGateway.Compile() + compiledRoute, err := restclient.GetGateway.Compile(nil) if err != nil { return err } - if err = g.Disgo().RestClient().Request(compiledRoute, nil, &gatewayRs); err != nil { + if err = g.Disgo().RestClient().Do(compiledRoute, nil, &gatewayRs); err != nil { return err } g.url = &gatewayRs.URL } - gatewayURL := *g.url + "?v=" + endpoints.APIVersion + "&encoding=json" + gatewayURL := *g.url + "?v=" + restclient.APIVersion + "&encoding=json" wsConn, rs, err := websocket.DefaultDialer.Dial(gatewayURL, nil) if err != nil { g.Close() diff --git a/internal/handlers/all_handlers.go b/internal/handlers/all_handlers.go index e3f12a41..1bbc90b8 100644 --- a/internal/handlers/all_handlers.go +++ b/internal/handlers/all_handlers.go @@ -7,9 +7,9 @@ import ( // GetAllHandlers returns all api.GatewayEventHandler(s) func GetAllHandlers() []api.EventHandler { return []api.EventHandler{ - ApplicationCommandCreateHandler{}, - ApplicationCommandDeleteHandler{}, - ApplicationCommandUpdateHandler{}, + CommandCreateHandler{}, + CommandDeleteHandler{}, + CommandUpdateHandler{}, ChannelCreateHandler{}, ChannelDeleteHandler{}, @@ -31,6 +31,8 @@ func GetAllHandlers() []api.EventHandler { InteractionCreateWebhookHandler{}, MessageCreateHandler{}, + MessageUpdateHandler{}, + MessageDeleteHandler{}, ReadyHandler{}, diff --git a/internal/handlers/application_command_create.go b/internal/handlers/application_command_create.go index 71d6de9e..fd21d2db 100644 --- a/internal/handlers/application_command_create.go +++ b/internal/handlers/application_command_create.go @@ -5,21 +5,21 @@ import ( "github.com/DisgoOrg/disgo/api/events" ) -// ApplicationCommandCreateHandler handles api.ApplicationCommandCreateEvent -type ApplicationCommandCreateHandler struct{} +// CommandCreateHandler handles api.CommandCreateEvent +type CommandCreateHandler struct{} // Event returns the raw gateway event Event -func (h ApplicationCommandCreateHandler) Event() api.GatewayEventType { - return api.GatewayEventApplicationCommandCreate +func (h CommandCreateHandler) Event() api.GatewayEventType { + return api.GatewayEventCommandCreate } // New constructs a new payload receiver for the raw gateway event -func (h ApplicationCommandCreateHandler) New() interface{} { +func (h CommandCreateHandler) New() interface{} { return &api.Command{} } // HandleGatewayEvent handles the specific raw gateway event -func (h ApplicationCommandCreateHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { +func (h CommandCreateHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { command, ok := i.(*api.Command) if !ok { return @@ -37,15 +37,15 @@ func (h ApplicationCommandCreateHandler) HandleGatewayEvent(disgo api.Disgo, eve command = disgo.EntityBuilder().CreateGlobalCommand(command, cacheStrategy) } - genericApplicationCommandEvent := events.GenericApplicationCommandEvent{ + genericCommandEvent := events.GenericCommandEvent{ GenericEvent: events.NewEvent(disgo, sequenceNumber), CommandID: command.ID, Command: command, GuildID: command.GuildID, } - eventManager.Dispatch(genericApplicationCommandEvent) + eventManager.Dispatch(genericCommandEvent) - eventManager.Dispatch(events.ApplicationCommandCreateEvent{ - GenericApplicationCommandEvent: genericApplicationCommandEvent, + eventManager.Dispatch(events.CommandCreateEvent{ + GenericCommandEvent: genericCommandEvent, }) } diff --git a/internal/handlers/application_command_delete.go b/internal/handlers/application_command_delete.go index d4353758..68cb449b 100644 --- a/internal/handlers/application_command_delete.go +++ b/internal/handlers/application_command_delete.go @@ -5,21 +5,21 @@ import ( "github.com/DisgoOrg/disgo/api/events" ) -// ApplicationCommandDeleteHandler handles api.ApplicationCommandCreateEvent -type ApplicationCommandDeleteHandler struct{} +// CommandDeleteHandler handles api.CommandCreateEvent +type CommandDeleteHandler struct{} // Event returns the raw gateway event Event -func (h ApplicationCommandDeleteHandler) Event() api.GatewayEventType { - return api.GatewayEventApplicationCommandDelete +func (h CommandDeleteHandler) Event() api.GatewayEventType { + return api.GatewayEventCommandDelete } // New constructs a new payload receiver for the raw gateway event -func (h ApplicationCommandDeleteHandler) New() interface{} { +func (h CommandDeleteHandler) New() interface{} { return &api.Command{} } // HandleGatewayEvent handles the specific raw gateway event -func (h ApplicationCommandDeleteHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { +func (h CommandDeleteHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { command, ok := i.(*api.Command) if !ok { return @@ -36,15 +36,15 @@ func (h ApplicationCommandDeleteHandler) HandleGatewayEvent(disgo api.Disgo, eve command = disgo.EntityBuilder().CreateGlobalCommand(command, api.CacheStrategyNo) } - genericApplicationCommandEvent := events.GenericApplicationCommandEvent{ + genericCommandEvent := events.GenericCommandEvent{ GenericEvent: events.NewEvent(disgo, sequenceNumber), CommandID: command.ID, Command: command, GuildID: command.GuildID, } - eventManager.Dispatch(genericApplicationCommandEvent) + eventManager.Dispatch(genericCommandEvent) - eventManager.Dispatch(events.ApplicationCommandDeleteEvent{ - GenericApplicationCommandEvent: genericApplicationCommandEvent, + eventManager.Dispatch(events.CommandDeleteEvent{ + GenericCommandEvent: genericCommandEvent, }) } diff --git a/internal/handlers/application_command_update.go b/internal/handlers/application_command_update.go index 341d7edc..8bca2b93 100644 --- a/internal/handlers/application_command_update.go +++ b/internal/handlers/application_command_update.go @@ -5,21 +5,21 @@ import ( "github.com/DisgoOrg/disgo/api/events" ) -// ApplicationCommandUpdateHandler handles api.ApplicationCommandCreateEvent -type ApplicationCommandUpdateHandler struct{} +// CommandUpdateHandler handles api.CommandCreateEvent +type CommandUpdateHandler struct{} // Event returns the raw gateway event Event -func (h ApplicationCommandUpdateHandler) Event() api.GatewayEventType { - return api.GatewayEventApplicationCommandUpdate +func (h CommandUpdateHandler) Event() api.GatewayEventType { + return api.GatewayEventCommandUpdate } // New constructs a new payload receiver for the raw gateway event -func (h ApplicationCommandUpdateHandler) New() interface{} { +func (h CommandUpdateHandler) New() interface{} { return &api.Command{} } // HandleGatewayEvent handles the specific raw gateway event -func (h ApplicationCommandUpdateHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { +func (h CommandUpdateHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { command, ok := i.(*api.Command) if !ok { return @@ -39,16 +39,16 @@ func (h ApplicationCommandUpdateHandler) HandleGatewayEvent(disgo api.Disgo, eve command = disgo.EntityBuilder().CreateGlobalCommand(command, api.CacheStrategyYes) } - genericApplicationCommandEvent := events.GenericApplicationCommandEvent{ + genericCommandEvent := events.GenericCommandEvent{ GenericEvent: events.NewEvent(disgo, sequenceNumber), CommandID: command.ID, Command: command, GuildID: command.GuildID, } - eventManager.Dispatch(genericApplicationCommandEvent) + eventManager.Dispatch(genericCommandEvent) - eventManager.Dispatch(events.ApplicationCommandUpdateEvent{ - GenericApplicationCommandEvent: genericApplicationCommandEvent, + eventManager.Dispatch(events.CommandUpdateEvent{ + GenericCommandEvent: genericCommandEvent, // always nil for not our own commands OldCommand: oldCommand, }) diff --git a/internal/handlers/interaction_create_handler.go b/internal/handlers/interaction_create_handler.go index b513e696..61c82373 100644 --- a/internal/handlers/interaction_create_handler.go +++ b/internal/handlers/interaction_create_handler.go @@ -15,33 +15,35 @@ func (h InteractionCreateHandler) Event() api.GatewayEventType { // New constructs a new payload receiver for the raw gateway event func (h InteractionCreateHandler) New() interface{} { - return &api.Interaction{} + return &api.FullInteraction{} } // HandleGatewayEvent handles the specific raw gateway event func (h InteractionCreateHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { - interaction, ok := i.(*api.Interaction) + fullInteraction, ok := i.(*api.FullInteraction) if !ok { return } - handleInteraction(disgo, eventManager, sequenceNumber, interaction, nil) + handleInteraction(disgo, eventManager, sequenceNumber, fullInteraction, nil) } -func handleInteraction(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, interaction *api.Interaction, c chan *api.InteractionResponse) { - - interaction = disgo.EntityBuilder().CreateInteraction(interaction, api.CacheStrategyYes) +func handleInteraction(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, fullInteraction *api.FullInteraction, c chan *api.InteractionResponse) { genericInteractionEvent := events.GenericInteractionEvent{ GenericEvent: events.NewEvent(disgo, sequenceNumber), - Interaction: interaction, } - eventManager.Dispatch(genericInteractionEvent) - if interaction.Data != nil { + switch fullInteraction.Type { + case api.InteractionTypeCommand: + interaction := disgo.EntityBuilder().CreateCommandInteraction(fullInteraction, c, api.CacheStrategyYes) + + genericInteractionEvent.Interaction = interaction.Interaction + eventManager.Dispatch(genericInteractionEvent) + options := interaction.Data.Options var subCommandName *string var subCommandGroupName *string if len(options) == 1 { - option := interaction.Data.Options[0] + option := options[0] if option.Type == api.CommandOptionTypeSubCommandGroup { subCommandGroupName = &option.Name options = option.Options @@ -52,6 +54,7 @@ func handleInteraction(disgo api.Disgo, eventManager api.EventManager, sequenceN options = option.Options } } + var newOptions []*api.Option for _, optionData := range options { newOptions = append(newOptions, &api.Option{ @@ -62,16 +65,24 @@ func handleInteraction(disgo api.Disgo, eventManager api.EventManager, sequenceN }) } - eventManager.Dispatch(events.SlashCommandEvent{ + eventManager.Dispatch(events.CommandEvent{ GenericInteractionEvent: genericInteractionEvent, - ResponseChannel: c, - FromWebhook: c != nil, + CommandInteraction: interaction, CommandID: interaction.Data.ID, CommandName: interaction.Data.Name, SubCommandName: subCommandName, SubCommandGroupName: subCommandGroupName, Options: newOptions, - Replied: false, + }) + case api.InteractionTypeComponent: + interaction := disgo.EntityBuilder().CreateButtonInteraction(fullInteraction, c, api.CacheStrategyYes) + + genericInteractionEvent.Interaction = interaction.Interaction + eventManager.Dispatch(genericInteractionEvent) + + eventManager.Dispatch(events.ButtonClickEvent{ + GenericInteractionEvent: genericInteractionEvent, + ButtonInteraction: interaction, }) } } diff --git a/internal/handlers/interaction_create_webhook_handler.go b/internal/handlers/interaction_create_webhook_handler.go index 495b56f8..b5595c76 100644 --- a/internal/handlers/interaction_create_webhook_handler.go +++ b/internal/handlers/interaction_create_webhook_handler.go @@ -14,22 +14,22 @@ func (h InteractionCreateWebhookHandler) Event() api.GatewayEventType { // New constructs a new payload receiver for the raw gateway event func (h InteractionCreateWebhookHandler) New() interface{} { - return &api.Interaction{} + return &api.FullInteraction{} } // HandleWebhookEvent handles the specific raw gateway event func (h InteractionCreateWebhookHandler) HandleWebhookEvent(disgo api.Disgo, eventManager api.EventManager, c chan *api.InteractionResponse, i interface{}) { - interaction, ok := i.(*api.Interaction) + fullInteraction, ok := i.(*api.FullInteraction) if !ok { return } - if interaction.Type == api.InteractionTypePing { + if fullInteraction.Type == api.InteractionTypePing { disgo.Logger().Debugf("received interaction ping") c <- &api.InteractionResponse{ Type: api.InteractionResponseTypePong, } return } - handleInteraction(disgo, eventManager, -1, interaction, c) + handleInteraction(disgo, eventManager, -1, fullInteraction, c) } diff --git a/internal/handlers/message_create_handler.go b/internal/handlers/message_create_handler.go index 80dba3ad..bd2a7471 100644 --- a/internal/handlers/message_create_handler.go +++ b/internal/handlers/message_create_handler.go @@ -5,7 +5,7 @@ import ( "github.com/DisgoOrg/disgo/api/events" ) -// MessageCreateHandler handles api.MessageCreateGatewayEvent +// MessageCreateHandler handles api.GatewayEventMessageCreate type MessageCreateHandler struct{} // Event returns the raw gateway event Event @@ -15,18 +15,17 @@ func (h MessageCreateHandler) Event() api.GatewayEventType { // New constructs a new payload receiver for the raw gateway event func (h MessageCreateHandler) New() interface{} { - return &api.Message{} + return &api.FullMessage{} } // HandleGatewayEvent handles the specific raw gateway event func (h MessageCreateHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { - message, ok := i.(*api.Message) + fullMessage, ok := i.(*api.FullMessage) if !ok { return } - message.Disgo = disgo - message.Author.Disgo = disgo + message := disgo.EntityBuilder().CreateMessage(fullMessage, api.CacheStrategyYes) genericMessageEvent := events.GenericMessageEvent{ GenericEvent: events.NewEvent(disgo, sequenceNumber), diff --git a/internal/handlers/message_delete_handler.go b/internal/handlers/message_delete_handler.go index 5ac8282f..3dfad6e7 100644 --- a/internal/handlers/message_delete_handler.go +++ b/internal/handlers/message_delete_handler.go @@ -1 +1,29 @@ package handlers + +import ( + "github.com/DisgoOrg/disgo/api" +) + +type messageDeletePayload struct { + MessageID api.Snowflake `json:"id"` + GuildID *api.Snowflake `json:"guild_id,omitempty"` + ChannelID api.Snowflake `json:"channel_id"` +} + +// MessageDeleteHandler handles api.GatewayEventMessageDelete +type MessageDeleteHandler struct{} + +// Event returns the raw gateway event Event +func (h MessageDeleteHandler) Event() api.GatewayEventType { + return api.GatewayEventMessageDelete +} + +// New constructs a new payload receiver for the raw gateway event +func (h MessageDeleteHandler) New() interface{} { + return &messageDeletePayload{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h MessageDeleteHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { + //payload, ok := i.(*api.messageDeletePayload) +} diff --git a/internal/handlers/message_update_handler.go b/internal/handlers/message_update_handler.go index 5ac8282f..f3764ce4 100644 --- a/internal/handlers/message_update_handler.go +++ b/internal/handlers/message_update_handler.go @@ -1 +1,21 @@ package handlers + +import "github.com/DisgoOrg/disgo/api" + +// MessageUpdateHandler handles api.GatewayEventMessageUpdate +type MessageUpdateHandler struct{} + +// Event returns the raw gateway event Event +func (h MessageUpdateHandler) Event() api.GatewayEventType { + return api.GatewayEventMessageUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h MessageUpdateHandler) New() interface{} { + return &api.FullMessage{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h MessageUpdateHandler) HandleGatewayEvent(disgo api.Disgo, eventManager api.EventManager, sequenceNumber int, i interface{}) { + //fullMessage, ok := i.(*api.FullMessage) +} diff --git a/internal/restclient_impl.go b/internal/restclient_impl.go index 74759d8c..17ada390 100644 --- a/internal/restclient_impl.go +++ b/internal/restclient_impl.go @@ -1,189 +1,96 @@ package internal import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" "net/http" - "net/url" "strings" - "github.com/DisgoOrg/disgo/api/events" - "github.com/DisgoOrg/disgo/api" - "github.com/DisgoOrg/disgo/api/endpoints" + "github.com/DisgoOrg/restclient" ) -func newRestClientImpl(disgo api.Disgo, client *http.Client) api.RestClient { - if client == nil { - client = http.DefaultClient +func newRestClientImpl(disgo api.Disgo, httpClient *http.Client) api.RestClient { + if httpClient == nil { + httpClient = http.DefaultClient } return &RestClientImpl{ - disgo: disgo, - client: client, + RestClient: restclient.NewRestClient(httpClient, disgo.Logger(), "DiscordBot (https://github.com/disgoorg/disgo, 0.0.1)", http.Header{"Authorization": []string{"Bot " + disgo.Token()}}), + disgo: disgo, } } // RestClientImpl is the rest client implementation used for HTTP requests to discord type RestClientImpl struct { - disgo api.Disgo - client *http.Client - token string + restclient.RestClient + disgo api.Disgo } // Disgo returns the api.Disgo instance -func (r RestClientImpl) Disgo() api.Disgo { +func (r *RestClientImpl) Disgo() api.Disgo { return r.disgo } -// Client returns the http.Client used by this api.RestClient -func (r RestClientImpl) Client() *http.Client { - return r.client -} - // Close cleans up the http managers connections -func (r RestClientImpl) Close() { - r.client.CloseIdleConnections() -} - -// UserAgent returns the user agent for this api.RestClient -func (r RestClientImpl) UserAgent() string { - return "DiscordBot (https://github.com/disgoorg/disgo, 0.0.1)" -} - -// Request makes a new rest request to discords api with the specific endpoints.APIRoute -func (r RestClientImpl) Request(route *endpoints.CompiledAPIRoute, rqBody interface{}, rsBody interface{}) error { - var reader io.Reader - var rqJSON []byte - var contentType string - if rqBody != nil { - switch v := rqBody.(type) { - case url.Values: - contentType = "application/x-www-form-urlencoded" - rqJSON = []byte(v.Encode()) - default: - contentType = "application/json" - var err error - rqJSON, err = json.Marshal(rqBody) - if err != nil { - return err - } - } - r.Disgo().Logger().Debugf("request body: \"%s\"", string(rqJSON)) - reader = bytes.NewBuffer(rqJSON) - } else { - reader = nil - } - - rq, err := http.NewRequest(route.Method().String(), route.Route(), reader) - if err != nil { - return err - } - rq.Header.Set("User-Agent", r.UserAgent()) - rq.Header.Set("Authorization", "Bot "+r.disgo.Token()) - rq.Header.Set("Content-Type", contentType) - - rs, err := r.client.Do(rq) - if err != nil { - return err - } - - defer func() { - err = rs.Body.Close() - if err != nil { - r.Disgo().Logger().Error("error closing response body", err.Error()) - } - }() - - rawRsBody, err := ioutil.ReadAll(rs.Body) - if err != nil { - r.Disgo().Logger().Errorf("error reading from response body: %s", err) - return err - } - - r.Disgo().Logger().Debugf("code: %d, response: %s", rs.StatusCode, string(rawRsBody)) +func (r *RestClientImpl) Close() { + r.HttpClient().CloseIdleConnections() +} - r.Disgo().EventManager().Dispatch(events.HTTPRequestEvent{ +// DoWithHeaders executes a rest request with custom headers +func (r *RestClientImpl) DoWithHeaders(route *restclient.CompiledAPIRoute, rqBody interface{}, rsBody interface{}, customHeader http.Header) (err restclient.RestError) { + err = r.RestClient.DoWithHeaders(route, rqBody, rsBody, customHeader) + // TODO reimplement events.HTTPRequestEvent + /*r.Disgo().EventManager().Dispatch(events.HTTPRequestEvent{ GenericEvent: events.NewEvent(r.Disgo(), 0), Request: rq, Response: rs, - }) + }) */ - switch rs.StatusCode { - case http.StatusOK, http.StatusCreated, http.StatusNoContent: - if rsBody != nil { - if err = json.Unmarshal(rawRsBody, rsBody); err != nil { - r.Disgo().Logger().Errorf("error unmarshalling response. error: %s", err) + // TODO reimplement api.ErrorResponse unmarshalling + /* + var errorRs api.ErrorResponse + if err = json.Unmarshal(rawRsBody, &errorRs); err != nil { + r.Disgo().Logger().Errorf("error unmarshalling error response. code: %d, error: %s", rs.StatusCode, err) return err } - } - return nil - - case http.StatusTooManyRequests: - limit := rs.Header.Get("X-RateLimit-Limit") - remaining := rs.Header.Get("X-RateLimit-Limit") - reset := rs.Header.Get("X-RateLimit-Limit") - bucket := rs.Header.Get("X-RateLimit-Limit") - r.Disgo().Logger().Errorf("too many requests. limit: %s, remaining: %s, reset: %s,bucket: %s", limit, remaining, reset, bucket) - return api.ErrRatelimited - - case http.StatusBadGateway: - r.Disgo().Logger().Error(api.ErrBadGateway) - return api.ErrBadGateway - - case http.StatusBadRequest: - r.Disgo().Logger().Errorf("bad request request: \"%s\", response: \"%s\"", string(rqJSON), string(rawRsBody)) - return api.ErrBadRequest - - case http.StatusUnauthorized: - r.Disgo().Logger().Error(api.ErrUnauthorized) - return api.ErrUnauthorized - - default: - var errorRs api.ErrorResponse - if err = json.Unmarshal(rawRsBody, &errorRs); err != nil { - r.Disgo().Logger().Errorf("error unmarshalling error response. code: %d, error: %s", rs.StatusCode, err) - return err - } - return fmt.Errorf("request to %s failed. statuscode: %d, errorcode: %d, message_events: %s", rq.URL, rs.StatusCode, errorRs.Code, errorRs.Message) - } + return fmt.Errorf("request to %s failed. statuscode: %d, errorcode: %d, message_events: %s", rq.URL, rs.StatusCode, errorRs.Code, errorRs.Message) + */ + return } // SendMessage lets you send a api.Message to a api.MessageChannel -func (r RestClientImpl) SendMessage(channelID api.Snowflake, message *api.MessageCreate) (msg *api.Message, err error) { - compiledRoute, err := endpoints.CreateMessage.Compile(channelID) +func (r *RestClientImpl) SendMessage(channelID api.Snowflake, message *api.MessageCreate) (msg *api.Message, err error) { + compiledRoute, err := restclient.CreateMessage.Compile(nil, channelID) if err != nil { return nil, err } - err = r.Request(compiledRoute, message, &msg) + var fullMsg *api.FullMessage + err = r.Do(compiledRoute, message, &fullMsg) if err == nil { - msg = r.Disgo().EntityBuilder().CreateMessage(msg, api.CacheStrategyNoWs) + msg = r.Disgo().EntityBuilder().CreateMessage(fullMsg, api.CacheStrategyNoWs) } return } // EditMessage lets you edit a api.Message -func (r RestClientImpl) EditMessage(channelID api.Snowflake, messageID api.Snowflake, message *api.MessageUpdate) (msg *api.Message, err error) { - compiledRoute, err := endpoints.UpdateMessage.Compile(channelID, messageID) +func (r *RestClientImpl) EditMessage(channelID api.Snowflake, messageID api.Snowflake, message *api.MessageUpdate) (msg *api.Message, err error) { + compiledRoute, err := restclient.UpdateMessage.Compile(nil, channelID, messageID) if err != nil { return nil, err } - err = r.Request(compiledRoute, message, &msg) + var fullMsg *api.FullMessage + err = r.Do(compiledRoute, message, &fullMsg) if err == nil { - msg = r.Disgo().EntityBuilder().CreateMessage(msg, api.CacheStrategyNoWs) + msg = r.Disgo().EntityBuilder().CreateMessage(fullMsg, api.CacheStrategyNoWs) } return } // DeleteMessage lets you delete a api.Message -func (r RestClientImpl) DeleteMessage(channelID api.Snowflake, messageID api.Snowflake) (err error) { - compiledRoute, err := endpoints.DeleteMessage.Compile(channelID, messageID) +func (r *RestClientImpl) DeleteMessage(channelID api.Snowflake, messageID api.Snowflake) (err error) { + compiledRoute, err := restclient.DeleteMessage.Compile(nil, channelID, messageID) if err != nil { return err } - err = r.Request(compiledRoute, nil, nil) + err = r.Do(compiledRoute, nil, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { r.Disgo().Cache().UncacheMessage(channelID, messageID) } @@ -191,12 +98,12 @@ func (r RestClientImpl) DeleteMessage(channelID api.Snowflake, messageID api.Sno } // BulkDeleteMessages lets you bulk delete api.Message(s) -func (r RestClientImpl) BulkDeleteMessages(channelID api.Snowflake, messageIDs ...api.Snowflake) (err error) { - compiledRoute, err := endpoints.BulkDeleteMessage.Compile(channelID) +func (r *RestClientImpl) BulkDeleteMessages(channelID api.Snowflake, messageIDs ...api.Snowflake) (err error) { + compiledRoute, err := restclient.BulkDeleteMessage.Compile(nil, channelID) if err != nil { return err } - err = r.Request(compiledRoute, api.MessageBulkDelete{Messages: messageIDs}, nil) + err = r.Do(compiledRoute, api.MessageBulkDelete{Messages: messageIDs}, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { // TODO: check here if no err means all messages deleted for _, messageID := range messageIDs { @@ -207,21 +114,22 @@ func (r RestClientImpl) BulkDeleteMessages(channelID api.Snowflake, messageIDs . } // CrosspostMessage lets you crosspost a api.Message in a channel with type api.ChannelTypeNews -func (r RestClientImpl) CrosspostMessage(channelID api.Snowflake, messageID api.Snowflake) (msg *api.Message, err error) { - compiledRoute, err := endpoints.CrosspostMessage.Compile(channelID, messageID) +func (r *RestClientImpl) CrosspostMessage(channelID api.Snowflake, messageID api.Snowflake) (msg *api.Message, err error) { + compiledRoute, err := restclient.CrosspostMessage.Compile(nil, channelID, messageID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &msg) + var fullMsg *api.FullMessage + err = r.Do(compiledRoute, nil, &fullMsg) if err == nil { - msg = r.Disgo().EntityBuilder().CreateMessage(msg, api.CacheStrategyNoWs) + msg = r.Disgo().EntityBuilder().CreateMessage(fullMsg, api.CacheStrategyNoWs) } return } // OpenDMChannel opens a new dm channel a user -func (r RestClientImpl) OpenDMChannel(userID api.Snowflake) (channel *api.DMChannel, err error) { - compiledRoute, err := endpoints.CreateDMChannel.Compile() +func (r *RestClientImpl) OpenDMChannel(userID api.Snowflake) (channel *api.DMChannel, err error) { + compiledRoute, err := restclient.CreateDMChannel.Compile(nil) if err != nil { return nil, err } @@ -230,7 +138,7 @@ func (r RestClientImpl) OpenDMChannel(userID api.Snowflake) (channel *api.DMChan }{ RecipientID: userID, } - err = r.Request(compiledRoute, body, &channel) + err = r.Do(compiledRoute, body, &channel) if err == nil { channel = r.Disgo().EntityBuilder().CreateDMChannel(&channel.MessageChannel.Channel, api.CacheStrategyNoWs) } @@ -238,13 +146,13 @@ func (r RestClientImpl) OpenDMChannel(userID api.Snowflake) (channel *api.DMChan } // UpdateSelfNick updates the bots nickname in a guild -func (r RestClientImpl) UpdateSelfNick(guildID api.Snowflake, nick *string) (newNick *string, err error) { - compiledRoute, err := endpoints.UpdateSelfNick.Compile(guildID) +func (r *RestClientImpl) UpdateSelfNick(guildID api.Snowflake, nick *string) (newNick *string, err error) { + compiledRoute, err := restclient.UpdateSelfNick.Compile(nil, guildID) if err != nil { return nil, err } var updateNick *api.UpdateSelfNick - err = r.Request(compiledRoute, &api.UpdateSelfNick{Nick: nick}, &updateNick) + err = r.Do(compiledRoute, &api.UpdateSelfNick{Nick: nick}, &updateNick) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { r.Disgo().Cache().Member(guildID, r.Disgo().ApplicationID()).Nick = updateNick.Nick newNick = updateNick.Nick @@ -253,12 +161,12 @@ func (r RestClientImpl) UpdateSelfNick(guildID api.Snowflake, nick *string) (new } // GetUser fetches the specific user -func (r RestClientImpl) GetUser(userID api.Snowflake) (user *api.User, err error) { - compiledRoute, err := endpoints.GetUser.Compile(userID) +func (r *RestClientImpl) GetUser(userID api.Snowflake) (user *api.User, err error) { + compiledRoute, err := restclient.GetUser.Compile(nil, userID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &user) + err = r.Do(compiledRoute, nil, &user) if err == nil { user = r.Disgo().EntityBuilder().CreateUser(user, api.CacheStrategyNoWs) } @@ -266,12 +174,12 @@ func (r RestClientImpl) GetUser(userID api.Snowflake) (user *api.User, err error } // GetMember fetches the specific member -func (r RestClientImpl) GetMember(guildID api.Snowflake, userID api.Snowflake) (member *api.Member, err error) { - compiledRoute, err := endpoints.GetMember.Compile(guildID, userID) +func (r *RestClientImpl) GetMember(guildID api.Snowflake, userID api.Snowflake) (member *api.Member, err error) { + compiledRoute, err := restclient.GetMember.Compile(nil, guildID, userID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &member) + err = r.Do(compiledRoute, nil, &member) if err == nil { member = r.Disgo().EntityBuilder().CreateMember(guildID, member, api.CacheStrategyNoWs) } @@ -279,12 +187,12 @@ func (r RestClientImpl) GetMember(guildID api.Snowflake, userID api.Snowflake) ( } // GetMembers fetches all members for a guild -func (r RestClientImpl) GetMembers(guildID api.Snowflake) (members []*api.Member, err error) { - compiledRoute, err := endpoints.GetMembers.Compile(guildID) +func (r *RestClientImpl) GetMembers(guildID api.Snowflake) (members []*api.Member, err error) { + compiledRoute, err := restclient.GetMembers.Compile(nil, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &members) + err = r.Do(compiledRoute, nil, &members) if err == nil { for _, member := range members { member = r.Disgo().EntityBuilder().CreateMember(guildID, member, api.CacheStrategyNoWs) @@ -294,12 +202,12 @@ func (r RestClientImpl) GetMembers(guildID api.Snowflake) (members []*api.Member } // AddMember adds a member to the guild with the oauth2 access BotToken. requires api.PermissionCreateInstantInvite -func (r RestClientImpl) AddMember(guildID api.Snowflake, userID api.Snowflake, addGuildMemberData *api.AddGuildMemberData) (member *api.Member, err error) { - compiledRoute, err := endpoints.AddMember.Compile(guildID, userID) +func (r *RestClientImpl) AddMember(guildID api.Snowflake, userID api.Snowflake, addGuildMemberData *api.AddGuildMemberData) (member *api.Member, err error) { + compiledRoute, err := restclient.AddMember.Compile(nil, guildID, userID) if err != nil { return nil, err } - err = r.Request(compiledRoute, addGuildMemberData, &member) + err = r.Do(compiledRoute, addGuildMemberData, &member) if err == nil { member = r.Disgo().EntityBuilder().CreateMember(guildID, member, api.CacheStrategyNoWs) } @@ -307,17 +215,17 @@ func (r RestClientImpl) AddMember(guildID api.Snowflake, userID api.Snowflake, a } // KickMember kicks a member from the guild. requires api.PermissionKickMembers -func (r RestClientImpl) KickMember(guildID api.Snowflake, userID api.Snowflake, reason *string) (err error) { - var compiledRoute *endpoints.CompiledAPIRoute - if reason == nil { - compiledRoute, err = endpoints.RemoveMember.Compile(guildID, userID) - } else { - compiledRoute, err = endpoints.RemoveMemberReason.Compile(guildID, userID, *reason) +func (r *RestClientImpl) KickMember(guildID api.Snowflake, userID api.Snowflake, reason *string) (err error) { + var compiledRoute *restclient.CompiledAPIRoute + var params map[string]interface{} + if reason != nil { + params = map[string]interface{}{"reason": *reason} } + compiledRoute, err = restclient.RemoveMember.Compile(params, guildID, userID) if err != nil { return } - err = r.Request(compiledRoute, nil, nil) + err = r.Do(compiledRoute, nil, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { r.Disgo().Cache().UncacheMember(guildID, userID) } @@ -325,12 +233,12 @@ func (r RestClientImpl) KickMember(guildID api.Snowflake, userID api.Snowflake, } // UpdateMember updates a member -func (r RestClientImpl) UpdateMember(guildID api.Snowflake, userID api.Snowflake, updateGuildMemberData *api.UpdateGuildMemberData) (member *api.Member, err error) { - compiledRoute, err := endpoints.UpdateMember.Compile(guildID, userID) +func (r *RestClientImpl) UpdateMember(guildID api.Snowflake, userID api.Snowflake, updateGuildMemberData *api.UpdateGuildMemberData) (member *api.Member, err error) { + compiledRoute, err := restclient.UpdateMember.Compile(nil, guildID, userID) if err != nil { return nil, err } - err = r.Request(compiledRoute, updateGuildMemberData, &member) + err = r.Do(compiledRoute, updateGuildMemberData, &member) if err == nil { member = r.Disgo().EntityBuilder().CreateMember(guildID, member, api.CacheStrategyNoWs) } @@ -338,12 +246,12 @@ func (r RestClientImpl) UpdateMember(guildID api.Snowflake, userID api.Snowflake } // MoveMember moves/kicks the member to/from a voice channel -func (r RestClientImpl) MoveMember(guildID api.Snowflake, userID api.Snowflake, channelID *api.Snowflake) (member *api.Member, err error) { - compiledRoute, err := endpoints.UpdateMember.Compile(guildID, userID) +func (r *RestClientImpl) MoveMember(guildID api.Snowflake, userID api.Snowflake, channelID *api.Snowflake) (member *api.Member, err error) { + compiledRoute, err := restclient.UpdateMember.Compile(nil, guildID, userID) if err != nil { return nil, err } - err = r.Request(compiledRoute, api.MoveGuildMemberData{ChannelID: channelID}, &member) + err = r.Do(compiledRoute, api.MoveGuildMemberData{ChannelID: channelID}, &member) if err == nil { member = r.Disgo().EntityBuilder().CreateMember(guildID, member, api.CacheStrategyNoWs) } @@ -351,12 +259,12 @@ func (r RestClientImpl) MoveMember(guildID api.Snowflake, userID api.Snowflake, } // AddMemberRole adds a role to a member -func (r RestClientImpl) AddMemberRole(guildID api.Snowflake, userID api.Snowflake, roleID api.Snowflake) (err error) { - compiledRoute, err := endpoints.AddMemberRole.Compile(guildID, userID, roleID) +func (r *RestClientImpl) AddMemberRole(guildID api.Snowflake, userID api.Snowflake, roleID api.Snowflake) (err error) { + compiledRoute, err := restclient.AddMemberRole.Compile(nil, guildID, userID, roleID) if err != nil { return err } - err = r.Request(compiledRoute, nil, nil) + err = r.Do(compiledRoute, nil, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { member := r.Disgo().Cache().Member(guildID, userID) if member != nil { @@ -367,12 +275,12 @@ func (r RestClientImpl) AddMemberRole(guildID api.Snowflake, userID api.Snowflak } // RemoveMemberRole removes a role from a member -func (r RestClientImpl) RemoveMemberRole(guildID api.Snowflake, userID api.Snowflake, roleID api.Snowflake) (err error) { - compiledRoute, err := endpoints.RemoveMemberRole.Compile(guildID, userID, roleID) +func (r *RestClientImpl) RemoveMemberRole(guildID api.Snowflake, userID api.Snowflake, roleID api.Snowflake) (err error) { + compiledRoute, err := restclient.RemoveMemberRole.Compile(nil, guildID, userID, roleID) if err != nil { return err } - err = r.Request(compiledRoute, nil, nil) + err = r.Do(compiledRoute, nil, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { member := r.Disgo().Cache().Member(guildID, userID) if member != nil { @@ -388,12 +296,12 @@ func (r RestClientImpl) RemoveMemberRole(guildID api.Snowflake, userID api.Snowf } // GetRoles fetches all roles from a guild -func (r RestClientImpl) GetRoles(guildID api.Snowflake) (roles []*api.Role, err error) { - compiledRoute, err := endpoints.GetRoles.Compile(guildID) +func (r *RestClientImpl) GetRoles(guildID api.Snowflake) (roles []*api.Role, err error) { + compiledRoute, err := restclient.GetRoles.Compile(nil, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &roles) + err = r.Do(compiledRoute, nil, &roles) if err == nil { for _, role := range roles { role = r.Disgo().EntityBuilder().CreateRole(guildID, role, api.CacheStrategyNoWs) @@ -403,12 +311,12 @@ func (r RestClientImpl) GetRoles(guildID api.Snowflake) (roles []*api.Role, err } // CreateRole creates a new role for a guild. Requires api.PermissionManageRoles -func (r RestClientImpl) CreateRole(guildID api.Snowflake, role *api.UpdateRole) (newRole *api.Role, err error) { - compiledRoute, err := endpoints.CreateRole.Compile(guildID) +func (r *RestClientImpl) CreateRole(guildID api.Snowflake, role *api.UpdateRole) (newRole *api.Role, err error) { + compiledRoute, err := restclient.CreateRole.Compile(nil, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, role, &newRole) + err = r.Do(compiledRoute, role, &newRole) if err == nil { newRole = r.Disgo().EntityBuilder().CreateRole(guildID, newRole, api.CacheStrategyNoWs) } @@ -416,12 +324,12 @@ func (r RestClientImpl) CreateRole(guildID api.Snowflake, role *api.UpdateRole) } // UpdateRole updates a role from a guild. Requires api.PermissionManageRoles -func (r RestClientImpl) UpdateRole(guildID api.Snowflake, roleID api.Snowflake, role *api.UpdateRole) (newRole *api.Role, err error) { - compiledRoute, err := endpoints.UpdateRole.Compile(guildID, roleID) +func (r *RestClientImpl) UpdateRole(guildID api.Snowflake, roleID api.Snowflake, role *api.UpdateRole) (newRole *api.Role, err error) { + compiledRoute, err := restclient.UpdateRole.Compile(nil, guildID, roleID) if err != nil { return nil, err } - err = r.Request(compiledRoute, role, &newRole) + err = r.Do(compiledRoute, role, &newRole) if err == nil { newRole = r.Disgo().EntityBuilder().CreateRole(guildID, newRole, api.CacheStrategyNoWs) } @@ -429,12 +337,12 @@ func (r RestClientImpl) UpdateRole(guildID api.Snowflake, roleID api.Snowflake, } // UpdateRolePositions updates the position of a role from a guild. Requires api.PermissionManageRoles -func (r RestClientImpl) UpdateRolePositions(guildID api.Snowflake, roleUpdates ...*api.UpdateRolePosition) (roles []*api.Role, err error) { - compiledRoute, err := endpoints.GetRoles.Compile(guildID) +func (r *RestClientImpl) UpdateRolePositions(guildID api.Snowflake, roleUpdates ...*api.UpdateRolePosition) (roles []*api.Role, err error) { + compiledRoute, err := restclient.GetRoles.Compile(nil, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, roleUpdates, &roles) + err = r.Do(compiledRoute, roleUpdates, &roles) if err == nil { for _, role := range roles { role = r.Disgo().EntityBuilder().CreateRole(guildID, role, api.CacheStrategyNoWs) @@ -444,12 +352,12 @@ func (r RestClientImpl) UpdateRolePositions(guildID api.Snowflake, roleUpdates . } // DeleteRole deletes a role from a guild. Requires api.PermissionManageRoles -func (r RestClientImpl) DeleteRole(guildID api.Snowflake, roleID api.Snowflake) (err error) { - compiledRoute, err := endpoints.UpdateRole.Compile(guildID, roleID) +func (r *RestClientImpl) DeleteRole(guildID api.Snowflake, roleID api.Snowflake) (err error) { + compiledRoute, err := restclient.UpdateRole.Compile(nil, guildID, roleID) if err != nil { return err } - err = r.Request(compiledRoute, nil, nil) + err = r.Do(compiledRoute, nil, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { r.disgo.Cache().UncacheRole(guildID, roleID) } @@ -457,39 +365,39 @@ func (r RestClientImpl) DeleteRole(guildID api.Snowflake, roleID api.Snowflake) } // AddReaction lets you add a reaction to a message_events -func (r RestClientImpl) AddReaction(channelID api.Snowflake, messageID api.Snowflake, emoji string) error { - compiledRoute, err := endpoints.AddReaction.Compile(channelID, messageID, normalizeEmoji(emoji)) +func (r *RestClientImpl) AddReaction(channelID api.Snowflake, messageID api.Snowflake, emoji string) error { + compiledRoute, err := restclient.AddReaction.Compile(nil, channelID, messageID, normalizeEmoji(emoji)) if err != nil { return err } - return r.Request(compiledRoute, nil, nil) + return r.Do(compiledRoute, nil, nil) } // RemoveOwnReaction lets you remove your own reaction from a message_events -func (r RestClientImpl) RemoveOwnReaction(channelID api.Snowflake, messageID api.Snowflake, emoji string) error { - compiledRoute, err := endpoints.RemoveOwnReaction.Compile(channelID, messageID, normalizeEmoji(emoji)) +func (r *RestClientImpl) RemoveOwnReaction(channelID api.Snowflake, messageID api.Snowflake, emoji string) error { + compiledRoute, err := restclient.RemoveOwnReaction.Compile(nil, channelID, messageID, normalizeEmoji(emoji)) if err != nil { return err } - return r.Request(compiledRoute, nil, nil) + return r.Do(compiledRoute, nil, nil) } // RemoveUserReaction lets you remove a specific reaction from a user from a message_events -func (r RestClientImpl) RemoveUserReaction(channelID api.Snowflake, messageID api.Snowflake, emoji string, userID api.Snowflake) error { - compiledRoute, err := endpoints.RemoveUserReaction.Compile(channelID, messageID, normalizeEmoji(emoji), userID) +func (r *RestClientImpl) RemoveUserReaction(channelID api.Snowflake, messageID api.Snowflake, emoji string, userID api.Snowflake) error { + compiledRoute, err := restclient.RemoveUserReaction.Compile(nil, channelID, messageID, normalizeEmoji(emoji), userID) if err != nil { return err } - return r.Request(compiledRoute, nil, nil) + return r.Do(compiledRoute, nil, nil) } // GetGlobalCommands gets you all global commands -func (r RestClientImpl) GetGlobalCommands(applicationID api.Snowflake) (commands []*api.Command, err error) { - compiledRoute, err := endpoints.GetGlobalCommands.Compile(applicationID) +func (r *RestClientImpl) GetGlobalCommands(applicationID api.Snowflake) (commands []*api.Command, err error) { + compiledRoute, err := restclient.GetGlobalCommands.Compile(nil, applicationID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &commands) + err = r.Do(compiledRoute, nil, &commands) if err == nil { for _, cmd := range commands { cmd = r.Disgo().EntityBuilder().CreateGlobalCommand(cmd, api.CacheStrategyNoWs) @@ -499,12 +407,12 @@ func (r RestClientImpl) GetGlobalCommands(applicationID api.Snowflake) (commands } // GetGlobalCommand gets you a specific global global command -func (r RestClientImpl) GetGlobalCommand(applicationID api.Snowflake, commandID api.Snowflake) (cmd *api.Command, err error) { - compiledRoute, err := endpoints.GetGlobalCommand.Compile(applicationID, commandID) +func (r *RestClientImpl) GetGlobalCommand(applicationID api.Snowflake, commandID api.Snowflake) (cmd *api.Command, err error) { + compiledRoute, err := restclient.GetGlobalCommand.Compile(nil, applicationID, commandID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &cmd) + err = r.Do(compiledRoute, nil, &cmd) if err == nil { cmd = r.Disgo().EntityBuilder().CreateGlobalCommand(cmd, api.CacheStrategyNoWs) } @@ -512,12 +420,12 @@ func (r RestClientImpl) GetGlobalCommand(applicationID api.Snowflake, commandID } // CreateGlobalCommand lets you create a new global command -func (r RestClientImpl) CreateGlobalCommand(applicationID api.Snowflake, command *api.CommandCreate) (cmd *api.Command, err error) { - compiledRoute, err := endpoints.CreateGlobalCommand.Compile(applicationID) +func (r *RestClientImpl) CreateGlobalCommand(applicationID api.Snowflake, command *api.CommandCreate) (cmd *api.Command, err error) { + compiledRoute, err := restclient.CreateGlobalCommand.Compile(nil, applicationID) if err != nil { return nil, err } - err = r.Request(compiledRoute, command, &cmd) + err = r.Do(compiledRoute, command, &cmd) if err == nil { cmd = r.Disgo().EntityBuilder().CreateGlobalCommand(cmd, api.CacheStrategyNoWs) } @@ -525,16 +433,16 @@ func (r RestClientImpl) CreateGlobalCommand(applicationID api.Snowflake, command } // SetGlobalCommands lets you override all global commands -func (r RestClientImpl) SetGlobalCommands(applicationID api.Snowflake, commands ...*api.CommandCreate) (cmds []*api.Command, err error) { - compiledRoute, err := endpoints.SetGlobalCommands.Compile(applicationID) +func (r *RestClientImpl) SetGlobalCommands(applicationID api.Snowflake, commands ...*api.CommandCreate) (cmds []*api.Command, err error) { + compiledRoute, err := restclient.SetGlobalCommands.Compile(nil, applicationID) if err != nil { return nil, err } if len(commands) > 100 { - err = api.ErrTooMuchApplicationCommands + err = api.ErrTooMuchCommands return } - err = r.Request(compiledRoute, commands, &cmds) + err = r.Do(compiledRoute, commands, &cmds) if err == nil { for _, cmd := range cmds { cmd = r.Disgo().EntityBuilder().CreateGlobalCommand(cmd, api.CacheStrategyNoWs) @@ -544,12 +452,12 @@ func (r RestClientImpl) SetGlobalCommands(applicationID api.Snowflake, commands } // EditGlobalCommand lets you edit a specific global command -func (r RestClientImpl) EditGlobalCommand(applicationID api.Snowflake, commandID api.Snowflake, command *api.CommandUpdate) (cmd *api.Command, err error) { - compiledRoute, err := endpoints.EditGlobalCommand.Compile(applicationID, commandID) +func (r *RestClientImpl) EditGlobalCommand(applicationID api.Snowflake, commandID api.Snowflake, command *api.CommandUpdate) (cmd *api.Command, err error) { + compiledRoute, err := restclient.UpdateGlobalCommand.Compile(nil, applicationID, commandID) if err != nil { return nil, err } - err = r.Request(compiledRoute, command, &cmd) + err = r.Do(compiledRoute, command, &cmd) if err == nil { cmd = r.Disgo().EntityBuilder().CreateGlobalCommand(cmd, api.CacheStrategyNoWs) } @@ -557,12 +465,12 @@ func (r RestClientImpl) EditGlobalCommand(applicationID api.Snowflake, commandID } // DeleteGlobalCommand lets you delete a specific global command -func (r RestClientImpl) DeleteGlobalCommand(applicationID api.Snowflake, commandID api.Snowflake) (err error) { - compiledRoute, err := endpoints.DeleteGlobalCommand.Compile(applicationID, commandID) +func (r *RestClientImpl) DeleteGlobalCommand(applicationID api.Snowflake, commandID api.Snowflake) (err error) { + compiledRoute, err := restclient.DeleteGlobalCommand.Compile(nil, applicationID, commandID) if err != nil { return err } - err = r.Request(compiledRoute, nil, nil) + err = r.Do(compiledRoute, nil, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { r.Disgo().Cache().UncacheCommand(commandID) } @@ -570,12 +478,12 @@ func (r RestClientImpl) DeleteGlobalCommand(applicationID api.Snowflake, command } // GetGuildCommands gets you all guild_events commands -func (r RestClientImpl) GetGuildCommands(applicationID api.Snowflake, guildID api.Snowflake) (commands []*api.Command, err error) { - compiledRoute, err := endpoints.GetGuildCommands.Compile(applicationID, guildID) +func (r *RestClientImpl) GetGuildCommands(applicationID api.Snowflake, guildID api.Snowflake) (commands []*api.Command, err error) { + compiledRoute, err := restclient.GetGuildCommands.Compile(nil, applicationID, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &commands) + err = r.Do(compiledRoute, nil, &commands) if err == nil { for _, cmd := range commands { cmd = r.Disgo().EntityBuilder().CreateGuildCommand(guildID, cmd, api.CacheStrategyNoWs) @@ -585,12 +493,12 @@ func (r RestClientImpl) GetGuildCommands(applicationID api.Snowflake, guildID ap } // CreateGuildCommand lets you create a new guild_events command -func (r RestClientImpl) CreateGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, command *api.CommandCreate) (cmd *api.Command, err error) { - compiledRoute, err := endpoints.CreateGuildCommand.Compile(applicationID, guildID) +func (r *RestClientImpl) CreateGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, command *api.CommandCreate) (cmd *api.Command, err error) { + compiledRoute, err := restclient.CreateGuildCommand.Compile(nil, applicationID, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, command, &cmd) + err = r.Do(compiledRoute, command, &cmd) if err == nil { cmd = r.Disgo().EntityBuilder().CreateGuildCommand(guildID, cmd, api.CacheStrategyNoWs) } @@ -598,16 +506,16 @@ func (r RestClientImpl) CreateGuildCommand(applicationID api.Snowflake, guildID } // SetGuildCommands lets you override all guild_events commands -func (r RestClientImpl) SetGuildCommands(applicationID api.Snowflake, guildID api.Snowflake, commands ...*api.CommandCreate) (cmds []*api.Command, err error) { - compiledRoute, err := endpoints.SetGuildCommands.Compile(applicationID, guildID) +func (r *RestClientImpl) SetGuildCommands(applicationID api.Snowflake, guildID api.Snowflake, commands ...*api.CommandCreate) (cmds []*api.Command, err error) { + compiledRoute, err := restclient.SetGuildCommands.Compile(nil, applicationID, guildID) if err != nil { return nil, err } if len(commands) > 100 { - err = api.ErrTooMuchApplicationCommands + err = api.ErrTooMuchCommands return } - err = r.Request(compiledRoute, commands, &cmds) + err = r.Do(compiledRoute, commands, &cmds) if err == nil { for _, cmd := range cmds { cmd = r.Disgo().EntityBuilder().CreateGuildCommand(guildID, cmd, api.CacheStrategyNoWs) @@ -617,12 +525,12 @@ func (r RestClientImpl) SetGuildCommands(applicationID api.Snowflake, guildID ap } // GetGuildCommand gets you a specific guild_events command -func (r RestClientImpl) GetGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake) (cmd *api.Command, err error) { - compiledRoute, err := endpoints.GetGuildCommand.Compile(applicationID, guildID, commandID) +func (r *RestClientImpl) GetGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake) (cmd *api.Command, err error) { + compiledRoute, err := restclient.GetGuildCommand.Compile(nil, applicationID, guildID, commandID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &cmd) + err = r.Do(compiledRoute, nil, &cmd) if err == nil { cmd = r.Disgo().EntityBuilder().CreateGuildCommand(guildID, cmd, api.CacheStrategyNoWs) } @@ -630,12 +538,12 @@ func (r RestClientImpl) GetGuildCommand(applicationID api.Snowflake, guildID api } // EditGuildCommand lets you edit a specific guild_events command -func (r RestClientImpl) EditGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake, command *api.CommandUpdate) (cmd *api.Command, err error) { - compiledRoute, err := endpoints.EditGuildCommand.Compile(applicationID, guildID, commandID) +func (r *RestClientImpl) EditGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake, command *api.CommandUpdate) (cmd *api.Command, err error) { + compiledRoute, err := restclient.UpdateGuildCommand.Compile(nil, applicationID, guildID, commandID) if err != nil { return nil, err } - err = r.Request(compiledRoute, command, &cmd) + err = r.Do(compiledRoute, command, &cmd) if err == nil { cmd = r.Disgo().EntityBuilder().CreateGuildCommand(guildID, cmd, api.CacheStrategyNoWs) } @@ -643,12 +551,12 @@ func (r RestClientImpl) EditGuildCommand(applicationID api.Snowflake, guildID ap } // DeleteGuildCommand lets you delete a specific guild_events command -func (r RestClientImpl) DeleteGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake) (err error) { - compiledRoute, err := endpoints.DeleteGuildCommand.Compile(applicationID, guildID, commandID) +func (r *RestClientImpl) DeleteGuildCommand(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake) (err error) { + compiledRoute, err := restclient.DeleteGuildCommand.Compile(nil, applicationID, guildID, commandID) if err != nil { return err } - err = r.Request(compiledRoute, nil, nil) + err = r.Do(compiledRoute, nil, nil) if err == nil && api.CacheStrategyNoWs(r.Disgo()) { r.Disgo().Cache().UncacheCommand(commandID) } @@ -656,12 +564,12 @@ func (r RestClientImpl) DeleteGuildCommand(applicationID api.Snowflake, guildID } // GetGuildCommandsPermissions returns the api.CommandPermission for a all api.Command(s) in a guild -func (r RestClientImpl) GetGuildCommandsPermissions(applicationID api.Snowflake, guildID api.Snowflake) (cmdsPerms []*api.GuildCommandPermissions, err error) { - compiledRoute, err := endpoints.GetGuildCommandPermissions.Compile(applicationID, guildID) +func (r *RestClientImpl) GetGuildCommandsPermissions(applicationID api.Snowflake, guildID api.Snowflake) (cmdsPerms []*api.GuildCommandPermissions, err error) { + compiledRoute, err := restclient.GetGuildCommandPermissions.Compile(nil, applicationID, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &cmdsPerms) + err = r.Do(compiledRoute, nil, &cmdsPerms) if err == nil { for _, cmdPerms := range cmdsPerms { cmdPerms = r.Disgo().EntityBuilder().CreateGuildCommandPermissions(cmdPerms, api.CacheStrategyNoWs) @@ -671,12 +579,12 @@ func (r RestClientImpl) GetGuildCommandsPermissions(applicationID api.Snowflake, } // GetGuildCommandPermissions returns the api.CommandPermission for a specific api.Command in a guild -func (r RestClientImpl) GetGuildCommandPermissions(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake) (cmdPerms *api.GuildCommandPermissions, err error) { - compiledRoute, err := endpoints.GetGuildCommandPermission.Compile(applicationID, guildID, commandID) +func (r *RestClientImpl) GetGuildCommandPermissions(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake) (cmdPerms *api.GuildCommandPermissions, err error) { + compiledRoute, err := restclient.GetGuildCommandPermission.Compile(nil, applicationID, guildID, commandID) if err != nil { return nil, err } - err = r.Request(compiledRoute, nil, &cmdPerms) + err = r.Do(compiledRoute, nil, &cmdPerms) if err == nil { cmdPerms = r.Disgo().EntityBuilder().CreateGuildCommandPermissions(cmdPerms, api.CacheStrategyNoWs) } @@ -684,12 +592,12 @@ func (r RestClientImpl) GetGuildCommandPermissions(applicationID api.Snowflake, } // SetGuildCommandsPermissions sets the api.GuildCommandPermissions for a all api.Command(s) -func (r RestClientImpl) SetGuildCommandsPermissions(applicationID api.Snowflake, guildID api.Snowflake, commandsPermissions ...*api.SetGuildCommandPermissions) (cmdsPerms []*api.GuildCommandPermissions, err error) { - compiledRoute, err := endpoints.SetGuildCommandsPermissions.Compile(applicationID, guildID) +func (r *RestClientImpl) SetGuildCommandsPermissions(applicationID api.Snowflake, guildID api.Snowflake, commandsPermissions ...*api.SetGuildCommandPermissions) (cmdsPerms []*api.GuildCommandPermissions, err error) { + compiledRoute, err := restclient.SetGuildCommandsPermissions.Compile(nil, applicationID, guildID) if err != nil { return nil, err } - err = r.Request(compiledRoute, api.SetGuildCommandsPermissions(commandsPermissions), &cmdsPerms) + err = r.Do(compiledRoute, api.SetGuildCommandsPermissions(commandsPermissions), &cmdsPerms) if err == nil { for _, cmdPerms := range cmdsPerms { cmdPerms = r.Disgo().EntityBuilder().CreateGuildCommandPermissions(cmdPerms, api.CacheStrategyNoWs) @@ -699,12 +607,12 @@ func (r RestClientImpl) SetGuildCommandsPermissions(applicationID api.Snowflake, } // SetGuildCommandPermissions sets the api.GuildCommandPermissions for a specific api.Command -func (r RestClientImpl) SetGuildCommandPermissions(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake, commandPermissions *api.SetGuildCommandPermissions) (cmdPerms *api.GuildCommandPermissions, err error) { - compiledRoute, err := endpoints.SetGuildCommandPermissions.Compile(applicationID, guildID, commandID) +func (r *RestClientImpl) SetGuildCommandPermissions(applicationID api.Snowflake, guildID api.Snowflake, commandID api.Snowflake, commandPermissions *api.SetGuildCommandPermissions) (cmdPerms *api.GuildCommandPermissions, err error) { + compiledRoute, err := restclient.SetGuildCommandPermissions.Compile(nil, applicationID, guildID, commandID) if err != nil { return nil, err } - err = r.Request(compiledRoute, commandPermissions, &cmdPerms) + err = r.Do(compiledRoute, commandPermissions, &cmdPerms) if err == nil { cmdPerms = r.Disgo().EntityBuilder().CreateGuildCommandPermissions(cmdPerms, api.CacheStrategyNoWs) } @@ -712,57 +620,57 @@ func (r RestClientImpl) SetGuildCommandPermissions(applicationID api.Snowflake, } // SendInteractionResponse used to send the initial response on an interaction -func (r RestClientImpl) SendInteractionResponse(interactionID api.Snowflake, interactionToken string, interactionResponse *api.InteractionResponse) error { - compiledRoute, err := endpoints.CreateInteractionResponse.Compile(interactionID, interactionToken) +func (r *RestClientImpl) SendInteractionResponse(interactionID api.Snowflake, interactionToken string, interactionResponse *api.InteractionResponse) error { + compiledRoute, err := restclient.CreateInteractionResponse.Compile(nil, interactionID, interactionToken) if err != nil { return err } - return r.Request(compiledRoute, interactionResponse, nil) + return r.Do(compiledRoute, interactionResponse, nil) } // EditInteractionResponse used to edit the initial response on an interaction -func (r RestClientImpl) EditInteractionResponse(applicationID api.Snowflake, interactionToken string, followupMessage *api.FollowupMessage) (message *api.Message, err error) { - compiledRoute, err := endpoints.EditInteractionResponse.Compile(applicationID, interactionToken) +func (r *RestClientImpl) EditInteractionResponse(applicationID api.Snowflake, interactionToken string, followupMessage *api.FollowupMessage) (message *api.Message, err error) { + compiledRoute, err := restclient.UpdateInteractionResponse.Compile(nil, applicationID, interactionToken) if err != nil { return nil, err } - return message, r.Request(compiledRoute, followupMessage, &message) + return message, r.Do(compiledRoute, followupMessage, &message) } // DeleteInteractionResponse used to delete the initial response on an interaction -func (r RestClientImpl) DeleteInteractionResponse(applicationID api.Snowflake, interactionToken string) error { - compiledRoute, err := endpoints.DeleteInteractionResponse.Compile(applicationID, interactionToken) +func (r *RestClientImpl) DeleteInteractionResponse(applicationID api.Snowflake, interactionToken string) error { + compiledRoute, err := restclient.DeleteInteractionResponse.Compile(nil, applicationID, interactionToken) if err != nil { return err } - return r.Request(compiledRoute, nil, nil) + return r.Do(compiledRoute, nil, nil) } // SendFollowupMessage used to send a followup message_events to an interaction -func (r RestClientImpl) SendFollowupMessage(applicationID api.Snowflake, interactionToken string, followupMessage *api.FollowupMessage) (message *api.Message, err error) { - compiledRoute, err := endpoints.CreateFollowupMessage.Compile(applicationID, interactionToken) +func (r *RestClientImpl) SendFollowupMessage(applicationID api.Snowflake, interactionToken string, followupMessage *api.FollowupMessage) (message *api.Message, err error) { + compiledRoute, err := restclient.CreateFollowupMessage.Compile(nil, applicationID, interactionToken) if err != nil { return nil, err } - return message, r.Request(compiledRoute, followupMessage, &message) + return message, r.Do(compiledRoute, followupMessage, &message) } // EditFollowupMessage used to edit a api.FollowupMessage from an api.Interaction -func (r RestClientImpl) EditFollowupMessage(applicationID api.Snowflake, interactionToken string, messageID api.Snowflake, followupMessage *api.FollowupMessage) (message *api.Message, err error) { - compiledRoute, err := endpoints.EditFollowupMessage.Compile(applicationID, interactionToken, messageID) +func (r *RestClientImpl) EditFollowupMessage(applicationID api.Snowflake, interactionToken string, messageID api.Snowflake, followupMessage *api.FollowupMessage) (message *api.Message, err error) { + compiledRoute, err := restclient.UpdateFollowupMessage.Compile(nil, applicationID, interactionToken, messageID) if err != nil { return nil, err } - return message, r.Request(compiledRoute, followupMessage, &message) + return message, r.Do(compiledRoute, followupMessage, &message) } // DeleteFollowupMessage used to delete a api.FollowupMessage from an api.Interaction -func (r RestClientImpl) DeleteFollowupMessage(applicationID api.Snowflake, interactionToken string, messageID api.Snowflake) error { - compiledRoute, err := endpoints.DeleteFollowupMessage.Compile(applicationID, interactionToken, messageID) +func (r *RestClientImpl) DeleteFollowupMessage(applicationID api.Snowflake, interactionToken string, messageID api.Snowflake) error { + compiledRoute, err := restclient.DeleteFollowupMessage.Compile(nil, applicationID, interactionToken, messageID) if err != nil { return err } - return r.Request(compiledRoute, nil, nil) + return r.Do(compiledRoute, nil, nil) } func normalizeEmoji(emoji string) string { diff --git a/internal/webhook_server_impl.go b/internal/webhook_server_impl.go index a522d1fb..fef8da2c 100644 --- a/internal/webhook_server_impl.go +++ b/internal/webhook_server_impl.go @@ -12,6 +12,8 @@ import ( "github.com/gorilla/mux" ) +var _ api.WebhookServer = (*WebhookServerImpl)(nil) + func newWebhookServerImpl(disgo api.Disgo, listenURL string, listenPort int, publicKey string) api.WebhookServer { hexDecodedKey, err := hex.DecodeString(publicKey) if err != nil {