about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-02-29 01:03:46 -0500
committerJune McEnroe <june@causal.agency>2020-02-29 01:03:46 -0500
commit8570a62235e5e9b6a6d719fd8b92cedc91a1d511 (patch)
tree209a365efebcec4457f4563a4308e6c5c8cdfdf4
parentAdd raw modes to mode message (diff)
downloadcatgirl-8570a62235e5e9b6a6d719fd8b92cedc91a1d511.tar.gz
catgirl-8570a62235e5e9b6a6d719fd8b92cedc91a1d511.zip
Implement the causal.agency/consumer capability
-rw-r--r--catgirl.114
-rw-r--r--chat.h3
-rw-r--r--handle.c11
-rw-r--r--ui.c10
4 files changed, 32 insertions, 6 deletions
diff --git a/catgirl.1 b/catgirl.1
index b1b72de..a69d282 100644
--- a/catgirl.1
+++ b/catgirl.1
@@ -1,4 +1,4 @@
-.Dd February 23, 2020
+.Dd February 29, 2020
 .Dt CATGIRL 1
 .Os
 .
@@ -658,6 +658,18 @@ join = #ascii.town
 .Re
 .El
 .
+.Ss Extensions
+The
+.Nm
+client can take advantage of the
+.Sy causal.agency/consumer
+vendor-specific IRCv3 capability
+implemented by
+.Xr pounce 1 .
+The consumer position is stored in the
+.Cm save
+file.
+.
 .Sh AUTHORS
 .An June Bug Aq Mt june@causal.agency
 .
diff --git a/chat.h b/chat.h
index 5b4e14c..91d175f 100644
--- a/chat.h
+++ b/chat.h
@@ -96,6 +96,7 @@ extern struct Network {
 } network;
 
 #define ENUM_CAP \
+	X("causal.agency/consumer", CapConsumer) \
 	X("extended-join", CapExtendedJoin) \
 	X("invite-notify", CapInviteNotify) \
 	X("multi-prefix", CapMultiPrefix) \
@@ -112,6 +113,7 @@ enum Cap {
 extern struct Self {
 	bool debug;
 	bool restricted;
+	size_t pos;
 	enum Cap caps;
 	char *plain;
 	char *join;
@@ -128,6 +130,7 @@ static inline void set(char **field, const char *value) {
 }
 
 #define ENUM_TAG \
+	X("causal.agency/pos", TagPos) \
 	X("time", TagTime)
 
 enum Tag {
diff --git a/handle.c b/handle.c
index 58fdce2..0a1dedb 100644
--- a/handle.c
+++ b/handle.c
@@ -126,6 +126,10 @@ static void handleCap(struct Message *msg) {
 	enum Cap caps = capParse(msg->params[2]);
 	if (!strcmp(msg->params[1], "LS")) {
 		caps &= ~CapSASL;
+		if (caps & CapConsumer && self.pos) {
+			ircFormat("CAP REQ %s=%zu\r\n", CapNames[CapConsumerBit], self.pos);
+			caps &= ~CapConsumer;
+		}
 		if (caps) {
 			ircFormat("CAP REQ :%s\r\n", capList(caps));
 		} else {
@@ -1019,9 +1023,10 @@ void handle(struct Message msg) {
 	);
 	if (handler) {
 		handler->fn(&msg);
-		return;
-	}
-	if (strcmp(msg.cmd, "400") >= 0 && strcmp(msg.cmd, "599") <= 0) {
+	} else if (strcmp(msg.cmd, "400") >= 0 && strcmp(msg.cmd, "599") <= 0) {
 		handleErrorGeneric(&msg);
 	}
+	if (msg.tags[TagPos]) {
+		self.pos = strtoull(msg.tags[TagPos], NULL, 10);
+	}
 }
diff --git a/ui.c b/ui.c
index d6f79c2..b3f3b09 100644
--- a/ui.c
+++ b/ui.c
@@ -960,7 +960,8 @@ void uiRead(void) {
 
 static const time_t Signatures[] = {
 	0x6C72696774616301, // no heat, unread, unreadWarm
-	0x6C72696774616302,
+	0x6C72696774616302, // no self.pos
+	0x6C72696774616303,
 };
 
 static size_t signatureVersion(time_t signature) {
@@ -981,7 +982,8 @@ int uiSave(const char *name) {
 	FILE *file = dataOpen(name, "w");
 	if (!file) return -1;
 
-	if (writeTime(file, Signatures[1])) return -1;
+	if (writeTime(file, Signatures[2])) return -1;
+	if (writeTime(file, self.pos)) return -1;
 	for (uint num = 0; num < windows.len; ++num) {
 		const struct Window *window = windows.ptrs[num];
 		if (writeString(file, idNames[window->id])) return -1;
@@ -1032,6 +1034,10 @@ void uiLoad(const char *name) {
 	}
 	size_t version = signatureVersion(signature);
 
+	if (version > 1) {
+		self.pos = readTime(file);
+	}
+
 	char *buf = NULL;
 	size_t cap = 0;
 	while (0 < readString(file, &buf, &cap)) {