Browse Source

Add basic support for mapped event handlers.

Chris Rhodes 9 years ago
parent
commit
fb6ae92555
4 changed files with 424 additions and 403 deletions
  1. 61 1
      discord.go
  2. 28 0
      state.go
  3. 2 0
      structs.go
  4. 333 402
      wsapi.go

+ 61 - 1
discord.go

@@ -13,7 +13,10 @@
 // Package discordgo provides Discord binding for Go
 package discordgo
 
-import "fmt"
+import (
+	"fmt"
+	"reflect"
+)
 
 // VERSION of Discordgo, follows Symantic Versioning. (http://semver.org/)
 const VERSION = "0.11.0-alpha"
@@ -118,3 +121,60 @@ func New(args ...interface{}) (s *Session, err error) {
 
 	return
 }
+
+func (s *Session) AddHandler(handler interface{}) {
+	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)
+
+	if s.Handlers == nil {
+		s.initialize()
+	}
+
+	handlers := s.Handlers[eventType]
+	if handlers == nil {
+		handlers = []interface{}{}
+	}
+
+	handlers = append(handlers, handler)
+	s.Handlers[eventType] = handlers
+}
+
+func (s *Session) Handle(event interface{}) (handled bool) {
+	eventType := reflect.TypeOf(event)
+
+	handlers, ok := s.Handlers[eventType]
+	if !ok {
+		return
+	}
+
+	for _, handler := range handlers {
+		reflect.ValueOf(handler).Call([]reflect.Value{reflect.ValueOf(s), reflect.ValueOf(event)})
+		handled = true
+	}
+
+	return
+}
+
+// initialize adds internal handlers such as onEvent and state tracking
+// handlers.
+func (s *Session) initialize() {
+	s.Handlers = map[interface{}][]interface{}{}
+	s.AddHandler(s.ready)
+	s.AddHandler(s.State.ready)
+	s.AddHandler(s.State.messageCreate)
+	s.AddHandler(s.State.messageUpdate)
+	s.AddHandler(s.State.messageDelete)
+}
+
+func (s *Session) ready(se *Session, r *Ready) {
+	go s.heartbeat(s.wsConn, s.listening, r.HeartbeatInterval)
+}

+ 28 - 0
state.go

@@ -468,3 +468,31 @@ func (s *State) Message(channelID, messageID string) (*Message, error) {
 
 	return nil, errors.New("Message not found.")
 }
+
+// ready is an event handler.
+func (s *State) ready(se *Session, r *Ready) {
+	if se.StateEnabled {
+		s.OnReady(r)
+	}
+}
+
+// messageCreate is an event handler.
+func (s *State) messageCreate(se *Session, m *MessageCreate) {
+	if se.StateEnabled {
+		s.MessageAdd(&m.Message)
+	}
+}
+
+// messageUpdate is an event handler.
+func (s *State) messageUpdate(se *Session, m *MessageUpdate) {
+	if se.StateEnabled {
+		s.MessageAdd(&m.Message)
+	}
+}
+
+// messageDelete is an event handler.
+func (s *State) messageDelete(se *Session, m *MessageDelete) {
+	if se.StateEnabled {
+		s.MessageRemove(&m.Message)
+	}
+}

+ 2 - 0
structs.go

