feat: implement IRC numerics batch 2 — connection registration, channel ops, user queries #59

Merged
sneak merged 4 commits from feature/irc-numerics-batch2 into main 2026-03-10 00:53:47 +01:00
3 changed files with 49 additions and 28 deletions
Showing only changes of commit 5efb4b6949 - Show all commits

View File

@@ -19,6 +19,9 @@ const (
httpTimeout = 30 * time.Second httpTimeout = 30 * time.Second
pollExtraTime = 5 pollExtraTime = 5
httpErrThreshold = 400 httpErrThreshold = 400
cmdJoin = "JOIN"
cmdPart = "PART"
) )
var errHTTP = errors.New("HTTP error") var errHTTP = errors.New("HTTP error")
@@ -168,7 +171,7 @@ func (client *Client) PollMessages(
func (client *Client) JoinChannel(channel string) error { func (client *Client) JoinChannel(channel string) error {
return client.SendMessage( return client.SendMessage(
&Message{ //nolint:exhaustruct // only command+to needed &Message{ //nolint:exhaustruct // only command+to needed
Command: "JOIN", To: channel, Command: cmdJoin, To: channel,
}, },
) )
} }
@@ -177,7 +180,7 @@ func (client *Client) JoinChannel(channel string) error {
func (client *Client) PartChannel(channel string) error { func (client *Client) PartChannel(channel string) error {
return client.SendMessage( return client.SendMessage(
&Message{ //nolint:exhaustruct // only command+to needed &Message{ //nolint:exhaustruct // only command+to needed
Command: "PART", To: channel, Command: cmdPart, To: channel,
}, },
) )
} }

View File

