Fix NICK on upstreams supporting MONITOR

Previously, uc.network.Network.Nick wasn't successfully updated on
downstream NICK. This would cause soju to immediately switch back to the
old nick when the upstream supported MONITOR, so long as the network had
a nick configured as of initialization.

In addition, stop monitoring our desired nick once we've successfully
switched to it once, in order to not immediately undo server-induced
nick changes.
This commit is contained in:
Ember Sawady 2022-08-22 19:59:52 +00:00 committed by Simon Ser
parent 5e56cc30c5
commit 57584c08ed
2 changed files with 12 additions and 2 deletions

View File

@ -1838,6 +1838,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
} }
if dc.network != nil { if dc.network != nil {
dc.network.Network.Nick = nick
if uc := dc.upstream(); uc != nil { if uc := dc.upstream(); uc != nil {
uc.SendMessageLabeled(ctx, dc.id, &irc.Message{ uc.SendMessageLabeled(ctx, dc.id, &irc.Message{
Command: "NICK", Command: "NICK",

View File

@ -159,6 +159,8 @@ type upstreamConn struct {
regainNickBackoff *backoffer regainNickBackoff *backoffer
gotMotd bool gotMotd bool
hasDesiredNick bool
} }
func connectToUpstream(ctx context.Context, network *network) (*upstreamConn, error) { func connectToUpstream(ctx context.Context, network *network) (*upstreamConn, error) {
@ -269,6 +271,7 @@ func connectToUpstream(ctx context.Context, network *network) (*upstreamConn, er
isupport: make(map[string]*string), isupport: make(map[string]*string),
pendingCmds: make(map[string][]pendingUpstreamCommand), pendingCmds: make(map[string][]pendingUpstreamCommand),
monitored: monitorCasemapMap{newCasemapMap()}, monitored: monitorCasemapMap{newCasemapMap()},
hasDesiredNick: true,
} }
return uc, nil return uc, nil
} }
@ -948,6 +951,10 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
uc.pendingRegainNick = "" uc.pendingRegainNick = ""
uc.stopRegainNickTimer() uc.stopRegainNickTimer()
} }
wantNick := database.GetNick(&uc.user.User, &uc.network.Network)
if uc.network.equalCasemap(wantNick, newNick) {
uc.hasDesiredNick = true
}
} }
uc.channels.ForEach(func(ch *upstreamChannel) { uc.channels.ForEach(func(ch *upstreamChannel) {
@ -1581,7 +1588,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
// Check if the nick we want is now free // Check if the nick we want is now free
wantNick := database.GetNick(&uc.user.User, &uc.network.Network) wantNick := database.GetNick(&uc.user.User, &uc.network.Network)
if !online && !uc.isOurNick(wantNick) { if !online && !uc.isOurNick(wantNick) && !uc.hasDesiredNick {
found := false found := false
for _, target := range targets { for _, target := range targets {
prefix := irc.ParsePrefix(target) prefix := irc.ParsePrefix(target)
@ -1790,6 +1797,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
// servers have NICKLEN=30 so let's just use that. // servers have NICKLEN=30 so let's just use that.
if !uc.registered && len(uc.nick)+1 < 30 { if !uc.registered && len(uc.nick)+1 < 30 {
uc.nick = uc.nick + "_" uc.nick = uc.nick + "_"
uc.hasDesiredNick = false
uc.logger.Printf("desired nick is not available, falling back to %q", uc.nick) uc.logger.Printf("desired nick is not available, falling back to %q", uc.nick)
uc.SendMessage(ctx, &irc.Message{ uc.SendMessage(ctx, &irc.Message{
Command: "NICK", Command: "NICK",
@ -2238,7 +2246,8 @@ func (uc *upstreamConn) updateMonitor() {
wantNick := database.GetNick(&uc.user.User, &uc.network.Network) wantNick := database.GetNick(&uc.user.User, &uc.network.Network)
wantNickCM := uc.network.casemap(wantNick) wantNickCM := uc.network.casemap(wantNick)
if _, ok := add[wantNickCM]; !ok && !uc.monitored.Has(wantNick) && !uc.isOurNick(wantNick) { if _, ok := add[wantNickCM]; !ok && !uc.monitored.Has(wantNick) &&
!uc.isOurNick(wantNick) && !uc.hasDesiredNick {
addList = append(addList, wantNickCM) addList = append(addList, wantNickCM)
add[wantNickCM] = struct{}{} add[wantNickCM] = struct{}{}
} }