forked from lug/matterbridge
		
	Update vendor (bwmarrin/discordgo) apiv6
This commit is contained in:
		
							
								
								
									
										3
									
								
								vendor/github.com/bwmarrin/discordgo/discord.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/bwmarrin/discordgo/discord.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -21,7 +21,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| // VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/) | // VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/) | ||||||
| const VERSION = "0.16.0" | const VERSION = "0.17.0" | ||||||
|  |  | ||||||
| // 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") | ||||||
| @@ -59,6 +59,7 @@ func New(args ...interface{}) (s *Session, err error) { | |||||||
| 		MaxRestRetries:         3, | 		MaxRestRetries:         3, | ||||||
| 		Client:                 &http.Client{Timeout: (20 * time.Second)}, | 		Client:                 &http.Client{Timeout: (20 * time.Second)}, | ||||||
| 		sequence:               new(int64), | 		sequence:               new(int64), | ||||||
|  | 		LastHeartbeatAck:       time.Now().UTC(), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// If no arguments are passed return the empty Session interface. | 	// If no arguments are passed return the empty Session interface. | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								vendor/github.com/bwmarrin/discordgo/endpoints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/bwmarrin/discordgo/endpoints.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,6 +11,9 @@ | |||||||
|  |  | ||||||
| package discordgo | package discordgo | ||||||
|  |  | ||||||
|  | // APIVersion is the Discord API version used for the REST and Websocket API. | ||||||
|  | var APIVersion = "6" | ||||||
|  |  | ||||||
| // Known Discord API Endpoints. | // Known Discord API Endpoints. | ||||||
| var ( | var ( | ||||||
| 	EndpointStatus     = "https://status.discordapp.com/api/v2/" | 	EndpointStatus     = "https://status.discordapp.com/api/v2/" | ||||||
| @@ -19,11 +22,12 @@ var ( | |||||||
| 	EndpointSmUpcoming = EndpointSm + "upcoming.json" | 	EndpointSmUpcoming = EndpointSm + "upcoming.json" | ||||||
|  |  | ||||||
| 	EndpointDiscord    = "https://discordapp.com/" | 	EndpointDiscord    = "https://discordapp.com/" | ||||||
| 	EndpointAPI      = EndpointDiscord + "api/" | 	EndpointAPI        = EndpointDiscord + "api/v" + APIVersion + "/" | ||||||
| 	EndpointGuilds     = EndpointAPI + "guilds/" | 	EndpointGuilds     = EndpointAPI + "guilds/" | ||||||
| 	EndpointChannels   = EndpointAPI + "channels/" | 	EndpointChannels   = EndpointAPI + "channels/" | ||||||
| 	EndpointUsers      = EndpointAPI + "users/" | 	EndpointUsers      = EndpointAPI + "users/" | ||||||
| 	EndpointGateway    = EndpointAPI + "gateway" | 	EndpointGateway    = EndpointAPI + "gateway" | ||||||
|  | 	EndpointGatewayBot = EndpointGateway + "/bot" | ||||||
| 	EndpointWebhooks   = EndpointAPI + "webhooks/" | 	EndpointWebhooks   = EndpointAPI + "webhooks/" | ||||||
|  |  | ||||||
| 	EndpointCDN             = "https://cdn.discordapp.com/" | 	EndpointCDN             = "https://cdn.discordapp.com/" | ||||||
| @@ -56,6 +60,7 @@ var ( | |||||||
|  |  | ||||||
| 	EndpointUser               = func(uID string) string { return EndpointUsers + uID } | 	EndpointUser               = func(uID string) string { return EndpointUsers + uID } | ||||||
| 	EndpointUserAvatar         = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" } | 	EndpointUserAvatar         = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" } | ||||||
|  | 	EndpointUserAvatarAnimated = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".gif" } | ||||||
| 	EndpointUserSettings       = func(uID string) string { return EndpointUsers + uID + "/settings" } | 	EndpointUserSettings       = func(uID string) string { return EndpointUsers + uID + "/settings" } | ||||||
| 	EndpointUserGuilds         = func(uID string) string { return EndpointUsers + uID + "/guilds" } | 	EndpointUserGuilds         = func(uID string) string { return EndpointUsers + uID + "/guilds" } | ||||||
| 	EndpointUserGuild          = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID } | 	EndpointUserGuild          = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID } | ||||||
| @@ -103,6 +108,9 @@ var ( | |||||||
| 	EndpointWebhook         = func(wID string) string { return EndpointWebhooks + wID } | 	EndpointWebhook         = func(wID string) string { return EndpointWebhooks + wID } | ||||||
| 	EndpointWebhookToken    = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token } | 	EndpointWebhookToken    = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token } | ||||||
|  |  | ||||||
|  | 	EndpointMessageReactionsAll = func(cID, mID string) string { | ||||||
|  | 		return EndpointChannelMessage(cID, mID) + "/reactions" | ||||||
|  | 	} | ||||||
| 	EndpointMessageReactions = func(cID, mID, eID string) string { | 	EndpointMessageReactions = func(cID, mID, eID string) string { | ||||||
| 		return EndpointChannelMessage(cID, mID) + "/reactions/" + eID | 		return EndpointChannelMessage(cID, mID) + "/reactions/" + eID | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								vendor/github.com/bwmarrin/discordgo/event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/bwmarrin/discordgo/event.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -156,13 +156,21 @@ func (s *Session) removeEventHandlerInstance(t string, ehi *eventHandlerInstance | |||||||
| // Handles calling permanent and once handlers for an event type. | // Handles calling permanent and once handlers for an event type. | ||||||
| func (s *Session) handle(t string, i interface{}) { | func (s *Session) handle(t string, i interface{}) { | ||||||
| 	for _, eh := range s.handlers[t] { | 	for _, eh := range s.handlers[t] { | ||||||
|  | 		if s.SyncEvents { | ||||||
|  | 			eh.eventHandler.Handle(s, i) | ||||||
|  | 		} else { | ||||||
| 			go eh.eventHandler.Handle(s, i) | 			go eh.eventHandler.Handle(s, i) | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if len(s.onceHandlers[t]) > 0 { | 	if len(s.onceHandlers[t]) > 0 { | ||||||
| 		for _, eh := range s.onceHandlers[t] { | 		for _, eh := range s.onceHandlers[t] { | ||||||
|  | 			if s.SyncEvents { | ||||||
|  | 				eh.eventHandler.Handle(s, i) | ||||||
|  | 			} else { | ||||||
| 				go eh.eventHandler.Handle(s, i) | 				go eh.eventHandler.Handle(s, i) | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 		s.onceHandlers[t] = nil | 		s.onceHandlers[t] = nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -216,7 +224,7 @@ func (s *Session) onInterface(i interface{}) { | |||||||
| 	case *VoiceStateUpdate: | 	case *VoiceStateUpdate: | ||||||
| 		go s.onVoiceStateUpdate(t) | 		go s.onVoiceStateUpdate(t) | ||||||
| 	} | 	} | ||||||
| 	err := s.State.onInterface(s, i) | 	err := s.State.OnInterface(s, i) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		s.log(LogDebug, "error dispatching internal event, %s", err) | 		s.log(LogDebug, "error dispatching internal event, %s", err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								vendor/github.com/bwmarrin/discordgo/message.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										90
									
								
								vendor/github.com/bwmarrin/discordgo/message.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -10,9 +10,24 @@ | |||||||
| package discordgo | package discordgo | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
| 	"regexp" | 	"regexp" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // MessageType is the type of Message | ||||||
|  | type MessageType int | ||||||
|  |  | ||||||
|  | // Block contains the valid known MessageType values | ||||||
|  | const ( | ||||||
|  | 	MessageTypeDefault MessageType = iota | ||||||
|  | 	MessageTypeRecipientAdd | ||||||
|  | 	MessageTypeRecipientRemove | ||||||
|  | 	MessageTypeCall | ||||||
|  | 	MessageTypeChannelNameChange | ||||||
|  | 	MessageTypeChannelIconChange | ||||||
|  | 	MessageTypeChannelPinnedMessage | ||||||
|  | 	MessageTypeGuildMemberJoin | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // A Message stores all data related to a specific Discord message. | // A Message stores all data related to a specific Discord message. | ||||||
| @@ -30,11 +45,13 @@ type Message struct { | |||||||
| 	Embeds          []*MessageEmbed      `json:"embeds"` | 	Embeds          []*MessageEmbed      `json:"embeds"` | ||||||
| 	Mentions        []*User              `json:"mentions"` | 	Mentions        []*User              `json:"mentions"` | ||||||
| 	Reactions       []*MessageReactions  `json:"reactions"` | 	Reactions       []*MessageReactions  `json:"reactions"` | ||||||
|  | 	Type            MessageType          `json:"type"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // File stores info about files you e.g. send in messages. | // File stores info about files you e.g. send in messages. | ||||||
| type File struct { | type File struct { | ||||||
| 	Name        string | 	Name        string | ||||||
|  | 	ContentType string | ||||||
| 	Reader      io.Reader | 	Reader      io.Reader | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -43,7 +60,10 @@ type MessageSend struct { | |||||||
| 	Content string        `json:"content,omitempty"` | 	Content string        `json:"content,omitempty"` | ||||||
| 	Embed   *MessageEmbed `json:"embed,omitempty"` | 	Embed   *MessageEmbed `json:"embed,omitempty"` | ||||||
| 	Tts     bool          `json:"tts"` | 	Tts     bool          `json:"tts"` | ||||||
| 	File    *File         `json:"file"` | 	Files   []*File       `json:"-"` | ||||||
|  |  | ||||||
|  | 	// TODO: Remove this when compatibility is not required. | ||||||
|  | 	File *File `json:"-"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // MessageEdit is used to chain parameters via ChannelMessageEditComplex, which | // MessageEdit is used to chain parameters via ChannelMessageEditComplex, which | ||||||
| @@ -168,13 +188,65 @@ type MessageReactions struct { | |||||||
|  |  | ||||||
| // ContentWithMentionsReplaced will replace all @<id> mentions with the | // ContentWithMentionsReplaced will replace all @<id> mentions with the | ||||||
| // username of the mention. | // username of the mention. | ||||||
| func (m *Message) ContentWithMentionsReplaced() string { | func (m *Message) ContentWithMentionsReplaced() (content string) { | ||||||
| 	if m.Mentions == nil { | 	content = m.Content | ||||||
| 		return m.Content |  | ||||||
| 	} |  | ||||||
| 	content := m.Content |  | ||||||
| 	for _, user := range m.Mentions { | 	for _, user := range m.Mentions { | ||||||
| 		content = regexp.MustCompile(fmt.Sprintf("<@!?(%s)>", user.ID)).ReplaceAllString(content, "@"+user.Username) | 		content = strings.NewReplacer( | ||||||
|  | 			"<@"+user.ID+">", "@"+user.Username, | ||||||
|  | 			"<@!"+user.ID+">", "@"+user.Username, | ||||||
|  | 		).Replace(content) | ||||||
| 	} | 	} | ||||||
| 	return content | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var patternChannels = regexp.MustCompile("<#[^>]*>") | ||||||
|  |  | ||||||
|  | // ContentWithMoreMentionsReplaced will replace all @<id> mentions with the | ||||||
|  | // username of the mention, but also role IDs and more. | ||||||
|  | func (m *Message) ContentWithMoreMentionsReplaced(s *Session) (content string, err error) { | ||||||
|  | 	content = m.Content | ||||||
|  |  | ||||||
|  | 	if !s.StateEnabled { | ||||||
|  | 		content = m.ContentWithMentionsReplaced() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	channel, err := s.State.Channel(m.ChannelID) | ||||||
|  | 	if err != nil { | ||||||
|  | 		content = m.ContentWithMentionsReplaced() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, user := range m.Mentions { | ||||||
|  | 		nick := user.Username | ||||||
|  |  | ||||||
|  | 		member, err := s.State.Member(channel.GuildID, user.ID) | ||||||
|  | 		if err == nil && member.Nick != "" { | ||||||
|  | 			nick = member.Nick | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		content = strings.NewReplacer( | ||||||
|  | 			"<@"+user.ID+">", "@"+user.Username, | ||||||
|  | 			"<@!"+user.ID+">", "@"+nick, | ||||||
|  | 		).Replace(content) | ||||||
|  | 	} | ||||||
|  | 	for _, roleID := range m.MentionRoles { | ||||||
|  | 		role, err := s.State.Role(channel.GuildID, roleID) | ||||||
|  | 		if err != nil || !role.Mentionable { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		content = strings.Replace(content, "<&"+role.ID+">", "@"+role.Name, -1) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	content = patternChannels.ReplaceAllStringFunc(content, func(mention string) string { | ||||||
|  | 		channel, err := s.State.Channel(mention[2 : len(mention)-1]) | ||||||
|  | 		if err != nil || channel.Type == ChannelTypeGuildVoice { | ||||||
|  | 			return mention | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return "#" + channel.Name | ||||||
|  | 	}) | ||||||
|  | 	return | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								vendor/github.com/bwmarrin/discordgo/ratelimit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/bwmarrin/discordgo/ratelimit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,17 +3,26 @@ package discordgo | |||||||
| import ( | import ( | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"strconv" | 	"strconv" | ||||||
|  | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // customRateLimit holds information for defining a custom rate limit | ||||||
|  | type customRateLimit struct { | ||||||
|  | 	suffix   string | ||||||
|  | 	requests int | ||||||
|  | 	reset    time.Duration | ||||||
|  | } | ||||||
|  |  | ||||||
| // RateLimiter holds all ratelimit buckets | // RateLimiter holds all ratelimit buckets | ||||||
| type RateLimiter struct { | type RateLimiter struct { | ||||||
| 	sync.Mutex | 	sync.Mutex | ||||||
| 	global           *int64 | 	global           *int64 | ||||||
| 	buckets          map[string]*Bucket | 	buckets          map[string]*Bucket | ||||||
| 	globalRateLimit  time.Duration | 	globalRateLimit  time.Duration | ||||||
|  | 	customRateLimits []*customRateLimit | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewRatelimiter returns a new RateLimiter | // NewRatelimiter returns a new RateLimiter | ||||||
| @@ -22,6 +31,13 @@ func NewRatelimiter() *RateLimiter { | |||||||
| 	return &RateLimiter{ | 	return &RateLimiter{ | ||||||
| 		buckets: make(map[string]*Bucket), | 		buckets: make(map[string]*Bucket), | ||||||
| 		global:  new(int64), | 		global:  new(int64), | ||||||
|  | 		customRateLimits: []*customRateLimit{ | ||||||
|  | 			&customRateLimit{ | ||||||
|  | 				suffix:   "//reactions//", | ||||||
|  | 				requests: 1, | ||||||
|  | 				reset:    200 * time.Millisecond, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -40,6 +56,14 @@ func (r *RateLimiter) getBucket(key string) *Bucket { | |||||||
| 		global:    r.global, | 		global:    r.global, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Check if there is a custom ratelimit set for this bucket ID. | ||||||
|  | 	for _, rl := range r.customRateLimits { | ||||||
|  | 		if strings.HasSuffix(b.Key, rl.suffix) { | ||||||
|  | 			b.customRateLimit = rl | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	r.buckets[key] = b | 	r.buckets[key] = b | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
| @@ -76,13 +100,28 @@ type Bucket struct { | |||||||
| 	limit     int | 	limit     int | ||||||
| 	reset     time.Time | 	reset     time.Time | ||||||
| 	global    *int64 | 	global    *int64 | ||||||
|  |  | ||||||
|  | 	lastReset       time.Time | ||||||
|  | 	customRateLimit *customRateLimit | ||||||
| } | } | ||||||
|  |  | ||||||
| // Release unlocks the bucket and reads the headers to update the buckets ratelimit info | // Release unlocks the bucket and reads the headers to update the buckets ratelimit info | ||||||
| // and locks up the whole thing in case if there's a global ratelimit. | // and locks up the whole thing in case if there's a global ratelimit. | ||||||
| func (b *Bucket) Release(headers http.Header) error { | func (b *Bucket) Release(headers http.Header) error { | ||||||
|  |  | ||||||
| 	defer b.Unlock() | 	defer b.Unlock() | ||||||
|  |  | ||||||
|  | 	// Check if the bucket uses a custom ratelimiter | ||||||
|  | 	if rl := b.customRateLimit; rl != nil { | ||||||
|  | 		if time.Now().Sub(b.lastReset) >= rl.reset { | ||||||
|  | 			b.remaining = rl.requests - 1 | ||||||
|  | 			b.lastReset = time.Now() | ||||||
|  | 		} | ||||||
|  | 		if b.remaining < 1 { | ||||||
|  | 			b.reset = time.Now().Add(rl.reset) | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if headers == nil { | 	if headers == nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										138
									
								
								vendor/github.com/bwmarrin/discordgo/restapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/bwmarrin/discordgo/restapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -23,6 +23,7 @@ import ( | |||||||
| 	"log" | 	"log" | ||||||
| 	"mime/multipart" | 	"mime/multipart" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/textproto" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| @@ -309,8 +310,8 @@ func (s *Session) UserUpdate(email, password, username, avatar, newPassword stri | |||||||
| 	// If left blank, avatar will be set to null/blank | 	// If left blank, avatar will be set to null/blank | ||||||
|  |  | ||||||
| 	data := struct { | 	data := struct { | ||||||
| 		Email       string `json:"email"` | 		Email       string `json:"email,omitempty"` | ||||||
| 		Password    string `json:"password"` | 		Password    string `json:"password,omitempty"` | ||||||
| 		Username    string `json:"username,omitempty"` | 		Username    string `json:"username,omitempty"` | ||||||
| 		Avatar      string `json:"avatar,omitempty"` | 		Avatar      string `json:"avatar,omitempty"` | ||||||
| 		NewPassword string `json:"new_password,omitempty"` | 		NewPassword string `json:"new_password,omitempty"` | ||||||
| @@ -763,7 +764,21 @@ func (s *Session) GuildMember(guildID, userID string) (st *Member, err error) { | |||||||
| // userID    : The ID of a User | // userID    : The ID of a User | ||||||
| func (s *Session) GuildMemberDelete(guildID, userID string) (err error) { | func (s *Session) GuildMemberDelete(guildID, userID string) (err error) { | ||||||
|  |  | ||||||
| 	_, err = s.RequestWithBucketID("DELETE", EndpointGuildMember(guildID, userID), nil, EndpointGuildMember(guildID, "")) | 	return s.GuildMemberDeleteWithReason(guildID, userID, "") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GuildMemberDeleteWithReason removes the given user from the given guild. | ||||||
|  | // guildID   : The ID of a Guild. | ||||||
|  | // userID    : The ID of a User | ||||||
|  | // reason    : The reason for the kick | ||||||
|  | func (s *Session) GuildMemberDeleteWithReason(guildID, userID, reason string) (err error) { | ||||||
|  |  | ||||||
|  | 	uri := EndpointGuildMember(guildID, userID) | ||||||
|  | 	if reason != "" { | ||||||
|  | 		uri += "?reason=" + url.QueryEscape(reason) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	_, err = s.RequestWithBucketID("DELETE", uri, nil, EndpointGuildMember(guildID, "")) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1316,6 +1331,8 @@ func (s *Session) ChannelMessageSend(channelID string, content string) (*Message | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"") | ||||||
|  |  | ||||||
| // ChannelMessageSendComplex sends a message to the given channel. | // ChannelMessageSendComplex sends a message to the given channel. | ||||||
| // channelID : The ID of a Channel. | // channelID : The ID of a Channel. | ||||||
| // data      : The message struct to send. | // data      : The message struct to send. | ||||||
| @@ -1326,48 +1343,62 @@ func (s *Session) ChannelMessageSendComplex(channelID string, data *MessageSend) | |||||||
|  |  | ||||||
| 	endpoint := EndpointChannelMessages(channelID) | 	endpoint := EndpointChannelMessages(channelID) | ||||||
|  |  | ||||||
| 	var response []byte | 	// TODO: Remove this when compatibility is not required. | ||||||
|  | 	files := data.Files | ||||||
| 	if data.File != nil { | 	if data.File != nil { | ||||||
|  | 		if files == nil { | ||||||
|  | 			files = []*File{data.File} | ||||||
|  | 		} else { | ||||||
|  | 			err = fmt.Errorf("cannot specify both File and Files") | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var response []byte | ||||||
|  | 	if len(files) > 0 { | ||||||
| 		body := &bytes.Buffer{} | 		body := &bytes.Buffer{} | ||||||
| 		bodywriter := multipart.NewWriter(body) | 		bodywriter := multipart.NewWriter(body) | ||||||
|  |  | ||||||
| 		// What's a better way of doing this? Reflect? Generator? I'm open to suggestions | 		var payload []byte | ||||||
|  | 		payload, err = json.Marshal(data) | ||||||
| 		if data.Content != "" { |  | ||||||
| 			if err = bodywriter.WriteField("content", data.Content); err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if data.Embed != nil { |  | ||||||
| 			var embed []byte |  | ||||||
| 			embed, err = json.Marshal(data.Embed) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 			err = bodywriter.WriteField("embed", string(embed)) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if data.Tts { |  | ||||||
| 			if err = bodywriter.WriteField("tts", "true"); err != nil { |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		var writer io.Writer |  | ||||||
| 		writer, err = bodywriter.CreateFormFile("file", data.File.Name) |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		_, err = io.Copy(writer, data.File.Reader) | 		var p io.Writer | ||||||
|  |  | ||||||
|  | 		h := make(textproto.MIMEHeader) | ||||||
|  | 		h.Set("Content-Disposition", `form-data; name="payload_json"`) | ||||||
|  | 		h.Set("Content-Type", "application/json") | ||||||
|  |  | ||||||
|  | 		p, err = bodywriter.CreatePart(h) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if _, err = p.Write(payload); err != nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for i, file := range files { | ||||||
|  | 			h := make(textproto.MIMEHeader) | ||||||
|  | 			h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file%d"; filename="%s"`, i, quoteEscaper.Replace(file.Name))) | ||||||
|  | 			contentType := file.ContentType | ||||||
|  | 			if contentType == "" { | ||||||
|  | 				contentType = "application/octet-stream" | ||||||
|  | 			} | ||||||
|  | 			h.Set("Content-Type", contentType) | ||||||
|  |  | ||||||
|  | 			p, err = bodywriter.CreatePart(h) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if _, err = io.Copy(p, file.Reader); err != nil { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		err = bodywriter.Close() | 		err = bodywriter.Close() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return | 			return | ||||||
| @@ -1685,6 +1716,28 @@ func (s *Session) Gateway() (gateway string, err error) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // GatewayBot returns the websocket Gateway address and the recommended number of shards | ||||||
|  | func (s *Session) GatewayBot() (st *GatewayBotResponse, err error) { | ||||||
|  |  | ||||||
|  | 	response, err := s.RequestWithBucketID("GET", EndpointGatewayBot, nil, EndpointGatewayBot) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = unmarshal(response, &st) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Ensure the gateway always has a trailing slash. | ||||||
|  | 	// MacOS will fail to connect if we add query params without a trailing slash on the base domain. | ||||||
|  | 	if !strings.HasSuffix(st.URL, "/") { | ||||||
|  | 		st.URL += "/" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
| // Functions specific to Webhooks | // Functions specific to Webhooks | ||||||
|  |  | ||||||
| // WebhookCreate returns a new Webhook. | // WebhookCreate returns a new Webhook. | ||||||
| @@ -1810,14 +1863,9 @@ func (s *Session) WebhookEditWithToken(webhookID, token, name, avatar string) (s | |||||||
|  |  | ||||||
| // WebhookDelete deletes a webhook for a given ID | // WebhookDelete deletes a webhook for a given ID | ||||||
| // webhookID: The ID of a webhook. | // webhookID: The ID of a webhook. | ||||||
| func (s *Session) WebhookDelete(webhookID string) (st *Webhook, err error) { | func (s *Session) WebhookDelete(webhookID string) (err error) { | ||||||
|  |  | ||||||
| 	body, err := s.RequestWithBucketID("DELETE", EndpointWebhook(webhookID), nil, EndpointWebhooks) | 	_, err = s.RequestWithBucketID("DELETE", EndpointWebhook(webhookID), nil, EndpointWebhooks) | ||||||
| 	if err != nil { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	err = unmarshal(body, &st) |  | ||||||
|  |  | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @@ -1875,6 +1923,16 @@ func (s *Session) MessageReactionRemove(channelID, messageID, emojiID, userID st | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // MessageReactionsRemoveAll deletes all reactions from a message | ||||||
|  | // channelID : The channel ID | ||||||
|  | // messageID : The message ID. | ||||||
|  | func (s *Session) MessageReactionsRemoveAll(channelID, messageID string) error { | ||||||
|  |  | ||||||
|  | 	_, err := s.RequestWithBucketID("DELETE", EndpointMessageReactionsAll(channelID, messageID), nil, EndpointMessageReactionsAll(channelID, messageID)) | ||||||
|  |  | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  |  | ||||||
| // MessageReactions gets all the users reactions for a specific emoji. | // MessageReactions gets all the users reactions for a specific emoji. | ||||||
| // channelID : The channel ID. | // channelID : The channel ID. | ||||||
| // messageID : The message ID. | // messageID : The message ID. | ||||||
|   | |||||||
							
								
								
									
										68
									
								
								vendor/github.com/bwmarrin/discordgo/state.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								vendor/github.com/bwmarrin/discordgo/state.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -42,6 +42,7 @@ type State struct { | |||||||
|  |  | ||||||
| 	guildMap   map[string]*Guild | 	guildMap   map[string]*Guild | ||||||
| 	channelMap map[string]*Channel | 	channelMap map[string]*Channel | ||||||
|  | 	memberMap  map[string]map[string]*Member | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewState creates an empty state. | // NewState creates an empty state. | ||||||
| @@ -59,9 +60,18 @@ func NewState() *State { | |||||||
| 		TrackPresences: true, | 		TrackPresences: true, | ||||||
| 		guildMap:       make(map[string]*Guild), | 		guildMap:       make(map[string]*Guild), | ||||||
| 		channelMap:     make(map[string]*Channel), | 		channelMap:     make(map[string]*Channel), | ||||||
|  | 		memberMap:      make(map[string]map[string]*Member), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s *State) createMemberMap(guild *Guild) { | ||||||
|  | 	members := make(map[string]*Member) | ||||||
|  | 	for _, m := range guild.Members { | ||||||
|  | 		members[m.User.ID] = m | ||||||
|  | 	} | ||||||
|  | 	s.memberMap[guild.ID] = members | ||||||
|  | } | ||||||
|  |  | ||||||
| // GuildAdd adds a guild to the current world state, or | // GuildAdd adds a guild to the current world state, or | ||||||
| // updates it if it already exists. | // updates it if it already exists. | ||||||
| func (s *State) GuildAdd(guild *Guild) error { | func (s *State) GuildAdd(guild *Guild) error { | ||||||
| @@ -77,6 +87,14 @@ func (s *State) GuildAdd(guild *Guild) error { | |||||||
| 		s.channelMap[c.ID] = c | 		s.channelMap[c.ID] = c | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// If this guild contains a new member slice, we must regenerate the member map so the pointers stay valid | ||||||
|  | 	if guild.Members != nil { | ||||||
|  | 		s.createMemberMap(guild) | ||||||
|  | 	} else if _, ok := s.memberMap[guild.ID]; !ok { | ||||||
|  | 		// Even if we have no new member slice, we still initialize the member map for this guild if it doesn't exist | ||||||
|  | 		s.memberMap[guild.ID] = make(map[string]*Member) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if g, ok := s.guildMap[guild.ID]; ok { | 	if g, ok := s.guildMap[guild.ID]; ok { | ||||||
| 		// We are about to replace `g` in the state with `guild`, but first we need to | 		// We are about to replace `g` in the state with `guild`, but first we need to | ||||||
| 		// make sure we preserve any fields that the `guild` doesn't contain from `g`. | 		// make sure we preserve any fields that the `guild` doesn't contain from `g`. | ||||||
| @@ -271,14 +289,19 @@ func (s *State) MemberAdd(member *Member) error { | |||||||
| 	s.Lock() | 	s.Lock() | ||||||
| 	defer s.Unlock() | 	defer s.Unlock() | ||||||
|  |  | ||||||
| 	for i, m := range guild.Members { | 	members, ok := s.memberMap[member.GuildID] | ||||||
| 		if m.User.ID == member.User.ID { | 	if !ok { | ||||||
| 			guild.Members[i] = member | 		return ErrStateNotFound | ||||||
| 			return nil |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	m, ok := members[member.User.ID] | ||||||
|  | 	if !ok { | ||||||
|  | 		members[member.User.ID] = member | ||||||
| 		guild.Members = append(guild.Members, member) | 		guild.Members = append(guild.Members, member) | ||||||
|  | 	} else { | ||||||
|  | 		*m = *member // Update the actual data, which will also update the member pointer in the slice | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -296,6 +319,17 @@ func (s *State) MemberRemove(member *Member) error { | |||||||
| 	s.Lock() | 	s.Lock() | ||||||
| 	defer s.Unlock() | 	defer s.Unlock() | ||||||
|  |  | ||||||
|  | 	members, ok := s.memberMap[member.GuildID] | ||||||
|  | 	if !ok { | ||||||
|  | 		return ErrStateNotFound | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	_, ok = members[member.User.ID] | ||||||
|  | 	if !ok { | ||||||
|  | 		return ErrStateNotFound | ||||||
|  | 	} | ||||||
|  | 	delete(members, member.User.ID) | ||||||
|  |  | ||||||
| 	for i, m := range guild.Members { | 	for i, m := range guild.Members { | ||||||
| 		if m.User.ID == member.User.ID { | 		if m.User.ID == member.User.ID { | ||||||
| 			guild.Members = append(guild.Members[:i], guild.Members[i+1:]...) | 			guild.Members = append(guild.Members[:i], guild.Members[i+1:]...) | ||||||
| @@ -312,18 +346,17 @@ func (s *State) Member(guildID, userID string) (*Member, error) { | |||||||
| 		return nil, ErrNilState | 		return nil, ErrNilState | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	guild, err := s.Guild(guildID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	s.RLock() | 	s.RLock() | ||||||
| 	defer s.RUnlock() | 	defer s.RUnlock() | ||||||
|  |  | ||||||
| 	for _, m := range guild.Members { | 	members, ok := s.memberMap[guildID] | ||||||
| 		if m.User.ID == userID { | 	if !ok { | ||||||
| 			return m, nil | 		return nil, ErrStateNotFound | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	m, ok := members[userID] | ||||||
|  | 	if ok { | ||||||
|  | 		return m, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil, ErrStateNotFound | 	return nil, ErrStateNotFound | ||||||
| @@ -427,7 +460,7 @@ func (s *State) ChannelAdd(channel *Channel) error { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if channel.IsPrivate { | 	if channel.Type == ChannelTypeDM || channel.Type == ChannelTypeGroupDM { | ||||||
| 		s.PrivateChannels = append(s.PrivateChannels, channel) | 		s.PrivateChannels = append(s.PrivateChannels, channel) | ||||||
| 	} else { | 	} else { | ||||||
| 		guild, ok := s.guildMap[channel.GuildID] | 		guild, ok := s.guildMap[channel.GuildID] | ||||||
| @@ -454,7 +487,7 @@ func (s *State) ChannelRemove(channel *Channel) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if channel.IsPrivate { | 	if channel.Type == ChannelTypeDM || channel.Type == ChannelTypeGroupDM { | ||||||
| 		s.Lock() | 		s.Lock() | ||||||
| 		defer s.Unlock() | 		defer s.Unlock() | ||||||
|  |  | ||||||
| @@ -735,6 +768,7 @@ func (s *State) onReady(se *Session, r *Ready) (err error) { | |||||||
|  |  | ||||||
| 	for _, g := range s.Guilds { | 	for _, g := range s.Guilds { | ||||||
| 		s.guildMap[g.ID] = g | 		s.guildMap[g.ID] = g | ||||||
|  | 		s.createMemberMap(g) | ||||||
|  |  | ||||||
| 		for _, c := range g.Channels { | 		for _, c := range g.Channels { | ||||||
| 			s.channelMap[c.ID] = c | 			s.channelMap[c.ID] = c | ||||||
| @@ -748,8 +782,8 @@ func (s *State) onReady(se *Session, r *Ready) (err error) { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // onInterface handles all events related to states. | // OnInterface handles all events related to states. | ||||||
| func (s *State) onInterface(se *Session, i interface{}) (err error) { | func (s *State) OnInterface(se *Session, i interface{}) (err error) { | ||||||
| 	if s == nil { | 	if s == nil { | ||||||
| 		return ErrNilState | 		return ErrNilState | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								vendor/github.com/bwmarrin/discordgo/structs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										87
									
								
								vendor/github.com/bwmarrin/discordgo/structs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -50,6 +50,10 @@ type Session struct { | |||||||
| 	// active guilds and the members of the guilds. | 	// active guilds and the members of the guilds. | ||||||
| 	StateEnabled bool | 	StateEnabled bool | ||||||
|  |  | ||||||
|  | 	// Whether or not to call event handlers synchronously. | ||||||
|  | 	// e.g false = launch event handlers in their own goroutines. | ||||||
|  | 	SyncEvents bool | ||||||
|  |  | ||||||
| 	// Exposed but should not be modified by User. | 	// Exposed but should not be modified by User. | ||||||
|  |  | ||||||
| 	// Whether the Data Websocket is ready | 	// Whether the Data Websocket is ready | ||||||
| @@ -78,6 +82,9 @@ type Session struct { | |||||||
| 	// The http client used for REST requests | 	// The http client used for REST requests | ||||||
| 	Client *http.Client | 	Client *http.Client | ||||||
|  |  | ||||||
|  | 	// Stores the last HeartbeatAck that was recieved (in UTC) | ||||||
|  | 	LastHeartbeatAck time.Time | ||||||
|  |  | ||||||
| 	// Event handlers | 	// Event handlers | ||||||
| 	handlersMu   sync.RWMutex | 	handlersMu   sync.RWMutex | ||||||
| 	handlers     map[string][]*eventHandlerInstance | 	handlers     map[string][]*eventHandlerInstance | ||||||
| @@ -141,18 +148,30 @@ type Invite struct { | |||||||
| 	Temporary bool      `json:"temporary"` | 	Temporary bool      `json:"temporary"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // ChannelType is the type of a Channel | ||||||
|  | type ChannelType int | ||||||
|  |  | ||||||
|  | // Block contains known ChannelType values | ||||||
|  | const ( | ||||||
|  | 	ChannelTypeGuildText ChannelType = iota | ||||||
|  | 	ChannelTypeDM | ||||||
|  | 	ChannelTypeGuildVoice | ||||||
|  | 	ChannelTypeGroupDM | ||||||
|  | 	ChannelTypeGuildCategory | ||||||
|  | ) | ||||||
|  |  | ||||||
| // A Channel holds all data related to an individual Discord channel. | // A Channel holds all data related to an individual Discord channel. | ||||||
| type Channel struct { | type Channel struct { | ||||||
| 	ID                   string                 `json:"id"` | 	ID                   string                 `json:"id"` | ||||||
| 	GuildID              string                 `json:"guild_id"` | 	GuildID              string                 `json:"guild_id"` | ||||||
| 	Name                 string                 `json:"name"` | 	Name                 string                 `json:"name"` | ||||||
| 	Topic                string                 `json:"topic"` | 	Topic                string                 `json:"topic"` | ||||||
| 	Type                 string                 `json:"type"` | 	Type                 ChannelType            `json:"type"` | ||||||
| 	LastMessageID        string                 `json:"last_message_id"` | 	LastMessageID        string                 `json:"last_message_id"` | ||||||
|  | 	NSFW                 bool                   `json:"nsfw"` | ||||||
| 	Position             int                    `json:"position"` | 	Position             int                    `json:"position"` | ||||||
| 	Bitrate              int                    `json:"bitrate"` | 	Bitrate              int                    `json:"bitrate"` | ||||||
| 	IsPrivate            bool                   `json:"is_private"` | 	Recipients           []*User                `json:"recipient"` | ||||||
| 	Recipient            *User                  `json:"recipient"` |  | ||||||
| 	Messages             []*Message             `json:"-"` | 	Messages             []*Message             `json:"-"` | ||||||
| 	PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites"` | 	PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites"` | ||||||
| } | } | ||||||
| @@ -292,13 +311,14 @@ type Presence struct { | |||||||
| 	Game   *Game    `json:"game"` | 	Game   *Game    `json:"game"` | ||||||
| 	Nick   string   `json:"nick"` | 	Nick   string   `json:"nick"` | ||||||
| 	Roles  []string `json:"roles"` | 	Roles  []string `json:"roles"` | ||||||
|  | 	Since  *int     `json:"since"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // A Game struct holds the name of the "playing .." game for a user | // A Game struct holds the name of the "playing .." game for a user | ||||||
| type Game struct { | type Game struct { | ||||||
| 	Name string `json:"name"` | 	Name string `json:"name"` | ||||||
| 	Type int    `json:"type"` | 	Type int    `json:"type"` | ||||||
| 	URL  string `json:"url"` | 	URL  string `json:"url,omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // UnmarshalJSON unmarshals json to Game struct | // UnmarshalJSON unmarshals json to Game struct | ||||||
| @@ -509,6 +529,12 @@ type MessageReaction struct { | |||||||
| 	ChannelID string `json:"channel_id"` | 	ChannelID string `json:"channel_id"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // GatewayBotResponse stores the data for the gateway/bot response | ||||||
|  | type GatewayBotResponse struct { | ||||||
|  | 	URL    string `json:"url"` | ||||||
|  | 	Shards int    `json:"shards"` | ||||||
|  | } | ||||||
|  |  | ||||||
| // Constants for the different bit offsets of text channel permissions | // Constants for the different bit offsets of text channel permissions | ||||||
| const ( | const ( | ||||||
| 	PermissionReadMessages = 1 << (iota + 10) | 	PermissionReadMessages = 1 << (iota + 10) | ||||||
| @@ -579,3 +605,56 @@ const ( | |||||||
| 		PermissionManageServer | | 		PermissionManageServer | | ||||||
| 		PermissionAdministrator | 		PermissionAdministrator | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // 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 | ||||||
|  |  | ||||||
|  | 	ErrCodeBotsCannotUseEndpoint  = 20001 | ||||||
|  | 	ErrCodeOnlyBotsCanUseEndpoint = 20002 | ||||||
|  |  | ||||||
|  | 	ErrCodeMaximumGuildsReached     = 30001 | ||||||
|  | 	ErrCodeMaximumFriendsReached    = 30002 | ||||||
|  | 	ErrCodeMaximumPinsReached       = 30003 | ||||||
|  | 	ErrCodeMaximumGuildRolesReached = 30005 | ||||||
|  | 	ErrCodeTooManyReactions         = 30010 | ||||||
|  |  | ||||||
|  | 	ErrCodeUnauthorized = 40001 | ||||||
|  |  | ||||||
|  | 	ErrCodeMissingAccess                             = 50001 | ||||||
|  | 	ErrCodeInvalidAccountType                        = 50002 | ||||||
|  | 	ErrCodeCannotExecuteActionOnDMChannel            = 50003 | ||||||
|  | 	ErrCodeEmbedCisabled                             = 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 | ||||||
|  |  | ||||||
|  | 	ErrCodeReactionBlocked = 90001 | ||||||
|  | ) | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								vendor/github.com/bwmarrin/discordgo/user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/bwmarrin/discordgo/user.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,9 @@ | |||||||
| package discordgo | package discordgo | ||||||
|  |  | ||||||
| import "fmt" | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
| // A User stores all data for an individual Discord user. | // A User stores all data for an individual Discord user. | ||||||
| type User struct { | type User struct { | ||||||
| @@ -24,3 +27,16 @@ func (u *User) String() string { | |||||||
| func (u *User) Mention() string { | func (u *User) Mention() string { | ||||||
| 	return fmt.Sprintf("<@%s>", u.ID) | 	return fmt.Sprintf("<@%s>", u.ID) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // AvatarURL returns a URL to the user's avatar. | ||||||
|  | //		size:     The size of the user's avatar as a power of two | ||||||
|  | func (u *User) AvatarURL(size string) string { | ||||||
|  | 	var URL string | ||||||
|  | 	if strings.HasPrefix(u.Avatar, "a_") { | ||||||
|  | 		URL = EndpointUserAvatarAnimated(u.ID, u.Avatar) | ||||||
|  | 	} else { | ||||||
|  | 		URL = EndpointUserAvatar(u.ID, u.Avatar) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return URL + "?size=" + size | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								vendor/github.com/bwmarrin/discordgo/voice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/bwmarrin/discordgo/voice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -796,7 +796,7 @@ func (v *VoiceConnection) opusReceiver(udpConn *net.UDPConn, close <-chan struct | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// For now, skip anything except audio. | 		// For now, skip anything except audio. | ||||||
| 		if rlen < 12 || recvbuf[0] != 0x80 { | 		if rlen < 12 || (recvbuf[0] != 0x80 && recvbuf[0] != 0x90) { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -810,8 +810,17 @@ func (v *VoiceConnection) opusReceiver(udpConn *net.UDPConn, close <-chan struct | |||||||
| 		copy(nonce[:], recvbuf[0:12]) | 		copy(nonce[:], recvbuf[0:12]) | ||||||
| 		p.Opus, _ = secretbox.Open(nil, recvbuf[12:rlen], &nonce, &v.op4.SecretKey) | 		p.Opus, _ = secretbox.Open(nil, recvbuf[12:rlen], &nonce, &v.op4.SecretKey) | ||||||
|  |  | ||||||
|  | 		if len(p.Opus) > 8 && recvbuf[0] == 0x90 { | ||||||
|  | 			// Extension bit is set, first 8 bytes is the extended header | ||||||
|  | 			p.Opus = p.Opus[8:] | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if c != nil { | 		if c != nil { | ||||||
| 			c <- &p | 			select { | ||||||
|  | 			case c <- &p: | ||||||
|  | 			case <-close: | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								vendor/github.com/bwmarrin/discordgo/wsapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/bwmarrin/discordgo/wsapi.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -15,7 +15,6 @@ import ( | |||||||
| 	"compress/zlib" | 	"compress/zlib" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"runtime" | 	"runtime" | ||||||
| @@ -87,7 +86,7 @@ func (s *Session) Open() (err error) { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Add the version and encoding to the URL | 		// Add the version and encoding to the URL | ||||||
| 		s.gateway = fmt.Sprintf("%s?v=5&encoding=json", s.gateway) | 		s.gateway = s.gateway + "?v=" + APIVersion + "&encoding=json" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	header := http.Header{} | 	header := http.Header{} | ||||||
| @@ -131,6 +130,7 @@ func (s *Session) Open() (err error) { | |||||||
| 	// lock. | 	// lock. | ||||||
| 	s.listening = make(chan interface{}) | 	s.listening = make(chan interface{}) | ||||||
| 	go s.listen(s.wsConn, s.listening) | 	go s.listen(s.wsConn, s.listening) | ||||||
|  | 	s.LastHeartbeatAck = time.Now().UTC() | ||||||
|  |  | ||||||
| 	s.Unlock() | 	s.Unlock() | ||||||
|  |  | ||||||
| @@ -199,10 +199,13 @@ type helloOp struct { | |||||||
| 	Trace             []string      `json:"_trace"` | 	Trace             []string      `json:"_trace"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // FailedHeartbeatAcks is the Number of heartbeat intervals to wait until forcing a connection restart. | ||||||
|  | const FailedHeartbeatAcks time.Duration = 5 * time.Millisecond | ||||||
|  |  | ||||||
| // heartbeat sends regular heartbeats to Discord so it knows the client | // heartbeat sends regular heartbeats to Discord so it knows the client | ||||||
| // is still connected.  If you do not send these heartbeats Discord will | // is still connected.  If you do not send these heartbeats Discord will | ||||||
| // disconnect the websocket connection after a few seconds. | // disconnect the websocket connection after a few seconds. | ||||||
| func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{}, i time.Duration) { | func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{}, heartbeatIntervalMsec time.Duration) { | ||||||
|  |  | ||||||
| 	s.log(LogInformational, "called") | 	s.log(LogInformational, "called") | ||||||
|  |  | ||||||
| @@ -211,20 +214,26 @@ func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{} | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var err error | 	var err error | ||||||
| 	ticker := time.NewTicker(i * time.Millisecond) | 	ticker := time.NewTicker(heartbeatIntervalMsec * time.Millisecond) | ||||||
| 	defer ticker.Stop() | 	defer ticker.Stop() | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
|  | 		s.RLock() | ||||||
|  | 		last := s.LastHeartbeatAck | ||||||
|  | 		s.RUnlock() | ||||||
| 		sequence := atomic.LoadInt64(s.sequence) | 		sequence := atomic.LoadInt64(s.sequence) | ||||||
| 		s.log(LogInformational, "sending gateway websocket heartbeat seq %d", sequence) | 		s.log(LogInformational, "sending gateway websocket heartbeat seq %d", sequence) | ||||||
| 		s.wsMutex.Lock() | 		s.wsMutex.Lock() | ||||||
| 		err = wsConn.WriteJSON(heartbeatOp{1, sequence}) | 		err = wsConn.WriteJSON(heartbeatOp{1, sequence}) | ||||||
| 		s.wsMutex.Unlock() | 		s.wsMutex.Unlock() | ||||||
|  | 		if err != nil || time.Now().UTC().Sub(last) > (heartbeatIntervalMsec*FailedHeartbeatAcks) { | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				s.log(LogError, "error sending heartbeat to gateway %s, %s", s.gateway, err) | 				s.log(LogError, "error sending heartbeat to gateway %s, %s", s.gateway, err) | ||||||
| 			s.Lock() | 			} else { | ||||||
| 			s.DataReady = false | 				s.log(LogError, "haven't gotten a heartbeat ACK in %v, triggering a reconnection", time.Now().UTC().Sub(last)) | ||||||
| 			s.Unlock() | 			} | ||||||
|  | 			s.Close() | ||||||
|  | 			s.reconnect() | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		s.Lock() | 		s.Lock() | ||||||
| @@ -241,8 +250,10 @@ func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{} | |||||||
| } | } | ||||||
|  |  | ||||||
| type updateStatusData struct { | type updateStatusData struct { | ||||||
| 	IdleSince *int  `json:"idle_since"` | 	IdleSince *int   `json:"since"` | ||||||
| 	Game      *Game  `json:"game"` | 	Game      *Game  `json:"game"` | ||||||
|  | 	AFK       bool   `json:"afk"` | ||||||
|  | 	Status    string `json:"status"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type updateStatusOp struct { | type updateStatusOp struct { | ||||||
| @@ -265,7 +276,10 @@ func (s *Session) UpdateStreamingStatus(idle int, game string, url string) (err | |||||||
| 		return ErrWSNotFound | 		return ErrWSNotFound | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var usd updateStatusData | 	usd := updateStatusData{ | ||||||
|  | 		Status: "online", | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if idle > 0 { | 	if idle > 0 { | ||||||
| 		usd.IdleSince = &idle | 		usd.IdleSince = &idle | ||||||
| 	} | 	} | ||||||
| @@ -398,7 +412,10 @@ func (s *Session) onEvent(messageType int, message []byte) { | |||||||
| 	// Reconnect | 	// Reconnect | ||||||
| 	// Must immediately disconnect from gateway and reconnect to new gateway. | 	// Must immediately disconnect from gateway and reconnect to new gateway. | ||||||
| 	if e.Operation == 7 { | 	if e.Operation == 7 { | ||||||
| 		// TODO | 		s.log(LogInformational, "Closing and reconnecting in response to Op7") | ||||||
|  | 		s.Close() | ||||||
|  | 		s.reconnect() | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Invalid Session | 	// Invalid Session | ||||||
| @@ -426,6 +443,14 @@ func (s *Session) onEvent(messageType int, message []byte) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if e.Operation == 11 { | ||||||
|  | 		s.Lock() | ||||||
|  | 		s.LastHeartbeatAck = time.Now().UTC() | ||||||
|  | 		s.Unlock() | ||||||
|  | 		s.log(LogInformational, "got heartbeat ACK") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Do not try to Dispatch a non-Dispatch Message | 	// Do not try to Dispatch a non-Dispatch Message | ||||||
| 	if e.Operation != 0 { | 	if e.Operation != 0 { | ||||||
| 		// But we probably should be doing something with them. | 		// But we probably should be doing something with them. | ||||||
| @@ -688,6 +713,13 @@ func (s *Session) reconnect() { | |||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			// Certain race conditions can call reconnect() twice. If this happens, we | ||||||
|  | 			// just break out of the reconnect loop | ||||||
|  | 			if err == ErrWSAlreadyOpen { | ||||||
|  | 				s.log(LogInformational, "Websocket already exists, no need to reconnect") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			s.log(LogError, "error reconnecting to gateway, %s", err) | 			s.log(LogError, "error reconnecting to gateway, %s", err) | ||||||
|  |  | ||||||
| 			<-time.After(wait * time.Second) | 			<-time.After(wait * time.Second) | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								vendor/manifest
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/manifest
									
									
									
									
										vendored
									
									
								
							| @@ -61,7 +61,7 @@ | |||||||
| 			"importpath": "github.com/bwmarrin/discordgo", | 			"importpath": "github.com/bwmarrin/discordgo", | ||||||
| 			"repository": "https://github.com/bwmarrin/discordgo", | 			"repository": "https://github.com/bwmarrin/discordgo", | ||||||
| 			"vcs": "git", | 			"vcs": "git", | ||||||
| 			"revision": "d420e28024ad527390b43aa7f64e029083e11989", | 			"revision": "2fda7ce223a66a5b70b66987c22c3c94d022ee66", | ||||||
| 			"branch": "master", | 			"branch": "master", | ||||||
| 			"notests": true | 			"notests": true | ||||||
| 		}, | 		}, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Wim
					Wim