summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-07-11 14:04:25 -0400
committerJune McEnroe <june@causal.agency>2020-07-11 14:04:25 -0400
commit24c7965d9d0aaf27985d29c5cbb12a4e08ac7d9c (patch)
tree2a9e3955d59c375edb7d02ae0bd195bf966d57ea
parentImplement basic search page (diff)
downloadscooper-24c7965d9d0aaf27985d29c5cbb12a4e08ac7d9c.tar.gz
scooper-24c7965d9d0aaf27985d29c5cbb12a4e08ac7d9c.zip
Factor out "scope" of pages
Use this to keep the search query around and hide network and context
from the search results if the scope is already limited.
Diffstat (limited to '')
-rw-r--r--contexts.c14
-rw-r--r--events.c21
-rw-r--r--html.c35
-rw-r--r--networks.c4
-rw-r--r--search.c26
-rw-r--r--server.h22
6 files changed, 65 insertions, 57 deletions
diff --git a/contexts.c b/contexts.c
index d8eb4fd..e17ccfe 100644
--- a/contexts.c
+++ b/contexts.c
@@ -46,22 +46,22 @@ const char *ContextsQuery = SQL(
 );
 
 enum kcgi_err pageContexts(struct kreq *req) {
-	if (!req->fieldmap[Network]) return httpFail(req, KHTTP_400);
+	struct Scope scope = htmlScope(req);
+	if (!scope.network) return httpFail(req, KHTTP_400);
+
 	enum kcgi_err error = httpHead(req, KHTTP_200, KMIME_TEXT_HTML);
 	if (req->method == KMETHOD_HEAD) return error;
 
-	const char *network = req->fieldmap[Network]->parsed.s;
-
 	struct khtmlreq html;
 	error = error
 		|| khttp_body(req)
 		|| khtml_open(&html, req, KHTML_PRETTY)
-		|| htmlHead(&html, network)
-		|| htmlNav(&html, network, NULL);
+		|| htmlHead(&html, scope.network)
+		|| htmlNav(&html, scope);
 	if (error) return error;
 
 	dbBindInt(stmt.contexts, ":recent", pageRecent);
-	dbBindText(stmt.contexts, ":network", network);
+	dbBindText(stmt.contexts, ":network", scope.network);
 	if (pagePublic) dbBindInt(stmt.contexts, ":query", false);
 
 	enum State {
@@ -92,7 +92,7 @@ enum kcgi_err pageContexts(struct kreq *req) {
 
 		char *href = khttp_urlpart(
 			NULL, NULL, Pages[Events],
-			Keys[Network].name, network,
+			Keys[Network].name, scope.network,
 			Keys[Context].name, context,
 			NULL
 		);
diff --git a/events.c b/events.c
index 32e94c2..5e332a3 100644
--- a/events.c
+++ b/events.c
@@ -70,11 +70,8 @@ const char *EventsBeforeQuery = SQL(
 );
 
 enum kcgi_err pageEvents(struct kreq *req) {
-	if (!req->fieldmap[Network] || !req->fieldmap[Context]) {
-		return httpFail(req, KHTTP_400);
-	}
-	const char *network = req->fieldmap[Network]->parsed.s;
-	const char *context = req->fieldmap[Context]->parsed.s;
+	struct Scope scope = htmlScope(req);
+	if (!scope.network || !scope.context) return httpFail(req, KHTTP_400);
 
 	if (!req->fieldmap[After] && !req->fieldmap[Before]) {
 		struct tm *tm = gmtime(&(time_t) { time(NULL) });
@@ -85,8 +82,8 @@ enum kcgi_err pageEvents(struct kreq *req) {
 
 		char *url = khttp_urlpart(
 			NULL, NULL, Pages[Events],
-			Keys[Network].name, network,
-			Keys[Context].name, context,
+			Keys[Network].name, scope.network,
+			Keys[Context].name, scope.context,
 			Keys[Before].name, time,
 			NULL
 		);
@@ -106,16 +103,16 @@ enum kcgi_err pageEvents(struct kreq *req) {
 	error = error
 		|| khttp_body(req)
 		|| khtml_open(&html, req, KHTML_PRETTY)
-		|| htmlHead(&html, context)
-		|| htmlNav(&html, network, context)
+		|| htmlHead(&html, scope.context)
+		|| htmlNav(&html, scope)
 		|| khtml_elem(&html, KELEM_TABLE);
 	if (error) return error;
 
 	sqlite3_stmt *events = stmt.eventsAfter;
 	if (req->fieldmap[Before]) events = stmt.eventsBefore;
 
-	dbBindText(events, ":network", network);
-	dbBindText(events, ":context", context);
+	dbBindText(events, ":network", scope.network);
+	dbBindText(events, ":context", scope.context);
 	if (pagePublic) dbBindInt(events, ":query", false);
 	dbBindText(events, ":time", time);
 	dbBindInt(events, ":limit", pageLimit);
@@ -132,7 +129,7 @@ enum kcgi_err pageEvents(struct kreq *req) {
 			.target = (const char *)sqlite3_column_text(events, 6),
 			.message = (const char *)sqlite3_column_text(events, 7),
 		};
-		error = htmlEvent(&html, event);
+		error = htmlEvent(&html, scope, event);
 		if (error) break;
 	}
 	if (result != SQLITE_DONE) errx(EX_SOFTWARE, "%s", sqlite3_errmsg(db));
diff --git a/html.c b/html.c
index 9386205..562f909 100644
--- a/html.c
+++ b/html.c
@@ -49,7 +49,7 @@ enum kcgi_err htmlHead(struct khtmlreq *html, const char *title) {
 }
 
 enum kcgi_err
-htmlNav(struct khtmlreq *html, const char *network, const char *context) {
+htmlNav(struct khtmlreq *html, struct Scope scope) {
 	enum kcgi_err error = 0
 		|| khtml_elem(html, KELEM_NAV)
 		|| khtml_elem(html, KELEM_OL)
@@ -59,33 +59,33 @@ htmlNav(struct khtmlreq *html, const char *network, const char *context) {
 		|| khtml_closeelem(html, 2);
 	if (error) return error;
 
-	if (network) {
+	if (scope.network) {
 		char *href = khttp_urlpart(
 			NULL, NULL, Pages[Contexts],
-			Keys[Network].name, network,
+			Keys[Network].name, scope.network,
 			NULL
 		);
 		if (!href) err(EX_OSERR, "khttp_urlpart");
 		error = 0
 			|| khtml_elem(html, KELEM_LI)
 			|| khtml_attr(html, KELEM_A, KATTR_HREF, href, KATTR__MAX)
-			|| khtml_puts(html, network)
+			|| khtml_puts(html, scope.network)
 			|| khtml_closeelem(html, 2);
 		if (error) return error;
 	}
 
-	if (network && context) {
+	if (scope.network && scope.context) {
 		char *href = khttp_urlpart(
 			NULL, NULL, Pages[Events],
-			Keys[Network].name, network,
-			Keys[Context].name, context,
+			Keys[Network].name, scope.network,
+			Keys[Context].name, scope.context,
 			NULL
 		);
 		if (!href) err(EX_OSERR, "khttp_urlpart");
 		error = 0
 			|| khtml_elem(html, KELEM_LI)
 			|| khtml_attr(html, KELEM_A, KATTR_HREF, href, KATTR__MAX)
-			|| khtml_puts(html, context)
+			|| khtml_puts(html, scope.context)
 			|| khtml_closeelem(html, 2);
 		if (error) return error;
 	}
@@ -93,7 +93,8 @@ htmlNav(struct khtmlreq *html, const char *network, const char *context) {
 	char label[256];
 	snprintf(
 		label, sizeof(label), "Search%s%s",
-		(network ? " " : ""), (context ? context : network ? network : "")
+		(scope.network ? " " : ""),
+		(scope.context ? scope.context : scope.network ? scope.network : "")
 	);
 
 	error = 0
@@ -108,6 +109,7 @@ htmlNav(struct khtmlreq *html, const char *network, const char *context) {
 			html, KELEM_INPUT,
 			KATTR_TYPE, "search",
 			KATTR_NAME, Keys[Query].name,
+			KATTR_VALUE, (scope.query ? scope.query : ""),
 			KATTR__MAX
 		)
 		|| khtml_attr(
@@ -118,23 +120,23 @@ htmlNav(struct khtmlreq *html, const char *network, const char *context) {
 		);
 	if (error) return error;
 
-	if (network) {
+	if (scope.network) {
 		error = khtml_attr(
 			html, KELEM_INPUT,
 			KATTR_TYPE, "hidden",
 			KATTR_NAME, Keys[Network].name,
-			KATTR_VALUE, network,
+			KATTR_VALUE, scope.network,
 			KATTR__MAX
 		);
 		if (error) return error;
 	}
 
-	if (context) {
+	if (scope.context) {
 		error = khtml_attr(
 			html, KELEM_INPUT,
 			KATTR_TYPE, "hidden",
 			KATTR_NAME, Keys[Context].name,
-			KATTR_VALUE, context,
+			KATTR_VALUE, scope.context,
 			KATTR__MAX
 		);
 		if (error) return error;
@@ -284,7 +286,8 @@ static const char *Types[TypesLen] = {
 #undef X
 };
 
-enum kcgi_err htmlEvent(struct khtmlreq *html, struct Event event) {
+enum kcgi_err
+htmlEvent(struct khtmlreq *html, struct Scope scope, struct Event event) {
 	const char *type = (event.type < TypesLen ? Types[event.type] : "unknown");
 	return 0
 		|| khtml_attrx(
@@ -294,8 +297,8 @@ enum kcgi_err htmlEvent(struct khtmlreq *html, struct Event event) {
 			KATTR__MAX
 		)
 		|| eventTime(html, event)
-		|| eventNetwork(html, event)
-		|| eventContext(html, event)
+		|| (scope.network ? 0 : eventNetwork(html, event))
+		|| (scope.context ? 0 : eventContext(html, event))
 		|| eventNick(html, event)
 		|| eventMessage(html, event)
 		|| khtml_closeelem(html, 1);
diff --git a/networks.c b/networks.c
index 7f974c4..74b9ea2 100644
--- a/networks.c
+++ b/networks.c
@@ -44,6 +44,8 @@ const char *NetworksQuery = SQL(
 );
 
 enum kcgi_err pageNetworks(struct kreq *req) {
+	struct Scope scope = {0};
+
 	enum kcgi_err error = httpHead(req, KHTTP_200, KMIME_TEXT_HTML);
 	if (req->method == KMETHOD_HEAD) return error;
 
@@ -52,7 +54,7 @@ enum kcgi_err pageNetworks(struct kreq *req) {
 		|| khttp_body(req)
 		|| khtml_open(&html, req, KHTML_PRETTY)
 		|| htmlHead(&html, "Litterbox")
-		|| htmlNav(&html, NULL, NULL);
+		|| htmlNav(&html, scope);
 	if (error) return error;
 
 	dbBindInt(stmt.networks, ":recent", pageRecent);
diff --git a/search.c b/search.c
index 767081b..6fba589 100644
--- a/search.c
+++ b/search.c
@@ -46,20 +46,12 @@ const char *SearchQuery = SQL(
 );
 
 enum kcgi_err pageSearch(struct kreq *req) {
-	if (!req->fieldmap[Query]) {
-		return httpFail(req, KHTTP_400);
-	}
-	if (req->fieldmap[Context] && !req->fieldmap[Network]) {
-		return httpFail(req, KHTTP_400);
-	}
-	const char *query = req->fieldmap[Query]->parsed.s;
+	struct Scope scope = htmlScope(req);
+	if (!scope.query) return httpFail(req, KHTTP_400);
+	if (scope.context && !scope.network) return httpFail(req, KHTTP_400);
 
 	int64_t offset = 0;
-	const char *network = NULL;
-	const char *context = NULL;
 	if (req->fieldmap[Offset]) offset = req->fieldmap[Offset]->parsed.i;
-	if (req->fieldmap[Network]) network = req->fieldmap[Network]->parsed.s;
-	if (req->fieldmap[Context]) context = req->fieldmap[Context]->parsed.s;
 
 	enum kcgi_err error = httpHead(req, KHTTP_200, KMIME_TEXT_HTML);
 	if (req->method == KMETHOD_HEAD) return error;
@@ -68,16 +60,16 @@ enum kcgi_err pageSearch(struct kreq *req) {
 	error = error
 		|| khttp_body(req)
 		|| khtml_open(&html, req, KHTML_PRETTY)
-		|| htmlHead(&html, query)
-		|| htmlNav(&html, network, context)
+		|| htmlHead(&html, scope.query)
+		|| htmlNav(&html, scope)
 		|| khtml_elem(&html, KELEM_TABLE);
 	if (error) return error;
 
 	dbBindText(stmt.search, ":highlight", "\26");
-	dbBindText(stmt.search, ":network", network);
-	dbBindText(stmt.search, ":context", context);
+	dbBindText(stmt.search, ":network", scope.network);
+	dbBindText(stmt.search, ":context", scope.context);
 	if (pagePublic) dbBindInt(stmt.search, ":query", false);
-	dbBindText(stmt.search, ":search", query);
+	dbBindText(stmt.search, ":search", scope.query);
 	dbBindInt(stmt.search, ":limit", pageLimit);
 	dbBindInt(stmt.search, ":offset", offset);
 
@@ -95,7 +87,7 @@ enum kcgi_err pageSearch(struct kreq *req) {
 			.target = (const char *)sqlite3_column_text(stmt.search, 8),
 			.message = (const char *)sqlite3_column_text(stmt.search, 9),
 		};
-		error = htmlEvent(&html, event);
+		error = htmlEvent(&html, scope, event);
 		if (error) break;
 	}
 	if (result != SQLITE_DONE) errx(EX_SOFTWARE, "%s", sqlite3_errmsg(db));
diff --git a/server.h b/server.h
index 502e228..318d103 100644
--- a/server.h
+++ b/server.h
@@ -171,10 +171,24 @@ static inline enum kcgi_err httpFail(struct kreq *req, enum khttp http) {
 		|| khttp_printf(req, "%s\n", khttps[http]);
 }
 
+struct Scope {
+	const char *network;
+	const char *context;
+	const char *query;
+};
+
+static inline struct Scope htmlScope(struct kreq *req) {
+	struct Scope s = {0};
+	if (req->fieldmap[Network]) s.network = req->fieldmap[Network]->parsed.s;
+	if (req->fieldmap[Context]) s.context = req->fieldmap[Context]->parsed.s;
+	if (req->fieldmap[Query]) s.query = req->fieldmap[Query]->parsed.s;
+	return s;
+}
+
 extern const char *htmlStylesheet;
 enum kcgi_err htmlHead(struct khtmlreq *html, const char *title);
-enum kcgi_err htmlNav(
-	struct khtmlreq *html, const char *network, const char *context
-);
+enum kcgi_err htmlNav(struct khtmlreq *html, struct Scope scope);
 enum kcgi_err htmlFooter(struct khtmlreq *html);
-enum kcgi_err htmlEvent(struct khtmlreq *html, struct Event event);
+enum kcgi_err htmlEvent(
+	struct khtmlreq *html, struct Scope scope, struct Event event
+);