summaryrefslogtreecommitdiff
path: root/degesch.c
diff options
context:
space:
mode:
Diffstat (limited to 'degesch.c')
-rw-r--r--degesch.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/degesch.c b/degesch.c
index dc36ef9..1cdc12c 100644
--- a/degesch.c
+++ b/degesch.c
@@ -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);