diff --git a/irc/handlers.go b/irc/handlers.go index 2b37dfcd..2c989d32 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -1602,7 +1602,7 @@ func umodeHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res } // apply mode changes - applied = ApplyUserModeChanges(target, changes, msg.Command == "SAMODE") + applied = ApplyUserModeChanges(target, changes, msg.Command == "SAMODE", nil) } if len(applied) > 0 { @@ -2117,7 +2117,7 @@ func applyOper(client *Client, oper *Oper, rb *ResponseBuffer) { Op: modes.Add, } copy(modeChanges[1:], oper.Modes) - applied := ApplyUserModeChanges(client, modeChanges, true) + applied := ApplyUserModeChanges(client, modeChanges, true, oper) client.server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), newDetails.nickMask, oper.Name)) diff --git a/irc/modes.go b/irc/modes.go index 08610ee5..5d2b7e0c 100644 --- a/irc/modes.go +++ b/irc/modes.go @@ -23,7 +23,9 @@ var ( ) // ApplyUserModeChanges applies the given changes, and returns the applied changes. -func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool) modes.ModeChanges { +// `oper` is the operclass of the client gaining +o, when applicable (this is just +// to confirm that the client actually has a valid operclass) +func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, oper *Oper) modes.ModeChanges { applied := make(modes.ModeChanges, 0) for _, change := range changes { @@ -31,7 +33,7 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool) case modes.Bot, modes.Invisible, modes.WallOps, modes.UserRoleplaying, modes.Operator, modes.LocalOperator, modes.RegisteredOnly: switch change.Op { case modes.Add: - if !force && (change.Mode == modes.Operator || change.Mode == modes.LocalOperator) { + if (change.Mode == modes.Operator || change.Mode == modes.LocalOperator) && !(force && oper != nil) { continue }