aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c80
1 files 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