mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-02 17:29:22 +01:00
Updated completely.
This commit is contained in:
parent
d5a324a0d2
commit
4b5909331a
@ -181,7 +181,7 @@ class Admin(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
irc.reply(utils.commaAndify(L))
|
irc.reply(utils.commaAndify(L))
|
||||||
else:
|
else:
|
||||||
irc.reply('I\'m not currently in any channels.')
|
irc.reply('I\'m not currently in any channels.')
|
||||||
channels = commands.wrap(channels, wrappers=['private'], noExtra=True)
|
channels = commands.wrap(channels, ['private'], noExtra=True)
|
||||||
|
|
||||||
def do484(self, irc, msg):
|
def do484(self, irc, msg):
|
||||||
irc = self.pendingNickChanges.get(irc, None)
|
irc = self.pendingNickChanges.get(irc, None)
|
||||||
@ -231,7 +231,7 @@ class Admin(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
self.pendingNickChanges[irc.getRealIrc()] = irc
|
self.pendingNickChanges[irc.getRealIrc()] = irc
|
||||||
else:
|
else:
|
||||||
irc.reply(irc.nick)
|
irc.reply(irc.nick)
|
||||||
nick = commands.wrap(nick, optional=['nick'])
|
nick = commands.wrap(nick, ['?nick'])
|
||||||
|
|
||||||
def part(self, irc, msg, args):
|
def part(self, irc, msg, args):
|
||||||
"""<channel> [<channel> ...] [<reason>]
|
"""<channel> [<channel> ...] [<reason>]
|
||||||
@ -342,7 +342,7 @@ class Admin(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
expires += time.time()
|
expires += time.time()
|
||||||
ircdb.ignores.add(hostmask, expires)
|
ircdb.ignores.add(hostmask, expires)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
ignore = commands.wrap(ignore, ['hostmask'], [('int', 0)])
|
ignore = commands.wrap(ignore, ['hostmask', ('?int', 0)])
|
||||||
|
|
||||||
def unignore(self, irc, msg, args, hostmask):
|
def unignore(self, irc, msg, args, hostmask):
|
||||||
"""<hostmask|nick>
|
"""<hostmask|nick>
|
||||||
|
266
src/Channel.py
266
src/Channel.py
@ -62,50 +62,41 @@ conf.registerChannelValue(conf.supybot.plugins.Channel, 'alwaysRejoin',
|
|||||||
rejoin a channel whenever it's kicked from the channel."""))
|
rejoin a channel whenever it's kicked from the channel."""))
|
||||||
|
|
||||||
class Channel(callbacks.Privmsg):
|
class Channel(callbacks.Privmsg):
|
||||||
def haveOps(self, irc, channel, what):
|
|
||||||
try:
|
|
||||||
if irc.nick in irc.state.channels[channel].ops:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
irc.error('How can I %s? I\'m not opped in %s.' %
|
|
||||||
(what, channel))
|
|
||||||
return False
|
|
||||||
except KeyError:
|
|
||||||
irc.error('I don\'t seem to be in %s.' % channel)
|
|
||||||
|
|
||||||
def doKick(self, irc, msg):
|
def doKick(self, irc, msg):
|
||||||
channel = msg.args[0]
|
channel = msg.args[0]
|
||||||
if msg.args[1] == irc.nick:
|
if msg.args[1] == irc.nick:
|
||||||
if self.registryValue('alwaysRejoin', channel):
|
if self.registryValue('alwaysRejoin', channel):
|
||||||
irc.sendMsg(ircmsgs.join(channel)) # Fix for keys.
|
irc.sendMsg(ircmsgs.join(channel)) # Fix for keys.
|
||||||
|
|
||||||
def mode(self, irc, msg, args, channel, mode):
|
def mode(self, irc, msg, args, channel):
|
||||||
"""[<channel>] <mode> [<arg> ...]
|
"""[<channel>] <mode> [<arg> ...]
|
||||||
|
|
||||||
Sets the mode in <channel> to <mode>, sending the arguments given.
|
Sets the mode in <channel> to <mode>, sending the arguments given.
|
||||||
<channel> is only necessary if the message isn't sent in the channel
|
<channel> is only necessary if the message isn't sent in the channel
|
||||||
itself.
|
itself.
|
||||||
"""
|
"""
|
||||||
if self.haveOps(irc, channel, 'change the mode'):
|
irc.queueMsg(ircmsgs.mode(channel, args))
|
||||||
irc.queueMsg(ircmsgs.mode(channel, mode))
|
mode = commands.wrap(mode,
|
||||||
mode = commands.wrap(mode, [('channel', 'op'), 'something'])
|
['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'change the mode')],
|
||||||
|
requireExtra=True)
|
||||||
|
|
||||||
def limit(self, irc, msg, args, channel, limit):
|
def limit(self, irc, msg, args, channel, limit):
|
||||||
"""[<channel>] <limit>
|
"""[<channel>] [<limit>]
|
||||||
|
|
||||||
Sets the channel limit to <limit>. If <limit> is 0, removes the
|
Sets the channel limit to <limit>. If <limit> is 0, or isn't given,
|
||||||
channel limit. <channel> is only necessary if the message isn't sent
|
removes the channel limit. <channel> is only necessary if the message
|
||||||
in the channel itself.
|
isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
if limit < 0:
|
|
||||||
irc.error('%r is not a positive integer.' % limit, Raise=True)
|
|
||||||
if limit:
|
if limit:
|
||||||
if self.haveOps(irc, channel, 'set the limit'):
|
irc.queueMsg(ircmsgs.mode(channel, ['+l', limit]))
|
||||||
irc.queueMsg(ircmsgs.mode(channel, ['+l', limit]))
|
|
||||||
else:
|
else:
|
||||||
if self.haveOps(irc, channel, 'unset the limit'):
|
irc.queueMsg(ircmsgs.mode(channel, ['-l']))
|
||||||
irc.queueMsg(ircmsgs.mode(channel, ['-l']))
|
limit = commands.wrap(mode, ['channel',
|
||||||
limit = commands.wrap(mode, [('channel', 'op'), 'int'])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'change the limit'),
|
||||||
|
('?nonNegativeInt', 0)])
|
||||||
|
|
||||||
def moderate(self, irc, msg, args, channel):
|
def moderate(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -114,9 +105,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
send messages to the channel. <channel> is only necessary if the
|
send messages to the channel. <channel> is only necessary if the
|
||||||
message isn't sent in the channel itself.
|
message isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
if self.haveOps(irc, channel, 'moderate the channel'):
|
irc.queueMsg(ircmsgs.mode(channel, ['+m']))
|
||||||
irc.queueMsg(ircmsgs.mode(channel, ['+m']))
|
moderate = commands.wrap(moderate, ['channel',
|
||||||
moderate = commands.wrap(moderate, [('channel', 'op')])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'moderate the channel')])
|
||||||
|
|
||||||
def unmoderate(self, irc, msg, args, channel):
|
def unmoderate(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -125,9 +117,11 @@ class Channel(callbacks.Privmsg):
|
|||||||
send messages to the channel. <channel> is only necessary if the
|
send messages to the channel. <channel> is only necessary if the
|
||||||
message isn't sent in the channel itself.
|
message isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
if self.haveOps(irc, channel, 'unmoderate the channel'):
|
irc.queueMsg(ircmsgs.mode(channel, ['-m']))
|
||||||
irc.queueMsg(ircmsgs.mode(channel, ['-m']))
|
unmoderate = commands.wrap(unmoderate, ['channel',
|
||||||
unmoderate = commands.wrap(unmoderate, [('channel', 'op')])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp',
|
||||||
|
'unmoderate the channel')])
|
||||||
|
|
||||||
def key(self, irc, msg, args, channel, key):
|
def key(self, irc, msg, args, channel, key):
|
||||||
"""[<channel>] [<key>]
|
"""[<channel>] [<key>]
|
||||||
@ -137,12 +131,13 @@ class Channel(callbacks.Privmsg):
|
|||||||
if the message isn't sent in the channel itself.
|
if the message isn't sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
if key:
|
if key:
|
||||||
if self.haveOps(irc, channel, 'set the keyword'):
|
irc.queueMsg(ircmsgs.mode(channel, ['+k', key]))
|
||||||
irc.queueMsg(ircmsgs.mode(channel, ['+k', key]))
|
|
||||||
else:
|
else:
|
||||||
if self.haveOps(irc, channel, 'unset the keyword'):
|
irc.queueMsg(ircmsgs.mode(channel, ['-k']))
|
||||||
irc.queueMsg(ircmsgs.mode(channel, ['-k']))
|
key = commands.wrap(key, ['channel',
|
||||||
key = commands.wrap(key, [('channel', 'op')], ['something'])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'change the keyword'),
|
||||||
|
'?somethingWithoutSpaces'])
|
||||||
|
|
||||||
def op(self, irc, msg, args, channel):
|
def op(self, irc, msg, args, channel):
|
||||||
"""[<channel>] [<nick> ...]
|
"""[<channel>] [<nick> ...]
|
||||||
@ -154,9 +149,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
"""
|
"""
|
||||||
if not args:
|
if not args:
|
||||||
args = [msg.nick]
|
args = [msg.nick]
|
||||||
if self.haveOps(irc, channel, 'op you'):
|
irc.queueMsg(ircmsgs.ops(channel, args))
|
||||||
irc.queueMsg(ircmsgs.ops(channel, args))
|
op = commands.wrap(op, ['channel',
|
||||||
op = commands.wrap(op, [('channel', 'op')])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'op someone')])
|
||||||
|
|
||||||
def halfop(self, irc, msg, args, channel):
|
def halfop(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -168,9 +164,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
"""
|
"""
|
||||||
if not args:
|
if not args:
|
||||||
args = [msg.nick]
|
args = [msg.nick]
|
||||||
if self.haveOps(irc, channel, 'halfop you'):
|
irc.queueMsg(ircmsgs.halfops(channel, args))
|
||||||
irc.queueMsg(ircmsgs.halfops(channel, args))
|
halfop = commands.wrap(halfop, ['channel',
|
||||||
halfop = commands.wrap(halfop, [('channel', 'halfop')])
|
('checkChannelCapability', 'halfop'),
|
||||||
|
('haveOp', 'halfop someone')])
|
||||||
|
|
||||||
def voice(self, irc, msg, args, channel):
|
def voice(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -182,9 +179,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
"""
|
"""
|
||||||
if not args:
|
if not args:
|
||||||
args = [msg.nick]
|
args = [msg.nick]
|
||||||
if self.haveOps(irc, channel, 'voice you'):
|
irc.queueMsg(ircmsgs.voices(channel, args))
|
||||||
irc.queueMsg(ircmsgs.voices(channel, args))
|
voice = commands.wrap(voice, ['channel',
|
||||||
voice = commands.wrap(voice, [('channel', 'voice')])
|
('checkChannelCapability', 'voice'),
|
||||||
|
('haveOp', 'voice someone')])
|
||||||
|
|
||||||
def deop(self, irc, msg, args, channel):
|
def deop(self, irc, msg, args, channel):
|
||||||
"""[<channel>] [<nick> ...]
|
"""[<channel>] [<nick> ...]
|
||||||
@ -199,9 +197,11 @@ class Channel(callbacks.Privmsg):
|
|||||||
irc.error('I cowardly refuse to deop myself. If you really want '
|
irc.error('I cowardly refuse to deop myself. If you really want '
|
||||||
'me deopped, tell me to op you and then deop me '
|
'me deopped, tell me to op you and then deop me '
|
||||||
'yourself.')
|
'yourself.')
|
||||||
elif self.haveOps(irc, channel, 'deop someone'):
|
else:
|
||||||
irc.queueMsg(ircmsgs.deops(channel, args))
|
irc.queueMsg(ircmsgs.deops(channel, args))
|
||||||
deop = commands.wrap(deop, [('channel', 'op')])
|
deop = commands.wrap(deop, ['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'deop someone')])
|
||||||
|
|
||||||
def dehalfop(self, irc, msg, args, channel):
|
def dehalfop(self, irc, msg, args, channel):
|
||||||
"""[<channel>] [<nick> ...]
|
"""[<channel>] [<nick> ...]
|
||||||
@ -216,9 +216,11 @@ class Channel(callbacks.Privmsg):
|
|||||||
irc.error('I cowardly refuse to dehalfop myself. If you really '
|
irc.error('I cowardly refuse to dehalfop myself. If you really '
|
||||||
'want me dehalfopped, tell me to op you and then '
|
'want me dehalfopped, tell me to op you and then '
|
||||||
'dehalfop me yourself.')
|
'dehalfop me yourself.')
|
||||||
elif self.haveOps(irc, channel, 'dehalfop someone'):
|
else:
|
||||||
irc.queueMsg(ircmsgs.dehalfops(channel, args))
|
irc.queueMsg(ircmsgs.dehalfops(channel, args))
|
||||||
dehalfop = commands.wrap(dehalfop, [('channel', 'halfop')])
|
dehalfop = commands.wrap(dehalfop, ['channel',
|
||||||
|
('checkChannelCapability', 'halfop'),
|
||||||
|
('haveOp', 'dehalfop someone')])
|
||||||
|
|
||||||
def devoice(self, irc, msg, args, channel):
|
def devoice(self, irc, msg, args, channel):
|
||||||
"""[<channel>] [<nick> ...]
|
"""[<channel>] [<nick> ...]
|
||||||
@ -233,9 +235,11 @@ class Channel(callbacks.Privmsg):
|
|||||||
irc.error('I cowardly refuse to devoice myself. If you really '
|
irc.error('I cowardly refuse to devoice myself. If you really '
|
||||||
'want me devoiced, tell me to op you and then devoice '
|
'want me devoiced, tell me to op you and then devoice '
|
||||||
'me yourself.')
|
'me yourself.')
|
||||||
elif self.haveOps(irc, channel, 'devoice someone'):
|
else:
|
||||||
irc.queueMsg(ircmsgs.devoices(channel, args))
|
irc.queueMsg(ircmsgs.devoices(channel, args))
|
||||||
devoice = commands.wrap(devoice, [('channel', 'voice')])
|
devoice = commands.wrap(devoice, ['channel',
|
||||||
|
('checkChannelCapability', 'voice'),
|
||||||
|
('haveOp', 'devoice someone')])
|
||||||
|
|
||||||
def cycle(self, irc, msg, args, channel, key):
|
def cycle(self, irc, msg, args, channel, key):
|
||||||
"""[<channel>] [<key>]
|
"""[<channel>] [<key>]
|
||||||
@ -249,7 +253,9 @@ class Channel(callbacks.Privmsg):
|
|||||||
key = None
|
key = None
|
||||||
irc.queueMsg(ircmsgs.part(channel))
|
irc.queueMsg(ircmsgs.part(channel))
|
||||||
irc.queueMsg(ircmsgs.join(channel, key))
|
irc.queueMsg(ircmsgs.join(channel, key))
|
||||||
cycle = commands.wrap(cycle, [('channel', 'op')], ['something'])
|
cycle = commands.wrap(cycle, ['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
'anything'])
|
||||||
|
|
||||||
def kick(self, irc, msg, args, channel, nick, reason):
|
def kick(self, irc, msg, args, channel, nick, reason):
|
||||||
"""[<channel>] <nick> [<reason>]
|
"""[<channel>] <nick> [<reason>]
|
||||||
@ -259,21 +265,25 @@ class Channel(callbacks.Privmsg):
|
|||||||
<channel> is only necessary if the message isn't sent in the channel
|
<channel> is only necessary if the message isn't sent in the channel
|
||||||
itself.
|
itself.
|
||||||
"""
|
"""
|
||||||
if self.haveOps(irc, channel, 'kick someone'):
|
if nick not in irc.state.channels[channel].users:
|
||||||
if nick not in irc.state.channels[channel].users:
|
irc.error('%s isn\'t in %s.' % (nick, channel))
|
||||||
irc.error('%s isn\'t in %s.' % (nick, channel))
|
return
|
||||||
return
|
if not reason:
|
||||||
if not reason:
|
reason = msg.nick
|
||||||
reason = msg.nick
|
kicklen = irc.state.supported.get('kicklen', sys.maxint)
|
||||||
kicklen = irc.state.supported.get('kicklen', sys.maxint)
|
if len(reason) > kicklen:
|
||||||
if len(reason) > kicklen:
|
irc.error('The reason you gave is longer than the allowed '
|
||||||
irc.error('The reason you gave is longer than the allowed '
|
'length for a KICK reason on this server.')
|
||||||
'length for a KICK reason on this server.')
|
return
|
||||||
return
|
irc.queueMsg(ircmsgs.kick(channel, nick, reason))
|
||||||
irc.queueMsg(ircmsgs.kick(channel, nick, reason))
|
kick = commands.wrap(kick, ['channel',
|
||||||
kick = commands.wrap(kick, [('channel', 'op'), 'something'], ['something'])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'kick someone'),
|
||||||
|
'nick',
|
||||||
|
'?anything'])
|
||||||
|
|
||||||
def kban(self, irc, msg, args, channel, bannedNick, length, reason, *optlist):
|
def kban(self, irc, msg, args,
|
||||||
|
optlist, channel, bannedNick, length, reason):
|
||||||
"""[<channel>] [--{exact,nick,user,host}] <nick> [<seconds>] [<reason>]
|
"""[<channel>] [--{exact,nick,user,host}] <nick> [<seconds>] [<reason>]
|
||||||
|
|
||||||
If you have the #channel,op capability, this will kickban <nick> for
|
If you have the #channel,op capability, this will kickban <nick> for
|
||||||
@ -287,7 +297,7 @@ class Channel(callbacks.Privmsg):
|
|||||||
itself.
|
itself.
|
||||||
"""
|
"""
|
||||||
# Check that they're not trying to make us kickban ourself.
|
# Check that they're not trying to make us kickban ourself.
|
||||||
self.log.critical('In kban')
|
self.log.debug('In kban')
|
||||||
if not ircutils.isNick(bannedNick):
|
if not ircutils.isNick(bannedNick):
|
||||||
self.log.warning('%r tried to kban a non nick: %r',
|
self.log.warning('%r tried to kban a non nick: %r',
|
||||||
msg.prefix, bannedNick)
|
msg.prefix, bannedNick)
|
||||||
@ -358,29 +368,29 @@ class Channel(callbacks.Privmsg):
|
|||||||
irc.queueMsg(ircmsgs.unban(channel, banmask))
|
irc.queueMsg(ircmsgs.unban(channel, banmask))
|
||||||
schedule.addEvent(f, time.time() + length)
|
schedule.addEvent(f, time.time() + length)
|
||||||
if bannedNick == msg.nick:
|
if bannedNick == msg.nick:
|
||||||
if self.haveOps(irc, channel, 'kick or ban someone'):
|
doBan()
|
||||||
doBan()
|
|
||||||
elif ircdb.checkCapability(msg.prefix, capability):
|
elif ircdb.checkCapability(msg.prefix, capability):
|
||||||
if ircdb.checkCapability(bannedHostmask, capability):
|
if ircdb.checkCapability(bannedHostmask, capability):
|
||||||
self.log.warning('%r tried to ban %r, but both have %s',
|
self.log.warning('%s tried to ban %r, but both have %s',
|
||||||
msg.prefix, bannedHostmask, capability)
|
msg.prefix, bannedHostmask, capability)
|
||||||
irc.error('%s has %s too, you can\'t ban him/her/it.' %
|
irc.error('%s has %s too, you can\'t ban him/her/it.' %
|
||||||
(bannedNick, capability))
|
(bannedNick, capability))
|
||||||
elif self.haveOps(irc, channel, 'kick or ban someone'):
|
else:
|
||||||
doBan()
|
doBan()
|
||||||
else:
|
else:
|
||||||
self.log.warning('%r attempted kban without %s',
|
self.log.warning('%r attempted kban without %s',
|
||||||
msg.prefix, capability)
|
msg.prefix, capability)
|
||||||
irc.errorNoCapability(capability)
|
irc.errorNoCapability(capability)
|
||||||
exact,nick,user,host
|
exact,nick,user,host
|
||||||
kban = \
|
kban = commands.wrap(kban, ['channel',
|
||||||
commands.wrap(kban, ['channel', 'something'],
|
('checkChannelCapability', 'op'),
|
||||||
[('expiry', 0), 'something'],
|
('haveOp', 'kick or ban someone'),
|
||||||
getopts={'exact': None,
|
'nick', ('expiry?', 0), '?anything'],
|
||||||
'nick': None,
|
getopts={'exact': None,
|
||||||
'user': None,
|
'nick': None,
|
||||||
'host': None})
|
'user': None,
|
||||||
|
'host': None})
|
||||||
|
|
||||||
def unban(self, irc, msg, args, channel, hostmask):
|
def unban(self, irc, msg, args, channel, hostmask):
|
||||||
"""[<channel>] <hostmask>
|
"""[<channel>] <hostmask>
|
||||||
|
|
||||||
@ -389,9 +399,11 @@ class Channel(callbacks.Privmsg):
|
|||||||
the channel. <channel> is only necessary if the message isn't sent
|
the channel. <channel> is only necessary if the message isn't sent
|
||||||
in the channel itself.
|
in the channel itself.
|
||||||
"""
|
"""
|
||||||
if self.haveOps(irc, channel, 'unban someone'):
|
irc.queueMsg(ircmsgs.unban(channel, hostmask))
|
||||||
irc.queueMsg(ircmsgs.unban(channel, hostmask))
|
unban = commands.wrap(unban, ['channel',
|
||||||
unban = commands.wrap(unban, [('channel', 'op'), 'hostmask'])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'unban someone'),
|
||||||
|
'hostmask'])
|
||||||
|
|
||||||
def invite(self, irc, msg, args, channel, nick):
|
def invite(self, irc, msg, args, channel, nick):
|
||||||
"""[<channel>] <nick>
|
"""[<channel>] <nick>
|
||||||
@ -400,9 +412,11 @@ class Channel(callbacks.Privmsg):
|
|||||||
to join <channel>. <channel> is only necessary if the message isn't
|
to join <channel>. <channel> is only necessary if the message isn't
|
||||||
sent in the channel itself.
|
sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
if self.haveOps(irc, channel, 'invite someone'):
|
irc.queueMsg(ircmsgs.invite(nick, channel))
|
||||||
irc.queueMsg(ircmsgs.invite(nick, channel))
|
invite = commands.wrap(invite, ['channel',
|
||||||
invite = commands.wrap(invite, [('channel', 'op'), 'something'])
|
('checkChannelCapability', 'op'),
|
||||||
|
('haveOp', 'invite someone'),
|
||||||
|
'nick'])
|
||||||
|
|
||||||
def lobotomize(self, irc, msg, args, channel):
|
def lobotomize(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -416,7 +430,8 @@ class Channel(callbacks.Privmsg):
|
|||||||
c.lobotomized = True
|
c.lobotomized = True
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
lobotomize = commands.wrap(lobotomize, [('channel', 'op')])
|
lobotomize = commands.wrap(lobotomize, ['channel',
|
||||||
|
('checkChannelCapability', 'op')])
|
||||||
|
|
||||||
def unlobotomize(self, irc, msg, args, channel):
|
def unlobotomize(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -430,7 +445,9 @@ class Channel(callbacks.Privmsg):
|
|||||||
c.lobotomized = False
|
c.lobotomized = False
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
unlobotomize = commands.wrap(unlobotomize, [('channel', 'op')])
|
unlobotomize = commands.wrap(unlobotomize,
|
||||||
|
['channel',
|
||||||
|
('checkChannelCapability', 'op')])
|
||||||
|
|
||||||
def permban(self, irc, msg, args, channel, banmask, expires):
|
def permban(self, irc, msg, args, channel, banmask, expires):
|
||||||
"""[<channel>] <nick|hostmask> [<expires>]
|
"""[<channel>] <nick|hostmask> [<expires>]
|
||||||
@ -448,8 +465,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
c.addBan(banmask, expires)
|
c.addBan(banmask, expires)
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
permban = \
|
permban = commands.wrap(permban, ['channel',
|
||||||
commands.wrap(permban, [('channel', 'op'), 'banmask', ('expiry', 0)])
|
('checkChannelCapability', 'op'),
|
||||||
|
'hostmask',
|
||||||
|
('?expiry', 0)])
|
||||||
|
|
||||||
def unpermban(self, irc, msg, args, channel, banmask):
|
def unpermban(self, irc, msg, args, channel, banmask):
|
||||||
"""[<channel>] <hostmask>
|
"""[<channel>] <hostmask>
|
||||||
@ -458,13 +477,13 @@ class Channel(callbacks.Privmsg):
|
|||||||
ban on <hostmask>. <channel> is only necessary if the message isn't
|
ban on <hostmask>. <channel> is only necessary if the message isn't
|
||||||
sent in the channel itself.
|
sent in the channel itself.
|
||||||
"""
|
"""
|
||||||
banmask = privmsgs.getArgs(args)
|
|
||||||
c = ircdb.channels.getChannel(channel)
|
c = ircdb.channels.getChannel(channel)
|
||||||
c.removeBan(banmask)
|
c.removeBan(banmask)
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
#irc.queueMsg(ircmsgs.unban(channel, banmask))
|
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
unpermban = commands.wrap(unpermban, [('channel', 'op'), 'banmask'])
|
unpermban = commands.wrap(unpermban, ['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
'hostmask'])
|
||||||
|
|
||||||
def permbans(self, irc, msg, args, channel):
|
def permbans(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -478,7 +497,8 @@ class Channel(callbacks.Privmsg):
|
|||||||
irc.reply(utils.commaAndify(map(utils.dqrepr, c.bans)))
|
irc.reply(utils.commaAndify(map(utils.dqrepr, c.bans)))
|
||||||
else:
|
else:
|
||||||
irc.reply('There are currently no permanent bans on %s' % channel)
|
irc.reply('There are currently no permanent bans on %s' % channel)
|
||||||
permbans = commands.wrap(permbans, [('channel', 'op')])
|
permbans = commands.wrap(permbans, ['channel',
|
||||||
|
('checkChannelCapability', 'op')])
|
||||||
|
|
||||||
def ignore(self, irc, msg, args, channel, banmask, expires):
|
def ignore(self, irc, msg, args, channel, banmask, expires):
|
||||||
"""[<channel>] <nick|hostmask> [<expires>]
|
"""[<channel>] <nick|hostmask> [<expires>]
|
||||||
@ -494,8 +514,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
c.addIgnore(banmask, expires)
|
c.addIgnore(banmask, expires)
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
ignore = \
|
ignore = commands.wrap(ignore, ['channel',
|
||||||
commands.wrap(ignore,[('channel', 'op'), 'banmask', ('expiry', 0)])
|
('checkChannelCapability', 'op'),
|
||||||
|
'hostmask',
|
||||||
|
('?expiry', 0)])
|
||||||
|
|
||||||
def unignore(self, irc, msg, args, channel, banmask):
|
def unignore(self, irc, msg, args, channel, banmask):
|
||||||
"""[<channel>] <hostmask>
|
"""[<channel>] <hostmask>
|
||||||
@ -508,7 +530,9 @@ class Channel(callbacks.Privmsg):
|
|||||||
c.removeIgnore(banmask)
|
c.removeIgnore(banmask)
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
unignore = commands.wrap(unignore, [('channel', 'op'), 'something'])
|
unignore = commands.wrap(unignore, ['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
'hostmask'])
|
||||||
|
|
||||||
def ignores(self, irc, msg, args, channel):
|
def ignores(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -525,7 +549,8 @@ class Channel(callbacks.Privmsg):
|
|||||||
else:
|
else:
|
||||||
L = sorted(c.ignores)
|
L = sorted(c.ignores)
|
||||||
irc.reply(utils.commaAndify(imap(repr, L)))
|
irc.reply(utils.commaAndify(imap(repr, L)))
|
||||||
ignores = commands.wrap(ignores, [('channel', 'op')])
|
ignores = commands.wrap(ignores, ['channel',
|
||||||
|
('checkChannelCapability', 'op')])
|
||||||
|
|
||||||
def addcapability(self, irc, msg, args, channel, hostmask, capabilities):
|
def addcapability(self, irc, msg, args, channel, hostmask, capabilities):
|
||||||
"""[<channel>] <name|hostmask> <capability> [<capability> ...]
|
"""[<channel>] <name|hostmask> <capability> [<capability> ...]
|
||||||
@ -545,9 +570,11 @@ class Channel(callbacks.Privmsg):
|
|||||||
user.addCapability(c)
|
user.addCapability(c)
|
||||||
ircdb.users.setUser(id, user)
|
ircdb.users.setUser(id, user)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
addcapability = \
|
addcapability = commands.wrap(addcapability,
|
||||||
commands.wrap(addcapability,
|
['channel',
|
||||||
[('channel', 'op'), 'hostmask', 'something'])
|
('checkChannelCapability', 'op'),
|
||||||
|
'hostmask',
|
||||||
|
'somethingWithoutSpaces'])
|
||||||
|
|
||||||
def removecapability(self, irc, msg, args, channel, hostmask, capabilities):
|
def removecapability(self, irc, msg, args, channel, hostmask, capabilities):
|
||||||
"""[<channel>] <name|hostmask> <capability> [<capability> ...]
|
"""[<channel>] <name|hostmask> <capability> [<capability> ...]
|
||||||
@ -576,10 +603,14 @@ class Channel(callbacks.Privmsg):
|
|||||||
(utils.commaAndify(fail),
|
(utils.commaAndify(fail),
|
||||||
utils.pluralize('capability', len(fail))), Raise=True)
|
utils.pluralize('capability', len(fail))), Raise=True)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
removecapability = \
|
removecapability = commands.wrap(removecapability,
|
||||||
commands.wrap(removecapability,
|
['channel',
|
||||||
[('channel', 'op'), 'hostmask', 'something'])
|
('checkChannelCapability', 'op'),
|
||||||
|
'hostmask',
|
||||||
|
'somethingWithoutSpaces'])
|
||||||
|
|
||||||
|
# XXX This needs to be fix0red to be like Owner.defaultcapability. Or
|
||||||
|
# something else. This is a horrible interface.
|
||||||
def setdefaultcapability(self, irc, msg, args, channel, v):
|
def setdefaultcapability(self, irc, msg, args, channel, v):
|
||||||
"""[<channel>] {True|False}
|
"""[<channel>] {True|False}
|
||||||
|
|
||||||
@ -595,8 +626,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
c.setDefaultCapability(False)
|
c.setDefaultCapability(False)
|
||||||
ircdb.channels.setChannel(channel, c)
|
ircdb.channels.setChannel(channel, c)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
setdefaultcapability = \
|
setdefaultcapability = commands.wrap(setdefaultcapability,
|
||||||
commands.wrap(setdefaultcapability, [('channel', 'op'), 'boolean'])
|
['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
'boolean'])
|
||||||
|
|
||||||
def setcapability(self, irc, msg, args, channel, capabilities):
|
def setcapability(self, irc, msg, args, channel, capabilities):
|
||||||
"""[<channel>] <capability> [<capability> ...]
|
"""[<channel>] <capability> [<capability> ...]
|
||||||
@ -610,8 +643,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
chan.addCapability(c)
|
chan.addCapability(c)
|
||||||
ircdb.channels.setChannel(channel, chan)
|
ircdb.channels.setChannel(channel, chan)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
setcapability = \
|
setcapability = commands.wrap(setcapability,
|
||||||
commands.wrap(setcapability, [('channel', 'op'), 'something'])
|
['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
'something'])
|
||||||
|
|
||||||
def unsetcapability(self, irc, msg, args, channel, capabilities):
|
def unsetcapability(self, irc, msg, args, channel, capabilities):
|
||||||
"""[<channel>] <capability> [<capability> ...]
|
"""[<channel>] <capability> [<capability> ...]
|
||||||
@ -634,8 +669,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
(utils.commaAndify(fail),
|
(utils.commaAndify(fail),
|
||||||
utils.pluralize('capability', len(fail))), Raise=True)
|
utils.pluralize('capability', len(fail))), Raise=True)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
unsetcapability = \
|
unsetcapability = commands.wrap(unsetcapability,
|
||||||
commands.wrap(unsetcapability, [('channel', 'op'), 'something'])
|
['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
'somethingWithoutSpaces'])
|
||||||
|
|
||||||
def capabilities(self, irc, msg, args, channel):
|
def capabilities(self, irc, msg, args, channel):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
@ -645,7 +682,7 @@ class Channel(callbacks.Privmsg):
|
|||||||
"""
|
"""
|
||||||
c = ircdb.channels.getChannel(channel)
|
c = ircdb.channels.getChannel(channel)
|
||||||
L = sorted(c.capabilities)
|
L = sorted(c.capabilities)
|
||||||
irc.reply('[%s]' % '; '.join(L))
|
irc.reply(' '.join(L))
|
||||||
capabilities = commands.wrap(capabilities, ['channel'])
|
capabilities = commands.wrap(capabilities, ['channel'])
|
||||||
|
|
||||||
def lobotomies(self, irc, msg, args):
|
def lobotomies(self, irc, msg, args):
|
||||||
@ -687,15 +724,16 @@ class Channel(callbacks.Privmsg):
|
|||||||
if ircdb.checkCapability(hostmask, capability):
|
if ircdb.checkCapability(hostmask, capability):
|
||||||
irc.reply(s, to=nick, private=True)
|
irc.reply(s, to=nick, private=True)
|
||||||
|
|
||||||
def alert(self, irc, msg, args, channel):
|
def alert(self, irc, msg, args, channel, text):
|
||||||
"""[<channel>] <text>
|
"""[<channel>] <text>
|
||||||
|
|
||||||
Sends <text> to all the users in <channel> who have the <channel>,op
|
Sends <text> to all the users in <channel> who have the <channel>,op
|
||||||
capability.
|
capability.
|
||||||
"""
|
"""
|
||||||
text = privmsgs.getArgs(args)
|
|
||||||
self.alertOps(irc, channel, text, frm=msg.nick)
|
self.alertOps(irc, channel, text, frm=msg.nick)
|
||||||
alert = privmsgs.checkChannelCapability(alert, 'op')
|
alert = commands.wrap(alert, ['channel',
|
||||||
|
('checkChannelCapability', 'op'),
|
||||||
|
'something'])
|
||||||
|
|
||||||
|
|
||||||
Class = Channel
|
Class = Channel
|
||||||
|
435
src/commands.py
435
src/commands.py
@ -43,6 +43,7 @@ import time
|
|||||||
import types
|
import types
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
import supybot.log as log
|
||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
import supybot.utils as utils
|
import supybot.utils as utils
|
||||||
import supybot.world as world
|
import supybot.world as world
|
||||||
@ -69,31 +70,6 @@ def thread(f):
|
|||||||
f(self, irc, msg, args, *L, **kwargs)
|
f(self, irc, msg, args, *L, **kwargs)
|
||||||
return utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
return utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
||||||
|
|
||||||
def private(f):
|
|
||||||
"""Makes sure a command is given in private."""
|
|
||||||
def newf(self, irc, msg, args, *L, **kwargs):
|
|
||||||
if ircutils.isChannel(msg.args[0]):
|
|
||||||
irc.errorRequiresPrivacy()
|
|
||||||
else:
|
|
||||||
f(self, irc, msg, args, *L, **kwargs)
|
|
||||||
return utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
|
||||||
|
|
||||||
def checkCapability(f, capability):
|
|
||||||
"""Makes sure a user has a certain capability before a command will run.
|
|
||||||
capability can be either a string or a callable object which will be called
|
|
||||||
in order to produce a string for ircdb.checkCapability."""
|
|
||||||
def newf(self, irc, msg, args):
|
|
||||||
cap = capability
|
|
||||||
if callable(cap):
|
|
||||||
cap = cap()
|
|
||||||
if ircdb.checkCapability(msg.prefix, cap):
|
|
||||||
f(self, irc, msg, args)
|
|
||||||
else:
|
|
||||||
self.log.info('%s attempted %s without %s.',
|
|
||||||
msg.prefix, f.func_name, cap)
|
|
||||||
irc.errorNoCapability(cap)
|
|
||||||
return utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
|
||||||
|
|
||||||
class UrlSnarfThread(threading.Thread):
|
class UrlSnarfThread(threading.Thread):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
assert 'url' in kwargs
|
assert 'url' in kwargs
|
||||||
@ -158,105 +134,141 @@ def urlSnarfer(f):
|
|||||||
newf = utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
newf = utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
||||||
return newf
|
return newf
|
||||||
|
|
||||||
wrappers = ircutils.IrcDict({
|
decorators = ircutils.IrcDict({
|
||||||
'thread': thread,
|
'thread': thread,
|
||||||
'private': private,
|
|
||||||
'urlSnarfer': urlSnarfer,
|
'urlSnarfer': urlSnarfer,
|
||||||
'checkCapability': checkCapability,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# Arg wrappers, wrappers that add arguments to the command.
|
# Arg wrappers, wrappers that add arguments to the command. They accept the
|
||||||
|
# irc, msg, and args, of course, as well as a State object which holds the args
|
||||||
|
# (and kwargs, though none currently take advantage of that) to be given to the
|
||||||
|
# command being decorated, as well as the name of the command, the plugin, the
|
||||||
|
# log, etc.
|
||||||
###
|
###
|
||||||
def getInt(irc, msg, args, default=None, type='integer'):
|
|
||||||
s = args.pop(0)
|
# This is just so we can centralize this, since it may change.
|
||||||
|
def _int(s):
|
||||||
|
return int(float(s))
|
||||||
|
|
||||||
|
def getInt(irc, msg, args, state, default=None, type='integer', p=None):
|
||||||
try:
|
try:
|
||||||
return int(s)
|
i = _int(args[0])
|
||||||
|
if p is not None:
|
||||||
|
if not p(i):
|
||||||
|
raise ValueError
|
||||||
|
state.args.append(_int(args[0]))
|
||||||
|
del args[0]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
if default is not None:
|
if default is not None:
|
||||||
return default
|
state.args.append(default)
|
||||||
else:
|
else:
|
||||||
irc.errorInvalid(type, s, Raise=True)
|
irc.errorInvalid(type, args[0])
|
||||||
|
|
||||||
def getId(irc, msg, args):
|
def getPositiveInt(irc, msg, args, state, *L):
|
||||||
getInt(irc, msg, args, type='id')
|
getInt(irc, msg, args, state,
|
||||||
|
p=lambda i: i<=0, type='positive integer', *L)
|
||||||
|
|
||||||
def getExpiry(irc, msg, args, default=None):
|
def getNonNegativeInt(irc, msg, args, state, *L):
|
||||||
s = args.pop(0)
|
getInt(irc, msg, args, state,
|
||||||
|
p=lambda i: i<0, type='non-negative integer', *L)
|
||||||
|
|
||||||
|
def getId(irc, msg, args, state):
|
||||||
|
getInt(irc, msg, args, state, type='id')
|
||||||
|
|
||||||
|
def getExpiry(irc, msg, args, state, default=None):
|
||||||
|
now = int(time.time())
|
||||||
try:
|
try:
|
||||||
expires = int(float(s))
|
expires = _int(args[0])
|
||||||
expires += int(time.time())
|
if expires:
|
||||||
|
expires += now
|
||||||
|
state.args.append(expires)
|
||||||
|
del args[0]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
if default is not None:
|
if default is not None:
|
||||||
return default
|
if default:
|
||||||
|
default += now
|
||||||
|
state.args.append(default)
|
||||||
else:
|
else:
|
||||||
irc.errorInvalid('number of seconds', s, Raise=True)
|
irc.errorInvalid('number of seconds', args[0])
|
||||||
|
# XXX This should be handled elsewhere; perhaps all optional args should
|
||||||
|
# consider their first extra arg to be a default.
|
||||||
|
except IndexError:
|
||||||
|
if default is not None:
|
||||||
|
if default:
|
||||||
|
default += now
|
||||||
|
state.args.append(default)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
def getBoolean(irc, msg, args, default=None):
|
def getBoolean(irc, msg, args, state, default=None):
|
||||||
s = args.pop(0).strip().lower()
|
try:
|
||||||
if s in ('true', 'on', 'enable', 'enabled'):
|
state.args.append(utils.toBool(args[0]))
|
||||||
return True
|
del args[0]
|
||||||
elif s in ('false', 'off', 'disable', 'disabled'):
|
except ValueError:
|
||||||
return False
|
if default is not None:
|
||||||
elif default is not None:
|
state.args.append(default)
|
||||||
return default
|
else:
|
||||||
else:
|
irc.errorInvalid('boolean', args[0])
|
||||||
irc.error("Value must be either True or False (or On or Off).",
|
|
||||||
Raise=True)
|
|
||||||
|
|
||||||
def getChannelDb(irc, msg, args, **kwargs):
|
def getChannelDb(irc, msg, args, state, **kwargs):
|
||||||
if not conf.supybot.databases.plugins.channelSpecific():
|
if not conf.supybot.databases.plugins.channelSpecific():
|
||||||
return None
|
state.args.append(None)
|
||||||
|
state.channel = None
|
||||||
else:
|
else:
|
||||||
return channel(irc, msg, args, **kwargs)
|
getChannel(irc, msg, args, state, **kwargs)
|
||||||
|
|
||||||
def validChannel(irc, msg, args):
|
def getHaveOp(irc, msg, args, state, action='do that'):
|
||||||
s = args.pop(0)
|
if state.channel not in irc.state.channels:
|
||||||
if ircutils.isChannel(s):
|
irc.error('I\'m not even in %s.' % state.channel, Raise=True)
|
||||||
return s
|
if irc.nick not in irc.state.channels[state.channel].ops:
|
||||||
|
irc.error('I need to be opped to %s.' % action, Raise=True)
|
||||||
|
|
||||||
|
def validChannel(irc, msg, args, state):
|
||||||
|
if ircutils.isChannel(args[0]):
|
||||||
|
# XXX Check maxlength in irc.state.supported.
|
||||||
|
state.args.append(args.pop(0))
|
||||||
else:
|
else:
|
||||||
irc.errorInvalid('channel', s, Raise=True)
|
irc.errorInvalid('channel', args[0])
|
||||||
|
|
||||||
def getHostmask(irc, msg, args):
|
def getHostmask(irc, msg, args, state):
|
||||||
if ircutils.isUserHostmask(args[0]):
|
if ircutils.isUserHostmask(args[0]):
|
||||||
return args.pop(0)
|
state.args.append(args.pop(0))
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
s = args.pop(0)
|
hostmask = irc.state.nickToHostmask(args[0])
|
||||||
return irc.state.nickToHostmask(s)
|
state.args.append(hostmask)
|
||||||
|
del args[0]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
irc.errorInvalid('nick or hostmask', s, Raise=True)
|
irc.errorInvalid('nick or hostmask', args[0])
|
||||||
|
|
||||||
def getBanmask(irc, msg, args):
|
def getBanmask(irc, msg, args, state):
|
||||||
if ircutils.isUserHostmask(args[0]):
|
getHostmask(irc, msg, args, state)
|
||||||
return args.pop(0)
|
# XXX Channel-specific stuff.
|
||||||
else:
|
state.args[-1] = ircutils.banmask(state.args[-1])
|
||||||
try:
|
|
||||||
s = args.pop(0)
|
|
||||||
return ircutils.banmask(irc.state.nickToHostmask(s))
|
|
||||||
except KeyError:
|
|
||||||
irc.errorInvalid('nick or hostmask', s, Raise=True)
|
|
||||||
|
|
||||||
def getUser(irc, msg, args):
|
def getUser(irc, msg, args, state):
|
||||||
try:
|
try:
|
||||||
return ircdb.users.getUser(msg.prefix)
|
state.args.append(ircdb.users.getUser(msg.prefix))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
irc.errorNotRegistered(Raise=True)
|
irc.errorNotRegistered(Raise=True)
|
||||||
|
|
||||||
def getOtherUser(irc, msg, args):
|
def getOtherUser(irc, msg, args, state):
|
||||||
s = args.pop(0)
|
|
||||||
try:
|
try:
|
||||||
return ircdb.users.getUser(s)
|
state.args.append(ircdb.users.getUser(args[0]))
|
||||||
|
del args[0]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
try:
|
try:
|
||||||
hostmask = getHostmask(irc, msg, [s])
|
getHostmask(irc, msg, args, state)
|
||||||
return ircdb.users.getUser(hostmask)
|
hostmask = state.args.pop()
|
||||||
|
state.args.append(ircdb.users.getUser(hostmask))
|
||||||
except (KeyError, IndexError, callbacks.Error):
|
except (KeyError, IndexError, callbacks.Error):
|
||||||
irc.errorNoUser(Raise=True)
|
irc.errorNoUser(Raise=True)
|
||||||
|
|
||||||
def _getRe(f):
|
def _getRe(f):
|
||||||
def get(irc, msg, args):
|
def get(irc, msg, args, state):
|
||||||
|
original = args[:]
|
||||||
s = args.pop(0)
|
s = args.pop(0)
|
||||||
def isRe(s):
|
def isRe(s):
|
||||||
try:
|
try:
|
||||||
@ -264,170 +276,233 @@ def _getRe(f):
|
|||||||
return True
|
return True
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
while not isRe(s):
|
try:
|
||||||
s += ' ' + args.pop(0)
|
while not isRe(s):
|
||||||
return f(s)
|
s += ' ' + args.pop(0)
|
||||||
|
state.args.append(f(s))
|
||||||
|
except IndexError:
|
||||||
|
args[:] = original
|
||||||
|
raise
|
||||||
return get
|
return get
|
||||||
|
|
||||||
getMatcher = _getRe(utils.perlReToPythonRe)
|
getMatcher = _getRe(utils.perlReToPythonRe)
|
||||||
getReplacer = _getRe(utils.perlReToReplacer)
|
getReplacer = _getRe(utils.perlReToReplacer)
|
||||||
|
|
||||||
def getNick(irc, msg, args):
|
def getNick(irc, msg, args, state):
|
||||||
s = args.pop(0)
|
if ircutils.isNick(args[0]):
|
||||||
if ircutils.isNick(s):
|
|
||||||
if 'nicklen' in irc.state.supported:
|
if 'nicklen' in irc.state.supported:
|
||||||
if len(s) > irc.state.supported['nicklen']:
|
if len(args[0]) > irc.state.supported['nicklen']:
|
||||||
irc.errorInvalid('nick', s,
|
irc.errorInvalid('nick', s,
|
||||||
'That nick is too long for this server.',
|
'That nick is too long for this server.')
|
||||||
Raise=True)
|
state.args.append(args.pop(0))
|
||||||
return s
|
|
||||||
else:
|
else:
|
||||||
irc.errorInvalid('nick', s, Raise=True)
|
irc.errorInvalid('nick', s)
|
||||||
|
|
||||||
def getChannel(irc, msg, args, cap=None):
|
def getChannel(irc, msg, args, state):
|
||||||
if ircutils.isChannel(args[0]):
|
if args and ircutils.isChannel(args[0]):
|
||||||
channel = args.pop(0)
|
channel = args.pop(0)
|
||||||
elif ircutils.isChannel(msg.args[0]):
|
elif ircutils.isChannel(msg.args[0]):
|
||||||
channel = msg.args[0]
|
channel = msg.args[0]
|
||||||
else:
|
else:
|
||||||
|
state.log.debug('Raising ArgumentError because there is no channel.')
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
if cap is not None:
|
state.channel = channel
|
||||||
if callable(cap):
|
state.args.append(channel)
|
||||||
cap = cap()
|
|
||||||
cap = ircdb.makeChannelCapability(channel, cap)
|
|
||||||
if not ircdb.checkCapability(msg.prefix, cap):
|
|
||||||
irc.errorNoCapability(cap, Raise=True)
|
|
||||||
return channel
|
|
||||||
|
|
||||||
def getLowered(irc, msg, args):
|
def checkChannelCapability(irc, msg, args, state, cap):
|
||||||
return ircutils.toLower(args.pop(0))
|
assert state.channel, \
|
||||||
|
'You must use a channel arg before you use checkChannelCapability.'
|
||||||
|
cap = ircdb.canonicalCapability(cap)
|
||||||
|
cap = ircdb.makeChannelCapability(state.channel, cap)
|
||||||
|
if not ircdb.checkCapability(msg.prefix, cap):
|
||||||
|
irc.errorNoCapability(cap, Raise=True)
|
||||||
|
|
||||||
|
def getLowered(irc, msg, args, state):
|
||||||
|
state.args.append(ircutils.toLower(args.pop(0)))
|
||||||
|
|
||||||
def getSomething(irc, msg, args):
|
def getSomething(irc, msg, args, state, errorMsg=None, p=None):
|
||||||
s = args.pop(0)
|
if p is None:
|
||||||
if not s:
|
p = lambda _: True
|
||||||
# XXX Better reply? How?
|
if not args[0] or not p(args[0]):
|
||||||
irc.error('You must not give the empty string as an argument.',
|
if errorMsg is None:
|
||||||
Raise=True)
|
errorMsg = 'You must not give the empty string as an argument.'
|
||||||
return s
|
irc.error(errorMsg, Raise=True)
|
||||||
|
else:
|
||||||
|
state.args.append(args.pop(0))
|
||||||
|
|
||||||
def getPlugin(irc, msg, args, requirePresent=False):
|
def getSomethingNoSpaces(irc, msg, args, state, *L):
|
||||||
s = args.pop(0)
|
def p(s):
|
||||||
cb = irc.getCallback(s)
|
return len(s.split(None, 1)) == 1
|
||||||
|
getSomething(irc, msg, args, state, p=p, *L)
|
||||||
|
|
||||||
|
def getPlugin(irc, msg, args, state, requirePresent=False):
|
||||||
|
cb = irc.getCallback(args[0])
|
||||||
if requirePresent and cb is None:
|
if requirePresent and cb is None:
|
||||||
irc.errorInvalid('plugin', s, Raise=True)
|
irc.errorInvalid('plugin', s)
|
||||||
return cb
|
state.args.append(cb)
|
||||||
|
del args[0]
|
||||||
|
|
||||||
argWrappers = ircutils.IrcDict({
|
def private(irc, msg, args, state):
|
||||||
|
if ircutils.isChannel(msg.args[0]):
|
||||||
|
irc.errorRequiresPrivacy(Raise=True)
|
||||||
|
|
||||||
|
def checkCapability(irc, msg, args, state, cap):
|
||||||
|
cap = ircdb.canonicalCapability(cap)
|
||||||
|
if not ircdb.checkCapability(msg.prefix, cap):
|
||||||
|
state.log.warning('%s tried %s without %s.',
|
||||||
|
msg.prefix, state.name, cap)
|
||||||
|
irc.errorNoCapability(cap, Raise=True)
|
||||||
|
|
||||||
|
def anything(irc, msg, args, state):
|
||||||
|
state.args.append(args.pop(0))
|
||||||
|
|
||||||
|
wrappers = ircutils.IrcDict({
|
||||||
'id': getId,
|
'id': getId,
|
||||||
'int': getInt,
|
'int': getInt,
|
||||||
|
'positiveInt': getPositiveInt,
|
||||||
|
'nonNegativeInt': getNonNegativeInt,
|
||||||
|
'haveOp': getHaveOp,
|
||||||
'expiry': getExpiry,
|
'expiry': getExpiry,
|
||||||
'nick': getNick,
|
'nick': getNick,
|
||||||
'channel': getChannel,
|
'channel': getChannel,
|
||||||
'plugin': getPlugin,
|
'plugin': getPlugin,
|
||||||
'boolean': getBoolean,
|
'boolean': getBoolean,
|
||||||
'lowered': getLowered,
|
'lowered': getLowered,
|
||||||
|
'anything': anything,
|
||||||
'something': getSomething,
|
'something': getSomething,
|
||||||
|
'somethingWithoutSpaces': getSomethingNoSpaces,
|
||||||
'channelDb': getChannelDb,
|
'channelDb': getChannelDb,
|
||||||
'hostmask': getHostmask,
|
'hostmask': getHostmask,
|
||||||
'banmask': getBanmask,
|
'banmask': getBanmask,
|
||||||
'user': getUser,
|
'user': getUser,
|
||||||
|
'private': private,
|
||||||
'otherUser': getOtherUser,
|
'otherUser': getOtherUser,
|
||||||
'regexpMatcher': getMatcher,
|
'regexpMatcher': getMatcher,
|
||||||
'validChannel': validChannel,
|
'validChannel': validChannel,
|
||||||
'regexpReplacer': getReplacer,
|
'regexpReplacer': getReplacer,
|
||||||
|
'checkCapability': checkCapability,
|
||||||
|
'checkChannelCapability': checkChannelCapability,
|
||||||
})
|
})
|
||||||
|
|
||||||
def args(irc,msg,args, required=[], optional=[], getopts=None, noExtra=False):
|
class State(object):
|
||||||
starArgs = []
|
def __init__(self, name=None, logger=None):
|
||||||
req = required[:]
|
if logger is None:
|
||||||
opt = optional[:]
|
logger = log
|
||||||
|
self.args = []
|
||||||
|
self.kwargs = {}
|
||||||
|
self.name = name
|
||||||
|
self.log = logger
|
||||||
|
self.getopts = []
|
||||||
|
self.channel = None
|
||||||
|
|
||||||
|
def args(irc,msg,args, types=[], state=None,
|
||||||
|
getopts=None, noExtra=False, requireExtra=False, combineRest=True):
|
||||||
|
orig = args[:]
|
||||||
|
if state is None:
|
||||||
|
state = State(name='unknown', logger=log)
|
||||||
|
if requireExtra:
|
||||||
|
combineRest = False # Implied by requireExtra.
|
||||||
|
types = types[:] # We're going to destroy this.
|
||||||
if getopts is not None:
|
if getopts is not None:
|
||||||
getoptL = []
|
getoptL = []
|
||||||
for (key, value) in getopts.iteritems():
|
for (key, value) in getopts.iteritems():
|
||||||
if value != '': # value can be None, remember.
|
if value != '': # value can be None, remember.
|
||||||
key += '='
|
key += '='
|
||||||
getoptL.append(key)
|
getoptL.append(key)
|
||||||
def getArgWrapper(x):
|
def callWrapper(spec):
|
||||||
if isinstance(x, tuple):
|
if isinstance(spec, tuple):
|
||||||
assert x
|
assert spec, 'tuple specification cannot be empty.'
|
||||||
name = x[0]
|
name = spec[0]
|
||||||
args = x[1:]
|
specArgs = spec[1:]
|
||||||
else:
|
else:
|
||||||
assert isinstance(x, basestring) or x is None
|
assert isinstance(spec, basestring) or spec is None
|
||||||
name = x
|
name = spec
|
||||||
args = ()
|
specArgs = ()
|
||||||
if name is not None:
|
if name is None:
|
||||||
return argWrappers[name], args
|
name = 'anything'
|
||||||
else:
|
enforce = True
|
||||||
return lambda irc, msg, args: args.pop(0), args
|
optional = False
|
||||||
def getConversion(name):
|
if name.startswith('?'):
|
||||||
(converter, convertArgs) = getArgWrapper(name)
|
optional = True
|
||||||
v = converter(irc, msg, args, *convertArgs)
|
name = name[1:]
|
||||||
return v
|
elif name.endswith('?'):
|
||||||
def callConverter(name):
|
optional = True
|
||||||
v = getConversion(name)
|
enforce = False
|
||||||
starArgs.append(v)
|
name = name[:-1]
|
||||||
|
wrapper = wrappers[name]
|
||||||
|
try:
|
||||||
|
wrapper(irc, msg, args, state, *specArgs)
|
||||||
|
except (callbacks.Error, ValueError, callbacks.ArgumentError), e:
|
||||||
|
state.log.debug('%r when calling wrapper.', utils.exnToString(e))
|
||||||
|
if not enforce:
|
||||||
|
state.args.append('')
|
||||||
|
else:
|
||||||
|
state.log.debug('Re-raising %s because of enforce.', e)
|
||||||
|
raise
|
||||||
|
except IndexError, e:
|
||||||
|
state.log.debug('%r when calling wrapper.', utils.exnToString(e))
|
||||||
|
if optional:
|
||||||
|
state.args.append('')
|
||||||
|
else:
|
||||||
|
state.log.debug('Raising ArgumentError because of '
|
||||||
|
'non-optional args.')
|
||||||
|
raise callbacks.ArgumentError
|
||||||
|
|
||||||
# First, we getopt stuff.
|
# First, we getopt stuff.
|
||||||
if getopts is not None:
|
if getopts is not None:
|
||||||
L = []
|
|
||||||
(optlist, args) = getopt.getopt(args, '', getoptL)
|
(optlist, args) = getopt.getopt(args, '', getoptL)
|
||||||
for (opt, arg) in optlist:
|
for (opt, arg) in optlist:
|
||||||
opt = opt[2:] # Strip --
|
opt = opt[2:] # Strip --
|
||||||
assert opt in getopts
|
assert opt in getopts
|
||||||
if arg is not None:
|
if arg is not None:
|
||||||
assert getopts[opt] != ''
|
assert getopts[opt] != ''
|
||||||
L.append((opt, getConversion(getopts[opt])))
|
state.getopts.append((opt, callWrapper(getopts[opt])))
|
||||||
else:
|
else:
|
||||||
assert getopts[opt] == ''
|
assert getopts[opt] == ''
|
||||||
L.append((opt, True))
|
state.getopts.append((opt, True))
|
||||||
starArgs.append(L)
|
|
||||||
|
|
||||||
# Second, we get out everything but the last argument.
|
# Second, we get out everything but the last argument (or, if combineRest
|
||||||
try:
|
# is False, we'll clear out all the types).
|
||||||
while len(req) + len(opt) > 1:
|
while len(types) > 1 or (types and not combineRest):
|
||||||
if req:
|
callWrapper(types.pop(0))
|
||||||
callConverter(req.pop(0))
|
# Third, if there is a remaining required or optional argument
|
||||||
else:
|
# (there's a possibility that there were no required or optional
|
||||||
assert opt
|
# arguments) then we join the remaining args and work convert that.
|
||||||
callConverter(opt.pop(0))
|
if types:
|
||||||
# Third, if there is a remaining required or optional argument
|
assert len(types) == 1
|
||||||
# (there's a possibility that there were no required or optional
|
if args:
|
||||||
# arguments) then we join the remaining args and work convert that.
|
|
||||||
if req or opt:
|
|
||||||
rest = ' '.join(args)
|
rest = ' '.join(args)
|
||||||
args = [rest]
|
args = [rest]
|
||||||
if required:
|
callWrapper(types.pop(0))
|
||||||
converterName = req.pop(0)
|
|
||||||
else:
|
|
||||||
converterName = opt.pop(0)
|
|
||||||
callConverter(converterName)
|
|
||||||
except IndexError:
|
|
||||||
if req:
|
|
||||||
raise callbacks.ArgumentError
|
|
||||||
while opt:
|
|
||||||
del opt[-1]
|
|
||||||
starArgs.append('')
|
|
||||||
if noExtra and args:
|
if noExtra and args:
|
||||||
|
log.debug('noExtra and args: %r (originally %r)', args, orig)
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
return starArgs
|
if requireExtra and not args:
|
||||||
|
log.debug('requireExtra and not args: %r (originally %r)', args, orig)
|
||||||
|
log.debug('args: %r' % args)
|
||||||
|
log.debug('State.args: %r' % state.args)
|
||||||
|
log.debug('State.getopts: %r' % state.getopts)
|
||||||
|
return state
|
||||||
|
|
||||||
# These are used below, but we need to rename them so their names aren't
|
# These are used below, but we need to rename them so their names aren't
|
||||||
# shadowed by our locals.
|
# shadowed by our locals.
|
||||||
_args = args
|
_args = args
|
||||||
_wrappers = wrappers
|
_decorators = decorators
|
||||||
def wrap(f, required=[], optional=[],
|
def wrap(f, *argsArgs, **argsKwargs):
|
||||||
wrappers=None, getopts=None, noExtra=False):
|
|
||||||
def newf(self, irc, msg, args, **kwargs):
|
def newf(self, irc, msg, args, **kwargs):
|
||||||
starArgs = _args(irc, msg, args,
|
state = State('%s.%s' % (self.name(), f.func_name), self.log)
|
||||||
getopts=getopts, noExtra=noExtra,
|
state.cb = self # This should probably be in State.__init__.
|
||||||
required=required, optional=optional)
|
_args(irc,msg,args, state=state, *argsArgs, **argsKwargs)
|
||||||
f(self, irc, msg, args, *starArgs, **kwargs)
|
if state.getopts:
|
||||||
|
f(self, irc, msg, args, state.getopts, *state.args, **state.kwargs)
|
||||||
|
else:
|
||||||
|
f(self, irc, msg, args, *state.args, **state.kwargs)
|
||||||
|
|
||||||
if wrappers is not None:
|
decorators = argsKwargs.pop('decorators', None)
|
||||||
wrappers = map(_wrappers.__getitem__, wrappers)
|
if decorators is not None:
|
||||||
for wrapper in wrappers:
|
decorators = map(_decorators.__getitem__, decorators)
|
||||||
newf = wrapper(newf)
|
for decorator in decorators:
|
||||||
|
newf = decorator(newf)
|
||||||
return utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
return utils.changeFunctionName(newf, f.func_name, f.__doc__)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user