diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2023-08-27 12:26:10 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2023-08-27 12:26:10 +0200 |
commit | 3ca4f2d3e54d6330c94834d688c67cd47d8b08f5 (patch) | |
tree | d0b4f4eb2e5bb328bb11b69999fbbd5b0cce34f1 /src/plugins/irc | |
parent | 300adb42faa614cf3a465de7441e51fdc0c61c0b (diff) | |
download | weechat-3ca4f2d3e54d6330c94834d688c67cd47d8b08f5.zip |
irc: add count and mode filter in command `/names` (closes #98)
Diffstat (limited to 'src/plugins/irc')
-rw-r--r-- | src/plugins/irc/irc-command.c | 78 | ||||
-rw-r--r-- | src/plugins/irc/irc-completion.c | 43 | ||||
-rw-r--r-- | src/plugins/irc/irc-protocol.c | 82 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 13 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.h | 1 |
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 */ |