changeset 954:30643d18a635

irccd: add onCommand support
author David Demelier <markand@malikania.fr>
date Wed, 20 Jan 2021 14:08:14 +0100
parents ab43ba409f9d
children 9b167c5c4b78
files irccd/main.c lib/irccd/event.h lib/irccd/irccd.c lib/irccd/js-plugin.c lib/irccd/jsapi-server.c lib/irccd/server.c
diffstat 6 files changed, 76 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/irccd/main.c	Wed Jan 20 12:32:59 2021 +0100
+++ b/irccd/main.c	Wed Jan 20 14:08:14 2021 +0100
@@ -38,10 +38,13 @@
 		.username = "circ",
 		.nickname = "circ",
 		.hostname = "malikania.fr",
+		.commandchar = "!",
 		.port = 6697,
 		.flags = IRC_SERVER_FLAGS_SSL | IRC_SERVER_FLAGS_JOIN_INVITE
 	};
-	struct irc_plugin p = {0};
+	struct irc_plugin p = {
+		.name = "test"
+	};
 
 	irc_log_set_verbose(true);
 	irc_bot_init();
--- a/lib/irccd/event.h	Wed Jan 20 12:32:59 2021 +0100
+++ b/lib/irccd/event.h	Wed Jan 20 14:08:14 2021 +0100
@@ -28,6 +28,7 @@
 
 enum irc_event_type {
 	IRC_EVENT_UNKNOWN,
+	IRC_EVENT_COMMAND,
 	IRC_EVENT_CONNECT,
 	IRC_EVENT_DISCONNECT,
 	IRC_EVENT_INVITE,
--- a/lib/irccd/irccd.c	Wed Jan 20 12:32:59 2021 +0100
+++ b/lib/irccd/irccd.c	Wed Jan 20 14:08:14 2021 +0100
@@ -17,6 +17,7 @@
  */
 
 #include <assert.h>
+#include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <poll.h>
@@ -43,7 +44,7 @@
 
 struct defer {
 	void (*exec)(void *);
-	void (*data);
+	void *data;
 };
 
 struct irc irc;
@@ -62,6 +63,39 @@
 	return p1->fd - p2->fd;
 }
 
+static bool
+is_command(const struct irc_plugin *p, const struct irc_event *ev)
+{
+	const char *cc;
+	size_t ccsz;
+
+	if (ev->type != IRC_EVENT_MESSAGE)
+		return false;
+
+	/* Get the command prefix (e.g !)*/
+	cc = ev->server->commandchar;
+	ccsz = strlen(cc);
+
+	return strncmp(ev->msg.args[1], cc, ccsz) == 0 &&
+	       strncmp(ev->msg.args[1] + ccsz, p->name, strlen(p->name)) == 0;
+}
+
+static struct irc_event *
+to_command(const struct irc_plugin *p, struct irc_event *ev)
+{
+	char *s;
+
+	ev->type = IRC_EVENT_COMMAND;
+	ev->msg.args[1] = ev->msg.args[1] + strlen(ev->server->commandchar) + strlen(p->name);
+
+	for (s = ev->msg.args[1]; *s && isspace(*s); )
+		++s;
+
+	ev->msg.args[1] = s;
+
+	return ev;
+}
+
 static struct pkg
 prepare(void)
 {
@@ -103,11 +137,34 @@
 			irc_peer_send(&irc.peers[i], buf);
 }
 
-static inline void
-invoke(const struct irc_event *ev)
+static void
+invoke(struct irc_event *ev)
 {
-	for (size_t i = 0; i < irc.pluginsz; ++i)
-		irc_plugin_handle(&irc.plugins[i], ev);
+	struct irc_plugin *plgcmd = NULL;
+
+	/*
+	 * Invoke for every plugin the event verbatim. Then, the event may match
+	 * a plugin name command in that case we need to modify the event but
+	 * only one plugin can match by its identifier. For example, the
+	 * following plugins are loaded:
+	 *
+	 * - ask
+	 * - hangman
+	 * - logger
+	 *
+	 * If the message is "!ask will I be reach?" then it will invoke
+	 * onMessage for hangman and logger but onCommand for ask. As such call
+	 * hangman and logger first and modify event before ask.
+	 */
+	for (size_t i = 0; i < irc.pluginsz; ++i) {
+		if (is_command(&irc.plugins[i], ev))
+			plgcmd = &irc.plugins[i];
+		else
+			irc_plugin_handle(&irc.plugins[i], ev);
+	}
+
+	if (plgcmd)
+		irc_plugin_handle(plgcmd, to_command(plgcmd, ev));
 }
 
 static void
@@ -222,7 +279,7 @@
 	irc_server_disconnect(s);
 
 	/* Don't forget to notify plugins. */
-	invoke(&(const struct irc_event) {
+	invoke(&(struct irc_event) {
 		.type = IRC_EVENT_DISCONNECT,
 		.server = s
 	});
--- a/lib/irccd/js-plugin.c	Wed Jan 20 12:32:59 2021 +0100
+++ b/lib/irccd/js-plugin.c	Wed Jan 20 14:08:14 2021 +0100
@@ -278,6 +278,10 @@
 	(void)ev;
 
 	switch (ev->type) {
+	case IRC_EVENT_COMMAND:
+		call(plg, "onCommand", "Ss ss", ev->server, ev->msg.prefix,
+		    ev->msg.args[0], ev->msg.args[1]);
+		break;
 	case IRC_EVENT_CONNECT:
 		call(plg, "onConnect", "S", ev->server);
 		break;
--- a/lib/irccd/jsapi-server.c	Wed Jan 20 12:32:59 2021 +0100
+++ b/lib/irccd/jsapi-server.c	Wed Jan 20 14:08:14 2021 +0100
@@ -585,7 +585,7 @@
 	irc_server_incref(s);
 
 	duk_push_object(ctx);
-	duk_push_string(ctx, s->name);
+	duk_push_pointer(ctx, s);
 	duk_put_prop_string(ctx, -2, SIGNATURE);
 	duk_get_global_string(ctx, PROTOTYPE);
 	duk_set_prototype(ctx, -2);
--- a/lib/irccd/server.c	Wed Jan 20 12:32:59 2021 +0100
+++ b/lib/irccd/server.c	Wed Jan 20 14:08:14 2021 +0100
@@ -336,8 +336,10 @@
 	const struct handler *c = bsearch(ev->msg.cmd, handlers, IRC_UTIL_SIZE(handlers),
 	    sizeof (*c), &(compare_handler));
 
-	if (c)
+	if (c) {
+		ev->server = s;
 		c->handle(s, ev);
+	}
 }
 
 static void