feature: /ignore command

Like it's already implemented in irc plugin, this commit adds the /ignore command. Now you can filter messages in group chats to not be shown, based on a part of Tox ID. The ignore list of IDs is manageable in this way:
[tox]  /ignore  list
                add <ID part>
                del <ID part>

ommit messages from people with certain Tox IDs

list: show the list of ignores
add: add an ID to the list
del: delete an ID from the list
This commit is contained in:
nogaems 2019-03-27 06:33:29 +03:00
parent fe5589432d
commit 5c8f9bc239
No known key found for this signature in database
GPG Key ID: 91316FB98FDBB08B
9 changed files with 290 additions and 16 deletions

View File

@ -280,6 +280,51 @@ twc_chat_search_buffer(struct t_gui_buffer *buffer)
return NULL;
}
/**
* Set a prefix to a nickname in the nicklist of a chat.
*/
void
twc_chat_update_prefix(struct t_twc_chat *chat, const char *id,
const char *prefix, const char *prefix_color)
{
struct t_gui_nick_group *ptr_group = NULL;
struct t_gui_nick *ptr_nick = NULL;
weechat_nicklist_get_next_item(chat->buffer, &ptr_group, &ptr_nick);
while (ptr_group || ptr_nick)
{
if (ptr_nick)
{
const char *name_field = weechat_nicklist_nick_get_string(
chat->buffer, ptr_nick, "name");
if (!weechat_strncasecmp(id, name_field + sizeof(char), strlen(id)))
{
weechat_nicklist_nick_set(chat->buffer, ptr_nick,
"prefix", prefix);
weechat_nicklist_nick_set(chat->buffer, ptr_nick,
"prefix_color", prefix_color);
weechat_nicklist_nick_set(chat->buffer, ptr_nick, "color",
"default");
return;
}
}
weechat_nicklist_get_next_item(chat->buffer, &ptr_group, &ptr_nick);
}
}
/**
* Update prefix for a certain nickname structure pointer.
*/
void
twc_chat_update_prefix_by_nick(struct t_gui_buffer *buffer,
struct t_gui_nick *nick, const char *prefix,
const char *prefix_color)
{
weechat_nicklist_nick_set(buffer, nick, "prefix", prefix);
weechat_nicklist_nick_set(buffer, nick, "prefix_color", prefix_color);
weechat_nicklist_nick_set(buffer, nick, "color", "default");
}
/**
* Print a chat message to a chat's buffer.
*/

View File

