Make an IRC listener connection follow its session's nick (closes #184)
check / check (push) Waiting to run

When the session's nick was changed from another client, such as the
web client over the HTTP API, the IRC listener connection kept the old
nick and sent its messages, joins and later NICK changes under it. Now,
whenever the relay passes on a NICK line, the connection first takes
the nick its session holds in the database. It does not go by the
line's old nick, as the connection may have taken that nick after
another user gave it up. As the relay goroutine can now change the
nick, the command handlers read it under the connection's lock,
through currentNick, as the relay already did.

Model: opus-5-5
This commit is contained in:
2026-10-21 14:04:22 +00:00
parent 129d87d578
commit d90962c960
5 changed files with 176 additions and 45 deletions
+19 -3
View File
@@ -92,7 +92,7 @@ func (c *Conn) drainQueue(ctx context.Context) bool {
//
//nolint:cyclop // dispatch table
func (c *Conn) deliverIRCMessage(
_ context.Context,
ctx context.Context,
msg *db.IRCMessage,
) {
command := msg.Command
@@ -120,7 +120,7 @@ func (c *Conn) deliverIRCMessage(
case command == irc.CmdPart:
c.deliverPart(msg, text)
case command == irc.CmdNick:
c.deliverNickChange(msg, text)
c.deliverNickChange(ctx, msg, text)
case command == irc.CmdQuit:
c.deliverQuitMsg(msg, text)
case command == irc.CmdTopic:
@@ -230,11 +230,27 @@ func (c *Conn) deliverPart(msg *db.IRCMessage, text string) {
}
}
// deliverNickChange sends a NICK change notification.
// deliverNickChange sends a NICK change notification. The
// change may be its own session's, made from another client,
// so the connection first takes the nick its session holds
// now. It does not go by the line's old nick: the connection
// may have taken that nick after another user gave it up. It
// reads the nick under c.mu, so that a NICK sent on the
// connection meanwhile is not undone.
func (c *Conn) deliverNickChange(
ctx context.Context,
msg *db.IRCMessage,
newNick string,
) {
c.mu.Lock()
nick, err := c.database.GetSessionNick(ctx, c.sessionID)
if err == nil {
c.nick = nick
}
c.mu.Unlock()
prefix := msg.From + "!" + msg.From + "@*"
c.send(FormatMessage(prefix, "NICK", newNick))