From 5af890548222b49fe6a222aca981520f8a22ab2a Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Wed, 13 Apr 2022 11:19:06 +0200 Subject: [PATCH 01/15] feat: Add support of StageInstance RESTAPI and Events --- endpoints.go | 20 +++++++------- eventhandlers.go | 63 +++++++++++++++++++++++++++++++++++++++++++ events.go | 15 +++++++++++ restapi.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ structs.go | 35 ++++++++++++++++++++++++ 5 files changed, 194 insertions(+), 9 deletions(-) diff --git a/endpoints.go b/endpoints.go index c0d5b7241..3e39f4d02 100644 --- a/endpoints.go +++ b/endpoints.go @@ -23,15 +23,16 @@ var ( EndpointSmActive = EndpointSm + "active.json" EndpointSmUpcoming = EndpointSm + "upcoming.json" - EndpointDiscord = "https://discord.com/" - EndpointAPI = EndpointDiscord + "api/v" + APIVersion + "/" - EndpointGuilds = EndpointAPI + "guilds/" - EndpointChannels = EndpointAPI + "channels/" - EndpointUsers = EndpointAPI + "users/" - EndpointGateway = EndpointAPI + "gateway" - EndpointGatewayBot = EndpointGateway + "/bot" - EndpointWebhooks = EndpointAPI + "webhooks/" - EndpointStickers = EndpointAPI + "stickers/" + EndpointDiscord = "https://discord.com/" + EndpointAPI = EndpointDiscord + "api/v" + APIVersion + "/" + EndpointGuilds = EndpointAPI + "guilds/" + EndpointChannels = EndpointAPI + "channels/" + EndpointUsers = EndpointAPI + "users/" + EndpointGateway = EndpointAPI + "gateway" + EndpointGatewayBot = EndpointGateway + "/bot" + EndpointWebhooks = EndpointAPI + "webhooks/" + EndpointStickers = EndpointAPI + "stickers/" + EndpointStageInstances = EndpointAPI + "stage-instances/" EndpointCDN = "https://cdn.discordapp.com/" EndpointCDNAttachments = EndpointCDN + "attachments/" @@ -95,6 +96,7 @@ var ( 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 } + EndpointStageInstance = func(sID string) string { return EndpointStageInstances + sID } EndpointGuildScheduledEvents = func(gID string) string { return EndpointGuilds + gID + "/scheduled-events" } EndpointGuildScheduledEvent = func(gID, eID string) string { return EndpointGuilds + gID + "/scheduled-events/" + eID } EndpointGuildScheduledEventUsers = func(gID, eID string) string { return EndpointGuildScheduledEvent(gID, eID) + "/users" } diff --git a/eventhandlers.go b/eventhandlers.go index 07f5d2167..d0e382f8a 100644 --- a/eventhandlers.go +++ b/eventhandlers.go @@ -27,6 +27,9 @@ const ( guildRoleCreateEventType = "GUILD_ROLE_CREATE" guildRoleDeleteEventType = "GUILD_ROLE_DELETE" guildRoleUpdateEventType = "GUILD_ROLE_UPDATE" + guildStageInstanceCreateEventType = "STAGE_INSTANCE_CREATE" + guildStageInstanceUpdateEventType = "STAGE_INSTANCE_UPDATE" + guildStageInstanceDeleteEventType = "STAGE_INSTANCE_DELETE" guildScheduledEventCreateEventType = "GUILD_SCHEDULED_EVENT_CREATE" guildScheduledEventDeleteEventType = "GUILD_SCHEDULED_EVENT_DELETE" guildScheduledEventUpdateEventType = "GUILD_SCHEDULED_EVENT_UPDATE" @@ -452,6 +455,66 @@ func (eh guildRoleUpdateEventHandler) Handle(s *Session, i interface{}) { } } +// guildStageInstanceEventCreateHandler is an event handler for StageInstanceEventCreate events. +type guildStageInstanceEventCreateHandler func(*Session, *StageInstanceEventCreate) + +// Type returns the event type for StageInstanceEventCreate events. +func (eh guildStageInstanceEventCreateHandler) Type() string { + return guildStageInstanceCreateEventType +} + +// New returns a new instance of StageInstanceEventCreate. +func (eh guildStageInstanceEventCreateHandler) New() interface{} { + return &StageInstanceEventCreate{} +} + +// Handle is the handler for StageInstanceEventCreate events. +func (eh guildStageInstanceEventCreateHandler) Handle(s *Session, i interface{}) { + if t, ok := i.(*StageInstanceEventCreate); ok { + eh(s, t) + } +} + +// guildStageInstanceEventUpdateHandler is an event handler for StageInstanceEventUpdate events. +type guildStageInstanceEventUpdateHandler func(*Session, *StageInstanceEventUpdate) + +// Type returns the event type for StageInstanceEventUpdate events. +func (eh guildStageInstanceEventUpdateHandler) Type() string { + return guildStageInstanceCreateEventType +} + +// New returns a new instance of StageInstanceEventUpdate. +func (eh guildStageInstanceEventUpdateHandler) New() interface{} { + return &StageInstanceEventUpdate{} +} + +// Handle is the handler for StageInstanceEventUpdate events. +func (eh guildStageInstanceEventUpdateHandler) Handle(s *Session, i interface{}) { + if t, ok := i.(*StageInstanceEventUpdate); ok { + eh(s, t) + } +} + +// guildStageInstanceEventDeleteHandler is an event handler for StageInstanceEventDelete events. +type guildStageInstanceEventDeleteHandler func(*Session, *StageInstanceEventDelete) + +// Type returns the event type for StageInstanceEventDelete events. +func (eh guildStageInstanceEventDeleteHandler) Type() string { + return guildStageInstanceCreateEventType +} + +// New returns a new instance of StageInstanceEventDelete. +func (eh guildStageInstanceEventDeleteHandler) New() interface{} { + return &StageInstanceEventDelete{} +} + +// Handle is the handler for StageInstanceEventDelete events. +func (eh guildStageInstanceEventDeleteHandler) Handle(s *Session, i interface{}) { + if t, ok := i.(*StageInstanceEventDelete); ok { + eh(s, t) + } +} + // guildScheduledEventCreateEventHandler is an event handler for GuildScheduledEventCreate events. type guildScheduledEventCreateEventHandler func(*Session, *GuildScheduledEventCreate) diff --git a/events.go b/events.go index bb45d2510..5c567df14 100644 --- a/events.go +++ b/events.go @@ -199,6 +199,21 @@ type GuildIntegrationsUpdate struct { GuildID string `json:"guild_id"` } +// StageInstanceEventCreate is the data for a StageInstanceEventCreate event. +type StageInstanceEventCreate struct { + *StageInstance +} + +// StageInstanceEventUpdate is the data for a StageInstanceEventUpdate event. +type StageInstanceEventUpdate struct { + *StageInstance +} + +// StageInstanceEventDelete is the data for a StageInstanceEventDelete event. +type StageInstanceEventDelete struct { + *StageInstance +} + // GuildScheduledEventCreate is the data for a GuildScheduledEventCreate event. type GuildScheduledEventCreate struct { *GuildScheduledEvent diff --git a/restapi.go b/restapi.go index fcefcbbdd..b4ad01e5b 100644 --- a/restapi.go +++ b/restapi.go @@ -2874,6 +2874,76 @@ func (s *Session) FollowupMessageDelete(appID string, interaction *Interaction, return s.WebhookMessageDelete(appID, interaction.Token, messageID) } +// ------------------------------------------------------------------------------------------------ +// Functions specific to stage instances +// ------------------------------------------------------------------------------------------------ + +// StageInstanceData is provided to StageInstanceCreate +type StageInstanceData struct { + // ChannelID represents the id of the Stage channel + ChannelID string `json:"channel_id"` + // Topic of the Stage instance (1-120 characters) + Topic string `json:"topic"` + // PrivacyLevel of the Stage instance (default GUILD_ONLY) + PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` + // SendStartNotification will notify @everyone that a Stage instance has started + SendStartNotification *bool `json:"send_start_notification,omitempty"` +} + +// StageInstanceCreate will creates a new Stage instance associated to a Stage channel. +// Returns that Stage instance created +func (s *Session) StageInstanceCreate(data *StageInstanceData) (si *StageInstance, err error) { + body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances) + if err != nil { + return + } + + err = unmarshal(body, &si) + return +} + +// StageInstance will retrieve a Stage instance by ID of the Stage channel. +// channelID : The ID of the Stage channel +func (s *Session) StageInstance(channelID string) (si *StageInstance, err error) { + body, err := s.RequestWithBucketID("GET", EndpointStageInstance(channelID), nil, EndpointStageInstance(channelID)) + if err != nil { + return + } + + err = unmarshal(body, &si) + return +} + +// StageInstanceEdit will edit a Stage instance by ID of the Stage channel. +// channelID : The ID of the Stage channel +// topic : The new topic of the Stage instance (1-120 characters). Set empty to keep the current topic. +// privacyLevel : The new privacy level of the Stage instance. Set nil to keep the current privacy level. +func (s *Session) StageInstanceEdit(channelID string, topic string, privacyLevel *StageInstancePrivacyLevel) (si *StageInstance, err error) { + data := struct { + Topic string `json:"topic,omitempty"` + // PrivacyLevel of the Stage instance (default GUILD_ONLY) + PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` + }{ + Topic: topic, + PrivacyLevel: privacyLevel, + } + + body, err := s.RequestWithBucketID("PATCH", EndpointStageInstance(channelID), data, EndpointStageInstance(channelID)) + if err != nil { + return + } + + err = unmarshal(body, &si) + return +} + +// StageInstanceDelete will delete a Stage instance by ID of the Stage channel. +// channelID : The ID of the Stage channel +func (s *Session) StageInstanceDelete(channelID string) (err error) { + _, err = s.RequestWithBucketID("DELETE", EndpointStageInstance(channelID), nil, EndpointStageInstance(channelID)) + return +} + // ------------------------------------------------------------------------------------------------ // Functions specific to guilds scheduled events // ------------------------------------------------------------------------------------------------ diff --git a/structs.go b/structs.go index c2927b5bb..3d0a6b899 100644 --- a/structs.go +++ b/structs.go @@ -260,6 +260,7 @@ const ( ChannelTypeGuildNewsThread ChannelType = 10 ChannelTypeGuildPublicThread ChannelType = 11 ChannelTypeGuildPrivateThread ChannelType = 12 + ChannelTypeGuildStageVoice ChannelType = 13 ) // A Channel holds all data related to an individual Discord channel. @@ -745,6 +746,9 @@ type Guild struct { // Permissions of our user Permissions int64 `json:"permissions,string"` + + // StageInstance in the guild + StageInstance []*StageInstance `json:"stage_instance"` } // A GuildPreview holds data related to a specific public Discord Guild, even if the user is not in the guild. @@ -1752,6 +1756,37 @@ type IdentifyProperties struct { ReferringDomain string `json:"$referring_domain"` } +// StageInstance holds information about a live stage. +// https://discord.com/developers/docs/resources/stage-instance#stage-instance-resource +type StageInstance struct { + // The id of this Stage instance + ID string `json:"id"` + // The guild id of the associated Stage channel + GuildID string `json:"guild_id"` + // The id of the associated Stage channel + ChannelID string `json:"channel_id"` + // The topic of the Stage instance (1-120 characters) + Topic string `json:"topic"` + // The privacy level of the Stage instance + // https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level + PrivacyLevel StageInstancePrivacyLevel `json:"privacy_level"` + // Whether or not Stage Discovery is disabled (deprecated) + DiscoverableDisabled bool `json:"discoverable_disabled"` + // The id of the scheduled event for this Stage instance + GuildScheduledEventID string `json:"guild_scheduled_event_id"` +} + +// StageInstancePrivacyLevel The privacy level of the Stage instance +// https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level +type StageInstancePrivacyLevel int + +const ( + // StageInstancePrivacyLevelPublic The Stage instance is visible publicly. (deprecated) + StageInstancePrivacyLevelPublic StageInstancePrivacyLevel = 1 + // StageInstancePrivacyLevelGuildOnly The Stage instance is visible to only guild members. + StageInstancePrivacyLevelGuildOnly StageInstancePrivacyLevel = 2 +) + // Constants for the different bit offsets of text channel permissions const ( // Deprecated: PermissionReadMessages has been replaced with PermissionViewChannel for text and voice channels From 251129a6c34aa9f26f08ab8370d837fdad391ef2 Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 00:28:12 +0200 Subject: [PATCH 02/15] chore: Make the changes for following the current convention of package --- restapi.go | 18 +++--------------- structs.go | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/restapi.go b/restapi.go index b4ad01e5b..a0b9b73f7 100644 --- a/restapi.go +++ b/restapi.go @@ -2878,18 +2878,6 @@ func (s *Session) FollowupMessageDelete(appID string, interaction *Interaction, // Functions specific to stage instances // ------------------------------------------------------------------------------------------------ -// StageInstanceData is provided to StageInstanceCreate -type StageInstanceData struct { - // ChannelID represents the id of the Stage channel - ChannelID string `json:"channel_id"` - // Topic of the Stage instance (1-120 characters) - Topic string `json:"topic"` - // PrivacyLevel of the Stage instance (default GUILD_ONLY) - PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` - // SendStartNotification will notify @everyone that a Stage instance has started - SendStartNotification *bool `json:"send_start_notification,omitempty"` -} - // StageInstanceCreate will creates a new Stage instance associated to a Stage channel. // Returns that Stage instance created func (s *Session) StageInstanceCreate(data *StageInstanceData) (si *StageInstance, err error) { @@ -2918,14 +2906,14 @@ func (s *Session) StageInstance(channelID string) (si *StageInstance, err error) // channelID : The ID of the Stage channel // topic : The new topic of the Stage instance (1-120 characters). Set empty to keep the current topic. // privacyLevel : The new privacy level of the Stage instance. Set nil to keep the current privacy level. -func (s *Session) StageInstanceEdit(channelID string, topic string, privacyLevel *StageInstancePrivacyLevel) (si *StageInstance, err error) { +func (s *Session) StageInstanceEdit(channelID string, instance *StageInstance) (si *StageInstance, err error) { data := struct { Topic string `json:"topic,omitempty"` // PrivacyLevel of the Stage instance (default GUILD_ONLY) PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` }{ - Topic: topic, - PrivacyLevel: privacyLevel, + Topic: instance.Topic, + PrivacyLevel: &instance.PrivacyLevel, } body, err := s.RequestWithBucketID("PATCH", EndpointStageInstance(channelID), data, EndpointStageInstance(channelID)) diff --git a/structs.go b/structs.go index 3d0a6b899..522f1bd43 100644 --- a/structs.go +++ b/structs.go @@ -747,8 +747,8 @@ type Guild struct { // Permissions of our user Permissions int64 `json:"permissions,string"` - // StageInstance in the guild - StageInstance []*StageInstance `json:"stage_instance"` + // Stage Instances in the guild + StageInstances []*StageInstance `json:"stage_instance"` } // A GuildPreview holds data related to a specific public Discord Guild, even if the user is not in the guild. @@ -1776,6 +1776,28 @@ type StageInstance struct { GuildScheduledEventID string `json:"guild_scheduled_event_id"` } +// StageInstanceData is provided to StageInstanceCreate +type StageInstanceData struct { + // ChannelID represents the id of the Stage channel + ChannelID string `json:"channel_id"` + // Topic of the Stage instance (1-120 characters) + Topic string `json:"topic"` + // PrivacyLevel of the Stage instance (default GUILD_ONLY) + PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` + // SendStartNotification will notify @everyone that a Stage instance has started + SendStartNotification *bool `json:"send_start_notification,omitempty"` +} + +// StageInstanceData is provided to StageInstanceCreate +type StageInstanceEditData struct { + // Topic of the Stage instance (1-120 characters) + Topic string `json:"topic"` + // PrivacyLevel of the Stage instance (default GUILD_ONLY) + PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` + // SendStartNotification will notify @everyone that a Stage instance has started + SendStartNotification *bool `json:"send_start_notification,omitempty"` +} + // StageInstancePrivacyLevel The privacy level of the Stage instance // https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level type StageInstancePrivacyLevel int From a9a36ee940de8896d828c82c64f02045301144fd Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 00:55:26 +0200 Subject: [PATCH 03/15] doc: Add missing docs and example for stage-instance --- endpoints.go | 2 +- examples/stage_instance/main.go | 57 +++++++++++++++++++++++++++++++++ restapi.go | 3 +- structs.go | 10 +++--- 4 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 examples/stage_instance/main.go diff --git a/endpoints.go b/endpoints.go index 3e39f4d02..de76f4624 100644 --- a/endpoints.go +++ b/endpoints.go @@ -96,7 +96,7 @@ var ( 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 } - EndpointStageInstance = func(sID string) string { return EndpointStageInstances + sID } + EndpointStageInstance = func(cID string) string { return EndpointStageInstances + cID } EndpointGuildScheduledEvents = func(gID string) string { return EndpointGuilds + gID + "/scheduled-events" } EndpointGuildScheduledEvent = func(gID, eID string) string { return EndpointGuilds + gID + "/scheduled-events/" + eID } EndpointGuildScheduledEventUsers = func(gID, eID string) string { return EndpointGuildScheduledEvent(gID, eID) + "/users" } diff --git a/examples/stage_instance/main.go b/examples/stage_instance/main.go new file mode 100644 index 000000000..cb891927f --- /dev/null +++ b/examples/stage_instance/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "flag" + "fmt" + "log" + + "github.com/bwmarrin/discordgo" +) + +// Flags +var ( + GuildID = flag.String("guild", "", "Test guild ID") + StageChannelID = flag.String("stage", "", "Test stage channel ID") + BotToken = flag.String("token", "", "Bot token") +) + +func init() { flag.Parse() } + +// To be correctly used, the bot needs to be in a guild. +// All actions must be done on a stage channel event +func main() { + s, _ := discordgo.New("Bot " + *BotToken) + s.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) { + fmt.Println("Bot is ready") + }) + + err := s.Open() + if err != nil { + log.Fatalf("Cannot open the session: %v", err) + } + defer s.Close() + + // Create a new Stage instance on the previous channel + si, err := s.StageInstanceCreate(&discordgo.StageInstanceData{ + ChannelID: *StageChannelID, + Topic: "Amazing topic", + PrivacyLevel: discordgo.StageInstancePrivacyLevelGuildOnly, + SendStartNotification: true, + }) + if err != nil { + log.Fatalf("Cannot create stage instance: %v", err) + } + log.Printf("Stage Instance %s has been successfully created", si.Topic) + + // Edit the stage instance with a new Topic + si.Topic = "New amazing topic" + si, err = s.StageInstanceEdit(*StageChannelID, si) + if err != nil { + log.Fatalf("Cannot edit stage instance: %v", err) + } + log.Printf("Stage Instance %s has been successfully edited", si.Topic) + + if err = s.StageInstanceDelete(*StageChannelID); err != nil { + log.Fatalf("Cannot delete stage instance: %v", err) + } +} diff --git a/restapi.go b/restapi.go index a0b9b73f7..0809ab5fd 100644 --- a/restapi.go +++ b/restapi.go @@ -2881,7 +2881,8 @@ func (s *Session) FollowupMessageDelete(appID string, interaction *Interaction, // StageInstanceCreate will creates a new Stage instance associated to a Stage channel. // Returns that Stage instance created func (s *Session) StageInstanceCreate(data *StageInstanceData) (si *StageInstance, err error) { - body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances) + url := strings.TrimSuffix(EndpointStageInstances, "/") + body, err := s.RequestWithBucketID("POST", url, data, url) if err != nil { return } diff --git a/structs.go b/structs.go index 522f1bd43..f5b6f066d 100644 --- a/structs.go +++ b/structs.go @@ -1783,19 +1783,17 @@ type StageInstanceData struct { // Topic of the Stage instance (1-120 characters) Topic string `json:"topic"` // PrivacyLevel of the Stage instance (default GUILD_ONLY) - PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` + PrivacyLevel StageInstancePrivacyLevel `json:"privacy_level,omitempty"` // SendStartNotification will notify @everyone that a Stage instance has started - SendStartNotification *bool `json:"send_start_notification,omitempty"` + SendStartNotification bool `json:"send_start_notification,omitempty"` } -// StageInstanceData is provided to StageInstanceCreate +// StageInstanceEditData is provided to StageInstanceEdit type StageInstanceEditData struct { // Topic of the Stage instance (1-120 characters) Topic string `json:"topic"` // PrivacyLevel of the Stage instance (default GUILD_ONLY) - PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` - // SendStartNotification will notify @everyone that a Stage instance has started - SendStartNotification *bool `json:"send_start_notification,omitempty"` + PrivacyLevel StageInstancePrivacyLevel `json:"privacy_level,omitempty"` } // StageInstancePrivacyLevel The privacy level of the Stage instance From 669e82055ed26cd4bba3a4429c3d772a5a55e224 Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 01:02:27 +0200 Subject: [PATCH 04/15] doc: Add final log for deleted stage instance --- examples/stage_instance/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/stage_instance/main.go b/examples/stage_instance/main.go index cb891927f..1a100f332 100644 --- a/examples/stage_instance/main.go +++ b/examples/stage_instance/main.go @@ -54,4 +54,5 @@ func main() { if err = s.StageInstanceDelete(*StageChannelID); err != nil { log.Fatalf("Cannot delete stage instance: %v", err) } + log.Printf("Stage Instance %s has been successfully deleted", si.Topic) } From 5b234f7ae7b17d4e51ce8838992d702c7178ceb7 Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 01:02:57 +0200 Subject: [PATCH 05/15] refactor: Prevent trailing slash on stage instance endpoint --- endpoints.go | 4 ++-- restapi.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/endpoints.go b/endpoints.go index de76f4624..f5822da64 100644 --- a/endpoints.go +++ b/endpoints.go @@ -32,7 +32,7 @@ var ( EndpointGatewayBot = EndpointGateway + "/bot" EndpointWebhooks = EndpointAPI + "webhooks/" EndpointStickers = EndpointAPI + "stickers/" - EndpointStageInstances = EndpointAPI + "stage-instances/" + EndpointStageInstances = EndpointAPI + "stage-instances" EndpointCDN = "https://cdn.discordapp.com/" EndpointCDNAttachments = EndpointCDN + "attachments/" @@ -96,7 +96,7 @@ var ( 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 } - EndpointStageInstance = func(cID string) string { return EndpointStageInstances + cID } + EndpointStageInstance = func(cID string) string { return EndpointStageInstances + "/" + cID } EndpointGuildScheduledEvents = func(gID string) string { return EndpointGuilds + gID + "/scheduled-events" } EndpointGuildScheduledEvent = func(gID, eID string) string { return EndpointGuilds + gID + "/scheduled-events/" + eID } EndpointGuildScheduledEventUsers = func(gID, eID string) string { return EndpointGuildScheduledEvent(gID, eID) + "/users" } diff --git a/restapi.go b/restapi.go index 0809ab5fd..a0b9b73f7 100644 --- a/restapi.go +++ b/restapi.go @@ -2881,8 +2881,7 @@ func (s *Session) FollowupMessageDelete(appID string, interaction *Interaction, // StageInstanceCreate will creates a new Stage instance associated to a Stage channel. // Returns that Stage instance created func (s *Session) StageInstanceCreate(data *StageInstanceData) (si *StageInstance, err error) { - url := strings.TrimSuffix(EndpointStageInstances, "/") - body, err := s.RequestWithBucketID("POST", url, data, url) + body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances) if err != nil { return } From adbb10d2ae0fd21846172c474eb4cbef2ee30b5f Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 21:43:32 +0200 Subject: [PATCH 06/15] chore: Harmonize params structure --- examples/stage_instance/main.go | 7 ++++--- restapi.go | 12 ++---------- structs.go | 15 ++++----------- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/examples/stage_instance/main.go b/examples/stage_instance/main.go index 1a100f332..8452efe55 100644 --- a/examples/stage_instance/main.go +++ b/examples/stage_instance/main.go @@ -32,7 +32,7 @@ func main() { defer s.Close() // Create a new Stage instance on the previous channel - si, err := s.StageInstanceCreate(&discordgo.StageInstanceData{ + si, err := s.StageInstanceCreate(&discordgo.StageInstanceParams{ ChannelID: *StageChannelID, Topic: "Amazing topic", PrivacyLevel: discordgo.StageInstancePrivacyLevelGuildOnly, @@ -44,8 +44,9 @@ func main() { log.Printf("Stage Instance %s has been successfully created", si.Topic) // Edit the stage instance with a new Topic - si.Topic = "New amazing topic" - si, err = s.StageInstanceEdit(*StageChannelID, si) + si, err = s.StageInstanceEdit(*StageChannelID, &discordgo.StageInstanceParams{ + Topic: "New amazing topic", + }) if err != nil { log.Fatalf("Cannot edit stage instance: %v", err) } diff --git a/restapi.go b/restapi.go index a0b9b73f7..7d03c5ee6 100644 --- a/restapi.go +++ b/restapi.go @@ -2880,7 +2880,7 @@ func (s *Session) FollowupMessageDelete(appID string, interaction *Interaction, // StageInstanceCreate will creates a new Stage instance associated to a Stage channel. // Returns that Stage instance created -func (s *Session) StageInstanceCreate(data *StageInstanceData) (si *StageInstance, err error) { +func (s *Session) StageInstanceCreate(data *StageInstanceParams) (si *StageInstance, err error) { body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances) if err != nil { return @@ -2906,15 +2906,7 @@ func (s *Session) StageInstance(channelID string) (si *StageInstance, err error) // channelID : The ID of the Stage channel // topic : The new topic of the Stage instance (1-120 characters). Set empty to keep the current topic. // privacyLevel : The new privacy level of the Stage instance. Set nil to keep the current privacy level. -func (s *Session) StageInstanceEdit(channelID string, instance *StageInstance) (si *StageInstance, err error) { - data := struct { - Topic string `json:"topic,omitempty"` - // PrivacyLevel of the Stage instance (default GUILD_ONLY) - PrivacyLevel *StageInstancePrivacyLevel `json:"privacy_level,omitempty"` - }{ - Topic: instance.Topic, - PrivacyLevel: &instance.PrivacyLevel, - } +func (s *Session) StageInstanceEdit(channelID string, data *StageInstanceParams) (si *StageInstance, err error) { body, err := s.RequestWithBucketID("PATCH", EndpointStageInstance(channelID), data, EndpointStageInstance(channelID)) if err != nil { diff --git a/structs.go b/structs.go index f5b6f066d..0d3f9a1a5 100644 --- a/structs.go +++ b/structs.go @@ -1776,10 +1776,11 @@ type StageInstance struct { GuildScheduledEventID string `json:"guild_scheduled_event_id"` } -// StageInstanceData is provided to StageInstanceCreate -type StageInstanceData struct { +// StageInstanceParams represents the parameters that allow to make a request via +// StageInstanceCreate and StageInstanceEdit +type StageInstanceParams struct { // ChannelID represents the id of the Stage channel - ChannelID string `json:"channel_id"` + ChannelID string `json:"channel_id,omitempty"` // Topic of the Stage instance (1-120 characters) Topic string `json:"topic"` // PrivacyLevel of the Stage instance (default GUILD_ONLY) @@ -1788,14 +1789,6 @@ type StageInstanceData struct { SendStartNotification bool `json:"send_start_notification,omitempty"` } -// StageInstanceEditData is provided to StageInstanceEdit -type StageInstanceEditData struct { - // Topic of the Stage instance (1-120 characters) - Topic string `json:"topic"` - // PrivacyLevel of the Stage instance (default GUILD_ONLY) - PrivacyLevel StageInstancePrivacyLevel `json:"privacy_level,omitempty"` -} - // StageInstancePrivacyLevel The privacy level of the Stage instance // https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level type StageInstancePrivacyLevel int From c699ab14359a9bb9f94799b94a809ce948cda40d Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Thu, 14 Apr 2022 21:50:31 +0200 Subject: [PATCH 07/15] Update structs.go Co-authored-by: Fedor Lapshin --- structs.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/structs.go b/structs.go index 0d3f9a1a5..27ffec43a 100644 --- a/structs.go +++ b/structs.go @@ -1776,8 +1776,7 @@ type StageInstance struct { GuildScheduledEventID string `json:"guild_scheduled_event_id"` } -// StageInstanceParams represents the parameters that allow to make a request via -// StageInstanceCreate and StageInstanceEdit +// StageInstanceParams represents the parameters needed to create or edit a stage instance type StageInstanceParams struct { // ChannelID represents the id of the Stage channel ChannelID string `json:"channel_id,omitempty"` From 0e725716a5b6ea81170db0cf8594cbdff72bb6da Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 21:53:17 +0200 Subject: [PATCH 08/15] docs: Remove deprecated doc --- restapi.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/restapi.go b/restapi.go index 7d03c5ee6..587a242eb 100644 --- a/restapi.go +++ b/restapi.go @@ -2904,8 +2904,6 @@ func (s *Session) StageInstance(channelID string) (si *StageInstance, err error) // StageInstanceEdit will edit a Stage instance by ID of the Stage channel. // channelID : The ID of the Stage channel -// topic : The new topic of the Stage instance (1-120 characters). Set empty to keep the current topic. -// privacyLevel : The new privacy level of the Stage instance. Set nil to keep the current privacy level. func (s *Session) StageInstanceEdit(channelID string, data *StageInstanceParams) (si *StageInstance, err error) { body, err := s.RequestWithBucketID("PATCH", EndpointStageInstance(channelID), data, EndpointStageInstance(channelID)) From f38a13bb8ee98263857ebe45a4bdc90291aed836 Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 21:54:52 +0200 Subject: [PATCH 09/15] docs: Add new documentation for restapi function --- restapi.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/restapi.go b/restapi.go index 587a242eb..20d34a4c7 100644 --- a/restapi.go +++ b/restapi.go @@ -2880,6 +2880,7 @@ func (s *Session) FollowupMessageDelete(appID string, interaction *Interaction, // StageInstanceCreate will creates a new Stage instance associated to a Stage channel. // Returns that Stage instance created +// data : The data of the Stage instance to create func (s *Session) StageInstanceCreate(data *StageInstanceParams) (si *StageInstance, err error) { body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances) if err != nil { @@ -2904,6 +2905,7 @@ func (s *Session) StageInstance(channelID string) (si *StageInstance, err error) // StageInstanceEdit will edit a Stage instance by ID of the Stage channel. // channelID : The ID of the Stage channel +// data : The data to edit the Stage instance func (s *Session) StageInstanceEdit(channelID string, data *StageInstanceParams) (si *StageInstance, err error) { body, err := s.RequestWithBucketID("PATCH", EndpointStageInstance(channelID), data, EndpointStageInstance(channelID)) From ea503390fa549c582f0bf6174dd9b610a42ae187 Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Thu, 14 Apr 2022 22:05:45 +0200 Subject: [PATCH 10/15] Update structs.go Co-authored-by: Fedor Lapshin --- structs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/structs.go b/structs.go index 27ffec43a..a959695c4 100644 --- a/structs.go +++ b/structs.go @@ -748,7 +748,7 @@ type Guild struct { Permissions int64 `json:"permissions,string"` // Stage Instances in the guild - StageInstances []*StageInstance `json:"stage_instance"` + StageInstances []*StageInstance `json:"stage_instances"` } // A GuildPreview holds data related to a specific public Discord Guild, even if the user is not in the guild. From ca65dc8f988f59e705cb8757ccd0d70312229656 Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Thu, 14 Apr 2022 22:05:51 +0200 Subject: [PATCH 11/15] Update structs.go Co-authored-by: Fedor Lapshin --- structs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/structs.go b/structs.go index a959695c4..3f9b0a9cd 100644 --- a/structs.go +++ b/structs.go @@ -747,7 +747,7 @@ type Guild struct { // Permissions of our user Permissions int64 `json:"permissions,string"` - // Stage Instances in the guild + // Stage instances in the guild StageInstances []*StageInstance `json:"stage_instances"` } From 3becd6cb9c717542517356b4ca5f87e548a73a39 Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Thu, 14 Apr 2022 22:06:35 +0200 Subject: [PATCH 12/15] Update restapi.go Co-authored-by: Fedor Lapshin --- restapi.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/restapi.go b/restapi.go index 20d34a4c7..96140aa2b 100644 --- a/restapi.go +++ b/restapi.go @@ -2878,8 +2878,8 @@ func (s *Session) FollowupMessageDelete(appID string, interaction *Interaction, // Functions specific to stage instances // ------------------------------------------------------------------------------------------------ -// StageInstanceCreate will creates a new Stage instance associated to a Stage channel. -// Returns that Stage instance created +// StageInstanceCreate creates and returns a new Stage instance associated to a Stage channel. +// data : Parameters needed to create a stage instance. // data : The data of the Stage instance to create func (s *Session) StageInstanceCreate(data *StageInstanceParams) (si *StageInstance, err error) { body, err := s.RequestWithBucketID("POST", EndpointStageInstances, data, EndpointStageInstances) From 52e54753c380ecd7ad9fcadf5bfaccd89a53a376 Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Thu, 14 Apr 2022 22:28:46 +0200 Subject: [PATCH 13/15] Update structs.go Co-authored-by: Fedor Lapshin --- structs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/structs.go b/structs.go index 3f9b0a9cd..e0ce99fba 100644 --- a/structs.go +++ b/structs.go @@ -1788,7 +1788,7 @@ type StageInstanceParams struct { SendStartNotification bool `json:"send_start_notification,omitempty"` } -// StageInstancePrivacyLevel The privacy level of the Stage instance +// StageInstancePrivacyLevel represents the privacy level of a Stage instance // https://discord.com/developers/docs/resources/stage-instance#stage-instance-object-privacy-level type StageInstancePrivacyLevel int From 38be4aa2a0342618893e0cfaa562bb689a006e0f Mon Sep 17 00:00:00 2001 From: 42Atomys Date: Thu, 14 Apr 2022 22:30:20 +0200 Subject: [PATCH 14/15] Update structs.go Co-authored-by: Fedor Lapshin --- structs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/structs.go b/structs.go index e0ce99fba..68005d445 100644 --- a/structs.go +++ b/structs.go @@ -1781,7 +1781,7 @@ type StageInstanceParams struct { // ChannelID represents the id of the Stage channel ChannelID string `json:"channel_id,omitempty"` // Topic of the Stage instance (1-120 characters) - Topic string `json:"topic"` + Topic string `json:"topic,omitempty"` // PrivacyLevel of the Stage instance (default GUILD_ONLY) PrivacyLevel StageInstancePrivacyLevel `json:"privacy_level,omitempty"` // SendStartNotification will notify @everyone that a Stage instance has started From 80a6e74a250c9649b3b89f01116f9a174ad5b7a8 Mon Sep 17 00:00:00 2001 From: Gregory DALMAR Date: Thu, 14 Apr 2022 22:48:31 +0200 Subject: [PATCH 15/15] doc: Add sleep in example to let user see by themselves --- examples/stage_instance/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/stage_instance/main.go b/examples/stage_instance/main.go index 8452efe55..db59dbb48 100644 --- a/examples/stage_instance/main.go +++ b/examples/stage_instance/main.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "log" + "time" "github.com/bwmarrin/discordgo" ) @@ -52,6 +53,7 @@ func main() { } log.Printf("Stage Instance %s has been successfully edited", si.Topic) + time.Sleep(5 * time.Second) if err = s.StageInstanceDelete(*StageChannelID); err != nil { log.Fatalf("Cannot delete stage instance: %v", err) }