Pārlūkot izejas kodu

Add Presence Tracking to State (#371)

* Add Presence tracking to the state

* Do not need to check if Roles and Game is nil

* Append presence to guild.Presences if not found
Rinzen Necroforger 7 gadi atpakaļ
vecāks
revīzija
f539136306
1 mainītis faili ar 149 papildinājumiem un 7 dzēšanām
  1. 149 7
      state.go

+ 149 - 7
state.go

@@ -34,6 +34,7 @@ type State struct {
 	TrackMembers    bool
 	TrackMembers    bool
 	TrackRoles      bool
 	TrackRoles      bool
 	TrackVoice      bool
 	TrackVoice      bool
+	TrackPresences  bool
 
 
 	guildMap   map[string]*Guild
 	guildMap   map[string]*Guild
 	channelMap map[string]*Channel
 	channelMap map[string]*Channel
@@ -46,13 +47,14 @@ func NewState() *State {
 			PrivateChannels: []*Channel{},
 			PrivateChannels: []*Channel{},
 			Guilds:          []*Guild{},
 			Guilds:          []*Guild{},
 		},
 		},
-		TrackChannels: true,
+		TrackChannels:  true,
-		TrackEmojis:   true,
+		TrackEmojis:    true,
-		TrackMembers:  true,
+		TrackMembers:   true,
-		TrackRoles:    true,
+		TrackRoles:     true,
-		TrackVoice:    true,
+		TrackVoice:     true,
-		guildMap:      make(map[string]*Guild),
+		TrackPresences: true,
-		channelMap:    make(map[string]*Channel),
+		guildMap:       make(map[string]*Guild),
+		channelMap:     make(map[string]*Channel),
 	}
 	}
 }
 }
 
 
@@ -147,6 +149,107 @@ func (s *State) Guild(guildID string) (*Guild, error) {
 	return nil, errors.New("guild not found")
 	return nil, errors.New("guild not found")
 }
 }
 
 
+// PresenceAdd adds a presence to the current world state, or
+// updates it if it already exists.
+func (s *State) PresenceAdd(guildID string, presence *Presence) error {
+	if s == nil {
+		return ErrNilState
+	}
+
+	guild, err := s.Guild(guildID)
+	if err != nil {
+		return err
+	}
+
+	s.Lock()
+	defer s.Unlock()
+
+	for i, p := range guild.Presences {
+		if p.User.ID == presence.User.ID {
+			//guild.Presences[i] = presence
+
+			//Update status
+			guild.Presences[i].Game = presence.Game
+			guild.Presences[i].Roles = presence.Roles
+			if presence.Status != "" {
+				guild.Presences[i].Status = presence.Status
+			}
+			if presence.Nick != "" {
+				guild.Presences[i].Nick = presence.Nick
+			}
+
+			//Update the optionally sent user information
+			//ID Is a mandatory field so you should not need to check if it is empty
+			guild.Presences[i].User.ID = presence.User.ID
+
+			if presence.User.Avatar != "" {
+				guild.Presences[i].User.Avatar = presence.User.Avatar
+			}
+			if presence.User.Discriminator != "" {
+				guild.Presences[i].User.Discriminator = presence.User.Discriminator
+			}
+			if presence.User.Email != "" {
+				guild.Presences[i].User.Email = presence.User.Email
+			}
+			if presence.User.Token != "" {
+				guild.Presences[i].User.Token = presence.User.Token
+			}
+			if presence.User.Username != "" {
+				guild.Presences[i].User.Username = presence.User.Username
+			}
+
+			return nil
+		}
+	}
+
+	guild.Presences = append(guild.Presences, presence)
+	return nil
+}
+
+// PresenceRemove removes a presence from the current world state.
+func (s *State) PresenceRemove(guildID string, presence *Presence) error {
+	if s == nil {
+		return ErrNilState
+	}
+
+	guild, err := s.Guild(guildID)
+	if err != nil {
+		return err
+	}
+
+	s.Lock()
+	defer s.Unlock()
+
+	for i, p := range guild.Presences {
+		if p.User.ID == presence.User.ID {
+			guild.Presences = append(guild.Presences[:i], guild.Presences[i+1:]...)
+			return nil
+		}
+	}
+
+	return errors.New("presence not found")
+}
+
+// Presence gets a presence by ID from a guild.
+func (s *State) Presence(guildID, userID string) (*Presence, error) {
+	if s == nil {
+		return nil, ErrNilState
+	}
+
+	guild, err := s.Guild(guildID)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, p := range guild.Presences {
+		if p.User.ID == userID {
+			return p, nil
+		}
+	}
+
+	return nil, errors.New("presence not found")
+}
+
 // TODO: Consider moving Guild state update methods onto *Guild.
 // TODO: Consider moving Guild state update methods onto *Guild.
 
 
 // MemberAdd adds a member to the current world state, or
 // MemberAdd adds a member to the current world state, or
@@ -725,6 +828,45 @@ func (s *State) onInterface(se *Session, i interface{}) (err error) {
 		if s.TrackVoice {
 		if s.TrackVoice {
 			err = s.voiceStateUpdate(t)
 			err = s.voiceStateUpdate(t)
 		}
 		}
+	case *PresenceUpdate:
+		if s.TrackPresences {
+			s.PresenceAdd(t.GuildID, &t.Presence)
+		}
+		if s.TrackMembers {
+			if t.Status == StatusOffline {
+				return
+			}
+
+			var m *Member
+			m, err = s.Member(t.GuildID, t.User.ID)
+
+			if err != nil {
+				// Member not found; this is a user coming online
+				m = &Member{
+					GuildID: t.GuildID,
+					Nick:    t.Nick,
+					User:    t.User,
+					Roles:   t.Roles,
+				}
+
+			} else {
+
+				if t.Nick != "" {
+					m.Nick = t.Nick
+				}
+
+				if t.User.Username != "" {
+					m.User.Username = t.User.Username
+				}
+
+				// PresenceUpdates always contain a list of roles, so there's no need to check for an empty list here
+				m.Roles = t.Roles
+
+			}
+
+			err = s.MemberAdd(m)
+		}
+
 	}
 	}
 
 
 	return
 	return