Merge pull request #866 from bwmarrin/v8

Switch library to API version v8
This commit is contained in:
Carson Hoffman 2021-01-23 19:52:04 -05:00 committed by GitHub
commit cbfa831b6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 114 additions and 128 deletions

View file

@ -22,7 +22,7 @@ import (
) )
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/) // VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
const VERSION = "0.22.0" const VERSION = "0.23.0-v8alpha"
// ErrMFA will be risen by New when the user has 2FA. // ErrMFA will be risen by New when the user has 2FA.
var ErrMFA = errors.New("account has 2FA enabled") var ErrMFA = errors.New("account has 2FA enabled")

View file

@ -125,7 +125,7 @@ func TestOpenClose(t *testing.T) {
// UpdateStatus - maybe we move this into wsapi_test.go but the websocket // UpdateStatus - maybe we move this into wsapi_test.go but the websocket
// created here is needed. This helps tests that the websocket was setup // created here is needed. This helps tests that the websocket was setup
// and it is working. // and it is working.
if err = d.UpdateStatus(0, time.Now().String()); err != nil { if err = d.UpdateGameStatus(0, time.Now().String()); err != nil {
t.Errorf("UpdateStatus error: %+v", err) t.Errorf("UpdateStatus error: %+v", err)
} }

View file

@ -14,7 +14,7 @@ package discordgo
import "strconv" import "strconv"
// APIVersion is the Discord API version used for the REST and Websocket API. // APIVersion is the Discord API version used for the REST and Websocket API.
var APIVersion = "6" var APIVersion = "8"
// Known Discord API Endpoints. // Known Discord API Endpoints.
var ( var (
@ -90,7 +90,8 @@ var (
EndpointGuildRoles = func(gID string) string { return EndpointGuilds + gID + "/roles" } EndpointGuildRoles = func(gID string) string { return EndpointGuilds + gID + "/roles" }
EndpointGuildRole = func(gID, rID string) string { return EndpointGuilds + gID + "/roles/" + rID } EndpointGuildRole = func(gID, rID string) string { return EndpointGuilds + gID + "/roles/" + rID }
EndpointGuildInvites = func(gID string) string { return EndpointGuilds + gID + "/invites" } EndpointGuildInvites = func(gID string) string { return EndpointGuilds + gID + "/invites" }
EndpointGuildEmbed = func(gID string) string { return EndpointGuilds + gID + "/embed" } EndpointGuildWidget = func(gID string) string { return EndpointGuilds + gID + "/widget" }
EndpointGuildEmbed = EndpointGuildWidget
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" } EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" } EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" }
EndpointGuildIconAnimated = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".gif" } EndpointGuildIconAnimated = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".gif" }

View file

@ -196,8 +196,7 @@ type PresencesReplace []*Presence
// PresenceUpdate is the data for a PresenceUpdate event. // PresenceUpdate is the data for a PresenceUpdate event.
type PresenceUpdate struct { type PresenceUpdate struct {
Presence Presence
GuildID string `json:"guild_id"` GuildID string `json:"guild_id"`
Roles []string `json:"roles"`
} }
// Resumed is the data for a Resumed event. // Resumed is the data for a Resumed event.

View file

@ -55,7 +55,7 @@ func main() {
// We need information about guilds (which includes their channels), // We need information about guilds (which includes their channels),
// messages and voice states. // messages and voice states.
dg.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsGuilds | discordgo.IntentsGuildMessages | discordgo.IntentsGuildVoiceStates) dg.Identify.Intents = discordgo.IntentsGuilds | discordgo.IntentsGuildMessages | discordgo.IntentsGuildVoiceStates
// Open the websocket and begin listening. // Open the websocket and begin listening.
err = dg.Open() err = dg.Open()
@ -78,7 +78,7 @@ func main() {
func ready(s *discordgo.Session, event *discordgo.Ready) { func ready(s *discordgo.Session, event *discordgo.Ready) {
// Set the playing status. // Set the playing status.
s.UpdateStatus(0, "!airhorn") s.UpdateGameStatus(0, "!airhorn")
} }
// This function will be called (due to AddHandler above) every time a new // This function will be called (due to AddHandler above) every time a new

View file

@ -34,7 +34,7 @@ func main() {
dg.AddHandler(messageCreate) dg.AddHandler(messageCreate)
// In this example, we only care about receiving message events. // In this example, we only care about receiving message events.
dg.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsGuildMessages) dg.Identify.Intents = discordgo.IntentsGuildMessages
// Open a websocket connection to Discord and begin listening. // Open a websocket connection to Discord and begin listening.
err = dg.Open() err = dg.Open()

View file

@ -75,7 +75,7 @@ func main() {
defer s.Close() defer s.Close()
// We only really care about receiving voice state updates. // We only really care about receiving voice state updates.
s.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsGuildVoiceStates) s.Identify.Intents = discordgo.IntentsGuildVoiceStates
err = s.Open() err = s.Open()
if err != nil { if err != nil {

View file

@ -34,8 +34,10 @@ const (
MessageTypeUserPremiumGuildSubscriptionTierTwo MessageTypeUserPremiumGuildSubscriptionTierTwo
MessageTypeUserPremiumGuildSubscriptionTierThree MessageTypeUserPremiumGuildSubscriptionTierThree
MessageTypeChannelFollowAdd MessageTypeChannelFollowAdd
MessageTypeGuildDiscoveryDisqualified MessageTypeGuildDiscoveryDisqualified = iota + 1
MessageTypeGuildDiscoveryRequalified MessageTypeGuildDiscoveryRequalified
MessageTypeReply = iota + 4
MessageTypeApplicationCommand
) )
// A Message stores all data related to a specific Discord message. // A Message stores all data related to a specific Discord message.

View file

@ -1,6 +1,7 @@
package discordgo package discordgo
import ( import (
"math"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -140,20 +141,21 @@ func (b *Bucket) Release(headers http.Header) error {
remaining := headers.Get("X-RateLimit-Remaining") remaining := headers.Get("X-RateLimit-Remaining")
reset := headers.Get("X-RateLimit-Reset") reset := headers.Get("X-RateLimit-Reset")
global := headers.Get("X-RateLimit-Global") global := headers.Get("X-RateLimit-Global")
retryAfter := headers.Get("Retry-After") resetAfter := headers.Get("X-RateLimit-Reset-After")
// Update global and per bucket reset time if the proper headers are available // Update global and per bucket reset time if the proper headers are available
// If global is set, then it will block all buckets until after Retry-After // If global is set, then it will block all buckets until after Retry-After
// If Retry-After without global is provided it will use that for the new reset // If Retry-After without global is provided it will use that for the new reset
// time since it's more accurate than X-RateLimit-Reset. // time since it's more accurate than X-RateLimit-Reset.
// If Retry-After after is not proided, it will update the reset time from X-RateLimit-Reset // If Retry-After after is not proided, it will update the reset time from X-RateLimit-Reset
if retryAfter != "" { if resetAfter != "" {
parsedAfter, err := strconv.ParseInt(retryAfter, 10, 64) parsedAfter, err := strconv.ParseFloat(resetAfter, 64)
if err != nil { if err != nil {
return err return err
} }
resetAt := time.Now().Add(time.Duration(parsedAfter) * time.Millisecond) whole, frac := math.Modf(parsedAfter)
resetAt := time.Now().Add(time.Duration(whole) * time.Second).Add(time.Duration(frac*1000) * time.Millisecond)
// Lock either this single bucket or all buckets // Lock either this single bucket or all buckets
if global != "" { if global != "" {
@ -168,7 +170,7 @@ func (b *Bucket) Release(headers http.Header) error {
return err return err
} }
unix, err := strconv.ParseInt(reset, 10, 64) unix, err := strconv.ParseFloat(reset, 64)
if err != nil { if err != nil {
return err return err
} }
@ -177,7 +179,8 @@ func (b *Bucket) Release(headers http.Header) error {
// some extra time is added because without it i still encountered 429's. // some extra time is added because without it i still encountered 429's.
// The added amount is the lowest amount that gave no 429's // The added amount is the lowest amount that gave no 429's
// in 1k requests // in 1k requests
delta := time.Unix(unix, 0).Sub(discordTime) + time.Millisecond*250 whole, frac := math.Modf(unix)
delta := time.Unix(int64(whole), 0).Add(time.Duration(frac*1000)*time.Millisecond).Sub(discordTime) + time.Millisecond*250
b.reset = time.Now().Add(delta) b.reset = time.Now().Add(delta)
} }

View file

@ -1,6 +1,7 @@
package discordgo package discordgo
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
"testing" "testing"
@ -18,7 +19,7 @@ func TestRatelimitReset(t *testing.T) {
headers.Set("X-RateLimit-Remaining", "0") headers.Set("X-RateLimit-Remaining", "0")
// Reset for approx 2 seconds from now // Reset for approx 2 seconds from now
headers.Set("X-RateLimit-Reset", strconv.FormatInt(time.Now().Add(time.Second*2).Unix(), 10)) headers.Set("X-RateLimit-Reset", fmt.Sprint(float64(time.Now().Add(time.Second*2).UnixNano())/1e9))
headers.Set("Date", time.Now().Format(time.RFC850)) headers.Set("Date", time.Now().Format(time.RFC850))
err := bucket.Release(headers) err := bucket.Release(headers)
@ -56,7 +57,7 @@ func TestRatelimitGlobal(t *testing.T) {
headers.Set("X-RateLimit-Global", "1") headers.Set("X-RateLimit-Global", "1")
// Reset for approx 1 seconds from now // Reset for approx 1 seconds from now
headers.Set("Retry-After", "1000") headers.Set("X-RateLimit-Reset-After", "1")
err := bucket.Release(headers) err := bucket.Release(headers)
if err != nil { if err != nil {
@ -105,7 +106,7 @@ func sendBenchReq(endpoint string, rl *RateLimiter) {
headers := http.Header(make(map[string][]string)) headers := http.Header(make(map[string][]string))
headers.Set("X-RateLimit-Remaining", "10") headers.Set("X-RateLimit-Remaining", "10")
headers.Set("X-RateLimit-Reset", strconv.FormatInt(time.Now().Unix(), 10)) headers.Set("X-RateLimit-Reset", fmt.Sprint(float64(time.Now().UnixNano())/1e9))
headers.Set("Date", time.Now().Format(time.RFC850)) headers.Set("Date", time.Now().Format(time.RFC850))
bucket.Release(headers) bucket.Release(headers)

View file

@ -465,7 +465,7 @@ func (s *Session) UserGuildSettingsEdit(guildID string, settings *UserGuildSetti
// //
// NOTE: This function is now deprecated and will be removed in the future. // NOTE: This function is now deprecated and will be removed in the future.
// Please see the same function inside state.go // Please see the same function inside state.go
func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions int, err error) { func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions int64, err error) {
// Try to just get permissions from state. // Try to just get permissions from state.
apermissions, err = s.State.UserChannelPermissions(userID, channelID) apermissions, err = s.State.UserChannelPermissions(userID, channelID)
if err == nil { if err == nil {
@ -507,7 +507,7 @@ func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions
// Calculates the permissions for a member. // Calculates the permissions for a member.
// https://support.discord.com/hc/en-us/articles/206141927-How-is-the-permission-hierarchy-structured- // https://support.discord.com/hc/en-us/articles/206141927-How-is-the-permission-hierarchy-structured-
func memberPermissions(guild *Guild, channel *Channel, userID string, roles []string) (apermissions int) { func memberPermissions(guild *Guild, channel *Channel, userID string, roles []string) (apermissions int64) {
if userID == guild.OwnerID { if userID == guild.OwnerID {
apermissions = PermissionAll apermissions = PermissionAll
return return
@ -542,13 +542,11 @@ func memberPermissions(guild *Guild, channel *Channel, userID string, roles []st
} }
} }
denies := 0 var denies, allows int64
allows := 0
// Member overwrites can override role overrides, so do two passes // Member overwrites can override role overrides, so do two passes
for _, overwrite := range channel.PermissionOverwrites { for _, overwrite := range channel.PermissionOverwrites {
for _, roleID := range roles { for _, roleID := range roles {
if overwrite.Type == "role" && roleID == overwrite.ID { if overwrite.Type == PermissionOverwriteTypeRole && roleID == overwrite.ID {
denies |= overwrite.Deny denies |= overwrite.Deny
allows |= overwrite.Allow allows |= overwrite.Allow
break break
@ -560,7 +558,7 @@ func memberPermissions(guild *Guild, channel *Channel, userID string, roles []st
apermissions |= allows apermissions |= allows
for _, overwrite := range channel.PermissionOverwrites { for _, overwrite := range channel.PermissionOverwrites {
if overwrite.Type == "member" && overwrite.ID == userID { if overwrite.Type == PermissionOverwriteTypeMember && overwrite.ID == userID {
apermissions &= ^overwrite.Deny apermissions &= ^overwrite.Deny
apermissions |= overwrite.Allow apermissions |= overwrite.Allow
break break
@ -717,7 +715,7 @@ func (s *Session) GuildBanCreateWithReason(guildID, userID, reason string, days
queryParams := url.Values{} queryParams := url.Values{}
if days > 0 { if days > 0 {
queryParams.Set("delete-message-days", strconv.Itoa(days)) queryParams.Set("delete_message_days", strconv.Itoa(days))
} }
if reason != "" { if reason != "" {
queryParams.Set("reason", reason) queryParams.Set("reason", reason)
@ -1809,13 +1807,13 @@ func (s *Session) ChannelInviteCreate(channelID string, i Invite) (st *Invite, e
// ChannelPermissionSet creates a Permission Override for the given channel. // ChannelPermissionSet creates a Permission Override for the given channel.
// NOTE: This func name may changed. Using Set instead of Create because // NOTE: This func name may changed. Using Set instead of Create because
// you can both create a new override or update an override with this function. // you can both create a new override or update an override with this function.
func (s *Session) ChannelPermissionSet(channelID, targetID, targetType string, allow, deny int) (err error) { func (s *Session) ChannelPermissionSet(channelID, targetID string, targetType PermissionOverwriteType, allow, deny int) (err error) {
data := struct { data := struct {
ID string `json:"id"` ID string `json:"id"`
Type string `json:"type"` Type PermissionOverwriteType `json:"type"`
Allow int `json:"allow"` Allow int `json:"allow"`
Deny int `json:"deny"` Deny int `json:"deny"`
}{targetID, targetType, allow, deny} }{targetID, targetType, allow, deny}
_, err = s.RequestWithBucketID("PUT", EndpointChannelPermission(channelID, targetID), data, EndpointChannelPermission(channelID, "")) _, err = s.RequestWithBucketID("PUT", EndpointChannelPermission(channelID, targetID), data, EndpointChannelPermission(channelID, ""))

View file

@ -200,14 +200,10 @@ func (s *State) PresenceAdd(guildID string, presence *Presence) error {
//guild.Presences[i] = presence //guild.Presences[i] = presence
//Update status //Update status
guild.Presences[i].Game = presence.Game guild.Presences[i].Activities = presence.Activities
guild.Presences[i].Roles = presence.Roles
if presence.Status != "" { if presence.Status != "" {
guild.Presences[i].Status = presence.Status guild.Presences[i].Status = presence.Status
} }
if presence.Nick != "" {
guild.Presences[i].Nick = presence.Nick
}
//Update the optionally sent user information //Update the optionally sent user information
//ID Is a mandatory field so you should not need to check if it is empty //ID Is a mandatory field so you should not need to check if it is empty
@ -966,24 +962,12 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
// Member not found; this is a user coming online // Member not found; this is a user coming online
m = &Member{ m = &Member{
GuildID: t.GuildID, GuildID: t.GuildID,
Nick: t.Nick,
User: t.User, User: t.User,
Roles: t.Roles,
} }
} else { } else {
if t.Nick != "" {
m.Nick = t.Nick
}
if t.User.Username != "" { if t.User.Username != "" {
m.User.Username = t.User.Username m.User.Username = t.User.Username
} }
// PresenceUpdates always contain a list of roles, so there's no need to check for an empty list here
m.Roles = t.Roles
} }
err = s.MemberAdd(m) err = s.MemberAdd(m)
@ -997,7 +981,7 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
// UserChannelPermissions returns the permission of a user in a channel. // UserChannelPermissions returns the permission of a user in a channel.
// userID : The ID of the user to calculate permissions for. // userID : The ID of the user to calculate permissions for.
// channelID : The ID of the channel to calculate permission for. // channelID : The ID of the channel to calculate permission for.
func (s *State) UserChannelPermissions(userID, channelID string) (apermissions int, err error) { func (s *State) UserChannelPermissions(userID, channelID string) (apermissions int64, err error) {
if s == nil { if s == nil {
return 0, ErrNilState return 0, ErrNilState
} }
@ -1022,7 +1006,7 @@ func (s *State) UserChannelPermissions(userID, channelID string) (apermissions i
// MessagePermissions returns the permissions of the author of the message // MessagePermissions returns the permissions of the author of the message
// in the channel in which it was sent. // in the channel in which it was sent.
func (s *State) MessagePermissions(message *Message) (apermissions int, err error) { func (s *State) MessagePermissions(message *Message) (apermissions int64, err error) {
if s == nil { if s == nil {
return 0, ErrNilState return 0, ErrNilState
} }

View file

@ -14,6 +14,7 @@ package discordgo
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math"
"net/http" "net/http"
"strings" "strings"
"sync" "sync"
@ -322,12 +323,22 @@ type ChannelFollow struct {
WebhookID string `json:"webhook_id"` WebhookID string `json:"webhook_id"`
} }
// PermissionOverwriteType represents the type of resource on which
// a permission overwrite acts.
type PermissionOverwriteType int
// The possible permission overwrite types.
const (
PermissionOverwriteTypeRole PermissionOverwriteType = iota
PermissionOverwriteTypeMember
)
// A PermissionOverwrite holds permission overwrite data for a Channel // A PermissionOverwrite holds permission overwrite data for a Channel
type PermissionOverwrite struct { type PermissionOverwrite struct {
ID string `json:"id"` ID string `json:"id"`
Type string `json:"type"` Type PermissionOverwriteType `json:"type"`
Deny int `json:"deny"` Deny int64 `json:"deny,string"`
Allow int `json:"allow"` Allow int64 `json:"allow,string"`
} }
// Emoji struct holds data related to Emoji's // Emoji struct holds data related to Emoji's
@ -427,9 +438,6 @@ type Guild struct {
// The ID of the AFK voice channel. // The ID of the AFK voice channel.
AfkChannelID string `json:"afk_channel_id"` AfkChannelID string `json:"afk_channel_id"`
// The ID of the embed channel ID, used for embed widgets.
EmbedChannelID string `json:"embed_channel_id"`
// The user ID of the owner of the guild. // The user ID of the owner of the guild.
OwnerID string `json:"owner_id"` OwnerID string `json:"owner_id"`
@ -458,9 +466,6 @@ type Guild struct {
// The verification level required for the guild. // The verification level required for the guild.
VerificationLevel VerificationLevel `json:"verification_level"` VerificationLevel VerificationLevel `json:"verification_level"`
// Whether the guild has embedding enabled.
EmbedEnabled bool `json:"embed_enabled"`
// Whether the guild is considered large. This is // Whether the guild is considered large. This is
// determined by a member threshold in the identify packet, // determined by a member threshold in the identify packet,
// and is currently hard-coded at 250 members in the library. // and is currently hard-coded at 250 members in the library.
@ -564,7 +569,7 @@ type Guild struct {
ApproximatePresenceCount int `json:"approximate_presence_count"` ApproximatePresenceCount int `json:"approximate_presence_count"`
// Permissions of our user // Permissions of our user
Permissions int `json:"permissions"` Permissions int64 `json:"permissions,string"`
} }
// MessageNotifications is the notification level for a guild // MessageNotifications is the notification level for a guild
@ -606,7 +611,7 @@ type UserGuild struct {
Name string `json:"name"` Name string `json:"name"`
Icon string `json:"icon"` Icon string `json:"icon"`
Owner bool `json:"owner"` Owner bool `json:"owner"`
Permissions int `json:"permissions"` Permissions int64 `json:"permissions,string"`
} }
// A GuildParams stores all the data needed to update discord guild settings // A GuildParams stores all the data needed to update discord guild settings
@ -650,7 +655,7 @@ type Role struct {
// The permissions of the role on the guild (doesn't include channel overrides). // The permissions of the role on the guild (doesn't include channel overrides).
// This is a combination of bit masks; the presence of a certain permission can // This is a combination of bit masks; the presence of a certain permission can
// be checked by performing a bitwise AND between this int and the permission. // be checked by performing a bitwise AND between this int and the permission.
Permissions int `json:"permissions"` Permissions int64 `json:"permissions,string"`
} }
// Mention returns a string which mentions the role // Mention returns a string which mentions the role
@ -688,39 +693,10 @@ type VoiceState struct {
// A Presence stores the online, offline, or idle and game status of Guild members. // A Presence stores the online, offline, or idle and game status of Guild members.
type Presence struct { type Presence struct {
User *User `json:"user"` User *User `json:"user"`
Status Status `json:"status"` Status Status `json:"status"`
Game *Game `json:"game"` Activities []*Activity `json:"activities"`
Activities []*Game `json:"activities"` Since *int `json:"since"`
Nick string `json:"nick"`
Roles []string `json:"roles"`
Since *int `json:"since"`
}
// GameType is the type of "game" (see GameType* consts) in the Game struct
type GameType int
// Valid GameType values
const (
GameTypeGame GameType = iota
GameTypeStreaming
GameTypeListening
GameTypeWatching
GameTypeCustom
)
// A Game struct holds the name of the "playing .." game for a user
type Game struct {
Name string `json:"name"`
Type GameType `json:"type"`
URL string `json:"url,omitempty"`
Details string `json:"details,omitempty"`
State string `json:"state,omitempty"`
TimeStamps TimeStamps `json:"timestamps,omitempty"`
Assets Assets `json:"assets,omitempty"`
ApplicationID string `json:"application_id,omitempty"`
Instance int8 `json:"instance,omitempty"`
// TODO: Party and Secrets (unknown structure)
} }
// A TimeStamps struct contains start and end times used in the rich presence "playing .." Game // A TimeStamps struct contains start and end times used in the rich presence "playing .." Game
@ -841,6 +817,26 @@ type TooManyRequests struct {
RetryAfter time.Duration `json:"retry_after"` RetryAfter time.Duration `json:"retry_after"`
} }
// UnmarshalJSON helps support translation of a milliseconds-based float
// into a time.Duration on TooManyRequests.
func (t *TooManyRequests) UnmarshalJSON(b []byte) error {
u := struct {
Bucket string `json:"bucket"`
Message string `json:"message"`
RetryAfter float64 `json:"retry_after"`
}{}
err := json.Unmarshal(b, &u)
if err != nil {
return err
}
t.Bucket = u.Bucket
t.Message = u.Message
whole, frac := math.Modf(u.RetryAfter)
t.RetryAfter = time.Duration(whole)*time.Second + time.Duration(frac*1000)*time.Millisecond
return nil
}
// A ReadState stores data on the read state of channels. // A ReadState stores data on the read state of channels.
type ReadState struct { type ReadState struct {
MentionCount int `json:"mention_count"` MentionCount int `json:"mention_count"`
@ -1131,7 +1127,7 @@ type ActivityType int
// Valid ActivityType values // Valid ActivityType values
const ( const (
ActivityTypeGame GameType = iota ActivityTypeGame ActivityType = iota
ActivityTypeStreaming ActivityTypeStreaming
ActivityTypeListening ActivityTypeListening
// ActivityTypeWatching // not valid in this use case? // ActivityTypeWatching // not valid in this use case?
@ -1148,7 +1144,7 @@ type Identify struct {
Shard *[2]int `json:"shard,omitempty"` Shard *[2]int `json:"shard,omitempty"`
Presence GatewayStatusUpdate `json:"presence,omitempty"` Presence GatewayStatusUpdate `json:"presence,omitempty"`
GuildSubscriptions bool `json:"guild_subscriptions"` GuildSubscriptions bool `json:"guild_subscriptions"`
Intents *Intent `json:"intents,omitempty"` Intents Intent `json:"intents"`
} }
// IdentifyProperties contains the "properties" portion of an Identify packet // IdentifyProperties contains the "properties" portion of an Identify packet
@ -1335,7 +1331,9 @@ const (
IntentsNone Intent = 0 IntentsNone Intent = 0
) )
// MakeIntent helps convert a gateway intent value for use in the Identify structure. // MakeIntent used to help convert a gateway intent value for use in the Identify structure;
func MakeIntent(intents Intent) *Intent { // this was useful to help support the use of a pointer type when intents were optional.
return &intents // This is now a no-op, and is not necessary to use.
func MakeIntent(intents Intent) Intent {
return intents
} }

View file

@ -322,10 +322,10 @@ func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{}
// UpdateStatusData ia provided to UpdateStatusComplex() // UpdateStatusData ia provided to UpdateStatusComplex()
type UpdateStatusData struct { type UpdateStatusData struct {
IdleSince *int `json:"since"` IdleSince *int `json:"since"`
Game *Game `json:"game"` Activities []*Activity `json:"activities"`
AFK bool `json:"afk"` AFK bool `json:"afk"`
Status string `json:"status"` Status string `json:"status"`
} }
type updateStatusOp struct { type updateStatusOp struct {
@ -333,7 +333,7 @@ type updateStatusOp struct {
Data UpdateStatusData `json:"d"` Data UpdateStatusData `json:"d"`
} }
func newUpdateStatusData(idle int, gameType GameType, game, url string) *UpdateStatusData { func newUpdateStatusData(idle int, activityType ActivityType, name, url string) *UpdateStatusData {
usd := &UpdateStatusData{ usd := &UpdateStatusData{
Status: "online", Status: "online",
} }
@ -342,43 +342,43 @@ func newUpdateStatusData(idle int, gameType GameType, game, url string) *UpdateS
usd.IdleSince = &idle usd.IdleSince = &idle
} }
if game != "" { if name != "" {
usd.Game = &Game{ usd.Activities = []*Activity{{
Name: game, Name: name,
Type: gameType, Type: activityType,
URL: url, URL: url,
} }}
} }
return usd return usd
} }
// UpdateStatus is used to update the user's status. // UpdateGameStatus is used to update the user's status.
// If idle>0 then set status to idle. // If idle>0 then set status to idle.
// If game!="" then set game. // If name!="" then set game.
// if otherwise, set status to active, and no game. // if otherwise, set status to active, and no activity.
func (s *Session) UpdateStatus(idle int, game string) (err error) { func (s *Session) UpdateGameStatus(idle int, name string) (err error) {
return s.UpdateStatusComplex(*newUpdateStatusData(idle, GameTypeGame, game, "")) return s.UpdateStatusComplex(*newUpdateStatusData(idle, ActivityTypeGame, name, ""))
} }
// UpdateStreamingStatus is used to update the user's streaming status. // UpdateStreamingStatus is used to update the user's streaming status.
// If idle>0 then set status to idle. // If idle>0 then set status to idle.
// If game!="" then set game. // If name!="" then set game.
// If game!="" and url!="" then set the status type to streaming with the URL set. // If name!="" and url!="" then set the status type to streaming with the URL set.
// if otherwise, set status to active, and no game. // if otherwise, set status to active, and no game.
func (s *Session) UpdateStreamingStatus(idle int, game string, url string) (err error) { func (s *Session) UpdateStreamingStatus(idle int, name string, url string) (err error) {
gameType := GameTypeGame gameType := ActivityTypeGame
if url != "" { if url != "" {
gameType = GameTypeStreaming gameType = ActivityTypeStreaming
} }
return s.UpdateStatusComplex(*newUpdateStatusData(idle, gameType, game, url)) return s.UpdateStatusComplex(*newUpdateStatusData(idle, gameType, name, url))
} }
// UpdateListeningStatus is used to set the user to "Listening to..." // UpdateListeningStatus is used to set the user to "Listening to..."
// If game!="" then set to what user is listening to // If name!="" then set to what user is listening to
// Else, set user to active and no game. // Else, set user to active and no activity.
func (s *Session) UpdateListeningStatus(game string) (err error) { func (s *Session) UpdateListeningStatus(name string) (err error) {
return s.UpdateStatusComplex(*newUpdateStatusData(0, GameTypeListening, game, "")) return s.UpdateStatusComplex(*newUpdateStatusData(0, ActivityTypeListening, name, ""))
} }
// UpdateStatusComplex allows for sending the raw status update data untouched by discordgo. // UpdateStatusComplex allows for sending the raw status update data untouched by discordgo.