Adapt PTGBot to OFTC

PTGBot was relying on a number of Freenode things and requires a
few changes to run on OFTC:

- Manually identify to NickServ instead of using SASL
- No longer use identify-msg capability
- Messages received are no longer prefixed by '+'

Change-Id: Ib014f58475c1eee89d34e718ee5988800602586b
This commit is contained in:
Thierry Carrez 2021-05-31 15:24:59 +02:00
parent 6445b85ccd
commit ab85e55d74
4 changed files with 54 additions and 72 deletions

View File

@ -253,7 +253,7 @@ Edit config.json contents, for example::
{ {
"irc_nick": "ptgbot", "irc_nick": "ptgbot",
"irc_server": "irc.freenode.net", "irc_server": "irc.oftc.net",
"irc_port": 6697, "irc_port": 6697,
"irc_channel": "#testptg", "irc_channel": "#testptg",
"db_filename": "html/ptg.json", "db_filename": "html/ptg.json",

View File

@ -1,7 +1,7 @@
{ {
"irc_nick": "NICK", "irc_nick": "NICK",
"irc_pass": "", "irc_pass": "",
"irc_server": "irc.freenode.net", "irc_server": "irc.oftc.net",
"irc_port": 6697, "irc_port": 6697,
"irc_channel": "#CHANNEL", "irc_channel": "#CHANNEL",
"db_filename": "html/ptg.json" "db_filename": "html/ptg.json"

View File

@ -16,7 +16,6 @@
import argparse import argparse
import collections import collections
import daemon import daemon
from ib3.auth import SASL
from ib3.connection import SSL from ib3.connection import SSL
import irc.bot import irc.bot
import json import json
@ -44,7 +43,7 @@ except ImportError:
irc.client.ServerConnection.buffer_class.errors = 'replace' irc.client.ServerConnection.buffer_class.errors = 'replace'
# If a long message is split, how long to sleep between sending parts # If a long message is split, how long to sleep between sending parts
# of a message. This is lower than the general recommended interval, # of a message. This is lower than the general recommended interval,
# but in practice freenode allows short bursts at a higher rate. # but in practice IRC networks allows short bursts at a higher rate.
MESSAGE_CONTINUATION_SLEEP = 0.5 MESSAGE_CONTINUATION_SLEEP = 0.5
# The amount of time to sleep between messages. # The amount of time to sleep between messages.
ANTI_FLOOD_SLEEP = 2 ANTI_FLOOD_SLEEP = 2
@ -62,33 +61,25 @@ def make_safe(func):
return inner return inner
class PTGBot(SASL, SSL, irc.bot.SingleServerIRCBot): class PTGBot(SSL, irc.bot.SingleServerIRCBot):
log = logging.getLogger("ptgbot.bot") log = logging.getLogger("ptgbot.bot")
def __init__(self, nickname, password, server, port, channel, db): def __init__(self, nickname, password, server, port, channel, db):
super(PTGBot, self).__init__( super(PTGBot, self).__init__(
server_list=[(server, port)], server_list=[(server, port)],
nickname=nickname, nickname=nickname,
realname=nickname, realname=nickname)
ident_password=password,
channels=[channel])
self.nickname = nickname self.nickname = nickname
self.password = password self.password = password
self.channel = channel self.channel = channel
self.identify_msg_cap = False
self.data = db self.data = db
def on_welcome(self, c, e): def on_welcome(self, c, e):
self.identify_msg_cap = False time.sleep(5)
self.log.debug("Requesting identify-msg capability") if self.password:
c.cap('REQ', 'identify-msg') self.send("NickServ", "IDENTIFY " + self.password)
c.cap('END') time.sleep(2)
self.connection.join(self.channel)
def on_cap(self, c, e):
self.log.debug("Received cap response %s" % repr(e.arguments))
if e.arguments[0] == 'ACK' and 'identify-msg' in e.arguments[1]:
self.log.debug("identify-msg cap acked")
self.identify_msg_cap = True
def usage(self, channel): def usage(self, channel):
self.send(channel, "I accept commands in the following format: " self.send(channel, "I accept commands in the following format: "
@ -104,12 +95,8 @@ class PTGBot(SASL, SSL, irc.bot.SingleServerIRCBot):
@make_safe @make_safe
def on_privmsg(self, c, e): def on_privmsg(self, c, e):
if not self.identify_msg_cap:
self.log.debug("Ignoring message because identify-msg "
"cap not enabled")
return
nick = e.source.split('!')[0] nick = e.source.split('!')[0]
args = e.arguments[0][1:] args = e.arguments[0]
words = args.split() words = args.split()
if len(words) < 1: if len(words) < 1:
self.log.debug("Ignoring privmsg with no content") self.log.debug("Ignoring privmsg with no content")
@ -148,7 +135,6 @@ class PTGBot(SASL, SSL, irc.bot.SingleServerIRCBot):
return process_user_command(self.data, nick, cmd[1:], words[1:]) return process_user_command(self.data, nick, cmd[1:], words[1:])
if cmd.startswith('#'): if cmd.startswith('#'):
if cmd in ['#in', '#out', '#seen', '#subscribe', '#unsubscribe']: if cmd in ['#in', '#out', '#seen', '#subscribe', '#unsubscribe']:
return process_user_command(self.data, nick, return process_user_command(self.data, nick,
cmd[1:], words[1:]) cmd[1:], words[1:])
@ -168,12 +154,8 @@ class PTGBot(SASL, SSL, irc.bot.SingleServerIRCBot):
@make_safe @make_safe
def on_pubmsg(self, c, e): def on_pubmsg(self, c, e):
if not self.identify_msg_cap:
self.log.debug("Ignoring message because identify-msg "
"cap not enabled")
return
nick = e.source.split('!')[0] nick = e.source.split('!')[0]
args = e.arguments[0][1:] args = e.arguments[0]
chan = e.target chan = e.target
msg = self.handle_public_command(chan, nick, args) msg = self.handle_public_command(chan, nick, args)

View File

@ -42,7 +42,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+hey ptgbot wazzzup']) ['hey ptgbot wazzzup'])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
@ -54,7 +54,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#help']) ['#help'])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
@ -69,7 +69,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#svift now Looking at me']) ['#svift now Looking at me'])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
@ -84,7 +84,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift now Looking at me']) ['#swift now Looking at me'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
@ -96,7 +96,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift next Looking at you']) ['#swift next Looking at you'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
@ -106,7 +106,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift next Looking at us']) ['#swift next Looking at us'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
@ -118,13 +118,13 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift next Looking at you']) ['#swift next Looking at you'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift now Looking at me']) ['#swift now Looking at me'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertFalse('swift' in self.db.data['next']) self.assertFalse('swift' in self.db.data['next'])
@ -133,7 +133,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift etherpad https://etherpad.opendev.org/swift']) ['#swift etherpad https://etherpad.opendev.org/swift'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
@ -143,7 +143,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift etherpad auto']) ['#swift etherpad auto'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertFalse('swift' in self.db.data['etherpads']) self.assertFalse('swift' in self.db.data['etherpads'])
@ -152,7 +152,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift url https://meetpad.opendev.org/swift']) ['#swift url https://meetpad.opendev.org/swift'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
@ -162,7 +162,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift url none']) ['#swift url none'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertFalse('swift' in self.db.data['urls']) self.assertFalse('swift' in self.db.data['urls'])
@ -171,7 +171,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift color #ffffff']) ['#swift color #ffffff'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
@ -183,7 +183,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift location On the beach']) ['#swift location On the beach'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
@ -195,7 +195,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift book Aspen-FriP1']) ['#swift book Aspen-FriP1'])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
@ -214,7 +214,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift unbook Vail-TueP2']) ['#swift unbook Vail-TueP2'])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
@ -240,7 +240,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift book ' + slot]) ['#swift book ' + slot])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'#channel', '#channel',
@ -258,7 +258,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+#swift unbook ' + slot]) ['#swift unbook ' + slot])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'#channel', '#channel',
@ -285,7 +285,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+' + cmd]) [cmd])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -300,7 +300,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+' + command]) [command])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
) as mock_send: ) as mock_send:
@ -318,7 +318,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'', '',
['+seen johndoe']) ['seen johndoe'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'janedoe', 'janedoe',
@ -328,7 +328,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+in swift']) ['in swift'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -342,7 +342,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'', '',
['+seen johndoe']) ['seen johndoe'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'janedoe', 'janedoe',
@ -353,7 +353,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+out']) ['out'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -363,7 +363,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'', '',
['+seen johndoe']) ['seen johndoe'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'janedoe', 'janedoe',
@ -378,7 +378,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+unsubscribe']) ['unsubscribe'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -388,7 +388,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+subscribe']) ['subscribe'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -398,7 +398,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+subscribe swift']) ['subscribe swift'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -412,7 +412,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+subscribe']) ['subscribe'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -422,7 +422,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'#channel', '#channel',
['+#nova now discussing with swift']) ['#nova now discussing with swift'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -432,7 +432,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+subscribe neutron']) ['subscribe neutron'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -446,14 +446,14 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'#channel', '#channel',
['+#nova now continuing discussion with swift']) ['#nova now continuing discussion with swift'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertFalse(mock_send.called) self.assertFalse(mock_send.called)
mock_send.reset_mock() mock_send.reset_mock()
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'', '',
['+unsubscribe']) ['unsubscribe'])
self.bot.on_privmsg('', msg) self.bot.on_privmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'johndoe', 'johndoe',
@ -463,7 +463,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'#channel', '#channel',
['+#neutron now doing swift things']) ['#neutron now doing swift things'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertFalse(mock_send.called) self.assertFalse(mock_send.called)
@ -471,7 +471,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+~list']) ['~list'])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
) as mock_send: ) as mock_send:
@ -506,7 +506,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+' + cmd]) [cmd])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
mock_send.assert_called_with( mock_send.assert_called_with(
'#channel', '#channel',
@ -523,7 +523,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+~add testtrack']) ['~add testtrack'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertTrue('testtrack' in self.db.data['tracks']) self.assertTrue('testtrack' in self.db.data['tracks'])
mock_send.reset_mock() mock_send.reset_mock()
@ -557,7 +557,7 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+' + cmd]) [cmd])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEqual(self.db.data['motd'], motd) self.assertEqual(self.db.data['motd'], motd)
@ -567,12 +567,12 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+~requirevoice']) ['~requirevoice'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'#channel', '#channel',
['+#swift now Looking at me']) ['#swift now Looking at me'])
with mock.patch.object( with mock.patch.object(
self.bot, 'send', self.bot, 'send',
) as mock_send: ) as mock_send:
@ -584,12 +584,12 @@ class TestProcessMessage(testtools.TestCase):
msg = Event('', msg = Event('',
'johndoe!~johndoe@openstack/member/johndoe', 'johndoe!~johndoe@openstack/member/johndoe',
'#channel', '#channel',
['+~alloweveryone']) ['~alloweveryone'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
msg = Event('', msg = Event('',
'janedoe!~janedoe@openstack/member/janedoe', 'janedoe!~janedoe@openstack/member/janedoe',
'#channel', '#channel',
['+#swift now Looking at me']) ['#swift now Looking at me'])
self.bot.on_pubmsg('', msg) self.bot.on_pubmsg('', msg)
self.assertEquals( self.assertEquals(
self.db.data['now']['swift'], self.db.data['now']['swift'],