2006-06-26 17:57:20 +00:00
|
|
|
from supybot.test import *
|
|
|
|
|
2010-03-30 20:13:51 +00:00
|
|
|
import supybot.conf as conf
|
|
|
|
import supybot.ircmsgs as ircmsgs
|
2010-04-04 04:31:15 +00:00
|
|
|
import supybot.world as world
|
2010-03-30 20:13:51 +00:00
|
|
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
2010-04-01 19:34:59 +00:00
|
|
|
pluginConf = conf.supybot.plugins.Bantracker
|
|
|
|
pluginConf.enabled.setValue(True)
|
|
|
|
pluginConf.bansite.setValue('http://foo.bar.com')
|
|
|
|
pluginConf.database.setValue('bantracker-test.db')
|
2010-03-30 20:13:51 +00:00
|
|
|
|
2010-04-01 19:34:59 +00:00
|
|
|
def quiet(channel, hostmask, prefix='', msg=None):
|
|
|
|
"""Returns a MODE to quiet nick on channel."""
|
|
|
|
return ircmsgs.mode(channel, ('+q', hostmask), prefix, msg)
|
2010-03-30 20:13:51 +00:00
|
|
|
|
|
|
|
class BantrackerTestCase(ChannelPluginTestCase):
|
2006-06-26 17:57:20 +00:00
|
|
|
plugins = ('Bantracker',)
|
2010-03-30 20:13:51 +00:00
|
|
|
|
2010-04-01 19:34:59 +00:00
|
|
|
def setUp(self):
|
2010-04-13 00:41:14 +00:00
|
|
|
self.setDb()
|
2010-04-01 19:34:59 +00:00
|
|
|
super(BantrackerTestCase, self).setUp()
|
2010-04-03 23:06:29 +00:00
|
|
|
pluginConf.request.setValue(False) # disable comments
|
|
|
|
pluginConf.request.ignore.set('')
|
2010-04-03 03:17:26 +00:00
|
|
|
pluginConf.request.forward.set('')
|
2010-04-03 16:20:15 +00:00
|
|
|
pluginConf.request.review.setValue(1.0/86400) # one second
|
2010-04-04 04:31:15 +00:00
|
|
|
# Bantracker for some reason doesn't use Supybot's own methods for check capabilities,
|
|
|
|
# so it doesn't have a clue about testing and screws my tests by default.
|
|
|
|
# This would fix it until I bring myself to take a look
|
|
|
|
cb = self.getCallback()
|
|
|
|
f = cb.check_auth
|
|
|
|
def test_check_auth(*args, **kwargs):
|
|
|
|
if world.testing:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return f(*args, **kwargs)
|
|
|
|
cb.check_auth = test_check_auth
|
2010-04-01 19:34:59 +00:00
|
|
|
|
|
|
|
def setDb(self):
|
|
|
|
import sqlite, os
|
|
|
|
dbfile = os.path.join(os.curdir, pluginConf.database())
|
|
|
|
try:
|
|
|
|
os.remove(dbfile)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
db = sqlite.connect(dbfile)
|
|
|
|
cursor = db.cursor()
|
|
|
|
cursor.execute('CREATE TABLE bans ('
|
|
|
|
'id INTEGER PRIMARY KEY,'
|
|
|
|
'channel VARCHAR(30) NOT NULL,'
|
|
|
|
'mask VARCHAR(100) NOT NULL,'
|
|
|
|
'operator VARCHAR(30) NOT NULL,'
|
|
|
|
'time VARCHAR(300) NOT NULL,'
|
|
|
|
'removal DATETIME,'
|
|
|
|
'removal_op VARCHAR(30),'
|
|
|
|
'log TEXT)')
|
|
|
|
cursor.execute('CREATE TABLE comments ('
|
|
|
|
'ban_id INTEGER,'
|
|
|
|
'who VARCHAR(100) NOT NULL,'
|
|
|
|
'comment MEDIUMTEXT NOT NULL,'
|
|
|
|
'time VARCHAR(300) NOT NULL)')
|
|
|
|
cursor.execute('CREATE TABLE sessions ('
|
|
|
|
'session_id VARCHAR(50) PRIMARY KEY,'
|
|
|
|
'user MEDIUMTEXT NOT NULL,'
|
|
|
|
'time INT NOT NULL)')
|
|
|
|
cursor.execute('CREATE TABLE users ('
|
|
|
|
'username VARCHAR(50) PRIMARY KEY,'
|
|
|
|
'salt VARCHAR(8),'
|
|
|
|
'password VARCHAR(50))')
|
|
|
|
db.commit()
|
|
|
|
cursor.close()
|
|
|
|
db.close()
|
|
|
|
|
2010-03-30 20:13:51 +00:00
|
|
|
def getCallback(self):
|
|
|
|
for cb in self.irc.callbacks:
|
|
|
|
if cb.name() == 'Bantracker':
|
|
|
|
break
|
|
|
|
return cb
|
|
|
|
|
2010-04-01 19:34:59 +00:00
|
|
|
def getDb(self):
|
|
|
|
return self.getCallback().db
|
|
|
|
|
|
|
|
def query(self, query, parms=()):
|
|
|
|
cursor = self.getDb().cursor()
|
|
|
|
cursor.execute(query, parms)
|
|
|
|
return cursor.fetchall()
|
|
|
|
|
|
|
|
def feedBan(self, hostmask, prefix='', channel=None, mode='b'):
|
|
|
|
if not channel:
|
|
|
|
channel = self.channel
|
|
|
|
if not prefix:
|
|
|
|
prefix = 'op!user@host.net'
|
|
|
|
if mode == 'b':
|
|
|
|
ban = ircmsgs.ban(channel, hostmask, prefix=prefix)
|
|
|
|
elif mode == 'q':
|
|
|
|
ban = quiet(channel, hostmask, prefix=prefix)
|
2010-04-03 03:17:26 +00:00
|
|
|
elif mode == 'k':
|
|
|
|
ban = ircmsgs.kick(channel, hostmask, s='kthxbye!', prefix=prefix)
|
|
|
|
elif mode == 'p':
|
|
|
|
ban = ircmsgs.part(channel, prefix=hostmask,
|
|
|
|
s='requested by %s (kthxbye!)' %prefix[:prefix.find('!')])
|
2010-03-30 20:13:51 +00:00
|
|
|
self.irc.feedMsg(ban)
|
2010-04-03 03:17:26 +00:00
|
|
|
return ban
|
2010-04-01 19:34:59 +00:00
|
|
|
|
2010-04-03 04:44:57 +00:00
|
|
|
def testComment(self):
|
2010-04-03 23:06:29 +00:00
|
|
|
pluginConf.request.setValue(True)
|
2010-04-01 19:34:59 +00:00
|
|
|
# test bans
|
|
|
|
self.feedBan('asd!*@*')
|
2010-03-30 20:13:51 +00:00
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
2010-04-01 19:34:59 +00:00
|
|
|
"PRIVMSG op :Please comment on the ban of asd!*@* in #test, use: @comment 1"
|
|
|
|
" <comment>")
|
|
|
|
# test quiets
|
|
|
|
self.feedBan('dude!*@*', mode='q')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"PRIVMSG op :Please comment on the quiet of dude!*@* in #test, use: @comment 2"
|
2010-03-30 20:13:51 +00:00
|
|
|
" <comment>")
|
2010-04-03 03:17:26 +00:00
|
|
|
# test kick/part
|
|
|
|
self.feedBan('dude', mode='k')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"PRIVMSG op :Please comment on the removal of dude in #test, use: @comment 3"
|
|
|
|
" <comment>")
|
2010-04-13 00:33:15 +00:00
|
|
|
self.feedBan('dude!dude@trollpit.com', mode='p')
|
2010-04-03 03:17:26 +00:00
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"PRIVMSG op :Please comment on the removal of dude in #test, use: @comment 4"
|
|
|
|
" <comment>")
|
2010-04-03 04:44:57 +00:00
|
|
|
|
2010-04-13 02:02:07 +00:00
|
|
|
def testCommentIgnore(self):
|
|
|
|
pluginConf.request.setValue(True)
|
|
|
|
pluginConf.request.ignore.set('FloodBot? FloodBotK?')
|
|
|
|
self.feedBan('asd!*@*', prefix='floodbotk1!bot@botpit.com')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(msg, None)
|
|
|
|
self.feedBan('dude!*@*', mode='q', prefix='FloodBot1!bot@botpit.com')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(msg, None)
|
|
|
|
self.feedBan('dude', mode='k', prefix='FloodBot2!bot@botbag.com')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(msg, None)
|
|
|
|
self.feedBan('dude!dude@trollpit.com', mode='p', prefix='FloodBotK2!bot@botbag.com')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(msg, None)
|
|
|
|
self.feedBan('asd!*@*')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"PRIVMSG op :Please comment on the ban of asd!*@* in #test, use: @comment 5"
|
|
|
|
" <comment>")
|
|
|
|
|
2010-04-03 04:44:57 +00:00
|
|
|
def testCommentForward(self):
|
2010-04-03 23:06:29 +00:00
|
|
|
pluginConf.request.setValue(True)
|
2010-04-03 03:17:26 +00:00
|
|
|
pluginConf.request.forward.set('bot')
|
|
|
|
pluginConf.request.forward.channels.set('#channel')
|
|
|
|
self.feedBan('qwe!*@*')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
2010-04-03 04:44:57 +00:00
|
|
|
"PRIVMSG op :Please comment on the ban of qwe!*@* in #test, use: @comment 1"
|
2010-04-03 03:17:26 +00:00
|
|
|
" <comment>")
|
|
|
|
self.feedBan('zxc!*@*', prefix='bot!user@host.com')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"NOTICE #channel :Please somebody comment on the ban of zxc!*@* in #test done by bot,"
|
2010-04-03 04:44:57 +00:00
|
|
|
" use: @comment 2 <comment>")
|
2010-03-30 20:13:51 +00:00
|
|
|
|
2010-04-03 04:44:57 +00:00
|
|
|
def testReview(self):
|
2010-04-03 23:06:29 +00:00
|
|
|
pluginConf.request.setValue(True)
|
2010-03-30 20:13:51 +00:00
|
|
|
cb = self.getCallback()
|
2010-04-01 19:34:59 +00:00
|
|
|
self.feedBan('asd!*@*')
|
2010-03-30 20:13:51 +00:00
|
|
|
self.irc.takeMsg() # ignore comment request comment
|
|
|
|
cb.reviewBans()
|
|
|
|
self.assertFalse(cb.pendingReviews)
|
2010-04-01 20:52:53 +00:00
|
|
|
print 'waiting 4 secs..'
|
2010-03-30 20:13:51 +00:00
|
|
|
time.sleep(2)
|
|
|
|
cb.reviewBans()
|
|
|
|
# check is pending
|
|
|
|
self.assertTrue(cb.pendingReviews)
|
2010-04-01 20:52:53 +00:00
|
|
|
# send msg if a user with a matching host says something
|
|
|
|
self.feedMsg('Hi!', frm='op!user@fakehost.net')
|
2010-03-30 20:13:51 +00:00
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(msg, None)
|
2010-04-01 20:52:53 +00:00
|
|
|
self.feedMsg('Hi!', frm='op_!user@host.net')
|
2010-03-30 20:13:51 +00:00
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
2010-04-01 20:52:53 +00:00
|
|
|
"PRIVMSG op_ :Hi, please review the ban 'asd!*@*' that you set on %s in #test, link: "\
|
|
|
|
"%s/bans.cgi?log=1" %(cb.bans['#test'][0].ascwhen, pluginConf.bansite()))
|
2010-03-30 20:13:51 +00:00
|
|
|
# don't ask again
|
|
|
|
cb.reviewBans()
|
|
|
|
self.assertFalse(cb.pendingReviews)
|
2010-04-04 02:48:54 +00:00
|
|
|
# test again with two ops
|
2010-04-01 20:52:53 +00:00
|
|
|
self.feedBan('asd2!*@*')
|
|
|
|
self.irc.takeMsg()
|
|
|
|
self.feedBan('qwe!*@*', prefix='otherop!user@home.net')
|
|
|
|
self.irc.takeMsg()
|
|
|
|
time.sleep(2)
|
|
|
|
cb.reviewBans()
|
|
|
|
self.assertTrue(len(cb.pendingReviews) == 2)
|
|
|
|
self.feedMsg('Hi!', frm='op!user@fakehost.net')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(msg, None)
|
2010-04-03 03:17:26 +00:00
|
|
|
self.assertResponse('banreview', 'Pending ban reviews (2): otherop:1 op:1')
|
2010-04-01 20:52:53 +00:00
|
|
|
self.feedMsg('Hi!', frm='mynickissocreative!user@home.net')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"PRIVMSG mynickissocreative :Hi, please review the ban 'qwe!*@*' that you set on %s in #test, link: "\
|
|
|
|
"%s/bans.cgi?log=3" %(cb.bans['#test'][2].ascwhen, pluginConf.bansite()))
|
|
|
|
self.feedMsg('ping', to='test', frm='op!user@host.net') # in a query
|
|
|
|
self.irc.takeMsg() # drop pong reply
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"PRIVMSG op :Hi, please review the ban 'asd2!*@*' that you set on %s in #test, link: "\
|
|
|
|
"%s/bans.cgi?log=2" %(cb.bans['#test'][1].ascwhen, pluginConf.bansite()))
|
|
|
|
|
2010-04-03 04:44:57 +00:00
|
|
|
def testReviewForward(self):
|
2010-04-03 23:06:29 +00:00
|
|
|
pluginConf.request.setValue(True)
|
2010-04-03 04:44:57 +00:00
|
|
|
pluginConf.request.forward.set('bot')
|
|
|
|
pluginConf.request.forward.channels.set('#channel')
|
|
|
|
cb = self.getCallback()
|
|
|
|
self.feedBan('asd!*@*', prefix='bot!user@host.net')
|
|
|
|
self.irc.takeMsg() # ignore comment request comment
|
|
|
|
cb.reviewBans(self.irc)
|
|
|
|
self.assertFalse(cb.pendingReviews)
|
|
|
|
print 'waiting 2 secs..'
|
|
|
|
time.sleep(2)
|
|
|
|
cb.reviewBans(self.irc)
|
|
|
|
# since it's a forward, it was sent already
|
|
|
|
self.assertFalse(cb.pendingReviews)
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"NOTICE #channel :Hi, please somebody review the ban 'asd!*@*' set by bot on %s in #test, link: "\
|
|
|
|
"%s/bans.cgi?log=1" %(cb.bans['#test'][0].ascwhen, pluginConf.bansite()))
|
|
|
|
|
2010-04-13 02:06:25 +00:00
|
|
|
def testReviewIgnore(self):
|
|
|
|
pluginConf.request.setValue(True)
|
|
|
|
pluginConf.request.ignore.set('FloodBot? FloodBotK?')
|
|
|
|
cb = self.getCallback()
|
|
|
|
self.feedBan('asd!*@*', prefix='floodbotk1!bot@botpit.com')
|
|
|
|
cb.reviewBans(self.irc)
|
|
|
|
self.assertFalse(cb.pendingReviews)
|
|
|
|
print 'waiting 2 secs..'
|
|
|
|
time.sleep(2)
|
|
|
|
cb.reviewBans(self.irc)
|
|
|
|
# since it's was ignored, it should not be queued
|
|
|
|
self.assertFalse(cb.pendingReviews)
|
|
|
|
|
2010-04-03 16:20:15 +00:00
|
|
|
def testReviewNickFallback(self):
|
|
|
|
"""If for some reason we don't have ops full hostmask, revert to nick match. This may be
|
|
|
|
needed in the future as hostmasks aren't stored in the db."""
|
2010-04-03 23:06:29 +00:00
|
|
|
pluginConf.request.setValue(True)
|
2010-04-03 16:20:15 +00:00
|
|
|
cb = self.getCallback()
|
|
|
|
self.feedBan('asd!*@*')
|
|
|
|
self.irc.takeMsg() # ignore comment request comment
|
|
|
|
cb.bans['#test'][0].who = 'op' # replace hostmask by nick
|
|
|
|
print 'waiting 2 secs..'
|
|
|
|
time.sleep(2)
|
|
|
|
cb.reviewBans()
|
|
|
|
# check is pending
|
|
|
|
self.assertTrue(cb.pendingReviews)
|
|
|
|
self.assertResponse('banreview', 'Pending ban reviews (1): op:1')
|
|
|
|
# send msg if a user with a matching nick says something
|
|
|
|
self.feedMsg('Hi!', frm='op_!user@host.net')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(msg, None)
|
|
|
|
self.feedMsg('Hi!', frm='op!user@host.net')
|
|
|
|
msg = self.irc.takeMsg()
|
|
|
|
self.assertEqual(str(msg).strip(),
|
|
|
|
"PRIVMSG op :Hi, please review the ban 'asd!*@*' that you set on %s in #test, link: "\
|
|
|
|
"%s/bans.cgi?log=1" %(cb.bans['#test'][0].ascwhen, pluginConf.bansite()))
|
|
|
|
# check not pending anymore
|
|
|
|
self.assertFalse(cb.pendingReviews)
|
|
|
|
|
2010-04-03 03:17:26 +00:00
|
|
|
def testPersistentCache(self):
|
2010-04-03 16:20:15 +00:00
|
|
|
"""Save pending reviews and when bans were last checked. This is needed for plugin
|
|
|
|
reloads"""
|
2010-04-03 03:17:26 +00:00
|
|
|
msg1 = ircmsgs.privmsg('nick', 'Hello World')
|
2010-05-14 03:09:50 +00:00
|
|
|
msg2 = ircmsgs.privmsg('nick', 'Hello World') # duplicate msg, should be ignored
|
|
|
|
msg2 = ircmsgs.privmsg('nick', 'Hello World2')
|
2010-04-03 03:17:26 +00:00
|
|
|
msg3 = ircmsgs.notice('#chan', 'Hello World')
|
|
|
|
msg4 = ircmsgs.privmsg('nick_', 'Hello World')
|
2010-04-04 04:31:15 +00:00
|
|
|
pr = self.getCallback().pendingReviews
|
2010-04-03 03:17:26 +00:00
|
|
|
pr['host.net'] = [('op', msg1), ('op', msg2), ('op_', msg3)]
|
|
|
|
pr['home.net'] = [('dude', msg4)]
|
2010-04-03 16:20:15 +00:00
|
|
|
self.assertResponse('banreview', 'Pending ban reviews (4): op_:1 dude:1 op:2')
|
2010-04-03 03:17:26 +00:00
|
|
|
pr.close()
|
|
|
|
pr.clear()
|
|
|
|
pr.open()
|
2010-04-03 16:20:15 +00:00
|
|
|
self.assertResponse('banreview', 'Pending ban reviews (4): op_:1 dude:1 op:2')
|
2010-04-03 03:17:26 +00:00
|
|
|
items = pr['host.net']
|
|
|
|
self.assertTrue(items[0][0] == 'op' and items[0][1] == msg1)
|
|
|
|
self.assertTrue(items[1][0] == 'op' and items[1][1] == msg2)
|
|
|
|
self.assertTrue(items[2][0] == 'op_' and items[2][1] == msg3)
|
|
|
|
items = pr['home.net']
|
|
|
|
self.assertTrue(items[0][0] == 'dude' and items[0][1] == msg4)
|
2010-03-30 20:13:51 +00:00
|
|
|
|
2010-04-04 04:31:15 +00:00
|
|
|
def testReviewBanreview(self):
|
|
|
|
pr = self.getCallback().pendingReviews
|
|
|
|
m = ircmsgs.privmsg('#test', 'asd')
|
|
|
|
pr['host.net'] = [('op', m), ('op_', m), ('op', m)]
|
|
|
|
pr['home.net'] = [('dude', m)]
|
|
|
|
self.assertResponse('banreview', 'Pending ban reviews (4): op_:1 dude:1 op:2')
|
|
|
|
|
2010-04-01 19:34:59 +00:00
|
|
|
def testBan(self):
|
|
|
|
self.feedBan('asd!*@*')
|
|
|
|
fetch = self.query("SELECT id,channel,mask,operator FROM bans")
|
|
|
|
self.assertEqual((1, '#test', 'asd!*@*', 'op'), fetch[0])
|
|
|
|
|
|
|
|
def testQuiet(self):
|
|
|
|
self.feedBan('asd!*@*', mode='q')
|
|
|
|
fetch = self.query("SELECT id,channel,mask,operator FROM bans")
|
|
|
|
self.assertEqual((1, '#test', '%asd!*@*', 'op'), fetch[0])
|
|
|
|
|
2010-04-03 03:17:26 +00:00
|
|
|
def testKick(self):
|
|
|
|
self.feedBan('troll', mode='k')
|
|
|
|
fetch = self.query("SELECT id,channel,mask,operator FROM bans")
|
|
|
|
self.assertEqual((1, '#test', 'troll', 'op'), fetch[0])
|
|
|
|
|
|
|
|
def testPart(self):
|
|
|
|
self.feedBan('troll!user@trollpit.net', mode='p')
|
|
|
|
fetch = self.query("SELECT id,channel,mask,operator FROM bans")
|
2010-04-13 00:33:15 +00:00
|
|
|
self.assertEqual((1, '#test', 'troll', 'op'), fetch[0])
|
2010-04-03 03:17:26 +00:00
|
|
|
|
|
|
|
|
2010-04-01 19:34:59 +00:00
|
|
|
|