From 28ddf0f5871b6e4906cdad7b4722f52a3b080e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Skocze=C5=84?= Date: Sat, 22 Oct 2022 11:51:58 +0200 Subject: [PATCH] Streamlined presence requests --- event.go | 30 +++++++++++++++--------------- wsapi.go | 49 ++++++++++++++++++++++++++----------------------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/event.go b/event.go index ab5e8a9e3..e29efe5bf 100644 --- a/event.go +++ b/event.go @@ -1,6 +1,8 @@ package discordgo -import "time" +import ( + "time" +) // EventHandler is an interface for Discord events. type EventHandler interface { @@ -252,23 +254,21 @@ func (s *Session) onReady(r *Ready) { func (s *Session) handlePresenceRequests(chunk *GuildMembersChunk) { data, ok := s.gatewayRequests.Load(chunk.Nonce) if ok { - data := data.(requestData) - if len(chunk.Presences) > 0 { - data.Presence = chunk.Presences[0] + response := responseData{} + if len(chunk.NotFound) == 0 { + response.Found = true + if len(chunk.Presences) > 0 { + response.Presence = chunk.Presences[0] + } } - now := time.Now().UTC().Unix() - data.Handled = &now - s.gatewayRequests.Store(chunk.Nonce, data) - data.Channel <- 1 + data.(requestData).Channel <- response + s.gatewayRequests.Delete(chunk.Nonce) } s.gatewayRequests.Range(func(key, value any) bool { // Cleanup - v := value.(requestData) - if v.Handled != nil { - now := time.Now().UTC().Unix() - diff := now - *v.Handled - if diff > 60 { - s.gatewayRequests.Delete(key) - } + now := time.Now().UTC().Unix() + diff := now - value.(requestData).Created + if diff > 10 { + s.gatewayRequests.Delete(key) } return true }) diff --git a/wsapi.go b/wsapi.go index f9e703986..dbdd4403f 100644 --- a/wsapi.go +++ b/wsapi.go @@ -17,6 +17,7 @@ import ( "errors" "fmt" "io" + "log" "math/rand" "net/http" "runtime" @@ -452,11 +453,13 @@ func (s *Session) RequestGuildMembers(guildID, query string, limit int) (err err } type requestData struct { - Nonce string - UserID string + Created int64 // unix timestamp + Channel chan responseData +} + +type responseData struct { + Found bool Presence *Presence - Handled *int64 // unix timestamp - Channel chan int } const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -469,11 +472,12 @@ func getRandomNonce() string { return string(out) } -func (s *Session) RequestPresence(guildId, userId string) (data requestData, err error) { - data = requestData{ - Nonce: getRandomNonce(), - UserID: userId, - Channel: make(chan int), +func (s *Session) RequestPresence(guildId, userId string) (chan responseData, error) { + nonce := getRandomNonce() + log.Println("Nonce:", nonce) + data := requestData{ + Created: time.Now().UTC().Unix(), + Channel: make(chan responseData), } req := struct { @@ -481,18 +485,22 @@ func (s *Session) RequestPresence(guildId, userId string) (data requestData, err UID string `json:"user_ids"` NON string `json:"nonce"` PRE bool `json:"presences"` - }{guildId, userId, data.Nonce, true} + }{guildId, userId, nonce, true} - s.gatewayRequests.Store(data.Nonce, data) + s.gatewayRequests.Store(nonce, data) s.wsMutex.Lock() - err = s.wsConn.WriteJSON(map[string]any{"op": 8, "d": req}) + err := s.wsConn.WriteJSON(map[string]any{"op": 8, "d": req}) s.wsMutex.Unlock() - return + if err != nil { + s.gatewayRequests.Delete(nonce) + return nil, err + } + return data.Channel, nil } func (s *Session) GetMemberPresence(guildId, userId string) (*Presence, error) { - data, err := s.RequestPresence(guildId, userId) + channel, err := s.RequestPresence(guildId, userId) if err != nil { return nil, err } @@ -501,16 +509,11 @@ func (s *Session) GetMemberPresence(guildId, userId string) (*Presence, error) { select { case <-timeout.C: return nil, fmt.Errorf("Timed out getting member presence") - case <-data.Channel: - presence, ok := s.gatewayRequests.Load(data.Nonce) - if ok { - presence := presence.(requestData) - if presence.Handled != nil && presence.Presence != nil { - s.gatewayRequests.Delete(data.Nonce) - return presence.Presence, nil - } + case presence := <-channel: + if presence.Found { + return presence.Presence, nil // Return nil to indicate offline } - return nil, fmt.Errorf("Failed to get member presence data") + return nil, fmt.Errorf("Member not found") } }