@ -56,6 +56,15 @@ twc_chat_search_group(struct t_twc_profile *profile, int32_t group_number,
struct t_twc_chat *
twc_chat_search_buffer(struct t_gui_buffer *target_buffer);
void
twc_chat_update_prefix(struct t_twc_chat *chat, const char *id,
const char *prefix, const char *prefix_color);
void
twc_chat_update_prefix_by_nick(struct t_gui_buffer *buffer,
struct t_gui_nick *nick, const char *prefix,
const char *prefix_color);
enum t_twc_rc
twc_chat_set_logging(struct t_twc_chat const *const chat, bool logging);

View File

@ -1381,6 +1381,102 @@ twc_input_complete(const void *pointer, void *data, struct t_gui_buffer *buffer,
}
return WEECHAT_RC_OK;
}
/**
* Update a certain nick's prefix in all opened group chats
*/
void
twc_name_prefix_in_groupchats(struct t_twc_profile *profile, const char *id,
const char *prefix, const char *prefix_color)
{
struct t_twc_list_item *item;
struct t_twc_chat *chat;
size_t index;
twc_list_foreach (profile->chats, index, item)
{
chat = (struct t_twc_chat *)(item->chat);
if ((chat->group_number) >= 0)
{
twc_chat_update_prefix(chat, id, prefix, prefix_color);
}
}
}
/**
* Command /ignore callback.
*/
int
twc_cmd_ignore(const void *pointer, void *data, struct t_gui_buffer *buffer,
int argc, char **argv, char **argv_eol)
{
struct t_twc_profile *profile = twc_profile_search_buffer(buffer);
TWC_CHECK_PROFILE(profile);
TWC_CHECK_PROFILE_LOADED(profile);
/* list ignores */
if ((argc == 1) ||
((argc == 2) && (weechat_strcasecmp(argv[1], "list") == 0)))
{
if (!weechat_list_size(profile->ignores))
{
weechat_printf(profile->buffer, "ignore list is empty");
return WEECHAT_RC_OK;
}
weechat_printf(profile->buffer, "ignore list:");
size_t i = 0;
struct t_weelist_item *item;
for (item = weechat_list_get(profile->ignores, 0); item;
item = weechat_list_next(item))
{
weechat_printf(profile->buffer, " [%d] %s", i,
weechat_list_string(item));
i++;
}
return WEECHAT_RC_OK;
}
/* add ignore */
const char *id = argv_eol[2];
struct t_weelist_item *item;
item = weechat_list_casesearch(profile->ignores, id);
if (weechat_strcasecmp(argv[1], "add") == 0)
{
WEECHAT_COMMAND_MIN_ARGS(3, "add");
if (!item)
{
weechat_list_add(profile->ignores, id, WEECHAT_LIST_POS_END, NULL);
weechat_printf(profile->buffer,
"%sID '%s' has been added to the ignore list",
weechat_prefix("action"), id);
twc_name_prefix_in_groupchats(profile, id, "-", "yellow");
}
else
weechat_printf(profile->buffer,
"%sID '%s' is already in the ignore list",
weechat_prefix("error"), id);
return WEECHAT_RC_OK;
}
/* delete ignore */
if (weechat_strcasecmp(argv[1], "del") == 0)
{
WEECHAT_COMMAND_MIN_ARGS(3, "del");
if (item)
{
weechat_list_remove(profile->ignores, item);
weechat_printf(profile->buffer,
"%sID '%s' has been deleted from the ignore list",
weechat_prefix("action"), id);
twc_name_prefix_in_groupchats(profile, id, " ", "default");
}
else
weechat_printf(profile->buffer,
"%sthere's no ID '%s' in the ignore list",
weechat_prefix("error"), id);
return WEECHAT_RC_OK;
}
return WEECHAT_RC_ERROR;
}
/**
* Register Tox-WeeChat commands.
@ -1519,4 +1615,16 @@ twc_commands_init()
"%(filename)"
" || %(tox_friend_name)|%(tox_friend_tox_id) %(filename)",
twc_cmd_send, NULL, NULL);
weechat_hook_command("ignore",
"ommit messages from people with certain Tox IDs",
"list"
" || add <ID part>"
" || del <ID part>",
"list: show the list of ignores\n"
"add: add an ID to the list\n"
"del: delete an ID from the list\n",
"list"
" || add %*"
" || del %*",
twc_cmd_ignore, NULL, NULL);
}

View File

@ -35,6 +35,7 @@ struct t_config_file *twc_config_file = NULL;
struct t_config_section *twc_config_section_look = NULL;
struct t_config_section *twc_config_section_profile = NULL;
struct t_config_section *twc_config_section_profile_default = NULL;
struct t_config_section *twc_config_section_ignore = NULL;
struct t_config_option *twc_config_friend_request_message;
struct t_config_option *twc_config_short_id_size;
@ -207,6 +208,80 @@ twc_config_profile_change_callback(const void *pointer, void *data,
}
}
/*
* Reads ignore option from configuration file.
*
* Returns:
* 1: OK
* 0: error
*/
int
twc_config_ignore_read_callback(const void *pointer, void *data,
struct t_config_file *config_file,
struct t_config_section *section,
const char *option_name, const char *value)
{
/* make C compiler happy */
(void)pointer;
(void)data;
(void)config_file;
(void)section;
if (option_name)
{
char *profile_name = strrchr(option_name, '.');
if (profile_name)
{
profile_name = strndup(option_name,
(profile_name - option_name) / sizeof(char));
struct t_twc_profile *profile =
twc_profile_search_name(profile_name);
if (profile)
{
weechat_list_add(profile->ignores, value, WEECHAT_LIST_POS_END,
NULL);
}
free(profile_name);
}
}
return 1;
}
/*
* Writes ignore section in tox configuration file.
*/
int
twc_config_ignore_write_callback(const void *pointer, void *data,
struct t_config_file *config_file,
const char *section_name)
{
/* make C compiler happy */
(void)pointer;
(void)data;
if (!weechat_config_write_line(config_file, section_name, NULL))
return WEECHAT_CONFIG_WRITE_ERROR;
struct t_twc_list_item *item;
size_t index;
twc_list_foreach (twc_profiles, index, item)
{
size_t option_name_len =
strlen(item->profile->name) + strlen(".ignore") + 1;
char option_name[option_name_len];
snprintf(option_name, option_name_len - 1, "%s.ignore",
item->profile->name);
struct t_weelist_item *ignore_item;
for (ignore_item = weechat_list_get(item->profile->ignores, 0);
ignore_item; ignore_item = weechat_list_next(ignore_item))
{
if (!weechat_config_write_line(config_file, option_name,
weechat_list_string(ignore_item)))
return WEECHAT_CONFIG_WRITE_ERROR;
}
}
return WEECHAT_CONFIG_WRITE_OK;
}
/**
* Create a new option for a profile. Returns NULL if an error occurs.
*/
@ -351,6 +426,12 @@ twc_config_init()
twc_config_file, "profile_default", 0, 0, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
twc_config_section_ignore = weechat_config_new_section(
twc_config_file, "ignore", 0, 0, twc_config_ignore_read_callback, NULL,
NULL, twc_config_ignore_write_callback, NULL, NULL,
twc_config_ignore_write_callback, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL);
for (int i = 0; i < TWC_PROFILE_NUM_OPTIONS; ++i)
{
twc_config_profile_default[i] =

View File

@ -166,6 +166,7 @@ twc_profile_new(const char *name)
profile->tox_online = false;
profile->chats = twc_list_new();
profile->ignores = weechat_list_new();
profile->friend_requests = twc_list_new();
profile->group_chat_invites = twc_list_new();
profile->message_queues = weechat_hashtable_new(
@ -247,10 +248,10 @@ twc_tox_new_print_error(struct t_twc_profile *profile,
weechat_prefix("error"), options->proxy_host);
break;
case TOX_ERR_NEW_PROXY_BAD_PORT:
weechat_printf(profile->buffer,
"%scould not load Tox (invalid proxy port: \"%"
PRIu16 "\")",
weechat_prefix("error"), options->proxy_port);
weechat_printf(
profile->buffer,
"%scould not load Tox (invalid proxy port: \"%" PRIu16 "\")",
weechat_prefix("error"), options->proxy_port);
break;
case TOX_ERR_NEW_PROXY_NOT_FOUND:
weechat_printf(
@ -698,6 +699,8 @@ twc_profile_free(struct t_twc_profile *profile)
/* free things */
twc_chat_free_list(profile->chats);
weechat_list_remove_all(profile->ignores);
weechat_list_free(profile->ignores);
twc_friend_request_free_list(profile->friend_requests);
twc_group_chat_invite_free_list(profile->group_chat_invites);
twc_tfer_free(profile->tfer);

View File

@ -59,6 +59,7 @@ struct t_twc_profile
struct t_hook *tox_do_timer;
struct t_twc_list *chats;
struct t_weelist *ignores;
struct t_twc_list *friend_requests;
struct t_twc_list *group_chat_invites;
struct t_hashtable *message_queues;

View File

@ -408,13 +408,18 @@ twc_handle_group_message(Tox *tox, int32_t group_number, int32_t peer_number,
bool rc;
struct t_twc_profile *profile = data;
char *short_id =
twc_get_peer_id_short(profile->tox, group_number, peer_number);
if (twc_is_id_ignored(profile, short_id))
{
free(short_id);
return;
}
struct t_twc_chat *chat =
twc_chat_search_group(profile, group_number, true);
char *myname = twc_get_self_name_nt(profile->tox);
char *name = twc_get_peer_name_nt(profile->tox, group_number, peer_number);
char *short_id =
twc_get_peer_id_short(profile->tox, group_number, peer_number);
char *full_name = twc_get_peer_name_prefixed(short_id, name);
char *tags = "notify_message";
char *message_nt = twc_null_terminate(message, length);
@ -526,6 +531,12 @@ twc_group_peer_list_changed_callback(Tox *tox, uint32_t group_number,
char *full_name = twc_get_peer_name_prefixed(short_id, name);
weechat_nicklist_add_nick(chat->buffer, chat->nicklist_group,
full_name, NULL, NULL, NULL, 1);
nick = weechat_nicklist_search_nick(
chat->buffer, chat->nicklist_group, full_name);
bool ignored = twc_is_id_ignored(profile, short_id);
twc_chat_update_prefix_by_nick(chat->buffer, nick,
ignored ? "-" : " ",
ignored ? "yellow" : "default");
weechat_printf(
chat->buffer, "%s%s just joined the group chat",
weechat_prefix("join"),
@ -602,12 +613,6 @@ twc_group_peer_name_callback(Tox *tox, uint32_t group_number,
nick = weechat_nicklist_search_nick(chat->buffer, chat->nicklist_group,
prev_full_name);
weechat_nicklist_remove_nick(chat->buffer, nick);
if (!twc_get_peer_name_count(chat->nicks, prev_name))
{
nick = weechat_nicklist_search_nick(chat->buffer, chat->nicklist_group,
prev_name);
weechat_nicklist_remove_nick(chat->buffer, nick);
}
err = TOX_ERR_CONFERENCE_PEER_QUERY_OK;
rc = tox_conference_peer_number_is_ours(tox, group_number, peer_number,
@ -620,9 +625,11 @@ twc_group_peer_name_callback(Tox *tox, uint32_t group_number,
weechat_list_set(n, name);
weechat_nicklist_add_nick(chat->buffer, chat->nicklist_group, full_name,
NULL, NULL, NULL, 1);
weechat_nicklist_add_nick(chat->buffer, chat->nicklist_group, name, NULL,
NULL, NULL, 0);
bool ignored = twc_is_id_ignored(profile, short_id);
nick = weechat_nicklist_search_nick(chat->buffer, chat->nicklist_group, full_name);
twc_chat_update_prefix_by_nick(chat->buffer, nick,
ignored ? "-" : " ",
ignored ? "yellow" : "default");
free(prev_full_name);
free(full_name);
free(name);

View File

@ -276,6 +276,23 @@ twc_get_next_completion(struct t_weelist *completion_list,
return comp;
}
/**
* Checks if an ID is ignored.
*/
bool
twc_is_id_ignored(struct t_twc_profile *profile, const char *short_id)
{
struct t_weelist_item *ignore_item;
for (ignore_item = weechat_list_get(profile->ignores, 0); ignore_item;
ignore_item = weechat_list_next(ignore_item))
{
if (!weechat_strncasecmp(short_id, weechat_list_string(ignore_item),
strlen(weechat_list_string(ignore_item))))
return true;
}
return false;
}
/**
* reverse the bytes of a 32-bit integer.
*/

View File

@ -21,10 +21,11 @@
#define TOX_WEECHAT_UTILS_H
#include <stdlib.h>
#include <tox/tox.h>
#include <weechat/weechat-plugin.h>
#include "twc-profile.h"
void
twc_hex2bin(const char *hex, size_t size, uint8_t *out);
@ -73,6 +74,8 @@ twc_starts_with(struct t_weelist *list, const char *search,
const char *
twc_get_next_completion(struct t_weelist *completion_list,
const char *prev_comp);
bool
twc_is_id_ignored(struct t_twc_profile *profile, const char *short_id);
uint32_t
twc_uint32_reverse_bytes(uint32_t num);