Add +M (only registered/voice can speak) chanmode.

Add chanmode preventing speech to error message.

Fixes #1182.
This commit is contained in:
Alex Jaspersen
2020-09-19 11:01:58 -07:00
parent f9ca93118f
commit 504659abb5
7 changed files with 34 additions and 17 deletions
+11 -8
View File
@@ -1188,22 +1188,25 @@ func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffe
channel.MarkDirty(IncludeTopic)
}
// CanSpeak returns true if the client can speak on this channel.
func (channel *Channel) CanSpeak(client *Client) bool {
// 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.
func (channel *Channel) CanSpeak(client *Client) (bool, modes.Mode) {
channel.stateMutex.RLock()
defer channel.stateMutex.RUnlock()
_, hasClient := channel.members[client]
if channel.flags.HasMode(modes.NoOutside) && !hasClient {
return false
return false, modes.NoOutside
}
if channel.flags.HasMode(modes.Moderated) && !channel.ClientIsAtLeast(client, modes.Voice) {
return false
return false, modes.Moderated
}
if channel.flags.HasMode(modes.RegisteredOnly) && client.Account() == "" {
return false
return false, modes.RegisteredOnly
}
return true
if channel.flags.HasMode(modes.RegisteredOnlySpeak) && client.Account() == "" && !channel.ClientIsAtLeast(client, modes.Voice) {
return false, modes.RegisteredOnlySpeak
}
return true, modes.Mode('?')
}
func msgCommandToHistType(command string) (history.ItemType, error) {
@@ -1225,9 +1228,9 @@ func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mod
return
}
if !channel.CanSpeak(client) {
if canSpeak, mode := channel.CanSpeak(client); !canSpeak {
if histType != history.Notice {
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, client.Nick(), channel.Name(), client.t("Cannot send to channel"))
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, client.Nick(), channel.Name(), fmt.Sprintf(client.t("Cannot send to channel (+%s)"), mode))
}
return
}
+1 -1
View File
@@ -1250,7 +1250,7 @@ func (config *Config) generateISupport() (err error) {
isupport.Add("BOT", "B")
isupport.Add("CASEMAPPING", "ascii")
isupport.Add("CHANLIMIT", fmt.Sprintf("%s:%d", chanTypes, config.Channels.MaxChannelsPerClient))
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()}, ","))
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()}, ","))
if config.History.Enabled && config.History.ChathistoryMax > 0 {
isupport.Add("draft/CHATHISTORY", strconv.Itoa(config.History.ChathistoryMax))
}
+1
View File
@@ -49,6 +49,7 @@ Oragono supports the following channel modes:
+n | No-outside-messages mode, only users that are on the channel can send
| messages to it.
+R | Only registered users can join the channel.
+M | Only registered or voiced users can speak in the channel.
+s | Secret mode, channel won't show up in /LIST or whois replies.
+t | Only channel opers can modify the topic.
+E | Roleplaying commands are enabled in the channel.
+1 -1
View File
@@ -271,7 +271,7 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
applied = append(applied, change)
}
case modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.RegisteredOnly, modes.Secret, modes.ChanRoleplaying, modes.NoCTCP:
case modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.RegisteredOnly, modes.Secret, modes.ChanRoleplaying, modes.NoCTCP, modes.RegisteredOnlySpeak:
if change.Op == modes.List {
continue
}
+6 -5
View File
@@ -21,8 +21,8 @@ var (
// SupportedChannelModes are the channel modes that we support.
SupportedChannelModes = Modes{
BanMask, ChanRoleplaying, ExceptMask, InviteMask, InviteOnly, Key,
Moderated, NoOutside, OpOnlyTopic, RegisteredOnly, Secret, UserLimit,
NoCTCP,
Moderated, NoOutside, OpOnlyTopic, RegisteredOnly, RegisteredOnlySpeak,
Secret, UserLimit, NoCTCP,
}
)
@@ -122,9 +122,10 @@ const (
NoOutside Mode = 'n' // flag
OpOnlyTopic Mode = 't' // flag
// RegisteredOnly mode is reused here from umode definition
Secret Mode = 's' // flag
UserLimit Mode = 'l' // flag arg
NoCTCP Mode = 'C' // flag
RegisteredOnlySpeak Mode = 'M' // flag
Secret Mode = 's' // flag
UserLimit Mode = 'l' // flag arg
NoCTCP Mode = 'C' // flag
)
var (
+2 -2
View File
@@ -74,8 +74,8 @@ func sendRoleplayMessage(server *Server, client *Client, source string, targetSt
}
targetString = channel.Name()
if !channel.CanSpeak(client) {
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, targetString, client.t("Cannot send to channel"))
if canSpeak, mode := channel.CanSpeak(client); !canSpeak {
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, targetString, fmt.Sprintf(client.t("Cannot send to channel (+%s)"), mode))
return
}