def doMode(self, irc, msg): channel = msg.args[0] chanOp = ircdb.makeChannelCapability(channel, 'op') chanVoice = ircdb.makeChannelCapability(channel, 'voice') chanHalfOp = ircdb.makeChannelCapability(channel, 'halfop') if not ircdb.checkCapability(msg.prefix, chanOp): irc.sendMsg(ircmsgs.deop(channel, msg.nick)) for (mode, value) in ircutils.separateModes(msg.args[1:]): if not value: continue if ircutils.strEqual(value, msg.nick): # We allow someone to mode themselves to oblivion. continue if irc.isNick(value): hostmask = irc.state.nickToHostmask(value) if mode == '+o': if not self.isOp(irc, channel, hostmask): irc.queueMsg(ircmsgs.deop(channel, value)) elif mode == '+h': if not ircdb.checkCapability(hostmask, chanHalfOp): irc.queueMsg(ircmsgs.dehalfop(channel, value)) elif mode == '+v': if not ircdb.checkCapability(hostmask, chanVoice): irc.queueMsg(ircmsgs.devoice(channel, value)) elif mode == '-o': if ircdb.checkCapability(hostmask, chanOp): irc.queueMsg(ircmsgs.op(channel, value)) elif mode == '-h': if ircdb.checkCapability(hostmask, chanOp): irc.queueMsg(ircmsgs.halfop(channel, value)) elif mode == '-v': if ircdb.checkCapability(hostmask, chanOp): irc.queueMsg(ircmsgs.voice(channel, value)) else: assert ircutils.isUserHostmask(value)
def addHostmask(self, hostmask): """Adds a hostmask to the user's hostmasks.""" assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask if len(unWildcardHostmask(hostmask)) < 8: raise ValueError, \ 'Hostmask must contain at least 8 non-wildcard characters.' self.hostmasks.add(hostmask)
def add(self, irc, msg, args, user, hostmask, password): """[<name>] [<hostmask>] [<password>] Adds the hostmask <hostmask> to the user specified by <name>. The <password> may only be required if the user is not recognized by hostmask. <password> is also not required if an owner user is giving the command on behalf of some other user. If <hostmask> is not given, it defaults to your current hostmask. If <name> is not given, it defaults to your currently identified name. This message must be sent to the bot privately (not on a channel) since it may contain a password. """ caller_is_owner = ircdb.checkCapability(msg.prefix, 'owner') if not hostmask: hostmask = msg.prefix if not ircutils.isUserHostmask(hostmask): irc.errorInvalid(_('hostmask'), hostmask, _('Make sure your hostmask includes a nick, ' 'then an exclamation point (!), then a user, ' 'then an at symbol (@), then a host. Feel ' 'free to use wildcards (* and ?, which work ' 'just like they do on the command line) in ' 'any of these parts.'), Raise=True) try: otherId = ircdb.users.getUserId(hostmask) if otherId != user.id: if caller_is_owner: err = _('That hostmask is already registered to %s.') err %= otherId else: err = _('That hostmask is already registered.') irc.error(err, Raise=True) except KeyError: pass if not user.checkPassword(password) and \ not user.checkHostmask(msg.prefix) and \ not caller_is_owner: irc.error(conf.supybot.replies.incorrectAuthentication(), Raise=True) try: user.addHostmask(hostmask) except ValueError as e: irc.error(str(e), Raise=True) try: ircdb.users.setUser(user) except ircdb.DuplicateHostmask as e: user.removeHostmask(hostmask) if caller_is_owner: err = _('That hostmask is already registered to %s.') \ % e.args[0] else: err = _('That hostmask is already registered.') irc.error(err, Raise=True) except ValueError as e: irc.error(str(e), Raise=True) irc.replySuccess()
def getHostmask(irc, msg, args, state): if ircutils.isUserHostmask(args[0]): state.args.append(args.pop(0)) else: try: hostmask = irc.state.nickToHostmask(args[0]) state.args.append(hostmask) del args[0] except KeyError: state.errorInvalid(_('nick or hostmask'), args[0])
def _getId(self, irc, userNickHostmask): try: id = ircdb.users.getUserId(userNickHostmask) except KeyError: if not ircutils.isUserHostmask(userNickHostmask): hostmask = irc.state.nickToHostmask(userNickHostmask) id = ircdb.users.getUserId(hostmask) else: raise KeyError return id
def getHostmask(irc, msg, args, state): if ircutils.isUserHostmask(args[0]) or (not conf.supybot.protocols.irc.strictRfc() and args[0].startswith("$")): state.args.append(args.pop(0)) else: try: hostmask = irc.state.nickToHostmask(args[0]) state.args.append(hostmask) del args[0] except KeyError: state.errorInvalid(_("nick or hostmask"), args[0])
def testHostmaskPatternEqual(self): for msg in msgs: if msg.prefix and ircutils.isUserHostmask(msg.prefix): s = msg.prefix self.failUnless(ircutils.hostmaskPatternEqual(s, s), "%r did not match itself." % s) banmask = ircutils.banmask(s) self.failUnless(ircutils.hostmaskPatternEqual(banmask, s), "%r did not match %r" % (s, banmask)) s = "[email protected]" self.failUnless(ircutils.hostmaskPatternEqual(s, s)) s = "jamessan|[email protected]." "abr-ubr1.sbo-abr.ma.cable.rcn.com" self.failUnless(ircutils.hostmaskPatternEqual(s, s))
def testBanmask(self): for msg in msgs: if ircutils.isUserHostmask(msg.prefix): banmask = ircutils.banmask(msg.prefix) self.failUnless( ircutils.hostmaskPatternEqual(banmask, msg.prefix), "%r didn't match %r" % (msg.prefix, banmask) ) self.assertEqual(ircutils.banmask("foobar!user@host"), "*!*@host") self.assertEqual(ircutils.banmask("[email protected]"), "*!*@host.tld") self.assertEqual(ircutils.banmask("[email protected]"), "*!*@*.host.tld") self.assertEqual(ircutils.banmask("foo!bar@2001::"), "*!*@2001::*")
def isImmune(self, irc, msg): if not ircutils.isUserHostmask(msg.prefix): self.log.debug('%q is immune, it\'s a server.', msg) return True # It's a server prefix. if ircutils.strEqual(msg.nick, irc.nick): self.log.debug('%q is immune, it\'s me.', msg) return True # It's the bot itself. if msg.nick in self.registryValue('immune', msg.args[0]): self.log.debug('%q is immune, it\'s configured to be immune.', msg) return True return False
def checkBan(self, hostmask): """Checks whether a given hostmask is banned by the channel banlist.""" assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask now = time.time() for (pattern, expiration) in self.bans.items(): if now < expiration or not expiration: if ircutils.hostmaskPatternEqual(pattern, hostmask): return True else: self.expiredBans.append((pattern, expiration)) del self.bans[pattern] return False
def doAccount (self,irc,msg): if ircutils.isUserHostmask(msg.prefix): nick = ircutils.nickFromHostmask(msg.prefix) for channel in irc.state.channels: chan = self.getChan(irc,channel) if nick in chan.nicks: a = chan.nicks[nick] account = msg.args[0] if account == '*': account = '' a[1] = account chan.nicks[nick] = a
def proxyuser (self,irc,msg,args,nick): """<nick|ip> check<nick|ip> against configured DNSBLS""" if ircutils.isUserHostmask(nick) h = irc.state.nickToHostmask(nick) (n,i,h) = ircutils.splitHostmask(h) else: h = nick check = self.check(h,'') if check and len(check): irc.reply(', '.join(check)) else: irc.reply('%s is clean' % nick)
def testBanmask(self): for msg in msgs: if ircutils.isUserHostmask(msg.prefix): banmask = ircutils.banmask(msg.prefix) self.failUnless(ircutils.hostmaskPatternEqual(banmask, msg.prefix), '%r didn\'t match %r' % (msg.prefix, banmask)) self.assertEqual(ircutils.banmask('foobar!user@host'), '*!*@host') self.assertEqual(ircutils.banmask('[email protected]'), '*!*@host.tld') self.assertEqual(ircutils.banmask('[email protected]'), '*!*@*.host.tld') self.assertEqual(ircutils.banmask('foo!bar@2001::'), '*!*@2001::*')
def getOtherUser(irc, msg, args, state): if ircutils.isUserHostmask(args[0]): state.errorNoUser(args[0]) try: state.args.append(ircdb.users.getUser(args[0])) del args[0] except KeyError: try: getHostmask(irc, msg, [args[0]], state) hostmask = state.args.pop() state.args.append(ircdb.users.getUser(hostmask)) del args[0] except (KeyError, callbacks.Error): state.errorNoUser(name=args[0])
def testHostmaskPatternEqual(self): for msg in msgs: if msg.prefix and ircutils.isUserHostmask(msg.prefix): s = msg.prefix self.failUnless(ircutils.hostmaskPatternEqual(s, s), '%r did not match itself.' % s) banmask = ircutils.banmask(s) self.failUnless(ircutils.hostmaskPatternEqual(banmask, s), '%r did not match %r' % (s, banmask)) s = '[email protected]' self.failUnless(ircutils.hostmaskPatternEqual(s, s)) s = 'jamessan|[email protected].' \ 'abr-ubr1.sbo-abr.ma.cable.rcn.com' self.failUnless(ircutils.hostmaskPatternEqual(s, s))
def getOtherUser(irc, msg, args, state): # Although ircdb.users.getUser could accept a hostmask, we're explicitly # excluding that from our interface with this check if ircutils.isUserHostmask(args[0]): state.errorNoUser(args[0]) try: state.args.append(ircdb.users.getUser(args[0])) del args[0] except KeyError: try: getHostmask(irc, msg, [args[0]], state) hostmask = state.args.pop() state.args.append(ircdb.users.getUser(hostmask)) del args[0] except (KeyError, callbacks.Error): state.errorNoUser(name=args[0])
def add(self, irc, msg, args, user, hostmask, password): """[<name>] [<hostmask>] [<password>] Adds the hostmask <hostmask> to the user specified by <name>. The <password> may only be required if the user is not recognized by hostmask. <password> is also not required if an owner user is giving the command on behalf of some other user. If <hostmask> is not given, it defaults to your current hostmask. If <name> is not given, it defaults to your currently identified name. This message must be sent to the bot privately (not on a channel) since it may contain a password. """ if not hostmask: hostmask = msg.prefix if not ircutils.isUserHostmask(hostmask): irc.errorInvalid( _('hostmask'), hostmask, _('Make sure your hostmask includes a nick, ' 'then an exclamation point (!), then a user, ' 'then an at symbol (@), then a host. Feel ' 'free to use wildcards (* and ?, which work ' 'just like they do on the command line) in ' 'any of these parts.'), Raise=True) try: otherId = ircdb.users.getUserId(hostmask) if otherId != user.id: irc.error(_('That hostmask is already registered.'), Raise=True) except KeyError: pass if not user.checkPassword(password) and \ not user.checkHostmask(msg.prefix): try: u = ircdb.users.getUser(msg.prefix) except KeyError: irc.error(conf.supybot.replies.incorrectAuthentication(), Raise=True) if not u._checkCapability('owner'): irc.error(conf.supybot.replies.incorrectAuthentication(), Raise=True) try: user.addHostmask(hostmask) except ValueError, e: irc.error(str(e), Raise=True)
def checkIgnored(self, hostmask): """Checks whether a given hostmask is to be ignored by the channel.""" if self.lobotomized: return True if world.testing: return False assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask if self.checkBan(hostmask): return True now = time.time() for (pattern, expiration) in self.ignores.items(): if now < expiration or not expiration: if ircutils.hostmaskPatternEqual(pattern, hostmask): return True else: del self.ignores[pattern] # Later we may wish to keep expiredIgnores, but not now. return False
def nick_to_host(self, irc=None, target='', with_nick=True, reply_now=True): target = target.lower() if ircutils.isUserHostmask(target): return target elif target in self.nicks: return self.nicks[target] elif irc: try: return irc.state.nickToHostmask(target) except: if reply_now: if with_nick: return "%s!*@*" % target return "*@*" return if target in self.nicks: return self.nicks[target] else: return "%s!*@*" % target
def register(self, irc, msg, args, name, password): """<name> <password> Registers <name> with the given password <password> and the current hostmask of the person registering. You shouldn't register twice; if you're not recognized as a user but you've already registered, use the hostmask add command to add another hostmask to your already-registered user, or use the identify command to identify just for a session. This command (and all other commands that include a password) must be sent to the bot privately, not in a channel. """ addHostmask = True try: ircdb.users.getUserId(name) irc.error(_('That name is already assigned to someone.'), Raise=True) except KeyError: pass if ircutils.isUserHostmask(name): irc.errorInvalid(_('username'), name, _('Hostmasks are not valid usernames.'), Raise=True) try: u = ircdb.users.getUser(msg.prefix) if u._checkCapability('owner'): addHostmask = False else: irc.error( _('Your hostmask is already registered to %s') % u.name) return except KeyError: pass user = ircdb.users.newUser() user.name = name user.setPassword(password) if addHostmask: user.addHostmask(msg.prefix) ircdb.users.setUser(user) irc.replySuccess()
def getUserId(self, s): """Returns the user ID of a given name or hostmask.""" if ircutils.isUserHostmask(s): try: return self._hostmaskCache[s] except KeyError: ids = {} for (id, user) in self.users.iteritems(): x = user.checkHostmask(s) if x: ids[id] = x if len(ids) == 1: id = ids.keys()[0] self._hostmaskCache[s] = id try: self._hostmaskCache[id].add(s) except KeyError: self._hostmaskCache[id] = set([s]) return id elif len(ids) == 0: raise KeyError, s else: log.error('Multiple matches found in user database. ' 'Removing the offending hostmasks.') for (id, hostmask) in ids.iteritems(): log.error('Removing %q from user %s.', hostmask, id) self.users[id].removeHostmask(hostmask) raise DuplicateHostmask, 'Ids %r matched.' % ids else: # Not a hostmask, must be a name. s = s.lower() try: return self._nameCache[s] except KeyError: for (id, user) in self.users.items(): if s == user.name.lower(): self._nameCache[s] = id self._nameCache[id] = s return id else: raise KeyError, s
def register(self, irc, msg, args, name, password): """<name> <password> Registers <name> with the given password <password> and the current hostmask of the person registering. You shouldn't register twice; if you're not recognized as a user but you've already registered, use the hostmask add command to add another hostmask to your already-registered user, or use the identify command to identify just for a session. This command (and all other commands that include a password) must be sent to the bot privately, not in a channel. """ addHostmask = True try: ircdb.users.getUserId(name) irc.error(_('That name is already assigned to someone.'), Raise=True) except KeyError: pass if ircutils.isUserHostmask(name): irc.errorInvalid(_('username'), name, _('Hostmasks are not valid usernames.'), Raise=True) try: u = ircdb.users.getUser(msg.prefix) if u._checkCapability('owner'): addHostmask = False else: irc.error(_('Your hostmask is already registered to %s') % u.name) return except KeyError: pass user = ircdb.users.newUser() user.name = name user.setPassword(password) if addHostmask: user.addHostmask(msg.prefix) ircdb.users.setUser(user) irc.replySuccess()
def zncadduser(self, irc, msg, args, username, hostmask, key, channel): """<username> <hostmask> <key> <channel> Add a user to the ZNC auto-op database. Ex: user1 *!*[email protected] passkey #channel NOTICE: I must be run via private message by an admin. """ # declare failcheck. failcheck = False if irc.isChannel(ircutils.toLower(msg.args[0])): irc.reply("ERROR: I must be run via private message by an admin.") return if username in self._users: # do our checks now to see if we can add. irc.reply("ERROR: I already have a user: {0}".format(username)) return if not ircutils.isChannel(channel): # make sure the channel is valid. irc.reply("ERROR: {0} is not a valid channel".format(channel)) return if not ircutils.isUserHostmask(hostmask): # make sure hostmask is valid. irc.reply("ERROR: {0} is not a valid hostmask.".format(hostmask)) return if len(self._users) > 0: # make sure we have users to check against. for (k, v) in self._users.items(): # check the hostnames. userhostname, userkey, userchannel = v[0] if ircutils.hostmaskPatternEqual(hostmask, userhostname) and channel == userchannel: irc.reply("ERROR: I cannot add {0}. Hostmask {1} matches the hostmask {2} in existing user: {3} for {4}".format(username, hostmask, userhostname, k, channel)) failcheck = True break # check if hostname passed. if failcheck: return # username and hostmask are clean. lets add. try: self._addUser(username, hostmask, key, channel) irc.replySuccess() except ValueError, e: irc.reply("Error adding {0} :: {1}".format(username, e))
def addBan(self, hostmask, expiration=0): """Adds a ban to the channel banlist.""" assert not conf.supybot.protocols.irc.strictRfc() or \ ircutils.isUserHostmask(hostmask), 'got %s' % hostmask self.bans[hostmask] = int(expiration)
def testIsUserHostmask(self): self.assertTrue(ircutils.isUserHostmask(self.hostmask)) self.assertTrue(ircutils.isUserHostmask('a!b@c')) self.assertFalse(ircutils.isUserHostmask('!bar@baz')) self.assertFalse(ircutils.isUserHostmask('!@baz')) self.assertFalse(ircutils.isUserHostmask('!bar@')) self.assertFalse(ircutils.isUserHostmask('!@')) self.assertFalse(ircutils.isUserHostmask('foo!@baz')) self.assertFalse(ircutils.isUserHostmask('foo!bar@')) self.assertFalse(ircutils.isUserHostmask('')) self.assertFalse(ircutils.isUserHostmask('!')) self.assertFalse(ircutils.isUserHostmask('@')) self.assertFalse(ircutils.isUserHostmask('!bar@baz'))
def removeIgnore(self, hostmask): """Removes an ignore from the channel ignore list.""" assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask return self.ignores.pop(hostmask)
def addIgnore(self, hostmask, expiration=0): """Adds an ignore to the channel ignore list.""" assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask self.ignores[hostmask] = int(expiration)
def setValue(self, v): if not ircutils.isUserHostmask(v): self.error() super(ValidHostmask, self).setValue(v)
def removeBan(self, hostmask): """Removes a ban from the channel banlist.""" assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask return self.bans.pop(hostmask)
def guessBanType(mask): if mask[0] == '%': return 'quiet' elif ircutils.isUserHostmask(mask) or mask.endswith('(realname)'): return 'ban' return 'removal'
def add(self, hostmask, expiration=0): assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask self.hostmasks[hostmask] = expiration
def removeBan(self, hostmask): """Removes a ban from the channel banlist.""" assert not conf.supybot.protocols.irc.strictRfc() or \ ircutils.isUserHostmask(hostmask), 'got %s' % hostmask return self.bans.pop(hostmask)
def testIsUserHostmask(self): self.failUnless(ircutils.isUserHostmask(self.hostmask)) self.failUnless(ircutils.isUserHostmask('a!b@c')) self.failIf(ircutils.isUserHostmask('!bar@baz')) self.failIf(ircutils.isUserHostmask('!@baz')) self.failIf(ircutils.isUserHostmask('!bar@')) self.failIf(ircutils.isUserHostmask('!@')) self.failIf(ircutils.isUserHostmask('foo!@baz')) self.failIf(ircutils.isUserHostmask('foo!bar@')) self.failIf(ircutils.isUserHostmask('')) self.failIf(ircutils.isUserHostmask('!')) self.failIf(ircutils.isUserHostmask('@')) self.failIf(ircutils.isUserHostmask('!bar@baz'))
def invalidCommand(self, irc, msg, tokens): assert not msg.repliedTo, "repliedTo msg in Misc.invalidCommand." assert self is irc.callbacks[-1], "Misc isn't last callback." assert msg.command in ("PRIVMSG", "NOTICE") self.log.debug("Misc.invalidCommand called (tokens %s)", tokens) # First, we check for invalidCommand floods. This is rightfully done # here since this will be the last invalidCommand called, and thus it # will only be called if this is *truly* an invalid command. maximum = conf.supybot.abuse.flood.command.invalid.maximum() self.invalidCommands.enqueue(msg) if ( self.invalidCommands.len(msg) > maximum and conf.supybot.abuse.flood.command.invalid() and not ircdb.checkCapability(msg.prefix, "owner") ): punishment = conf.supybot.abuse.flood.command.invalid.punishment() banmask = "*!%s@%s" % (msg.user, msg.host) self.log.info( "Ignoring %s for %s seconds due to an apparent " "invalid command flood.", banmask, punishment ) if tokens and tokens[0] == "Error:": self.log.warning( "Apparent error loop with another Supybot " "observed. Consider ignoring this bot " "permanently." ) ircdb.ignores.add(banmask, time.time() + punishment) if conf.supybot.abuse.flood.command.invalid.notify(): irc.reply( _("You've given me %s invalid commands within the last " "%i seconds; I'm now ignoring you for %s.") % (maximum, conf.supybot.abuse.flood.interval(), utils.timeElapsed(punishment, seconds=False)) ) return # Now, for normal handling. channel = msg.args[0] # Only bother with the invaildCommand flood handling if it's actually # enabled if conf.supybot.abuse.flood.command.invalid(): # First, we check for invalidCommand floods. This is rightfully done # here since this will be the last invalidCommand called, and thus it # will only be called if this is *truly* an invalid command. maximum = conf.supybot.abuse.flood.command.invalid.maximum() banmasker = conf.supybot.protocols.irc.banmask.makeBanmask self.invalidCommands.enqueue(msg) if ( self.invalidCommands.len(msg) > maximum and not ircdb.checkCapability(msg.prefix, "owner") and msg.prefix != irc.prefix and ircutils.isUserHostmask(msg.prefix) ): penalty = conf.supybot.abuse.flood.command.invalid.punishment() banmask = banmasker(msg.prefix, channel=None) self.log.info( "Ignoring %s for %s seconds due to an apparent " "invalid command flood.", banmask, penalty ) if tokens and tokens[0] == "Error:": self.log.warning( "Apparent error loop with another Supybot " "observed. Consider ignoring this bot " "permanently." ) ircdb.ignores.add(banmask, time.time() + penalty) if conf.supybot.abuse.flood.command.invalid.notify(): irc.reply( "You've given me %s invalid commands within " "the last minute; I'm now ignoring you for %s." % (maximum, utils.timeElapsed(penalty, seconds=False)) ) return # Now, for normal handling. if conf.get(conf.supybot.reply.whenNotCommand, channel): if len(tokens) >= 2: cb = irc.getCallback(tokens[0]) if cb: plugin = cb.name() irc.error( format( _( "The %q plugin is loaded, but there is " 'no command named %q in it. Try "list ' '%s" to see the commands in the %q ' "plugin." ), plugin, tokens[1], plugin, plugin, ) ) else: irc.errorInvalid(_("command"), tokens[0], repr=False) else: command = tokens and tokens[0] or "" irc.errorInvalid(_("command"), command, repr=False) else: if tokens: # echo [] will get us an empty token set, but there's no need # to log this in that case anyway, it being a nested command. self.log.info("Not replying to %s, not a command.", tokens[0]) if irc.nested: bracketConfig = conf.supybot.commands.nested.brackets brackets = conf.get(bracketConfig, channel) if brackets: (left, right) = brackets irc.reply(left + " ".join(tokens) + right) else: pass # Let's just do nothing, I can't think of better.
def invalidCommand(self, irc, msg, tokens): assert not msg.repliedTo, 'repliedTo msg in Misc.invalidCommand.' assert self is irc.callbacks[-1], 'Misc isn\'t last callback.' assert msg.command in ('PRIVMSG', 'NOTICE') self.log.debug('Misc.invalidCommand called (tokens %s)', tokens) # First, we check for invalidCommand floods. This is rightfully done # here since this will be the last invalidCommand called, and thus it # will only be called if this is *truly* an invalid command. maximum = conf.supybot.abuse.flood.command.invalid.maximum() self.invalidCommands.enqueue(msg) if self.invalidCommands.len(msg) > maximum and \ conf.supybot.abuse.flood.command.invalid() and \ not ircdb.checkCapability(msg.prefix, 'trusted'): punishment = conf.supybot.abuse.flood.command.invalid.punishment() banmask = '*!%s@%s' % (msg.user, msg.host) self.log.info( 'Ignoring %s for %s seconds due to an apparent ' 'invalid command flood.', banmask, punishment) if tokens and tokens[0] == 'Error:': self.log.warning('Apparent error loop with another Supybot ' 'observed. Consider ignoring this bot ' 'permanently.') ircdb.ignores.add(banmask, time.time() + punishment) if conf.supybot.abuse.flood.command.invalid.notify(): irc.reply( _('You\'ve given me %s invalid commands within the last ' '%i seconds; I\'m now ignoring you for %s.') % (maximum, conf.supybot.abuse.flood.interval(), utils.timeElapsed(punishment, seconds=False))) return # Now, for normal handling. channel = msg.channel # Only bother with the invaildCommand flood handling if it's actually # enabled if conf.supybot.abuse.flood.command.invalid(): # First, we check for invalidCommand floods. This is rightfully done # here since this will be the last invalidCommand called, and thus it # will only be called if this is *truly* an invalid command. maximum = conf.supybot.abuse.flood.command.invalid.maximum() banmasker = conf.supybot.protocols.irc.banmask.makeBanmask if self.invalidCommands.len(msg) > maximum and \ not ircdb.checkCapability(msg.prefix, 'trusted') and \ msg.prefix != irc.prefix and \ ircutils.isUserHostmask(msg.prefix): penalty = conf.supybot.abuse.flood.command.invalid.punishment() banmask = banmasker(msg.prefix, channel=channel, network=irc.network) self.log.info( 'Ignoring %s for %s seconds due to an apparent ' 'invalid command flood.', banmask, penalty) if tokens and tokens[0] == 'Error:': self.log.warning( 'Apparent error loop with another Supybot ' 'observed. Consider ignoring this bot ' 'permanently.') ircdb.ignores.add(banmask, time.time() + penalty) if conf.supybot.abuse.flood.command.invalid.notify(): irc.reply( 'You\'ve given me %s invalid commands within ' 'the last minute; I\'m now ignoring you for %s.' % (maximum, utils.timeElapsed(penalty, seconds=False))) return # Now, for normal handling. if conf.supybot.reply.whenNotCommand.getSpecific(irc.network, channel)(): if len(tokens) >= 2: cb = irc.getCallback(tokens[0]) if cb: plugin = cb.name() irc.error( format( _('The %q plugin is loaded, but there is ' 'no command named %q in it. Try "list ' '%s" to see the commands in the %q ' 'plugin.'), plugin, tokens[1], plugin, plugin)) else: irc.errorInvalid(_('command'), tokens[0], repr=False) else: command = tokens and tokens[0] or '' irc.errorInvalid(_('command'), command, repr=False) else: if tokens: # echo [] will get us an empty token set, but there's no need # to log this in that case anyway, it being a nested command. self.log.info('Not replying to %s in %s, not a command.', tokens[0], channel if channel != irc.nick else _('private')) if irc.nested: bracketConfig = conf.supybot.commands.nested.brackets brackets = bracketConfig.getSpecific(irc.network, channel)() if brackets: (left, right) = brackets irc.reply(left + ' '.join(tokens) + right) else: pass # Let's just do nothing, I can't think of better.
def addBan(self, hostmask, expiration=0): """Adds a ban to the channel banlist.""" assert ircutils.isUserHostmask(hostmask), 'got %s' % hostmask self.bans[hostmask] = int(expiration)
def invalidCommand(self, irc, msg, tokens): assert not msg.repliedTo, 'repliedTo msg in Misc.invalidCommand.' assert self is irc.callbacks[-1], 'Misc isn\'t last callback.' assert msg.command in ('PRIVMSG', 'NOTICE') self.log.debug('Misc.invalidCommand called (tokens %s)', tokens) # First, we check for invalidCommand floods. This is rightfully done # here since this will be the last invalidCommand called, and thus it # will only be called if this is *truly* an invalid command. maximum = conf.supybot.abuse.flood.command.invalid.maximum() self.invalidCommands.enqueue(msg) if self.invalidCommands.len(msg) > maximum and \ conf.supybot.abuse.flood.command.invalid() and \ not ircdb.checkCapability(msg.prefix, 'owner'): punishment = conf.supybot.abuse.flood.command.invalid.punishment() banmask = '*!%s@%s' % (msg.user, msg.host) self.log.info('Ignoring %s for %s seconds due to an apparent ' 'invalid command flood.', banmask, punishment) if tokens and tokens[0] == 'Error:': self.log.warning('Apparent error loop with another Supybot ' 'observed. Consider ignoring this bot ' 'permanently.') ircdb.ignores.add(banmask, time.time() + punishment) if conf.supybot.abuse.flood.command.invalid.notify(): irc.reply(_('You\'ve given me %s invalid commands within the last ' '%i seconds; I\'m now ignoring you for %s.') % (maximum, conf.supybot.abuse.flood.interval(), utils.timeElapsed(punishment, seconds=False))) return # Now, for normal handling. channel = msg.args[0] # Only bother with the invaildCommand flood handling if it's actually # enabled if conf.supybot.abuse.flood.command.invalid(): # First, we check for invalidCommand floods. This is rightfully done # here since this will be the last invalidCommand called, and thus it # will only be called if this is *truly* an invalid command. maximum = conf.supybot.abuse.flood.command.invalid.maximum() banmasker = conf.supybot.protocols.irc.banmask.makeBanmask if self.invalidCommands.len(msg) > maximum and \ not ircdb.checkCapability(msg.prefix, 'owner') and \ msg.prefix != irc.prefix and \ ircutils.isUserHostmask(msg.prefix): penalty = conf.supybot.abuse.flood.command.invalid.punishment() banmask = banmasker(msg.prefix, channel=None) self.log.info('Ignoring %s for %s seconds due to an apparent ' 'invalid command flood.', banmask, penalty) if tokens and tokens[0] == 'Error:': self.log.warning('Apparent error loop with another Supybot ' 'observed. Consider ignoring this bot ' 'permanently.') ircdb.ignores.add(banmask, time.time() + penalty) if conf.supybot.abuse.flood.command.invalid.notify(): irc.reply('You\'ve given me %s invalid commands within ' 'the last minute; I\'m now ignoring you for %s.' % (maximum, utils.timeElapsed(penalty, seconds=False))) return # Now, for normal handling. if conf.get(conf.supybot.reply.whenNotCommand, channel): if len(tokens) >= 2: cb = irc.getCallback(tokens[0]) if cb: plugin = cb.name() irc.error(format(_('The %q plugin is loaded, but there is ' 'no command named %q in it. Try "list ' '%s" to see the commands in the %q ' 'plugin.'), plugin, tokens[1], plugin, plugin)) else: irc.errorInvalid(_('command'), tokens[0], repr=False) else: command = tokens and tokens[0] or '' irc.errorInvalid(_('command'), command, repr=False) else: if tokens: # echo [] will get us an empty token set, but there's no need # to log this in that case anyway, it being a nested command. self.log.info('Not replying to %s in %s, not a command.' % (tokens[0], channel if channel != irc.nick else _('private'))) if irc.nested: bracketConfig = conf.supybot.commands.nested.brackets brackets = conf.get(bracketConfig, channel) if brackets: (left, right) = brackets irc.reply(left + ' '.join(tokens) + right) else: pass # Let's just do nothing, I can't think of better.
def testIsUserHostmask(self): self.failUnless(ircutils.isUserHostmask(self.hostmask)) self.failUnless(ircutils.isUserHostmask("a!b@c")) self.failIf(ircutils.isUserHostmask("!bar@baz")) self.failIf(ircutils.isUserHostmask("!@baz")) self.failIf(ircutils.isUserHostmask("!bar@")) self.failIf(ircutils.isUserHostmask("!@")) self.failIf(ircutils.isUserHostmask("foo!@baz")) self.failIf(ircutils.isUserHostmask("foo!bar@")) self.failIf(ircutils.isUserHostmask("")) self.failIf(ircutils.isUserHostmask("!")) self.failIf(ircutils.isUserHostmask("@")) self.failIf(ircutils.isUserHostmask("!bar@baz"))