about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--bounce.h3
-rw-r--r--client.c54
-rw-r--r--pounce.11
-rw-r--r--server.c2
4 files changed, 53 insertions, 7 deletions
diff --git a/bounce.h b/bounce.h
index da52592..7f7c247 100644
--- a/bounce.h
+++ b/bounce.h
@@ -71,6 +71,7 @@ static inline struct Message parse(char *line) {
 	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) \
@@ -81,7 +82,7 @@ enum Cap {
 #define X(name, id) BIT(id),
 	ENUM_CAP
 #undef X
-	TagCaps = CapServerTime,
+	TagCaps = CapMessageTags | CapServerTime,
 };
 
 static const char *CapNames[] = {
diff --git a/client.c b/client.c
index 8a4e86f..b81732d 100644
--- a/client.c
+++ b/client.c
@@ -227,17 +227,45 @@ static void handleQuit(struct Client *client, struct Message *msg) {
 
 static void handlePrivmsg(struct Client *client, struct Message *msg) {
 	if (!msg->params[0] || !msg->params[1]) return;
-	char line[1024];
+	char line[MessageCap];
+	if (msg->tags) {
+		snprintf(
+			line, sizeof(line), "@%s :%s %s %s :%s",
+			msg->tags, stateEcho(), msg->cmd, msg->params[0], msg->params[1]
+		);
+	} else {
+		snprintf(
+			line, sizeof(line), ":%s %s %s :%s",
+			stateEcho(), msg->cmd, msg->params[0], msg->params[1]
+		);
+	}
+	size_t diff = ringDiff(client->consumer);
+	ringProduce(line);
+	if (!diff) ringConsume(NULL, client->consumer);
+	if (!strcmp(msg->params[0], stateNick())) return;
+
+	if (msg->tags) {
+		serverFormat(
+			"@%s %s %s :%s\r\n",
+			msg->tags, msg->cmd, msg->params[0], msg->params[1]
+		);
+	} else {
+		serverFormat("%s %s :%s\r\n", msg->cmd, msg->params[0], msg->params[1]);
+	}
+}
+
+static void handleTagmsg(struct Client *client, struct Message *msg) {
+	if (!msg->tags || !msg->params[0]) return;
+	char line[MessageCap];
 	snprintf(
-		line, sizeof(line), ":%s %s %s :%s",
-		stateEcho(), msg->cmd, msg->params[0], msg->params[1]
+		line, sizeof(line), "@%s :%s TAGMSG %s",
+		msg->tags, stateEcho(), msg->params[0]
 	);
 	size_t diff = ringDiff(client->consumer);
 	ringProduce(line);
 	if (!diff) ringConsume(NULL, client->consumer);
 	if (!strcmp(msg->params[0], stateNick())) return;
-
-	serverFormat("%s %s :%s\r\n", msg->cmd, msg->params[0], msg->params[1]);
+	serverFormat("@%s TAGMSG %s\r\n", msg->tags, msg->params[0]);
 }
 
 static const struct {
@@ -252,6 +280,7 @@ static const struct {
 	{ "PASS", handlePass, false },
 	{ "PRIVMSG", handlePrivmsg, true },
 	{ "QUIT", handleQuit, true },
+	{ "TAGMSG", handleTagmsg, true },
 	{ "USER", handleUser, false },
 };
 
@@ -268,10 +297,20 @@ static void clientParse(struct Client *client, char *line) {
 }
 
 static bool intercept(const char *line, size_t len) {
+	if (line[0] == '@') {
+		const char *sp = memchr(line, ' ', len);
+		len -= sp - line;
+		line = sp;
+		if (len) {
+			len--;
+			line++;
+		}
+	}
 	if (len >= 4 && !memcmp(line, "CAP ", 4)) return true;
 	if (len == 4 && !memcmp(line, "QUIT", 4)) return true;
 	if (len >= 5 && !memcmp(line, "QUIT ", 5)) return true;
 	if (len >= 7 && !memcmp(line, "NOTICE ", 7)) return true;
+	if (len >= 7 && !memcmp(line, "TAGMSG ", 7)) return true;
 	if (len >= 8 && !memcmp(line, "PRIVMSG ", 8)) return true;
 	return false;
 }
@@ -396,6 +435,10 @@ static const char *filterInviteNotify(const char *line) {
 	return (wordcmp(line, 2, stateNick()) ? NULL : line);
 }
 
+static const char *filterMessageTags(const char *line) {
+	return (wordcmp(line, 1, "TAGMSG") ? line : NULL);
+}
+
 static const char *filterMultiPrefix(const char *line) {
 	static char buf[MessageCap + 1];
 	if (!wordcmp(line, 1, "352")) {
@@ -437,6 +480,7 @@ static Filter *Filters[] = {
 	[CapChghostBit] = filterChghost,
 	[CapExtendedJoinBit] = filterExtendedJoin,
 	[CapInviteNotifyBit] = filterInviteNotify,
+	[CapMessageTagsBit] = filterMessageTags,
 	[CapMultiPrefixBit] = filterMultiPrefix,
 	[CapUserhostInNamesBit] = filterUserhostInNames,
 };
diff --git a/pounce.1 b/pounce.1
index 7ed431f..a205857 100644
--- a/pounce.1
+++ b/pounce.1
@@ -342,6 +342,7 @@ is supported:
 .Sy chghost ,
 .Sy extended-join ,
 .Sy invite-notify ,
+.Sy message-tags ,
 .Sy multi-prefix ,
 .Sy server-time ,
 .Sy userhost-in-names .
diff --git a/server.c b/server.c
index e8c8880..abc7d40 100644
--- a/server.c
+++ b/server.c
@@ -139,7 +139,7 @@ void serverSend(const char *ptr, size_t len) {
 }
 
 void serverFormat(const char *format, ...) {
-	char buf[1024];
+	char buf[MessageCap];
 	va_list ap;
 	va_start(ap, format);
 	int len = vsnprintf(buf, sizeof(buf), format, ap);