event.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. // The first parameter is a *Session, and the second parameter is a pointer
  82. // to a struct corresponding to the event for which you want to listen.
  83. //
  84. // eg:
  85. // Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
  86. // })
  87. //
  88. // or:
  89. // Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
  90. // })
  91. //
  92. // List of events can be found at this page, with corresponding names in the
  93. // library for each event: https://discord.com/developers/docs/topics/gateway#event-names
  94. // There are also synthetic events fired by the library internally which are
  95. // available for handling, like Connect, Disconnect, and RateLimit.
  96. // events.go contains all of the Discord WSAPI and synthetic events that can be handled.
  97. //
  98. // The return value of this method is a function, that when called will remove the
  99. // event handler.
  100. func (s *Session) AddHandler(handler interface{}) func() {
  101. eh := handlerForInterface(handler)
  102. if eh == nil {
  103. s.log(LogError, "Invalid handler type, handler will never be called")
  104. return func() {}
  105. }
  106. return s.addEventHandler(eh)
  107. }
  108. // AddHandlerOnce allows you to add an event handler that will be fired the next time
  109. // the Discord WSAPI event that matches the function fires.
  110. // See AddHandler for more details.
  111. func (s *Session) AddHandlerOnce(handler interface{}) func() {
  112. eh := handlerForInterface(handler)
  113. if eh == nil {
  114. s.log(LogError, "Invalid handler type, handler will never be called")
  115. return func() {}
  116. }
  117. return s.addEventHandlerOnce(eh)
  118. }
  119. // removeEventHandler instance removes an event handler instance.
  120. func (s *Session) removeEventHandlerInstance(t string, ehi *eventHandlerInstance) {
  121. s.handlersMu.Lock()
  122. defer s.handlersMu.Unlock()
  123. handlers := s.handlers[t]
  124. for i := range handlers {
  125. if handlers[i] == ehi {
  126. s.handlers[t] = append(handlers[:i], handlers[i+1:]...)
  127. }
  128. }
  129. onceHandlers := s.onceHandlers[t]
  130. for i := range onceHandlers {
  131. if onceHandlers[i] == ehi {
  132. s.onceHandlers[t] = append(onceHandlers[:i], handlers[i+1:]...)
  133. }
  134. }
  135. }
  136. // Handles calling permanent and once handlers for an event type.
  137. func (s *Session) handle(t string, i interface{}) {
  138. for _, eh := range s.handlers[t] {
  139. if s.SyncEvents {
  140. eh.eventHandler.Handle(s, i)
  141. } else {
  142. go eh.eventHandler.Handle(s, i)
  143. }
  144. }
  145. if len(s.onceHandlers[t]) > 0 {
  146. for _, eh := range s.onceHandlers[t] {
  147. if s.SyncEvents {
  148. eh.eventHandler.Handle(s, i)
  149. } else {
  150. go eh.eventHandler.Handle(s, i)
  151. }
  152. }
  153. s.onceHandlers[t] = nil
  154. }
  155. }
  156. // Handles an event type by calling internal methods, firing handlers and firing the
  157. // interface{} event.
  158. func (s *Session) handleEvent(t string, i interface{}) {
  159. s.handlersMu.RLock()
  160. defer s.handlersMu.RUnlock()
  161. // All events are dispatched internally first.
  162. s.onInterface(i)
  163. // Then they are dispatched to anyone handling interface{} events.
  164. s.handle(interfaceEventType, i)
  165. // Finally they are dispatched to any typed handlers.
  166. s.handle(t, i)
  167. }
  168. // setGuildIds will set the GuildID on all the members of a guild.
  169. // This is done as event data does not have it set.
  170. func setGuildIds(g *Guild) {
  171. for _, c := range g.Channels {
  172. c.GuildID = g.ID
  173. }
  174. for _, m := range g.Members {
  175. m.GuildID = g.ID
  176. }
  177. for _, vs := range g.VoiceStates {
  178. vs.GuildID = g.ID
  179. }
  180. }
  181. // onInterface handles all internal events and routes them to the appropriate internal handler.
  182. func (s *Session) onInterface(i interface{}) {
  183. switch t := i.(type) {
  184. case *Ready:
  185. for _, g := range t.Guilds {
  186. setGuildIds(g)
  187. }
  188. s.onReady(t)
  189. case *GuildCreate:
  190. setGuildIds(t.Guild)
  191. case *GuildUpdate:
  192. setGuildIds(t.Guild)
  193. case *VoiceServerUpdate:
  194. go s.onVoiceServerUpdate(t)
  195. case *VoiceStateUpdate:
  196. go s.onVoiceStateUpdate(t)
  197. }
  198. err := s.State.OnInterface(s, i)
  199. if err != nil {
  200. s.log(LogDebug, "error dispatching internal event, %s", err)
  201. }
  202. }
  203. // onReady handles the ready event.
  204. func (s *Session) onReady(r *Ready) {
  205. // Store the SessionID within the Session struct.
  206. s.sessionID = r.SessionID
  207. }