kike: implement LIST

This commit is contained in:
Přemysl Eric Janouch 2014-08-02 23:31:41 +02:00
parent 97f35bedfd
commit 96f4b81182
2 changed files with 56 additions and 3 deletions

View File

@ -634,7 +634,7 @@ str_map_iter_init (struct str_map_iter *self, struct str_map *map)
self->link = NULL;
}
static bool
static void *
str_map_iter_next (struct str_map_iter *self)
{
struct str_map *map = self->map;
@ -643,10 +643,10 @@ str_map_iter_next (struct str_map_iter *self)
while (!self->link)
{
if (self->next_index >= map->len)
return false;
return NULL;
self->link = map->map[self->next_index++];
}
return true;
return self->link->data;
}
static uint64_t

View File

@ -325,6 +325,8 @@ struct channel
char *key; ///< Channel key
long user_limit; ///< User limit or -1
char *topic; ///< Channel topic
struct channel_user *users; ///< Channel users
struct str_vector ban_list; ///< Ban list
@ -347,6 +349,7 @@ channel_free (struct channel *self)
{
free (self->name);
free (self->key);
free (self->topic);
struct channel_user *link, *tmp;
for (link = self->users; link; link = tmp)
@ -627,6 +630,8 @@ enum
IRC_RPL_LUSERME = 255,
IRC_RPL_USERHOST = 302,
IRC_RPL_LIST = 322,
IRC_RPL_LISTEND = 323,
IRC_RPL_VERSION = 351,
IRC_RPL_MOTD = 372,
IRC_RPL_MOTDSTART = 375,
@ -662,6 +667,8 @@ static const char *g_default_replies[] =
[IRC_RPL_LUSERME] = ":I have %d clients and %d servers",
[IRC_RPL_USERHOST] = ":%s",
[IRC_RPL_LIST] = "%s %d :%s",
[IRC_RPL_LISTEND] = ":End of LIST",
[IRC_RPL_VERSION] = "%s.%d %s :%s",
[IRC_RPL_MOTD] = ":- %s",
[IRC_RPL_MOTDSTART] = ":- %s Message of the day - ",
@ -998,6 +1005,51 @@ irc_handle_privmsg (const struct irc_message *msg, struct client *c)
}
}
static void
irc_send_rpl_list (struct client *c, const struct channel *chan)
{
int visible = 0;
for (struct channel_user *user = chan->users;
user; user = user->next)
visible++;
irc_send_reply (c, IRC_RPL_LIST, chan->name, visible, chan->topic);
}
static void
irc_handle_list (const struct irc_message *msg, struct client *c)
{
if (msg->params.len > 1 && !irc_is_this_me (c->ctx, msg->params.vector[1]))
{
irc_send_reply (c, IRC_ERR_NOSUCHSERVER, msg->params.vector[1]);
return;
}
struct channel *chan;
if (msg->params.len == 0)
{
struct str_map_iter iter;
str_map_iter_init (&iter, &c->ctx->channels);
while ((chan = str_map_iter_next (&iter)))
if (!(chan->modes & (IRC_CHAN_MODE_PRIVATE | IRC_CHAN_MODE_SECRET))
|| client_on_channel (c, chan))
irc_send_rpl_list (c, chan);
}
else
{
struct str_vector channels;
str_vector_init (&channels);
split_str_ignore_empty (msg->params.vector[0], ',', &channels);
for (size_t i = 0; i < channels.len; i++)
if ((chan = str_map_find (&c->ctx->channels, channels.vector[i]))
&& (!(chan->modes & IRC_CHAN_MODE_SECRET)
|| client_on_channel (c, chan)))
irc_send_rpl_list (c, chan);
str_vector_free (&channels);
}
irc_send_reply (c, IRC_RPL_LISTEND);
}
// -----------------------------------------------------------------------------
struct irc_command
@ -1028,6 +1080,7 @@ irc_register_handlers (struct server_context *ctx)
{ "VERSION", true, irc_handle_version },
{ "PRIVMSG", true, irc_handle_privmsg },
{ "LIST", true, irc_handle_list },
};
for (size_t i = 0; i < N_ELEMENTS (message_handlers); i++)