From eab5f8747abae8c1fe27f1e2c8d9c0a5c55fd8da Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Fri, 15 Aug 2025 21:35:27 +0200 Subject: [PATCH] feat: support and handle changing nicknames --- cmds/cmds.go | 6 +++++ irc/handler/handler.go | 49 ++++++++++++++++++++++++++++++++++++++ ui/mainscreen/sidepanel.go | 2 +- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/cmds/cmds.go b/cmds/cmds.go index 30ed5ed..c36ce74 100644 --- a/cmds/cmds.go +++ b/cmds/cmds.go @@ -69,6 +69,12 @@ func SwitchChannels() tea.Msg { return SwitchChannelsMsg{} } +type UpdateNicksMsg struct{} + +func UpdateNicks() tea.Msg { + return UpdateNicksMsg{} +} + type UpdateTabBarMsg struct{} func UpdateTabBar() tea.Msg { diff --git a/irc/handler/handler.go b/irc/handler/handler.go index 385f035..c2ece14 100644 --- a/irc/handler/handler.go +++ b/irc/handler/handler.go @@ -155,6 +155,53 @@ func handleJoin(msg irc.Message, client *irc.Client) { } } +// Sent from server to client to acknowledge a nickname change, or to inform of a nickname change of another user. +func handleNick(msg irc.Message, client *irc.Client) { + oldNick := strings.SplitN(msg.Source, "!", 2)[0] + newNick := msg.Parameters[0] + + // TODO: the actual case-sensitivity is determined by the CASEMAPPING feature + isMe := strings.EqualFold(oldNick, client.Nickname) + + msgOpts := irc.MsgFmtOpts{ + WithTimestamp: true, + AsServerMsg: true, + } + + message := "" + + if isMe { + message = fmt.Sprintf("Your nickname was changed to %v", newNick) + } else { + message = fmt.Sprintf("%v changed their nickname to %v", oldNick, newNick) + } + + for i, channel := range client.Channels { + // Rename this user in every channel we can find + if user, ok := channel.Users[oldNick]; ok { + delete(client.Channels[i].Users, oldNick) + client.Channels[i].Users[newNick] = user + client.Channels[i].AppendMsg(msg.Timestamp, message, msgOpts) + } + + // If we have a private channel open with this user, rename it as well. + if strings.EqualFold(channel.Name, oldNick) { + client.Channels[i].Name = newNick + + if client.ActiveChannelIndex == i { + client.ActiveChannel = newNick + } + } + } + + if isMe { + client.Channels[0].AppendMsg(msg.Timestamp, message, msgOpts) + client.Nickname = newNick + } + + client.Tea.Send(cmds.UpdateNicks()) +} + func handleQuit(msg irc.Message, client *irc.Client) { nick := strings.SplitN(msg.Source, "!", 2)[0] reason := msg.Parameters[0] @@ -898,6 +945,8 @@ func HandleCommand(msg irc.Message, client *irc.Client) { handleNotice(msg, client) case commands.JOIN: handleJoin(msg, client) + case commands.NICK: + handleNick(msg, client) case commands.QUIT: handleQuit(msg, client) case commands.PART: diff --git a/ui/mainscreen/sidepanel.go b/ui/mainscreen/sidepanel.go index 08002f8..00ac7dc 100644 --- a/ui/mainscreen/sidepanel.go +++ b/ui/mainscreen/sidepanel.go @@ -104,7 +104,7 @@ func (s SidePanelState) Update(msg tea.Msg) (SidePanelState, tea.Cmd) { var cmdsToProcess []tea.Cmd switch msg := msg.(type) { - case cmds.SwitchChannelsMsg: + case cmds.SwitchChannelsMsg, cmds.UpdateNicksMsg: s.UpdateNicks() return s, nil case tea.KeyMsg: