kike: implement the multi-prefix capability
This commit is contained in:
parent
20fc6c17d1
commit
bf01fb7aa3
83
kike.c
83
kike.c
|
@ -293,6 +293,11 @@ enum
|
||||||
IRC_USER_MODE_RX_SERVER_NOTICES = (1 << 4)
|
IRC_USER_MODE_RX_SERVER_NOTICES = (1 << 4)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
IRC_CAP_MULTI_PREFIX = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
struct client
|
struct client
|
||||||
{
|
{
|
||||||
LIST_HEADER (struct client)
|
LIST_HEADER (struct client)
|
||||||
|
@ -314,6 +319,7 @@ struct client
|
||||||
bool half_closed; ///< Closing link: conn. is half-closed
|
bool half_closed; ///< Closing link: conn. is half-closed
|
||||||
|
|
||||||
unsigned long cap_version; ///< CAP protocol version
|
unsigned long cap_version; ///< CAP protocol version
|
||||||
|
unsigned caps; ///< Enabled capabilities
|
||||||
|
|
||||||
bool ssl_rx_want_tx; ///< SSL_read() wants to write
|
bool ssl_rx_want_tx; ///< SSL_read() wants to write
|
||||||
bool ssl_tx_want_rx; ///< SSL_write() wants to read
|
bool ssl_tx_want_rx; ///< SSL_write() wants to read
|
||||||
|
@ -1140,20 +1146,53 @@ irc_handle_cap (const struct irc_message *msg, struct client *c)
|
||||||
subcommand, "Ignoring invalid protocol version number");
|
subcommand, "Ignoring invalid protocol version number");
|
||||||
|
|
||||||
c->cap_negotiating = true;
|
c->cap_negotiating = true;
|
||||||
// TODO: actually implement a few capabilities
|
client_send (c, "CAP %s LS :multi-prefix", target);
|
||||||
client_send (c, "CAP %s LS :", target);
|
|
||||||
}
|
}
|
||||||
else if (!irc_strcmp (subcommand, "LIST"))
|
else if (!irc_strcmp (subcommand, "LIST"))
|
||||||
{
|
{
|
||||||
// TODO: list currently enabled capabilities
|
struct str_vector caps;
|
||||||
client_send (c, "CAP %s LIST :", target);
|
str_vector_init (&caps);
|
||||||
|
|
||||||
|
if (c->caps & IRC_CAP_MULTI_PREFIX)
|
||||||
|
str_vector_add (&caps, "multi-prefix");
|
||||||
|
|
||||||
|
char *caps_str = join_str_vector (&caps, ' ');
|
||||||
|
str_vector_free (&caps);
|
||||||
|
client_send (c, "CAP %s LIST :%s", target, caps_str);
|
||||||
|
free (caps_str);
|
||||||
}
|
}
|
||||||
else if (!irc_strcmp (subcommand, "REQ"))
|
else if (!irc_strcmp (subcommand, "REQ"))
|
||||||
{
|
{
|
||||||
c->cap_negotiating = true;
|
c->cap_negotiating = true;
|
||||||
// TODO: process the capability change request, "-" disables
|
|
||||||
if (v.len)
|
unsigned new_caps = c->caps;
|
||||||
|
bool success = true;
|
||||||
|
for (size_t i = 0; i < v.len; i++)
|
||||||
|
{
|
||||||
|
bool neg = false;
|
||||||
|
const char *name = v.vector[i];
|
||||||
|
if (*name == '-')
|
||||||
|
{
|
||||||
|
neg = true;
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
unsigned cap = 0;
|
||||||
|
if (!strcmp (name, "multi-prefix"))
|
||||||
|
cap = IRC_CAP_MULTI_PREFIX;
|
||||||
|
else
|
||||||
|
success = false;
|
||||||
|
|
||||||
|
if (neg)
|
||||||
|
new_caps &= ~cap;
|
||||||
|
else
|
||||||
|
new_caps |= cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
c->caps = new_caps;
|
||||||
client_send (c, "CAP %s NAK :%s", target, params);
|
client_send (c, "CAP %s NAK :%s", target, params);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
client_send (c, "CAP %s ACK :%s", target, params);
|
client_send (c, "CAP %s ACK :%s", target, params);
|
||||||
}
|
}
|
||||||
|
@ -1943,6 +1982,26 @@ irc_handle_list (const struct irc_message *msg, struct client *c)
|
||||||
irc_send_reply (c, IRC_RPL_LISTEND);
|
irc_send_reply (c, IRC_RPL_LISTEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
irc_append_prefixes (struct client *c, struct channel_user *user,
|
||||||
|
struct str *output)
|
||||||
|
{
|
||||||
|
struct str prefixes;
|
||||||
|
str_init (&prefixes);
|
||||||
|
|
||||||
|
if (user->modes & IRC_CHAN_MODE_OPERATOR) str_append_c (&prefixes, '@');
|
||||||
|
if (user->modes & IRC_CHAN_MODE_VOICE) str_append_c (&prefixes, '+');
|
||||||
|
|
||||||
|
if (prefixes.len)
|
||||||
|
{
|
||||||
|
if (c->caps & IRC_CAP_MULTI_PREFIX)
|
||||||
|
str_append (output, prefixes.str);
|
||||||
|
else
|
||||||
|
str_append_c (output, prefixes.str[0]);
|
||||||
|
}
|
||||||
|
str_free (&prefixes);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
irc_send_rpl_namreply (struct client *c, const struct channel *chan)
|
irc_send_rpl_namreply (struct client *c, const struct channel *chan)
|
||||||
{
|
{
|
||||||
|
@ -1963,10 +2022,7 @@ irc_send_rpl_namreply (struct client *c, const struct channel *chan)
|
||||||
|
|
||||||
struct str result;
|
struct str result;
|
||||||
str_init (&result);
|
str_init (&result);
|
||||||
if (iter->modes & IRC_CHAN_MODE_OPERATOR)
|
irc_append_prefixes (c, iter, &result);
|
||||||
str_append_c (&result, '@');
|
|
||||||
else if (iter->modes & IRC_CHAN_MODE_VOICE)
|
|
||||||
str_append_c (&result, '+');
|
|
||||||
str_append (&result, iter->c->nickname);
|
str_append (&result, iter->c->nickname);
|
||||||
str_vector_add_owned (&nicks, str_steal (&result));
|
str_vector_add_owned (&nicks, str_steal (&result));
|
||||||
}
|
}
|
||||||
|
@ -2029,12 +2085,7 @@ irc_send_rpl_whoreply (struct client *c, const struct channel *chan,
|
||||||
|
|
||||||
struct channel_user *user;
|
struct channel_user *user;
|
||||||
if (chan && (user = channel_get_user (chan, target)))
|
if (chan && (user = channel_get_user (chan, target)))
|
||||||
{
|
irc_append_prefixes (c, user, &chars);
|
||||||
if (user->modes & IRC_CHAN_MODE_OPERATOR)
|
|
||||||
str_append_c (&chars, '@');
|
|
||||||
else if (user->modes & IRC_CHAN_MODE_VOICE)
|
|
||||||
str_append_c (&chars, '+');
|
|
||||||
}
|
|
||||||
|
|
||||||
irc_send_reply (c, IRC_RPL_WHOREPLY, chan ? chan->name : "*",
|
irc_send_reply (c, IRC_RPL_WHOREPLY, chan ? chan->name : "*",
|
||||||
target->username, target->hostname, target->ctx->server_name,
|
target->username, target->hostname, target->ctx->server_name,
|
||||||
|
|
Loading…
Reference in New Issue