Add /mode, /except, /invex and handle lists replies

master
C. McEnroe 2020-02-25 02:12:35 -05:00
parent c3c40d738b
commit 3c5e1c95a4
4 changed files with 134 additions and 18 deletions

View File

@ -1,4 +1,4 @@
.Dd February 19, 2020 .Dd February 23, 2020
.Dt CATGIRL 1 .Dt CATGIRL 1
.Os .Os
. .
@ -242,16 +242,12 @@ can be typed
.Bl -tag -width Ds .Bl -tag -width Ds
.It Ic /away Op Ar message .It Ic /away Op Ar message
Set or clear your away status. Set or clear your away status.
.It Ic /ban Op Ar mask ...
List or ban masks from the channel.
.It Ic /cs Ar command .It Ic /cs Ar command
Send a command to ChanServ. Send a command to ChanServ.
.It Ic /invite Ar nick .It Ic /invite Ar nick
Invite a user to the channel. Invite a user to the channel.
.It Ic /join Ar channel .It Ic /join Ar channel
Join a channel. Join a channel.
.It Ic /kick Ar nick Op Ar message
Kick a user from the channel.
.It Ic /list Op Ar channel .It Ic /list Op Ar channel
List channels. List channels.
.It Ic /me Op Ar action .It Ic /me Op Ar action
@ -276,8 +272,6 @@ Quit IRC.
Send a raw IRC command. Send a raw IRC command.
.It Ic /topic Op Ar topic .It Ic /topic Op Ar topic
Show or set the topic of the channel. Show or set the topic of the channel.
.It Ic /unban Ar mask ...
Unban masks from the channel.
.It Ic /whois Ar nick .It Ic /whois Ar nick
Query information about a user. Query information about a user.
.El .El
@ -326,6 +320,30 @@ Switch to window by name.
Switch to window by number. Switch to window by number.
.El .El
. .
.Ss Operator Commands
.Bl -tag -width Ds
.It Ic /ban Op Ar mask ...
List or ban masks from the channel.
.It Ic /except Op Ar mask ...
List or add masks to the channel ban exception list.
.It Ic /invex Op Ar mask ...
List or add masks to the channel invite list.
.It Ic /kick Ar nick Op Ar message
Kick a user from the channel.
.It Ic /mode Oo Ar modes Oc Op Ar param ...
Show or set channel modes.
In the
.Sy <network>
window,
show or set user modes.
.It Ic /unban Ar mask ...
Unban masks from the channel.
.It Ic /unexcept Ar mask ...
Remove masks from the channel ban exception list.
.It Ic /uninvex Ar mask ...
Remove masks from the channel invite list.
.El
.
.Sh KEY BINDINGS .Sh KEY BINDINGS
The The
.Nm .Nm

2
chat.h
View File

