kike: implement the KICK command
This commit is contained in:
parent
c386592d70
commit
08b93c3a71
64
src/kike.c
64
src/kike.c
|
@ -836,6 +836,7 @@ enum
|
|||
IRC_ERR_NONICKNAMEGIVEN = 431,
|
||||
IRC_ERR_ERRONEOUSNICKNAME = 432,
|
||||
IRC_ERR_NICKNAMEINUSE = 433,
|
||||
IRC_ERR_USERNOTINCHANNEL = 441,
|
||||
IRC_ERR_NOTONCHANNEL = 442,
|
||||
IRC_ERR_SUMMONDISABLED = 445,
|
||||
IRC_ERR_USERSDISABLED = 446,
|
||||
|
@ -903,6 +904,7 @@ static const char *g_default_replies[] =
|
|||
[IRC_ERR_NONICKNAMEGIVEN] = ":No nickname given",
|
||||
[IRC_ERR_ERRONEOUSNICKNAME] = "%s :Erroneous nickname",
|
||||
[IRC_ERR_NICKNAMEINUSE] = "%s :Nickname is already in use",
|
||||
[IRC_ERR_USERNOTINCHANNEL] = "%s %s :They aren't on that channel",
|
||||
[IRC_ERR_NOTONCHANNEL] = "%s :You're not on that channel",
|
||||
[IRC_ERR_SUMMONDISABLED] = ":SUMMON has been disabled",
|
||||
[IRC_ERR_USERSDISABLED] = ":USERS has been disabled",
|
||||
|
@ -1597,7 +1599,7 @@ irc_handle_topic (const struct irc_message *msg, struct client *c)
|
|||
|
||||
if ((chan->modes & IRC_CHAN_MODE_PROTECTED_TOPIC)
|
||||
&& !(user->modes & IRC_CHAN_MODE_OPERATOR))
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_CHANOPRIVSNEEDED);
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_CHANOPRIVSNEEDED, target);
|
||||
|
||||
free (chan->topic);
|
||||
chan->topic = xstrdup (msg->params.vector[1]);
|
||||
|
@ -1665,6 +1667,65 @@ irc_handle_part (const struct irc_message *msg, struct client *c)
|
|||
str_vector_free (&channels);
|
||||
}
|
||||
|
||||
static void
|
||||
irc_try_kick (struct client *c, const char *channel_name, const char *nick,
|
||||
const char *reason)
|
||||
{
|
||||
struct channel *chan;
|
||||
if (!(chan = str_map_find (&c->ctx->channels, channel_name)))
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_NOSUCHCHANNEL, channel_name);
|
||||
|
||||
struct channel_user *user;
|
||||
if (!(user = channel_get_user (chan, c)))
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_NOTONCHANNEL, channel_name);
|
||||
if (!(user->modes & IRC_CHAN_MODE_OPERATOR))
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_CHANOPRIVSNEEDED, channel_name);
|
||||
|
||||
struct client *client;
|
||||
if (!(client = str_map_find (&c->ctx->users, nick))
|
||||
|| !(user = channel_get_user (chan, client)))
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_USERNOTINCHANNEL, nick, channel_name);
|
||||
|
||||
char *message = xstrdup_printf (":%s!%s@%s KICK %s %s :%s",
|
||||
c->nickname, c->username, c->hostname, channel_name, nick, reason);
|
||||
if (!(chan->modes & IRC_CHAN_MODE_QUIET))
|
||||
irc_channel_multicast (chan, message);
|
||||
else
|
||||
irc_send (c, "%s", message);
|
||||
free (message);
|
||||
|
||||
channel_remove_user (chan, user);
|
||||
channel_destroy_if_empty (c->ctx, chan);
|
||||
}
|
||||
|
||||
static void
|
||||
irc_handle_kick (const struct irc_message *msg, struct client *c)
|
||||
{
|
||||
if (msg->params.len < 2)
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_NEEDMOREPARAMS, msg->command);
|
||||
|
||||
const char *reason = c->nickname;
|
||||
if (msg->params.len > 2)
|
||||
reason = msg->params.vector[2];
|
||||
|
||||
struct str_vector channels;
|
||||
struct str_vector users;
|
||||
str_vector_init (&channels);
|
||||
str_vector_init (&users);
|
||||
split_str_ignore_empty (msg->params.vector[0], ',', &channels);
|
||||
split_str_ignore_empty (msg->params.vector[1], ',', &users);
|
||||
|
||||
if (channels.len == 1)
|
||||
for (size_t i = 0; i < users.len; i++)
|
||||
irc_try_kick (c, channels.vector[0], users.vector[i], reason);
|
||||
else
|
||||
for (size_t i = 0; i < channels.len && i < users.len; i++)
|
||||
irc_try_kick (c, channels.vector[i], users.vector[i], reason);
|
||||
|
||||
str_vector_free (&channels);
|
||||
str_vector_free (&users);
|
||||
}
|
||||
|
||||
static void
|
||||
irc_try_join (struct client *c, const char *channel_name, const char *key)
|
||||
{
|
||||
|
@ -1804,6 +1865,7 @@ irc_register_handlers (struct server_context *ctx)
|
|||
{ "NOTICE", true, irc_handle_notice },
|
||||
{ "JOIN", true, irc_handle_join },
|
||||
{ "PART", true, irc_handle_part },
|
||||
{ "KICK", true, irc_handle_kick },
|
||||
{ "TOPIC", true, irc_handle_topic },
|
||||
{ "LIST", true, irc_handle_list },
|
||||
{ "NAMES", true, irc_handle_names },
|
||||
|
|
Loading…
Reference in New Issue