Merge pull request #804 from nyuszika7h/account-notify

Implement account-notify, extended-join and WHOX
This commit is contained in:
Valentin Lorentz 2014-08-03 19:12:51 +02:00
commit 599f20588c
4 changed files with 115 additions and 33 deletions

View File

@ -167,6 +167,59 @@ class NickAuth(callbacks.Plugin):
else: else:
irc.error(_('No user has this nick on this network.')) irc.error(_('No user has this nick on this network.'))
def doAccount(self, irc, msg):
account = msg.args[0]
user = ircdb.users.getUserFromNick(irc.network, account)
if not user:
try:
user = ircdb.users.getUser(msg.prefix)
except KeyError:
user = None
if user:
if account == '*':
user.clearAuth()
else:
user.addAuth(msg.prefix)
ircdb.users.setUser(user, flush=False)
def doJoin(self, irc, msg):
if len(msg.args) < 2:
# extended-join is not supported
return
account = msg.args[1]
user = ircdb.users.getUserFromNick(irc.network, account)
if not user:
try:
user = ircdb.users.getUser(msg.prefix)
except KeyError:
user = None
if user:
if account != '*':
user.addAuth(msg.prefix)
ircdb.users.setUser(user, flush=False)
def do354(self, irc, msg):
(__, ident, host, nick, account) = msg.args
prefix = '%s!%s@%s' % (nick, ident, host)
user = ircdb.users.getUserFromNick(irc.network, account)
if not user:
try:
user = ircdb.users.getUser(prefix)
except KeyError:
user = None
if user:
if account != '0':
user.addAuth(prefix)
ircdb.users.setUser(user, flush=False)
Class = NickAuth Class = NickAuth

View File

@ -483,13 +483,21 @@ class IrcState(IrcCommandDispatcher):
def do352(self, irc, msg): def do352(self, irc, msg):
# WHO reply. # WHO reply.
(nick, user, host) = (msg.args[5], msg.args[2], msg.args[3]) (nick, user, host) = (msg.args[5], msg.args[2], msg.args[3])
hostmask = '%s!%s@%s' % (nick, user, host) hostmask = '%s!%s@%s' % (nick, user, host)
self.nicksToHostmasks[nick] = hostmask self.nicksToHostmasks[nick] = hostmask
def do354(self, irc, msg):
# WHOX reply.
(__, user, host, nick, ___) = msg.args
hostmask = '%s!%s@%s' % (nick, user, host)
self.nicksToHostmasks[nick] = hostmask
def do353(self, irc, msg): def do353(self, irc, msg):
# NAMES reply. # NAMES reply.
(_, type, channel, names) = msg.args (__, type, channel, names) = msg.args
if channel not in self.channels: if channel not in self.channels:
self.channels[channel] = ChannelState() self.channels[channel] = ChannelState()
c = self.channels[channel] c = self.channels[channel]
@ -927,25 +935,26 @@ class Irc(IrcCommandDispatcher):
if self.zombie: if self.zombie:
self.driver.die() self.driver.die()
self._reallyDie() self._reallyDie()
else:
if self.sasl_password: return
if not self.sasl_username:
log.warning('%s: SASL username is not set, unable to ' self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('LS',)))
'identify.', self.network)
else: if self.password:
log.debug("%s: Requesting capability 'sasl'.", log.info('%s: Queuing PASS command, not logging the password.',
self.network) self.network)
self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('REQ', 'sasl')))
if self.password: self.queueMsg(ircmsgs.password(self.password))
log.info('%s: Queuing PASS command, not logging the password.',
self.network) log.debug('%s: Queuing NICK command, nick is %s.',
self.queueMsg(ircmsgs.password(self.password)) self.network, self.nick)
log.debug('%s: Queuing NICK command, nick is %s.',
self.network, self.nick) self.queueMsg(ircmsgs.nick(self.nick))
self.queueMsg(ircmsgs.nick(self.nick))
log.debug('%s: Queuing USER command, ident is %s, user is %s.', log.debug('%s: Queuing USER command, ident is %s, user is %s.',
self.network, self.ident, self.user) self.network, self.ident, self.user)
self.queueMsg(ircmsgs.user(self.ident, self.user))
self.queueMsg(ircmsgs.user(self.ident, self.user))
def doAuthenticate(self, msg): def doAuthenticate(self, msg):
if msg.args[0] == '+': if msg.args[0] == '+':
@ -960,16 +969,32 @@ class Irc(IrcCommandDispatcher):
self.queueMsg(ircmsgs.IrcMsg(command='AUTHENTICATE', args=(authstring,))) self.queueMsg(ircmsgs.IrcMsg(command='AUTHENTICATE', args=(authstring,)))
def doCap(self, msg): def doCap(self, msg):
if msg.args[2] == 'sasl': caps = ['account-notify', 'extended-join']
if msg.args[1] == 'ACK':
log.debug("%s: Server acknowledged 'sasl' capability", if self.sasl_password:
self.network) if self.sasl_username:
self.queueMsg(ircmsgs.IrcMsg(command='AUTHENTICATE', caps.append('sasl')
args=('PLAIN',))) else:
log.warning('%s: SASL username is not set, unable to '
'identify.', self.network)
for cap in msg.args[2].split(' '):
if msg.args[1] == 'LS' and cap in caps:
log.debug('%s: Requesting capability %r', self.network, cap)
self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('REQ', cap)))
elif msg.args[1] == 'ACK':
log.info('%s: Server acknowledged capability %r',
self.network, cap)
if cap == 'sasl':
self.queueMsg(ircmsgs.IrcMsg(command='AUTHENTICATE',
args=('PLAIN',)))
elif msg.args[1] == 'NAK': elif msg.args[1] == 'NAK':
log.warning("%s: Server refused 'sasl' capability", log.warning('%s: Server refused capability %r',
self.network) self.network, cap)
self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('END',)))
if cap == 'sasl':
self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('END',)))
def do903(self, msg): def do903(self, msg):
log.info('%s: SASL authentication successful', self.network) log.info('%s: SASL authentication successful', self.network)
@ -1068,7 +1093,7 @@ class Irc(IrcCommandDispatcher):
def doJoin(self, msg): def doJoin(self, msg):
if msg.nick == self.nick: if msg.nick == self.nick:
channel = msg.args[0] channel = msg.args[0]
self.queueMsg(ircmsgs.who(channel)) # Ends with 315. self.queueMsg(ircmsgs.who(channel, args=('%uhna',))) # Ends with 315.
self.queueMsg(ircmsgs.mode(channel)) # Ends with 329. self.queueMsg(ircmsgs.mode(channel)) # Ends with 329.
for channel in msg.args[0].split(','): for channel in msg.args[0].split(','):
self.queueMsg(ircmsgs.mode(channel, '+b')) self.queueMsg(ircmsgs.mode(channel, '+b'))

