Add support for BATCH.

This commit is contained in:
Valentin Lorentz 2015-12-04 01:37:23 +01:00
parent f880229d78
commit d2749ea4d6
3 changed files with 51 additions and 3 deletions

View File

@ -32,6 +32,7 @@ import copy
import time import time
import random import random
import base64 import base64
import collections
try: try:
from ecdsa import SigningKey, BadDigestError from ecdsa import SigningKey, BadDigestError
@ -341,6 +342,7 @@ class ChannelState(utils.python.Object):
ret = ret and getattr(self, name) == getattr(other, name) ret = ret and getattr(self, name) == getattr(other, name)
return ret return ret
Batch = collections.namedtuple('Batch', 'type arguments messages')
class IrcState(IrcCommandDispatcher, log.Firewalled): class IrcState(IrcCommandDispatcher, log.Firewalled):
"""Maintains state of the Irc connection. Should also become smarter. """Maintains state of the Irc connection. Should also become smarter.
@ -366,6 +368,7 @@ class IrcState(IrcCommandDispatcher, log.Firewalled):
self.history = history self.history = history
self.channels = channels self.channels = channels
self.nicksToHostmasks = nicksToHostmasks self.nicksToHostmasks = nicksToHostmasks
self.batches = {}
def reset(self): def reset(self):
"""Resets the state to normal, unconnected state.""" """Resets the state to normal, unconnected state."""
@ -374,6 +377,7 @@ class IrcState(IrcCommandDispatcher, log.Firewalled):
self.supported.clear() self.supported.clear()
self.nicksToHostmasks.clear() self.nicksToHostmasks.clear()
self.history.resize(conf.supybot.protocols.irc.maxHistoryLength()) self.history.resize(conf.supybot.protocols.irc.maxHistoryLength())
self.batches = {}
def __reduce__(self): def __reduce__(self):
return (self.__class__, (self.history, self.supported, return (self.__class__, (self.history, self.supported,
@ -383,7 +387,8 @@ class IrcState(IrcCommandDispatcher, log.Firewalled):
return self.history == other.history and \ return self.history == other.history and \
self.channels == other.channels and \ self.channels == other.channels and \
self.supported == other.supported and \ self.supported == other.supported and \
self.nicksToHostmasks == other.nicksToHostmasks self.nicksToHostmasks == other.nicksToHostmasks and \
self.batches == other.batches
def __ne__(self, other): def __ne__(self, other):
return not self == other return not self == other
@ -393,6 +398,7 @@ class IrcState(IrcCommandDispatcher, log.Firewalled):
ret.history = copy.deepcopy(self.history) ret.history = copy.deepcopy(self.history)
ret.nicksToHostmasks = copy.deepcopy(self.nicksToHostmasks) ret.nicksToHostmasks = copy.deepcopy(self.nicksToHostmasks)
ret.channels = copy.deepcopy(self.channels) ret.channels = copy.deepcopy(self.channels)
ret.batches = copy.deepcopy(self.batches)
return ret return ret
def addMsg(self, irc, msg): def addMsg(self, irc, msg):
@ -400,6 +406,11 @@ class IrcState(IrcCommandDispatcher, log.Firewalled):
self.history.append(msg) self.history.append(msg)
if ircutils.isUserHostmask(msg.prefix) and not msg.command == 'NICK': if ircutils.isUserHostmask(msg.prefix) and not msg.command == 'NICK':
self.nicksToHostmasks[msg.nick] = msg.prefix self.nicksToHostmasks[msg.nick] = msg.prefix
if 'batch' in msg.server_tags:
batch = msg.server_tags['batch']
assert batch in self.batches, \
'Server references undeclared batch %s' % batch
self.batches[batch].messages.append(msg)
method = self.dispatchCommand(msg.command) method = self.dispatchCommand(msg.command)
if method is not None: if method is not None:
method(irc, msg) method(irc, msg)
@ -647,6 +658,18 @@ class IrcState(IrcCommandDispatcher, log.Firewalled):
for channel in self.channels.values(): for channel in self.channels.values():
channel.replaceUser(oldNick, newNick) channel.replaceUser(oldNick, newNick)
def doBatch(self, irc, msg):
batch_name = msg.args[0][1:]
if msg.args[0].startswith('+'):
batch_type = msg.args[1]
batch_arguments = tuple(msg.args[2:])
self.batches[batch_name] = Batch(type=batch_type,
arguments=batch_arguments, messages=[])
elif msg.args[0].startswith('-'):
batch = self.batches.pop(batch_name)
msg.tag('batch', batch)
else:
assert False, msg.args[0]
### ###
@ -967,7 +990,7 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
REQUEST_CAPABILITIES = set(['account-notify', 'extended-join', REQUEST_CAPABILITIES = set(['account-notify', 'extended-join',
'multi-prefix', 'metadata-notify', 'account-tag', 'multi-prefix', 'metadata-notify', 'account-tag',
'userhost-in-names', 'invite-notify', 'server-time', 'userhost-in-names', 'invite-notify', 'server-time',
'chghost']) 'chghost', 'batch'])
def _queueConnectMessages(self): def _queueConnectMessages(self):
if self.zombie: if self.zombie:

View File

@ -186,6 +186,7 @@ class IrcMsg(object):
assert all(ircutils.isValidArgument, args), args assert all(ircutils.isValidArgument, args), args
self.args = args self.args = args
self.time = None self.time = None
self.server_tags = {}
self.args = tuple(self.args) self.args = tuple(self.args)
if isUserHostmask(self.prefix): if isUserHostmask(self.prefix):
(self.nick,self.user,self.host)=ircutils.splitHostmask(self.prefix) (self.nick,self.user,self.host)=ircutils.splitHostmask(self.prefix)

View File

@ -482,7 +482,31 @@ class IrcTestCase(SupyTestCase):
self.irc.feedMsg(ircmsgs.IrcMsg(':someuser QUIT')) self.irc.feedMsg(ircmsgs.IrcMsg(':someuser QUIT'))
finally: finally:
self.irc.removeCallback(c.name()) self.irc.removeCallback(c.name())
self.assertEqual(c.channels_set, ircutils.IrcSet({'#foo', '#bar'})) self.assertEqual(c.channels_set, ircutils.IrcSet(['#foo', '#bar']))
def testBatch(self):
self.irc.reset()
self.irc.feedMsg(ircmsgs.IrcMsg(':someuser1 JOIN #foo'))
self.irc.feedMsg(ircmsgs.IrcMsg(':host BATCH +name netjoin'))
m1 = ircmsgs.IrcMsg('@batch=name :someuser2 JOIN #foo')
self.irc.feedMsg(m1)
self.irc.feedMsg(ircmsgs.IrcMsg(':someuser3 JOIN #foo'))
m2 = ircmsgs.IrcMsg('@batch=name :someuser4 JOIN #foo')
self.irc.feedMsg(m2)
class Callback(irclib.IrcCallback):
batch = None
def name(self):
return 'testcallback'
def doBatch(self2, irc, msg):
self2.batch = msg.tagged('batch')
c = Callback()
self.irc.addCallback(c)
try:
self.irc.feedMsg(ircmsgs.IrcMsg(':host BATCH -name'))
finally:
self.irc.removeCallback(c.name())
self.assertEqual(c.batch, irclib.Batch('netjoin', (), [m1, m2]))