diff options
-rw-r--r-- | src/common.c | 6 | ||||
-rw-r--r-- | src/kike.c | 53 |
2 files changed, 56 insertions, 3 deletions
diff --git a/src/common.c b/src/common.c index 2593cdc..5a505b2 100644 --- a/src/common.c +++ b/src/common.c @@ -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 @@ -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++) |