diff options
-rw-r--r-- | degesch.c | 51 |
1 files changed, 47 insertions, 4 deletions
@@ -3415,6 +3415,10 @@ irc_register (struct server *s) const char *realname = get_config_string (s->config, "realname"); hard_assert (nickname && username && realname); + // Start IRCv3.1 capability negotiation; + // at worst the server will ignore this or send a harmless error message + irc_send (s, "CAP LS"); + const char *password = get_config_string (s->config, "password"); if (password) irc_send (s, "PASS :%s", password); @@ -4041,6 +4045,48 @@ irc_handle_mode_user (struct server *s, char **params) // --- Input handling ---------------------------------------------------------- static void +irc_handle_cap (struct server *s, const struct irc_message *msg) +{ + if (msg->params.len < 2) + return; + + struct str_vector v; + str_vector_init (&v); + + if (msg->params.len > 2) + split_str_ignore_empty (msg->params.vector[2], ' ', &v); + + const char *subcommand = msg->params.vector[1]; + if (!strcasecmp_ascii (subcommand, "ACK") + || !strcasecmp_ascii (subcommand, "NAK")) + { + // So far we don't need to take any other actions + irc_send (s, "CAP END"); + } + else if (!strcasecmp_ascii (subcommand, "LS")) + { + struct str_vector chosen; + str_vector_init (&chosen); + + // Filter server capabilities for ones we can make use of + for (size_t i = 0; i < v.len; i++) + { + const char *cap = v.vector[i]; + if (!strcasecmp_ascii (cap, "multi-prefix") + || !strcasecmp_ascii (cap, "invite-notify")) + str_vector_add (&chosen, cap); + } + + char *chosen_str = join_str_vector (&chosen, ' '); + str_vector_free (&chosen); + irc_send (s, "CAP REQ :%s", chosen_str); + free (chosen_str); + } + + str_vector_free (&v); +} + +static void irc_handle_invite (struct server *s, const struct irc_message *msg) { if (!msg->prefix || msg->params.len < 2) @@ -4630,6 +4676,7 @@ static struct irc_handler g_irc_handlers[] = { // This list needs to stay sorted + { "CAP", irc_handle_cap }, { "INVITE", irc_handle_invite }, { "JOIN", irc_handle_join }, { "KICK", irc_handle_kick }, @@ -5128,10 +5175,6 @@ irc_handle_rpl_isupport (struct server *s, const struct irc_message *msg) irc_handle_isupport_statusmsg (s, value_unescaped.str); else if (!strcmp (param, "CHANMODES")) irc_handle_isupport_chanmodes (s, value_unescaped.str); - else if (!strcmp (param, "NAMESX")) - // We support receiving multiple mode chars in RPL_NAMREPLY - // TODO: get rid of this and instead implement CAP negotiation - irc_send (s, "PROTOCTL NAMESX"); // TODO: also parse MODES, TARGMAX and make use of them // to split client commands as necessary |