changeset 462:eaec3bff1db8

Merge from stable-2
author David Demelier <markand@malikania.fr>
date Fri, 28 Jul 2017 11:41:41 +0200
parents 2958f36cb3be (current diff) 8be634087c72 (diff)
children 0af316941583
files libirccd/irccd/rule.cpp plugins/hangman/hangman.js tests/plugin-hangman/main.cpp
diffstat 14 files changed, 203 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsigs	Thu Jul 27 17:04:23 2017 +0200
+++ b/.hgsigs	Fri Jul 28 11:41:41 2017 +0200
@@ -5,3 +5,4 @@
 13097484da5145f5e83705aed9288c3f3d745375 0 iQEzBAABCAAdFiEEvr8S/JLqYAXrLA5Xodr5uEAj8x8FAliRvf0ACgkQodr5uEAj8x/MbQf7B8PnmQLQvB5URnAZiPQlxUwV/ueu1g2ygZaMv3shop9PQBDUHEkVso+kivGDrIhX+E94JeNno3L+FMaNigOHS67x2ycoaerk89COcTIfj426KyvBSJ/nP5m8Sx3AnXXjuqV83blQCOhi99lNE1o3Zw9UX9IwhIjZnLX6o48ybEhbh/DeXQ/qw4KIbqhA4LjE+UNndf0zDCgSN9DJXw3kUejRCNb7ygP/zkbnhpuM5prdzjHFsrAlGCtTAebB2Aq7oAn/ZYIJclh38E2j89fFxUbz8wg5JtXJBUQ2a4oGtByM6aKD8zXUMgTRHc/EfLvjlL8EoOZG8HkUM+kMcgPGDw==
 033d85c3c81e053368714174c22b692d99b03c24 0 iQEcBAABCAAGBQJYvpdpAAoJEKHa+bhAI/MfD68H/RSos3CKE1SU4n3iz0Y005J39nKVwYia8i4EPb1chuVS2qxiYISYCGHcmnALkIGYek8nSzEYAH6EoMoWnUz5WSYGuV0X5KH6722J+kgRlYn3l8ZgIt+cgOBfZh+91JCyIPSDRBCD3qF2bTXsgweX9F/iqWWRGIBcYLm/qw8YDaroiTm2kF9Txzs1VtJrLGLaltsndRj3v1sWyAeVD8xuKiF8v+zB1vZQQi75wSrhyovdQf13dy+GDUwqMZnZu+O9hTeq+mxIijGf+WXFLsBZ4Myxi1UNq5HAKO6kKKNMWdNnMqasL6VNx6D7dtDEJ1RV8DgbGsKUDFb957mdvLRFBr8=
 ae054128f365f9c91aa0f112a0b2c4c99265c00a 0 iQEcBAABAgAGBQJZWI5EAAoJEKHa+bhAI/MfWOIIAK7paY/J/qmm8tWi1zz981MqaJbXaL0+uLZCWNDXp3WjC237IHPa3bhLf5NL5bU4UnVwpBJSx9Sow4jrHZckuDSx+1I1cRoPngvsHDwo6YnekYHF2XX4ZI7NFQ+3D/IDYx+PQEKbQmw/XzxLGAfDzMLLo6mLfL8I/zak4fMprQ309Ka0lvsTdxiAzimYYVRN6MRVhVyv3udxQRGVU+waNCwzgfFZTjFHacFjBkY7PQWdVdtuf5uRyOiVF5HpBFf/Xi8eyfkRwRwKsSqsphkXPJctu8xeF9AYtu5/9x+T5L8SPK4fST1dRLdq0TZUFPhU/mgcVXiiqXpOagNQolKdjW0=
+b347b10d24c1f21737c677b5dcfbdcce97a2e945 0 iQEcBAABAgAGBQJZewPlAAoJEKHa+bhAI/MfXvcIAKX+kjUlKUxLqTkEPJYSTavlLwjdBoee1tesN7r4rMkxzy+WEHZnFEZToRgOqq4bcPS02J3XQcgZdHEysI43SezV44ZQVjdYyN2p2T98RuaXYXScE/pN7m0OFhiQHK6ozbeIRdDmx3i0l7ROYBiUmDWew0PZ4YULaLcSUnzELPYQfajCi2Vx4tmuKp42OG4gZQdgK60T2prl/tkzplS0TOErnPwCN0Vg+zJkD9JR9f9hsd7A2+3bkVyn7qe3HcgHzl6OsPt/P75siDpQv9lXA7s2mSYlzTmuffrviyms90K5ogbEkW56QQ8H8DGvtM5mLsIgNiatfAuXxAJfNj6FJj4=
--- a/.hgtags	Thu Jul 27 17:04:23 2017 +0200
+++ b/.hgtags	Fri Jul 28 11:41:41 2017 +0200
@@ -5,3 +5,4 @@
 a8b0353ac831ef6cb9be9f92a634252a680169b0 2.1.0
 4022c5fa8b7c62b461380bc9a6cb150fe6a53186 2.1.1
 315460895f853f525f2a5427109a6a05436429d7 2.1.2
+c3f46ad1ece6c9eccfe42f0f683f01aa3a29da9f 2.1.3
--- a/CHANGES.md	Thu Jul 27 17:04:23 2017 +0200
+++ b/CHANGES.md	Fri Jul 28 11:41:41 2017 +0200
@@ -1,6 +1,13 @@
 IRC Client Daemon CHANGES
 =========================
 
+irccd 2.1.3 2017-07-28
+----------------------
+
+  - Rules are now case insensitive (#645),
+  - Plugin hangman, history and logger are now case insensitive (#642),
+  - Plugin hangman: fix successive word selection (#644).
+
 irccd 2.1.2 2017-06-02
 ----------------------
 
--- a/cmake/IrccdVersion.cmake	Thu Jul 27 17:04:23 2017 +0200
+++ b/cmake/IrccdVersion.cmake	Fri Jul 28 11:41:41 2017 +0200
@@ -19,7 +19,7 @@
 # Irccd version.
 set(IRCCD_VERSION_MAJOR "2")
 set(IRCCD_VERSION_MINOR "1")
-set(IRCCD_VERSION_PATCH "2")
+set(IRCCD_VERSION_PATCH "3")
 set(IRCCD_VERSION "${IRCCD_VERSION_MAJOR}.${IRCCD_VERSION_MINOR}.${IRCCD_VERSION_PATCH}")
 set(IRCCD_VERSION_SHLIB "2")
 
@@ -32,6 +32,6 @@
 # IRCCD_RELEASE_DATE_DAY        2 digits (01 = first day of month)
 #
 set(IRCCD_RELEASE_DATE_YEAR 2017)
-set(IRCCD_RELEASE_DATE_MONTH 06)
-set(IRCCD_RELEASE_DATE_DAY 02)
+set(IRCCD_RELEASE_DATE_MONTH 07)
+set(IRCCD_RELEASE_DATE_DAY 28)
 set(IRCCD_RELEASE_DATE "${IRCCD_RELEASE_DATE_YEAR}-${IRCCD_RELEASE_DATE_MONTH}-${IRCCD_RELEASE_DATE_DAY}")
--- a/libirccd/irccd/rule.cpp	Thu Jul 27 17:04:23 2017 +0200
+++ b/libirccd/irccd/rule.cpp	Fri Jul 28 11:41:41 2017 +0200
@@ -16,7 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <cassert>
+#include <algorithm>
+#include <cctype>
 #include <stdexcept>
 
 #include "logger.hpp"
@@ -75,10 +76,15 @@
                  const std::string &plugin,
                  const std::string &event) const noexcept
 {
-    return matchMap(m_servers, server) &&
-           matchMap(m_channels, channel) &&
-           matchMap(m_origins, nick) &&
-           matchMap(m_plugins, plugin) &&
+    auto tolower = [] (auto str) {
+        std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+        return str;
+    };
+
+    return matchMap(m_servers, tolower(server)) &&
+           matchMap(m_channels, tolower(channel)) &&
+           matchMap(m_origins, tolower(nick)) &&
+           matchMap(m_plugins, tolower(plugin)) &&
            matchMap(m_events, event);
 }
 
--- a/plugins/hangman/hangman.js	Thu Jul 27 17:04:23 2017 +0200
+++ b/plugins/hangman/hangman.js	Fri Jul 28 11:41:41 2017 +0200
@@ -62,9 +62,12 @@
 Hangman.map = {};
 
 /**
- * List of words
+ * List of words.
  */
-Hangman.words = [];
+Hangman.words = {
+    all: [],        //!< All words,
+    registry: {}    //!< Words list per server/channel.
+};
 
 /**
  * Search for an existing game.
@@ -139,15 +142,15 @@
 
         while ((line = file.readline()) !== undefined)
             if (Hangman.isWord(line))
-                Hangman.words.push(line);
+                Hangman.words.all.push(line);
     } catch (e) {
         throw new Error("could not open '" + path + "'");
     }
 
-    if (Hangman.words.length === 0)
+    if (Hangman.words.all.length === 0)
         throw new Error("empty word database");
 
-    Logger.info("number of words in database: " + Hangman.words.length);
+    Logger.info("number of words in database: " + Hangman.words.all.length);
 }
 
 /**
@@ -182,14 +185,18 @@
  */
 Hangman.prototype.select = function ()
 {
+    var id = this.server.toString() + "@" + this.channel;
+
     // Reload the words if empty.
-    if (!this.words || this.words.length === 0)
-        this.words = Hangman.words.slice(0);
+    if (!Hangman.words.registry[id] || Hangman.words.registry[id].length === 0)
+        Hangman.words.registry[id] = Hangman.words.all.slice(0);
 
-    var i = Math.floor(Math.random() * this.words.length);
+    var i = Math.floor(Math.random() * Hangman.words.registry[id].length);
 
-    this.word = this.words[i];
-    this.words.splice(i, 1);
+    this.word = Hangman.words.registry[id][i];
+
+    // Erase words from the registry.
+    Hangman.words.registry[id].splice(i, 1);
 
     // Fill table.
     this.table = {};
--- a/plugins/history/history.js	Thu Jul 27 17:04:23 2017 +0200
+++ b/plugins/history/history.js	Fri Jul 28 11:41:41 2017 +0200
@@ -142,6 +142,8 @@
 
 function onCommand(server, origin, channel, message)
 {
+    channel = channel.toLowerCase();
+
     var args = message.trim().split(" ");
     var kw = {
         channel: channel,
@@ -162,6 +164,8 @@
         return;
     }
 
+    args[1] = args[1].toLowerCase();
+
     if (isSelf(server, args[1]))
         return;
 
@@ -186,19 +190,28 @@
 
 function onJoin(server, origin, channel)
 {
-    write(server, channel, Util.splituser(origin));
+    origin = Util.splituser(origin).toLowerCase();
+    channel = channel.toLowerCase();
+
+    write(server, channel, origin);
 }
 
 function onMessage(server, origin, channel, message)
 {
-    write(server, channel, Util.splituser(origin), message);
+    origin = Util.splituser(origin).toLowerCase();
+    channel = channel.toLowerCase();
+
+    write(server, channel, origin, message);
 }
 
 onMe = onMessage;
 
 function onTopic(server, origin, channel)
 {
-    write(server, channel, Util.splituser(origin));
+    origin = Util.splituser(origin).toLowerCase();
+    channel = channel.toLowerCase();
+
+    write(server, origin, channel)
 }
 
 function onLoad()
@@ -220,5 +233,5 @@
 function onNames(server, channel, list)
 {
     for (var i = 0; i < list.length; ++i)
-        write(server, channel, list[i]);
+        write(server, channel.toLowerCase(), list[i]);
 }
--- a/plugins/logger/logger.js	Thu Jul 27 17:04:23 2017 +0200
+++ b/plugins/logger/logger.js	Fri Jul 28 11:41:41 2017 +0200
@@ -124,65 +124,88 @@
 
 function onChannelMode(server, origin, channel, mode, arg)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("cmode", keywords(server, channel, origin, {
-        "arg":        arg,
-        "mode":        mode,
-        "source":    channel
+        "arg":      arg,
+        "mode":     mode,
+        "source":   channel
     }));
 }
 
 function onChannelNotice(server, origin, channel, notice)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("cnotice", keywords(server, channel, origin, {
-        "message":    notice,
-        "source":    channel
+        "message":  notice,
+        "source":   channel
     }));
 }
 
 function onInvite(server, origin, channel)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("invite", keywords(server, channel, origin, {
-        "source":    channel
+        "source":   channel
     }));
 }
 
 function onJoin(server, origin, channel)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("join", keywords(server, channel, origin, {
-        "source":    channel
+        "source":   channel
     }));
 }
 
 function onKick(server, origin, channel, target, reason)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("kick", keywords(server, channel, origin, {
-        "target":    target,
-        "source":    channel,
-        "reason":    reason
+        "target":   target,
+        "source":   channel,
+        "reason":   reason
     }));
 }
 
 function onMe(server, origin, channel, message)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("me", keywords(server, channel, origin, {
-        "message":    message,
-        "source":    channel
+        "message":  message,
+        "source":   channel
     }));
 }
 
 function onMessage(server, origin, channel, message)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("message", keywords(server, channel, origin, {
-        "message":    message,
-        "source":    channel
+        "message":  message,
+        "source":   channel
     }));
 }
 
 function onMode(server, origin, mode)
 {
+    origin = origin.toLowerCase();
+
     write("mode", keywords(server, undefined, origin, {
-        "mode":        mode,
-        "source":    Util.splituser(origin)
+        "mode":     mode,
+        "source":   Util.splituser(origin)
     }));
 }
 
@@ -193,32 +216,42 @@
 
 function onNotice(server, origin, notice)
 {
+    origin = origin.toLowerCase();
+
     write("notice", keywords(server, undefined, origin, {
-        "message":    notice,
-        "source":    Util.splituser(origin)
+        "message":  notice,
+        "source":   Util.splituser(origin)
     }));
 }
 
 function onPart(server, origin, channel, reason)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("part", keywords(server, channel, origin, {
-        "reason":    reason,
-        "source":    channel
+        "reason":   reason,
+        "source":   channel
     }));
 }
 
 function onQuery(server, origin, message)
 {
+    origin = origin.toLowerCase();
+
     write("query", keywords(server, undefined, origin, {
-        "source":    Util.splituser(origin),
-        "message":    message
+        "source":   Util.splituser(origin),
+        "message":  message
     }));
 }
 
 function onTopic(server, origin, channel, topic)
 {
+    origin = origin.toLowerCase();
+    channel = channel.toLowerCase();
+
     write("topic", keywords(server, channel, origin, {
-        "source":    channel,
+        "source":   channel,
         "topic":    topic
     }));
 }
--- a/tests/plugin-hangman/CMakeLists.txt	Thu Jul 27 17:04:23 2017 +0200
+++ b/tests/plugin-hangman/CMakeLists.txt	Fri Jul 28 11:41:41 2017 +0200
@@ -18,7 +18,7 @@
 
 irccd_define_test(
     NAME plugin-hangman
-    SOURCES main.cpp
+    SOURCES main.cpp words.conf wordlist_fix_644.conf
     LIBRARIES libirccd
     FLAGS PLUGINDIR=\"${IRCCD_FAKEROOTDIR}/${WITH_PLUGINDIR}\"
 )
--- a/tests/plugin-hangman/main.cpp	Thu Jul 27 17:04:23 2017 +0200
+++ b/tests/plugin-hangman/main.cpp	Fri Jul 28 11:41:41 2017 +0200
@@ -16,6 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <unordered_map>
+#include <unordered_set>
+
 #include <gtest/gtest.h>
 
 #include <irccd/irccd.hpp>
@@ -199,7 +202,7 @@
     ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _", m_server->last());
 }
 
-TEST_F(HangmanTest, caseInsensitive)
+TEST_F(HangmanTest, case_fix_642)
 {
     load();
 
@@ -237,6 +240,57 @@
     ASSERT_EQ("#hangman:running=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ y", m_server->last());
 }
 
+TEST_F(HangmanTest, wordlist_fix_644)
+{
+    /*
+     * To be sure that the selection use the same list, we create a list of
+     * three words that has different size to determine which one was selected.
+     *
+     * Then we run 3 games and verify that the old selection is not the same
+     * as the current.
+     *
+     * This is not very accurate but it's better than nothing.
+     */
+    load({{ "file", SOURCEDIR "/wordlist_fix_644.conf" }});
+
+    std::unordered_map<unsigned, std::string> words{
+        { 14, "abc"     },
+        { 16, "abcd"    },
+        { 18, "abcde"   }
+    };
+    std::unordered_set<unsigned> found;
+
+    m_plugin->setFormats({
+        { "start", "#{word}" }
+    });
+
+    unsigned last, current;
+
+    // 1. Initial game + finish.
+    m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", ""});
+    last = m_server->last().length();
+    found.insert(last);
+    m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", words[last]});
+
+    // 2. Current must not be the last one.
+    m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", ""});
+    current = m_server->last().length();
+
+    ASSERT_NE(last, current);
+    ASSERT_EQ(0U, found.count(current));
+
+    found.insert(current);
+    last = current;
+    m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", words[current]});
+
+    // 3. Last word must be the one that is kept into the map.
+    m_plugin->onCommand(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#hangman", ""});
+    current = m_server->last().length();
+
+    ASSERT_NE(last, current);
+    ASSERT_EQ(0U, found.count(current));
+}
+
 int main(int argc, char **argv)
 {
     path::setApplicationPath(argv[0]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/plugin-hangman/wordlist_fix_644.conf	Fri Jul 28 11:41:41 2017 +0200
@@ -0,0 +1,3 @@
+abc
+abcd
+abcde
--- a/tests/plugin-history/main.cpp	Thu Jul 27 17:04:23 2017 +0200
+++ b/tests/plugin-history/main.cpp	Fri Jul 28 11:41:41 2017 +0200
@@ -124,6 +124,21 @@
     ASSERT_EQ("#history:unknown=history:!history:test:#history:destructor!dst@localhost:destructor:nobody", m_server->last());
 }
 
+TEST_F(HistoryTest, case_fix_642)
+{
+    std::regex rule("#history:said=history:!history:test:#history:destructor!dst@localhost:destructor:jean:hello:\\d{2}:\\d{2}");
+
+    remove(BINARYDIR "/case.json");
+    load({{"file", BINARYDIR "/case.json"}});
+
+    m_plugin->onMessage(m_irccd, MessageEvent{m_server, "JeaN!JeaN@localhost", "#history", "hello"});
+
+    m_plugin->onCommand(m_irccd, MessageEvent{m_server, "destructor!dst@localhost", "#HISTORY", "said JEAN"});
+    ASSERT_TRUE(std::regex_match(m_server->last(), rule));
+    m_plugin->onCommand(m_irccd, MessageEvent{m_server, "destructor!dst@localhost", "#HiSToRy", "said JeaN"});
+    ASSERT_TRUE(std::regex_match(m_server->last(), rule));
+}
+
 int main(int argc, char **argv)
 {
     path::setApplicationPath(argv[0]);
--- a/tests/plugin-logger/main.cpp	Thu Jul 27 17:04:23 2017 +0200
+++ b/tests/plugin-logger/main.cpp	Fri Jul 28 11:41:41 2017 +0200
@@ -182,6 +182,15 @@
     ASSERT_EQ("topic=test:#staff:jean!jean@localhost:jean:oh yeah yeaaaaaaaah\n", last());
 }
 
+TEST_F(LoggerTest, case_fix_642)
+{
+    load();
+
+    m_plugin->onMessage(m_irccd, MessageEvent{m_server, "jean!jean@localhost", "#STAFF", "hello guys"});
+
+    ASSERT_EQ("message=test:#staff:jean!jean@localhost:jean:hello guys\n", last());
+}
+
 int main(int argc, char **argv)
 {
     path::setApplicationPath(argv[0]);
--- a/tests/rules/main.cpp	Thu Jul 27 17:04:23 2017 +0200
+++ b/tests/rules/main.cpp	Fri Jul 28 11:41:41 2017 +0200
@@ -18,6 +18,7 @@
 
 #include <gtest/gtest.h>
 
+#include <irccd/logger.hpp>
 #include <irccd/rule.hpp>
 #include <irccd/service.hpp>
 
@@ -228,10 +229,16 @@
     ASSERT_FALSE(m_rules.solve("malikania", "#test", "", "game", "onMessage"));
 }
 
+TEST_F(RulesTest, case_fix_645)
+{
+    ASSERT_FALSE(m_rules.solve("MALIKANIA", "#STAFF", "", "SYSTEM", "onCommand"));
+}
+
 } // !irccd
 
 int main(int argc, char **argv)
 {
+    irccd::log::setLogger(std::make_unique<irccd::log::SilentLogger>());
     testing::InitGoogleTest(&argc, argv);
 
     return RUN_ALL_TESTS();