mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-15 08:29:25 +01:00
Update vendor bwmarrin/discordgo
This commit is contained in:
parent
2522158127
commit
fd0fe3390b
4
vendor/github.com/bwmarrin/discordgo/discord.go
generated
vendored
4
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.17.0"
|
const VERSION = "0.18.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")
|
||||||
@ -50,7 +50,7 @@ func New(args ...interface{}) (s *Session, err error) {
|
|||||||
// Create an empty Session interface.
|
// Create an empty Session interface.
|
||||||
s = &Session{
|
s = &Session{
|
||||||
State: NewState(),
|
State: NewState(),
|
||||||
ratelimiter: NewRatelimiter(),
|
Ratelimiter: NewRatelimiter(),
|
||||||
StateEnabled: true,
|
StateEnabled: true,
|
||||||
Compress: true,
|
Compress: true,
|
||||||
ShouldReconnectOnError: true,
|
ShouldReconnectOnError: true,
|
||||||
|
5
vendor/github.com/bwmarrin/discordgo/endpoints.go
generated
vendored
5
vendor/github.com/bwmarrin/discordgo/endpoints.go
generated
vendored
@ -71,7 +71,6 @@ var (
|
|||||||
EndpointUserNotes = func(uID string) string { return EndpointUsers + "@me/notes/" + uID }
|
EndpointUserNotes = func(uID string) string { return EndpointUsers + "@me/notes/" + uID }
|
||||||
|
|
||||||
EndpointGuild = func(gID string) string { return EndpointGuilds + gID }
|
EndpointGuild = func(gID string) string { return EndpointGuilds + gID }
|
||||||
EndpointGuildInivtes = func(gID string) string { return EndpointGuilds + gID + "/invites" }
|
|
||||||
EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" }
|
EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" }
|
||||||
EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" }
|
EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" }
|
||||||
EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID }
|
EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID }
|
||||||
@ -98,7 +97,7 @@ var (
|
|||||||
EndpointChannelMessages = func(cID string) string { return EndpointChannels + cID + "/messages" }
|
EndpointChannelMessages = func(cID string) string { return EndpointChannels + cID + "/messages" }
|
||||||
EndpointChannelMessage = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID }
|
EndpointChannelMessage = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID }
|
||||||
EndpointChannelMessageAck = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID + "/ack" }
|
EndpointChannelMessageAck = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID + "/ack" }
|
||||||
EndpointChannelMessagesBulkDelete = func(cID string) string { return EndpointChannel(cID) + "/messages/bulk_delete" }
|
EndpointChannelMessagesBulkDelete = func(cID string) string { return EndpointChannel(cID) + "/messages/bulk-delete" }
|
||||||
EndpointChannelMessagesPins = func(cID string) string { return EndpointChannel(cID) + "/pins" }
|
EndpointChannelMessagesPins = func(cID string) string { return EndpointChannel(cID) + "/pins" }
|
||||||
EndpointChannelMessagePin = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID }
|
EndpointChannelMessagePin = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID }
|
||||||
|
|
||||||
@ -122,6 +121,8 @@ var (
|
|||||||
EndpointRelationship = func(uID string) string { return EndpointRelationships() + "/" + uID }
|
EndpointRelationship = func(uID string) string { return EndpointRelationships() + "/" + uID }
|
||||||
EndpointRelationshipsMutual = func(uID string) string { return EndpointUsers + uID + "/relationships" }
|
EndpointRelationshipsMutual = func(uID string) string { return EndpointUsers + uID + "/relationships" }
|
||||||
|
|
||||||
|
EndpointGuildCreate = EndpointAPI + "guilds"
|
||||||
|
|
||||||
EndpointInvite = func(iID string) string { return EndpointAPI + "invite/" + iID }
|
EndpointInvite = func(iID string) string { return EndpointAPI + "invite/" + iID }
|
||||||
|
|
||||||
EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" }
|
EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" }
|
||||||
|
2
vendor/github.com/bwmarrin/discordgo/event.go
generated
vendored
2
vendor/github.com/bwmarrin/discordgo/event.go
generated
vendored
@ -6,7 +6,7 @@ type EventHandler interface {
|
|||||||
Type() string
|
Type() string
|
||||||
|
|
||||||
// Handle is called whenever an event of Type() happens.
|
// Handle is called whenever an event of Type() happens.
|
||||||
// It is the recievers responsibility to type assert that the interface
|
// It is the receivers responsibility to type assert that the interface
|
||||||
// is the expected struct.
|
// is the expected struct.
|
||||||
Handle(*Session, interface{})
|
Handle(*Session, interface{})
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/bwmarrin/discordgo/examples/appmaker/main.go
generated
vendored
2
vendor/github.com/bwmarrin/discordgo/examples/appmaker/main.go
generated
vendored
@ -79,7 +79,7 @@ func main() {
|
|||||||
ap.Name = Name
|
ap.Name = Name
|
||||||
ap, err = dg.ApplicationCreate(ap)
|
ap, err = dg.ApplicationCreate(ap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("error creating new applicaiton,", err)
|
fmt.Println("error creating new application,", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
vendor/github.com/bwmarrin/discordgo/logging.go
generated
vendored
12
vendor/github.com/bwmarrin/discordgo/logging.go
generated
vendored
@ -23,7 +23,7 @@ const (
|
|||||||
LogError int = iota
|
LogError int = iota
|
||||||
|
|
||||||
// LogWarning level is used for very abnormal events and errors that are
|
// LogWarning level is used for very abnormal events and errors that are
|
||||||
// also returend to a calling function.
|
// also returned to a calling function.
|
||||||
LogWarning
|
LogWarning
|
||||||
|
|
||||||
// LogInformational level is used for normal non-error activity
|
// LogInformational level is used for normal non-error activity
|
||||||
@ -34,14 +34,21 @@ const (
|
|||||||
LogDebug
|
LogDebug
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Logger can be used to replace the standard logging for discordgo
|
||||||
|
var Logger func(msgL, caller int, format string, a ...interface{})
|
||||||
|
|
||||||
// msglog provides package wide logging consistancy for discordgo
|
// msglog provides package wide logging consistancy for discordgo
|
||||||
// the format, a... portion this command follows that of fmt.Printf
|
// the format, a... portion this command follows that of fmt.Printf
|
||||||
// msgL : LogLevel of the message
|
// msgL : LogLevel of the message
|
||||||
// caller : 1 + the number of callers away from the message source
|
// caller : 1 + the number of callers away from the message source
|
||||||
// format : Printf style message format
|
// format : Printf style message format
|
||||||
// a ... : comma seperated list of values to pass
|
// a ... : comma separated list of values to pass
|
||||||
func msglog(msgL, caller int, format string, a ...interface{}) {
|
func msglog(msgL, caller int, format string, a ...interface{}) {
|
||||||
|
|
||||||
|
if Logger != nil {
|
||||||
|
Logger(msgL, caller, format, a...)
|
||||||
|
} else {
|
||||||
|
|
||||||
pc, file, line, _ := runtime.Caller(caller)
|
pc, file, line, _ := runtime.Caller(caller)
|
||||||
|
|
||||||
files := strings.Split(file, "/")
|
files := strings.Split(file, "/")
|
||||||
@ -55,6 +62,7 @@ func msglog(msgL, caller int, format string, a ...interface{}) {
|
|||||||
|
|
||||||
log.Printf("[DG%d] %s:%d:%s() %s\n", msgL, file, line, name, msg)
|
log.Printf("[DG%d] %s:%d:%s() %s\n", msgL, file, line, name, msg)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// helper function that wraps msglog for the Session struct
|
// helper function that wraps msglog for the Session struct
|
||||||
// This adds a check to insure the message is only logged
|
// This adds a check to insure the message is only logged
|
||||||
|
49
vendor/github.com/bwmarrin/discordgo/ratelimit.go
generated
vendored
49
vendor/github.com/bwmarrin/discordgo/ratelimit.go
generated
vendored
@ -41,8 +41,8 @@ func NewRatelimiter() *RateLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getBucket retrieves or creates a bucket
|
// GetBucket retrieves or creates a bucket
|
||||||
func (r *RateLimiter) getBucket(key string) *Bucket {
|
func (r *RateLimiter) GetBucket(key string) *Bucket {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ func (r *RateLimiter) getBucket(key string) *Bucket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b := &Bucket{
|
b := &Bucket{
|
||||||
remaining: 1,
|
Remaining: 1,
|
||||||
Key: key,
|
Key: key,
|
||||||
global: r.global,
|
global: r.global,
|
||||||
}
|
}
|
||||||
@ -68,27 +68,37 @@ func (r *RateLimiter) getBucket(key string) *Bucket {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// LockBucket Locks until a request can be made
|
// GetWaitTime returns the duration you should wait for a Bucket
|
||||||
func (r *RateLimiter) LockBucket(bucketID string) *Bucket {
|
func (r *RateLimiter) GetWaitTime(b *Bucket, minRemaining int) time.Duration {
|
||||||
|
|
||||||
b := r.getBucket(bucketID)
|
|
||||||
|
|
||||||
b.Lock()
|
|
||||||
|
|
||||||
// If we ran out of calls and the reset time is still ahead of us
|
// If we ran out of calls and the reset time is still ahead of us
|
||||||
// then we need to take it easy and relax a little
|
// then we need to take it easy and relax a little
|
||||||
if b.remaining < 1 && b.reset.After(time.Now()) {
|
if b.Remaining < minRemaining && b.reset.After(time.Now()) {
|
||||||
time.Sleep(b.reset.Sub(time.Now()))
|
return b.reset.Sub(time.Now())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for global ratelimits
|
// Check for global ratelimits
|
||||||
sleepTo := time.Unix(0, atomic.LoadInt64(r.global))
|
sleepTo := time.Unix(0, atomic.LoadInt64(r.global))
|
||||||
if now := time.Now(); now.Before(sleepTo) {
|
if now := time.Now(); now.Before(sleepTo) {
|
||||||
time.Sleep(sleepTo.Sub(now))
|
return sleepTo.Sub(now)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.remaining--
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// LockBucket Locks until a request can be made
|
||||||
|
func (r *RateLimiter) LockBucket(bucketID string) *Bucket {
|
||||||
|
return r.LockBucketObject(r.GetBucket(bucketID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LockBucketObject Locks an already resolved bucket until a request can be made
|
||||||
|
func (r *RateLimiter) LockBucketObject(b *Bucket) *Bucket {
|
||||||
|
b.Lock()
|
||||||
|
|
||||||
|
if wait := r.GetWaitTime(b, 1); wait > 0 {
|
||||||
|
time.Sleep(wait)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Remaining--
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,13 +106,14 @@ func (r *RateLimiter) LockBucket(bucketID string) *Bucket {
|
|||||||
type Bucket struct {
|
type Bucket struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
Key string
|
Key string
|
||||||
remaining int
|
Remaining int
|
||||||
limit int
|
limit int
|
||||||
reset time.Time
|
reset time.Time
|
||||||
global *int64
|
global *int64
|
||||||
|
|
||||||
lastReset time.Time
|
lastReset time.Time
|
||||||
customRateLimit *customRateLimit
|
customRateLimit *customRateLimit
|
||||||
|
Userdata interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@ -113,10 +124,10 @@ func (b *Bucket) Release(headers http.Header) error {
|
|||||||
// Check if the bucket uses a custom ratelimiter
|
// Check if the bucket uses a custom ratelimiter
|
||||||
if rl := b.customRateLimit; rl != nil {
|
if rl := b.customRateLimit; rl != nil {
|
||||||
if time.Now().Sub(b.lastReset) >= rl.reset {
|
if time.Now().Sub(b.lastReset) >= rl.reset {
|
||||||
b.remaining = rl.requests - 1
|
b.Remaining = rl.requests - 1
|
||||||
b.lastReset = time.Now()
|
b.lastReset = time.Now()
|
||||||
}
|
}
|
||||||
if b.remaining < 1 {
|
if b.Remaining < 1 {
|
||||||
b.reset = time.Now().Add(rl.reset)
|
b.reset = time.Now().Add(rl.reset)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -176,7 +187,7 @@ func (b *Bucket) Release(headers http.Header) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.remaining = int(parsedRemaining)
|
b.Remaining = int(parsedRemaining)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
48
vendor/github.com/bwmarrin/discordgo/restapi.go
generated
vendored
48
vendor/github.com/bwmarrin/discordgo/restapi.go
generated
vendored
@ -65,9 +65,11 @@ func (s *Session) request(method, urlStr, contentType string, b []byte, bucketID
|
|||||||
if bucketID == "" {
|
if bucketID == "" {
|
||||||
bucketID = strings.SplitN(urlStr, "?", 2)[0]
|
bucketID = strings.SplitN(urlStr, "?", 2)[0]
|
||||||
}
|
}
|
||||||
|
return s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucket(bucketID), sequence)
|
||||||
|
}
|
||||||
|
|
||||||
bucket := s.ratelimiter.LockBucket(bucketID)
|
// RequestWithLockedBucket makes a request using a bucket that's already been locked
|
||||||
|
func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b []byte, bucket *Bucket, sequence int) (response []byte, err error) {
|
||||||
if s.Debug {
|
if s.Debug {
|
||||||
log.Printf("API REQUEST %8s :: %s\n", method, urlStr)
|
log.Printf("API REQUEST %8s :: %s\n", method, urlStr)
|
||||||
log.Printf("API REQUEST PAYLOAD :: [%s]\n", string(b))
|
log.Printf("API REQUEST PAYLOAD :: [%s]\n", string(b))
|
||||||
@ -139,7 +141,7 @@ func (s *Session) request(method, urlStr, contentType string, b []byte, bucketID
|
|||||||
if sequence < s.MaxRestRetries {
|
if sequence < s.MaxRestRetries {
|
||||||
|
|
||||||
s.log(LogInformational, "%s Failed (%s), Retrying...", urlStr, resp.Status)
|
s.log(LogInformational, "%s Failed (%s), Retrying...", urlStr, resp.Status)
|
||||||
response, err = s.request(method, urlStr, contentType, b, bucketID, sequence+1)
|
response, err = s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucketObject(bucket), sequence+1)
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("Exceeded Max retries HTTP %s, %s", resp.Status, response)
|
err = fmt.Errorf("Exceeded Max retries HTTP %s, %s", resp.Status, response)
|
||||||
}
|
}
|
||||||
@ -158,7 +160,7 @@ func (s *Session) request(method, urlStr, contentType string, b []byte, bucketID
|
|||||||
// we can make the above smarter
|
// we can make the above smarter
|
||||||
// this method can cause longer delays than required
|
// this method can cause longer delays than required
|
||||||
|
|
||||||
response, err = s.request(method, urlStr, contentType, b, bucketID, sequence)
|
response, err = s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucketObject(bucket), sequence)
|
||||||
|
|
||||||
default: // Error condition
|
default: // Error condition
|
||||||
err = newRestError(req, resp, response)
|
err = newRestError(req, resp, response)
|
||||||
@ -585,7 +587,7 @@ func (s *Session) GuildCreate(name string) (st *Guild, err error) {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}{name}
|
}{name}
|
||||||
|
|
||||||
body, err := s.RequestWithBucketID("POST", EndpointGuilds, data, EndpointGuilds)
|
body, err := s.RequestWithBucketID("POST", EndpointGuildCreate, data, EndpointGuildCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -907,7 +909,7 @@ func (s *Session) GuildChannelsReorder(guildID string, channels []*Channel) (err
|
|||||||
// GuildInvites returns an array of Invite structures for the given guild
|
// GuildInvites returns an array of Invite structures for the given guild
|
||||||
// guildID : The ID of a Guild.
|
// guildID : The ID of a Guild.
|
||||||
func (s *Session) GuildInvites(guildID string) (st []*Invite, err error) {
|
func (s *Session) GuildInvites(guildID string) (st []*Invite, err error) {
|
||||||
body, err := s.RequestWithBucketID("GET", EndpointGuildInvites(guildID), nil, EndpointGuildInivtes(guildID))
|
body, err := s.RequestWithBucketID("GET", EndpointGuildInvites(guildID), nil, EndpointGuildInvites(guildID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -957,6 +959,7 @@ func (s *Session) GuildRoleEdit(guildID, roleID, name string, color int, hoist b
|
|||||||
// Prevent sending a color int that is too big.
|
// Prevent sending a color int that is too big.
|
||||||
if color > 0xFFFFFF {
|
if color > 0xFFFFFF {
|
||||||
err = fmt.Errorf("color value cannot be larger than 0xFFFFFF")
|
err = fmt.Errorf("color value cannot be larger than 0xFFFFFF")
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
@ -1020,6 +1023,9 @@ func (s *Session) GuildPruneCount(guildID string, days uint32) (count uint32, er
|
|||||||
|
|
||||||
uri := EndpointGuildPrune(guildID) + fmt.Sprintf("?days=%d", days)
|
uri := EndpointGuildPrune(guildID) + fmt.Sprintf("?days=%d", days)
|
||||||
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildPrune(guildID))
|
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildPrune(guildID))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = unmarshal(body, &p)
|
err = unmarshal(body, &p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1204,7 +1210,7 @@ func (s *Session) GuildEmbedEdit(guildID string, enabled bool, channelID string)
|
|||||||
// Functions specific to Discord Channels
|
// Functions specific to Discord Channels
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Channel returns a Channel strucutre of a specific Channel.
|
// Channel returns a Channel structure of a specific Channel.
|
||||||
// channelID : The ID of the Channel you want returned.
|
// channelID : The ID of the Channel you want returned.
|
||||||
func (s *Session) Channel(channelID string) (st *Channel, err error) {
|
func (s *Session) Channel(channelID string) (st *Channel, err error) {
|
||||||
body, err := s.RequestWithBucketID("GET", EndpointChannel(channelID), nil, EndpointChannel(channelID))
|
body, err := s.RequestWithBucketID("GET", EndpointChannel(channelID), nil, EndpointChannel(channelID))
|
||||||
@ -1219,12 +1225,16 @@ func (s *Session) Channel(channelID string) (st *Channel, err error) {
|
|||||||
// ChannelEdit edits the given channel
|
// ChannelEdit edits the given channel
|
||||||
// channelID : The ID of a Channel
|
// channelID : The ID of a Channel
|
||||||
// name : The new name to assign the channel.
|
// name : The new name to assign the channel.
|
||||||
func (s *Session) ChannelEdit(channelID, name string) (st *Channel, err error) {
|
func (s *Session) ChannelEdit(channelID, name string) (*Channel, error) {
|
||||||
|
return s.ChannelEditComplex(channelID, &ChannelEdit{
|
||||||
data := struct {
|
Name: name,
|
||||||
Name string `json:"name"`
|
})
|
||||||
}{name}
|
}
|
||||||
|
|
||||||
|
// ChannelEditComplex edits an existing channel, replacing the parameters entirely with ChannelEdit struct
|
||||||
|
// channelID : The ID of a Channel
|
||||||
|
// data : The channel struct to send
|
||||||
|
func (s *Session) ChannelEditComplex(channelID string, data *ChannelEdit) (st *Channel, err error) {
|
||||||
body, err := s.RequestWithBucketID("PATCH", EndpointChannel(channelID), data, EndpointChannel(channelID))
|
body, err := s.RequestWithBucketID("PATCH", EndpointChannel(channelID), data, EndpointChannel(channelID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -1476,7 +1486,7 @@ func (s *Session) ChannelMessageDelete(channelID, messageID string) (err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ChannelMessagesBulkDelete bulk deletes the messages from the channel for the provided messageIDs.
|
// ChannelMessagesBulkDelete bulk deletes the messages from the channel for the provided messageIDs.
|
||||||
// If only one messageID is in the slice call channelMessageDelete funciton.
|
// If only one messageID is in the slice call channelMessageDelete function.
|
||||||
// If the slice is empty do nothing.
|
// If the slice is empty do nothing.
|
||||||
// channelID : The ID of the channel for the messages to delete.
|
// channelID : The ID of the channel for the messages to delete.
|
||||||
// messages : The IDs of the messages to be deleted. A slice of string IDs. A maximum of 100 messages.
|
// messages : The IDs of the messages to be deleted. A slice of string IDs. A maximum of 100 messages.
|
||||||
@ -1569,16 +1579,14 @@ func (s *Session) ChannelInvites(channelID string) (st []*Invite, err error) {
|
|||||||
|
|
||||||
// ChannelInviteCreate creates a new invite for the given channel.
|
// ChannelInviteCreate creates a new invite for the given channel.
|
||||||
// channelID : The ID of a Channel
|
// channelID : The ID of a Channel
|
||||||
// i : An Invite struct with the values MaxAge, MaxUses, Temporary,
|
// i : An Invite struct with the values MaxAge, MaxUses and Temporary defined.
|
||||||
// and XkcdPass defined.
|
|
||||||
func (s *Session) ChannelInviteCreate(channelID string, i Invite) (st *Invite, err error) {
|
func (s *Session) ChannelInviteCreate(channelID string, i Invite) (st *Invite, err error) {
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
MaxAge int `json:"max_age"`
|
MaxAge int `json:"max_age"`
|
||||||
MaxUses int `json:"max_uses"`
|
MaxUses int `json:"max_uses"`
|
||||||
Temporary bool `json:"temporary"`
|
Temporary bool `json:"temporary"`
|
||||||
XKCDPass string `json:"xkcdpass"`
|
}{i.MaxAge, i.MaxUses, i.Temporary}
|
||||||
}{i.MaxAge, i.MaxUses, i.Temporary, i.XkcdPass}
|
|
||||||
|
|
||||||
body, err := s.RequestWithBucketID("POST", EndpointChannelInvites(channelID), data, EndpointChannelInvites(channelID))
|
body, err := s.RequestWithBucketID("POST", EndpointChannelInvites(channelID), data, EndpointChannelInvites(channelID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1618,7 +1626,7 @@ func (s *Session) ChannelPermissionDelete(channelID, targetID string) (err error
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Invite returns an Invite structure of the given invite
|
// Invite returns an Invite structure of the given invite
|
||||||
// inviteID : The invite code (or maybe xkcdpass?)
|
// inviteID : The invite code
|
||||||
func (s *Session) Invite(inviteID string) (st *Invite, err error) {
|
func (s *Session) Invite(inviteID string) (st *Invite, err error) {
|
||||||
|
|
||||||
body, err := s.RequestWithBucketID("GET", EndpointInvite(inviteID), nil, EndpointInvite(""))
|
body, err := s.RequestWithBucketID("GET", EndpointInvite(inviteID), nil, EndpointInvite(""))
|
||||||
@ -1631,7 +1639,7 @@ func (s *Session) Invite(inviteID string) (st *Invite, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InviteDelete deletes an existing invite
|
// InviteDelete deletes an existing invite
|
||||||
// inviteID : the code (or maybe xkcdpass?) of an invite
|
// inviteID : the code of an invite
|
||||||
func (s *Session) InviteDelete(inviteID string) (st *Invite, err error) {
|
func (s *Session) InviteDelete(inviteID string) (st *Invite, err error) {
|
||||||
|
|
||||||
body, err := s.RequestWithBucketID("DELETE", EndpointInvite(inviteID), nil, EndpointInvite(""))
|
body, err := s.RequestWithBucketID("DELETE", EndpointInvite(inviteID), nil, EndpointInvite(""))
|
||||||
@ -1644,7 +1652,7 @@ func (s *Session) InviteDelete(inviteID string) (st *Invite, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InviteAccept accepts an Invite to a Guild or Channel
|
// InviteAccept accepts an Invite to a Guild or Channel
|
||||||
// inviteID : The invite code (or maybe xkcdpass?)
|
// inviteID : The invite code
|
||||||
func (s *Session) InviteAccept(inviteID string) (st *Invite, err error) {
|
func (s *Session) InviteAccept(inviteID string) (st *Invite, err error) {
|
||||||
|
|
||||||
body, err := s.RequestWithBucketID("POST", EndpointInvite(inviteID), nil, EndpointInvite(""))
|
body, err := s.RequestWithBucketID("POST", EndpointInvite(inviteID), nil, EndpointInvite(""))
|
||||||
|
9
vendor/github.com/bwmarrin/discordgo/state.go
generated
vendored
9
vendor/github.com/bwmarrin/discordgo/state.go
generated
vendored
@ -531,7 +531,7 @@ func (s *State) PrivateChannel(channelID string) (*Channel, error) {
|
|||||||
return s.Channel(channelID)
|
return s.Channel(channelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel gets a channel by ID, it will look in all guilds an private channels.
|
// Channel gets a channel by ID, it will look in all guilds and private channels.
|
||||||
func (s *State) Channel(channelID string) (*Channel, error) {
|
func (s *State) Channel(channelID string) (*Channel, error) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil, ErrNilState
|
return nil, ErrNilState
|
||||||
@ -816,6 +816,13 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
|
|||||||
if s.TrackMembers {
|
if s.TrackMembers {
|
||||||
err = s.MemberRemove(t.Member)
|
err = s.MemberRemove(t.Member)
|
||||||
}
|
}
|
||||||
|
case *GuildMembersChunk:
|
||||||
|
if s.TrackMembers {
|
||||||
|
for i := range t.Members {
|
||||||
|
t.Members[i].GuildID = t.GuildID
|
||||||
|
err = s.MemberAdd(t.Members[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
case *GuildRoleCreate:
|
case *GuildRoleCreate:
|
||||||
if s.TrackRoles {
|
if s.TrackRoles {
|
||||||
err = s.RoleAdd(t.GuildID, t.Role)
|
err = s.RoleAdd(t.GuildID, t.Role)
|
||||||
|
90
vendor/github.com/bwmarrin/discordgo/structs.go
generated
vendored
90
vendor/github.com/bwmarrin/discordgo/structs.go
generated
vendored
@ -14,7 +14,6 @@ package discordgo
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -85,6 +84,9 @@ type Session struct {
|
|||||||
// Stores the last HeartbeatAck that was recieved (in UTC)
|
// Stores the last HeartbeatAck that was recieved (in UTC)
|
||||||
LastHeartbeatAck time.Time
|
LastHeartbeatAck time.Time
|
||||||
|
|
||||||
|
// used to deal with rate limits
|
||||||
|
Ratelimiter *RateLimiter
|
||||||
|
|
||||||
// Event handlers
|
// Event handlers
|
||||||
handlersMu sync.RWMutex
|
handlersMu sync.RWMutex
|
||||||
handlers map[string][]*eventHandlerInstance
|
handlers map[string][]*eventHandlerInstance
|
||||||
@ -96,9 +98,6 @@ type Session struct {
|
|||||||
// When nil, the session is not listening.
|
// When nil, the session is not listening.
|
||||||
listening chan interface{}
|
listening chan interface{}
|
||||||
|
|
||||||
// used to deal with rate limits
|
|
||||||
ratelimiter *RateLimiter
|
|
||||||
|
|
||||||
// sequence tracks the current gateway api websocket sequence number
|
// sequence tracks the current gateway api websocket sequence number
|
||||||
sequence *int64
|
sequence *int64
|
||||||
|
|
||||||
@ -143,9 +142,9 @@ type Invite struct {
|
|||||||
MaxAge int `json:"max_age"`
|
MaxAge int `json:"max_age"`
|
||||||
Uses int `json:"uses"`
|
Uses int `json:"uses"`
|
||||||
MaxUses int `json:"max_uses"`
|
MaxUses int `json:"max_uses"`
|
||||||
XkcdPass string `json:"xkcdpass"`
|
|
||||||
Revoked bool `json:"revoked"`
|
Revoked bool `json:"revoked"`
|
||||||
Temporary bool `json:"temporary"`
|
Temporary bool `json:"temporary"`
|
||||||
|
Unique bool `json:"unique"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelType is the type of a Channel
|
// ChannelType is the type of a Channel
|
||||||
@ -171,9 +170,22 @@ type Channel struct {
|
|||||||
NSFW bool `json:"nsfw"`
|
NSFW bool `json:"nsfw"`
|
||||||
Position int `json:"position"`
|
Position int `json:"position"`
|
||||||
Bitrate int `json:"bitrate"`
|
Bitrate int `json:"bitrate"`
|
||||||
Recipients []*User `json:"recipient"`
|
Recipients []*User `json:"recipients"`
|
||||||
Messages []*Message `json:"-"`
|
Messages []*Message `json:"-"`
|
||||||
PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites"`
|
PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites"`
|
||||||
|
ParentID string `json:"parent_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ChannelEdit holds Channel Feild data for a channel edit.
|
||||||
|
type ChannelEdit struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Topic string `json:"topic,omitempty"`
|
||||||
|
NSFW bool `json:"nsfw,omitempty"`
|
||||||
|
Position int `json:"position"`
|
||||||
|
Bitrate int `json:"bitrate,omitempty"`
|
||||||
|
UserLimit int `json:"user_limit,omitempty"`
|
||||||
|
PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites,omitempty"`
|
||||||
|
ParentID string `json:"parent_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A PermissionOverwrite holds permission overwrite data for a Channel
|
// A PermissionOverwrite holds permission overwrite data for a Channel
|
||||||
@ -191,6 +203,7 @@ type Emoji struct {
|
|||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
Managed bool `json:"managed"`
|
Managed bool `json:"managed"`
|
||||||
RequireColons bool `json:"require_colons"`
|
RequireColons bool `json:"require_colons"`
|
||||||
|
Animated bool `json:"animated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIName returns an correctly formatted API name for use in the MessageReactions endpoints.
|
// APIName returns an correctly formatted API name for use in the MessageReactions endpoints.
|
||||||
@ -204,7 +217,7 @@ func (e *Emoji) APIName() string {
|
|||||||
return e.ID
|
return e.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerificationLevel type defination
|
// VerificationLevel type definition
|
||||||
type VerificationLevel int
|
type VerificationLevel int
|
||||||
|
|
||||||
// Constants for VerificationLevel levels from 0 to 3 inclusive
|
// Constants for VerificationLevel levels from 0 to 3 inclusive
|
||||||
@ -314,43 +327,56 @@ type Presence struct {
|
|||||||
Since *int `json:"since"`
|
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
|
||||||
|
)
|
||||||
|
|
||||||
// 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 GameType `json:"type"`
|
||||||
URL string `json:"url,omitempty"`
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals json to Game struct
|
// A TimeStamps struct contains start and end times used in the rich presence "playing .." Game
|
||||||
func (g *Game) UnmarshalJSON(bytes []byte) error {
|
type TimeStamps struct {
|
||||||
temp := &struct {
|
EndTimestamp int64 `json:"end,omitempty"`
|
||||||
Name json.Number `json:"name"`
|
StartTimestamp int64 `json:"start,omitempty"`
|
||||||
Type json.RawMessage `json:"type"`
|
}
|
||||||
URL string `json:"url"`
|
|
||||||
|
// UnmarshalJSON unmarshals JSON into TimeStamps struct
|
||||||
|
func (t *TimeStamps) UnmarshalJSON(b []byte) error {
|
||||||
|
temp := struct {
|
||||||
|
End float64 `json:"end,omitempty"`
|
||||||
|
Start float64 `json:"start,omitempty"`
|
||||||
}{}
|
}{}
|
||||||
err := json.Unmarshal(bytes, temp)
|
err := json.Unmarshal(b, &temp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
g.URL = temp.URL
|
t.EndTimestamp = int64(temp.End)
|
||||||
g.Name = temp.Name.String()
|
t.StartTimestamp = int64(temp.Start)
|
||||||
|
|
||||||
if temp.Type != nil {
|
|
||||||
err = json.Unmarshal(temp.Type, &g.Type)
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
s := ""
|
// An Assets struct contains assets and labels used in the rich presence "playing .." Game
|
||||||
err = json.Unmarshal(temp.Type, &s)
|
type Assets struct {
|
||||||
if err == nil {
|
LargeImageID string `json:"large_image,omitempty"`
|
||||||
g.Type, err = strconv.Atoi(s)
|
SmallImageID string `json:"small_image,omitempty"`
|
||||||
}
|
LargeText string `json:"large_text,omitempty"`
|
||||||
|
SmallText string `json:"small_text,omitempty"`
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Member stores user information for Guild members.
|
// A Member stores user information for Guild members.
|
||||||
@ -383,7 +409,7 @@ type Settings struct {
|
|||||||
DeveloperMode bool `json:"developer_mode"`
|
DeveloperMode bool `json:"developer_mode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status type defination
|
// Status type definition
|
||||||
type Status string
|
type Status string
|
||||||
|
|
||||||
// Constants for Status with the different current available status
|
// Constants for Status with the different current available status
|
||||||
|
5
vendor/github.com/bwmarrin/discordgo/user.go
generated
vendored
5
vendor/github.com/bwmarrin/discordgo/user.go
generated
vendored
@ -30,6 +30,8 @@ func (u *User) Mention() string {
|
|||||||
|
|
||||||
// AvatarURL returns a URL to the user's avatar.
|
// AvatarURL returns a URL to the user's avatar.
|
||||||
// size: The size of the user's avatar as a power of two
|
// size: The size of the user's avatar as a power of two
|
||||||
|
// if size is an empty string, no size parameter will
|
||||||
|
// be added to the URL.
|
||||||
func (u *User) AvatarURL(size string) string {
|
func (u *User) AvatarURL(size string) string {
|
||||||
var URL string
|
var URL string
|
||||||
if strings.HasPrefix(u.Avatar, "a_") {
|
if strings.HasPrefix(u.Avatar, "a_") {
|
||||||
@ -38,5 +40,8 @@ func (u *User) AvatarURL(size string) string {
|
|||||||
URL = EndpointUserAvatar(u.ID, u.Avatar)
|
URL = EndpointUserAvatar(u.ID, u.Avatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if size != "" {
|
||||||
return URL + "?size=" + size
|
return URL + "?size=" + size
|
||||||
}
|
}
|
||||||
|
return URL
|
||||||
|
}
|
||||||
|
11
vendor/github.com/bwmarrin/discordgo/voice.go
generated
vendored
11
vendor/github.com/bwmarrin/discordgo/voice.go
generated
vendored
@ -13,7 +13,6 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -69,7 +68,7 @@ type VoiceConnection struct {
|
|||||||
voiceSpeakingUpdateHandlers []VoiceSpeakingUpdateHandler
|
voiceSpeakingUpdateHandlers []VoiceSpeakingUpdateHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// VoiceSpeakingUpdateHandler type provides a function defination for the
|
// VoiceSpeakingUpdateHandler type provides a function definition for the
|
||||||
// VoiceSpeakingUpdate event
|
// VoiceSpeakingUpdate event
|
||||||
type VoiceSpeakingUpdateHandler func(vc *VoiceConnection, vs *VoiceSpeakingUpdate)
|
type VoiceSpeakingUpdateHandler func(vc *VoiceConnection, vs *VoiceSpeakingUpdate)
|
||||||
|
|
||||||
@ -104,7 +103,7 @@ func (v *VoiceConnection) Speaking(b bool) (err error) {
|
|||||||
defer v.Unlock()
|
defer v.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.speaking = false
|
v.speaking = false
|
||||||
log.Println("Speaking() write json error:", err)
|
v.log(LogError, "Speaking() write json error:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +180,7 @@ func (v *VoiceConnection) Close() {
|
|||||||
v.log(LogInformational, "closing udp")
|
v.log(LogInformational, "closing udp")
|
||||||
err := v.udpConn.Close()
|
err := v.udpConn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error closing udp connection: ", err)
|
v.log(LogError, "error closing udp connection: ", err)
|
||||||
}
|
}
|
||||||
v.udpConn = nil
|
v.udpConn = nil
|
||||||
}
|
}
|
||||||
@ -247,7 +246,7 @@ type voiceOP2 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WaitUntilConnected waits for the Voice Connection to
|
// WaitUntilConnected waits for the Voice Connection to
|
||||||
// become ready, if it does not become ready it retuns an err
|
// become ready, if it does not become ready it returns an err
|
||||||
func (v *VoiceConnection) waitUntilConnected() error {
|
func (v *VoiceConnection) waitUntilConnected() error {
|
||||||
|
|
||||||
v.log(LogInformational, "called")
|
v.log(LogInformational, "called")
|
||||||
@ -858,7 +857,7 @@ func (v *VoiceConnection) reconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if v.session.DataReady == false || v.session.wsConn == nil {
|
if v.session.DataReady == false || v.session.wsConn == nil {
|
||||||
v.log(LogInformational, "cannot reconenct to channel %s with unready session", v.ChannelID)
|
v.log(LogInformational, "cannot reconnect to channel %s with unready session", v.ChannelID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
255
vendor/github.com/bwmarrin/discordgo/wsapi.go
generated
vendored
255
vendor/github.com/bwmarrin/discordgo/wsapi.go
generated
vendored
@ -15,6 +15,7 @@ import (
|
|||||||
"compress/zlib"
|
"compress/zlib"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -45,19 +46,114 @@ type resumePacket struct {
|
|||||||
} `json:"d"`
|
} `json:"d"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open opens a websocket connection to Discord.
|
// Open creates a websocket connection to Discord.
|
||||||
func (s *Session) Open() (err error) {
|
// See: https://discordapp.com/developers/docs/topics/gateway#connecting
|
||||||
|
func (s *Session) Open() error {
|
||||||
s.log(LogInformational, "called")
|
s.log(LogInformational, "called")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Prevent Open or other major Session functions from
|
||||||
|
// being called while Open is still running.
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer func() {
|
defer s.Unlock()
|
||||||
|
|
||||||
|
// If the websock is already open, bail out here.
|
||||||
|
if s.wsConn != nil {
|
||||||
|
return ErrWSAlreadyOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the gateway to use for the Websocket connection
|
||||||
|
if s.gateway == "" {
|
||||||
|
s.gateway, err = s.Gateway()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Unlock()
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the version and encoding to the URL
|
||||||
|
s.gateway = s.gateway + "?v=" + APIVersion + "&encoding=json"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to the Gateway
|
||||||
|
s.log(LogInformational, "connecting to gateway %s", s.gateway)
|
||||||
|
header := http.Header{}
|
||||||
|
header.Add("accept-encoding", "zlib")
|
||||||
|
s.wsConn, _, err = websocket.DefaultDialer.Dial(s.gateway, header)
|
||||||
|
if err != nil {
|
||||||
|
s.log(LogWarning, "error connecting to gateway %s, %s", s.gateway, err)
|
||||||
|
s.gateway = "" // clear cached gateway
|
||||||
|
s.wsConn = nil // Just to be safe.
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
// because of this, all code below must set err to the error
|
||||||
|
// when exiting with an error :) Maybe someone has a better
|
||||||
|
// way :)
|
||||||
|
if err != nil {
|
||||||
|
s.wsConn.Close()
|
||||||
|
s.wsConn = nil
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// The first response from Discord should be an Op 10 (Hello) Packet.
|
||||||
|
// When processed by onEvent the heartbeat goroutine will be started.
|
||||||
|
mt, m, err := s.wsConn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e, err := s.onEvent(mt, m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if e.Operation != 10 {
|
||||||
|
err = fmt.Errorf("expecting Op 10, got Op %d instead", e.Operation)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.log(LogInformational, "Op 10 Hello Packet received from Discord")
|
||||||
|
s.LastHeartbeatAck = time.Now().UTC()
|
||||||
|
var h helloOp
|
||||||
|
if err = json.Unmarshal(e.RawData, &h); err != nil {
|
||||||
|
err = fmt.Errorf("error unmarshalling helloOp, %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we send either an Op 2 Identity if this is a brand new
|
||||||
|
// connection or Op 6 Resume if we are resuming an existing connection.
|
||||||
|
sequence := atomic.LoadInt64(s.sequence)
|
||||||
|
if s.sessionID == "" && sequence == 0 {
|
||||||
|
|
||||||
|
// Send Op 2 Identity Packet
|
||||||
|
err = s.identify()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("error sending identify packet to gateway, %s, %s", s.gateway, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Send Op 6 Resume Packet
|
||||||
|
p := resumePacket{}
|
||||||
|
p.Op = 6
|
||||||
|
p.Data.Token = s.Token
|
||||||
|
p.Data.SessionID = s.sessionID
|
||||||
|
p.Data.Sequence = sequence
|
||||||
|
|
||||||
|
s.log(LogInformational, "sending resume packet to gateway")
|
||||||
|
s.wsMutex.Lock()
|
||||||
|
err = s.wsConn.WriteJSON(p)
|
||||||
|
s.wsMutex.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("error sending gateway resume packet, %s, %s", s.gateway, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// A basic state is a hard requirement for Voice.
|
// A basic state is a hard requirement for Voice.
|
||||||
|
// We create it here so the below READY/RESUMED packet can populate
|
||||||
|
// the state :)
|
||||||
|
// XXX: Move to New() func?
|
||||||
if s.State == nil {
|
if s.State == nil {
|
||||||
state := NewState()
|
state := NewState()
|
||||||
state.TrackChannels = false
|
state.TrackChannels = false
|
||||||
@ -68,77 +164,42 @@ func (s *Session) Open() (err error) {
|
|||||||
s.State = state
|
s.State = state
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.wsConn != nil {
|
// Now Discord should send us a READY or RESUMED packet.
|
||||||
err = ErrWSAlreadyOpen
|
mt, m, err = s.wsConn.ReadMessage()
|
||||||
return
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
e, err = s.onEvent(mt, m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if e.Type != `READY` && e.Type != `RESUMED` {
|
||||||
|
// This is not fatal, but it does not follow their API documentation.
|
||||||
|
s.log(LogWarning, "Expected READY/RESUMED, instead got:\n%#v\n", e)
|
||||||
|
}
|
||||||
|
s.log(LogInformational, "First Packet:\n%#v\n", e)
|
||||||
|
|
||||||
|
s.log(LogInformational, "We are now connected to Discord, emitting connect event")
|
||||||
|
s.handleEvent(connectEventType, &Connect{})
|
||||||
|
|
||||||
|
// A VoiceConnections map is a hard requirement for Voice.
|
||||||
|
// XXX: can this be moved to when opening a voice connection?
|
||||||
if s.VoiceConnections == nil {
|
if s.VoiceConnections == nil {
|
||||||
s.log(LogInformational, "creating new VoiceConnections map")
|
s.log(LogInformational, "creating new VoiceConnections map")
|
||||||
s.VoiceConnections = make(map[string]*VoiceConnection)
|
s.VoiceConnections = make(map[string]*VoiceConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the gateway to use for the Websocket connection
|
// Create listening chan outside of listen, as it needs to happen inside the
|
||||||
if s.gateway == "" {
|
// mutex lock and needs to exist before calling heartbeat and listen
|
||||||
s.gateway, err = s.Gateway()
|
// go rountines.
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the version and encoding to the URL
|
|
||||||
s.gateway = s.gateway + "?v=" + APIVersion + "&encoding=json"
|
|
||||||
}
|
|
||||||
|
|
||||||
header := http.Header{}
|
|
||||||
header.Add("accept-encoding", "zlib")
|
|
||||||
|
|
||||||
s.log(LogInformational, "connecting to gateway %s", s.gateway)
|
|
||||||
s.wsConn, _, err = websocket.DefaultDialer.Dial(s.gateway, header)
|
|
||||||
if err != nil {
|
|
||||||
s.log(LogWarning, "error connecting to gateway %s, %s", s.gateway, err)
|
|
||||||
s.gateway = "" // clear cached gateway
|
|
||||||
// TODO: should we add a retry block here?
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence := atomic.LoadInt64(s.sequence)
|
|
||||||
if s.sessionID != "" && sequence > 0 {
|
|
||||||
|
|
||||||
p := resumePacket{}
|
|
||||||
p.Op = 6
|
|
||||||
p.Data.Token = s.Token
|
|
||||||
p.Data.SessionID = s.sessionID
|
|
||||||
p.Data.Sequence = sequence
|
|
||||||
|
|
||||||
s.log(LogInformational, "sending resume packet to gateway")
|
|
||||||
err = s.wsConn.WriteJSON(p)
|
|
||||||
if err != nil {
|
|
||||||
s.log(LogWarning, "error sending gateway resume packet, %s, %s", s.gateway, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
err = s.identify()
|
|
||||||
if err != nil {
|
|
||||||
s.log(LogWarning, "error sending gateway identify packet, %s, %s", s.gateway, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create listening outside of listen, as it needs to happen inside the mutex
|
|
||||||
// lock.
|
|
||||||
s.listening = make(chan interface{})
|
s.listening = make(chan interface{})
|
||||||
|
|
||||||
|
// Start sending heartbeats and reading messages from Discord.
|
||||||
|
go s.heartbeat(s.wsConn, s.listening, h.HeartbeatInterval)
|
||||||
go s.listen(s.wsConn, s.listening)
|
go s.listen(s.wsConn, s.listening)
|
||||||
s.LastHeartbeatAck = time.Now().UTC()
|
|
||||||
|
|
||||||
s.Unlock()
|
|
||||||
|
|
||||||
s.log(LogInformational, "emit connect event")
|
|
||||||
s.handleEvent(connectEventType, &Connect{})
|
|
||||||
|
|
||||||
s.log(LogInformational, "exiting")
|
s.log(LogInformational, "exiting")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// listen polls the websocket connection for events, it will stop when the
|
// listen polls the websocket connection for events, it will stop when the
|
||||||
@ -249,7 +310,8 @@ func (s *Session) heartbeat(wsConn *websocket.Conn, listening <-chan interface{}
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type updateStatusData struct {
|
// UpdateStatusData ia provided to UpdateStatusComplex()
|
||||||
|
type UpdateStatusData struct {
|
||||||
IdleSince *int `json:"since"`
|
IdleSince *int `json:"since"`
|
||||||
Game *Game `json:"game"`
|
Game *Game `json:"game"`
|
||||||
AFK bool `json:"afk"`
|
AFK bool `json:"afk"`
|
||||||
@ -258,7 +320,7 @@ type updateStatusData struct {
|
|||||||
|
|
||||||
type updateStatusOp struct {
|
type updateStatusOp struct {
|
||||||
Op int `json:"op"`
|
Op int `json:"op"`
|
||||||
Data updateStatusData `json:"d"`
|
Data UpdateStatusData `json:"d"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStreamingStatus is used to update the user's streaming status.
|
// UpdateStreamingStatus is used to update the user's streaming status.
|
||||||
@ -270,13 +332,7 @@ func (s *Session) UpdateStreamingStatus(idle int, game string, url string) (err
|
|||||||
|
|
||||||
s.log(LogInformational, "called")
|
s.log(LogInformational, "called")
|
||||||
|
|
||||||
s.RLock()
|
usd := UpdateStatusData{
|
||||||
defer s.RUnlock()
|
|
||||||
if s.wsConn == nil {
|
|
||||||
return ErrWSNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
usd := updateStatusData{
|
|
||||||
Status: "online",
|
Status: "online",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,9 +341,9 @@ func (s *Session) UpdateStreamingStatus(idle int, game string, url string) (err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if game != "" {
|
if game != "" {
|
||||||
gameType := 0
|
gameType := GameTypeGame
|
||||||
if url != "" {
|
if url != "" {
|
||||||
gameType = 1
|
gameType = GameTypeStreaming
|
||||||
}
|
}
|
||||||
usd.Game = &Game{
|
usd.Game = &Game{
|
||||||
Name: game,
|
Name: game,
|
||||||
@ -296,6 +352,18 @@ func (s *Session) UpdateStreamingStatus(idle int, game string, url string) (err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return s.UpdateStatusComplex(usd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateStatusComplex allows for sending the raw status update data untouched by discordgo.
|
||||||
|
func (s *Session) UpdateStatusComplex(usd UpdateStatusData) (err error) {
|
||||||
|
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
if s.wsConn == nil {
|
||||||
|
return ErrWSNotFound
|
||||||
|
}
|
||||||
|
|
||||||
s.wsMutex.Lock()
|
s.wsMutex.Lock()
|
||||||
err = s.wsConn.WriteJSON(updateStatusOp{3, usd})
|
err = s.wsConn.WriteJSON(updateStatusOp{3, usd})
|
||||||
s.wsMutex.Unlock()
|
s.wsMutex.Unlock()
|
||||||
@ -357,9 +425,7 @@ func (s *Session) RequestGuildMembers(guildID, query string, limit int) (err err
|
|||||||
//
|
//
|
||||||
// If you use the AddHandler() function to register a handler for the
|
// If you use the AddHandler() function to register a handler for the
|
||||||
// "OnEvent" event then all events will be passed to that handler.
|
// "OnEvent" event then all events will be passed to that handler.
|
||||||
//
|
func (s *Session) onEvent(messageType int, message []byte) (*Event, error) {
|
||||||
// TODO: You may also register a custom event handler entirely using...
|
|
||||||
func (s *Session) onEvent(messageType int, message []byte) {
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var reader io.Reader
|
var reader io.Reader
|
||||||
@ -371,7 +437,7 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
z, err2 := zlib.NewReader(reader)
|
z, err2 := zlib.NewReader(reader)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
s.log(LogError, "error uncompressing websocket message, %s", err)
|
s.log(LogError, "error uncompressing websocket message, %s", err)
|
||||||
return
|
return nil, err2
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -389,7 +455,7 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
decoder := json.NewDecoder(reader)
|
decoder := json.NewDecoder(reader)
|
||||||
if err = decoder.Decode(&e); err != nil {
|
if err = decoder.Decode(&e); err != nil {
|
||||||
s.log(LogError, "error decoding websocket message, %s", err)
|
s.log(LogError, "error decoding websocket message, %s", err)
|
||||||
return
|
return e, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.log(LogDebug, "Op: %d, Seq: %d, Type: %s, Data: %s\n\n", e.Operation, e.Sequence, e.Type, string(e.RawData))
|
s.log(LogDebug, "Op: %d, Seq: %d, Type: %s, Data: %s\n\n", e.Operation, e.Sequence, e.Type, string(e.RawData))
|
||||||
@ -403,10 +469,10 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
s.wsMutex.Unlock()
|
s.wsMutex.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(LogError, "error sending heartbeat in response to Op1")
|
s.log(LogError, "error sending heartbeat in response to Op1")
|
||||||
return
|
return e, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reconnect
|
// Reconnect
|
||||||
@ -415,7 +481,7 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
s.log(LogInformational, "Closing and reconnecting in response to Op7")
|
s.log(LogInformational, "Closing and reconnecting in response to Op7")
|
||||||
s.Close()
|
s.Close()
|
||||||
s.reconnect()
|
s.reconnect()
|
||||||
return
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalid Session
|
// Invalid Session
|
||||||
@ -427,20 +493,15 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
err = s.identify()
|
err = s.identify()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(LogWarning, "error sending gateway identify packet, %s, %s", s.gateway, err)
|
s.log(LogWarning, "error sending gateway identify packet, %s, %s", s.gateway, err)
|
||||||
return
|
return e, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Operation == 10 {
|
if e.Operation == 10 {
|
||||||
var h helloOp
|
// Op10 is handled by Open()
|
||||||
if err = json.Unmarshal(e.RawData, &h); err != nil {
|
return e, nil
|
||||||
s.log(LogError, "error unmarshalling helloOp, %s", err)
|
|
||||||
} else {
|
|
||||||
go s.heartbeat(s.wsConn, s.listening, h.HeartbeatInterval)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.Operation == 11 {
|
if e.Operation == 11 {
|
||||||
@ -448,7 +509,7 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
s.LastHeartbeatAck = time.Now().UTC()
|
s.LastHeartbeatAck = time.Now().UTC()
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
s.log(LogInformational, "got heartbeat ACK")
|
s.log(LogInformational, "got heartbeat ACK")
|
||||||
return
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not try to Dispatch a non-Dispatch Message
|
// Do not try to Dispatch a non-Dispatch Message
|
||||||
@ -456,7 +517,7 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
// But we probably should be doing something with them.
|
// But we probably should be doing something with them.
|
||||||
// TEMP
|
// TEMP
|
||||||
s.log(LogWarning, "unknown Op: %d, Seq: %d, Type: %s, Data: %s, message: %s", e.Operation, e.Sequence, e.Type, string(e.RawData), string(message))
|
s.log(LogWarning, "unknown Op: %d, Seq: %d, Type: %s, Data: %s, message: %s", e.Operation, e.Sequence, e.Type, string(e.RawData), string(message))
|
||||||
return
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the message sequence
|
// Store the message sequence
|
||||||
@ -485,6 +546,8 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
|||||||
|
|
||||||
// For legacy reasons, we send the raw event also, this could be useful for handling unknown events.
|
// For legacy reasons, we send the raw event also, this could be useful for handling unknown events.
|
||||||
s.handleEvent(eventEventType, e)
|
s.handleEvent(eventEventType, e)
|
||||||
|
|
||||||
|
return e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
@ -610,7 +673,7 @@ func (s *Session) onVoiceServerUpdate(st *VoiceServerUpdate) {
|
|||||||
voice.GuildID = st.GuildID
|
voice.GuildID = st.GuildID
|
||||||
voice.Unlock()
|
voice.Unlock()
|
||||||
|
|
||||||
// Open a conenction to the voice server
|
// Open a connection to the voice server
|
||||||
err := voice.open()
|
err := voice.open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log(LogError, "onVoiceServerUpdate voice.open, %s", err)
|
s.log(LogError, "onVoiceServerUpdate voice.open, %s", err)
|
||||||
|
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": "2fda7ce223a66a5b70b66987c22c3c94d022ee66",
|
"revision": "8d5ab59c63e553fd2030706008a806a8b553188c",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"notests": true
|
"notests": true
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user