Skip to content

Commit

Permalink
Add entry point commands + callback updates (#390)
Browse files Browse the repository at this point in the history
* Add interaction callback response

* Add entry point commands + callback updates

* add missing newlines

* handle entry point command interactions

* add LaunchActivity to InteractionEvent

* fix bad copypaste

* make Handler optional when creating

* make Handler a bointer

* adjust func so it makes more sense

* adjust comment

* add newline back :-)

* address review

* remove 🅱️ointers
  • Loading branch information
sebm253 authored Aug 31, 2024
1 parent 47dd91b commit 814a7e3
Show file tree
Hide file tree
Showing 15 changed files with 418 additions and 0 deletions.
133 changes: 133 additions & 0 deletions discord/application_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const (
ApplicationCommandTypeSlash ApplicationCommandType = iota + 1
ApplicationCommandTypeUser
ApplicationCommandTypeMessage
ApplicationCommandTypePrimaryEntryPoint
)

type ApplicationCommand interface {
Expand Down Expand Up @@ -69,6 +70,11 @@ func (u *UnmarshalApplicationCommand) UnmarshalJSON(data []byte) error {
err = json.Unmarshal(data, &v)
applicationCommand = v

case ApplicationCommandTypePrimaryEntryPoint:
var v EntryPointCommand
err = json.Unmarshal(data, &v)
applicationCommand = v

default:
err = fmt.Errorf("unknown application command with type %d received", cType.Type)
}
Expand Down Expand Up @@ -180,6 +186,7 @@ func (c SlashCommand) NameLocalized() string {
func (c SlashCommand) DefaultMemberPermissions() Permissions {
return c.defaultMemberPermissions
}

func (c SlashCommand) DMPermission() bool {
return c.dmPermission
}
Expand Down Expand Up @@ -297,6 +304,7 @@ func (c UserCommand) NameLocalized() string {
func (c UserCommand) DefaultMemberPermissions() Permissions {
return c.defaultMemberPermissions
}

func (c UserCommand) DMPermission() bool {
return c.dmPermission
}
Expand Down Expand Up @@ -410,6 +418,7 @@ func (c MessageCommand) NameLocalized() string {
func (c MessageCommand) DefaultMemberPermissions() Permissions {
return c.defaultMemberPermissions
}

func (c MessageCommand) DMPermission() bool {
return c.dmPermission
}
Expand All @@ -435,3 +444,127 @@ func (c MessageCommand) CreatedAt() time.Time {
}

func (MessageCommand) applicationCommand() {}

var _ ApplicationCommand = (*EntryPointCommand)(nil)

type EntryPointCommand struct {
id snowflake.ID
applicationID snowflake.ID
guildID *snowflake.ID
name string
nameLocalizations map[Locale]string
nameLocalized string
defaultMemberPermissions Permissions
dmPermission bool
nsfw bool
integrationTypes []ApplicationIntegrationType
contexts []InteractionContextType
version snowflake.ID
Handler EntryPointCommandHandlerType
}

func (c *EntryPointCommand) UnmarshalJSON(data []byte) error {
var v rawEntryPointCommand
if err := json.Unmarshal(data, &v); err != nil {
return err
}

c.id = v.ID
c.applicationID = v.ApplicationID
c.guildID = v.GuildID
c.name = v.Name
c.nameLocalizations = v.NameLocalizations
c.nameLocalized = v.NameLocalized
c.defaultMemberPermissions = v.DefaultMemberPermissions
c.dmPermission = v.DMPermission
c.nsfw = v.NSFW
c.integrationTypes = v.IntegrationTypes
c.contexts = v.Contexts
c.version = v.Version
c.Handler = v.Handler
return nil
}

func (c EntryPointCommand) MarshalJSON() ([]byte, error) {
return json.Marshal(rawEntryPointCommand{
ID: c.id,
Type: c.Type(),
ApplicationID: c.applicationID,
GuildID: c.guildID,
Name: c.name,
NameLocalizations: c.nameLocalizations,
NameLocalized: c.nameLocalized,
DefaultMemberPermissions: c.defaultMemberPermissions,
DMPermission: c.dmPermission,
NSFW: c.nsfw,
IntegrationTypes: c.integrationTypes,
Contexts: c.contexts,
Version: c.version,
Handler: c.Handler,
})
}

func (c EntryPointCommand) ID() snowflake.ID {
return c.id
}

func (EntryPointCommand) Type() ApplicationCommandType {
return ApplicationCommandTypePrimaryEntryPoint
}

func (c EntryPointCommand) ApplicationID() snowflake.ID {
return c.applicationID
}

func (c EntryPointCommand) GuildID() *snowflake.ID {
return c.guildID
}

func (c EntryPointCommand) Name() string {
return c.name
}

func (c EntryPointCommand) NameLocalizations() map[Locale]string {
return c.nameLocalizations
}

func (c EntryPointCommand) NameLocalized() string {
return c.nameLocalized
}

func (c EntryPointCommand) DefaultMemberPermissions() Permissions {
return c.defaultMemberPermissions
}

func (c EntryPointCommand) DMPermission() bool {
return c.dmPermission
}

func (c EntryPointCommand) NSFW() bool {
return c.nsfw
}

func (c EntryPointCommand) IntegrationTypes() []ApplicationIntegrationType {
return c.integrationTypes
}

func (c EntryPointCommand) Contexts() []InteractionContextType {
return c.contexts
}

func (c EntryPointCommand) Version() snowflake.ID {
return c.version
}

func (c EntryPointCommand) CreatedAt() time.Time {
return c.id.Time()
}

func (EntryPointCommand) applicationCommand() {}

type EntryPointCommandHandlerType int

const (
EntryPointCommandHandlerTypeAppHandler EntryPointCommandHandlerType = iota + 1
EntryPointCommandHandlerTypeDiscordLaunchActivity
)
33 changes: 33 additions & 0 deletions discord/application_command_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,36 @@ func (c MessageCommandCreate) CommandName() string {
}

func (MessageCommandCreate) applicationCommandCreate() {}

type EntryPointCommandCreate struct {
Name string `json:"name"`
NameLocalizations map[Locale]string `json:"name_localizations,omitempty"`
DefaultMemberPermissions *json.Nullable[Permissions] `json:"default_member_permissions,omitempty"`
// Deprecated: Use Contexts instead
DMPermission *bool `json:"dm_permission,omitempty"`
IntegrationTypes []ApplicationIntegrationType `json:"integration_types,omitempty"`
Contexts []InteractionContextType `json:"contexts,omitempty"`
NSFW *bool `json:"nsfw,omitempty"`
Handler EntryPointCommandHandlerType `json:"handler,omitempty"`
}

func (c EntryPointCommandCreate) MarshalJSON() ([]byte, error) {
type entryPointCommandCreate EntryPointCommandCreate
return json.Marshal(struct {
Type ApplicationCommandType `json:"type"`
entryPointCommandCreate
}{
Type: c.Type(),
entryPointCommandCreate: entryPointCommandCreate(c),
})
}

func (EntryPointCommandCreate) Type() ApplicationCommandType {
return ApplicationCommandTypePrimaryEntryPoint
}

func (c EntryPointCommandCreate) CommandName() string {
return c.Name
}

func (EntryPointCommandCreate) applicationCommandCreate() {}
17 changes: 17 additions & 0 deletions discord/application_command_raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,20 @@ type rawContextCommand struct {
Contexts []InteractionContextType `json:"contexts"`
Version snowflake.ID `json:"version"`
}

type rawEntryPointCommand struct {
ID snowflake.ID `json:"id"`
Type ApplicationCommandType `json:"type"`
ApplicationID snowflake.ID `json:"application_id"`
GuildID *snowflake.ID `json:"guild_id,omitempty"`
Name string `json:"name"`
NameLocalizations map[Locale]string `json:"name_localizations,omitempty"`
NameLocalized string `json:"name_localized,omitempty"`
DefaultMemberPermissions Permissions `json:"default_member_permissions"`
DMPermission bool `json:"dm_permission"`
NSFW bool `json:"nsfw"`
IntegrationTypes []ApplicationIntegrationType `json:"integration_types"`
Contexts []InteractionContextType `json:"contexts"`
Version snowflake.ID `json:"version"`
Handler EntryPointCommandHandlerType `json:"handler"`
}
33 changes: 33 additions & 0 deletions discord/application_command_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,36 @@ func (c MessageCommandUpdate) CommandName() *string {
}

func (MessageCommandUpdate) applicationCommandUpdate() {}

type EntryPointCommandUpdate struct {
Name *string `json:"name,omitempty"`
NameLocalizations *map[Locale]string `json:"name_localizations,omitempty"`
DefaultMemberPermissions *json.Nullable[Permissions] `json:"default_member_permissions,omitempty"`
// Deprecated: Use Contexts instead
DMPermission *bool `json:"dm_permission,omitempty"`
IntegrationTypes *[]ApplicationIntegrationType `json:"integration_types,omitempty"`
Contexts *[]InteractionContextType `json:"contexts,omitempty"`
NSFW *bool `json:"nsfw,omitempty"`
Handler *EntryPointCommandHandlerType `json:"handler,omitempty"`
}

func (c EntryPointCommandUpdate) MarshalJSON() ([]byte, error) {
type entryPointCommandUpdate EntryPointCommandUpdate
return json.Marshal(struct {
Type ApplicationCommandType `json:"type"`
entryPointCommandUpdate
}{
Type: c.Type(),
entryPointCommandUpdate: entryPointCommandUpdate(c),
})
}

func (EntryPointCommandUpdate) Type() ApplicationCommandType {
return ApplicationCommandTypePrimaryEntryPoint
}

func (c EntryPointCommandUpdate) CommandName() *string {
return c.Name
}

func (EntryPointCommandUpdate) applicationCommandUpdate() {}
59 changes: 59 additions & 0 deletions discord/interaction_application_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error {
v.Resolved.Messages[id] = msg
}
}
case ApplicationCommandTypePrimaryEntryPoint:
v := EntryPointCommandInteractionData{}
err = json.Unmarshal(interaction.Data, &v)
interactionData = v

default:
return fmt.Errorf("unknown application rawInteraction data with type %d received", cType.Type)
Expand Down Expand Up @@ -131,6 +135,10 @@ func (i ApplicationCommandInteraction) MessageCommandInteractionData() MessageCo
return i.Data.(MessageCommandInteractionData)
}

func (i ApplicationCommandInteraction) EntryPointCommandInteractionData() EntryPointCommandInteractionData {
return i.Data.(EntryPointCommandInteractionData)
}

func (ApplicationCommandInteraction) interaction() {}

type ApplicationCommandInteractionData interface {
Expand Down Expand Up @@ -687,3 +695,54 @@ func (MessageCommandInteractionData) contextCommandInteractionData() {}
type MessageCommandResolved struct {
Messages map[snowflake.ID]Message `json:"messages,omitempty"`
}

var (
_ ApplicationCommandInteractionData = (*EntryPointCommandInteractionData)(nil)
)

type rawEntryPointCommandInteractionData struct {
ID snowflake.ID `json:"id"`
Name string `json:"name"`
Type ApplicationCommandType `json:"type"`
}

type EntryPointCommandInteractionData struct {
id snowflake.ID
name string
}

func (d *EntryPointCommandInteractionData) UnmarshalJSON(data []byte) error {
var iData rawEntryPointCommandInteractionData
if err := json.Unmarshal(data, &iData); err != nil {
return err
}
d.id = iData.ID
d.name = iData.Name
return nil
}

func (d *EntryPointCommandInteractionData) MarshalJSON() ([]byte, error) {
return json.Marshal(rawEntryPointCommandInteractionData{
ID: d.id,
Name: d.name,
Type: d.Type(),
})
}

func (EntryPointCommandInteractionData) Type() ApplicationCommandType {
return ApplicationCommandTypePrimaryEntryPoint
}

func (d EntryPointCommandInteractionData) CommandID() snowflake.ID {
return d.id
}

func (d EntryPointCommandInteractionData) CommandName() string {
return d.name
}

func (d EntryPointCommandInteractionData) GuildID() *snowflake.ID {
return nil
}

func (EntryPointCommandInteractionData) applicationCommandInteractionData() {}
27 changes: 27 additions & 0 deletions discord/interaction_callback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package discord

import "github.com/disgoorg/snowflake/v2"

type InteractionCallbackResponse struct {
Interaction InteractionCallback `json:"interaction"`
Resource *InteractionCallbackResource `json:"resource"`
}

type InteractionCallback struct {
ID snowflake.ID `json:"id"`
Type InteractionType `json:"type"`
ActivityInstanceID string `json:"activity_instance_id"`
ResponseMessageID snowflake.ID `json:"response_message_id"`
ResponseMessageLoading bool `json:"response_message_loading"`
ResponseMessageEphemeral bool `json:"response_message_ephemeral"`
}

type InteractionCallbackResource struct {
Type InteractionResponseType `json:"type"`
ActivityInstance *InteractionCallbackActivityInstance `json:"activity_instance"`
Message *Message `json:"message"`
}

type InteractionCallbackActivityInstance struct {
ID string `json:"id"`
}
2 changes: 2 additions & 0 deletions discord/interaction_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const (
InteractionResponseTypeAutocompleteResult
InteractionResponseTypeModal
InteractionResponseTypePremiumRequired
_
InteractionResponseTypeLaunchActivity
)

// 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.
Expand Down
Loading

0 comments on commit 814a7e3

Please sign in to comment.