about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--litterbox.113
-rw-r--r--litterbox.c34
2 files changed, 46 insertions, 1 deletions
diff --git a/litterbox.1 b/litterbox.1
index 6e9f64c..b7d0111 100644
--- a/litterbox.1
+++ b/litterbox.1
@@ -1,4 +1,4 @@
-.Dd May 21, 2020
+.Dd July 19, 2020
 .Dt LITTERBOX 1
 .Os
 .
@@ -10,6 +10,7 @@
 .Nm
 .Op Fl Qqv
 .Op Fl N Ar network
+.Op Fl U Ar url
 .Op Fl c Ar cert
 .Op Fl d Ar path
 .Op Fl h Ar host
@@ -113,6 +114,16 @@ The searchable columns are
 For search query syntax, see
 .Aq Lk https://www.sqlite.org/fts5.html#full_text_query_syntax .
 .
+.It Fl U Ar url , Cm scooper-url = Ar url
+Set the base URL of a
+.Xr scooper 1
+instance
+used to construct links to full search results
+in response to the search query interface enabled by
+.Fl Q
+or
+.Fl q .
+.
 .It Fl b Ar path
 Perform a live database backup to
 .Ar path
diff --git a/litterbox.c b/litterbox.c
index 70a5185..884bed6 100644
--- a/litterbox.c
+++ b/litterbox.c
@@ -243,6 +243,28 @@ static void handleReplyEndOfMOTD(struct Message *msg) {
 	memset(&motd, 0, sizeof(motd));
 }
 
+static char *scooperURL;
+
+static void urlEncode(const char *str) {
+	static const char *Safe = {
+		"$-_.+!*'(),"
+		"0123456789"
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+		"abcdefghijklmnopqrstuvwxyz"
+	};
+	while (*str) {
+		size_t len = strspn(str, Safe);
+		if (len) clientWrite(str, len);
+		str += len;
+		if (*str == ' ') {
+			clientWrite("+", 1);
+			str++;
+		} else if (*str) {
+			format("%%%02X", *str++);
+		}
+	}
+}
+
 static int color(const char *user) {
 	return 2 + hash(user) % 74;
 }
@@ -338,6 +360,12 @@ static void querySearch(struct Message *msg) {
 		} else {
 			warnx("%s", sqlite3_errmsg(db));
 		}
+	} else if (scooperURL) {
+		format("NOTICE %s :%s/search?network=", msg->nick, scooperURL);
+		urlEncode(network);
+		format("&query=");
+		urlEncode(msg->params[1]);
+		format("\r\n");
 	}
 
 	sqlite3_reset(stmt);
@@ -738,6 +766,7 @@ int main(int argc, char *argv[]) {
 		{ .val = '!', .name = "insecure", no_argument },
 		{ .val = 'N', .name = "network", required_argument },
 		{ .val = 'Q', .name = "public-query", no_argument },
+		{ .val = 'U', .name = "scooper-url", required_argument },
 		{ .val = 'b', .name = "backup", required_argument },
 		{ .val = 'c', .name = "cert", required_argument },
 		{ .val = 'd', .name = "database", required_argument },
@@ -766,6 +795,7 @@ int main(int argc, char *argv[]) {
 			break; case '!': insecure = true;
 			break; case 'N': defaultNetwork = optarg;
 			break; case 'Q': searchQuery = Public;
+			break; case 'U': scooperURL = optarg;
 			break; case 'b': backup = optarg;
 			break; case 'c': cert = optarg;
 			break; case 'd': path = optarg;
@@ -785,6 +815,10 @@ int main(int argc, char *argv[]) {
 		}
 	}
 	if (!user) user = nick;
+	if (scooperURL && scooperURL[0]) {
+		size_t len = strlen(scooperURL);
+		if (scooperURL[len - 1] == '/') scooperURL[len - 1] = '\0';
+	}
 
 	int flags = SQLITE_OPEN_READWRITE;
 	if (init) flags |= SQLITE_OPEN_CREATE;