summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2021-05-04 15:34:27 -0400
committerJune McEnroe <june@causal.agency>2021-05-04 15:34:27 -0400
commit6207aaf1a87f3f1ecfb46ad6b0288db94fc6329e (patch)
treee1f77ed10140038af243266dd7ff316a87eed7a7
parentAdd support for BINDIR, fix default MANDIR, use LDADD vars (diff)
downloadcatgirl-6207aaf1a87f3f1ecfb46ad6b0288db94fc6329e.tar.gz
catgirl-6207aaf1a87f3f1ecfb46ad6b0288db94fc6329e.zip
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.
Diffstat (limited to '')
-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;
 }
server if client has no needsJune McEnroe 2019-10-23Implement some amount of client connectionJune McEnroe 2019-10-23Set clients non-blockingJune McEnroe 2019-10-23Clean up state.c and factor out parsingJune McEnroe 2019-10-23Respond to pingsJune McEnroe 2019-10-23Add verbose flagJune McEnroe 2019-10-23Set NOSIGPIPE on server connectionJune McEnroe 2019-10-23Set an initial loop capJune McEnroe 2019-10-23Fix rest parsingJune McEnroe 2019-10-23Add dynamic poll listJune McEnroe 2019-10-23Don't assume commands have targets and handle ERRORJune McEnroe 2019-10-23Clean up state somewhatJune McEnroe 2019-10-23Actually send the buffer...June McEnroe 2019-10-23Add stateJune McEnroe