From 8d082865da5dbde23c47e560a5fe2a38cf7b3af1 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Sun, 17 Mar 2024 11:42:39 -0400 Subject: [PATCH] fix #2133 (#2137) * fix #2133 Don't record NICK and QUIT in history for invisible auditorium members --- irc/channel.go | 20 ++++++++++++++++++++ irc/client.go | 9 ++++++--- irc/nickname.go | 4 +++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/irc/channel.go b/irc/channel.go index 586d80d1..c6807a5c 100644 --- a/irc/channel.go +++ b/irc/channel.go @@ -1622,6 +1622,26 @@ func (channel *Channel) auditoriumFriends(client *Client) (friends []*Client) { return } +// returns whether the client is visible to unprivileged users in the channel +// (i.e., respecting auditorium mode). note that this assumes that the client +// is a member; if the client is not, it may return true anyway +func (channel *Channel) memberIsVisible(client *Client) bool { + // fast path, we assume they're a member so if this isn't an auditorium, + // they're visible: + if !channel.flags.HasMode(modes.Auditorium) { + return true + } + + channel.stateMutex.RLock() + defer channel.stateMutex.RUnlock() + + clientData, found := channel.members[client] + if !found { + return false + } + return clientData.modes.HighestChannelUserMode() != modes.Mode(0) +} + // data for RPL_LIST func (channel *Channel) listData() (memberCount int, name, topic string) { channel.stateMutex.RLock() diff --git a/irc/client.go b/irc/client.go index cc303e71..47aca273 100644 --- a/irc/client.go +++ b/irc/client.go @@ -1297,10 +1297,10 @@ func (client *Client) destroy(session *Session) { } var quitItem history.Item - var channels []*Channel + var quitHistoryChannels []*Channel // use a defer here to avoid writing to mysql while holding the destroy semaphore: defer func() { - for _, channel := range channels { + for _, channel := range quitHistoryChannels { channel.AddHistoryItem(quitItem, details.account) } }() @@ -1322,8 +1322,11 @@ func (client *Client) destroy(session *Session) { // clean up channels // (note that if this is a reattach, client has no channels and therefore no friends) friends := make(ClientSet) - channels = client.Channels() + channels := client.Channels() for _, channel := range channels { + if channel.memberIsVisible(client) { + quitHistoryChannels = append(quitHistoryChannels, channel) + } for _, member := range channel.auditoriumFriends(client) { friends.Add(member) } diff --git a/irc/nickname.go b/irc/nickname.go index b180c005..9373871d 100644 --- a/irc/nickname.go +++ b/irc/nickname.go @@ -120,7 +120,9 @@ func performNickChange(server *Server, client *Client, target *Client, session * } for _, channel := range target.Channels() { - channel.AddHistoryItem(histItem, details.account) + if channel.memberIsVisible(client) { + channel.AddHistoryItem(histItem, details.account) + } } newCfnick := target.NickCasefolded()