Skip to content

Commit

Permalink
feat: Add support of Stage Instance REST API and Events (#1158)
Browse files Browse the repository at this point in the history
* feat: Add support of StageInstance RESTAPI and Events

* chore: Make the changes for following the current convention of package

* doc: Add missing docs and example for stage-instance

* doc: Add final log for deleted stage instance

* refactor: Prevent trailing slash on stage instance endpoint

* chore: Harmonize params structure

* Update structs.go

Co-authored-by: Fedor Lapshin <fe.lap.prog@gmail.com>

* docs: Remove deprecated doc

* docs: Add new documentation for restapi function

* Update structs.go

Co-authored-by: Fedor Lapshin <fe.lap.prog@gmail.com>

* Update structs.go

Co-authored-by: Fedor Lapshin <fe.lap.prog@gmail.com>

* Update restapi.go

Co-authored-by: Fedor Lapshin <fe.lap.prog@gmail.com>

* Update structs.go

Co-authored-by: Fedor Lapshin <fe.lap.prog@gmail.com>

* Update structs.go

Co-authored-by: Fedor Lapshin <fe.lap.prog@gmail.com>

* doc: Add sleep in example to let user see by themselves

Co-authored-by: Fedor Lapshin <fe.lap.prog@gmail.com>
  • Loading branch information
42atomys and FedorLap2006 committed Apr 14, 2022
1 parent b138df6 commit 8a126aa
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 9 deletions.
20 changes: 11 additions & 9 deletions endpoints.go
Expand Up @@ -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/"
Expand Down Expand Up @@ -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(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" }
Expand Down
63 changes: 63 additions & 0 deletions eventhandlers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions events.go
Expand Up @@ -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
Expand Down
61 changes: 61 additions & 0 deletions examples/stage_instance/main.go
@@ -0,0 +1,61 @@
package main

import (
"flag"
"fmt"
"log"
"time"

"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.StageInstanceParams{
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, err = s.StageInstanceEdit(*StageChannelID, &discordgo.StageInstanceParams{
Topic: "New amazing topic",
})
if err != nil {
log.Fatalf("Cannot edit stage instance: %v", err)
}
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)
}
log.Printf("Stage Instance %s has been successfully deleted", si.Topic)
}
50 changes: 50 additions & 0 deletions restapi.go
Expand Up @@ -2886,6 +2886,56 @@ func (s *Session) FollowupMessageDelete(interaction *Interaction, messageID stri
return s.WebhookMessageDelete(interaction.AppID, interaction.Token, messageID)
}

// ------------------------------------------------------------------------------------------------
// Functions specific to stage instances
// ------------------------------------------------------------------------------------------------

// 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)
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
// 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))
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
// ------------------------------------------------------------------------------------------------
Expand Down
47 changes: 47 additions & 0 deletions structs.go
Expand Up @@ -263,6 +263,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.
Expand Down Expand Up @@ -748,6 +749,9 @@ type Guild struct {

// Permissions of our user
Permissions int64 `json:"permissions,string"`

// Stage instances in the guild
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.
Expand Down Expand Up @@ -1755,6 +1759,49 @@ 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"`
}

// 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"`
// Topic of the Stage instance (1-120 characters)
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
SendStartNotification bool `json:"send_start_notification,omitempty"`
}

// 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

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
Expand Down

0 comments on commit 8a126aa

Please sign in to comment.