summary refs log tree commit diff
diff options
context:
space:
mode:
authorC. McEnroe2021-05-04 15:34:27 -0400
committerC. McEnroe2021-05-04 15:34:27 -0400
commit6207aaf1a87f3f1ecfb46ad6b0288db94fc6329e (patch)
treee1f77ed10140038af243266dd7ff316a87eed7a7
parentff87d561bd545c715dbe6beb813724a28535e7f4 (diff)
Ignore messages in reply to previously ignored messages
Using the +draft/reply client tag, which is supported by BitBot.
This hides the bot's replies to ignored users or ignored bot command
messages.

This commit is dedicated to the land of Estonia.
-rw-r--r--catgirl.114
-rw-r--r--chat.h3
-rw-r--r--filter.c29
3 files changed, 45 insertions, 1 deletions
diff --git a/catgirl.1 b/catgirl.1
index c5ac74e..9954def 100644
--- a/catgirl.1
+++ b/catgirl.1
@@ -935,6 +935,20 @@ catgirl freenode
 .Re
 .It
 .Rs
+.%A James Wheare
+.%T Reply Client Tag
+.%I IRCv3 Working Group
+.%U https://ircv3.net/specs/client-tags/reply
+.Re
+.It
+.Rs
+.%A James Wheare
+.%T Message IDs
+.%I IRCv3 Working Group
+.%U https://ircv3.net/specs/extensions/message-ids
+.Re
+.It
+.Rs
 .%A K. Zeilenga, Ed.
 .%T The PLAIN Simple Authentication and Security Layer (SASL) Mechanism
 .%I IETF
diff --git a/chat.h b/chat.h
index eb826a8..fadbc30 100644
--- a/chat.h
+++ b/chat.h
@@ -171,6 +171,7 @@ extern struct Network {
 	X("chghost", CapChghost) \
 	X("extended-join", CapExtendedJoin) \
 	X("invite-notify", CapInviteNotify) \
+	X("message-tags", CapMessageTags) \
 	X("multi-prefix", CapMultiPrefix) \
 	X("sasl", CapSASL) \
 	X("server-time", CapServerTime) \
@@ -205,7 +206,9 @@ static inline void set(char **field, const char *value) {
 }
 
 #define ENUM_TAG \
+	X("+draft/reply", TagReply) \
 	X("causal.agency/pos", TagPos) \
+	X("msgid", TagMsgID) \
 	X("time", TagTime)
 
 enum Tag {
diff --git a/filter.c b/filter.c
index a648d8b..63c3369 100644
--- a/filter.c
+++ b/filter.c
@@ -94,12 +94,39 @@ static bool filterTest(
 	return !fnmatch(filter.mesg, msg->params[1], FNM_CASEFOLD);
 }
 
+enum { IcedCap = 8 };
+static struct {
+	size_t len;
+	char *msgIDs[IcedCap];
+} iced;
+
+static void icedPush(const char *msgID) {
+	if (!msgID) return;
+	size_t i = iced.len % IcedCap;
+	free(iced.msgIDs[i]);
+	iced.msgIDs[i] = strdup(msgID);
+	if (!iced.msgIDs[i]) err(EX_OSERR, "strdup");
+	iced.len++;
+}
+
 enum Heat filterCheck(enum Heat heat, uint id, const struct Message *msg) {
 	if (!len) return heat;
+
+	if (msg->tags[TagReply]) {
+		for (size_t i = 0; i < IcedCap; ++i) {
+			if (!iced.msgIDs[i]) continue;
+			if (strcmp(msg->tags[TagReply], iced.msgIDs[i])) continue;
+			icedPush(msg->tags[TagMsgID]);
+			return Ice;
+		}
+	}
+
 	char mask[512];
 	snprintf(mask, sizeof(mask), "%s!%s@%s", msg->nick, msg->user, msg->host);
 	for (size_t i = 0; i < len; ++i) {
-		if (filterTest(filters[i], mask, id, msg)) return filters[i].heat;
+		if (!filterTest(filters[i], mask, id, msg)) continue;
+		if (filters[i].heat == Ice) icedPush(msg->tags[TagMsgID]);
+		return filters[i].heat;
 	}
 	return heat;
 }