diff --git a/irc/accounts.go b/irc/accounts.go index d4d8e7f9..b68b0f7f 100644 --- a/irc/accounts.go +++ b/irc/accounts.go @@ -1227,7 +1227,7 @@ func (am *AccountManager) Login(client *Client, account ClientAccount) { return } - client.nickTimer.Touch() + client.nickTimer.Touch(nil) am.applyVHostInfo(client, account.VHost) @@ -1313,7 +1313,7 @@ func (am *AccountManager) logoutOfAccount(client *Client) { } client.SetAccountName("") - go client.nickTimer.Touch() + go client.nickTimer.Touch(nil) // dispatch account-notify // TODO: doing the I/O here is kind of a kludge, let's move this somewhere else diff --git a/irc/client.go b/irc/client.go index e7ad8316..48a84183 100644 --- a/irc/client.go +++ b/irc/client.go @@ -451,7 +451,7 @@ func (client *Client) tryResume() (success bool) { // this is a bit racey client.resumeDetails.ResumedAt = time.Now() - client.nickTimer.Touch() + client.nickTimer.Touch(nil) // resume successful, proceed to copy client state (nickname, flags, etc.) // after this, the server thinks that `newClient` owns the nickname diff --git a/irc/idletimer.go b/irc/idletimer.go index deae2e27..fe158e46 100644 --- a/irc/idletimer.go +++ b/irc/idletimer.go @@ -222,11 +222,16 @@ func (nt *NickTimer) Timeout() (timeout time.Duration) { } // Touch records a nick change and updates the timer as necessary -func (nt *NickTimer) Touch() { +func (nt *NickTimer) Touch(rb *ResponseBuffer) { if !nt.Enabled() { return } + var session *Session + if rb != nil { + session = rb.session + } + cfnick, skeleton := nt.client.uniqueIdentifiers() account := nt.client.Account() accountForNick, method := nt.client.server.accounts.EnforcementStatus(cfnick, skeleton) @@ -259,7 +264,16 @@ func (nt *NickTimer) Touch() { }() if shouldWarn { - nt.client.Send(nil, "NickServ", "NOTICE", nt.client.Nick(), fmt.Sprintf(ircfmt.Unescape(nt.client.t(nsTimeoutNotice)), nt.Timeout())) + tnick := nt.client.Nick() + message := fmt.Sprintf(ircfmt.Unescape(nt.client.t(nsTimeoutNotice)), nt.Timeout()) + // #449 + for _, mSession := range nt.client.Sessions() { + if mSession == session { + rb.Add(nil, "NickServ", "NOTICE", tnick, message) + } else { + mSession.Send(nil, "NickServ", "NOTICE", tnick, message) + } + } } else if shouldRename { nt.client.Notice(nt.client.t("Nickname is reserved by a different account")) nt.client.server.RandomlyRename(nt.client) diff --git a/irc/nickname.go b/irc/nickname.go index a1737e2b..611d88b5 100644 --- a/irc/nickname.go +++ b/irc/nickname.go @@ -57,8 +57,6 @@ func performNickChange(server *Server, client *Client, target *Client, session * return false } - target.nickTimer.Touch() - client.server.logger.Debug("nick", fmt.Sprintf("%s changed nickname to %s [%s]", origNickMask, nickname, cfnick)) if hadNick { target.server.snomasks.Send(sno.LocalNicks, fmt.Sprintf(ircfmt.Unescape("$%s$r changed nickname to %s"), whowas.nick, nickname)) @@ -71,6 +69,8 @@ func performNickChange(server *Server, client *Client, target *Client, session * } } + target.nickTimer.Touch(rb) + if target.Registered() { client.server.monitorManager.AlertAbout(target, true) } diff --git a/irc/nickserv.go b/irc/nickserv.go index ccb59c91..74941658 100644 --- a/irc/nickserv.go +++ b/irc/nickserv.go @@ -31,7 +31,7 @@ var ( // 1. sent with prefix `nickserv` // 2. contains the string "identify" // 3. contains at least one of several other magic strings ("msg" works) - nsTimeoutNotice = `This nickname is reserved. Please login within %v (using $b/msg NickServ IDENTIFY $b or SASL)` + nsTimeoutNotice = `This nickname is reserved. Please login within %v (using $b/msg NickServ IDENTIFY $b or SASL), or switch to a different nickname.` ) const nickservHelp = `NickServ lets you register and login to an account. diff --git a/irc/server.go b/irc/server.go index 85c6e57e..396e8009 100644 --- a/irc/server.go +++ b/irc/server.go @@ -816,7 +816,7 @@ func (server *Server) applyConfig(config *Config, initial bool) (err error) { if !oldConfig.Accounts.NickReservation.Enabled && config.Accounts.NickReservation.Enabled { sClient.nickTimer.Initialize(sClient) - sClient.nickTimer.Touch() + sClient.nickTimer.Touch(nil) } else if oldConfig.Accounts.NickReservation.Enabled && !config.Accounts.NickReservation.Enabled { sClient.nickTimer.Stop() }