# HG changeset patch # User David Demelier # Date 1611148094 -3600 # Node ID 30643d18a635af4837704dcbadd9ee144ecc2d73 # Parent ab43ba409f9df1cf6567f7cd383a884f78759d7b irccd: add onCommand support diff -r ab43ba409f9d -r 30643d18a635 irccd/main.c --- 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(); diff -r ab43ba409f9d -r 30643d18a635 lib/irccd/event.h --- 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, diff -r ab43ba409f9d -r 30643d18a635 lib/irccd/irccd.c --- 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 +#include #include #include #include @@ -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 }); diff -r ab43ba409f9d -r 30643d18a635 lib/irccd/js-plugin.c --- 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; diff -r ab43ba409f9d -r 30643d18a635 lib/irccd/jsapi-server.c --- 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); diff -r ab43ba409f9d -r 30643d18a635 lib/irccd/server.c --- 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