@ -176,6 +176,8 @@ static inline void utilPush(struct Util *util, const char *arg) {
extern struct Replies { extern struct Replies {
uint away; uint away;
uint ban; uint ban;
uint excepts;
uint invex;
uint join; uint join;
uint list; uint list;
uint names; uint names;

View File

@ -143,14 +143,34 @@ static void commandKick(uint id, char *params) {
} }
} }
static void commandMode(uint id, char *params) {
if (id == Network) {
if (params) {
ircFormat("MODE %s %s\r\n", self.nick, params);
} else {
ircFormat("MODE %s\r\n", self.nick);
}
} else {
if (params) {
ircFormat("MODE %s %s\r\n", idNames[id], params);
} else {
ircFormat("MODE %s\r\n", idNames[id]);
}
}
}
static void channelListMode(uint id, char pm, char l, char *params) {
int count = 1;
for (char *ch = params; *ch; ++ch) {
if (*ch == ' ') count++;
}
char modes[ParamCap - 2] = { l, l, l, l, l, l, l, l, l, l, l, l, l };
ircFormat("MODE %s %c%.*s %s\r\n", idNames[id], pm, count, modes, params);
}
static void commandBan(uint id, char *params) { static void commandBan(uint id, char *params) {
if (params) { if (params) {
int count = 1; channelListMode(id, '+', 'b', params);
for (char *ch = params; *ch; ++ch) {
if (*ch == ' ') count++;
}
char b[ParamCap - 2] = "bbbbbbbbbbbbb";
ircFormat("MODE %s +%.*s %s\r\n", idNames[id], count, b, params);
} else { } else {
ircFormat("MODE %s b\r\n", idNames[id]); ircFormat("MODE %s b\r\n", idNames[id]);
replies.ban++; replies.ban++;
@ -159,12 +179,35 @@ static void commandBan(uint id, char *params) {
static void commandUnban(uint id, char *params) { static void commandUnban(uint id, char *params) {
if (!params) return; if (!params) return;
int count = 1; channelListMode(id, '-', 'b', params);
for (char *ch = params; *ch; ++ch) { }
if (*ch == ' ') count++;
static void commandExcept(uint id, char *params) {
if (params) {
channelListMode(id, '+', network.excepts, params);
} else {
ircFormat("MODE %s %c\r\n", idNames[id], network.excepts);
replies.excepts++;
} }
char b[ParamCap - 2] = "bbbbbbbbbbbbb"; }
ircFormat("MODE %s -%.*s %s\r\n", idNames[id], count, b, params);
static void commandUnexcept(uint id, char *params) {
if (!params) return;
channelListMode(id, '-', network.excepts, params);
}
static void commandInvex(uint id, char *params) {
if (params) {
channelListMode(id, '+', network.invex, params);
} else {
ircFormat("MODE %s %c\r\n", idNames[id], network.invex);
replies.invex++;
}
}
static void commandUninvex(uint id, char *params) {
if (!params) return;
channelListMode(id, '-', network.invex, params);
} }
static void commandList(uint id, char *params) { static void commandList(uint id, char *params) {
@ -293,13 +336,16 @@ static const struct Handler {
{ "/copy", .fn = commandCopy, .restricted = true }, { "/copy", .fn = commandCopy, .restricted = true },
{ "/cs", .fn = commandCS }, { "/cs", .fn = commandCS },
{ "/debug", .fn = commandDebug, .restricted = true }, { "/debug", .fn = commandDebug, .restricted = true },
{ "/except", .fn = commandExcept },
{ "/exec", .fn = commandExec, .restricted = true }, { "/exec", .fn = commandExec, .restricted = true },
{ "/help", .fn = commandHelp }, { "/help", .fn = commandHelp },
{ "/invex", .fn = commandInvex },
{ "/invite", .fn = commandInvite }, { "/invite", .fn = commandInvite },
{ "/join", .fn = commandJoin, .restricted = true }, { "/join", .fn = commandJoin, .restricted = true },
{ "/kick", .fn = commandKick }, { "/kick", .fn = commandKick },
{ "/list", .fn = commandList }, { "/list", .fn = commandList },
{ "/me", .fn = commandMe }, { "/me", .fn = commandMe },
{ "/mode", .fn = commandMode },
{ "/move", .fn = commandMove }, { "/move", .fn = commandMove },
{ "/msg", .fn = commandMsg, .restricted = true }, { "/msg", .fn = commandMsg, .restricted = true },
{ "/names", .fn = commandNames }, { "/names", .fn = commandNames },
@ -313,6 +359,8 @@ static const struct Handler {
{ "/quote", .fn = commandQuote, .restricted = true }, { "/quote", .fn = commandQuote, .restricted = true },
{ "/topic", .fn = commandTopic }, { "/topic", .fn = commandTopic },
{ "/unban", .fn = commandUnban }, { "/unban", .fn = commandUnban },
{ "/unexcept", .fn = commandUnexcept },
{ "/uninvex", .fn = commandUninvex },
{ "/whois", .fn = commandWhois }, { "/whois", .fn = commandWhois },
{ "/window", .fn = commandWindow }, { "/window", .fn = commandWindow },
}; };

View File

@ -606,6 +606,50 @@ static void handleReplyEndOfBanList(struct Message *msg) {
if (replies.ban) replies.ban--; if (replies.ban) replies.ban--;
} }
static void onList(const char *list, struct Message *msg) {
uint id = idFor(msg->params[1]);
if (msg->params[3] && msg->params[4]) {
char since[sizeof("0000-00-00 00:00:00")];
time_t time = strtol(msg->params[4], NULL, 10);
strftime(since, sizeof(since), "%F %T", localtime(&time));
uiFormat(
id, Cold, tagTime(msg),
"On the \3%02d%s\3 %s list since %s by \3%02d%s\3: %s",
hash(msg->params[1]), msg->params[1], list,
since, completeColor(id, msg->params[3]), msg->params[3],
msg->params[2]
);
} else {
uiFormat(
id, Cold, tagTime(msg),
"On the \3%02d%s\3 %s list: %s",
hash(msg->params[1]), msg->params[1], list, msg->params[2]
);
}
}
static void handleReplyExceptList(struct Message *msg) {
require(msg, false, 3);
if (!replies.excepts) return;
onList("except", msg);
}
static void handleReplyEndOfExceptList(struct Message *msg) {
(void)msg;
if (replies.excepts) replies.excepts--;
}
static void handleReplyInviteList(struct Message *msg) {
require(msg, false, 3);
if (!replies.invex) return;
onList("invite", msg);
}
static void handleReplyEndOfInviteList(struct Message *msg) {
(void)msg;
if (replies.invex) replies.invex--;
}
static void handleReplyList(struct Message *msg) { static void handleReplyList(struct Message *msg) {
require(msg, false, 4); require(msg, false, 4);
if (!replies.list) return; if (!replies.list) return;
@ -881,6 +925,10 @@ static const struct Handler {
{ "331", handleReplyNoTopic }, { "331", handleReplyNoTopic },
{ "332", handleReplyTopic }, { "332", handleReplyTopic },
{ "341", handleReplyInviting }, { "341", handleReplyInviting },
{ "346", handleReplyInviteList },
{ "347", handleReplyEndOfInviteList },
{ "348", handleReplyExceptList },
{ "349", handleReplyEndOfExceptList },
{ "353", handleReplyNames }, { "353", handleReplyNames },
{ "366", handleReplyEndOfNames }, { "366", handleReplyEndOfNames },
{ "367", handleReplyBanList }, { "367", handleReplyBanList },