Merge branch 'develop'
This commit is contained in:
commit
002b6b91ca
21 changed files with 2907 additions and 570 deletions
|
@ -1,7 +1,7 @@
|
||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.6
|
- 1.6
|
||||||
- tip
|
- 1.7
|
||||||
install:
|
install:
|
||||||
- go get github.com/bwmarrin/discordgo
|
- go get github.com/bwmarrin/discordgo
|
||||||
- go get -v .
|
- go get -v .
|
||||||
|
|
142
discord.go
142
discord.go
|
@ -13,13 +13,10 @@
|
||||||
// Package discordgo provides Discord binding for Go
|
// Package discordgo provides Discord binding for Go
|
||||||
package discordgo
|
package discordgo
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VERSION of Discordgo, follows Symantic Versioning. (http://semver.org/)
|
// VERSION of Discordgo, follows Symantic Versioning. (http://semver.org/)
|
||||||
const VERSION = "0.13.0"
|
const VERSION = "0.14.0-dev"
|
||||||
|
|
||||||
// New creates a new Discord session and will automate some startup
|
// New creates a new Discord session and will automate some startup
|
||||||
// tasks if given enough information to do so. Currently you can pass zero
|
// tasks if given enough information to do so. Currently you can pass zero
|
||||||
|
@ -39,11 +36,13 @@ 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(),
|
||||||
StateEnabled: true,
|
StateEnabled: true,
|
||||||
Compress: true,
|
Compress: true,
|
||||||
ShouldReconnectOnError: true,
|
ShouldReconnectOnError: true,
|
||||||
ShardID: 0,
|
ShardID: 0,
|
||||||
ShardCount: 1,
|
ShardCount: 1,
|
||||||
|
MaxRestRetries: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no arguments are passed return the empty Session interface.
|
// If no arguments are passed return the empty Session interface.
|
||||||
|
@ -124,136 +123,3 @@ func New(args ...interface{}) (s *Session, err error) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateHandler takes an event handler func, and returns the type of event.
|
|
||||||
// eg.
|
|
||||||
// Session.validateHandler(func (s *discordgo.Session, m *discordgo.MessageCreate))
|
|
||||||
// will return the reflect.Type of *discordgo.MessageCreate
|
|
||||||
func (s *Session) validateHandler(handler interface{}) reflect.Type {
|
|
||||||
|
|
||||||
handlerType := reflect.TypeOf(handler)
|
|
||||||
|
|
||||||
if handlerType.NumIn() != 2 {
|
|
||||||
panic("Unable to add event handler, handler must be of the type func(*discordgo.Session, *discordgo.EventType).")
|
|
||||||
}
|
|
||||||
|
|
||||||
if handlerType.In(0) != reflect.TypeOf(s) {
|
|
||||||
panic("Unable to add event handler, first argument must be of type *discordgo.Session.")
|
|
||||||
}
|
|
||||||
|
|
||||||
eventType := handlerType.In(1)
|
|
||||||
|
|
||||||
// Support handlers of type interface{}, this is a special handler, which is triggered on every event.
|
|
||||||
if eventType.Kind() == reflect.Interface {
|
|
||||||
eventType = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return eventType
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddHandler allows you to add an event handler that will be fired anytime
|
|
||||||
// the Discord WSAPI event that matches the interface fires.
|
|
||||||
// eventToInterface in events.go has a list of all the Discord WSAPI events
|
|
||||||
// and their respective interface.
|
|
||||||
// eg:
|
|
||||||
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// or:
|
|
||||||
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
|
|
||||||
// })
|
|
||||||
// The return value of this method is a function, that when called will remove the
|
|
||||||
// event handler.
|
|
||||||
func (s *Session) AddHandler(handler interface{}) func() {
|
|
||||||
|
|
||||||
s.initialize()
|
|
||||||
|
|
||||||
eventType := s.validateHandler(handler)
|
|
||||||
|
|
||||||
s.handlersMu.Lock()
|
|
||||||
defer s.handlersMu.Unlock()
|
|
||||||
|
|
||||||
h := reflect.ValueOf(handler)
|
|
||||||
|
|
||||||
s.handlers[eventType] = append(s.handlers[eventType], h)
|
|
||||||
|
|
||||||
// This must be done as we need a consistent reference to the
|
|
||||||
// reflected value, otherwise a RemoveHandler method would have
|
|
||||||
// been nice.
|
|
||||||
return func() {
|
|
||||||
s.handlersMu.Lock()
|
|
||||||
defer s.handlersMu.Unlock()
|
|
||||||
|
|
||||||
handlers := s.handlers[eventType]
|
|
||||||
for i, v := range handlers {
|
|
||||||
if h == v {
|
|
||||||
s.handlers[eventType] = append(handlers[:i], handlers[i+1:]...)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle calls any handlers that match the event type and any handlers of
|
|
||||||
// interface{}.
|
|
||||||
func (s *Session) handle(event interface{}) {
|
|
||||||
|
|
||||||
s.handlersMu.RLock()
|
|
||||||
defer s.handlersMu.RUnlock()
|
|
||||||
|
|
||||||
if s.handlers == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
handlerParameters := []reflect.Value{reflect.ValueOf(s), reflect.ValueOf(event)}
|
|
||||||
|
|
||||||
if handlers, ok := s.handlers[nil]; ok {
|
|
||||||
for _, handler := range handlers {
|
|
||||||
go handler.Call(handlerParameters)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if handlers, ok := s.handlers[reflect.TypeOf(event)]; ok {
|
|
||||||
for _, handler := range handlers {
|
|
||||||
go handler.Call(handlerParameters)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize adds all internal handlers and state tracking handlers.
|
|
||||||
func (s *Session) initialize() {
|
|
||||||
|
|
||||||
s.log(LogInformational, "called")
|
|
||||||
|
|
||||||
s.handlersMu.Lock()
|
|
||||||
if s.handlers != nil {
|
|
||||||
s.handlersMu.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.handlers = map[interface{}][]reflect.Value{}
|
|
||||||
s.handlersMu.Unlock()
|
|
||||||
|
|
||||||
s.AddHandler(s.onReady)
|
|
||||||
s.AddHandler(s.onResumed)
|
|
||||||
s.AddHandler(s.onVoiceServerUpdate)
|
|
||||||
s.AddHandler(s.onVoiceStateUpdate)
|
|
||||||
s.AddHandler(s.State.onInterface)
|
|
||||||
}
|
|
||||||
|
|
||||||
// onReady handles the ready event.
|
|
||||||
func (s *Session) onReady(se *Session, r *Ready) {
|
|
||||||
|
|
||||||
// Store the SessionID within the Session struct.
|
|
||||||
s.sessionID = r.SessionID
|
|
||||||
|
|
||||||
// Start the heartbeat to keep the connection alive.
|
|
||||||
go s.heartbeat(s.wsConn, s.listening, r.HeartbeatInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// onResumed handles the resumed event.
|
|
||||||
func (s *Session) onResumed(se *Session, r *Resumed) {
|
|
||||||
|
|
||||||
// Start the heartbeat to keep the connection alive.
|
|
||||||
go s.heartbeat(s.wsConn, s.listening, r.HeartbeatInterval)
|
|
||||||
}
|
|
||||||
|
|
|
@ -223,8 +223,8 @@ func TestAddHandler(t *testing.T) {
|
||||||
d.AddHandler(interfaceHandler)
|
d.AddHandler(interfaceHandler)
|
||||||
d.AddHandler(bogusHandler)
|
d.AddHandler(bogusHandler)
|
||||||
|
|
||||||
d.handle(&MessageCreate{})
|
d.handleEvent(messageCreateEventType, &MessageCreate{})
|
||||||
d.handle(&MessageDelete{})
|
d.handleEvent(messageDeleteEventType, &MessageDelete{})
|
||||||
|
|
||||||
<-time.After(500 * time.Millisecond)
|
<-time.After(500 * time.Millisecond)
|
||||||
|
|
||||||
|
@ -253,11 +253,11 @@ func TestRemoveHandler(t *testing.T) {
|
||||||
d := Session{}
|
d := Session{}
|
||||||
r := d.AddHandler(testHandler)
|
r := d.AddHandler(testHandler)
|
||||||
|
|
||||||
d.handle(&MessageCreate{})
|
d.handleEvent(messageCreateEventType, &MessageCreate{})
|
||||||
|
|
||||||
r()
|
r()
|
||||||
|
|
||||||
d.handle(&MessageCreate{})
|
d.handleEvent(messageCreateEventType, &MessageCreate{})
|
||||||
|
|
||||||
<-time.After(500 * time.Millisecond)
|
<-time.After(500 * time.Millisecond)
|
||||||
|
|
||||||
|
|
18
endpoints.go
18
endpoints.go
|
@ -24,6 +24,7 @@ var (
|
||||||
EndpointChannels = EndpointAPI + "channels/"
|
EndpointChannels = EndpointAPI + "channels/"
|
||||||
EndpointUsers = EndpointAPI + "users/"
|
EndpointUsers = EndpointAPI + "users/"
|
||||||
EndpointGateway = EndpointAPI + "gateway"
|
EndpointGateway = EndpointAPI + "gateway"
|
||||||
|
EndpointWebhooks = EndpointAPI + "webhooks/"
|
||||||
|
|
||||||
EndpointAuth = EndpointAPI + "auth/"
|
EndpointAuth = EndpointAPI + "auth/"
|
||||||
EndpointLogin = EndpointAuth + "login"
|
EndpointLogin = EndpointAuth + "login"
|
||||||
|
@ -61,6 +62,7 @@ var (
|
||||||
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 }
|
||||||
|
EndpointGuildMemberRole = func(gID, uID, rID string) string { return EndpointGuilds + gID + "/members/" + uID + "/roles/" + rID }
|
||||||
EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" }
|
EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" }
|
||||||
EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID }
|
EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID }
|
||||||
EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" }
|
EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" }
|
||||||
|
@ -73,6 +75,7 @@ var (
|
||||||
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
|
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
|
||||||
EndpointGuildIcon = func(gID, hash string) string { return EndpointGuilds + gID + "/icons/" + hash + ".jpg" }
|
EndpointGuildIcon = func(gID, hash string) string { return EndpointGuilds + gID + "/icons/" + hash + ".jpg" }
|
||||||
EndpointGuildSplash = func(gID, hash string) string { return EndpointGuilds + gID + "/splashes/" + hash + ".jpg" }
|
EndpointGuildSplash = func(gID, hash string) string { return EndpointGuilds + gID + "/splashes/" + hash + ".jpg" }
|
||||||
|
EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" }
|
||||||
|
|
||||||
EndpointChannel = func(cID string) string { return EndpointChannels + cID }
|
EndpointChannel = func(cID string) string { return EndpointChannels + cID }
|
||||||
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" }
|
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" }
|
||||||
|
@ -86,6 +89,21 @@ var (
|
||||||
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 }
|
||||||
|
|
||||||
|
EndpointChannelWebhooks = func(cID string) string { return EndpointChannel(cID) + "/webhooks" }
|
||||||
|
EndpointWebhook = func(wID string) string { return EndpointWebhooks + wID }
|
||||||
|
EndpointWebhookToken = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token }
|
||||||
|
|
||||||
|
EndpointMessageReactions = func(cID, mID, eID string) string {
|
||||||
|
return EndpointChannelMessage(cID, mID) + "/reactions/" + eID
|
||||||
|
}
|
||||||
|
EndpointMessageReaction = func(cID, mID, eID, uID string) string {
|
||||||
|
return EndpointMessageReactions(cID, mID, eID) + "/" + uID
|
||||||
|
}
|
||||||
|
|
||||||
|
EndpointRelationships = func() string { return EndpointUsers + "@me" + "/relationships" }
|
||||||
|
EndpointRelationship = func(uID string) string { return EndpointRelationships() + "/" + uID }
|
||||||
|
EndpointRelationshipsMutual = func(uID string) string { return EndpointUsers + uID + "/relationships" }
|
||||||
|
|
||||||
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" }
|
||||||
|
|
238
event.go
Normal file
238
event.go
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// EventHandler is an interface for Discord events.
|
||||||
|
type EventHandler interface {
|
||||||
|
// Type returns the type of event this handler belongs to.
|
||||||
|
Type() string
|
||||||
|
|
||||||
|
// Handle is called whenever an event of Type() happens.
|
||||||
|
// It is the recievers responsibility to type assert that the interface
|
||||||
|
// is the expected struct.
|
||||||
|
Handle(*Session, interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventInterfaceProvider is an interface for providing empty interfaces for
|
||||||
|
// Discord events.
|
||||||
|
type EventInterfaceProvider interface {
|
||||||
|
// Type is the type of event this handler belongs to.
|
||||||
|
Type() string
|
||||||
|
|
||||||
|
// New returns a new instance of the struct this event handler handles.
|
||||||
|
// This is called once per event.
|
||||||
|
// The struct is provided to all handlers of the same Type().
|
||||||
|
New() interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// interfaceEventType is the event handler type for interface{} events.
|
||||||
|
const interfaceEventType = "__INTERFACE__"
|
||||||
|
|
||||||
|
// interfaceEventHandler is an event handler for interface{} events.
|
||||||
|
type interfaceEventHandler func(*Session, interface{})
|
||||||
|
|
||||||
|
// Type returns the event type for interface{} events.
|
||||||
|
func (eh interfaceEventHandler) Type() string {
|
||||||
|
return interfaceEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for an interface{} event.
|
||||||
|
func (eh interfaceEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
eh(s, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
var registeredInterfaceProviders = map[string]EventInterfaceProvider{}
|
||||||
|
|
||||||
|
// registerInterfaceProvider registers a provider so that DiscordGo can
|
||||||
|
// access it's New() method.
|
||||||
|
func registerInterfaceProvider(eh EventInterfaceProvider) error {
|
||||||
|
if _, ok := registeredInterfaceProviders[eh.Type()]; ok {
|
||||||
|
return fmt.Errorf("event %s already registered", eh.Type())
|
||||||
|
}
|
||||||
|
registeredInterfaceProviders[eh.Type()] = eh
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// eventHandlerInstance is a wrapper around an event handler, as functions
|
||||||
|
// cannot be compared directly.
|
||||||
|
type eventHandlerInstance struct {
|
||||||
|
eventHandler EventHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// addEventHandler adds an event handler that will be fired anytime
|
||||||
|
// the Discord WSAPI matching eventHandler.Type() fires.
|
||||||
|
func (s *Session) addEventHandler(eventHandler EventHandler) func() {
|
||||||
|
s.handlersMu.Lock()
|
||||||
|
defer s.handlersMu.Unlock()
|
||||||
|
|
||||||
|
if s.handlers == nil {
|
||||||
|
s.handlers = map[string][]*eventHandlerInstance{}
|
||||||
|
}
|
||||||
|
|
||||||
|
ehi := &eventHandlerInstance{eventHandler}
|
||||||
|
s.handlers[eventHandler.Type()] = append(s.handlers[eventHandler.Type()], ehi)
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
s.removeEventHandlerInstance(eventHandler.Type(), ehi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addEventHandler adds an event handler that will be fired the next time
|
||||||
|
// the Discord WSAPI matching eventHandler.Type() fires.
|
||||||
|
func (s *Session) addEventHandlerOnce(eventHandler EventHandler) func() {
|
||||||
|
s.handlersMu.Lock()
|
||||||
|
defer s.handlersMu.Unlock()
|
||||||
|
|
||||||
|
if s.onceHandlers == nil {
|
||||||
|
s.onceHandlers = map[string][]*eventHandlerInstance{}
|
||||||
|
}
|
||||||
|
|
||||||
|
ehi := &eventHandlerInstance{eventHandler}
|
||||||
|
s.onceHandlers[eventHandler.Type()] = append(s.onceHandlers[eventHandler.Type()], ehi)
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
s.removeEventHandlerInstance(eventHandler.Type(), ehi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddHandler allows you to add an event handler that will be fired anytime
|
||||||
|
// the Discord WSAPI event that matches the function fires.
|
||||||
|
// events.go contains all the Discord WSAPI events that can be fired.
|
||||||
|
// eg:
|
||||||
|
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// or:
|
||||||
|
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
|
||||||
|
// })
|
||||||
|
// The return value of this method is a function, that when called will remove the
|
||||||
|
// event handler.
|
||||||
|
func (s *Session) AddHandler(handler interface{}) func() {
|
||||||
|
eh := handlerForInterface(handler)
|
||||||
|
|
||||||
|
if eh == nil {
|
||||||
|
s.log(LogError, "Invalid handler type, handler will never be called")
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.addEventHandler(eh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddHandlerOnce allows you to add an event handler that will be fired the next time
|
||||||
|
// the Discord WSAPI event that matches the function fires.
|
||||||
|
// See AddHandler for more details.
|
||||||
|
func (s *Session) AddHandlerOnce(handler interface{}) func() {
|
||||||
|
eh := handlerForInterface(handler)
|
||||||
|
|
||||||
|
if eh == nil {
|
||||||
|
s.log(LogError, "Invalid handler type, handler will never be called")
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.addEventHandlerOnce(eh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeEventHandler instance removes an event handler instance.
|
||||||
|
func (s *Session) removeEventHandlerInstance(t string, ehi *eventHandlerInstance) {
|
||||||
|
s.handlersMu.Lock()
|
||||||
|
defer s.handlersMu.Unlock()
|
||||||
|
|
||||||
|
handlers := s.handlers[t]
|
||||||
|
for i := range handlers {
|
||||||
|
if handlers[i] == ehi {
|
||||||
|
s.handlers[t] = append(handlers[:i], handlers[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onceHandlers := s.onceHandlers[t]
|
||||||
|
for i := range onceHandlers {
|
||||||
|
if onceHandlers[i] == ehi {
|
||||||
|
s.onceHandlers[t] = append(onceHandlers[:i], handlers[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles calling permanent and once handlers for an event type.
|
||||||
|
func (s *Session) handle(t string, i interface{}) {
|
||||||
|
for _, eh := range s.handlers[t] {
|
||||||
|
go eh.eventHandler.Handle(s, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.onceHandlers[t]) > 0 {
|
||||||
|
for _, eh := range s.onceHandlers[t] {
|
||||||
|
go eh.eventHandler.Handle(s, i)
|
||||||
|
}
|
||||||
|
s.onceHandlers[t] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles an event type by calling internal methods, firing handlers and firing the
|
||||||
|
// interface{} event.
|
||||||
|
func (s *Session) handleEvent(t string, i interface{}) {
|
||||||
|
s.handlersMu.RLock()
|
||||||
|
defer s.handlersMu.RUnlock()
|
||||||
|
|
||||||
|
// All events are dispatched internally first.
|
||||||
|
s.onInterface(i)
|
||||||
|
|
||||||
|
// Then they are dispatched to anyone handling interface{} events.
|
||||||
|
s.handle(interfaceEventType, i)
|
||||||
|
|
||||||
|
// Finally they are dispatched to any typed handlers.
|
||||||
|
s.handle(t, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setGuildIds will set the GuildID on all the members of a guild.
|
||||||
|
// This is done as event data does not have it set.
|
||||||
|
func setGuildIds(g *Guild) {
|
||||||
|
for _, c := range g.Channels {
|
||||||
|
c.GuildID = g.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range g.Members {
|
||||||
|
m.GuildID = g.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, vs := range g.VoiceStates {
|
||||||
|
vs.GuildID = g.ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// onInterface handles all internal events and routes them to the appropriate internal handler.
|
||||||
|
func (s *Session) onInterface(i interface{}) {
|
||||||
|
switch t := i.(type) {
|
||||||
|
case *Ready:
|
||||||
|
for _, g := range t.Guilds {
|
||||||
|
setGuildIds(g)
|
||||||
|
}
|
||||||
|
s.onReady(t)
|
||||||
|
case *GuildCreate:
|
||||||
|
setGuildIds(t.Guild)
|
||||||
|
case *GuildUpdate:
|
||||||
|
setGuildIds(t.Guild)
|
||||||
|
case *Resumed:
|
||||||
|
s.onResumed(t)
|
||||||
|
case *VoiceServerUpdate:
|
||||||
|
go s.onVoiceServerUpdate(t)
|
||||||
|
case *VoiceStateUpdate:
|
||||||
|
go s.onVoiceStateUpdate(t)
|
||||||
|
}
|
||||||
|
s.State.onInterface(s, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// onReady handles the ready event.
|
||||||
|
func (s *Session) onReady(r *Ready) {
|
||||||
|
|
||||||
|
// Store the SessionID within the Session struct.
|
||||||
|
s.sessionID = r.SessionID
|
||||||
|
|
||||||
|
// Start the heartbeat to keep the connection alive.
|
||||||
|
go s.heartbeat(s.wsConn, s.listening, r.HeartbeatInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
// onResumed handles the resumed event.
|
||||||
|
func (s *Session) onResumed(r *Resumed) {
|
||||||
|
|
||||||
|
// Start the heartbeat to keep the connection alive.
|
||||||
|
go s.heartbeat(s.wsConn, s.listening, r.HeartbeatInterval)
|
||||||
|
}
|
977
eventhandlers.go
Normal file
977
eventhandlers.go
Normal file
|
@ -0,0 +1,977 @@
|
||||||
|
// Code generated by \"eventhandlers\"; DO NOT EDIT
|
||||||
|
// See events.go
|
||||||
|
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
// Following are all the event types.
|
||||||
|
// Event type values are used to match the events returned by Discord.
|
||||||
|
// EventTypes surrounded by __ are synthetic and are internal to DiscordGo.
|
||||||
|
const (
|
||||||
|
channelCreateEventType = "CHANNEL_CREATE"
|
||||||
|
channelDeleteEventType = "CHANNEL_DELETE"
|
||||||
|
channelPinsUpdateEventType = "CHANNEL_PINS_UPDATE"
|
||||||
|
channelUpdateEventType = "CHANNEL_UPDATE"
|
||||||
|
connectEventType = "__CONNECT__"
|
||||||
|
disconnectEventType = "__DISCONNECT__"
|
||||||
|
eventEventType = "__EVENT__"
|
||||||
|
guildBanAddEventType = "GUILD_BAN_ADD"
|
||||||
|
guildBanRemoveEventType = "GUILD_BAN_REMOVE"
|
||||||
|
guildCreateEventType = "GUILD_CREATE"
|
||||||
|
guildDeleteEventType = "GUILD_DELETE"
|
||||||
|
guildEmojisUpdateEventType = "GUILD_EMOJIS_UPDATE"
|
||||||
|
guildIntegrationsUpdateEventType = "GUILD_INTEGRATIONS_UPDATE"
|
||||||
|
guildMemberAddEventType = "GUILD_MEMBER_ADD"
|
||||||
|
guildMemberRemoveEventType = "GUILD_MEMBER_REMOVE"
|
||||||
|
guildMemberUpdateEventType = "GUILD_MEMBER_UPDATE"
|
||||||
|
guildMembersChunkEventType = "GUILD_MEMBERS_CHUNK"
|
||||||
|
guildRoleCreateEventType = "GUILD_ROLE_CREATE"
|
||||||
|
guildRoleDeleteEventType = "GUILD_ROLE_DELETE"
|
||||||
|
guildRoleUpdateEventType = "GUILD_ROLE_UPDATE"
|
||||||
|
guildUpdateEventType = "GUILD_UPDATE"
|
||||||
|
messageAckEventType = "MESSAGE_ACK"
|
||||||
|
messageCreateEventType = "MESSAGE_CREATE"
|
||||||
|
messageDeleteEventType = "MESSAGE_DELETE"
|
||||||
|
messageReactionAddEventType = "MESSAGE_REACTION_ADD"
|
||||||
|
messageReactionRemoveEventType = "MESSAGE_REACTION_REMOVE"
|
||||||
|
messageUpdateEventType = "MESSAGE_UPDATE"
|
||||||
|
presenceUpdateEventType = "PRESENCE_UPDATE"
|
||||||
|
presencesReplaceEventType = "PRESENCES_REPLACE"
|
||||||
|
rateLimitEventType = "__RATE_LIMIT__"
|
||||||
|
readyEventType = "READY"
|
||||||
|
relationshipAddEventType = "RELATIONSHIP_ADD"
|
||||||
|
relationshipRemoveEventType = "RELATIONSHIP_REMOVE"
|
||||||
|
resumedEventType = "RESUMED"
|
||||||
|
typingStartEventType = "TYPING_START"
|
||||||
|
userGuildSettingsUpdateEventType = "USER_GUILD_SETTINGS_UPDATE"
|
||||||
|
userSettingsUpdateEventType = "USER_SETTINGS_UPDATE"
|
||||||
|
userUpdateEventType = "USER_UPDATE"
|
||||||
|
voiceServerUpdateEventType = "VOICE_SERVER_UPDATE"
|
||||||
|
voiceStateUpdateEventType = "VOICE_STATE_UPDATE"
|
||||||
|
)
|
||||||
|
|
||||||
|
// channelCreateEventHandler is an event handler for ChannelCreate events.
|
||||||
|
type channelCreateEventHandler func(*Session, *ChannelCreate)
|
||||||
|
|
||||||
|
// Type returns the event type for ChannelCreate events.
|
||||||
|
func (eh channelCreateEventHandler) Type() string {
|
||||||
|
return channelCreateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of ChannelCreate.
|
||||||
|
func (eh channelCreateEventHandler) New() interface{} {
|
||||||
|
return &ChannelCreate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for ChannelCreate events.
|
||||||
|
func (eh channelCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*ChannelCreate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// channelDeleteEventHandler is an event handler for ChannelDelete events.
|
||||||
|
type channelDeleteEventHandler func(*Session, *ChannelDelete)
|
||||||
|
|
||||||
|
// Type returns the event type for ChannelDelete events.
|
||||||
|
func (eh channelDeleteEventHandler) Type() string {
|
||||||
|
return channelDeleteEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of ChannelDelete.
|
||||||
|
func (eh channelDeleteEventHandler) New() interface{} {
|
||||||
|
return &ChannelDelete{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for ChannelDelete events.
|
||||||
|
func (eh channelDeleteEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*ChannelDelete); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// channelPinsUpdateEventHandler is an event handler for ChannelPinsUpdate events.
|
||||||
|
type channelPinsUpdateEventHandler func(*Session, *ChannelPinsUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for ChannelPinsUpdate events.
|
||||||
|
func (eh channelPinsUpdateEventHandler) Type() string {
|
||||||
|
return channelPinsUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of ChannelPinsUpdate.
|
||||||
|
func (eh channelPinsUpdateEventHandler) New() interface{} {
|
||||||
|
return &ChannelPinsUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for ChannelPinsUpdate events.
|
||||||
|
func (eh channelPinsUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*ChannelPinsUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// channelUpdateEventHandler is an event handler for ChannelUpdate events.
|
||||||
|
type channelUpdateEventHandler func(*Session, *ChannelUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for ChannelUpdate events.
|
||||||
|
func (eh channelUpdateEventHandler) Type() string {
|
||||||
|
return channelUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of ChannelUpdate.
|
||||||
|
func (eh channelUpdateEventHandler) New() interface{} {
|
||||||
|
return &ChannelUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for ChannelUpdate events.
|
||||||
|
func (eh channelUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*ChannelUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// connectEventHandler is an event handler for Connect events.
|
||||||
|
type connectEventHandler func(*Session, *Connect)
|
||||||
|
|
||||||
|
// Type returns the event type for Connect events.
|
||||||
|
func (eh connectEventHandler) Type() string {
|
||||||
|
return connectEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of Connect.
|
||||||
|
func (eh connectEventHandler) New() interface{} {
|
||||||
|
return &Connect{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for Connect events.
|
||||||
|
func (eh connectEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*Connect); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// disconnectEventHandler is an event handler for Disconnect events.
|
||||||
|
type disconnectEventHandler func(*Session, *Disconnect)
|
||||||
|
|
||||||
|
// Type returns the event type for Disconnect events.
|
||||||
|
func (eh disconnectEventHandler) Type() string {
|
||||||
|
return disconnectEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of Disconnect.
|
||||||
|
func (eh disconnectEventHandler) New() interface{} {
|
||||||
|
return &Disconnect{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for Disconnect events.
|
||||||
|
func (eh disconnectEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*Disconnect); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// eventEventHandler is an event handler for Event events.
|
||||||
|
type eventEventHandler func(*Session, *Event)
|
||||||
|
|
||||||
|
// Type returns the event type for Event events.
|
||||||
|
func (eh eventEventHandler) Type() string {
|
||||||
|
return eventEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of Event.
|
||||||
|
func (eh eventEventHandler) New() interface{} {
|
||||||
|
return &Event{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for Event events.
|
||||||
|
func (eh eventEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*Event); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildBanAddEventHandler is an event handler for GuildBanAdd events.
|
||||||
|
type guildBanAddEventHandler func(*Session, *GuildBanAdd)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildBanAdd events.
|
||||||
|
func (eh guildBanAddEventHandler) Type() string {
|
||||||
|
return guildBanAddEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildBanAdd.
|
||||||
|
func (eh guildBanAddEventHandler) New() interface{} {
|
||||||
|
return &GuildBanAdd{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildBanAdd events.
|
||||||
|
func (eh guildBanAddEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildBanAdd); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildBanRemoveEventHandler is an event handler for GuildBanRemove events.
|
||||||
|
type guildBanRemoveEventHandler func(*Session, *GuildBanRemove)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildBanRemove events.
|
||||||
|
func (eh guildBanRemoveEventHandler) Type() string {
|
||||||
|
return guildBanRemoveEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildBanRemove.
|
||||||
|
func (eh guildBanRemoveEventHandler) New() interface{} {
|
||||||
|
return &GuildBanRemove{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildBanRemove events.
|
||||||
|
func (eh guildBanRemoveEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildBanRemove); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildCreateEventHandler is an event handler for GuildCreate events.
|
||||||
|
type guildCreateEventHandler func(*Session, *GuildCreate)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildCreate events.
|
||||||
|
func (eh guildCreateEventHandler) Type() string {
|
||||||
|
return guildCreateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildCreate.
|
||||||
|
func (eh guildCreateEventHandler) New() interface{} {
|
||||||
|
return &GuildCreate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildCreate events.
|
||||||
|
func (eh guildCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildCreate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildDeleteEventHandler is an event handler for GuildDelete events.
|
||||||
|
type guildDeleteEventHandler func(*Session, *GuildDelete)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildDelete events.
|
||||||
|
func (eh guildDeleteEventHandler) Type() string {
|
||||||
|
return guildDeleteEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildDelete.
|
||||||
|
func (eh guildDeleteEventHandler) New() interface{} {
|
||||||
|
return &GuildDelete{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildDelete events.
|
||||||
|
func (eh guildDeleteEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildDelete); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildEmojisUpdateEventHandler is an event handler for GuildEmojisUpdate events.
|
||||||
|
type guildEmojisUpdateEventHandler func(*Session, *GuildEmojisUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildEmojisUpdate events.
|
||||||
|
func (eh guildEmojisUpdateEventHandler) Type() string {
|
||||||
|
return guildEmojisUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildEmojisUpdate.
|
||||||
|
func (eh guildEmojisUpdateEventHandler) New() interface{} {
|
||||||
|
return &GuildEmojisUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildEmojisUpdate events.
|
||||||
|
func (eh guildEmojisUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildEmojisUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildIntegrationsUpdateEventHandler is an event handler for GuildIntegrationsUpdate events.
|
||||||
|
type guildIntegrationsUpdateEventHandler func(*Session, *GuildIntegrationsUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildIntegrationsUpdate events.
|
||||||
|
func (eh guildIntegrationsUpdateEventHandler) Type() string {
|
||||||
|
return guildIntegrationsUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildIntegrationsUpdate.
|
||||||
|
func (eh guildIntegrationsUpdateEventHandler) New() interface{} {
|
||||||
|
return &GuildIntegrationsUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildIntegrationsUpdate events.
|
||||||
|
func (eh guildIntegrationsUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildIntegrationsUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildMemberAddEventHandler is an event handler for GuildMemberAdd events.
|
||||||
|
type guildMemberAddEventHandler func(*Session, *GuildMemberAdd)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildMemberAdd events.
|
||||||
|
func (eh guildMemberAddEventHandler) Type() string {
|
||||||
|
return guildMemberAddEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildMemberAdd.
|
||||||
|
func (eh guildMemberAddEventHandler) New() interface{} {
|
||||||
|
return &GuildMemberAdd{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildMemberAdd events.
|
||||||
|
func (eh guildMemberAddEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildMemberAdd); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildMemberRemoveEventHandler is an event handler for GuildMemberRemove events.
|
||||||
|
type guildMemberRemoveEventHandler func(*Session, *GuildMemberRemove)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildMemberRemove events.
|
||||||
|
func (eh guildMemberRemoveEventHandler) Type() string {
|
||||||
|
return guildMemberRemoveEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildMemberRemove.
|
||||||
|
func (eh guildMemberRemoveEventHandler) New() interface{} {
|
||||||
|
return &GuildMemberRemove{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildMemberRemove events.
|
||||||
|
func (eh guildMemberRemoveEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildMemberRemove); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildMemberUpdateEventHandler is an event handler for GuildMemberUpdate events.
|
||||||
|
type guildMemberUpdateEventHandler func(*Session, *GuildMemberUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildMemberUpdate events.
|
||||||
|
func (eh guildMemberUpdateEventHandler) Type() string {
|
||||||
|
return guildMemberUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildMemberUpdate.
|
||||||
|
func (eh guildMemberUpdateEventHandler) New() interface{} {
|
||||||
|
return &GuildMemberUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildMemberUpdate events.
|
||||||
|
func (eh guildMemberUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildMemberUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildMembersChunkEventHandler is an event handler for GuildMembersChunk events.
|
||||||
|
type guildMembersChunkEventHandler func(*Session, *GuildMembersChunk)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildMembersChunk events.
|
||||||
|
func (eh guildMembersChunkEventHandler) Type() string {
|
||||||
|
return guildMembersChunkEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildMembersChunk.
|
||||||
|
func (eh guildMembersChunkEventHandler) New() interface{} {
|
||||||
|
return &GuildMembersChunk{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildMembersChunk events.
|
||||||
|
func (eh guildMembersChunkEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildMembersChunk); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildRoleCreateEventHandler is an event handler for GuildRoleCreate events.
|
||||||
|
type guildRoleCreateEventHandler func(*Session, *GuildRoleCreate)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildRoleCreate events.
|
||||||
|
func (eh guildRoleCreateEventHandler) Type() string {
|
||||||
|
return guildRoleCreateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildRoleCreate.
|
||||||
|
func (eh guildRoleCreateEventHandler) New() interface{} {
|
||||||
|
return &GuildRoleCreate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildRoleCreate events.
|
||||||
|
func (eh guildRoleCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildRoleCreate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildRoleDeleteEventHandler is an event handler for GuildRoleDelete events.
|
||||||
|
type guildRoleDeleteEventHandler func(*Session, *GuildRoleDelete)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildRoleDelete events.
|
||||||
|
func (eh guildRoleDeleteEventHandler) Type() string {
|
||||||
|
return guildRoleDeleteEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildRoleDelete.
|
||||||
|
func (eh guildRoleDeleteEventHandler) New() interface{} {
|
||||||
|
return &GuildRoleDelete{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildRoleDelete events.
|
||||||
|
func (eh guildRoleDeleteEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildRoleDelete); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildRoleUpdateEventHandler is an event handler for GuildRoleUpdate events.
|
||||||
|
type guildRoleUpdateEventHandler func(*Session, *GuildRoleUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildRoleUpdate events.
|
||||||
|
func (eh guildRoleUpdateEventHandler) Type() string {
|
||||||
|
return guildRoleUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildRoleUpdate.
|
||||||
|
func (eh guildRoleUpdateEventHandler) New() interface{} {
|
||||||
|
return &GuildRoleUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildRoleUpdate events.
|
||||||
|
func (eh guildRoleUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildRoleUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// guildUpdateEventHandler is an event handler for GuildUpdate events.
|
||||||
|
type guildUpdateEventHandler func(*Session, *GuildUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for GuildUpdate events.
|
||||||
|
func (eh guildUpdateEventHandler) Type() string {
|
||||||
|
return guildUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of GuildUpdate.
|
||||||
|
func (eh guildUpdateEventHandler) New() interface{} {
|
||||||
|
return &GuildUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for GuildUpdate events.
|
||||||
|
func (eh guildUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*GuildUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageAckEventHandler is an event handler for MessageAck events.
|
||||||
|
type messageAckEventHandler func(*Session, *MessageAck)
|
||||||
|
|
||||||
|
// Type returns the event type for MessageAck events.
|
||||||
|
func (eh messageAckEventHandler) Type() string {
|
||||||
|
return messageAckEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessageAck.
|
||||||
|
func (eh messageAckEventHandler) New() interface{} {
|
||||||
|
return &MessageAck{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessageAck events.
|
||||||
|
func (eh messageAckEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessageAck); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageCreateEventHandler is an event handler for MessageCreate events.
|
||||||
|
type messageCreateEventHandler func(*Session, *MessageCreate)
|
||||||
|
|
||||||
|
// Type returns the event type for MessageCreate events.
|
||||||
|
func (eh messageCreateEventHandler) Type() string {
|
||||||
|
return messageCreateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessageCreate.
|
||||||
|
func (eh messageCreateEventHandler) New() interface{} {
|
||||||
|
return &MessageCreate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessageCreate events.
|
||||||
|
func (eh messageCreateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessageCreate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageDeleteEventHandler is an event handler for MessageDelete events.
|
||||||
|
type messageDeleteEventHandler func(*Session, *MessageDelete)
|
||||||
|
|
||||||
|
// Type returns the event type for MessageDelete events.
|
||||||
|
func (eh messageDeleteEventHandler) Type() string {
|
||||||
|
return messageDeleteEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessageDelete.
|
||||||
|
func (eh messageDeleteEventHandler) New() interface{} {
|
||||||
|
return &MessageDelete{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessageDelete events.
|
||||||
|
func (eh messageDeleteEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessageDelete); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageReactionAddEventHandler is an event handler for MessageReactionAdd events.
|
||||||
|
type messageReactionAddEventHandler func(*Session, *MessageReactionAdd)
|
||||||
|
|
||||||
|
// Type returns the event type for MessageReactionAdd events.
|
||||||
|
func (eh messageReactionAddEventHandler) Type() string {
|
||||||
|
return messageReactionAddEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessageReactionAdd.
|
||||||
|
func (eh messageReactionAddEventHandler) New() interface{} {
|
||||||
|
return &MessageReactionAdd{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessageReactionAdd events.
|
||||||
|
func (eh messageReactionAddEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessageReactionAdd); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageReactionRemoveEventHandler is an event handler for MessageReactionRemove events.
|
||||||
|
type messageReactionRemoveEventHandler func(*Session, *MessageReactionRemove)
|
||||||
|
|
||||||
|
// Type returns the event type for MessageReactionRemove events.
|
||||||
|
func (eh messageReactionRemoveEventHandler) Type() string {
|
||||||
|
return messageReactionRemoveEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessageReactionRemove.
|
||||||
|
func (eh messageReactionRemoveEventHandler) New() interface{} {
|
||||||
|
return &MessageReactionRemove{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessageReactionRemove events.
|
||||||
|
func (eh messageReactionRemoveEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessageReactionRemove); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageUpdateEventHandler is an event handler for MessageUpdate events.
|
||||||
|
type messageUpdateEventHandler func(*Session, *MessageUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for MessageUpdate events.
|
||||||
|
func (eh messageUpdateEventHandler) Type() string {
|
||||||
|
return messageUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessageUpdate.
|
||||||
|
func (eh messageUpdateEventHandler) New() interface{} {
|
||||||
|
return &MessageUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessageUpdate events.
|
||||||
|
func (eh messageUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessageUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// presenceUpdateEventHandler is an event handler for PresenceUpdate events.
|
||||||
|
type presenceUpdateEventHandler func(*Session, *PresenceUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for PresenceUpdate events.
|
||||||
|
func (eh presenceUpdateEventHandler) Type() string {
|
||||||
|
return presenceUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of PresenceUpdate.
|
||||||
|
func (eh presenceUpdateEventHandler) New() interface{} {
|
||||||
|
return &PresenceUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for PresenceUpdate events.
|
||||||
|
func (eh presenceUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*PresenceUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// presencesReplaceEventHandler is an event handler for PresencesReplace events.
|
||||||
|
type presencesReplaceEventHandler func(*Session, *PresencesReplace)
|
||||||
|
|
||||||
|
// Type returns the event type for PresencesReplace events.
|
||||||
|
func (eh presencesReplaceEventHandler) Type() string {
|
||||||
|
return presencesReplaceEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of PresencesReplace.
|
||||||
|
func (eh presencesReplaceEventHandler) New() interface{} {
|
||||||
|
return &PresencesReplace{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for PresencesReplace events.
|
||||||
|
func (eh presencesReplaceEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*PresencesReplace); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rateLimitEventHandler is an event handler for RateLimit events.
|
||||||
|
type rateLimitEventHandler func(*Session, *RateLimit)
|
||||||
|
|
||||||
|
// Type returns the event type for RateLimit events.
|
||||||
|
func (eh rateLimitEventHandler) Type() string {
|
||||||
|
return rateLimitEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of RateLimit.
|
||||||
|
func (eh rateLimitEventHandler) New() interface{} {
|
||||||
|
return &RateLimit{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for RateLimit events.
|
||||||
|
func (eh rateLimitEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*RateLimit); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readyEventHandler is an event handler for Ready events.
|
||||||
|
type readyEventHandler func(*Session, *Ready)
|
||||||
|
|
||||||
|
// Type returns the event type for Ready events.
|
||||||
|
func (eh readyEventHandler) Type() string {
|
||||||
|
return readyEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of Ready.
|
||||||
|
func (eh readyEventHandler) New() interface{} {
|
||||||
|
return &Ready{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for Ready events.
|
||||||
|
func (eh readyEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*Ready); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// relationshipAddEventHandler is an event handler for RelationshipAdd events.
|
||||||
|
type relationshipAddEventHandler func(*Session, *RelationshipAdd)
|
||||||
|
|
||||||
|
// Type returns the event type for RelationshipAdd events.
|
||||||
|
func (eh relationshipAddEventHandler) Type() string {
|
||||||
|
return relationshipAddEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of RelationshipAdd.
|
||||||
|
func (eh relationshipAddEventHandler) New() interface{} {
|
||||||
|
return &RelationshipAdd{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for RelationshipAdd events.
|
||||||
|
func (eh relationshipAddEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*RelationshipAdd); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// relationshipRemoveEventHandler is an event handler for RelationshipRemove events.
|
||||||
|
type relationshipRemoveEventHandler func(*Session, *RelationshipRemove)
|
||||||
|
|
||||||
|
// Type returns the event type for RelationshipRemove events.
|
||||||
|
func (eh relationshipRemoveEventHandler) Type() string {
|
||||||
|
return relationshipRemoveEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of RelationshipRemove.
|
||||||
|
func (eh relationshipRemoveEventHandler) New() interface{} {
|
||||||
|
return &RelationshipRemove{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for RelationshipRemove events.
|
||||||
|
func (eh relationshipRemoveEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*RelationshipRemove); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resumedEventHandler is an event handler for Resumed events.
|
||||||
|
type resumedEventHandler func(*Session, *Resumed)
|
||||||
|
|
||||||
|
// Type returns the event type for Resumed events.
|
||||||
|
func (eh resumedEventHandler) Type() string {
|
||||||
|
return resumedEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of Resumed.
|
||||||
|
func (eh resumedEventHandler) New() interface{} {
|
||||||
|
return &Resumed{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for Resumed events.
|
||||||
|
func (eh resumedEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*Resumed); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// typingStartEventHandler is an event handler for TypingStart events.
|
||||||
|
type typingStartEventHandler func(*Session, *TypingStart)
|
||||||
|
|
||||||
|
// Type returns the event type for TypingStart events.
|
||||||
|
func (eh typingStartEventHandler) Type() string {
|
||||||
|
return typingStartEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of TypingStart.
|
||||||
|
func (eh typingStartEventHandler) New() interface{} {
|
||||||
|
return &TypingStart{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for TypingStart events.
|
||||||
|
func (eh typingStartEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*TypingStart); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// userGuildSettingsUpdateEventHandler is an event handler for UserGuildSettingsUpdate events.
|
||||||
|
type userGuildSettingsUpdateEventHandler func(*Session, *UserGuildSettingsUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for UserGuildSettingsUpdate events.
|
||||||
|
func (eh userGuildSettingsUpdateEventHandler) Type() string {
|
||||||
|
return userGuildSettingsUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of UserGuildSettingsUpdate.
|
||||||
|
func (eh userGuildSettingsUpdateEventHandler) New() interface{} {
|
||||||
|
return &UserGuildSettingsUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for UserGuildSettingsUpdate events.
|
||||||
|
func (eh userGuildSettingsUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*UserGuildSettingsUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// userSettingsUpdateEventHandler is an event handler for UserSettingsUpdate events.
|
||||||
|
type userSettingsUpdateEventHandler func(*Session, *UserSettingsUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for UserSettingsUpdate events.
|
||||||
|
func (eh userSettingsUpdateEventHandler) Type() string {
|
||||||
|
return userSettingsUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of UserSettingsUpdate.
|
||||||
|
func (eh userSettingsUpdateEventHandler) New() interface{} {
|
||||||
|
return &UserSettingsUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for UserSettingsUpdate events.
|
||||||
|
func (eh userSettingsUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*UserSettingsUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// userUpdateEventHandler is an event handler for UserUpdate events.
|
||||||
|
type userUpdateEventHandler func(*Session, *UserUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for UserUpdate events.
|
||||||
|
func (eh userUpdateEventHandler) Type() string {
|
||||||
|
return userUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of UserUpdate.
|
||||||
|
func (eh userUpdateEventHandler) New() interface{} {
|
||||||
|
return &UserUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for UserUpdate events.
|
||||||
|
func (eh userUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*UserUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// voiceServerUpdateEventHandler is an event handler for VoiceServerUpdate events.
|
||||||
|
type voiceServerUpdateEventHandler func(*Session, *VoiceServerUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for VoiceServerUpdate events.
|
||||||
|
func (eh voiceServerUpdateEventHandler) Type() string {
|
||||||
|
return voiceServerUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of VoiceServerUpdate.
|
||||||
|
func (eh voiceServerUpdateEventHandler) New() interface{} {
|
||||||
|
return &VoiceServerUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for VoiceServerUpdate events.
|
||||||
|
func (eh voiceServerUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*VoiceServerUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// voiceStateUpdateEventHandler is an event handler for VoiceStateUpdate events.
|
||||||
|
type voiceStateUpdateEventHandler func(*Session, *VoiceStateUpdate)
|
||||||
|
|
||||||
|
// Type returns the event type for VoiceStateUpdate events.
|
||||||
|
func (eh voiceStateUpdateEventHandler) Type() string {
|
||||||
|
return voiceStateUpdateEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of VoiceStateUpdate.
|
||||||
|
func (eh voiceStateUpdateEventHandler) New() interface{} {
|
||||||
|
return &VoiceStateUpdate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for VoiceStateUpdate events.
|
||||||
|
func (eh voiceStateUpdateEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*VoiceStateUpdate); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlerForInterface(handler interface{}) EventHandler {
|
||||||
|
switch v := handler.(type) {
|
||||||
|
case func(*Session, interface{}):
|
||||||
|
return interfaceEventHandler(v)
|
||||||
|
case func(*Session, *ChannelCreate):
|
||||||
|
return channelCreateEventHandler(v)
|
||||||
|
case func(*Session, *ChannelDelete):
|
||||||
|
return channelDeleteEventHandler(v)
|
||||||
|
case func(*Session, *ChannelPinsUpdate):
|
||||||
|
return channelPinsUpdateEventHandler(v)
|
||||||
|
case func(*Session, *ChannelUpdate):
|
||||||
|
return channelUpdateEventHandler(v)
|
||||||
|
case func(*Session, *Connect):
|
||||||
|
return connectEventHandler(v)
|
||||||
|
case func(*Session, *Disconnect):
|
||||||
|
return disconnectEventHandler(v)
|
||||||
|
case func(*Session, *Event):
|
||||||
|
return eventEventHandler(v)
|
||||||
|
case func(*Session, *GuildBanAdd):
|
||||||
|
return guildBanAddEventHandler(v)
|
||||||
|
case func(*Session, *GuildBanRemove):
|
||||||
|
return guildBanRemoveEventHandler(v)
|
||||||
|
case func(*Session, *GuildCreate):
|
||||||
|
return guildCreateEventHandler(v)
|
||||||
|
case func(*Session, *GuildDelete):
|
||||||
|
return guildDeleteEventHandler(v)
|
||||||
|
case func(*Session, *GuildEmojisUpdate):
|
||||||
|
return guildEmojisUpdateEventHandler(v)
|
||||||
|
case func(*Session, *GuildIntegrationsUpdate):
|
||||||
|
return guildIntegrationsUpdateEventHandler(v)
|
||||||
|
case func(*Session, *GuildMemberAdd):
|
||||||
|
return guildMemberAddEventHandler(v)
|
||||||
|
case func(*Session, *GuildMemberRemove):
|
||||||
|
return guildMemberRemoveEventHandler(v)
|
||||||
|
case func(*Session, *GuildMemberUpdate):
|
||||||
|
return guildMemberUpdateEventHandler(v)
|
||||||
|
case func(*Session, *GuildMembersChunk):
|
||||||
|
return guildMembersChunkEventHandler(v)
|
||||||
|
case func(*Session, *GuildRoleCreate):
|
||||||
|
return guildRoleCreateEventHandler(v)
|
||||||
|
case func(*Session, *GuildRoleDelete):
|
||||||
|
return guildRoleDeleteEventHandler(v)
|
||||||
|
case func(*Session, *GuildRoleUpdate):
|
||||||
|
return guildRoleUpdateEventHandler(v)
|
||||||
|
case func(*Session, *GuildUpdate):
|
||||||
|
return guildUpdateEventHandler(v)
|
||||||
|
case func(*Session, *MessageAck):
|
||||||
|
return messageAckEventHandler(v)
|
||||||
|
case func(*Session, *MessageCreate):
|
||||||
|
return messageCreateEventHandler(v)
|
||||||
|
case func(*Session, *MessageDelete):
|
||||||
|
return messageDeleteEventHandler(v)
|
||||||
|
case func(*Session, *MessageReactionAdd):
|
||||||
|
return messageReactionAddEventHandler(v)
|
||||||
|
case func(*Session, *MessageReactionRemove):
|
||||||
|
return messageReactionRemoveEventHandler(v)
|
||||||
|
case func(*Session, *MessageUpdate):
|
||||||
|
return messageUpdateEventHandler(v)
|
||||||
|
case func(*Session, *PresenceUpdate):
|
||||||
|
return presenceUpdateEventHandler(v)
|
||||||
|
case func(*Session, *PresencesReplace):
|
||||||
|
return presencesReplaceEventHandler(v)
|
||||||
|
case func(*Session, *RateLimit):
|
||||||
|
return rateLimitEventHandler(v)
|
||||||
|
case func(*Session, *Ready):
|
||||||
|
return readyEventHandler(v)
|
||||||
|
case func(*Session, *RelationshipAdd):
|
||||||
|
return relationshipAddEventHandler(v)
|
||||||
|
case func(*Session, *RelationshipRemove):
|
||||||
|
return relationshipRemoveEventHandler(v)
|
||||||
|
case func(*Session, *Resumed):
|
||||||
|
return resumedEventHandler(v)
|
||||||
|
case func(*Session, *TypingStart):
|
||||||
|
return typingStartEventHandler(v)
|
||||||
|
case func(*Session, *UserGuildSettingsUpdate):
|
||||||
|
return userGuildSettingsUpdateEventHandler(v)
|
||||||
|
case func(*Session, *UserSettingsUpdate):
|
||||||
|
return userSettingsUpdateEventHandler(v)
|
||||||
|
case func(*Session, *UserUpdate):
|
||||||
|
return userUpdateEventHandler(v)
|
||||||
|
case func(*Session, *VoiceServerUpdate):
|
||||||
|
return voiceServerUpdateEventHandler(v)
|
||||||
|
case func(*Session, *VoiceStateUpdate):
|
||||||
|
return voiceStateUpdateEventHandler(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func init() {
|
||||||
|
registerInterfaceProvider(channelCreateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(channelDeleteEventHandler(nil))
|
||||||
|
registerInterfaceProvider(channelPinsUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(channelUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildBanAddEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildBanRemoveEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildCreateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildDeleteEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildEmojisUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildIntegrationsUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildMemberAddEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildMemberRemoveEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildMemberUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildMembersChunkEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildRoleCreateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildRoleDeleteEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildRoleUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(guildUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messageAckEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messageCreateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messageDeleteEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messageReactionAddEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messageReactionRemoveEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messageUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(presenceUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(presencesReplaceEventHandler(nil))
|
||||||
|
registerInterfaceProvider(readyEventHandler(nil))
|
||||||
|
registerInterfaceProvider(relationshipAddEventHandler(nil))
|
||||||
|
registerInterfaceProvider(relationshipRemoveEventHandler(nil))
|
||||||
|
registerInterfaceProvider(resumedEventHandler(nil))
|
||||||
|
registerInterfaceProvider(typingStartEventHandler(nil))
|
||||||
|
registerInterfaceProvider(userGuildSettingsUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(userSettingsUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(userUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(voiceServerUpdateEventHandler(nil))
|
||||||
|
registerInterfaceProvider(voiceStateUpdateEventHandler(nil))
|
||||||
|
}
|
243
events.go
243
events.go
|
@ -1,159 +1,238 @@
|
||||||
package discordgo
|
package discordgo
|
||||||
|
|
||||||
// eventToInterface is a mapping of Discord WSAPI events to their
|
import (
|
||||||
// DiscordGo event container.
|
"encoding/json"
|
||||||
// Each Discord WSAPI event maps to a unique interface.
|
"time"
|
||||||
// Use Session.AddHandler with one of these types to handle that
|
)
|
||||||
// type of event.
|
|
||||||
// eg:
|
|
||||||
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// or:
|
|
||||||
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
|
|
||||||
// })
|
|
||||||
var eventToInterface = map[string]interface{}{
|
|
||||||
"CHANNEL_CREATE": ChannelCreate{},
|
|
||||||
"CHANNEL_UPDATE": ChannelUpdate{},
|
|
||||||
"CHANNEL_DELETE": ChannelDelete{},
|
|
||||||
"GUILD_CREATE": GuildCreate{},
|
|
||||||
"GUILD_UPDATE": GuildUpdate{},
|
|
||||||
"GUILD_DELETE": GuildDelete{},
|
|
||||||
"GUILD_BAN_ADD": GuildBanAdd{},
|
|
||||||
"GUILD_BAN_REMOVE": GuildBanRemove{},
|
|
||||||
"GUILD_MEMBER_ADD": GuildMemberAdd{},
|
|
||||||
"GUILD_MEMBER_UPDATE": GuildMemberUpdate{},
|
|
||||||
"GUILD_MEMBER_REMOVE": GuildMemberRemove{},
|
|
||||||
"GUILD_ROLE_CREATE": GuildRoleCreate{},
|
|
||||||
"GUILD_ROLE_UPDATE": GuildRoleUpdate{},
|
|
||||||
"GUILD_ROLE_DELETE": GuildRoleDelete{},
|
|
||||||
"GUILD_INTEGRATIONS_UPDATE": GuildIntegrationsUpdate{},
|
|
||||||
"GUILD_EMOJIS_UPDATE": GuildEmojisUpdate{},
|
|
||||||
"MESSAGE_ACK": MessageAck{},
|
|
||||||
"MESSAGE_CREATE": MessageCreate{},
|
|
||||||
"MESSAGE_UPDATE": MessageUpdate{},
|
|
||||||
"MESSAGE_DELETE": MessageDelete{},
|
|
||||||
"PRESENCE_UPDATE": PresenceUpdate{},
|
|
||||||
"PRESENCES_REPLACE": PresencesReplace{},
|
|
||||||
"READY": Ready{},
|
|
||||||
"USER_UPDATE": UserUpdate{},
|
|
||||||
"USER_SETTINGS_UPDATE": UserSettingsUpdate{},
|
|
||||||
"USER_GUILD_SETTINGS_UPDATE": UserGuildSettingsUpdate{},
|
|
||||||
"TYPING_START": TypingStart{},
|
|
||||||
"VOICE_SERVER_UPDATE": VoiceServerUpdate{},
|
|
||||||
"VOICE_STATE_UPDATE": VoiceStateUpdate{},
|
|
||||||
"RESUMED": Resumed{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect is an empty struct for an event.
|
// This file contains all the possible structs that can be
|
||||||
|
// handled by AddHandler/EventHandler.
|
||||||
|
// DO NOT ADD ANYTHING BUT EVENT HANDLER STRUCTS TO THIS FILE.
|
||||||
|
//go:generate go run tools/cmd/eventhandlers/main.go
|
||||||
|
|
||||||
|
// Connect is the data for a Connect event.
|
||||||
|
// This is a sythetic event and is not dispatched by Discord.
|
||||||
type Connect struct{}
|
type Connect struct{}
|
||||||
|
|
||||||
// Disconnect is an empty struct for an event.
|
// Disconnect is the data for a Disconnect event.
|
||||||
|
// This is a sythetic event and is not dispatched by Discord.
|
||||||
type Disconnect struct{}
|
type Disconnect struct{}
|
||||||
|
|
||||||
// RateLimit is a struct for the RateLimited event
|
// RateLimit is the data for a RateLimit event.
|
||||||
|
// This is a sythetic event and is not dispatched by Discord.
|
||||||
type RateLimit struct {
|
type RateLimit struct {
|
||||||
*TooManyRequests
|
*TooManyRequests
|
||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageCreate is a wrapper struct for an event.
|
// Event provides a basic initial struct for all websocket events.
|
||||||
type MessageCreate struct {
|
type Event struct {
|
||||||
*Message
|
Operation int `json:"op"`
|
||||||
|
Sequence int `json:"s"`
|
||||||
|
Type string `json:"t"`
|
||||||
|
RawData json.RawMessage `json:"d"`
|
||||||
|
// Struct contains one of the other types in this file.
|
||||||
|
Struct interface{} `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageUpdate is a wrapper struct for an event.
|
// A Ready stores all data for the websocket READY event.
|
||||||
type MessageUpdate struct {
|
type Ready struct {
|
||||||
*Message
|
Version int `json:"v"`
|
||||||
|
SessionID string `json:"session_id"`
|
||||||
|
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
||||||
|
User *User `json:"user"`
|
||||||
|
ReadState []*ReadState `json:"read_state"`
|
||||||
|
PrivateChannels []*Channel `json:"private_channels"`
|
||||||
|
Guilds []*Guild `json:"guilds"`
|
||||||
|
|
||||||
|
// Undocumented fields
|
||||||
|
Settings *Settings `json:"user_settings"`
|
||||||
|
UserGuildSettings []*UserGuildSettings `json:"user_guild_settings"`
|
||||||
|
Relationships []*Relationship `json:"relationships"`
|
||||||
|
Presences []*Presence `json:"presences"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageDelete is a wrapper struct for an event.
|
// ChannelCreate is the data for a ChannelCreate event.
|
||||||
type MessageDelete struct {
|
|
||||||
*Message
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChannelCreate is a wrapper struct for an event.
|
|
||||||
type ChannelCreate struct {
|
type ChannelCreate struct {
|
||||||
*Channel
|
*Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelUpdate is a wrapper struct for an event.
|
// ChannelUpdate is the data for a ChannelUpdate event.
|
||||||
type ChannelUpdate struct {
|
type ChannelUpdate struct {
|
||||||
*Channel
|
*Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelDelete is a wrapper struct for an event.
|
// ChannelDelete is the data for a ChannelDelete event.
|
||||||
type ChannelDelete struct {
|
type ChannelDelete struct {
|
||||||
*Channel
|
*Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildCreate is a wrapper struct for an event.
|
// ChannelPinsUpdate stores data for a ChannelPinsUpdate event.
|
||||||
|
type ChannelPinsUpdate struct {
|
||||||
|
LastPinTimestamp string `json:"last_pin_timestamp"`
|
||||||
|
ChannelID string `json:"channel_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GuildCreate is the data for a GuildCreate event.
|
||||||
type GuildCreate struct {
|
type GuildCreate struct {
|
||||||
*Guild
|
*Guild
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildUpdate is a wrapper struct for an event.
|
// GuildUpdate is the data for a GuildUpdate event.
|
||||||
type GuildUpdate struct {
|
type GuildUpdate struct {
|
||||||
*Guild
|
*Guild
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildDelete is a wrapper struct for an event.
|
// GuildDelete is the data for a GuildDelete event.
|
||||||
type GuildDelete struct {
|
type GuildDelete struct {
|
||||||
*Guild
|
*Guild
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildBanAdd is a wrapper struct for an event.
|
// GuildBanAdd is the data for a GuildBanAdd event.
|
||||||
type GuildBanAdd struct {
|
type GuildBanAdd struct {
|
||||||
*GuildBan
|
User *User `json:"user"`
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildBanRemove is a wrapper struct for an event.
|
// GuildBanRemove is the data for a GuildBanRemove event.
|
||||||
type GuildBanRemove struct {
|
type GuildBanRemove struct {
|
||||||
*GuildBan
|
User *User `json:"user"`
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildMemberAdd is a wrapper struct for an event.
|
// GuildMemberAdd is the data for a GuildMemberAdd event.
|
||||||
type GuildMemberAdd struct {
|
type GuildMemberAdd struct {
|
||||||
*Member
|
*Member
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildMemberUpdate is a wrapper struct for an event.
|
// GuildMemberUpdate is the data for a GuildMemberUpdate event.
|
||||||
type GuildMemberUpdate struct {
|
type GuildMemberUpdate struct {
|
||||||
*Member
|
*Member
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildMemberRemove is a wrapper struct for an event.
|
// GuildMemberRemove is the data for a GuildMemberRemove event.
|
||||||
type GuildMemberRemove struct {
|
type GuildMemberRemove struct {
|
||||||
*Member
|
*Member
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildRoleCreate is a wrapper struct for an event.
|
// GuildRoleCreate is the data for a GuildRoleCreate event.
|
||||||
type GuildRoleCreate struct {
|
type GuildRoleCreate struct {
|
||||||
*GuildRole
|
*GuildRole
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildRoleUpdate is a wrapper struct for an event.
|
// GuildRoleUpdate is the data for a GuildRoleUpdate event.
|
||||||
type GuildRoleUpdate struct {
|
type GuildRoleUpdate struct {
|
||||||
*GuildRole
|
*GuildRole
|
||||||
}
|
}
|
||||||
|
|
||||||
// PresencesReplace is an array of Presences for an event.
|
// A GuildRoleDelete is the data for a GuildRoleDelete event.
|
||||||
type PresencesReplace []*Presence
|
type GuildRoleDelete struct {
|
||||||
|
RoleID string `json:"role_id"`
|
||||||
// VoiceStateUpdate is a wrapper struct for an event.
|
GuildID string `json:"guild_id"`
|
||||||
type VoiceStateUpdate struct {
|
|
||||||
*VoiceState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserUpdate is a wrapper struct for an event.
|
// A GuildEmojisUpdate is the data for a guild emoji update event.
|
||||||
|
type GuildEmojisUpdate struct {
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
Emojis []*Emoji `json:"emojis"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A GuildMembersChunk is the data for a GuildMembersChunk event.
|
||||||
|
type GuildMembersChunk struct {
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
Members []*Member `json:"members"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GuildIntegrationsUpdate is the data for a GuildIntegrationsUpdate event.
|
||||||
|
type GuildIntegrationsUpdate struct {
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageAck is the data for a MessageAck event.
|
||||||
|
type MessageAck struct {
|
||||||
|
MessageID string `json:"message_id"`
|
||||||
|
ChannelID string `json:"channel_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageCreate is the data for a MessageCreate event.
|
||||||
|
type MessageCreate struct {
|
||||||
|
*Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageUpdate is the data for a MessageUpdate event.
|
||||||
|
type MessageUpdate struct {
|
||||||
|
*Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageDelete is the data for a MessageDelete event.
|
||||||
|
type MessageDelete struct {
|
||||||
|
*Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReactionAdd is the data for a MessageReactionAdd event.
|
||||||
|
type MessageReactionAdd struct {
|
||||||
|
*MessageReaction
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReactionRemove is the data for a MessageReactionRemove event.
|
||||||
|
type MessageReactionRemove struct {
|
||||||
|
*MessageReaction
|
||||||
|
}
|
||||||
|
|
||||||
|
// PresencesReplace is the data for a PresencesReplace event.
|
||||||
|
type PresencesReplace []*Presence
|
||||||
|
|
||||||
|
// PresenceUpdate is the data for a PresenceUpdate event.
|
||||||
|
type PresenceUpdate struct {
|
||||||
|
Presence
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
Roles []string `json:"roles"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resumed is the data for a Resumed event.
|
||||||
|
type Resumed struct {
|
||||||
|
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
||||||
|
Trace []string `json:"_trace"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RelationshipAdd is the data for a RelationshipAdd event.
|
||||||
|
type RelationshipAdd struct {
|
||||||
|
*Relationship
|
||||||
|
}
|
||||||
|
|
||||||
|
// RelationshipRemove is the data for a RelationshipRemove event.
|
||||||
|
type RelationshipRemove struct {
|
||||||
|
*Relationship
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypingStart is the data for a TypingStart event.
|
||||||
|
type TypingStart struct {
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
ChannelID string `json:"channel_id"`
|
||||||
|
Timestamp int `json:"timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserUpdate is the data for a UserUpdate event.
|
||||||
type UserUpdate struct {
|
type UserUpdate struct {
|
||||||
*User
|
*User
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserSettingsUpdate is a map for an event.
|
// UserSettingsUpdate is the data for a UserSettingsUpdate event.
|
||||||
type UserSettingsUpdate map[string]interface{}
|
type UserSettingsUpdate map[string]interface{}
|
||||||
|
|
||||||
// UserGuildSettingsUpdate is a map for an event.
|
// UserGuildSettingsUpdate is the data for a UserGuildSettingsUpdate event.
|
||||||
type UserGuildSettingsUpdate struct {
|
type UserGuildSettingsUpdate struct {
|
||||||
*UserGuildSettings
|
*UserGuildSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VoiceServerUpdate is the data for a VoiceServerUpdate event.
|
||||||
|
type VoiceServerUpdate struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
Endpoint string `json:"endpoint"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VoiceStateUpdate is the data for a VoiceStateUpdate event.
|
||||||
|
type VoiceStateUpdate struct {
|
||||||
|
*VoiceState
|
||||||
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||||
// This function will be called (due to AddHandler above) every time a new
|
// This function will be called (due to AddHandler above) every time a new
|
||||||
// guild is joined.
|
// guild is joined.
|
||||||
func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) {
|
func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) {
|
||||||
if event.Guild.Unavailable != nil {
|
if event.Guild.Unavailable {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +131,10 @@ func loadSound() error {
|
||||||
|
|
||||||
// If this is the end of the file, just return.
|
// If this is the end of the file, just return.
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||||
|
file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
100
message.go
100
message.go
|
@ -19,8 +19,8 @@ type Message struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
ChannelID string `json:"channel_id"`
|
ChannelID string `json:"channel_id"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Timestamp string `json:"timestamp"`
|
Timestamp Timestamp `json:"timestamp"`
|
||||||
EditedTimestamp string `json:"edited_timestamp"`
|
EditedTimestamp Timestamp `json:"edited_timestamp"`
|
||||||
MentionRoles []string `json:"mention_roles"`
|
MentionRoles []string `json:"mention_roles"`
|
||||||
Tts bool `json:"tts"`
|
Tts bool `json:"tts"`
|
||||||
MentionEveryone bool `json:"mention_everyone"`
|
MentionEveryone bool `json:"mention_everyone"`
|
||||||
|
@ -28,6 +28,7 @@ type Message struct {
|
||||||
Attachments []*MessageAttachment `json:"attachments"`
|
Attachments []*MessageAttachment `json:"attachments"`
|
||||||
Embeds []*MessageEmbed `json:"embeds"`
|
Embeds []*MessageEmbed `json:"embeds"`
|
||||||
Mentions []*User `json:"mentions"`
|
Mentions []*User `json:"mentions"`
|
||||||
|
Reactions []*MessageReactions `json:"reactions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A MessageAttachment stores data for message attachments.
|
// A MessageAttachment stores data for message attachments.
|
||||||
|
@ -41,31 +42,80 @@ type MessageAttachment struct {
|
||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MessageEmbedFooter is a part of a MessageEmbed struct.
|
||||||
|
type MessageEmbedFooter struct {
|
||||||
|
Text string `json:"text,omitempty"`
|
||||||
|
IconURL string `json:"icon_url,omitempty"`
|
||||||
|
ProxyIconURL string `json:"proxy_icon_url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageEmbedImage is a part of a MessageEmbed struct.
|
||||||
|
type MessageEmbedImage struct {
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
ProxyURL string `json:"proxy_url,omitempty"`
|
||||||
|
Width int `json:"width,omitempty"`
|
||||||
|
Height int `json:"height,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageEmbedThumbnail is a part of a MessageEmbed struct.
|
||||||
|
type MessageEmbedThumbnail struct {
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
ProxyURL string `json:"proxy_url,omitempty"`
|
||||||
|
Width int `json:"width,omitempty"`
|
||||||
|
Height int `json:"height,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageEmbedVideo is a part of a MessageEmbed struct.
|
||||||
|
type MessageEmbedVideo struct {
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
ProxyURL string `json:"proxy_url,omitempty"`
|
||||||
|
Width int `json:"width,omitempty"`
|
||||||
|
Height int `json:"height,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageEmbedProvider is a part of a MessageEmbed struct.
|
||||||
|
type MessageEmbedProvider struct {
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageEmbedAuthor is a part of a MessageEmbed struct.
|
||||||
|
type MessageEmbedAuthor struct {
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
IconURL string `json:"icon_url,omitempty"`
|
||||||
|
ProxyIconURL string `json:"proxy_icon_url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageEmbedField is a part of a MessageEmbed struct.
|
||||||
|
type MessageEmbedField struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
Inline bool `json:"inline,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// An MessageEmbed stores data for message embeds.
|
// An MessageEmbed stores data for message embeds.
|
||||||
type MessageEmbed struct {
|
type MessageEmbed struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url,omitempty"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type,omitempty"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title,omitempty"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description,omitempty"`
|
||||||
Thumbnail *struct {
|
Timestamp string `json:"timestamp,omitempty"`
|
||||||
URL string `json:"url"`
|
Color int `json:"color,omitempty"`
|
||||||
ProxyURL string `json:"proxy_url"`
|
Footer *MessageEmbedFooter `json:"footer,omitempty"`
|
||||||
Width int `json:"width"`
|
Image *MessageEmbedImage `json:"image,omitempty"`
|
||||||
Height int `json:"height"`
|
Thumbnail *MessageEmbedThumbnail `json:"thumbnail,omitempty"`
|
||||||
} `json:"thumbnail"`
|
Video *MessageEmbedVideo `json:"video,omitempty"`
|
||||||
Provider *struct {
|
Provider *MessageEmbedProvider `json:"provider,omitempty"`
|
||||||
URL string `json:"url"`
|
Author *MessageEmbedAuthor `json:"author,omitempty"`
|
||||||
Name string `json:"name"`
|
Fields []*MessageEmbedField `json:"fields,omitempty"`
|
||||||
} `json:"provider"`
|
}
|
||||||
Author *struct {
|
|
||||||
URL string `json:"url"`
|
// MessageReactions holds a reactions object for a message.
|
||||||
Name string `json:"name"`
|
type MessageReactions struct {
|
||||||
} `json:"author"`
|
Count int `json:"count"`
|
||||||
Video *struct {
|
Me bool `json:"me"`
|
||||||
URL string `json:"url"`
|
Emoji *Emoji `json:"emoji"`
|
||||||
Width int `json:"width"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
} `json:"video"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContentWithMentionsReplaced will replace all @<id> mentions with the
|
// ContentWithMentionsReplaced will replace all @<id> mentions with the
|
||||||
|
|
13
oauth2.go
13
oauth2.go
|
@ -21,13 +21,14 @@ type Application struct {
|
||||||
Icon string `json:"icon,omitempty"`
|
Icon string `json:"icon,omitempty"`
|
||||||
Secret string `json:"secret,omitempty"`
|
Secret string `json:"secret,omitempty"`
|
||||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
||||||
|
Owner *User `json:"owner"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Application returns an Application structure of a specific Application
|
// Application returns an Application structure of a specific Application
|
||||||
// appID : The ID of an Application
|
// appID : The ID of an Application
|
||||||
func (s *Session) Application(appID string) (st *Application, err error) {
|
func (s *Session) Application(appID string) (st *Application, err error) {
|
||||||
|
|
||||||
body, err := s.Request("GET", EndpointApplication(appID), nil)
|
body, err := s.RequestWithBucketID("GET", EndpointApplication(appID), nil, EndpointApplication(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -39,7 +40,7 @@ func (s *Session) Application(appID string) (st *Application, err error) {
|
||||||
// Applications returns all applications for the authenticated user
|
// Applications returns all applications for the authenticated user
|
||||||
func (s *Session) Applications() (st []*Application, err error) {
|
func (s *Session) Applications() (st []*Application, err error) {
|
||||||
|
|
||||||
body, err := s.Request("GET", EndpointApplications, nil)
|
body, err := s.RequestWithBucketID("GET", EndpointApplications, nil, EndpointApplications)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -59,7 +60,7 @@ func (s *Session) ApplicationCreate(ap *Application) (st *Application, err error
|
||||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
||||||
}{ap.Name, ap.Description, ap.RedirectURIs}
|
}{ap.Name, ap.Description, ap.RedirectURIs}
|
||||||
|
|
||||||
body, err := s.Request("POST", EndpointApplications, data)
|
body, err := s.RequestWithBucketID("POST", EndpointApplications, data, EndpointApplications)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ func (s *Session) ApplicationUpdate(appID string, ap *Application) (st *Applicat
|
||||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
RedirectURIs *[]string `json:"redirect_uris,omitempty"`
|
||||||
}{ap.Name, ap.Description, ap.RedirectURIs}
|
}{ap.Name, ap.Description, ap.RedirectURIs}
|
||||||
|
|
||||||
body, err := s.Request("PUT", EndpointApplication(appID), data)
|
body, err := s.RequestWithBucketID("PUT", EndpointApplication(appID), data, EndpointApplication(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,7 @@ func (s *Session) ApplicationUpdate(appID string, ap *Application) (st *Applicat
|
||||||
// appID : The ID of an Application
|
// appID : The ID of an Application
|
||||||
func (s *Session) ApplicationDelete(appID string) (err error) {
|
func (s *Session) ApplicationDelete(appID string) (err error) {
|
||||||
|
|
||||||
_, err = s.Request("DELETE", EndpointApplication(appID), nil)
|
_, err = s.RequestWithBucketID("DELETE", EndpointApplication(appID), nil, EndpointApplication(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -110,7 +111,7 @@ func (s *Session) ApplicationDelete(appID string) (err error) {
|
||||||
// NOTE: func name may change, if I can think up something better.
|
// NOTE: func name may change, if I can think up something better.
|
||||||
func (s *Session) ApplicationBotCreate(appID string) (st *User, err error) {
|
func (s *Session) ApplicationBotCreate(appID string) (st *User, err error) {
|
||||||
|
|
||||||
body, err := s.Request("POST", EndpointApplicationsBot(appID), nil)
|
body, err := s.RequestWithBucketID("POST", EndpointApplicationsBot(appID), nil, EndpointApplicationsBot(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
157
ratelimit.go
Normal file
157
ratelimit.go
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RateLimiter holds all ratelimit buckets
|
||||||
|
type RateLimiter struct {
|
||||||
|
sync.Mutex
|
||||||
|
global *Bucket
|
||||||
|
buckets map[string]*Bucket
|
||||||
|
globalRateLimit time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRatelimiter returns a new RateLimiter
|
||||||
|
func NewRatelimiter() *RateLimiter {
|
||||||
|
|
||||||
|
return &RateLimiter{
|
||||||
|
buckets: make(map[string]*Bucket),
|
||||||
|
global: &Bucket{Key: "global"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getBucket retrieves or creates a bucket
|
||||||
|
func (r *RateLimiter) getBucket(key string) *Bucket {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
if bucket, ok := r.buckets[key]; ok {
|
||||||
|
return bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &Bucket{
|
||||||
|
remaining: 1,
|
||||||
|
Key: key,
|
||||||
|
global: r.global,
|
||||||
|
}
|
||||||
|
|
||||||
|
r.buckets[key] = b
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// LockBucket Locks until a request can be made
|
||||||
|
func (r *RateLimiter) LockBucket(bucketID string) *Bucket {
|
||||||
|
|
||||||
|
b := r.getBucket(bucketID)
|
||||||
|
|
||||||
|
b.Lock()
|
||||||
|
|
||||||
|
// 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
|
||||||
|
if b.remaining < 1 && b.reset.After(time.Now()) {
|
||||||
|
time.Sleep(b.reset.Sub(time.Now()))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for global ratelimits
|
||||||
|
r.global.Lock()
|
||||||
|
r.global.Unlock()
|
||||||
|
|
||||||
|
b.remaining--
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucket represents a ratelimit bucket, each bucket gets ratelimited individually (-global ratelimits)
|
||||||
|
type Bucket struct {
|
||||||
|
sync.Mutex
|
||||||
|
Key string
|
||||||
|
remaining int
|
||||||
|
limit int
|
||||||
|
reset time.Time
|
||||||
|
global *Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func (b *Bucket) Release(headers http.Header) error {
|
||||||
|
|
||||||
|
defer b.Unlock()
|
||||||
|
if headers == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining := headers.Get("X-RateLimit-Remaining")
|
||||||
|
reset := headers.Get("X-RateLimit-Reset")
|
||||||
|
global := headers.Get("X-RateLimit-Global")
|
||||||
|
retryAfter := headers.Get("Retry-After")
|
||||||
|
|
||||||
|
// If it's global just keep the main ratelimit mutex locked
|
||||||
|
if global != "" {
|
||||||
|
parsedAfter, err := strconv.Atoi(retryAfter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock it in a new goroutine so that this isn't a blocking call
|
||||||
|
go func() {
|
||||||
|
// Make sure if several requests were waiting we don't sleep for n * retry-after
|
||||||
|
// where n is the amount of requests that were going on
|
||||||
|
sleepTo := time.Now().Add(time.Duration(parsedAfter) * time.Millisecond)
|
||||||
|
|
||||||
|
b.global.Lock()
|
||||||
|
|
||||||
|
sleepDuration := sleepTo.Sub(time.Now())
|
||||||
|
if sleepDuration > 0 {
|
||||||
|
time.Sleep(sleepDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.global.Unlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update reset time if either retry after or reset headers are present
|
||||||
|
// Prefer retryafter because it's more accurate with time sync and whatnot
|
||||||
|
if retryAfter != "" {
|
||||||
|
parsedAfter, err := strconv.ParseInt(retryAfter, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.reset = time.Now().Add(time.Duration(parsedAfter) * time.Millisecond)
|
||||||
|
|
||||||
|
} else if reset != "" {
|
||||||
|
// Calculate the reset time by using the date header returned from discord
|
||||||
|
discordTime, err := http.ParseTime(headers.Get("Date"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
unix, err := strconv.ParseInt(reset, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the time until reset and add it to the current local time
|
||||||
|
// some extra time is added because without it i still encountered 429's.
|
||||||
|
// The added amount is the lowest amount that gave no 429's
|
||||||
|
// in 1k requests
|
||||||
|
delta := time.Unix(unix, 0).Sub(discordTime) + time.Millisecond*250
|
||||||
|
b.reset = time.Now().Add(delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Udpate remaining if header is present
|
||||||
|
if remaining != "" {
|
||||||
|
parsedRemaining, err := strconv.ParseInt(remaining, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.remaining = int(parsedRemaining)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
112
ratelimit_test.go
Normal file
112
ratelimit_test.go
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This test takes ~2 seconds to run
|
||||||
|
func TestRatelimitReset(t *testing.T) {
|
||||||
|
rl := NewRatelimiter()
|
||||||
|
|
||||||
|
sendReq := func(endpoint string) {
|
||||||
|
bucket := rl.LockBucket(endpoint)
|
||||||
|
|
||||||
|
headers := http.Header(make(map[string][]string))
|
||||||
|
|
||||||
|
headers.Set("X-RateLimit-Remaining", "0")
|
||||||
|
// Reset for approx 2 seconds from now
|
||||||
|
headers.Set("X-RateLimit-Reset", strconv.FormatInt(time.Now().Add(time.Second*2).Unix(), 10))
|
||||||
|
headers.Set("Date", time.Now().Format(time.RFC850))
|
||||||
|
|
||||||
|
err := bucket.Release(headers)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Release returned error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sent := time.Now()
|
||||||
|
sendReq("/guilds/99/channels")
|
||||||
|
sendReq("/guilds/55/channels")
|
||||||
|
sendReq("/guilds/66/channels")
|
||||||
|
|
||||||
|
sendReq("/guilds/99/channels")
|
||||||
|
sendReq("/guilds/55/channels")
|
||||||
|
sendReq("/guilds/66/channels")
|
||||||
|
|
||||||
|
// We hit the same endpoint 2 times, so we should only be ratelimited 2 second
|
||||||
|
// And always less than 4 seconds (unless you're on a stoneage computer or using swap or something...)
|
||||||
|
if time.Since(sent) >= time.Second && time.Since(sent) < time.Second*4 {
|
||||||
|
t.Log("OK", time.Since(sent))
|
||||||
|
} else {
|
||||||
|
t.Error("Did not ratelimit correctly, got:", time.Since(sent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test takes ~1 seconds to run
|
||||||
|
func TestRatelimitGlobal(t *testing.T) {
|
||||||
|
rl := NewRatelimiter()
|
||||||
|
|
||||||
|
sendReq := func(endpoint string) {
|
||||||
|
bucket := rl.LockBucket(endpoint)
|
||||||
|
|
||||||
|
headers := http.Header(make(map[string][]string))
|
||||||
|
|
||||||
|
headers.Set("X-RateLimit-Global", "1")
|
||||||
|
// Reset for approx 1 seconds from now
|
||||||
|
headers.Set("Retry-After", "1000")
|
||||||
|
|
||||||
|
err := bucket.Release(headers)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Release returned error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sent := time.Now()
|
||||||
|
|
||||||
|
// This should trigger a global ratelimit
|
||||||
|
sendReq("/guilds/99/channels")
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
|
||||||
|
// This shouldn't go through in less than 1 second
|
||||||
|
sendReq("/guilds/55/channels")
|
||||||
|
|
||||||
|
if time.Since(sent) >= time.Second && time.Since(sent) < time.Second*2 {
|
||||||
|
t.Log("OK", time.Since(sent))
|
||||||
|
} else {
|
||||||
|
t.Error("Did not ratelimit correctly, got:", time.Since(sent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRatelimitSingleEndpoint(b *testing.B) {
|
||||||
|
rl := NewRatelimiter()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
sendBenchReq("/guilds/99/channels", rl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRatelimitParallelMultiEndpoints(b *testing.B) {
|
||||||
|
rl := NewRatelimiter()
|
||||||
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
|
i := 0
|
||||||
|
for pb.Next() {
|
||||||
|
sendBenchReq("/guilds/"+strconv.Itoa(i)+"/channels", rl)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does not actually send requests, but locks the bucket and releases it with made-up headers
|
||||||
|
func sendBenchReq(endpoint string, rl *RateLimiter) {
|
||||||
|
bucket := rl.LockBucket(endpoint)
|
||||||
|
|
||||||
|
headers := http.Header(make(map[string][]string))
|
||||||
|
|
||||||
|
headers.Set("X-RateLimit-Remaining", "10")
|
||||||
|
headers.Set("X-RateLimit-Reset", strconv.FormatInt(time.Now().Unix(), 10))
|
||||||
|
headers.Set("Date", time.Now().Format(time.RFC850))
|
||||||
|
|
||||||
|
bucket.Release(headers)
|
||||||
|
}
|
705
restapi.go
705
restapi.go
File diff suppressed because it is too large
Load diff
|
@ -131,6 +131,17 @@ func TestUserSettings(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserUpdateStatus(t *testing.T) {
|
||||||
|
if dg == nil {
|
||||||
|
t.Skip("Cannot TestUserSettings, dg not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := dg.UserUpdateStatus(StatusDoNotDisturb)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestLogout tests the Logout() function. This should not return an error.
|
// TestLogout tests the Logout() function. This should not return an error.
|
||||||
func TestLogout(t *testing.T) {
|
func TestLogout(t *testing.T) {
|
||||||
|
|
||||||
|
@ -227,3 +238,39 @@ func TestChannelMessageSend2(t *testing.T) {
|
||||||
t.Errorf("ChannelMessageSend returned error: %+v", err)
|
t.Errorf("ChannelMessageSend returned error: %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestGuildPruneCount tests GuildPruneCount() function. This should not return an error.
|
||||||
|
func TestGuildPruneCount(t *testing.T) {
|
||||||
|
|
||||||
|
if envGuild == "" {
|
||||||
|
t.Skip("Skipping, DG_GUILD not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if dg == nil {
|
||||||
|
t.Skip("Skipping, dg not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := dg.GuildPruneCount(envGuild, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GuildPruneCount returned error: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TestGuildPrune tests GuildPrune() function. This should not return an error.
|
||||||
|
func TestGuildPrune(t *testing.T) {
|
||||||
|
|
||||||
|
if envGuild == "" {
|
||||||
|
t.Skip("Skipping, DG_GUILD not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if dg == nil {
|
||||||
|
t.Skip("Skipping, dg not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := dg.GuildPrune(envGuild, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GuildPrune returned error: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
124
state.go
124
state.go
|
@ -55,33 +55,6 @@ func NewState() *State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnReady takes a Ready event and updates all internal state.
|
|
||||||
func (s *State) OnReady(r *Ready) error {
|
|
||||||
if s == nil {
|
|
||||||
return ErrNilState
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.Ready = *r
|
|
||||||
|
|
||||||
for _, g := range s.Guilds {
|
|
||||||
s.guildMap[g.ID] = g
|
|
||||||
|
|
||||||
for _, c := range g.Channels {
|
|
||||||
c.GuildID = g.ID
|
|
||||||
s.channelMap[c.ID] = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range s.PrivateChannels {
|
|
||||||
s.channelMap[c.ID] = c
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
||||||
|
@ -94,20 +67,30 @@ func (s *State) GuildAdd(guild *Guild) error {
|
||||||
|
|
||||||
// Update the channels to point to the right guild, adding them to the channelMap as we go
|
// Update the channels to point to the right guild, adding them to the channelMap as we go
|
||||||
for _, c := range guild.Channels {
|
for _, c := range guild.Channels {
|
||||||
c.GuildID = guild.ID
|
|
||||||
s.channelMap[c.ID] = c
|
s.channelMap[c.ID] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the guild exists, replace it.
|
|
||||||
if g, ok := s.guildMap[guild.ID]; ok {
|
if g, ok := s.guildMap[guild.ID]; ok {
|
||||||
// If this guild already exists with data, don't stomp on props.
|
// We are about to replace `g` in the state with `guild`, but first we need to
|
||||||
if g.Unavailable != nil && !*g.Unavailable {
|
// make sure we preserve any fields that the `guild` doesn't contain from `g`.
|
||||||
|
if guild.Roles == nil {
|
||||||
|
guild.Roles = g.Roles
|
||||||
|
}
|
||||||
|
if guild.Emojis == nil {
|
||||||
|
guild.Emojis = g.Emojis
|
||||||
|
}
|
||||||
|
if guild.Members == nil {
|
||||||
guild.Members = g.Members
|
guild.Members = g.Members
|
||||||
|
}
|
||||||
|
if guild.Presences == nil {
|
||||||
guild.Presences = g.Presences
|
guild.Presences = g.Presences
|
||||||
|
}
|
||||||
|
if guild.Channels == nil {
|
||||||
guild.Channels = g.Channels
|
guild.Channels = g.Channels
|
||||||
|
}
|
||||||
|
if guild.VoiceStates == nil {
|
||||||
guild.VoiceStates = g.VoiceStates
|
guild.VoiceStates = g.VoiceStates
|
||||||
}
|
}
|
||||||
|
|
||||||
*g = *guild
|
*g = *guild
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -325,8 +308,12 @@ func (s *State) ChannelAdd(channel *Channel) error {
|
||||||
|
|
||||||
// If the channel exists, replace it
|
// If the channel exists, replace it
|
||||||
if c, ok := s.channelMap[channel.ID]; ok {
|
if c, ok := s.channelMap[channel.ID]; ok {
|
||||||
channel.Messages = c.Messages
|
if channel.Messages == nil {
|
||||||
channel.PermissionOverwrites = c.PermissionOverwrites
|
channel.Messages = c.Messages
|
||||||
|
}
|
||||||
|
if channel.PermissionOverwrites == nil {
|
||||||
|
channel.PermissionOverwrites = c.PermissionOverwrites
|
||||||
|
}
|
||||||
|
|
||||||
*c = *channel
|
*c = *channel
|
||||||
return nil
|
return nil
|
||||||
|
@ -511,6 +498,12 @@ func (s *State) MessageAdd(message *Message) error {
|
||||||
if message.Attachments != nil {
|
if message.Attachments != nil {
|
||||||
m.Attachments = message.Attachments
|
m.Attachments = message.Attachments
|
||||||
}
|
}
|
||||||
|
if message.Timestamp != "" {
|
||||||
|
m.Timestamp = message.Timestamp
|
||||||
|
}
|
||||||
|
if message.Author != nil {
|
||||||
|
m.Author = message.Author
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -602,18 +595,63 @@ func (s *State) Message(channelID, messageID string) (*Message, error) {
|
||||||
return nil, errors.New("Message not found.")
|
return nil, errors.New("Message not found.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnReady takes a Ready event and updates all internal state.
|
||||||
|
func (s *State) onReady(se *Session, r *Ready) (err error) {
|
||||||
|
if s == nil {
|
||||||
|
return ErrNilState
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
// We must track at least the current user for Voice, even
|
||||||
|
// if state is disabled, store the bare essentials.
|
||||||
|
if !se.StateEnabled {
|
||||||
|
ready := Ready{
|
||||||
|
Version: r.Version,
|
||||||
|
SessionID: r.SessionID,
|
||||||
|
HeartbeatInterval: r.HeartbeatInterval,
|
||||||
|
User: r.User,
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Ready = ready
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Ready = *r
|
||||||
|
|
||||||
|
for _, g := range s.Guilds {
|
||||||
|
s.guildMap[g.ID] = g
|
||||||
|
|
||||||
|
for _, c := range g.Channels {
|
||||||
|
s.channelMap[c.ID] = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range s.PrivateChannels {
|
||||||
|
s.channelMap[c.ID] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r, ok := i.(*Ready)
|
||||||
|
if ok {
|
||||||
|
return s.onReady(se, r)
|
||||||
|
}
|
||||||
|
|
||||||
if !se.StateEnabled {
|
if !se.StateEnabled {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t := i.(type) {
|
switch t := i.(type) {
|
||||||
case *Ready:
|
|
||||||
err = s.OnReady(t)
|
|
||||||
case *GuildCreate:
|
case *GuildCreate:
|
||||||
err = s.GuildAdd(t.Guild)
|
err = s.GuildAdd(t.Guild)
|
||||||
case *GuildUpdate:
|
case *GuildUpdate:
|
||||||
|
@ -685,6 +723,9 @@ func (s *State) onInterface(se *Session, i interface{}) (err error) {
|
||||||
// userID : The ID of the user to calculate permissions for.
|
// userID : The ID of the user to calculate permissions for.
|
||||||
// channelID : The ID of the channel to calculate permission for.
|
// channelID : The ID of the channel to calculate permission for.
|
||||||
func (s *State) UserChannelPermissions(userID, channelID string) (apermissions int, err error) {
|
func (s *State) UserChannelPermissions(userID, channelID string) (apermissions int, err error) {
|
||||||
|
if s == nil {
|
||||||
|
return 0, ErrNilState
|
||||||
|
}
|
||||||
|
|
||||||
channel, err := s.Channel(channelID)
|
channel, err := s.Channel(channelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -706,6 +747,13 @@ func (s *State) UserChannelPermissions(userID, channelID string) (apermissions i
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, role := range guild.Roles {
|
||||||
|
if role.ID == guild.ID {
|
||||||
|
apermissions |= role.Permissions
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, role := range guild.Roles {
|
for _, role := range guild.Roles {
|
||||||
for _, roleID := range member.Roles {
|
for _, roleID := range member.Roles {
|
||||||
if role.ID == roleID {
|
if role.ID == roleID {
|
||||||
|
@ -715,7 +763,7 @@ func (s *State) UserChannelPermissions(userID, channelID string) (apermissions i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if apermissions&PermissionManageRoles > 0 {
|
if apermissions&PermissionAdministrator > 0 {
|
||||||
apermissions |= PermissionAll
|
apermissions |= PermissionAll
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,7 +786,7 @@ func (s *State) UserChannelPermissions(userID, channelID string) (apermissions i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if apermissions&PermissionManageRoles > 0 {
|
if apermissions&PermissionAdministrator > 0 {
|
||||||
apermissions |= PermissionAllChannel
|
apermissions |= PermissionAllChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
272
structs.go
272
structs.go
|
@ -13,7 +13,7 @@ package discordgo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -53,6 +53,9 @@ type Session struct {
|
||||||
// Whether the Data Websocket is ready
|
// Whether the Data Websocket is ready
|
||||||
DataReady bool // NOTE: Maye be deprecated soon
|
DataReady bool // NOTE: Maye be deprecated soon
|
||||||
|
|
||||||
|
// Max number of REST API retries
|
||||||
|
MaxRestRetries int
|
||||||
|
|
||||||
// Status stores the currect status of the websocket connection
|
// Status stores the currect status of the websocket connection
|
||||||
// this is being tested, may stay, may go away.
|
// this is being tested, may stay, may go away.
|
||||||
status int32
|
status int32
|
||||||
|
@ -70,13 +73,10 @@ type Session struct {
|
||||||
// StateEnabled is true.
|
// StateEnabled is true.
|
||||||
State *State
|
State *State
|
||||||
|
|
||||||
handlersMu sync.RWMutex
|
// Event handlers
|
||||||
// This is a mapping of event struct to a reflected value
|
handlersMu sync.RWMutex
|
||||||
// for event handlers.
|
handlers map[string][]*eventHandlerInstance
|
||||||
// We store the reflected value instead of the function
|
onceHandlers map[string][]*eventHandlerInstance
|
||||||
// reference as it is more performant, instead of re-reflecting
|
|
||||||
// the function each event.
|
|
||||||
handlers map[interface{}][]reflect.Value
|
|
||||||
|
|
||||||
// The websocket connection.
|
// The websocket connection.
|
||||||
wsConn *websocket.Conn
|
wsConn *websocket.Conn
|
||||||
|
@ -85,9 +85,7 @@ type Session struct {
|
||||||
listening chan interface{}
|
listening chan interface{}
|
||||||
|
|
||||||
// used to deal with rate limits
|
// used to deal with rate limits
|
||||||
// may switch to slices later
|
ratelimiter *RateLimiter
|
||||||
// TODO: performance test map vs slices
|
|
||||||
rateLimit rateLimitMutex
|
|
||||||
|
|
||||||
// sequence tracks the current gateway api websocket sequence number
|
// sequence tracks the current gateway api websocket sequence number
|
||||||
sequence int
|
sequence int
|
||||||
|
@ -108,12 +106,6 @@ type rateLimitMutex struct {
|
||||||
// bucket map[string]*sync.Mutex // TODO :)
|
// bucket map[string]*sync.Mutex // TODO :)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Resumed struct holds the data received in a RESUMED event
|
|
||||||
type Resumed struct {
|
|
||||||
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
|
||||||
Trace []string `json:"_trace"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A VoiceRegion stores data for a specific voice region server.
|
// A VoiceRegion stores data for a specific voice region server.
|
||||||
type VoiceRegion struct {
|
type VoiceRegion struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
@ -137,17 +129,17 @@ type ICEServer struct {
|
||||||
|
|
||||||
// A Invite stores all data related to a specific Discord Guild or Channel invite.
|
// A Invite stores all data related to a specific Discord Guild or Channel invite.
|
||||||
type Invite struct {
|
type Invite struct {
|
||||||
Guild *Guild `json:"guild"`
|
Guild *Guild `json:"guild"`
|
||||||
Channel *Channel `json:"channel"`
|
Channel *Channel `json:"channel"`
|
||||||
Inviter *User `json:"inviter"`
|
Inviter *User `json:"inviter"`
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
CreatedAt string `json:"created_at"` // TODO make timestamp
|
CreatedAt Timestamp `json:"created_at"`
|
||||||
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"`
|
XkcdPass string `json:"xkcdpass"`
|
||||||
Revoked bool `json:"revoked"`
|
Revoked bool `json:"revoked"`
|
||||||
Temporary bool `json:"temporary"`
|
Temporary bool `json:"temporary"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Channel holds all data related to an individual Discord channel.
|
// A Channel holds all data related to an individual Discord channel.
|
||||||
|
@ -183,6 +175,17 @@ type Emoji struct {
|
||||||
RequireColons bool `json:"require_colons"`
|
RequireColons bool `json:"require_colons"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APIName returns an correctly formatted API name for use in the MessageReactions endpoints.
|
||||||
|
func (e *Emoji) APIName() string {
|
||||||
|
if e.ID != "" && e.Name != "" {
|
||||||
|
return e.Name + ":" + e.ID
|
||||||
|
}
|
||||||
|
if e.Name != "" {
|
||||||
|
return e.Name
|
||||||
|
}
|
||||||
|
return e.ID
|
||||||
|
}
|
||||||
|
|
||||||
// VerificationLevel type defination
|
// VerificationLevel type defination
|
||||||
type VerificationLevel int
|
type VerificationLevel int
|
||||||
|
|
||||||
|
@ -204,9 +207,10 @@ type Guild struct {
|
||||||
AfkChannelID string `json:"afk_channel_id"`
|
AfkChannelID string `json:"afk_channel_id"`
|
||||||
EmbedChannelID string `json:"embed_channel_id"`
|
EmbedChannelID string `json:"embed_channel_id"`
|
||||||
OwnerID string `json:"owner_id"`
|
OwnerID string `json:"owner_id"`
|
||||||
JoinedAt string `json:"joined_at"` // make this a timestamp
|
JoinedAt Timestamp `json:"joined_at"`
|
||||||
Splash string `json:"splash"`
|
Splash string `json:"splash"`
|
||||||
AfkTimeout int `json:"afk_timeout"`
|
AfkTimeout int `json:"afk_timeout"`
|
||||||
|
MemberCount int `json:"member_count"`
|
||||||
VerificationLevel VerificationLevel `json:"verification_level"`
|
VerificationLevel VerificationLevel `json:"verification_level"`
|
||||||
EmbedEnabled bool `json:"embed_enabled"`
|
EmbedEnabled bool `json:"embed_enabled"`
|
||||||
Large bool `json:"large"` // ??
|
Large bool `json:"large"` // ??
|
||||||
|
@ -217,7 +221,16 @@ type Guild struct {
|
||||||
Presences []*Presence `json:"presences"`
|
Presences []*Presence `json:"presences"`
|
||||||
Channels []*Channel `json:"channels"`
|
Channels []*Channel `json:"channels"`
|
||||||
VoiceStates []*VoiceState `json:"voice_states"`
|
VoiceStates []*VoiceState `json:"voice_states"`
|
||||||
Unavailable *bool `json:"unavailable"`
|
Unavailable bool `json:"unavailable"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A UserGuild holds a brief version of a Guild
|
||||||
|
type UserGuild struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
Owner bool `json:"owner"`
|
||||||
|
Permissions int `json:"permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A GuildParams stores all the data needed to update discord guild settings
|
// A GuildParams stores all the data needed to update discord guild settings
|
||||||
|
@ -232,6 +245,7 @@ type Role struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Managed bool `json:"managed"`
|
Managed bool `json:"managed"`
|
||||||
|
Mentionable bool `json:"mentionable"`
|
||||||
Hoist bool `json:"hoist"`
|
Hoist bool `json:"hoist"`
|
||||||
Color int `json:"color"`
|
Color int `json:"color"`
|
||||||
Position int `json:"position"`
|
Position int `json:"position"`
|
||||||
|
@ -253,9 +267,11 @@ type VoiceState struct {
|
||||||
|
|
||||||
// A Presence stores the online, offline, or idle and game status of Guild members.
|
// A Presence stores the online, offline, or idle and game status of Guild members.
|
||||||
type Presence struct {
|
type Presence struct {
|
||||||
User *User `json:"user"`
|
User *User `json:"user"`
|
||||||
Status string `json:"status"`
|
Status Status `json:"status"`
|
||||||
Game *Game `json:"game"`
|
Game *Game `json:"game"`
|
||||||
|
Nick string `json:"nick"`
|
||||||
|
Roles []string `json:"roles"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -265,6 +281,38 @@ type Game struct {
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals json to Game struct
|
||||||
|
func (g *Game) UnmarshalJSON(bytes []byte) error {
|
||||||
|
temp := &struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type json.RawMessage `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}{}
|
||||||
|
err := json.Unmarshal(bytes, temp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g.Name = temp.Name
|
||||||
|
g.URL = temp.URL
|
||||||
|
|
||||||
|
if temp.Type != nil {
|
||||||
|
err = json.Unmarshal(temp.Type, &g.Type)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s := ""
|
||||||
|
err = json.Unmarshal(temp.Type, &s)
|
||||||
|
if err == nil {
|
||||||
|
g.Type, err = strconv.Atoi(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// A Member stores user information for Guild members.
|
// A Member stores user information for Guild members.
|
||||||
type Member struct {
|
type Member struct {
|
||||||
GuildID string `json:"guild_id"`
|
GuildID string `json:"guild_id"`
|
||||||
|
@ -291,21 +339,35 @@ type User struct {
|
||||||
|
|
||||||
// A Settings stores data for a specific users Discord client settings.
|
// A Settings stores data for a specific users Discord client settings.
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
RenderEmbeds bool `json:"render_embeds"`
|
RenderEmbeds bool `json:"render_embeds"`
|
||||||
InlineEmbedMedia bool `json:"inline_embed_media"`
|
InlineEmbedMedia bool `json:"inline_embed_media"`
|
||||||
InlineAttachmentMedia bool `json:"inline_attachment_media"`
|
InlineAttachmentMedia bool `json:"inline_attachment_media"`
|
||||||
EnableTtsCommand bool `json:"enable_tts_command"`
|
EnableTtsCommand bool `json:"enable_tts_command"`
|
||||||
MessageDisplayCompact bool `json:"message_display_compact"`
|
MessageDisplayCompact bool `json:"message_display_compact"`
|
||||||
ShowCurrentGame bool `json:"show_current_game"`
|
ShowCurrentGame bool `json:"show_current_game"`
|
||||||
AllowEmailFriendRequest bool `json:"allow_email_friend_request"`
|
ConvertEmoticons bool `json:"convert_emoticons"`
|
||||||
ConvertEmoticons bool `json:"convert_emoticons"`
|
Locale string `json:"locale"`
|
||||||
Locale string `json:"locale"`
|
Theme string `json:"theme"`
|
||||||
Theme string `json:"theme"`
|
GuildPositions []string `json:"guild_positions"`
|
||||||
GuildPositions []string `json:"guild_positions"`
|
RestrictedGuilds []string `json:"restricted_guilds"`
|
||||||
RestrictedGuilds []string `json:"restricted_guilds"`
|
FriendSourceFlags *FriendSourceFlags `json:"friend_source_flags"`
|
||||||
FriendSourceFlags *FriendSourceFlags `json:"friend_source_flags"`
|
Status Status `json:"status"`
|
||||||
|
DetectPlatformAccounts bool `json:"detect_platform_accounts"`
|
||||||
|
DeveloperMode bool `json:"developer_mode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status type defination
|
||||||
|
type Status string
|
||||||
|
|
||||||
|
// Constants for Status with the different current available status
|
||||||
|
const (
|
||||||
|
StatusOnline Status = "online"
|
||||||
|
StatusIdle Status = "idle"
|
||||||
|
StatusDoNotDisturb Status = "dnd"
|
||||||
|
StatusInvisible Status = "invisible"
|
||||||
|
StatusOffline Status = "offline"
|
||||||
|
)
|
||||||
|
|
||||||
// FriendSourceFlags stores ... TODO :)
|
// FriendSourceFlags stores ... TODO :)
|
||||||
type FriendSourceFlags struct {
|
type FriendSourceFlags struct {
|
||||||
All bool `json:"all"`
|
All bool `json:"all"`
|
||||||
|
@ -313,32 +375,6 @@ type FriendSourceFlags struct {
|
||||||
MutualFriends bool `json:"mutual_friends"`
|
MutualFriends bool `json:"mutual_friends"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// An Event provides a basic initial struct for all websocket event.
|
|
||||||
type Event struct {
|
|
||||||
Operation int `json:"op"`
|
|
||||||
Sequence int `json:"s"`
|
|
||||||
Type string `json:"t"`
|
|
||||||
RawData json.RawMessage `json:"d"`
|
|
||||||
Struct interface{} `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Ready stores all data for the websocket READY event.
|
|
||||||
type Ready struct {
|
|
||||||
Version int `json:"v"`
|
|
||||||
SessionID string `json:"session_id"`
|
|
||||||
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
|
||||||
User *User `json:"user"`
|
|
||||||
ReadState []*ReadState `json:"read_state"`
|
|
||||||
PrivateChannels []*Channel `json:"private_channels"`
|
|
||||||
Guilds []*Guild `json:"guilds"`
|
|
||||||
|
|
||||||
// Undocumented fields
|
|
||||||
Settings *Settings `json:"user_settings"`
|
|
||||||
UserGuildSettings []*UserGuildSettings `json:"user_guild_settings"`
|
|
||||||
Relationships []*Relationship `json:"relationships"`
|
|
||||||
Presences []*Presence `json:"presences"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Relationship between the logged in user and Relationship.User
|
// A Relationship between the logged in user and Relationship.User
|
||||||
type Relationship struct {
|
type Relationship struct {
|
||||||
User *User `json:"user"`
|
User *User `json:"user"`
|
||||||
|
@ -361,54 +397,21 @@ type ReadState struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A TypingStart stores data for the typing start websocket event.
|
// An Ack is used to ack messages
|
||||||
type TypingStart struct {
|
type Ack struct {
|
||||||
UserID string `json:"user_id"`
|
Token string `json:"token"`
|
||||||
ChannelID string `json:"channel_id"`
|
|
||||||
Timestamp int `json:"timestamp"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A PresenceUpdate stores data for the presence update websocket event.
|
// A GuildRole stores data for guild roles.
|
||||||
type PresenceUpdate struct {
|
|
||||||
Presence
|
|
||||||
GuildID string `json:"guild_id"`
|
|
||||||
Roles []string `json:"roles"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A MessageAck stores data for the message ack websocket event.
|
|
||||||
type MessageAck struct {
|
|
||||||
MessageID string `json:"message_id"`
|
|
||||||
ChannelID string `json:"channel_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A GuildIntegrationsUpdate stores data for the guild integrations update
|
|
||||||
// websocket event.
|
|
||||||
type GuildIntegrationsUpdate struct {
|
|
||||||
GuildID string `json:"guild_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A GuildRole stores data for guild role websocket events.
|
|
||||||
type GuildRole struct {
|
type GuildRole struct {
|
||||||
Role *Role `json:"role"`
|
Role *Role `json:"role"`
|
||||||
GuildID string `json:"guild_id"`
|
GuildID string `json:"guild_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A GuildRoleDelete stores data for the guild role delete websocket event.
|
|
||||||
type GuildRoleDelete struct {
|
|
||||||
RoleID string `json:"role_id"`
|
|
||||||
GuildID string `json:"guild_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A GuildBan stores data for a guild ban.
|
// A GuildBan stores data for a guild ban.
|
||||||
type GuildBan struct {
|
type GuildBan struct {
|
||||||
User *User `json:"user"`
|
Reason string `json:"reason"`
|
||||||
GuildID string `json:"guild_id"`
|
User *User `json:"user"`
|
||||||
}
|
|
||||||
|
|
||||||
// A GuildEmojisUpdate stores data for a guild emoji update event.
|
|
||||||
type GuildEmojisUpdate struct {
|
|
||||||
GuildID string `json:"guild_id"`
|
|
||||||
Emojis []*Emoji `json:"emojis"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A GuildIntegration stores data for a guild integration.
|
// A GuildIntegration stores data for a guild integration.
|
||||||
|
@ -464,6 +467,41 @@ type UserGuildSettingsEdit struct {
|
||||||
ChannelOverrides map[string]*UserGuildSettingsChannelOverride `json:"channel_overrides"`
|
ChannelOverrides map[string]*UserGuildSettingsChannelOverride `json:"channel_overrides"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An APIErrorMessage is an api error message returned from discord
|
||||||
|
type APIErrorMessage struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Webhook stores the data for a webhook.
|
||||||
|
type Webhook struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
ChannelID string `json:"channel_id"`
|
||||||
|
User *User `json:"user"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookParams is a struct for webhook params, used in the WebhookExecute command.
|
||||||
|
type WebhookParams struct {
|
||||||
|
Content string `json:"content,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
AvatarURL string `json:"avatar_url,omitempty"`
|
||||||
|
TTS bool `json:"tts,omitempty"`
|
||||||
|
File string `json:"file,omitempty"`
|
||||||
|
Embeds []*MessageEmbed `json:"embeds,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReaction stores the data for a message reaction.
|
||||||
|
type MessageReaction struct {
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
MessageID string `json:"message_id"`
|
||||||
|
Emoji Emoji `json:"emoji"`
|
||||||
|
ChannelID string `json:"channel_id"`
|
||||||
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
|
@ -474,6 +512,7 @@ const (
|
||||||
PermissionAttachFiles
|
PermissionAttachFiles
|
||||||
PermissionReadMessageHistory
|
PermissionReadMessageHistory
|
||||||
PermissionMentionEveryone
|
PermissionMentionEveryone
|
||||||
|
PermissionUseExternalEmojis
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constants for the different bit offsets of voice permissions
|
// Constants for the different bit offsets of voice permissions
|
||||||
|
@ -486,12 +525,21 @@ const (
|
||||||
PermissionVoiceUseVAD
|
PermissionVoiceUseVAD
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Constants for general management.
|
||||||
|
const (
|
||||||
|
PermissionChangeNickname = 1 << (iota + 26)
|
||||||
|
PermissionManageNicknames
|
||||||
|
PermissionManageRoles
|
||||||
|
PermissionManageWebhooks
|
||||||
|
PermissionManageEmojis
|
||||||
|
)
|
||||||
|
|
||||||
// Constants for the different bit offsets of general permissions
|
// Constants for the different bit offsets of general permissions
|
||||||
const (
|
const (
|
||||||
PermissionCreateInstantInvite = 1 << iota
|
PermissionCreateInstantInvite = 1 << iota
|
||||||
PermissionKickMembers
|
PermissionKickMembers
|
||||||
PermissionBanMembers
|
PermissionBanMembers
|
||||||
PermissionManageRoles
|
PermissionAdministrator
|
||||||
PermissionManageChannels
|
PermissionManageChannels
|
||||||
PermissionManageServer
|
PermissionManageServer
|
||||||
|
|
||||||
|
|
123
tools/cmd/eventhandlers/main.go
Normal file
123
tools/cmd/eventhandlers/main.go
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"go/format"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
var eventHandlerTmpl = template.Must(template.New("eventHandler").Funcs(template.FuncMap{
|
||||||
|
"constName": constName,
|
||||||
|
"isDiscordEvent": isDiscordEvent,
|
||||||
|
"privateName": privateName,
|
||||||
|
}).Parse(`// Code generated by \"eventhandlers\"; DO NOT EDIT
|
||||||
|
// See events.go
|
||||||
|
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
// Following are all the event types.
|
||||||
|
// Event type values are used to match the events returned by Discord.
|
||||||
|
// EventTypes surrounded by __ are synthetic and are internal to DiscordGo.
|
||||||
|
const ({{range .}}
|
||||||
|
{{privateName .}}EventType = "{{constName .}}"{{end}}
|
||||||
|
)
|
||||||
|
{{range .}}
|
||||||
|
// {{privateName .}}EventHandler is an event handler for {{.}} events.
|
||||||
|
type {{privateName .}}EventHandler func(*Session, *{{.}})
|
||||||
|
|
||||||
|
// Type returns the event type for {{.}} events.
|
||||||
|
func (eh {{privateName .}}EventHandler) Type() string {
|
||||||
|
return {{privateName .}}EventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of {{.}}.
|
||||||
|
func (eh {{privateName .}}EventHandler) New() interface{} {
|
||||||
|
return &{{.}}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for {{.}} events.
|
||||||
|
func (eh {{privateName .}}EventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*{{.}}); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
func handlerForInterface(handler interface{}) EventHandler {
|
||||||
|
switch v := handler.(type) {
|
||||||
|
case func(*Session, interface{}):
|
||||||
|
return interfaceEventHandler(v){{range .}}
|
||||||
|
case func(*Session, *{{.}}):
|
||||||
|
return {{privateName .}}EventHandler(v){{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func init() { {{range .}}{{if isDiscordEvent .}}
|
||||||
|
registerInterfaceProvider({{privateName .}}EventHandler(nil)){{end}}{{end}}
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
dir := filepath.Dir(".")
|
||||||
|
|
||||||
|
fs := token.NewFileSet()
|
||||||
|
parsedFile, err := parser.ParseFile(fs, "events.go", nil, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("warning: internal error: could not parse events.go: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
names := []string{}
|
||||||
|
for object := range parsedFile.Scope.Objects {
|
||||||
|
names = append(names, object)
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
eventHandlerTmpl.Execute(&buf, names)
|
||||||
|
|
||||||
|
src, err := format.Source(buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
log.Println("warning: internal error: invalid Go generated:", err)
|
||||||
|
src = buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filepath.Join(dir, strings.ToLower("eventhandlers.go")), src, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(buf, "writing output: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var constRegexp = regexp.MustCompile("([a-z])([A-Z])")
|
||||||
|
|
||||||
|
func constCase(name string) string {
|
||||||
|
return strings.ToUpper(constRegexp.ReplaceAllString(name, "${1}_${2}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDiscordEvent(name string) bool {
|
||||||
|
switch {
|
||||||
|
case name == "Connect", name == "Disconnect", name == "Event", name == "RateLimit", name == "Interface":
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func constName(name string) string {
|
||||||
|
if !isDiscordEvent(name) {
|
||||||
|
return "__" + constCase(name) + "__"
|
||||||
|
}
|
||||||
|
|
||||||
|
return constCase(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func privateName(name string) string {
|
||||||
|
return strings.ToLower(string(name[0])) + name[1:]
|
||||||
|
}
|
58
types.go
Normal file
58
types.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// Discordgo - Discord bindings for Go
|
||||||
|
// Available at https://github.com/bwmarrin/discordgo
|
||||||
|
|
||||||
|
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file contains custom types, currently only a timestamp wrapper.
|
||||||
|
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Timestamp stores a timestamp, as sent by the Discord API.
|
||||||
|
type Timestamp string
|
||||||
|
|
||||||
|
// Parse parses a timestamp string into a time.Time object.
|
||||||
|
// The only time this can fail is if Discord changes their timestamp format.
|
||||||
|
func (t Timestamp) Parse() (time.Time, error) {
|
||||||
|
return time.Parse(time.RFC3339, string(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RESTError stores error information about a request with a bad response code.
|
||||||
|
// Message is not always present, there are cases where api calls can fail
|
||||||
|
// without returning a json message.
|
||||||
|
type RESTError struct {
|
||||||
|
Request *http.Request
|
||||||
|
Response *http.Response
|
||||||
|
ResponseBody []byte
|
||||||
|
|
||||||
|
Message *APIErrorMessage // Message may be nil.
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRestError(req *http.Request, resp *http.Response, body []byte) *RESTError {
|
||||||
|
restErr := &RESTError{
|
||||||
|
Request: req,
|
||||||
|
Response: resp,
|
||||||
|
ResponseBody: body,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to decode the error and assume no message was provided if it fails
|
||||||
|
var msg *APIErrorMessage
|
||||||
|
err := json.Unmarshal(body, &msg)
|
||||||
|
if err == nil {
|
||||||
|
restErr.Message = msg
|
||||||
|
}
|
||||||
|
|
||||||
|
return restErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r RESTError) Error() string {
|
||||||
|
return fmt.Sprintf("HTTP %s, %s", r.Response.Status, r.ResponseBody)
|
||||||
|
}
|
24
types_test.go
Normal file
24
types_test.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTimestampParse(t *testing.T) {
|
||||||
|
ts, err := Timestamp("2016-03-24T23:15:59.605000+00:00").Parse()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if ts.Year() != 2016 || ts.Month() != time.March || ts.Day() != 24 {
|
||||||
|
t.Error("Incorrect date")
|
||||||
|
}
|
||||||
|
if ts.Hour() != 23 || ts.Minute() != 15 || ts.Second() != 59 {
|
||||||
|
t.Error("Incorrect time")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, offset := ts.Zone()
|
||||||
|
if offset != 0 {
|
||||||
|
t.Error("Incorrect timezone")
|
||||||
|
}
|
||||||
|
}
|
4
voice.go
4
voice.go
|
@ -441,7 +441,7 @@ func (v *VoiceConnection) onEvent(message []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
v.log(LogError, "unknown voice operation, %d, %s", e.Operation, string(e.RawData))
|
v.log(LogDebug, "unknown voice operation, %d, %s", e.Operation, string(e.RawData))
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -570,7 +570,7 @@ func (v *VoiceConnection) udpOpen() (err error) {
|
||||||
return fmt.Errorf("received udp packet too small")
|
return fmt.Errorf("received udp packet too small")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over position 4 though 20 to grab the IP address
|
// Loop over position 4 through 20 to grab the IP address
|
||||||
// Should never be beyond position 20.
|
// Should never be beyond position 20.
|
||||||
var ip string
|
var ip string
|
||||||
for i := 4; i < 20; i++ {
|
for i := 4; i < 20; i++ {
|
||||||
|
|
104
wsapi.go
104
wsapi.go
|
@ -17,9 +17,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -47,6 +45,17 @@ func (s *Session) Open() (err error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// A basic state is a hard requirement for Voice.
|
||||||
|
if s.State == nil {
|
||||||
|
state := NewState()
|
||||||
|
state.TrackChannels = false
|
||||||
|
state.TrackEmojis = false
|
||||||
|
state.TrackMembers = false
|
||||||
|
state.TrackRoles = false
|
||||||
|
state.TrackVoice = false
|
||||||
|
s.State = state
|
||||||
|
}
|
||||||
|
|
||||||
if s.wsConn != nil {
|
if s.wsConn != nil {
|
||||||
err = errors.New("Web socket already opened.")
|
err = errors.New("Web socket already opened.")
|
||||||
return
|
return
|
||||||
|
@ -111,9 +120,8 @@ func (s *Session) Open() (err error) {
|
||||||
|
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
s.initialize()
|
|
||||||
s.log(LogInformational, "emit connect event")
|
s.log(LogInformational, "emit connect event")
|
||||||
s.handle(&Connect{})
|
s.handleEvent(connectEventType, &Connect{})
|
||||||
|
|
||||||
s.log(LogInformational, "exiting")
|
s.log(LogInformational, "exiting")
|
||||||
return
|
return
|
||||||
|
@ -269,6 +277,44 @@ func (s *Session) UpdateStatus(idle int, game string) (err error) {
|
||||||
return s.UpdateStreamingStatus(idle, game, "")
|
return s.UpdateStreamingStatus(idle, game, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type requestGuildMembersData struct {
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
Query string `json:"query"`
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type requestGuildMembersOp struct {
|
||||||
|
Op int `json:"op"`
|
||||||
|
Data requestGuildMembersData `json:"d"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestGuildMembers requests guild members from the gateway
|
||||||
|
// The gateway responds with GuildMembersChunk events
|
||||||
|
// guildID : The ID of the guild to request members of
|
||||||
|
// query : String that username starts with, leave empty to return all members
|
||||||
|
// limit : Max number of items to return, or 0 to request all members matched
|
||||||
|
func (s *Session) RequestGuildMembers(guildID, query string, limit int) (err error) {
|
||||||
|
s.log(LogInformational, "called")
|
||||||
|
|
||||||
|
s.RLock()
|
||||||
|
defer s.RUnlock()
|
||||||
|
if s.wsConn == nil {
|
||||||
|
return errors.New("no websocket connection exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
data := requestGuildMembersData{
|
||||||
|
GuildID: guildID,
|
||||||
|
Query: query,
|
||||||
|
Limit: limit,
|
||||||
|
}
|
||||||
|
|
||||||
|
s.wsMutex.Lock()
|
||||||
|
err = s.wsConn.WriteJSON(requestGuildMembersOp{8, data})
|
||||||
|
s.wsMutex.Unlock()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// onEvent is the "event handler" for all messages received on the
|
// onEvent is the "event handler" for all messages received on the
|
||||||
// Discord Gateway API websocket connection.
|
// Discord Gateway API websocket connection.
|
||||||
//
|
//
|
||||||
|
@ -361,16 +407,12 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
||||||
// Store the message sequence
|
// Store the message sequence
|
||||||
s.sequence = e.Sequence
|
s.sequence = e.Sequence
|
||||||
|
|
||||||
// Map event to registered event handlers and pass it along
|
// Map event to registered event handlers and pass it along to any registered handlers.
|
||||||
// to any registered functions
|
if eh, ok := registeredInterfaceProviders[e.Type]; ok {
|
||||||
i := eventToInterface[e.Type]
|
e.Struct = eh.New()
|
||||||
if i != nil {
|
|
||||||
|
|
||||||
// Create a new instance of the event type.
|
|
||||||
i = reflect.New(reflect.TypeOf(i)).Interface()
|
|
||||||
|
|
||||||
// Attempt to unmarshal our event.
|
// Attempt to unmarshal our event.
|
||||||
if err = json.Unmarshal(e.RawData, i); err != nil {
|
if err = json.Unmarshal(e.RawData, e.Struct); err != nil {
|
||||||
s.log(LogError, "error unmarshalling %s event, %s", e.Type, err)
|
s.log(LogError, "error unmarshalling %s event, %s", e.Type, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,30 +423,19 @@ func (s *Session) onEvent(messageType int, message []byte) {
|
||||||
// it's better to pass along what we received than nothing at all.
|
// it's better to pass along what we received than nothing at all.
|
||||||
// TODO: Think about that decision :)
|
// TODO: Think about that decision :)
|
||||||
// Either way, READY events must fire, even with errors.
|
// Either way, READY events must fire, even with errors.
|
||||||
go s.handle(i)
|
s.handleEvent(e.Type, e.Struct)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
s.log(LogWarning, "unknown event: Op: %d, Seq: %d, Type: %s, Data: %s", e.Operation, e.Sequence, e.Type, string(e.RawData))
|
s.log(LogWarning, "unknown event: Op: %d, Seq: %d, Type: %s, Data: %s", e.Operation, e.Sequence, e.Type, string(e.RawData))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit event to the OnEvent handler
|
// For legacy reasons, we send the raw event also, this could be useful for handling unknown events.
|
||||||
e.Struct = i
|
s.handleEvent(eventEventType, e)
|
||||||
go s.handle(e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Code related to voice connections that initiate over the data websocket
|
// Code related to voice connections that initiate over the data websocket
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// A VoiceServerUpdate stores the data received during the Voice Server Update
|
|
||||||
// data websocket event. This data is used during the initial Voice Channel
|
|
||||||
// join handshaking.
|
|
||||||
type VoiceServerUpdate struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
GuildID string `json:"guild_id"`
|
|
||||||
Endpoint string `json:"endpoint"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type voiceChannelJoinData struct {
|
type voiceChannelJoinData struct {
|
||||||
GuildID *string `json:"guild_id"`
|
GuildID *string `json:"guild_id"`
|
||||||
ChannelID *string `json:"channel_id"`
|
ChannelID *string `json:"channel_id"`
|
||||||
|
@ -461,7 +492,7 @@ func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool) (voice *Voi
|
||||||
}
|
}
|
||||||
|
|
||||||
// onVoiceStateUpdate handles Voice State Update events on the data websocket.
|
// onVoiceStateUpdate handles Voice State Update events on the data websocket.
|
||||||
func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) {
|
func (s *Session) onVoiceStateUpdate(st *VoiceStateUpdate) {
|
||||||
|
|
||||||
// If we don't have a connection for the channel, don't bother
|
// If we don't have a connection for the channel, don't bother
|
||||||
if st.ChannelID == "" {
|
if st.ChannelID == "" {
|
||||||
|
@ -474,22 +505,13 @@ func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to have this happen at login and store it in the Session
|
// We only care about events that are about us.
|
||||||
// TODO : This should be done upon connecting to Discord, or
|
if s.State.User.ID != st.UserID {
|
||||||
// be moved to a small helper function
|
|
||||||
self, err := s.User("@me") // TODO: move to Login/New
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// We only care about events that are about us
|
|
||||||
if st.UserID != self.ID {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the SessionID for later use.
|
// Store the SessionID for later use.
|
||||||
voice.UserID = self.ID // TODO: Review
|
voice.UserID = st.UserID
|
||||||
voice.sessionID = st.SessionID
|
voice.sessionID = st.SessionID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +520,7 @@ func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) {
|
||||||
// This is also fired if the Guild's voice region changes while connected
|
// This is also fired if the Guild's voice region changes while connected
|
||||||
// to a voice channel. In that case, need to re-establish connection to
|
// to a voice channel. In that case, need to re-establish connection to
|
||||||
// the new region endpoint.
|
// the new region endpoint.
|
||||||
func (s *Session) onVoiceServerUpdate(se *Session, st *VoiceServerUpdate) {
|
func (s *Session) onVoiceServerUpdate(st *VoiceServerUpdate) {
|
||||||
|
|
||||||
s.log(LogInformational, "called")
|
s.log(LogInformational, "called")
|
||||||
|
|
||||||
|
@ -673,7 +695,7 @@ func (s *Session) Close() (err error) {
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
s.log(LogInformational, "emit disconnect event")
|
s.log(LogInformational, "emit disconnect event")
|
||||||
s.handle(&Disconnect{})
|
s.handleEvent(disconnectEventType, &Disconnect{})
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue