Browse Source

Merge pull request #1273 from ajaspers/mute_unregistered

Add +M (only registered/voice can speak) chanmode.
tags/v2.4.0-rc1
Shivaram Lingamneni 3 years ago
parent
commit
4a949877a0
No account linked to committer's email address
7 changed files with 34 additions and 17 deletions
  1. 12
    0
      docs/MANUAL.md
  2. 11
    8
      irc/channel.go
  3. 1
    1
      irc/config.go
  4. 1
    0
      irc/help.go
  5. 1
    1
      irc/modes.go
  6. 6
    5
      irc/modes/modes.go
  7. 2
    2
      irc/roleplay.go

+ 12
- 0
docs/MANUAL.md View File

@@ -654,6 +654,18 @@ To unset this mode:
654 654
 
655 655
     /MODE #test -R
656 656
 
657
+### +M - Only Registered Users Can Speak
658
+
659
+If this mode is set, only users that have logged into an account will be able to speak on the channel. If this is set and a regular, un-logged-in user tries to speak, they will be rejected. Users who have been voiced (+v) are excepted from this restriction.
660
+
661
+To set this mode:
662
+
663
+    /MODE #test +M
664
+
665
+To unset this mode:
666
+
667
+    /MODE #test -M
668
+
657 669
 ### +s - Secret
658 670
 
659 671
 If this mode is set, it means that your channel should be marked as 'secret'. Your channel won't show up in `/LIST` or `/WHOIS`, and non-members won't be able to see its members with `/NAMES` or `/WHO`.

+ 11
- 8
irc/channel.go View File

@@ -1188,22 +1188,25 @@ func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffe
1188 1188
 	channel.MarkDirty(IncludeTopic)
1189 1189
 }
1190 1190
 
1191
-// CanSpeak returns true if the client can speak on this channel.
1192
-func (channel *Channel) CanSpeak(client *Client) bool {
1191
+// CanSpeak returns true if the client can speak on this channel, otherwise it returns false along with the channel mode preventing the client from speaking.
1192
+func (channel *Channel) CanSpeak(client *Client) (bool, modes.Mode) {
1193 1193
 	channel.stateMutex.RLock()
1194 1194
 	defer channel.stateMutex.RUnlock()
1195 1195
 
1196 1196
 	_, hasClient := channel.members[client]
1197 1197
 	if channel.flags.HasMode(modes.NoOutside) && !hasClient {
1198
-		return false
1198
+		return false, modes.NoOutside
1199 1199
 	}
1200 1200
 	if channel.flags.HasMode(modes.Moderated) && !channel.ClientIsAtLeast(client, modes.Voice) {
1201
-		return false
1201
+		return false, modes.Moderated
1202 1202
 	}
1203 1203
 	if channel.flags.HasMode(modes.RegisteredOnly) && client.Account() == "" {
1204
-		return false
1204
+		return false, modes.RegisteredOnly
1205
+	}
1206
+	if channel.flags.HasMode(modes.RegisteredOnlySpeak) && client.Account() == "" && !channel.ClientIsAtLeast(client, modes.Voice) {
1207
+		return false, modes.RegisteredOnlySpeak
1205 1208
 	}
1206
-	return true
1209
+	return true, modes.Mode('?')
1207 1210
 }
1208 1211
 
1209 1212
 func msgCommandToHistType(command string) (history.ItemType, error) {
@@ -1225,9 +1228,9 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod
1225 1228
 		return
1226 1229
 	}
1227 1230
 
1228
-	if !channel.CanSpeak(client) {
1231
+	if canSpeak, mode := channel.CanSpeak(client); !canSpeak {
1229 1232
 		if histType != history.Notice {
1230
-			rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, client.Nick(), channel.Name(), client.t("Cannot send to channel"))
1233
+			rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, client.Nick(), channel.Name(), fmt.Sprintf(client.t("Cannot send to channel (+%s)"), mode))
1231 1234
 		}
1232 1235
 		return
1233 1236
 	}

+ 1
- 1
irc/config.go View File

