Merge pull request #294 from iopred/reflect

Remove the use of reflect.
This commit is contained in:
Bruce 2016-12-08 10:19:13 -06:00 committed by GitHub
commit 0759785277
9 changed files with 1505 additions and 389 deletions

View file

@ -13,10 +13,7 @@
// 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.14.0-dev" const VERSION = "0.14.0-dev"
@ -126,170 +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)}
s.onInterface(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()
defer s.handlersMu.Unlock()
if s.handlers != nil {
return
}
s.handlers = map[interface{}][]reflect.Value{}
}
// 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)
}

View file

@ -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)

238
event.go Normal file
View 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
View 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
View file

@ -1,187 +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{},
"CHANNEL_PINS_UPDATE": ChannelPinsUpdate{},
"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{},
"GUILD_MEMBERS_CHUNK": GuildMembersChunk{},
"MESSAGE_ACK": MessageAck{},
"MESSAGE_CREATE": MessageCreate{},
"MESSAGE_UPDATE": MessageUpdate{},
"MESSAGE_DELETE": MessageDelete{},
"MESSAGE_REACTION_ADD": MessageReactionAdd{},
"MESSAGE_REACTION_REMOVE": MessageReactionRemove{},
"PRESENCE_UPDATE": PresenceUpdate{},
"PRESENCES_REPLACE": PresencesReplace{},
"READY": Ready{},
"RELATIONSHIP_ADD": RelationshipAdd{},
"RELATIONSHIP_REMOVE": RelationshipRemove{},
"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
}
// MessageReactionAdd is a wrapper struct for an event.
type MessageReactionAdd struct {
*MessageReaction
}
// MessageReactionRemove is a wrapper struct for an event.
type MessageReactionRemove struct {
*MessageReaction
}
// 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 {
User *User `json:"user"` User *User `json:"user"`
GuildID string `json:"guild_id"` 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 {
User *User `json:"user"` User *User `json:"user"`
GuildID string `json:"guild_id"` 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 GuildRoleDelete struct {
RoleID string `json:"role_id"`
GuildID string `json:"guild_id"`
}
// A GuildEmojisUpdate is the data for a guild emoji update event.
type GuildEmojisUpdate struct {
GuildID string `json:"guild_id"`
Emojis []*Emoji `json:"emojis"`
}
// 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 type PresencesReplace []*Presence
// RelationshipAdd is a wrapper struct for an event. // 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 { type RelationshipAdd struct {
*Relationship *Relationship
} }
// RelationshipRemove is a wrapper struct for an event. // RelationshipRemove is the data for a RelationshipRemove event.
type RelationshipRemove struct { type RelationshipRemove struct {
*Relationship *Relationship
} }
// VoiceStateUpdate is a wrapper struct for an event. // TypingStart is the data for a TypingStart event.
type VoiceStateUpdate struct { type TypingStart struct {
*VoiceState UserID string `json:"user_id"`
ChannelID string `json:"channel_id"`
Timestamp int `json:"timestamp"`
} }
// UserUpdate is a wrapper struct for an event. // 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
}

View file

@ -146,7 +146,7 @@ func (s *Session) request(method, urlStr, contentType string, b []byte, bucketID
return return
} }
s.log(LogInformational, "Rate Limiting %s, retry in %d", urlStr, rl.RetryAfter) s.log(LogInformational, "Rate Limiting %s, retry in %d", urlStr, rl.RetryAfter)
s.handle(RateLimit{TooManyRequests: &rl, URL: urlStr}) s.handleEvent(rateLimitEventType, RateLimit{TooManyRequests: &rl, URL: urlStr})
time.Sleep(rl.RetryAfter * time.Millisecond) time.Sleep(rl.RetryAfter * time.Millisecond)
// we can make the above smarter // we can make the above smarter

View file

@ -13,7 +13,6 @@ package discordgo
import ( import (
"encoding/json" "encoding/json"
"reflect"
"strconv" "strconv"
"sync" "sync"
"time" "time"
@ -74,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
@ -110,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"`
@ -385,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"`
@ -433,67 +397,23 @@ type ReadState struct {
ID string `json:"id"` ID string `json:"id"`
} }
// A TypingStart stores data for the typing start websocket event.
type TypingStart struct {
UserID string `json:"user_id"`
ChannelID string `json:"channel_id"`
Timestamp int `json:"timestamp"`
}
// A PresenceUpdate stores data for the presence update websocket event.
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"`
}
// An Ack is used to ack messages // An Ack is used to ack messages
type Ack struct { type Ack struct {
Token string `json:"token"` Token string `json:"token"`
} }
// A GuildIntegrationsUpdate stores data for the guild integrations update // A GuildRole stores data for guild roles.
// 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 {
Reason string `json:"reason"` Reason string `json:"reason"`
User *User `json:"user"` 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 GuildMembersChunk stores data for the Guild Members Chunk websocket event.
type GuildMembersChunk struct {
GuildID string `json:"guild_id"`
Members []*Member `json:"members"`
}
// A GuildIntegration stores data for a guild integration. // A GuildIntegration stores data for a guild integration.
type GuildIntegration struct { type GuildIntegration struct {
ID string `json:"id"` ID string `json:"id"`
@ -553,12 +473,6 @@ type APIErrorMessage struct {
Message string `json:"message"` Message string `json:"message"`
} }
// ChannelPinsUpdate stores data for the channel pins update event
type ChannelPinsUpdate struct {
LastPinTimestamp string `json:"last_pin_timestamp"`
ChannelID string `json:"channel_id"`
}
// Webhook stores the data for a webhook. // Webhook stores the data for a webhook.
type Webhook struct { type Webhook struct {
ID string `json:"id"` ID string `json:"id"`

View 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:]
}

View file

@ -18,7 +18,6 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"reflect"
"runtime" "runtime"
"time" "time"
@ -121,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
@ -409,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)
} }
@ -429,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"`
@ -712,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
} }