@@ -36,6 +36,8 @@ type Session struct {
 	// This is a good handler to add reconnection logic to.
 	OnDisconnect func(*Session)
 
+	Handlers map[interface{}][]interface{}
+
 	// Settable Callback functions for Websocket Events
 	OnEvent                   func(*Session, *Event)
 	OnReady                   func(*Session, *Ready)

+ 333 - 402
wsapi.go

@@ -247,17 +247,6 @@ func (s *Session) UpdateStatus(idle int, game string) (err error) {
 	return
 }
 
-// Not sure how needed this is and where it would be best to call it.
-// somewhere.
-
-func unmarshalEvent(event *Event, i interface{}) (err error) {
-	if err = unmarshal(event.RawData, i); err != nil {
-		fmt.Println("Unable to unmarshal event data.")
-		printEvent(event)
-	}
-	return
-}
-
 // Front line handler for all Websocket Events.  Determines the
 // event type and passes the message along to the next handler.
 
@@ -266,6 +255,10 @@ func unmarshalEvent(event *Event, i interface{}) (err error) {
 // Events will be handled by any implemented handler in Session.
 // All unhandled events will then be handled by OnEvent.
 func (s *Session) event(messageType int, message []byte) {
+	if s.Handlers == nil {
+		s.initialize()
+	}
+
 	var err error
 	var reader io.Reader
 	reader = bytes.NewBuffer(message)
@@ -296,405 +289,343 @@ func (s *Session) event(messageType int, message []byte) {
 		printEvent(e)
 	}
 
+	var i interface{}
+
 	switch e.Type {
 	case "READY":
-		var st *Ready
-		if err = unmarshalEvent(e, &st); err == nil {
-			go s.heartbeat(s.wsConn, s.listening, st.HeartbeatInterval)
-			if s.StateEnabled {
-				err := s.State.OnReady(st)
-				if err != nil {
-					fmt.Println("error: ", err)
-				}
-
-			}
-			if s.OnReady != nil {
-				s.OnReady(s, st)
-			}
-		}
-		if s.OnReady != nil {
-			return
-		}
-	case "VOICE_SERVER_UPDATE":
-		if s.Voice == nil && s.OnVoiceServerUpdate == nil {
-			break
-		}
-		var st *VoiceServerUpdate
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.Voice != nil {
-				s.onVoiceServerUpdate(st)
-			}
-			if s.OnVoiceServerUpdate != nil {
-				s.OnVoiceServerUpdate(s, st)
-			}
-		}
-		if s.OnVoiceServerUpdate != nil {
-			return
-		}
-	case "VOICE_STATE_UPDATE":
-		if s.Voice == nil && s.OnVoiceStateUpdate == nil {
-			break
-		}
-		var st *VoiceState
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.Voice != nil {
-				s.onVoiceStateUpdate(st)
-			}
-			if s.OnVoiceStateUpdate != nil {
-				s.OnVoiceStateUpdate(s, st)
-			}
-		}
-		if s.OnVoiceStateUpdate != nil {
-			return
-		}
-	case "USER_UPDATE":
-		if s.OnUserUpdate != nil {
-			var st *User
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnUserUpdate(s, st)
-			}
-			return
-		}
-	case "PRESENCE_UPDATE":
-		if s.OnPresenceUpdate != nil {
-			var st *PresenceUpdate
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnPresenceUpdate(s, st)
-			}
-			return
-		}
-	case "TYPING_START":
-		if s.OnTypingStart != nil {
-			var st *TypingStart
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnTypingStart(s, st)
-			}
-			return
-		}
-		/* Never seen this come in but saw it in another Library.
-		case "MESSAGE_ACK":
-			if s.OnMessageAck != nil {
-			}
-		*/
+		i = &Ready{}
 	case "MESSAGE_CREATE":
