From 9d8bbd419810b98130cb5a9adb483feadf2a191a Mon Sep 17 00:00:00 2001 From: Gisle Aune Date: Sun, 29 Nov 2020 15:12:50 +0100 Subject: [PATCH] fix nick change being done during capability negotiation. --- client.go | 35 ++++++++++++++++++++++++++--------- client_test.go | 2 +- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/client.go b/client.go index d78d322..071dae3 100644 --- a/client.go +++ b/client.go @@ -850,6 +850,8 @@ func (client *Client) handleSendLoop() { // handleEvent is always first and gets to break a few rules. func (client *Client) handleEvent(event *Event) { + sentCapEnd := false + // IRCv3 `server-time` if timeTag, ok := event.Tags["time"]; ok { serverTime, err := time.Parse(time.RFC3339Nano, timeTag) @@ -946,33 +948,36 @@ func (client *Client) handleEvent(event *Event) { // Nick rotation case "packet.431", "packet.432", "packet.433", "packet.436": { + lockNickChange, _ := client.Value("internal.lockNickChange").(bool) + // Ignore if client is registered if client.Nick() != "" { break } - // Ignore if in middle of SASL authentication - if event.Verb() == "433" && client.Value("sasl.usingMethod") != nil { - break - } nick := event.Args[1] + newNick := "" // "AltN" -> "AltN+1", ... prev := client.config.Nick - sent := false for _, alt := range client.config.Alternatives { if nick == prev { - _ = client.Sendf("NICK %s", alt) - sent = true + newNick = alt break } prev = alt } - if !sent { + if newNick == "" { // "LastAlt" -> "Nick23962" - _ = client.Sendf("NICK %s%05d", client.config.Nick, mathRand.Int31n(99999)) + newNick = fmt.Sprintf("%s%05d", client.config.Nick, mathRand.Int31n(99999)) + } + + if lockNickChange { + client.SetValue("internal.primedNickChange", newNick) + } else { + _ = client.Sendf("NICK %s", newNick) } } @@ -1008,6 +1013,8 @@ func (client *Client) handleEvent(event *Event) { switch capCommand { case "LS": { + client.SetValue("internal.lockNickChange", true) + for _, token := range capTokens { split := strings.SplitN(token, "=", 2) key := split[0] @@ -1042,6 +1049,7 @@ func (client *Client) handleEvent(event *Event) { _ = client.Send("CAP REQ :" + requestedCaps) } else { + sentCapEnd = true _ = client.Send("CAP END") } } @@ -1122,6 +1130,7 @@ func (client *Client) handleEvent(event *Event) { } if !client.Ready() { + sentCapEnd = true _ = client.Send("CAP END") } } @@ -1464,6 +1473,14 @@ func (client *Client) handleEvent(event *Event) { } } + if sentCapEnd { + client.SetValue("internal.lockNickChange", false) + + if primedNick, _ := client.Value("internal.primedNickChange").(string); primedNick != "" { + _ = client.Sendf("NICK %s", primedNick) + } + } + if len(event.targets) == 0 { client.handleInTarget(client.status, event) } diff --git a/client_test.go b/client_test.go index 6ed32d9..e064be9 100644 --- a/client_test.go +++ b/client_test.go @@ -37,6 +37,7 @@ func TestClient(t *testing.T) { {Client: "USER Tester 8 * :..."}, {Server: ":testserver.example.com NOTICE * :*** Checking your bits..."}, {Server: ":testserver.example.com CAP * LS :multi-prefix chghost userhost-in-names vendorname/custom-stuff echo-message =malformed vendorname/advanced-custom-stuff=things,and,items"}, + {Server: ":testserver.example.com 433 * Test :Nick is not available"}, {Client: "CAP REQ :multi-prefix chghost userhost-in-names echo-message"}, {Server: ":testserver.example.com CAP * ACK :multi-prefix userhost-in-names"}, {Client: "CAP END"}, @@ -56,7 +57,6 @@ func TestClient(t *testing.T) { return nil }}, - {Server: ":testserver.example.com 433 * Test :Nick is not available"}, {Client: "NICK Test2"}, {Server: ":testserver.example.com 433 * Test2 :Nick is not available"}, {Client: "NICK Test3"},