event.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package discordgo
  2. // EventHandler is an interface for Discord events.
  3. type EventHandler interface {
  4. // Type returns the type of event this handler belongs to.
  5. Type() string
  6. // Handle is called whenever an event of Type() happens.
  7. // It is the receivers responsibility to type assert that the interface
  8. // is the expected struct.
  9. Handle(*Session, interface{})
  10. }
  11. // EventInterfaceProvider is an interface for providing empty interfaces for
  12. // Discord events.
  13. type EventInterfaceProvider interface {
  14. // Type is the type of event this handler belongs to.
  15. Type() string
  16. // New returns a new instance of the struct this event handler handles.
  17. // This is called once per event.
  18. // The struct is provided to all handlers of the same Type().
  19. New() interface{}
  20. }
  21. // interfaceEventType is the event handler type for interface{} events.
  22. const interfaceEventType = "__INTERFACE__"
  23. // interfaceEventHandler is an event handler for interface{} events.
  24. type interfaceEventHandler func(*Session, interface{})
  25. // Type returns the event type for interface{} events.
  26. func (eh interfaceEventHandler) Type() string {
  27. return interfaceEventType
  28. }
  29. // Handle is the handler for an interface{} event.
  30. func (eh interfaceEventHandler) Handle(s *Session, i interface{}) {
  31. eh(s, i)
  32. }
  33. var registeredInterfaceProviders = map[string]EventInterfaceProvider{}
  34. // registerInterfaceProvider registers a provider so that DiscordGo can
  35. // access it's New() method.
  36. func registerInterfaceProvider(eh EventInterfaceProvider) {
  37. if _, ok := registeredInterfaceProviders[eh.Type()]; ok {
  38. return
  39. // XXX:
  40. // if we should error here, we need to do something with it.
  41. // fmt.Errorf("event %s already registered", eh.Type())
  42. }
  43. registeredInterfaceProviders[eh.Type()] = eh
  44. return
  45. }
  46. // eventHandlerInstance is a wrapper around an event handler, as functions
  47. // cannot be compared directly.
  48. type eventHandlerInstance struct {
  49. eventHandler EventHandler
  50. }
  51. // addEventHandler adds an event handler that will be fired anytime
  52. // the Discord WSAPI matching eventHandler.Type() fires.
  53. func (s *Session) addEventHandler(eventHandler EventHandler) func() {
  54. s.handlersMu.Lock()
  55. defer s.handlersMu.Unlock()
  56. if s.handlers == nil {
  57. s.handlers = map[string][]*eventHandlerInstance{}
  58. }
  59. ehi := &eventHandlerInstance{eventHandler}
  60. s.handlers[eventHandler.Type()] = append(s.handlers[eventHandler.Type()], ehi)
  61. return func() {
  62. s.removeEventHandlerInstance(eventHandler.Type(), ehi)
  63. }
  64. }
  65. // addEventHandler adds an event handler that will be fired the next time
  66. // the Discord WSAPI matching eventHandler.Type() fires.
  67. func (s *Session) addEventHandlerOnce(eventHandler EventHandler) func() {
  68. s.handlersMu.Lock()
  69. defer s.handlersMu.Unlock()
  70. if s.onceHandlers == nil {
  71. s.onceHandlers = map[string][]*eventHandlerInstance{}
  72. }
  73. ehi := &eventHandlerInstance{eventHandler}
  74. s.onceHandlers[eventHandler.Type()] = append(s.onceHandlers[eventHandler.Type()], ehi)
  75. return func() {
  76. s.removeEventHandlerInstance(eventHandler.Type(), ehi)
  77. }
  78. }
  79. // AddHandler allows you to add an event handler that will be fired anytime
  80. // the Discord WSAPI event that matches the function fires.
  81. // events.go contains all the Discord WSAPI events that can be fired.
  82. // eg:
  83. // Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
  84. // })
  85. //
  86. // or:
  87. // Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
  88. // })
  89. // The return value of this method is a function, that when called will remove the
  90. // event handler.
  91. func (s *Session) AddHandler(handler interface{}) func() {
  92. eh := handlerForInterface(handler)
  93. if eh == nil {
  94. s.log(LogError, "Invalid handler type, handler will never be called")
  95. return func() {}
  96. }
  97. return s.addEventHandler(eh)
  98. }
  99. // AddHandlerOnce allows you to add an event handler that will be fired the next time
  100. // the Discord WSAPI event that matches the function fires.
  101. // See AddHandler for more details.
  102. func (s *Session) AddHandlerOnce(handler interface{}) func() {
  103. eh := handlerForInterface(handler)
  104. if eh == nil {
  105. s.log(LogError, "Invalid handler type, handler will never be called")
  106. return func() {}
  107. }
  108. return s.addEventHandlerOnce(eh)
  109. }
  110. // removeEventHandler instance removes an event handler instance.
  111. func (s *Session) removeEventHandlerInstance(t string, ehi *eventHandlerInstance) {
  112. s.handlersMu.Lock()
  113. defer s.handlersMu.Unlock()
  114. handlers := s.handlers[t]
  115. for i := range handlers {
  116. if handlers[i] == ehi {
  117. s.handlers[t] = append(handlers[:i], handlers[i+1:]...)
  118. }
  119. }
  120. onceHandlers := s.onceHandlers[t]
  121. for i := range onceHandlers {
  122. if onceHandlers[i] == ehi {
  123. s.onceHandlers[t] = append(onceHandlers[:i], handlers[i+1:]...)
  124. }
  125. }
  126. }
  127. // Handles calling permanent and once handlers for an event type.
  128. func (s *Session) handle(t string, i interface{}) {
  129. for _, eh := range s.handlers[t] {
  130. if s.SyncEvents {
  131. eh.eventHandler.Handle(s, i)
  132. } else {
  133. go eh.eventHandler.Handle(s, i)
  134. }
  135. }
  136. if len(s.onceHandlers[t]) > 0 {
  137. for _, eh := range s.onceHandlers[t] {
  138. if s.SyncEvents {
  139. eh.eventHandler.Handle(s, i)
  140. } else {
  141. go eh.eventHandler.Handle(s, i)
  142. }
  143. }
  144. s.onceHandlers[t] = nil
  145. }
  146. }
  147. // Handles an event type by calling internal methods, firing handlers and firing the
  148. // interface{} event.
  149. func (s *Session) handleEvent(t string, i interface{}) {
  150. s.handlersMu.RLock()
  151. defer s.handlersMu.RUnlock()
  152. // All events are dispatched internally first.
  153. s.onInterface(i)
  154. // Then they are dispatched to anyone handling interface{} events.
  155. s.handle(interfaceEventType, i)
  156. // Finally they are dispatched to any typed handlers.
  157. s.handle(t, i)
  158. }
  159. // setGuildIds will set the GuildID on all the members of a guild.
  160. // This is done as event data does not have it set.
  161. func setGuildIds(g *Guild) {
  162. for _, c := range g.Channels {
  163. c.GuildID = g.ID
  164. }
  165. for _, m := range g.Members {
  166. m.GuildID = g.ID
  167. }
  168. for _, vs := range g.VoiceStates {
  169. vs.GuildID = g.ID
  170. }
  171. }
  172. // onInterface handles all internal events and routes them to the appropriate internal handler.
  173. func (s *Session) onInterface(i interface{}) {
  174. switch t := i.(type) {
  175. case *Ready:
  176. for _, g := range t.Guilds {
  177. setGuildIds(g)
  178. }
  179. s.onReady(t)
  180. case *GuildCreate:
  181. setGuildIds(t.Guild)
  182. case *GuildUpdate:
  183. setGuildIds(t.Guild)
  184. case *VoiceServerUpdate:
  185. go s.onVoiceServerUpdate(t)
  186. case *VoiceStateUpdate:
  187. go s.onVoiceStateUpdate(t)
  188. }
  189. err := s.State.OnInterface(s, i)
  190. if err != nil {
  191. s.log(LogDebug, "error dispatching internal event, %s", err)
  192. }
  193. }
  194. // onReady handles the ready event.
  195. func (s *Session) onReady(r *Ready) {
  196. // Store the SessionID within the Session struct.
  197. s.sessionID = r.SessionID
  198. }