degesch: correctly update user prefixes

This commit is contained in:
Přemysl Eric Janouch 2015-06-05 00:57:39 +02:00
parent c8aff23ab2
commit 7f57bed563
1 changed files with 30 additions and 26 deletions

View File

@ -820,13 +820,14 @@ struct channel_user
LIST_HEADER (struct channel_user)
struct user *user; ///< Reference to user
char *modes; ///< Ordered @+... characters
struct str prefixes; ///< Ordered @+... characters
};
static struct channel_user *
channel_user_new (void)
{
struct channel_user *self = xcalloc (1, sizeof *self);
str_init (&self->prefixes);
return self;
}
@ -834,7 +835,7 @@ static void
channel_user_destroy (struct channel_user *self)
{
user_unref (self->user);
free (self->modes);
str_free (&self->prefixes);
free (self);
}
@ -3878,7 +3879,6 @@ irc_handle_join (struct server *s, const struct irc_message *msg)
struct channel_user *channel_user = channel_user_new ();
channel_user->user = user;
channel_user->modes = xstrdup ("");
LIST_PREPEND (channel->users, channel_user);
// Finally log the message
@ -3938,8 +3938,8 @@ struct mode_processor
char **params; ///< Mode string parameters
struct server *s; ///< Who does the changes
struct channel *channel; ///< The channel we're modifying
struct server *s; ///< Server
struct channel *channel; ///< The channel being modified
// Internals:
@ -3978,24 +3978,27 @@ mode_processor_do_user (struct mode_processor *self)
if (!channel_user)
return;
char prefix = self->s->irc_chanuser_prefixes
[strchr (self->s->irc_chanuser_modes, self->mode_char)
- self->s->irc_chanuser_modes];
const char *all_prefixes = self->s->irc_chanuser_prefixes;
const char *all_modes = self->s->irc_chanuser_modes;
char prefix = all_prefixes[strchr (all_modes, self->mode_char) - all_modes];
// XXX: shouldn't this rather be a "struct str"?
char *modes = channel_user->modes;
char *pos = strchr (modes, self->mode_char);
struct str *prefixes = &channel_user->prefixes;
const char *pos = strchr (prefixes->str, prefix);
if (self->adding == !!pos)
return;
if (self->adding)
{
// FIXME: this doesn't give two fucks about the correct order
channel_user->modes = xstrdup_printf ("%s%c", modes, prefix);
free (modes);
// Add the new mode prefix while retaining the right order
char *old_prefixes = str_steal (prefixes);
str_init (prefixes);
for (const char *p = all_prefixes; *p; p++)
if (*p == prefix || strchr (old_prefixes, *p))
str_append_c (prefixes, *p);
free (old_prefixes);
}
else
memmove (pos, pos + 1, strlen (pos + 1));
str_remove_slice (prefixes, pos - prefixes->str, 1);
}
static void
@ -4689,26 +4692,27 @@ irc_process_names (struct server *s, struct channel *channel)
for (size_t i = 0; i < updates->len; i++)
{
const char *item = updates->vector[i];
const char *nick = item + strspn (item, s->irc_chanuser_prefixes);
char *modes = xstrndup (item, nick - item);
size_t n_prefixes = strspn (item, s->irc_chanuser_prefixes);
const char *nick = item + n_prefixes;
char prefixes[n_prefixes + 1];
memcpy (prefixes, item, n_prefixes);
prefixes[n_prefixes] = '\0';
struct channel_user *channel_user = str_map_find (&map, nick);
if (!channel_user)
{
channel_user = channel_user_new ();
channel_user->user = irc_get_or_make_user (s, nick);
channel_user->modes = modes;
LIST_PREPEND (channel->users, channel_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->modes[0] != modes[0])
{
free (channel_user->modes);
channel_user->modes = modes;
}
else
free (modes);
else 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":
@ -4721,7 +4725,7 @@ irc_process_names (struct server *s, struct channel *channel)
str_vector_init (&v);
LIST_FOR_EACH (struct channel_user, iter, channel->users)
str_vector_add_owned (&v,
xstrdup_printf ("%s%s", iter->modes, iter->user->nickname));
xstrdup_printf ("%s%s", iter->prefixes.str, iter->user->nickname));
char *all_users = join_str_vector (&v, ' ');
str_vector_free (&v);