all plugins: Use msg.channel instead of msg.args[0] + give network name to self.registryValue.

This commit is contained in:
Valentin Lorentz 2019-08-24 17:50:05 +02:00
parent 9326331c60
commit c1ae3f5c81
42 changed files with 407 additions and 350 deletions

View File

@ -49,9 +49,9 @@ def getChannel(irc, msg, args):
If the channel was given in args, args is modified (the channel is If the channel was given in args, args is modified (the channel is
removed). removed).
""" """
if args and irc.isChannel(msg.args[0]): if args and msg.channel:
if conf.supybot.reply.requireChannelCommandsToBeSentInChannel(): if conf.supybot.reply.requireChannelCommandsToBeSentInChannel():
if args[0] != msg.args[0]: if args[0] != msg.channel:
s = 'Channel commands must be sent in the channel to which ' \ s = 'Channel commands must be sent in the channel to which ' \
'they apply; if this is not the behavior you desire, ' \ 'they apply; if this is not the behavior you desire, ' \
'ask the bot\'s administrator to change the registry ' \ 'ask the bot\'s administrator to change the registry ' \
@ -60,8 +60,8 @@ def getChannel(irc, msg, args):
'to False.' 'to False.'
raise callbacks.Error(s) raise callbacks.Error(s)
return args.pop(0) return args.pop(0)
elif irc.isChannel(msg.args[0]): elif msg.channel:
return msg.args[0] return msg.channel
else: else:
raise callbacks.Error('Command must be sent in a channel or ' \ raise callbacks.Error('Command must be sent in a channel or ' \
'include a channel in its arguments.') 'include a channel in its arguments.')

View File

@ -50,17 +50,20 @@ class Anonymous(callbacks.Plugin):
supybot.plugins.Anonymous.requireRegistration. supybot.plugins.Anonymous.requireRegistration.
""" """
def _preCheck(self, irc, msg, target, action): def _preCheck(self, irc, msg, target, action):
if self.registryValue('requireRegistration', target): if self.registryValue('requireRegistration', target, irc.network):
try: try:
foo = ircdb.users.getUser(msg.prefix) foo = ircdb.users.getUser(msg.prefix)
except KeyError: except KeyError:
irc.errorNotRegistered(Raise=True) irc.errorNotRegistered(Raise=True)
capability = self.registryValue('requireCapability', target) capability = self.registryValue('requireCapability',
target, irc.network)
if capability: if capability:
if not ircdb.checkCapability(msg.prefix, capability): if not ircdb.checkCapability(msg.prefix, capability):
irc.errorNoCapability(capability, Raise=True) irc.errorNoCapability(capability, Raise=True)
if action != 'tell': if action != 'tell':
if self.registryValue('requirePresenceInChannel', target) and \ require_presence = self.registryValue('requirePresenceInChannel',
target, irc.network)
if require_presence and \
msg.nick not in irc.state.channels[target].users: msg.nick not in irc.state.channels[target].users:
irc.error(format(_('You must be in %s to %q in there.'), irc.error(format(_('You must be in %s to %q in there.'),
target, action), Raise=True) target, action), Raise=True)

View File

@ -48,12 +48,13 @@ class AutoMode(callbacks.Plugin):
"""This plugin, when configured, allows the bot to automatically set modes """This plugin, when configured, allows the bot to automatically set modes
on users when they join.""" on users when they join."""
def doJoin(self, irc, msg): def doJoin(self, irc, msg):
channel = msg.args[0] channel = msg.channel
network = irc.network
if ircutils.strEqual(irc.nick, msg.nick): if ircutils.strEqual(irc.nick, msg.nick):
return return
if not self.registryValue('enable', channel): if not self.registryValue('enable', channel, network):
return return
fallthrough = self.registryValue('fallthrough', channel) fallthrough = self.registryValue('fallthrough', channel, network)
def do(type): def do(type):
cap = ircdb.makeChannelCapability(channel, type) cap = ircdb.makeChannelCapability(channel, type)
cap_auto = ircdb.makeChannelCapability(channel, 'auto'+type) cap_auto = ircdb.makeChannelCapability(channel, 'auto'+type)
@ -63,7 +64,7 @@ class AutoMode(callbacks.Plugin):
ignoreChannelOp=True, ignoreDefaultAllow=True) ignoreChannelOp=True, ignoreDefaultAllow=True)
except KeyError: except KeyError:
apply_mode = False apply_mode = False
if self.registryValue('alternativeCapabilities', channel): if self.registryValue('alternativeCapabilities', channel, network):
try: try:
override = ircdb.checkCapability(msg.prefix, cap_auto, override = ircdb.checkCapability(msg.prefix, cap_auto,
ignoreOwner=not self.registryValue('owner'), ignoreOwner=not self.registryValue('owner'),
@ -73,9 +74,9 @@ class AutoMode(callbacks.Plugin):
else: else:
override = False override = False
if apply_mode or override: if apply_mode or override:
if override or self.registryValue(type, channel): if override or self.registryValue(type, channel, network):
self.log.info('Scheduling auto-%s of %s in %s.', self.log.info('Scheduling auto-%s of %s in %s @ %s.',
type, msg.prefix, channel) type, msg.prefix, channel, network)
def dismiss(): def dismiss():
"""Determines whether or not a mode has already """Determines whether or not a mode has already
been applied.""" been applied."""
@ -87,8 +88,9 @@ class AutoMode(callbacks.Plugin):
raise Continue # Even if fallthrough, let's only do one. raise Continue # Even if fallthrough, let's only do one.
elif not fallthrough: elif not fallthrough:
self.log.debug('%s has %s, but supybot.plugins.AutoMode.%s' self.log.debug('%s has %s, but supybot.plugins.AutoMode.%s'
' is not enabled in %s, refusing to fall ' ' is not enabled in %s @ %s, refusing to '
'through.', msg.prefix, cap, type, channel) 'fall through.',
msg.prefix, cap, type, channel, network)
raise Continue raise Continue
def schedule_msg(msg, dismiss): def schedule_msg(msg, dismiss):
def f(): def f():
@ -96,7 +98,7 @@ class AutoMode(callbacks.Plugin):
irc.queueMsg(msg) irc.queueMsg(msg)
else: else:
self.log.info('Dismissing auto-mode for %s.', msg.args[2]) self.log.info('Dismissing auto-mode for %s.', msg.args[2])
delay = self.registryValue('delay', channel) delay = self.registryValue('delay', channel, network)
if delay: if delay:
schedule.addEvent(f, time.time() + delay) schedule.addEvent(f, time.time() + delay)
else: else:
@ -107,7 +109,7 @@ class AutoMode(callbacks.Plugin):
except KeyError: except KeyError:
return return
pattern = re.compile('-|\+') pattern = re.compile('-|\+')
for item in self.registryValue('extra', channel): for item in self.registryValue('extra', channel, network):
try: try:
username, modes = pattern.split(item, maxsplit=1) username, modes = pattern.split(item, maxsplit=1)
modes = item[len(username)] + modes modes = item[len(username)] + modes
@ -118,8 +120,8 @@ class AutoMode(callbacks.Plugin):
if username != user.name: if username != user.name:
continue continue
else: else:
self.log.info('Scheduling auto-modes %s of %s in %s.', self.log.info('Scheduling auto-modes %s of %s in %s @ %s.',
modes, msg.prefix, channel) modes, msg.prefix, channel, network)
modes = [modes] + \ modes = [modes] + \
([msg.nick]*len(pattern.sub('', modes))) ([msg.nick]*len(pattern.sub('', modes)))
schedule_msg(ircmsgs.mode(channel, modes), lambda :False) schedule_msg(ircmsgs.mode(channel, modes), lambda :False)
@ -133,8 +135,9 @@ class AutoMode(callbacks.Plugin):
finally: finally:
extra_modes() extra_modes()
c = ircdb.channels.getChannel(channel) c = ircdb.channels.getChannel(channel)
if c.checkBan(msg.prefix) and self.registryValue('ban', channel): if c.checkBan(msg.prefix) and self.registryValue('ban',
period = self.registryValue('ban.period', channel) channel, network):
period = self.registryValue('ban.period', channel, network)
if period: if period:
def unban(): def unban():
try: try:

View File

@ -72,10 +72,11 @@ class BadWords(callbacks.Privmsg):
# We need to check for bad words here rather than in doPrivmsg because # We need to check for bad words here rather than in doPrivmsg because
# messages don't get to doPrivmsg if the user is ignored. # messages don't get to doPrivmsg if the user is ignored.
if msg.command == 'PRIVMSG' and self.words(): if msg.command == 'PRIVMSG' and self.words():
channel = msg.args[0] channel = msg.channel
self.updateRegexp(channel) self.updateRegexp(channel, irc.network)
s = ircutils.stripFormatting(msg.args[1]) s = ircutils.stripFormatting(msg.args[1])
if irc.isChannel(channel) and self.registryValue('kick', channel): if irc.isChannel(channel) \
and self.registryValue('kick', channel, irc.network):
if self.regexp.search(s): if self.regexp.search(s):
c = irc.state.channels[channel] c = irc.state.channels[channel]
cap = ircdb.makeChannelCapability(channel, 'op') cap = ircdb.makeChannelCapability(channel, 'op')
@ -86,22 +87,23 @@ class BadWords(callbacks.Privmsg):
"they are halfop+ or can't be " "they are halfop+ or can't be "
"kicked.", msg.nick, channel) "kicked.", msg.nick, channel)
else: else:
message = self.registryValue('kick.message', channel) message = self.registryValue('kick.message',
channel, irc.network)
irc.queueMsg(ircmsgs.kick(channel, msg.nick, message)) irc.queueMsg(ircmsgs.kick(channel, msg.nick, message))
else: else:
self.log.warning('Should kick %s from %s, but not opped.', self.log.warning('Should kick %s from %s, but not opped.',
msg.nick, channel) msg.nick, channel)
return msg return msg
def updateRegexp(self, channel): def updateRegexp(self, channel, network):
if self.lastModified < self.words.lastModified: if self.lastModified < self.words.lastModified:
self.makeRegexp(self.words(), channel) self.makeRegexp(self.words(), channel, network)
self.lastModified = time.time() self.lastModified = time.time()
def outFilter(self, irc, msg): def outFilter(self, irc, msg):
if self.filtering and msg.command == 'PRIVMSG' and self.words(): if self.filtering and msg.command == 'PRIVMSG' and self.words():
channel = msg.args[0] channel = msg.channel
self.updateRegexp(channel) self.updateRegexp(channel, irc.network)
s = msg.args[1] s = msg.args[1]
if self.registryValue('stripFormatting'): if self.registryValue('stripFormatting'):
s = ircutils.stripFormatting(s) s = ircutils.stripFormatting(s)
@ -110,9 +112,9 @@ class BadWords(callbacks.Privmsg):
msg = ircmsgs.privmsg(msg.args[0], t, msg=msg) msg = ircmsgs.privmsg(msg.args[0], t, msg=msg)
return msg return msg
def makeRegexp(self, iterable, channel): def makeRegexp(self, iterable, channel, network):
s = '(%s)' % '|'.join(map(re.escape, iterable)) s = '(%s)' % '|'.join(map(re.escape, iterable))
if self.registryValue('requireWordBoundaries', channel): if self.registryValue('requireWordBoundaries', channel, network):
s = r'\b%s\b' % s s = r'\b%s\b' % s
self.regexp = re.compile(s, re.I) self.regexp = re.compile(s, re.I)

View File

@ -54,24 +54,26 @@ class Channel(callbacks.Plugin):
self.invites = {} self.invites = {}
def doKick(self, irc, msg): def doKick(self, irc, msg):
channel = msg.args[0] channel = msg.channel
network = irc.network
if msg.args[1] == irc.nick: if msg.args[1] == irc.nick:
if self.registryValue('alwaysRejoin', channel): if self.registryValue('alwaysRejoin', channel, network):
delay = self.registryValue('rejoinDelay', channel) delay = self.registryValue('rejoinDelay', channel, network)
networkGroup = conf.supybot.networks.get(irc.network) networkGroup = conf.supybot.networks.get(irc.network)
if delay: if delay:
def f(): def f():
irc.sendMsg(networkGroup.channels.join(channel)) irc.sendMsg(networkGroup.channels.join(channel))
schedule.addEvent(f, time.time() + delay) schedule.addEvent(f, time.time() + delay)
self.log.info('Kicked from %s by %s. Rejoining after %s ' self.log.info('Kicked from %s @ %s by %s. '
'seconds.', channel, msg.prefix, delay) 'Rejoining after %s seconds.',
channel, network, msg.prefix, delay)
else: else:
self.log.info('Kicked from %s by %s. Rejoining.', self.log.info('Kicked from %s @ %s by %s. Rejoining.',
channel, msg.prefix) channel, network, msg.prefix)
irc.sendMsg(networkGroup.channels.join(channel)) irc.sendMsg(networkGroup.channels.join(channel))
else: else:
self.log.info('Kicked from %s by %s. Not auto-rejoining.', self.log.info('Kicked from %s @ %s by %s. Not auto-rejoining.',
channel, msg.prefix) channel, network, msg.prefix)
def _sendMsg(self, irc, msg): def _sendMsg(self, irc, msg):
irc.queueMsg(msg) irc.queueMsg(msg)
@ -274,7 +276,7 @@ class Channel(callbacks.Plugin):
supybot.plugins.Channel.partMsg will be used. No part message will be supybot.plugins.Channel.partMsg will be used. No part message will be
used if neither a cycle reason nor a default part message is given. used if neither a cycle reason nor a default part message is given.
""" """
reason = (reason or self.registryValue("partMsg", channel)) reason = (reason or self.registryValue("partMsg", channel, irc.network))
reason = ircutils.standardSubstitute(irc, msg, reason) reason = ircutils.standardSubstitute(irc, msg, reason)
self._sendMsg(irc, ircmsgs.part(channel, reason)) self._sendMsg(irc, ircmsgs.part(channel, reason))
networkGroup = conf.supybot.networks.get(irc.network) networkGroup = conf.supybot.networks.get(irc.network)
@ -907,12 +909,20 @@ class Channel(callbacks.Plugin):
nicks if --count option is provided. nicks if --count option is provided.
""" """
# Make sure we don't elicit information about private channels to # Make sure we don't elicit information about private channels to
# people or channels that shouldn't know # people or channels that shouldn't know. Someone is allowed if
# any of these are true:
# * the channel is not secret (mode +s),
# * the request is sent to the channel itself (FIXME: what about
# channels without +n?),
# * the requester is op,
# * the request is not sent to a channel (or else everyone in the
# channel would see the response) and the requester is in the
# channel themselves
capability = ircdb.makeChannelCapability(channel, 'op') capability = ircdb.makeChannelCapability(channel, 'op')
if 's' in irc.state.channels[channel].modes and \ if 's' in irc.state.channels[channel].modes and \
msg.args[0] != channel and \ msg.channel != channel and \
not ircdb.checkCapability(msg.prefix, capability) and \ not ircdb.checkCapability(msg.prefix, capability) and \
(irc.isChannel(msg.args[0]) or \ (msg.channel or \
msg.nick not in irc.state.channels[channel].users): msg.nick not in irc.state.channels[channel].users):
irc.error(_('You don\'t have access to that information.'), irc.error(_('You don\'t have access to that information.'),
Raise=True) Raise=True)
@ -920,7 +930,7 @@ class Channel(callbacks.Plugin):
keys = [option for (option, arg) in optlist] keys = [option for (option, arg) in optlist]
if 'count' not in keys: if 'count' not in keys:
utils.sortBy(str.lower, L) utils.sortBy(str.lower, L)
private = self.registryValue("nicksInPrivate", channel) private = self.registryValue("nicksInPrivate", channel, irc.network)
irc.reply(utils.str.commaAndify(L), private=private) irc.reply(utils.str.commaAndify(L), private=private)
else: else:
irc.reply(str(len(L))) irc.reply(str(len(L)))
@ -961,10 +971,8 @@ class Channel(callbacks.Plugin):
supybot.plugins.Channel.partMsg will be used. No part message will be supybot.plugins.Channel.partMsg will be used. No part message will be
used if no default is configured. used if no default is configured.
""" """
if channel is None: channel = channel or msg.channel
if irc.isChannel(msg.args[0]): if not channel:
channel = msg.args[0]
else:
irc.error(Raise=True) irc.error(Raise=True)
capability = ircdb.makeChannelCapability(channel, 'op') capability = ircdb.makeChannelCapability(channel, 'op')
if not ircdb.checkCapabilities(msg.prefix, [capability, 'admin']): if not ircdb.checkCapabilities(msg.prefix, [capability, 'admin']):
@ -976,7 +984,7 @@ class Channel(callbacks.Plugin):
pass pass
if channel not in irc.state.channels: if channel not in irc.state.channels:
irc.error(_('I\'m not in %s.') % channel, Raise=True) irc.error(_('I\'m not in %s.') % channel, Raise=True)
reason = (reason or self.registryValue("partMsg", channel)) reason = (reason or self.registryValue("partMsg", channel, irc.network))
reason = ircutils.standardSubstitute(irc, msg, reason) reason = ircutils.standardSubstitute(irc, msg, reason)
irc.queueMsg(ircmsgs.part(channel, reason)) irc.queueMsg(ircmsgs.part(channel, reason))
if msg.nick in irc.state.channels[channel].users: if msg.nick in irc.state.channels[channel].users:

View File

@ -90,11 +90,11 @@ class ChannelLogger(callbacks.Plugin):
self.log.exception('Odd exception:') self.log.exception('Odd exception:')
def logNameTimestamp(self, channel): def logNameTimestamp(self, channel):
format = self.registryValue('filenameTimestamp', channel) format = self.registryValue('filenameTimestamp', channel, irc.network)
return time.strftime(format) return time.strftime(format)
def getLogName(self, channel): def getLogName(self, channel):
if self.registryValue('rotateLogs', channel): if self.registryValue('rotateLogs', channel, irc.network):
return '%s.%s.log' % (channel, self.logNameTimestamp(channel)) return '%s.%s.log' % (channel, self.logNameTimestamp(channel))
else: else:
return '%s.log' % channel return '%s.log' % channel
@ -118,7 +118,7 @@ class ChannelLogger(callbacks.Plugin):
def checkLogNames(self): def checkLogNames(self):
for (irc, logs) in self.logs.items(): for (irc, logs) in self.logs.items():
for (channel, log) in list(logs.items()): for (channel, log) in list(logs.items()):
if self.registryValue('rotateLogs', channel): if self.registryValue('rotateLogs', channel, irc.network):
name = self.getLogName(channel) name = self.getLogName(channel)
if name != os.path.basename(log.name): if name != os.path.basename(log.name):
log.close() log.close()
@ -156,26 +156,27 @@ class ChannelLogger(callbacks.Plugin):
return ircutils.toLower(channel) return ircutils.toLower(channel)
def doLog(self, irc, channel, s, *args): def doLog(self, irc, channel, s, *args):
if not self.registryValue('enable', channel): if not self.registryValue('enable', channel, irc.network):
return return
s = format(s, *args) s = format(s, *args)
channel = self.normalizeChannel(irc, channel) channel = self.normalizeChannel(irc, channel)
log = self.getLog(irc, channel) log = self.getLog(irc, channel)
if self.registryValue('timestamp', channel): if self.registryValue('timestamp', channel, irc.network):
self.timestamp(log) self.timestamp(log)
if self.registryValue('stripFormatting', channel): if self.registryValue('stripFormatting', channel, irc.network):
s = ircutils.stripFormatting(s) s = ircutils.stripFormatting(s)
if minisix.PY2: if minisix.PY2:
s = s.decode('utf8', 'ignore') s = s.decode('utf8', 'ignore')
log.write(s) log.write(s)
if self.registryValue('flushImmediately'): if self.registryValue('flushImmediately', irc.network):
log.flush() log.flush()
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
(recipients, text) = msg.args (recipients, text) = msg.args
for channel in recipients.split(','): for channel in recipients.split(','):
if irc.isChannel(channel): if irc.isChannel(channel):
noLogPrefix = self.registryValue('noLogPrefix', channel) noLogPrefix = self.registryValue('noLogPrefix',
channel, irc.network)
cap = ircdb.makeChannelCapability(channel, 'logChannelMessages') cap = ircdb.makeChannelCapability(channel, 'logChannelMessages')
try: try:
logChannelMessages = ircdb.checkCapability(msg.prefix, cap, logChannelMessages = ircdb.checkCapability(msg.prefix, cap,
@ -217,7 +218,7 @@ class ChannelLogger(callbacks.Plugin):
def doJoin(self, irc, msg): def doJoin(self, irc, msg):
for channel in msg.args[0].split(','): for channel in msg.args[0].split(','):
if(self.registryValue('showJoinParts', channel)): if(self.registryValue('showJoinParts', channel, irc.network)):
self.doLog(irc, channel, self.doLog(irc, channel,
'*** %s <%s> has joined %s\n', '*** %s <%s> has joined %s\n',
msg.nick, msg.prefix, channel) msg.nick, msg.prefix, channel)
@ -242,7 +243,7 @@ class ChannelLogger(callbacks.Plugin):
else: else:
reason = "" reason = ""
for channel in msg.args[0].split(','): for channel in msg.args[0].split(','):
if(self.registryValue('showJoinParts', channel)): if(self.registryValue('showJoinParts', channel, irc.network)):
self.doLog(irc, channel, self.doLog(irc, channel,
'*** %s <%s> has left %s%s\n', '*** %s <%s> has left %s%s\n',
msg.nick, msg.prefix, channel, reason) msg.nick, msg.prefix, channel, reason)
@ -268,7 +269,7 @@ class ChannelLogger(callbacks.Plugin):
else: else:
reason = "" reason = ""
for channel in msg.tagged('channels'): for channel in msg.tagged('channels'):
if(self.registryValue('showJoinParts', channel)): if(self.registryValue('showJoinParts', channel, irc.network)):
self.doLog(irc, channel, self.doLog(irc, channel,
'*** %s <%s> has quit IRC%s\n', '*** %s <%s> has quit IRC%s\n',
msg.nick, msg.prefix, reason) msg.nick, msg.prefix, reason)

View File

@ -142,8 +142,8 @@ class StatsDB(plugins.ChannelUserDB):
return UserStat(*L) return UserStat(*L)
def addMsg(self, irc, msg, id=None): def addMsg(self, irc, msg, id=None):
if msg.args and irc.isChannel(msg.args[0]): if msg.channel:
channel = plugins.getChannel(msg.args[0]) channel = plugins.getChannel(msg.channel)
if (channel, 'channelStats') not in self: if (channel, 'channelStats') not in self:
self[channel, 'channelStats'] = ChannelStat() self[channel, 'channelStats'] = ChannelStat()
self[channel, 'channelStats'].addMsg(msg) self[channel, 'channelStats'].addMsg(msg)
@ -186,8 +186,8 @@ class ChannelStats(callbacks.Plugin):
def outFilter(self, irc, msg): def outFilter(self, irc, msg):
if msg.command == 'PRIVMSG': if msg.command == 'PRIVMSG':
if irc.isChannel(msg.args[0]): if msg.channel:
if self.registryValue('selfStats', msg.args[0]): if self.registryValue('selfStats', msg.channel, irc.network):
try: try:
self.outFiltering = True self.outFiltering = True
self.db.addMsg(irc, msg, 0) self.db.addMsg(irc, msg, 0)

View File

@ -199,21 +199,22 @@ class Config(callbacks.Plugin):
search = wrap(search, ['lowered']) # XXX compose with withoutSpaces? search = wrap(search, ['lowered']) # XXX compose with withoutSpaces?
def _getValue(self, irc, msg, group, network=None, channel=None, addGlobal=False): def _getValue(self, irc, msg, group, network=None, channel=None, addGlobal=False):
global_group = group
global_value = str(group) or ' ' global_value = str(group) or ' '
group = group.getSpecific( group = group.getSpecific(
network=network.network, channel=channel, check=None) network=network.network, channel=channel, check=False)
value = str(group) or ' ' value = str(group) or ' '
if addGlobal and not irc.nested: if addGlobal and not irc.nested:
value = _( value = _(
'Global: %(global_value)s; ' 'Global: %(global_value)s; '
'%(channel_name)s @ %(network_name)s: %(channel_value)s') % { '%(channel_name)s @ %(network_name)s: %(channel_value)s') % {
'global_value': global_value, 'global_value': global_value,
'channel_name': msg.args[0], 'channel_name': msg.channel,
'network_name': irc.network, 'network_name': irc.network,
'channel_value': value, 'channel_value': value,
} }
if hasattr(group, 'value'): if hasattr(global_group, 'value'):
if not group._private: if not global_group._private:
return (value, None) return (value, None)
else: else:
capability = getCapability(irc, group._name) capability = getCapability(irc, group._name)
@ -224,7 +225,7 @@ class Config(callbacks.Plugin):
else: else:
irc.error(_('That registry variable has no value. Use the list ' irc.error(_('That registry variable has no value. Use the list '
'command in this plugin to see what variables are ' 'command in this plugin to see what variables are '
'available in this group.')) 'available in this group.'), Raise=True)
def _setValue(self, irc, msg, group, value): def _setValue(self, irc, msg, group, value):
if isReadOnly(group._name): if isReadOnly(group._name):
@ -304,7 +305,7 @@ class Config(callbacks.Plugin):
else: else:
(value, private) = self._getValue( (value, private) = self._getValue(
irc, msg, group, network=irc, irc, msg, group, network=irc,
channel=msg.args[0] if irc.isChannel(msg.args[0]) else None, channel=msg.channel,
addGlobal=group._channelValue) addGlobal=group._channelValue)
irc.reply(value, private=private) irc.reply(value, private=private)
config = wrap(config, ['settableConfigVar', additional('text')]) config = wrap(config, ['settableConfigVar', additional('text')])
@ -319,11 +320,10 @@ class Config(callbacks.Plugin):
s = group.help() s = group.help()
if s: if s:
if hasattr(group, 'value') and not group._private: if hasattr(group, 'value') and not group._private:
channel = msg.args[0] if msg.channel and \
if irc.isChannel(channel) and \ msg.channel in group._children:
channel in group._children:
globvalue = str(group) globvalue = str(group)
chanvalue = str(group.get(channel)) chanvalue = str(group.get(msg.channel))
if chanvalue != globvalue: if chanvalue != globvalue:
s += _(' (Current global value: %s; ' s += _(' (Current global value: %s; '
'current channel value: %s)') % \ 'current channel value: %s)') % \

View File

@ -93,13 +93,13 @@ class Dict(callbacks.Plugin):
if words[0] in dbs: if words[0] in dbs:
dictionary = words.pop(0) dictionary = words.pop(0)
else: else:
default = self.registryValue('default', msg.args[0]) default = self.registryValue('default', msg.channel, irc.network)
if default in dbs: if default in dbs:
dictionary = default dictionary = default
else: else:
if default: if default:
self.log.info('Default dict for %s is not a supported ' self.log.info('Default dict for %s @ %s is not a supported '
'dictionary: %s.', msg.args[0], default) 'dictionary: %s.', msg.channel, irc.network, default)
dictionary = '*' dictionary = '*'
if not words: if not words:
irc.error(_('You must give a word to define.'), Raise=True) irc.error(_('You must give a word to define.'), Raise=True)
@ -123,7 +123,7 @@ class Dict(callbacks.Plugin):
L.append('%s: %s' % (db, s)) L.append('%s: %s' % (db, s))
utils.sortBy(len, L) utils.sortBy(len, L)
if dictionary == '*' and len(dbs) > 1 and \ if dictionary == '*' and len(dbs) > 1 and \
self.registryValue("showDictName", msg.args[0]): self.registryValue("showDictName", msg.channel, irc.network):
s = format(_('%L responded: %s'), list(dbs), '; '.join(L)) s = format(_('%L responded: %s'), list(dbs), '; '.join(L))
else: else:
s = '; '.join(L) s = '; '.join(L)

View File

@ -42,12 +42,12 @@ class Dunno(plugins.ChannelIdDatabasePlugin):
callAfter = ['MoobotFactoids', 'Factoids', 'Infobot'] callAfter = ['MoobotFactoids', 'Factoids', 'Infobot']
def invalidCommand(self, irc, msg, tokens): def invalidCommand(self, irc, msg, tokens):
channel = msg.args[0] if msg.channel:
if irc.isChannel(channel): dunno = self.db.random(msg.channel)
dunno = self.db.random(channel)
if dunno is not None: if dunno is not None:
dunno = dunno.text dunno = dunno.text
prefixNick = self.registryValue('prefixNick', channel) prefixNick = self.registryValue('prefixNick',
msg.channel, irc.network)
env = {'command': tokens[0]} env = {'command': tokens[0]}
self.log.info('Issuing "dunno" answer, %s is not a command.', self.log.info('Issuing "dunno" answer, %s is not a command.',
tokens[0]) tokens[0])

View File

@ -53,7 +53,8 @@ from supybot.utils.seq import dameraulevenshtein
def getFactoid(irc, msg, args, state): def getFactoid(irc, msg, args, state):
assert not state.channel assert not state.channel
callConverter('channel', irc, msg, args, state) callConverter('channel', irc, msg, args, state)
separator = state.cb.registryValue('learnSeparator', state.channel) separator = state.cb.registryValue('learnSeparator',
state.channel, irc.network)
try: try:
i = args.index(separator) i = args.index(separator)
except ValueError: except ValueError:
@ -137,7 +138,8 @@ class FactoidsCallback(httpserver.SupyHTTPServerCallback):
{'title': 'Factoids - not a channel', {'title': 'Factoids - not a channel',
'error': 'This is not a channel'}) 'error': 'This is not a channel'})
return return
if not self._plugin.registryValue('web.channel', channel): if not self._plugin.registryValue('web.channel',
channel, irc.network):
self.send_response(403) self.send_response(403)
self.send_header('Content-type', 'text/html; charset=utf-8') self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers() self.end_headers()
@ -252,13 +254,16 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
method = self.getCommandMethod(command) method = self.getCommandMethod(command)
if method.__func__.__name__ == 'learn': if method.__func__.__name__ == 'learn':
chan = None chan = None
network = None
if dynamic.msg is not None: if dynamic.msg is not None:
chan = dynamic.msg.args[0] chan = dynamic.msg.channel
s = self.registryValue('learnSeparator', chan) if dynamic.irc is not None:
network = dynamic.irc.network
s = self.registryValue('learnSeparator', chan, network)
help = callbacks.getHelp help = callbacks.getHelp
if simpleSyntax is None: if simpleSyntax is None:
simpleSyntax = conf.get(conf.supybot.reply.showSimpleSyntax, simpleSyntax = conf.supybot.reply.showSimpleSyntax.getSpecific(
chan) dynamic.irc.network, chan)()
if simpleSyntax: if simpleSyntax:
help = callbacks.getSyntax help = callbacks.getSyntax
return help(method, return help(method,
@ -276,7 +281,7 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
return (keyresults, factresults,) return (keyresults, factresults,)
def learn(self, irc, msg, args, channel, key, factoid): def learn(self, irc, msg, args, channel, key, factoid):
if self.registryValue('requireVoice', channel) and \ if self.registryValue('requireVoice', channel, irc.network) and \
not irc.state.channels[channel].isVoicePlus(msg.nick): not irc.state.channels[channel].isVoicePlus(msg.nick):
irc.error(_('You have to be at least voiced to teach factoids.'), Raise=True) irc.error(_('You have to be at least voiced to teach factoids.'), Raise=True)
@ -366,8 +371,8 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
return [] return []
def _updateRank(self, channel, factoids): def _updateRank(self, network, channel, factoids):
if self.registryValue('keepRankInfo', channel): if self.registryValue('keepRankInfo', channel, network):
db = self.getDb(channel) db = self.getDb(channel)
cursor = db.cursor() cursor = db.cursor()
for (fact,factid,relationid) in factoids: for (fact,factid,relationid) in factoids:
@ -391,7 +396,7 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
if number: if number:
try: try:
irc.reply(format_fact(factoids[number-1][0])) irc.reply(format_fact(factoids[number-1][0]))
self._updateRank(channel, [factoids[number-1]]) self._updateRank(irc.network, channel, [factoids[number-1]])
except IndexError: except IndexError:
irc.error(_('That\'s not a valid number for that key.')) irc.error(_('That\'s not a valid number for that key.'))
return return
@ -399,7 +404,8 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
env = {'key': key} env = {'key': key}
def prefixer(v): def prefixer(v):
env['value'] = v env['value'] = v
formatter = self.registryValue('format', msg.args[0]) formatter = self.registryValue('format',
msg.channel, irc.network)
return ircutils.standardSubstitute(irc, msg, return ircutils.standardSubstitute(irc, msg,
formatter, env) formatter, env)
if len(factoids) == 1: if len(factoids) == 1:
@ -413,7 +419,7 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
counter += 1 counter += 1
irc.replies(factoidsS, prefixer=prefixer, irc.replies(factoidsS, prefixer=prefixer,
joiner=', or ', onlyPrefixFirst=True) joiner=', or ', onlyPrefixFirst=True)
self._updateRank(channel, factoids) self._updateRank(irc.network, channel, factoids)
elif error: elif error:
irc.error(_('No factoid matches that key.')) irc.error(_('No factoid matches that key.'))
@ -429,9 +435,9 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
irc.error('No factoid matches that key.') irc.error('No factoid matches that key.')
def invalidCommand(self, irc, msg, tokens): def invalidCommand(self, irc, msg, tokens):
if irc.isChannel(msg.args[0]): channel = msg.channel
channel = msg.args[0] if channel:
if self.registryValue('replyWhenInvalidCommand', channel): if self.registryValue('replyWhenInvalidCommand', channel, irc.network):
key = ' '.join(tokens) key = ' '.join(tokens)
factoids = self._lookupFactoid(channel, key) factoids = self._lookupFactoid(channel, key)
if factoids: if factoids:
@ -556,7 +562,7 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
itself. itself.
""" """
if not number: if not number:
number = self.registryValue('rankListLength', channel) number = self.registryValue('rankListLength', channel, irc.network)
db = self.getDb(channel) db = self.getDb(channel)
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""SELECT keys.key, relations.usage_count cursor.execute("""SELECT keys.key, relations.usage_count
@ -655,7 +661,7 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
<channel> is only necessary if <channel> is only necessary if
the message isn't sent in the channel itself. the message isn't sent in the channel itself.
""" """
if self.registryValue('requireVoice', channel) and \ if self.registryValue('requireVoice', channel, irc.network) and \
not irc.state.channels[channel].isVoicePlus(msg.nick): not irc.state.channels[channel].isVoicePlus(msg.nick):
irc.error(_('You have to be at least voiced to remove factoids.'), Raise=True) irc.error(_('You have to be at least voiced to remove factoids.'), Raise=True)
number = None number = None
@ -834,7 +840,8 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
if cursor.rowcount == 0: if cursor.rowcount == 0:
irc.reply(_('No keys matched that query.')) irc.reply(_('No keys matched that query.'))
elif cursor.rowcount == 1 and \ elif cursor.rowcount == 1 and \
self.registryValue('showFactoidIfOnlyOneMatch', channel): self.registryValue('showFactoidIfOnlyOneMatch',
channel, irc.network):
self.whatis(irc, msg, [channel, cursor.fetchone()[0]]) self.whatis(irc, msg, [channel, cursor.fetchone()[0]])
elif cursor.rowcount > 100: elif cursor.rowcount > 100:
irc.reply(_('More than 100 keys matched that query; ' irc.reply(_('More than 100 keys matched that query; '
@ -843,7 +850,8 @@ class Factoids(callbacks.Plugin, plugins.ChannelDBHandler):
if len(results) == 0: if len(results) == 0:
irc.reply(_('No keys matched that query.')) irc.reply(_('No keys matched that query.'))
elif len(results) == 1 and \ elif len(results) == 1 and \
self.registryValue('showFactoidIfOnlyOneMatch', channel): self.registryValue('showFactoidIfOnlyOneMatch',
channel, irc.network):
self.whatis(irc, msg, [channel, results[0][0]]) self.whatis(irc, msg, [channel, results[0][0]])
elif len(results) > 100: elif len(results) > 100:
irc.reply(_('More than 100 keys matched that query; ' irc.reply(_('More than 100 keys matched that query; '

View File

@ -63,12 +63,12 @@ class Filter(callbacks.Plugin):
def outFilter(self, irc, msg): def outFilter(self, irc, msg):
if msg.command in ('PRIVMSG', 'NOTICE'): if msg.command in ('PRIVMSG', 'NOTICE'):
if msg.args[0] in self.outFilters: if msg.channel in self.outFilters:
if ircmsgs.isAction(msg): if ircmsgs.isAction(msg):
s = ircmsgs.unAction(msg) s = ircmsgs.unAction(msg)
else: else:
s = msg.args[1] s = msg.args[1]
methods = self.outFilters[msg.args[0]] methods = self.outFilters[msg.channel]
for filtercommand in methods: for filtercommand in methods:
myIrc = MyFilterProxy() myIrc = MyFilterProxy()
filtercommand(myIrc, msg, [s]) filtercommand(myIrc, msg, [s])
@ -651,7 +651,8 @@ class Filter(callbacks.Plugin):
"internationalization" becomes "i18n"). "internationalization" becomes "i18n").
""" """
L = [] L = []
minimum = self.registryValue('shrink.minimum', msg.args[0]) minimum = self.registryValue('shrink.minimum',
msg.channel, irc.network)
r = re.compile(r'[A-Za-z]{%s,}' % minimum) r = re.compile(r'[A-Za-z]{%s,}' % minimum)
def shrink(m): def shrink(m):
s = m.group(0) s = m.group(0)

View File

@ -130,7 +130,7 @@ class Games(callbacks.Plugin):
self._rouletteBullet = random.randrange(0, 6) self._rouletteBullet = random.randrange(0, 6)
irc.reply(_('*SPIN* Are you feeling lucky?'), prefixNick=False) irc.reply(_('*SPIN* Are you feeling lucky?'), prefixNick=False)
return return
channel = msg.args[0] channel = msg.channel
if self._rouletteChamber == self._rouletteBullet: if self._rouletteChamber == self._rouletteBullet:
self._rouletteBullet = random.randrange(0, 6) self._rouletteBullet = random.randrange(0, 6)
self._rouletteChamber = random.randrange(0, 6) self._rouletteChamber = random.randrange(0, 6)

View File

@ -69,7 +69,7 @@ class Google(callbacks.PluginRegexp):
_googleRe = re.compile(r'\b(google)\b', re.I) _googleRe = re.compile(r'\b(google)\b', re.I)
def outFilter(self, irc, msg): def outFilter(self, irc, msg):
if msg.command == 'PRIVMSG' and \ if msg.command == 'PRIVMSG' and \
self.registryValue('colorfulFilter', msg.args[0]): self.registryValue('colorfulFilter', msg.channel, irc.network):
s = msg.args[1] s = msg.args[1]
s = re.sub(self._googleRe, self._getColorGoogle, s) s = re.sub(self._googleRe, self._getColorGoogle, s)
msg = ircmsgs.privmsg(msg.args[0], s, msg=msg) msg = ircmsgs.privmsg(msg.args[0], s, msg=msg)
@ -88,7 +88,7 @@ class Google(callbacks.PluginRegexp):
_gsearchUrl = 'https://www.google.com/search' _gsearchUrl = 'https://www.google.com/search'
def search(self, query, channel, options={}): def search(self, query, channel, network, options={}):
"""search("search phrase", options={}) """search("search phrase", options={})
Valid options are: Valid options are:
@ -121,11 +121,11 @@ class Google(callbacks.PluginRegexp):
opts['safe'] = v opts['safe'] = v
elif k == 'language': elif k == 'language':
opts['hl'] = v opts['hl'] = v
defLang = self.registryValue('defaultLanguage', channel) defLang = self.registryValue('defaultLanguage', channel, network)
if 'hl' not in opts and defLang: if 'hl' not in opts and defLang:
opts['hl'] = defLang.strip('lang_') opts['hl'] = defLang.strip('lang_')
if 'safe' not in opts: if 'safe' not in opts:
opts['safe'] = self.registryValue('searchFilter', dynamic.channel) opts['safe'] = self.registryValue('searchFilter', channel, network)
if 'rsz' not in opts: if 'rsz' not in opts:
opts['rsz'] = 'large' opts['rsz'] = 'large'
@ -169,7 +169,8 @@ class Google(callbacks.PluginRegexp):
If option --snippet is given, returns also the page text snippet. If option --snippet is given, returns also the page text snippet.
""" """
opts = dict(opts) opts = dict(opts)
data = self.search(text, msg.args[0], {'smallsearch': True}) data = self.search(text, msg.channel, irc.network,
{'smallsearch': True})
data = self.decode(data) data = self.decode(data)
if data: if data:
url = data[0]['url'] url = data[0]['url']
@ -195,13 +196,13 @@ class Google(callbacks.PluginRegexp):
if 'language' in optlist and optlist['language'].lower() not in \ if 'language' in optlist and optlist['language'].lower() not in \
conf.supybot.plugins.Google.safesearch.validStrings: conf.supybot.plugins.Google.safesearch.validStrings:
irc.errorInvalid('language') irc.errorInvalid('language')
data = self.search(text, msg.args[0], dict(optlist)) data = self.search(text, msg.channel, irc.network, dict(optlist))
bold = self.registryValue('bold', msg.args[0]) bold = self.registryValue('bold', msg.channel, irc.network)
max = self.registryValue('maximumResults', msg.args[0]) max = self.registryValue('maximumResults', msg.channel, irc.network)
# We don't use supybot.reply.oneToOne here, because you generally # We don't use supybot.reply.oneToOne here, because you generally
# do not want @google to echo ~20 lines of results, even if you # do not want @google to echo ~20 lines of results, even if you
# have reply.oneToOne enabled. # have reply.oneToOne enabled.
onetoone = self.registryValue('oneToOne', msg.args[0]) onetoone = self.registryValue('oneToOne', msg.channel, irc.network)
for result in self.formatData(data, for result in self.formatData(data,
bold=bold, max=max, onetoone=onetoone): bold=bold, max=max, onetoone=onetoone):
irc.reply(result) irc.reply(result)
@ -215,7 +216,7 @@ class Google(callbacks.PluginRegexp):
Returns a link to the cached version of <url> if it is available. Returns a link to the cached version of <url> if it is available.
""" """
data = self.search(url, msg.args[0], {'smallsearch': True}) data = self.search(url, msg.channel, irc.network, {'smallsearch': True})
if data: if data:
m = data[0] m = data[0]
if m['cacheUrl']: if m['cacheUrl']:
@ -233,10 +234,11 @@ class Google(callbacks.PluginRegexp):
Returns the results of each search, in order, from greatest number Returns the results of each search, in order, from greatest number
of results to least. of results to least.
""" """
channel = msg.args[0] channel = msg.channel
network = irc.network
results = [] results = []
for arg in args: for arg in args:
text = self.search(arg, channel, {'smallsearch': True}) text = self.search(arg, channel, network, {'smallsearch': True})
i = text.find('id="resultStats"') i = text.find('id="resultStats"')
stats = utils.web.htmlToText(self._fight_re.search(text).group('stats')) stats = utils.web.htmlToText(self._fight_re.search(text).group('stats'))
if stats == '': if stats == '':
@ -246,7 +248,7 @@ class Google(callbacks.PluginRegexp):
results.append((int(count), arg)) results.append((int(count), arg))
results.sort() results.sort()
results.reverse() results.reverse()
if self.registryValue('bold', msg.args[0]): if self.registryValue('bold', channel, network):
bold = ircutils.bold bold = ircutils.bold
else: else:
bold = repr bold = repr
@ -294,26 +296,26 @@ class Google(callbacks.PluginRegexp):
codes (not language names), which are listed here: codes (not language names), which are listed here:
https://cloud.google.com/translate/docs/languages https://cloud.google.com/translate/docs/languages
""" """
channel = msg.args[0]
(text, language) = self._translate(sourceLang, targetLang, text) (text, language) = self._translate(sourceLang, targetLang, text)
irc.reply(text, language) irc.reply(text, language)
translate = wrap(translate, ['something', 'to', 'something', 'text']) translate = wrap(translate, ['something', 'to', 'something', 'text'])
def googleSnarfer(self, irc, msg, match): def googleSnarfer(self, irc, msg, match):
r"^google\s+(.*)$" r"^google\s+(.*)$"
if not self.registryValue('searchSnarfer', msg.args[0]): if not self.registryValue('searchSnarfer', msg.channel, irc.network):
return return
searchString = match.group(1) searchString = match.group(1)
data = self.search(searchString, msg.args[0], {'smallsearch': True}) data = self.search(searchString, msg.channel, irc.network,
{'smallsearch': True})
if data['responseData']['results']: if data['responseData']['results']:
url = data['responseData']['results'][0]['unescapedUrl'] url = data['responseData']['results'][0]['unescapedUrl']
irc.reply(url, prefixNick=False) irc.reply(url, prefixNick=False)
googleSnarfer = urlSnarfer(googleSnarfer) googleSnarfer = urlSnarfer(googleSnarfer)
def _googleUrl(self, s, channel): def _googleUrl(self, s, channel, network):
s = utils.web.urlquote_plus(s) s = utils.web.urlquote_plus(s)
url = r'http://%s/search?q=%s' % \ url = r'http://%s/search?q=%s' % \
(self.registryValue('baseUrl', channel), s) (self.registryValue('baseUrl', channel, network), s)
return url return url
_calcRe1 = re.compile(r'<span class="cwcot".*?>(.*?)</span>', re.I) _calcRe1 = re.compile(r'<span class="cwcot".*?>(.*?)</span>', re.I)
@ -325,10 +327,7 @@ class Google(callbacks.PluginRegexp):
Uses Google's calculator to calculate the value of <expression>. Uses Google's calculator to calculate the value of <expression>.
""" """
channel = msg.args[0] url = self._googleUrl(expr, msg.channel, irc.network)
if not irc.isChannel(channel):
channel = None
url = self._googleUrl(expr, channel)
h = {"User-Agent":"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36"} h = {"User-Agent":"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36"}
html = utils.web.getUrl(url, headers=h).decode('utf8') html = utils.web.getUrl(url, headers=h).decode('utf8')
match = self._calcRe1.search(html) match = self._calcRe1.search(html)
@ -359,10 +358,7 @@ class Google(callbacks.PluginRegexp):
Looks <phone number> up on Google. Looks <phone number> up on Google.
""" """
channel = msg.args[0] url = self._googleUrl(phonenumber, msg.channel, irc.network)
if not irc.isChannel(channel):
channel = None
url = self._googleUrl(phonenumber, channel)
html = utils.web.getUrl(url).decode('utf8') html = utils.web.getUrl(url).decode('utf8')
m = self._phoneRe.search(html) m = self._phoneRe.search(html)
if m is not None: if m is not None:

View File

@ -92,7 +92,7 @@ class Herald(callbacks.Plugin):
return # Recently split. return # Recently split.
channel = msg.args[0] channel = msg.args[0]
irc = callbacks.SimpleProxy(irc, msg) irc = callbacks.SimpleProxy(irc, msg)
if self.registryValue('heralding', channel): if self.registryValue('heralding', channel, irc.network):
try: try:
id = ircdb.users.getUserId(msg.prefix) id = ircdb.users.getUserId(msg.prefix)
if id in self.splitters: if id in self.splitters:
@ -100,22 +100,26 @@ class Herald(callbacks.Plugin):
return return
herald = self.db[channel, id] herald = self.db[channel, id]
except KeyError: except KeyError:
default = self.registryValue('default', channel) default = self.registryValue('default', channel, irc.network)
if default: if default:
default = ircutils.standardSubstitute(irc, msg, default) default = ircutils.standardSubstitute(irc, msg, default)
msgmaker = ircmsgs.privmsg msgmaker = ircmsgs.privmsg
if self.registryValue('default.notice', channel): if self.registryValue('default.notice',
channel, irc.network):
msgmaker = ircmsgs.notice msgmaker = ircmsgs.notice
target = msg.nick target = msg.nick
if self.registryValue('default.public', channel): if self.registryValue('default.public',
channel, irc.network):
target = channel target = channel
irc.queueMsg(msgmaker(target, default)) irc.queueMsg(msgmaker(target, default))
return return
now = time.time() now = time.time()
throttle = self.registryValue('throttle', channel) throttle = self.registryValue('throttle',
channel, irc.network)
if now - self.lastHerald.get((channel, id), 0) > throttle: if now - self.lastHerald.get((channel, id), 0) > throttle:
if (channel, id) in self.lastParts: if (channel, id) in self.lastParts:
i = self.registryValue('throttle.afterPart', channel) i = self.registryValue('throttle.afterPart',
channel, irc.network)
if now - self.lastParts[channel, id] < i: if now - self.lastParts[channel, id] < i:
return return
self.lastHerald[channel, id] = now self.lastHerald[channel, id] = now
@ -160,7 +164,7 @@ class Herald(callbacks.Plugin):
self.setRegistryValue('default', text, channel) self.setRegistryValue('default', text, channel)
irc.replySuccess() irc.replySuccess()
else: else:
resp = self.registryValue('default', channel) or \ resp = self.registryValue('default', channel, irc.network) or \
_('I do not have a default herald set for %s.') % channel _('I do not have a default herald set for %s.') % channel
irc.reply(resp) irc.reply(resp)
default = wrap(default, ['channel', default = wrap(default, ['channel',

View File

@ -243,16 +243,16 @@ class Karma(callbacks.Plugin):
return thing return thing
def _respond(self, irc, channel, thing, karma): def _respond(self, irc, channel, thing, karma):
if self.registryValue('response', channel): if self.registryValue('response', channel, irc.network):
irc.reply(_('%(thing)s\'s karma is now %(karma)i') % irc.reply(_('%(thing)s\'s karma is now %(karma)i') %
{'thing': thing, 'karma': karma}) {'thing': thing, 'karma': karma})
else: else:
irc.noReply() irc.noReply()
def _doKarma(self, irc, msg, channel, thing): def _doKarma(self, irc, msg, channel, thing):
inc = self.registryValue('incrementChars', channel) inc = self.registryValue('incrementChars', channel, irc.network)
dec = self.registryValue('decrementChars', channel) dec = self.registryValue('decrementChars', channel, irc.network)
onlynicks = self.registryValue('onlyNicks', channel) onlynicks = self.registryValue('onlyNicks', channel, irc.network)
karma = '' karma = ''
for s in inc: for s in inc:
if thing.endswith(s): if thing.endswith(s):
@ -262,7 +262,8 @@ class Karma(callbacks.Plugin):
irc.state.channels[channel].users): irc.state.channels[channel].users):
return return
if ircutils.strEqual(thing, msg.nick) and \ if ircutils.strEqual(thing, msg.nick) and \
not self.registryValue('allowSelfRating', channel): not self.registryValue('allowSelfRating',
channel, irc.network):
irc.error(_('You\'re not allowed to adjust your own karma.')) irc.error(_('You\'re not allowed to adjust your own karma.'))
return return
self.db.increment(channel, self._normalizeThing(thing)) self.db.increment(channel, self._normalizeThing(thing))
@ -274,7 +275,8 @@ class Karma(callbacks.Plugin):
irc.state.channels[channel].users): irc.state.channels[channel].users):
return return
if ircutils.strEqual(thing, msg.nick) and \ if ircutils.strEqual(thing, msg.nick) and \
not self.registryValue('allowSelfRating', channel): not self.registryValue('allowSelfRating',
channel, irc.network):
irc.error(_('You\'re not allowed to adjust your own karma.')) irc.error(_('You\'re not allowed to adjust your own karma.'))
return return
self.db.decrement(channel, self._normalizeThing(thing)) self.db.decrement(channel, self._normalizeThing(thing))
@ -283,23 +285,22 @@ class Karma(callbacks.Plugin):
self._respond(irc, channel, thing, karma[0]-karma[1]) self._respond(irc, channel, thing, karma[0]-karma[1])
def invalidCommand(self, irc, msg, tokens): def invalidCommand(self, irc, msg, tokens):
channel = msg.args[0] if msg.channel and tokens:
if irc.isChannel(channel) and tokens:
thing = ' '.join(tokens) thing = ' '.join(tokens)
self._doKarma(irc, msg, channel, thing) self._doKarma(irc, msg, msg.channel, thing)
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
# We don't handle this if we've been addressed because invalidCommand # We don't handle this if we've been addressed because invalidCommand
# will handle it for us. This prevents us from accessing the db twice # will handle it for us. This prevents us from accessing the db twice
# and therefore crashing. # and therefore crashing.
if not (msg.addressed or msg.repliedTo): if not (msg.addressed or msg.repliedTo):
channel = msg.args[0] if msg.channel and \
if irc.isChannel(channel) and \
not ircmsgs.isCtcp(msg) and \ not ircmsgs.isCtcp(msg) and \
self.registryValue('allowUnaddressedKarma', channel): self.registryValue('allowUnaddressedKarma',
msg.channel, irc.network):
irc = callbacks.SimpleProxy(irc, msg) irc = callbacks.SimpleProxy(irc, msg)
thing = msg.args[1].rstrip() thing = msg.args[1].rstrip()
self._doKarma(irc, msg, channel, thing) self._doKarma(irc, msg, msg.channel, thing)
@internationalizeDocstring @internationalizeDocstring
def karma(self, irc, msg, args, channel, things): def karma(self, irc, msg, args, channel, things):
@ -320,7 +321,7 @@ class Karma(callbacks.Plugin):
else: else:
(added, subtracted) = t (added, subtracted) = t
total = added - subtracted total = added - subtracted
if self.registryValue('simpleOutput', channel): if self.registryValue('simpleOutput', channel, irc.network):
s = format('%s: %i', name, total) s = format('%s: %i', name, total)
else: else:
s = format(_('Karma for %q has been increased %n and ' s = format(_('Karma for %q has been increased %n and '
@ -342,7 +343,7 @@ class Karma(callbacks.Plugin):
irc.reply(_('I didn\'t know the karma for any of those ' irc.reply(_('I didn\'t know the karma for any of those '
'things.')) 'things.'))
else: # No name was given. Return the top/bottom N karmas. else: # No name was given. Return the top/bottom N karmas.
limit = self.registryValue('rankingDisplay', channel) limit = self.registryValue('rankingDisplay', channel, irc.network)
highest = [format('%q (%s)', s, t) highest = [format('%q (%s)', s, t)
for (s, t) in self.db.top(channel, limit)] for (s, t) in self.db.top(channel, limit)]
lowest = [format('%q (%s)', s, t) lowest = [format('%q (%s)', s, t)
@ -372,7 +373,8 @@ class Karma(callbacks.Plugin):
necessary if the message isn't sent in the channel itself. necessary if the message isn't sent in the channel itself.
""" """
L = self.db.most(channel, kind, L = self.db.most(channel, kind,
self.registryValue('mostDisplay', channel)) self.registryValue('mostDisplay',
channel, irc.network))
if L: if L:
L = [format('%q: %i', name, i) for (name, i) in L] L = [format('%q: %i', name, i) for (name, i) in L]
irc.reply(format('%L', L)) irc.reply(format('%L', L))

View File

@ -85,7 +85,7 @@ class Lart(plugins.ChannelIdDatabasePlugin):
text = text.replace('$who', target) text = text.replace('$who', target)
if reason: if reason:
text += _(' for ') + reason text += _(' for ') + reason
if self.registryValue('showIds', channel): if self.registryValue('showIds', channel, irc.network):
text += format(' (#%i)', lart.id) text += format(' (#%i)', lart.id)
irc.reply(text, action=True) irc.reply(text, action=True)
lart = wrap(lart, ['channeldb', optional('id'), 'text']) lart = wrap(lart, ['channeldb', optional('id'), 'text'])

View File

@ -48,9 +48,9 @@ class Limiter(callbacks.Plugin):
irc.noReply() irc.noReply()
def _enforceLimit(self, irc, channel): def _enforceLimit(self, irc, channel):
if self.registryValue('enable', channel): if self.registryValue('enable', channel, irc.network):
maximum = self.registryValue('maximumExcess', channel) maximum = self.registryValue('maximumExcess', channel, irc.network)
minimum = self.registryValue('minimumExcess', channel) minimum = self.registryValue('minimumExcess', channel, irc.network)
assert maximum > minimum assert maximum > minimum
currentUsers = len(irc.state.channels[channel].users) currentUsers = len(irc.state.channels[channel].users)
currentLimit = irc.state.channels[channel].modes.get('l', 0) currentLimit = irc.state.channels[channel].modes.get('l', 0)
@ -62,7 +62,7 @@ class Limiter(callbacks.Plugin):
def doJoin(self, irc, msg): def doJoin(self, irc, msg):
if not ircutils.strEqual(msg.nick, irc.nick): if not ircutils.strEqual(msg.nick, irc.nick):
irc = callbacks.SimpleProxy(irc, msg) irc = callbacks.SimpleProxy(irc, msg)
self._enforceLimit(irc, msg.args[0]) self._enforceLimit(irc, msg.channel)
doPart = doJoin doPart = doJoin
doKick = doJoin doKick = doJoin

View File

@ -115,9 +115,9 @@ class MessageParser(callbacks.Plugin, plugins.ChannelDBHandler):
db.isolation_level = None db.isolation_level = None
return db return db
def _updateRank(self, channel, regexp): def _updateRank(self, network, channel, regexp):
subfolder = None if channel == 'global' else channel subfolder = None if channel == 'global' else channel
if self.registryValue('keepRankInfo', subfolder): if self.registryValue('keepRankInfo', subfolder, network):
db = self.getDb(channel) db = self.getDb(channel)
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""SELECT usage_count cursor.execute("""SELECT usage_count
@ -153,10 +153,10 @@ class MessageParser(callbacks.Plugin, plugins.ChannelDBHandler):
return True return True
def do_privmsg_notice(self, irc, msg): def do_privmsg_notice(self, irc, msg):
channel = msg.args[0] channel = msg.channel
if not irc.isChannel(channel): if not channel:
return return
if self.registryValue('enable', channel): if self.registryValue('enable', channel, irc.network):
actions = [] actions = []
results = [] results = []
for channel in set(map(plugins.getChannel, (channel, 'global'))): for channel in set(map(plugins.getChannel, (channel, 'global'))):
@ -168,12 +168,12 @@ class MessageParser(callbacks.Plugin, plugins.ChannelDBHandler):
results.extend([(channel,)+x for x in cursor.fetchall()]) results.extend([(channel,)+x for x in cursor.fetchall()])
if len(results) == 0: if len(results) == 0:
return return
max_triggers = self.registryValue('maxTriggers', channel) max_triggers = self.registryValue('maxTriggers', channel, irc.network)
for (channel, regexp, action) in results: for (channel, regexp, action) in results:
for match in re.finditer(regexp, msg.args[1]): for match in re.finditer(regexp, msg.args[1]):
if match is not None: if match is not None:
thisaction = action thisaction = action
self._updateRank(channel, regexp) self._updateRank(irc.network, channel, regexp)
for (i, j) in enumerate(match.groups()): for (i, j) in enumerate(match.groups()):
if match.group(i+1) is not None: if match.group(i+1) is not None:
thisaction = re.sub(r'\$' + str(i+1), match.group(i+1), thisaction) thisaction = re.sub(r'\$' + str(i+1), match.group(i+1), thisaction)
@ -192,7 +192,7 @@ class MessageParser(callbacks.Plugin, plugins.ChannelDBHandler):
self.do_privmsg_notice(irc, msg) self.do_privmsg_notice(irc, msg)
def doNotice(self, irc, msg): def doNotice(self, irc, msg):
if self.registryValue('enableForNotices', msg.args[0]): if self.registryValue('enableForNotices', msg.channel, irc.network):
self.do_privmsg_notice(irc, msg) self.do_privmsg_notice(irc, msg)
@internationalizeDocstring @internationalizeDocstring
@ -406,7 +406,7 @@ class MessageParser(callbacks.Plugin, plugins.ChannelDBHandler):
return return
s = [ "%s: %s" % (ircutils.bold('#'+str(regexp[1])), regexp[0]) for regexp in regexps ] s = [ "%s: %s" % (ircutils.bold('#'+str(regexp[1])), regexp[0]) for regexp in regexps ]
separator = self.registryValue('listSeparator', channel) separator = self.registryValue('listSeparator', channel, irc.network)
irc.reply(separator.join(s)) irc.reply(separator.join(s))
list = wrap(list, ['channelOrGlobal']) list = wrap(list, ['channelOrGlobal'])
@ -419,7 +419,7 @@ class MessageParser(callbacks.Plugin, plugins.ChannelDBHandler):
rankListLength registry value. <channel> is only necessary if the rankListLength registry value. <channel> is only necessary if the
message isn't sent in the channel itself. message isn't sent in the channel itself.
""" """
numregexps = self.registryValue('rankListLength', channel) numregexps = self.registryValue('rankListLength', channel, irc.network)
db = self.getDb(channel) db = self.getDb(channel)
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""SELECT regexp, usage_count cursor.execute("""SELECT regexp, usage_count

View File

@ -124,7 +124,7 @@ class Misc(callbacks.Plugin):
utils.timeElapsed(punishment, seconds=False))) utils.timeElapsed(punishment, seconds=False)))
return return
# Now, for normal handling. # Now, for normal handling.
channel = msg.args[0] channel = msg.channel
# Only bother with the invaildCommand flood handling if it's actually # Only bother with the invaildCommand flood handling if it's actually
# enabled # enabled
if conf.supybot.abuse.flood.command.invalid(): if conf.supybot.abuse.flood.command.invalid():
@ -138,7 +138,8 @@ class Misc(callbacks.Plugin):
msg.prefix != irc.prefix and \ msg.prefix != irc.prefix and \
ircutils.isUserHostmask(msg.prefix): ircutils.isUserHostmask(msg.prefix):
penalty = conf.supybot.abuse.flood.command.invalid.punishment() penalty = conf.supybot.abuse.flood.command.invalid.punishment()
banmask = banmasker(msg.prefix, channel=None) banmask = banmasker(msg.prefix, channel=channel,
network=irc.network)
self.log.info('Ignoring %s for %s seconds due to an apparent ' self.log.info('Ignoring %s for %s seconds due to an apparent '
'invalid command flood.', banmask, penalty) 'invalid command flood.', banmask, penalty)
if tokens and tokens[0] == 'Error:': if tokens and tokens[0] == 'Error:':
@ -153,7 +154,8 @@ class Misc(callbacks.Plugin):
utils.timeElapsed(penalty, seconds=False))) utils.timeElapsed(penalty, seconds=False)))
return return
# Now, for normal handling. # Now, for normal handling.
if conf.get(conf.supybot.reply.whenNotCommand, channel): if conf.supybot.reply.whenNotCommand.getSpecific(
channel, irc.network)():
if len(tokens) >= 2: if len(tokens) >= 2:
cb = irc.getCallback(tokens[0]) cb = irc.getCallback(tokens[0])
if cb: if cb:
@ -177,7 +179,7 @@ class Misc(callbacks.Plugin):
if channel != irc.nick else _('private')) if channel != irc.nick else _('private'))
if irc.nested: if irc.nested:
bracketConfig = conf.supybot.commands.nested.brackets bracketConfig = conf.supybot.commands.nested.brackets
brackets = conf.get(bracketConfig, channel) brackets = bracketConfig.getSpecific(channel, irc.network)()
if brackets: if brackets:
(left, right) = brackets (left, right) = brackets
irc.reply(left + ' '.join(tokens) + right) irc.reply(left + ' '.join(tokens) + right)
@ -386,7 +388,7 @@ class Misc(callbacks.Plugin):
return return
try: try:
L = irc._mores[userHostmask] L = irc._mores[userHostmask]
number = self.registryValue('mores', msg.args[0]) number = self.registryValue('mores', msg.channel, irc.network)
chunks = [L.pop() for x in range(0, number)] chunks = [L.pop() for x in range(0, number)]
if L: if L:
if len(L) < 2: if len(L) < 2:
@ -406,7 +408,7 @@ class Misc(callbacks.Plugin):
def _validLastMsg(self, irc, msg): def _validLastMsg(self, irc, msg):
return msg.prefix and \ return msg.prefix and \
msg.command == 'PRIVMSG' and \ msg.command == 'PRIVMSG' and \
irc.isChannel(msg.args[0]) msg.channel
@internationalizeDocstring @internationalizeDocstring
def last(self, irc, msg, args, optlist): def last(self, irc, msg, args, optlist):
@ -423,9 +425,9 @@ class Misc(callbacks.Plugin):
predicates = {} predicates = {}
nolimit = False nolimit = False
skipfirst = True skipfirst = True
if irc.isChannel(msg.args[0]): if msg.channel:
predicates['in'] = lambda m: ircutils.strEqual(m.args[0], predicates['in'] = lambda m: ircutils.strEqual(m.args[0],
msg.args[0]) msg.channel)
else: else:
skipfirst = False skipfirst = False
for (option, arg) in optlist: for (option, arg) in optlist:
@ -437,7 +439,7 @@ class Misc(callbacks.Plugin):
def f(m, arg=arg): def f(m, arg=arg):
return ircutils.strEqual(m.args[0], arg) return ircutils.strEqual(m.args[0], arg)
predicates['in'] = f predicates['in'] = f
if arg != msg.args[0]: if arg != msg.channel:
skipfirst = False skipfirst = False
elif option == 'on': elif option == 'on':
def f(m, arg=arg): def f(m, arg=arg):
@ -484,6 +486,7 @@ class Misc(callbacks.Plugin):
predicates.append(userInChannel) predicates.append(userInChannel)
# Make sure the user can't get messages from a +s channel unless # Make sure the user can't get messages from a +s channel unless
# they're calling the command from that channel or from a query # they're calling the command from that channel or from a query
# TODO: support statusmsg, but be careful about leaking scopes.
def notSecretMsg(m): def notSecretMsg(m):
return not irc.isChannel(msg.args[0]) \ return not irc.isChannel(msg.args[0]) \
or msg.args[0] == m.args[0] \ or msg.args[0] == m.args[0] \

View File

@ -325,7 +325,7 @@ class MoobotFactoids(callbacks.Plugin):
else: else:
key = ' '.join(tokens) key = ' '.join(tokens)
key = self._sanitizeKey(key) key = self._sanitizeKey(key)
channel = plugins.getChannel(msg.args[0]) channel = plugins.getChannel(msg.channel)
fact = self.db.getFactoid(channel, key) fact = self.db.getFactoid(channel, key)
if fact: if fact:
self.db.updateRequest(channel, key, msg.prefix) self.db.updateRequest(channel, key, msg.prefix)
@ -385,7 +385,7 @@ class MoobotFactoids(callbacks.Plugin):
def addFactoid(self, irc, msg, tokens): def addFactoid(self, irc, msg, tokens):
# First, check and see if the entire message matches a factoid key # First, check and see if the entire message matches a factoid key
channel = plugins.getChannel(msg.args[0]) channel = plugins.getChannel(msg.channel)
id = self._getUserId(irc, msg.prefix) id = self._getUserId(irc, msg.prefix)
try: try:
(key, fact) = self._getKeyAndFactoid(tokens) (key, fact) = self._getKeyAndFactoid(tokens)
@ -401,7 +401,7 @@ class MoobotFactoids(callbacks.Plugin):
id = self._getUserId(irc, msg.prefix) id = self._getUserId(irc, msg.prefix)
(key, regexp) = list(map(' '.join, (key, regexp) = list(map(' '.join,
utils.iter.split('=~'.__eq__, tokens, maxsplit=1))) utils.iter.split('=~'.__eq__, tokens, maxsplit=1)))
channel = plugins.getChannel(msg.args[0]) channel = plugins.getChannel(msg.channel)
# Check and make sure it's in the DB # Check and make sure it's in the DB
fact = self._getFactoid(irc, channel, key) fact = self._getFactoid(irc, channel, key)
self._checkNotLocked(irc, channel, key) self._checkNotLocked(irc, channel, key)
@ -422,7 +422,7 @@ class MoobotFactoids(callbacks.Plugin):
isAlso = pairs.index(['is', 'also']) isAlso = pairs.index(['is', 'also'])
key = ' '.join(tokens[:isAlso]) key = ' '.join(tokens[:isAlso])
new_text = ' '.join(tokens[isAlso+2:]) new_text = ' '.join(tokens[isAlso+2:])
channel = plugins.getChannel(msg.args[0]) channel = plugins.getChannel(msg.channel)
fact = self._getFactoid(irc, channel, key) fact = self._getFactoid(irc, channel, key)
self._checkNotLocked(irc, channel, key) self._checkNotLocked(irc, channel, key)
# It's fair game if we get to here # It's fair game if we get to here
@ -433,7 +433,7 @@ class MoobotFactoids(callbacks.Plugin):
def replaceFactoid(self, irc, msg, tokens): def replaceFactoid(self, irc, msg, tokens):
# Must be registered! # Must be registered!
channel = plugins.getChannel(msg.args[0]) channel = plugins.getChannel(msg.channel)
id = self._getUserId(irc, msg.prefix) id = self._getUserId(irc, msg.prefix)
del tokens[0] # remove the "no," del tokens[0] # remove the "no,"
try: try:
@ -576,7 +576,7 @@ class MoobotFactoids(callbacks.Plugin):
method = getattr(self, '_most%s' % method, None) method = getattr(self, '_most%s' % method, None)
if method is None: if method is None:
raise callbacks.ArgumentError raise callbacks.ArgumentError
limit = self.registryValue('mostCount', channel) limit = self.registryValue('mostCount', channel, irc.network)
method(irc, channel, limit) method(irc, channel, limit)
most = wrap(most, ['channeldb', most = wrap(most, ['channeldb',
('literal', ('popular', 'authored', 'recent'))]) ('literal', ('popular', 'authored', 'recent'))])
@ -652,7 +652,8 @@ class MoobotFactoids(callbacks.Plugin):
if not results: if not results:
irc.reply(format(_('No keys matching %q found.'), search)) irc.reply(format(_('No keys matching %q found.'), search))
elif len(results) == 1 and \ elif len(results) == 1 and \
self.registryValue('showFactoidIfOnlyOneMatch', channel): self.registryValue('showFactoidIfOnlyOneMatch',
channel, irc.network):
key = results[0][0] key = results[0][0]
self.invalidCommand(irc, msg, [key]) self.invalidCommand(irc, msg, [key])
else: else:

View File

@ -186,7 +186,7 @@ class Note(callbacks.Plugin):
specified by separating their names by commas. specified by separating their names by commas.
""" """
# Let's get the from user. # Let's get the from user.
public = irc.isChannel(msg.args[0]) public = bool(msg.channel)
sent = [] sent = []
for target in targets: for target in targets:
id = self.db.send(user.id, target.id, public, text) id = self.db.send(user.id, target.id, public, text)
@ -209,7 +209,7 @@ class Note(callbacks.Plugin):
'that have been sent to you.', Raise=True) 'that have been sent to you.', Raise=True)
self.db.setRead(id) self.db.setRead(id)
text += ' (in reply to #%s)' % id text += ' (in reply to #%s)' % id
public = irc.isChannel(msg.args[0]) public = bool(msg.channel)
try: try:
target = ircdb.users.getUser(note.frm) target = ircdb.users.getUser(note.frm)
except KeyError: except KeyError:
@ -271,7 +271,7 @@ class Note(callbacks.Plugin):
note = wrap(note, ['user', ('id', 'note')]) note = wrap(note, ['user', ('id', 'note')])
def _formatNoteId(self, irc, msg, note, sent=False): def _formatNoteId(self, irc, msg, note, sent=False):
if note.public or not irc.isChannel(msg.args[0]): if note.public or not msg.channel:
if sent: if sent:
sender = plugins.getUserName(note.to) sender = plugins.getUserName(note.to)
return format('#%i to %s', note.id, sender) return format('#%i to %s', note.id, sender)

View File

@ -258,7 +258,8 @@ class Owner(callbacks.Plugin):
utils.timeElapsed(punishment, seconds=False))) utils.timeElapsed(punishment, seconds=False)))
return return
try: try:
tokens = callbacks.tokenize(s, channel=msg.args[0]) tokens = callbacks.tokenize(s, channel=msg.channel,
network=irc.network)
self.Proxy(irc, msg, tokens) self.Proxy(irc, msg, tokens)
except SyntaxError as e: except SyntaxError as e:
irc.error(str(e)) irc.error(str(e))

View File

@ -84,7 +84,7 @@ class Praise(plugins.ChannelIdDatabasePlugin):
text = text.replace('$who', target) text = text.replace('$who', target)
if reason: if reason:
text += _(' for ') + reason text += _(' for ') + reason
if self.registryValue('showIds', channel): if self.registryValue('showIds', channel, irc.network):
text += format(' (#%i)', praise.id) text += format(' (#%i)', praise.id)
irc.reply(text, action=True) irc.reply(text, action=True)
praise = wrap(praise, ['channeldb', optional('id'), 'text']) praise = wrap(praise, ['channeldb', optional('id'), 'text'])

View File

@ -45,7 +45,7 @@ class Protector(callbacks.Plugin):
if ircutils.strEqual(msg.nick, irc.nick): if ircutils.strEqual(msg.nick, irc.nick):
self.log.debug('%q is immune, it\'s me.', msg) self.log.debug('%q is immune, it\'s me.', msg)
return True # It's the bot itself. return True # It's the bot itself.
if msg.nick in self.registryValue('immune', msg.args[0]): if msg.nick in self.registryValue('immune', msg.channel, irc.network):
self.log.debug('%q is immune, it\'s configured to be immune.', msg) self.log.debug('%q is immune, it\'s configured to be immune.', msg)
return True return True
return False return False
@ -78,18 +78,18 @@ class Protector(callbacks.Plugin):
self.log.debug('Ignoring %q, %s.', msg, reason) self.log.debug('Ignoring %q, %s.', msg, reason)
if not msg.args: if not msg.args:
ignore('no msg.args') ignore('no msg.args')
elif not irc.isChannel(msg.args[0]): elif not msg.channel:
ignore('not on a channel') ignore('not on a channel')
elif not self.registryValue('enable', msg.args[0]): elif not self.registryValue('enable', msg.channel, irc.network):
ignore('supybot.plugins.Protector.enable is False.') ignore('supybot.plugins.Protector.enable is False.')
elif msg.args[0] not in irc.state.channels: elif msg.channel not in irc.state.channels:
# One has to wonder how this would happen, but just in case... # One has to wonder how this would happen, but just in case...
ignore('bot isn\'t in channel') ignore('bot isn\'t in channel')
elif irc.nick not in irc.state.channels[msg.args[0]].ops: elif irc.nick not in irc.state.channels[msg.channel].ops:
ignore('bot is not opped') ignore('bot is not opped')
elif msg.nick not in irc.state.channels[msg.args[0]].users: elif msg.nick not in irc.state.channels[msg.channel].users:
ignore('sender is not in channel (ChanServ, maybe?)') ignore('sender is not in channel (ChanServ, maybe?)')
elif msg.nick not in irc.state.channels[msg.args[0]].ops: elif msg.nick not in irc.state.channels[msg.channel].ops:
ignore('sender is not an op in channel (IRCOP, maybe?)') ignore('sender is not an op in channel (IRCOP, maybe?)')
elif self.isImmune(irc, msg): elif self.isImmune(irc, msg):
ignore('sender is immune') ignore('sender is immune')
@ -97,7 +97,7 @@ class Protector(callbacks.Plugin):
super(Protector, self).__call__(irc, msg) super(Protector, self).__call__(irc, msg)
def doMode(self, irc, msg): def doMode(self, irc, msg):
channel = msg.args[0] channel = msg.channel
chanOp = ircdb.makeChannelCapability(channel, 'op') chanOp = ircdb.makeChannelCapability(channel, 'op')
chanVoice = ircdb.makeChannelCapability(channel, 'voice') chanVoice = ircdb.makeChannelCapability(channel, 'voice')
chanHalfOp = ircdb.makeChannelCapability(channel, 'halfop') chanHalfOp = ircdb.makeChannelCapability(channel, 'halfop')
@ -134,7 +134,7 @@ class Protector(callbacks.Plugin):
# Handle bans. # Handle bans.
def doKick(self, irc, msg): def doKick(self, irc, msg):
channel = msg.args[0] channel = msg.channel
kicked = msg.args[1].split(',') kicked = msg.args[1].split(',')
protected = [] protected = []
for nick in kicked: for nick in kicked:

View File

@ -241,14 +241,17 @@ class QuoteGrabs(callbacks.Plugin):
if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg): if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg):
return return
irc = callbacks.SimpleProxy(irc, msg) irc = callbacks.SimpleProxy(irc, msg)
if irc.isChannel(msg.args[0]): if msg.channel:
(chan, payload) = msg.args payload = msg.args[1]
words = self.registryValue('randomGrabber.minimumWords', chan) words = self.registryValue('randomGrabber.minimumWords',
length = self.registryValue('randomGrabber.minimumCharacters',chan) msg.channel, irc.network)
length = self.registryValue('randomGrabber.minimumCharacters',
msg.channel, irc.network)
grabTime = \ grabTime = \
self.registryValue('randomGrabber.averageTimeBetweenGrabs', chan) self.registryValue('randomGrabber.averageTimeBetweenGrabs',
channel = plugins.getChannel(chan) msg.channel, irc.network)
if self.registryValue('randomGrabber', chan): channel = plugins.getChannel(msg.channel)
if self.registryValue('randomGrabber', msg.channel, irc.network):
if len(payload) > length and len(payload.split()) > words: if len(payload) > length and len(payload.split()) > words:
try: try:
last = int(self.db.select(channel, msg.nick)) last = int(self.db.select(channel, msg.nick))
@ -287,6 +290,8 @@ class QuoteGrabs(callbacks.Plugin):
for m in reversed(irc.state.history): for m in reversed(irc.state.history):
if m.command == 'PRIVMSG' and ircutils.nickEqual(m.nick, nick) \ if m.command == 'PRIVMSG' and ircutils.nickEqual(m.nick, nick) \
and ircutils.strEqual(m.args[0], chan): and ircutils.strEqual(m.args[0], chan):
# TODO: strip statusmsg prefix for comparison? Must be careful
# abouk leaks, though.
self._grab(channel, irc, m, msg.prefix) self._grab(channel, irc, m, msg.prefix)
irc.replySuccess() irc.replySuccess()
return return

View File

@ -352,7 +352,7 @@ class RSS(callbacks.Plugin):
announced_feeds = set() announced_feeds = set()
for irc in world.ircs: for irc in world.ircs:
for channel in irc.state.channels: for channel in irc.state.channels:
announced_feeds |= self.registryValue('announce', channel) announced_feeds |= self.registryValue('announce', channel, irc.network)
for name in announced_feeds: for name in announced_feeds:
feed = self.get_feed(name) feed = self.get_feed(name)
if not feed: if not feed:
@ -385,14 +385,15 @@ class RSS(callbacks.Plugin):
new_entries = sort_feed_items(new_entries, 'newestFirst') new_entries = sort_feed_items(new_entries, 'newestFirst')
for irc in world.ircs: for irc in world.ircs:
for channel in irc.state.channels: for channel in irc.state.channels:
if feed.name not in self.registryValue('announce', channel): if feed.name not in self.registryValue('announce',
channel, irc.network):
continue continue
if initial: if initial:
max_entries = \ max_entries = self.registryValue(
self.registryValue('initialAnnounceHeadlines', channel) 'initialAnnounceHeadlines', channel, irc.network)
else: else:
max_entries = \ max_entries = self.registryValue(
self.registryValue('maximumAnnounceHeadlines', channel) 'maximumAnnounceHeadlines', channel, irc.network)
announced_entries = new_entries[0:max_entries] announced_entries = new_entries[0:max_entries]
announced_entries = sort_feed_items(announced_entries, order) announced_entries = sort_feed_items(announced_entries, order)
for entry in announced_entries: for entry in announced_entries:
@ -402,9 +403,9 @@ class RSS(callbacks.Plugin):
################# #################
# Entry rendering # Entry rendering
def should_send_entry(self, channel, entry): def should_send_entry(self, network, channel, entry):
whitelist = self.registryValue('keywordWhitelist', channel) whitelist = self.registryValue('keywordWhitelist', channel, network)
blacklist = self.registryValue('keywordBlacklist', channel) blacklist = self.registryValue('keywordBlacklist', channel, network)
# fix shadowing by "from supybot.commands import *" # fix shadowing by "from supybot.commands import *"
try: try:
@ -429,14 +430,15 @@ class RSS(callbacks.Plugin):
_normalize_entry = utils.str.multipleReplacer( _normalize_entry = utils.str.multipleReplacer(
{'\r': ' ', '\n': ' ', '\x00': ''}) {'\r': ' ', '\n': ' ', '\x00': ''})
def format_entry(self, channel, feed, entry, is_announce): def format_entry(self, network, channel, feed, entry, is_announce):
key_name = 'announceFormat' if is_announce else 'format' key_name = 'announceFormat' if is_announce else 'format'
if feed.name in self.registryValue('feeds'): if feed.name in self.registryValue('feeds'):
specific_key_name = registry.join(['feeds', feed.name, key_name]) specific_key_name = registry.join(['feeds', feed.name, key_name])
template = self.registryValue(specific_key_name, channel) or \ template = self.registryValue(specific_key_name,
self.registryValue(key_name, channel) channel, network) or \
self.registryValue(key_name, channel, network)
else: else:
template = self.registryValue(key_name, channel) template = self.registryValue(key_name, channel, network)
date = entry.get('published_parsed') date = entry.get('published_parsed')
date = utils.str.timestamp(date) date = utils.str.timestamp(date)
s = string.Template(template).substitute( s = string.Template(template).substitute(
@ -446,9 +448,9 @@ class RSS(callbacks.Plugin):
return self._normalize_entry(s) return self._normalize_entry(s)
def announce_entry(self, irc, channel, feed, entry): def announce_entry(self, irc, channel, feed, entry):
if self.should_send_entry(channel, entry): if self.should_send_entry(irc.network, channel, entry):
s = self.format_entry(channel, feed, entry, True) s = self.format_entry(irc.network, channel, feed, entry, True)
if self.registryValue('notice', channel): if self.registryValue('notice', channel, irc.network):
m = ircmsgs.notice(channel, s) m = ircmsgs.notice(channel, s)
else: else:
m = ircmsgs.privmsg(channel, s) m = ircmsgs.privmsg(channel, s)
@ -559,10 +561,7 @@ class RSS(callbacks.Plugin):
feed = self.get_feed(url) feed = self.get_feed(url)
if not feed: if not feed:
feed = Feed(url, url, True) feed = Feed(url, url, True)
if irc.isChannel(msg.args[0]): channel = msg.channel
channel = msg.args[0]
else:
channel = None
self.update_feed_if_needed(feed) self.update_feed_if_needed(feed)
entries = feed.entries entries = feed.entries
if not entries: if not entries:
@ -573,13 +572,13 @@ class RSS(callbacks.Plugin):
s += str(feed.last_exception) s += str(feed.last_exception)
irc.error(s) irc.error(s)
return return
n = n or self.registryValue('defaultNumberOfHeadlines', channel) n = n or self.registryValue('defaultNumberOfHeadlines', channel, irc.network)
entries = list(filter(lambda e:self.should_send_entry(channel, e), entries = list(filter(lambda e:self.should_send_entry(irc.network, channel, e),
feed.entries)) feed.entries))
entries = entries[:n] entries = entries[:n]
headlines = map(lambda e:self.format_entry(channel, feed, e, False), headlines = map(lambda e:self.format_entry(irc.network, channel, feed, e, False),
entries) entries)
sep = self.registryValue('headlineSeparator', channel) sep = self.registryValue('headlineSeparator', channel, irc.network)
irc.replies(headlines, joiner=sep) irc.replies(headlines, joiner=sep)
rss = wrap(rss, [first('url', 'feedName'), additional('int')]) rss = wrap(rss, [first('url', 'feedName'), additional('int')])

View File

@ -197,7 +197,7 @@ class Relay(callbacks.Plugin):
do401 = do402 do401 = do402
def _formatPrivmsg(self, nick, network, msg): def _formatPrivmsg(self, nick, network, msg):
channel = msg.args[0] channel = msg.channel
if self.registryValue('includeNetwork', channel): if self.registryValue('includeNetwork', channel):
network = '@' + network network = '@' + network
else: else:
@ -229,12 +229,12 @@ class Relay(callbacks.Plugin):
assert msg.command in ('PRIVMSG', 'NOTICE', 'TOPIC') assert msg.command in ('PRIVMSG', 'NOTICE', 'TOPIC')
for otherIrc in world.ircs: for otherIrc in world.ircs:
if otherIrc != irc and not otherIrc.zombie: if otherIrc != irc and not otherIrc.zombie:
if msg.args[0] in otherIrc.state.channels: if msg.channel in otherIrc.state.channels:
msg.tag('relayedMsg') msg.tag('relayedMsg')
otherIrc.queueMsg(msg) otherIrc.queueMsg(msg)
def _checkRelayMsg(self, msg): def _checkRelayMsg(self, msg):
channel = msg.args[0] channel = msg.channel
if channel in self.lastRelayMsgs: if channel in self.lastRelayMsgs:
q = self.lastRelayMsgs[channel] q = self.lastRelayMsgs[channel]
unformatted = ircutils.stripFormatting(msg.args[1]) unformatted = ircutils.stripFormatting(msg.args[1])
@ -247,7 +247,7 @@ class Relay(callbacks.Plugin):
def _punishRelayers(self, msg): def _punishRelayers(self, msg):
assert self._checkRelayMsg(msg), 'Punishing without checking.' assert self._checkRelayMsg(msg), 'Punishing without checking.'
who = msg.prefix who = msg.prefix
channel = msg.args[0] channel = msg.channel
def notPunishing(irc, s, *args): def notPunishing(irc, s, *args):
self.log.info('Not punishing %s in %s on %s: %s.', self.log.info('Not punishing %s in %s on %s: %s.',
msg.prefix, channel, irc.network, s, *args) msg.prefix, channel, irc.network, s, *args)
@ -268,12 +268,12 @@ class Relay(callbacks.Plugin):
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg): if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg):
return return
(channel, text) = msg.args text = msg.args[1]
if irc.isChannel(channel): if msg.channel:
irc = self._getRealIrc(irc) irc = self._getRealIrc(irc)
if channel not in self.registryValue('channels'): if msg.channel not in self.registryValue('channels'):
return return
ignores = self.registryValue('ignores', channel) ignores = self.registryValue('ignores', msg.channel, irc.network)
for ignore in ignores: for ignore in ignores:
if ircutils.hostmaskPatternEqual(ignore, msg.prefix): if ircutils.hostmaskPatternEqual(ignore, msg.prefix):
self.log.debug('Refusing to relay %s, ignored by %s.', self.log.debug('Refusing to relay %s, ignored by %s.',
@ -281,7 +281,8 @@ class Relay(callbacks.Plugin):
return return
# Let's try to detect other relay bots. # Let's try to detect other relay bots.
if self._checkRelayMsg(msg): if self._checkRelayMsg(msg):
if self.registryValue('punishOtherRelayBots', channel): if self.registryValue('punishOtherRelayBots',
msg.channel, irc.network):
self._punishRelayers(msg) self._punishRelayers(msg)
# Either way, we don't relay the message. # Either way, we don't relay the message.
else: else:
@ -291,13 +292,12 @@ class Relay(callbacks.Plugin):
else: else:
network = self._getIrcName(irc) network = self._getIrcName(irc)
s = self._formatPrivmsg(msg.nick, network, msg) s = self._formatPrivmsg(msg.nick, network, msg)
m = self._msgmaker(channel, s) m = self._msgmaker(msg.channel, network, s)
self._sendToOthers(irc, m) self._sendToOthers(irc, m)
def _msgmaker(self, target, s): def _msgmaker(self, target, network, s):
msg = dynamic.msg msg = dynamic.msg
channel = dynamic.channel if self.registryValue('noticeNonPrivmsgs', target) and \
if self.registryValue('noticeNonPrivmsgs', dynamic.channel) and \
msg.command != 'PRIVMSG': msg.command != 'PRIVMSG':
return ircmsgs.notice(target, s) return ircmsgs.notice(target, s)
else: else:
@ -423,16 +423,15 @@ class Relay(callbacks.Plugin):
if msg.relayedMsg: if msg.relayedMsg:
self._addRelayMsg(msg) self._addRelayMsg(msg)
else: else:
channel = msg.args[0] if msg.channel in self.registryValue('channels'):
if channel in self.registryValue('channels'):
network = self._getIrcName(irc) network = self._getIrcName(irc)
s = self._formatPrivmsg(irc.nick, network, msg) s = self._formatPrivmsg(irc.nick, network, msg)
relayMsg = self._msgmaker(channel, s) relayMsg = self._msgmaker(msg.args[0], s)
self._sendToOthers(irc, relayMsg) self._sendToOthers(irc, relayMsg)
return msg return msg
def _addRelayMsg(self, msg): def _addRelayMsg(self, msg):
channel = msg.args[0] channel = msg.channel
if channel in self.lastRelayMsgs: if channel in self.lastRelayMsgs:
q = self.lastRelayMsgs[channel] q = self.lastRelayMsgs[channel]
else: else:

View File

@ -125,8 +125,8 @@ class Seen(callbacks.Plugin):
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg): if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg):
return return
if irc.isChannel(msg.args[0]): if msg.channel:
channel = msg.args[0] channel = msg.channel
said = ircmsgs.prettyPrint(msg) said = ircmsgs.prettyPrint(msg)
self.db.update(channel, msg.nick, said) self.db.update(channel, msg.nick, said)
self.anydb.update(channel, msg.nick, said) self.anydb.update(channel, msg.nick, said)
@ -184,7 +184,8 @@ class Seen(callbacks.Plugin):
results = [] results = []
if '*' in name: if '*' in name:
if (len(name.replace('*', '')) < if (len(name.replace('*', '')) <
self.registryValue('minimumNonWildcard', channel)): self.registryValue('minimumNonWildcard',
channel, irc.network)):
irc.error(_('Not enough non-wildcard characters.'), irc.error(_('Not enough non-wildcard characters.'),
Raise=True) Raise=True)
results = db.seenWildcard(channel, name) results = db.seenWildcard(channel, name)
@ -196,7 +197,7 @@ class Seen(callbacks.Plugin):
reply = format(_('%s was last seen in %s %s ago'), reply = format(_('%s was last seen in %s %s ago'),
nick, channel, nick, channel,
utils.timeElapsed(time.time()-when)) utils.timeElapsed(time.time()-when))
if self.registryValue('showLastMessage', channel): if self.registryValue('showLastMessage', channel, irc.network):
if minisix.PY2: if minisix.PY2:
said = said.decode('utf8') said = said.decode('utf8')
reply = _('%s: %s') % (reply, said) reply = _('%s: %s') % (reply, said)
@ -277,7 +278,7 @@ class Seen(callbacks.Plugin):
(when, said) = db.seen(channel, '<last>') (when, said) = db.seen(channel, '<last>')
reply = format(_('Someone was last seen in %s %s ago'), reply = format(_('Someone was last seen in %s %s ago'),
channel, utils.timeElapsed(time.time()-when)) channel, utils.timeElapsed(time.time()-when))
if self.registryValue('showLastMessage', channel): if self.registryValue('showLastMessage', channel, irc.network):
reply = _('%s: %s') % (reply, said) reply = _('%s: %s') % (reply, said)
irc.reply(reply) irc.reply(reply)
except KeyError: except KeyError:
@ -304,7 +305,7 @@ class Seen(callbacks.Plugin):
reply = format(_('%s was last seen in %s %s ago'), reply = format(_('%s was last seen in %s %s ago'),
user.name, channel, user.name, channel,
utils.timeElapsed(time.time()-when)) utils.timeElapsed(time.time()-when))
if self.registryValue('showLastMessage', channel): if self.registryValue('showLastMessage', channel, irc.network):
reply = _('%s: %s') % (reply, said) reply = _('%s: %s') % (reply, said)
irc.reply(reply) irc.reply(reply)
except KeyError: except KeyError:

View File

@ -76,8 +76,8 @@ class Services(callbacks.Plugin):
if msg.command == 'JOIN' and not self.disabled(irc): if msg.command == 'JOIN' and not self.disabled(irc):
if not self.identified: if not self.identified:
if self.registryValue('noJoinsUntilIdentified'): if self.registryValue('noJoinsUntilIdentified'):
self.log.info('Holding JOIN to %s until identified.', self.log.info('Holding JOIN to %s @ %s until identified.',
msg.args[0]) msg.channel, irc.network)
self.waitingJoins.setdefault(irc.network, []) self.waitingJoins.setdefault(irc.network, [])
self.waitingJoins[irc.network].append(msg) self.waitingJoins[irc.network].append(msg)
return None return None
@ -357,17 +357,17 @@ class Services(callbacks.Plugin):
return return
chanserv = self.registryValue('ChanServ') chanserv = self.registryValue('ChanServ')
on = 'on %s' % irc.network on = 'on %s' % irc.network
if chanserv and self.registryValue('ChanServ.op', channel): if chanserv and self.registryValue('ChanServ.op', channel, irc.network):
if irc.nick not in irc.state.channels[channel].ops: if irc.nick not in irc.state.channels[channel].ops:
self.log.info('Requesting op from %s in %s %s.', self.log.info('Requesting op from %s in %s %s.',
chanserv, channel, on) chanserv, channel, on)
irc.sendMsg(ircmsgs.privmsg(chanserv, 'op %s' % channel)) irc.sendMsg(ircmsgs.privmsg(chanserv, 'op %s' % channel))
if chanserv and self.registryValue('ChanServ.halfop', channel): if chanserv and self.registryValue('ChanServ.halfop', channel, irc.network):
if irc.nick not in irc.state.channels[channel].halfops: if irc.nick not in irc.state.channels[channel].halfops:
self.log.info('Requesting halfop from %s in %s %s.', self.log.info('Requesting halfop from %s in %s %s.',
chanserv, channel, on) chanserv, channel, on)
irc.sendMsg(ircmsgs.privmsg(chanserv, 'halfop %s' % channel)) irc.sendMsg(ircmsgs.privmsg(chanserv, 'halfop %s' % channel))
if chanserv and self.registryValue('ChanServ.voice', channel): if chanserv and self.registryValue('ChanServ.voice', channel, irc.network):
if irc.nick not in irc.state.channels[channel].voices: if irc.nick not in irc.state.channels[channel].voices:
self.log.info('Requesting voice from %s in %s %s.', self.log.info('Requesting voice from %s in %s %s.',
chanserv, channel, on) chanserv, channel, on)

View File

@ -105,15 +105,17 @@ class ShrinkUrl(callbacks.PluginRegexp):
def _outFilterThread(self, irc, msg): def _outFilterThread(self, irc, msg):
(channel, text) = msg.args (channel, text) = msg.args
network = irc.network
for m in utils.web.httpUrlRe.finditer(text): for m in utils.web.httpUrlRe.finditer(text):
url = m.group(1) url = m.group(1)
if len(url) > self.registryValue('minimumLength', channel): if len(url) > self.registryValue('minimumLength', channel, network):
try: try:
cmd = self.registryValue('serviceRotation', cmd = self.registryValue('serviceRotation',
channel, value=False) channel, network, value=False)
cmd = cmd.getService().capitalize() cmd = cmd.getService().capitalize()
except ValueError: except ValueError:
cmd = self.registryValue('default', channel).capitalize() cmd = self.registryValue('default', channel, network) \
.capitalize()
try: try:
shortUrl = getattr(self, '_get%sUrl' % cmd)(url) shortUrl = getattr(self, '_get%sUrl' % cmd)(url)
text = text.replace(url, shortUrl) text = text.replace(url, shortUrl)
@ -126,39 +128,41 @@ class ShrinkUrl(callbacks.PluginRegexp):
def outFilter(self, irc, msg): def outFilter(self, irc, msg):
if msg.command != 'PRIVMSG': if msg.command != 'PRIVMSG':
return msg return msg
channel = msg.args[0] if msg.channel:
if irc.isChannel(channel):
if not msg.shrunken: if not msg.shrunken:
if self.registryValue('outFilter', channel): if self.registryValue('outFilter', msg.channel, irc.network):
if utils.web.httpUrlRe.search(msg.args[1]): if utils.web.httpUrlRe.search(msg.args[1]):
self._outFilterThread(irc, msg) self._outFilterThread(irc, msg)
return None return None
return msg return msg
def shrinkSnarfer(self, irc, msg, match): def shrinkSnarfer(self, irc, msg, match):
channel = msg.args[0] channel = msg.channel
if not irc.isChannel(channel): network = irc.network
if not channel:
return return
if self.registryValue('shrinkSnarfer', channel): if self.registryValue('shrinkSnarfer', channel, network):
url = match.group(0) url = match.group(0)
r = self.registryValue('nonSnarfingRegexp', channel) r = self.registryValue('nonSnarfingRegexp', channel, network)
if r and r.search(url) is not None: if r and r.search(url) is not None:
self.log.debug('Matched nonSnarfingRegexp: %u', url) self.log.debug('Matched nonSnarfingRegexp: %u', url)
return return
minlen = self.registryValue('minimumLength', channel) minlen = self.registryValue('minimumLength', channel, network)
try: try:
cmd = self.registryValue('serviceRotation', cmd = self.registryValue('serviceRotation',
channel, value=False) channel, network, value=False)
cmd = cmd.getService().capitalize() cmd = cmd.getService().capitalize()
except ValueError: except ValueError:
cmd = self.registryValue('default', channel).capitalize() cmd = self.registryValue('default', channel, network) \
.capitalize()
if len(url) >= minlen: if len(url) >= minlen:
try: try:
shorturl = getattr(self, '_get%sUrl' % cmd)(url) shorturl = getattr(self, '_get%sUrl' % cmd)(url)
except (utils.web.Error, AttributeError, ShrinkError): except (utils.web.Error, AttributeError, ShrinkError):
self.log.info('Couldn\'t get shorturl for %u', url) self.log.info('Couldn\'t get shorturl for %u', url)
return return
if self.registryValue('shrinkSnarfer.showDomain', channel): if self.registryValue('shrinkSnarfer.showDomain',
channel, network):
domain = ' (at %s)' % utils.web.getDomain(url) domain = ' (at %s)' % utils.web.getDomain(url)
else: else:
domain = '' domain = ''

View File

@ -140,9 +140,9 @@ class Status(callbacks.Plugin):
""" """
(user, system, childUser, childSystem, elapsed) = os.times() (user, system, childUser, childSystem, elapsed) = os.times()
now = time.time() now = time.time()
target = msg.args[0] target = (msg.channel, irc.network)
timeRunning = now - world.startedAt timeRunning = now - world.startedAt
if self.registryValue('cpu.children', target) and \ if self.registryValue('cpu.children', *target) and \
user+system < timeRunning+1: # Fudge for FPU inaccuracies. user+system < timeRunning+1: # Fudge for FPU inaccuracies.
children = _('My children have taken %.2f seconds of user time ' children = _('My children have taken %.2f seconds of user time '
'and %.2f seconds of system time ' 'and %.2f seconds of system time '
@ -154,11 +154,11 @@ class Status(callbacks.Plugin):
response = _('I have taken %.2f seconds of user time and %.2f seconds ' response = _('I have taken %.2f seconds of user time and %.2f seconds '
'of system time, for a total of %.2f seconds of CPU ' 'of system time, for a total of %.2f seconds of CPU '
'time. %s') % (user, system, user + system, children) 'time. %s') % (user, system, user + system, children)
if self.registryValue('cpu.threads', target): if self.registryValue('cpu.threads', *target):
response += format('I have spawned %n; I currently have %i still ' response += format('I have spawned %n; I currently have %i still '
'running.', 'running.',
(world.threadsSpawned, 'thread'), activeThreads) (world.threadsSpawned, 'thread'), activeThreads)
if self.registryValue('cpu.memory', target): if self.registryValue('cpu.memory', *target):
mem = None mem = None
pid = os.getpid() pid = os.getpid()
plat = sys.platform plat = sys.platform

View File

@ -50,7 +50,8 @@ class Success(plugins.ChannelIdDatabasePlugin):
class MySuccessClass(self.originalClass): class MySuccessClass(self.originalClass):
__slots__ = () __slots__ = ()
def __call__(self): def __call__(self):
ret = pluginSelf.db.random(dynamic.msg.args[0]) msg = dynamic.msg
ret = pluginSelf.db.random(msg.channel or msg.args[0])
if ret is None: if ret is None:
try: try:
self.__class__ = pluginSelf.originalClass self.__class__ = pluginSelf.originalClass

View File

@ -175,7 +175,8 @@ class Time(callbacks.Plugin):
<channel> is given without <format>, uses the format for <channel>. <channel> is given without <format>, uses the format for <channel>.
""" """
if not format: if not format:
format = self.registryValue('format', channel or msg.args[0]) format = self.registryValue('format', channel or msg.channel,
irc.network)
if tzlocal: if tzlocal:
irc.reply(datetime.fromtimestamp(seconds, tzlocal()).strftime(format)) irc.reply(datetime.fromtimestamp(seconds, tzlocal()).strftime(format))
else: else:
@ -209,7 +210,7 @@ class Time(callbacks.Plugin):
timezone = pytz.timezone(timezone) timezone = pytz.timezone(timezone)
except pytz.UnknownTimeZoneError: except pytz.UnknownTimeZoneError:
irc.error(_('Unknown timezone'), Raise=True) irc.error(_('Unknown timezone'), Raise=True)
format = self.registryValue("format", msg.args[0]) format = self.registryValue("format", msg.channel, irc.network)
irc.reply(datetime.now(timezone).strftime(format)) irc.reply(datetime.now(timezone).strftime(format))
tztime = wrap(tztime, ['text']) tztime = wrap(tztime, ['text'])

View File

@ -64,16 +64,17 @@ def canChangeTopic(irc, msg, args, state):
def getTopic(irc, msg, args, state, format=True): def getTopic(irc, msg, args, state, format=True):
separator = state.cb.registryValue('separator', state.channel) separator = state.cb.registryValue('separator', state.channel, irc.network)
if separator in args[0] and not \ if separator in args[0] and not \
state.cb.registryValue('allowSeparatorinTopics', state.channel): state.cb.registryValue('allowSeparatorinTopics',
state.channel, irc.network):
state.errorInvalid('topic', args[0], state.errorInvalid('topic', args[0],
format(_('The topic must not include %q.'), format(_('The topic must not include %q.'),
separator)) separator))
topic = args.pop(0) topic = args.pop(0)
if format: if format:
env = {'topic': topic} env = {'topic': topic}
formatter = state.cb.registryValue('format', state.channel) formatter = state.cb.registryValue('format', state.channel, irc.network)
topic = ircutils.standardSubstitute(irc, msg, formatter, env) topic = ircutils.standardSubstitute(irc, msg, formatter, env)
state.args.append(topic) state.args.append(topic)
@ -90,7 +91,7 @@ def getTopicNumber(irc, msg, args, state):
if n > 0: if n > 0:
n -= 1 n -= 1
topic = irc.state.getTopic(state.channel) topic = irc.state.getTopic(state.channel)
separator = state.cb.registryValue('separator', state.channel) separator = state.cb.registryValue('separator', state.channel, irc.network)
topics = splitTopic(topic, separator) topics = splitTopic(topic, separator)
if not topics: if not topics:
state.error(format(_('There are no topics in %s.'), state.channel), state.error(format(_('There are no topics in %s.'), state.channel),
@ -162,24 +163,25 @@ class Topic(callbacks.Plugin):
except (IOError, shutil.Error) as e: except (IOError, shutil.Error) as e:
self.log.warning('File error: %s', e) self.log.warning('File error: %s', e)
def _splitTopic(self, topic, channel): def _splitTopic(self, irc, channel):
separator = self.registryValue('separator', channel) topic = irc.state.getTopic(channel)
separator = self.registryValue('separator', channel, irc.network)
return splitTopic(topic, separator) return splitTopic(topic, separator)
def _joinTopic(self, channel, topics): def _joinTopic(self, irc, channel, topics):
separator = self.registryValue('separator', channel) separator = self.registryValue('separator', channel, irc.network)
return separator.join(topics) return separator.join(topics)
def _addUndo(self, channel, topics): def _addUndo(self, irc, channel, topics):
stack = self.undos.setdefault(channel, []) stack = self.undos.setdefault(channel, [])
stack.append(topics) stack.append(topics)
maxLen = self.registryValue('undo.max', channel) maxLen = self.registryValue('undo.max', channel, irc.network)
del stack[:len(stack) - maxLen] del stack[:len(stack) - maxLen]
def _addRedo(self, channel, topics): def _addRedo(self, irc, channel, topics):
stack = self.redos.setdefault(channel, []) stack = self.redos.setdefault(channel, [])
stack.append(topics) stack.append(topics)
maxLen = self.registryValue('undo.max', channel) maxLen = self.registryValue('undo.max', channel, irc.network)
del stack[:len(stack) - maxLen] del stack[:len(stack) - maxLen]
def _getUndo(self, channel): def _getUndo(self, channel):
@ -197,16 +199,16 @@ class Topic(callbacks.Plugin):
def _formatTopics(self, irc, channel, topics, fit=False): def _formatTopics(self, irc, channel, topics, fit=False):
topics = [s for s in topics if s and not s.isspace()] topics = [s for s in topics if s and not s.isspace()]
self.lastTopics[channel] = topics self.lastTopics[channel] = topics
newTopic = self._joinTopic(channel, topics) newTopic = self._joinTopic(irc, channel, topics)
try: try:
maxLen = irc.state.supported['topiclen'] maxLen = irc.state.supported['topiclen']
if fit: if fit:
while len(newTopic) > maxLen: while len(newTopic) > maxLen:
topics.pop(0) topics.pop(0)
self.lastTopics[channel] = topics self.lastTopics[channel] = topics
newTopic = self._joinTopic(channel, topics) newTopic = self._joinTopic(irc, channel, topics)
elif len(newTopic) > maxLen: elif len(newTopic) > maxLen:
if self.registryValue('recognizeTopiclen', channel): if self.registryValue('recognizeTopiclen', channel, irc.network):
irc.error(format(_('That topic is too long for this ' irc.error(format(_('That topic is too long for this '
'server (maximum length: %i; this topic: ' 'server (maximum length: %i; this topic: '
'%i).'), maxLen, len(newTopic)), '%i).'), maxLen, len(newTopic)),
@ -219,7 +221,7 @@ class Topic(callbacks.Plugin):
if isinstance(topics, list) or isinstance(topics, tuple): if isinstance(topics, list) or isinstance(topics, tuple):
assert topics is not None assert topics is not None
topics = self._formatTopics(irc, channel, topics, fit) topics = self._formatTopics(irc, channel, topics, fit)
self._addUndo(channel, topics) self._addUndo(irc, channel, topics)
if not isDo and channel in self.redos: if not isDo and channel in self.redos:
del self.redos[channel] del self.redos[channel]
irc.queueMsg(ircmsgs.topic(channel, topics)) irc.queueMsg(ircmsgs.topic(channel, topics))
@ -238,7 +240,8 @@ class Topic(callbacks.Plugin):
c = irc.state.channels[channel] c = irc.state.channels[channel]
if msg.nick in c.ops or msg.nick in c.halfops or 't' not in c.modes: if msg.nick in c.ops or msg.nick in c.halfops or 't' not in c.modes:
return True return True
capabilities = self.registryValue('requireManageCapability', channel) capabilities = self.registryValue('requireManageCapability',
channel, irc.network)
if capabilities: if capabilities:
for capability in re.split(r'\s*;\s*', capabilities): for capability in re.split(r'\s*;\s*', capabilities):
if capability.startswith('channel,'): if capability.startswith('channel,'):
@ -247,7 +250,7 @@ class Topic(callbacks.Plugin):
if capability and ircdb.checkCapability(msg.prefix, capability): if capability and ircdb.checkCapability(msg.prefix, capability):
return return
capabilities = self.registryValue('requireManageCapability', capabilities = self.registryValue('requireManageCapability',
channel) channel, irc.network)
irc.errorNoCapability(capabilities, Raise=True) irc.errorNoCapability(capabilities, Raise=True)
else: else:
return return
@ -261,7 +264,7 @@ class Topic(callbacks.Plugin):
# Try to restore the topic when not set yet. # Try to restore the topic when not set yet.
channel = msg.args[1] channel = msg.args[1]
c = irc.state.channels.get(channel) c = irc.state.channels.get(channel)
if c is None or not self.registryValue('setOnJoin', channel): if c is None or not self.registryValue('setOnJoin', channel, irc.network):
return return
if irc.nick not in c.ops and 't' in c.modes: if irc.nick not in c.ops and 't' in c.modes:
self.log.debug('Not trying to restore topic in %s. I\'m not opped ' self.log.debug('Not trying to restore topic in %s. I\'m not opped '
@ -274,7 +277,8 @@ class Topic(callbacks.Plugin):
else: else:
newTopic = self._formatTopics(irc, channel, topics) newTopic = self._formatTopics(irc, channel, topics)
if c.topic == '' or (c.topic != newTopic and if c.topic == '' or (c.topic != newTopic and
self.registryValue('alwaysSetOnJoin', channel)): self.registryValue('alwaysSetOnJoin',
channel, irc.network)):
self._sendTopics(irc, channel, newTopic) self._sendTopics(irc, channel, newTopic)
def do332(self, irc, msg): def do332(self, irc, msg):
@ -282,7 +286,7 @@ class Topic(callbacks.Plugin):
self.watchingFor332.remove(msg.args[1]) self.watchingFor332.remove(msg.args[1])
# Store an undo for the topic when we join a channel. This allows # Store an undo for the topic when we join a channel. This allows
# us to undo the first topic change that takes place in a channel. # us to undo the first topic change that takes place in a channel.
self._addUndo(msg.args[1], [msg.args[2]]) self._addUndo(irc, msg.args[1], [msg.args[2]])
def topic(self, irc, msg, args, channel): def topic(self, irc, msg, args, channel):
"""[<channel>] """[<channel>]
@ -301,7 +305,7 @@ class Topic(callbacks.Plugin):
if the message isn't sent in the channel itself. if the message isn't sent in the channel itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
topics.append(topic) topics.append(topic)
self._sendTopics(irc, channel, topics) self._sendTopics(irc, channel, topics)
add = wrap(add, ['canChangeTopic', rest('topic')]) add = wrap(add, ['canChangeTopic', rest('topic')])
@ -315,7 +319,7 @@ class Topic(callbacks.Plugin):
itself. itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
topics.append(topic) topics.append(topic)
self._sendTopics(irc, channel, topics, fit=True) self._sendTopics(irc, channel, topics, fit=True)
fit = wrap(fit, ['canChangeTopic', rest('topic')]) fit = wrap(fit, ['canChangeTopic', rest('topic')])
@ -326,7 +330,7 @@ class Topic(callbacks.Plugin):
Replaces topic <number> with <topic>. Replaces topic <number> with <topic>.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
topics[i] = topic topics[i] = topic
self._sendTopics(irc, channel, topics) self._sendTopics(irc, channel, topics)
replace = wrap(replace, ['canChangeTopic', 'topicNumber', rest('topic')]) replace = wrap(replace, ['canChangeTopic', 'topicNumber', rest('topic')])
@ -339,7 +343,7 @@ class Topic(callbacks.Plugin):
isn't sent in the channel itself. isn't sent in the channel itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
topics.insert(0, topic) topics.insert(0, topic)
self._sendTopics(irc, channel, topics) self._sendTopics(irc, channel, topics)
insert = wrap(insert, ['canChangeTopic', rest('topic')]) insert = wrap(insert, ['canChangeTopic', rest('topic')])
@ -351,7 +355,7 @@ class Topic(callbacks.Plugin):
message isn't sent in the channel itself. message isn't sent in the channel itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
if len(topics) == 0 or len(topics) == 1: if len(topics) == 0 or len(topics) == 1:
irc.error(_('I can\'t shuffle 1 or fewer topics.'), Raise=True) irc.error(_('I can\'t shuffle 1 or fewer topics.'), Raise=True)
elif len(topics) == 2: elif len(topics) == 2:
@ -372,7 +376,7 @@ class Topic(callbacks.Plugin):
itself. itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
num = len(topics) num = len(topics)
if num == 0 or num == 1: if num == 0 or num == 1:
irc.error(_('I cannot reorder 1 or fewer topics.'), Raise=True) irc.error(_('I cannot reorder 1 or fewer topics.'), Raise=True)
@ -392,7 +396,7 @@ class Topic(callbacks.Plugin):
Mostly useful for topic reordering. <channel> is only necessary if the Mostly useful for topic reordering. <channel> is only necessary if the
message isn't sent in the channel itself. message isn't sent in the channel itself.
""" """
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
L = [] L = []
for (i, t) in enumerate(topics): for (i, t) in enumerate(topics):
L.append(format(_('%i: %s'), i + 1, utils.str.ellipsisify(t, 30))) L.append(format(_('%i: %s'), i + 1, utils.str.ellipsisify(t, 30)))
@ -407,7 +411,7 @@ class Topic(callbacks.Plugin):
index into the topics. <channel> is only necessary if the message index into the topics. <channel> is only necessary if the message
isn't sent in the channel itself. isn't sent in the channel itself.
""" """
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
irc.reply(topics[number]) irc.reply(topics[number])
get = wrap(get, ['inChannel', 'topicNumber']) get = wrap(get, ['inChannel', 'topicNumber'])
@ -421,7 +425,7 @@ class Topic(callbacks.Plugin):
isn't sent in the channel itself. isn't sent in the channel itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
topics[number] = replacer(topics[number]) topics[number] = replacer(topics[number])
self._sendTopics(irc, channel, topics) self._sendTopics(irc, channel, topics)
change = wrap(change, ['canChangeTopic', 'topicNumber', 'regexpReplacer']) change = wrap(change, ['canChangeTopic', 'topicNumber', 'regexpReplacer'])
@ -435,7 +439,7 @@ class Topic(callbacks.Plugin):
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
if number is not None: if number is not None:
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
topics[number] = topic topics[number] = topic
else: else:
topics = [topic] topics = [topic]
@ -453,7 +457,7 @@ class Topic(callbacks.Plugin):
necessary if the message isn't sent in the channel itself. necessary if the message isn't sent in the channel itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
numbers = set(numbers) numbers = set(numbers)
for n in numbers: for n in numbers:
# Equivalent of marking the topic for deletion; there's no # Equivalent of marking the topic for deletion; there's no
@ -534,7 +538,7 @@ class Topic(callbacks.Plugin):
channel itself. channel itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
self._addRedo(channel, self._getUndo(channel)) # current topic. self._addRedo(irc, channel, self._getUndo(channel)) # current topic.
topics = self._getUndo(channel) # This is the topic list we want. topics = self._getUndo(channel) # This is the topic list we want.
if topics is not None: if topics is not None:
self._sendTopics(irc, channel, topics, isDo=True) self._sendTopics(irc, channel, topics, isDo=True)
@ -564,7 +568,7 @@ class Topic(callbacks.Plugin):
itself. itself.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
if first == second: if first == second:
irc.error(_('I refuse to swap the same topic with itself.')) irc.error(_('I refuse to swap the same topic with itself.'))
return return
@ -598,7 +602,7 @@ class Topic(callbacks.Plugin):
variable supybot.plugins.Topic.default. variable supybot.plugins.Topic.default.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topic = self.registryValue('default', channel) topic = self.registryValue('default', channel, irc.network)
if topic: if topic:
self._sendTopics(irc, channel, [topic]) self._sendTopics(irc, channel, [topic])
else: else:
@ -613,7 +617,7 @@ class Topic(callbacks.Plugin):
current topic appropriately. current topic appropriately.
""" """
self._checkManageCapabilities(irc, msg, channel) self._checkManageCapabilities(irc, msg, channel)
topics = self._splitTopic(irc.state.getTopic(channel), channel) topics = self._splitTopic(irc, channel)
self.setRegistryValue('separator', separator, channel) self.setRegistryValue('separator', separator, channel)
self._sendTopics(irc, channel, topics) self._sendTopics(irc, channel, topics)
separator = wrap(separator, ['canChangeTopic', 'something']) separator = wrap(separator, ['canChangeTopic', 'something'])

View File

@ -73,19 +73,19 @@ class URL(callbacks.Plugin):
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg): if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg):
return return
channel = msg.args[0] if msg.channel:
if irc.isChannel(channel):
if ircmsgs.isAction(msg): if ircmsgs.isAction(msg):
text = ircmsgs.unAction(msg) text = ircmsgs.unAction(msg)
else: else:
text = msg.args[1] text = msg.args[1]
for url in utils.web.urlRe.findall(text): for url in utils.web.urlRe.findall(text):
r = self.registryValue('nonSnarfingRegexp', channel) r = self.registryValue('nonSnarfingRegexp',
msg.channel, irc.network)
if r and r.search(url): if r and r.search(url):
self.log.debug('Skipping adding %u to db.', url) self.log.debug('Skipping adding %u to db.', url)
continue continue
self.log.debug('Adding %u to db.', url) self.log.debug('Adding %u to db.', url)
self.db.add(channel, url, msg) self.db.add(msg.channel, url, msg)
@internationalizeDocstring @internationalizeDocstring
def stats(self, irc, msg, args, channel): def stats(self, irc, msg, args, channel):

View File

@ -207,17 +207,18 @@ class Unix(callbacks.Plugin):
Returns a fortune from the *nix fortune program. Returns a fortune from the *nix fortune program.
""" """
channel = msg.args[0] channel = msg.channel
network = irc.network
fortuneCmd = self.registryValue('fortune.command') fortuneCmd = self.registryValue('fortune.command')
if fortuneCmd: if fortuneCmd:
args = [fortuneCmd] args = [fortuneCmd]
if self.registryValue('fortune.short', channel): if self.registryValue('fortune.short', channel, network):
args.append('-s') args.append('-s')
if self.registryValue('fortune.equal', channel): if self.registryValue('fortune.equal', channel, network):
args.append('-e') args.append('-e')
if self.registryValue('fortune.offensive', channel): if self.registryValue('fortune.offensive', channel, network):
args.append('-a') args.append('-a')
args.extend(self.registryValue('fortune.files', channel)) args.extend(self.registryValue('fortune.files', channel, network))
try: try:
with open(os.devnull) as null: with open(os.devnull) as null:
inst = subprocess.Popen(args, inst = subprocess.Popen(args,

View File

@ -46,7 +46,7 @@ class User(callbacks.Plugin):
authentication to the bot. This is a core Supybot plugin that should authentication to the bot. This is a core Supybot plugin that should
not be removed!""" not be removed!"""
def _checkNotChannel(self, irc, msg, password=' '): def _checkNotChannel(self, irc, msg, password=' '):
if password and irc.isChannel(msg.args[0]): if password and msg.channel:
raise callbacks.Error(conf.supybot.replies.requiresPrivacy()) raise callbacks.Error(conf.supybot.replies.requiresPrivacy())
@internationalizeDocstring @internationalizeDocstring
@ -88,7 +88,8 @@ class User(callbacks.Plugin):
users.append(u.name) users.append(u.name)
if users: if users:
utils.sortBy(str.lower, users) utils.sortBy(str.lower, users)
private = self.registryValue("listInPrivate", msg.args[0]) private = self.registryValue("listInPrivate",
msg.channel, irc.network)
irc.reply(format('%L', users), private=private) irc.reply(format('%L', users), private=private)
else: else:
if predicates: if predicates:

View File

@ -144,7 +144,7 @@ class Web(callbacks.PluginRegexp):
threaded = True threaded = True
def noIgnore(self, irc, msg): def noIgnore(self, irc, msg):
return not self.registryValue('checkIgnored', msg.args[0]) return not self.registryValue('checkIgnored', msg.channel, irc.network)
def getTitle(self, irc, url, raiseErrors): def getTitle(self, irc, url, raiseErrors):
size = conf.supybot.protocols.http.peekSize() size = conf.supybot.protocols.http.peekSize()
@ -184,16 +184,17 @@ class Web(callbacks.PluginRegexp):
@fetch_sandbox @fetch_sandbox
def titleSnarfer(self, irc, msg, match): def titleSnarfer(self, irc, msg, match):
channel = msg.args[0] channel = msg.channel
if not irc.isChannel(channel): network = irc.network
if not channel:
return return
if callbacks.addressed(irc.nick, msg): if callbacks.addressed(irc.nick, msg):
return return
if self.registryValue('titleSnarfer', channel): if self.registryValue('titleSnarfer', channel, network):
url = match.group(0) url = match.group(0)
if not self._checkURLWhitelist(url): if not self._checkURLWhitelist(url):
return return
r = self.registryValue('nonSnarfingRegexp', channel) r = self.registryValue('nonSnarfingRegexp', channel, network)
if r and r.search(url): if r and r.search(url):
self.log.debug('Not titleSnarfing %q.', url) self.log.debug('Not titleSnarfing %q.', url)
return return
@ -203,14 +204,15 @@ class Web(callbacks.PluginRegexp):
(target, title) = r (target, title) = r
if title: if title:
domain = utils.web.getDomain(target domain = utils.web.getDomain(target
if self.registryValue('snarferShowTargetDomain', channel) if self.registryValue('snarferShowTargetDomain',
channel, network)
else url) else url)
prefix = self.registryValue('snarferPrefix', channel) prefix = self.registryValue('snarferPrefix', channel, network)
s = "%s %s" % (prefix, title) s = "%s %s" % (prefix, title)
if self.registryValue('snarferShowDomain', channel): if self.registryValue('snarferShowDomain', channel, network):
s += format(_(' (at %s)'), domain) s += format(_(' (at %s)'), domain)
irc.reply(s, prefixNick=False) irc.reply(s, prefixNick=False)
if self.registryValue('snarfMultipleUrls', channel): if self.registryValue('snarfMultipleUrls', channel, network):
# FIXME: hack # FIXME: hack
msg.tag('repliedTo', False) msg.tag('repliedTo', False)
titleSnarfer = urlSnarfer(titleSnarfer) titleSnarfer = urlSnarfer(titleSnarfer)

View File

@ -170,11 +170,11 @@ def _makeReply(irc, msg, s,
# XXX This isn't entirely right. Consider to=#foo, private=True. # XXX This isn't entirely right. Consider to=#foo, private=True.
target = ircutils.replyTo(msg) target = ircutils.replyTo(msg)
def isPublic(s): def isPublic(s):
return irc.isChannel(irc._stripChannelPrefix(s)) return irc.isChannel(irc.stripChannelPrefix(s))
if to is not None and isPublic(to): if to is not None and isPublic(to):
target = to target = to
if isPublic(target): if isPublic(target):
channel = irc._stripChannelPrefix(target) channel = irc.stripChannelPrefix(target)
else: else:
channel = None channel = None
if notice is None: if notice is None:
@ -376,16 +376,16 @@ class Tokenizer(object):
args[-1].append(ends.pop()) args[-1].append(ends.pop())
return args return args
def tokenize(s, channel=None): def tokenize(s, channel=None, network=None):
"""A utility function to create a Tokenizer and tokenize a string.""" """A utility function to create a Tokenizer and tokenize a string."""
pipe = False pipe = False
brackets = '' brackets = ''
nested = conf.supybot.commands.nested nested = conf.supybot.commands.nested
if nested(): if nested():
brackets = conf.get(nested.brackets, channel) brackets = nested.brackets.getSpecific(network, channel)()
if conf.get(nested.pipeSyntax, channel): # No nesting, no pipe. if conf.get(nested.pipeSyntax, channel): # No nesting, no pipe.
pipe = True pipe = True
quotes = conf.get(conf.supybot.commands.quotes, channel) quotes = conf.supybot.commands.quotes.getSpecific(network, channel)()
try: try:
ret = Tokenizer(brackets=brackets,pipe=pipe,quotes=quotes).tokenize(s) ret = Tokenizer(brackets=brackets,pipe=pipe,quotes=quotes).tokenize(s)
return ret return ret
@ -1414,8 +1414,9 @@ class PluginMixin(BasePlugin, irclib.IrcCallback):
names = registry.split(name) names = registry.split(name)
for name in names: for name in names:
group = group.get(name) group = group.get(name)
if value: if channel or network:
group = group.getSpecific(network=network, channel=channel) group = group.getSpecific(network=network, channel=channel)
if value:
return group() return group()
else: else:
return group return group

View File

@ -1135,7 +1135,7 @@ class Banmask(registry.SpaceSeparatedSetOfStrings):
self.error() self.error()
self.__parent.setValue(self.List(v)) self.__parent.setValue(self.List(v))
def makeBanmask(self, hostmask, options=None, channel=None): def makeBanmask(self, hostmask, options=None, channel=None, network=None):
"""Create a banmask from the given hostmask. If a style of banmask """Create a banmask from the given hostmask. If a style of banmask
isn't specified via options, the value of isn't specified via options, the value of
conf.supybot.protocols.irc.banmask is used. conf.supybot.protocols.irc.banmask is used.
@ -1145,13 +1145,15 @@ class Banmask(registry.SpaceSeparatedSetOfStrings):
only the exact hostmask will be used.""" only the exact hostmask will be used."""
if not channel: if not channel:
channel = dynamic.channel channel = dynamic.channel
assert channel is None or ircutils.isChannel(channel) if not network:
network = dynamic.irc.network
(nick, user, host) = ircutils.splitHostmask(hostmask) (nick, user, host) = ircutils.splitHostmask(hostmask)
bnick = '*' bnick = '*'
buser = '*' buser = '*'
bhost = '*' bhost = '*'
if not options: if not options:
options = get(supybot.protocols.irc.banmask, channel) options = supybot.protocols.irc.banmask.getSpecific(
channel, network)()
for option in options: for option in options:
if option == 'nick': if option == 'nick':
bnick = nick bnick = nick

View File

@ -843,6 +843,7 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
self.queueMsg(ircmsgs.ping(now)) self.queueMsg(ircmsgs.ping(now))
if msg: if msg:
for callback in reversed(self.callbacks): for callback in reversed(self.callbacks):
self._setMsgChannel(msg)
msg = callback.outFilter(self, msg) msg = callback.outFilter(self, msg)
if msg is None: if msg is None:
log.debug('%s.outFilter returned None.', callback.name()) log.debug('%s.outFilter returned None.', callback.name())
@ -882,18 +883,20 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
msg.tag('receivedOn', self.network) msg.tag('receivedOn', self.network)
msg.tag('receivedAt', time.time()) msg.tag('receivedAt', time.time())
# Check if the message is sent to a channel self._setMsgChannel(msg)
def _setMsgChannel(self, msg):
if msg.args: if msg.args:
msg.channel = msg.args[0] msg.channel = msg.args[0]
if msg.command in ('NOTICE', 'PRIVMSG') and \ if msg.command in ('NOTICE', 'PRIVMSG') and \
not conf.supybot.protocols.irc.strictRfc(): not conf.supybot.protocols.irc.strictRfc():
msg.channel = self._stripChannelPrefix(msg.channel) msg.channel = self.stripChannelPrefix(msg.channel)
if not self.isChannel(msg.channel): if not self.isChannel(msg.channel):
msg.channel = None msg.channel = None
else: else:
msg.channel = None msg.channel = None
def _stripChannelPrefix(self, channel): def stripChannelPrefix(self, channel):
statusmsg_chars = self.state.supported.get('statusmsg', '') statusmsg_chars = self.state.supported.get('statusmsg', '')
return channel.lstrip(statusmsg_chars) return channel.lstrip(statusmsg_chars)