View File

@ -736,7 +736,7 @@ def user(ident, user, prefix='', msg=None):
return IrcMsg(prefix=prefix, command='USER', return IrcMsg(prefix=prefix, command='USER',
args=(ident, '0', '*', user), msg=msg) args=(ident, '0', '*', user), msg=msg)
def who(hostmaskOrChannel, prefix='', msg=None): def who(hostmaskOrChannel, prefix='', msg=None, args=()):
"""Returns a WHO for the hostmask or channel hostmaskOrChannel.""" """Returns a WHO for the hostmask or channel hostmaskOrChannel."""
if conf.supybot.protocols.irc.strictRfc(): if conf.supybot.protocols.irc.strictRfc():
assert isChannel(hostmaskOrChannel) or \ assert isChannel(hostmaskOrChannel) or \
@ -744,7 +744,7 @@ def who(hostmaskOrChannel, prefix='', msg=None):
if msg and not prefix: if msg and not prefix:
prefix = msg.prefix prefix = msg.prefix
return IrcMsg(prefix=prefix, command='WHO', return IrcMsg(prefix=prefix, command='WHO',
args=(hostmaskOrChannel,), msg=msg) args=(hostmaskOrChannel,) + args, msg=msg)
def _whois(COMMAND, nick, mask='', prefix='', msg=None): def _whois(COMMAND, nick, mask='', prefix='', msg=None):
"""Returns a WHOIS for nick.""" """Returns a WHOIS for nick."""

View File

@ -382,6 +382,8 @@ class IrcTestCase(SupyTestCase):
m = self.irc.takeMsg() m = self.irc.takeMsg()
self.failUnless(m.command == 'NICK', 'Expected NICK, got %r.' % m) self.failUnless(m.command == 'NICK', 'Expected NICK, got %r.' % m)
m = self.irc.takeMsg() m = self.irc.takeMsg()
self.failUnless(m.command == 'CAP', 'Expected CAP, got %r.' % m)
m = self.irc.takeMsg()
self.failUnless(m.command == 'USER', 'Expected USER, got %r.' % m) self.failUnless(m.command == 'USER', 'Expected USER, got %r.' % m)
def testPingResponse(self): def testPingResponse(self):
@ -478,7 +480,9 @@ class IrcCallbackTestCase(SupyTestCase):
conf.supybot.nick.setValue(nick) conf.supybot.nick.setValue(nick)
user = 'user any user' user = 'user any user'
conf.supybot.user.setValue(user) conf.supybot.user.setValue(user)
expected = [ircmsgs.nick(nick), ircmsgs.user('limnoria', user)] expected = [ircmsgs.nick(nick),
ircmsgs.IrcMsg(command='CAP', args=('LS',)),
ircmsgs.user('limnoria', user)]
irc = irclib.Irc('test') irc = irclib.Irc('test')
msgs = [irc.takeMsg()] msgs = [irc.takeMsg()]
while msgs[-1] != None: while msgs[-1] != None: