diff --git a/.gitignore b/.gitignore index 040bd64fe5c8a9a9a23a27b0cee10055b1df0ce1..4bc35c81083b31248efc411f6c967939aea613ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ wantzel.ini config.py *.pyc -db.sqlite3 +db*.sqlite3 wantzel.log ve*/ diff --git a/tests/requirements_tests.txt b/tests/requirements_tests.txt index 5c1ec1a52fd3196cf5e1a80e23f2d8b3702234ed..6bbaa3ea252fb7cc8dba460902459a0741e6ca48 100644 --- a/tests/requirements_tests.txt +++ b/tests/requirements_tests.txt @@ -2,3 +2,4 @@ pylint coverage nose +mock diff --git a/tests/test_commands.py b/tests/test_commands.py index cbf4130678b038b3649f96f5d4e2b4a7edb5a151..7effe4d252da42fcfa98640480faac0a1e6c5ddd 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -5,23 +5,20 @@ Testing commands of wantzel from mock import Mock import unittest +import sqlite3 -import tests.config +import config from messages import messages from wantzel import DEBUG, get_cursor, Utils, Wantzel -LOG_FILE = "wantzel_test.log" +LOG_FILE = "tests/wantzel.log" LOG_LEVEL = DEBUG - -def fake_send_message(channel, message): - global global_channel, global_message - global_channel = channel - global_message = message - -def fake_topic(topic): - global global_topic - global_topic = topic +config.dbuser = "root" +config.dbpassword = "root" +config.dbserver = "localhost" +config.dbname = "wantzel_test" +config.sqlite_db = "tests/db_test.sqlite3" class TestWantzel(unittest.TestCase): @@ -34,31 +31,32 @@ class TestWantzel(unittest.TestCase): self.wantzel.irc.client = Mock() self.wantzel.irc.client.topic = Mock() cursor = get_cursor() - # Creating tables if necessary - with open("create_mysql_tables.sql") as file_handle: - cursor.execute(file_handle.read()) # clearing datas cursor.execute("DELETE FROM presse") + connection = sqlite3.connect(config.sqlite_db) + connection.execute("DELETE FROM moderator") + connection.execute("INSERT INTO moderator (name) VALUES ('admin')") + connection.commit() def tearDown(self): # Destroying database cursor = get_cursor() cursor.execute("DELETE FROM presse") + connection = sqlite3.connect(config.sqlite_db) + connection.execute("DELETE FROM moderator") + connection.commit() - def test_command_help(self): + def testHelpAnswerIsInQuery(self): self.wantzel.on_privmsg("test!test.me", "#test_channel", "~help") - self.wantzel.send_message.assert_called_once_with("#test_channel", messages["help"]) + self.wantzel.send_message.assert_called_once_with("test", messages["help"]) - def test_command_help_command(self): + def testSubHelpAnswersAreInQuery(self): commands = ['help', 'rp', 'status', 'stats', 'kill', 'admin'] for command in commands: self.wantzel.on_privmsg("test!test.me", "#test_channel", "~help %s" % command) - self.wantzel.send_message.assert_called_with( - "#test_channel", - messages["help_%s" % command] - ) + self.wantzel.send_message.assert_called_with("test", messages["help_%s" % command]) - def test_command_rp_with_no_url(self): + def testRpCommandWithNoUrlDoesNothing(self): self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp nothing") self.wantzel.send_message.assert_not_called() cursor = get_cursor() @@ -66,7 +64,7 @@ class TestWantzel(unittest.TestCase): rows = cursor.fetchall() self.assertEqual(0, int(rows[0][0])) - def test_command_rp_new_article(self): + def testRpCommandWithNewArticleSavesIt(self): self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/article") self.wantzel.send_message.assert_called_once_with( "#test_channel", @@ -80,7 +78,24 @@ class TestWantzel(unittest.TestCase): rows = cursor.fetchall() self.assertEqual(1, int(rows[0][0])) - def test_command_rp_known_article(self): + def testDoubleRpCommandWithAKnownArticleIsNotModifyingNote(self): + cursor = get_cursor() + # Adding article for first time + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/article") + # Then, just add a point + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["rp_known_article"] % "test" + ) + cursor.execute("SELECT COUNT(*) FROM presse") + rows = cursor.fetchall() + self.assertEqual(1, int(rows[0][0])) + cursor.execute("SELECT note FROM presse WHERE url='%s'" % "http://test.me/article") + rows = cursor.fetchall() + self.assertEqual(1, int(rows[0][0])) + + def testRpCommandWithAKnownArticle(self): cursor = get_cursor() # Adding article for first time self.wantzel.on_privmsg("first_test!test.me", "#test_channel", "~rp http://test.me/article") @@ -97,7 +112,7 @@ class TestWantzel(unittest.TestCase): rows = cursor.fetchall() self.assertEqual(2, int(rows[0][0])) - def test_command_rp_taken_article(self): + def testRpCommandWithAPublishableArticle(self): cursor = get_cursor() # Adding article for first time self.wantzel.on_privmsg("first_test!test.me", "#test_channel", "~rp http://test.me/article") @@ -116,3 +131,189 @@ class TestWantzel(unittest.TestCase): rows = cursor.fetchall() self.assertEqual(3, int(rows[0][0])) + def testStatusCommandForAnUnknownArticle(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~status http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["status_unknown_article"] % "test" + ) + + def testStatusCommandForAKnownArticle(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/article") + for i in range(1, 5): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~status http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + "test: note %s / non publié" % i + ) + self.wantzel.on_privmsg("other_test!test.me", "#test_channel", "~rp http://test.me/article") + + def testStatusCommandForAPublishedArticle(self): + cursor = get_cursor() + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/article") + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~status http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + "test: note 1 / non publié" + ) + for i in range(1, 5): + cursor.execute("UPDATE presse SET nid=%s WHERE url='%s'" % ( + i, + "http://test.me/article", + )) + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~status http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + "test: note 1 / publié (https://laquadrature.net/node/%s)" % i + ) + + def testStatsCommandWithNoArticle(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~stats") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["stats_bravo"] % 15 + ) + + def testStatsCommandWithOneArticle(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/article") + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~stats") + self.wantzel.send_message.assert_called_with( + "#test_channel", + "note>=0: 1j:1, 3j:1, 7j:1, 15j:1" + ) + + def testStatsCommandWithSomeOldArticles(self): + cursor = get_cursor() + # Old article + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/old_article") + cursor.execute(""" + UPDATE presse + SET datec=(NOW()-INTERVAL 5 DAY) + WHERE url='%s'""" % "http://test.me/old_article" + ) + # New article + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/new_article") + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~stats") + self.wantzel.send_message.assert_called_with( + "#test_channel", + "note>=0: 1j:1, 3j:1, 7j:2, 15j:2" + ) + + def testKillCommandWithoutCredentials(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~kill http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["not_moderator"] + ) + + def testKillCommandWithAnUnknownArticle(self): + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~kill http://test.me/unknown_article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["kill_none"] % "http://test.me/unknown_article" + ) + + def testKillCommandWithAKnownArticle(self): + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~rp http://test.me/article") + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~kill http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["kill_done"] % "http://test.me/article" + ) + cursor = get_cursor() + cursor.execute("SELECT note FROM presse WHERE url='%s'" % "http://test.me/article") + rows = cursor.fetchall() + self.assertEqual(-100, int(rows[0][0])) + + def testAdminListCommandWithoutCredentials(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["not_moderator"] + ) + + def testAdminListCommand(self): + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["admin_list"] % "admin" + ) + + def testAdminAddCommandWithoutCredentials(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~admin add test") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["not_moderator"] + ) + + def testAdminAddCommandWithOneName(self): + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin add toto") + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["admin_list"] % "admin, toto" + ) + + def testAdminAddCommandWithMultipleName(self): + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin add tata, titi,tutu, toto") + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["admin_list"] % "admin, tata, titi, toto, tutu" + ) + + def testAdminDelCommandWithoutCredentials(self): + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~admin del test") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["not_moderator"] + ) + + def testAdminDelCommandWithOneName(self): + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin add tata, titi,tutu, toto") + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["admin_list"] % "admin, tata, titi, toto, tutu" + ) + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin del titi") + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["admin_list"] % "admin, tata, toto, tutu" + ) + + def testAdminDelCommandWithMultipleName(self): + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin add tata, titi,tutu, toto") + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["admin_list"] % "admin, tata, titi, toto, tutu" + ) + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin del toto, tutu,titi") + self.wantzel.on_privmsg("admin!test.me", "#test_channel", "~admin list") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["admin_list"] % "admin, tata" + ) + + + + def notest(self): + # Adding article for first time + self.wantzel.on_privmsg("first_test!test.me", "#test_channel", "~rp http://test.me/article") + self.wantzel.on_privmsg("second_test!test.me", "#test_channel", "~rp http://test.me/article") + # Then, test its status + self.wantzel.on_privmsg("test!test.me", "#test_channel", "~rp http://test.me/article") + self.wantzel.send_message.assert_called_with( + "#test_channel", + messages["rp_taken_article"] % "test" + ) + self.wantzel.irc.client.topic.assert_called_once_with("#lqdn-rp", messages["topic"] % 1) + cursor.execute("SELECT COUNT(*) FROM presse") + rows = cursor.fetchall() + self.assertEqual(1, int(rows[0][0])) + cursor.execute("SELECT note FROM presse WHERE url='%s'" % "http://test.me/article") + rows = cursor.fetchall() + self.assertEqual(3, int(rows[0][0])) + diff --git a/wantzel.py b/wantzel.py index 3be86e4bae4cfde73c0078102e54b1881d4620c5..e3bbb6cab80e3fde815879a6a99e06207085f519 100644 --- a/wantzel.py +++ b/wantzel.py @@ -231,7 +231,7 @@ class Wantzel(object): channel = user # Help command, specific if "wantzel" in msg and ("help" in msg or "aide" in msg): - self.help(channel, msg) + self.help(user, channel, msg) # Find known command command = re.search("[!~](rp[acp]*|status|kill|help|stats|admin)", msg) Utils.debug("Command: %s" % command) @@ -291,20 +291,22 @@ class Wantzel(object): if not url: return + # Managing flags + # LQdN is quoted + if "c" in command: + cite += 1 + # the article speak about LQdN + if command.count("p") > 1: + cite += 2 + # Archive this article + if "a" in command: + cite += 4 + # Looking for such an article in database cursor = get_cursor() cursor.execute("SELECT id, note, provenance FROM presse WHERE url = %s", (url, )) rows = cursor.fetchall() if not rows: - # LQdN is quoted - if "c" in command: - cite += 2 - # the article speak about LQdN - if command.count("p") > 1: - cite += 2 - # Archive this article - if "a" in command: - note = -2 Utils.debug("Adding an article by %s: %s" % (user, url)) cursor.execute( """INSERT INTO presse SET @@ -344,21 +346,25 @@ class Wantzel(object): # Looking for such an article in database cursor = get_cursor() cursor.execute(""" - SELECT cite, published, nid, screenshot, fetched, seemscite, note + SELECT cite, nid, note FROM presse WHERE url = %s""", (url, )) rows = cursor.fetchall() if not rows: self.send_message(channel, messages["status_unknown_article"] % user) else: - message = "%s: note %s / " % (user, rows[0][6]) - if rows[0][0] != "0": - message += "cite lqdn / " - if rows[0][1] == 1: - published = "publié (noeud %s) / " % rows[0][2] + message = "%s: note %s / " % (user, rows[0][2]) + if rows[0][0] & 1: + message += "cite LQdN / " + if rows[0][0] & 2: + message += "parle de LQdN / " + if rows[0][0] & 4: + message += "archivé / " + if rows[0][1] > 0: + message += "publié (https://laquadrature.net/node/%s) / " % rows[0][1] else: - published = "non publié / " - self.send_message(channel, message[:-2]) + message += "non publié / " + self.send_message(channel, message[:-3]) def kill(self, user, channel, msg): """ @@ -395,7 +401,6 @@ class Wantzel(object): notes = [0, 3, 4] notnull = 0 somethingatall = 0 - result = "" for note in notes: notnull = 0 period_result = "" @@ -413,10 +418,9 @@ class Wantzel(object): notnull = 1 somethingatall = 1 if notnull: - result = result + "note>=%s: " % note + period_result[:-2] + "\n" + self.send_message(channel, "note>=%s: " % note + period_result[:-2]) if somethingatall == 0: - result = messages["stats_bravo"] % periods[-1] - self.send_message(channel, result) + self.send_message(channel, messages["stats_bravo"] % periods[-1]) def admin(self, user, channel, msg): """ @@ -447,7 +451,7 @@ class Wantzel(object): names = [] for row in connection.execute("SELECT name FROM moderator"): names.append(row[0].encode("utf-8")) - self.send_message(channel, messages["admin_list"] % ", ".join(names)) + self.send_message(channel, messages["admin_list"] % ", ".join(sorted(names))) else: self.send_message(channel, messages["not_moderator"]) @@ -462,7 +466,7 @@ class Wantzel(object): connection = sqlite3.connect(config.sqlite_db) result = re.search("~admin add (([^,]+, ?)+)?(.*)", msg) if result.group(1): - names = [name for name in result.group(1).split(", ") if name != ""] + names = [name.strip() for name in result.group(1).split(",") if name.strip() != ""] names.append(result.group(3)) # Do not add actual moderators moderators = [] @@ -492,7 +496,7 @@ class Wantzel(object): names = [] result = re.search("~admin del (([^,]+, ?)+)?(.*)", msg) if result.group(1): - names = [name for name in result.group(1).split(", ") if name != ""] + names = [name.strip() for name in result.group(1).split(",") if name.strip() != ""] names.append(result.group(3)) names = list(set(names)) Utils.debug(names)