aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/degesch.c b/degesch.c
index 16aa500..cbeaad1 100644
--- a/degesch.c
+++ b/degesch.c
@@ -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