forked from External/ergo
fix #484
This commit is contained in:
parent
4a7ca14bdc
commit
8c99dcb2c7
6 changed files with 102 additions and 30 deletions
104
irc/channel.go
104
irc/channel.go
|
|
@ -439,8 +439,12 @@ func (channel *Channel) regenerateMembersCache() {
|
|||
|
||||
// Names sends the list of users joined to the channel to the given client.
|
||||
func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
||||
isJoined := channel.hasClient(client)
|
||||
channel.stateMutex.RLock()
|
||||
clientModes, isJoined := channel.members[client]
|
||||
channel.stateMutex.RUnlock()
|
||||
isOper := client.HasMode(modes.Operator)
|
||||
respectAuditorium := channel.flags.HasMode(modes.Auditorium) && !isOper &&
|
||||
(!isJoined || clientModes.HighestChannelUserMode() == modes.Mode(0))
|
||||
isMultiPrefix := rb.session.capabilities.Has(caps.MultiPrefix)
|
||||
isUserhostInNames := rb.session.capabilities.Has(caps.UserhostInNames)
|
||||
|
||||
|
|
@ -464,6 +468,9 @@ func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
|||
if !isJoined && target.HasMode(modes.Invisible) && !isOper {
|
||||
continue
|
||||
}
|
||||
if respectAuditorium && modeSet.HighestChannelUserMode() == modes.Mode(0) {
|
||||
continue
|
||||
}
|
||||
prefix := modeSet.Prefixes(isMultiPrefix)
|
||||
if buffer.Len()+len(nick)+len(prefix)+1 > maxNamLen {
|
||||
namesLines = append(namesLines, buffer.String())
|
||||
|
|
@ -748,8 +755,9 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
|
|||
}()
|
||||
|
||||
var message utils.SplitMessage
|
||||
respectAuditorium := givenMode == modes.Mode(0) && channel.flags.HasMode(modes.Auditorium)
|
||||
// no history item for fake persistent joins
|
||||
if rb != nil {
|
||||
if rb != nil && !respectAuditorium {
|
||||
message = utils.MakeMessage("")
|
||||
histItem := history.Item{
|
||||
Type: history.Join,
|
||||
|
|
@ -772,6 +780,14 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
|
|||
|
||||
isAway, awayMessage := client.Away()
|
||||
for _, member := range channel.Members() {
|
||||
if respectAuditorium {
|
||||
channel.stateMutex.RLock()
|
||||
memberModes, ok := channel.members[member]
|
||||
channel.stateMutex.RUnlock()
|
||||
if !ok || memberModes.HighestChannelUserMode() == modes.Mode(0) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
for _, session := range member.Sessions() {
|
||||
if session == rb.session {
|
||||
continue
|
||||
|
|
@ -889,8 +905,12 @@ func (channel *Channel) playJoinForSession(session *Session) {
|
|||
|
||||
// Part parts the given client from this channel, with the given message.
|
||||
func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer) {
|
||||
chname := channel.Name()
|
||||
if !channel.hasClient(client) {
|
||||
channel.stateMutex.RLock()
|
||||
chname := channel.name
|
||||
clientModes, ok := channel.members[client]
|
||||
channel.stateMutex.RUnlock()
|
||||
|
||||
if !ok {
|
||||
rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.Nick(), chname, client.t("You're not on that channel"))
|
||||
return
|
||||
}
|
||||
|
|
@ -905,7 +925,17 @@ func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer)
|
|||
if message != "" {
|
||||
params = append(params, message)
|
||||
}
|
||||
respectAuditorium := channel.flags.HasMode(modes.Auditorium) &&
|
||||
clientModes.HighestChannelUserMode() == modes.Mode(0)
|
||||
for _, member := range channel.Members() {
|
||||
if respectAuditorium {
|
||||
channel.stateMutex.RLock()
|
||||
memberModes, ok := channel.members[member]
|
||||
channel.stateMutex.RUnlock()
|
||||
if !ok || memberModes.HighestChannelUserMode() == modes.Mode(0) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
member.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
|
||||
}
|
||||
rb.AddFromClient(splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
|
||||
|
|
@ -915,12 +945,14 @@ func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer)
|
|||
}
|
||||
}
|
||||
|
||||
channel.AddHistoryItem(history.Item{
|
||||
Type: history.Part,
|
||||
Nick: details.nickMask,
|
||||
AccountName: details.accountName,
|
||||
Message: splitMessage,
|
||||
}, details.account)
|
||||
if !respectAuditorium {
|
||||
channel.AddHistoryItem(history.Item{
|
||||
Type: history.Part,
|
||||
Nick: details.nickMask,
|
||||
AccountName: details.accountName,
|
||||
Message: splitMessage,
|
||||
}, details.account)
|
||||
}
|
||||
|
||||
client.server.logger.Debug("part", fmt.Sprintf("%s left channel %s", details.nick, chname))
|
||||
}
|
||||
|
|
@ -951,20 +983,24 @@ func (channel *Channel) resumeAndAnnounce(session *Session) {
|
|||
// send join for old clients
|
||||
chname := channel.Name()
|
||||
details := session.client.Details()
|
||||
for _, member := range channel.Members() {
|
||||
for _, session := range member.Sessions() {
|
||||
if session.capabilities.Has(caps.Resume) {
|
||||
continue
|
||||
}
|
||||
// TODO: for now, skip this entirely for auditoriums,
|
||||
// but really we should send it to voiced clients
|
||||
if !channel.flags.HasMode(modes.Auditorium) {
|
||||
for _, member := range channel.Members() {
|
||||
for _, session := range member.Sessions() {
|
||||
if session.capabilities.Has(caps.Resume) {
|
||||
continue
|
||||
}
|
||||
|
||||
if session.capabilities.Has(caps.ExtendedJoin) {
|
||||
session.Send(nil, details.nickMask, "JOIN", chname, details.accountName, details.realname)
|
||||
} else {
|
||||
session.Send(nil, details.nickMask, "JOIN", chname)
|
||||
}
|
||||
if session.capabilities.Has(caps.ExtendedJoin) {
|
||||
session.Send(nil, details.nickMask, "JOIN", chname, details.accountName, details.realname)
|
||||
} else {
|
||||
session.Send(nil, details.nickMask, "JOIN", chname)
|
||||
}
|
||||
|
||||
if 0 < len(oldModes) {
|
||||
session.Send(nil, channel.server.name, "MODE", chname, oldModes, details.nick)
|
||||
if 0 < len(oldModes) {
|
||||
session.Send(nil, channel.server.name, "MODE", chname, oldModes, details.nick)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1451,6 +1487,30 @@ func (channel *Channel) Invite(invitee *Client, inviter *Client, rb *ResponseBuf
|
|||
}
|
||||
}
|
||||
|
||||
// returns who the client can "see" in the channel, respecting the auditorium mode
|
||||
func (channel *Channel) auditoriumFriends(client *Client) (friends []*Client) {
|
||||
channel.stateMutex.RLock()
|
||||
defer channel.stateMutex.RUnlock()
|
||||
|
||||
clientModes := channel.members[client]
|
||||
if clientModes == nil {
|
||||
return // non-members have no friends
|
||||
}
|
||||
if !channel.flags.HasMode(modes.Auditorium) {
|
||||
return channel.membersCache // default behavior for members
|
||||
}
|
||||
if clientModes.HighestChannelUserMode() != modes.Mode(0) {
|
||||
return channel.membersCache // +v and up can see everyone in the auditorium
|
||||
}
|
||||
// without +v, your friends are those with +v and up
|
||||
for member, memberModes := range channel.members {
|
||||
if memberModes.HighestChannelUserMode() != modes.Mode(0) {
|
||||
friends = append(friends, member)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// data for RPL_LIST
|
||||
func (channel *Channel) listData() (memberCount int, name, topic string) {
|
||||
channel.stateMutex.RLock()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue