changeset 1009:637a98de3910

misc: add more examples
author David Demelier <markand@malikania.fr>
date Wed, 17 Feb 2021 19:45:00 +0100
parents 201ddc487807
children d1ec9b99b580
files CMakeLists.txt examples/CMakeLists.txt examples/sample-plugin.c examples/sample-plugin.js man/CMakeLists.txt man/irccd-api.3 plugins/ask/ask.js plugins/auth/auth.js plugins/hangman/hangman.js plugins/history/history.js plugins/joke/joke.js plugins/logger/logger.js plugins/plugin/plugin.js plugins/roulette/roulette.js plugins/tictactoe/tictactoe.js
diffstat 15 files changed, 405 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Wed Feb 17 19:33:00 2021 +0100
+++ b/CMakeLists.txt	Wed Feb 17 19:45:00 2021 +0100
@@ -59,6 +59,7 @@
 add_subdirectory(lib)
 add_subdirectory(irccd)
 add_subdirectory(irccdctl)
+add_subdirectory(examples)
 add_subdirectory(plugins)
 add_subdirectory(man)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/CMakeLists.txt	Wed Feb 17 19:45:00 2021 +0100
@@ -0,0 +1,26 @@
+#
+# CMakeLists.txt -- CMake build for irccd
+#
+# Copyright (c) 2013-2021 David Demelier <markand@malikania.fr>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+project(examples)
+
+install(
+	FILES
+		${examples_SOURCE_DIR}/sample-plugin.c
+		${examples_SOURCE_DIR}/sample-plugin.js
+	DESTINATION ${CMAKE_INSTALL_DATADIR}/irccd
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/sample-plugin.c	Wed Feb 17 19:45:00 2021 +0100
@@ -0,0 +1,174 @@
+/*
+ * This is a sample plugin in native C API.
+ *
+ * Note: we recommend that C plugins should be used as last resort because any
+ * error will crash the whole daemon. It is also less convenient to share and
+ * update.
+ *
+ * You can use CMake to build and install it to appropriate place using the
+ * following code:
+ *
+ *   find_package(irccd REQUIRED)
+ *   irccd_define_c_plugin(
+ *     MAME myplugin
+ *     SOURCES muplugin.c
+ *   )
+ *
+ * You can also compile by hand using the pkg-config irccd file.
+ *
+ *   cc myplugin.c -o myplugin.so $(pkg-config --libs --cflags irccd)
+ *
+ * All symbols exported from the file must start with the plugin file basename
+ * without its extension and with every non allowed character translated to
+ * `_'. For example if the plugin is name `example-stuff' symbol must start
+ * with `example_stuff_'. In this example we consider `example_`.
+ */
+
+/*
+ * Include convention is using irccd/ prefix.
+ *
+ * The compat.h header contains additional BSD/POSIX extensions that may be
+ * missing on your system. It is optional unless you explicitly use them.
+ */
+
+#include <string.h>
+
+#include <irccd/compat.h>
+#include <irccd/event.h>
+#include <irccd/server.h>
+
+/*
+ * This is the plugin identifier, every variable are optional.
+ */
+const char *example_description = "Example of C plugin"
+const char *example_version = "0.1.0";
+const char *example_license = "ISC";
+const char *example_author = "Name and optional email";
+
+/*
+ * get_options | get_templates | get_paths
+ * ----------------------------------------------------------------------
+ *
+ * The following optional functions indicate to the daemon which keys are
+ * supported as options, templates and paths respectively.
+ *
+ * Note: even if get_paths is not present or return NULL, irccd allows `cache',
+ * `data' and `config' as standard keys.
+ *
+ * All three functions should return an array of strings which should be
+ * terminated with a NULL value. They should not be dynamically allocated
+ * because irccd does not assume they are.
+ */
+
+const char **
+example_get_options(void)
+{
+	/* Indicate to irccd we support options `level' and `language' */
+	static const char *keys[] = {
+		"level",
+		"language",
+		NULL
+	};
+
+	return keys;
+}
+
+const char **
+example_get_templates(void)
+{
+	/* Indicate to irccd we support templates `start' and `finish' */
+	static const char *keys[] = {
+		"start",
+		"finish",
+		NULL
+	};
+
+	return keys;
+}
+
+/*
+ * get_option | get_template | get_path
+ * ----------------------------------------------------------------------
+ *
+ * Those optional functions are analogous to their respective plural form
+ * except they take a key as parameter.
+ *
+ * The plugin can receive an unknown key from the user, NULL can be returned if
+ * they are not supported.
+ *
+ * The returned string isn't free'd by irccd so don't allocate any value
+ * without storing it somewhere if really needed.
+ */
+
+const char *
+example_get_option(const char *key)
+{
+	if (strcmp(key, "level") == 0)
+		return "hard";
+	else if (strcmp(key, "language") == 0)
+		return "french";
+
+	return NULL;
+}
+
+const char *
+example_get_template(const char *key)
+{
+	if (strcmp(key, "start") == 0)
+		return "#{nickname}, the game has started";
+	else if (strcmp(key, "finish") == 0)
+		return "#{nickname}, the game has finished";
+
+	return NULL;
+}
+
+/*
+ * set_option | set_template | set_path
+ * ----------------------------------------------------------------------
+ *
+ * Finally the three functions are used to set a new value as options,
+ * templates and paths respectively. Like their `get_*' counterpart, the plugin
+ * may receive a unknown key from the user in that case it should be simply
+ * ignored.
+ *
+ * Tip: the easiest to manage those is to use global fixed size strings.
+ */
+
+void
+example_set_option(const char *key, const char *value)
+{
+	/* Assuming my_option_* variable exist. */
+	if (strcmp(key, "level") == 0)
+		strlcpy(my_option_level, value, sizeof (my_option_level));
+	else if (strcmp(key, "language") == 0)
+		strlcpy(my_option_language, value, sizeof (my_option_language));
+}
+
+void
+example_set_template(const char *key)
+{
+	/* Assuming my_template_* variable exist. */
+	if (strcmp(key, "level") == 0)
+		strlcpy(my_template_level, value, sizeof (my_template_level));
+	else if (strcmp(key, "language") == 0)
+		strlcpy(my_template_language, value, sizeof (my_template_language));
+}
+
+/*
+ * event
+ * ----------------------------------------------------------------------
+ *
+ * This function is called when an event has been received. The parameter ev
+ * contains a union with every possible supported event, the plugin must not
+ * modify it.
+ *
+ * Use the ev->type enumeration to read the appropriate union member.
+ */
+
+void
+example_event(const struct irc_event *ev)
+{
+	/* Simply echo back in case of message. */
+	if (ev->type == IRC_EVENT_MESSAGE)
+		irc_server_message(ev->server, ev->message.channel, ev->message.message);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/sample-plugin.js	Wed Feb 17 19:45:00 2021 +0100
@@ -0,0 +1,153 @@
+/*
+ * This is a sample plugin in Javascript API.
+ */
+
+/*
+ * This is the plugin identifier, every variable are optional.
+ */
+info = {
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "Crazy module for asking a medium",
+	version: "@IRCCD_VERSION@"
+};
+
+/*
+ * Called when the user invoke the plugin using its identifier and the server
+ * prefix.
+ *
+ * Example: !example foo bar baz
+ */
+function onCommand(server, origin, channel, message)
+{
+}
+
+/*
+ * Called when a server successfully connect and identifies to a IRC server.
+ */
+function onConnect(server)
+{
+}
+
+/*
+ * Called when a server disconnection is detected.
+ */
+function onDisconnect(server)
+{
+}
+
+/*
+ * Called when someone invites the bot on a channel.
+ */
+function onInvite(server, origin, channel)
+{
+}
+
+/*
+ * Called when someones join a channel (the bot included).
+ */
+function onJoin(server, origin, channel)
+{
+}
+
+/*
+ * Called when a someone was kicked from a channel.
+ */
+function onKick(server, origin, channel, reason)
+{
+}
+
+/*
+ * Called when a plugin is being loaded. Never happens from IRC.
+ */
+function onLoad()
+{
+}
+
+/*
+ * Called when a special CTCP ACTION (/me) is received.
+ */
+function onMe(server, origin, channel, message)
+{
+}
+
+/*
+ * Called when a message has been received.
+ */
+function onMessage(server, origin, channel, message)
+{
+}
+
+/*
+ * Called when a user/channel mode change. The channel can be the bot nickname.
+ * The args is a list of string containing mode arguments.
+ */
+function onMode(server, origin, channel, args)
+{
+}
+
+/*
+ * Called when a list of names have been received.
+ *
+ * Note: in contrast to the IRC names listing, the names are not prefixed with
+ * their optional channel mode (e.g. @+ etc).
+ *
+ * Tip: using this event is no longer necessary starting from irccd 4, the bot
+ * keeps track of users of every channel it is present and can be accessed
+ * through the method Irccd.Server.prototype.info.
+ */
+function onNames(server, channel, names)
+{
+}
+
+/*
+ * Called when a nickname change.
+ */
+function onNick(server, origin, nickname)
+{
+}
+
+/*
+ * Called when a notice is received. The channel can be the bot nickname as
+ * well.
+ */
+function onNotice(server, origin, channel, notice)
+{
+}
+
+/*
+ * Called when someone leaves a channel.
+ */
+function onPart(server, origin, channel, reason)
+{
+}
+
+/*
+ * Called when the user request a plugin reload. Never happens from IRC.
+ */
+function onReload()
+{
+}
+
+/*
+ * Called when a topic change.
+ */
+function onTopic(server, origin, channel, topic)
+{
+}
+
+/*
+ * Called when the plugin is about to be removed. Never happens from IRC.
+ */
+function onUnload()
+{
+}
+
+/*
+ * Called when a whois information has been received. This function is usually
+ * never called unless the plugin explicitly calls Irccd.Server.prototype.whois
+ * beforehand.
+ */
+function onWhois(server, info)
+{
+}
--- a/man/CMakeLists.txt	Wed Feb 17 19:33:00 2021 +0100
+++ b/man/CMakeLists.txt	Wed Feb 17 19:45:00 2021 +0100
@@ -18,6 +18,15 @@
 
 project(man)
 
+function(man file section)
+	get_filename_component(basename ${file} NAME)
+	configure_file(${file} ${man_BINARY_DIR}/${basename})
+	install(
+		FILES ${man_BINARY_DIR}/${basename}
+		DESTINATION ${CMAKE_INSTALL_MANDIR}/${section}
+	)
+endfunction()
+
 set(
 	MAN1
 	${man_SOURCE_DIR}/irccd.1
@@ -26,21 +35,27 @@
 
 set(
 	MAN3
-	${man_SOURCE_DIR}/irccd-api-chrono.3
-	${man_SOURCE_DIR}/irccd-api-directory.3
-	${man_SOURCE_DIR}/irccd-api-file.3
-	${man_SOURCE_DIR}/irccd-api-hook.3
-	${man_SOURCE_DIR}/irccd-api-logger.3
-	${man_SOURCE_DIR}/irccd-api-plugin.3
-	${man_SOURCE_DIR}/irccd-api-rule.3
-	${man_SOURCE_DIR}/irccd-api-server.3
-	${man_SOURCE_DIR}/irccd-api-system.3
-	${man_SOURCE_DIR}/irccd-api-timer.3
-	${man_SOURCE_DIR}/irccd-api-unicode.3
-	${man_SOURCE_DIR}/irccd-api-util.3
-	${man_SOURCE_DIR}/irccd-api.3
 )
 
+if (IRCCD_WITH_JS)
+	list(
+		APPEND MAN3
+		${man_SOURCE_DIR}/irccd-api-chrono.3
+		${man_SOURCE_DIR}/irccd-api-directory.3
+		${man_SOURCE_DIR}/irccd-api-file.3
+		${man_SOURCE_DIR}/irccd-api-hook.3
+		${man_SOURCE_DIR}/irccd-api-logger.3
+		${man_SOURCE_DIR}/irccd-api-plugin.3
+		${man_SOURCE_DIR}/irccd-api-rule.3
+		${man_SOURCE_DIR}/irccd-api-server.3
+		${man_SOURCE_DIR}/irccd-api-system.3
+		${man_SOURCE_DIR}/irccd-api-timer.3
+		${man_SOURCE_DIR}/irccd-api-unicode.3
+		${man_SOURCE_DIR}/irccd-api-util.3
+		${man_SOURCE_DIR}/irccd-api.3
+	)
+endif ()
+
 set(
 	MAN5
 	${man_SOURCE_DIR}/irccd.conf.5
@@ -53,17 +68,17 @@
 )
 
 foreach (m ${MAN1})
-	install(FILES ${m} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+	man(${m} man1)
 endforeach ()
 
 foreach (m ${MAN3})
-	install(FILES ${m} DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
+	man(${m} man3)
 endforeach ()
 
 foreach (m ${MAN5})
-	install(FILES ${m} DESTINATION ${CMAKE_INSTALL_MANDIR}/man5)
+	man(${m} man5)
 endforeach ()
 
 foreach (m ${MAN7})
-	install(FILES ${m} DESTINATION ${CMAKE_INSTALL_MANDIR}/man7)
+	man(${m} man7)
 endforeach ()
--- a/man/irccd-api.3	Wed Feb 17 19:33:00 2021 +0100
+++ b/man/irccd-api.3	Wed Feb 17 19:45:00 2021 +0100
@@ -65,6 +65,25 @@
 .Em optional
 in square brackets means it may not exist on your platform. A quick check in
 Javascript will let you test its presence.
+.Pp
+An example of plugin can be found at
+.Pa @CMAKE_INSTALL_FULL_DATADIR@/irccd/sample-plugin.js
+.\" INFO
+.Sh INFO
+The global
+.Vt info
+object in the plugin can contain the following strings which identifies the
+plugin information:
+.Bl -tag
+.It Vt license
+Plugin license.
+.It Vt version
+Arbitraty version.
+.It Vt author
+Author.
+.It Vt summary
+A short description about the plugin.
+.El
 .\" EVENTS
 .Sh EVENTS
 The following is a list of events that Javascript plugins support. All functions
--- a/plugins/ask/ask.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/ask/ask.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "ask",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "Crazy module for asking a medium",
--- a/plugins/auth/auth.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/auth/auth.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "auth",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "Generic plugin to authenticate to services",
--- a/plugins/hangman/hangman.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/hangman/hangman.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "hangman",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "A hangman game for IRC",
--- a/plugins/history/history.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/history/history.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "history",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "track nickname's history",
--- a/plugins/joke/joke.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/joke/joke.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "joke",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "display some jokes",
--- a/plugins/logger/logger.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/logger/logger.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "logger",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "A plugin to log everything",
--- a/plugins/plugin/plugin.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/plugin/plugin.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "plugin",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "A plugin to inspect plugins",
--- a/plugins/roulette/roulette.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/roulette/roulette.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "roulette",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "A russian roulette for IRC",
--- a/plugins/tictactoe/tictactoe.js	Wed Feb 17 19:33:00 2021 +0100
+++ b/plugins/tictactoe/tictactoe.js	Wed Feb 17 19:45:00 2021 +0100
@@ -18,7 +18,6 @@
 
 // Plugin information.
 info = {
-	name: "tictactoe",
 	author: "David Demelier <markand@malikania.fr>",
 	license: "ISC",
 	summary: "A tictactoe game for IRC",