discord: Refactor interaction commands and components
This commit is an amalgamation of the following local commits: - Fix UnknownCommandOption unmarshaling - Add missing ButtonComponent.UnmarshalJSON - Fix ButtonComponents Style unmarshaling - Remove debug logging - SelectComponent.ComponentEmoji - Fix incorrect CommandOption interface - Switch to pointer types for interfaces - Remove CommandOptionMeta - Less verbose CommandOption type names - Fix unused CommandInteractionOption - Remove ComponentInteractionData
This commit is contained in:
parent
123f8bc41f
commit
80b1dc3831
|
@ -19,82 +19,85 @@ func main() {
|
|||
|
||||
token := os.Getenv("BOT_TOKEN")
|
||||
if token == "" {
|
||||
log.Fatalln("No $BOT_TOKEN given.")
|
||||
log.Fatalln("no $BOT_TOKEN given")
|
||||
}
|
||||
|
||||
s, err := session.New("Bot " + token)
|
||||
if err != nil {
|
||||
log.Fatalln("Session failed:", err)
|
||||
log.Fatalln("session failed:", err)
|
||||
return
|
||||
}
|
||||
|
||||
app, err := s.CurrentApplication()
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to get application ID:", err)
|
||||
log.Fatalln("failed to get application ID:", err)
|
||||
}
|
||||
appID := app.ID
|
||||
|
||||
s.AddHandler(func(e *gateway.InteractionCreateEvent) {
|
||||
if e.Type == discord.CommandInteraction {
|
||||
var resp api.InteractionResponse
|
||||
|
||||
switch data := e.Data.(type) {
|
||||
case discord.CommandInteraction:
|
||||
if data.Name != "buttons" {
|
||||
resp = api.InteractionResponse{
|
||||
Type: api.MessageInteractionWithSource,
|
||||
Data: &api.InteractionResponseData{
|
||||
Content: option.NewNullableString("Unknown command: " + data.Name),
|
||||
},
|
||||
}
|
||||
break
|
||||
}
|
||||
// Send a message with a button back on slash commands.
|
||||
data := api.InteractionResponse{
|
||||
resp = api.InteractionResponse{
|
||||
Type: api.MessageInteractionWithSource,
|
||||
Data: &api.InteractionResponseData{
|
||||
Content: option.NewNullableString("This is a message with a button!"),
|
||||
Components: &[]discord.Component{
|
||||
&discord.ActionRowComponent{
|
||||
Components: []discord.Component{
|
||||
&discord.ButtonComponent{
|
||||
Label: "Hello World!",
|
||||
CustomID: "first_button",
|
||||
Emoji: &discord.ButtonEmoji{
|
||||
Name: "👋",
|
||||
},
|
||||
Style: discord.PrimaryButton,
|
||||
},
|
||||
&discord.ButtonComponent{
|
||||
Label: "Secondary",
|
||||
CustomID: "second_button",
|
||||
Style: discord.SecondaryButton,
|
||||
},
|
||||
&discord.ButtonComponent{
|
||||
Label: "Success",
|
||||
CustomID: "success_button",
|
||||
Style: discord.SuccessButton,
|
||||
},
|
||||
&discord.ButtonComponent{
|
||||
Label: "Danger",
|
||||
CustomID: "danger_button",
|
||||
Style: discord.DangerButton,
|
||||
},
|
||||
&discord.ButtonComponent{
|
||||
Label: "Link",
|
||||
URL: "https://google.com",
|
||||
Style: discord.LinkButton,
|
||||
},
|
||||
Components: discord.ComponentsPtr(
|
||||
discord.ActionRowComponent{
|
||||
discord.ButtonComponent{
|
||||
Label: "Hello World!",
|
||||
CustomID: "first_button",
|
||||
Emoji: &discord.ComponentEmoji{Name: "👋"},
|
||||
Style: discord.PrimaryButtonStyle(),
|
||||
},
|
||||
discord.ButtonComponent{
|
||||
Label: "Secondary",
|
||||
CustomID: "second_button",
|
||||
Style: discord.SecondaryButtonStyle(),
|
||||
},
|
||||
discord.ButtonComponent{
|
||||
Label: "Success",
|
||||
CustomID: "success_button",
|
||||
Style: discord.SuccessButtonStyle(),
|
||||
},
|
||||
discord.ButtonComponent{
|
||||
Label: "Danger",
|
||||
CustomID: "danger_button",
|
||||
Style: discord.DangerButtonStyle(),
|
||||
},
|
||||
},
|
||||
},
|
||||
// This is automatically put into its own row.
|
||||
discord.ButtonComponent{
|
||||
Label: "Link",
|
||||
Style: discord.LinkButtonStyle("https://google.com"),
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
if err := s.RespondInteraction(e.ID, e.Token, data); err != nil {
|
||||
log.Println("failed to send interaction callback:", err)
|
||||
case discord.ComponentInteraction:
|
||||
resp = api.InteractionResponse{
|
||||
Type: api.UpdateMessage,
|
||||
Data: &api.InteractionResponseData{
|
||||
Content: option.NewNullableString("Custom ID: " + string(data.ID())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if e.Type != discord.ComponentInteraction {
|
||||
default:
|
||||
log.Printf("unknown interaction type %T", e.Data)
|
||||
return
|
||||
}
|
||||
customID := e.Data.(*discord.ComponentInteractionData).CustomID
|
||||
data := api.InteractionResponse{
|
||||
Type: api.UpdateMessage,
|
||||
Data: &api.InteractionResponseData{
|
||||
Content: option.NewNullableString("Custom ID: " + customID),
|
||||
},
|
||||
}
|
||||
|
||||
if err := s.RespondInteraction(e.ID, e.Token, data); err != nil {
|
||||
if err := s.RespondInteraction(e.ID, e.Token, resp); err != nil {
|
||||
log.Println("failed to send interaction callback:", err)
|
||||
}
|
||||
})
|
||||
|
@ -125,6 +128,8 @@ func main() {
|
|||
},
|
||||
}
|
||||
|
||||
log.Println("Creating guild commands...")
|
||||
|
||||
for _, command := range newCommands {
|
||||
_, err := s.CreateGuildCommand(appID, guildID, command)
|
||||
if err != nil {
|
||||
|
@ -132,6 +137,8 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
log.Println("Guild commands created. Bot is ready.")
|
||||
|
||||
// Block forever.
|
||||
select {}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/session"
|
||||
"github.com/diamondburned/arikawa/v3/state"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
||||
)
|
||||
|
||||
|
@ -22,7 +22,7 @@ func main() {
|
|||
log.Fatalln("No $BOT_TOKEN given.")
|
||||
}
|
||||
|
||||
s, err := session.New("Bot " + token)
|
||||
s, err := state.New("Bot " + token)
|
||||
if err != nil {
|
||||
log.Fatalln("Session failed:", err)
|
||||
return
|
||||
|
@ -32,7 +32,6 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatalln("Failed to get application ID:", err)
|
||||
}
|
||||
appID := app.ID
|
||||
|
||||
s.AddHandler(func(e *gateway.InteractionCreateEvent) {
|
||||
data := api.InteractionResponse{
|
||||
|
@ -57,7 +56,7 @@ func main() {
|
|||
|
||||
log.Println("Gateway connected. Getting all guild commands.")
|
||||
|
||||
commands, err := s.GuildCommands(appID, guildID)
|
||||
commands, err := s.GuildCommands(app.ID, guildID)
|
||||
if err != nil {
|
||||
log.Fatalln("failed to get guild commands:", err)
|
||||
}
|
||||
|
@ -74,7 +73,7 @@ func main() {
|
|||
}
|
||||
|
||||
for _, command := range newCommands {
|
||||
_, err := s.CreateGuildCommand(appID, guildID, command)
|
||||
_, err := s.CreateGuildCommand(app.ID, guildID, command)
|
||||
if err != nil {
|
||||
log.Fatalln("failed to create guild command:", err)
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ func (c *Client) CurrentApplication() (*discord.Application, error) {
|
|||
|
||||
// https://discord.com/developers/docs/interactions/slash-commands#create-global-application-command-json-params
|
||||
type CreateCommandData struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Options []discord.CommandOption `json:"options,omitempty"`
|
||||
NoDefaultPermission bool `json:"-"`
|
||||
Type discord.CommandType `json:"type,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Options discord.CommandOptions `json:"options,omitempty"`
|
||||
NoDefaultPermission bool `json:"-"`
|
||||
Type discord.CommandType `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
func (c CreateCommandData) MarshalJSON() ([]byte, error) {
|
||||
|
|
|
@ -63,7 +63,7 @@ type InteractionResponseData struct {
|
|||
Embeds *[]discord.Embed `json:"embeds,omitempty"`
|
||||
// Components is the list of components (such as buttons) to be attached to
|
||||
// the message.
|
||||
Components *[]discord.Component `json:"components,omitempty"`
|
||||
Components *discord.ContainerComponents `json:"components,omitempty"`
|
||||
// AllowedMentions are the allowed mentions for the message.
|
||||
AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
// Flags are the interaction application command callback data flags.
|
||||
|
@ -149,7 +149,7 @@ type EditInteractionResponseData struct {
|
|||
// Embeds contains embedded rich content.
|
||||
Embeds *[]discord.Embed `json:"embeds,omitempty"`
|
||||
// Components contains the new components to attach.
|
||||
Components *[]discord.Component `json:"components,omitempty"`
|
||||
Components *discord.ContainerComponents `json:"components,omitempty"`
|
||||
// AllowedMentions are the allowed mentions for the message.
|
||||
AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
// Attachments are the attached files to keep.
|
||||
|
|
|
@ -287,7 +287,7 @@ type EditMessageData struct {
|
|||
// Embeds contains embedded rich content.
|
||||
Embeds *[]discord.Embed `json:"embeds,omitempty"`
|
||||
// Components contains the new components to attach.
|
||||
Components *[]discord.Component `json:"components,omitempty"`
|
||||
Components *discord.ContainerComponents `json:"components,omitempty"`
|
||||
// AllowedMentions are the allowed mentions for a message.
|
||||
AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
// Attachments are the attached files to keep
|
||||
|
|
|
@ -108,7 +108,7 @@ type SendMessageData struct {
|
|||
Files []sendpart.File `json:"-"`
|
||||
// Components is the list of components (such as buttons) to be attached to
|
||||
// the message.
|
||||
Components []discord.Component `json:"components,omitempty"`
|
||||
Components discord.ContainerComponents `json:"components,omitempty"`
|
||||
|
||||
// AllowedMentions are the allowed mentions for a message.
|
||||
AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
|
|
|
@ -147,7 +147,7 @@ type ExecuteData struct {
|
|||
|
||||
// Components is the list of components (such as buttons) to be attached to
|
||||
// the message.
|
||||
Components []discord.Component `json:"components,omitempty"`
|
||||
Components discord.ContainerComponents `json:"components,omitempty"`
|
||||
|
||||
// Files represents a list of files to upload. This will not be
|
||||
// JSON-encoded and will only be available through WriteMultipart.
|
||||
|
@ -238,7 +238,7 @@ type EditMessageData struct {
|
|||
// Embeds contains embedded rich content.
|
||||
Embeds *[]discord.Embed `json:"embeds,omitempty"`
|
||||
// Components contains the new components to attach.
|
||||
Components *[]discord.Component `json:"components,omitempty"`
|
||||
Components *discord.ContainerComponents `json:"components,omitempty"`
|
||||
// AllowedMentions are the allowed mentions for a message.
|
||||
AllowedMentions *api.AllowedMentions `json:"allowed_mentions,omitempty"`
|
||||
// Attachments are the attached files to keep
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
)
|
||||
|
||||
type Application struct {
|
||||
// ID is the ID of the app.
|
||||
ID AppID `json:"id"`
|
||||
// Name is the name of the app.
|
||||
Name string `json:"string"`
|
||||
Name string `json:"name"`
|
||||
// Icon is the icon hash of the app.
|
||||
Icon *Hash `json:"icon"`
|
||||
// Description is the description of the app.
|
||||
Description string `json:"string"`
|
||||
Description string `json:"description"`
|
||||
// RPCOrigins is the RPC origin urls, if RPC is enabled.
|
||||
RPCOrigins []string `json:"rpc_origins"`
|
||||
// BotPublic is whether users besides the app owner can join the app's bot
|
||||
|
@ -54,6 +48,7 @@ type Application struct {
|
|||
// Slug is the URL slug that links to the game's store page.
|
||||
Slug string `json:"slug"`
|
||||
}
|
||||
|
||||
type ApplicationFlags uint32
|
||||
|
||||
const (
|
||||
|
@ -96,158 +91,6 @@ const (
|
|||
MembershipAccepted
|
||||
)
|
||||
|
||||
// Command is the base "command" model that belongs to an application. This is
|
||||
// what you are creating when you POST a new command.
|
||||
//
|
||||
// https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-structure
|
||||
type Command struct {
|
||||
// ID is the unique id of the command.
|
||||
ID CommandID `json:"id"`
|
||||
// Type is the type of command.
|
||||
Type CommandType `json:"type,omitempty"`
|
||||
// AppID is the unique id of the parent application.
|
||||
AppID AppID `json:"application_id"`
|
||||
// GuildID is the guild id of the command, if not global.
|
||||
GuildID GuildID `json:"guild_id,omitempty"`
|
||||
// Name is the 1-32 lowercase character name matching ^[\w-]{1,32}$.
|
||||
Name string `json:"name"`
|
||||
// Description is the 1-100 character description.
|
||||
Description string `json:"description"`
|
||||
// Options are the parameters for the command.
|
||||
//
|
||||
// Note that required options must be listed before optional options, and
|
||||
// a command, or each individual subcommand, can have a maximum of 25
|
||||
// options.
|
||||
//
|
||||
// It is only present on ChatInputCommands.
|
||||
Options []CommandOption `json:"options,omitempty"`
|
||||
// NoDefaultPermissions defines whether the command is NOT enabled by
|
||||
// default when the app is added to a guild.
|
||||
NoDefaultPermission bool `json:"-"`
|
||||
// Version is an autoincrementing version identifier updated during
|
||||
// substantial record changes
|
||||
Version Snowflake `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
type CommandType uint
|
||||
|
||||
const (
|
||||
ChatInputCommand CommandType = iota + 1
|
||||
UserCommand
|
||||
MessageCommand
|
||||
)
|
||||
|
||||
func (c Command) MarshalJSON() ([]byte, error) {
|
||||
type RawCommand Command
|
||||
cmd := struct {
|
||||
RawCommand
|
||||
DefaultPermission bool `json:"default_permission"`
|
||||
}{RawCommand: RawCommand(c)}
|
||||
|
||||
// Discord defaults default_permission to true, so we need to invert the
|
||||
// meaning of the field (>No<DefaultPermission) to match Go's default
|
||||
// value, false.
|
||||
cmd.DefaultPermission = !c.NoDefaultPermission
|
||||
|
||||
return json.Marshal(cmd)
|
||||
}
|
||||
|
||||
func (c *Command) UnmarshalJSON(data []byte) error {
|
||||
type RawCommand Command
|
||||
cmd := struct {
|
||||
*RawCommand
|
||||
DefaultPermission bool `json:"default_permission"`
|
||||
}{RawCommand: (*RawCommand)(c)}
|
||||
if err := json.Unmarshal(data, &cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Discord defaults default_permission to true, so we need to invert the
|
||||
// meaning of the field (>No<DefaultPermission) to match Go's default
|
||||
// value, false.
|
||||
c.NoDefaultPermission = !cmd.DefaultPermission
|
||||
|
||||
// Discord defaults type to 1 if omitted.
|
||||
if c.Type == 0 {
|
||||
c.Type = ChatInputCommand
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreatedAt returns a time object representing when the command was created.
|
||||
func (c Command) CreatedAt() time.Time {
|
||||
return c.ID.Time()
|
||||
}
|
||||
|
||||
type CommandOption struct {
|
||||
Type CommandOptionType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []CommandOptionChoice `json:"choices,omitempty"`
|
||||
Options []CommandOption `json:"options,omitempty"`
|
||||
|
||||
// If this option is a channel type, the channels shown will be restricted to these types
|
||||
ChannelTypes []ChannelType `json:"-"`
|
||||
}
|
||||
|
||||
func (c CommandOption) MarshalJSON() ([]byte, error) {
|
||||
type RawOption CommandOption
|
||||
option := struct {
|
||||
RawOption
|
||||
ChannelTypes []uint16 `json:"channel_types,omitempty"`
|
||||
}{RawOption: RawOption(c)}
|
||||
|
||||
// []uint8 is marshalled as a base64 string, so we marshal a []uint64 instead.
|
||||
if len(c.ChannelTypes) > 0 {
|
||||
option.ChannelTypes = make([]uint16, 0, len(c.ChannelTypes))
|
||||
for _, t := range c.ChannelTypes {
|
||||
option.ChannelTypes = append(option.ChannelTypes, uint16(t))
|
||||
}
|
||||
}
|
||||
|
||||
return json.Marshal(option)
|
||||
}
|
||||
|
||||
func (c *CommandOption) UnmarshalJSON(data []byte) error {
|
||||
type RawOption CommandOption
|
||||
cmd := struct {
|
||||
*RawOption
|
||||
ChannelTypes []uint16 `json:"channel_types,omitempty"`
|
||||
}{RawOption: (*RawOption)(c)}
|
||||
if err := json.Unmarshal(data, &cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.ChannelTypes = make([]ChannelType, 0, len(cmd.ChannelTypes))
|
||||
for _, t := range cmd.ChannelTypes {
|
||||
c.ChannelTypes = append(c.ChannelTypes, ChannelType(t))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CommandOptionType uint
|
||||
|
||||
const (
|
||||
SubcommandOption CommandOptionType = iota + 1
|
||||
SubcommandGroupOption
|
||||
StringOption
|
||||
IntegerOption
|
||||
BooleanOption
|
||||
UserOption
|
||||
ChannelOption
|
||||
RoleOption
|
||||
MentionableOption
|
||||
NumberOption
|
||||
)
|
||||
|
||||
type CommandOptionChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// https://discord.com/developers/docs/interactions/slash-commands#application-command-permissions-object-guild-application-command-permissions-structure
|
||||
type GuildCommandPermissions struct {
|
||||
ID CommandID `json:"id"`
|
||||
|
|
|
@ -144,9 +144,11 @@ func (ch Channel) IconURLWithType(t ImageType) string {
|
|||
ch.ID.String() + "/" + t.format(ch.Icon)
|
||||
}
|
||||
|
||||
type ChannelType uint8
|
||||
|
||||
// ChannelType describes the type of the channel.
|
||||
//
|
||||
// https://discord.com/developers/docs/resources/channel#channel-object-channel-types
|
||||
type ChannelType uint16
|
||||
|
||||
const (
|
||||
// GuildText is a text channel within a server.
|
||||
GuildText ChannelType = iota
|
||||
|
|
|
@ -0,0 +1,505 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// CommandType is the type of the command, which describes the intended
|
||||
// invokation source of the command.
|
||||
type CommandType uint
|
||||
|
||||
const (
|
||||
ChatInputCommand CommandType = iota + 1
|
||||
UserCommand
|
||||
MessageCommand
|
||||
)
|
||||
|
||||
// Command is the base "command" model that belongs to an application. This is
|
||||
// what you are creating when you POST a new command.
|
||||
//
|
||||
// https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-structure
|
||||
type Command struct {
|
||||
// ID is the unique id of the command.
|
||||
ID CommandID `json:"id"`
|
||||
// Type is the intended source of the command.
|
||||
Type CommandType `json:"type,omitempty"`
|
||||
// AppID is the unique id of the parent application.
|
||||
AppID AppID `json:"application_id"`
|
||||
// GuildID is the guild id of the command, if not global.
|
||||
GuildID GuildID `json:"guild_id,omitempty"`
|
||||
// Name is the 1-32 lowercase character name matching ^[\w-]{1,32}$.
|
||||
Name string `json:"name"`
|
||||
// Description is the 1-100 character description.
|
||||
Description string `json:"description"`
|
||||
// Options are the parameters for the command. Its types are value types,
|
||||
// which can either be a SubcommandOption or a SubcommandGroupOption.
|
||||
//
|
||||
// Note that required options must be listed before optional options, and
|
||||
// a command, or each individual subcommand, can have a maximum of 25
|
||||
// options.
|
||||
//
|
||||
// It is only present on ChatInputCommands.
|
||||
Options CommandOptions `json:"options,omitempty"`
|
||||
// NoDefaultPermissions defines whether the command is NOT enabled by
|
||||
// default when the app is added to a guild.
|
||||
NoDefaultPermission bool `json:"-"`
|
||||
// Version is an autoincrementing version identifier updated during
|
||||
// substantial record changes
|
||||
Version Snowflake `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// CreatedAt returns a time object representing when the command was created.
|
||||
func (c *Command) CreatedAt() time.Time {
|
||||
return c.ID.Time()
|
||||
}
|
||||
|
||||
func (c *Command) MarshalJSON() ([]byte, error) {
|
||||
type RawCommand Command
|
||||
cmd := struct {
|
||||
*RawCommand
|
||||
DefaultPermission bool `json:"default_permission"`
|
||||
}{RawCommand: (*RawCommand)(c)}
|
||||
|
||||
// Discord defaults default_permission to true, so we need to invert the
|
||||
// meaning of the field (>No<DefaultPermission) to match Go's default
|
||||
// value, false.
|
||||
cmd.DefaultPermission = !c.NoDefaultPermission
|
||||
|
||||
return json.Marshal(cmd)
|
||||
}
|
||||
|
||||
func (c *Command) UnmarshalJSON(data []byte) error {
|
||||
type rawCommand Command
|
||||
|
||||
cmd := struct {
|
||||
*rawCommand
|
||||
DefaultPermission bool `json:"default_permission"`
|
||||
}{
|
||||
rawCommand: (*rawCommand)(c),
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Discord defaults default_permission to true, so we need to invert the
|
||||
// meaning of the field (>No<DefaultPermission) to match Go's default
|
||||
// value, false.
|
||||
c.NoDefaultPermission = !cmd.DefaultPermission
|
||||
|
||||
// Discord defaults type to 1 if omitted.
|
||||
if c.Type == 0 {
|
||||
c.Type = ChatInputCommand
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// commandTypeCheckError is returned if a one of Command's Options fails the
|
||||
// type check.
|
||||
type commandTypeCheckError struct {
|
||||
name string
|
||||
got interface{}
|
||||
expect string
|
||||
}
|
||||
|
||||
// Name returns the name of the erroneous command.
|
||||
func (err commandTypeCheckError) Name() string {
|
||||
return err.name
|
||||
}
|
||||
|
||||
// Data returns the erroneous data that belongs to this error. It is usually
|
||||
// either a CommandOption or a CommandOptionValue.
|
||||
func (err commandTypeCheckError) Data() interface{} {
|
||||
return err.got
|
||||
}
|
||||
|
||||
// Error implements error.
|
||||
func (err commandTypeCheckError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"error at option name %q: expected %s, got %T",
|
||||
err.name, err.expect, err.got,
|
||||
)
|
||||
}
|
||||
|
||||
// CommandOptions is used primarily for unmarshaling.
|
||||
type CommandOptions []CommandOption
|
||||
|
||||
// UnmarshalJSON unmarshals b into these CommandOptions.
|
||||
func (c *CommandOptions) UnmarshalJSON(b []byte) error {
|
||||
var unknowns []UnknownCommandOption
|
||||
if err := json.Unmarshal(b, &unknowns); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(unknowns) == 0 {
|
||||
*c = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
*c = make([]CommandOption, len(unknowns))
|
||||
for i, v := range unknowns {
|
||||
(*c)[i] = v.data
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnknownCommandOption is used for unknown or unmarshaled CommandOption values.
|
||||
// It is used in the unmarshaling stage for all CommandOption types.
|
||||
//
|
||||
// An UnknownCommandOption will satisfy both CommandOption and
|
||||
// CommandOptionValue. Code that type-switches on either of them should not
|
||||
// assume that only the expected types are used.
|
||||
type UnknownCommandOption struct {
|
||||
OptionName string `json:"name"`
|
||||
OptionType CommandOptionType `json:"type"`
|
||||
|
||||
raw json.Raw
|
||||
data CommandOption
|
||||
}
|
||||
|
||||
// Name returns the supposeed name for this UnknownCommandOption.
|
||||
func (u *UnknownCommandOption) Name() string {
|
||||
return u.OptionName
|
||||
}
|
||||
|
||||
// Type returns the supposed type for this UnknownCommandOption.
|
||||
func (u *UnknownCommandOption) Type() CommandOptionType {
|
||||
return u.OptionType
|
||||
}
|
||||
|
||||
// Raw returns the raw JSON of this UnknownCommandOption. It will only return a
|
||||
// non-nil blob of JSON if the command option's type cannot be found. If this
|
||||
// method doesn't return nil, then Data's type will be UnknownCommandOption.
|
||||
func (u *UnknownCommandOption) Raw() json.Raw {
|
||||
return u.raw
|
||||
}
|
||||
|
||||
// Data returns the underlying data type, which is a type that satisfies either
|
||||
// CommandOption or CommandOptionValue.
|
||||
func (u *UnknownCommandOption) Data() CommandOption {
|
||||
return u.data
|
||||
}
|
||||
|
||||
// Implement both CommandOption and CommandOptionValue.
|
||||
func (u *UnknownCommandOption) _val() {}
|
||||
|
||||
// UnmarshalJSON parses the JSON into the struct as-is then reads all its
|
||||
// children Options/Choices (if subcommand(group)). Typed command options are
|
||||
// created into u.Data, or u.Raw if the type is unknown. This is done from the
|
||||
// bottom up.
|
||||
func (u *UnknownCommandOption) UnmarshalJSON(b []byte) error {
|
||||
type unknown UnknownCommandOption
|
||||
|
||||
if err := json.Unmarshal(b, (*unknown)(u)); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal unknown")
|
||||
}
|
||||
|
||||
switch u.Type() {
|
||||
case SubcommandOptionType:
|
||||
u.data = &SubcommandOption{}
|
||||
case SubcommandGroupOptionType:
|
||||
u.data = &SubcommandGroupOption{}
|
||||
case StringOptionType:
|
||||
u.data = &StringOption{}
|
||||
case IntegerOptionType:
|
||||
u.data = &IntegerOption{}
|
||||
case BooleanOptionType:
|
||||
u.data = &BooleanOption{}
|
||||
case UserOptionType:
|
||||
u.data = &UserOption{}
|
||||
case ChannelOptionType:
|
||||
u.data = &ChannelOption{}
|
||||
case RoleOptionType:
|
||||
u.data = &RoleOption{}
|
||||
case MentionableOptionType:
|
||||
u.data = &MentionableOption{}
|
||||
case NumberOptionType:
|
||||
u.data = &NumberOption{}
|
||||
default:
|
||||
// Copy the blob of bytes into a new slice.
|
||||
u.raw = append(json.Raw(nil), b...)
|
||||
u.data = u
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, u.data); err != nil {
|
||||
return errors.Wrapf(err, "failed to unmarshal type %d", u.Type())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommandOptionType is the enumerated integer type for command options. The
|
||||
// user usually won't have to touch any of these enum constants.
|
||||
type CommandOptionType uint
|
||||
|
||||
const (
|
||||
SubcommandOptionType CommandOptionType = iota + 1
|
||||
SubcommandGroupOptionType
|
||||
StringOptionType
|
||||
IntegerOptionType
|
||||
BooleanOptionType
|
||||
UserOptionType
|
||||
ChannelOptionType
|
||||
RoleOptionType
|
||||
MentionableOptionType
|
||||
NumberOptionType
|
||||
maxOptionType // for bound checking
|
||||
)
|
||||
|
||||
// CommandOption is a union of command option types. The constructors for
|
||||
// CommandOption will hint the types that can be a CommandOption.
|
||||
type CommandOption interface {
|
||||
Name() string
|
||||
Type() CommandOptionType
|
||||
}
|
||||
|
||||
// Maintaining these structs is quite an effort. If a new field is added into
|
||||
// the generic CommandOption type, you MUST update ALL CommandOption structs.
|
||||
// This means copy-pasting, yes.
|
||||
|
||||
// SubcommandGroupOption is a subcommand group that fits into a CommandOption.
|
||||
type SubcommandGroupOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Subcommands []*SubcommandOption `json:"options"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (s *SubcommandGroupOption) Name() string { return s.OptionName }
|
||||
|
||||
// Type implements CommandOption.
|
||||
func (s *SubcommandGroupOption) Type() CommandOptionType { return SubcommandGroupOptionType }
|
||||
|
||||
// SubcommandOption is a subcommand option that fits into a CommandOption.
|
||||
type SubcommandOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
// Options contains command option values. All CommandOption types except
|
||||
// for SubcommandOption and SubcommandGroupOption will implement this
|
||||
// interface.
|
||||
Options []CommandOptionValue `json:"options"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (s *SubcommandOption) Name() string { return s.OptionName }
|
||||
|
||||
// Type implements CommandOption.
|
||||
func (s *SubcommandOption) Type() CommandOptionType { return SubcommandOptionType }
|
||||
|
||||
// UnmarshalJSON unmarshals the given JSON bytes. It actually does
|
||||
// type-checking.
|
||||
func (s *SubcommandOption) UnmarshalJSON(b []byte) error {
|
||||
type raw SubcommandOption
|
||||
|
||||
var opt struct {
|
||||
*raw
|
||||
Type CommandOptionType `json:"type"`
|
||||
Options []UnknownCommandOption `json:"options"`
|
||||
}
|
||||
|
||||
opt.raw = (*raw)(s)
|
||||
|
||||
if err := json.Unmarshal(b, &opt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opt.Type != SubcommandOptionType {
|
||||
return fmt.Errorf("unexpected (not SubcommandOption) type %d", s.Type())
|
||||
}
|
||||
|
||||
s.Options = make([]CommandOptionValue, len(opt.Options))
|
||||
for i, opt := range opt.Options {
|
||||
ov, ok := opt.data.(CommandOptionValue)
|
||||
if !ok {
|
||||
return commandTypeCheckError{opt.OptionName, opt.data, "CommandOptionValue"}
|
||||
}
|
||||
s.Options[i] = ov
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommandOptionValue is a subcommand option that fits into a subcommand.
|
||||
type CommandOptionValue interface {
|
||||
CommandOption
|
||||
_val()
|
||||
}
|
||||
|
||||
// StringOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type StringOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []StringChoice `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (s *StringOption) Name() string { return s.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (s *StringOption) Type() CommandOptionType { return StringOptionType }
|
||||
func (s *StringOption) _val() {}
|
||||
|
||||
// StringChoice is a pair of string key to a string.
|
||||
type StringChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// IntegerOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type IntegerOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []IntegerChoice `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (i *IntegerOption) Name() string { return i.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (i *IntegerOption) Type() CommandOptionType { return IntegerOptionType }
|
||||
func (i *IntegerOption) _val() {}
|
||||
|
||||
// IntegerChoice is a pair of string key to an integer.
|
||||
type IntegerChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value int `json:"value"`
|
||||
}
|
||||
|
||||
// BooleanOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type BooleanOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []BooleanChoice `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (b *BooleanOption) Name() string { return b.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (b *BooleanOption) Type() CommandOptionType { return BooleanOptionType }
|
||||
func (b *BooleanOption) _val() {}
|
||||
|
||||
// BooleanChoice is a pair of string key to a boolean.
|
||||
type BooleanChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value bool `json:"value"`
|
||||
}
|
||||
|
||||
// UserOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type UserOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []UserChoice `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (u *UserOption) Name() string { return u.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (u *UserOption) Type() CommandOptionType { return UserOptionType }
|
||||
func (u *UserOption) _val() {}
|
||||
|
||||
// UserChoice is a pair of string key to a user ID.
|
||||
type UserChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value UserID `json:"value,string"`
|
||||
}
|
||||
|
||||
// ChannelOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type ChannelOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []ChannelChoice `json:"choices,omitempty"`
|
||||
ChannelTypes []ChannelType `json:"channel_types,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (c *ChannelOption) Name() string { return c.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (c *ChannelOption) Type() CommandOptionType { return ChannelOptionType }
|
||||
func (c *ChannelOption) _val() {}
|
||||
|
||||
// ChannelChoice is a pair of string key to a channel ID.
|
||||
type ChannelChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value ChannelID `json:"value,string"`
|
||||
}
|
||||
|
||||
// RoleOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type RoleOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []RoleChoice `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (r *RoleOption) Name() string { return r.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (r *RoleOption) Type() CommandOptionType { return RoleOptionType }
|
||||
func (r *RoleOption) _val() {}
|
||||
|
||||
// RoleChoice is a pair of string key to a role ID.
|
||||
type RoleChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value RoleID `json:"value,string"`
|
||||
}
|
||||
|
||||
// MentionableOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type MentionableOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []MentionableChoice `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (m *MentionableOption) Name() string { return m.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (m *MentionableOption) Type() CommandOptionType { return MentionableOptionType }
|
||||
func (m *MentionableOption) _val() {}
|
||||
|
||||
// MentionableChoice is a pair of string key to a mentionable snowflake IDs. To
|
||||
// use this correctly, use the Resolved field.
|
||||
type MentionableChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value Snowflake `json:"value,string"`
|
||||
}
|
||||
|
||||
// NumberOption is a subcommand option that fits into a CommandOptionValue.
|
||||
type NumberOption struct {
|
||||
OptionName string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Choices []NumberChoice `json:"choices,omitempty"`
|
||||
}
|
||||
|
||||
// Name implements CommandOption.
|
||||
func (n *NumberOption) Name() string { return n.OptionName }
|
||||
|
||||
// Type implements CommandOptionValue.
|
||||
func (n *NumberOption) Type() CommandOptionType { return NumberOptionType }
|
||||
func (n *NumberOption) _val() {}
|
||||
|
||||
// NumberChoice is a pair of string key to a float64 values.
|
||||
type NumberChoice struct {
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
}
|
|
@ -1,246 +1,455 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var ErrNestedActionRow = errors.New("action row cannot have action row as a child")
|
||||
|
||||
// ComponentType is the type of a component.
|
||||
type ComponentType uint
|
||||
|
||||
const (
|
||||
ActionRowComponentType ComponentType = iota + 1
|
||||
_ ComponentType = iota
|
||||
ActionRowComponentType
|
||||
ButtonComponentType
|
||||
SelectComponentType
|
||||
)
|
||||
|
||||
// ComponentWrap wraps Component for the purpose of JSON unmarshalling.
|
||||
// Type assertions should be made on Component to access the underlying data.
|
||||
// The underlying types of the Component are pointer types.
|
||||
type ComponentWrap struct {
|
||||
Component Component
|
||||
}
|
||||
|
||||
// UnwrapComponents returns a slice of the underlying component interfaces.
|
||||
func UnwrapComponents(wraps []ComponentWrap) []Component {
|
||||
components := make([]Component, len(wraps))
|
||||
for i, w := range wraps {
|
||||
components[i] = w.Component
|
||||
}
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
// Type returns the underlying component's type.
|
||||
func (c *ComponentWrap) Type() ComponentType {
|
||||
return c.Component.Type()
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the component in the format Discord expects.
|
||||
func (c *ComponentWrap) MarshalJSON() ([]byte, error) {
|
||||
return c.Component.MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals json into the component.
|
||||
func (c *ComponentWrap) UnmarshalJSON(b []byte) error {
|
||||
var t struct {
|
||||
Type ComponentType `json:"type"`
|
||||
}
|
||||
|
||||
err := json.Unmarshal(b, &t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch t.Type {
|
||||
// String formats Type's name as a string.
|
||||
func (t ComponentType) String() string {
|
||||
switch t {
|
||||
case ActionRowComponentType:
|
||||
c.Component = &ActionRowComponent{}
|
||||
return "ActionRow"
|
||||
case ButtonComponentType:
|
||||
c.Component = &ButtonComponent{}
|
||||
return "Button"
|
||||
case SelectComponentType:
|
||||
return "Select"
|
||||
default:
|
||||
c.Component = &UnknownComponent{typ: t.Type}
|
||||
return fmt.Sprintf("ComponentType(%d)", int(t))
|
||||
}
|
||||
|
||||
return json.Unmarshal(b, c.Component)
|
||||
}
|
||||
|
||||
// Component is a component that can be attached to an interaction response.
|
||||
type Component interface {
|
||||
json.Marshaler
|
||||
Type() ComponentType
|
||||
}
|
||||
// ContainerComponents is primarily used for unmarshaling. It is the top-level
|
||||
// type for component lists.
|
||||
type ContainerComponents []ContainerComponent
|
||||
|
||||
// ActionRowComponent is a row of components at the bottom of a message.
|
||||
type ActionRowComponent struct {
|
||||
Components []Component `json:"components"`
|
||||
}
|
||||
|
||||
// Type implements the Component interface.
|
||||
func (*ActionRowComponent) Type() ComponentType {
|
||||
return ActionRowComponentType
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the action row in the format Discord expects.
|
||||
func (a ActionRowComponent) MarshalJSON() ([]byte, error) {
|
||||
type actionRow ActionRowComponent
|
||||
|
||||
return json.Marshal(struct {
|
||||
actionRow
|
||||
Type ComponentType `json:"type"`
|
||||
}{
|
||||
actionRow: actionRow(a),
|
||||
Type: ActionRowComponentType,
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals json into the components.
|
||||
func (a *ActionRowComponent) UnmarshalJSON(b []byte) error {
|
||||
type actionRow ActionRowComponent
|
||||
|
||||
type rowTypes struct {
|
||||
Components []struct {
|
||||
Type ComponentType `json:"type"`
|
||||
} `json:"components"`
|
||||
}
|
||||
|
||||
var r rowTypes
|
||||
err := json.Unmarshal(b, &r)
|
||||
if err != nil {
|
||||
// UnmarshalJSON unmarshals JSON into the component. It does type-checking and
|
||||
// will only accept container components.
|
||||
func (c *ContainerComponents) UnmarshalJSON(b []byte) error {
|
||||
var jsons []json.Raw
|
||||
if err := json.Unmarshal(b, &jsons); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Components = make([]Component, len(r.Components))
|
||||
for i, t := range r.Components {
|
||||
switch t.Type {
|
||||
case ActionRowComponentType:
|
||||
// ActionRow cannot have child components of type Actionrow
|
||||
return ErrNestedActionRow
|
||||
case ButtonComponentType:
|
||||
a.Components[i] = &ButtonComponent{}
|
||||
default:
|
||||
a.Components[i] = &UnknownComponent{typ: t.Type}
|
||||
*c = make([]ContainerComponent, len(jsons))
|
||||
|
||||
for i, b := range jsons {
|
||||
p, err := ParseComponent(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
alias := actionRow(*a)
|
||||
err = json.Unmarshal(b, &alias)
|
||||
if err != nil {
|
||||
return err
|
||||
cc, ok := p.(ContainerComponent)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected container, got %T", p)
|
||||
}
|
||||
(*c)[i] = cc
|
||||
}
|
||||
|
||||
*a = ActionRowComponent(alias)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ButtonComponent is a clickable button that may be added to an interaction
|
||||
// response.
|
||||
type ButtonComponent struct {
|
||||
Label string `json:"label"`
|
||||
// CustomID attached to InteractionCreate event when clicked.
|
||||
CustomID string `json:"custom_id"`
|
||||
Style ButtonStyle `json:"style"`
|
||||
Emoji *ButtonEmoji `json:"emoji,omitempty"`
|
||||
// URL is only present on link-style buttons.
|
||||
URL URL `json:"url,omitempty"`
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
// Component is a component that can be attached to an interaction response. A
|
||||
// Component is either an InteractiveComponent or a ContainerComponent. See
|
||||
// those appropriate types for more information.
|
||||
type Component interface {
|
||||
// Type returns the type of the underlying component.
|
||||
Type() ComponentType
|
||||
_cmp()
|
||||
}
|
||||
|
||||
// InteractiveComponent extends the Component for components that are
|
||||
// interactible, or components that aren't containers (like ActionRow). This is
|
||||
// useful for ActionRow to type-check that no nested ActionRows are allowed.
|
||||
type InteractiveComponent interface {
|
||||
Component
|
||||
// ID returns the ID of the underlying component.
|
||||
ID() ComponentID
|
||||
_icp()
|
||||
}
|
||||
|
||||
// ContainerComponent is the opposite of InteractiveComponent: it describes
|
||||
// components that only contain other components. The only component that
|
||||
// satisfies that is ActionRow.
|
||||
type ContainerComponent interface {
|
||||
Component
|
||||
_ctn()
|
||||
}
|
||||
|
||||
// NewComponent returns a new Component from the given type that's matched with
|
||||
// the global ComponentFunc map. If the type is unknown, then Unknown is used.
|
||||
func ParseComponent(b []byte) (Component, error) {
|
||||
var t struct {
|
||||
Type ComponentType
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component type")
|
||||
}
|
||||
|
||||
var c Component
|
||||
|
||||
switch t.Type {
|
||||
case ActionRowComponentType:
|
||||
c = &ActionRowComponent{}
|
||||
case ButtonComponentType:
|
||||
c = &ButtonComponent{}
|
||||
case SelectComponentType:
|
||||
c = &SelectComponent{}
|
||||
default:
|
||||
c = &UnknownComponent{typ: t.Type}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, c); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component body")
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// ActionRow is a row of components at the bottom of a message. Its type,
|
||||
// InteractiveComponent, ensures that only non-ActionRow components are allowed
|
||||
// on it.
|
||||
type ActionRowComponent []InteractiveComponent
|
||||
|
||||
// Components wraps the given list of components inside ActionRows if it's not
|
||||
// already in one. This is a convenient function that wraps components inside
|
||||
// ActionRows for the user. It panics if any of the action rows have nested
|
||||
// action rows in them.
|
||||
//
|
||||
// Here's an example of how to use it:
|
||||
//
|
||||
// discord.Components(
|
||||
// discord.TextButtonComponent("Hello, world!"),
|
||||
// discord.Components(
|
||||
// discord.TextButtonComponent("Hello!"),
|
||||
// discord.TextButtonComponent("Delete."),
|
||||
// ),
|
||||
// )
|
||||
//
|
||||
func Components(components ...Component) ContainerComponents {
|
||||
new := make([]ContainerComponent, len(components))
|
||||
|
||||
for i, comp := range components {
|
||||
cc, ok := comp.(ContainerComponent)
|
||||
if !ok {
|
||||
// Wrap. We're asserting that comp is either a ContainerComponent or
|
||||
// an InteractiveComponent. Neither would be a bug, therefore panic.
|
||||
cc = &ActionRowComponent{comp.(InteractiveComponent)}
|
||||
}
|
||||
|
||||
new[i] = cc
|
||||
}
|
||||
|
||||
return new
|
||||
}
|
||||
|
||||
// ComponentsPtr returns the pointer to Components' return. This is a
|
||||
// convenient function.
|
||||
func ComponentsPtr(components ...Component) *ContainerComponents {
|
||||
v := Components(components...)
|
||||
return &v
|
||||
}
|
||||
|
||||
// Type implements the Component interface.
|
||||
func (*ButtonComponent) Type() ComponentType {
|
||||
return ButtonComponentType
|
||||
func (a *ActionRowComponent) Type() ComponentType {
|
||||
return ActionRowComponentType
|
||||
}
|
||||
|
||||
// ButtonStyle is the style to display a button in.
|
||||
type ButtonStyle uint
|
||||
func (a *ActionRowComponent) _cmp() {}
|
||||
func (a *ActionRowComponent) _ctn() {}
|
||||
|
||||
// All types of ButtonStyle documented.
|
||||
const (
|
||||
// PrimaryButton is a blurple button.
|
||||
PrimaryButton ButtonStyle = iota + 1
|
||||
// SecondaryButton is a grey button.
|
||||
SecondaryButton
|
||||
// SuccessButton is a green button.
|
||||
SuccessButton
|
||||
// DangerButton is a red button.
|
||||
DangerButton
|
||||
// LinkButton is a button that navigates to a URL.
|
||||
LinkButton
|
||||
)
|
||||
// MarshalJSON marshals the action row in the format Discord expects.
|
||||
func (a *ActionRowComponent) MarshalJSON() ([]byte, error) {
|
||||
var actionRow struct {
|
||||
Type ComponentType `json:"type"`
|
||||
Components *[]InteractiveComponent `json:"components"`
|
||||
}
|
||||
|
||||
// ButtonEmoji is the emoji displayed on the button before the text.
|
||||
type ButtonEmoji struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
actionRow.Components = (*[]InteractiveComponent)(a)
|
||||
actionRow.Type = a.Type()
|
||||
|
||||
return json.Marshal(actionRow)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals JSON into the components. It does type-checking and
|
||||
// will only accept interactive components.
|
||||
func (a *ActionRowComponent) UnmarshalJSON(b []byte) error {
|
||||
var row struct {
|
||||
Components []json.Raw `json:"components"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, &row); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*a = make(ActionRowComponent, len(row.Components))
|
||||
|
||||
for i, b := range row.Components {
|
||||
p, err := ParseComponent(b)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse component %d", i)
|
||||
}
|
||||
|
||||
ic, ok := p.(InteractiveComponent)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected interactive, got %T", p)
|
||||
}
|
||||
(*a)[i] = ic
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ComponentID is the type for a component's custom ID. It is NOT a snowflake,
|
||||
// but rather a user-defined opaque string.
|
||||
type ComponentID string
|
||||
|
||||
// ComponentEmoji is the emoji displayed on the button before the text. For more
|
||||
// information, see Emoji.
|
||||
type ComponentEmoji struct {
|
||||
ID EmojiID `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Animated bool `json:"animated,omitempty"`
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the button in the format Discord expects.
|
||||
func (b ButtonComponent) MarshalJSON() ([]byte, error) {
|
||||
type button ButtonComponent
|
||||
|
||||
if b.Style == 0 {
|
||||
b.Style = PrimaryButton // Sane default for button.
|
||||
}
|
||||
|
||||
return json.Marshal(struct {
|
||||
button
|
||||
Type ComponentType `json:"type"`
|
||||
}{
|
||||
button: button(b),
|
||||
Type: ButtonComponentType,
|
||||
})
|
||||
// ButtonComponentStyle is the style to display a button in. Use one of the
|
||||
// ButtonStyle constructor functions.
|
||||
type ButtonComponentStyle interface {
|
||||
style() int
|
||||
}
|
||||
|
||||
// SelectComponent is a clickable button that may be added to an interaction
|
||||
type basicButtonStyle int
|
||||
|
||||
func (s basicButtonStyle) style() int { return int(s) }
|
||||
|
||||
const (
|
||||
_ basicButtonStyle = iota
|
||||
primaryButtonStyle
|
||||
secondaryButtonStyle
|
||||
successButtonStyle
|
||||
dangerButtonStyle
|
||||
linkButtonStyleNum
|
||||
basicButtonStyleLen
|
||||
)
|
||||
|
||||
// PrimaryButtonStyle is a style for a blurple button.
|
||||
func PrimaryButtonStyle() ButtonComponentStyle { return primaryButtonStyle }
|
||||
|
||||
// SecondaryButtonStyle is a style for a grey button.
|
||||
func SecondaryButtonStyle() ButtonComponentStyle { return secondaryButtonStyle }
|
||||
|
||||
// SuccessButtonStyle is a style for a green button.
|
||||
func SuccessButtonStyle() ButtonComponentStyle { return successButtonStyle }
|
||||
|
||||
// DangerButtonStyle is a style for a red button.
|
||||
func DangerButtonStyle() ButtonComponentStyle { return dangerButtonStyle }
|
||||
|
||||
type linkButtonStyle URL
|
||||
|
||||
func (s linkButtonStyle) style() int { return int(linkButtonStyleNum) }
|
||||
|
||||
// LinkButtonStyle is a button style that navigates to a URL.
|
||||
func LinkButtonStyle(url URL) ButtonComponentStyle { return linkButtonStyle(url) }
|
||||
|
||||
// Button is a clickable button that may be added to an interaction
|
||||
// response.
|
||||
type SelectComponent struct {
|
||||
CustomID string `json:"custom_id"`
|
||||
Options []SelectComponentOption `json:"options"`
|
||||
Placeholder string `json:"placeholder,omitempty"`
|
||||
MinValues option.Int `json:"min_values,omitempty"`
|
||||
MaxValues int `json:"max_values,omitempty"`
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
type ButtonComponent struct {
|
||||
// Style is one of the button styles.
|
||||
Style ButtonComponentStyle `json:"style"`
|
||||
// CustomID attached to InteractionCreate event when clicked.
|
||||
CustomID ComponentID `json:"custom_id,omitempty"`
|
||||
// Label is the text that appears on the button. It can have maximum 100
|
||||
// characters.
|
||||
Label string `json:"label,omitempty"`
|
||||
// Emoji should have Name, ID and Animated filled.
|
||||
Emoji *ComponentEmoji `json:"emoji,omitempty"`
|
||||
// Disabled determines whether the button is disabled.
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
}
|
||||
|
||||
type SelectComponentOption struct {
|
||||
Label string `json:"label"`
|
||||
Value string `json:"value"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Emoji *ButtonEmoji `json:"emoji,omitempty"`
|
||||
Default bool `json:"default,omitempty"`
|
||||
// TextButtonComponent creates a new button with the given label used for the label and
|
||||
// the custom ID.
|
||||
func TextButtonComponent(style ButtonComponentStyle, label string) ButtonComponent {
|
||||
return ButtonComponent{
|
||||
Style: style,
|
||||
Label: label,
|
||||
CustomID: ComponentID(label),
|
||||
}
|
||||
}
|
||||
|
||||
// ID implements the Component interface.
|
||||
func (b *ButtonComponent) ID() ComponentID { return b.CustomID }
|
||||
|
||||
// Type implements the Component interface.
|
||||
func (*SelectComponent) Type() ComponentType {
|
||||
func (b *ButtonComponent) Type() ComponentType {
|
||||
return ButtonComponentType
|
||||
}
|
||||
|
||||
func (b *ButtonComponent) _cmp() {}
|
||||
func (b *ButtonComponent) _icp() {}
|
||||
|
||||
// MarshalJSON marshals the button in the format Discord expects.
|
||||
func (b *ButtonComponent) MarshalJSON() ([]byte, error) {
|
||||
if b.Style == nil {
|
||||
b.Style = PrimaryButtonStyle() // Sane default for button.
|
||||
}
|
||||
|
||||
type button ButtonComponent
|
||||
|
||||
type Msg struct {
|
||||
*button
|
||||
Type ComponentType `json:"type"`
|
||||
Style int `json:"style"`
|
||||
URL URL `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
msg := Msg{
|
||||
Type: ButtonComponentType,
|
||||
Style: b.Style.style(),
|
||||
button: (*button)(b),
|
||||
}
|
||||
|
||||
if link, ok := b.Style.(linkButtonStyle); ok {
|
||||
msg.URL = URL(link)
|
||||
}
|
||||
|
||||
return json.Marshal(msg)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals a component JSON into the button. It does NOT do
|
||||
// type-checking; use ParseComponent for that.
|
||||
func (b *ButtonComponent) UnmarshalJSON(j []byte) error {
|
||||
type button ButtonComponent
|
||||
|
||||
msg := struct {
|
||||
*button
|
||||
Style basicButtonStyle `json:"style"`
|
||||
URL URL `json:"url,omitempty"`
|
||||
}{
|
||||
button: (*button)(b),
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(j, &msg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if 0 > msg.Style || msg.Style >= basicButtonStyleLen {
|
||||
return fmt.Errorf("unknown button style %d", msg.Style)
|
||||
}
|
||||
|
||||
switch msg.Style {
|
||||
case linkButtonStyleNum:
|
||||
b.Style = LinkButtonStyle(msg.URL)
|
||||
default:
|
||||
b.Style = msg.Style
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Select is a clickable button that may be added to an interaction
|
||||
// response.
|
||||
type SelectComponent struct {
|
||||
// Options are the choices in the select.
|
||||
Options []SelectOption `json:"options"`
|
||||
// CustomID is the custom unique ID.
|
||||
CustomID ComponentID `json:"custom_id,omitempty"`
|
||||
// Placeholder is the custom placeholder text if nothing is selected. Max
|
||||
// 100 characters.
|
||||
Placeholder string `json:"placeholder,omitempty"`
|
||||
// ValueLimits is the minimum and maximum number of items that can be
|
||||
// chosen. The default is [1, 1] if ValueLimits is a zero-value.
|
||||
ValueLimits [2]int `json:"-"`
|
||||
// Disabled disables the select if true.
|
||||
Disabled bool `json:"disabled,omitempty"`
|
||||
}
|
||||
|
||||
// SelectOption is an option in the select component.
|
||||
type SelectOption struct {
|
||||
// Label is the user-facing name of the option. Max 100 characters.
|
||||
Label string `json:"label"`
|
||||
// Value is the internal value that is echoed back to the program. It's
|
||||
// similar to the custom ID. Max 100 characters.
|
||||
Value string `json:"value"`
|
||||
// Description is the additional description of an option.
|
||||
Description string `json:"description,omitempty"`
|
||||
// Emoji is the optional emoji object.
|
||||
Emoji *ComponentEmoji `json:"emoji,omitempty"`
|
||||
// Default will render this option as selected by default if true.
|
||||
Default bool `json:"default,omitempty"`
|
||||
}
|
||||
|
||||
// ID implements the Component interface.
|
||||
func (s *SelectComponent) ID() ComponentID { return s.CustomID }
|
||||
|
||||
// Type implements the Component interface.
|
||||
func (s *SelectComponent) Type() ComponentType {
|
||||
return SelectComponentType
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the select in the format Discord expects.
|
||||
func (s SelectComponent) MarshalJSON() ([]byte, error) {
|
||||
type selectComponent SelectComponent
|
||||
func (s *SelectComponent) _cmp() {}
|
||||
func (s *SelectComponent) _icp() {}
|
||||
|
||||
return json.Marshal(struct {
|
||||
selectComponent
|
||||
// MarshalJSON marshals the select in the format Discord expects.
|
||||
func (s *SelectComponent) MarshalJSON() ([]byte, error) {
|
||||
type sel SelectComponent
|
||||
|
||||
type Msg struct {
|
||||
Type ComponentType `json:"type"`
|
||||
}{
|
||||
selectComponent: selectComponent(s),
|
||||
Type: SelectComponentType,
|
||||
})
|
||||
*sel
|
||||
MinValues *int `json:"min_values,omitempty"`
|
||||
MaxValues *int `json:"max_values,omitempty"`
|
||||
}
|
||||
|
||||
msg := Msg{
|
||||
Type: SelectComponentType,
|
||||
sel: (*sel)(s),
|
||||
}
|
||||
|
||||
if s.ValueLimits != [2]int{0, 0} {
|
||||
msg.MinValues = new(int)
|
||||
msg.MaxValues = new(int)
|
||||
|
||||
*msg.MinValues = s.ValueLimits[0]
|
||||
*msg.MaxValues = s.ValueLimits[1]
|
||||
}
|
||||
|
||||
return json.Marshal(msg)
|
||||
}
|
||||
|
||||
// UnknownComponent is reserved for components with unknown or not yet
|
||||
// implemented components types.
|
||||
// Unknown is reserved for components with unknown or not yet implemented
|
||||
// components types. It can also be used in place of a ComponentInteraction.
|
||||
type UnknownComponent struct {
|
||||
json.Raw
|
||||
id ComponentID
|
||||
typ ComponentType
|
||||
}
|
||||
|
||||
// Type implements the Component interface.
|
||||
func (u *UnknownComponent) Type() ComponentType {
|
||||
return u.typ
|
||||
// ID implements the Component and ComponentInteraction interfaces.
|
||||
func (u *UnknownComponent) ID() ComponentID { return u.id }
|
||||
|
||||
// Type implements the Component and ComponentInteraction interfaces.
|
||||
func (u *UnknownComponent) Type() ComponentType { return u.typ }
|
||||
|
||||
// Type implements InteractionData.
|
||||
func (u *UnknownComponent) InteractionType() InteractionDataType {
|
||||
return ComponentInteractionType
|
||||
}
|
||||
|
||||
func (u *UnknownComponent) resp() {}
|
||||
func (u *UnknownComponent) data() {}
|
||||
func (u *UnknownComponent) _cmp() {}
|
||||
func (u *UnknownComponent) _icp() {}
|
||||
|
|
|
@ -4,14 +4,17 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InteractionEvent describes the full incoming interaction event. It may be a
|
||||
// gateway event or a webhook event.
|
||||
//
|
||||
// https://discord.com/developers/docs/topics/gateway#interactions
|
||||
type Interaction struct {
|
||||
type InteractionEvent struct {
|
||||
ID InteractionID `json:"id"`
|
||||
Data InteractionData `json:"data"`
|
||||
AppID AppID `json:"application_id"`
|
||||
Type InteractionType `json:"type"`
|
||||
Data InteractionData `json:"data,omitempty"`
|
||||
ChannelID ChannelID `json:"channel_id,omitempty"`
|
||||
Token string `json:"token"`
|
||||
Version int `json:"version"`
|
||||
|
@ -20,119 +23,286 @@ type Interaction struct {
|
|||
// Only present for component interactions, not command interactions.
|
||||
Message *Message `json:"message,omitempty"`
|
||||
|
||||
// Member is only present if this came from a guild.
|
||||
// Member is only present if this came from a guild. To get a user, use the
|
||||
// Sender method.
|
||||
Member *Member `json:"member,omitempty"`
|
||||
GuildID GuildID `json:"guild_id,omitempty"`
|
||||
|
||||
// User is only present if this didn't come from a guild.
|
||||
// User is only present if this didn't come from a guild. To get a user, use
|
||||
// the Sender method.
|
||||
User *User `json:"user,omitempty"`
|
||||
}
|
||||
|
||||
func (i *Interaction) UnmarshalJSON(p []byte) error {
|
||||
type interaction Interaction
|
||||
v := struct {
|
||||
Data json.Raw `json:"data,omitempty"`
|
||||
*interaction
|
||||
}{interaction: (*interaction)(i)}
|
||||
if err := json.Unmarshal(p, &v); err != nil {
|
||||
// Sender returns the sender of this event from either the Member field or the
|
||||
// User field. If neither of those fields are available, then nil is returned.
|
||||
func (e *InteractionEvent) Sender() *User {
|
||||
if e.User != nil {
|
||||
return e.User
|
||||
}
|
||||
if e.Member != nil {
|
||||
return &e.Member.User
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SenderID returns the sender's ID. See Sender for more information. If Sender
|
||||
// returns nil, then 0 is returned.
|
||||
func (e *InteractionEvent) SenderID() UserID {
|
||||
if sender := e.Sender(); sender != nil {
|
||||
return sender.ID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *InteractionEvent) UnmarshalJSON(b []byte) error {
|
||||
type event InteractionEvent
|
||||
|
||||
target := struct {
|
||||
Type InteractionDataType `json:"type"`
|
||||
Data json.Raw `json:"data"`
|
||||
*event
|
||||
}{
|
||||
event: (*event)(e),
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, &target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch v.Type {
|
||||
case PingInteraction:
|
||||
var err error
|
||||
|
||||
switch target.Type {
|
||||
case PingInteractionType:
|
||||
e.Data = &PingInteraction{}
|
||||
case CommandInteractionType:
|
||||
e.Data = &CommandInteraction{}
|
||||
case ComponentInteractionType:
|
||||
d, err := ParseComponentInteraction(target.Data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal component interaction event data")
|
||||
}
|
||||
e.Data = d
|
||||
return nil
|
||||
case ComponentInteraction:
|
||||
i.Data = &ComponentInteractionData{}
|
||||
case CommandInteraction:
|
||||
i.Data = &CommandInteractionData{}
|
||||
default:
|
||||
i.Data = &UnknownInteractionData{typ: v.Type}
|
||||
e.Data = &UnknownInteractionData{
|
||||
Raw: target.Data,
|
||||
typ: target.Type,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return json.Unmarshal(v.Data, i.Data)
|
||||
if err := json.Unmarshal(target.Data, e.Data); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal interaction event data")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type InteractionType uint
|
||||
func (e *InteractionEvent) MarshalJSON() ([]byte, error) {
|
||||
type event InteractionEvent
|
||||
|
||||
if e.Data == nil {
|
||||
return nil, errors.New("missing InteractionEvent.Data")
|
||||
}
|
||||
if e.Data.InteractionType() == 0 {
|
||||
return nil, errors.New("unexpected 0 InteractionEvent.Data.Type")
|
||||
}
|
||||
|
||||
v := struct {
|
||||
Type InteractionDataType `json:"type"`
|
||||
*event
|
||||
}{
|
||||
Type: e.Data.InteractionType(),
|
||||
event: (*event)(e),
|
||||
}
|
||||
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
// InteractionDataType is the type of each Interaction, enumerated in
|
||||
// integers.
|
||||
type InteractionDataType uint
|
||||
|
||||
const (
|
||||
PingInteraction InteractionType = iota + 1
|
||||
CommandInteraction
|
||||
ComponentInteraction
|
||||
_ InteractionDataType = iota
|
||||
PingInteractionType
|
||||
CommandInteractionType
|
||||
ComponentInteractionType
|
||||
)
|
||||
|
||||
// InteractionData holds the data of an interaction.
|
||||
// Type assertions should be made on InteractionData to access the underlying data.
|
||||
// The underlying types of the InteractionData are pointer types.
|
||||
// InteractionData holds the respose data of an interaction, or more
|
||||
// specifically, the data that Discord sends to us. Type assertions should be
|
||||
// made on it to access the underlying data. The underlying types of the
|
||||
// Responses are value types. See the constructors for the possible types.
|
||||
type InteractionData interface {
|
||||
Type() InteractionType
|
||||
InteractionType() InteractionDataType
|
||||
data()
|
||||
}
|
||||
|
||||
type ComponentInteractionData struct {
|
||||
CustomID string `json:"custom_id"`
|
||||
ComponentType ComponentType `json:"component_type"`
|
||||
Values []string `json:"values"`
|
||||
// PingInteraction is a ping Interaction response.
|
||||
type PingInteraction struct{}
|
||||
|
||||
// InteractionType implements InteractionData.
|
||||
func (*PingInteraction) InteractionType() InteractionDataType { return PingInteractionType }
|
||||
func (*PingInteraction) data() {}
|
||||
|
||||
// ComponentInteraction is a union component interaction response types. The
|
||||
// types can be whatever the constructors for this type will return. Underlying
|
||||
// types of Response are all value types.
|
||||
type ComponentInteraction interface {
|
||||
InteractionData
|
||||
// ID returns the ID of the component in response.
|
||||
ID() ComponentID
|
||||
// Type returns the type of the component in response.
|
||||
Type() ComponentType
|
||||
resp()
|
||||
}
|
||||
|
||||
func (*ComponentInteractionData) Type() InteractionType {
|
||||
return ComponentInteraction
|
||||
// SelectInteraction is a select component's response.
|
||||
type SelectInteraction struct {
|
||||
CustomID ComponentID `json:"custom_id"`
|
||||
Values []string `json:"values"`
|
||||
}
|
||||
|
||||
type CommandInteractionData struct {
|
||||
ID CommandID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Options []InteractionOption `json:"options"`
|
||||
// ID implements ComponentInteraction.
|
||||
func (s *SelectInteraction) ID() ComponentID { return s.CustomID }
|
||||
|
||||
// Type implements ComponentInteraction.
|
||||
func (s *SelectInteraction) Type() ComponentType { return SelectComponentType }
|
||||
|
||||
// InteractionType implements InteractionData.
|
||||
func (s *SelectInteraction) InteractionType() InteractionDataType {
|
||||
return ComponentInteractionType
|
||||
}
|
||||
|
||||
func (*CommandInteractionData) Type() InteractionType {
|
||||
return CommandInteraction
|
||||
func (s *SelectInteraction) resp() {}
|
||||
func (s *SelectInteraction) data() {}
|
||||
|
||||
// ButtonInteraction is a button component's response. It is the custom ID of
|
||||
// the button within the component tree.
|
||||
type ButtonInteraction struct {
|
||||
CustomID ComponentID `json:"custom_id"`
|
||||
}
|
||||
|
||||
type UnknownInteractionData struct {
|
||||
json.Raw
|
||||
typ InteractionType
|
||||
// ID implements ComponentInteraction.
|
||||
func (b *ButtonInteraction) ID() ComponentID { return b.CustomID }
|
||||
|
||||
// Type implements ComponentInteraction.
|
||||
func (b *ButtonInteraction) Type() ComponentType { return ButtonComponentType }
|
||||
|
||||
// InteractionType implements InteractionData.
|
||||
func (b *ButtonInteraction) InteractionType() InteractionDataType {
|
||||
return ComponentInteractionType
|
||||
}
|
||||
|
||||
func (u *UnknownInteractionData) Type() InteractionType {
|
||||
return u.typ
|
||||
func (b *ButtonInteraction) data() {}
|
||||
func (b *ButtonInteraction) resp() {}
|
||||
|
||||
// ParseComponentInteraction parses the given bytes as a component response.
|
||||
func ParseComponentInteraction(b []byte) (ComponentInteraction, error) {
|
||||
var t struct {
|
||||
Type ComponentType `json:"type"`
|
||||
CustomID ComponentID `json:"custom_id"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component interaction header")
|
||||
}
|
||||
|
||||
var d ComponentInteraction
|
||||
|
||||
switch t.Type {
|
||||
case ButtonComponentType:
|
||||
d = &ButtonInteraction{CustomID: t.CustomID}
|
||||
case SelectComponentType:
|
||||
d = &SelectInteraction{CustomID: t.CustomID}
|
||||
default:
|
||||
d = &UnknownComponent{
|
||||
Raw: append(json.Raw(nil), b...),
|
||||
id: t.CustomID,
|
||||
typ: t.Type,
|
||||
}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(b, d); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component interaction data")
|
||||
}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
type InteractionOption struct {
|
||||
Name string `json:"name"`
|
||||
Value json.Raw `json:"value"`
|
||||
Options []InteractionOption `json:"options"`
|
||||
// CommandInteraction is a command interaction that Discord sends to us.
|
||||
type CommandInteraction struct {
|
||||
ID CommandID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Options []CommandInteractionOption `json:"options"`
|
||||
}
|
||||
|
||||
// InteractionType implements InteractionData.
|
||||
func (*CommandInteraction) InteractionType() InteractionDataType {
|
||||
return CommandInteractionType
|
||||
}
|
||||
|
||||
func (*CommandInteraction) data() {}
|
||||
|
||||
// CommandInteractionOption is an option for a Command interaction response.
|
||||
type CommandInteractionOption struct {
|
||||
Name string `json:"name"`
|
||||
Value json.Raw `json:"value"`
|
||||
Options []CommandInteractionOption `json:"options"`
|
||||
}
|
||||
|
||||
// String will return the value if the option's value is a valid string.
|
||||
// Otherwise, it will return the raw JSON value of the other type.
|
||||
func (o InteractionOption) String() string {
|
||||
func (o CommandInteractionOption) String() string {
|
||||
val := string(o.Value)
|
||||
|
||||
s, err := strconv.Unquote(val)
|
||||
if err != nil {
|
||||
return val
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (o InteractionOption) Int() (int64, error) {
|
||||
// IntValue reads the option's value as an int.
|
||||
func (o CommandInteractionOption) IntValue() (int64, error) {
|
||||
var i int64
|
||||
err := o.Value.UnmarshalTo(&i)
|
||||
return i, err
|
||||
}
|
||||
|
||||
func (o InteractionOption) Bool() (bool, error) {
|
||||
// BoolValue reads the option's value as a bool.
|
||||
func (o CommandInteractionOption) BoolValue() (bool, error) {
|
||||
var b bool
|
||||
err := o.Value.UnmarshalTo(&b)
|
||||
return b, err
|
||||
}
|
||||
|
||||
func (o InteractionOption) Snowflake() (Snowflake, error) {
|
||||
// SnowflakeValue reads the option's value as a snowflake.
|
||||
func (o CommandInteractionOption) SnowflakeValue() (Snowflake, error) {
|
||||
var id Snowflake
|
||||
err := o.Value.UnmarshalTo(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
func (o InteractionOption) Float() (float64, error) {
|
||||
// FloatValue reads the option's value as a float64.
|
||||
func (o CommandInteractionOption) FloatValue() (float64, error) {
|
||||
var f float64
|
||||
err := o.Value.UnmarshalTo(&f)
|
||||
return f, err
|
||||
}
|
||||
|
||||
// UnknownInteractionData describes an Interaction response with an unknown
|
||||
// type.
|
||||
type UnknownInteractionData struct {
|
||||
json.Raw
|
||||
typ InteractionDataType
|
||||
}
|
||||
|
||||
// InteractionType implements InteractionData.
|
||||
func (u *UnknownInteractionData) InteractionType() InteractionDataType {
|
||||
return u.typ
|
||||
}
|
||||
|
||||
func (u *UnknownInteractionData) data() {}
|
||||
|
|
|
@ -75,7 +75,7 @@ type Message struct {
|
|||
// Reactions contains any reactions to the message.
|
||||
Reactions []Reaction `json:"reactions,omitempty"`
|
||||
// Components contains any attached components.
|
||||
Components []ComponentWrap `json:"components,omitempty"`
|
||||
Components ContainerComponents `json:"components,omitempty"`
|
||||
|
||||
// Used for validating a message was sent
|
||||
Nonce string `json:"nonce,omitempty"`
|
||||
|
|
|
@ -15,16 +15,31 @@ func DurationSinceEpoch(t time.Time) time.Duration {
|
|||
return time.Duration(t.UnixNano()) - Epoch
|
||||
}
|
||||
|
||||
//go:generate go run ../utils/gensnowflake -o snowflake_types.go AppID AttachmentID AuditLogEntryID ChannelID CommandID EmojiID GuildID IntegrationID InteractionID MessageID RoleID StageID StickerID StickerPackID TeamID UserID WebhookID
|
||||
|
||||
// Mention generates the mention syntax for this channel ID.
|
||||
func (s ChannelID) Mention() string { return "<#" + s.String() + ">" }
|
||||
|
||||
// Mention generates the mention syntax for this role ID.
|
||||
func (s RoleID) Mention() string { return "<@&" + s.String() + ">" }
|
||||
|
||||
// Mention generates the mention syntax for this user ID.
|
||||
func (s UserID) Mention() string { return "<@" + s.String() + ">" }
|
||||
|
||||
// Snowflake is the format of Discord's ID type. It is a format that can be
|
||||
// sorted chronologically.
|
||||
type Snowflake uint64
|
||||
|
||||
// NullSnowflake gets encoded into a null. This is used for
|
||||
// optional and nullable snowflake fields.
|
||||
const NullSnowflake = ^Snowflake(0)
|
||||
|
||||
// NewSnowflake creates a new snowflake from the given time.
|
||||
func NewSnowflake(t time.Time) Snowflake {
|
||||
return Snowflake((DurationSinceEpoch(t) / time.Millisecond) << 22)
|
||||
}
|
||||
|
||||
// ParseSnowflake parses a snowflake.
|
||||
func ParseSnowflake(sf string) (Snowflake, error) {
|
||||
if sf == "null" {
|
||||
return NullSnowflake, nil
|
||||
|
@ -93,244 +108,3 @@ func (s Snowflake) PID() uint8 {
|
|||
func (s Snowflake) Increment() uint16 {
|
||||
return uint16(s & 0xFFF)
|
||||
}
|
||||
|
||||
type AppID Snowflake
|
||||
|
||||
const NullAppID = AppID(NullSnowflake)
|
||||
|
||||
func (s AppID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *AppID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s AppID) String() string { return Snowflake(s).String() }
|
||||
func (s AppID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s AppID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s AppID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s AppID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s AppID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s AppID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type TeamID Snowflake
|
||||
|
||||
const NullTeamID = AppID(NullSnowflake)
|
||||
|
||||
func (s TeamID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *TeamID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s TeamID) String() string { return Snowflake(s).String() }
|
||||
func (s TeamID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s TeamID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s TeamID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s TeamID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s TeamID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s TeamID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type AttachmentID Snowflake
|
||||
|
||||
const NullAttachmentID = AttachmentID(NullSnowflake)
|
||||
|
||||
func (s AttachmentID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *AttachmentID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s AttachmentID) String() string { return Snowflake(s).String() }
|
||||
func (s AttachmentID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s AttachmentID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s AttachmentID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s AttachmentID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s AttachmentID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s AttachmentID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type AuditLogEntryID Snowflake
|
||||
|
||||
const NullAuditLogEntryID = AuditLogEntryID(NullSnowflake)
|
||||
|
||||
func (s AuditLogEntryID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *AuditLogEntryID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s AuditLogEntryID) String() string { return Snowflake(s).String() }
|
||||
func (s AuditLogEntryID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s AuditLogEntryID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s AuditLogEntryID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s AuditLogEntryID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s AuditLogEntryID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s AuditLogEntryID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type ChannelID Snowflake
|
||||
|
||||
const NullChannelID = ChannelID(NullSnowflake)
|
||||
|
||||
func (s ChannelID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *ChannelID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s ChannelID) String() string { return Snowflake(s).String() }
|
||||
func (s ChannelID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s ChannelID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s ChannelID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s ChannelID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s ChannelID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s ChannelID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
func (s ChannelID) Mention() string { return "<#" + s.String() + ">" }
|
||||
|
||||
type CommandID Snowflake
|
||||
|
||||
const NullCommandID = CommandID(NullSnowflake)
|
||||
|
||||
func (s CommandID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *CommandID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s CommandID) String() string { return Snowflake(s).String() }
|
||||
func (s CommandID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s CommandID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s CommandID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s CommandID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s CommandID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s CommandID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type EmojiID Snowflake
|
||||
|
||||
const NullEmojiID = EmojiID(NullSnowflake)
|
||||
|
||||
func (s EmojiID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *EmojiID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s EmojiID) String() string { return Snowflake(s).String() }
|
||||
func (s EmojiID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s EmojiID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s EmojiID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s EmojiID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s EmojiID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s EmojiID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type IntegrationID Snowflake
|
||||
|
||||
const NullIntegrationID = IntegrationID(NullSnowflake)
|
||||
|
||||
func (s IntegrationID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *IntegrationID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s IntegrationID) String() string { return Snowflake(s).String() }
|
||||
func (s IntegrationID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s IntegrationID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s IntegrationID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s IntegrationID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s IntegrationID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s IntegrationID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type InteractionID Snowflake
|
||||
|
||||
const NullInteractionID = InteractionID(NullSnowflake)
|
||||
|
||||
func (s InteractionID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *InteractionID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s InteractionID) String() string { return Snowflake(s).String() }
|
||||
func (s InteractionID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s InteractionID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s InteractionID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s InteractionID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s InteractionID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s InteractionID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type GuildID Snowflake
|
||||
|
||||
const NullGuildID = GuildID(NullSnowflake)
|
||||
|
||||
func (s GuildID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *GuildID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s GuildID) String() string { return Snowflake(s).String() }
|
||||
func (s GuildID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s GuildID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s GuildID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s GuildID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s GuildID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s GuildID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type MessageID Snowflake
|
||||
|
||||
const NullMessageID = MessageID(NullSnowflake)
|
||||
|
||||
func (s MessageID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *MessageID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s MessageID) String() string { return Snowflake(s).String() }
|
||||
func (s MessageID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s MessageID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s MessageID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s MessageID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s MessageID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s MessageID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type RoleID Snowflake
|
||||
|
||||
const NullRoleID = RoleID(NullSnowflake)
|
||||
|
||||
func (s RoleID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *RoleID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s RoleID) String() string { return Snowflake(s).String() }
|
||||
func (s RoleID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s RoleID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s RoleID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s RoleID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s RoleID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s RoleID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
func (s RoleID) Mention() string { return "<@&" + s.String() + ">" }
|
||||
|
||||
type StageID Snowflake
|
||||
|
||||
const NullStageID = StageID(NullSnowflake)
|
||||
|
||||
func (s StageID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *StageID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s StageID) String() string { return Snowflake(s).String() }
|
||||
func (s StageID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s StageID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s StageID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s StageID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s StageID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s StageID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type StickerID Snowflake
|
||||
|
||||
const NullStickerID = StickerID(NullSnowflake)
|
||||
|
||||
func (s StickerID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *StickerID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s StickerID) String() string { return Snowflake(s).String() }
|
||||
func (s StickerID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s StickerID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s StickerID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s StickerID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s StickerID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s StickerID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type StickerPackID Snowflake
|
||||
|
||||
const NullStickerPackID = StickerPackID(NullSnowflake)
|
||||
|
||||
func (s StickerPackID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *StickerPackID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s StickerPackID) String() string { return Snowflake(s).String() }
|
||||
func (s StickerPackID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s StickerPackID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s StickerPackID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s StickerPackID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s StickerPackID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s StickerPackID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
type UserID Snowflake
|
||||
|
||||
const NullUserID = UserID(NullSnowflake)
|
||||
|
||||
func (s UserID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *UserID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s UserID) String() string { return Snowflake(s).String() }
|
||||
func (s UserID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s UserID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s UserID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s UserID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s UserID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s UserID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
func (s UserID) Mention() string { return "<@" + s.String() + ">" }
|
||||
|
||||
type WebhookID Snowflake
|
||||
|
||||
const NullWebhookID = WebhookID(NullSnowflake)
|
||||
|
||||
func (s WebhookID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *WebhookID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
func (s WebhookID) String() string { return Snowflake(s).String() }
|
||||
func (s WebhookID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
func (s WebhookID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
func (s WebhookID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s WebhookID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s WebhookID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s WebhookID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
|
|
@ -0,0 +1,396 @@
|
|||
// Code generated by gensnowflake. DO NOT EDIT.
|
||||
|
||||
package discord
|
||||
|
||||
import "time"
|
||||
|
||||
// AppID is the snowflake type for a AppID.
|
||||
type AppID Snowflake
|
||||
|
||||
// NullAppID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullAppID = AppID(NullSnowflake)
|
||||
|
||||
func (s AppID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *AppID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s AppID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s AppID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s AppID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s AppID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s AppID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s AppID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s AppID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// AttachmentID is the snowflake type for a AttachmentID.
|
||||
type AttachmentID Snowflake
|
||||
|
||||
// NullAttachmentID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullAttachmentID = AttachmentID(NullSnowflake)
|
||||
|
||||
func (s AttachmentID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *AttachmentID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s AttachmentID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s AttachmentID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s AttachmentID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s AttachmentID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s AttachmentID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s AttachmentID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s AttachmentID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// AuditLogEntryID is the snowflake type for a AuditLogEntryID.
|
||||
type AuditLogEntryID Snowflake
|
||||
|
||||
// NullAuditLogEntryID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullAuditLogEntryID = AuditLogEntryID(NullSnowflake)
|
||||
|
||||
func (s AuditLogEntryID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *AuditLogEntryID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s AuditLogEntryID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s AuditLogEntryID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s AuditLogEntryID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s AuditLogEntryID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s AuditLogEntryID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s AuditLogEntryID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s AuditLogEntryID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// ChannelID is the snowflake type for a ChannelID.
|
||||
type ChannelID Snowflake
|
||||
|
||||
// NullChannelID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullChannelID = ChannelID(NullSnowflake)
|
||||
|
||||
func (s ChannelID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *ChannelID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s ChannelID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s ChannelID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s ChannelID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s ChannelID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s ChannelID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s ChannelID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s ChannelID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// CommandID is the snowflake type for a CommandID.
|
||||
type CommandID Snowflake
|
||||
|
||||
// NullCommandID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullCommandID = CommandID(NullSnowflake)
|
||||
|
||||
func (s CommandID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *CommandID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s CommandID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s CommandID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s CommandID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s CommandID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s CommandID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s CommandID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s CommandID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// EmojiID is the snowflake type for a EmojiID.
|
||||
type EmojiID Snowflake
|
||||
|
||||
// NullEmojiID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullEmojiID = EmojiID(NullSnowflake)
|
||||
|
||||
func (s EmojiID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *EmojiID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s EmojiID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s EmojiID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s EmojiID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s EmojiID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s EmojiID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s EmojiID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s EmojiID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// GuildID is the snowflake type for a GuildID.
|
||||
type GuildID Snowflake
|
||||
|
||||
// NullGuildID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullGuildID = GuildID(NullSnowflake)
|
||||
|
||||
func (s GuildID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *GuildID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s GuildID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s GuildID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s GuildID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s GuildID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s GuildID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s GuildID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s GuildID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// IntegrationID is the snowflake type for a IntegrationID.
|
||||
type IntegrationID Snowflake
|
||||
|
||||
// NullIntegrationID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullIntegrationID = IntegrationID(NullSnowflake)
|
||||
|
||||
func (s IntegrationID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *IntegrationID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s IntegrationID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s IntegrationID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s IntegrationID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s IntegrationID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s IntegrationID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s IntegrationID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s IntegrationID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// InteractionID is the snowflake type for a InteractionID.
|
||||
type InteractionID Snowflake
|
||||
|
||||
// NullInteractionID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullInteractionID = InteractionID(NullSnowflake)
|
||||
|
||||
func (s InteractionID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *InteractionID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s InteractionID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s InteractionID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s InteractionID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s InteractionID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s InteractionID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s InteractionID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s InteractionID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// MessageID is the snowflake type for a MessageID.
|
||||
type MessageID Snowflake
|
||||
|
||||
// NullMessageID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullMessageID = MessageID(NullSnowflake)
|
||||
|
||||
func (s MessageID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *MessageID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s MessageID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s MessageID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s MessageID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s MessageID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s MessageID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s MessageID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s MessageID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// RoleID is the snowflake type for a RoleID.
|
||||
type RoleID Snowflake
|
||||
|
||||
// NullRoleID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullRoleID = RoleID(NullSnowflake)
|
||||
|
||||
func (s RoleID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *RoleID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s RoleID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s RoleID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s RoleID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s RoleID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s RoleID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s RoleID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s RoleID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// StageID is the snowflake type for a StageID.
|
||||
type StageID Snowflake
|
||||
|
||||
// NullStageID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullStageID = StageID(NullSnowflake)
|
||||
|
||||
func (s StageID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *StageID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s StageID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s StageID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s StageID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s StageID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s StageID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s StageID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s StageID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// StickerID is the snowflake type for a StickerID.
|
||||
type StickerID Snowflake
|
||||
|
||||
// NullStickerID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullStickerID = StickerID(NullSnowflake)
|
||||
|
||||
func (s StickerID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *StickerID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s StickerID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s StickerID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s StickerID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s StickerID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s StickerID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s StickerID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s StickerID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// StickerPackID is the snowflake type for a StickerPackID.
|
||||
type StickerPackID Snowflake
|
||||
|
||||
// NullStickerPackID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullStickerPackID = StickerPackID(NullSnowflake)
|
||||
|
||||
func (s StickerPackID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *StickerPackID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s StickerPackID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s StickerPackID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s StickerPackID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s StickerPackID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s StickerPackID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s StickerPackID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s StickerPackID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// TeamID is the snowflake type for a TeamID.
|
||||
type TeamID Snowflake
|
||||
|
||||
// NullTeamID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullTeamID = TeamID(NullSnowflake)
|
||||
|
||||
func (s TeamID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *TeamID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s TeamID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s TeamID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s TeamID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s TeamID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s TeamID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s TeamID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s TeamID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// UserID is the snowflake type for a UserID.
|
||||
type UserID Snowflake
|
||||
|
||||
// NullUserID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullUserID = UserID(NullSnowflake)
|
||||
|
||||
func (s UserID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *UserID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s UserID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s UserID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s UserID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s UserID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s UserID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s UserID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s UserID) Increment() uint16 { return Snowflake(s).Increment() }
|
||||
|
||||
// WebhookID is the snowflake type for a WebhookID.
|
||||
type WebhookID Snowflake
|
||||
|
||||
// NullWebhookID gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const NullWebhookID = WebhookID(NullSnowflake)
|
||||
|
||||
func (s WebhookID) MarshalJSON() ([]byte, error) { return Snowflake(s).MarshalJSON() }
|
||||
func (s *WebhookID) UnmarshalJSON(v []byte) error { return (*Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s WebhookID) String() string { return Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s WebhookID) IsValid() bool { return Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s WebhookID) IsNull() bool { return Snowflake(s).IsNull() }
|
||||
|
||||
func (s WebhookID) Time() time.Time { return Snowflake(s).Time() }
|
||||
func (s WebhookID) Worker() uint8 { return Snowflake(s).Worker() }
|
||||
func (s WebhookID) PID() uint8 { return Snowflake(s).PID() }
|
||||
func (s WebhookID) Increment() uint16 { return Snowflake(s).Increment() }
|
|
@ -397,7 +397,7 @@ type (
|
|||
)
|
||||
|
||||
type InteractionCreateEvent struct {
|
||||
discord.Interaction
|
||||
discord.InteractionEvent
|
||||
}
|
||||
|
||||
// Undocumented
|
||||
|
|
|
@ -193,6 +193,7 @@ func NewCustomIdentifiedGateway(gatewayURL string, id *Identifier) *Gateway {
|
|||
|
||||
ErrorLog: wsutil.WSError,
|
||||
AfterClose: func(error) {},
|
||||
PacerLoop: wsutil.PacemakerLoop{ErrorLog: wsutil.WSError},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,6 +1,6 @@
|
|||
module github.com/diamondburned/arikawa/v3
|
||||
|
||||
go 1.13
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/gorilla/schema v1.2.0
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"go/format"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
type data struct {
|
||||
Package string
|
||||
ImportDiscord bool
|
||||
Snowflakes []snowflakeType
|
||||
}
|
||||
|
||||
type snowflakeType struct {
|
||||
TypeName string
|
||||
}
|
||||
|
||||
//go:embed template.tmpl
|
||||
var packageTmpl string
|
||||
|
||||
var tmpl = template.Must(template.New("").Parse(packageTmpl))
|
||||
|
||||
func main() {
|
||||
var pkg string
|
||||
var out string
|
||||
|
||||
log.SetFlags(0)
|
||||
|
||||
flag.Usage = func() {
|
||||
log.Printf("usage: %s [-p package] <type names...>", filepath.Base(os.Args[0]))
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
flag.StringVar(&out, "o", "", "output, empty for stdout")
|
||||
flag.StringVar(&pkg, "p", "discord", "package name")
|
||||
flag.Parse()
|
||||
|
||||
if len(flag.Args()) == 0 {
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
d := data{
|
||||
Package: pkg,
|
||||
ImportDiscord: pkg != "discord",
|
||||
}
|
||||
|
||||
for _, arg := range flag.Args() {
|
||||
d.Snowflakes = append(d.Snowflakes, snowflakeType{
|
||||
TypeName: arg,
|
||||
})
|
||||
}
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
if err := tmpl.Execute(&buf, d); err != nil {
|
||||
log.Fatalln("failed to execute template:", err)
|
||||
}
|
||||
|
||||
b, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatalln("failed to fmt:", err)
|
||||
}
|
||||
|
||||
outFile := os.Stdout
|
||||
|
||||
if out != "" {
|
||||
f, err := os.Create(out)
|
||||
if err != nil {
|
||||
log.Fatalln("failed to create output file:", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
outFile = f
|
||||
}
|
||||
|
||||
if _, err := outFile.Write(b); err != nil {
|
||||
log.Fatalln("failed to write to file:", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// Code generated by gensnowflake. DO NOT EDIT.
|
||||
|
||||
package {{ .Package }}
|
||||
|
||||
{{ $dot := "" }}
|
||||
|
||||
{{ if .ImportDiscord }}
|
||||
{{ $dot = "discord." }}
|
||||
import "github.com/diamondburned/arikawa/v3/discord"
|
||||
{{ end }}
|
||||
|
||||
import "time"
|
||||
|
||||
{{ range .Snowflakes }}
|
||||
|
||||
// {{ .TypeName }} is the snowflake type for a {{ .TypeName }}.
|
||||
type {{.TypeName}} {{$dot}}Snowflake
|
||||
|
||||
// Null{{.TypeName}} gets encoded into a null. This is used for optional and nullable snowflake fields.
|
||||
const Null{{.TypeName}} = {{.TypeName}}({{$dot}}NullSnowflake)
|
||||
|
||||
func (s {{.TypeName}}) MarshalJSON() ([]byte, error) { return {{$dot}}Snowflake(s).MarshalJSON() }
|
||||
func (s *{{.TypeName}}) UnmarshalJSON(v []byte) error { return (*{{$dot}}Snowflake)(s).UnmarshalJSON(v) }
|
||||
|
||||
// String returns the ID, or nothing if the snowflake isn't valid.
|
||||
func (s {{.TypeName}}) String() string { return {{$dot}}Snowflake(s).String() }
|
||||
|
||||
// IsValid returns whether or not the snowflake is valid.
|
||||
func (s {{.TypeName}}) IsValid() bool { return {{$dot}}Snowflake(s).IsValid() }
|
||||
|
||||
// IsNull returns whether or not the snowflake is null.
|
||||
func (s {{.TypeName}}) IsNull() bool { return {{$dot}}Snowflake(s).IsNull() }
|
||||
|
||||
func (s {{.TypeName}}) Time() time.Time { return {{$dot}}Snowflake(s).Time() }
|
||||
func (s {{.TypeName}}) Worker() uint8 { return {{$dot}}Snowflake(s).Worker() }
|
||||
func (s {{.TypeName}}) PID() uint8 { return {{$dot}}Snowflake(s).PID() }
|
||||
func (s {{.TypeName}}) Increment() uint16 { return {{$dot}}Snowflake(s).Increment() }
|
||||
{{ end }}
|
|
@ -267,7 +267,7 @@ func (c *Client) request(
|
|||
}
|
||||
|
||||
// Optionally unmarshal the error.
|
||||
json.Unmarshal(httpErr.Body, &httpErr)
|
||||
json.Unmarshal(httpErr.Body, httpErr)
|
||||
|
||||
doErr = httpErr
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue