diff --git a/irc/commands.go b/irc/commands.go index ee27a5bd..6f553443 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -187,6 +187,11 @@ var Commands = map[string]Command{ minParams: 2, oper: true, }, + "SAMODE": { + handler: modeHandler, + minParams: 1, + capabs: []string{"samode"}, + }, "SCENE": { handler: sceneHandler, minParams: 2, diff --git a/irc/help.go b/irc/help.go index 91ed9b07..ec9290a3 100644 --- a/irc/help.go +++ b/irc/help.go @@ -295,6 +295,14 @@ Sends the text to the given targets as a PRIVMSG.`, text: `SANICK Gives the given user a new nickname.`, + }, + "samode": { + oper: true, + text: `SAMODE [ [...]] + +Forcibly sets and removes modes from the given target -- only available to +opers. For more specific information on mode characters, see the help for +"cmode" and "umode".`, }, "scene": { text: `SCENE diff --git a/irc/modes.go b/irc/modes.go index 4983d8db..5dd34fbd 100644 --- a/irc/modes.go +++ b/irc/modes.go @@ -263,9 +263,7 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { return false } - //TODO(dan): restricting to Operator here should be done with SAMODE only - // point SAMODE at this handler too, if they are operator and SAMODE was called then fine - if client != target && !client.flags[Operator] { + if client != target && msg.Command != "SAMODE" { if len(msg.Params) > 1 { client.Send(nil, server.name, ERR_USERSDONTMATCH, client.nick, "Can't change modes for other users") } else { @@ -420,7 +418,7 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { for _, change := range changes { // chan priv modes are checked specially so ignore them // means regular users can't view ban/except lists... but I'm not worried about that - if ChannelModePrefixes[change.mode] == "" && !clientIsOp { + if msg.Command != "SAMODE" && ChannelModePrefixes[change.mode] == "" && !clientIsOp { if !alreadySentPrivError { alreadySentPrivError = true client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, "You're not a channel operator") @@ -512,19 +510,23 @@ func cmodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { // make sure client has privs to edit the given prefix var hasPrivs bool - for _, mode := range ChannelPrivModes { - if channel.members[client][mode] { - hasPrivs = true + if msg.Command == "SAMODE" { + hasPrivs = true + } else { + for _, mode := range ChannelPrivModes { + if channel.members[client][mode] { + hasPrivs = true - // Admins can't give other people Admin or remove it from others, - // standard for that channel mode, we worry about this later - if mode == ChannelAdmin && change.mode == ChannelAdmin { - hasPrivs = false + // Admins can't give other people Admin or remove it from others, + // standard for that channel mode, we worry about this later + if mode == ChannelAdmin && change.mode == ChannelAdmin { + hasPrivs = false + } + + break + } else if mode == change.mode { + break } - - break - } else if mode == change.mode { - break } } diff --git a/oragono.yaml b/oragono.yaml index 9dd29dcf..a714597d 100644 --- a/oragono.yaml +++ b/oragono.yaml @@ -154,6 +154,7 @@ oper-classes: capabilities: - "oper:rehash" - "oper:die" + - "samode" # ircd operators opers: