Merge branch 'main' into feature/irc-numerics-batch2
Some checks failed
check / check (push) Failing after 22s
Some checks failed
check / check (push) Failing after 22s
This commit is contained in:
@@ -781,13 +781,12 @@ func (hdlr *Handlers) dispatchCommand(
|
||||
hdlr.handleQuit(
|
||||
writer, request, sessionID, nick, body,
|
||||
)
|
||||
case "PING":
|
||||
hdlr.respondJSON(writer, request,
|
||||
map[string]string{
|
||||
"command": "PONG",
|
||||
"from": hdlr.serverName(),
|
||||
},
|
||||
http.StatusOK)
|
||||
case "MOTD", "LIST", "WHO", "WHOIS", "PING":
|
||||
hdlr.dispatchInfoCommand(
|
||||
writer, request,
|
||||
sessionID, clientID, nick,
|
||||
command, target, bodyLines,
|
||||
)
|
||||
default:
|
||||
hdlr.dispatchQueryCommand(
|
||||
writer, request,
|
||||
@@ -1551,6 +1550,269 @@ func (hdlr *Handlers) executeTopic(
|
||||
http.StatusOK)
|
||||
}
|
||||
|
||||
// dispatchInfoCommand handles informational IRC commands
|
||||
// that produce server-side numerics (MOTD, LIST, WHO,
|
||||
// WHOIS, PING).
|
||||
func (hdlr *Handlers) dispatchInfoCommand(
|
||||
writer http.ResponseWriter,
|
||||
request *http.Request,
|
||||
sessionID, clientID int64,
|
||||
nick, command, target string,
|
||||
bodyLines func() []string,
|
||||
) {
|
||||
okResp := map[string]string{"status": "ok"}
|
||||
|
||||
switch command {
|
||||
case "MOTD":
|
||||
hdlr.deliverMOTD(
|
||||
request, clientID, sessionID, nick,
|
||||
)
|
||||
case "LIST":
|
||||
hdlr.handleListCmd(
|
||||
request, clientID, sessionID, nick,
|
||||
)
|
||||
case "WHO":
|
||||
hdlr.handleWhoCmd(
|
||||
request, clientID, sessionID, nick,
|
||||
target,
|
||||
)
|
||||
case "WHOIS":
|
||||
hdlr.handleWhoisCmd(
|
||||
request, clientID, sessionID, nick,
|
||||
target, bodyLines,
|
||||
)
|
||||
case "PING":
|
||||
hdlr.respondJSON(writer, request,
|
||||
map[string]string{
|
||||
"command": "PONG",
|
||||
"from": hdlr.serverName(),
|
||||
},
|
||||
http.StatusOK)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
hdlr.respondJSON(
|
||||
writer, request, okResp, http.StatusOK,
|
||||
)
|
||||
}
|
||||
|
||||
// handleListCmd sends RPL_LIST (322) for each channel,
|
||||
// then sends 323 to signal the end of the list.
|
||||
func (hdlr *Handlers) handleListCmd(
|
||||
request *http.Request,
|
||||
clientID, sessionID int64,
|
||||
nick string,
|
||||
) {
|
||||
ctx := request.Context()
|
||||
|
||||
channels, err := hdlr.params.Database.ListAllChannels(
|
||||
ctx,
|
||||
)
|
||||
if err != nil {
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "323", nick, nil,
|
||||
"End of /LIST",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, channel := range channels {
|
||||
memberIDs, _ :=
|
||||
hdlr.params.Database.GetChannelMemberIDs(
|
||||
ctx, channel.ID,
|
||||
)
|
||||
|
||||
count := strconv.Itoa(len(memberIDs))
|
||||
topic := channel.Topic
|
||||
|
||||
if topic == "" {
|
||||
topic = " "
|
||||
}
|
||||
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "322", nick,
|
||||
[]string{channel.Name, count}, topic,
|
||||
)
|
||||
}
|
||||
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "323", nick, nil,
|
||||
"End of /LIST",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
}
|
||||
|
||||
// handleWhoCmd sends RPL_WHOREPLY (352) for each member
|
||||
// of the target channel, followed by RPL_ENDOFWHO (315).
|
||||
func (hdlr *Handlers) handleWhoCmd(
|
||||
request *http.Request,
|
||||
clientID, sessionID int64,
|
||||
nick, target string,
|
||||
) {
|
||||
ctx := request.Context()
|
||||
|
||||
if target == "" {
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "461", nick,
|
||||
[]string{"WHO"}, "Not enough parameters",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
channel := target
|
||||
if !strings.HasPrefix(channel, "#") {
|
||||
channel = "#" + channel
|
||||
}
|
||||
|
||||
chID, err := hdlr.params.Database.GetChannelByName(
|
||||
ctx, channel,
|
||||
)
|
||||
if err != nil {
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "315", nick,
|
||||
[]string{channel}, "End of /WHO list",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
members, err := hdlr.params.Database.ChannelMembers(
|
||||
ctx, chID,
|
||||
)
|
||||
if err == nil {
|
||||
srvName := hdlr.serverName()
|
||||
|
||||
for _, mem := range members {
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "352", nick,
|
||||
[]string{
|
||||
channel, mem.Nick, "neoirc",
|
||||
srvName, mem.Nick, "H",
|
||||
},
|
||||
"0 "+mem.Nick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "315", nick,
|
||||
[]string{channel}, "End of /WHO list",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
}
|
||||
|
||||
// handleWhoisCmd sends WHOIS reply numerics (311, 312,
|
||||
// 319, 318) for the target nick.
|
||||
func (hdlr *Handlers) handleWhoisCmd(
|
||||
request *http.Request,
|
||||
clientID, sessionID int64,
|
||||
nick, target string,
|
||||
bodyLines func() []string,
|
||||
) {
|
||||
ctx := request.Context()
|
||||
|
||||
whoisNick := target
|
||||
if whoisNick == "" {
|
||||
lines := bodyLines()
|
||||
if len(lines) > 0 {
|
||||
whoisNick = strings.TrimSpace(lines[0])
|
||||
}
|
||||
}
|
||||
|
||||
if whoisNick == "" {
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "461", nick,
|
||||
[]string{"WHOIS"}, "Not enough parameters",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
targetSID, err :=
|
||||
hdlr.params.Database.GetSessionByNick(
|
||||
ctx, whoisNick,
|
||||
)
|
||||
if err != nil {
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "401", nick,
|
||||
[]string{whoisNick},
|
||||
"No such nick/channel",
|
||||
)
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "318", nick,
|
||||
[]string{whoisNick},
|
||||
"End of /WHOIS list",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
hdlr.sendWhoisNumerics(
|
||||
ctx, clientID, sessionID, nick,
|
||||
whoisNick, targetSID,
|
||||
)
|
||||
}
|
||||
|
||||
// sendWhoisNumerics emits 311/312/319/318 for a
|
||||
// resolved WHOIS target.
|
||||
func (hdlr *Handlers) sendWhoisNumerics(
|
||||
ctx context.Context,
|
||||
clientID, sessionID int64,
|
||||
nick, whoisNick string,
|
||||
targetSID int64,
|
||||
) {
|
||||
srvName := hdlr.serverName()
|
||||
|
||||
// 311 RPL_WHOISUSER
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "311", nick,
|
||||
[]string{whoisNick, whoisNick, "neoirc", "*"},
|
||||
whoisNick,
|
||||
)
|
||||
|
||||
// 312 RPL_WHOISSERVER
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "312", nick,
|
||||
[]string{whoisNick, srvName},
|
||||
srvName,
|
||||
)
|
||||
|
||||
// 319 RPL_WHOISCHANNELS
|
||||
channels, _ := hdlr.params.Database.GetSessionChannels(
|
||||
ctx, targetSID,
|
||||
)
|
||||
|
||||
if len(channels) > 0 {
|
||||
names := make([]string, 0, len(channels))
|
||||
|
||||
for _, chanInfo := range channels {
|
||||
names = append(names, chanInfo.Name)
|
||||
}
|
||||
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "319", nick,
|
||||
[]string{whoisNick},
|
||||
strings.Join(names, " "),
|
||||
)
|
||||
}
|
||||
|
||||
// 318 RPL_ENDOFWHOIS
|
||||
hdlr.enqueueNumeric(
|
||||
ctx, clientID, "318", nick,
|
||||
[]string{whoisNick},
|
||||
"End of /WHOIS list",
|
||||
)
|
||||
hdlr.broker.Notify(sessionID)
|
||||
}
|
||||
|
||||
func (hdlr *Handlers) handleQuit(
|
||||
writer http.ResponseWriter,
|
||||
request *http.Request,
|
||||
|
||||
Reference in New Issue
Block a user