kike: fix RPL_WHOISCHANNELS and RPL_NAMREPLY
Now we automatically split the lists and send multiple replies, but only if it's needed.
This commit is contained in:
parent
3552b9e1fb
commit
7bcf2a066b
81
kike.c
81
kike.c
@ -944,23 +944,66 @@ client_set_ping_timer (struct client *c)
|
||||
|
||||
// --- IRC command handling ----------------------------------------------------
|
||||
|
||||
static void
|
||||
irc_make_reply (struct client *c, int id, va_list ap, struct str *output)
|
||||
{
|
||||
str_append_printf (output, ":%s %03d %s ",
|
||||
c->ctx->server_name, id, c->nickname ? c->nickname : "");
|
||||
str_append_vprintf (output,
|
||||
irc_get_text (c->ctx, id, g_default_replies[id]), ap);
|
||||
}
|
||||
|
||||
// XXX: this way we cannot typecheck the arguments, so we must be careful
|
||||
static void
|
||||
irc_send_reply (struct client *c, int id, ...)
|
||||
{
|
||||
struct str tmp;
|
||||
str_init (&tmp);
|
||||
struct str reply;
|
||||
str_init (&reply);
|
||||
|
||||
va_list ap;
|
||||
va_start (ap, id);
|
||||
str_append_printf (&tmp, ":%s %03d %s ",
|
||||
c->ctx->server_name, id, c->nickname ? c->nickname : "");
|
||||
str_append_vprintf (&tmp,
|
||||
irc_get_text (c->ctx, id, g_default_replies[id]), ap);
|
||||
irc_make_reply (c, id, ap, &reply);
|
||||
va_end (ap);
|
||||
|
||||
client_send_str (c, &tmp);
|
||||
str_free (&tmp);
|
||||
client_send_str (c, &reply);
|
||||
str_free (&reply);
|
||||
}
|
||||
|
||||
/// Send a space-separated list of words across as many replies as needed
|
||||
static void
|
||||
irc_send_reply_vector (struct client *c, int id, char **items, ...)
|
||||
{
|
||||
struct str common;
|
||||
str_init (&common);
|
||||
|
||||
va_list ap;
|
||||
va_start (ap, items);
|
||||
irc_make_reply (c, id, ap, &common);
|
||||
va_end (ap);
|
||||
|
||||
// We always send at least one message (there might be a client that
|
||||
// expects us to send this message at least once)
|
||||
do
|
||||
{
|
||||
struct str reply;
|
||||
str_init (&reply);
|
||||
str_append_str (&reply, &common);
|
||||
|
||||
// If not even a single item fits in the limit (which may happen,
|
||||
// in theory) it just gets cropped. We could also skip it.
|
||||
if (*items)
|
||||
str_append (&reply, *items++);
|
||||
|
||||
// Append as many items as fits in a single message
|
||||
while (*items
|
||||
&& reply.len + 1 + strlen (*items) <= IRC_MAX_MESSAGE_LENGTH)
|
||||
str_append_printf (&reply, " %s", *items++);
|
||||
|
||||
client_send_str (c, &reply);
|
||||
str_free (&reply);
|
||||
}
|
||||
while (*items);
|
||||
str_free (&common);
|
||||
}
|
||||
|
||||
#define RETURN_WITH_REPLY(c, ...) \
|
||||
@ -1858,13 +1901,8 @@ irc_send_rpl_namreply (struct client *c, const struct channel *chan)
|
||||
str_vector_add_owned (&nicks, str_steal (&result));
|
||||
}
|
||||
|
||||
if (nicks.len)
|
||||
{
|
||||
// FIXME: split it into multiple messages if it's too long
|
||||
char *reply = join_str_vector (&nicks, ' ');
|
||||
irc_send_reply (c, IRC_RPL_NAMREPLY, type, chan->name, reply);
|
||||
free (reply);
|
||||
}
|
||||
irc_send_reply_vector (c, IRC_RPL_NAMREPLY,
|
||||
nicks.vector, type, chan->name, "");
|
||||
str_vector_free (&nicks);
|
||||
}
|
||||
|
||||
@ -2024,6 +2062,9 @@ irc_send_whois_reply (struct client *c, const struct client *target)
|
||||
if (target->away_message)
|
||||
irc_send_reply (c, IRC_RPL_AWAY, nick, target->away_message);
|
||||
|
||||
struct str_vector channels;
|
||||
str_vector_init (&channels);
|
||||
|
||||
struct str_map_iter iter;
|
||||
str_map_iter_init (&iter, &c->ctx->channels);
|
||||
struct channel *chan;
|
||||
@ -2040,14 +2081,12 @@ irc_send_whois_reply (struct client *c, const struct client *target)
|
||||
else if (channel_user->modes & IRC_CHAN_MODE_VOICE)
|
||||
str_append_c (&item, '+');
|
||||
str_append (&item, chan->name);
|
||||
str_append_c (&item, ' ');
|
||||
|
||||
// TODO: try to merge the results into as few messages as possible
|
||||
irc_send_reply (c, IRC_RPL_WHOISCHANNELS, nick, item.str);
|
||||
|
||||
str_free (&item);
|
||||
str_vector_add_owned (&channels, str_steal (&item));
|
||||
}
|
||||
|
||||
irc_send_reply_vector (c, IRC_RPL_WHOISCHANNELS, channels.vector, nick, "");
|
||||
str_vector_free (&channels);
|
||||
|
||||
irc_send_reply (c, IRC_RPL_ENDOFWHOIS, nick);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user