From 09e3d894b734d812cc53927b87bf7e503e61d9f7 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Thu, 9 Dec 2021 04:03:43 +0300 Subject: [PATCH 01/33] feat: modal interactions and text input component --- components.go | 42 +++++++++++ examples/modals/main.go | 159 ++++++++++++++++++++++++++++++++++++++++ interactions.go | 56 +++++++++++++- 3 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 examples/modals/main.go diff --git a/components.go b/components.go index 2ad19a07d..b7b4708e7 100644 --- a/components.go +++ b/components.go @@ -13,6 +13,7 @@ const ( ActionsRowComponent ComponentType = 1 ButtonComponent ComponentType = 2 SelectMenuComponent ComponentType = 3 + InputTextComponent ComponentType = 4 ) // MessageComponent is a base interface for all message components. @@ -42,6 +43,8 @@ func (umc *unmarshalableMessageComponent) UnmarshalJSON(src []byte) error { umc.MessageComponent = &Button{} case SelectMenuComponent: umc.MessageComponent = &SelectMenu{} + case InputTextComponent: + umc.MessageComponent = &InputText{} default: return fmt.Errorf("unknown component type: %d", v.Type) } @@ -195,3 +198,42 @@ func (m SelectMenu) MarshalJSON() ([]byte, error) { Type: m.Type(), }) } + +// InputText represents text input component. +type InputText struct { + CustomID string `json:"custom_id,omitempty"` + Label string `json:"label"` + Style TextStyleType `json:"style"` + Placeholder string `json:"placeholder,omitempty"` + Value string `json:"value,omitempty"` + Required bool `json:"required"` + MinLength int `json:"min_length"` + MaxLength int `json:"max_length,omitempty"` +} + +// Type is a method to get the type of a component. +func (InputText) Type() ComponentType { + return InputTextComponent +} + +// MarshalJSON is a method for marshaling InputText to a JSON object. +func (m InputText) MarshalJSON() ([]byte, error) { + type inputText InputText + + return json.Marshal(struct { + inputText + Type ComponentType `json:"type"` + }{ + inputText: inputText(m), + Type: m.Type(), + }) +} + +// TextStyleType is style of text in InputText component. +type TextStyleType uint + +// Text styles +const ( + TextStyleShort TextStyleType = 1 + TextStyleParagraph TextStyleType = 2 +) diff --git a/examples/modals/main.go b/examples/modals/main.go new file mode 100644 index 000000000..0a38c54de --- /dev/null +++ b/examples/modals/main.go @@ -0,0 +1,159 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "strings" + + "github.com/bwmarrin/discordgo" +) + +// Bot parameters +var ( + GuildID = flag.String("guild", "", "Test guild ID") + BotToken = flag.String("token", "", "Bot access token") + AppID = flag.String("app", "", "Application ID") + Cleanup = flag.Bool("cleanup", true, "Cleanup of commands") + ResultsChannel = flag.String("results", "", "Channel where send survey results to") +) + +var s *discordgo.Session + +func init() { + flag.Parse() +} + +func init() { + var err error + s, err = discordgo.New("Bot " + *BotToken) + if err != nil { + log.Fatalf("Invalid bot parameters: %v", err) + } +} + +var ( + commands = []discordgo.ApplicationCommand{ + { + Name: "modals-survey", + Description: "Take a survey about modals", + }, + } + commandsHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){ + "modals-survey": func(s *discordgo.Session, i *discordgo.InteractionCreate) { + err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseModal, + Data: &discordgo.InteractionResponseData{ + CustomID: "modals_survey_" + i.Interaction.Member.User.ID, + Title: "Modals survey", + Components: []discordgo.MessageComponent{ + discordgo.ActionsRow{ + Components: []discordgo.MessageComponent{ + discordgo.InputText{ + CustomID: "opinion", + Label: "What is your opinion on them?", + Style: discordgo.TextStyleShort, + Placeholder: "Don't be shy, share your opinion with us", + Required: true, + MaxLength: 300, + }, + }, + }, + discordgo.ActionsRow{ + Components: []discordgo.MessageComponent{ + discordgo.InputText{ + CustomID: "suggestions", + Label: "What would you suggest to improve them?", + Style: discordgo.TextStyleParagraph, + Required: false, + MaxLength: 2000, + }, + }, + }, + }, + }, + }) + if err != nil { + panic(err) + } + }, + } +) + +func main() { + s.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) { + log.Println("Bot is up!") + }) + + s.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) { + switch i.Type { + case discordgo.InteractionApplicationCommand: + if h, ok := commandsHandlers[i.ApplicationCommandData().Name]; ok { + h(s, i) + } + case discordgo.InteractionModalSubmit: + err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "Thank you for taking your time to fill this survey", + Flags: 1 << 6, + }, + }) + if err != nil { + panic(err) + } + data := i.ModalSubmitData() + + if !strings.HasPrefix(data.CustomID, "modals_survey") { + return + } + + userid := strings.Split(data.CustomID, "_")[2] + _, err = s.ChannelMessageSend(*ResultsChannel, fmt.Sprintf( + "Feedback received. From <@%s>\n\n**Opinion**:\n%s\n\n**Suggestions**:\n%s", + userid, + data.Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.InputText).Value, + data.Components[1].(*discordgo.ActionsRow).Components[0].(*discordgo.InputText).Value, + )) + if err != nil { + panic(err) + } + } + }) + + cmdIDs := make(map[string]string, len(commands)) + + for _, cmd := range commands { + rcmd, err := s.ApplicationCommandCreate(*AppID, *GuildID, &cmd) + if err != nil { + log.Fatalf("Cannot create slash command %q: %v", cmd.Name, err) + } + + cmdIDs[rcmd.ID] = rcmd.Name + } + + err := s.Open() + if err != nil { + log.Fatalf("Cannot open the session: %v", err) + } + defer s.Close() + + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt) + <-stop + log.Println("Graceful shutdown") + + if !*Cleanup { + return + } + + for id, name := range cmdIDs { + err := s.ApplicationCommandDelete(*AppID, *GuildID, id) + if err != nil { + log.Fatalf("Cannot delete slash command %q: %v", name, err) + } + } + +} diff --git a/interactions.go b/interactions.go index 6f1891792..b56e46ada 100644 --- a/interactions.go +++ b/interactions.go @@ -113,6 +113,7 @@ const ( InteractionApplicationCommand InteractionType = 2 InteractionMessageComponent InteractionType = 3 InteractionApplicationCommandAutocomplete InteractionType = 4 + InteractionModalSubmit InteractionType = 5 ) func (t InteractionType) String() string { @@ -123,6 +124,8 @@ func (t InteractionType) String() string { return "ApplicationCommand" case InteractionMessageComponent: return "MessageComponent" + case InteractionModalSubmit: + return "ModalSubmit" } return fmt.Sprintf("InteractionType(%d)", t) } @@ -137,8 +140,8 @@ type Interaction struct { // The message on which interaction was used. // NOTE: this field is only filled when a button click triggered the interaction. Otherwise it will be nil. - Message *Message `json:"message"` + Message *Message `json:"message"` // The member who invoked this interaction. // NOTE: this field is only filled when the slash command was invoked in a guild; // if it was invoked in a DM, the `User` field will be filled instead. @@ -186,6 +189,13 @@ func (i *Interaction) UnmarshalJSON(raw []byte) error { return err } i.Data = v + case InteractionModalSubmit: + v := ModalSubmitInteractionData{} + err = json.Unmarshal(tmp.Data, &v) + if err != nil { + return err + } + i.Data = v } return nil } @@ -208,6 +218,15 @@ func (i Interaction) ApplicationCommandData() (data ApplicationCommandInteractio return i.Data.(ApplicationCommandInteractionData) } +// ModalSubmitData is helper function to assert the innter InteractionData to ModalSubmitInteractionData. +// Make sure to check that the Type of the interaction is InteractionModalSubmit before calling. +func (i Interaction) ModalSubmitData() (data ModalSubmitInteractionData) { + if i.Type != InteractionModalSubmit { + panic("ModalSubmitData called on interaction of type " + i.Type.String()) + } + return i.Data.(ModalSubmitInteractionData) +} + // InteractionData is a common interface for all types of interaction data. type InteractionData interface { Type() InteractionType @@ -256,6 +275,36 @@ func (MessageComponentInteractionData) Type() InteractionType { return InteractionMessageComponent } +// ModalSubmitInteractionData contains the data of modal submit interaction. +type ModalSubmitInteractionData struct { + CustomID string `json:"custom_id"` + Components []MessageComponent `json:"-"` +} + +// Type returns the type of interaction data. +func (ModalSubmitInteractionData) Type() InteractionType { + return InteractionModalSubmit +} + +// UnmarshalJSON is a helper function to correctly unmarshal Components. +func (d *ModalSubmitInteractionData) UnmarshalJSON(data []byte) error { + type modalSubmitInteractionData ModalSubmitInteractionData + var v struct { + modalSubmitInteractionData + RawComponents []unmarshalableMessageComponent `json:"components"` + } + err := json.Unmarshal(data, &v) + if err != nil { + return err + } + *d = ModalSubmitInteractionData(v.modalSubmitInteractionData) + d.Components = make([]MessageComponent, len(v.RawComponents)) + for i, v := range v.RawComponents { + d.Components[i] = v.MessageComponent + } + return err +} + // ApplicationCommandInteractionDataOption represents an option of a slash command. type ApplicationCommandInteractionDataOption struct { Name string `json:"name"` @@ -398,6 +447,8 @@ const ( InteractionResponseUpdateMessage InteractionResponseType = 7 // InteractionApplicationCommandAutocompleteResult shows autocompletion results. Autocomplete interaction only. InteractionApplicationCommandAutocompleteResult InteractionResponseType = 8 + // InteractionResponseModal is for responding to an interaction with a modal window. + InteractionResponseModal InteractionResponseType = 9 ) // InteractionResponse represents a response for an interaction event. @@ -418,6 +469,9 @@ type InteractionResponseData struct { // NOTE: autocomplete interaction only. Choices []*ApplicationCommandOptionChoice `json:"choices,omitempty"` + + CustomID string `json:"custom_id,omitempty"` + Title string `json:"title,omitempty"` } // VerifyInteraction implements message verification of the discord interactions api From 6ff665e56e6058b6004f0178c7f15201159b7d3c Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Tue, 8 Feb 2022 16:38:19 +0300 Subject: [PATCH 02/33] feat: drop email-password session authentication. This commit drops old email/password authentication for New function. It violates Discord ToS and due to recent changes in rules for community resources on Discord API Docs it needs to be dropped. --- discord.go | 115 ++++------------------------------------------------- 1 file changed, 8 insertions(+), 107 deletions(-) diff --git a/discord.go b/discord.go index b8765deaf..b05fc0233 100644 --- a/discord.go +++ b/discord.go @@ -24,32 +24,12 @@ import ( // VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/) const VERSION = "0.23.0" -// ErrMFA will be risen by New when the user has 2FA. -var ErrMFA = errors.New("account has 2FA enabled") - -// New creates a new Discord session and will automate some startup -// tasks if given enough information to do so. Currently you can pass zero -// arguments and it will return an empty Discord session. -// There are 3 ways to call New: -// With a single auth token - All requests will use the token blindly -// (just tossing it into the HTTP Authorization header); -// no verification of the token will be done and requests may fail. -// IF THE TOKEN IS FOR A BOT, IT MUST BE PREFIXED WITH `BOT ` -// eg: `"Bot "` -// IF IT IS AN OAUTH2 ACCESS TOKEN, IT MUST BE PREFIXED WITH `Bearer ` -// eg: `"Bearer "` -// With an email and password - Discord will sign in with the provided -// credentials. -// With an email, password and auth token - Discord will verify the auth -// token, if it is invalid it will sign in with the provided -// credentials. This is the Discord recommended way to sign in. -// -// NOTE: While email/pass authentication is supported by DiscordGo it is -// HIGHLY DISCOURAGED by Discord. Please only use email/pass to obtain a token -// and then use that authentication token for all future connections. -// Also, doing any form of automation with a user (non Bot) account may result -// in that account being permanently banned from Discord. -func New(args ...interface{}) (s *Session, err error) { +// New creates a new Discord session with provided token. +// If the token is for a bot, it must be prefixed with "Bot ". +// e.g. "Bot ..." +// Or if it is an OAuth2 token, it must be prefixed with "Bearer " +// e.g. "Bearer ..." +func New(token string) (s *Session, err error) { // Create an empty Session interface. s = &Session{ @@ -75,87 +55,8 @@ func New(args ...interface{}) (s *Session, err error) { s.Identify.Properties.OS = runtime.GOOS s.Identify.Properties.Browser = "DiscordGo v" + VERSION s.Identify.Intents = MakeIntent(IntentsAllWithoutPrivileged) - - // If no arguments are passed return the empty Session interface. - if args == nil { - return - } - - // Variables used below when parsing func arguments - var auth, pass string - - // Parse passed arguments - for _, arg := range args { - - switch v := arg.(type) { - - case []string: - if len(v) > 3 { - err = fmt.Errorf("too many string parameters provided") - return - } - - // First string is either token or username - if len(v) > 0 { - auth = v[0] - } - - // If second string exists, it must be a password. - if len(v) > 1 { - pass = v[1] - } - - // If third string exists, it must be an auth token. - if len(v) > 2 { - s.Identify.Token = v[2] - s.Token = v[2] // TODO: Remove, Deprecated - Kept for backwards compatibility. - } - - case string: - // First string must be either auth token or username. - // Second string must be a password. - // Only 2 input strings are supported. - - if auth == "" { - auth = v - } else if pass == "" { - pass = v - } else if s.Token == "" { - s.Identify.Token = v - s.Token = v // TODO: Remove, Deprecated - Kept for backwards compatibility. - } else { - err = fmt.Errorf("too many string parameters provided") - return - } - - // case Config: - // TODO: Parse configuration struct - - default: - err = fmt.Errorf("unsupported parameter type provided") - return - } - } - - // If only one string was provided, assume it is an auth token. - // Otherwise get auth token from Discord, if a token was specified - // Discord will verify it for free, or log the user in if it is - // invalid. - if pass == "" { - s.Identify.Token = auth - s.Token = auth // TODO: Remove, Deprecated - Kept for backwards compatibility. - } else { - err = s.Login(auth, pass) - // TODO: Remove last s.Token part, Deprecated - Kept for backwards compatibility. - if err != nil || s.Identify.Token == "" || s.Token == "" { - if s.MFA { - err = ErrMFA - } else { - err = fmt.Errorf("Unable to fetch discord authentication token. %v", err) - } - return - } - } + s.Identify.Token = token + s.Token = token return } From e253d2882eca5231346329e1c9cc85a50b049f59 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Tue, 8 Feb 2022 17:10:52 +0300 Subject: [PATCH 03/33] fix(discord#New): fixed imports and removed MakeIntent --- discord.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/discord.go b/discord.go index b05fc0233..5e7aab2c5 100644 --- a/discord.go +++ b/discord.go @@ -14,8 +14,6 @@ package discordgo import ( - "errors" - "fmt" "net/http" "runtime" "time" @@ -54,7 +52,7 @@ func New(token string) (s *Session, err error) { s.Identify.GuildSubscriptions = true s.Identify.Properties.OS = runtime.GOOS s.Identify.Properties.Browser = "DiscordGo v" + VERSION - s.Identify.Intents = MakeIntent(IntentsAllWithoutPrivileged) + s.Identify.Intents = IntentsAllWithoutPrivileged s.Identify.Token = token s.Token = token From 5bf32ec1832baaf4c9d59ec0144bcc8a5a8d9fbb Mon Sep 17 00:00:00 2001 From: nitroflap Date: Tue, 8 Feb 2022 17:13:44 +0300 Subject: [PATCH 04/33] feat: dropped unnecessary tests for New function --- discord_test.go | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/discord_test.go b/discord_test.go index 30d2c75a8..973e3a654 100644 --- a/discord_test.go +++ b/discord_test.go @@ -40,30 +40,6 @@ func init() { ////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// START OF TESTS -// TestNew tests the New() function without any arguments. This should return -// a valid Session{} struct and no errors. -func TestNew(t *testing.T) { - - _, err := New() - if err != nil { - t.Errorf("New() returned error: %+v", err) - } -} - -// TestInvalidToken tests the New() function with an invalid token -func TestInvalidToken(t *testing.T) { - d, err := New("asjkldhflkjasdh") - if err != nil { - t.Fatalf("New(InvalidToken) returned error: %+v", err) - } - - // New with just a token does not do any communication, so attempt an api call. - _, err = d.UserSettings() - if err == nil { - t.Errorf("New(InvalidToken), d.UserSettings returned nil error.") - } -} - // TestNewToken tests the New() function with a Token. func TestNewToken(t *testing.T) { From d5c82ad3746213ae7e0720b13244f242c20e5177 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Tue, 8 Feb 2022 18:25:24 +0300 Subject: [PATCH 05/33] feat(*)!: dropped undocumented endpoints --- endpoints.go | 34 +------ restapi.go | 250 +----------------------------------------------- restapi_test.go | 58 ----------- 3 files changed, 10 insertions(+), 332 deletions(-) diff --git a/endpoints.go b/endpoints.go index fdcbc17dd..400076d8a 100644 --- a/endpoints.go +++ b/endpoints.go @@ -41,26 +41,10 @@ var ( EndpointCDNChannelIcons = EndpointCDN + "channel-icons/" EndpointCDNBanners = EndpointCDN + "banners/" - EndpointAuth = EndpointAPI + "auth/" - EndpointLogin = EndpointAuth + "login" - EndpointLogout = EndpointAuth + "logout" - EndpointVerify = EndpointAuth + "verify" - EndpointVerifyResend = EndpointAuth + "verify/resend" - EndpointForgotPassword = EndpointAuth + "forgot" - EndpointResetPassword = EndpointAuth + "reset" - EndpointRegister = EndpointAuth + "register" - EndpointVoice = EndpointAPI + "/voice/" EndpointVoiceRegions = EndpointVoice + "regions" - EndpointVoiceIce = EndpointVoice + "ice" - - EndpointTutorial = EndpointAPI + "tutorial/" - EndpointTutorialIndicators = EndpointTutorial + "indicators" - EndpointTrack = EndpointAPI + "track" - EndpointSso = EndpointAPI + "sso" - EndpointReport = EndpointAPI + "report" - EndpointIntegrations = EndpointAPI + "integrations" + // TODO: EndpointUserGuildMember EndpointUser = func(uID string) string { return EndpointUsers + uID } EndpointUserAvatar = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" } @@ -69,14 +53,10 @@ var ( uDiscriminatorInt, _ := strconv.Atoi(uDiscriminator) return EndpointCDN + "embed/avatars/" + strconv.Itoa(uDiscriminatorInt%5) + ".png" } - EndpointUserSettings = func(uID string) string { return EndpointUsers + uID + "/settings" } - EndpointUserGuilds = func(uID string) string { return EndpointUsers + uID + "/guilds" } - EndpointUserGuild = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID } - EndpointUserGuildSettings = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID + "/settings" } - EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" } - EndpointUserDevices = func(uID string) string { return EndpointUsers + uID + "/devices" } - EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" } - EndpointUserNotes = func(uID string) string { return EndpointUsers + "@me/notes/" + uID } + EndpointUserGuilds = func(uID string) string { return EndpointUsers + uID + "/guilds" } + EndpointUserGuild = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID } + EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" } + EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" } EndpointGuild = func(gID string) string { return EndpointGuilds + gID } EndpointGuildPreview = func(gID string) string { return EndpointGuilds + gID + "/preview" } @@ -171,10 +151,6 @@ var ( return EndpointWebhookMessage(aID, iToken, mID) } - EndpointRelationships = func() string { return EndpointUsers + "@me" + "/relationships" } - EndpointRelationship = func(uID string) string { return EndpointRelationships() + "/" + uID } - EndpointRelationshipsMutual = func(uID string) string { return EndpointUsers + uID + "/relationships" } - EndpointGuildCreate = EndpointAPI + "guilds" EndpointInvite = func(iID string) string { return EndpointAPI + "invites/" + iID } diff --git a/restapi.go b/restapi.go index 61fcd5fa6..955c5eeb7 100644 --- a/restapi.go +++ b/restapi.go @@ -182,91 +182,6 @@ func unmarshal(data []byte, v interface{}) error { return nil } -// ------------------------------------------------------------------------------------------------ -// Functions specific to Discord Sessions -// ------------------------------------------------------------------------------------------------ - -// Login asks the Discord server for an authentication token. -// -// NOTE: While email/pass authentication is supported by DiscordGo it is -// HIGHLY DISCOURAGED by Discord. Please only use email/pass to obtain a token -// and then use that authentication token for all future connections. -// Also, doing any form of automation with a user (non Bot) account may result -// in that account being permanently banned from Discord. -func (s *Session) Login(email, password string) (err error) { - - data := struct { - Email string `json:"email"` - Password string `json:"password"` - }{email, password} - - response, err := s.RequestWithBucketID("POST", EndpointLogin, data, EndpointLogin) - if err != nil { - return - } - - temp := struct { - Token string `json:"token"` - MFA bool `json:"mfa"` - }{} - - err = unmarshal(response, &temp) - if err != nil { - return - } - - s.Token = temp.Token - s.MFA = temp.MFA - return -} - -// Register sends a Register request to Discord, and returns the authentication token -// Note that this account is temporary and should be verified for future use. -// Another option is to save the authentication token external, but this isn't recommended. -func (s *Session) Register(username string) (token string, err error) { - - data := struct { - Username string `json:"username"` - }{username} - - response, err := s.RequestWithBucketID("POST", EndpointRegister, data, EndpointRegister) - if err != nil { - return - } - - temp := struct { - Token string `json:"token"` - }{} - - err = unmarshal(response, &temp) - if err != nil { - return - } - - token = temp.Token - return -} - -// Logout sends a logout request to Discord. -// This does not seem to actually invalidate the token. So you can still -// make API calls even after a Logout. So, it seems almost pointless to -// even use. -func (s *Session) Logout() (err error) { - - // _, err = s.Request("POST", LOGOUT, `{"token": "` + s.Token + `"}`) - - if s.Token == "" { - return - } - - data := struct { - Token string `json:"token"` - }{s.Token} - - _, err = s.RequestWithBucketID("POST", EndpointLogout, data, EndpointLogout) - return -} - // ------------------------------------------------------------------------------------------------ // Functions specific to Discord Users // ------------------------------------------------------------------------------------------------ @@ -307,8 +222,8 @@ func (s *Session) UserAvatarDecode(u *User) (img image.Image, err error) { return } -// UserUpdate updates a users settings. -func (s *Session) UserUpdate(email, password, username, avatar, newPassword string) (st *User, err error) { +// UserUpdate updates current user settings. +func (s *Session) UserUpdate(username, avatar string) (st *User, err error) { // NOTE: Avatar must be either the hash/id of existing Avatar or // data:image/png;base64,BASE64_STRING_OF_NEW_AVATAR_PNG @@ -316,12 +231,9 @@ func (s *Session) UserUpdate(email, password, username, avatar, newPassword stri // If left blank, avatar will be set to null/blank data := struct { - Email string `json:"email,omitempty"` - Password string `json:"password,omitempty"` - Username string `json:"username,omitempty"` - Avatar string `json:"avatar,omitempty"` - NewPassword string `json:"new_password,omitempty"` - }{email, password, username, avatar, newPassword} + Username string `json:"username,omitempty"` + Avatar string `json:"avatar,omitempty"` + }{username, avatar} body, err := s.RequestWithBucketID("PATCH", EndpointUser("@me"), data, EndpointUsers) if err != nil { @@ -332,39 +244,6 @@ func (s *Session) UserUpdate(email, password, username, avatar, newPassword stri return } -// UserSettings returns the settings for a given user -func (s *Session) UserSettings() (st *Settings, err error) { - - body, err := s.RequestWithBucketID("GET", EndpointUserSettings("@me"), nil, EndpointUserSettings("")) - if err != nil { - return - } - - err = unmarshal(body, &st) - return -} - -// UserUpdateStatus update the user status -// status : The new status (Actual valid status are 'online','idle','dnd','invisible') -func (s *Session) UserUpdateStatus(status Status) (st *Settings, err error) { - if status == StatusOffline { - err = ErrStatusOffline - return - } - - data := struct { - Status Status `json:"status"` - }{status} - - body, err := s.RequestWithBucketID("PATCH", EndpointUserSettings("@me"), data, EndpointUserSettings("")) - if err != nil { - return - } - - err = unmarshal(body, &st) - return -} - // UserConnections returns the user's connections func (s *Session) UserConnections() (conn []*UserConnection, err error) { response, err := s.RequestWithBucketID("GET", EndpointUserConnections("@me"), nil, EndpointUserConnections("@me")) @@ -380,19 +259,6 @@ func (s *Session) UserConnections() (conn []*UserConnection, err error) { return } -// UserChannels returns an array of Channel structures for all private -// channels. -func (s *Session) UserChannels() (st []*Channel, err error) { - - body, err := s.RequestWithBucketID("GET", EndpointUserChannels("@me"), nil, EndpointUserChannels("")) - if err != nil { - return - } - - err = unmarshal(body, &st) - return -} - // UserChannelCreate creates a new User (Private) Channel with another User // recipientID : A user ID for the user to which this channel is opened with. func (s *Session) UserChannelCreate(recipientID string) (st *Channel, err error) { @@ -443,20 +309,6 @@ func (s *Session) UserGuilds(limit int, beforeID, afterID string) (st []*UserGui return } -// UserGuildSettingsEdit Edits the users notification settings for a guild -// guildID : The ID of the guild to edit the settings on -// settings : The settings to update -func (s *Session) UserGuildSettingsEdit(guildID string, settings *UserGuildSettingsEdit) (st *UserGuildSettings, err error) { - - body, err := s.RequestWithBucketID("PATCH", EndpointUserGuildSettings("@me", guildID), settings, EndpointUserGuildSettings("", guildID)) - if err != nil { - return - } - - err = unmarshal(body, &st) - return -} - // UserChannelPermissions returns the permission of a user in a channel. // userID : The ID of the user to calculate permissions for. // channelID : The ID of the channel to calculate permission for. @@ -1958,18 +1810,6 @@ func (s *Session) VoiceRegions() (st []*VoiceRegion, err error) { return } -// VoiceICE returns the voice server ICE information -func (s *Session) VoiceICE() (st *VoiceICE, err error) { - - body, err := s.RequestWithBucketID("GET", EndpointVoiceIce, nil, EndpointVoiceIce) - if err != nil { - return - } - - err = unmarshal(body, &st) - return -} - // ------------------------------------------------------------------------------------------------ // Functions specific to Discord Websockets // ------------------------------------------------------------------------------------------------ @@ -2348,86 +2188,6 @@ func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit i return } -// ------------------------------------------------------------------------------------------------ -// Functions specific to user notes -// ------------------------------------------------------------------------------------------------ - -// UserNoteSet sets the note for a specific user. -func (s *Session) UserNoteSet(userID string, message string) (err error) { - data := struct { - Note string `json:"note"` - }{message} - - _, err = s.RequestWithBucketID("PUT", EndpointUserNotes(userID), data, EndpointUserNotes("")) - return -} - -// ------------------------------------------------------------------------------------------------ -// Functions specific to Discord Relationships (Friends list) -// ------------------------------------------------------------------------------------------------ - -// RelationshipsGet returns an array of all the relationships of the user. -func (s *Session) RelationshipsGet() (r []*Relationship, err error) { - body, err := s.RequestWithBucketID("GET", EndpointRelationships(), nil, EndpointRelationships()) - if err != nil { - return - } - - err = unmarshal(body, &r) - return -} - -// relationshipCreate creates a new relationship. (I.e. send or accept a friend request, block a user.) -// relationshipType : 1 = friend, 2 = blocked, 3 = incoming friend req, 4 = sent friend req -func (s *Session) relationshipCreate(userID string, relationshipType int) (err error) { - data := struct { - Type int `json:"type"` - }{relationshipType} - - _, err = s.RequestWithBucketID("PUT", EndpointRelationship(userID), data, EndpointRelationships()) - return -} - -// RelationshipFriendRequestSend sends a friend request to a user. -// userID: ID of the user. -func (s *Session) RelationshipFriendRequestSend(userID string) (err error) { - err = s.relationshipCreate(userID, 4) - return -} - -// RelationshipFriendRequestAccept accepts a friend request from a user. -// userID: ID of the user. -func (s *Session) RelationshipFriendRequestAccept(userID string) (err error) { - err = s.relationshipCreate(userID, 1) - return -} - -// RelationshipUserBlock blocks a user. -// userID: ID of the user. -func (s *Session) RelationshipUserBlock(userID string) (err error) { - err = s.relationshipCreate(userID, 2) - return -} - -// RelationshipDelete removes the relationship with a user. -// userID: ID of the user. -func (s *Session) RelationshipDelete(userID string) (err error) { - _, err = s.RequestWithBucketID("DELETE", EndpointRelationship(userID), nil, EndpointRelationships()) - return -} - -// RelationshipsMutualGet returns an array of all the users both @me and the given user is friends with. -// userID: ID of the user. -func (s *Session) RelationshipsMutualGet(userID string) (mf []*User, err error) { - body, err := s.RequestWithBucketID("GET", EndpointRelationshipsMutual(userID), nil, EndpointRelationshipsMutual(userID)) - if err != nil { - return - } - - err = unmarshal(body, &mf) - return -} - // ------------------------------------------------------------------------------------------------ // Functions specific to application (slash) commands // ------------------------------------------------------------------------------------------------ diff --git a/restapi_test.go b/restapi_test.go index 6f52ed349..2e23a58df 100644 --- a/restapi_test.go +++ b/restapi_test.go @@ -99,17 +99,6 @@ func TestUserChannelCreate(t *testing.T) { // TODO make sure the channel was added } -func TestUserChannels(t *testing.T) { - if dg == nil { - t.Skip("Cannot TestUserChannels, dg not set.") - } - - _, err := dg.UserChannels() - if err != nil { - t.Errorf(err.Error()) - } -} - func TestUserGuilds(t *testing.T) { if dg == nil { t.Skip("Cannot TestUserGuilds, dg not set.") @@ -121,41 +110,6 @@ func TestUserGuilds(t *testing.T) { } } -func TestUserSettings(t *testing.T) { - if dg == nil { - t.Skip("Cannot TestUserSettings, dg not set.") - } - - _, err := dg.UserSettings() - if err != nil { - t.Errorf(err.Error()) - } -} - -func TestUserUpdateStatus(t *testing.T) { - if dg == nil { - t.Skip("Cannot TestUserSettings, dg not set.") - } - - _, err := dg.UserUpdateStatus(StatusDoNotDisturb) - if err != nil { - t.Errorf(err.Error()) - } -} - -// TestLogout tests the Logout() function. This should not return an error. -func TestLogout(t *testing.T) { - - if dg == nil { - t.Skip("Cannot TestLogout, dg not set.") - } - - err := dg.Logout() - if err != nil { - t.Errorf("Logout() returned error: %+v", err) - } -} - func TestGateway(t *testing.T) { if dg == nil { @@ -178,18 +132,6 @@ func TestGatewayBot(t *testing.T) { } } -func TestVoiceICE(t *testing.T) { - - if dg == nil { - t.Skip("Skipping, dg not set.") - } - - _, err := dg.VoiceICE() - if err != nil { - t.Errorf("VoiceICE() returned error: %+v", err) - } -} - func TestVoiceRegions(t *testing.T) { if dg == nil { From a8b351019fc29c0f1ca9d565ade81f039eb0bd4d Mon Sep 17 00:00:00 2001 From: nitroflap Date: Tue, 8 Feb 2022 20:43:43 +0300 Subject: [PATCH 06/33] feat(*): dropped more undocumented endpoints --- endpoints.go | 58 ++++++++++++++++++++++++---------------------------- restapi.go | 24 ---------------------- 2 files changed, 27 insertions(+), 55 deletions(-) diff --git a/endpoints.go b/endpoints.go index 400076d8a..5124394ad 100644 --- a/endpoints.go +++ b/endpoints.go @@ -58,42 +58,40 @@ var ( EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" } EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" } - EndpointGuild = func(gID string) string { return EndpointGuilds + gID } - EndpointGuildPreview = func(gID string) string { return EndpointGuilds + gID + "/preview" } - EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" } - EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" } - EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID } - EndpointGuildMemberRole = func(gID, uID, rID string) string { return EndpointGuilds + gID + "/members/" + uID + "/roles/" + rID } - EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" } - EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID } - EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" } - EndpointGuildIntegration = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID } - EndpointGuildIntegrationSync = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID + "/sync" } - EndpointGuildRoles = func(gID string) string { return EndpointGuilds + gID + "/roles" } - EndpointGuildRole = func(gID, rID string) string { return EndpointGuilds + gID + "/roles/" + rID } - EndpointGuildInvites = func(gID string) string { return EndpointGuilds + gID + "/invites" } - EndpointGuildWidget = func(gID string) string { return EndpointGuilds + gID + "/widget" } - EndpointGuildEmbed = EndpointGuildWidget - EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" } - EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" } - EndpointGuildIconAnimated = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".gif" } - EndpointGuildSplash = func(gID, hash string) string { return EndpointCDNSplashes + gID + "/" + hash + ".png" } - EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" } - EndpointGuildAuditLogs = func(gID string) string { return EndpointGuilds + gID + "/audit-logs" } - EndpointGuildEmojis = func(gID string) string { return EndpointGuilds + gID + "/emojis" } - EndpointGuildEmoji = func(gID, eID string) string { return EndpointGuilds + gID + "/emojis/" + eID } - EndpointGuildBanner = func(gID, hash string) string { return EndpointCDNBanners + gID + "/" + hash + ".png" } - EndpointGuildStickers = func(gID string) string { return EndpointGuilds + gID + "/stickers" } - EndpointGuildSticker = func(gID, sID string) string { return EndpointGuilds + gID + "/stickers/" + sID } + EndpointGuild = func(gID string) string { return EndpointGuilds + gID } + EndpointGuildPreview = func(gID string) string { return EndpointGuilds + gID + "/preview" } + EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" } + EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" } + EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID } + EndpointGuildMemberRole = func(gID, uID, rID string) string { return EndpointGuilds + gID + "/members/" + uID + "/roles/" + rID } + EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" } + EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID } + EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" } + EndpointGuildIntegration = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID } + EndpointGuildRoles = func(gID string) string { return EndpointGuilds + gID + "/roles" } + EndpointGuildRole = func(gID, rID string) string { return EndpointGuilds + gID + "/roles/" + rID } + EndpointGuildInvites = func(gID string) string { return EndpointGuilds + gID + "/invites" } + EndpointGuildWidget = func(gID string) string { return EndpointGuilds + gID + "/widget" } + EndpointGuildEmbed = EndpointGuildWidget + EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" } + EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" } + EndpointGuildIconAnimated = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".gif" } + EndpointGuildSplash = func(gID, hash string) string { return EndpointCDNSplashes + gID + "/" + hash + ".png" } + EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" } + EndpointGuildAuditLogs = func(gID string) string { return EndpointGuilds + gID + "/audit-logs" } + EndpointGuildEmojis = func(gID string) string { return EndpointGuilds + gID + "/emojis" } + EndpointGuildEmoji = func(gID, eID string) string { return EndpointGuilds + gID + "/emojis/" + eID } + EndpointGuildBanner = func(gID, hash string) string { return EndpointCDNBanners + gID + "/" + hash + ".png" } + EndpointGuildStickers = func(gID string) string { return EndpointGuilds + gID + "/stickers" } + EndpointGuildSticker = func(gID, sID string) string { return EndpointGuilds + gID + "/stickers/" + sID } EndpointChannel = func(cID string) string { return EndpointChannels + cID } EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" } - EndpointChannelPermission = func(cID, tID string) string { return EndpointChannels + cID + "/permissions/" + tID } + EndpointChannelPermission = func(cID, tID string) string { return EndpointChannelPermissions(cID) + "/" + tID } EndpointChannelInvites = func(cID string) string { return EndpointChannels + cID + "/invites" } EndpointChannelTyping = func(cID string) string { return EndpointChannels + cID + "/typing" } EndpointChannelMessages = func(cID string) string { return EndpointChannels + cID + "/messages" } EndpointChannelMessage = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID } - EndpointChannelMessageAck = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID + "/ack" } EndpointChannelMessagesBulkDelete = func(cID string) string { return EndpointChannel(cID) + "/messages/bulk-delete" } EndpointChannelMessagesPins = func(cID string) string { return EndpointChannel(cID) + "/pins" } EndpointChannelMessagePin = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID } @@ -155,8 +153,6 @@ var ( EndpointInvite = func(iID string) string { return EndpointAPI + "invites/" + iID } - EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" } - EndpointEmoji = func(eID string) string { return EndpointCDN + "emojis/" + eID + ".png" } EndpointEmojiAnimated = func(eID string) string { return EndpointCDN + "emojis/" + eID + ".gif" } diff --git a/restapi.go b/restapi.go index 955c5eeb7..74ba48282 100644 --- a/restapi.go +++ b/restapi.go @@ -1100,15 +1100,6 @@ func (s *Session) GuildIntegrationDelete(guildID, integrationID string) (err err return } -// GuildIntegrationSync syncs an integration. -// guildID : The ID of a Guild. -// integrationID : The ID of an integration. -func (s *Session) GuildIntegrationSync(guildID, integrationID string) (err error) { - - _, err = s.RequestWithBucketID("POST", EndpointGuildIntegrationSync(guildID, integrationID), nil, EndpointGuildIntegration(guildID, "")) - return -} - // GuildIcon returns an image.Image of a guild icon. // guildID : The ID of a Guild. func (s *Session) GuildIcon(guildID string) (img image.Image, err error) { @@ -1388,21 +1379,6 @@ func (s *Session) ChannelMessage(channelID, messageID string) (st *Message, err return } -// ChannelMessageAck acknowledges and marks the given message as read -// channeld : The ID of a Channel -// messageID : the ID of a Message -// lastToken : token returned by last ack -func (s *Session) ChannelMessageAck(channelID, messageID, lastToken string) (st *Ack, err error) { - - body, err := s.RequestWithBucketID("POST", EndpointChannelMessageAck(channelID, messageID), &Ack{Token: lastToken}, EndpointChannelMessageAck(channelID, "")) - if err != nil { - return - } - - err = unmarshal(body, &st) - return -} - // ChannelMessageSend sends a message to the given channel. // channelID : The ID of a Channel. // content : The message to send. From a0095c14ed964b9fe8de42b67c98b6167d6eb4f2 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 9 Feb 2022 03:39:28 +0300 Subject: [PATCH 07/33] chore(components): rename InputText to TextInput --- components.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/components.go b/components.go index b7b4708e7..6c68de845 100644 --- a/components.go +++ b/components.go @@ -13,7 +13,7 @@ const ( ActionsRowComponent ComponentType = 1 ButtonComponent ComponentType = 2 SelectMenuComponent ComponentType = 3 - InputTextComponent ComponentType = 4 + TextInputComponent ComponentType = 4 ) // MessageComponent is a base interface for all message components. @@ -43,8 +43,8 @@ func (umc *unmarshalableMessageComponent) UnmarshalJSON(src []byte) error { umc.MessageComponent = &Button{} case SelectMenuComponent: umc.MessageComponent = &SelectMenu{} - case InputTextComponent: - umc.MessageComponent = &InputText{} + case TextInputComponent: + umc.MessageComponent = &TextInput{} default: return fmt.Errorf("unknown component type: %d", v.Type) } @@ -199,8 +199,8 @@ func (m SelectMenu) MarshalJSON() ([]byte, error) { }) } -// InputText represents text input component. -type InputText struct { +// TextInput represents text input component. +type TextInput struct { CustomID string `json:"custom_id,omitempty"` Label string `json:"label"` Style TextStyleType `json:"style"` @@ -212,13 +212,13 @@ type InputText struct { } // Type is a method to get the type of a component. -func (InputText) Type() ComponentType { - return InputTextComponent +func (TextInput) Type() ComponentType { + return TextInputComponent } -// MarshalJSON is a method for marshaling InputText to a JSON object. -func (m InputText) MarshalJSON() ([]byte, error) { - type inputText InputText +// MarshalJSON is a method for marshaling TextInput to a JSON object. +func (m TextInput) MarshalJSON() ([]byte, error) { + type inputText TextInput return json.Marshal(struct { inputText @@ -229,7 +229,7 @@ func (m InputText) MarshalJSON() ([]byte, error) { }) } -// TextStyleType is style of text in InputText component. +// TextStyleType is style of text in TextInput component. type TextStyleType uint // Text styles From 1b48b9b22e0b58e173fce5d3abda3e4b9395c3c9 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 9 Feb 2022 03:45:50 +0300 Subject: [PATCH 08/33] fix(examples/modals): renamed InputText to TextInput --- examples/modals/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/modals/main.go b/examples/modals/main.go index 0a38c54de..284814e42 100644 --- a/examples/modals/main.go +++ b/examples/modals/main.go @@ -51,7 +51,7 @@ var ( Components: []discordgo.MessageComponent{ discordgo.ActionsRow{ Components: []discordgo.MessageComponent{ - discordgo.InputText{ + discordgo.TextInput{ CustomID: "opinion", Label: "What is your opinion on them?", Style: discordgo.TextStyleShort, @@ -63,7 +63,7 @@ var ( }, discordgo.ActionsRow{ Components: []discordgo.MessageComponent{ - discordgo.InputText{ + discordgo.TextInput{ CustomID: "suggestions", Label: "What would you suggest to improve them?", Style: discordgo.TextStyleParagraph, From 19d46d852a7a8b69b930290b2286c99ddc71b93d Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 9 Feb 2022 03:46:09 +0300 Subject: [PATCH 09/33] feat(examples/modals): added MinLength --- examples/modals/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/modals/main.go b/examples/modals/main.go index 284814e42..bdb3960aa 100644 --- a/examples/modals/main.go +++ b/examples/modals/main.go @@ -58,6 +58,7 @@ var ( Placeholder: "Don't be shy, share your opinion with us", Required: true, MaxLength: 300, + MinLength: 10, }, }, }, From dcf6fe0128ee0e6456357e758120e28ff0dbcbd6 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 9 Feb 2022 03:47:44 +0300 Subject: [PATCH 10/33] fix(examples/modals): more renaming of InputText to TextInput --- examples/modals/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/modals/main.go b/examples/modals/main.go index bdb3960aa..90e9887d6 100644 --- a/examples/modals/main.go +++ b/examples/modals/main.go @@ -115,8 +115,8 @@ func main() { _, err = s.ChannelMessageSend(*ResultsChannel, fmt.Sprintf( "Feedback received. From <@%s>\n\n**Opinion**:\n%s\n\n**Suggestions**:\n%s", userid, - data.Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.InputText).Value, - data.Components[1].(*discordgo.ActionsRow).Components[0].(*discordgo.InputText).Value, + data.Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value, + data.Components[1].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput).Value, )) if err != nil { panic(err) From 147703db8e8d13f5099d56af059aa0c8267f28ae Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Wed, 9 Feb 2022 03:58:16 +0300 Subject: [PATCH 11/33] feat(components): renamed TextStyleType to TextInputStyleType --- components.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components.go b/components.go index 6c68de845..b2943c58a 100644 --- a/components.go +++ b/components.go @@ -229,11 +229,11 @@ func (m TextInput) MarshalJSON() ([]byte, error) { }) } -// TextStyleType is style of text in TextInput component. -type TextStyleType uint +// TextInputStyleType is style of text in TextInput component. +type TextInputStyleType uint // Text styles const ( - TextStyleShort TextStyleType = 1 - TextStyleParagraph TextStyleType = 2 + TextInputShort TextStyleType = 1 + TextInputParagraph TextStyleType = 2 ) From f4ad6e85ea5003719556676351d899dc8932ed7d Mon Sep 17 00:00:00 2001 From: constantoine Date: Wed, 9 Feb 2022 11:23:02 +0100 Subject: [PATCH 12/33] Add MessageFlags values --- message.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/message.go b/message.go index 7bde46f72..6252a4f27 100644 --- a/message.go +++ b/message.go @@ -178,11 +178,24 @@ type MessageFlags int // Valid MessageFlags values const ( - MessageFlagsCrossPosted MessageFlags = 1 << 0 - MessageFlagsIsCrossPosted MessageFlags = 1 << 1 - MessageFlagsSupressEmbeds MessageFlags = 1 << 2 - MessageFlagsSourceMessageDeleted MessageFlags = 1 << 3 - MessageFlagsUrgent MessageFlags = 1 << 4 + // MessageFlagsCrossPosted This message has been published to subscribed channels (via Channel Following). + MessageFlagsCrossPosted MessageFlags = 1 << iota + // MessageFlagsIsCrossPosted this message originated from a message in another channel (via Channel Following). + MessageFlagsIsCrossPosted + // MessageFlagsSupressEmbeds do not include any embeds when serializing this message. + MessageFlagsSupressEmbeds + // MessageFlagsSourceMessageDeleted the source message for this crosspost has been deleted (via Channel Following). + MessageFlagsSourceMessageDeleted + // MessageFlagsUrgent this message came from the urgent message system. + MessageFlagsUrgent + // MessageFlagsHasThread this message has an associated thread, with the same id as the message. + MessageFlagsHasThread + // MessageFlagsEphemeral this message is only visible to the user who invoked the Interaction. + MessageFlagsEphemeral + // MessageFlagsLoading this message is an Interaction Response and the bot is "thinking". + MessageFlagsLoading + // MessageFlagsFailedToMentionSomeRolesInThread this message failed to mention some roles and add their members to the thread. + MessageFlagsFailedToMentionSomeRolesInThread ) // File stores info about files you e.g. send in messages. From 7248e0673e05b14b16e9747586a224dbf60e151a Mon Sep 17 00:00:00 2001 From: constantoine Date: Wed, 9 Feb 2022 11:59:10 +0100 Subject: [PATCH 13/33] Explicit values --- message.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/message.go b/message.go index 6252a4f27..ef7f83fd3 100644 --- a/message.go +++ b/message.go @@ -179,23 +179,23 @@ type MessageFlags int // Valid MessageFlags values const ( // MessageFlagsCrossPosted This message has been published to subscribed channels (via Channel Following). - MessageFlagsCrossPosted MessageFlags = 1 << iota + MessageFlagsCrossPosted MessageFlags = 1 << 0 // MessageFlagsIsCrossPosted this message originated from a message in another channel (via Channel Following). - MessageFlagsIsCrossPosted + MessageFlagsIsCrossPosted MessageFlags = 1 << 1 // MessageFlagsSupressEmbeds do not include any embeds when serializing this message. - MessageFlagsSupressEmbeds + MessageFlagsSupressEmbeds MessageFlags = 1 << 2 // MessageFlagsSourceMessageDeleted the source message for this crosspost has been deleted (via Channel Following). - MessageFlagsSourceMessageDeleted + MessageFlagsSourceMessageDeleted MessageFlags = 1 << 3 // MessageFlagsUrgent this message came from the urgent message system. - MessageFlagsUrgent + MessageFlagsUrgent MessageFlags = 1 << 4 // MessageFlagsHasThread this message has an associated thread, with the same id as the message. - MessageFlagsHasThread + MessageFlagsHasThread MessageFlags = 1 << 5 // MessageFlagsEphemeral this message is only visible to the user who invoked the Interaction. - MessageFlagsEphemeral + MessageFlagsEphemeral MessageFlags = 1 << 6 // MessageFlagsLoading this message is an Interaction Response and the bot is "thinking". - MessageFlagsLoading + MessageFlagsLoading MessageFlags = 1 << 7 // MessageFlagsFailedToMentionSomeRolesInThread this message failed to mention some roles and add their members to the thread. - MessageFlagsFailedToMentionSomeRolesInThread + MessageFlagsFailedToMentionSomeRolesInThread MessageFlags = 1 << 8 ) // File stores info about files you e.g. send in messages. From 21ba398898a50ec5c426225981c4ef9371c44293 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Wed, 9 Feb 2022 14:07:36 +0300 Subject: [PATCH 14/33] feat(components): add omitempty and use TextInputStyle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ToπSenpai <15636011+TopiSenpai@users.noreply.github.com> --- components.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components.go b/components.go index b2943c58a..1f4ba58fb 100644 --- a/components.go +++ b/components.go @@ -201,13 +201,13 @@ func (m SelectMenu) MarshalJSON() ([]byte, error) { // TextInput represents text input component. type TextInput struct { - CustomID string `json:"custom_id,omitempty"` + CustomID string `json:"custom_id"` Label string `json:"label"` - Style TextStyleType `json:"style"` + Style TextInputStyle `json:"style"` Placeholder string `json:"placeholder,omitempty"` Value string `json:"value,omitempty"` - Required bool `json:"required"` - MinLength int `json:"min_length"` + Required bool `json:"required,omitempty"` + MinLength int `json:"min_length,omitempty"` MaxLength int `json:"max_length,omitempty"` } From e6b33f37b70abcafeee8c3422c0c09eee7d6c870 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 9 Feb 2022 14:12:31 +0300 Subject: [PATCH 15/33] fix(components): renamed TextInputStyleType to TextInputStyle and fixed example --- components.go | 22 +++++++++++----------- examples/modals/main.go | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components.go b/components.go index 1f4ba58fb..4537bb26a 100644 --- a/components.go +++ b/components.go @@ -201,14 +201,14 @@ func (m SelectMenu) MarshalJSON() ([]byte, error) { // TextInput represents text input component. type TextInput struct { - CustomID string `json:"custom_id"` - Label string `json:"label"` + CustomID string `json:"custom_id"` + Label string `json:"label"` Style TextInputStyle `json:"style"` - Placeholder string `json:"placeholder,omitempty"` - Value string `json:"value,omitempty"` - Required bool `json:"required,omitempty"` - MinLength int `json:"min_length,omitempty"` - MaxLength int `json:"max_length,omitempty"` + Placeholder string `json:"placeholder,omitempty"` + Value string `json:"value,omitempty"` + Required bool `json:"required,omitempty"` + MinLength int `json:"min_length,omitempty"` + MaxLength int `json:"max_length,omitempty"` } // Type is a method to get the type of a component. @@ -229,11 +229,11 @@ func (m TextInput) MarshalJSON() ([]byte, error) { }) } -// TextInputStyleType is style of text in TextInput component. -type TextInputStyleType uint +// TextInputStyle is style of text in TextInput component. +type TextInputStyle uint // Text styles const ( - TextInputShort TextStyleType = 1 - TextInputParagraph TextStyleType = 2 + TextInputShort TextInputStyle = 1 + TextInputParagraph TextInputStyle = 2 ) diff --git a/examples/modals/main.go b/examples/modals/main.go index 90e9887d6..effd8f1a3 100644 --- a/examples/modals/main.go +++ b/examples/modals/main.go @@ -54,7 +54,7 @@ var ( discordgo.TextInput{ CustomID: "opinion", Label: "What is your opinion on them?", - Style: discordgo.TextStyleShort, + Style: discordgo.TextInputShort, Placeholder: "Don't be shy, share your opinion with us", Required: true, MaxLength: 300, @@ -67,7 +67,7 @@ var ( discordgo.TextInput{ CustomID: "suggestions", Label: "What would you suggest to improve them?", - Style: discordgo.TextStyleParagraph, + Style: discordgo.TextInputParagraph, Required: false, MaxLength: 2000, }, From 3f0e0f86500fd1c8cc8094b2b0006104b75628df Mon Sep 17 00:00:00 2001 From: nitroflap Date: Tue, 15 Feb 2022 23:42:22 +0300 Subject: [PATCH 16/33] fix: typo in comment to New function --- discord.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord.go b/discord.go index 5e7aab2c5..a453a4dea 100644 --- a/discord.go +++ b/discord.go @@ -23,7 +23,7 @@ import ( const VERSION = "0.23.0" // New creates a new Discord session with provided token. -// If the token is for a bot, it must be prefixed with "Bot ". +// If the token is for a bot, it must be prefixed with "Bot " // e.g. "Bot ..." // Or if it is an OAuth2 token, it must be prefixed with "Bearer " // e.g. "Bearer ..." From e44c83a1fc44227fa89d07c5e4ce8fe35e416ff0 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 02:13:29 +0300 Subject: [PATCH 17/33] feat(interactions): added note about modals to InteractionResponse --- interactions.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interactions.go b/interactions.go index b56e46ada..b71ebb130 100644 --- a/interactions.go +++ b/interactions.go @@ -470,6 +470,8 @@ type InteractionResponseData struct { // NOTE: autocomplete interaction only. Choices []*ApplicationCommandOptionChoice `json:"choices,omitempty"` + // NOTE: modal interaction only. + CustomID string `json:"custom_id,omitempty"` Title string `json:"title,omitempty"` } From 195a4c4418d10486b02df93b0488a8a449bc4892 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 02:15:16 +0300 Subject: [PATCH 18/33] fix(interactions): typo in comment to ModalSubmitData --- interactions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interactions.go b/interactions.go index b71ebb130..1658af3b4 100644 --- a/interactions.go +++ b/interactions.go @@ -218,7 +218,7 @@ func (i Interaction) ApplicationCommandData() (data ApplicationCommandInteractio return i.Data.(ApplicationCommandInteractionData) } -// ModalSubmitData is helper function to assert the innter InteractionData to ModalSubmitInteractionData. +// ModalSubmitData is helper function to assert the inner InteractionData to ModalSubmitInteractionData. // Make sure to check that the Type of the interaction is InteractionModalSubmit before calling. func (i Interaction) ModalSubmitData() (data ModalSubmitInteractionData) { if i.Type != InteractionModalSubmit { From a731868627444345ed449b7346e636164cc97825 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 02:16:44 +0300 Subject: [PATCH 19/33] fix(interactions): unnecessary newline between field and comment --- interactions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interactions.go b/interactions.go index 1658af3b4..b65d72b2f 100644 --- a/interactions.go +++ b/interactions.go @@ -140,8 +140,8 @@ type Interaction struct { // The message on which interaction was used. // NOTE: this field is only filled when a button click triggered the interaction. Otherwise it will be nil. - Message *Message `json:"message"` + // The member who invoked this interaction. // NOTE: this field is only filled when the slash command was invoked in a guild; // if it was invoked in a DM, the `User` field will be filled instead. From c26bf45ce0d8db5359e5e82700bedae2cf32e676 Mon Sep 17 00:00:00 2001 From: Pedro Pessoa Date: Wed, 16 Feb 2022 08:50:16 -0300 Subject: [PATCH 20/33] Update auditlog keys and actions (#1098) * update audit log keys and actions * remove unncessary tab * move comments above * feat: corrected comments for audit log change keys * fix: typos in audit log change keys comments and definitions Co-authored-by: nitroflap --- structs.go | 209 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 160 insertions(+), 49 deletions(-) diff --git a/structs.go b/structs.go index 9d7c1fccb..384a56c60 100644 --- a/structs.go +++ b/structs.go @@ -956,53 +956,146 @@ type AuditLogChangeKey string // Block of valid AuditLogChangeKey const ( - AuditLogChangeKeyName AuditLogChangeKey = "name" - AuditLogChangeKeyIconHash AuditLogChangeKey = "icon_hash" - AuditLogChangeKeySplashHash AuditLogChangeKey = "splash_hash" - AuditLogChangeKeyOwnerID AuditLogChangeKey = "owner_id" - AuditLogChangeKeyRegion AuditLogChangeKey = "region" - AuditLogChangeKeyAfkChannelID AuditLogChangeKey = "afk_channel_id" - AuditLogChangeKeyAfkTimeout AuditLogChangeKey = "afk_timeout" - AuditLogChangeKeyMfaLevel AuditLogChangeKey = "mfa_level" - AuditLogChangeKeyVerificationLevel AuditLogChangeKey = "verification_level" - AuditLogChangeKeyExplicitContentFilter AuditLogChangeKey = "explicit_content_filter" + // AuditLogChangeKeyAfkChannelID is sent when afk channel changed (snowflake) - guild + AuditLogChangeKeyAfkChannelID AuditLogChangeKey = "afk_channel_id" + // AuditLogChangeKeyAfkTimeout is sent when afk timeout duration changed (int) - guild + AuditLogChangeKeyAfkTimeout AuditLogChangeKey = "afk_timeout" + // AuditLogChangeKeyAllow is sent when a permission on a text or voice channel was allowed for a role (string) - role + AuditLogChangeKeyAllow AuditLogChangeKey = "allow" + // AudirChangeKeyApplicationID is sent when application id of the added or removed webhook or bot (snowflake) - channel + AuditLogChangeKeyApplicationID AuditLogChangeKey = "application_id" + // AuditLogChangeKeyArchived is sent when thread was archived/unarchived (bool) - thread + AuditLogChangeKeyArchived AuditLogChangeKey = "archived" + // AuditLogChangeKeyAsset is sent when asset is changed (string) - sticker + AuditLogChangeKeyAsset AuditLogChangeKey = "asset" + // AuditLogChangeKeyAutoArchiveDuration is sent when auto archive duration changed (int) - thread + AuditLogChangeKeyAutoArchiveDuration AuditLogChangeKey = "auto_archive_duration" + // AuditLogChangeKeyAvailable is sent when availability of sticker changed (bool) - sticker + AuditLogChangeKeyAvailable AuditLogChangeKey = "available" + // AuditLogChangeKeyAvatarHash is sent when user avatar changed (string) - user + AuditLogChangeKeyAvatarHash AuditLogChangeKey = "avatar_hash" + // AuditLogChangeKeyBannerHash is sent when guild banner changed (string) - guild + AuditLogChangeKeyBannerHash AuditLogChangeKey = "banner_hash" + // AuditLogChangeKeyBitrate is sent when voice channel bitrate changed (int) - channel + AuditLogChangeKeyBitrate AuditLogChangeKey = "bitrate" + // AuditLogChangeKeyChannelID is sent when channel for invite code or guild scheduled event changed (snowflake) - invite or guild scheduled event + AuditLogChangeKeyChannelID AuditLogChangeKey = "channel_id" + // AuditLogChangeKeyCode is sent when invite code changed (string) - invite + AuditLogChangeKeyCode AuditLogChangeKey = "code" + // AuditLogChangeKeyColor is sent when role color changed (int) - role + AuditLogChangeKeyColor AuditLogChangeKey = "color" + // AuditLogChangeKeyCommunicationDisabledUntil is sent when member timeout state changed (ISO8601 timestamp) - member + AuditLogChangeKeyCommunicationDisabledUntil AuditLogChangeKey = "communication_disabled_until" + // AuditLogChangeKeyDeaf is sent when user server deafened/undeafened (bool) - member + AuditLogChangeKeyDeaf AuditLogChangeKey = "deaf" + // AuditLogChangeKeyDefaultAutoArchiveDuration is sent when default auto archive duration for newly created threads changed (int) - channel + AuditLogChangeKeyDefaultAutoArchiveDuration AuditLogChangeKey = "default_auto_archive_duration" + // AuditLogChangeKeyDefaultMessageNotification is sent when default message notification level changed (int) - guild AuditLogChangeKeyDefaultMessageNotification AuditLogChangeKey = "default_message_notifications" - AuditLogChangeKeyVanityURLCode AuditLogChangeKey = "vanity_url_code" - AuditLogChangeKeyRoleAdd AuditLogChangeKey = "$add" - AuditLogChangeKeyRoleRemove AuditLogChangeKey = "$remove" - AuditLogChangeKeyPruneDeleteDays AuditLogChangeKey = "prune_delete_days" - AuditLogChangeKeyWidgetEnabled AuditLogChangeKey = "widget_enabled" - AuditLogChangeKeyWidgetChannelID AuditLogChangeKey = "widget_channel_id" - AuditLogChangeKeySystemChannelID AuditLogChangeKey = "system_channel_id" - AuditLogChangeKeyPosition AuditLogChangeKey = "position" - AuditLogChangeKeyTopic AuditLogChangeKey = "topic" - AuditLogChangeKeyBitrate AuditLogChangeKey = "bitrate" - AuditLogChangeKeyPermissionOverwrite AuditLogChangeKey = "permission_overwrites" - AuditLogChangeKeyNSFW AuditLogChangeKey = "nsfw" - AuditLogChangeKeyApplicationID AuditLogChangeKey = "application_id" - AuditLogChangeKeyRateLimitPerUser AuditLogChangeKey = "rate_limit_per_user" - AuditLogChangeKeyPermissions AuditLogChangeKey = "permissions" - AuditLogChangeKeyColor AuditLogChangeKey = "color" - AuditLogChangeKeyHoist AuditLogChangeKey = "hoist" - AuditLogChangeKeyMentionable AuditLogChangeKey = "mentionable" - AuditLogChangeKeyAllow AuditLogChangeKey = "allow" - AuditLogChangeKeyDeny AuditLogChangeKey = "deny" - AuditLogChangeKeyCode AuditLogChangeKey = "code" - AuditLogChangeKeyChannelID AuditLogChangeKey = "channel_id" - AuditLogChangeKeyInviterID AuditLogChangeKey = "inviter_id" - AuditLogChangeKeyMaxUses AuditLogChangeKey = "max_uses" - AuditLogChangeKeyUses AuditLogChangeKey = "uses" - AuditLogChangeKeyMaxAge AuditLogChangeKey = "max_age" - AuditLogChangeKeyTempoary AuditLogChangeKey = "temporary" - AuditLogChangeKeyDeaf AuditLogChangeKey = "deaf" - AuditLogChangeKeyMute AuditLogChangeKey = "mute" - AuditLogChangeKeyNick AuditLogChangeKey = "nick" - AuditLogChangeKeyAvatarHash AuditLogChangeKey = "avatar_hash" - AuditLogChangeKeyID AuditLogChangeKey = "id" - AuditLogChangeKeyType AuditLogChangeKey = "type" - AuditLogChangeKeyEnableEmoticons AuditLogChangeKey = "enable_emoticons" - AuditLogChangeKeyExpireBehavior AuditLogChangeKey = "expire_behavior" - AuditLogChangeKeyExpireGracePeriod AuditLogChangeKey = "expire_grace_period" + // AuditLogChangeKeyDeny is sent when a permission on a text or voice channel was denied for a role (string) - role + AuditLogChangeKeyDeny AuditLogChangeKey = "deny" + // AuditLogChangeKeyDescription is sent when description changed (string) - guild, sticker, or guild scheduled event + AuditLogChangeKeyDescription AuditLogChangeKey = "description" + // AuditLogChangeKeyDiscoverySplashHash is sent when discovery splash changed (string) - guild + AuditLogChangeKeyDiscoverySplashHash AuditLogChangeKey = "discovery_splash_hash" + // AuditLogChangeKeyEnableEmoticons is sent when integration emoticons enabled/disabled (bool) - integration + AuditLogChangeKeyEnableEmoticons AuditLogChangeKey = "enable_emoticons" + // AuditLogChangeKeyEntityType is sent when entity type of guild scheduled event was changed (int) - guild scheduled event + AuditLogChangeKeyEntityType AuditLogChangeKey = "entity_type" + // AuditLogChangeKeyExpireBehavior is sent when integration expiring subscriber behavior changed (int) - integration + AuditLogChangeKeyExpireBehavior AuditLogChangeKey = "expire_behavior" + // AuditLogChangeKeyExpireGracePeriod is sent when integration expire grace period changed (int) - integration + AuditLogChangeKeyExpireGracePeriod AuditLogChangeKey = "expire_grace_period" + // AuditLogChangeKeyExplicitContentFilter is sent when change in whose messages are scanned and deleted for explicit content in the server is made (int) - guild + AuditLogChangeKeyExplicitContentFilter AuditLogChangeKey = "explicit_content_filter" + // AuditLogChangeKeyFormatType is sent when format type of sticker changed (int - sticker format type) - sticker + AuditLogChangeKeyFormatType AuditLogChangeKey = "format_type" + // AuditLogChangeKeyGuildID is sent when guild sticker is in changed (snowflake) - sticker + AuditLogChangeKeyGuildID AuditLogChangeKey = "guild_id" + // AuditLogChangeKeyHoist is sent when role is now displayed/no longer displayed separate from online users (bool) - role + AuditLogChangeKeyHoist AuditLogChangeKey = "hoist" + // AuditLogChangeKeyIconHash is sent when icon changed (string) - guild or role + AuditLogChangeKeyIconHash AuditLogChangeKey = "icon_hash" + // AuditLogChangeKeyID is sent when the id of the changed entity - sometimes used in conjunction with other keys (snowflake) - any + AuditLogChangeKeyID AuditLogChangeKey = "id" + // AuditLogChangeKeyInvitable is sent when private thread is now invitable/uninvitable (bool) - thread + AuditLogChangeKeyInvitable AuditLogChangeKey = "invitable" + // AuditLogChangeKeyInviterID is sent when person who created invite code changed (snowflake) - invite + AuditLogChangeKeyInviterID AuditLogChangeKey = "inviter_id" + // AuditLogChangeKeyLocation is sent when channel id for guild scheduled event changed (string) - guild scheduled event + AuditLogChangeKeyLocation AuditLogChangeKey = "location" + // AuditLogChangeKeyLocked is sent when thread was locked/unlocked (bool) - thread + AuditLogChangeKeyLocked AuditLogChangeKey = "locked" + // AuditLogChangeKeyMaxAge is sent when invite code expiration time changed (int) - invite + AuditLogChangeKeyMaxAge AuditLogChangeKey = "max_age" + // AuditLogChangeKeyMaxUses is sent when max number of times invite code can be used changed (int) - invite + AuditLogChangeKeyMaxUses AuditLogChangeKey = "max_uses" + // AuditLogChangeKeyMentionable is sent when role is now mentionable/unmentionable (bool) - role + AuditLogChangeKeyMentionable AuditLogChangeKey = "mentionable" + // AuditLogChangeKeyMfaLevel is sent when two-factor auth requirement changed (int - mfa level) - guild + AuditLogChangeKeyMfaLevel AuditLogChangeKey = "mfa_level" + // AuditLogChangeKeyMute is sent when user server muted/unmuted (bool) - member + AuditLogChangeKeyMute AuditLogChangeKey = "mute" + // AuditLogChangeKeyName is sent when name changed (string) - any + AuditLogChangeKeyName AuditLogChangeKey = "name" + // AuditLogChangeKeyNick is sent when user nickname changed (string) - member + AuditLogChangeKeyNick AuditLogChangeKey = "nick" + // AuditLogChangeKeyNSFW is sent when channel nsfw restriction changed (bool) - channel + AuditLogChangeKeyNSFW AuditLogChangeKey = "nsfw" + // AuditLogChangeKeyOwnerID is sent when owner changed (snowflake) - guild + AuditLogChangeKeyOwnerID AuditLogChangeKey = "owner_id" + // AuditLogChangeKeyPermissionOverwrite is sent when permissions on a channel changed (array of channel overwrite objects) - channel + AuditLogChangeKeyPermissionOverwrite AuditLogChangeKey = "permission_overwrites" + // AuditLogChangeKeyPermissions is sent when permissions for a role changed (string) - role + AuditLogChangeKeyPermissions AuditLogChangeKey = "permissions" + // AuditLogChangeKeyPosition is sent when text or voice channel position changed (int) - channel + AuditLogChangeKeyPosition AuditLogChangeKey = "position" + // AuditLogChangeKeyPreferredLocale is sent when preferred locale changed (string) - guild + AuditLogChangeKeyPreferredLocale AuditLogChangeKey = "preferred_locale" + // AuditLogChangeKeyPrivacylevel is sent when privacy level of the stage instance changed (integer - privacy level) - stage instance or guild scheduled event + AuditLogChangeKeyPrivacylevel AuditLogChangeKey = "privacy_level" + // AuditLogChangeKeyPruneDeleteDays is sent when number of days after which inactive and role-unassigned members are kicked changed (int) - guild + AuditLogChangeKeyPruneDeleteDays AuditLogChangeKey = "prune_delete_days" + // AuditLogChangeKeyPulibUpdatesChannelID is sent when id of the public updates channel changed (snowflake) - guild + AuditLogChangeKeyPulibUpdatesChannelID AuditLogChangeKey = "public_updates_channel_id" + // AuditLogChangeKeyRateLimitPerUser is sent when amount of seconds a user has to wait before sending another message changed (int) - channel + AuditLogChangeKeyRateLimitPerUser AuditLogChangeKey = "rate_limit_per_user" + // AuditLogChangeKeyRegion is sent when region changed (string) - guild + AuditLogChangeKeyRegion AuditLogChangeKey = "region" + // AuditLogChangeKeyRulesChannelID is sent when id of the rules channel changed (snowflake) - guild + AuditLogChangeKeyRulesChannelID AuditLogChangeKey = "rules_channel_id" + // AuditLogChangeKeySplashHash is sent when invite splash page artwork changed (string) - guild + AuditLogChangeKeySplashHash AuditLogChangeKey = "splash_hash" + // AuditLogChangeKeyStatus is sent when status of guild scheduled event was changed (int - guild scheduled event status) - guild scheduled event + AuditLogChangeKeyStatus AuditLogChangeKey = "status" + // AuditLogChangeKeySystemChannelID is sent when id of the system channel changed (snowflake) - guild + AuditLogChangeKeySystemChannelID AuditLogChangeKey = "system_channel_id" + // AuditLogChangeKeyTags is sent when related emoji of sticker changed (string) - sticker + AuditLogChangeKeyTags AuditLogChangeKey = "tags" + // AuditLogChangeKeyTemporary is sent when invite code is now temporary or never expires (bool) - invite + AuditLogChangeKeyTemporary AuditLogChangeKey = "temporary" + // AuditLogChangeKeyTopic is sent when text channel topic or stage instance topic changed (string) - channel or stage instance + AuditLogChangeKeyTopic AuditLogChangeKey = "topic" + // AuditLogChangeKeyType is sent when type of entity created (int or string) - any + AuditLogChangeKeyType AuditLogChangeKey = "type" + // AuditLogChangeKeyUnicodeEmoji is sent when role unicode emoji changed (string) - role + AuditLogChangeKeyUnicodeEmoji AuditLogChangeKey = "unicode_emoji" + // AuditLogChangeKeyUserLimit is sent when new user limit in a voice channel set (int) - voice channel + AuditLogChangeKeyUserLimit AuditLogChangeKey = "user_limit" + // AuditLogChangeKeyUses is sent when number of times invite code used changed (int) - invite + AuditLogChangeKeyUses AuditLogChangeKey = "uses" + // AuditLogChangeKeyVanityURLCode is sent when guild invite vanity url changed (string) - guild + AuditLogChangeKeyVanityURLCode AuditLogChangeKey = "vanity_url_code" + // AuditLogChangeKeyVerificationLevel is sent when required verification level changed (int - verification level) - guild + AuditLogChangeKeyVerificationLevel AuditLogChangeKey = "verification_level" + // AuditLogChangeKeyWidgetChannelID is sent when channel id of the server widget changed (snowflake) - guild + AuditLogChangeKeyWidgetChannelID AuditLogChangeKey = "widget_channel_id" + // AuditLogChangeKeyWidgetEnabled is sent when server widget enabled/disabled (bool) - guild + AuditLogChangeKeyWidgetEnabled AuditLogChangeKey = "widget_enabled" + // AuditLogChangeKeyRoleAdd is sent when new role added (array of partial role objects) - guild + AuditLogChangeKeyRoleAdd AuditLogChangeKey = "$add" + // AuditLogChangeKeyRoleRemove is sent when role removed (array of partial role objects) - guild + AuditLogChangeKeyRoleRemove AuditLogChangeKey = "$remove" ) // AuditLogOptions optional data for the AuditLog @@ -1049,6 +1142,9 @@ const ( AuditLogActionMemberBanRemove AuditLogAction = 23 AuditLogActionMemberUpdate AuditLogAction = 24 AuditLogActionMemberRoleUpdate AuditLogAction = 25 + AuditLogActionMemberMove AuditLogAction = 26 + AuditLogActionMemberDisconnect AuditLogAction = 27 + AuditLogActionBotAdd AuditLogAction = 28 AuditLogActionRoleCreate AuditLogAction = 30 AuditLogActionRoleUpdate AuditLogAction = 31 @@ -1071,9 +1167,24 @@ const ( AuditLogActionMessagePin AuditLogAction = 74 AuditLogActionMessageUnpin AuditLogAction = 75 - AuditLogActionIntegrationCreate AuditLogAction = 80 - AuditLogActionIntegrationUpdate AuditLogAction = 81 - AuditLogActionIntegrationDelete AuditLogAction = 82 + AuditLogActionIntegrationCreate AuditLogAction = 80 + AuditLogActionIntegrationUpdate AuditLogAction = 81 + AuditLogActionIntegrationDelete AuditLogAction = 82 + AuditLogActionStageInstanceCreate AuditLogAction = 83 + AuditLogActionStageInstanceUpdate AuditLogAction = 84 + AuditLogActionStageInstanceDelete AuditLogAction = 85 + + AuditLogActionStickerCreate AuditLogAction = 90 + AuditLogActionStickerUpdate AuditLogAction = 91 + AuditLogActionStickerDelete AuditLogAction = 92 + + AuditLogGuildScheduledEventCreate AuditLogAction = 100 + AuditLogGuildScheduledEventUpdare AuditLogAction = 101 + AuditLogGuildScheduledEventDelete AuditLogAction = 102 + + AuditLogActionThreadCreate AuditLogAction = 110 + AuditLogActionThreadUpdate AuditLogAction = 111 + AuditLogActionThreadDelete AuditLogAction = 112 ) // A UserGuildSettingsChannelOverride stores data for a channel override for a users guild settings. From 5ee06354aa7a277da487b427a6790512e1bd0e7e Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 14:57:14 +0300 Subject: [PATCH 21/33] fix: added AuditLogChangeKeyTempoary back for compatibility --- structs.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/structs.go b/structs.go index 384a56c60..60de63dd7 100644 --- a/structs.go +++ b/structs.go @@ -1074,6 +1074,8 @@ const ( AuditLogChangeKeyTags AuditLogChangeKey = "tags" // AuditLogChangeKeyTemporary is sent when invite code is now temporary or never expires (bool) - invite AuditLogChangeKeyTemporary AuditLogChangeKey = "temporary" + // TODO: remove when compatibility is not required + AuditLogChangeKeyTempoary = AuditLogChangeKeyTemporary // AuditLogChangeKeyTopic is sent when text channel topic or stage instance topic changed (string) - channel or stage instance AuditLogChangeKeyTopic AuditLogChangeKey = "topic" // AuditLogChangeKeyType is sent when type of entity created (int or string) - any From 115adf2866b55809fad82b1437ef5efe62dedc3b Mon Sep 17 00:00:00 2001 From: Pedro Pessoa Date: Wed, 16 Feb 2022 09:29:20 -0300 Subject: [PATCH 22/33] add missing json error codes (#1096) * add missing json error codes * Update structs.go Co-authored-by: Fedor Lapshin * Update structs.go Co-authored-by: Fedor Lapshin * requested changes * Update structs.go Co-authored-by: Fedor Lapshin * Update structs.go Co-authored-by: Fedor Lapshin * formatting * add ErrCodeEmbedDisabled back Co-authored-by: Fedor Lapshin --- structs.go | 203 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 154 insertions(+), 49 deletions(-) diff --git a/structs.go b/structs.go index 60de63dd7..2a2369fb5 100644 --- a/structs.go +++ b/structs.go @@ -1449,57 +1449,162 @@ const ( // Block contains Discord JSON Error Response codes const ( - ErrCodeUnknownAccount = 10001 - ErrCodeUnknownApplication = 10002 - ErrCodeUnknownChannel = 10003 - ErrCodeUnknownGuild = 10004 - ErrCodeUnknownIntegration = 10005 - ErrCodeUnknownInvite = 10006 - ErrCodeUnknownMember = 10007 - ErrCodeUnknownMessage = 10008 - ErrCodeUnknownOverwrite = 10009 - ErrCodeUnknownProvider = 10010 - ErrCodeUnknownRole = 10011 - ErrCodeUnknownToken = 10012 - ErrCodeUnknownUser = 10013 - ErrCodeUnknownEmoji = 10014 - ErrCodeUnknownWebhook = 10015 - ErrCodeUnknownBan = 10026 - - ErrCodeBotsCannotUseEndpoint = 20001 - ErrCodeOnlyBotsCanUseEndpoint = 20002 - - ErrCodeMaximumGuildsReached = 30001 - ErrCodeMaximumFriendsReached = 30002 - ErrCodeMaximumPinsReached = 30003 - ErrCodeMaximumGuildRolesReached = 30005 - ErrCodeTooManyReactions = 30010 - - ErrCodeUnauthorized = 40001 - - ErrCodeMissingAccess = 50001 - ErrCodeInvalidAccountType = 50002 - ErrCodeCannotExecuteActionOnDMChannel = 50003 - ErrCodeEmbedDisabled = 50004 - ErrCodeCannotEditFromAnotherUser = 50005 - ErrCodeCannotSendEmptyMessage = 50006 - ErrCodeCannotSendMessagesToThisUser = 50007 - ErrCodeCannotSendMessagesInVoiceChannel = 50008 - ErrCodeChannelVerificationLevelTooHigh = 50009 - ErrCodeOAuth2ApplicationDoesNotHaveBot = 50010 - ErrCodeOAuth2ApplicationLimitReached = 50011 - ErrCodeInvalidOAuthState = 50012 - ErrCodeMissingPermissions = 50013 - ErrCodeInvalidAuthenticationToken = 50014 - ErrCodeNoteTooLong = 50015 - ErrCodeTooFewOrTooManyMessagesToDelete = 50016 - ErrCodeCanOnlyPinMessageToOriginatingChannel = 50019 - ErrCodeCannotExecuteActionOnSystemMessage = 50021 - ErrCodeMessageProvidedTooOldForBulkDelete = 50034 - ErrCodeInvalidFormBody = 50035 - ErrCodeInviteAcceptedToGuildApplicationsBotNotIn = 50036 + ErrCodeGeneralError = 0 + + ErrCodeUnknownAccount = 10001 + ErrCodeUnknownApplication = 10002 + ErrCodeUnknownChannel = 10003 + ErrCodeUnknownGuild = 10004 + ErrCodeUnknownIntegration = 10005 + ErrCodeUnknownInvite = 10006 + ErrCodeUnknownMember = 10007 + ErrCodeUnknownMessage = 10008 + ErrCodeUnknownOverwrite = 10009 + ErrCodeUnknownProvider = 10010 + ErrCodeUnknownRole = 10011 + ErrCodeUnknownToken = 10012 + ErrCodeUnknownUser = 10013 + ErrCodeUnknownEmoji = 10014 + ErrCodeUnknownWebhook = 10015 + ErrCodeUnknownWebhookService = 10016 + ErrCodeUnknownSession = 10020 + ErrCodeUnknownBan = 10026 + ErrCodeUnknownSKU = 10027 + ErrCodeUnknownStoreListing = 10028 + ErrCodeUnknownEntitlement = 10029 + ErrCodeUnknownBuild = 10030 + ErrCodeUnknownLobby = 10031 + ErrCodeUnknownBranch = 10032 + ErrCodeUnknownStoreDirectoryLayout = 10033 + ErrCodeUnknownRedistributable = 10036 + ErrCodeUnknownGiftCode = 10038 + ErrCodeUnknownStream = 10049 + ErrCodeUnknownPremiumServerSubscribeCooldown = 10050 + ErrCodeUnknownGuildTemplate = 10057 + ErrCodeUnknownDiscoveryCategory = 10059 + ErrCodeUnknownSticker = 10060 + ErrCodeUnknownInteraction = 10062 + ErrCodeUnknownApplicationCommand = 10063 + ErrCodeUnknownApplicationCommandPermissions = 10066 + ErrCodeUnknownStageInstance = 10067 + ErrCodeUnknownGuildMemberVerificationForm = 10068 + ErrCodeUnknownGuildWelcomeScreen = 10069 + ErrCodeUnknownGuildScheduledEvent = 10070 + ErrCodeUnknownGuildScheduledEventUser = 10071 + + ErrCodeBotsCannotUseEndpoint = 20001 + ErrCodeOnlyBotsCanUseEndpoint = 20002 + ErrCodeExplicitContentCannotBeSentToTheDesiredRecipients = 20009 + ErrCodeYouAreNotAuthorizedToPerformThisActionOnThisApplication = 20012 + ErrCodeThisActionCannotBePerformedDueToSlowmodeRateLimit = 20016 + ErrCodeOnlyTheOwnerOfThisAccountCanPerformThisAction = 20018 + ErrCodeMessageCannotBeEditedDueToAnnouncementRateLimits = 20022 + ErrCodeChannelHasHitWriteRateLimit = 20028 + ErrCodeTheWriteActionYouArePerformingOnTheServerHasHitTheWriteRateLimit = 20029 + ErrCodeStageTopicContainsNotAllowedWordsForPublicStages = 20031 + ErrCodeGuildPremiumSubscriptionLevelTooLow = 20035 + + ErrCodeMaximumPinsReached = 30003 + ErrCodeMaximumNumberOfRecipientsReached = 30004 + ErrCodeMaximumGuildRolesReached = 30005 + ErrCodeMaximumNumberOfWebhooksReached = 30007 + ErrCodeMaximumNumberOfEmojisReached = 30008 + ErrCodeTooManyReactions = 30010 + ErrCodeMaximumNumberOfGuildChannelsReached = 30013 + ErrCodeMaximumNumberOfAttachmentsInAMessageReached = 30015 + ErrCodeMaximumNumberOfInvitesReached = 30016 + ErrCodeMaximumNumberOfAnimatedEmojisReached = 30018 + ErrCodeMaximumNumberOfServerMembersReached = 30019 + ErrCodeMaximumNumberOfGuildDiscoverySubcategoriesReached = 30030 + ErrCodeGuildAlreadyHasATemplate = 30031 + ErrCodeMaximumNumberOfThreadParticipantsReached = 30033 + ErrCodeMaximumNumberOfBansForNonGuildMembersHaveBeenExceeded = 30035 + ErrCodeMaximumNumberOfBansFetchesHasBeenReached = 30037 + ErrCodeMaximumNumberOfUncompletedGuildScheduledEventsReached = 30038 + ErrCodeMaximumNumberOfStickersReached = 30039 + ErrCodeMaximumNumberOfPruneRequestsHasBeenReached = 30040 + ErrCodeMaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReached = 30042 + ErrCodeMaximumNumberOfEditsToMessagesOlderThanOneHourReached = 30046 + + ErrCodeUnauthorized = 40001 + ErrCodeActionRequiredVerifiedAccount = 40002 + ErrCodeOpeningDirectMessagesTooFast = 40003 + ErrCodeSendMessagesHasBeenTemporarilyDisabled = 40004 + ErrCodeRequestEntityTooLarge = 40005 + ErrCodeFeatureTemporarilyDisabledServerSide = 40006 + ErrCodeUserIsBannedFromThisGuild = 40007 + ErrCodeTargetIsNotConnectedToVoice = 40032 + ErrCodeMessageAlreadyCrossposted = 40033 + ErrCodeAnApplicationWithThatNameAlreadyExists = 40041 + ErrCodeInteractionHasAlreadyBeenAcknowledged = 40060 + + ErrCodeMissingAccess = 50001 + ErrCodeInvalidAccountType = 50002 + ErrCodeCannotExecuteActionOnDMChannel = 50003 + ErrCodeEmbedDisabled = 50004 + ErrCodeGuildWidgetDisabled = 50004 + ErrCodeCannotEditFromAnotherUser = 50005 + ErrCodeCannotSendEmptyMessage = 50006 + ErrCodeCannotSendMessagesToThisUser = 50007 + ErrCodeCannotSendMessagesInVoiceChannel = 50008 + ErrCodeChannelVerificationLevelTooHigh = 50009 + ErrCodeOAuth2ApplicationDoesNotHaveBot = 50010 + ErrCodeOAuth2ApplicationLimitReached = 50011 + ErrCodeInvalidOAuthState = 50012 + ErrCodeMissingPermissions = 50013 + ErrCodeInvalidAuthenticationToken = 50014 + ErrCodeTooFewOrTooManyMessagesToDelete = 50016 + ErrCodeCanOnlyPinMessageToOriginatingChannel = 50019 + ErrCodeInviteCodeWasEitherInvalidOrTaken = 50020 + ErrCodeCannotExecuteActionOnSystemMessage = 50021 + ErrCodeCannotExecuteActionOnThisChannelType = 50024 + ErrCodeInvalidOAuth2AccessTokenProvided = 50025 + ErrCodeMissingRequiredOAuth2Scope = 50026 + ErrCodeInvalidWebhookTokenProvided = 50027 + ErrCodeInvalidRole = 50028 + ErrCodeInvalidRecipients = 50033 + ErrCodeMessageProvidedTooOldForBulkDelete = 50034 + ErrCodeInvalidFormBody = 50035 + ErrCodeInviteAcceptedToGuildApplicationsBotNotIn = 50036 + ErrCodeInvalidAPIVersionProvided = 50041 + ErrCodeFileUploadedExceedsTheMaximumSize = 50045 + ErrCodeInvalidFileUploaded = 50046 + ErrCodeInvalidGuild = 50055 + ErrCodeInvalidMessageType = 50068 + ErrCodeCannotDeleteAChannelRequiredForCommunityGuilds = 50074 + ErrCodeInvalidStickerSent = 50081 + ErrCodePerformedOperationOnArchivedThread = 50083 + ErrCodeBeforeValueIsEarlierThanThreadCreationDate = 50085 + ErrCodeCommunityServerChannelsMustBeTextChannels = 50086 + ErrCodeThisServerIsNotAvailableInYourLocation = 50095 + ErrCodeThisServerNeedsMonetizationEnabledInOrderToPerformThisAction = 50097 + ErrCodeThisServerNeedsMoreBoostsToPerformThisAction = 50101 + ErrCodeTheRequestBodyContainsInvalidJSON = 50109 + + ErrCodeNoUsersWithDiscordTagExist = 80004 ErrCodeReactionBlocked = 90001 + + ErrCodeAPIResourceIsCurrentlyOverloaded = 130000 + + ErrCodeTheStageIsAlreadyOpen = 150006 + + ErrCodeCannotReplyWithoutPermissionToReadMessageHistory = 160002 + ErrCodeThreadAlreadyCreatedForThisMessage = 160004 + ErrCodeThreadIsLocked = 160005 + ErrCodeMaximumNumberOfActiveThreadsReached = 160006 + ErrCodeMaximumNumberOfActiveAnnouncementThreadsReached = 160007 + + ErrCodeInvalidJSONForUploadedLottieFile = 170001 + ErrCodeUploadedLottiesCannotContainRasterizedImages = 170002 + ErrCodeStickerMaximumFramerateExceeded = 170003 + ErrCodeStickerFrameCountExceedsMaximumOfOneThousandFrames = 170004 + ErrCodeLottieAnimationMaximumDimensionsExceeded = 170005 + ErrCodeStickerFrameRateOutOfRange = 170006 + ErrCodeStickerAnimationDurationExceedsMaximumOfFiveSeconds = 170007 + + ErrCodeCannotUpdateAFinishedEvent = 180000 + ErrCodeFailedToCreateStageNeededForStageEvent = 180002 ) // Intent is the type of a Gateway Intent From c871464295222a37fcfafea7a23a0db45d9c9dd7 Mon Sep 17 00:00:00 2001 From: Pedro Pessoa Date: Wed, 16 Feb 2022 09:30:32 -0300 Subject: [PATCH 23/33] update intents (#1097) --- structs.go | 68 +++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/structs.go b/structs.go index 2a2369fb5..29a2eb07a 100644 --- a/structs.go +++ b/structs.go @@ -1613,38 +1613,44 @@ type Intent int // Constants for the different bit offsets of intents const ( - IntentsGuilds Intent = 1 << 0 - IntentsGuildMembers Intent = 1 << 1 - IntentsGuildBans Intent = 1 << 2 - IntentsGuildEmojis Intent = 1 << 3 - IntentsGuildIntegrations Intent = 1 << 4 - IntentsGuildWebhooks Intent = 1 << 5 - IntentsGuildInvites Intent = 1 << 6 - IntentsGuildVoiceStates Intent = 1 << 7 - IntentsGuildPresences Intent = 1 << 8 - IntentsGuildMessages Intent = 1 << 9 - IntentsGuildMessageReactions Intent = 1 << 10 - IntentsGuildMessageTyping Intent = 1 << 11 - IntentsDirectMessages Intent = 1 << 12 - IntentsDirectMessageReactions Intent = 1 << 13 - IntentsDirectMessageTyping Intent = 1 << 14 - - IntentsAllWithoutPrivileged = IntentsGuilds | - IntentsGuildBans | - IntentsGuildEmojis | - IntentsGuildIntegrations | - IntentsGuildWebhooks | - IntentsGuildInvites | - IntentsGuildVoiceStates | - IntentsGuildMessages | - IntentsGuildMessageReactions | - IntentsGuildMessageTyping | - IntentsDirectMessages | - IntentsDirectMessageReactions | - IntentsDirectMessageTyping + IntentGuilds Intent = 1 << 0 + IntentGuildMembers Intent = 1 << 1 + IntentGuildBans Intent = 1 << 2 + IntentGuildEmojis Intent = 1 << 3 + IntentGuildIntegrations Intent = 1 << 4 + IntentGuildWebhooks Intent = 1 << 5 + IntentGuildInvites Intent = 1 << 6 + IntentGuildVoiceStates Intent = 1 << 7 + IntentGuildPresences Intent = 1 << 8 + IntentGuildMessages Intent = 1 << 9 + IntentGuildMessageReactions Intent = 1 << 10 + IntentGuildMessageTyping Intent = 1 << 11 + IntentDirectMessages Intent = 1 << 12 + IntentDirectMessageReactions Intent = 1 << 13 + IntentDirectMessageTyping Intent = 1 << 14 + IntentMessageContent Intent = 1 << 15 + IntentGuildScheduledEvents Intent = 1 << 16 + + IntentsAllWithoutPrivileged = IntentGuilds | + IntentGuildBans | + IntentGuildEmojis | + IntentGuildIntegrations | + IntentGuildWebhooks | + IntentGuildInvites | + IntentGuildVoiceStates | + IntentGuildMessages | + IntentGuildMessageReactions | + IntentGuildMessageTyping | + IntentDirectMessages | + IntentDirectMessageReactions | + IntentDirectMessageTyping | + IntentGuildScheduledEvents + IntentsAll = IntentsAllWithoutPrivileged | - IntentsGuildMembers | - IntentsGuildPresences + IntentGuildMembers | + IntentGuildPresences | + IntentMessageContent + IntentsNone Intent = 0 ) From 971184a54275f83aed80607c1f7e1f073821cbbb Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Wed, 16 Feb 2022 16:24:17 +0300 Subject: [PATCH 24/33] CI (#1076) * feat: ci barebones * fix(.github/workflows): checkout * feat(.golangci.yml): removed presets * feat(workflows/ci): moved matrix to test job * feat(golangci-lint): disabled all linters except golint * fix(workflows/ci): golangci-lint action cache fix * feat(workflows/ci): custom step with golangci-lint on normal commit * feat(.github/workflows): moved setup-go into individual jobs * feat(workflows/ci): only new lint issues for pull requests --- .github/workflows/ci.yml | 60 ++++++++++++++++++++++++++++++++++++++++ .golangci.yml | 19 +++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .golangci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..63e14622f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,60 @@ +on: + push: + pull_request: + +name: CI + +jobs: + format: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - name: Code + uses: actions/checkout@v2 + - name: Check diff between gofmt and code + run: diff <(gofmt -d .) <(echo -n) + + test: + runs-on: ubuntu-latest + strategy: + matrix: + go-version: [1.13, 1.14, 1.15, 1.16, 1.17] + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: Code + uses: actions/checkout@v2 + - run: go test -v -race ./... + + lint: + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - name: Code + uses: actions/checkout@v2 + - name: Go vet + run: go vet -x ./... + + - name: GolangCI-Lint + uses: golangci/golangci-lint-action@v2.5.2 + if: github.event.name == 'pull_request' + with: + only-new-issues: true + skip-pkg-cache: true + skip-build-cache: true + + - name: GolangCI-Lint + if: github.event.name != 'pull_request' # See https://github.com/golangci/golangci-lint-action/issues/362 + run: | + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.43.0 + + $(go env GOPATH)/bin/golangci-lint run + diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 000000000..dd9d2e5b4 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,19 @@ +linters: + disable-all: true + enable: + # - staticcheck + # - unused + - golint + +linters-settings: + staticcheck: + go: "1.13" + + checks: ["all"] + + unused: + go: "1.13" + +issues: + include: + - EXC0002 From e16b1f8e5ba735f93321d1266d9b4754bc2024a5 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 16:31:13 +0300 Subject: [PATCH 25/33] fix(structs): added back old intent definitions for compatibility --- structs.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/structs.go b/structs.go index 29a2eb07a..17789f89f 100644 --- a/structs.go +++ b/structs.go @@ -1631,6 +1631,26 @@ const ( IntentMessageContent Intent = 1 << 15 IntentGuildScheduledEvents Intent = 1 << 16 + // TODO: remove when compatibility is not needed + + IntentsGuilds Intent = 1 << 0 + IntentsGuildMembers Intent = 1 << 1 + IntentsGuildBans Intent = 1 << 2 + IntentsGuildEmojis Intent = 1 << 3 + IntentsGuildIntegrations Intent = 1 << 4 + IntentsGuildWebhooks Intent = 1 << 5 + IntentsGuildInvites Intent = 1 << 6 + IntentsGuildVoiceStates Intent = 1 << 7 + IntentsGuildPresences Intent = 1 << 8 + IntentsGuildMessages Intent = 1 << 9 + IntentsGuildMessageReactions Intent = 1 << 10 + IntentsGuildMessageTyping Intent = 1 << 11 + IntentsDirectMessages Intent = 1 << 12 + IntentsDirectMessageReactions Intent = 1 << 13 + IntentsDirectMessageTyping Intent = 1 << 14 + IntentsMessageContent Intent = 1 << 15 + IntentsGuildScheduledEvents Intent = 1 << 16 + IntentsAllWithoutPrivileged = IntentGuilds | IntentGuildBans | IntentGuildEmojis | From 7044ee62cb915887c017b1bca67134637e989cbb Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 16:32:48 +0300 Subject: [PATCH 26/33] fix(examples/avatar): parameters for UserUpdate --- examples/avatar/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/avatar/main.go b/examples/avatar/main.go index e0a9c8802..58fa608fd 100644 --- a/examples/avatar/main.go +++ b/examples/avatar/main.go @@ -82,7 +82,7 @@ func main() { // Now lets format our base64 image into the proper format Discord wants // and then call UserUpdate to set it as our user's Avatar. avatar := fmt.Sprintf("data:%s;base64,%s", contentType, base64img) - _, err = dg.UserUpdate("", "", "", avatar, "") + _, err = dg.UserUpdate("", avatar) if err != nil { fmt.Println(err) } From 3d0ad546d1cd8d7cbd89727c630e525cf13ca8ee Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 16:38:21 +0300 Subject: [PATCH 27/33] feat(discord_test#init): check for oauth2 token --- discord_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/discord_test.go b/discord_test.go index 973e3a654..f35318558 100644 --- a/discord_test.go +++ b/discord_test.go @@ -15,11 +15,11 @@ var ( dg *Session // Stores a global discordgo user session dgBot *Session // Stores a global discordgo bot session - envToken = os.Getenv("DGU_TOKEN") // Token to use when authenticating the user account - envBotToken = os.Getenv("DGB_TOKEN") // Token to use when authenticating the bot account - envGuild = os.Getenv("DG_GUILD") // Guild ID to use for tests - envChannel = os.Getenv("DG_CHANNEL") // Channel ID to use for tests - envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests + envOAuth2Token = os.Getenv("DG_OAUTH2_TOKEN") // Token to use when authenticating using OAuth2 token + envBotToken = os.Getenv("DGB_TOKEN") // Token to use when authenticating the bot account + envGuild = os.Getenv("DG_GUILD") // Guild ID to use for tests + envChannel = os.Getenv("DG_CHANNEL") // Channel ID to use for tests + envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests ) func init() { @@ -30,10 +30,10 @@ func init() { } } - if d, err := New(envToken); err == nil { - dg = d - } else { - fmt.Println("dg is nil, error", err) + if envOAuth2Token != "" { + if d, err := New(envOAuth2Token); err == nil { + dg = d + } } } @@ -43,11 +43,11 @@ func init() { // TestNewToken tests the New() function with a Token. func TestNewToken(t *testing.T) { - if envToken == "" { + if envOAuth2Token == "" { t.Skip("Skipping New(token), DGU_TOKEN not set") } - d, err := New(envToken) + d, err := New(envOAuth2Token) if err != nil { t.Fatalf("New(envToken) returned error: %+v", err) } @@ -62,11 +62,11 @@ func TestNewToken(t *testing.T) { } func TestOpenClose(t *testing.T) { - if envToken == "" { + if envOAuth2Token == "" { t.Skip("Skipping TestClose, DGU_TOKEN not set") } - d, err := New(envToken) + d, err := New(envOAuth2Token) if err != nil { t.Fatalf("TestClose, New(envToken) returned error: %+v", err) } From 12b412a989e2635b7038eea089b920ffe0dffeca Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 16:39:50 +0300 Subject: [PATCH 28/33] feat(discord_test): rewrote init as TestMain --- discord_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/discord_test.go b/discord_test.go index f35318558..f2dd28c3d 100644 --- a/discord_test.go +++ b/discord_test.go @@ -22,7 +22,7 @@ var ( envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests ) -func init() { +func TestMain(m *testing.M) { fmt.Println("Init is being called.") if envBotToken != "" { if d, err := New(envBotToken); err == nil { @@ -35,6 +35,8 @@ func init() { dg = d } } + + os.Exit(m.Run()) } ////////////////////////////////////////////////////////////////////////////// From d8f15b1bc606bbaec7bc94bd3e10fa3e0e7eff9c Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 16:41:37 +0300 Subject: [PATCH 29/33] feat(discord_test): check for DGU_TOKEN for compatibility --- discord_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/discord_test.go b/discord_test.go index f2dd28c3d..720397ba3 100644 --- a/discord_test.go +++ b/discord_test.go @@ -30,6 +30,10 @@ func TestMain(m *testing.M) { } } + if envOAuth2Token == "" { + envOAuth2Token = os.Getenv("DGU_TOKEN") + } + if envOAuth2Token != "" { if d, err := New(envOAuth2Token); err == nil { dg = d From fca422b28f35af1961313fa1f8675c1ff4f6d516 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 16:47:30 +0300 Subject: [PATCH 30/33] fix(examples): signal.Notify unbuffered channel --- examples/autocomplete/main.go | 4 ++-- examples/slash_commands/main.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/autocomplete/main.go b/examples/autocomplete/main.go index 3e509af4d..55dbc6a39 100644 --- a/examples/autocomplete/main.go +++ b/examples/autocomplete/main.go @@ -239,8 +239,8 @@ func main() { log.Fatalf("Cannot register commands: %v", err) } - stop := make(chan os.Signal) - signal.Notify(stop, os.Interrupt) //nolint: staticcheck + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt) <-stop log.Println("Gracefully shutting down") diff --git a/examples/slash_commands/main.go b/examples/slash_commands/main.go index 1cb3dead0..3a1cf584c 100644 --- a/examples/slash_commands/main.go +++ b/examples/slash_commands/main.go @@ -379,7 +379,7 @@ func main() { defer s.Close() - stop := make(chan os.Signal) + stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt) <-stop log.Println("Gracefully shutdowning") From 0494cdf33cbd69e4153ad0207a18138df08915ee Mon Sep 17 00:00:00 2001 From: nitroflap Date: Wed, 16 Feb 2022 16:50:33 +0300 Subject: [PATCH 31/33] feat(components): added comment to MessageComponentFromJSON --- components.go | 1 + 1 file changed, 1 insertion(+) diff --git a/components.go b/components.go index 4537bb26a..a6716c0ef 100644 --- a/components.go +++ b/components.go @@ -51,6 +51,7 @@ func (umc *unmarshalableMessageComponent) UnmarshalJSON(src []byte) error { return json.Unmarshal(src, umc.MessageComponent) } +// MessageComponentFromJSON is a helper function for unmarshaling message components func MessageComponentFromJSON(b []byte) (MessageComponent, error) { var u unmarshalableMessageComponent err := u.UnmarshalJSON(b) From 0a0955c5f9e38e9c97f338c8ad4849eee3c1e098 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Wed, 16 Feb 2022 21:02:44 +0300 Subject: [PATCH 32/33] Application commands: attachment option (#1088) * feat(interactions): application command attachment option * fix(interactions): corrected application command attachment option type --- interactions.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/interactions.go b/interactions.go index 33cc8ade6..be11d53cc 100644 --- a/interactions.go +++ b/interactions.go @@ -55,6 +55,7 @@ const ( ApplicationCommandOptionChannel ApplicationCommandOptionType = 7 ApplicationCommandOptionRole ApplicationCommandOptionType = 8 ApplicationCommandOptionMentionable ApplicationCommandOptionType = 9 + ApplicationCommandOptionAttachment ApplicationCommandOptionType = 11 ) func (t ApplicationCommandOptionType) String() string { @@ -77,6 +78,8 @@ func (t ApplicationCommandOptionType) String() string { return "Role" case ApplicationCommandOptionMentionable: return "Mentionable" + case ApplicationCommandOptionAttachment: + return "Attachment" } return fmt.Sprintf("ApplicationCommandOptionType(%d)", t) } @@ -255,11 +258,12 @@ type ApplicationCommandInteractionData struct { // Partial Member objects are missing user, deaf and mute fields. // Partial Channel objects only have id, name, type and permissions fields. type ApplicationCommandInteractionDataResolved struct { - Users map[string]*User `json:"users"` - Members map[string]*Member `json:"members"` - Roles map[string]*Role `json:"roles"` - Channels map[string]*Channel `json:"channels"` - Messages map[string]*Message `json:"messages"` + Users map[string]*User `json:"users"` + Members map[string]*Member `json:"members"` + Roles map[string]*Role `json:"roles"` + Channels map[string]*Channel `json:"channels"` + Messages map[string]*Message `json:"messages"` + Attachments map[string]*MessageAttachment `json:"attachments"` } // Type returns the type of interaction data. From d5bacb5401a6652f48edfbf133fd55a159b95b18 Mon Sep 17 00:00:00 2001 From: Bjorn Zandvliet Date: Wed, 16 Feb 2022 20:17:26 +0100 Subject: [PATCH 33/33] Add Default Permission to #943 (#1071) * Create edit application command permissions endpoint * Add remaining command permissions endpoints * Clean up naming a bit * Add docs for application command permissions endpoints * Update comments * More comments * :^) * Put the verb in API method names at the end * Review feedback * Add default permissions * feat(restapi): rewording of comments to application command permissions endpoints * fix(rest): errors for application commands permissions endpoints * style(interactions): changed order of fields in ApplicationCommand Co-authored-by: NotUnlikeTheWaves Co-authored-by: nitroflap --- endpoints.go | 6 ++++++ interactions.go | 47 ++++++++++++++++++++++++++++++++++------- restapi.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 8 deletions(-) diff --git a/endpoints.go b/endpoints.go index 5124394ad..b161c0cac 100644 --- a/endpoints.go +++ b/endpoints.go @@ -133,6 +133,12 @@ var ( EndpointApplicationGuildCommand = func(aID, gID, cID string) string { return EndpointApplicationGuildCommands(aID, gID) + "/" + cID } + EndpointApplicationCommandPermissions = func(aID, gID, cID string) string { + return EndpointApplicationGuildCommand(aID, gID, cID) + "/permissions" + } + EndpointApplicationCommandsGuildPermissions = func(aID, gID string) string { + return EndpointApplicationGuildCommands(aID, gID) + "/permissions" + } EndpointInteraction = func(aID, iToken string) string { return EndpointAPI + "interactions/" + aID + "/" + iToken } diff --git a/interactions.go b/interactions.go index be11d53cc..9ce3d4811 100644 --- a/interactions.go +++ b/interactions.go @@ -30,15 +30,17 @@ const ( // ApplicationCommand represents an application's slash command. type ApplicationCommand struct { - ID string `json:"id,omitempty"` - ApplicationID string `json:"application_id,omitempty"` - Type ApplicationCommandType `json:"type,omitempty"` - Name string `json:"name"` - // NOTE: Chat commands only. Otherwise it mustn't be set. - Description string `json:"description,omitempty"` - Version string `json:"version,omitempty"` + ID string `json:"id,omitempty"` + ApplicationID string `json:"application_id,omitempty"` + Version string `json:"version,omitempty"` + Type ApplicationCommandType `json:"type,omitempty"` + Name string `json:"name"` + DefaultPermission *bool `json:"default_permission,omitempty"` + // NOTE: Chat commands only. Otherwise it mustn't be set. - Options []*ApplicationCommandOption `json:"options"` + + Description string `json:"description,omitempty"` + Options []*ApplicationCommandOption `json:"options"` } // ApplicationCommandOptionType indicates the type of a slash command's option. @@ -107,6 +109,35 @@ type ApplicationCommandOptionChoice struct { Value interface{} `json:"value"` } +// ApplicationCommandPermissions represents a single user or role permission for a command. +type ApplicationCommandPermissions struct { + ID string `json:"id"` + Type ApplicationCommandPermissionType `json:"type"` + Permission bool `json:"permission"` +} + +// ApplicationCommandPermissionsList represents a list of ApplicationCommandPermissions, needed for serializing to JSON. +type ApplicationCommandPermissionsList struct { + Permissions []*ApplicationCommandPermissions `json:"permissions"` +} + +// GuildApplicationCommandPermissions represents all permissions for a single guild command. +type GuildApplicationCommandPermissions struct { + ID string `json:"id"` + ApplicationID string `json:"application_id"` + GuildID string `json:"guild_id"` + Permissions []*ApplicationCommandPermissions `json:"permissions"` +} + +// ApplicationCommandPermissionType indicates whether a permission is user or role based. +type ApplicationCommandPermissionType uint8 + +// Application command permission types. +const ( + ApplicationCommandPermissionTypeRole ApplicationCommandPermissionType = 1 + ApplicationCommandPermissionTypeUser ApplicationCommandPermissionType = 2 +) + // InteractionType indicates the type of an interaction event. type InteractionType uint8 diff --git a/restapi.go b/restapi.go index 74ba48282..94c8de78a 100644 --- a/restapi.go +++ b/restapi.go @@ -2282,6 +2282,62 @@ func (s *Session) ApplicationCommands(appID, guildID string) (cmd []*Application return } +// GuildApplicationCommandsPermissions returns permissions for all application commands in a guild. +// appID : The application ID +// guildID : Guild ID to retrieve application commands permissions for. +func (s *Session) GuildApplicationCommandsPermissions(appID, guildID string) (permissions []*GuildApplicationCommandPermissions, err error) { + endpoint := EndpointApplicationCommandsGuildPermissions(appID, guildID) + + var body []byte + body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint) + if err != nil { + return + } + + err = unmarshal(body, &permissions) + return +} + +// ApplicationCommandPermissions returns all permissions of an application command +// appID : The Application ID +// guildID : The guild ID containing the application command +// cmdID : The command ID to retrieve the permissions of +func (s *Session) ApplicationCommandPermissions(appID, guildID, cmdID string) (permissions *GuildApplicationCommandPermissions, err error) { + endpoint := EndpointApplicationCommandPermissions(appID, guildID, cmdID) + + var body []byte + body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint) + if err != nil { + return + } + + err = unmarshal(body, &permissions) + return +} + +// ApplicationCommandPermissionsEdit edits the permissions of an application command +// appID : The Application ID +// guildID : The guild ID containing the application command +// cmdID : The command ID to edit the permissions of +// permissions : An object containing a list of permissions for the application command +func (s *Session) ApplicationCommandPermissionsEdit(appID, guildID, cmdID string, permissions *ApplicationCommandPermissionsList) (err error) { + endpoint := EndpointApplicationCommandPermissions(appID, guildID, cmdID) + + _, err = s.RequestWithBucketID("PUT", endpoint, permissions, endpoint) + return +} + +// ApplicationCommandPermissionsBatchEdit edits the permissions of a batch of commands +// appID : The Application ID +// guildID : The guild ID to batch edit commands of +// permissions : A list of permissions paired with a command ID, guild ID, and application ID per application command +func (s *Session) ApplicationCommandPermissionsBatchEdit(appID, guildID string, permissions []*GuildApplicationCommandPermissions) (err error) { + endpoint := EndpointApplicationCommandsGuildPermissions(appID, guildID) + + _, err = s.RequestWithBucketID("PUT", endpoint, permissions, endpoint) + return +} + // InteractionRespond creates the response to an interaction. // appID : The application ID. // interaction : Interaction instance.