diff --git a/src/twc-chat.c b/src/twc-chat.c index f2724cc..657a71d 100644 --- a/src/twc-chat.c +++ b/src/twc-chat.c @@ -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. */ diff --git a/src/twc-chat.h b/src/twc-chat.h index 8ed87af..836e8eb 100644 --- a/src/twc-chat.h +++ b/src/twc-chat.h @@ -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); diff --git a/src/twc-commands.c b/src/twc-commands.c index 3336bc7..44ed2c3 100644 --- a/src/twc-commands.c +++ b/src/twc-commands.c @@ -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 " + " || del ", + "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); } diff --git a/src/twc-config.c b/src/twc-config.c index 2854026..f823f0e 100644 --- a/src/twc-config.c +++ b/src/twc-config.c @@ -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] = diff --git a/src/twc-profile.c b/src/twc-profile.c index 7936794..f460033 100644 --- a/src/twc-profile.c +++ b/src/twc-profile.c @@ -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); diff --git a/src/twc-profile.h b/src/twc-profile.h index eca37f5..baeb1d2 100644 --- a/src/twc-profile.h +++ b/src/twc-profile.h @@ -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; diff --git a/src/twc-tox-callbacks.c b/src/twc-tox-callbacks.c index be1b0b4..918fe42 100644 --- a/src/twc-tox-callbacks.c +++ b/src/twc-tox-callbacks.c @@ -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); diff --git a/src/twc-utils.c b/src/twc-utils.c index 74276bb..fa8990c 100644 --- a/src/twc-utils.c +++ b/src/twc-utils.c @@ -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. */ diff --git a/src/twc-utils.h b/src/twc-utils.h index 6b641f7..377683f 100644 --- a/src/twc-utils.h +++ b/src/twc-utils.h @@ -21,10 +21,11 @@ #define TOX_WEECHAT_UTILS_H #include - #include #include +#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);