mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-26 20:59:27 +01:00
A bunch more %r -> %s conversions as well as wrap updates, new policy for
Channel.voice and some bug fixes for Debian
This commit is contained in:
parent
2adef7c265
commit
cbd5abbab7
@ -124,7 +124,7 @@ class Debian(callbacks.Privmsg,
|
|||||||
# that).
|
# that).
|
||||||
if not optlist and not glob:
|
if not optlist and not glob:
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
if optlist and glob > 1:
|
if optlist and glob:
|
||||||
irc.error('You must specify either a glob or a regexp/exact '
|
irc.error('You must specify either a glob or a regexp/exact '
|
||||||
'search, but not both.')
|
'search, but not both.')
|
||||||
for (option, arg) in optlist:
|
for (option, arg) in optlist:
|
||||||
@ -181,8 +181,8 @@ class Debian(callbacks.Privmsg,
|
|||||||
irc.reply('I found no packages with that file.')
|
irc.reply('I found no packages with that file.')
|
||||||
else:
|
else:
|
||||||
irc.reply(utils.commaAndify(packages))
|
irc.reply(utils.commaAndify(packages))
|
||||||
file = wrap(file, [getopts({'regexp':'regexpMatcher', 'exact':'text'}),
|
file = wrap(file, [getopts({'regexp':'regexpMatcher','exact':'something'}),
|
||||||
additional('text')])
|
additional('glob')])
|
||||||
|
|
||||||
_debreflags = re.DOTALL | re.IGNORECASE
|
_debreflags = re.DOTALL | re.IGNORECASE
|
||||||
_deblistre = re.compile(r'<h3>Package ([^<]+)</h3>(.*?)</ul>', _debreflags)
|
_deblistre = re.compile(r'<h3>Package ([^<]+)</h3>(.*?)</ul>', _debreflags)
|
||||||
@ -264,8 +264,8 @@ class Debian(callbacks.Privmsg,
|
|||||||
archPredicate = lambda s, arg=arg: (arg in s)
|
archPredicate = lambda s, arg=arg: (arg in s)
|
||||||
predicates.append(archPredicate)
|
predicates.append(archPredicate)
|
||||||
for glob in globs:
|
for glob in globs:
|
||||||
glob = glob.replace('*', '.*').replace('?', '.?')
|
glob = fnmatch.translate(glob)
|
||||||
predicates.append(re.compile(r'.*%s.*' % glob).search)
|
predicates.append(re.compile(glob).search)
|
||||||
packages = []
|
packages = []
|
||||||
try:
|
try:
|
||||||
fd = webutils.getUrlFd('http://incoming.debian.org/')
|
fd = webutils.getUrlFd('http://incoming.debian.org/')
|
||||||
@ -285,18 +285,16 @@ class Debian(callbacks.Privmsg,
|
|||||||
irc.reply(utils.commaAndify(packages))
|
irc.reply(utils.commaAndify(packages))
|
||||||
incoming = thread(wrap(incoming,
|
incoming = thread(wrap(incoming,
|
||||||
[getopts({'regexp':'regexpMatcher', 'arch':'text'}),
|
[getopts({'regexp':'regexpMatcher', 'arch':'text'}),
|
||||||
any('text')]))
|
any('glob')]))
|
||||||
|
|
||||||
_newpkgre = re.compile(r'<li><a href[^>]+>([^<]+)</a>')
|
_newpkgre = re.compile(r'<li><a href[^>]+>([^<]+)</a>')
|
||||||
def new(self, irc, msg, args, optlist, glob):
|
def new(self, irc, msg, args, section, glob):
|
||||||
"""[{main,contrib,non-free}] [<glob>]
|
"""[{main,contrib,non-free}] [<glob>]
|
||||||
|
|
||||||
Checks for packages that have been added to Debian's unstable branch
|
Checks for packages that have been added to Debian's unstable branch
|
||||||
in the past week. If no glob is specified, returns a list of all
|
in the past week. If no glob is specified, returns a list of all
|
||||||
packages. If no section is specified, defaults to main.
|
packages. If no section is specified, defaults to main.
|
||||||
"""
|
"""
|
||||||
if '?' not in glob and '*' not in glob:
|
|
||||||
glob = '*%s*' % glob
|
|
||||||
try:
|
try:
|
||||||
fd = webutils.getUrlFd(
|
fd = webutils.getUrlFd(
|
||||||
'http://packages.debian.org/unstable/newpkg_%s' % section)
|
'http://packages.debian.org/unstable/newpkg_%s' % section)
|
||||||
@ -316,7 +314,7 @@ class Debian(callbacks.Privmsg,
|
|||||||
irc.error('No packages matched that search.')
|
irc.error('No packages matched that search.')
|
||||||
new = wrap(new, [optional(('literal', ('main', 'contrib', 'non-free')),
|
new = wrap(new, [optional(('literal', ('main', 'contrib', 'non-free')),
|
||||||
'main'),
|
'main'),
|
||||||
additional('text', '*')])
|
additional('glob', '*')])
|
||||||
|
|
||||||
_severity = re.compile(r'.*(?:severity set to `([^\']+)\'|'
|
_severity = re.compile(r'.*(?:severity set to `([^\']+)\'|'
|
||||||
r'severity:\s+([^\s]+))', re.I)
|
r'severity:\s+([^\s]+))', re.I)
|
||||||
|
@ -163,7 +163,7 @@ class Channel(callbacks.Privmsg):
|
|||||||
irc.queueMsg(ircmsgs.halfops(channel, nicks))
|
irc.queueMsg(ircmsgs.halfops(channel, nicks))
|
||||||
halfop = wrap(halfop, [('checkChannelCapability', 'halfop'),
|
halfop = wrap(halfop, [('checkChannelCapability', 'halfop'),
|
||||||
('haveOp', 'halfop someone'),
|
('haveOp', 'halfop someone'),
|
||||||
many('nickInChannel')])
|
any('nickInChannel')])
|
||||||
|
|
||||||
def voice(self, irc, msg, args, channel, nicks):
|
def voice(self, irc, msg, args, channel, nicks):
|
||||||
"""[<channel>] [<nick> ...]
|
"""[<channel>] [<nick> ...]
|
||||||
@ -173,12 +173,21 @@ class Channel(callbacks.Privmsg):
|
|||||||
voice you. <channel> is only necessary if the message isn't sent in the
|
voice you. <channel> is only necessary if the message isn't sent in the
|
||||||
channel itself.
|
channel itself.
|
||||||
"""
|
"""
|
||||||
if not nicks:
|
if nicks:
|
||||||
|
if len(nicks) == 1 and msg.nick in nicks:
|
||||||
|
capability = 'voice'
|
||||||
|
else:
|
||||||
|
capability = 'op'
|
||||||
|
else:
|
||||||
nicks = [msg.nick]
|
nicks = [msg.nick]
|
||||||
irc.queueMsg(ircmsgs.voices(channel, nicks))
|
capability = 'voice'
|
||||||
voice = wrap(voice, [('checkChannelCapability', 'voice'),
|
capability = ircdb.makeChannelCapability(channel, capability)
|
||||||
('haveOp', 'voice someone'),
|
if ircdb.checkCapability(msg.prefix, capability):
|
||||||
many('nickInChannel')])
|
irc.queueMsg(ircmsgs.voices(channel, nicks))
|
||||||
|
else:
|
||||||
|
irc.errorNoCapability(capability)
|
||||||
|
voice = wrap(voice, ['channel', ('haveOp', 'voice someone'),
|
||||||
|
any('nickInChannel')])
|
||||||
|
|
||||||
def deop(self, irc, msg, args, channel, nicks):
|
def deop(self, irc, msg, args, channel, nicks):
|
||||||
"""[<channel>] [<nick> ...]
|
"""[<channel>] [<nick> ...]
|
||||||
@ -193,11 +202,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
'yourself.', Raise=True)
|
'yourself.', Raise=True)
|
||||||
if not nicks:
|
if not nicks:
|
||||||
nicks = [msg.nick]
|
nicks = [msg.nick]
|
||||||
else:
|
irc.queueMsg(ircmsgs.deops(channel, nicks))
|
||||||
irc.queueMsg(ircmsgs.deops(channel, nicks))
|
|
||||||
deop = wrap(deop, [('checkChannelCapability', 'op'),
|
deop = wrap(deop, [('checkChannelCapability', 'op'),
|
||||||
('haveOp', 'deop someone'),
|
('haveOp', 'deop someone'),
|
||||||
many('nickInChannel')])
|
any('nickInChannel')])
|
||||||
|
|
||||||
def dehalfop(self, irc, msg, args, channel, nicks):
|
def dehalfop(self, irc, msg, args, channel, nicks):
|
||||||
"""[<channel>] [<nick> ...]
|
"""[<channel>] [<nick> ...]
|
||||||
@ -212,11 +220,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
'dehalfop me yourself.', Raise=True)
|
'dehalfop me yourself.', Raise=True)
|
||||||
if not nicks:
|
if not nicks:
|
||||||
nicks = [msg.nick]
|
nicks = [msg.nick]
|
||||||
else:
|
irc.queueMsg(ircmsgs.dehalfops(channel, nicks))
|
||||||
irc.queueMsg(ircmsgs.dehalfops(channel, nicks))
|
|
||||||
dehalfop = wrap(dehalfop, [('checkChannelCapability', 'halfop'),
|
dehalfop = wrap(dehalfop, [('checkChannelCapability', 'halfop'),
|
||||||
('haveOp', 'dehalfop someone'),
|
('haveOp', 'dehalfop someone'),
|
||||||
many('nickInChannel')])
|
any('nickInChannel')])
|
||||||
|
|
||||||
# XXX These nicks should really be sets, rather than lists, especially
|
# XXX These nicks should really be sets, rather than lists, especially
|
||||||
# we check whether the bot's nick is in them.
|
# we check whether the bot's nick is in them.
|
||||||
@ -235,11 +242,10 @@ class Channel(callbacks.Privmsg):
|
|||||||
'me yourself.', Raise=True)
|
'me yourself.', Raise=True)
|
||||||
if not nicks:
|
if not nicks:
|
||||||
nicks = [msg.nick]
|
nicks = [msg.nick]
|
||||||
else:
|
irc.queueMsg(ircmsgs.devoices(channel, nicks))
|
||||||
irc.queueMsg(ircmsgs.devoices(channel, nicks))
|
|
||||||
devoice = wrap(devoice, [('checkChannelCapability', 'voice'),
|
devoice = wrap(devoice, [('checkChannelCapability', 'voice'),
|
||||||
('haveOp', 'devoice someone'),
|
('haveOp', 'devoice someone'),
|
||||||
many('nickInChannel')])
|
any('nickInChannel')])
|
||||||
|
|
||||||
def cycle(self, irc, msg, args, channel, key):
|
def cycle(self, irc, msg, args, channel, key):
|
||||||
"""[<channel>] [<key>]
|
"""[<channel>] [<key>]
|
||||||
@ -299,11 +305,13 @@ class Channel(callbacks.Privmsg):
|
|||||||
# Check that they're not trying to make us kickban ourself.
|
# Check that they're not trying to make us kickban ourself.
|
||||||
self.log.debug('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('%s tried to kban a non nick: %s',
|
||||||
msg.prefix, bannedNick)
|
utils.quoted(msg.prefix),
|
||||||
|
utils.quoted(bannedNick))
|
||||||
raise callbacks.ArgumentError
|
raise callbacks.ArgumentError
|
||||||
elif bannedNick == irc.nick:
|
elif bannedNick == irc.nick:
|
||||||
self.log.warning('%r tried to make me kban myself.', msg.prefix)
|
self.log.warning('%s tried to make me kban myself.',
|
||||||
|
utils.quoted(msg.prefix))
|
||||||
irc.error('I cowardly refuse to kickban myself.')
|
irc.error('I cowardly refuse to kickban myself.')
|
||||||
return
|
return
|
||||||
if not reason:
|
if not reason:
|
||||||
@ -337,7 +345,8 @@ class Channel(callbacks.Privmsg):
|
|||||||
# Check (again) that they're not trying to make us kickban ourself.
|
# Check (again) that they're not trying to make us kickban ourself.
|
||||||
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
|
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
|
||||||
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
|
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
|
||||||
self.log.warning('%r tried to make me kban myself.',msg.prefix)
|
self.log.warning('%s tried to make me kban myself.',
|
||||||
|
utils.quoted(msg.prefix))
|
||||||
irc.error('I cowardly refuse to ban myself.')
|
irc.error('I cowardly refuse to ban myself.')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@ -360,15 +369,16 @@ class Channel(callbacks.Privmsg):
|
|||||||
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('%s tried to ban %r, but both have %s',
|
self.log.warning('%s tried to ban %s, but both have %s',
|
||||||
msg.prefix, bannedHostmask, capability)
|
msg.prefix, utils.quoted(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))
|
||||||
else:
|
else:
|
||||||
doBan()
|
doBan()
|
||||||
else:
|
else:
|
||||||
self.log.warning('%r attempted kban without %s',
|
self.log.warning('%s attempted kban without %s',
|
||||||
msg.prefix, capability)
|
utils.quoted(msg.prefix), capability)
|
||||||
irc.errorNoCapability(capability)
|
irc.errorNoCapability(capability)
|
||||||
exact,nick,user,host
|
exact,nick,user,host
|
||||||
kban = wrap(kban,
|
kban = wrap(kban,
|
||||||
@ -519,7 +529,8 @@ class Channel(callbacks.Privmsg):
|
|||||||
# XXX Add the expirations.
|
# XXX Add the expirations.
|
||||||
c = ircdb.channels.getChannel(channel)
|
c = ircdb.channels.getChannel(channel)
|
||||||
if len(c.ignores) == 0:
|
if len(c.ignores) == 0:
|
||||||
s = 'I\'m not currently ignoring any hostmasks in %r' % channel
|
s = 'I\'m not currently ignoring any hostmasks in %s' % \
|
||||||
|
utils.quoted(channel)
|
||||||
irc.reply(s)
|
irc.reply(s)
|
||||||
else:
|
else:
|
||||||
L = sorted(c.ignores)
|
L = sorted(c.ignores)
|
||||||
|
@ -387,8 +387,8 @@ class Misc(callbacks.Privmsg):
|
|||||||
if irc.nested:
|
if irc.nested:
|
||||||
irc.reply(utils.commaAndify(names))
|
irc.reply(utils.commaAndify(names))
|
||||||
else:
|
else:
|
||||||
irc.reply('The %r command is available in the %s %s.' %
|
irc.reply('The %s command is available in the %s %s.' %
|
||||||
(command, plugin,
|
(utils.quoted(command), plugin,
|
||||||
utils.pluralize('plugin', len(names))))
|
utils.pluralize('plugin', len(names))))
|
||||||
else:
|
else:
|
||||||
irc.error('There is no such command %s.' % command)
|
irc.error('There is no such command %s.' % command)
|
||||||
@ -675,7 +675,7 @@ class Misc(callbacks.Privmsg):
|
|||||||
if getattr(module, '__author__', False) == authorInfo:
|
if getattr(module, '__author__', False) == authorInfo:
|
||||||
isAuthor = True
|
isAuthor = True
|
||||||
# XXX Partition needs moved to utils.
|
# XXX Partition needs moved to utils.
|
||||||
(nonCommands, commands) = fix.partition(lambda s: ' ' in s,
|
(nonCommands, commands) = fix.partition(lambda s: ' ' in s,
|
||||||
contributions)
|
contributions)
|
||||||
results = []
|
results = []
|
||||||
if commands:
|
if commands:
|
||||||
|
20
src/Owner.py
20
src/Owner.py
@ -75,7 +75,8 @@ def loadPluginModule(name, ignoreDeprecation=False):
|
|||||||
try:
|
try:
|
||||||
files.extend(os.listdir(dir))
|
files.extend(os.listdir(dir))
|
||||||
except EnvironmentError: # OSError, IOError superclass.
|
except EnvironmentError: # OSError, IOError superclass.
|
||||||
log.warning('Invalid plugin directory: %r; removing.', dir)
|
log.warning('Invalid plugin directory: %s; removing.',
|
||||||
|
utils.quoted(dir))
|
||||||
conf.supybot.directories.plugins().remove(dir)
|
conf.supybot.directories.plugins().remove(dir)
|
||||||
loweredFiles = map(str.lower, files)
|
loweredFiles = map(str.lower, files)
|
||||||
try:
|
try:
|
||||||
@ -98,7 +99,8 @@ def loadPluginModule(name, ignoreDeprecation=False):
|
|||||||
if ignoreDeprecation:
|
if ignoreDeprecation:
|
||||||
log.warning('Deprecated plugin loaded: %s', name)
|
log.warning('Deprecated plugin loaded: %s', name)
|
||||||
else:
|
else:
|
||||||
raise Deprecated, 'Attempted to load deprecated plugin %r' % name
|
raise Deprecated, 'Attempted to load deprecated plugin %s' % \
|
||||||
|
utils.quoted(name)
|
||||||
if module.__name__ in sys.modules:
|
if module.__name__ in sys.modules:
|
||||||
sys.modules[module.__name__] = module
|
sys.modules[module.__name__] = module
|
||||||
linecache.checkcache()
|
linecache.checkcache()
|
||||||
@ -173,8 +175,8 @@ def renameCommand(cb, name, newName):
|
|||||||
method = getattr(cb.__class__, name)
|
method = getattr(cb.__class__, name)
|
||||||
setattr(cb.__class__, newName, method)
|
setattr(cb.__class__, newName, method)
|
||||||
delattr(cb.__class__, name)
|
delattr(cb.__class__, name)
|
||||||
|
|
||||||
|
|
||||||
registerDefaultPlugin('list', 'Misc')
|
registerDefaultPlugin('list', 'Misc')
|
||||||
registerDefaultPlugin('help', 'Misc')
|
registerDefaultPlugin('help', 'Misc')
|
||||||
registerDefaultPlugin('ignore', 'Admin')
|
registerDefaultPlugin('ignore', 'Admin')
|
||||||
@ -248,7 +250,7 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
# There are no plugins that are all-lowercase, so we'll at
|
# There are no plugins that are all-lowercase, so we'll at
|
||||||
# least attempt to capitalize them.
|
# least attempt to capitalize them.
|
||||||
if name == name.lower():
|
if name == name.lower():
|
||||||
name = name.capitalize()
|
name = name.capitalize()
|
||||||
conf.registerPlugin(name)
|
conf.registerPlugin(name)
|
||||||
if name.startswith('supybot.commands.defaultPlugins'):
|
if name.startswith('supybot.commands.defaultPlugins'):
|
||||||
try:
|
try:
|
||||||
@ -266,7 +268,7 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
self.log.warning('Tried to send a message to myself: %r.', msg)
|
self.log.warning('Tried to send a message to myself: %r.', msg)
|
||||||
return None
|
return None
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def isCommand(self, name):
|
def isCommand(self, name):
|
||||||
return name == 'log' or \
|
return name == 'log' or \
|
||||||
self.__parent.isCommand(name)
|
self.__parent.isCommand(name)
|
||||||
@ -396,7 +398,8 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
self._evalEnv['_'] = x
|
self._evalEnv['_'] = x
|
||||||
irc.reply(repr(x))
|
irc.reply(repr(x))
|
||||||
except SyntaxError, e:
|
except SyntaxError, e:
|
||||||
irc.reply('%s: %r' % (utils.exnToString(e), s))
|
irc.reply('%s: %s' % (utils.exnToString(e),
|
||||||
|
utils.quoted(s)))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.log.exception('Uncaught exception in Owner.eval. '
|
self.log.exception('Uncaught exception in Owner.eval. '
|
||||||
'This is not a bug. Please do not '
|
'This is not a bug. Please do not '
|
||||||
@ -491,7 +494,6 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
|
|
||||||
Sends the raw string given to the server.
|
Sends the raw string given to the server.
|
||||||
"""
|
"""
|
||||||
s = privmsgs.getArgs(args)
|
|
||||||
try:
|
try:
|
||||||
m = ircmsgs.IrcMsg(s)
|
m = ircmsgs.IrcMsg(s)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
@ -678,7 +680,7 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
defaultcapability = wrap(defaultcapability,
|
defaultcapability = wrap(defaultcapability,
|
||||||
[('literal', ['add','remove']), 'capability'])
|
[('literal', ['add','remove']), 'capability'])
|
||||||
|
|
||||||
def disable(self, irc, msg, args):
|
def disable(self, irc, msg, args):
|
||||||
"""[<plugin>] <command>
|
"""[<plugin>] <command>
|
||||||
|
|
||||||
|
178
src/User.py
178
src/User.py
@ -46,6 +46,7 @@ from itertools import imap, ifilter
|
|||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
import supybot.utils as utils
|
import supybot.utils as utils
|
||||||
import supybot.ircdb as ircdb
|
import supybot.ircdb as ircdb
|
||||||
|
from supybot.commands import *
|
||||||
import supybot.ircutils as ircutils
|
import supybot.ircutils as ircutils
|
||||||
import supybot.privmsgs as privmsgs
|
import supybot.privmsgs as privmsgs
|
||||||
import supybot.callbacks as callbacks
|
import supybot.callbacks as callbacks
|
||||||
@ -55,26 +56,22 @@ class User(callbacks.Privmsg):
|
|||||||
if password and ircutils.isChannel(msg.args[0]):
|
if password and ircutils.isChannel(msg.args[0]):
|
||||||
raise callbacks.Error, conf.supybot.replies.requiresPrivacy()
|
raise callbacks.Error, conf.supybot.replies.requiresPrivacy()
|
||||||
|
|
||||||
def list(self, irc, msg, args):
|
def list(self, irc, msg, args, optlist, glob):
|
||||||
"""[--capability <capability>] [<glob>]
|
"""[--capability=<capability>] [<glob>]
|
||||||
|
|
||||||
Returns the valid registered usernames matching <glob>. If <glob> is
|
Returns the valid registered usernames matching <glob>. If <glob> is
|
||||||
not given, returns all registered usernames.
|
not given, returns all registered usernames.
|
||||||
"""
|
"""
|
||||||
(optlist, rest) = getopt.getopt(args, '', ['capability='])
|
|
||||||
predicates = []
|
predicates = []
|
||||||
for (option, arg) in optlist:
|
for (option, arg) in optlist:
|
||||||
if option == '--capability':
|
if option == 'capability':
|
||||||
def p(u, cap=arg):
|
def p(u, cap=arg):
|
||||||
try:
|
try:
|
||||||
return u.checkCapability(cap)
|
return u.checkCapability(cap)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return False
|
return False
|
||||||
predicates.append(p)
|
predicates.append(p)
|
||||||
glob = privmsgs.getArgs(rest, required=0, optional=1)
|
|
||||||
if glob:
|
if glob:
|
||||||
if '*' not in glob and '?' not in glob:
|
|
||||||
glob = '*%s*' % glob
|
|
||||||
r = re.compile(fnmatch.translate(glob), re.I)
|
r = re.compile(fnmatch.translate(glob), re.I)
|
||||||
def p(u):
|
def p(u):
|
||||||
return r.match(u.name) is not None
|
return r.match(u.name) is not None
|
||||||
@ -94,8 +91,10 @@ class User(callbacks.Privmsg):
|
|||||||
irc.reply('There are no matching registered users.')
|
irc.reply('There are no matching registered users.')
|
||||||
else:
|
else:
|
||||||
irc.reply('There are no registered users.')
|
irc.reply('There are no registered users.')
|
||||||
|
list = wrap(list, [getopts({'capability':'capability'}),
|
||||||
|
additional('glob')])
|
||||||
|
|
||||||
def register(self, irc, msg, args):
|
def register(self, irc, msg, args, optlist, name, password):
|
||||||
"""[--hashed] <name> <password>
|
"""[--hashed] <name> <password>
|
||||||
|
|
||||||
Registers <name> with the given password <password> and the current
|
Registers <name> with the given password <password> and the current
|
||||||
@ -104,14 +103,11 @@ class User(callbacks.Privmsg):
|
|||||||
not in a channel. If --hashed is given, the password will be hashed
|
not in a channel. If --hashed is given, the password will be hashed
|
||||||
on disk, rather than being stored in the default configured format.
|
on disk, rather than being stored in the default configured format.
|
||||||
"""
|
"""
|
||||||
(optlist, rest) = getopt.getopt(args, '', ['hashed'])
|
|
||||||
(name, password) = privmsgs.getArgs(rest, required=2)
|
|
||||||
addHostmask = True
|
addHostmask = True
|
||||||
hashed = conf.supybot.databases.users.hash()
|
hashed = conf.supybot.databases.users.hash()
|
||||||
for (option, arg) in optlist:
|
for (option, arg) in optlist:
|
||||||
if option == '--hashed':
|
if option == 'hashed':
|
||||||
hashed = True
|
hashed = True
|
||||||
self._checkNotChannel(irc, msg, password)
|
|
||||||
try:
|
try:
|
||||||
ircdb.users.getUserId(name)
|
ircdb.users.getUserId(name)
|
||||||
irc.error('That name is already assigned to someone.', Raise=True)
|
irc.error('That name is already assigned to someone.', Raise=True)
|
||||||
@ -136,30 +132,26 @@ class User(callbacks.Privmsg):
|
|||||||
user.addHostmask(msg.prefix)
|
user.addHostmask(msg.prefix)
|
||||||
ircdb.users.setUser(user)
|
ircdb.users.setUser(user)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
|
register = wrap(register, ['private', getopts({'hashed':''}), 'something',
|
||||||
|
'something'])
|
||||||
|
|
||||||
def unregister(self, irc, msg, args):
|
def unregister(self, irc, msg, args, user, password):
|
||||||
"""<name> [<password>]
|
"""<name> [<password>]
|
||||||
|
|
||||||
Unregisters <name> from the user database. If the user giving this
|
Unregisters <name> from the user database. If the user giving this
|
||||||
command is an owner user, the password is not necessary.
|
command is an owner user, the password is not necessary.
|
||||||
"""
|
"""
|
||||||
(name, password) = privmsgs.getArgs(args, optional=1)
|
if not user.checkPassword(password):
|
||||||
self._checkNotChannel(irc, msg, password)
|
user = ircdb.users.getUser(msg.prefix)
|
||||||
try:
|
if not user.checkCapability('owner'):
|
||||||
id = ircdb.users.getUserId(name)
|
|
||||||
u = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.error('That username isn\'t registered.')
|
|
||||||
return
|
|
||||||
if not u.checkPassword(password):
|
|
||||||
u = ircdb.users.getUser(msg.prefix)
|
|
||||||
if not u.checkCapability('owner'):
|
|
||||||
irc.error(conf.supybot.replies.incorrectAuthentication())
|
irc.error(conf.supybot.replies.incorrectAuthentication())
|
||||||
return
|
return
|
||||||
ircdb.users.delUser(id)
|
ircdb.users.delUser(user.id)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
|
unregister = wrap(unregister, ['private', 'otherUser',
|
||||||
|
additional('something')])
|
||||||
|
|
||||||
def changename(self, irc, msg, args):
|
def changename(self, irc, msg, args, user, newname, password):
|
||||||
"""<name> <new name> [<password>]
|
"""<name> <new name> [<password>]
|
||||||
|
|
||||||
Changes your current user database name to the new name given.
|
Changes your current user database name to the new name given.
|
||||||
@ -167,17 +159,9 @@ class User(callbacks.Privmsg):
|
|||||||
If you include the <password> parameter, this message must be sent
|
If you include the <password> parameter, this message must be sent
|
||||||
to the bot privately (not on a channel).
|
to the bot privately (not on a channel).
|
||||||
"""
|
"""
|
||||||
(name,newname,password) = privmsgs.getArgs(args,required=2,optional=1)
|
|
||||||
self._checkNotChannel(irc, msg, password)
|
|
||||||
try:
|
|
||||||
id = ircdb.users.getUserId(name)
|
|
||||||
user = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.error('That username isn\'t registered.')
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
id = ircdb.users.getUserId(newname)
|
id = ircdb.users.getUserId(newname)
|
||||||
irc.error('%r is already registered.' % newname)
|
irc.error('%s is already registered.' % utils.quoted(newname))
|
||||||
return
|
return
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
@ -185,8 +169,10 @@ class User(callbacks.Privmsg):
|
|||||||
user.name = newname
|
user.name = newname
|
||||||
ircdb.users.setUser(user)
|
ircdb.users.setUser(user)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
|
changename = wrap(changename, ['private', 'otherUser', 'something',
|
||||||
|
additional('something')])
|
||||||
|
|
||||||
def addhostmask(self, irc, msg, args):
|
def addhostmask(self, irc, msg, args, user, hostmask, password):
|
||||||
"""[<name>] [<hostmask>] [<password>]
|
"""[<name>] [<hostmask>] [<password>]
|
||||||
|
|
||||||
Adds the hostmask <hostmask> to the user specified by <name>. The
|
Adds the hostmask <hostmask> to the user specified by <name>. The
|
||||||
@ -198,12 +184,8 @@ class User(callbacks.Privmsg):
|
|||||||
hostmask. If <name> is not given, it defaults to your currently
|
hostmask. If <name> is not given, it defaults to your currently
|
||||||
identified name.
|
identified name.
|
||||||
"""
|
"""
|
||||||
(name, hostmask, password) = privmsgs.getArgs(args, 0, 3)
|
|
||||||
self._checkNotChannel(irc, msg, password)
|
|
||||||
if not hostmask:
|
if not hostmask:
|
||||||
hostmask = msg.prefix
|
hostmask = msg.prefix
|
||||||
if not name:
|
|
||||||
name = msg.prefix
|
|
||||||
if not ircutils.isUserHostmask(hostmask):
|
if not ircutils.isUserHostmask(hostmask):
|
||||||
irc.errorInvalid('hostmask', hostmask, 'Make sure your hostmask '
|
irc.errorInvalid('hostmask', hostmask, 'Make sure your hostmask '
|
||||||
'includes a nick, then an exclamation point (!), then '
|
'includes a nick, then an exclamation point (!), then '
|
||||||
@ -211,11 +193,6 @@ class User(callbacks.Privmsg):
|
|||||||
'free to use wildcards (* and ?, which work just like '
|
'free to use wildcards (* and ?, which work just like '
|
||||||
'they do on the command line) in any of these parts.',
|
'they do on the command line) in any of these parts.',
|
||||||
Raise=True)
|
Raise=True)
|
||||||
try:
|
|
||||||
id = ircdb.users.getUserId(name)
|
|
||||||
user = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNoUser(Raise=True)
|
|
||||||
try:
|
try:
|
||||||
otherId = ircdb.users.getUserId(hostmask)
|
otherId = ircdb.users.getUserId(hostmask)
|
||||||
if otherId != id:
|
if otherId != id:
|
||||||
@ -241,8 +218,11 @@ class User(callbacks.Privmsg):
|
|||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
irc.error(str(e), Raise=True)
|
irc.error(str(e), Raise=True)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
|
addhostmask = wrap(addhostmask, [first('otherUser', 'user'),
|
||||||
|
optional('something'),
|
||||||
|
additional('something')])
|
||||||
|
|
||||||
def removehostmask(self, irc, msg, args):
|
def removehostmask(self, irc, msg, args, user, hostmask, password):
|
||||||
"""<name> <hostmask> [<password>]
|
"""<name> <hostmask> [<password>]
|
||||||
|
|
||||||
Removes the hostmask <hostmask> from the record of the user specified
|
Removes the hostmask <hostmask> from the record of the user specified
|
||||||
@ -251,14 +231,6 @@ class User(callbacks.Privmsg):
|
|||||||
recognized by his hostmask. If you include the <password> parameter,
|
recognized by his hostmask. If you include the <password> parameter,
|
||||||
this message must be sent to the bot privately (not on a channel).
|
this message must be sent to the bot privately (not on a channel).
|
||||||
"""
|
"""
|
||||||
(name, hostmask, password) = privmsgs.getArgs(args, 2, 1)
|
|
||||||
self._checkNotChannel(irc, msg, password)
|
|
||||||
try:
|
|
||||||
id = ircdb.users.getUserId(name)
|
|
||||||
user = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNoUser()
|
|
||||||
return
|
|
||||||
if not user.checkPassword(password) and \
|
if not user.checkPassword(password) and \
|
||||||
not user.checkHostmask(msg.prefix):
|
not user.checkHostmask(msg.prefix):
|
||||||
u = ircdb.users.getUser(msg.prefix)
|
u = ircdb.users.getUser(msg.prefix)
|
||||||
@ -277,8 +249,10 @@ class User(callbacks.Privmsg):
|
|||||||
return
|
return
|
||||||
ircdb.users.setUser(user)
|
ircdb.users.setUser(user)
|
||||||
irc.replySuccess(s)
|
irc.replySuccess(s)
|
||||||
|
removehostmask = wrap(removehostmask, ['private', 'otherUser', 'something',
|
||||||
|
additional('something')])
|
||||||
|
|
||||||
def setpassword(self, irc, msg, args):
|
def setpassword(self, irc, msg, args, optlist, user, password,newpassword):
|
||||||
"""[--hashed] <name> <old password> <new password>
|
"""[--hashed] <name> <old password> <new password>
|
||||||
|
|
||||||
Sets the new password for the user specified by <name> to
|
Sets the new password for the user specified by <name> to
|
||||||
@ -289,57 +263,36 @@ class User(callbacks.Privmsg):
|
|||||||
changed isn't that same owner user), then <old password> needn't be
|
changed isn't that same owner user), then <old password> needn't be
|
||||||
correct.
|
correct.
|
||||||
"""
|
"""
|
||||||
(optlist, rest) = getopt.getopt(args, '', ['hashed'])
|
|
||||||
(name, oldpassword, newpassword) = privmsgs.getArgs(rest, 3)
|
|
||||||
hashed = conf.supybot.databases.users.hash()
|
hashed = conf.supybot.databases.users.hash()
|
||||||
for (option, arg) in optlist:
|
for (option, arg) in optlist:
|
||||||
if option == '--hashed':
|
if option == 'hashed':
|
||||||
hashed = True
|
hashed = True
|
||||||
self._checkNotChannel(irc, msg, oldpassword+newpassword)
|
|
||||||
try:
|
|
||||||
id = ircdb.users.getUserId(name)
|
|
||||||
user = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNoUser()
|
|
||||||
return
|
|
||||||
u = ircdb.users.getUser(msg.prefix)
|
u = ircdb.users.getUser(msg.prefix)
|
||||||
if user.checkPassword(oldpassword) or \
|
if user.checkPassword(password) or \
|
||||||
(u.checkCapability('owner') and not u == user):
|
(u.checkCapability('owner') and not u == user):
|
||||||
user.setPassword(newpassword, hashed=hashed)
|
user.setPassword(newpassword, hashed=hashed)
|
||||||
ircdb.users.setUser(user)
|
ircdb.users.setUser(user)
|
||||||
irc.replySuccess()
|
irc.replySuccess()
|
||||||
else:
|
else:
|
||||||
irc.error(conf.supybot.replies.incorrectAuthentication())
|
irc.error(conf.supybot.replies.incorrectAuthentication())
|
||||||
|
setpassword = wrap(setpassword, [getopts({'hashed':''}), 'otherUser',
|
||||||
|
'something', 'something'])
|
||||||
|
|
||||||
def username(self, irc, msg, args):
|
def username(self, irc, msg, args, user):
|
||||||
"""<hostmask|nick>
|
"""<hostmask|nick>
|
||||||
|
|
||||||
Returns the username of the user specified by <hostmask> or <nick> if
|
Returns the username of the user specified by <hostmask> or <nick> if
|
||||||
the user is registered.
|
the user is registered.
|
||||||
"""
|
"""
|
||||||
hostmask = privmsgs.getArgs(args)
|
irc.reply(user.name)
|
||||||
if not ircutils.isUserHostmask(hostmask):
|
username = wrap(username, ['otherUser'])
|
||||||
try:
|
|
||||||
hostmask = irc.state.nickToHostmask(hostmask)
|
|
||||||
except KeyError:
|
|
||||||
irc.reply('I couldn\'t find %s in my user database.' %hostmask)
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
user = ircdb.users.getUser(hostmask)
|
|
||||||
irc.reply(user.name)
|
|
||||||
except KeyError:
|
|
||||||
irc.reply('I couldn\'t find %s in my user database.' % hostmask)
|
|
||||||
|
|
||||||
def hostmasks(self, irc, msg, args):
|
def hostmasks(self, irc, msg, args, name):
|
||||||
"""[<name>]
|
"""[<name>]
|
||||||
|
|
||||||
Returns the hostmasks of the user specified by <name>; if <name> isn't
|
Returns the hostmasks of the user specified by <name>; if <name> isn't
|
||||||
specified, returns the hostmasks of the user calling the command.
|
specified, returns the hostmasks of the user calling the command.
|
||||||
"""
|
"""
|
||||||
if ircutils.isChannel(msg.args[0]):
|
|
||||||
irc.errorRequiresPrivacy()
|
|
||||||
return
|
|
||||||
name = privmsgs.getArgs(args, required=0, optional=1)
|
|
||||||
try:
|
try:
|
||||||
user = ircdb.users.getUser(msg.prefix)
|
user = ircdb.users.getUser(msg.prefix)
|
||||||
if name:
|
if name:
|
||||||
@ -355,38 +308,24 @@ class User(callbacks.Privmsg):
|
|||||||
irc.reply(repr(user.hostmasks))
|
irc.reply(repr(user.hostmasks))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
irc.errorNotRegistered()
|
irc.errorNotRegistered()
|
||||||
|
hostmasks = wrap(hostmasks, ['private', additional('something')])
|
||||||
|
|
||||||
def capabilities(self, irc, msg, args):
|
def capabilities(self, irc, msg, args, user):
|
||||||
"""[<name>]
|
"""[<name>]
|
||||||
|
|
||||||
Returns the capabilities of the user specified by <name>; if <name>
|
Returns the capabilities of the user specified by <name>; if <name>
|
||||||
isn't specified, returns the hostmasks of the user calling the command.
|
isn't specified, returns the hostmasks of the user calling the command.
|
||||||
"""
|
"""
|
||||||
if not args:
|
irc.reply('[%s]' % '; '.join(user.capabilities))
|
||||||
name = msg.prefix
|
capabilities = wrap(capabilities, [first('otherUser', 'user')])
|
||||||
else:
|
|
||||||
name = privmsgs.getArgs(args)
|
|
||||||
try:
|
|
||||||
user = ircdb.users.getUser(name)
|
|
||||||
irc.reply('[%s]' % '; '.join(user.capabilities))
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNoUser()
|
|
||||||
|
|
||||||
def identify(self, irc, msg, args):
|
def identify(self, irc, msg, args, user, password):
|
||||||
"""<name> <password>
|
"""<name> <password>
|
||||||
|
|
||||||
Identifies the user as <name>. This command (and all other
|
Identifies the user as <name>. This command (and all other
|
||||||
commands that include a password) must be sent to the bot privately,
|
commands that include a password) must be sent to the bot privately,
|
||||||
not in a channel.
|
not in a channel.
|
||||||
"""
|
"""
|
||||||
(name, password) = privmsgs.getArgs(args, 2)
|
|
||||||
self._checkNotChannel(irc, msg)
|
|
||||||
try:
|
|
||||||
id = ircdb.users.getUserId(name)
|
|
||||||
user = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNoUser()
|
|
||||||
return
|
|
||||||
if user.checkPassword(password):
|
if user.checkPassword(password):
|
||||||
try:
|
try:
|
||||||
user.addAuth(msg.prefix)
|
user.addAuth(msg.prefix)
|
||||||
@ -397,8 +336,9 @@ class User(callbacks.Privmsg):
|
|||||||
'doesn\'t match any of your known hostmasks.')
|
'doesn\'t match any of your known hostmasks.')
|
||||||
else:
|
else:
|
||||||
irc.error(conf.supybot.replies.incorrectAuthentication())
|
irc.error(conf.supybot.replies.incorrectAuthentication())
|
||||||
|
identify = wrap(identify, ['private', 'otherUser', 'something'])
|
||||||
|
|
||||||
def unidentify(self, irc, msg, args):
|
def unidentify(self, irc, msg, args, user):
|
||||||
"""takes no arguments
|
"""takes no arguments
|
||||||
|
|
||||||
Un-identifies you. Note that this may not result in the desired
|
Un-identifies you. Note that this may not result in the desired
|
||||||
@ -406,12 +346,6 @@ class User(callbacks.Privmsg):
|
|||||||
have added hostmasks to your user that can cause the bot to continue to
|
have added hostmasks to your user that can cause the bot to continue to
|
||||||
recognize you.
|
recognize you.
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
id = ircdb.users.getUserId(msg.prefix)
|
|
||||||
user = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNoUser()
|
|
||||||
return
|
|
||||||
user.clearAuth()
|
user.clearAuth()
|
||||||
ircdb.users.setUser(user)
|
ircdb.users.setUser(user)
|
||||||
irc.replySuccess('If you remain recognized after giving this command, '
|
irc.replySuccess('If you remain recognized after giving this command, '
|
||||||
@ -419,6 +353,7 @@ class User(callbacks.Privmsg):
|
|||||||
'by password. You must remove whatever hostmask is '
|
'by password. You must remove whatever hostmask is '
|
||||||
'causing you to be recognized in order not to be '
|
'causing you to be recognized in order not to be '
|
||||||
'recognized.')
|
'recognized.')
|
||||||
|
unidentify = wrap(unidentify, ['user'])
|
||||||
|
|
||||||
def whoami(self, irc, msg, args):
|
def whoami(self, irc, msg, args):
|
||||||
"""takes no arguments
|
"""takes no arguments
|
||||||
@ -430,8 +365,9 @@ class User(callbacks.Privmsg):
|
|||||||
irc.reply(user.name)
|
irc.reply(user.name)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
irc.reply('I don\'t recognize you.')
|
irc.reply('I don\'t recognize you.')
|
||||||
|
whoami = wrap(whoami)
|
||||||
|
|
||||||
def setsecure(self, irc, msg, args):
|
def setsecure(self, irc, msg, args, user, password, value):
|
||||||
"""<password> [<True|False>]
|
"""<password> [<True|False>]
|
||||||
|
|
||||||
Sets the secure flag on the user of the person sending the message.
|
Sets the secure flag on the user of the person sending the message.
|
||||||
@ -441,21 +377,8 @@ class User(callbacks.Privmsg):
|
|||||||
If a specific True/False value is not given, it inverts the current
|
If a specific True/False value is not given, it inverts the current
|
||||||
value.
|
value.
|
||||||
"""
|
"""
|
||||||
(password, value) = privmsgs.getArgs(args, optional=1)
|
if value is None:
|
||||||
self._checkNotChannel(irc, msg, password)
|
|
||||||
try:
|
|
||||||
id = ircdb.users.getUserId(msg.prefix)
|
|
||||||
user = ircdb.users.getUser(id)
|
|
||||||
except KeyError:
|
|
||||||
irc.errorNotRegistered()
|
|
||||||
if value == '':
|
|
||||||
value = not user.secure
|
value = not user.secure
|
||||||
elif value.lower() in ('true', 'on', 'enable'):
|
|
||||||
value = True
|
|
||||||
elif value.lower() in ('false', 'off', 'disable'):
|
|
||||||
value = False
|
|
||||||
else:
|
|
||||||
irc.errorInvalid('boolean value', value, Raise=True)
|
|
||||||
if user.checkPassword(password) and \
|
if user.checkPassword(password) and \
|
||||||
user.checkHostmask(msg.prefix, useAuth=False):
|
user.checkHostmask(msg.prefix, useAuth=False):
|
||||||
user.secure = value
|
user.secure = value
|
||||||
@ -463,6 +386,8 @@ class User(callbacks.Privmsg):
|
|||||||
irc.reply('Secure flag set to %s' % value)
|
irc.reply('Secure flag set to %s' % value)
|
||||||
else:
|
else:
|
||||||
irc.error(conf.supybot.replies.incorrectAuthentication())
|
irc.error(conf.supybot.replies.incorrectAuthentication())
|
||||||
|
setsecure = wrap(setsecure, ['private', 'user', 'something',
|
||||||
|
additional('boolean')])
|
||||||
|
|
||||||
def stats(self, irc, msg, args):
|
def stats(self, irc, msg, args):
|
||||||
"""takes no arguments
|
"""takes no arguments
|
||||||
@ -488,7 +413,8 @@ class User(callbacks.Privmsg):
|
|||||||
'%s and %s.' % (users, hostmasks,
|
'%s and %s.' % (users, hostmasks,
|
||||||
utils.nItems('owner', owners),
|
utils.nItems('owner', owners),
|
||||||
utils.nItems('admin', admins)))
|
utils.nItems('admin', admins)))
|
||||||
|
stats = wrap(stats)
|
||||||
|
|
||||||
|
|
||||||
## def config(self, irc, msg, args):
|
## def config(self, irc, msg, args):
|
||||||
## """[--list] <name> [<value>]
|
## """[--list] <name> [<value>]
|
||||||
|
@ -480,8 +480,8 @@ class RichReplyMethods(object):
|
|||||||
if 'Raise' not in kwargs:
|
if 'Raise' not in kwargs:
|
||||||
kwargs['Raise'] = True
|
kwargs['Raise'] = True
|
||||||
if isinstance(capability, basestring): # checkCommandCapability!
|
if isinstance(capability, basestring): # checkCommandCapability!
|
||||||
log.warning('Denying %s for lacking %r capability.',
|
log.warning('Denying %s for lacking %s capability.',
|
||||||
self.msg.prefix, capability)
|
self.msg.prefix, utils.quoted(capability))
|
||||||
if not self._getConfig(conf.supybot.reply.noCapabilityError):
|
if not self._getConfig(conf.supybot.reply.noCapabilityError):
|
||||||
v = self._getConfig(conf.supybot.replies.noCapability)
|
v = self._getConfig(conf.supybot.replies.noCapability)
|
||||||
s = self.__makeReply(v % capability, s)
|
s = self.__makeReply(v % capability, s)
|
||||||
@ -1092,7 +1092,8 @@ class Privmsg(irclib.IrcCallback):
|
|||||||
def getCommand(self, name):
|
def getCommand(self, name):
|
||||||
"""Gets the given command from this plugin."""
|
"""Gets the given command from this plugin."""
|
||||||
name = canonicalName(name)
|
name = canonicalName(name)
|
||||||
assert self.isCommand(name), '%r is not a command.' % name
|
assert self.isCommand(name), '%s is not a command.' % \
|
||||||
|
utils.quoted(name)
|
||||||
return getattr(self, name)
|
return getattr(self, name)
|
||||||
|
|
||||||
def callCommand(self, name, irc, msg, *L, **kwargs):
|
def callCommand(self, name, irc, msg, *L, **kwargs):
|
||||||
@ -1243,7 +1244,8 @@ class PrivmsgRegexp(Privmsg):
|
|||||||
r = re.compile(value.__doc__, self.flags)
|
r = re.compile(value.__doc__, self.flags)
|
||||||
self.res.append((r, name))
|
self.res.append((r, name))
|
||||||
except re.error, e:
|
except re.error, e:
|
||||||
self.log.warning('Invalid regexp: %r (%s)',value.__doc__,e)
|
self.log.warning('Invalid regexp: %s (%s)',
|
||||||
|
utils.quoted(value.__doc__), e)
|
||||||
utils.sortBy(operator.itemgetter(1), self.res)
|
utils.sortBy(operator.itemgetter(1), self.res)
|
||||||
|
|
||||||
def callCommand(self, name, irc, msg, *L, **kwargs):
|
def callCommand(self, name, irc, msg, *L, **kwargs):
|
||||||
|
@ -426,6 +426,12 @@ def checkCapability(irc, msg, args, state, cap):
|
|||||||
def anything(irc, msg, args, state):
|
def anything(irc, msg, args, state):
|
||||||
state.args.append(args.pop(0))
|
state.args.append(args.pop(0))
|
||||||
|
|
||||||
|
def getGlob(irc, msg, args, state):
|
||||||
|
glob = args.pop(0)
|
||||||
|
if '*' not in glob and '?' not in glob:
|
||||||
|
glob = '*%s*' % glob
|
||||||
|
state.args.append(glob)
|
||||||
|
|
||||||
def getUrl(irc, msg, args, state):
|
def getUrl(irc, msg, args, state):
|
||||||
if webutils.urlRe.match(args[0]):
|
if webutils.urlRe.match(args[0]):
|
||||||
state.args.append(args.pop(0))
|
state.args.append(args.pop(0))
|
||||||
@ -521,6 +527,7 @@ wrappers = ircutils.IrcDict({
|
|||||||
'something': getSomething,
|
'something': getSomething,
|
||||||
'filename': getSomething, # XXX Check for validity.
|
'filename': getSomething, # XXX Check for validity.
|
||||||
'commandName': getCommandName,
|
'commandName': getCommandName,
|
||||||
|
'glob': getGlob,
|
||||||
'text': anything,
|
'text': anything,
|
||||||
'somethingWithoutSpaces': getSomethingNoSpaces,
|
'somethingWithoutSpaces': getSomethingNoSpaces,
|
||||||
'capability': getSomethingNoSpaces,
|
'capability': getSomethingNoSpaces,
|
||||||
|
@ -457,7 +457,7 @@ registerChannelValue(supybot.replies, 'notRegistered',
|
|||||||
but they're not currently recognized."""))
|
but they're not currently recognized."""))
|
||||||
|
|
||||||
registerChannelValue(supybot.replies, 'noCapability',
|
registerChannelValue(supybot.replies, 'noCapability',
|
||||||
registry.NormalizedString("""You don't have the %r capability. If you
|
registry.NormalizedString("""You don't have the %s capability. If you
|
||||||
think that you should have this capability, be sure that you are identified
|
think that you should have this capability, be sure that you are identified
|
||||||
before trying again. The 'whoami' command can tell you if you're
|
before trying again. The 'whoami' command can tell you if you're
|
||||||
identified.""", """Determines what error message is given when the bot is
|
identified.""", """Determines what error message is given when the bot is
|
||||||
|
13
src/ircdb.py
13
src/ircdb.py
@ -225,10 +225,11 @@ class IrcUser(object):
|
|||||||
self.hostmasks = hostmasks
|
self.hostmasks = hostmasks
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(id=%s, ignore=%s, password="", name=%r, hashed=%r, ' \
|
return '%s(id=%s, ignore=%s, password="", name=%s, hashed=%r, ' \
|
||||||
'capabilities=%r, hostmasks=[], secure=%r)\n' % \
|
'capabilities=%r, hostmasks=[], secure=%r)\n' % \
|
||||||
(self.__class__.__name__, self.id, self.ignore, self.name,
|
(self.__class__.__name__, self.id, self.ignore,
|
||||||
self.hashed, self.capabilities, self.secure)
|
utils.quoted(self.name), self.hashed, self.capabilities,
|
||||||
|
self.secure)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.id)
|
return hash(self.id)
|
||||||
@ -655,7 +656,8 @@ class UsersDictionary(utils.IterableMap):
|
|||||||
log.error('Multiple matches found in user database. '
|
log.error('Multiple matches found in user database. '
|
||||||
'Removing the offending hostmasks.')
|
'Removing the offending hostmasks.')
|
||||||
for (id, hostmask) in ids.iteritems():
|
for (id, hostmask) in ids.iteritems():
|
||||||
log.error('Removing %r from user %s.', hostmask, id)
|
log.error('Removing %s from user %s.',
|
||||||
|
utils.quoted(hostmask), id)
|
||||||
self.users[id].removeHostmask(hostmask)
|
self.users[id].removeHostmask(hostmask)
|
||||||
raise DuplicateHostmask, 'Ids %r matched.' % ids
|
raise DuplicateHostmask, 'Ids %r matched.' % ids
|
||||||
else: # Not a hostmask, must be a name.
|
else: # Not a hostmask, must be a name.
|
||||||
@ -855,7 +857,8 @@ class IgnoresDB(object):
|
|||||||
expiration = 0
|
expiration = 0
|
||||||
self.add(hostmask, expiration)
|
self.add(hostmask, expiration)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.error('Invalid line in ignores database: %r', line)
|
log.error('Invalid line in ignores database: %s',
|
||||||
|
utils.quoted(line))
|
||||||
fd.close()
|
fd.close()
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
|
@ -172,7 +172,8 @@ class IrcMsgQueue(object):
|
|||||||
if msg in self.msgs and \
|
if msg in self.msgs and \
|
||||||
not conf.supybot.protocols.irc.queueDuplicateMessages():
|
not conf.supybot.protocols.irc.queueDuplicateMessages():
|
||||||
s = str(msg).strip()
|
s = str(msg).strip()
|
||||||
log.warning('Not adding message %r to queue, already added.', s)
|
log.warning('Not adding message %s to queue, already added.',
|
||||||
|
utils.quoted(s))
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self.msgs.add(msg)
|
self.msgs.add(msg)
|
||||||
|
@ -43,6 +43,7 @@ import time
|
|||||||
import string
|
import string
|
||||||
|
|
||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
|
import supybot.utils as utils
|
||||||
import supybot.ircutils as ircutils
|
import supybot.ircutils as ircutils
|
||||||
|
|
||||||
###
|
###
|
||||||
@ -197,13 +198,14 @@ class IrcMsg(object):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self._repr is not None:
|
if self._repr is not None:
|
||||||
return self._repr
|
return self._repr
|
||||||
self._repr = 'IrcMsg(prefix=%r, command=%r, args=%r)' % \
|
self._repr = 'IrcMsg(prefix=%s, command=%s, args=%r)' % \
|
||||||
(self.prefix, self.command, self.args)
|
(utils.quoted(self.prefix), utils.quoted(self.command),
|
||||||
|
self.args)
|
||||||
return self._repr
|
return self._repr
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self):
|
||||||
return (self.__class__, (str(self),))
|
return (self.__class__, (str(self),))
|
||||||
|
|
||||||
def tag(self, tag, value=True):
|
def tag(self, tag, value=True):
|
||||||
self.tags[tag] = value
|
self.tags[tag] = value
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ def toLower(s, casemapping=None):
|
|||||||
elif casemapping == 'ascii': # freenode
|
elif casemapping == 'ascii': # freenode
|
||||||
return s.lower()
|
return s.lower()
|
||||||
else:
|
else:
|
||||||
raise ValueError, 'Invalid casemapping: %r' % casemapping
|
raise ValueError, 'Invalid casemapping: %s' % utils.quoted(casemapping)
|
||||||
|
|
||||||
def strEqual(nick1, nick2):
|
def strEqual(nick1, nick2):
|
||||||
"""Returns True if nick1 == nick2 according to IRC case rules."""
|
"""Returns True if nick1 == nick2 according to IRC case rules."""
|
||||||
@ -360,7 +360,7 @@ class FormatContext(object):
|
|||||||
# Should we individually end formatters?
|
# Should we individually end formatters?
|
||||||
s += '\x0f'
|
s += '\x0f'
|
||||||
return s
|
return s
|
||||||
|
|
||||||
class FormatParser(object):
|
class FormatParser(object):
|
||||||
def __init__(self, s):
|
def __init__(self, s):
|
||||||
self.fd = sio(s)
|
self.fd = sio(s)
|
||||||
@ -427,7 +427,7 @@ def wrap(s, length):
|
|||||||
context = FormatParser(chunk).parse()
|
context = FormatParser(chunk).parse()
|
||||||
processed.append(context.end(chunk))
|
processed.append(context.end(chunk))
|
||||||
return processed
|
return processed
|
||||||
|
|
||||||
def isValidArgument(s):
|
def isValidArgument(s):
|
||||||
"""Returns whether s is strictly a valid argument for an IRC message."""
|
"""Returns whether s is strictly a valid argument for an IRC message."""
|
||||||
return '\r' not in s and '\n' not in s and '\x00' not in s
|
return '\r' not in s and '\n' not in s and '\x00' not in s
|
||||||
@ -437,7 +437,7 @@ def safeArgument(s):
|
|||||||
if isinstance(s, unicode):
|
if isinstance(s, unicode):
|
||||||
s = s.encode('utf-8')
|
s = s.encode('utf-8')
|
||||||
elif not isinstance(s, basestring):
|
elif not isinstance(s, basestring):
|
||||||
debug('Got a non-string in safeArgument: %r', s)
|
debug('Got a non-string in safeArgument: %s', utils.quoted(s))
|
||||||
s = str(s)
|
s = str(s)
|
||||||
if isValidArgument(s):
|
if isValidArgument(s):
|
||||||
return s
|
return s
|
||||||
@ -504,7 +504,7 @@ class IrcSet(utils.NormalizingSet):
|
|||||||
"""A sets.Set using IrcStrings instead of regular strings."""
|
"""A sets.Set using IrcStrings instead of regular strings."""
|
||||||
def normalize(self, s):
|
def normalize(self, s):
|
||||||
return IrcString(s)
|
return IrcString(s)
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self):
|
||||||
return (self.__class__, (list(self),))
|
return (self.__class__, (list(self),))
|
||||||
|
|
||||||
@ -548,7 +548,7 @@ class FloodQueue(object):
|
|||||||
return q
|
return q
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def enqueue(self, msg, what=None):
|
def enqueue(self, msg, what=None):
|
||||||
if what is None:
|
if what is None:
|
||||||
what = msg
|
what = msg
|
||||||
@ -571,7 +571,7 @@ class FloodQueue(object):
|
|||||||
if elt == what:
|
if elt == what:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
mircColors = IrcDict({
|
mircColors = IrcDict({
|
||||||
'white': '0',
|
'white': '0',
|
||||||
|
@ -88,7 +88,8 @@ class Logger(logging.Logger):
|
|||||||
eId = hex(hash(eStrId) & 0xFFFFF)
|
eId = hex(hash(eStrId) & 0xFFFFF)
|
||||||
logging.Logger.exception(self, *args)
|
logging.Logger.exception(self, *args)
|
||||||
if hasattr(e, '__revision__') and e.__revision__:
|
if hasattr(e, '__revision__') and e.__revision__:
|
||||||
self.error('Exception __revision__: %r', e.__revision__)
|
self.error('Exception __revision__: %s',
|
||||||
|
utils.quoted(e.__revision__))
|
||||||
self.error('Exception id: %s', eId)
|
self.error('Exception id: %s', eId)
|
||||||
# The traceback should be sufficient if we want it.
|
# The traceback should be sufficient if we want it.
|
||||||
# self.error('Exception string: %s', eStrId)
|
# self.error('Exception string: %s', eStrId)
|
||||||
@ -290,7 +291,7 @@ registry.exception = exception
|
|||||||
def stat(*args):
|
def stat(*args):
|
||||||
level = conf.supybot.log.statistics()
|
level = conf.supybot.log.statistics()
|
||||||
_logger.log(level, *args)
|
_logger.log(level, *args)
|
||||||
|
|
||||||
setLevel = _logger.setLevel
|
setLevel = _logger.setLevel
|
||||||
|
|
||||||
atexit.register(logging.shutdown)
|
atexit.register(logging.shutdown)
|
||||||
|
14
src/utils.py
14
src/utils.py
@ -507,10 +507,10 @@ def safeEval(s, namespace={'True': True, 'False': False, 'None': None}):
|
|||||||
if node.__class__ is compiler.ast.Module:
|
if node.__class__ is compiler.ast.Module:
|
||||||
return node.doc
|
return node.doc
|
||||||
else:
|
else:
|
||||||
raise ValueError, 'Unsafe string: %r' % s
|
raise ValueError, 'Unsafe string: %s' % quoted(s)
|
||||||
node = nodes[0]
|
node = nodes[0]
|
||||||
if node.__class__ is not compiler.ast.Discard:
|
if node.__class__ is not compiler.ast.Discard:
|
||||||
raise ValueError, 'Invalid expression: %r' % s
|
raise ValueError, 'Invalid expression: %s' % quoted(s)
|
||||||
node = node.getChildNodes()[0]
|
node = node.getChildNodes()[0]
|
||||||
def checkNode(node):
|
def checkNode(node):
|
||||||
if node.__class__ is compiler.ast.Const:
|
if node.__class__ is compiler.ast.Const:
|
||||||
@ -529,7 +529,7 @@ def safeEval(s, namespace={'True': True, 'False': False, 'None': None}):
|
|||||||
if checkNode(node):
|
if checkNode(node):
|
||||||
return eval(s, namespace, namespace)
|
return eval(s, namespace, namespace)
|
||||||
else:
|
else:
|
||||||
raise ValueError, 'Unsafe string: %r' % s
|
raise ValueError, 'Unsafe string: %s' % quoted(s)
|
||||||
|
|
||||||
def exnToString(e):
|
def exnToString(e):
|
||||||
"""Turns a simple exception instance into a string (better than str(e))"""
|
"""Turns a simple exception instance into a string (better than str(e))"""
|
||||||
@ -726,7 +726,7 @@ class AtomicFile(file):
|
|||||||
def __init__(self, filename, mode='w', allowEmptyOverwrite=True,
|
def __init__(self, filename, mode='w', allowEmptyOverwrite=True,
|
||||||
makeBackupIfSmaller=True, tmpDir=None, backupDir=None):
|
makeBackupIfSmaller=True, tmpDir=None, backupDir=None):
|
||||||
if mode not in ('w', 'wb'):
|
if mode not in ('w', 'wb'):
|
||||||
raise ValueError, 'Invalid mode: %r' % mode
|
raise ValueError, 'Invalid mode: %s' % quoted(mode)
|
||||||
self.rolledback = False
|
self.rolledback = False
|
||||||
self.allowEmptyOverwrite = allowEmptyOverwrite
|
self.allowEmptyOverwrite = allowEmptyOverwrite
|
||||||
self.makeBackupIfSmaller = makeBackupIfSmaller
|
self.makeBackupIfSmaller = makeBackupIfSmaller
|
||||||
@ -826,12 +826,12 @@ def toBool(s):
|
|||||||
elif s in ('false', 'off', 'disable', 'disabled'):
|
elif s in ('false', 'off', 'disable', 'disabled'):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
raise ValueError, 'Invalid string for toBool: %r' % s
|
raise ValueError, 'Invalid string for toBool: %s' % quoted(s)
|
||||||
|
|
||||||
def mapinto(f, L):
|
def mapinto(f, L):
|
||||||
for (i, x) in enumerate(L):
|
for (i, x) in enumerate(L):
|
||||||
L[i] = f(x)
|
L[i] = f(x)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod(sys.modules['__main__'])
|
doctest.testmod(sys.modules['__main__'])
|
||||||
|
@ -33,7 +33,7 @@ import supybot.conf as conf
|
|||||||
import supybot.ircdb as ircdb
|
import supybot.ircdb as ircdb
|
||||||
import supybot.ircmsgs as ircmsgs
|
import supybot.ircmsgs as ircmsgs
|
||||||
|
|
||||||
class ChannelTestCase(ChannelPluginTestCase, PluginDocumentation):
|
class ChannelTestCase(ChannelPluginTestCase):
|
||||||
plugins = ('Channel', 'User')
|
plugins = ('Channel', 'User')
|
||||||
def testLobotomies(self):
|
def testLobotomies(self):
|
||||||
self.assertRegexp('lobotomies', 'not.*any')
|
self.assertRegexp('lobotomies', 'not.*any')
|
||||||
|
@ -32,29 +32,29 @@ import time
|
|||||||
|
|
||||||
from testsupport import *
|
from testsupport import *
|
||||||
|
|
||||||
class DebianTestCase(PluginTestCase, PluginDocumentation):
|
class DebianTestCase(PluginTestCase):
|
||||||
plugins = ('Debian',)
|
plugins = ('Debian',)
|
||||||
timeout = 100
|
timeout = 100
|
||||||
cleanDataDir = False
|
cleanDataDir = False
|
||||||
fileDownloaded = False
|
fileDownloaded = False
|
||||||
|
|
||||||
if network:
|
if network:
|
||||||
def setup(self, nick='test'):
|
def setUp(self, nick='test'):
|
||||||
plugintestcase.setup(self)
|
PluginTestCase.setUp(self)
|
||||||
try:
|
try:
|
||||||
datadir = conf.supybot.directories.data()
|
datadir = conf.supybot.directories.data()
|
||||||
if os.path.exists(os.path.join(datadir,
|
if os.path.exists(os.path.join(datadir,
|
||||||
'contents-i386.gz')):
|
'Contents-i386.gz')):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print
|
print
|
||||||
print "downloading files, this may take awhile"
|
print "Downloading files, this may take awhile"
|
||||||
filename = os.path.join(datadir, 'contents-i386.gz')
|
filename = os.path.join(datadir, 'Contents-i386.gz')
|
||||||
while not os.path.exists(filename):
|
while not os.path.exists(filename):
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
print "download complete"
|
print "Download complete"
|
||||||
print "starting test ..."
|
print "Starting test ..."
|
||||||
self.filedownloaded = true
|
self.fileDownloaded = True
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ class CommandsTestCase(SupyTestCase):
|
|||||||
def testAny(self):
|
def testAny(self):
|
||||||
self.assertState([any('int')], ['1', '2', '3'], [[1, 2, 3]])
|
self.assertState([any('int')], ['1', '2', '3'], [[1, 2, 3]])
|
||||||
self.assertState([None, any('int')], ['1', '2', '3'], ['1', [2, 3]])
|
self.assertState([None, any('int')], ['1', '2', '3'], ['1', [2, 3]])
|
||||||
|
self.assertState([any('int')], [], [[]])
|
||||||
|
|
||||||
## def testAny(self):
|
## def testAny(self):
|
||||||
## self.assertState([None, any('int'), None],
|
## self.assertState([None, any('int'), None],
|
||||||
@ -104,6 +105,12 @@ class CommandsTestCase(SupyTestCase):
|
|||||||
self.assertState(spec, ['#foo', '+s'], ['#foo', '+s'])
|
self.assertState(spec, ['#foo', '+s'], ['#foo', '+s'])
|
||||||
self.assertState(spec, ['+s'], ['#foo', '+s'], target='#foo')
|
self.assertState(spec, ['+s'], ['#foo', '+s'], target='#foo')
|
||||||
|
|
||||||
|
def testGlob(self):
|
||||||
|
spec = ['glob']
|
||||||
|
self.assertState(spec, ['foo'], ['*foo*'])
|
||||||
|
self.assertState(spec, ['?foo'], ['?foo'])
|
||||||
|
self.assertState(spec, ['foo*'], ['foo*'])
|
||||||
|
|
||||||
def testGetId(self):
|
def testGetId(self):
|
||||||
spec = ['id']
|
spec = ['id']
|
||||||
self.assertState(spec, ['#12'], [12])
|
self.assertState(spec, ['#12'], [12])
|
||||||
|
Loading…
Reference in New Issue
Block a user