@@ -1250,7 +1250,7 @@ func (config *Config) generateISupport() (err error) {
1250 1250
 	isupport.Add("BOT", "B")
1251 1251
 	isupport.Add("CASEMAPPING", "ascii")
1252 1252
 	isupport.Add("CHANLIMIT", fmt.Sprintf("%s:%d", chanTypes, config.Channels.MaxChannelsPerClient))
1253
-	isupport.Add("CHANMODES", strings.Join([]string{modes.Modes{modes.BanMask, modes.ExceptMask, modes.InviteMask}.String(), modes.Modes{modes.Key}.String(), modes.Modes{modes.UserLimit}.String(), modes.Modes{modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.ChanRoleplaying, modes.Secret, modes.NoCTCP, modes.RegisteredOnly}.String()}, ","))
1253
+	isupport.Add("CHANMODES", strings.Join([]string{modes.Modes{modes.BanMask, modes.ExceptMask, modes.InviteMask}.String(), modes.Modes{modes.Key}.String(), modes.Modes{modes.UserLimit}.String(), modes.Modes{modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.ChanRoleplaying, modes.Secret, modes.NoCTCP, modes.RegisteredOnly, modes.RegisteredOnlySpeak}.String()}, ","))
1254 1254
 	if config.History.Enabled && config.History.ChathistoryMax > 0 {
1255 1255
 		isupport.Add("draft/CHATHISTORY", strconv.Itoa(config.History.ChathistoryMax))
1256 1256
 	}

+ 1
- 0
irc/help.go View File

@@ -49,6 +49,7 @@ Oragono supports the following channel modes:
49 49
   +n  |  No-outside-messages mode, only users that are on the channel can send
50 50
       |  messages to it.
51 51
   +R  |  Only registered users can join the channel.
52
+  +M  |  Only registered or voiced users can speak in the channel.
52 53
   +s  |  Secret mode, channel won't show up in /LIST or whois replies.
53 54
   +t  |  Only channel opers can modify the topic.
54 55
   +E  |  Roleplaying commands are enabled in the channel.

+ 1
- 1
irc/modes.go View File

@@ -271,7 +271,7 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
271 271
 				applied = append(applied, change)
272 272
 			}
273 273
 
274
-		case modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.RegisteredOnly, modes.Secret, modes.ChanRoleplaying, modes.NoCTCP:
274
+		case modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.RegisteredOnly, modes.Secret, modes.ChanRoleplaying, modes.NoCTCP, modes.RegisteredOnlySpeak:
275 275
 			if change.Op == modes.List {
276 276
 				continue
277 277
 			}

+ 6
- 5
irc/modes/modes.go View File

@@ -21,8 +21,8 @@ var (
21 21
 	// SupportedChannelModes are the channel modes that we support.
22 22
 	SupportedChannelModes = Modes{
23 23
 		BanMask, ChanRoleplaying, ExceptMask, InviteMask, InviteOnly, Key,
24
-		Moderated, NoOutside, OpOnlyTopic, RegisteredOnly, Secret, UserLimit,
25
-		NoCTCP,
24
+		Moderated, NoOutside, OpOnlyTopic, RegisteredOnly, RegisteredOnlySpeak,
25
+		Secret, UserLimit, NoCTCP,
26 26
 	}
27 27
 )
28 28
 
@@ -122,9 +122,10 @@ const (
122 122
 	NoOutside       Mode = 'n' // flag
123 123
 	OpOnlyTopic     Mode = 't' // flag
124 124
 	// RegisteredOnly mode is reused here from umode definition
125
-	Secret    Mode = 's' // flag
126
-	UserLimit Mode = 'l' // flag arg
127
-	NoCTCP    Mode = 'C' // flag
125
+	RegisteredOnlySpeak Mode = 'M' // flag
126
+	Secret              Mode = 's' // flag
127
+	UserLimit           Mode = 'l' // flag arg
128
+	NoCTCP              Mode = 'C' // flag
128 129
 )
129 130
 
130 131
 var (

+ 2
- 2
irc/roleplay.go View File

@@ -74,8 +74,8 @@ func sendRoleplayMessage(server *Server, client *Client, source string, targetSt
74 74
 		}
75 75
 
76 76
 		targetString = channel.Name()
77
-		if !channel.CanSpeak(client) {
78
-			rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, targetString, client.t("Cannot send to channel"))
77
+		if canSpeak, mode := channel.CanSpeak(client); !canSpeak {
78
+			rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, targetString, fmt.Sprintf(client.t("Cannot send to channel (+%s)"), mode))
79 79
 			return
80 80
 		}
81 81
 

Loading…
Cancel
Save