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 do(type): cap = ircdb.makeChannelCapability(channel, type) cap_auto = ircdb.makeChannelCapability(channel, "auto" + type) try: apply_mode = ircdb.checkCapability( msg.prefix, cap, ignoreOwner=not self.registryValue("owner"), ignoreChannelOp=True, ignoreDefaultAllow=True, ) except KeyError: apply_mode = False if self.registryValue("alternativeCapabilities", channel): try: override = ircdb.checkCapability( msg.prefix, cap_auto, ignoreOwner=not self.registryValue("owner"), ignoreChannelOp=True, ignoreDefaultAllow=True, ) except KeyError: override = False else: override = False if apply_mode or override: if override or self.registryValue(type, channel): self.log.info("Scheduling auto-%s of %s in %s.", type, msg.prefix, channel) def dismiss(): """Determines whether or not a mode has already been applied.""" l = getattr(irc.state.channels[channel], type + "s") return msg.nick in l msgmaker = getattr(ircmsgs, type) schedule_msg(msgmaker(channel, msg.nick), dismiss) raise Continue # Even if fallthrough, let's only do one. elif not fallthrough: self.log.debug( "%s has %s, but supybot.plugins.AutoMode.%s" " is not enabled in %s, refusing to fall " "through.", msg.prefix, cap, type, channel, ) raise Continue
def nicks(self, irc, msg, args, channel, optlist): """[<channel>] [--count] Returns the nicks in <channel>. <channel> is only necessary if the message isn't sent in the channel itself. Returns only the number of nicks if --count option is provided. """ # Make sure we don't elicit information about private channels to # people or channels that shouldn't know capability = ircdb.makeChannelCapability(channel, 'op') hostmask = irc.state.nickToHostmask(msg.nick) if 's' in irc.state.channels[channel].modes and \ msg.args[0] != channel and \ not ircdb.checkCapability(hostmask, capability) and \ (ircutils.isChannel(msg.args[0]) or \ msg.nick not in irc.state.channels[channel].users): irc.error(_('You don\'t have access to that information.'), Raise=True) L = list(irc.state.channels[channel].users) keys = [option for (option, arg) in optlist] if 'count' not in keys: utils.sortBy(str.lower, L) private = self.registryValue("nicksInPrivate", channel) irc.reply(utils.str.commaAndify(L), private=private) else: irc.reply(str(len(L)))
def voice(self, irc, msg, args, channel, nicks): """[<channel>] [<nick> ...] If you have the #channel,voice capability, this will voice all the <nick>s you provide. If you don't provide any <nick>s, this will voice you. <channel> is only necessary if the message isn't sent in the channel itself. """ if nicks: if len(nicks) == 1 and msg.nick in nicks: capability = "voice" else: capability = "op" else: nicks = [msg.nick] capability = "voice" capability = ircdb.makeChannelCapability(channel, capability) if ircdb.checkCapability(msg.prefix, capability): def f(L): return ircmsgs.voices(channel, L) self._sendMsgs(irc, nicks, f) else: irc.errorNoCapability(capability)
def inFilter(self, irc, msg): self.filtering = True # We need to check for bad words here rather than in doPrivmsg because # messages don't get to doPrivmsg if the user is ignored. if msg.command == 'PRIVMSG': channel = msg.args[0] self.updateRegexp(channel) s = ircutils.stripFormatting(msg.args[1]) if ircutils.isChannel(channel) and self.registryValue('kick', channel): if self.words and self.regexp.search(s): c = irc.state.channels[channel] cap = ircdb.makeChannelCapability(channel, 'op') if c.isHalfopPlus(irc.nick): if c.isHalfopPlus(msg.nick) or \ ircdb.checkCapability(msg.prefix, cap): self.log.debug("Not kicking %s from %s, because " "they are halfop+ or can't be " "kicked.", msg.nick, channel) else: message = self.registryValue('kick.message', channel) irc.queueMsg(ircmsgs.kick(channel, msg.nick, message)) else: self.log.warning('Should kick %s from %s, but not opped.', msg.nick, channel) return msg
def checkChannelCapability(irc, msg, args, state, cap): if not state.channel: getChannel(irc, msg, args, state) cap = ircdb.canonicalCapability(cap) cap = ircdb.makeChannelCapability(state.channel, cap) if not ircdb.checkCapability(msg.prefix, cap): state.errorNoCapability(cap, Raise=True)
def devoice(self, irc, msg, args, channel, nicks): """[<channel>] [<nick> ...] If you have the #channel,op capability, this will remove voice from all the nicks given. If no nicks are given, removes voice from the person sending the message. """ if irc.nick in nicks: irc.error(_('I cowardly refuse to devoice myself. If you really ' 'want me devoiced, tell me to op you and then devoice ' 'me yourself.'), Raise=True) if nicks: if len(nicks) == 1 and msg.nick in nicks: capability = 'voice' else: capability = 'op' else: nicks = [msg.nick] capability = 'voice' capability = ircdb.makeChannelCapability(channel, capability) if ircdb.checkCapability(msg.prefix, capability): def f(L): return ircmsgs.devoices(channel, L) self._sendMsgs(irc, nicks, f) else: irc.errorNoCapability(capability)
def checkChangeAllowed(self, irc, msg, channel, user, record): if user.id == record.by: return True cap = ircdb.makeChannelCapability(channel, 'op') if ircdb.checkCapability(msg.prefix, cap): return True irc.errorNoCapability(cap)
def learn(self, irc, msg, args, channel, key, factoid): db = self.getDb(channel) cursor = db.cursor() cursor.execute("SELECT id, locked FROM keys WHERE key LIKE %s", key) if cursor.rowcount == 0: cursor.execute("""INSERT INTO keys VALUES (NULL, %s, 0)""", key) db.commit() cursor.execute("SELECT id, locked FROM keys WHERE key LIKE %s", key) (id, locked) = map(int, cursor.fetchone()) capability = ircdb.makeChannelCapability(channel, "factoids") if not locked: if ircdb.users.hasUser(msg.prefix): name = ircdb.users.getUser(msg.prefix).name else: name = msg.nick cursor.execute( """INSERT INTO factoids VALUES (NULL, %s, %s, %s, %s)""", id, name, int(time.time()), factoid, ) db.commit() irc.replySuccess() else: irc.error("That factoid is locked.")
def checkAndAct (self,irc,prefix,chan,kind,items,text,msg): protected = ircdb.makeChannelCapability(chan.name, 'protected') if ircdb.checkCapability(prefix, protected): return for pattern in list(items.keys()): item = chan.kinds[kind][pattern] if item.enable == '1': for match in re.finditer(item.re, text): if match: act = item.action account = '' gecos = '' if prefix.split('!')[0] in chan.nicks: (prefix,account,gecos) = chan.nicks[prefix.split('!')[0]] act = act.replace('$nick',prefix.split('!')[0]) act = act.replace('$hostmask',prefix) act = act.replace('$account',account) act = act.replace('$username',gecos) act = act.replace('$id',str(item.uid)) act = act.replace('$channel',chan.name) act = act.replace('$*',text) if act.find(' :') != -1: a = text.split(' :') if len(a) > 1: act = act.replace('$text',text.split(' :')[1]) for (i, j) in enumerate(match.groups()): act = re.sub(r'\$' + str(i+1), match.group(i+1), act) self.act(irc,msg,chan.name,act,item.owner) break
def newpoll(self, irc, msg, args, channel, interval, answers, question): """<number of minutes for announce interval> <"answer,answer,..."> question Creates a new poll with the given question and answers. <channel> is only necessary if the message isn't sent in the channel itself.""" capability = ircdb.makeChannelCapability(channel, 'op') if not ircdb.checkCapability(msg.prefix, capability): irc.error('Need ops') return db = self.getDb(channel) cursor = db.cursor() self._execute_query(cursor, 'INSERT INTO polls VALUES (?,?,?,?,?)', None, datetime.datetime.now(), 1, None, question) pollid = cursor.lastrowid # used to add choices into db. each choice represented by character, starting at capital A (code 65) def genAnswers(): for i, answer in enumerate(answers, start=65): yield pollid, chr(i), answer cursor.executemany('INSERT INTO choices VALUES (?,?,?)', genAnswers()) db.commit() irc.reply('Started new poll #%s' % pollid) # function called by schedule event. can not have args def runPoll(): self._runPoll(irc, channel, pollid) # start schedule. will announce poll/choices to channel at interval schedule.addPeriodicEvent(runPoll, interval*60, name='%s_poll_%s' % (channel, pollid)) self.poll_schedules.append('%s_poll_%s' % (channel, pollid))
def _checkManageCapabilities(self, irc, msg, channel): """Check if the user has any of the required capabilities to manage the channel topic. The list of required capabilities is in requireManageCapability channel config. Also allow if the user is a chanop. Since they can change the topic manually anyway. """ c = irc.state.channels[channel] if msg.nick in c.ops or msg.nick in c.halfops or 't' not in c.modes: return True capabilities = self.registryValue('requireManageCapability', channel) if capabilities: for capability in re.split(r'\s*;\s*', capabilities): if capability.startswith('channel,'): capability = ircdb.makeChannelCapability( channel, capability[8:]) if capability and ircdb.checkCapability(msg.prefix, capability): return capabilities = self.registryValue('requireManageCapability', channel) irc.errorNoCapability(capabilities, Raise=True) else: return
def part(self, irc, msg, args, channel, reason): """[<channel>] [<reason>] Tells the bot to part the list of channels you give it. <channel> is only necessary if you want the bot to part a channel other than the current channel. If <reason> is specified, use it as the part message. Otherwise, the default part message specified in supybot.plugins.Channel.partMsg will be used. No part message will be used if no default is configured. """ if channel is None: if irc.isChannel(msg.args[0]): channel = msg.args[0] else: irc.error(Raise=True) capability = ircdb.makeChannelCapability(channel, 'op') hostmask = irc.state.nickToHostmask(msg.nick) if not ircdb.checkCapabilities(hostmask, [capability, 'admin']): irc.errorNoCapability(capability, Raise=True) try: network = conf.supybot.networks.get(irc.network) network.channels().remove(channel) except KeyError: pass if channel not in irc.state.channels: irc.error(_('I\'m not in %s.') % channel, Raise=True) reason = (reason or self.registryValue("partMsg", channel)) reason = ircutils.standardSubstitute(irc, msg, reason) irc.queueMsg(ircmsgs.part(channel, reason)) if msg.nick in irc.state.channels[channel].users: irc.noReply() else: irc.replySuccess()
def doPrivmsg(self, irc, msg): (recipients, text) = msg.args for channel in recipients.split(','): if irc.isChannel(channel): noLogPrefix = self.registryValue('noLogPrefix', channel) cap = ircdb.makeChannelCapability(channel, 'logChannelMessages') try: logChannelMessages = ircdb.checkCapability(msg.prefix, cap, ignoreOwner=True) except KeyError: logChannelMessages = True nick = msg.nick or irc.nick if msg.tagged('LogsToDB__relayed'): (nick, text) = text.split(' ', 1) nick = nick[1:-1] msg.args = (recipients, text) if (noLogPrefix and text.startswith(noLogPrefix)) or \ not logChannelMessages: text = '-= THIS MESSAGE NOT LOGGED =-' if ircmsgs.isAction(msg): self.doLog(irc, channel, '* %s %s\n', nick, ircmsgs.unAction(msg)) else: self.doLog(irc, channel, '<%s> %s\n', nick, text) message = msg.args[1] self.logViewerDB.add_message(msg.nick, msg.prefix, message, channel) self.logViewerFile.write_message(msg.nick, message)
def setUp(self): ChannelPluginTestCase.setUp(self) self.prefix = "foo!bar@baz" self.nick = "foo" self.irc.feedMsg(ircmsgs.privmsg(self.irc.nick, "register foo bar", prefix=self.prefix)) _ = self.irc.takeMsg() chanop = ircdb.makeChannelCapability(self.channel, "op") ircdb.users.getUser(self.nick).addCapability(chanop)
def _kban(self, irc, msg, args, bannedNick, reason): # Check that they're not trying to make us kickban ourself. channel = msg.args[0] if not irc.isNick(bannedNick[0]): self.log.warning('%q tried to kban a non nick: %q', msg.prefix, bannedNick) raise callbacks.ArgumentError elif bannedNick == irc.nick: self.log.warning('%q tried to make me kban myself.', msg.prefix) irc.error('I cowardly refuse to kickban myself.') return if not reason: reason = msg.nick try: bannedHostmask = irc.state.nickToHostmask(bannedNick) except KeyError: irc.error(format('I haven\'t seen %s.', bannedNick), Raise=True) capability = ircdb.makeChannelCapability(channel, 'op') banmaskstyle = conf.supybot.protocols.irc.banmask banmask = banmaskstyle.makeBanmask(bannedHostmask, ["host", "user"]) # Check (again) that they're not trying to make us kickban ourself. if ircutils.hostmaskPatternEqual(banmask, irc.prefix): if ircutils.hostmaskPatternEqual(bannedHostmask, irc.prefix): self.log.warning('%q tried to make me kban myself.',msg.prefix) irc.error('I cowardly refuse to ban myself.') return else: self.log.warning('Using exact hostmask since banmask would ' 'ban myself.') banmask = bannedHostmask # Now, let's actually get to it. Check to make sure they have # #channel,op and the bannee doesn't have #channel,op; or that the # bannee and the banner are both the same person. def doBan(): if irc.state.channels[channel].isOp(bannedNick): irc.queueMsg(ircmsgs.deop(channel, bannedNick)) irc.queueMsg(ircmsgs.ban(channel, banmask)) irc.queueMsg(ircmsgs.kick(channel, bannedNick, reason)) def f(): if channel in irc.state.channels and \ banmask in irc.state.channels[channel].bans: irc.queueMsg(ircmsgs.unban(channel, banmask)) schedule.addEvent(f, 3600) if bannedNick == msg.nick: doBan() elif ircdb.checkCapability(msg.prefix, capability): if ircdb.checkCapability(bannedHostmask, capability): self.log.warning('%s tried to ban %q, but both have %s', msg.prefix, bannedHostmask, capability) irc.error(format('%s has %s too, you can\'t ban him/her/it.', bannedNick, capability)) else: doBan() else: self.log.warning('%q attempted kban without %s', msg.prefix, capability) irc.errorNoCapability(capability) exact,nick,user,host
def isProtected(self, irc, channel, hostmask): cap = ircdb.makeChannelCapability(channel, 'protected') if ircdb.checkCapability(hostmask, cap): self.log.debug('%s is protected on %s, it has %s.', hostmask, channel, cap) return True if ircutils.strEqual(hostmask, irc.prefix): return True return False
def _checkManageCapabilities(self, irc, msg, channel): """Check if the user has any of the required capabilities to manage the regexp database.""" if channel != 'global': capability = ircdb.makeChannelCapability(channel, 'op') else: capability = 'admin' if not ircdb.checkCapability(msg.prefix, capability): irc.errorNoCapability(capability, Raise=True)
def setUp(self): ChannelPluginTestCase.setUp(self) self.prefix = 'foo!bar@baz' self.nick = 'foo' self.wildcardTest = ['f*', '*oo', '*foo*', 'f*o*o'] self.irc.feedMsg(ircmsgs.privmsg(self.irc.nick, 'register foo bar', prefix=self.prefix)) _ = self.irc.takeMsg() chancap = ircdb.makeChannelCapability(self.channel, 'op') ircdb.users.getUser(self.nick).addCapability(chancap)
def alertOps(self, irc, channel, s, frm=None): """Internal message for notifying all the #channel,ops in a channel of a given situation.""" capability = ircdb.makeChannelCapability(channel, 'op') s = format(_('Alert to all %s ops: %s'), channel, s) if frm is not None: s += format(_(' (from %s)'), frm) for nick in irc.state.channels[channel].users: hostmask = irc.state.nickToHostmask(nick) if ircdb.checkCapability(hostmask, capability): irc.reply(s, to=nick, private=True)
def getCapability(name): capability = 'owner' # Default to requiring the owner capability. parts = registry.split(name) while parts: part = parts.pop() if ircutils.isChannel(part): # If a registry value has a channel in it, it requires a channel.op # capability, or so we assume. We'll see if we're proven wrong. capability = ircdb.makeChannelCapability(part, 'op') ### Do more later, for specific capabilities/sections. return capability
def user_has_capability(self, msg): channel = msg.args[0] mask = msg.prefix required_capability = self.registryValue("requireCapability") cap = ircdb.makeChannelCapability(channel, required_capability) has_cap = ircdb.checkCapability(mask, cap, ignoreDefaultAllow=True) if has_cap: log.debug("SpiffyTitles: %s has required capability '%s'" % (mask, required_capability)) else: log.debug("SpiffyTitles: %s does NOT have required capability '%s'" % (mask, required_capability)) return has_cap
def add(self, irc, msg, args, channel, user, capabilities): """[<channel>] <nick|username> <capability> [<capability> ...] If you have the #channel,op capability, this will give the <username> (or the user to whom <nick> maps) the capability <capability> in the channel. <channel> is only necessary if the message isn't sent in the channel itself. """ for c in capabilities.split(): c = ircdb.makeChannelCapability(channel, c) user.addCapability(c) ircdb.users.setUser(user) irc.replySuccess()
def sendAlert(self, irc, channel, sender, s=None): """Internal message to send an alets to all <channel>,ops. """ capability = ircdb.makeChannelCapability(channel, "op") if s: s = format(_("Alert to all %s ops: %s"), channel, s) else: s = format(_("Alert to all %s ops:"), channel) if sender is not None: s += format(_(" (requested by %s)"), sender) for nick in irc.state.channels[channel].users: hostmask = irc.state.nickToHostmask(nick) if ircdb.checkCapability(hostmask, capability): irc.reply(nick + ": " + s, to=nick, private=True)
def _checkManageCapabilities(self, irc, msg, channel): """Check if the user has any of the required capabilities to manage the regexp database.""" capabilities = self.registryValue('requireManageCapability') if capabilities: for capability in re.split(r'\s*;\s*', capabilities): if capability.startswith('channel,'): capability = ircdb.makeChannelCapability(channel, capability[8:]) if capability and ircdb.checkCapability(msg.prefix, capability): #print "has capability:", capability return True return False else: return True
def do(type): cap = ircdb.makeChannelCapability(channel, type) if ircdb.checkCapability(msg.prefix, cap, ignoreOwner=not self.registryValue('owner')): if self.registryValue(type, channel): self.log.info('Sending auto-%s of %s in %s.', type, msg.prefix, channel) msgmaker = getattr(ircmsgs, type) irc.queueMsg(msgmaker(channel, msg.nick)) raise Continue # Even if fallthrough, let's only do one. elif not fallthrough: self.log.debug('%s has %s, but supybot.plugins.AutoMode.%s' ' is not enabled in %s, refusing to fall ' 'through.', msg.prefix, cap, type, channel) raise Continue
def clear(self, irc, msg, args, channel, optlist): """[<channel>] Clear database for the <channel>. If <channel> is not given, it defaults to the current channel.""" capability = ircdb.makeChannelCapability(channel, 'op') if not ircdb.checkCapability(msg.prefix, capability): irc.errorNoCapability(capability, Raise=True) if not optlist: irc.reply(_('Running this command will wipe all webstats data ' 'for the channel. If you are sure you want to do this, ' 'add the --confirm switch.')) return self.db.clearChannel(channel) irc.replySuccess()
def testSelfStats(self): self.assertError('channelstats stats %s' % self.irc.nick) self.assertNotError('channelstats stats %s' % self.irc.nick) self.assertNotError('channelstats stats %s' % self.irc.nick) self.assertNotError('channelstats stats %s' % self.irc.nick.upper()) u = ircdb.users.getUser(self.prefix) u.addCapability(ircdb.makeChannelCapability(self.channel, 'op')) ircdb.users.setUser(u) try: conf.supybot.plugins.ChannelStats.selfStats.setValue(False) m1 = self.getMsg('channelstats stats %s' % self.irc.nick) m2 = self.getMsg('channelstats stats %s' % self.irc.nick) self.assertEqual(m1.args[1], m2.args[1]) finally: conf.supybot.plugins.ChannelStats.selfStats.setValue(True)
def _voice(self, irc, msg, args, channel, nicks, fn): if nicks: if len(nicks) == 1 and msg.nick in nicks: capability = 'voice' else: capability = 'op' else: nicks = [msg.nick] capability = 'voice' capability = ircdb.makeChannelCapability(channel, capability) if ircdb.checkCapability(msg.prefix, capability): def f(L): return fn(channel, L) self._sendMsgs(irc, nicks, f) else: irc.errorNoCapability(capability)
def testSelfStats(self): self.irc.feedMsg(ircmsgs.join(self.channel, prefix=self.prefix)) self.assertError('channelstats stats %s' % self.irc.nick) self.assertNotError('channelstats stats %s' % self.irc.nick) self.assertNotError('channelstats stats %s' % self.irc.nick) self.assertNotError('channelstats stats %s' % self.irc.nick.upper()) self.assertRegexp('channelstats rank chars', self.irc.nick) u = ircdb.users.getUser(self.prefix) u.addCapability(ircdb.makeChannelCapability(self.channel, 'op')) ircdb.users.setUser(u) try: conf.supybot.plugins.ChannelStats.selfStats.setValue(False) m1 = self.getMsg('channelstats stats %s' % self.irc.nick) m2 = self.getMsg('channelstats stats %s' % self.irc.nick) self.assertEqual(m1.args[1], m2.args[1]) finally: conf.supybot.plugins.ChannelStats.selfStats.setValue(True)
def userCorrect(self,irc,msg,match): r"^u[/].*[/].*[/].*$" if msg.args[0] != '##powder-bots' and msg.args[0] != '##jacksonmj-test': irc.noReply() return if not ircdb.checkCapability(msg.prefix, ircdb.makeChannelCapability(msg.args[0], 'op')): irc.noReply() return match = match.group(0) data = match.split('/') user = data[1] newData = [] x=0 while x < len(data): if len(data[x]) and '\\' == data[x][-1] and x+1 < len(data): newData+=['{0}/{1}'.format(data[x][:-1],data[x+1])] x+=2 else: newData+=[data[x]] x+=1 data=newData channel = msg.args[0] try: self.buffer[channel] except: self.buffer[channel]=[] for each in self.buffer[channel]: print user.lower(),each[0].lower(),user.lower() is each[0].lower() if user.lower() in each[0].lower(): output = each[1] x=2 while x+1 < len(data): output=output.replace(data[x],data[x+1]) output=output[0:min(len(output),4096)] x+=2 self.log.info('Changing {0} to {1}'.format(each[1],output)) irc.reply('<{0}> {1}'.format(each[0],output),prefixNick=False) return 0 irc.error('Not found in buffer')
def do(type): if ircdb.checkCapability(msg.prefix, 'owner') and not \ self.registryValue('owner'): raise Continue cap = ircdb.makeChannelCapability(channel, type) if ircdb.checkCapability(msg.prefix, cap): if self.registryValue(type, channel): self.log.info('Sending auto-%s of %s in %s.', type, msg.prefix, channel) msgmaker = getattr(ircmsgs, type) irc.queueMsg(msgmaker(channel, msg.nick)) raise Continue # Even if fallthrough, let's only do one. elif not fallthrough: self.log.debug('%s has %s, but supybot.plugins.AutoMode.%s' ' is not enabled in %s, refusing to fall ' 'through.', msg.prefix, cap, type, channel) raise Continue
def getCapability(name): capability = 'owner' # Default to requiring the owner capability. if not name.startswith('supybot') and not name.startswith('users'): name = 'supybot.' + name parts = registry.split(name) group = getattr(conf, parts.pop(0)) while parts: part = parts.pop(0) group = group.get(part) if not getattr(group, '_opSettable', True): return 'owner' if ircutils.isChannel(part): # If a registry value has a channel in it, it requires a # 'channel,op' capability, or so we assume. We'll see if we're # proven wrong. capability = ircdb.makeChannelCapability(part, 'op') ### Do more later, for specific capabilities/sections. return capability
def _checkManageCapabilities(self, irc, msg, channel): """Check if the user has any of the required capabilities to manage the regexp database.""" capabilities = self.registryValue('requireManageCapability') if capabilities: for capability in re.split(r'\s*;\s*', capabilities): if capability.startswith('channel,'): capability = capability[8:] if channel != 'global': capability = ircdb.makeChannelCapability( channel, capability) if capability and ircdb.checkCapability( msg.prefix, capability): #print "has capability:", capability return True return False else: return True
def inFilter(self, irc, msg): if msg.command == 'PRIVMSG' and self.active: channel = msg.args[0] s = ircutils.stripFormatting(msg.args[1]) if ircutils.isChannel(channel) and self.registryValue( 'kick', channel): if confusables.is_mixed_script(s): c = irc.state.channels[channel] cap = ircdb.makeChannelCapability(channel, 'op') u = msg.nick t = time.time() self.thresh[u].append(t) self.thresh[u] = [ item for item in self.thresh[u] if item > (t - self.registryValue('slw')) ] self.log.warning( "Detected mixed <%s>, threshold" "for user %s is now %s", s, u, len(self.thresh[u])) if len(self.thresh[u]) > self.registryValue('rep'): self.log.warning( "Threshold reached, trying to kick %s", u) if c.isHalfopPlus(irc.nick): if c.isHalfopPlus(u) or \ ircdb.checkCapability(msg.prefix, cap): self.log.warning( "Not kicking %s from %s, because " "they are halfop+ or can't be " "kicked.", u, channel) else: message = self.registryValue( 'kick.message', channel) irc.queueMsg(ircmsgs.kick(channel, u, message)) self.log.warning("Kicked %s from %s", u, channel) else: self.log.warning( 'Should kick %s from %s, but not opped.', u, channel) return msg
def list(self, irc, msg, args): """takes no arguments Returns the channels in which this bot is lobotomized. """ L = [] for (channel, c) in ircdb.channels.items(): if c.lobotomized: chancap = ircdb.makeChannelCapability(channel, 'op') if ircdb.checkCapability(msg.prefix, 'admin') or \ ircdb.checkCapability(msg.prefix, chancap) or \ (channel in irc.state.channels and \ msg.nick in irc.state.channels[channel].users): L.append(channel) if L: L.sort() s = format(_('I\'m currently lobotomized in %L.'), L) irc.reply(s) else: irc.reply(_('I\'m not currently lobotomized in any channels ' 'that you\'re in.'))
def doPrivmsg(self, irc, msg): (recipients, text) = msg.args for channel in recipients.split(','): if irc.isChannel(channel): noLogPrefix = self.registryValue('noLogPrefix', channel, irc.network) cap = ircdb.makeChannelCapability(channel, 'logChannelMessages') try: logChannelMessages = ircdb.checkCapability( msg.prefix, cap, ignoreOwner=True) except KeyError: logChannelMessages = True nick = msg.nick or irc.nick rewriteRelayed = self.registryValue('rewriteRelayed', channel, irc.network) if msg.tagged('ChannelLogger__relayed'): wasRelayed = True elif 'label' in msg.server_tags: label = msg.server_tags['label'] if label in self._emitted_relayed_msgs: del self._emitted_relayed_msgs[label] wasRelayed = True else: wasRelayed = False else: wasRelayed = False if rewriteRelayed and wasRelayed: (nick, text) = text.split(' ', 1) nick = nick[1:-1] msg.args = (recipients, text) if (noLogPrefix and text.startswith(noLogPrefix)) or \ not logChannelMessages: text = '-= THIS MESSAGE NOT LOGGED =-' if ircmsgs.isAction(msg): self.doLog(irc, channel, '* %s %s\n', nick, ircmsgs.unAction(msg)) else: self.doLog(irc, channel, '<%s> %s\n', nick, text)
def learn(self, irc, msg, args, channel, key, factoid): db = self.getDb(channel) cursor = db.cursor() cursor.execute("SELECT id, locked FROM keys WHERE key LIKE %s", key) if cursor.rowcount == 0: cursor.execute("""INSERT INTO keys VALUES (NULL, %s, 0)""", key) db.commit() cursor.execute("SELECT id, locked FROM keys WHERE key LIKE %s",key) (id, locked) = map(int, cursor.fetchone()) capability = ircdb.makeChannelCapability(channel, 'factoids') if not locked: if ircdb.users.hasUser(msg.prefix): name = ircdb.users.getUser(msg.prefix).name else: name = msg.nick cursor.execute("""INSERT INTO factoids VALUES (NULL, %s, %s, %s, %s)""", id, name, int(time.time()), factoid) db.commit() irc.replySuccess() else: irc.error('That factoid is locked.')
def _checkManageCapabilities(self, irc, msg, channel): """Check if the user has any of the required capabilities to manage the channel topic. The list of required capabilities is in requireManageCapability channel config. Also allow if the user is a chanop. Since he can change the topic manually anyway. """ c = irc.state.channels[channel] if msg.nick in c.ops or msg.nick in c.halfops or 't' not in c.modes: return True capabilities = self.registryValue('requireManageCapability') if capabilities: for capability in re.split(r'\s*;\s*', capabilities): if capability.startswith('channel,'): capability = ircdb.makeChannelCapability(channel, capability[8:]) if capability and ircdb.checkCapability(msg.prefix, capability): return True return False else: return True
def voice(self, irc, msg, args, channel, nicks): """[<channel>] [<nick> ...] If you have the #channel,voice capability, this will voice all the <nick>s you provide. If you don't provide any <nick>s, this will voice you. <channel> is only necessary if the message isn't sent in the channel itself. """ if nicks: if len(nicks) == 1 and msg.nick in nicks: capability = 'voice' else: capability = 'op' else: nicks = [msg.nick] capability = 'voice' capability = ircdb.makeChannelCapability(channel, capability) if ircdb.checkCapability(msg.prefix, capability): def f(L): return ircmsgs.voices(channel, L) self._sendMsgs(irc, nicks, f) else: irc.errorNoCapability(capability)
def remove(self, irc, msg, args, channel, user, capabilities): """[<channel>] <name|hostmask> <capability> [<capability> ...] If you have the #channel,op capability, this will take from the user currently identified as <name> (or the user to whom <hostmask> maps) the capability <capability> in the channel. <channel> is only necessary if the message isn't sent in the channel itself. """ fail = [] for c in capabilities.split(): cap = ircdb.makeChannelCapability(channel, c) try: user.removeCapability(cap) except KeyError: fail.append(c) ircdb.users.setUser(user) if fail: s = 'capability' if len(fail) > 1: s = utils.str.pluralize(s) irc.error(format(_('That user didn\'t have the %L %s.'), fail, s), Raise=True) irc.replySuccess()
def do(type): cap = ircdb.makeChannelCapability(channel, type) try: if ircdb.checkCapability(msg.prefix, cap, ignoreOwner=not self.registryValue('owner')): if self.registryValue(type, channel): self.log.info('Scheduling auto-%s of %s in %s.', type, msg.prefix, channel) def dismiss(): """Determines whether or not a mode has already been applied.""" l = getattr(irc.state.channels[channel], type+'s') return (msg.nick in l) msgmaker = getattr(ircmsgs, type) schedule_msg(msgmaker(channel, msg.nick), dismiss) raise Continue # Even if fallthrough, let's only do one. elif not fallthrough: self.log.debug('%s has %s, but supybot.plugins.AutoMode.%s' ' is not enabled in %s, refusing to fall ' 'through.', msg.prefix, cap, type, channel) raise Continue except KeyError: pass
def learn(self, irc, msg, args, channel, key, factoid): db = self.getDb(channel) cursor = db.cursor() cursor.execute("SELECT id, locked FROM keys WHERE key LIKE ?", (key, )) row = cursor.fetchone() if row is None: cursor.execute("""INSERT INTO keys VALUES (NULL, ?, 0)""", (key, )) db.commit() cursor.execute("SELECT id, locked FROM keys WHERE key LIKE ?", (key, )) row = cursor.fetchone() (id, locked) = map(int, row) capability = ircdb.makeChannelCapability(channel, 'factoids') if not locked: if ircdb.users.hasUser(msg.prefix): name = ircdb.users.getUser(msg.prefix).name else: name = msg.nick cursor.execute("""INSERT INTO factoids VALUES (NULL, ?, ?, ?, ?)""", (id, unicode(name), int(time.time()), unicode(factoid))) db.commit() irc.replySuccess() else: irc.error('That factoid is locked.')
def newpoll(self, irc, msg, args, channel, interval, answers, question): """<number of minutes for announce interval> <"answer,answer,..."> question Creates a new poll with the given question and answers. <channel> is only necessary if the message isn't sent in the channel itself.""" capability = ircdb.makeChannelCapability(channel, 'op') if not ircdb.checkCapability(msg.prefix, capability): irc.error('Need ops') return db = self.getDb(channel) cursor = db.cursor() self._execute_query(cursor, 'INSERT INTO polls VALUES (?,?,?,?,?)', None, datetime.datetime.now(), 1, None, question) pollid = cursor.lastrowid # used to add choices into db. each choice represented by character, starting at capital A (code 65) def genAnswers(): for i, answer in enumerate(answers, start=65): yield pollid, chr(i), answer cursor.executemany('INSERT INTO choices VALUES (?,?,?)', genAnswers()) db.commit() irc.reply('Started new poll #%s' % pollid) # function called by schedule event. can not have args def runPoll(): self._runPoll(irc, channel, pollid) # start schedule. will announce poll/choices to channel at interval schedule.addPeriodicEvent(runPoll, interval * 60, name='%s_poll_%s' % (channel, pollid)) self.poll_schedules.append('%s_poll_%s' % (channel, pollid))
def doPrivmsg(self, irc, msg): (recipients, text) = msg.args for channel in recipients.split(','): if irc.isChannel(channel): noLogPrefix = self.registryValue('noLogPrefix', channel) cap = ircdb.makeChannelCapability(channel, 'logChannelMessages') try: logChannelMessages = ircdb.checkCapability(msg.prefix, cap, ignoreOwner=True) except KeyError: logChannelMessages = True nick = msg.nick or irc.nick if msg.tagged('ChannelLogger__relayed'): (nick, text) = text.split(' ', 1) nick = nick[1:-1] msg.args = (recipients, text) if (noLogPrefix and text.startswith(noLogPrefix)) or \ not logChannelMessages: text = '-= THIS MESSAGE NOT LOGGED =-' if ircmsgs.isAction(msg): self.doLog(irc, channel, '* %s %s\n', nick, ircmsgs.unAction(msg)) else: self.doLog(irc, channel, '<%s> %s\n', nick, text)
def chanban(self, irc, msg, args, channel, optlist, bannedHostmask, expiry, reason): """[<channel>] [--{exact,nick,user,host}] <hostmask> [<seconds>] [<reason>] If you have the #channel,op capability, this will ban <hostmask> for as many seconds as you specify, or else (if you specify 0 seconds or don't specify a number of seconds) it will ban the person indefinitely. --exact bans only the exact hostmask; --nick bans just the nick; --user bans just the user, and --host bans just the host. You can combine these options as you choose. <reason> is a reason to give for the kick. <channel> is only necessary if the message isn't sent in the channel itself. """ # Check that they're not trying to make us kickban ourself. self.log.debug('In chanban') if not reason: reason = msg.nick capability = ircdb.makeChannelCapability(channel, 'op') def makeBanmask(bannedHostmask, options): (nick, user, host) = ircutils.splitHostmask(bannedHostmask) self.log.debug('*** nick: %s', nick) self.log.debug('*** user: %s', user) self.log.debug('*** host: %s', host) bnick = '*' buser = '******' bhost = '*' for option in options: if option == 'nick': bnick = nick elif option == 'user': buser = user elif option == 'host': bhost = host elif option == 'exact': (bnick, buser, bhost) = \ ircutils.splitHostmask(bannedHostmask) return ircutils.joinHostmask(bnick, buser, bhost) if optlist: banmask = makeBanmask(bannedHostmask, [o[0] for o in optlist]) else: banmask = makeBanmask(bannedHostmask, self.registryValue('banmask', channel)) # Check (again) that they're not trying to make us kickban ourself. if ircutils.hostmaskPatternEqual(banmask, irc.prefix): if ircutils.hostmaskPatternEqual(banmask, irc.prefix): self.log.warning('%q tried to make me chanban myself.', msg.prefix) irc.error('I cowardly refuse to chanban myself.') return else: banmask = bannedHostmask # Now, let's actually get to it. Check to make sure they have # #channel,op and the bannee doesn't have #channel,op; or that the # bannee and the banner are both the same person. def doBan(): irc.queueMsg(ircmsgs.ban(channel, banmask)) if expiry > 0: def f(): if channel in irc.state.channels and \ banmask in irc.state.channels[channel].bans: irc.queueMsg(ircmsgs.unban(channel, banmask)) schedule.addEvent(f, expiry) if ircdb.checkCapability(msg.prefix, capability): if ircdb.checkCapability(bannedHostmask, capability): self.log.warning('%s tried to ban %q, but both have %s', msg.prefix, bannedHostmask, capability) irc.error( format('%s has %s too, you can\'t ban him/her/it.', bannedHostmask, capability)) else: doBan() else: self.log.warning('%q attempted chanban without %s', msg.prefix, capability) irc.errorNoCapability(capability) exact, nick, user, host
class CheckCapabilityTestCase(IrcdbTestCase): filename = os.path.join(conf.supybot.directories.conf(), 'CheckCapabilityTestCase.conf') owner = 'owner!owner@owner' nothing = 'nothing!nothing@nothing' justfoo = 'justfoo!justfoo@justfoo' antifoo = 'antifoo!antifoo@antifoo' justchanfoo = 'justchanfoo!justchanfoo@justchanfoo' antichanfoo = 'antichanfoo!antichanfoo@antichanfoo' securefoo = 'securefoo!securefoo@securefoo' channel = '#channel' cap = 'foo' anticap = ircdb.makeAntiCapability(cap) chancap = ircdb.makeChannelCapability(channel, cap) antichancap = ircdb.makeAntiCapability(chancap) chanop = ircdb.makeChannelCapability(channel, 'op') channelnothing = ircdb.IrcChannel() channelcap = ircdb.IrcChannel() channelcap.addCapability(cap) channelanticap = ircdb.IrcChannel() channelanticap.addCapability(anticap) def setUp(self): IrcdbTestCase.setUp(self) try: os.remove(self.filename) except: pass self.users = ircdb.UsersDictionary() #self.users.open(self.filename) self.channels = ircdb.ChannelsDictionary() #self.channels.open(self.filename) owner = self.users.newUser() owner.name = 'owner' owner.addCapability('owner') owner.addHostmask(self.owner) self.users.setUser(owner) nothing = self.users.newUser() nothing.name = 'nothing' nothing.addHostmask(self.nothing) self.users.setUser(nothing) justfoo = self.users.newUser() justfoo.name = 'justfoo' justfoo.addCapability(self.cap) justfoo.addHostmask(self.justfoo) self.users.setUser(justfoo) antifoo = self.users.newUser() antifoo.name = 'antifoo' antifoo.addCapability(self.anticap) antifoo.addHostmask(self.antifoo) self.users.setUser(antifoo) justchanfoo = self.users.newUser() justchanfoo.name = 'justchanfoo' justchanfoo.addCapability(self.chancap) justchanfoo.addHostmask(self.justchanfoo) self.users.setUser(justchanfoo) antichanfoo = self.users.newUser() antichanfoo.name = 'antichanfoo' antichanfoo.addCapability(self.antichancap) antichanfoo.addHostmask(self.antichanfoo) self.users.setUser(antichanfoo) securefoo = self.users.newUser() securefoo.name = 'securefoo' securefoo.addCapability(self.cap) securefoo.secure = True securefoo.addHostmask(self.securefoo) self.users.setUser(securefoo) channel = ircdb.IrcChannel() self.channels.setChannel(self.channel, channel) def checkCapability(self, hostmask, capability): return ircdb.checkCapability(hostmask, capability, self.users, self.channels) def testOwner(self): self.assertTrue(self.checkCapability(self.owner, self.cap)) self.assertFalse(self.checkCapability(self.owner, self.anticap)) self.assertTrue(self.checkCapability(self.owner, self.chancap)) self.assertFalse(self.checkCapability(self.owner, self.antichancap)) self.channels.setChannel(self.channel, self.channelanticap) self.assertTrue(self.checkCapability(self.owner, self.cap)) self.assertFalse(self.checkCapability(self.owner, self.anticap)) def testNothingAgainstChannel(self): self.channels.setChannel(self.channel, self.channelnothing) self.assertEqual(self.checkCapability(self.nothing, self.chancap), self.channelnothing.defaultAllow) self.channelnothing.defaultAllow = not self.channelnothing.defaultAllow self.channels.setChannel(self.channel, self.channelnothing) self.assertEqual(self.checkCapability(self.nothing, self.chancap), self.channelnothing.defaultAllow) self.channels.setChannel(self.channel, self.channelcap) self.assertTrue(self.checkCapability(self.nothing, self.chancap)) self.assertFalse(self.checkCapability(self.nothing, self.antichancap)) self.channels.setChannel(self.channel, self.channelanticap) self.assertFalse(self.checkCapability(self.nothing, self.chancap)) self.assertTrue(self.checkCapability(self.nothing, self.antichancap)) def testNothing(self): self.assertEqual(self.checkCapability(self.nothing, self.cap), conf.supybot.capabilities.default()) self.assertEqual(self.checkCapability(self.nothing, self.anticap), not conf.supybot.capabilities.default()) def testJustFoo(self): self.assertTrue(self.checkCapability(self.justfoo, self.cap)) self.assertFalse(self.checkCapability(self.justfoo, self.anticap)) def testAntiFoo(self): self.assertTrue(self.checkCapability(self.antifoo, self.anticap)) self.assertFalse(self.checkCapability(self.antifoo, self.cap)) def testJustChanFoo(self): self.channels.setChannel(self.channel, self.channelnothing) self.assertTrue(self.checkCapability(self.justchanfoo, self.chancap)) self.assertFalse( self.checkCapability(self.justchanfoo, self.antichancap)) self.channelnothing.defaultAllow = not self.channelnothing.defaultAllow self.assertTrue(self.checkCapability(self.justchanfoo, self.chancap)) self.assertFalse( self.checkCapability(self.justchanfoo, self.antichancap)) self.channels.setChannel(self.channel, self.channelanticap) self.assertTrue(self.checkCapability(self.justchanfoo, self.chancap)) self.assertFalse( self.checkCapability(self.justchanfoo, self.antichancap)) def testChanOpCountsAsEverything(self): self.channels.setChannel(self.channel, self.channelanticap) id = self.users.getUserId('nothing') u = self.users.getUser(id) u.addCapability(self.chanop) self.users.setUser(u) self.assertTrue(self.checkCapability(self.nothing, self.chancap)) self.channels.setChannel(self.channel, self.channelnothing) self.assertTrue(self.checkCapability(self.nothing, self.chancap)) self.channelnothing.defaultAllow = not self.channelnothing.defaultAllow self.assertTrue(self.checkCapability(self.nothing, self.chancap)) def testAntiChanFoo(self): self.channels.setChannel(self.channel, self.channelnothing) self.assertFalse(self.checkCapability(self.antichanfoo, self.chancap)) self.assertTrue( self.checkCapability(self.antichanfoo, self.antichancap)) def testSecurefoo(self): self.assertTrue(self.checkCapability(self.securefoo, self.cap)) id = self.users.getUserId(self.securefoo) u = self.users.getUser(id) u.addAuth(self.securefoo) self.users.setUser(u) try: originalConfDefaultAllow = conf.supybot.capabilities.default() conf.supybot.capabilities.default.set('False') self.assertFalse( self.checkCapability('a' + self.securefoo, self.cap)) finally: conf.supybot.capabilities.default.set( str(originalConfDefaultAllow))
def testMakeChannelCapability(self): self.assertEqual(ircdb.makeChannelCapability('#f', 'b'), '#f,b') self.assertEqual(ircdb.makeChannelCapability('#f', '-b'), '#f,-b')
def kban(self, irc, msg, args, channel, optlist, bannedNick, expiry, reason): """[<channel>] [--{exact,nick,user,host}] <nick> [<seconds>] [<reason>] If you have the #channel,op capability, this will kickban <nick> for as many seconds as you specify, or else (if you specify 0 seconds or don't specify a number of seconds) it will ban the person indefinitely. --exact bans only the exact hostmask; --nick bans just the nick; --user bans just the user, and --host bans just the host. You can combine these options as you choose. <reason> is a reason to give for the kick. <channel> is only necessary if the message isn't sent in the channel itself. """ # Check that they're not trying to make us kickban ourself. if not irc.isNick(bannedNick): self.log.warning('%q tried to kban a non nick: %q', msg.prefix, bannedNick) raise callbacks.ArgumentError elif bannedNick == irc.nick: self.log.warning('%q tried to make me kban myself.', msg.prefix) irc.error(_('I cowardly refuse to kickban myself.')) return if not reason: reason = msg.nick try: bannedHostmask = irc.state.nickToHostmask(bannedNick) except KeyError: irc.error(format(_('I haven\'t seen %s.'), bannedNick), Raise=True) capability = ircdb.makeChannelCapability(channel, 'op') banmaskstyle = conf.supybot.protocols.irc.banmask banmask = banmaskstyle.makeBanmask(bannedHostmask, [o[0] for o in optlist]) # Check (again) that they're not trying to make us kickban ourself. if ircutils.hostmaskPatternEqual(banmask, irc.prefix): if ircutils.hostmaskPatternEqual(bannedHostmask, irc.prefix): self.log.warning('%q tried to make me kban myself.', msg.prefix) irc.error(_('I cowardly refuse to ban myself.')) return else: self.log.warning('Using exact hostmask since banmask would ' 'ban myself.') banmask = bannedHostmask # Now, let's actually get to it. Check to make sure they have # #channel,op and the bannee doesn't have #channel,op; or that the # bannee and the banner are both the same person. def doBan(): if irc.state.channels[channel].isOp(bannedNick): irc.queueMsg(ircmsgs.deop(channel, bannedNick)) irc.queueMsg(ircmsgs.ban(channel, banmask)) irc.queueMsg(ircmsgs.kick(channel, bannedNick, reason)) if expiry > 0: def f(): if channel in irc.state.channels and \ banmask in irc.state.channels[channel].bans: irc.queueMsg(ircmsgs.unban(channel, banmask)) schedule.addEvent(f, expiry) if bannedNick == msg.nick: doBan() elif ircdb.checkCapability(msg.prefix, capability): if ircdb.checkCapability(bannedHostmask, capability) and \ not ircdb.checkCapability(msg.prefix, 'owner'): self.log.warning('%s tried to ban %q, but both have %s', msg.prefix, bannedHostmask, capability) irc.error( format(_('%s has %s too, you can\'t ban ' 'him/her/it.'), bannedNick, capability)) else: doBan() else: self.log.warning('%q attempted kban without %s', msg.prefix, capability) irc.errorNoCapability(capability) exact, nick, user, host
def _ban(self, irc, msg, args, channel, optlist, target, expiry, reason, kick): # Check that they're not trying to make us kickban ourself. if irc.isNick(target): bannedNick = target try: bannedHostmask = irc.state.nickToHostmask(target) banmaskstyle = conf.supybot.protocols.irc.banmask banmask = banmaskstyle.makeBanmask(bannedHostmask, [o[0] for o in optlist]) except KeyError: if not conf.supybot.protocols.irc.strictRfc() and \ target.startswith('$'): # Select the last part, or the whole target: bannedNick = target.split(':')[-1] banmask = bannedHostmask = target else: irc.error(format(_('I haven\'t seen %s.'), bannedNick), Raise=True) else: bannedNick = ircutils.nickFromHostmask(target) banmask = bannedHostmask = target if not irc.isNick(bannedNick): self.log.warning('%q tried to kban a non nick: %q', msg.prefix, bannedNick) raise callbacks.ArgumentError elif bannedNick == irc.nick: self.log.warning('%q tried to make me kban myself.', msg.prefix) irc.error(_('I cowardly refuse to kickban myself.')) return if not reason: reason = msg.nick capability = ircdb.makeChannelCapability(channel, 'op') # Check (again) that they're not trying to make us kickban ourself. if ircutils.hostmaskPatternEqual(banmask, irc.prefix): if ircutils.hostmaskPatternEqual(bannedHostmask, irc.prefix): self.log.warning('%q tried to make me kban myself.',msg.prefix) irc.error(_('I cowardly refuse to ban myself.')) return else: self.log.warning('Using exact hostmask since banmask would ' 'ban myself.') banmask = bannedHostmask # Now, let's actually get to it. Check to make sure they have # #channel,op and the bannee doesn't have #channel,op; or that the # bannee and the banner are both the same person. def doBan(): if irc.state.channels[channel].isOp(bannedNick): irc.queueMsg(ircmsgs.deop(channel, bannedNick)) irc.queueMsg(ircmsgs.ban(channel, banmask)) if kick: irc.queueMsg(ircmsgs.kick(channel, bannedNick, reason)) if expiry > 0: def f(): if channel in irc.state.channels and \ banmask in irc.state.channels[channel].bans: irc.queueMsg(ircmsgs.unban(channel, banmask)) schedule.addEvent(f, expiry) if bannedNick == msg.nick: doBan() elif ircdb.checkCapability(msg.prefix, capability): if ircdb.checkCapability(bannedHostmask, capability) and \ not ircdb.checkCapability(msg.prefix, 'owner'): self.log.warning('%s tried to ban %q, but both have %s', msg.prefix, bannedHostmask, capability) irc.error(format(_('%s has %s too, you can\'t ban ' 'them.'), bannedNick, capability)) else: doBan() else: self.log.warning('%q attempted kban without %s', msg.prefix, capability) irc.errorNoCapability(capability)