-		stateEnabled := s.StateEnabled && s.State.MaxMessageCount > 0
-		if !stateEnabled && s.OnMessageCreate == nil {
-			break
-		}
-		var st *Message
-		if err = unmarshalEvent(e, &st); err == nil {
-			if stateEnabled {
-				err := s.State.MessageAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnMessageCreate != nil {
-				s.OnMessageCreate(s, st)
-			}
-		}
-		if s.OnMessageCreate != nil {
-			return
-		}
+		i = &MessageCreate{}
 	case "MESSAGE_UPDATE":
-		stateEnabled := s.StateEnabled && s.State.MaxMessageCount > 0
-		if !stateEnabled && s.OnMessageUpdate == nil {
-			break
-		}
-		var st *Message
-		if err = unmarshalEvent(e, &st); err == nil {
-			if stateEnabled {
-				err := s.State.MessageAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnMessageUpdate != nil {
-				s.OnMessageUpdate(s, st)
-			}
-		}
-		return
+		i = &MessageUpdate{}
 	case "MESSAGE_DELETE":
-		stateEnabled := s.StateEnabled && s.State.MaxMessageCount > 0
-		if !stateEnabled && s.OnMessageDelete == nil {
-			break
-		}
-		var st *Message
-		if err = unmarshalEvent(e, &st); err == nil {
-			if stateEnabled {
-				err := s.State.MessageRemove(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnMessageDelete != nil {
-				s.OnMessageDelete(s, st)
-			}
-		}
-		return
-	case "MESSAGE_ACK":
-		if s.OnMessageAck != nil {
-			var st *MessageAck
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnMessageAck(s, st)
-			}
-			return
-		}
-	case "CHANNEL_CREATE":
-		if !s.StateEnabled && s.OnChannelCreate == nil {
-			break
-		}
-		var st *Channel
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.ChannelAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnChannelCreate != nil {
-				s.OnChannelCreate(s, st)
-			}
-		}
-		if s.OnChannelCreate != nil {
-			return
-		}
-	case "CHANNEL_UPDATE":
-		if !s.StateEnabled && s.OnChannelUpdate == nil {
-			break
-		}
-		var st *Channel
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.ChannelAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnChannelUpdate != nil {
-				s.OnChannelUpdate(s, st)
-			}
-		}
-		if s.OnChannelUpdate != nil {
-			return
-		}
-	case "CHANNEL_DELETE":
-		if !s.StateEnabled && s.OnChannelDelete == nil {
-			break
-		}
-		var st *Channel
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.ChannelRemove(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnChannelDelete != nil {
-				s.OnChannelDelete(s, st)
-			}
-		}
-		if s.OnChannelDelete != nil {
-			return
-		}
-	case "GUILD_CREATE":
-		if !s.StateEnabled && s.OnGuildCreate == nil {
-			break
-		}
-		var st *Guild
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.GuildAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnGuildCreate != nil {
-				s.OnGuildCreate(s, st)
-			}
-		}
-		if s.OnGuildCreate != nil {
-			return
-		}
-	case "GUILD_UPDATE":
-		if !s.StateEnabled && s.OnGuildUpdate == nil {
-			break
-		}
-		var st *Guild
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.GuildAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnGuildCreate != nil {
-				s.OnGuildUpdate(s, st)
-			}
-		}
-		if s.OnGuildUpdate != nil {
-			return
-		}
-	case "GUILD_DELETE":
-		if !s.StateEnabled && s.OnGuildDelete == nil {
-			break
-		}
-		var st *Guild
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.GuildRemove(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnGuildDelete != nil {
-				s.OnGuildDelete(s, st)
-			}
-		}
-		if s.OnGuildDelete != nil {
-			return
-		}
-	case "GUILD_MEMBER_ADD":
-		if !s.StateEnabled && s.OnGuildMemberAdd == nil {
-			break
-		}
-		var st *Member
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.MemberAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnGuildMemberAdd != nil {
-				s.OnGuildMemberAdd(s, st)
-			}
-		}
-		if s.OnGuildMemberAdd != nil {
-			return
-		}
-	case "GUILD_MEMBER_REMOVE":
-		if !s.StateEnabled && s.OnGuildMemberRemove == nil {
-			break
-		}
-		var st *Member
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.MemberRemove(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnGuildMemberRemove != nil {
-				s.OnGuildMemberRemove(s, st)
-			}
-		}
-		if s.OnGuildMemberRemove != nil {
-			return
-		}
-	case "GUILD_MEMBER_UPDATE":
-		if !s.StateEnabled && s.OnGuildMemberUpdate == nil {
-			break
-		}
-		var st *Member
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.MemberAdd(st)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnGuildMemberUpdate != nil {
-				s.OnGuildMemberUpdate(s, st)
-			}
-		}
-		if s.OnGuildMemberUpdate != nil {
-			return
-		}
-	case "GUILD_ROLE_CREATE":
-		if s.OnGuildRoleCreate != nil {
-			var st *GuildRole
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnGuildRoleCreate(s, st)
-			}
-			return
-		}
-	case "GUILD_ROLE_UPDATE":
-		if s.OnGuildRoleUpdate != nil {
-			var st *GuildRole
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnGuildRoleUpdate(s, st)
-			}
-			return
-		}
-	case "GUILD_ROLE_DELETE":
-		if s.OnGuildRoleDelete != nil {
-			var st *GuildRoleDelete
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnGuildRoleDelete(s, st)
-			}
-			return
-		}
-	case "GUILD_INTEGRATIONS_UPDATE":
-		if s.OnGuildIntegrationsUpdate != nil {
-			var st *GuildIntegrationsUpdate
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnGuildIntegrationsUpdate(s, st)
-			}
-			return
-		}
-	case "GUILD_BAN_ADD":
-		if s.OnGuildBanAdd != nil {
-			var st *GuildBan
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnGuildBanAdd(s, st)
-			}
-			return
-		}
-	case "GUILD_BAN_REMOVE":
-		if s.OnGuildBanRemove != nil {
-			var st *GuildBan
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnGuildBanRemove(s, st)
-			}
-			return
-		}
-	case "GUILD_EMOJIS_UPDATE":
-		if !s.StateEnabled && s.OnGuildEmojisUpdate == nil {
-			break
-		}
-		var st *GuildEmojisUpdate
-		if err = unmarshalEvent(e, &st); err == nil {
-			if s.StateEnabled {
-				err := s.State.EmojisAdd(st.GuildID, st.Emojis)
-				if err != nil {
-					fmt.Println("error :", err)
-				}
-			}
-			if s.OnGuildEmojisUpdate != nil {
-				s.OnGuildEmojisUpdate(s, st)
-			}
-		}
-		if s.OnGuildEmojisUpdate != nil {
-			return
-		}
-	case "USER_SETTINGS_UPDATE":
-		if s.OnUserSettingsUpdate != nil {
-			var st map[string]interface{}
-			if err = unmarshalEvent(e, &st); err == nil {
-				s.OnUserSettingsUpdate(s, st)
-			}
-			return
-		}
-	default:
-		fmt.Println("Unknown Event.")
+		i = &MessageDelete{}
+	case "PRESENCE_UPDATE":
+		i = &PresenceUpdate{}
+	case "TYPING_START":
+		i = &TypingStart{}
+	}
+
+	// case "VOICE_SERVER_UPDATE":
+	// 	if s.Voice == nil && s.OnVoiceServerUpdate == nil {
+	// 		break
+	// 	}
+	// 	var st *VoiceServerUpdate
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.Voice != nil {
+	// 			s.onVoiceServerUpdate(st)
+	// 		}
+	// 		if s.OnVoiceServerUpdate != nil {
+	// 			s.OnVoiceServerUpdate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnVoiceServerUpdate != nil {
+	// 		return
+	// 	}
+	// case "VOICE_STATE_UPDATE":
+	// 	if s.Voice == nil && s.OnVoiceStateUpdate == nil {
+	// 		break
+	// 	}
+	// 	var st *VoiceState
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.Voice != nil {
+	// 			s.onVoiceStateUpdate(st)
+	// 		}
+	// 		if s.OnVoiceStateUpdate != nil {
+	// 			s.OnVoiceStateUpdate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnVoiceStateUpdate != nil {
+	// 		return
+	// 	}
+	// case "USER_UPDATE":
+	// 	if s.OnUserUpdate != nil {
+	// 		var st *User
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnUserUpdate(s, st)
+	// 		}
+	// 		return
+	// 	}
+
+	// 	/* Never seen this come in but saw it in another Library.
+	// 	case "MESSAGE_ACK":
+	// 		if s.OnMessageAck != nil {
+	// 		}
+	// 	*/
+
+	// case "MESSAGE_ACK":
+	// 	if s.OnMessageAck != nil {
+	// 		var st *MessageAck
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnMessageAck(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// case "CHANNEL_CREATE":
+	// 	if !s.StateEnabled && s.OnChannelCreate == nil {
+	// 		break
+	// 	}
+	// 	var st *Channel
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.ChannelAdd(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnChannelCreate != nil {
+	// 			s.OnChannelCreate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnChannelCreate != nil {
+	// 		return
+	// 	}
+	// case "CHANNEL_UPDATE":
+	// 	if !s.StateEnabled && s.OnChannelUpdate == nil {
+	// 		break
+	// 	}
+	// 	var st *Channel
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.ChannelAdd(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnChannelUpdate != nil {
+	// 			s.OnChannelUpdate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnChannelUpdate != nil {
+	// 		return
+	// 	}
+	// case "CHANNEL_DELETE":
+	// 	if !s.StateEnabled && s.OnChannelDelete == nil {
+	// 		break
+	// 	}
+	// 	var st *Channel
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.ChannelRemove(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnChannelDelete != nil {
+	// 			s.OnChannelDelete(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnChannelDelete != nil {
+	// 		return
+	// 	}
+	// case "GUILD_CREATE":
+	// 	if !s.StateEnabled && s.OnGuildCreate == nil {
+	// 		break
+	// 	}
+	// 	var st *Guild
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.GuildAdd(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnGuildCreate != nil {
+	// 			s.OnGuildCreate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnGuildCreate != nil {
+	// 		return
+	// 	}
+	// case "GUILD_UPDATE":
+	// 	if !s.StateEnabled && s.OnGuildUpdate == nil {
+	// 		break
+	// 	}
+	// 	var st *Guild
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.GuildAdd(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnGuildCreate != nil {
+	// 			s.OnGuildUpdate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnGuildUpdate != nil {
+	// 		return
+	// 	}
+	// case "GUILD_DELETE":
+	// 	if !s.StateEnabled && s.OnGuildDelete == nil {
+	// 		break
+	// 	}
+	// 	var st *Guild
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.GuildRemove(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnGuildDelete != nil {
+	// 			s.OnGuildDelete(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnGuildDelete != nil {
+	// 		return
+	// 	}
+	// case "GUILD_MEMBER_ADD":
+	// 	if !s.StateEnabled && s.OnGuildMemberAdd == nil {
+	// 		break
+	// 	}
+	// 	var st *Member
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.MemberAdd(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnGuildMemberAdd != nil {
+	// 			s.OnGuildMemberAdd(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnGuildMemberAdd != nil {
+	// 		return
+	// 	}
+	// case "GUILD_MEMBER_REMOVE":
+	// 	if !s.StateEnabled && s.OnGuildMemberRemove == nil {
+	// 		break
+	// 	}
+	// 	var st *Member
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.MemberRemove(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnGuildMemberRemove != nil {
+	// 			s.OnGuildMemberRemove(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnGuildMemberRemove != nil {
+	// 		return
+	// 	}
+	// case "GUILD_MEMBER_UPDATE":
+	// 	if !s.StateEnabled && s.OnGuildMemberUpdate == nil {
+	// 		break
+	// 	}
+	// 	var st *Member
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.MemberAdd(st)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnGuildMemberUpdate != nil {
+	// 			s.OnGuildMemberUpdate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnGuildMemberUpdate != nil {
+	// 		return
+	// 	}
+	// case "GUILD_ROLE_CREATE":
+	// 	if s.OnGuildRoleCreate != nil {
+	// 		var st *GuildRole
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnGuildRoleCreate(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// case "GUILD_ROLE_UPDATE":
+	// 	if s.OnGuildRoleUpdate != nil {
+	// 		var st *GuildRole
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnGuildRoleUpdate(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// case "GUILD_ROLE_DELETE":
+	// 	if s.OnGuildRoleDelete != nil {
+	// 		var st *GuildRoleDelete
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnGuildRoleDelete(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// case "GUILD_INTEGRATIONS_UPDATE":
+	// 	if s.OnGuildIntegrationsUpdate != nil {
+	// 		var st *GuildIntegrationsUpdate
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnGuildIntegrationsUpdate(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// case "GUILD_BAN_ADD":
+	// 	if s.OnGuildBanAdd != nil {
+	// 		var st *GuildBan
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnGuildBanAdd(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// case "GUILD_BAN_REMOVE":
+	// 	if s.OnGuildBanRemove != nil {
+	// 		var st *GuildBan
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnGuildBanRemove(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// case "GUILD_EMOJIS_UPDATE":
+	// 	if !s.StateEnabled && s.OnGuildEmojisUpdate == nil {
+	// 		break
+	// 	}
+	// 	var st *GuildEmojisUpdate
+	// 	if err = unmarshalEvent(e, &st); err == nil {
+	// 		if s.StateEnabled {
+	// 			err := s.State.EmojisAdd(st.GuildID, st.Emojis)
+	// 			if err != nil {
+	// 				fmt.Println("error :", err)
+	// 			}
+	// 		}
+	// 		if s.OnGuildEmojisUpdate != nil {
+	// 			s.OnGuildEmojisUpdate(s, st)
+	// 		}
+	// 	}
+	// 	if s.OnGuildEmojisUpdate != nil {
+	// 		return
+	// 	}
+	// case "USER_SETTINGS_UPDATE":
+	// 	if s.OnUserSettingsUpdate != nil {
+	// 		var st map[string]interface{}
+	// 		if err = unmarshalEvent(e, &st); err == nil {
+	// 			s.OnUserSettingsUpdate(s, st)
+	// 		}
+	// 		return
+	// 	}
+	// default:
+	// 	fmt.Println("Unknown Event.")
+	// 	printEvent(e)
+	// }
+
+	// Attempt to unmarshal our event.
+	// If there is an error (eg. we don't know how to handle it) we should handle the event itself.
+	if err = unmarshal(e.RawData, i); err != nil {
+		fmt.Println("Unable to unmarshal event data.")
 		printEvent(e)
+		i = e
 	}
 
-	// if still here, send to generic OnEvent
-	if s.OnEvent != nil {
-		s.OnEvent(s, e)
-		return
+	if !s.Handle(i) {
+		if i != e {
+			// If there was not a handler for the struct, handle the event, as long as it wasn't the
+			// event we were trying to handle.
+			s.Handle(e)
+		}
 	}
 
 	return