diff options
-rw-r--r-- | degesch.c | 27 |
1 files changed, 16 insertions, 11 deletions
@@ -4686,40 +4686,45 @@ irc_process_names (struct server *s, struct channel *channel) str_map_init (&map); map.key_xfrm = s->irc_strxfrm; - // Initialize list of users - LIST_FOR_EACH (struct channel_user, iter, channel->users) - str_map_set (&map, iter->user->nickname, iter); - - // Update them with contents of RPL_NAMES struct str_vector *updates = &channel->names_buf; for (size_t i = 0; i < updates->len; i++) { const char *item = updates->vector[i]; size_t n_prefixes = strspn (item, s->irc_chanuser_prefixes); - const char *nick = item + n_prefixes; + const char *nickname = item + n_prefixes; + + // Store the nickname in a hashset + str_map_set (&map, nickname, (void *) 1); char prefixes[n_prefixes + 1]; memcpy (prefixes, item, n_prefixes); prefixes[n_prefixes] = '\0'; - struct channel_user *channel_user = str_map_find (&map, nick); + struct user *user = irc_get_or_make_user (s, nickname); + struct channel_user *channel_user = + irc_channel_get_user (channel, user); if (!channel_user) { channel_user = channel_user_new (); - channel_user->user = irc_get_or_make_user (s, nick); + channel_user->user = user; LIST_PREPEND (channel->users, channel_user); } + else + user_unref (user); + // If our idea of the user's modes disagrees with what the server's // sent us (the most powerful modes differ), use the latter one - else if (channel_user->prefixes.str[0] == prefixes[0]) + if (channel_user->prefixes.str[0] == prefixes[0]) continue; str_reset (&channel_user->prefixes); str_append (&channel_user->prefixes, prefixes); } - // TODO: get rid of channel users missing from "updates": - // either mark them or don't initialize the map with them + // Get rid of channel users missing from "updates" + LIST_FOR_EACH (struct channel_user, iter, channel->users) + if (!str_map_find (&map, iter->user->nickname)) + irc_channel_unlink_user (channel, iter); str_map_free (&map); str_vector_reset (&channel->names_buf); |