summary refs log tree commit diff
path: root/events.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--events.c78
1 files changed, 76 insertions, 2 deletions
diff --git a/events.c b/events.c
index 9262225..04fdbf8 100644
--- a/events.c
+++ b/events.c
@@ -21,9 +21,59 @@
 
 #include "server.h"
 
+const char *EventsAfterQuery = SQL(
+	SELECT
+		events.event,
+		events.time,
+		events.type,
+		names.nick,
+		names.user,
+		names.host,
+		events.target,
+		events.message
+	FROM events
+	JOIN contexts USING (context)
+	JOIN names USING (name)
+	WHERE contexts.network = :network
+		AND contexts.name = :context
+		AND coalesce(contexts.query = :query, true)
+		AND events.time >= strftime('%s', :time)
+	ORDER BY events.time
+	LIMIT :limit;
+);
+
+const char *EventsBeforeQuery = SQL(
+	WITH before AS (
+		SELECT
+			events.event,
+			events.time,
+			events.type,
+			names.nick,
+			names.user,
+			names.host,
+			events.target,
+			events.message
+		FROM events
+		JOIN contexts USING (context)
+		JOIN names USING (name)
+		WHERE contexts.network = :network
+			AND contexts.name = :context
+			AND coalesce(contexts.query = :query, true)
+			AND events.time < strftime('%s', :time)
+		ORDER BY events.time DESC
+		LIMIT :limit
+	)
+	SELECT *
+	FROM before
+	ORDER BY time;
+);
+
 enum kcgi_err pageEvents(struct kreq *req) {
 	if (!req->fieldmap[Network] || !req->fieldmap[Context]) {
-		return httpFail(req, KHTTP_404);
+		return httpFail(req, KHTTP_400);
+	}
+	if (!req->fieldmap[After] && !req->fieldmap[Before]) {
+		return httpFail(req, KHTTP_400);
 	}
 
 	enum kcgi_err error = httpHead(req, KHTTP_200, KMIME_TEXT_HTML);
@@ -31,6 +81,9 @@ enum kcgi_err pageEvents(struct kreq *req) {
 
 	const char *network = req->fieldmap[Network]->parsed.s;
 	const char *context = req->fieldmap[Context]->parsed.s;
+	const char *time = req->fieldmap[Before]
+		? req->fieldmap[Before]->parsed.s
+		: req->fieldmap[After]->parsed.s;
 
 	struct khtmlreq html;
 	error = error
@@ -41,5 +94,26 @@ enum kcgi_err pageEvents(struct kreq *req) {
 		|| htmlSearch(&html, network, context);
 	if (error) return error;
 
-	return khtml_close(&html);
+	sqlite3_stmt *events = stmt.eventsAfter;
+	if (req->fieldmap[Before]) events = stmt.eventsBefore;
+
+	dbBindText(events, ":network", network);
+	dbBindText(events, ":context", context);
+	if (pagePublic) dbBindInt(events, ":query", false);
+	dbBindText(events, ":time", time);
+	dbBindInt(events, ":limit", pageLimit);
+
+	int result;
+	while (SQLITE_ROW == (result = sqlite3_step(events))) {
+		const char *msg = (const char *)sqlite3_column_text(events, 7);
+		if (!msg) continue;
+		error = 0
+			|| khtml_puts(&html, msg)
+			|| khtml_elem(&html, KELEM_BR);
+		if (error) break;
+	}
+	if (result != SQLITE_DONE) errx(EX_SOFTWARE, "%s", sqlite3_errmsg(db));
+	sqlite3_reset(events);
+
+	return error || khtml_close(&html);
 }