diff --git a/degesch.c b/degesch.c index eca8a89..20e1ff7 100644 --- a/degesch.c +++ b/degesch.c @@ -1206,8 +1206,33 @@ init_buffers (struct app_context *ctx) LIST_APPEND_WITH_TAIL (ctx->buffers, ctx->buffers_tail, server); } +// --- Users, channels --------------------------------------------------------- + // --- Supporting code --------------------------------------------------------- +static char * +irc_cut_nickname (const char *prefix) +{ + return xstrndup (prefix, strcspn (prefix, "!@")); +} + +static bool +irc_is_this_us (struct app_context *ctx, const char *prefix) +{ + char *nick = irc_cut_nickname (prefix); + bool result = !irc_strcmp (nick, ctx->irc_nickname); + free (nick); + return result; +} + +static bool +irc_is_channel (struct app_context *ctx, const char *ident) +{ + (void) ctx; // TODO: parse prefixes from server features + + return *ident && !!strchr ("#&+!", *ident); +} + static void irc_shutdown (struct app_context *ctx) { @@ -1712,8 +1737,69 @@ irc_to_utf8 (struct app_context *ctx, const char *text) static void irc_handle_join (struct app_context *ctx, const struct irc_message *msg) { - // TODO: if the user is us, create a new buffer and activate it. - // TODO: log a message + if (!msg->prefix || msg->params.len < 1) + return; + + const char *target = msg->params.vector[0]; + if (!irc_is_channel (ctx, target)) + return; + + struct channel *channel = str_map_find (&ctx->irc_channels, target); + struct buffer *buffer = str_map_find (&ctx->irc_buffer_map, target); + hard_assert ((channel && buffer) || + (channel && !buffer) || (!channel && !buffer)); + + // We've joined a new channel + if (!channel && irc_is_this_us (ctx, msg->prefix)) + { + channel = channel_new (); + channel->name = xstrdup (target); + channel->mode = xstrdup (""); + channel->topic = NULL; + str_map_set (&ctx->irc_channels, channel->name, channel); + + buffer = buffer_new (); + buffer->type = BUFFER_CHANNEL; + buffer->name = xstrdup (target); + buffer->channel = channel_ref (channel); + LIST_APPEND_WITH_TAIL (ctx->buffers, ctx->buffers_tail, buffer); + str_map_set (&ctx->irc_buffer_map, channel->name, buffer); + + buffer_activate (ctx, buffer); + } + + // This is weird, ignoring + if (!channel) + return; + + // Get or make a user object + char *nickname = irc_cut_nickname (msg->prefix); + struct user *user = str_map_find (&ctx->irc_users, nickname); + if (!user) + { + user = user_new (); + user->nickname = nickname; + str_map_set (&ctx->irc_users, user->nickname, user); + } + else + free (nickname); + + // Link the user with the channel + struct user_channel *user_channel = user_channel_new (); + user_channel->channel = channel_ref (channel); + LIST_PREPEND (user->channels, user_channel); + + struct channel_user *channel_user = channel_user_new (); + channel_user->user = user_ref (user); + channel_user->modes = xstrdup (""); + LIST_PREPEND (channel->users, channel_user); + + // Finally log the message + if (buffer) + { + buffer_send (ctx, buffer, BUFFER_LINE_JOIN, 0, + msg->prefix, NULL, "%s", target); + } } static void