From 819f9d16c9fbb014f6bd4ed88b57689347674727 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Sun, 29 Jun 2014 22:07:33 +0100 Subject: [PATCH 1/6] Change NO_ACT so it can be used in addition to other ignores This results in a more flexible system and is less surprising as it means levels can be used in the way they normally can in an ignore. As an example the current approach to NO_ACT provides no way to let HILIGHTS be shown, with this change /set activity_hide_targets can be recreated with: /ignore #channel NO_ACT /ignore #channel -except -regexp -pattern . NO_ACT HILIGHTS (but obviously this can be configured in many more ways if desired). --- docs/help/in/ignore.in | 13 +++++++++++++ src/core/ignore.c | 24 ++++++++++++++++++++++-- src/core/ignore.h | 1 + src/fe-common/core/fe-ignore.c | 17 ++++++++++++++--- src/fe-common/core/fe-messages.c | 20 ++++++++++++-------- 5 files changed, 62 insertions(+), 13 deletions(-) diff --git a/docs/help/in/ignore.in b/docs/help/in/ignore.in index 26c269a4..fbb23fe4 100644 --- a/docs/help/in/ignore.in +++ b/docs/help/in/ignore.in @@ -40,6 +40,19 @@ Some suggestions for ignoring annoying public aways: /IGNORE *afk* NICKS /IGNORE *away* NICKS +The special level "NO_ACT" can be used to ignore activity ("Act:") but not +actually ignore the message entirely. It is somewhat special because it is +allowed in addition to another ignore for the same target. + +Examples: + + /IGNORE #channel NO_ACT JOINS PARTS QUITS - hide joins, etc from activity + /IGNORE nick NO_ACT -MSGS - ignore activity from nick, except for /MSG + /IGNORE -regexp -pattern . -except nick NO_ACT HILIGHT + - combined with the ignore above show hilights from this nick (needs to be + an except as "PUBLIC HILIGHT" still matches public, the regexp is used to + have more than one ignore for "nick"). + For regular expressions, see `man 7 regex`. See also: UNIGNORE, SILENCE, ACCEPT diff --git a/src/core/ignore.c b/src/core/ignore.c index a7aa106f..63b8f279 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -104,8 +104,15 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) stristr(text, rec->pattern) != NULL; } +/* MSGLEVEL_NO_ACT is special in ignores, when provided to ignore_check() it's + * used as a flag to indicate it should only look at ignore items with NO_ACT. + * However we also want to allow NO_ACT combined with levels, so mask it out and + * match levels if set. */ #define ignore_match_level(rec, level) \ - ((level & (rec)->level) != 0) + (((level & MSGLEVEL_NO_ACT) != 0) ? \ + ((~MSGLEVEL_NO_ACT & level) & (rec)->level) != 0 : \ + ((rec)->level & MSGLEVEL_NO_ACT ? 0 : \ + (level & (rec)->level) != 0)) #define ignore_match_nickmask(rec, nick, nickmask) \ ((rec)->mask == NULL || \ @@ -180,7 +187,14 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, } IGNORE_REC *ignore_find(const char *servertag, const char *mask, - char **channels) + char **channels) +{ + return ignore_find_noact(servertag, mask, channels, 0); +} + + +IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, + char **channels, int noact) { GSList *tmp; char **chan; @@ -202,6 +216,12 @@ IGNORE_REC *ignore_find(const char *servertag, const char *mask, continue; } + if (noact && (rec->level & MSGLEVEL_NO_ACT) == 0) + continue; + + if (!noact && (rec->level & MSGLEVEL_NO_ACT) != 0) + continue; + if ((rec->mask == NULL && mask != NULL) || (rec->mask != NULL && mask == NULL)) continue; diff --git a/src/core/ignore.h b/src/core/ignore.h index 4abfaca5..46025d4c 100644 --- a/src/core/ignore.h +++ b/src/core/ignore.h @@ -32,6 +32,7 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, const char *channel, const char *text, int level); IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels); +IGNORE_REC *ignore_find_noact(const char *servertag, const char *mask, char **channels, int noact); void ignore_add_rec(IGNORE_REC *rec); void ignore_update_rec(IGNORE_REC *rec); diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 7c23ad94..3b57f5f3 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -118,7 +118,7 @@ static void cmd_ignore(const char *data) char *patternarg, *chanarg, *mask, *levels, *timestr, *servertag; char **channels; void *free_arg; - int new_ignore, msecs; + int new_ignore, msecs, level; if (*data == '\0') { cmd_ignore_show(); @@ -138,6 +138,7 @@ static void cmd_ignore(const char *data) if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*levels == '\0') levels = "ALL"; + level = level2bits(levels, NULL); msecs = 0; timestr = g_hash_table_lookup(optlist, "time"); @@ -154,7 +155,8 @@ static void cmd_ignore(const char *data) channels = (chanarg == NULL || *chanarg == '\0') ? NULL : g_strsplit(chanarg, ",", -1); - rec = patternarg != NULL ? NULL: ignore_find(servertag, mask, channels); + rec = patternarg != NULL ? NULL: ignore_find_noact(servertag, mask, channels, + (level & MSGLEVEL_NO_ACT)); new_ignore = rec == NULL; if (rec == NULL) { @@ -170,6 +172,12 @@ static void cmd_ignore(const char *data) rec->level = combine_level(rec->level, levels); + if (rec->level == MSGLEVEL_NO_ACT) { + /* If only NO_ACT was specified add all levels; it makes no + * sense on its own. */ + rec->level |= MSGLEVEL_ALL; + } + if (new_ignore && rec->level == 0) { /* tried to unignore levels from nonexisting ignore */ printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, @@ -226,7 +234,10 @@ static void cmd_unignore(const char *data) chans[0] = mask; mask = NULL; } - rec = ignore_find("*", mask, (char **) chans); + rec = ignore_find_noact("*", mask, (char **) chans, 0); + if (rec == NULL) { + rec = ignore_find_noact("*", mask, (char **) chans, 1); + } } if (rec != NULL) { diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index 367863c7..67c95745 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -190,7 +190,7 @@ static void sig_message_public(SERVER_REC *server, const char *msg, if (for_me) level |= MSGLEVEL_HILIGHT; - if (ignore_check(server, nick, address, target, msg, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, target, msg, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; if (settings_get_bool("emphasis")) @@ -238,13 +238,17 @@ static void sig_message_private(SERVER_REC *server, const char *msg, { QUERY_REC *query; char *freemsg = NULL; + int level = MSGLEVEL_MSGS; query = query_find(server, nick); if (settings_get_bool("emphasis")) msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg); - printformat(server, nick, MSGLEVEL_MSGS, + if (ignore_check(server, nick, address, NULL, msg, level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + + printformat(server, nick, level, query == NULL ? TXT_MSG_PRIVATE : TXT_MSG_PRIVATE_QUERY, nick, address, msg); @@ -330,7 +334,7 @@ static void sig_message_join(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_JOINS; - if (ignore_check(server, nick, address, channel, NULL, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, channel, NULL, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -343,7 +347,7 @@ static void sig_message_part(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_PARTS; - if (ignore_check(server, nick, address, channel, NULL, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, channel, NULL, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -362,7 +366,7 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_QUITS)) return; - if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, NULL, reason, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; print_channel = NULL; @@ -432,7 +436,7 @@ static void sig_message_kick(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_KICKS; - if (ignore_check(server, kicker, address, channel, reason, MSGLEVEL_NO_ACT)) + if (ignore_check(server, kicker, address, channel, reason, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -453,7 +457,7 @@ static void print_nick_change_channel(SERVER_REC *server, const char *channel, level = MSGLEVEL_NICKS; if (ownnick) level |= MSGLEVEL_NO_ACT; - if (!(level & MSGLEVEL_NO_ACT) && ignore_check(server, oldnick, address, channel, newnick, MSGLEVEL_NO_ACT)) + if (!(level & MSGLEVEL_NO_ACT) && ignore_check(server, oldnick, address, channel, newnick, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, @@ -532,7 +536,7 @@ static void sig_message_topic(SERVER_REC *server, const char *channel, { int level = MSGLEVEL_TOPICS; - if (ignore_check(server, nick, address, channel, topic, MSGLEVEL_NO_ACT)) + if (ignore_check(server, nick, address, channel, topic, level | MSGLEVEL_NO_ACT)) level |= MSGLEVEL_NO_ACT; printformat(server, channel, level, From d84811b19230901698a89a5ec89f23d97fc2697b Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Sun, 29 Jun 2014 20:13:49 +0100 Subject: [PATCH 2/6] Don't expand ALL when combined with NEVER/NO_ACT --- src/core/levels.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/core/levels.c b/src/core/levels.c index b47079ba..7997ba98 100644 --- a/src/core/levels.c +++ b/src/core/levels.c @@ -136,19 +136,25 @@ char *bits2level(int bits) if (bits == 0) return g_strdup(""); - if (bits == MSGLEVEL_ALL) - return g_strdup("ALL"); str = g_string_new(NULL); - if (bits & MSGLEVEL_NEVER) + if (bits & MSGLEVEL_NEVER) { g_string_append(str, "NEVER "); + bits &= ~MSGLEVEL_NEVER; + } - if (bits & MSGLEVEL_NO_ACT) + if (bits & MSGLEVEL_NO_ACT) { g_string_append(str, "NO_ACT "); + bits &= ~MSGLEVEL_NO_ACT; + } - for (n = 0; levels[n] != NULL; n++) { - if (bits & (1L << n)) - g_string_append_printf(str, "%s ", levels[n]); + if (bits == MSGLEVEL_ALL) { + g_string_append(str, "ALL "); + } else { + for (n = 0; levels[n] != NULL; n++) { + if (bits & (1L << n)) + g_string_append_printf(str, "%s ", levels[n]); + } } if (str->len > 0) g_string_truncate(str, str->len-1); From 6bbb114046f54a85bed6674011411d4d869ef2fb Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Mon, 30 Jun 2014 00:05:46 +0100 Subject: [PATCH 3/6] Remove NO_ACT if we see a user specified hilight In this path we can't look up ignores again because the print text signal doesn't know the nick, etc. Instead just show it. The user can use -actcolor %n or make the hilight more specific if desired. --- src/fe-common/core/hilight-text.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 34c5c643..d4eeb1f3 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -336,6 +336,12 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text, if (!nick_match || (dest->level & MSGLEVEL_HILIGHT)) { /* update the level / hilight info */ hilight_update_text_dest(dest, hilight); + /* Remove NO_ACT, this means explicitly defined hilights will bypass + * /IGNORE ... NO_ACT. + * (It's still possible to use /hilight -actcolor %n to hide + * hilight/beep). + */ + dest->level &= ~MSGLEVEL_NO_ACT; } if (nick_match) From e8b0eb4986ee24b83ef185354a931b120b29ad96 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Mon, 30 Jun 2014 00:10:24 +0100 Subject: [PATCH 4/6] Add NO_ACT checks for actions and notices --- src/fe-common/irc/fe-irc-messages.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/fe-common/irc/fe-irc-messages.c b/src/fe-common/irc/fe-irc-messages.c index fb8d1e94..a8d52745 100644 --- a/src/fe-common/irc/fe-irc-messages.c +++ b/src/fe-common/irc/fe-irc-messages.c @@ -170,6 +170,10 @@ static void sig_message_irc_action(IRC_SERVER_REC *server, const char *msg, if (ignore_check(SERVER(server), nick, address, target, msg, level)) return; + if (ignore_check(SERVER(server), nick, address, target, msg, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + if (ischannel(*target)) item = irc_channel_find(server, target); else @@ -214,6 +218,7 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg, const char *target) { const char *oldtarget; + int level = MSGLEVEL_NOTICES; oldtarget = target; target = skip_target(IRC_SERVER(server), target); @@ -230,18 +235,23 @@ static void sig_message_irc_notice(SERVER_REC *server, const char *msg, if (ignore_check(server, nick, address, ischannel(*target) ? target : NULL, - msg, MSGLEVEL_NOTICES)) + msg, level)) return; + if (ignore_check(server, nick, address, + ischannel(*target) ? target : NULL, + msg, level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + if (ischannel(*target)) { /* notice in some channel */ - printformat(server, target, MSGLEVEL_NOTICES, + printformat(server, target, level, IRCTXT_NOTICE_PUBLIC, nick, oldtarget, msg); } else { /* private notice */ privmsg_get_query(SERVER(server), nick, FALSE, MSGLEVEL_NOTICES); - printformat(server, nick, MSGLEVEL_NOTICES, + printformat(server, nick, level, IRCTXT_NOTICE_PRIVATE, nick, address, msg); } } From 3698ddfc3baa024304342ed360a6136a40c25d36 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Mon, 30 Jun 2014 00:10:45 +0100 Subject: [PATCH 5/6] Add NO_ACT checks for DCC messages --- src/fe-common/irc/dcc/fe-dcc-chat-messages.c | 22 +++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/fe-common/irc/dcc/fe-dcc-chat-messages.c b/src/fe-common/irc/dcc/fe-dcc-chat-messages.c index 23ccc943..93e10943 100644 --- a/src/fe-common/irc/dcc/fe-dcc-chat-messages.c +++ b/src/fe-common/irc/dcc/fe-dcc-chat-messages.c @@ -25,6 +25,7 @@ #include "irc-servers.h" #include "irc-queries.h" #include "dcc-chat.h" +#include "ignore.h" #include "module-formats.h" #include "printtext.h" @@ -86,12 +87,17 @@ static void sig_message_dcc(CHAT_DCC_REC *dcc, const char *msg) TEXT_DEST_REC dest; QUERY_REC *query; char *tag; + int level = MSGLEVEL_DCCMSGS; tag = g_strconcat("=", dcc->id, NULL); query = query_find(NULL, tag); + if (ignore_check(SERVER(dcc->server), tag, dcc->addrstr, NULL, msg, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + format_create_dest_tag(&dest, dcc->server, dcc->servertag, tag, - MSGLEVEL_DCCMSGS, NULL); + level, NULL); printformat_dest(&dest, query != NULL ? IRCTXT_DCC_MSG_QUERY : IRCTXT_DCC_MSG, dcc->id, msg); @@ -103,12 +109,17 @@ static void sig_message_dcc_action(CHAT_DCC_REC *dcc, const char *msg) TEXT_DEST_REC dest; QUERY_REC *query; char *tag; + int level = MSGLEVEL_DCCMSGS | MSGLEVEL_ACTIONS; tag = g_strconcat("=", dcc->id, NULL); query = query_find(NULL, tag); + if (ignore_check(SERVER(dcc->server), tag, dcc->addrstr, NULL, msg, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + format_create_dest_tag(&dest, dcc->server, dcc->servertag, tag, - MSGLEVEL_DCCMSGS | MSGLEVEL_ACTIONS, NULL); + level, NULL); printformat_dest(&dest, query != NULL ? IRCTXT_ACTION_DCC_QUERY : IRCTXT_ACTION_DCC, dcc->id, msg); @@ -120,11 +131,16 @@ static void sig_message_dcc_ctcp(CHAT_DCC_REC *dcc, const char *cmd, { TEXT_DEST_REC dest; char *tag; + int level = MSGLEVEL_DCCMSGS | MSGLEVEL_CTCPS; tag = g_strconcat("=", dcc->id, NULL); + if (ignore_check(SERVER(dcc->server), tag, dcc->addrstr, NULL, cmd, + level | MSGLEVEL_NO_ACT)) + level |= MSGLEVEL_NO_ACT; + format_create_dest_tag(&dest, dcc->server, dcc->servertag, tag, - MSGLEVEL_DCC | MSGLEVEL_CTCPS, NULL); + level, NULL); printformat_dest(&dest, IRCTXT_DCC_CTCP, dcc->id, cmd, data); g_free(tag); From a9d9756d4d4aa61e07f98f3d58f5db85cda08437 Mon Sep 17 00:00:00 2001 From: David Leadbeater Date: Mon, 30 Jun 2014 09:35:31 +0100 Subject: [PATCH 6/6] Make /ignore -replies work with NO_ACT --- src/core/ignore.c | 51 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/src/core/ignore.c b/src/core/ignore.c index 63b8f279..af816237 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -58,30 +58,6 @@ static int ignore_check_replies_rec(IGNORE_REC *rec, CHANNEL_REC *channel, return FALSE; } -#define ignore_match_channel(rec, channel) \ - ((rec)->channels == NULL || ((channel) != NULL && \ - strarray_find((rec)->channels, (channel)) != -1)) - -static int ignore_check_replies(CHANNEL_REC *chanrec, const char *text) -{ - GSList *tmp; - - if (text == NULL || chanrec == NULL) - return FALSE; - - /* check reply ignores */ - for (tmp = ignores; tmp != NULL; tmp = tmp->next) { - IGNORE_REC *rec = tmp->data; - - if (rec->mask != NULL && rec->replies && - ignore_match_channel(rec, chanrec->name) && - ignore_check_replies_rec(rec, chanrec, text)) - return TRUE; - } - - return FALSE; -} - static int ignore_match_pattern(IGNORE_REC *rec, const char *text) { if (rec->pattern == NULL) @@ -124,6 +100,31 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) ((rec)->servertag == NULL || \ g_ascii_strcasecmp((server)->tag, (rec)->servertag) == 0) +#define ignore_match_channel(rec, channel) \ + ((rec)->channels == NULL || ((channel) != NULL && \ + strarray_find((rec)->channels, (channel)) != -1)) + +static int ignore_check_replies(CHANNEL_REC *chanrec, const char *text, int level) +{ + GSList *tmp; + + if (text == NULL || chanrec == NULL) + return FALSE; + + /* check reply ignores */ + for (tmp = ignores; tmp != NULL; tmp = tmp->next) { + IGNORE_REC *rec = tmp->data; + + if (rec->mask != NULL && rec->replies && + ignore_match_level(rec, level) && + ignore_match_channel(rec, chanrec->name) && + ignore_check_replies_rec(rec, chanrec, text)) + return TRUE; + } + + return FALSE; +} + int ignore_check(SERVER_REC *server, const char *nick, const char *host, const char *channel, const char *text, int level) { @@ -183,7 +184,7 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, if (best_match || (level & MSGLEVEL_PUBLIC) == 0) return best_match; - return ignore_check_replies(chanrec, text); + return ignore_check_replies(chanrec, text, level); } IGNORE_REC *ignore_find(const char *servertag, const char *mask,