From 883e777bacc85b92f460524098ae27b6a8d4d221 Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Tue, 21 Apr 2015 21:36:16 +0200 Subject: degesch: implement PART and KICK handlers --- degesch.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/degesch.c b/degesch.c index ac44a71..c4e2385 100644 --- a/degesch.c +++ b/degesch.c @@ -1309,6 +1309,25 @@ irc_make_channel (struct app_context *ctx, char *name) return channel; } +static void +irc_unlink_user_from_channel + (struct app_context *ctx, struct user *user, struct channel *channel) +{ + // The order is important here as the channel can hold the last reference + LIST_FOR_EACH (struct user_channel, iter, user->channels) + if (iter->channel == channel) + { + LIST_UNLINK (user->channels, iter); + user_channel_destroy (iter); + } + LIST_FOR_EACH (struct channel_user, iter, channel->users) + if (iter->user == user) + { + LIST_UNLINK (channel->users, iter); + channel_user_destroy (iter); + } +} + // --- Supporting code --------------------------------------------------------- static char * @@ -1896,15 +1915,41 @@ irc_handle_join (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_JOIN, 0, - msg->prefix, NULL, "%s", target); + msg->prefix, NULL, "%s", channel_name); } } static void irc_handle_kick (struct app_context *ctx, const struct irc_message *msg) { - // TODO: remove user from the channel - // TODO: log a message + if (!msg->prefix || msg->params.len < 2) + return; + + const char *channel_name = msg->params.vector[0]; + const char *target = msg->params.vector[1]; + if (!irc_is_channel (ctx, channel_name) + || irc_is_channel (ctx, target)) + return; + + const char *message = NULL; + if (msg->params.len > 2) + message = msg->params.vector[2]; + + struct user *user = str_map_find (&ctx->irc_users, target); + struct channel *channel = str_map_find (&ctx->irc_channels, channel_name); + struct buffer *buffer = str_map_find (&ctx->irc_buffer_map, channel_name); + hard_assert ((channel && buffer) || + (channel && !buffer) || (!channel && !buffer)); + + // It would be is weird for this to be false + if (user && channel) + irc_unlink_user_from_channel (ctx, user, channel); + + if (buffer) + { + buffer_send (ctx, buffer, BUFFER_LINE_KICK, 0, + msg->prefix, message, "%s", target); + } } static void @@ -2000,27 +2045,32 @@ irc_handle_part (struct app_context *ctx, const struct irc_message *msg) if (!msg->prefix || msg->params.len < 1) return; - char *nickname = irc_cut_nickname (msg->prefix); - struct user *user = str_map_find (&ctx->irc_users, nickname); - free (nickname); - if (!user) - return; - - const char *target = msg->params.vector[0]; - if (!irc_is_channel (ctx, target)) + const char *channel_name = msg->params.vector[0]; + if (!irc_is_channel (ctx, channel_name)) return; const char *message = NULL; if (msg->params.len > 1) message = msg->params.vector[1]; - struct channel *channel = str_map_find (&ctx->irc_channels, target); - struct buffer *buffer = str_map_find (&ctx->irc_buffer_map, target); + char *nickname = irc_cut_nickname (msg->prefix); + struct user *user = str_map_find (&ctx->irc_users, nickname); + free (nickname); + + struct channel *channel = str_map_find (&ctx->irc_channels, channel_name); + struct buffer *buffer = str_map_find (&ctx->irc_buffer_map, channel_name); hard_assert ((channel && buffer) || (channel && !buffer) || (!channel && !buffer)); - // TODO: remove user from the channel - // TODO: log a message + // It would be is weird for this to be false + if (user && channel) + irc_unlink_user_from_channel (ctx, user, channel); + + if (buffer) + { + buffer_send (ctx, buffer, BUFFER_LINE_PART, 0, + msg->prefix, message, "%s", channel_name); + } } static void -- cgit v1.2.3-70-g09d2