|
@@ -122,11 +122,11 @@ func New(args ...interface{}) (s *Session, err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-// AddHandler allows you to add an event handler that will be fired anytime
|
|
|
-// the given event is triggered.
|
|
|
-func (s *Session) AddHandler(handler interface{}) {
|
|
|
- s.initialize()
|
|
|
-
|
|
|
+// 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 {
|
|
@@ -137,9 +137,6 @@ func (s *Session) AddHandler(handler interface{}) {
|
|
|
panic("Unable to add event handler, first argument must be of type *discordgo.Session.")
|
|
|
}
|
|
|
|
|
|
- s.Lock()
|
|
|
- defer s.Unlock()
|
|
|
-
|
|
|
eventType := handlerType.In(1)
|
|
|
|
|
|
// Support handlers of type interface{}, this is a special handler, which is triggered on every event.
|
|
@@ -147,18 +144,62 @@ func (s *Session) AddHandler(handler 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)
|
|
|
+
|
|
|
handlers := s.handlers[eventType]
|
|
|
if handlers == nil {
|
|
|
handlers = []reflect.Value{}
|
|
|
}
|
|
|
- s.handlers[eventType] = append(handlers, reflect.ValueOf(handler))
|
|
|
+ s.handlers[eventType] = append(handlers, 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.initialize()
|
|
|
|
|
|
- s.RLock()
|
|
|
- defer s.RUnlock()
|
|
|
+ s.handlersMu.RLock()
|
|
|
+ defer s.handlersMu.RUnlock()
|
|
|
|
|
|
handlerParameters := []reflect.Value{reflect.ValueOf(s), reflect.ValueOf(event)}
|
|
|
|
|
@@ -177,16 +218,14 @@ func (s *Session) handle(event interface{}) {
|
|
|
|
|
|
// initialize adds all internal handlers and state tracking handlers.
|
|
|
func (s *Session) initialize() {
|
|
|
- s.RLock()
|
|
|
+ s.handlersMu.Lock()
|
|
|
if s.handlers != nil {
|
|
|
- s.RUnlock()
|
|
|
+ s.handlersMu.Unlock()
|
|
|
return
|
|
|
}
|
|
|
- s.RUnlock()
|
|
|
|
|
|
- s.Lock()
|
|
|
s.handlers = map[interface{}][]reflect.Value{}
|
|
|
- s.Unlock()
|
|
|
+ s.handlersMu.Unlock()
|
|
|
|
|
|
s.AddHandler(s.onEvent)
|
|
|
s.AddHandler(s.onReady)
|