feat: add irc numerics package, deduplicate constants, fix dead code
All checks were successful
check / check (push) Successful in 1m5s

- Create internal/irc/ package with all IRC numeric reply codes (RFC 1459/2812)
  and command string constants as the single source of truth
- Replace all 69+ bare numeric string literals in api.go with named constants
  (e.g. irc.RplWelcome, irc.ErrNoSuchChannel)
- Add 'code' (int) and named 'command' (e.g. RPL_YOURHOST) fields to IRC
  message JSON replies via irc.Name() lookup in scanMessages
- Deduplicate command constants: remove local definitions from api.go,
  cmd/neoirc-cli/main.go, and cmd/neoirc-cli/api/client.go; all now import
  from internal/irc
- Fix dead code: remove handleListCmd/handleWhoCmd/handleWhoisCmd/
  sendWhoisNumerics that were unreachable due to dispatchCommand routing
  LIST/WHO/WHOIS to dispatchInfoCommand before dispatchQueryCommand.
  Route these commands to dispatchQueryCommand which has the improved
  implementations (e.g. ListAllChannelsWithCounts single-query vs N+1)
- Update enqueueNumeric and respondIRCError signatures from string to int
- Update test helper findNumeric to check the new 'code' JSON field

Closes #52
This commit is contained in:
clawbot
2026-03-09 15:49:29 -07:00
parent 5efb4b6949
commit 7bbd6de73a
7 changed files with 307 additions and 361 deletions

View File

@@ -9,6 +9,7 @@ import (
"time"
api "git.eeqj.de/sneak/neoirc/cmd/neoirc-cli/api"
"git.eeqj.de/sneak/neoirc/internal/irc"
)
const (
@@ -16,17 +17,6 @@ const (
pollTimeout = 15
pollRetry = 2 * time.Second
timeFormat = "15:04"
cmdJoin = "JOIN"
cmdMotd = "MOTD"
cmdNick = "NICK"
cmdNotice = "NOTICE"
cmdPart = "PART"
cmdPrivmsg = "PRIVMSG"
cmdQuit = "QUIT"
cmdTopic = "TOPIC"
cmdWho = "WHO"
cmdWhois = "WHOIS"
)
// App holds the application state.
@@ -97,7 +87,7 @@ func (a *App) handleInput(text string) {
}
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: cmdPrivmsg,
Command: irc.CmdPrivmsg,
To: target,
Body: []string{text},
})
@@ -252,7 +242,7 @@ func (a *App) cmdNick(nick string) {
}
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: cmdNick,
Command: irc.CmdNick,
Body: []string{nick},
})
if err != nil {
@@ -387,7 +377,7 @@ func (a *App) cmdMsg(args string) {
}
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: cmdPrivmsg,
Command: irc.CmdPrivmsg,
To: target,
Body: []string{text},
})
@@ -445,7 +435,7 @@ func (a *App) cmdTopic(args string) {
if args == "" {
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: cmdTopic,
Command: irc.CmdTopic,
To: target,
})
if err != nil {
@@ -458,7 +448,7 @@ func (a *App) cmdTopic(args string) {
}
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: cmdTopic,
Command: irc.CmdTopic,
To: target,
Body: []string{args},
})
@@ -546,7 +536,7 @@ func (a *App) cmdMotd() {
}
err := a.client.SendMessage(
&api.Message{Command: cmdMotd}, //nolint:exhaustruct
&api.Message{Command: irc.CmdMotd}, //nolint:exhaustruct
)
if err != nil {
a.ui.AddStatus(fmt.Sprintf(
@@ -583,7 +573,7 @@ func (a *App) cmdWho(args string) {
err := a.client.SendMessage(
&api.Message{ //nolint:exhaustruct
Command: cmdWho, To: channel,
Command: irc.CmdWho, To: channel,
},
)
if err != nil {
@@ -614,7 +604,7 @@ func (a *App) cmdWhois(args string) {
err := a.client.SendMessage(
&api.Message{ //nolint:exhaustruct
Command: cmdWhois, To: args,
Command: irc.CmdWhois, To: args,
},
)
if err != nil {
@@ -664,7 +654,7 @@ func (a *App) cmdQuit() {
if a.connected && a.client != nil {
_ = a.client.SendMessage(
&api.Message{Command: cmdQuit}, //nolint:exhaustruct
&api.Message{Command: irc.CmdQuit}, //nolint:exhaustruct
)
}
@@ -749,19 +739,19 @@ func (a *App) handleServerMessage(msg *api.Message) {
a.mu.Unlock()
switch msg.Command {
case cmdPrivmsg:
case irc.CmdPrivmsg:
a.handlePrivmsgEvent(msg, timestamp, myNick)
case cmdJoin:
case irc.CmdJoin:
a.handleJoinEvent(msg, timestamp)
case cmdPart:
case irc.CmdPart:
a.handlePartEvent(msg, timestamp)
case cmdQuit:
case irc.CmdQuit:
a.handleQuitEvent(msg, timestamp)
case cmdNick:
case irc.CmdNick:
a.handleNickEvent(msg, timestamp, myNick)
case cmdNotice:
case irc.CmdNotice:
a.handleNoticeEvent(msg, timestamp)
case cmdTopic:
case irc.CmdTopic:
a.handleTopicEvent(msg, timestamp)
default:
a.handleDefaultEvent(msg, timestamp)