diff --git a/gateway/ready.go b/gateway/ready.go index 192c171..1608100 100644 --- a/gateway/ready.go +++ b/gateway/ready.go @@ -26,7 +26,7 @@ type ( ReadStates []ReadState `json:"read_state,omitempty"` UserGuildSettings []UserGuildSetting `json:"user_guild_settings,omitempty"` Relationships []discord.Relationship `json:"relationships,omitempty"` - MergedMembers [][]SupplementalMember `json:"merged_members,omitempty"` + Presences []Presence `json:"presences,omitempty"` FriendSuggestionCount int `json:"friend_suggestion_count,omitempty"` GeoOrderedRTCRegions []string `json:"geo_ordered_rtc_regions,omitempty"` @@ -64,6 +64,8 @@ type ( ContactSync bool `json:"contact_sync_enabled"` NativePhoneIntegration bool `json:"native_phone_integration_enabled"` + TimezoneOffset int `json:"timezone_offset"` + Locale string `json:"locale"` Theme string `json:"theme"` @@ -126,27 +128,6 @@ type ( Color discord.Color `json:"color"` } - // SupplementalMember is the struct for a member in the MergedMembers field - // of ReadySupplementalEvent. It has slight differences to discord.Member. - SupplementalMember struct { - UserID discord.UserID `json:"user_id"` - Nick string `json:"nick,omitempty"` - RoleIDs []discord.RoleID `json:"roles"` - - GuildID discord.GuildID `json:"guild_id,omitempty"` - IsPending bool `json:"is_pending,omitempty"` - HoistedRole discord.RoleID `json:"hoisted_role"` - - Mute bool `json:"mute"` - Deaf bool `json:"deaf"` - - // Joined specifies when the user joined the guild. - Joined discord.Timestamp `json:"joined_at"` - - // BoostedSince specifies when the user started boosting the guild. - BoostedSince discord.Timestamp `json:"premium_since,omitempty"` - } - // FriendSourceFlags describes sources that friend requests could be sent // from. It belongs to the UserSettings struct and is undocumented. FriendSourceFlags struct { @@ -195,7 +176,8 @@ func (g GuildFolderID) MarshalJSON() ([]byte, error) { return []byte(strconv.FormatInt(int64(g), 10)), nil } -// ReadySupplemental event structs. +// ReadySupplemental event structs. For now, this event is never used, and its +// usage have yet been discovered. type ( // ReadySupplementalEvent is the struct for a READY_SUPPLEMENTAL event, // which is an undocumented event. @@ -205,6 +187,27 @@ type ( MergedPresences MergedPresences `json:"merged_presences"` } + // SupplementalMember is the struct for a member in the MergedMembers field + // of ReadySupplementalEvent. It has slight differences to discord.Member. + SupplementalMember struct { + UserID discord.UserID `json:"user_id"` + Nick string `json:"nick,omitempty"` + RoleIDs []discord.RoleID `json:"roles"` + + GuildID discord.GuildID `json:"guild_id,omitempty"` + IsPending bool `json:"is_pending,omitempty"` + HoistedRole discord.RoleID `json:"hoisted_role"` + + Mute bool `json:"mute"` + Deaf bool `json:"deaf"` + + // Joined specifies when the user joined the guild. + Joined discord.Timestamp `json:"joined_at"` + + // BoostedSince specifies when the user started boosting the guild. + BoostedSince discord.Timestamp `json:"premium_since,omitempty"` + } + // MergedPresences is the struct for presences of guilds' members and // friends. It is undocumented. MergedPresences struct { diff --git a/state/state_events.go b/state/state_events.go index d82c397..ba856f4 100644 --- a/state/state_events.go +++ b/state/state_events.go @@ -51,14 +51,15 @@ func (s *State) hookSession() { func (s *State) onEvent(iface interface{}) { switch ev := iface.(type) { case *gateway.ReadyEvent: - // Acquire the ready mutex for the rest of these update calls, as they - // will be accessing ready's fields. + // Acquire the ready mutex, but since we're only writing the value and + // not anything in it, we should be fine. s.readyMu.Lock() s.ready = *ev + s.readyMu.Unlock() // Reset the store before proceeding. if err := s.Cabinet.Reset(); err != nil { - s.stateErr(err, "failed to reset state on READY") + s.stateErr(err, "failed to reset state in Ready") } // Handle guilds @@ -66,21 +67,25 @@ func (s *State) onEvent(iface interface{}) { s.batchLog(storeGuildCreate(s.Cabinet, &ev.Guilds[i])) } + // Handle guild presences + for _, p := range ev.Presences { + if err := s.Cabinet.PresenceSet(p.GuildID, p); err != nil { + s.stateErr(err, "failed to set presence in Ready") + } + } + // Handle private channels for _, ch := range ev.PrivateChannels { if err := s.Cabinet.ChannelSet(ch); err != nil { - s.stateErr(err, "failed to set channel in state") + s.stateErr(err, "failed to set channel in Ready") } } // Handle user if err := s.Cabinet.MyselfSet(ev.User); err != nil { - s.stateErr(err, "failed to set self in state") + s.stateErr(err, "failed to set self in Ready") } - // Release the ready mutex only after we're done with everything. - s.readyMu.Unlock() - case *gateway.ReadySupplementalEvent: // Handle guilds for _, guild := range ev.Guilds {