@@ -16,6 +16,17 @@ const (
pollTimeout = 15 pollTimeout = 15
pollRetry = 2 * time.Second pollRetry = 2 * time.Second
timeFormat = "15:04" 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. // App holds the application state.
@@ -86,7 +97,7 @@ func (a *App) handleInput(text string) {
} }
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: "PRIVMSG", Command: cmdPrivmsg,
To: target, To: target,
Body: []string{text}, Body: []string{text},
}) })
@@ -241,7 +252,7 @@ func (a *App) cmdNick(nick string) {
} }
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: "NICK", Command: cmdNick,
Body: []string{nick}, Body: []string{nick},
}) })
if err != nil { if err != nil {
@@ -376,7 +387,7 @@ func (a *App) cmdMsg(args string) {
} }
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: "PRIVMSG", Command: cmdPrivmsg,
To: target, To: target,
Body: []string{text}, Body: []string{text},
}) })
@@ -434,7 +445,7 @@ func (a *App) cmdTopic(args string) {
if args == "" { if args == "" {
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: "TOPIC", Command: cmdTopic,
To: target, To: target,
}) })
if err != nil { if err != nil {
@@ -447,7 +458,7 @@ func (a *App) cmdTopic(args string) {
} }
err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct err := a.client.SendMessage(&api.Message{ //nolint:exhaustruct
Command: "TOPIC", Command: cmdTopic,
To: target, To: target,
Body: []string{args}, Body: []string{args},
}) })
@@ -535,7 +546,7 @@ func (a *App) cmdMotd() {
} }
err := a.client.SendMessage( err := a.client.SendMessage(
&api.Message{Command: "MOTD"}, //nolint:exhaustruct &api.Message{Command: cmdMotd}, //nolint:exhaustruct
) )
if err != nil { if err != nil {
a.ui.AddStatus(fmt.Sprintf( a.ui.AddStatus(fmt.Sprintf(
@@ -572,7 +583,7 @@ func (a *App) cmdWho(args string) {
err := a.client.SendMessage( err := a.client.SendMessage(
&api.Message{ //nolint:exhaustruct &api.Message{ //nolint:exhaustruct
Command: "WHO", To: channel, Command: cmdWho, To: channel,
}, },
) )
if err != nil { if err != nil {
@@ -603,7 +614,7 @@ func (a *App) cmdWhois(args string) {
err := a.client.SendMessage( err := a.client.SendMessage(
&api.Message{ //nolint:exhaustruct &api.Message{ //nolint:exhaustruct
Command: "WHOIS", To: args, Command: cmdWhois, To: args,
}, },
) )
if err != nil { if err != nil {
@@ -653,7 +664,7 @@ func (a *App) cmdQuit() {
if a.connected && a.client != nil { if a.connected && a.client != nil {
_ = a.client.SendMessage( _ = a.client.SendMessage(
&api.Message{Command: "QUIT"}, //nolint:exhaustruct &api.Message{Command: cmdQuit}, //nolint:exhaustruct
) )
} }
@@ -738,19 +749,19 @@ func (a *App) handleServerMessage(msg *api.Message) {
a.mu.Unlock() a.mu.Unlock()
switch msg.Command { switch msg.Command {
case "PRIVMSG": case cmdPrivmsg:
a.handlePrivmsgEvent(msg, timestamp, myNick) a.handlePrivmsgEvent(msg, timestamp, myNick)
case "JOIN": case cmdJoin:
a.handleJoinEvent(msg, timestamp) a.handleJoinEvent(msg, timestamp)
case "PART": case cmdPart:
a.handlePartEvent(msg, timestamp) a.handlePartEvent(msg, timestamp)
case "QUIT": case cmdQuit:
a.handleQuitEvent(msg, timestamp) a.handleQuitEvent(msg, timestamp)
case "NICK": case cmdNick:
a.handleNickEvent(msg, timestamp, myNick) a.handleNickEvent(msg, timestamp, myNick)
case "NOTICE": case cmdNotice:
a.handleNoticeEvent(msg, timestamp) a.handleNoticeEvent(msg, timestamp)
case "TOPIC": case cmdTopic:
a.handleTopicEvent(msg, timestamp) a.handleTopicEvent(msg, timestamp)
default: default:
a.handleDefaultEvent(msg, timestamp) a.handleDefaultEvent(msg, timestamp)

View File

@@ -29,8 +29,15 @@ const (
maxHistLimit = 500 maxHistLimit = 500
cmdJoin = "JOIN" cmdJoin = "JOIN"
cmdList = "LIST" cmdList = "LIST"
cmdLusers = "LUSERS"
cmdMode = "MODE"
cmdMotd = "MOTD"
cmdNames = "NAMES"
cmdNick = "NICK" cmdNick = "NICK"
cmdNotice = "NOTICE"
cmdPart = "PART" cmdPart = "PART"
cmdPing = "PING"
cmdPong = "PONG"
cmdPrivmsg = "PRIVMSG" cmdPrivmsg = "PRIVMSG"
cmdQuit = "QUIT" cmdQuit = "QUIT"
cmdTopic = "TOPIC" cmdTopic = "TOPIC"
@@ -758,7 +765,7 @@ func (hdlr *Handlers) dispatchCommand(
bodyLines func() []string, bodyLines func() []string,
) { ) {
switch command { switch command {
case cmdPrivmsg, "NOTICE": case cmdPrivmsg, cmdNotice:
hdlr.handlePrivmsg( hdlr.handlePrivmsg(
writer, request, writer, request,
sessionID, clientID, nick, sessionID, clientID, nick,
@@ -789,7 +796,7 @@ func (hdlr *Handlers) dispatchCommand(
hdlr.handleQuit( hdlr.handleQuit(
writer, request, sessionID, nick, body, writer, request, sessionID, nick, body,
) )
case "MOTD", cmdList, cmdWho, cmdWhois, "PING": case cmdMotd, cmdList, cmdWho, cmdWhois, cmdPing:
hdlr.dispatchInfoCommand( hdlr.dispatchInfoCommand(
writer, request, writer, request,
sessionID, clientID, nick, sessionID, clientID, nick,
@@ -812,13 +819,13 @@ func (hdlr *Handlers) dispatchQueryCommand(
bodyLines func() []string, bodyLines func() []string,
) { ) {
switch command { switch command {
case "MODE": case cmdMode:
hdlr.handleMode( hdlr.handleMode(
writer, request, writer, request,
sessionID, clientID, nick, sessionID, clientID, nick,
target, bodyLines, target, bodyLines,
) )
case "NAMES": case cmdNames:
hdlr.handleNames( hdlr.handleNames(
writer, request, writer, request,
sessionID, clientID, nick, target, sessionID, clientID, nick, target,
@@ -839,7 +846,7 @@ func (hdlr *Handlers) dispatchQueryCommand(
writer, request, writer, request,
sessionID, clientID, nick, target, sessionID, clientID, nick, target,
) )
case "LUSERS": case cmdLusers:
hdlr.handleLusers( hdlr.handleLusers(
writer, request, writer, request,
sessionID, clientID, nick, sessionID, clientID, nick,
@@ -1571,7 +1578,7 @@ func (hdlr *Handlers) dispatchInfoCommand(
okResp := map[string]string{"status": "ok"} okResp := map[string]string{"status": "ok"}
switch command { switch command {
case "MOTD": case cmdMotd:
hdlr.deliverMOTD( hdlr.deliverMOTD(
request, clientID, sessionID, nick, request, clientID, sessionID, nick,
) )
@@ -1589,10 +1596,10 @@ func (hdlr *Handlers) dispatchInfoCommand(
request, clientID, sessionID, nick, request, clientID, sessionID, nick,
target, bodyLines, target, bodyLines,
) )
case "PING": case cmdPing:
hdlr.respondJSON(writer, request, hdlr.respondJSON(writer, request,
map[string]string{ map[string]string{
"command": "PONG", "command": cmdPong,
"from": hdlr.serverName(), "from": hdlr.serverName(),
}, },
http.StatusOK) http.StatusOK)
@@ -1892,7 +1899,7 @@ func (hdlr *Handlers) handleMode(
if target == "" { if target == "" {
hdlr.respondIRCError( hdlr.respondIRCError(
writer, request, clientID, sessionID, writer, request, clientID, sessionID,
"461", nick, []string{"MODE"}, "461", nick, []string{cmdMode},
"Not enough parameters", "Not enough parameters",
) )
@@ -1981,7 +1988,7 @@ func (hdlr *Handlers) handleNames(
if target == "" { if target == "" {
hdlr.respondIRCError( hdlr.respondIRCError(
writer, request, clientID, sessionID, writer, request, clientID, sessionID,
"461", nick, []string{"NAMES"}, "461", nick, []string{cmdNames},
"Not enough parameters", "Not enough parameters",
) )