xC/xP: relay and render channel modes
This commit is contained in:
parent
1f0e0b1ce4
commit
d3628928b9
4
xC-proto
4
xC-proto
@ -131,6 +131,8 @@ struct EventMessage {
|
||||
case CHANNEL:
|
||||
string server_name;
|
||||
ItemData topic<>;
|
||||
// This includes parameters, separated by spaces.
|
||||
string modes;
|
||||
case PRIVATE_MESSAGE:
|
||||
string server_name;
|
||||
} context;
|
||||
@ -169,7 +171,7 @@ struct EventMessage {
|
||||
void;
|
||||
case REGISTERED:
|
||||
string user;
|
||||
string user_mode;
|
||||
string user_modes;
|
||||
// Theoretically, we could also send user information in this state,
|
||||
// but we'd have to duplicate both fields.
|
||||
case DISCONNECTING:
|
||||
|
102
xC.c
102
xC.c
@ -1841,7 +1841,7 @@ struct server
|
||||
|
||||
struct user *irc_user; ///< Our own user
|
||||
int nick_counter; ///< Iterates "nicks" when registering
|
||||
struct str irc_user_mode; ///< Our current user modes
|
||||
struct str irc_user_modes; ///< Our current user modes
|
||||
char *irc_user_host; ///< Our current user@host
|
||||
bool autoaway_active; ///< Autoaway is currently active
|
||||
|
||||
@ -1889,7 +1889,7 @@ static struct ispect_field g_server_ispect[] =
|
||||
// TODO: either rename the underlying field or fix the plugins
|
||||
{ "user", offsetof (struct server, irc_user),
|
||||
ISPECT_REF, 0, g_user_ispect, false },
|
||||
{ "user_mode", offsetof (struct server, irc_user_mode),
|
||||
{ "user_mode", offsetof (struct server, irc_user_modes),
|
||||
ISPECT_STR, 0, NULL, false },
|
||||
|
||||
{}
|
||||
@ -1978,7 +1978,7 @@ server_new (struct poller *poller)
|
||||
self->irc_buffer_map = str_map_make (NULL);
|
||||
self->irc_buffer_map.key_xfrm = irc_strxfrm;
|
||||
|
||||
self->irc_user_mode = str_make ();
|
||||
self->irc_user_modes = str_make ();
|
||||
|
||||
self->outstanding_joins = strv_make ();
|
||||
self->cap_ls_buf = strv_make ();
|
||||
@ -2025,7 +2025,7 @@ server_destroy (struct server *self)
|
||||
|
||||
if (self->irc_user)
|
||||
user_unref (self->irc_user);
|
||||
str_free (&self->irc_user_mode);
|
||||
str_free (&self->irc_user_modes);
|
||||
free (self->irc_user_host);
|
||||
|
||||
strv_free (&self->outstanding_joins);
|
||||
@ -2976,6 +2976,45 @@ relay_prepare_buffer_line (struct app_context *ctx, struct buffer *buffer,
|
||||
|
||||
// TODO: Consider pushing this whole block of code much further down.
|
||||
static void formatter_add (struct formatter *self, const char *format, ...);
|
||||
static char *irc_to_utf8 (const char *text);
|
||||
|
||||
static void
|
||||
relay_prepare_channel_buffer_update (struct app_context *ctx,
|
||||
struct buffer *buffer, struct relay_buffer_context_channel *e)
|
||||
{
|
||||
struct channel *channel = buffer->channel;
|
||||
struct formatter f = formatter_make (ctx, buffer->server);
|
||||
if (channel->topic)
|
||||
formatter_add (&f, "#m", channel->topic);
|
||||
e->topic = relay_items (ctx, f.items, &e->topic_len);
|
||||
formatter_free (&f);
|
||||
|
||||
// As in make_prompt(), conceal the last known channel modes.
|
||||
// XXX: This should use irc_channel_is_joined().
|
||||
if (!channel->users_len)
|
||||
return;
|
||||
|
||||
struct str modes = str_make ();
|
||||
str_append_str (&modes, &channel->no_param_modes);
|
||||
|
||||
struct str params = str_make ();
|
||||
struct str_map_iter iter = str_map_iter_make (&channel->param_modes);
|
||||
const char *param;
|
||||
while ((param = str_map_iter_next (&iter)))
|
||||
{
|
||||
str_append_c (&modes, iter.link->key[0]);
|
||||
str_append_c (¶ms, ' ');
|
||||
str_append (¶ms, param);
|
||||
}
|
||||
|
||||
str_append_str (&modes, ¶ms);
|
||||
str_free (¶ms);
|
||||
|
||||
char *modes_utf8 = irc_to_utf8 (modes.str);
|
||||
str_free (&modes);
|
||||
e->modes = str_from_cstr (modes_utf8);
|
||||
free (modes_utf8);
|
||||
}
|
||||
|
||||
static void
|
||||
relay_prepare_buffer_update (struct app_context *ctx, struct buffer *buffer)
|
||||
@ -2997,18 +3036,10 @@ relay_prepare_buffer_update (struct app_context *ctx, struct buffer *buffer)
|
||||
server_name = &e->context.server.server_name;
|
||||
break;
|
||||
case BUFFER_CHANNEL:
|
||||
{
|
||||
e->context.kind = RELAY_BUFFER_KIND_CHANNEL;
|
||||
server_name = &e->context.channel.server_name;
|
||||
|
||||
struct formatter f = formatter_make (ctx, buffer->server);
|
||||
if (buffer->channel->topic)
|
||||
formatter_add (&f, "#m", buffer->channel->topic);
|
||||
e->context.channel.topic =
|
||||
relay_items (ctx, f.items, &e->context.channel.topic_len);
|
||||
formatter_free (&f);
|
||||
relay_prepare_channel_buffer_update (ctx, buffer, &e->context.channel);
|
||||
break;
|
||||
}
|
||||
case BUFFER_PM:
|
||||
e->context.kind = RELAY_BUFFER_KIND_PRIVATE_MESSAGE;
|
||||
server_name = &e->context.private_message.server_name;
|
||||
@ -3086,9 +3117,6 @@ relay_server_state_for_server (struct server *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: Consider pushing this whole block of code further down.
|
||||
static char *irc_to_utf8 (const char *text);
|
||||
|
||||
static void
|
||||
relay_prepare_server_update (struct app_context *ctx, struct server *s)
|
||||
{
|
||||
@ -3103,9 +3131,9 @@ relay_prepare_server_update (struct app_context *ctx, struct server *s)
|
||||
e->data.registered.user = str_from_cstr (user_utf8);
|
||||
free (user_utf8);
|
||||
|
||||
char *user_mode_utf8 = irc_to_utf8 (s->irc_user_mode.str);
|
||||
e->data.registered.user_mode = str_from_cstr (user_mode_utf8);
|
||||
free (user_mode_utf8);
|
||||
char *user_modes_utf8 = irc_to_utf8 (s->irc_user_modes.str);
|
||||
e->data.registered.user_modes = str_from_cstr (user_modes_utf8);
|
||||
free (user_modes_utf8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5311,10 +5339,8 @@ irc_make_channel (struct server *s, char *name)
|
||||
}
|
||||
|
||||
static void
|
||||
irc_channel_set_topic (struct channel *channel, const char *topic)
|
||||
irc_channel_broadcast_buffer_update (const struct channel *channel)
|
||||
{
|
||||
cstr_set (&channel->topic, xstrdup (topic));
|
||||
|
||||
struct server *s = channel->s;
|
||||
struct buffer *buffer = str_map_find (&s->irc_buffer_map, channel->name);
|
||||
if (buffer)
|
||||
@ -5324,6 +5350,13 @@ irc_channel_set_topic (struct channel *channel, const char *topic)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
irc_channel_set_topic (struct channel *channel, const char *topic)
|
||||
{
|
||||
cstr_set (&channel->topic, xstrdup (topic));
|
||||
irc_channel_broadcast_buffer_update (channel);
|
||||
}
|
||||
|
||||
static struct channel_user *
|
||||
irc_channel_get_user (struct channel *channel, struct user *user)
|
||||
{
|
||||
@ -5349,6 +5382,9 @@ irc_left_channel (struct channel *channel)
|
||||
|
||||
LIST_FOR_EACH (struct channel_user, iter, channel->users)
|
||||
irc_channel_unlink_user (channel, iter);
|
||||
|
||||
// Send empty channel modes.
|
||||
irc_channel_broadcast_buffer_update (channel);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@ -5693,7 +5729,7 @@ irc_destroy_state (struct server *s)
|
||||
s->irc_user = NULL;
|
||||
}
|
||||
|
||||
str_reset (&s->irc_user_mode);
|
||||
str_reset (&s->irc_user_modes);
|
||||
cstr_set (&s->irc_user_host, NULL);
|
||||
|
||||
strv_reset (&s->outstanding_joins);
|
||||
@ -6671,7 +6707,7 @@ make_chanmode_postfix (struct channel *channel, struct str *modes)
|
||||
str_append (modes, channel->no_param_modes.str);
|
||||
|
||||
struct str_map_iter iter = str_map_iter_make (&channel->param_modes);
|
||||
char *param;
|
||||
const char *param;
|
||||
while ((param = str_map_iter_next (&iter)))
|
||||
str_append_c (modes, iter.link->key[0]);
|
||||
}
|
||||
@ -6688,8 +6724,8 @@ make_server_postfix_registered (struct buffer *buffer, struct str *output)
|
||||
irc_get_channel_user_prefix (s, channel_user, output);
|
||||
}
|
||||
str_append (output, s->irc_user->nickname);
|
||||
if (s->irc_user_mode.len)
|
||||
str_append_printf (output, "(%s)", s->irc_user_mode.str);
|
||||
if (s->irc_user_modes.len)
|
||||
str_append_printf (output, "(%s)", s->irc_user_modes.str);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6736,7 +6772,7 @@ make_prompt (struct app_context *ctx, struct str *output)
|
||||
buffer_get_index (ctx, buffer), buffer->name);
|
||||
// We remember old modes, don't show them while we're not on the channel
|
||||
if (buffer->type == BUFFER_CHANNEL
|
||||
&& buffer->channel->users_len)
|
||||
&& irc_channel_is_joined (buffer->channel))
|
||||
{
|
||||
struct str modes = str_make ();
|
||||
make_chanmode_postfix (buffer->channel, &modes);
|
||||
@ -7100,7 +7136,11 @@ irc_handle_mode_channel (struct channel *channel, char **params)
|
||||
{
|
||||
struct mode_processor p = { .s = channel->s, .channel = channel };
|
||||
mode_processor_run (&p, params, mode_processor_apply_channel);
|
||||
return p.changes == p.usermode_changes;
|
||||
if (p.changes == p.usermode_changes)
|
||||
return true;
|
||||
|
||||
irc_channel_broadcast_buffer_update (channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@ -7108,7 +7148,7 @@ irc_handle_mode_channel (struct channel *channel, char **params)
|
||||
static bool
|
||||
mode_processor_apply_user (struct mode_processor *self)
|
||||
{
|
||||
mode_processor_toggle (self, &self->s->irc_user_mode);
|
||||
mode_processor_toggle (self, &self->s->irc_user_modes);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8191,7 +8231,7 @@ static void
|
||||
irc_on_registered (struct server *s, const char *nickname)
|
||||
{
|
||||
s->irc_user = irc_get_or_make_user (s, nickname);
|
||||
str_reset (&s->irc_user_mode);
|
||||
str_reset (&s->irc_user_modes);
|
||||
cstr_set (&s->irc_user_host, NULL);
|
||||
|
||||
irc_set_state (s, IRC_REGISTERED);
|
||||
@ -8262,7 +8302,7 @@ irc_handle_rpl_umodeis (struct server *s, const struct irc_message *msg)
|
||||
if (msg->params.len < 2)
|
||||
return;
|
||||
|
||||
str_reset (&s->irc_user_mode);
|
||||
str_reset (&s->irc_user_modes);
|
||||
irc_handle_mode_user (s, msg->params.vector + 1);
|
||||
|
||||
// XXX: do we want to log a message?
|
||||
|
@ -328,6 +328,7 @@ rpcEventHandlers.set(Relay.Event.BufferUpdate, e => {
|
||||
b.kind = e.context.kind
|
||||
b.server = servers.get(e.context.serverName)
|
||||
b.topic = e.context.topic
|
||||
b.modes = e.context.modes
|
||||
})
|
||||
|
||||
rpcEventHandlers.set(Relay.Event.BufferStats, e => {
|
||||
@ -702,6 +703,8 @@ let Status = {
|
||||
return m('.status', {}, 'Synchronizing...')
|
||||
|
||||
let status = `${bufferCurrent}`
|
||||
if (b.modes)
|
||||
status += `(+${b.modes})`
|
||||
if (b.hideUnimportant)
|
||||
status += `<H>`
|
||||
return m('.status', {}, [status, m(Toolbar)])
|
||||
@ -716,8 +719,8 @@ let Prompt = {
|
||||
|
||||
if (b.server.data.user !== undefined) {
|
||||
let user = b.server.data.user
|
||||
if (b.server.data.userMode)
|
||||
user += `(${b.server.data.userMode})`
|
||||
if (b.server.data.userModes)
|
||||
user += `(${b.server.data.userModes})`
|
||||
return m('.prompt', {}, `${user}`)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user