From 535af954ad067adf6863e433932f49a732be6d32 Mon Sep 17 00:00:00 2001 From: Alcor Date: Fri, 8 May 2026 20:41:50 +0200 Subject: [PATCH 4/7] add /wallops command Special thanks to RektIRC for help with testing. --- catgirl.1 | 2 ++ chat.h | 1 + command.c | 33 ++++++++++++++++++++++++++++----- input.c | 4 ++++ 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/catgirl.1 b/catgirl.1 index 9f8ceeb..eb644a6 100644 --- a/catgirl.1 +++ b/catgirl.1 @@ -811,6 +811,8 @@ Remove masks from the channel ban exception list. Remove masks from the channel invite list. .It Ic /voice Op Ar nick ... Grant users or yourself voice in the channel. +.It Ic /wallops Ar message +Send a WALLOPS. .El . .Sh KEY BINDINGS diff --git a/chat.h b/chat.h index bd69b5e..d08fe38 100644 --- a/chat.h +++ b/chat.h @@ -303,6 +303,7 @@ void command(uint id, char *input); const char *commandIsPrivmsg(uint id, const char *input); const char *commandIsNotice(uint id, const char *input); const char *commandIsAction(uint id, const char *input); +const char *commandIsWallops(uint id, const char *input); size_t commandWillSplit(uint id, const char *input); void commandCompletion(void); diff --git a/command.c b/command.c index 35e1d63..b985ed5 100644 --- a/command.c +++ b/command.c @@ -53,24 +53,32 @@ static void commandQuote(uint id, char *params) { static void echoMessage(char *cmd, uint id, char *params) { if (!params) return; - ircFormat("%s %s :%s\r\n", cmd, idNames[id], params); + bool wallops = (*cmd == 'W'); + if (wallops) { + ircFormat("%s :%s\r\n", cmd, params); + } else { + ircFormat("%s %s :%s\r\n", cmd, idNames[id], params); + } struct Message msg = { .nick = self.nick, .user = self.user, .cmd = cmd, - .params[0] = idNames[id], - .params[1] = params, + .params[0] = (wallops ? params : idNames[id]), + .params[1] = (wallops ? NULL : params), }; handle(&msg); } static int splitChunk(const char *cmd, uint id) { + bool wallops = (*cmd == 'W'); int overhead = snprintf( - NULL, 0, ":%s!%*s@%*s %s %s :\r\n", + NULL, 0, ":%s!%*s@%*s %s%s%s :\r\n", self.nick, (self.user ? 0 : network.userLen), (self.user ?: "*"), (self.host ? 0 : network.hostLen), (self.host ?: "*"), - cmd, idNames[id] + cmd, + (wallops ? "" : " "), + (wallops ? "" : idNames[id]) ); assert(overhead > 0 && overhead < 512); return 512 - overhead; @@ -315,6 +323,12 @@ static void commandVoice(uint id, char *params) { } } +static void commandWallops(uint id, char *params) { + (void)id; + if (!params) return; + splitMessage("WALLOPS", Network, params); +} + static void commandDevoice(uint id, char *params) { channelListMode(id, '-', 'v', (params ?: self.nick)); } @@ -619,6 +633,7 @@ static const struct Handler { { "/unignore", commandUnignore, 0, 0 }, { "/uninvex", commandUninvex, 0, 0 }, { "/voice", commandVoice, 0, 0 }, + { "/wallops", commandWallops, Multiline, 0 }, { "/whois", commandWhois, 0, 0 }, { "/whowas", commandWhowas, 0, 0 }, { "/window", commandWindow, 0, 0 }, @@ -650,6 +665,12 @@ const char *commandIsAction(uint id, const char *input) { return &input[4]; } +const char *commandIsWallops(uint id, const char *input) { + if (id == Debug) return NULL; + if (strncmp(input, "/wallops ", 9)) return NULL; + return &input[9]; +} + size_t commandWillSplit(uint id, const char *input) { int chunk; const char *params; @@ -659,6 +680,8 @@ size_t commandWillSplit(uint id, const char *input) { chunk = splitChunk("NOTICE", id); } else if (NULL != (params = commandIsAction(id, input))) { chunk = splitChunk("PRIVMSG \1ACTION\1", id); + } else if (NULL != (params = commandIsWallops(id, input))) { + chunk = splitChunk("WALLOPS", id); } else if (id != Network && id != Debug && !strncmp(input, "/say ", 5)) { params = &input[5]; chunk = splitChunk("PRIVMSG", id); diff --git a/input.c b/input.c index 748dca2..920c5f1 100644 --- a/input.c +++ b/input.c @@ -184,6 +184,7 @@ void inputUpdate(void) { const char *privmsg = commandIsPrivmsg(id, buf); const char *notice = commandIsNotice(id, buf); const char *action = commandIsAction(id, buf); + const char *wallops = commandIsWallops(id, buf); if (privmsg) { prefix = "<"; suffix = "> "; skip = privmsg; @@ -196,6 +197,9 @@ void inputUpdate(void) { stylePrompt.attr |= Italic; styleInput.attr |= Italic; skip = action; + } else if (wallops) { + prefix = "!"; suffix = "! "; + skip = wallops; } else if (id == Debug && buf[0] != '/') { prompt = "<< "; stylePrompt.fg = Gray; -- 2.47.3