summaryrefslogtreecommitdiff
path: root/src/plugins/irc
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/irc')
-rw-r--r--src/plugins/irc/irc-command.c78
-rw-r--r--src/plugins/irc/irc-completion.c43
-rw-r--r--src/plugins/irc/irc-protocol.c82
-rw-r--r--src/plugins/irc/irc-server.c13
-rw-r--r--src/plugins/irc/irc-server.h1
5 files changed, 193 insertions, 24 deletions
diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c
index 9e8c37dbe..3b6b91929 100644
--- a/src/plugins/irc/irc-command.c
+++ b/src/plugins/irc/irc-command.c
@@ -3895,6 +3895,10 @@ IRC_COMMAND_CALLBACK(msg)
IRC_COMMAND_CALLBACK(names)
{
+ int i, arg_channels;
+ char filter[2], **channels, *channel_name_lower;
+ int num_channels;
+
IRC_BUFFER_GET_SERVER_CHANNEL(buffer);
IRC_COMMAND_CHECK_SERVER("names", 1, 1);
@@ -3903,26 +3907,64 @@ IRC_COMMAND_CALLBACK(names)
(void) data;
(void) argv;
- if (argc > 1)
+ arg_channels = argc;
+ filter[0] = '\0';
+ filter[1] = '\0';
+
+ for (i = 1; i < argc; i++)
{
- irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
- "NAMES %s", argv_eol[1]);
+ if (argv[i][0] == '-')
+ {
+ if (weechat_strcmp (argv[i], "-count") == 0)
+ filter[0] = '#';
+ else if (argv[i][1])
+ filter[0] = argv[i][1];
+ }
+ else
+ {
+ arg_channels = i;
+ break;
+ }
}
- else
+
+ if ((arg_channels >= argc)
+ && (!ptr_channel || (ptr_channel->type != IRC_CHANNEL_TYPE_CHANNEL)))
{
- if (!ptr_channel || (ptr_channel->type != IRC_CHANNEL_TYPE_CHANNEL))
+ weechat_printf (
+ ptr_server->buffer,
+ _("%s%s: \"%s\" command can only be executed in a channel "
+ "buffer"),
+ weechat_prefix ("error"), IRC_PLUGIN_NAME, "names");
+ return WEECHAT_RC_OK;
+ }
+
+ if (filter[0])
+ {
+ channels = weechat_string_split (
+ (arg_channels < argc) ? argv_eol[arg_channels] : ptr_channel->name,
+ ",", NULL, 0, 0, &num_channels);
+ if (channels)
{
- weechat_printf (
- ptr_server->buffer,
- _("%s%s: \"%s\" command can only be executed in a channel "
- "buffer"),
- weechat_prefix ("error"), IRC_PLUGIN_NAME, "names");
- return WEECHAT_RC_OK;
+ for (i = 0; i < num_channels; i++)
+ {
+ channel_name_lower = weechat_string_tolower (channels[i]);
+ if (channel_name_lower)
+ {
+ weechat_hashtable_set (ptr_server->names_channel_filter,
+ channel_name_lower,
+ filter);
+ free (channel_name_lower);
+ }
+ }
+ weechat_string_free_split (channels);
}
- irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
- "NAMES %s", ptr_channel->name);
}
+ irc_server_sendf (
+ ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_HIGH, NULL,
+ "NAMES %s",
+ (arg_channels < argc) ? argv_eol[arg_channels] : ptr_channel->name);
+
return WEECHAT_RC_OK;
}
@@ -7432,9 +7474,13 @@ irc_command_init ()
weechat_hook_command (
"names",
N_("list nicks on channels"),
- N_("[<channel>[,<channel>...]]"),
- N_("channel: channel name"),
- "%(irc_channels)", &irc_command_names, NULL, NULL);
+ N_("[-count | -x] [<channel>[,<channel>...]]"),
+ N_(" -count: display only number of users\n"
+ " -x: display only users with this mode: -o for ops, "
+ "-h for halfops, -v for voiced, etc. and -* for regular users\n"
+ "channel: channel name"),
+ "-count|%(irc_server_prefix_modes_filter) %(irc_channels)"
+ " || %(irc_channels)", &irc_command_names, NULL, NULL);
weechat_hook_command (
"nick",
N_("change current nick"),
diff --git a/src/plugins/irc/irc-completion.c b/src/plugins/irc/irc-completion.c
index 1df549157..4848d54d2 100644
--- a/src/plugins/irc/irc-completion.c
+++ b/src/plugins/irc/irc-completion.c
@@ -212,6 +212,45 @@ irc_completion_server_nicks_cb (const void *pointer, void *data,
}
/*
+ * Adds prefix modes filters to completion list.
+ */
+
+int
+irc_completion_server_prefix_modes_filter_cb (const void *pointer, void *data,
+ const char *completion_item,
+ struct t_gui_buffer *buffer,
+ struct t_gui_completion *completion)
+{
+ const char *ptr_prefix_modes;
+ char str_filter[16];
+ int i;
+
+ IRC_BUFFER_GET_SERVER_CHANNEL(buffer);
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) completion_item;
+
+ ptr_prefix_modes = irc_server_get_prefix_modes (ptr_server);
+ if (!ptr_prefix_modes)
+ return WEECHAT_RC_OK;
+
+ for (i = 0; ptr_prefix_modes[i]; i++)
+ {
+ snprintf (str_filter, sizeof (str_filter), "-%c", ptr_prefix_modes[i]);
+ weechat_completion_list_add (completion, str_filter,
+ 1, WEECHAT_LIST_POS_END);
+ }
+
+ /* add filter on regular users at the end */
+ weechat_completion_list_add (completion, "-*",
+ 1, WEECHAT_LIST_POS_END);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
* Adds servers to completion list.
*/
@@ -938,6 +977,10 @@ irc_completion_init ()
weechat_hook_completion ("irc_server_nicks",
N_("nicks on all channels of current IRC server"),
&irc_completion_server_nicks_cb, NULL, NULL);
+ weechat_hook_completion ("irc_server_prefix_modes_filter",
+ N_("arguments to filter by prefix mode "
+ "(for example: \"-o\", \"-h\", \"-v\", \"-*\")"),
+ &irc_completion_server_prefix_modes_filter_cb, NULL, NULL);
weechat_hook_completion ("irc_servers",
N_("IRC servers (internal names)"),
&irc_completion_servers_cb, NULL, NULL);
diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c
index 5fff17b35..44b2e95a9 100644
--- a/src/plugins/irc/irc-protocol.c
+++ b/src/plugins/irc/irc-protocol.c
@@ -6478,17 +6478,34 @@ IRC_PROTOCOL_CALLBACK(354)
/*
* Returns a string with the list of nicks on a channel.
*
+ * If filter is NULL, all nicks are displayed.
+ * Otherwise first char of filter is a mode:
+ * o: ops
+ * h: halfops
+ * v: voiced
+ * ...
+ * *: regular
+ *
* Note: result must be freed after use.
*/
char *
irc_protocol_get_string_channel_nicks (struct t_irc_server *server,
- struct t_irc_channel *channel)
+ struct t_irc_channel *channel,
+ const char *filter)
{
struct t_infolist *infolist;
struct t_config_option *ptr_option;
- const char *prefix, *prefix_color, *nickname;
+ const char *prefix, *prefix_color, *nickname, *ptr_prefix_modes;
char **str_nicks, *color;
+ int index_mode, filter_ok;
+
+ /*
+ * filter "#" means display only nicks count, so the list of nicks is not
+ * displayed at all
+ */
+ if (filter && (filter[0] == '#'))
+ return NULL;
str_nicks = weechat_string_dyn_alloc (1024);
if (!str_nicks)
@@ -6501,10 +6518,30 @@ irc_protocol_get_string_channel_nicks (struct t_irc_server *server,
return NULL;
}
+ ptr_prefix_modes = irc_server_get_prefix_modes (server);
+
while (weechat_infolist_next (infolist))
{
if (strcmp (weechat_infolist_string (infolist, "type"), "nick") == 0)
{
+ prefix = weechat_infolist_string (infolist, "prefix");
+ index_mode = (prefix[0] && (prefix[0] != ' ')) ?
+ irc_server_get_prefix_char_index (server, prefix[0]) : -1;
+
+ /* check filter */
+ if (filter && ptr_prefix_modes)
+ {
+ filter_ok = (((filter[0] == '*') && (index_mode < 0))
+ || ((filter[0] != '*') && (index_mode >= 0)
+ && (filter[0] == ptr_prefix_modes[index_mode])));
+ }
+ else
+ {
+ filter_ok = 1;
+ }
+ if (!filter_ok)
+ continue;
+
if (*str_nicks[0])
{
weechat_string_dyn_concat (str_nicks,
@@ -6512,7 +6549,6 @@ irc_protocol_get_string_channel_nicks (struct t_irc_server *server,
-1);
weechat_string_dyn_concat (str_nicks, " ", -1);
}
- prefix = weechat_infolist_string (infolist, "prefix");
if (prefix[0] && (prefix[0] != ' '))
{
prefix_color = weechat_infolist_string (infolist,
@@ -6653,7 +6689,8 @@ irc_protocol_get_string_channel_nicks_count (struct t_irc_server *server,
IRC_PROTOCOL_CALLBACK(366)
{
struct t_irc_channel *ptr_channel;
- char *str_params, *string;
+ const char *ptr_filter;
+ char *str_params, *string, *channel_name_lower, str_filter[256];
IRC_PROTOCOL_MIN_PARAMS(3);
@@ -6661,23 +6698,44 @@ IRC_PROTOCOL_CALLBACK(366)
if (ptr_channel && ptr_channel->nicks)
{
+ /* check if a filter was given to /names command */
+ ptr_filter = NULL;
+ channel_name_lower = weechat_string_tolower (ptr_channel->name);
+ if (channel_name_lower)
+ {
+ ptr_filter = weechat_hashtable_get (server->names_channel_filter,
+ channel_name_lower);
+ }
+
/* display the list of users on channel */
- if (weechat_hashtable_has_key (ptr_channel->join_msg_received, "353")
- || weechat_hashtable_has_key (irc_config_hashtable_display_join_message, "353"))
+ if ((!ptr_filter || (ptr_filter[0] != '#'))
+ && (weechat_hashtable_has_key (ptr_channel->join_msg_received, "353")
+ || weechat_hashtable_has_key (irc_config_hashtable_display_join_message, "353")))
{
- string = irc_protocol_get_string_channel_nicks (server, ptr_channel);
+ string = irc_protocol_get_string_channel_nicks (server, ptr_channel,
+ ptr_filter);
if (string)
{
+ if (ptr_filter)
+ {
+ snprintf (str_filter, sizeof (str_filter),
+ " (%s %s)", _("filter:"), ptr_filter);
+ }
+ else
+ {
+ str_filter[0] = '\0';
+ }
weechat_printf_date_tags (
irc_msgbuffer_get_target_buffer (
server, NULL, command, "names", ptr_channel->buffer),
date,
irc_protocol_tags (server, command, tags, NULL, NULL, NULL),
- _("%sNicks %s%s%s: %s[%s%s]"),
+ _("%sNicks %s%s%s%s: %s[%s%s]"),
weechat_prefix ("network"),
IRC_COLOR_CHAT_CHANNEL,
ptr_channel->name,
IRC_COLOR_RESET,
+ str_filter,
IRC_COLOR_CHAT_DELIMITERS,
string,
IRC_COLOR_CHAT_DELIMITERS);
@@ -6714,6 +6772,14 @@ IRC_PROTOCOL_CALLBACK(366)
}
}
+ if (channel_name_lower)
+ {
+ /* remove filter */
+ weechat_hashtable_remove (server->names_channel_filter,
+ channel_name_lower);
+ free (channel_name_lower);
+ }
+
if (!weechat_hashtable_has_key (ptr_channel->join_msg_received, command))
{
irc_command_mode_server (server, "MODE", ptr_channel, NULL,
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index 2cd37d1ff..2fa848792 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -1782,6 +1782,11 @@ irc_server_alloc (const char *name)
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_TIME,
NULL, NULL);
+ new_server->names_channel_filter = weechat_hashtable_new (
+ 32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
new_server->batches = NULL;
new_server->last_batch = NULL;
new_server->buffer = NULL;
@@ -2269,6 +2274,7 @@ irc_server_free_data (struct t_irc_server *server)
weechat_hashtable_free (server->join_channel_key);
weechat_hashtable_free (server->join_noswitch);
weechat_hashtable_free (server->echo_msg_recv);
+ weechat_hashtable_free (server->names_channel_filter);
/* free server data */
for (i = 0; i < IRC_SERVER_NUM_OPTIONS; i++)
@@ -4218,6 +4224,9 @@ irc_server_close_connection (struct t_irc_server *server)
/* remove all messages stored (with capability echo-message) */
weechat_hashtable_remove_all (server->echo_msg_recv);
+ /* remove all /names filters */
+ weechat_hashtable_remove_all (server->names_channel_filter);
+
/* remove all batched events pending */
irc_batch_free_all (server);
@@ -6478,6 +6487,7 @@ irc_server_hdata_server_cb (const void *pointer, void *data,
WEECHAT_HDATA_VAR(struct t_irc_server, join_channel_key, HASHTABLE, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, join_noswitch, HASHTABLE, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, echo_msg_recv, HASHTABLE, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, names_channel_filter, HASHTABLE, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, batches, POINTER, 0, NULL, "irc_batch");
WEECHAT_HDATA_VAR(struct t_irc_server, last_batch, POINTER, 0, NULL, "irc_batch");
WEECHAT_HDATA_VAR(struct t_irc_server, buffer, POINTER, 0, NULL, "buffer");
@@ -7277,6 +7287,9 @@ irc_server_print_log ()
weechat_log_printf (" echo_msg_recv . . . . . . : 0x%lx (hashtable: '%s')",
ptr_server->echo_msg_recv,
weechat_hashtable_get_string (ptr_server->echo_msg_recv, "keys_values"));
+ weechat_log_printf (" names_channel_filter. . . : 0x%lx (hashtable: '%s')",
+ ptr_server->names_channel_filter,
+ weechat_hashtable_get_string (ptr_server->names_channel_filter, "keys_values"));
weechat_log_printf (" batches . . . . . . . . . : 0x%lx", ptr_server->batches);
weechat_log_printf (" last_batch. . . . . . . . : 0x%lx", ptr_server->last_batch);
weechat_log_printf (" buffer. . . . . . . . . . : 0x%lx", ptr_server->buffer);
diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h
index 054516a8f..cd2637ccf 100644
--- a/src/plugins/irc/irc-server.h
+++ b/src/plugins/irc/irc-server.h
@@ -298,6 +298,7 @@ struct t_irc_server
struct t_hashtable *join_channel_key; /* keys pending for joins */
struct t_hashtable *join_noswitch; /* joins w/o switch to buffer */
struct t_hashtable *echo_msg_recv; /* msg received with echo-message */
+ struct t_hashtable *names_channel_filter; /* filter for /names on channel*/
struct t_irc_batch *batches; /* batched events (cap "batch") */
struct t_irc_batch *last_batch; /* last batch */
struct t_gui_buffer *buffer; /* GUI buffer allocated for server */