changeset 916:e0de249c3378 stable-3

misc: merge from default
author David Demelier <markand@malikania.fr>
date Fri, 03 Jul 2020 11:34:15 +0200
parents 081fe7608403 (current diff) ffb59515fde5 (diff)
children 91d8ded8719b 378dc1a023f0
files
diffstat 400 files changed, 2951 insertions(+), 390 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES.md	Sun Oct 06 09:20:04 2019 +0200
+++ b/CHANGES.md	Fri Jul 03 11:34:15 2020 +0200
@@ -1,6 +1,14 @@
 IRC Client Daemon CHANGES
 =========================
 
+irccd current
+----------------------
+
+irccd:
+
+- Added a new hook system. Hooks consist of an alternative approach to plugins
+  to extend irccd in any language (#2342).
+
 irccd 3.0.3 2019-10-06
 ----------------------
 
--- a/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/LICENSE.md	Sun Oct 06 09:20:04 2019 +0200
+++ b/LICENSE.md	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 IRC Client Daemon ISC LICENSE
 =============================
 
-Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+Copyright (c) 2013-2020 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
--- a/cmake/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/IrccdOptions.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/IrccdOptions.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdOptions.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/IrccdPackage.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/IrccdPackage.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CPackConfing.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/IrccdSystem.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/IrccdSystem.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # Config.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/IrccdVersion.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/IrccdVersion.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/check/PutTime.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/check/PutTime.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/export/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/export/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/export/irccd-config.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/export/irccd-config.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/function/IrccdDefineExecutable.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdDefineExecutable.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdDefineExecutable.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/function/IrccdDefineLibrary.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdDefineLibrary.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdDefineLibrary.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/function/IrccdDefineMan.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdDefineMan.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdDefineMan.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/function/IrccdDefinePlugin.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdDefinePlugin.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdDefinePlugin.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/function/IrccdDefineTest.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdDefineTest.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdDefineTest.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/function/IrccdIndentMessage.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdIndentMessage.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdIndentMessage.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2016-2020 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
--- a/cmake/function/IrccdInstallDependencies.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdInstallDependencies.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2016-2020 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
--- a/cmake/function/IrccdSetGlobal.cmake	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/IrccdSetGlobal.cmake	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # IrccdSetGlobal.cmake -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/cmake/function/dependencies.cmake.in	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/function/dependencies.cmake.in	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2016-2020 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
--- a/cmake/internal/sysconfig.hpp.in	Sun Oct 06 09:20:04 2019 +0200
+++ b/cmake/internal/sysconfig.hpp.in	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * sysconfig.hpp -- configuration for irccd
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/doc/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/doc/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/doc/doxygen/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/doc/doxygen/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/doc/doxygen/modules.dox	Sun Oct 06 09:20:04 2019 +0200
+++ b/doc/doxygen/modules.dox	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * modules.cpp -- doxygen modules page
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/doc/doxygen/pages.dox	Sun Oct 06 09:20:04 2019 +0200
+++ b/doc/doxygen/pages.dox	Fri Jul 03 11:34:15 2020 +0200
@@ -2,7 +2,7 @@
 /*
  * pages.cpp -- doxygen related pages
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/doc/examples/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/doc/examples/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
@@ -36,6 +36,11 @@
 	DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}
 )
 
+install(
+	FILES ${examples_SOURCE_DIR}/sample-hook.sh
+	DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples
+)
+
 irccd_set_global(CPACK_COMPONENT_EXAMPLES_HIDDEN On)
 irccd_set_global(CPACK_COMPONENT_EXAMPLES_DESCRIPTION "Install examples of configuration files")
 irccd_set_global(CPACK_COMPONENT_EXAMPLES_GROUP "Documentation")
--- a/doc/examples/irccd.conf.sample	Sun Oct 06 09:20:04 2019 +0200
+++ b/doc/examples/irccd.conf.sample	Fri Jul 03 11:34:15 2020 +0200
@@ -152,3 +152,10 @@
 #
 # [templates.hangman]
 # win = "you win!"
+
+# Section hooks:
+#    This sections lets you define hooks that are executed each time an IRC
+#    event arrives.
+#
+# [hooks]
+# mail = "/path/to/mail.py"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/examples/sample-hook.sh	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,130 @@
+#!/bin/sh
+#
+# sample-hook.sh -- a sample hook in shell script
+#
+# Copyright (c) 2013-2020 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.
+#
+
+onConnect()
+{
+	echo "event:   connect"
+	echo "server:  $2"
+}
+
+onDisconnect()
+{
+	echo "event:   disconnect"
+	echo "server:  $2"
+}
+
+onInvite()
+{
+	echo "event:   invite"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "target:  $5"
+}
+
+onJoin()
+{
+	echo "event:   join"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+}
+
+onKick()
+{
+	echo "event:   kick"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "target:  $5"
+	echo "reason:  $6"
+}
+
+onMessage()
+{
+	echo "event:   message"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "message: $5"
+}
+
+onMe()
+{
+	echo "event:   me"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "message: $5"
+}
+
+onMode()
+{
+	echo "event:   mode"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "mode:    $5"
+	echo "limit:   $6"
+	echo "user:    $7"
+	echo "mask:    $8"
+}
+
+onNick()
+{
+	echo "event:   nick"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "nick:    $4"
+}
+
+onNotice()
+{
+	echo "event:   notice"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "message: $5"
+}
+
+onPart()
+{
+	echo "event:   part"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "reason:  $5"
+}
+
+onTopic()
+{
+	echo "event:   topic"
+	echo "server:  $2"
+	echo "origin:  $3"
+	echo "channel: $4"
+	echo "topic:   $5"
+}
+
+#
+# Call the appropriate function with the same name as the event and pass
+# arguments.
+#
+# Please keep quotes between $@ as some arguments are quoted (like messages).
+#
+$1 "$@"
--- a/extern/duktape/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/extern/duktape/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for duktape
 #
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2016-2020 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
--- a/extern/json/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/extern/json/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/irccd-test/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccd-test/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/irccd-test/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccd-test/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- irccd-test main file
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/irccd/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccd/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/irccd/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccd/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- irccd main file
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/irccdctl/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccdctl/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/irccdctl/alias.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccdctl/alias.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * alias.cpp -- create irccdctl aliases
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/irccdctl/alias.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccdctl/alias.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * alias.hpp -- create irccdctl aliases
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/irccdctl/cli.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccdctl/cli.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * cli.cpp -- command line for irccdctl
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -224,6 +224,9 @@
 // {{{ cli
 
 const std::vector<cli::constructor> cli::registry{
+	bind<hook_add_cli>(),
+	bind<hook_list_cli>(),
+	bind<hook_remove_cli>(),
 	bind<plugin_config_cli>(),
 	bind<plugin_info_cli>(),
 	bind<plugin_list_cli>(),
@@ -281,6 +284,74 @@
 
 // }}}
 
+// {{{ hook_add_cli
+
+auto hook_add_cli::get_name() const noexcept -> std::string_view
+{
+	return "hook-add";
+}
+
+void hook_add_cli::exec(ctl::controller& ctl, const std::vector<std::string>& argv)
+{
+	if (argv.size() < 2U)
+		throw std::invalid_argument("hook-add requires 2 arguments");
+
+	request(ctl, nlohmann::json::object({
+		{ "command",    "hook-add"              },
+		{ "id",         argv[0]                 },
+		{ "path",       argv[1]                 }
+	}));
+}
+
+// }}}
+
+// {{{ hook_list_cli
+
+auto hook_list_cli::get_name() const noexcept -> std::string_view
+{
+	return "hook-list";
+}
+
+void hook_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&)
+{
+	request(ctl, {{ "command", "hook-list" }}, [] (auto result) {
+		for (const auto& obj : result["list"]) {
+			if (!obj.is_object())
+				continue;
+
+			const deserializer document(obj);
+
+			std::cout << std::setw(16) << std::left;
+			std::cout << document.get<std::string>("id").value_or("(unknown)");
+			std::cout << " ";
+			std::cout << document.get<std::string>("path").value_or("(unknown)");
+			std::cout << std::endl;
+		}
+	});
+}
+
+// }}}
+
+// {{{ hook_remove_cli
+
+auto hook_remove_cli::get_name() const noexcept -> std::string_view
+{
+	return "hook-remove";
+}
+
+void hook_remove_cli::exec(ctl::controller& ctl, const std::vector<std::string>& argv)
+{
+	if (argv.size() < 1U)
+		throw std::invalid_argument("hook-remove requires 1 argument");
+
+	request(ctl, nlohmann::json::object({
+		{ "command",    "hook-remove"   },
+		{ "id",         argv[0]         },
+	}));
+}
+
+// }}}
+
 // {{{ plugin_config_cli
 
 void plugin_config_cli::set(ctl::controller& ctl, const std::vector<std::string>&args)
--- a/irccdctl/cli.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccdctl/cli.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * cli.hpp -- command line for irccdctl
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -105,6 +105,66 @@
 
 // }}}
 
+// {{{ hook_add_cli
+
+/**
+ * \brief Implementation of irccdctl hook-add.
+ */
+class hook_add_cli : public cli {
+public:
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
+
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+};
+
+// }}}
+
+// {{{ hook_list_cli
+
+/**
+ * \brief Implementation of irccdctl hook-list.
+ */
+class hook_list_cli : public cli {
+public:
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
+
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+};
+
+// }}}
+
+// {{{ hook_remove_cli
+
+/**
+ * \brief Implementation of irccdctl hook-remove.
+ */
+class hook_remove_cli : public cli {
+public:
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
+
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+};
+
+// }}}
+
 // {{{ plugin_config_cli
 
 /**
--- a/irccdctl/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/irccdctl/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- irccd controller main
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -72,7 +72,10 @@
 [[noreturn]]
 void usage()
 {
-	std::cerr << "usage: irccdctl plugin-config id [variable] [value]\n";
+	std::cerr << "usage: irccdctl hook-add id path\n";
+	std::cerr << "       irccdctl hook-list\n";
+	std::cerr << "       irccdctl hook-remove id\n";
+	std::cerr << "       irccdctl plugin-config id [variable] [value]\n";
 	std::cerr << "       irccdctl plugin-info id\n";
 	std::cerr << "       irccdctl plugin-list\n";
 	std::cerr << "       irccdctl plugin-load name\n";
--- a/libirccd-ctl/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-ctl/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/libirccd-ctl/irccd/ctl.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-ctl/irccd/ctl.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * ctl.hpp -- libirccd-ctl convenience header
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-ctl/irccd/ctl/controller.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-ctl/irccd/ctl/controller.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * controller.cpp -- main irccdctl interface
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -22,15 +22,17 @@
 #include <irccd/json_util.hpp>
 
 #include <irccd/daemon/bot.hpp>
-#include <irccd/daemon/server.hpp>
+#include <irccd/daemon/hook.hpp>
 #include <irccd/daemon/plugin.hpp>
 #include <irccd/daemon/rule.hpp>
+#include <irccd/daemon/server.hpp>
 
 #include "controller.hpp"
 
 using irccd::json_util::deserializer;
 
 using irccd::daemon::bot_error;
+using irccd::daemon::hook_error;
 using irccd::daemon::plugin_error;
 using irccd::daemon::rule_error;
 using irccd::daemon::server_error;
@@ -138,6 +140,8 @@
 				code = make_error_code(static_cast<plugin_error::error>(*e));
 			else if (*c == "rule")
 				code = make_error_code(static_cast<rule_error::error>(*e));
+			else if (*c == "hook")
+				code = make_error_code(static_cast<hook_error::error>(*e));
 		}
 
 		handler(std::move(code), std::move(msg));
--- a/libirccd-ctl/irccd/ctl/controller.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-ctl/irccd/ctl/controller.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * controller.hpp -- main irccdctl interface
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
@@ -25,6 +25,10 @@
 	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/bot.hpp
 	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/dynlib_plugin.cpp
 	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/dynlib_plugin.hpp
+	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/hook.cpp
+	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/hook.hpp
+	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/hook_service.cpp
+	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/hook_service.hpp
 	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/irc.cpp
 	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/irc.hpp
 	${libirccd-daemon_SOURCE_DIR}/irccd/daemon/logger.cpp
--- a/libirccd-daemon/irccd/daemon.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * daemon.hpp -- libirccd-daemon convenience header
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -28,6 +28,8 @@
 
 #include "daemon/bot.hpp"
 #include "daemon/dynlib_plugin.hpp"
+#include "daemon/hook.hpp"
+#include "daemon/hook_service.hpp"
 #include "daemon/irc.hpp"
 #include "daemon/logger.hpp"
 #include "daemon/plugin.hpp"
--- a/libirccd-daemon/irccd/daemon/bot.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/bot.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * bot.cpp -- main bot class
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -26,6 +26,7 @@
 #include <irccd/system.hpp>
 
 #include "bot.hpp"
+#include "hook_service.hpp"
 #include "logger.hpp"
 #include "plugin_service.hpp"
 #include "rule_service.hpp"
@@ -185,10 +186,25 @@
 	sink_->set_filter(*filter_);
 }
 
+void bot::load_hooks()
+{
+	const auto sc = config_.get("hooks");
+
+	for (const auto& opt : sc) {
+		if (!string_util::is_identifier(opt.get_key()))
+			throw hook_error(hook_error::invalid_identifier, opt.get_key(), "");
+		if (opt.get_value().empty())
+			throw hook_error(hook_error::invalid_path, opt.get_key(), "");
+
+		hook_service_->add(hook(opt.get_key(), opt.get_value()));
+	}
+}
+
 bot::bot(boost::asio::io_service& service, std::string config)
 	: config_(std::move(config))
 	, service_(service)
 	, sink_(std::make_unique<logger::console_sink>())
+	, hook_service_(std::make_unique<hook_service>(*this))
 	, server_service_(std::make_unique<server_service>(*this))
 	, tpt_service_(std::make_unique<transport_service>(*this))
 	, rule_service_(std::make_unique<rule_service>(*this))
@@ -228,6 +244,11 @@
 	return *sink_;
 }
 
+auto bot::get_hooks() noexcept -> hook_service&
+{
+	return *hook_service_;
+}
+
 auto bot::get_servers() noexcept -> server_service&
 {
 	return *server_service_;
@@ -267,6 +288,7 @@
 	// [logs] and [templates] sections.
 	load_logs();
 	load_templates();
+	load_hooks();
 
 	if (!loaded_)
 		sink_->info("irccd", "") << "loading configuration from " << config_.get_path() << std::endl;
--- a/libirccd-daemon/irccd/daemon/bot.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/bot.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * bot.hpp -- main bot class
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -47,6 +47,7 @@
 
 } // !logger
 
+class hook_service;
 class plugin_service;
 class rule_service;
 class server_service;
@@ -71,6 +72,7 @@
 	std::unique_ptr<logger::filter> filter_;
 
 	// Services.
+	std::unique_ptr<hook_service> hook_service_;
 	std::unique_ptr<server_service> server_service_;
 	std::unique_ptr<transport_service> tpt_service_;
 	std::unique_ptr<rule_service> rule_service_;
@@ -88,6 +90,7 @@
 	void load_logs_syslog();
 	void load_logs();
 	void load_templates();
+	void load_hooks();
 
 public:
 	/**
@@ -158,6 +161,13 @@
 	void set_log(std::unique_ptr<logger::sink> sink) noexcept;
 
 	/**
+	 * Access the hook service.
+	 *
+	 * \return the service
+	 */
+	auto get_hooks() noexcept -> hook_service&;
+
+	/**
 	 * Access the server service.
 	 *
 	 * \return the service
--- a/libirccd-daemon/irccd/daemon/dynlib_plugin.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/dynlib_plugin.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * dynlib_plugin.cpp -- native plugin implementation
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -30,8 +30,6 @@
 
 #if BOOST_OS_WINDOWS
 #	define DYNLIB_EXTENSION ".dll"
-#elif BOOST_OS_MACOS
-#	define DYNLIB_EXTENSION ".dylib"
 #else
 #	define DYNLIB_EXTENSION ".so"
 #endif
--- a/libirccd-daemon/irccd/daemon/dynlib_plugin.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/dynlib_plugin.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * dynlib_plugin.hpp -- native plugin implementation
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-daemon/irccd/daemon/hook.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,292 @@
+/*
+ * hook.cpp -- irccd hooks
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#include <cassert>
+#include <initializer_list>
+#include <string_view>
+#include <sstream>
+
+#include <boost/process.hpp>
+
+#include <irccd/string_util.hpp>
+
+#include "bot.hpp"
+#include "hook.hpp"
+#include "logger.hpp"
+#include "server.hpp"
+
+using boost::process::args;
+using boost::process::child;
+using boost::process::exe;
+using boost::process::ipstream;
+using boost::process::std_out;
+
+using std::getline;
+using std::initializer_list;
+using std::ostringstream;
+using std::string;
+using std::string_view;
+
+using irccd::string_util::is_identifier;
+
+namespace irccd::daemon {
+
+namespace {
+
+void exec(bot& bot, hook& hook, initializer_list<string> arguments)
+{
+	try {
+		ipstream is;
+		child c(exe = hook.get_path(), args = arguments, std_out > is);
+
+		// Log everything that is output by the hook.
+		for (string line; c.running() && getline(is, line); )
+			bot.get_log().info(hook) << line << std::endl;
+
+		c.wait();
+	} catch (const std::exception& ex) {
+		throw hook_error(hook_error::exec_error, hook.get_id(), ex.what());
+	}
+}
+
+} // !namespace
+
+hook::hook(std::string id, std::string path) noexcept
+	: id_(std::move(id))
+	, path_(std::move(path))
+{
+	assert(is_identifier(id_));
+	assert(!path_.empty());
+}
+
+auto hook::get_id() const noexcept -> const std::string&
+{
+	return id_;
+}
+
+auto hook::get_path() const noexcept -> const std::string&
+{
+	return path_;
+}
+
+void hook::handle_connect(bot& bot, const connect_event& event)
+{
+	exec(bot, *this, {"onConnect", event.server->get_id()});
+}
+
+void hook::handle_disconnect(bot& bot, const disconnect_event& event)
+{
+	exec(bot, *this, {"onDisconnect", event.server->get_id()});
+}
+
+void hook::handle_invite(bot& bot, const invite_event& event)
+{
+	exec(bot, *this, {
+		"onInvite",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.nickname
+	});
+}
+
+void hook::handle_join(bot& bot, const join_event& event)
+{
+	exec(bot, *this, {
+		"onJoin",
+		event.server->get_id(),
+		event.origin,
+		event.channel
+	});
+}
+
+void hook::handle_kick(bot& bot, const kick_event& event)
+{
+	exec(bot, *this, {
+		"onKick",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.target,
+		event.reason
+	});
+}
+
+void hook::handle_message(bot& bot, const message_event& event)
+{
+	exec(bot, *this, {
+		"onMessage",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.message
+	});
+}
+
+void hook::handle_me(bot& bot, const me_event& event)
+{
+	exec(bot, *this, {
+		"onMe",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.message
+	});
+}
+
+void hook::handle_mode(bot& bot, const mode_event& event)
+{
+	exec(bot, *this, {
+		"onMode",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.mode,
+		event.limit,
+		event.user,
+		event.mask
+	});
+}
+
+void hook::handle_nick(bot& bot, const nick_event& event)
+{
+	exec(bot, *this, {
+		"onNick",
+		event.server->get_id(),
+		event.origin,
+		event.nickname
+	});
+}
+
+void hook::handle_notice(bot& bot, const notice_event& event)
+{
+	exec(bot, *this, {
+		"onNotice",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.message
+	});
+}
+
+void hook::handle_part(bot& bot, const part_event& event)
+{
+	exec(bot, *this, {
+		"onPart",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.reason
+	});
+}
+
+void hook::handle_topic(bot& bot, const topic_event& event)
+{
+	exec(bot, *this, {
+		"onTopic",
+		event.server->get_id(),
+		event.origin,
+		event.channel,
+		event.topic
+	});
+}
+
+auto operator==(const hook& h1, const hook& h2) noexcept -> bool
+{
+	return h1.get_id() == h2.get_id() &&
+	       h1.get_path() == h2.get_path();
+}
+
+auto operator!=(const hook& h1, const hook& h2) noexcept -> bool
+{
+	return !(h1 == h2);
+}
+
+hook_error::hook_error(error errc, std::string id, std::string message)
+	: system_error(make_error_code(errc))
+	, id_(std::move(id))
+	, message_(std::move(message))
+{
+}
+
+auto hook_error::get_id() const noexcept -> const std::string&
+{
+	return id_;
+}
+
+auto hook_error::get_message() const noexcept -> const std::string&
+{
+	return message_;
+}
+
+auto hook_error::what() const noexcept -> const char*
+{
+	return message_.c_str();
+}
+
+auto hook_category() -> const std::error_category&
+{
+	static const class category : public std::error_category {
+	public:
+		auto name() const noexcept -> const char* override
+		{
+			return "hook";
+		}
+
+		auto message(int e) const -> std::string override
+		{
+			switch (static_cast<hook_error::error>(e)) {
+			case hook_error::not_found:
+				return "hook not found";
+			case hook_error::invalid_path:
+				return "invalid path given";
+			case hook_error::invalid_identifier:
+				return "invalid hook identifier";
+			case hook_error::exec_error:
+				return "hook exec error";
+			case hook_error::already_exists:
+				return "hook already exists";
+			default:
+				return "no error";
+			}
+		}
+	} category;
+
+	return category;
+}
+
+auto make_error_code(hook_error::error e) -> std::error_code
+{
+	return { static_cast<int>(e), hook_category() };
+}
+
+namespace logger {
+
+auto type_traits<hook>::get_category(const hook&) -> std::string_view
+{
+	return "hook";
+}
+
+auto type_traits<hook>::get_component(const hook& hook) -> std::string_view
+{
+	return hook.get_id();
+}
+
+} // !logger
+
+} // !irccd::daemon
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-daemon/irccd/daemon/hook.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,331 @@
+/*
+ * hook.hpp -- irccd hooks
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#ifndef IRCCD_DAEMON_HOOK_HPP
+#define IRCCD_DAEMON_HOOK_HPP
+
+/**
+ * \file irccd/daemon/hook.hpp
+ * \brief irccd hooks
+ */
+
+#include <irccd/sysconfig.hpp>
+
+#include <string>
+#include <string_view>
+#include <system_error>
+#include <type_traits>
+
+namespace irccd::daemon {
+
+class bot;
+
+struct connect_event;
+struct disconnect_event;
+struct invite_event;
+struct join_event;
+struct kick_event;
+struct me_event;
+struct message_event;
+struct mode_event;
+struct nick_event;
+struct notice_event;
+struct part_event;
+struct topic_event;
+
+/**
+ * \brief Event hook.
+ *
+ * A hook is a lightweight alternative to plugins, it is executed once an event
+ * arrive and can be written in any language.
+ */
+class hook {
+private:
+	std::string id_;
+	std::string path_;
+
+public:
+	/**
+	 * Construct a hook.
+	 *
+	 * This does not check the presence of the script.
+	 *
+	 * \pre id must be a valid identifier
+	 * \pre path must not be empty
+	 * \param id the hook id
+	 * \param path the path to the hook
+	 */
+	hook(std::string id, std::string path) noexcept;
+
+	/**
+	 * Get user unique id.
+	 *
+	 * \return the hook id
+	 */
+	auto get_id() const noexcept -> const std::string&;
+
+	/**
+	 * Get path to the hook.
+	 *
+	 * \return the path
+	 */
+	auto get_path() const noexcept -> const std::string&;
+
+	/**
+	 * Similar interface to plugin::handle_connect.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_connect(bot& bot, const connect_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_disconnect.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_disconnect(bot& bot, const disconnect_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_invite.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_invite(bot& bot, const invite_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_join.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_join(bot& bot, const join_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_kick.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_kick(bot& bot, const kick_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_message.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_message(bot& bot, const message_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_me.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_me(bot& bot, const me_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_mode.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_mode(bot& bot, const mode_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_nick.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_nick(bot& bot, const nick_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_notice.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_notice(bot& bot, const notice_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_part.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_part(bot& bot, const part_event& event);
+
+	/**
+	 * Similar interface to plugin::handle_topic.
+	 *
+	 * \param bot the irccd instance
+	 * \param event the event
+	 */
+	void handle_topic(bot& bot, const topic_event& event);
+};
+
+/**
+ * Equality operator.
+ *
+ * \param lhs the left side
+ * \param rhs the right side
+ * \return true if they equals
+ */
+auto operator==(const hook& lhs, const hook& rhs) noexcept -> bool;
+
+/**
+ * Equality operator.
+ *
+ * \param lhs the left side
+ * \param rhs the right side
+ * \return false if they equals
+ */
+auto operator!=(const hook& lhs, const hook& rhs) noexcept -> bool;
+
+/**
+ * \brief Hook error.
+ */
+class hook_error : public std::system_error {
+public:
+	/**
+	 * \brief Plugin related errors.
+	 */
+	enum error {
+		//!< No error.
+		no_error = 0,
+
+		//!< The specified identifier is invalid.
+		invalid_identifier,
+
+		//!< The specified hook is not found.
+		not_found,
+
+		//!< Invalid path given.
+		invalid_path,
+
+		//!< The hook was unable to run the function.
+		exec_error,
+
+		//!< The hook is already loaded.
+		already_exists,
+	};
+
+private:
+	std::string id_;
+	std::string message_;
+
+public:
+	/**
+	 * Constructor.
+	 *
+	 * \param code the error code
+	 * \param id the hook id
+	 * \param message the optional message (e.g. error from hook)
+	 */
+	hook_error(error code, std::string id, std::string message = "");
+
+	/**
+	 * Get the hook identifier.
+	 *
+	 * \return the id
+	 */
+	auto get_id() const noexcept -> const std::string&;
+
+	/**
+	 * Get the additional message.
+	 *
+	 * \return the message
+	 */
+	auto get_message() const noexcept -> const std::string&;
+
+	/**
+	 * Get message appropriate for use with logger.
+	 *
+	 * \return the error message
+	 */
+	auto what() const noexcept -> const char* override;
+};
+
+/**
+ * Get the hook error category singleton.
+ *
+ * \return the singleton
+ */
+auto hook_category() -> const std::error_category&;
+
+/**
+ * Create a std::error_code from hook_error::error enum.
+ *
+ * \param e the error code
+ * \return the error code
+ */
+auto make_error_code(hook_error::error e) -> std::error_code;
+
+namespace logger {
+
+template <typename T>
+struct type_traits;
+
+/**
+ * \brief Specialization for hook.
+ * \ingroup daemon-loggers-traits
+ */
+template <>
+struct type_traits<hook> {
+	/**
+	 * Get 'hook' category.
+	 *
+	 * \param hook the hook
+	 * \return hook
+	 */
+	static auto get_category(const hook& hook) -> std::string_view;
+
+	/**
+	 * Get the hook id.
+	 *
+	 * \param hook the hook
+	 * \return the hook id
+	 */
+	static auto get_component(const hook& hook) -> std::string_view;
+};
+
+} // !logger
+
+} // !irccd::daemon
+
+/**
+ * \cond IRCCD_HIDDEN_SYMBOLS
+ */
+
+namespace std {
+
+template <>
+struct is_error_code_enum<irccd::daemon::hook_error::error> : public std::true_type {
+};
+
+} // !std
+
+/**
+ * \endcond
+ */
+
+#endif // !IRCCD_DAEMON_PLUGIN_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-daemon/irccd/daemon/hook_service.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,66 @@
+/*
+ * hook_service.cpp -- irccd hook service
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#include <algorithm>
+
+#include "hook_service.hpp"
+
+using std::find;
+using std::move;
+
+namespace irccd::daemon {
+
+hook_service::hook_service(bot& bot) noexcept
+	: bot_(bot)
+{
+}
+
+auto hook_service::has(const hook& hook) const noexcept -> bool
+{
+	return find(hooks_.begin(), hooks_.end(), hook) != hooks_.end();
+}
+
+void hook_service::add(hook hook)
+{
+	if (has(hook))
+		throw hook_error(hook_error::already_exists, hook.get_id(), "");
+
+	hooks_.push_back(move(hook));
+}
+
+void hook_service::remove(const hook& hook) noexcept
+{
+	hooks_.erase(std::remove(hooks_.begin(), hooks_.end(), hook), hooks_.end());
+}
+
+auto hook_service::list() const noexcept -> const hooks&
+{
+	return hooks_;
+}
+
+auto hook_service::list() noexcept -> hooks&
+{
+	return hooks_;
+}
+
+void hook_service::clear() noexcept
+{
+	hooks_.clear();
+}
+
+} // !irccd::daemon
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-daemon/irccd/daemon/hook_service.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,134 @@
+/*
+ * hook_service.hpp -- irccd hook service
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#ifndef IRCCD_DAEMON_HOOK_SERVICE_HPP
+#define IRCCD_DAEMON_HOOK_SERVICE_HPP
+
+/**
+ * \file irccd/daemon/hook_service.hpp
+ * \brief Irccd hook service.
+ */
+
+#include <functional>
+#include <vector>
+#include <utility>
+
+#include "bot.hpp"
+#include "hook.hpp"
+#include "logger.hpp"
+
+namespace irccd::daemon {
+
+class bot;
+
+/**
+ * \brief Irccd hook service.
+ */
+class hook_service {
+public:
+	/**
+	 * List of hooks.
+	 */
+	using hooks = std::vector<hook>;
+
+private:
+	bot& bot_;
+	hooks hooks_;
+
+public:
+	/**
+	 * Constructor.
+	 *
+	 * \param bot the bot
+	 */
+	hook_service(bot& bot) noexcept;
+
+	/**
+	 * Tells if a hook already exists.
+	 *
+	 * \param hook the hook to check
+	 * \return true if hook is already present
+	 */
+	auto has(const hook& hook) const noexcept -> bool;
+
+	/**
+	 * Add a new hook.
+	 *
+	 * \param hook the hook
+	 * \throw hook_error if the hook is already present
+	 */
+	void add(hook hook);
+
+	/**
+	 * Remove the specified hook.
+	 *
+	 * \param hook the hook to remove
+	 */
+	void remove(const hook& hook) noexcept;
+
+	/**
+	 * Get the list of hooks.
+	 *
+	 * \return the hooks
+	 */
+	auto list() const noexcept -> const hooks&;
+
+	/**
+	 * Overloaded function.
+	 *
+	 * \return the hooks
+	 */
+	auto list() noexcept -> hooks&;
+
+	/**
+	 * Remove all hooks.
+	 */
+	void clear() noexcept;
+
+	/**
+	 * Convenient function to call a hook member function for all hook
+	 * present in the list.
+	 *
+	 * \param func the function to call (e.g. hook::handle_connect)
+	 * \param args the arguments to the hook function
+	 * \throw hook_error on errors
+	 */
+	template <typename Func, typename... Args>
+	void dispatch(Func&& func, Args&&... args);
+};
+
+template <typename Func, typename... Args>
+void hook_service::dispatch(Func&& func, Args&&... args)
+{
+	using std::invoke;
+	using std::forward;
+	using std::exception;
+
+	for (auto& hook : hooks_) {
+		// Protect to avoid stopping all next hooks.
+		try {
+			invoke(forward<Func>(func), hook, bot_, forward<Args>(args)...);
+		} catch (const exception& ex) {
+			bot_.get_log().warning(hook) << ex.what() << std::endl;
+		}
+	}
+}
+
+} // !irccd::daemon
+
+#endif // !IRCCD_DAEMON_HOOK_SERVICE_HPP
--- a/libirccd-daemon/irccd/daemon/irc.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/irc.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * irc.cpp -- low level IRC functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/irc.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/irc.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * irc.hpp -- low level IRC functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/logger.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/logger.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * logger.cpp -- irccd logging
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/logger.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/logger.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * logger.hpp -- irccd logging
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/plugin.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/plugin.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin.cpp -- irccd JavaScript plugin interface
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/plugin.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/plugin.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin.hpp -- irccd JavaScript plugin interface
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/plugin_service.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/plugin_service.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin_service.cpp -- plugin service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/plugin_service.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/plugin_service.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin_service.hpp -- plugin service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/rule.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/rule.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * rule.cpp -- rule for server and channels
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/rule.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/rule.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * rule.hpp -- rule for server and channels
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/rule_service.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/rule_service.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * rule_service.cpp -- rule service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/rule_service.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/rule_service.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * rule_service.hpp -- rule service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/rule_util.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/rule_util.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * rule_util.cpp -- rule utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/rule_util.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/rule_util.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * rule_util.hpp -- rule utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/server.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/server.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server.cpp -- an IRC server
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/server.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/server.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server.hpp -- an IRC server
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/server_service.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/server_service.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server_service.cpp -- server service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -22,6 +22,7 @@
 #include <irccd/string_util.hpp>
 
 #include "bot.hpp"
+#include "hook_service.hpp"
 #include "logger.hpp"
 #include "plugin_service.hpp"
 #include "rule_service.hpp"
@@ -102,6 +103,7 @@
 		{ "event",      "onConnect"             },
 		{ "server",     ev.server->get_id()     }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_connect, ev);
 
 	dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
 		[=] (plugin&) -> std::string {
@@ -120,6 +122,7 @@
 		{ "event",      "onDisconnect"          },
 		{ "server",     ev.server->get_id()     }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_disconnect, ev);
 
 	dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
 		[=] (plugin&) -> std::string {
@@ -144,6 +147,7 @@
 		{ "origin",     ev.origin               },
 		{ "channel",    ev.channel              }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_invite, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, ev.channel,
 		[=] (plugin&) -> std::string {
@@ -167,6 +171,7 @@
 		{ "origin",     ev.origin               },
 		{ "channel",    ev.channel              }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_join, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, ev.channel,
 		[=] (plugin&) -> std::string {
@@ -194,6 +199,7 @@
 		{ "target",     ev.target               },
 		{ "reason",     ev.reason               }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_kick, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, ev.channel,
 		[=] (plugin&) -> std::string {
@@ -219,6 +225,7 @@
 		{ "channel",    ev.channel              },
 		{ "message",    ev.message              }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_message, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, ev.channel,
 		[=] (plugin& plugin) -> std::string {
@@ -260,6 +267,7 @@
 		{ "target",     ev.channel              },
 		{ "message",    ev.message              }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_me, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, ev.channel,
 		[=] (plugin&) -> std::string {
@@ -291,6 +299,7 @@
 		{ "user",       ev.user                 },
 		{ "mask",       ev.mask                 }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_mode, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
 		[=] (plugin &) -> std::string {
@@ -342,6 +351,7 @@
 		{ "origin",     ev.origin               },
 		{ "nickname",   ev.nickname             }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_nick, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
 		[=] (plugin&) -> std::string {
@@ -367,6 +377,7 @@
 		{ "channel",    ev.channel              },
 		{ "message",    ev.message              }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_notice, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
 		[=] (plugin&) -> std::string {
@@ -392,6 +403,7 @@
 		{ "channel",    ev.channel              },
 		{ "reason",     ev.reason               }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_part, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, ev.channel,
 		[=] (plugin&) -> std::string {
@@ -417,6 +429,7 @@
 		{ "channel",    ev.channel              },
 		{ "topic",      ev.topic                }
 	}));
+	bot_.get_hooks().dispatch(&hook::handle_topic, ev);
 
 	dispatch(ev.server->get_id(), ev.origin, ev.channel,
 		[=] (plugin&) -> std::string {
--- a/libirccd-daemon/irccd/daemon/server_service.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/server_service.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server_service.hpp -- server service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/server_util.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/server_util.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server_util.cpp -- server utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/server_util.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/server_util.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server_util.hpp -- server utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_client.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_client.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_client.cpp -- server side transport clients
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_client.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_client.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_client.hpp -- server side transport clients
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_command.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_command.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * command.cpp -- remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -21,6 +21,7 @@
 #include <irccd/string_util.hpp>
 
 #include "bot.hpp"
+#include "hook_service.hpp"
 #include "plugin.hpp"
 #include "plugin_service.hpp"
 #include "rule.hpp"
@@ -93,6 +94,9 @@
 auto transport_command::registry() noexcept -> const std::vector<constructor>&
 {
 	static const std::vector<transport_command::constructor> list{
+		bind<hook_add_command>(),
+		bind<hook_list_command>(),
+		bind<hook_remove_command>(),
 		bind<plugin_config_command>(),
 		bind<plugin_info_command>(),
 		bind<plugin_list_command>(),
@@ -126,6 +130,84 @@
 	return list;
 }
 
+// {{{ hook_add_command
+
+auto hook_add_command::get_name() const noexcept -> std::string_view
+{
+	return "hook-add";
+}
+
+void hook_add_command::exec(bot& bot, transport_client& client, const document& args)
+{
+	const auto id = args.get<std::string>("id");
+	const auto path = args.get<std::string>("path");
+
+	if (!id || !string_util::is_identifier(*id))
+		throw hook_error(hook_error::invalid_identifier, id.value_or(""));
+	if (!path || path->empty())
+		throw hook_error(hook_error::invalid_path, *id, path.value_or(""));
+
+	// The add function may throws already_exists
+	bot.get_hooks().add(hook(*id, *path));
+	client.success("hook-add");
+}
+
+// }}}
+
+// {{{ hook_list_command
+
+auto hook_list_command::get_name() const noexcept -> std::string_view
+{
+	return "hook-list";
+}
+
+void hook_list_command::exec(bot& bot, transport_client& client, const document&)
+{
+	auto array = nlohmann::json::array();
+
+	for (const auto& hook : bot.get_hooks().list())
+		array.push_back(nlohmann::json::object({
+			{ "id",         hook.get_id()   },
+			{ "path",       hook.get_path() }
+		}));
+
+	client.write({
+		{ "command",    "hook-list"             },
+		{ "list",       std::move(array)        }
+	});
+}
+
+// }}}
+
+// {{{ hook_remove_command
+
+auto hook_remove_command::get_name() const noexcept -> std::string_view
+{
+	return "hook-remove";
+}
+
+void hook_remove_command::exec(bot& bot, transport_client& client, const document& args)
+{
+	const auto id = args.get<std::string>("id");
+
+	if (!id || !string_util::is_identifier(*id))
+		throw hook_error(hook_error::invalid_identifier, id.value_or(""));
+
+	// We don't use hook_service::remove because it never fails.
+	auto& hooks = bot.get_hooks().list();
+	auto it = std::find_if(hooks.begin(), hooks.end(), [&] (const auto& hook) {
+		return hook.get_id() == *id;
+	});
+
+	if (it == hooks.end())
+		throw hook_error(hook_error::not_found, *id);
+
+	hooks.erase(it);
+	client.success("hook-remove");
+}
+
+// }}}
+
 // {{{ plugin_config_command
 
 auto plugin_config_command::get_name() const noexcept -> std::string_view
@@ -268,7 +350,7 @@
 
 void rule_add_command::exec(bot& bot, transport_client& client, const document& args)
 {
-	const auto index = args.optional<std::size_t>("index", bot.get_rules().list().size());
+	const auto index = args.optional<std::uint64_t>("index", bot.get_rules().list().size());
 
 	if (!index || *index > bot.get_rules().list().size())
 		throw rule_error(rule_error::error::invalid_index);
@@ -299,7 +381,7 @@
 		}
 	};
 
-	const auto index = args.get<std::size_t>("index");
+	const auto index = args.get<std::uint64_t>("index");
 
 	if (!index)
 		throw rule_error(rule_error::invalid_index);
@@ -343,7 +425,7 @@
 
 void rule_info_command::exec(bot& bot, transport_client& client, const document& args)
 {
-	const auto index = args.get<std::size_t>("index");
+	const auto index = args.get<std::uint64_t>("index");
 
 	if (!index)
 		throw rule_error(rule_error::invalid_index);
@@ -387,8 +469,8 @@
 
 void rule_move_command::exec(bot& bot, transport_client& client, const document& args)
 {
-	const auto from = args.get<std::size_t>("from");
-	const auto to = args.get<std::size_t>("to");
+	const auto from = args.get<std::uint64_t>("from");
+	const auto to = args.get<std::uint64_t>("to");
 
 	if (!from || !to)
 		throw rule_error(rule_error::invalid_index);
@@ -450,7 +532,7 @@
 
 void rule_remove_command::exec(bot& bot, transport_client& client, const document& args)
 {
-	const auto index = args.get<std::size_t>("index");
+	const auto index = args.get<std::uint64_t>("index");
 
 	if (!index || *index >= bot.get_rules().list().size())
 		throw rule_error(rule_error::invalid_index);
--- a/libirccd-daemon/irccd/daemon/transport_command.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_command.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_command.hpp -- remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -91,6 +91,80 @@
 
 // }}}
 
+// {{{ hook_add_command
+
+/**
+ * \brief Implementation of hook-add transport command.
+ * \ingroup daemon-transport-commands
+ *
+ * Replies:
+ *
+ * - hook_error::already_exists
+ * - hook_error::invalid_identifier
+ * - hook_error::invalid_path
+ */
+class hook_add_command : public transport_command {
+public:
+	/**
+	 * \copydoc transport_command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
+
+	/**
+	 * \copydoc transport_command::exec
+	 */
+	void exec(bot& bot, transport_client& client, const document& args) override;
+};
+
+// }}}
+
+// {{{ hook_list_command
+
+/**
+ * \brief Implementation of hook-list transport command.
+ * \ingroup daemon-transport-commands
+ */
+class hook_list_command : public transport_command {
+public:
+	/**
+	 * \copydoc transport_command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
+
+	/**
+	 * \copydoc transport_command::exec
+	 */
+	void exec(bot& bot, transport_client& client, const document& args) override;
+};
+
+// }}}
+
+// {{{ hook_remove_command
+
+/**
+ * \brief Implementation of hook-remove transport command.
+ * \ingroup daemon-transport-commands
+ *
+ * Replies:
+ *
+ * - hook_error::invalid_identifier
+ * - hook_error::not_found
+ */
+class hook_remove_command : public transport_command {
+public:
+	/**
+	 * \copydoc transport_command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
+
+	/**
+	 * \copydoc transport_command::exec
+	 */
+	void exec(bot& bot, transport_client& client, const document& args) override;
+};
+
+// }}}
+
 // {{{ plugin_config_command
 
 /**
--- a/libirccd-daemon/irccd/daemon/transport_server.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_server.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_server.cpp -- server side transports
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_server.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_server.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_server.hpp -- server side transports
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_service.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_service.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_service.cpp -- transport service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_service.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_service.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_service.hpp -- transport service
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_util.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_util.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_util.cpp -- transport utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-daemon/irccd/daemon/transport_util.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-daemon/irccd/daemon/transport_util.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * transport_util.hpp -- transport utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * js.hpp -- libirccd-js convenience header
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * api.cpp -- Javascript API module
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * api.hpp -- Javascript API module
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/chrono_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/chrono_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * chrono_api.cpp -- Irccd.Chrono API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/chrono_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/chrono_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * chrono_api.hpp -- Irccd.Chrono API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/directory_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/directory_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * directory_api.cpp -- Irccd.Directory API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/directory_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/directory_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * directory_api.hpp -- Irccd.Directory API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/duk.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/duk.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * duk.cpp -- miscellaneous Duktape extras
  *
- * Copyright (c) 2017-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2017-2020 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
--- a/libirccd-js/irccd/js/duk.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/duk.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * duk.hpp -- miscellaneous Duktape extras
  *
- * Copyright (c) 2017-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2017-2020 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
--- a/libirccd-js/irccd/js/file_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/file_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * file_api.cpp -- Irccd.File API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/file_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/file_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * file_api.hpp -- Irccd.File API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/irccd_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/irccd_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * irccd_api.cpp -- Irccd API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/irccd_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/irccd_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * irccd_api.hpp -- Irccd API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/logger_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/logger_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * logger_api.cpp -- Irccd.Logger API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/logger_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/logger_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * logger_api.hpp -- Irccd.Logger API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/plugin.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/plugin.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin.cpp -- Javascript plugins for irccd
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/plugin.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/plugin.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin.hpp -- JavaScript plugins for irccd
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/plugin_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/plugin_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin_api.cpp -- Irccd.Plugin API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/plugin_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/plugin_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin_api.hpp -- Irccd.Plugin API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/server_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/server_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server_api.cpp -- Irccd.Server API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/server_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/server_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * server_api.hpp -- Irccd.Server API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/system_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/system_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * system_api.cpp -- Irccd.System API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/system_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/system_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * system_api.hpp -- Irccd.System API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/timer_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/timer_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * timer_api.cpp -- Irccd.timer API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/timer_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/timer_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * timer_api.hpp -- Irccd.Timer API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/unicode.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/unicode.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * unicode.cpp -- UTF-8 to UTF-32 conversions and various operations
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/unicode.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/unicode.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * unicode.hpp -- UTF-8 to UTF-32 conversions and various operations
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/unicode_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/unicode_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * unicode_api.cpp -- Irccd.Unicode API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/unicode_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/unicode_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * unicode_api.hpp -- Irccd.Unicode API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/util_api.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/util_api.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * util_api.cpp -- Irccd.Util API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-js/irccd/js/util_api.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-js/irccd/js/util_api.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * util_api.hpp -- Irccd.Util API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * test.hpp -- libirccd-test convenience header
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/broken_plugin.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/broken_plugin.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * broken_plugin.cpp -- broken plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/broken_plugin.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/broken_plugin.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * broken_plugin.hpp -- broken plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/cli_fixture.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/cli_fixture.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * cli_fixture.cpp -- test fixture for irccdctl frontend
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/cli_fixture.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/cli_fixture.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * cli_fixture.hpp -- test fixture for irccdctl frontend
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -31,6 +31,7 @@
 #include <boost/asio.hpp>
 
 #include <irccd/daemon/bot.hpp>
+#include <irccd/daemon/hook_service.hpp>
 #include <irccd/daemon/plugin_service.hpp>
 #include <irccd/daemon/rule_service.hpp>
 #include <irccd/daemon/server_service.hpp>
--- a/libirccd-test/irccd/test/command_fixture.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/command_fixture.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * command_fixture.cpp -- test fixture helper for transport commands
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/command_fixture.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/command_fixture.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * command_fixture.hpp -- test fixture helper for transport commands
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
@@ -28,6 +28,7 @@
 #include <irccd/daemon/rule_service.hpp>
 #include <irccd/daemon/server_service.hpp>
 #include <irccd/daemon/transport_client.hpp>
+#include <irccd/daemon/hook_service.hpp>
 
 #include "irccd_fixture.hpp"
 #include "mock_server.hpp"
@@ -58,6 +59,7 @@
 	 * \brief The fake transport_client stream.
 	 */
 	std::shared_ptr<mock_stream> stream_;
+
 	/**
 	 * \brief Client sending request.
 	 */
--- a/libirccd-test/irccd/test/debug_server.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/debug_server.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * debug_server.cpp -- server which prints everything in the console
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/debug_server.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/debug_server.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * debug_server.hpp -- server which prints everything in the console
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/irccd_fixture.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/irccd_fixture.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * irccd_fixture.cpp -- test fixture for irccd
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/irccd_fixture.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/irccd_fixture.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * irccd_fixture.hpp -- test fixture for irccd
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/js_fixture.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/js_fixture.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * js.cpp -- test fixture helper for Javascript modules
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/js_fixture.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/js_fixture.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * js_fixture.hpp -- test fixture helper for Javascript modules
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/js_plugin_fixture.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/js_plugin_fixture.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin_fixture.cpp -- test fixture helper for Javascript plugins
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/js_plugin_fixture.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/js_plugin_fixture.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * js_plugin_fixture.hpp -- test fixture helper for Javascript plugins
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock.cpp -- keep track of function invocations
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock.hpp -- keep track of function invocations
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock_plugin.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock_plugin.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock_plugin.cpp -- mock plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock_plugin.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock_plugin.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock_plugin.hpp -- mock plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock_server.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock_server.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock_server.cpp -- mock server
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock_server.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock_server.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock_server.hpp -- mock server
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock_stream.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock_stream.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock_stream.cpp -- mock stream
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/mock_stream.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/mock_stream.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * mock_stream.hpp -- mock stream
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/test_plugin_loader.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/test_plugin_loader.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * test_plugin_loader.cpp -- special plugin loader for unit tests
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd-test/irccd/test/test_plugin_loader.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd-test/irccd/test/test_plugin_loader.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * test_plugin_loader.hpp -- special plugin loader for unit tests
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/libirccd/irccd/acceptor.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/acceptor.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * acceptor.hpp -- abstract stream acceptor interface
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/config.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/config.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * config.cpp -- irccd configuration loader
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/config.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/config.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * config.hpp -- irccd configuration loader
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/connector.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/connector.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * connector.hpp -- abstract connection interface
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/core.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/core.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * core.hpp -- libirccd convenience header
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/fs_util.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/fs_util.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * fs_util.cpp -- filesystem utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/fs_util.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/fs_util.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * fs_util.hpp -- filesystem utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/ini.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/ini.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * ini.cpp -- extended .ini file parser
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/ini.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/ini.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * ini.hpp -- extended .ini file parser
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/ini_util.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/ini_util.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * ini_util.hpp -- ini utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/json_util.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/json_util.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * json_util.cpp -- utilities for JSON
  *
- * Copyright (c) 2018-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2018-2020 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
--- a/libirccd/irccd/json_util.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/json_util.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * json_util.hpp -- utilities for JSON
  *
- * Copyright (c) 2018-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2018-2020 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
--- a/libirccd/irccd/options.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/options.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * options.hpp -- C++ similar interface to getopt(3)
  *
- * Copyright (c) 2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2020 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
--- a/libirccd/irccd/stream.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/stream.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * stream.hpp -- abstract stream interface
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/string_util.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/string_util.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * string_util.cpp -- string utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/string_util.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/string_util.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * string_util.hpp -- string utilities
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/system.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/system.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * system.cpp -- platform dependent functions for system inspection
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/system.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/system.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * system.hpp -- platform dependent functions for system inspection
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/libirccd/irccd/xdg.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/libirccd/irccd/xdg.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * xdg.hpp -- XDG directory specifications
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/man/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/man/irccd-api.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccd-api.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/man/irccd-ipc.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccd-ipc.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/man/irccd-templates.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccd-templates.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/man/irccd-test.1	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccd-test.1	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/man/irccd.1	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccd.1	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
@@ -61,7 +61,7 @@
 .Sh PLUGINS
 The
 .Nm
-program can runs plugins once IRC events are received. For example, if someone
+program can run plugins once IRC events are received. For example, if someone
 sends you a private message plugins will be invoked with that event. Both native
 plugins written in C++ and Javascript are supported (if enabled at compile
 time).
@@ -173,6 +173,38 @@
 See additional documentation in their own manual page in the form
 .Xr irccd-plugin-name 7
 where name is the actual plugin name.
+.\" HOOKS
+.Sh HOOKS
+Hooks are a different and more lightweight approach to plugins, they are
+executed upon incoming events and spawned each time a new event arrives.
+.Pp
+In contrast to plugins, differences are:
+.Pp
+.Bl -bullet -compact
+.It
+Hooks can not be filtered with rules.
+.It
+Hooks does not support all events. These events are not supported:
+.Em onLoad , onUnload , onReload , onCommand , onNames , onWhois .
+.It
+Hooks can be written in any language.
+.It
+Execution may be slower since scripting languages require to fire up the
+interpreter each time a new event is available.
+.El
+.Pp
+Each hook will receive as positional argument the event name (similar to plugin
+events) and the event arguments.
+.Pp
+An example of hook in shell script is available as
+.Pa @CMAKE_INSTALL_FULL_DOCDIR@/examples/sample-hook.sh
+file.
+.Pp
+See also the section
+.Va [hooks]
+in
+.Xr irccd.conf 5
+manual page to enable hooks.
 .\" TRANSPORTS
 .Sh TRANSPORTS
 The daemon can be controlled at runtime using the dedicated
--- a/man/irccd.conf.5	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccd.conf.5	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
@@ -208,6 +208,7 @@
 The section is redefinable per plugin basis using the
 .Va [paths.<plugin>]
 syntax.
+.\" [plugins]
 .Ss plugins
 This section is used to load plugins.
 .Pp
@@ -216,6 +217,10 @@
 path (including the .js extension).
 .Pp
 Warning: remember to add an empty string for searching plugins.
+.\" [hooks]
+.Ss hooks
+This sections stores every hooks in key-value pairs. The option key denotes the
+hook id and the value must be a path to the actual hook file.
 .\" [transport]
 .Ss transport
 This section defines transports that are used to communicate through clients
@@ -355,6 +360,11 @@
 channels = "#staff"
 plugins = "reboot"
 action = accept
+
+# Example of hooks
+# This create an hook named "mail" with the given path.
+[hooks]
+mail = "/path/to/mail.py"
 .Ed
 .\" SEE ALSO
 .Sh SEE ALSO
--- a/man/irccdctl.1	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccdctl.1	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
@@ -22,8 +22,20 @@
 .Nd irccd controller agent
 .\" SYNOPSIS
 .Sh SYNOPSIS
+.\" hook-add
 .Nm
+.Cm hook-add
+.Ar id
+.Ar path
+.\" hook-list
+.Nm
+.Cm hook-list
+.\" hook-remove
+.Nm
+.Cm hook-remove
+.Ar id
 .\" plugin-config
+.Nm
 .Cm plugin-config
 .Ar id
 .Op Ar variable
@@ -223,6 +235,20 @@
 .\" COMMANDS
 .Sh COMMANDS
 .Bl -tag -width xxxxxxxx-yyyyyyyyy
+.\" hook-add
+.It Cm hook-add
+Add a new hook with
+.Ar id
+as unique identifier and
+.Ar path
+as local path (on the machine where irccd is running).
+.\" hook-list
+.It Cm hook-list
+List active hooks.
+.\" hook-remove
+.It Cm hook-remove
+Remove a hook with identifier
+.Ar id .
 .\" plugin-config
 .It Cm plugin-config
 Manipulate a configuration variable for the plugin specified by
--- a/man/irccdctl.conf.5	Sun Oct 06 09:20:04 2019 +0200
+++ b/man/irccdctl.conf.5	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/ask/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/ask/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/ask/ask.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/ask/ask.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/ask/ask.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/ask/ask.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * ask.js -- crazy module for asking a medium
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/auth/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/auth/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/auth/auth.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/auth/auth.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/auth/auth.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/auth/auth.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * auth.js -- generic plugin to authenticate to services
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/hangman/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/hangman/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/hangman/hangman.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/hangman/hangman.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/hangman/hangman.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/hangman/hangman.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * hangman.js -- hangman game for IRC
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/history/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/history/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/history/history.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/history/history.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/history/history.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/history/history.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * history.js -- track nickname's history
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/joke/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/joke/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/joke/joke.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/joke/joke.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/joke/joke.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/joke/joke.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * joke.js -- display some jokes
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/links/links.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/links.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/links/links.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/links.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * links.cpp -- links plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/links.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/links.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * links.hpp -- links plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/requester.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/requester.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * requester.cpp -- convenient HTTP get requester
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/requester.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/requester.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * requester.hpp -- convenient HTTP get requester
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/scope_exit.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/scope_exit.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * scope_exit.cpp -- do something on scope exit
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/scope_exit.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/scope_exit.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * scope_exit.hpp -- do something on scope exit
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/uri.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/uri.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * uri.cpp -- simple uriparser based parser
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/links/uri.hpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/links/uri.hpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * uri.hpp -- simple uriparser based parser
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/logger/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/logger/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/logger/logger.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/logger/logger.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/logger/logger.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/logger/logger.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * logger.js -- plugin to log everything
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/plugin/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/plugin/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/plugin/plugin.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/plugin/plugin.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/plugin/plugin.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/plugin/plugin.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * plugin.js -- plugin inspector
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/roulette/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/roulette/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/roulette/roulette.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/roulette/roulette.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/roulette/roulette.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/roulette/roulette.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * roulette.js -- russian roulette game
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/plugins/tictactoe/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/tictactoe/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/plugins/tictactoe/tictactoe.7	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/tictactoe/tictactoe.7	Fri Jul 03 11:34:15 2020 +0200
@@ -1,5 +1,5 @@
 .\"
-.\" Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+.\" Copyright (c) 2013-2020 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
--- a/plugins/tictactoe/tictactoe.js	Sun Oct 06 09:20:04 2019 +0200
+++ b/plugins/tictactoe/tictactoe.js	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * tictactoe.js -- tictactoe game for IRC
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/systemd/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/systemd/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
@@ -25,6 +25,10 @@
 	add_subdirectory(cli-plugin-unload)
 endif ()
 
+add_subdirectory(cli-hook-add)
+add_subdirectory(cli-hook-list)
+add_subdirectory(cli-hook-remove)
+
 add_subdirectory(cli-rule-add)
 add_subdirectory(cli-rule-edit)
 add_subdirectory(cli-rule-info)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-hook-add/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,25 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2020 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.
+#
+
+irccd_define_test(
+	NAME cli-hook-add
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	DEPENDS irccd irccdctl
+	FLAGS IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccdctl>"
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-hook-add/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,117 @@
+/*
+ * main.cpp -- test irccdctl hook-add
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl hook-add"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_fixture.hpp>
+
+using namespace irccd::test;
+
+using irccd::daemon::hook;
+
+namespace irccd {
+
+namespace {
+
+class hook_add_fixture : public cli_fixture {
+public:
+	hook_add_fixture()
+		: cli_fixture(IRCCDCTL_EXECUTABLE)
+	{
+	}
+};
+
+BOOST_FIXTURE_TEST_SUITE(hook_add_suite, hook_add_fixture)
+
+BOOST_AUTO_TEST_CASE(basic)
+{
+	start();
+
+	// true -> /bin/true
+	{
+		const auto [code, out, err] = exec({ "hook-add", "true", "/bin/true" });
+
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
+
+	// false -> /bin/false
+	{
+		const auto [code, out, err] = exec({ "hook-add", "false", "/bin/false" });
+
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
+
+	BOOST_TEST(bot_.get_hooks().list().size() == 2U);
+	BOOST_TEST(bot_.get_hooks().list()[0].get_id() == "true");
+	BOOST_TEST(bot_.get_hooks().list()[0].get_path() == "/bin/true");
+	BOOST_TEST(bot_.get_hooks().list()[1].get_id() == "false");
+	BOOST_TEST(bot_.get_hooks().list()[1].get_path() == "/bin/false");
+}
+
+BOOST_AUTO_TEST_SUITE(errors)
+
+BOOST_AUTO_TEST_CASE(invalid_identifier)
+{
+	start();
+
+	const auto [code, out, err] = exec({ "hook-add", "#@#@", "/bin/true" });
+
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid hook identifier");
+}
+
+BOOST_AUTO_TEST_CASE(invalid_path)
+{
+	start();
+
+	const auto [code, out, err] = exec({ "hook-add", "true", "\"\"" });
+
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid path given");
+}
+
+BOOST_AUTO_TEST_CASE(already_exists)
+{
+	bot_.get_hooks().add(hook("true", "/bin/true"));
+
+	start();
+
+	const auto [code, out, err] = exec({ "hook-add", "true", "/bin/true" });
+
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: hook already exists");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-hook-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,25 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2020 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.
+#
+
+irccd_define_test(
+	NAME cli-hook-list
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	DEPENDS irccd irccdctl
+	FLAGS IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccdctl>"
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-hook-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,61 @@
+/*
+ * main.cpp -- test irccdctl hook-list
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl hook-list"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_fixture.hpp>
+
+using namespace irccd::test;
+
+using irccd::daemon::hook;
+
+namespace irccd {
+
+namespace {
+
+class hook_list_fixture : public cli_fixture {
+public:
+	hook_list_fixture()
+		: cli_fixture(IRCCDCTL_EXECUTABLE)
+	{
+		bot_.get_hooks().add(hook("true", "/bin/true"));
+		bot_.get_hooks().add(hook("false", "/bin/false"));
+	}
+};
+
+BOOST_FIXTURE_TEST_SUITE(hook_list_suite, hook_list_fixture)
+
+BOOST_AUTO_TEST_CASE(basic)
+{
+	start();
+
+	const auto [code, out, err] = exec({ "hook-list" });
+
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 2U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0] == "true             /bin/true");
+	BOOST_TEST(out[1] == "false            /bin/false");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-hook-remove/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,25 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2020 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.
+#
+
+irccd_define_test(
+	NAME cli-hook-remove
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	DEPENDS irccd irccdctl
+	FLAGS IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccdctl>"
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-hook-remove/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,90 @@
+/*
+ * main.cpp -- test irccdctl hook-remove
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl hook-remove"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_fixture.hpp>
+
+using namespace irccd::test;
+
+using irccd::daemon::hook;
+
+namespace irccd {
+
+namespace {
+
+class hook_remove_fixture : public cli_fixture {
+public:
+	hook_remove_fixture()
+		: cli_fixture(IRCCDCTL_EXECUTABLE)
+	{
+		bot_.get_hooks().add(hook("true", "/bin/true"));
+		bot_.get_hooks().add(hook("false", "/bin/false"));
+	}
+};
+
+BOOST_FIXTURE_TEST_SUITE(hook_remove_suite, hook_remove_fixture)
+
+BOOST_AUTO_TEST_CASE(basic)
+{
+	start();
+
+	const auto [code, out, err] = exec({ "hook-remove", "false" });
+
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(bot_.get_hooks().list().size() == 1U);
+	BOOST_TEST(bot_.get_hooks().list()[0].get_id() == "true");
+	BOOST_TEST(bot_.get_hooks().list()[0].get_path() == "/bin/true");
+}
+
+BOOST_AUTO_TEST_SUITE(errors)
+
+BOOST_AUTO_TEST_CASE(invalid_identifier)
+{
+	start();
+
+	const auto [code, out, err] = exec({ "hook-remove", "#@#@" });
+
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid hook identifier");
+}
+
+BOOST_AUTO_TEST_CASE(not_found)
+{
+	start();
+
+	const auto [code, out, err] = exec({ "hook-remove", "nonexistent" });
+
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: hook not found");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd
--- a/tests/src/irccdctl/cli-plugin-config/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-config/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-config/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-config/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl plugin-config
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-info/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-info/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-info/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-info/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl plugin-info
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-list/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-list/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl plugin-list
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-load/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-load/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-load/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-load/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl plugin-load
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-reload/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-reload/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-reload/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-reload/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl plugin-reload
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-unload/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-unload/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-plugin-unload/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-plugin-unload/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl plugin-unload
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-add/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-add/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-add/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-add/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl rule-add
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-edit/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-edit/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-edit/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-edit/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl rule-edit
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-info/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-info/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-info/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-info/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl rule-info
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-list/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-list/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl rule-list
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-move/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-move/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-move/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-move/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl rule-move
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-remove/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-remove/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-rule-remove/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-rule-remove/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl rule-remove
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-disconnect/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-disconnect/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-disconnect/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-disconnect/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-disconnect
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-info/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-info/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-info/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-info/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-info
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-invite/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-invite/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-invite/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-invite/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-invite
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-join/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-join/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-join/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-join/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-join
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-kick/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-kick/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-kick/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-kick/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-kick
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-list/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-list/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-list
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-me/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-me/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-me/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-me/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-me
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-message/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-message/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-message/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-message/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-message
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-mode/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-mode/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-mode/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-mode/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-mode
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-nick/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-nick/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-nick/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-nick/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-nick
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-notice/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-notice/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-notice/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-notice/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-notice
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-part/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-part/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-part/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-part/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-part
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-reconnect/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-reconnect/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-reconnect/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-reconnect/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-reconnect
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-topic/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-topic/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/irccdctl/cli-server-topic/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/irccdctl/cli-server-topic/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irccdctl server-topic
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
@@ -16,18 +16,24 @@
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #
 
+add_subdirectory(command-hook-add)
+add_subdirectory(command-hook-list)
+add_subdirectory(command-hook-remove)
+
 add_subdirectory(command-plugin-config)
 add_subdirectory(command-plugin-info)
 add_subdirectory(command-plugin-list)
 add_subdirectory(command-plugin-load)
 add_subdirectory(command-plugin-reload)
 add_subdirectory(command-plugin-unload)
+
 add_subdirectory(command-rule-add)
 add_subdirectory(command-rule-edit)
 add_subdirectory(command-rule-info)
 add_subdirectory(command-rule-list)
 add_subdirectory(command-rule-move)
 add_subdirectory(command-rule-remove)
+
 add_subdirectory(command-server-connect)
 add_subdirectory(command-server-disconnect)
 add_subdirectory(command-server-info)
@@ -45,12 +51,13 @@
 add_subdirectory(command-server-topic)
 
 add_subdirectory(dynlib-plugin)
+add_subdirectory(hook)
 add_subdirectory(irc)
 add_subdirectory(logger)
 add_subdirectory(plugin-service)
 add_subdirectory(rule-service)
 add_subdirectory(rule-util)
 add_subdirectory(server)
+add_subdirectory(server-service)
 add_subdirectory(server-util)
-add_subdirectory(server-service)
 add_subdirectory(transports)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/command-hook-add/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,23 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2020 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.
+#
+
+irccd_define_test(
+	NAME command-hook-add
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/command-hook-add/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,106 @@
+/*
+ * main.cpp -- test hook-add remote command
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#define BOOST_TEST_MODULE "hook-add"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/command_fixture.hpp>
+
+using std::string;
+
+using irccd::daemon::hook;
+using irccd::daemon::hook_error;
+
+namespace irccd {
+
+namespace {
+
+BOOST_FIXTURE_TEST_SUITE(hook_add_fixture_suite, test::command_fixture)
+
+BOOST_AUTO_TEST_CASE(basic)
+{
+	request({
+		{ "command",    "hook-add"      },
+		{ "id",         "true"          },
+		{ "path",       "/bin/true"     }
+	});
+	request({
+		{ "command",    "hook-add"      },
+		{ "id",         "false"         },
+		{ "path",       "/bin/false"    }
+	});
+
+	BOOST_TEST(bot_.get_hooks().list().size() == 2U);
+	BOOST_TEST(bot_.get_hooks().list()[0].get_id() == "true");
+	BOOST_TEST(bot_.get_hooks().list()[0].get_path() == "/bin/true");
+	BOOST_TEST(bot_.get_hooks().list()[1].get_id() == "false");
+	BOOST_TEST(bot_.get_hooks().list()[1].get_path() == "/bin/false");
+}
+
+BOOST_AUTO_TEST_SUITE(errors)
+
+BOOST_AUTO_TEST_CASE(invalid_identifier)
+{
+	const auto json = request({
+		{ "command",    "hook-add"      },
+		{ "id"    ,     "#@#@"          }
+	});
+
+	BOOST_TEST(json.size() == 4U);
+	BOOST_TEST(json["command"].get<string>() == "hook-add");
+	BOOST_TEST(json["error"].get<int>() == hook_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<string>() == "hook");
+}
+
+BOOST_AUTO_TEST_CASE(invalid_path)
+{
+	const auto json = request({
+		{ "command",    "hook-add"      },
+		{ "id",         "true"          },
+		{ "path",       1234            }
+	});
+
+	BOOST_TEST(json.size() == 4U);
+	BOOST_TEST(json["command"].get<string>() == "hook-add");
+	BOOST_TEST(json["error"].get<int>() == hook_error::invalid_path);
+	BOOST_TEST(json["errorCategory"].get<string>() == "hook");
+}
+
+BOOST_AUTO_TEST_CASE(already_exists)
+{
+	bot_.get_hooks().add(hook("true", "/bin/true"));
+
+	const auto json = request({
+		{ "command",    "hook-add"      },
+		{ "id",         "true"          },
+		{ "path",       "/bin/true"     }
+	});
+
+	BOOST_TEST(json.size() == 4U);
+	BOOST_TEST(json["command"].get<string>() == "hook-add");
+	BOOST_TEST(json["error"].get<int>() == hook_error::already_exists);
+	BOOST_TEST(json["errorCategory"].get<string>() == "hook");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/command-hook-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,23 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2020 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.
+#
+
+irccd_define_test(
+	NAME command-hook-list
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/command-hook-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,54 @@
+/*
+ * main.cpp -- test hook-list remote command
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#define BOOST_TEST_MODULE "hook-list"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/command_fixture.hpp>
+
+using std::string;
+
+using irccd::daemon::hook;
+
+namespace irccd {
+
+namespace {
+
+BOOST_FIXTURE_TEST_SUITE(hook_list_fixture_suite, test::command_fixture)
+
+BOOST_AUTO_TEST_CASE(basic)
+{
+	bot_.get_hooks().add(hook("true", "/bin/true"));
+	bot_.get_hooks().add(hook("false", "/bin/false"));
+
+	const auto json = request({{"command", "hook-list"}});
+
+	BOOST_TEST(json.size() == 2U);
+	BOOST_TEST(json["command"].get<string>() == "hook-list");
+	BOOST_TEST(json["list"].size() == 2U);
+	BOOST_TEST(json["list"][0]["id"].get<string>() == "true");
+	BOOST_TEST(json["list"][0]["path"].get<string>() == "/bin/true");
+	BOOST_TEST(json["list"][1]["id"].get<string>() == "false");
+	BOOST_TEST(json["list"][1]["path"].get<string>() == "/bin/false");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/command-hook-remove/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,23 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2020 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.
+#
+
+irccd_define_test(
+	NAME command-hook-remove
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/command-hook-remove/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,94 @@
+/*
+ * main.cpp -- test hook-remove remote command
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#define BOOST_TEST_MODULE "hook-remove"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/command_fixture.hpp>
+
+using std::string;
+
+using irccd::daemon::hook;
+using irccd::daemon::hook_error;
+
+namespace irccd {
+
+namespace {
+
+BOOST_FIXTURE_TEST_SUITE(hook_remove_fixture_suite, test::command_fixture)
+
+BOOST_AUTO_TEST_CASE(basic)
+{
+	bot_.get_hooks().add(hook("true", "/bin/true"));
+	bot_.get_hooks().add(hook("false", "/bin/false"));
+
+	const auto json = request({
+		{ "command",    "hook-remove"   },
+		{ "id",         "false"         },
+	});
+
+	BOOST_TEST(json.size() == 1U);
+	BOOST_TEST(json["command"].get<string>() == "hook-remove");
+	BOOST_TEST(bot_.get_hooks().list().size() == 1U);
+	BOOST_TEST(bot_.get_hooks().list()[0].get_id() == "true");
+	BOOST_TEST(bot_.get_hooks().list()[0].get_path() == "/bin/true");
+}
+
+BOOST_AUTO_TEST_SUITE(errors)
+
+BOOST_AUTO_TEST_CASE(invalid_identifier)
+{
+	const auto json = request({
+		{ "command",    "hook-remove"   },
+		{ "action",     "#@#@"          }
+	});
+
+	BOOST_TEST(json.size() == 4U);
+	BOOST_TEST(json["command"].get<string>() == "hook-remove");
+	BOOST_TEST(json["error"].get<int>() == hook_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<string>() == "hook");
+}
+
+BOOST_AUTO_TEST_CASE(not_found)
+{
+	request({
+		{ "command",    "hook-add"      },
+		{ "id",         "true"          },
+		{ "path",       "/bin/true"     }
+	});
+
+	stream_->clear();
+
+	const auto json = request({
+		{ "command",    "hook-remove"   },
+		{ "id",         "nonexistent"   },
+	});
+
+	BOOST_TEST(json.size() == 4U);
+	BOOST_TEST(json["command"].get<string>() == "hook-remove");
+	BOOST_TEST(json["error"].get<int>() == hook_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<string>() == "hook");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd
--- a/tests/src/libirccd-daemon/command-plugin-config/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-config/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-config/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-config/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin-config remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-info/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-info/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-info/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-info/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin-info remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-list/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-list/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin-list remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-load/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-load/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-load/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-load/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin-load remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-reload/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-reload/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-reload/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-reload/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin-reload remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-unload/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-unload/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-plugin-unload/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-plugin-unload/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin-unload remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-add/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-add/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-add/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-add/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule-add remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-edit/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-edit/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-edit/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-edit/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule-edit remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-info/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-info/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-info/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-info/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule-info remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-list/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-list/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule-list remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-move/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-move/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-move/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-move/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule-move remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-remove/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-remove/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-rule-remove/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-rule-remove/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule-remove remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-connect/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-connect/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-connect/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-connect/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-connect remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-disconnect/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-disconnect/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-disconnect/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-disconnect/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-disconnect remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-info/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-info/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-info/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-info/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-info remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-invite/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-invite/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-invite/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-invite/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-invite remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-join/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-join/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-join/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-join/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-join remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-kick/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-kick/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-kick/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-kick/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-kick remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-list/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-list/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-list/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-list/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-list remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-me/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-me/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-me/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-me/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-me remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-message/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-message/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-message/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-message/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-message remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-mode/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-mode/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-mode/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-mode/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-mode remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-nick/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-nick/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-nick/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-nick/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-nick remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-notice/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-notice/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-notice/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-notice/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-notice remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-part/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-part/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-part/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-part/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-part remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-reconnect/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-reconnect/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-reconnect/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-reconnect/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-reconnect remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-topic/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-topic/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/command-server-topic/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/command-server-topic/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server-topic remote command
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/dynlib-plugin/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/dynlib-plugin/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/dynlib-plugin/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/dynlib-plugin/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test dynlib_plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/dynlib-plugin/sample_plugin.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/dynlib-plugin/sample_plugin.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * sample_plugin.cpp -- basic exported plugin test
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/hook/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,48 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2020 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.
+#
+
+find_package(Boost REQUIRED QUIET)
+
+add_executable(sample-hook sample_hook.cpp)
+
+set_target_properties(
+	sample-hook
+	PROPERTIES
+		PREFIX ""
+		FOLDER "test"
+		RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+		LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+foreach (cfg ${CMAKE_CONFIGURATION_TYPES})
+	string(TOUPPER ${cfg} cfg)
+	set_target_properties(
+		sample-hook
+		PROPERTIES
+			RUNTIME_OUTPUT_DIRECTORY_${cfg} ${CMAKE_CURRENT_BINARY_DIR}
+			LIBRARY_OUTPUT_DIRECTORY_${cfg} ${CMAKE_CURRENT_BINARY_DIR}
+	)
+endforeach ()
+
+irccd_define_test(
+	NAME hook
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-test
+	DEPENDS sample-hook
+	FLAGS HOOK_FILE="$<TARGET_FILE:sample-hook>"
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/hook/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,272 @@
+/*
+ * main.cpp -- test hook functions
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#define BOOST_TEST_MODULE "hook"
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <vector>
+
+#include <irccd/daemon/bot.hpp>
+#include <irccd/daemon/hook.hpp>
+#include <irccd/daemon/logger.hpp>
+
+#include <irccd/test/mock_server.hpp>
+
+using std::string;
+using std::vector;
+using std::shared_ptr;
+using std::make_unique;
+using std::make_shared;
+
+using boost::asio::io_context;
+
+using irccd::daemon::logger::sink;
+
+using irccd::test::mock_server;
+
+namespace irccd::daemon {
+
+namespace {
+
+/*
+ * Since stdout/stderr from the hook is logger through the irccd's logger, we'll
+ * gonna store every message logged into it and compare if the values are
+ * appropriate.
+ */
+class memory_sink : public logger::sink {
+public:
+	using list = vector<string>;
+
+private:
+	list warning_;
+	list info_;
+
+public:
+	auto get_info() const noexcept -> const list&;
+	auto get_warning() const noexcept -> const list&;
+	void write_debug(const std::string& line) override;
+	void write_info(const std::string& line) override;
+	void write_warning(const std::string& line) override;
+};
+
+auto memory_sink::get_info() const noexcept -> const list&
+{
+	return info_;
+}
+
+auto memory_sink::get_warning() const noexcept -> const list&
+{
+	return warning_;
+}
+
+void memory_sink::write_debug(const std::string&)
+{
+}
+
+void memory_sink::write_info(const std::string& line)
+{
+	info_.push_back(line);
+}
+
+void memory_sink::write_warning(const std::string& line)
+{
+	warning_.push_back(line);
+}
+
+class hook_fixture {
+protected:
+	io_context io_;
+	bot bot_{io_};
+	hook hook_{"test", HOOK_FILE};
+	memory_sink* sink_{nullptr};
+	shared_ptr<mock_server> server_;
+
+public:
+	hook_fixture();
+};
+
+hook_fixture::hook_fixture()
+	: server_(make_shared<mock_server>(io_, "test"))
+{
+	auto sink = make_unique<memory_sink>();
+
+	sink_ = sink.get();
+	bot_.set_log(std::move(sink));
+	bot_.get_log().set_verbose(true);
+}
+
+BOOST_FIXTURE_TEST_SUITE(hook_fixture_suite, hook_fixture)
+
+BOOST_AUTO_TEST_CASE(connect)
+{
+	hook_.handle_connect(bot_, {server_});
+
+	BOOST_TEST(sink_->get_info().size() == 2U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onConnect");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+}
+
+BOOST_AUTO_TEST_CASE(disconnect)
+{
+	hook_.handle_disconnect(bot_, {server_});
+
+	BOOST_TEST(sink_->get_info().size() == 2U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onDisconnect");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+}
+
+BOOST_AUTO_TEST_CASE(invite)
+{
+	hook_.handle_invite(bot_, {server_, "jean", "#staff", "NiReaS"});
+
+	BOOST_TEST(sink_->get_info().size() == 5U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onInvite");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: target:  NiReaS");
+}
+
+BOOST_AUTO_TEST_CASE(join)
+{
+	hook_.handle_join(bot_, {server_, "jean", "#staff"});
+
+	BOOST_TEST(sink_->get_info().size() == 4U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onJoin");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff");
+}
+
+BOOST_AUTO_TEST_CASE(kick)
+{
+	hook_.handle_kick(bot_, {server_, "jean", "#staff", "NiReaS", "stop it"});
+
+	BOOST_TEST(sink_->get_info().size() == 6U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onKick");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: target:  NiReaS");
+	BOOST_TEST(sink_->get_info()[5] == "hook test: reason:  stop it");
+}
+
+BOOST_AUTO_TEST_CASE(message)
+{
+	hook_.handle_message(bot_, {server_, "jean", "#staff", "coucou tout le monde"});
+
+	BOOST_TEST(sink_->get_info().size() == 5U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onMessage");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: message: coucou tout le monde");
+}
+
+BOOST_AUTO_TEST_CASE(me)
+{
+	hook_.handle_me(bot_, {server_, "jean", "#staff", "coucou tout le monde"});
+
+	BOOST_TEST(sink_->get_info().size() == 5U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onMe");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: message: coucou tout le monde");
+}
+
+BOOST_AUTO_TEST_CASE(mode)
+{
+	hook_.handle_mode(bot_, {server_, "jean", "#staff", "+o", "franck", "abc", "xyz" });
+
+	BOOST_TEST(sink_->get_info().size() == 8U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onMode");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: mode:    +o");
+	BOOST_TEST(sink_->get_info()[5] == "hook test: limit:   franck");
+	BOOST_TEST(sink_->get_info()[6] == "hook test: user:    abc");
+	BOOST_TEST(sink_->get_info()[7] == "hook test: mask:    xyz");
+}
+
+BOOST_AUTO_TEST_CASE(nick)
+{
+	hook_.handle_nick(bot_, {server_, "jean", "doctor"});
+
+	BOOST_TEST(sink_->get_info().size() == 4U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onNick");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: nick:    doctor");
+}
+
+BOOST_AUTO_TEST_CASE(notice)
+{
+	hook_.handle_notice(bot_, {server_, "jean", "#staff", "coucou tout le monde"});
+
+	BOOST_TEST(sink_->get_info().size() == 5U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onNotice");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: message: coucou tout le monde");
+}
+
+BOOST_AUTO_TEST_CASE(part)
+{
+	hook_.handle_part(bot_, {server_, "jean", "#windows", "je n'aime pas ici"});
+
+	BOOST_TEST(sink_->get_info().size() == 5U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onPart");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #windows");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: reason:  je n'aime pas ici");
+}
+
+BOOST_AUTO_TEST_CASE(topic)
+{
+	hook_.handle_topic(bot_, {server_, "jean", "#windows", "attention Windows est un malware"});
+
+	BOOST_TEST(sink_->get_info().size() == 5U);
+	BOOST_TEST(sink_->get_warning().empty());
+	BOOST_TEST(sink_->get_info()[0] == "hook test: event:   onTopic");
+	BOOST_TEST(sink_->get_info()[1] == "hook test: server:  test");
+	BOOST_TEST(sink_->get_info()[2] == "hook test: origin:  jean");
+	BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #windows");
+	BOOST_TEST(sink_->get_info()[4] == "hook test: topic:   attention Windows est un malware");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd::daemon
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/hook/sample_hook.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -0,0 +1,177 @@
+/*
+ * sample_hook.cpp -- sample hook for unit tests
+ *
+ * Copyright (c) 2013-2020 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.
+ */
+
+#include <iostream>
+#include <functional>
+#include <string_view>
+#include <unordered_map>
+
+using std::function;
+using std::string_view;
+using std::unordered_map;
+using std::cerr;
+using std::cout;
+using std::endl;
+
+namespace {
+
+auto print(int argc, char** argv, int index) -> string_view
+{
+	return argc > index ? argv[index] : "";
+}
+
+void handle_onConnect(int argc, char** argv)
+{
+	cout << "event:   onConnect" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+}
+
+void handle_onDisconnect(int argc, char** argv)
+{
+	cout << "event:   onDisconnect" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+}
+
+void handle_onInvite(int argc, char** argv)
+{
+	cout << "event:   onInvite" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "target:  " << print(argc, argv, 3) << endl;
+}
+
+void handle_onJoin(int argc, char** argv)
+{
+	cout << "event:   onJoin" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+}
+
+void handle_onKick(int argc, char** argv)
+{
+	cout << "event:   onKick" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "target:  " << print(argc, argv, 3) << endl;
+	cout << "reason:  " << print(argc, argv, 4) << endl;
+}
+
+void handle_onMessage(int argc, char** argv)
+{
+	cout << "event:   onMessage" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "message: " << print(argc, argv, 3) << endl;
+}
+
+void handle_onMe(int argc, char** argv)
+{
+	cout << "event:   onMe" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "message: " << print(argc, argv, 3) << endl;
+}
+
+void handle_onMode(int argc, char** argv)
+{
+	cout << "event:   onMode" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "mode:    " << print(argc, argv, 3) << endl;
+	cout << "limit:   " << print(argc, argv, 4) << endl;
+	cout << "user:    " << print(argc, argv, 5) << endl;
+	cout << "mask:    " << print(argc, argv, 6) << endl;
+}
+
+void handle_onNick(int argc, char** argv)
+{
+	cout << "event:   onNick" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "nick:    " << print(argc, argv, 2) << endl;
+}
+
+void handle_onNotice(int argc, char** argv)
+{
+	cout << "event:   onNotice" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "message: " << print(argc, argv, 3) << endl;
+}
+
+void handle_onPart(int argc, char** argv)
+{
+	cout << "event:   onPart" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "reason:  " << print(argc, argv, 3) << endl;
+}
+
+void handle_onTopic(int argc, char** argv)
+{
+	cout << "event:   onTopic" << endl;
+	cout << "server:  " << print(argc, argv, 0) << endl;
+	cout << "origin:  " << print(argc, argv, 1) << endl;
+	cout << "channel: " << print(argc, argv, 2) << endl;
+	cout << "topic:   " << print(argc, argv, 3) << endl;
+}
+
+unordered_map<string_view, function<void (int, char**)>> handlers{
+	{ "onConnect",    handle_onConnect          },
+	{ "onDisconnect", handle_onDisconnect       },
+	{ "onInvite",     handle_onInvite           },
+	{ "onJoin",       handle_onJoin             },
+	{ "onKick",       handle_onKick             },
+	{ "onMessage",    handle_onMessage          },
+	{ "onMe",         handle_onMe               },
+	{ "onMode",       handle_onMode             },
+	{ "onNick",       handle_onNick             },
+	{ "onNotice",     handle_onNotice           },
+	{ "onPart",       handle_onPart             },
+	{ "onTopic",      handle_onTopic            }
+};
+
+} // !namespace
+
+int main(int argc, char** argv)
+{
+	--argc;
+	++argv;
+
+	if (argc == 0) {
+		cerr << "abort: no command given" << endl;
+		return 1;
+	}
+
+	const auto handler = handlers.find(argv[0]);
+
+	if (handler == handlers.end()) {
+		cerr << "abort: unknown message hook: " << argv[0] << endl;
+		return 1;
+	}
+
+	handler->second(--argc, ++argv);
+}
--- a/tests/src/libirccd-daemon/irc/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/irc/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/irc/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/irc/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test irc functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/logger/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/logger/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/logger/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/logger/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test logger functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/plugin-service/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/plugin-service/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/plugin-service/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/plugin-service/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin_service object
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/rule-service/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/rule-service/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/rule-service/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/rule-service/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule_service object
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/rule-util/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/rule-util/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/rule-util/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/rule-util/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test rule_util functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/server-service/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/server-service/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/server-service/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/server-service/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server_service object
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/server-util/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/server-util/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/server-util/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/server-util/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server_util functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/server/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/server/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/server/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/server/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server object
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/transports/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/transports/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-daemon/transports/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-daemon/transports/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test server object
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-chrono/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-chrono/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-chrono/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-chrono/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.Chrono API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-directory/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-directory/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-directory/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-directory/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.Directory API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-file/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-file/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-file/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-file/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.File API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-irccd/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-irccd/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-irccd/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-irccd/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-logger/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-logger/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-logger/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-logger/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.Logger API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-system/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-system/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-system/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-system/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.System API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-timer/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-timer/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-timer/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-timer/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.Timer API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-unicode/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-unicode/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-unicode/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-unicode/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.Unicode API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-util/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-util/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-api-util/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-api-util/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test Irccd.Util API
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-plugin/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-plugin/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd-js/js-plugin/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd-js/js-plugin/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test js_plugin object
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd/fs-util/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd/fs-util/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd/fs-util/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd/fs-util/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test fs_util functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd/stream/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd/stream/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd/stream/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd/stream/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test network classes
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/libirccd/string-util/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd/string-util/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/libirccd/string-util/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/libirccd/string-util/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test string_util functions
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/ask/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/ask/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/ask/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/ask/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test ask plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/auth/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/auth/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/auth/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/auth/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test auth plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/hangman/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/hangman/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/hangman/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/hangman/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test hangman plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/history/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/history/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/history/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/history/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test history plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/joke/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/joke/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/joke/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/joke/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test joke plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/logger/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/logger/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/logger/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/logger/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test logger plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/plugin/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/plugin/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/plugin/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/plugin/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test plugin plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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
--- a/tests/src/plugins/tictactoe/CMakeLists.txt	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/tictactoe/CMakeLists.txt	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 #
 # CMakeLists.txt -- CMake build system for irccd
 #
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+# Copyright (c) 2013-2020 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
--- a/tests/src/plugins/tictactoe/main.cpp	Sun Oct 06 09:20:04 2019 +0200
+++ b/tests/src/plugins/tictactoe/main.cpp	Fri Jul 03 11:34:15 2020 +0200
@@ -1,7 +1,7 @@
 /*
  * main.cpp -- test tictactoe plugin
  *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
+ * Copyright (c) 2013-2020 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