Skip to content

Commit

Permalink
Add Snowflake type, which is a string with a custom UnmarshalJSON.
Browse files Browse the repository at this point in the history
Change all fields which are of type `snowflake` in the Discord API to this new type.

The Snowflake type will unmarshal all string values (some special identifiers, such as `@me` are used), and any valid uint64.
  • Loading branch information
kagadar committed Jan 12, 2024
1 parent afc5788 commit a323fa3
Show file tree
Hide file tree
Showing 19 changed files with 684 additions and 628 deletions.
7 changes: 5 additions & 2 deletions discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ const VERSION = "0.27.1"

// 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 ..."
//
// e.g. "Bot ..."
//
// Or if it is an OAuth2 token, it must be prefixed with "Bearer "
// e.g. "Bearer ..."
//
// e.g. "Bearer ..."
func New(token string) (s *Session, err error) {

// Create an empty Session interface.
Expand Down
16 changes: 8 additions & 8 deletions discord_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ import (
"time"
)

//////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// VARS NEEDED FOR TESTING
// ////////////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////// VARS NEEDED FOR TESTING
var (
dg *Session // Stores a global discordgo user session
dgBot *Session // Stores a global discordgo bot session

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
envVoiceChannel = os.Getenv("DG_VOICE_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 = Snowflake(os.Getenv("DG_GUILD")) // Guild ID to use for tests
envChannel = Snowflake(os.Getenv("DG_CHANNEL")) // Channel ID to use for tests
envVoiceChannel = Snowflake(os.Getenv("DG_VOICE_CHANNEL")) // Channel ID to use for tests
envAdmin = Snowflake(os.Getenv("DG_ADMIN")) // User ID of admin user to use for tests
)

func TestMain(m *testing.M) {
Expand Down
276 changes: 151 additions & 125 deletions endpoints.go

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ func registerInterfaceProvider(eh EventInterfaceProvider) {
// fmt.Errorf("event %s already registered", eh.Type())
}
registeredInterfaceProviders[eh.Type()] = eh
return
}

// eventHandlerInstance is a wrapper around an event handler, as functions
Expand Down Expand Up @@ -102,12 +101,14 @@ func (s *Session) addEventHandlerOnce(eventHandler EventHandler) func() {
// to a struct corresponding to the event for which you want to listen.
//
// eg:
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
// })
//
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
// })
//
// or:
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
// })
//
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
// })
//
// List of events can be found at this page, with corresponding names in the
// library for each event: https://discord.com/developers/docs/topics/gateway#event-names
Expand Down
76 changes: 38 additions & 38 deletions events.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ type ChannelDelete struct {

// ChannelPinsUpdate stores data for a ChannelPinsUpdate event.
type ChannelPinsUpdate struct {
LastPinTimestamp string `json:"last_pin_timestamp"`
ChannelID string `json:"channel_id"`
GuildID string `json:"guild_id,omitempty"`
LastPinTimestamp string `json:"last_pin_timestamp"`
ChannelID Snowflake `json:"channel_id"`
GuildID Snowflake `json:"guild_id,omitempty"`
}

// ThreadCreate is the data for a ThreadCreate event.
Expand All @@ -87,11 +87,11 @@ type ThreadDelete struct {
// ThreadListSync is the data for a ThreadListSync event.
type ThreadListSync struct {
// The id of the guild
GuildID string `json:"guild_id"`
GuildID Snowflake `json:"guild_id"`
// The parent channel ids whose threads are being synced.
// If omitted, then threads were synced for the entire guild.
// This array may contain channel_ids that have no active threads as well, so you know to clear that data.
ChannelIDs []string `json:"channel_ids"`
ChannelIDs []Snowflake `json:"channel_ids"`
// All active threads in the given channels that the current user can access
Threads []*Channel `json:"threads"`
// All thread member objects from the synced threads for the current user,
Expand All @@ -102,16 +102,16 @@ type ThreadListSync struct {
// ThreadMemberUpdate is the data for a ThreadMemberUpdate event.
type ThreadMemberUpdate struct {
*ThreadMember
GuildID string `json:"guild_id"`
GuildID Snowflake `json:"guild_id"`
}

// ThreadMembersUpdate is the data for a ThreadMembersUpdate event.
type ThreadMembersUpdate struct {
ID string `json:"id"`
GuildID string `json:"guild_id"`
ID Snowflake `json:"id"`
GuildID Snowflake `json:"guild_id"`
MemberCount int `json:"member_count"`
AddedMembers []AddedThreadMember `json:"added_members"`
RemovedMembers []string `json:"removed_member_ids"`
RemovedMembers []Snowflake `json:"removed_member_ids"`
}

// GuildCreate is the data for a GuildCreate event.
Expand All @@ -132,14 +132,14 @@ type GuildDelete struct {

// GuildBanAdd is the data for a GuildBanAdd event.
type GuildBanAdd struct {
User *User `json:"user"`
GuildID string `json:"guild_id"`
User *User `json:"user"`
GuildID Snowflake `json:"guild_id"`
}

// GuildBanRemove is the data for a GuildBanRemove event.
type GuildBanRemove struct {
User *User `json:"user"`
GuildID string `json:"guild_id"`
User *User `json:"user"`
GuildID Snowflake `json:"guild_id"`
}

// GuildMemberAdd is the data for a GuildMemberAdd event.
Expand Down Expand Up @@ -170,19 +170,19 @@ type GuildRoleUpdate struct {

// A GuildRoleDelete is the data for a GuildRoleDelete event.
type GuildRoleDelete struct {
RoleID string `json:"role_id"`
GuildID string `json:"guild_id"`
RoleID Snowflake `json:"role_id"`
GuildID Snowflake `json:"guild_id"`
}

// A GuildEmojisUpdate is the data for a guild emoji update event.
type GuildEmojisUpdate struct {
GuildID string `json:"guild_id"`
Emojis []*Emoji `json:"emojis"`
GuildID Snowflake `json:"guild_id"`
Emojis []*Emoji `json:"emojis"`
}

// A GuildMembersChunk is the data for a GuildMembersChunk event.
type GuildMembersChunk struct {
GuildID string `json:"guild_id"`
GuildID Snowflake `json:"guild_id"`
Members []*Member `json:"members"`
ChunkIndex int `json:"chunk_index"`
ChunkCount int `json:"chunk_count"`
Expand All @@ -193,7 +193,7 @@ type GuildMembersChunk struct {

// GuildIntegrationsUpdate is the data for a GuildIntegrationsUpdate event.
type GuildIntegrationsUpdate struct {
GuildID string `json:"guild_id"`
GuildID Snowflake `json:"guild_id"`
}

// StageInstanceEventCreate is the data for a StageInstanceEventCreate event.
Expand Down Expand Up @@ -228,16 +228,16 @@ type GuildScheduledEventDelete struct {

// GuildScheduledEventUserAdd is the data for a GuildScheduledEventUserAdd event.
type GuildScheduledEventUserAdd struct {
GuildScheduledEventID string `json:"guild_scheduled_event_id"`
UserID string `json:"user_id"`
GuildID string `json:"guild_id"`
GuildScheduledEventID Snowflake `json:"guild_scheduled_event_id"`
UserID Snowflake `json:"user_id"`
GuildID Snowflake `json:"guild_id"`
}

// GuildScheduledEventUserRemove is the data for a GuildScheduledEventUserRemove event.
type GuildScheduledEventUserRemove struct {
GuildScheduledEventID string `json:"guild_scheduled_event_id"`
UserID string `json:"user_id"`
GuildID string `json:"guild_id"`
GuildScheduledEventID Snowflake `json:"guild_scheduled_event_id"`
UserID Snowflake `json:"user_id"`
GuildID Snowflake `json:"guild_id"`
}

// MessageCreate is the data for a MessageCreate event.
Expand Down Expand Up @@ -295,7 +295,7 @@ type PresencesReplace []*Presence
// PresenceUpdate is the data for a PresenceUpdate event.
type PresenceUpdate struct {
Presence
GuildID string `json:"guild_id"`
GuildID Snowflake `json:"guild_id"`
}

// Resumed is the data for a Resumed event.
Expand All @@ -305,10 +305,10 @@ type Resumed struct {

// TypingStart is the data for a TypingStart event.
type TypingStart struct {
UserID string `json:"user_id"`
ChannelID string `json:"channel_id"`
GuildID string `json:"guild_id,omitempty"`
Timestamp int `json:"timestamp"`
UserID Snowflake `json:"user_id"`
ChannelID Snowflake `json:"channel_id"`
GuildID Snowflake `json:"guild_id,omitempty"`
Timestamp int `json:"timestamp"`
}

// UserUpdate is the data for a UserUpdate event.
Expand All @@ -318,9 +318,9 @@ type UserUpdate struct {

// VoiceServerUpdate is the data for a VoiceServerUpdate event.
type VoiceServerUpdate struct {
Token string `json:"token"`
GuildID string `json:"guild_id"`
Endpoint string `json:"endpoint"`
Token string `json:"token"`
GuildID Snowflake `json:"guild_id"`
Endpoint string `json:"endpoint"`
}

// VoiceStateUpdate is the data for a VoiceStateUpdate event.
Expand All @@ -332,15 +332,15 @@ type VoiceStateUpdate struct {

// MessageDeleteBulk is the data for a MessageDeleteBulk event
type MessageDeleteBulk struct {
Messages []string `json:"ids"`
ChannelID string `json:"channel_id"`
GuildID string `json:"guild_id"`
Messages []Snowflake `json:"ids"`
ChannelID Snowflake `json:"channel_id"`
GuildID Snowflake `json:"guild_id"`
}

// WebhooksUpdate is the data for a WebhooksUpdate event
type WebhooksUpdate struct {
GuildID string `json:"guild_id"`
ChannelID string `json:"channel_id"`
GuildID Snowflake `json:"guild_id"`
ChannelID Snowflake `json:"channel_id"`
}

// InteractionCreate is the data for a InteractionCreate event
Expand Down
16 changes: 8 additions & 8 deletions interactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,12 @@ func (t InteractionType) String() string {

// Interaction represents data of an interaction.
type Interaction struct {
ID string `json:"id"`
AppID string `json:"application_id"`
ID Snowflake `json:"id"`
AppID Snowflake `json:"application_id"`
Type InteractionType `json:"type"`
Data InteractionData `json:"data"`
GuildID string `json:"guild_id"`
ChannelID string `json:"channel_id"`
GuildID Snowflake `json:"guild_id"`
ChannelID Snowflake `json:"channel_id"`

// 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.
Expand Down Expand Up @@ -454,7 +454,7 @@ func (o ApplicationCommandInteractionDataOption) ChannelValue(s *Session) *Chann
if o.Type != ApplicationCommandOptionChannel {
panic("ChannelValue called on data option of type " + o.Type.String())
}
chanID := o.Value.(string)
chanID := Snowflake(o.Value.(string))

if s == nil {
return &Channel{ID: chanID}
Expand All @@ -473,11 +473,11 @@ func (o ApplicationCommandInteractionDataOption) ChannelValue(s *Session) *Chann

// RoleValue is a utility function for casting option value to role object.
// s : Session object, if not nil, function additionally fetches all role's data
func (o ApplicationCommandInteractionDataOption) RoleValue(s *Session, gID string) *Role {
func (o ApplicationCommandInteractionDataOption) RoleValue(s *Session, gID Snowflake) *Role {
if o.Type != ApplicationCommandOptionRole && o.Type != ApplicationCommandOptionMentionable {
panic("RoleValue called on data option of type " + o.Type.String())
}
roleID := o.Value.(string)
roleID := Snowflake(o.Value.(string))

if s == nil || gID == "" {
return &Role{ID: roleID}
Expand Down Expand Up @@ -505,7 +505,7 @@ func (o ApplicationCommandInteractionDataOption) UserValue(s *Session) *User {
if o.Type != ApplicationCommandOptionUser && o.Type != ApplicationCommandOptionMentionable {
panic("UserValue called on data option of type " + o.Type.String())
}
userID := o.Value.(string)
userID := Snowflake(o.Value.(string))

if s == nil {
return &User{ID: userID}
Expand Down
9 changes: 5 additions & 4 deletions logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ var Logger func(msgL, caller int, format string, a ...interface{})

// msglog provides package wide logging consistency for discordgo
// the format, a... portion this command follows that of fmt.Printf
// msgL : LogLevel of the message
// caller : 1 + the number of callers away from the message source
// format : Printf style message format
// a ... : comma separated list of values to pass
//
// msgL : LogLevel of the message
// caller : 1 + the number of callers away from the message source
// format : Printf style message format
// a ... : comma separated list of values to pass
func msglog(msgL, caller int, format string, a ...interface{}) {

if Logger != nil {
Expand Down
Loading

0 comments on commit a323fa3

Please sign in to comment.