summary refs log tree commit diff
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rw-r--r--bin/man1/typer.19
-rw-r--r--bin/typer.c32
2 files changed, 32 insertions, 9 deletions
diff --git a/bin/man1/typer.1 b/bin/man1/typer.1
index 11856406..a3b0eb90 100644
--- a/bin/man1/typer.1
+++ b/bin/man1/typer.1
@@ -1,4 +1,4 @@
-.Dd March 23, 2021
+.Dd April 18, 2021
 .Dt TYPER 1
 .Os
 .
@@ -8,7 +8,7 @@
 .
 .Sh SYNOPSIS
 .Nm
-.Op Fl Pv
+.Op Fl PRv
 .Op Fl c Ar cert
 .Op Fl n Ar nick
 .Op Fl p Ar port
@@ -26,6 +26,11 @@ The arguments are as follows:
 Request the
 .Sy causal.agency/passive
 vendor-specific capability.
+.It Fl R
+Reverse
+.Nm .
+Send other users' typing indicators
+as regular messages for all to see.
 .It Fl c Ar cert
 Use the TLS client certificate
 and private key loaded from
diff --git a/bin/typer.c b/bin/typer.c
index 5ee94515..0218ee24 100644
--- a/bin/typer.c
+++ b/bin/typer.c
@@ -63,10 +63,13 @@ static void format(const char *format, ...) {
 }
 
 static bool joined;
+static bool reverse;
 
 static void handle(char *line) {
-	if (line && line[0] == '@') strsep(&line, " ");
-	if (line && line[0] == ':') strsep(&line, " ");
+	char *tags = NULL;
+	char *origin = NULL;
+	if (line && line[0] == '@') tags = 1 + strsep(&line, " ");
+	if (line && line[0] == ':') origin = 1 + strsep(&line, " ");
 	char *cmd = strsep(&line, " ");
 	if (!cmd) return;
 	if (!strcmp(cmd, "CAP")) {
@@ -81,6 +84,15 @@ static void handle(char *line) {
 		joined = true;
 	} else if (!strcmp(cmd, "PING")) {
 		format("PONG %s\r\n", line);
+	} else if (reverse && !strcmp(cmd, "TAGMSG") && tags && origin) {
+		char *nick = strsep(&origin, "!");
+		if (strstr(tags, "typing=active")) {
+			format("PRIVMSG %s :\u2328\uFE0F %s is typing!\r\n", chan, nick);
+		} else if (strstr(tags, "typing=paused")) {
+			format("PRIVMSG %s :\U0001F914 %s is thinking!\r\n", chan, nick);
+		} else if (strstr(tags, "typing=done")) {
+			format("PRIVMSG %s :\u270B %s stopped typing!\r\n", chan, nick);
+		}
 	}
 }
 
@@ -102,9 +114,10 @@ int main(int argc, char *argv[]) {
 	const char *user = "typer";
 	bool passive = false;
 
-	for (int opt; 0 < (opt = getopt(argc, argv, "Pc:n:p:u:v"));) {
+	for (int opt; 0 < (opt = getopt(argc, argv, "PRc:n:p:u:v"));) {
 		switch (opt) {
 			break; case 'P': passive = true;
+			break; case 'R': reverse = true;
 			break; case 'c': cert = optarg;
 			break; case 'n': nick = optarg;
 			break; case 'p': port = optarg;
@@ -143,10 +156,15 @@ int main(int argc, char *argv[]) {
 		nick, user
 	);
 
-	signal(SIGALRM, timer);
-	struct itimerval itimer = { .it_interval.tv_sec = 5, .it_value.tv_sec = 5 };
-	error = setitimer(ITIMER_REAL, &itimer, NULL);
-	if (error) err(EX_OSERR, "setitimer");
+	if (!reverse) {
+		signal(SIGALRM, timer);
+		struct itimerval itimer = {
+			.it_interval.tv_sec = 5,
+			.it_value.tv_sec = 5
+		};
+		error = setitimer(ITIMER_REAL, &itimer, NULL);
+		if (error) err(EX_OSERR, "setitimer");
+	}
 
 	size_t len = 0;
 	char buf[4096];