diff --git a/CHANGELOG.md b/CHANGELOG.md index d62a99b4..092f429c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ New release of Oragono! * Added ARM build (for Raspberry PIs and similar). * Added automated connection throttling! See the new `connection-throttling` section in the config. * Added `KLINE` and `UNKLINE` commands. Complementing `DLINE`'s per-IP and per-network bans, this lets you ban masks from the server. +* Added LUSERS command. It works for a single server for now (by @vegax87) ### Changed * Changed casemapping from "rfc7700" to "rfc7613", to match new draft spec. diff --git a/irc/commands.go b/irc/commands.go index 964eaca3..b3bb056c 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -116,6 +116,10 @@ var Commands = map[string]Command{ handler: listHandler, minParams: 0, }, + "LUSERS": { + handler: lusersHandler, + minParams: 0, + }, "MODE": { handler: modeHandler, minParams: 1, diff --git a/irc/help.go b/irc/help.go index a2227ed2..3dce40df 100644 --- a/irc/help.go +++ b/irc/help.go @@ -189,6 +189,15 @@ Shows information on the given channels (or if none are given, then on all channels). s modify how the channels are selected.`, //TODO(dan): Explain s in more specific detail }, + "lusers": { + text: `LUSERS [ [ ] ] + +Returns statistics about the size of the network. +If called with no arguments, the statistics will reflect the entire network. +If is given, it will return only statistics reflecting the masked subset of the network. +If is given, the command will be forwarded to for evaluation.`, + //TODO(vegax87): Include network statistics and parameters + }, "mode": { text: `MODE [ [...]] diff --git a/irc/server.go b/irc/server.go index 985aaa75..ee1447a9 100644 --- a/irc/server.go +++ b/irc/server.go @@ -1677,3 +1677,38 @@ func whowasHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { } return false } + +// LUSERS [ [ ] ] +func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { + //TODO(vegax87) Fix Unknown connections and additional parameters + + var totalcount int + var invisiblecount int + var opercount int + var chancount int + + server.clients.ByNickMutex.RLock() + defer server.clients.ByNickMutex.RUnlock() + + for _, onlineusers := range server.clients.ByNick { + totalcount += 1 + if onlineusers.flags[Invisible] { + invisiblecount += 1 + } + if onlineusers.flags[Operator] { + opercount += 1 + } + } + + for chans := range server.channels { + //Little hack just to avoid "variable declared but not used" error + _ = chans + chancount += 1 + } + client.Send(nil, server.name, RPL_LUSERCLIENT, client.nick, fmt.Sprintf("There are %d users and %d invisible on %d server(s)", totalcount, invisiblecount, 1)) + client.Send(nil, server.name, RPL_LUSEROP, client.nick, fmt.Sprintf("%d operators online", opercount)) + client.Send(nil, server.name, RPL_LUSERUNKNOWN, client.nick, "X unknown connection(s)") + client.Send(nil, server.name, RPL_LUSERCHANNELS, client.nick, fmt.Sprintf("%d channels formed", chancount)) + client.Send(nil, server.name, RPL_LUSERME, client.nick, fmt.Sprintf("I have %d clients and %d servers", totalcount, 1)) + return false +}