|
@@ -439,8 +439,12 @@ func (channel *Channel) regenerateMembersCache() {
|
439
|
439
|
|
440
|
440
|
// Names sends the list of users joined to the channel to the given client.
|
441
|
441
|
func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
442
|
|
- isJoined := channel.hasClient(client)
|
|
442
|
+ channel.stateMutex.RLock()
|
|
443
|
+ clientModes, isJoined := channel.members[client]
|
|
444
|
+ channel.stateMutex.RUnlock()
|
443
|
445
|
isOper := client.HasMode(modes.Operator)
|
|
446
|
+ respectAuditorium := channel.flags.HasMode(modes.Auditorium) && !isOper &&
|
|
447
|
+ (!isJoined || clientModes.HighestChannelUserMode() == modes.Mode(0))
|
444
|
448
|
isMultiPrefix := rb.session.capabilities.Has(caps.MultiPrefix)
|
445
|
449
|
isUserhostInNames := rb.session.capabilities.Has(caps.UserhostInNames)
|
446
|
450
|
|
|
@@ -464,6 +468,9 @@ func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
464
|
468
|
if !isJoined && target.HasMode(modes.Invisible) && !isOper {
|
465
|
469
|
continue
|
466
|
470
|
}
|
|
471
|
+ if respectAuditorium && modeSet.HighestChannelUserMode() == modes.Mode(0) {
|
|
472
|
+ continue
|
|
473
|
+ }
|
467
|
474
|
prefix := modeSet.Prefixes(isMultiPrefix)
|
468
|
475
|
if buffer.Len()+len(nick)+len(prefix)+1 > maxNamLen {
|
469
|
476
|
namesLines = append(namesLines, buffer.String())
|
|
@@ -748,8 +755,9 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
|
748
|
755
|
}()
|
749
|
756
|
|
750
|
757
|
var message utils.SplitMessage
|
|
758
|
+ respectAuditorium := givenMode == modes.Mode(0) && channel.flags.HasMode(modes.Auditorium)
|
751
|
759
|
// no history item for fake persistent joins
|
752
|
|
- if rb != nil {
|
|
760
|
+ if rb != nil && !respectAuditorium {
|
753
|
761
|
message = utils.MakeMessage("")
|
754
|
762
|
histItem := history.Item{
|
755
|
763
|
Type: history.Join,
|
|
@@ -772,6 +780,14 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
|
772
|
780
|
|
773
|
781
|
isAway, awayMessage := client.Away()
|
774
|
782
|
for _, member := range channel.Members() {
|
|
783
|
+ if respectAuditorium {
|
|
784
|
+ channel.stateMutex.RLock()
|
|
785
|
+ memberModes, ok := channel.members[member]
|
|
786
|
+ channel.stateMutex.RUnlock()
|
|
787
|
+ if !ok || memberModes.HighestChannelUserMode() == modes.Mode(0) {
|
|
788
|
+ continue
|
|
789
|
+ }
|
|
790
|
+ }
|
775
|
791
|
for _, session := range member.Sessions() {
|
776
|
792
|
if session == rb.session {
|
777
|
793
|
continue
|
|
@@ -889,8 +905,12 @@ func (channel *Channel) playJoinForSession(session *Session) {
|
889
|
905
|
|
890
|
906
|
// Part parts the given client from this channel, with the given message.
|
891
|
907
|
func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer) {
|
892
|
|
- chname := channel.Name()
|
893
|
|
- if !channel.hasClient(client) {
|
|
908
|
+ channel.stateMutex.RLock()
|
|
909
|
+ chname := channel.name
|
|
910
|
+ clientModes, ok := channel.members[client]
|
|
911
|
+ channel.stateMutex.RUnlock()
|
|
912
|
+
|
|
913
|
+ if !ok {
|
894
|
914
|
rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.Nick(), chname, client.t("You're not on that channel"))
|
895
|
915
|
return
|
896
|
916
|
}
|
|
@@ -905,7 +925,17 @@ func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer)
|
905
|
925
|
if message != "" {
|
906
|
926
|
params = append(params, message)
|
907
|
927
|
}
|
|
928
|
+ respectAuditorium := channel.flags.HasMode(modes.Auditorium) &&
|
|
929
|
+ clientModes.HighestChannelUserMode() == modes.Mode(0)
|
908
|
930
|
for _, member := range channel.Members() {
|
|
931
|
+ if respectAuditorium {
|
|
932
|
+ channel.stateMutex.RLock()
|
|
933
|
+ memberModes, ok := channel.members[member]
|
|
934
|
+ channel.stateMutex.RUnlock()
|
|
935
|
+ if !ok || memberModes.HighestChannelUserMode() == modes.Mode(0) {
|
|
936
|
+ continue
|
|
937
|
+ }
|
|
938
|
+ }
|
909
|
939
|
member.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
|
910
|
940
|
}
|
911
|
941
|
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)
|
915
|
945
|
}
|
916
|
946
|
}
|
917
|
947
|
|
918
|
|
- channel.AddHistoryItem(history.Item{
|
919
|
|
- Type: history.Part,
|
920
|
|
- Nick: details.nickMask,
|
921
|
|
- AccountName: details.accountName,
|
922
|
|
- Message: splitMessage,
|
923
|
|
- }, details.account)
|
|
948
|
+ if !respectAuditorium {
|
|
949
|
+ channel.AddHistoryItem(history.Item{
|
|
950
|
+ Type: history.Part,
|
|
951
|
+ Nick: details.nickMask,
|
|
952
|
+ AccountName: details.accountName,
|
|
953
|
+ Message: splitMessage,
|
|
954
|
+ }, details.account)
|
|
955
|
+ }
|
924
|
956
|
|
925
|
957
|
client.server.logger.Debug("part", fmt.Sprintf("%s left channel %s", details.nick, chname))
|
926
|
958
|
}
|
|
@@ -951,20 +983,24 @@ func (channel *Channel) resumeAndAnnounce(session *Session) {
|
951
|
983
|
// send join for old clients
|
952
|
984
|
chname := channel.Name()
|
953
|
985
|
details := session.client.Details()
|
954
|
|
- for _, member := range channel.Members() {
|
955
|
|
- for _, session := range member.Sessions() {
|
956
|
|
- if session.capabilities.Has(caps.Resume) {
|
957
|
|
- continue
|
958
|
|
- }
|
|
986
|
+ // TODO: for now, skip this entirely for auditoriums,
|
|
987
|
+ // but really we should send it to voiced clients
|
|
988
|
+ if !channel.flags.HasMode(modes.Auditorium) {
|
|
989
|
+ for _, member := range channel.Members() {
|
|
990
|
+ for _, session := range member.Sessions() {
|
|
991
|
+ if session.capabilities.Has(caps.Resume) {
|
|
992
|
+ continue
|
|
993
|
+ }
|
959
|
994
|
|
960
|
|
- if session.capabilities.Has(caps.ExtendedJoin) {
|
961
|
|
- session.Send(nil, details.nickMask, "JOIN", chname, details.accountName, details.realname)
|
962
|
|
- } else {
|
963
|
|
- session.Send(nil, details.nickMask, "JOIN", chname)
|
964
|
|
- }
|
|
995
|
+ if session.capabilities.Has(caps.ExtendedJoin) {
|
|
996
|
+ session.Send(nil, details.nickMask, "JOIN", chname, details.accountName, details.realname)
|
|
997
|
+ } else {
|
|
998
|
+ session.Send(nil, details.nickMask, "JOIN", chname)
|
|
999
|
+ }
|
965
|
1000
|
|
966
|
|
- if 0 < len(oldModes) {
|
967
|
|
- session.Send(nil, channel.server.name, "MODE", chname, oldModes, details.nick)
|
|
1001
|
+ if 0 < len(oldModes) {
|
|
1002
|
+ session.Send(nil, channel.server.name, "MODE", chname, oldModes, details.nick)
|
|
1003
|
+ }
|
968
|
1004
|
}
|
969
|
1005
|
}
|
970
|
1006
|
}
|
|
@@ -1451,6 +1487,30 @@ func (channel *Channel) Invite(invitee *Client, inviter *Client, rb *ResponseBuf
|
1451
|
1487
|
}
|
1452
|
1488
|
}
|
1453
|
1489
|
|
|
1490
|
+// returns who the client can "see" in the channel, respecting the auditorium mode
|
|
1491
|
+func (channel *Channel) auditoriumFriends(client *Client) (friends []*Client) {
|
|
1492
|
+ channel.stateMutex.RLock()
|
|
1493
|
+ defer channel.stateMutex.RUnlock()
|
|
1494
|
+
|
|
1495
|
+ clientModes := channel.members[client]
|
|
1496
|
+ if clientModes == nil {
|
|
1497
|
+ return // non-members have no friends
|
|
1498
|
+ }
|
|
1499
|
+ if !channel.flags.HasMode(modes.Auditorium) {
|
|
1500
|
+ return channel.membersCache // default behavior for members
|
|
1501
|
+ }
|
|
1502
|
+ if clientModes.HighestChannelUserMode() != modes.Mode(0) {
|
|
1503
|
+ return channel.membersCache // +v and up can see everyone in the auditorium
|
|
1504
|
+ }
|
|
1505
|
+ // without +v, your friends are those with +v and up
|
|
1506
|
+ for member, memberModes := range channel.members {
|
|
1507
|
+ if memberModes.HighestChannelUserMode() != modes.Mode(0) {
|
|
1508
|
+ friends = append(friends, member)
|
|
1509
|
+ }
|
|
1510
|
+ }
|
|
1511
|
+ return
|
|
1512
|
+}
|
|
1513
|
+
|
1454
|
1514
|
// data for RPL_LIST
|
1455
|
1515
|
func (channel *Channel) listData() (memberCount int, name, topic string) {
|
1456
|
1516
|
channel.stateMutex.RLock()
|