Quellcode durchsuchen

fix #484

tags/v2.4.0-rc1
Shivaram Lingamneni vor 3 Jahren
Ursprung
Commit
8c99dcb2c7
6 geänderte Dateien mit 102 neuen und 30 gelöschten Zeilen
  1. 82
    22
      irc/channel.go
  2. 4
    4
      irc/client.go
  3. 10
    1
      irc/handlers.go
  4. 3
    1
      irc/help.go
  5. 2
    1
      irc/modes/modes.go
  6. 1
    1
      irctest

+ 82
- 22
irc/channel.go Datei anzeigen

@@ -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()

+ 4
- 4
irc/client.go Datei anzeigen

@@ -934,7 +934,7 @@ func (session *Session) playResume() {
934 934
 	// work out how much time, if any, is not covered by history buffers
935 935
 	// assume that a persistent buffer covers the whole resume period
936 936
 	for _, channel := range client.Channels() {
937
-		for _, member := range channel.Members() {
937
+		for _, member := range channel.auditoriumFriends(client) {
938 938
 			friends.Add(member)
939 939
 		}
940 940
 		status, _ := channel.historyStatus(config)
@@ -1161,7 +1161,7 @@ func (client *Client) Friends(capabs ...caps.Capability) (result map[*Session]em
1161 1161
 	addFriendsToSet(result, client, capabs...)
1162 1162
 
1163 1163
 	for _, channel := range client.Channels() {
1164
-		for _, member := range channel.Members() {
1164
+		for _, member := range channel.auditoriumFriends(client) {
1165 1165
 			addFriendsToSet(result, member, capabs...)
1166 1166
 		}
1167 1167
 	}
@@ -1512,10 +1512,10 @@ func (client *Client) destroy(session *Session) {
1512 1512
 	friends := make(ClientSet)
1513 1513
 	channels = client.Channels()
1514 1514
 	for _, channel := range channels {
1515
-		channel.Quit(client)
1516
-		for _, member := range channel.Members() {
1515
+		for _, member := range channel.auditoriumFriends(client) {
1517 1516
 			friends.Add(member)
1518 1517
 		}
1518
+		channel.Quit(client)
1519 1519
 	}
1520 1520
 	friends.Remove(client)
1521 1521
 

+ 10
- 1
irc/handlers.go Datei anzeigen

@@ -3051,7 +3051,13 @@ func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
3051 3051
 		if channel != nil {
3052 3052
 			isJoined := channel.hasClient(client)
3053 3053
 			if !channel.flags.HasMode(modes.Secret) || isJoined || isOper {
3054
-				for _, member := range channel.Members() {
3054
+				var members []*Client
3055
+				if isOper {
3056
+					members = channel.Members()
3057
+				} else {
3058
+					members = channel.auditoriumFriends(client)
3059
+				}
3060
+				for _, member := range members {
3055 3061
 					if !member.HasMode(modes.Invisible) || isJoined || isOper {
3056 3062
 						client.rplWhoReply(channel, member, rb, isWhox, fields, whoType)
3057 3063
 					}
@@ -3072,6 +3078,9 @@ func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
3072 3078
 			}
3073 3079
 
3074 3080
 			for _, channel := range otherClient.Channels() {
3081
+				if channel.flags.HasMode(modes.Auditorium) {
3082
+					return false // TODO this should respect +v etc.
3083
+				}
3075 3084
 				if _, present := userChannels[channel]; present {
3076 3085
 					return true
3077 3086
 				}

+ 3
- 1
irc/help.go Datei anzeigen

@@ -54,6 +54,8 @@ Oragono supports the following channel modes:
54 54
   +t  |  Only channel opers can modify the topic.
55 55
   +E  |  Roleplaying commands are enabled in the channel.
56 56
   +C  |  Clients are blocked from sending CTCP messages in the channel.
57
+  +u  |  Auditorium mode: JOIN, PART, QUIT, NAMES, and WHO are hidden
58
+         hidden from unvoiced clients.
57 59
 
58 60
 = Prefixes =
59 61
 
@@ -74,7 +76,7 @@ Oragono supports the following user modes:
74 76
   +Z  |  User is connected via TLS.
75 77
   +B  |  User is a bot.
76 78
   +E  |  User can receive roleplaying commands.
77
-  +T  |  User is blocked from sending CTCP messages.`
79
+  +T  |  CTCP messages to the user are blocked.`
78 80
 	snomaskHelpText = `== Server Notice Masks ==
79 81
 
80 82
 Oragono supports the following server notice masks for operators:

+ 2
- 1
irc/modes/modes.go Datei anzeigen

@@ -23,7 +23,7 @@ var (
23 23
 	SupportedChannelModes = Modes{
24 24
 		BanMask, ChanRoleplaying, ExceptMask, InviteMask, InviteOnly, Key,
25 25
 		Moderated, NoOutside, OpOnlyTopic, RegisteredOnly, RegisteredOnlySpeak,
26
-		Secret, UserLimit, NoCTCP,
26
+		Secret, UserLimit, NoCTCP, Auditorium,
27 27
 	}
28 28
 )
29 29
 
@@ -113,6 +113,7 @@ const (
113 113
 
114 114
 // Channel Modes
115 115
 const (
116
+	Auditorium      Mode = 'u' // flag
116 117
 	BanMask         Mode = 'b' // arg
117 118
 	ChanRoleplaying Mode = 'E' // flag
118 119
 	ExceptMask      Mode = 'e' // arg

+ 1
- 1
irctest

@@ -1 +1 @@
1
-Subproject commit 0287b837971c27ee55bc4dca95d31afc68d2aeea
1
+Subproject commit 616785eae403536954f1b1181f74ef51343e33f7

Laden…
Abbrechen
Speichern