def testAddressedWithMultipleNicks(self): msg = ircmsgs.privmsg("#foo", "bar: baz") self.assertEqual(callbacks.addressed("bar", msg), "baz") # need to recreate the msg objects since the old ones have already # been tagged msg = ircmsgs.privmsg("#foo", "bar: baz") self.assertEqual(callbacks.addressed("biff", msg, nicks=["bar"]), "baz")
def testAddressedWithMultipleNicks(self): msg = ircmsgs.privmsg('#foo', 'bar: baz') self.assertEqual(callbacks.addressed('bar', msg), 'baz') # need to recreate the msg objects since the old ones have already # been tagged msg = ircmsgs.privmsg('#foo', 'bar: baz') self.assertEqual(callbacks.addressed('biff', msg, nicks=['bar']), 'baz')
def doPrivmsg(self, irc, msg): (channel, text) = msg.args if (callbacks.addressed(irc.nick, msg) or ircmsgs.isCtcp(msg) or not irc.isChannel(channel) or not (None == re.match( self.registryValue('ignoreRegex'), text))): # Was the message a CTCP command, a command to the bot, is this message supposed to be ignored, or are we not in a channel?? self.log.debug( "The method 'callbacks.addressed(irc.nick, msg)' returns {0}!". format(True == callbacks.addressed(irc.nick, msg))) self.log.debug( "The method 'ircmsgs.isCtcp(msg)' returns {0}!".format( True == ircmsgs.isCtcp(msg))) self.log.debug( "The method 'irc.isChannel(channel)' returns {0}!".format( False == irc.isChannel(channel))) self.log.debug( "The method 're.match(self.registryValue('ignoreRegex'), text)' returns {0}!" .format(False == (None == re.match( self.registryValue('ignoreRegex'), text)))) return if ircmsgs.isAction(msg): # If the message was an action...we'll learn it anyways! text = ircmsgs.unAction(msg) if self.registryValue('stripUrls'): # strip URLs text = re.sub(r'(http[^\s]*)', '', text) # strip › text = re.sub(r'›', '', text) if irc.nick.lower() in text.lower(): # Were we addressed in the channel? probability = self.registryValue('probabilityWhenAddressed', channel) else: # Okay, we were not addressed, but what's the probability we should reply? probability = self.registryValue('probability', channel) #if self.registryValue('stripNicks'): # removenicks = '|'.join(item + '\W.*?\s' for item in irc.state.channels[channel].users) # text = re.sub(r'' + removenicks + '', 'MAGIC_NICK', text) self._learn(irc, msg, channel, text, probability) # Now we can pass this to our learn function!
def doPrivmsg(self, irc, msg): if (irc.isChannel(msg.args[0])): channel = plugins.getChannel(msg.args[0]) canSpeak = False now = time.time() throttle = self.registryValue('randomSpeaking.throttleTime', channel) prob = self.registryValue('randomSpeaking.probability', channel) delay = self.registryValue('randomSpeaking.maxDelay', channel) irc = callbacks.SimpleProxy(irc, msg) if now > self.lastSpoke + throttle: canSpeak = True if canSpeak and random.random() < prob: #f = self._markov(channel, irc, prefixNick=False, to=channel, Random=True) reply = self.db.buildReply(channel, None) if (reply is None): return irc.reply(reply, prefixNick=False, to=channel) #self._markov(channel, irc, prefixNick=False, to=channel, Random=True) #schedule.addEvent(lambda: self.q.enqueue(f), now+delay) self.lastSpoke = now + delay words = self.tokenize(msg) if not words or len(words) == 3: return if (self.registryValue('ignoreBotCommands', channel) and callbacks.addressed(irc.nick, msg)): return self.db.addPair(channel, None, words[0]) self.db.addPair(channel, words[-1], None) for (first, second) in utils.seq.window(words, 2): self.db.addPair(channel, first, second)
def titleSnarfer(self, irc, msg, match): channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return if self.registryValue('titleSnarfer', channel): url = match.group(0) if not self._checkURLWhitelist(url): return r = self.registryValue('nonSnarfingRegexp', channel) if r and r.search(url): self.log.debug('Not titleSnarfing %q.', url) return r = self.getTitle(irc, url, False) if not r: return (target, title) = r if title: domain = utils.web.getDomain(target if self.registryValue( 'snarferShowTargetDomain', channel) else url) prefix = self.registryValue('snarferPrefix', channel) s = "%s %s" % (prefix, title) if self.registryValue('snarferShowDomain', channel): s += format(_(' (at %s)'), domain) irc.reply(s, prefixNick=False) if self.registryValue('snarfMultipleUrls', channel): # FIXME: hack msg.tag('repliedTo', False)
def doPrivmsg(self, irc, msg): assert self is irc.callbacks[0], \ 'Owner isn\'t first callback: %r' % irc.callbacks if ircmsgs.isCtcp(msg): return s = callbacks.addressed(irc.nick, msg) if s: ignored = ircdb.checkIgnored(msg.prefix) if ignored: self.log.info('Ignoring command from %s.', msg.prefix) return maximum = conf.supybot.abuse.flood.command.maximum() self.commands.enqueue(msg) if conf.supybot.abuse.flood.command() \ and self.commands.len(msg) > maximum \ and not ircdb.checkCapability(msg.prefix, 'trusted'): punishment = conf.supybot.abuse.flood.command.punishment() banmask = ircutils.banmask(msg.prefix) self.log.info('Ignoring %s for %s seconds due to an apparent ' 'command flood.', banmask, punishment) ircdb.ignores.add(banmask, time.time() + punishment) irc.reply('You\'ve given me %s commands within the last ' 'minute; I\'m now ignoring you for %s.' % (maximum, utils.timeElapsed(punishment, seconds=False))) return try: tokens = callbacks.tokenize(s, channel=msg.args[0]) self.Proxy(irc, msg, tokens) except SyntaxError, e: irc.queueMsg(callbacks.error(msg, str(e)))
def doPrivmsg(self, irc, msg): channel = msg.args[0].lower() text = msg.args[1].strip() # ignore ctcp, action and only messages in a channel. # if txt.startswith(conf.supybot.reply.whenAddressedBy.chars()): if ircmsgs.isCtcp(msg) or ircmsgs.isAction(msg) or not irc.isChannel(channel): return # on to the text. check if we're ignoring the text matching regex here. if re.match(self.registryValue('ignoreRegex'), text): return # should we strip urls from text? if self.registryValue('stripUrls'): text = re.sub(r'(http[^\s]*)', '', text) # determine probability if addressed or not. if callbacks.addressed(irc.nick, msg): text = re.sub('(' + irc.nick + '*?\W+)', '', text, re.IGNORECASE) probability = self.registryValue('probabilityWhenAddressed', channel) else: probability = self.registryValue('probability', channel) # should we strip nicks from the text? if self.registryValue('stripNicks'): removenicks = '|'.join(item + '\W.*?\s' for item in irc.stats.channels[channel].users) text = re.sub(r'' + removenicks + '', '', text) # finally, pass to our learn function. self._learn(irc, channel, text, probability)
def testAddressedPrefixCharsTakePrecedenceOverNickAtEnd(self): msg = ircmsgs.privmsg('#foo', '@echo foo') self.assertEqual( callbacks.addressed('foo', msg, whenAddressedByNickAtEnd=True, prefixChars='@'), 'echo foo')
def doPrivmsg(self, irc, msg): if irc.isChannel(msg.args[0]): channel = plugins.getChannel(msg.args[0]) canSpeak = False now = time.time() throttle = self.registryValue('randomSpeaking.throttleTime', channel) prob = self.registryValue('randomSpeaking.probability', channel) delay = self.registryValue('randomSpeaking.maxDelay', channel) irc = callbacks.SimpleProxy(irc, msg) if now > self.lastSpoke + throttle: canSpeak = True if canSpeak and random.random() < prob: f = self._markov(channel, irc, prefixNick=False, to=channel, Random=True) schedule.addEvent(lambda: self.q.enqueue(f), now + delay) self.lastSpoke = now + delay words = self.tokenize(msg) words.insert(0, '\n') words.insert(0, '\n') words.append('\n') # This shouldn't happen often (CTCP messages being the possible exception) if not words or len(words) == 3: return if self.registryValue('ignoreBotCommands', channel) and \ callbacks.addressed(irc.nick, msg): return def doPrivmsg(db): for (first, second, follower) in utils.seq.window(words, 3): db.addPair(channel, first, second, follower) self.q.enqueue(doPrivmsg)
def sendToOthers(self, irc, triggerMsg, s): channel = triggerMsg.args[0] nick = triggerMsg.nick for relay in self.relays: if relay.channelRegex.match(channel) and relay.networkRegex.match(irc.network) and (len(triggerMsg.args[1] < 1 or relay.messageRegex.search(triggerMsg.args[1]))): if not relay.hasIRC: self.log.info('LinkRelay: IRC %s not yet scraped.' % relay.targetNetwork) elif relay.targetIRC.zombie: self.log.info('LinkRelay: IRC %s appears to be a zombie' % relay.targetNetwork) elif relay.targetChannel not in relay.targetIRC.state.channels: self.log.info('LinkRelay: I\'m not in in %s on %s' % (relay.targetChannel, relay.targetNetwork)) else: # if re.match('\x0314\w+ has quit on \w+ \(.*\)', s): # pm = False # else: # pm = True # for chan in irc.state.channels: # if re.match('^%s$' % relay.sourceChannel, chan): # pm = False if triggerMsg.args[0] not in irc.state.channels and not re.match('\x0314\w+ has quit on \w+ \(.*\)', s): # cuts off the end of commands, so that passwords won't be revealed in relayed PM's if callbacks.addressed(irc.nick, triggerMsg): s = re.sub('(>\x03 \w+) .*', '\\1 \x0314[truncated]', s) s = '(via PM) %s' % s msg = ircmsgs.privmsg(relay.targetChannel, s) msg.tag('relayedMsg') relay.targetIRC.sendMsg(msg)
def getName(self, nick, msg, match): addressed = callbacks.addressed(nick, msg) name = callbacks.addressed(nick, ircmsgs.IrcMsg(prefix="", args=(msg.args[0], match.group(1)), msg=msg)) if not name: name = match.group(1) if not addressed: if not self.registryValue("allowUnaddressedKarma"): return "" if not msg.args[1].startswith(match.group(1)): return "" name = match.group(1) elif addressed: if not addressed.startswith(name): return "" name = name.strip("()") return name
def doPrivmsg(self, irc, msg): if not world.testing and msg.args[0] not in ("#BMN"): return if callbacks.addressed(irc.nick, msg): return # Internal match = self._addressed.match(msg.args[1]) if match is None: prefix = "" else: prefix = match.group(1) + ": " def reply(string): irc.reply(prefix + string, prefixNick=False) # Factoids matches = self._factoid.findall(msg.args[1]) for name in matches: arg = None match = self._dynamicFactoid.match(name) if match is not None: name = match.group("name") arg = match.group("arg") name = name.lower() if arg is None: if name in staticFactoids: reply(staticFactoids[name]) else: if name in dynamicFactoids: reply(dynamicFactoids[name] % arg)
def doPrivmsg(self, irc, msg): if callbacks.addressed(irc, msg): return snarfChannel = self.registryValue('snarfChannel') if not msg.channel == snarfChannel: return """ log.error(msg.channel) log.error(msg.nick) log.error(msg.args[1]) log.error(self.registryValue('snarfRegex')) log.error(re.search(self.registryValue('snarfRegex'), msg.args[1])) """ x = re.search(self.registryValue('snarfRegex'), msg.args[1]) if x: jira = JIRA(self.server) try: issue = jira.issue(x.group(0)) recentDate = issue.fields.created splitdate = recentDate.split('T') replytext = ( "\x1F\x02\x034{0}\x0F\x03 \x02\x036[{1}] \x03\"{2}\" \x0Freported by \x02\x033{3}\x03\x0F at \x02{4}\x0F. Status: \x1F\x02{5}\x0F" .format(issue.key, issue.fields.issuetype, issue.fields.summary.strip(), issue.fields.creator, splitdate[0], issue.fields.status)) # .strip() to get rid of accidential added leading or trailing whitespaces in issue summary irc.reply(replytext, prefixNick=False) except: replytext = ( "Detected regex match for Armbian issue: \x1F\x02\x034{0}\x0F\x03. Could not find it on Jira though. :-(" .format(x.group(0))) irc.reply(replytext, prefixNick=False) return
def doPrivmsg(self, irc, msg): channel = msg.args[0] if not irc.isChannel(channel): return if self.registryValue('enable', channel): if callbacks.addressed(irc.nick, msg): #message is direct command return actions = [] results = [] for channel in (channel, 'global'): db = self.getDb(channel) cursor = db.cursor() cursor.execute("SELECT regexp, action FROM triggers") # Fetch results and prepend channel name or 'global'. This # prevents duplicating the following lines. results.extend(map(lambda x: (channel,)+x, cursor.fetchall())) if len(results) == 0: return for (channel, regexp, action) in results: for match in re.finditer(regexp, msg.args[1]): if match is not None: thisaction = action self._updateRank(channel, regexp) for (i, j) in enumerate(match.groups()): thisaction = re.sub(r'\$' + str(i+1), match.group(i+1), thisaction) actions.append(thisaction) for action in actions: self._runCommandFunction(irc, msg, action)
def doPrivmsg(self, irc, msg): channel = msg.args[0] if not irc.isChannel(channel): return if self.registryValue('enable', channel): if callbacks.addressed(irc.nick, msg): #message is direct command return actions = [] db = self.getDb(channel) cursor = db.cursor() cursor.execute("SELECT regexp, action FROM triggers") results = cursor.fetchall() if len(results) == 0: return for (regexp, action) in results: for match in re.finditer(regexp, msg.args[1]): if match is not None: thisaction = action self._updateRank(channel, regexp) for (i, j) in enumerate(match.groups()): thisaction = re.sub(r'\$' + str(i+1), match.group(i+1), thisaction) actions.append(thisaction) for action in actions: self._runCommandFunction(irc, msg, action)
def testAddressedReplyWhenNotAddressed(self): msg1 = ircmsgs.privmsg('#foo', '@bar') msg2 = ircmsgs.privmsg('#foo', 'bar') self.assertEqual(callbacks.addressed('blah', msg1), 'bar') self.assertEqual(callbacks.addressed('blah', msg2), '') try: original = conf.supybot.reply.whenNotAddressed() conf.supybot.reply.whenNotAddressed.setValue(True) # need to recreate the msg objects since the old ones have already # been tagged msg1 = ircmsgs.privmsg('#foo', '@bar') msg2 = ircmsgs.privmsg('#foo', 'bar') self.assertEqual(callbacks.addressed('blah', msg1), 'bar') self.assertEqual(callbacks.addressed('blah', msg2), 'bar') finally: conf.supybot.reply.whenNotAddressed.setValue(original)
def doPrivmsg(self, irc, msg): if not conf.supybot.defaultIgnore(): # Only do this when defaultIgnore is set return if chr(1) in msg.args[1]: return try: user = ircdb.users.getUser(msg.prefix) if user.checkHostmask(msg.prefix): return except: pass text = callbacks.addressed(irc.nick, msg) cmd = '' if not text or text != "login": if msg.args[1]: if ircutils.isChannel(msg.args[0]): if msg.args[1][0] == '@': cmd = msg.args[1][1:] else: if msg.args[1][0] == '@': cmd = msg.args[1][1:] else: cmd = msg.args[1] if cmd != "login": return else: return self.log.info("IRCLogin: Calling login for %s" % msg.prefix) self._callCommand(["login"], irc, msg, [])
def doPrivmsg(self, irc, msg): if callbacks.addressed(irc.nick, msg): #message is not direct command return channel = msg.args[0] if not self.registryValue('correct.enable', channel): return if not hasattr(self, '_re'): threading.Thread(target=self.fetch_dict).start() return occurences = self._re.findall(msg.args[1]) if not occurences: return unique_occurences = [] occurences_set = set() for occurence in occurences: if not occurence in self._dict and \ occurence.endswith('s') and occurence[0:-1] in self._dict: occurence = occurence[0:-1] if occurence not in occurences_set: unique_occurences.append(occurence) occurences_set.add(occurence) irc.reply(format('Utilise %L plutôt que %L.', ['« %s »' % self._dict[x] for x in unique_occurences], ['« %s »' % x for x in unique_occurences]) .replace(' and ', ' et ')) # fix i18n
def doPrivmsg(self, irc, msg): if irc.isChannel(msg.args[0]): speakChan = msg.args[0] dbChan = plugins.getChannel(speakChan) canSpeak = False now = time.time() throttle = self.registryValue('randomSpeaking.throttleTime', speakChan) prob = self.registryValue('randomSpeaking.probability', speakChan) delay = self.registryValue('randomSpeaking.maxDelay', speakChan) if now > self.lastSpoke + throttle: canSpeak = True if canSpeak and random.random() < prob: f = self._markov(speakChan, irc, prefixNick=False, to=speakChan, Random=True) schedule.addEvent(lambda: self.q.enqueue(f), now + delay) self.lastSpoke = now + delay words = self.tokenize(msg) # This shouldn't happen often (CTCP messages being the possible # exception) if not words: return if self.registryValue('ignoreBotCommands', speakChan) and \ callbacks.addressed(irc.nick, msg): return words.insert(0, None) words.insert(0, None) words.append(None) def doPrivmsg(db): for (first, second, follower) in utils.seq.window(words, 3): db.addPair(dbChan, first, second, follower, isFirst=(first is None and second is None), isLast=(follower is None)) self.q.enqueue(doPrivmsg)
def doPrivmsg(self, irc, msg): self.addIRC(irc) channel = msg.args[0] s = msg.args[1] s, args = self.getPrivmsgData(channel, msg.nick, s, self.registryValue('color', channel)) ignoreNicks = [ircutils.toLower(item) for item in \ self.registryValue('nickstoIgnore.nicks', msg.args[0])] if self.registryValue('nickstoIgnore.affectPrivmsgs', msg.args[0]) \ == 1 and ircutils.toLower(msg.nick) in ignoreNicks: #self.log.debug('LinkRelay: %s in nickstoIgnore...' % ircutils.toLower(msg.nick)) #self.log.debug('LinkRelay: List of ignored nicks: %s' % ignoreNicks) return elif channel not in irc.state.channels: # in private # cuts off the end of commands, so that passwords # won't be revealed in relayed PM's if callbacks.addressed(irc.nick, msg): if self.registryValue('color', channel): color = '\x03' + self.registryValue('colors.truncated', channel) match = '(>\017 \w+) .*' else: color = '' match = '(> \w+) .*' s = re.sub(match, '\\1 %s[%s]' % (color, _('truncated')), s) s = '(via PM) %s' % s self.sendToOthers(irc, channel, s, args, isPrivmsg=True)
def doPrivmsg(self, irc, msg): if (irc.isChannel(msg.args[0])): channel = plugins.getChannel(msg.args[0]) canSpeak = False now = time.time() throttle = self.registryValue('randomSpeaking.throttleTime', channel) prob = self.registryValue('randomSpeaking.probability', channel) delay = self.registryValue('randomSpeaking.maxDelay', channel) irc = callbacks.SimpleProxy(irc, msg) if now > self.lastSpoke + throttle: canSpeak = True if canSpeak and random.random() < prob: #f = self._markov(channel, irc, prefixNick=False, to=channel, Random=True) reply = self.db.buildReply(channel, None) if (reply is None): return irc.reply(reply, prefixNick=False, to=channel) #self._markov(channel, irc, prefixNick=False, to=channel, Random=True) #schedule.addEvent(lambda: self.q.enqueue(f), now+delay) self.lastSpoke = now+delay words = self.tokenize(msg) if not words or len(words) == 3: return if (self.registryValue('ignoreBotCommands', channel) and callbacks.addressed(irc.nick, msg)): return self.db.addPair(channel, None, words[0]) self.db.addPair(channel, words[-1], None) for (first, second) in utils.seq.window(words, 2): self.db.addPair(channel, first, second)
def doPrivmsg(self, irc, msg): assert self is irc.callbacks[0], \ 'Owner isn\'t first callback: %r' % irc.callbacks if ircmsgs.isCtcp(msg): return s = callbacks.addressed(irc.nick, msg) if s: ignored = ircdb.checkIgnored(msg.prefix) if ignored: self.log.info('Ignoring command from %s.', msg.prefix) return maximum = conf.supybot.abuse.flood.command.maximum() self.commands.enqueue(msg) if conf.supybot.abuse.flood.command() \ and self.commands.len(msg) > maximum \ and not ircdb.checkCapability(msg.prefix, 'trusted'): punishment = conf.supybot.abuse.flood.command.punishment() banmask = conf.supybot.protocols.irc.banmask \ .makeBanmask(msg.prefix) self.log.info('Ignoring %s for %s seconds due to an apparent ' 'command flood.', banmask, punishment) ircdb.ignores.add(banmask, time.time() + punishment) if conf.supybot.abuse.flood.command.notify(): irc.reply('You\'ve given me %s 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 try: tokens = callbacks.tokenize(s, channel=msg.args[0]) self.Proxy(irc, msg, tokens) except SyntaxError as e: irc.queueMsg(callbacks.error(msg, str(e)))
def titleSnarfer(self, irc, msg, match): r"https?://[^\])>\s]+" channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return if self.registryValue('titleSnarfer', channel): url = match.group(0) r = self.registryValue('nonSnarfingRegexp', channel) if r and r.search(url): self.log.debug('Not titleSnarfing %q.', url) return try: size = conf.supybot.protocols.http.peekSize() text = utils.web.getUrl(url, size=size) except utils.web.Error, e: self.log.info('Couldn\'t snarf title of %u: %s.', url, e) return parser = Title() try: parser.feed(text) except HTMLParser.HTMLParseError: self.log.debug('Encountered a problem parsing %u. Title may ' 'already be set, though', url) if parser.title: domain = utils.web.getDomain(url) title = utils.web.htmlToText(parser.title.strip()) s = format('Title: %s (at %s)', title, domain) irc.reply(s, prefixNick=False)
def doPrivmsg(self, irc, msg): if callbacks.addressed(irc.nick, msg): #message is not direct command return channel = msg.args[0] if not self.registryValue('correct.enable', channel): return if not hasattr(self, '_re'): threading.Thread(target=self.fetch_dict).start() return occurences = self._re.findall(msg.args[1]) if not occurences: return unique_occurences = [] occurences_set = set() for occurence in occurences: if not occurence in self._dict and \ occurence.endswith('s') and occurence[0:-1] in self._dict: occurence = occurence[0:-1] if occurence not in occurences_set: unique_occurences.append(occurence) occurences_set.add(occurence) irc.reply( format('Utilise %L plutôt que %L.', ['« %s »' % self._dict[x] for x in unique_occurences], ['« %s »' % x for x in unique_occurences]).replace(' and ', ' et ')) # fix i18n
def doPrivmsg(self, irc, msg): if callbacks.addressed(irc.nick, msg): #message is direct command return (channel, text) = msg.args if ircmsgs.isAction(msg): text = ircmsgs.unAction(msg) learn = self.registryValue('learn', channel) reply = self.registryValue('reply', channel) replyOnMention = self.registryValue('replyOnMention', channel) replyWhenSpokenTo = self.registryValue('replyWhenSpokenTo', channel) mention = irc.nick.lower() in text.lower() spokenTo = msg.args[1].lower().startswith('%s: ' % irc.nick.lower()) if replyWhenSpokenTo and spokenTo: reply = 100 text = text.replace('%s: ' % irc.nick, '') text = text.replace('%s: ' % irc.nick.lower(), '') if replyOnMention and mention: if not replyWhenSpokenTo and spokenTo: reply = 0 else: reply = 100 if randint(0, 99) < reply: self.reply(irc, msg, text) if learn: self.learn(irc, msg, text)
def doPrivmsg(self, irc, msg): if not world.testing and \ msg.args[0] not in ('#limnoria', '#limnoria-bots'): return if callbacks.addressed(irc.nick, msg): return # Internal match = self._addressed.match(msg.args[1]) if match is None: prefix = '' else: prefix = match.group(1) + ': ' def reply(string): irc.reply(prefix + string, prefixNick=False) # Factoids matches = self._factoid.findall(msg.args[1]) for name in matches: arg = None match = self._dynamicFactoid.match(name) if match is not None: name = match.group('name') arg = match.group('arg') name = name.lower() if arg is None: if name in staticFactoids: reply(staticFactoids[name]) else: if name in dynamicFactoids: reply(dynamicFactoids[name] % arg)
def doPrivmsg(self, irc, msg): (channel, message) = msg.args if callbacks.addressed(irc.nick, msg) or ircmsgs.isCtcp( msg) or not irc.isChannel(channel) or not self.registryValue( 'enable', channel): return if msg.nick.lower() in self.registryValue('ignoreNicks', channel): log.debug("Cobe: nick %s in ignoreNicks for %s" % (msg.nick, channel)) return if ircmsgs.isAction(msg): # If the message was an action...we'll learn it anyways! message = ircmsgs.unAction(msg) if irc.nick.lower() in message.lower(): # Were we addressed in the channel? probability = self.registryValue('probabilityWhenAddressed', channel) else: # Okay, we were not addressed, but what's the probability we should reply? probability = self.registryValue('probability', channel) #if self.registryValue('stripNicks'): # removenicks = '|'.join(item + '\W.*?\s' for item in irc.state.channels[channel].users) # text = re.sub(r'' + removenicks + '', 'MAGIC_NICK', text) self._learn(irc, msg, channel, message, probability) # Now we can pass this to our learn function!
def titleSnarfer(self, irc, msg, match): channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return if self.registryValue('titleSnarfer', channel): url = match.group(0) r = self.registryValue('nonSnarfingRegexp', channel) if r and r.search(url): self.log.debug('Not titleSnarfing %q.', url) return try: size = conf.supybot.protocols.http.peekSize() text = utils.web.getUrl(url, size=size) except utils.web.Error, e: self.log.info('Couldn\'t snarf title of %u: %s.', url, e) return parser = Title() try: parser.feed(text) except HTMLParser.HTMLParseError: self.log.debug('Encountered a problem parsing %u. Title may ' 'already be set, though', url) if parser.title: domain = utils.web.getDomain(url) title = utils.web.htmlToText(parser.title.strip()) s = format('Title: %s (at %s)', title, domain) irc.reply(s, prefixNick=False)
def titleSnarfer(self, irc, msg, match): channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return if self.registryValue('titleSnarfer', channel): url = match.group(0) if not self._checkURLWhitelist(url): return r = self.registryValue('nonSnarfingRegexp', channel) if r and r.search(url): self.log.debug('Not titleSnarfing %q.', url) return r = self.getTitle(irc, url, False) if not r: return (target, title) = r if title: domain = utils.web.getDomain(target if self.registryValue('snarferShowTargetDomain', channel) else url) prefix = self.registryValue('snarferPrefix', channel) s = "%s %s" % (prefix, title) if self.registryValue('snarferShowDomain', channel): s += format(_(' (at %s)'), domain) irc.reply(s, prefixNick=False) if self.registryValue('snarfMultipleUrls', channel): # FIXME: hack msg.tag('repliedTo', False)
def doPrivmsg(self, irc, msg): if callbacks.addressed(irc.nick, msg): #message is direct command return (channel, text) = msg.args if ircmsgs.isAction(msg): text = ircmsgs.unAction(msg) learn = self.registryValue('learn', channel) reply = self.registryValue('reply', channel) replyOnMention = self.registryValue('replyOnMention', channel) replyWhenSpokenTo = self.registryValue('replyWhenSpokenTo', channel) mention = irc.nick.lower() in text.lower() spokenTo = msg.args[1].lower().startswith('%s: ' % irc.nick.lower()) if replyWhenSpokenTo and spokenTo: reply = 1000 text = text.replace('%s: ' % irc.nick, '') text = text.replace('%s: ' % irc.nick.lower(), '') if replyOnMention and mention: if not replyWhenSpokenTo and spokenTo: reply = 0 else: reply = 1000 if randint(0, 999) < reply: self.reply(irc, msg, text) if learn: self.learn(irc, msg, text)
def testAddressedWithNickAtEnd(self): irc = getTestIrc() msg = ircmsgs.privmsg('#foo', 'baz, bar') irc._tagMsg(msg) self.assertEqual( callbacks.addressed('bar', msg, whenAddressedByNickAtEnd=True), 'baz')
def doPrivmsg(self, irc, msg): channel = msg.args[0] if not irc.isChannel(channel): return if self.registryValue('enable', channel): if callbacks.addressed(irc.nick, msg): #message is direct command return actions = [] db = self.getDb(channel) cursor = db.cursor() cursor.execute("SELECT regexp, action FROM triggers") results = cursor.fetchall() if len(results) == 0: return for (regexp, action) in results: for match in re.finditer(regexp, msg.args[1]): if match is not None: thisaction = action self._updateRank(channel, regexp) for (i, j) in enumerate(match.groups()): thisaction = re.sub(r'\$' + str(i + 1), match.group(i + 1), thisaction) actions.append(thisaction) for action in actions: self._runCommandFunction(irc, msg, action)
def doPrivmsg(self, irc, msg): channel = ircutils.toLower(msg.args[0]) if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return if channel in self.games: self.games[channel].answer(msg)
def testAddressedLegacy(self): """Checks callbacks.addressed still accepts the 'nick' argument instead of 'irc'.""" irc = getTestIrc() oldprefixchars = str(conf.supybot.reply.whenAddressedBy.chars) nick = 'supybot' conf.supybot.reply.whenAddressedBy.chars.set('~!@') inChannel = ['~foo', '@foo', '!foo', '%s: foo' % nick, '%s foo' % nick, '%s: foo' % nick.capitalize(), '%s: foo' % nick.upper()] inChannel = [ircmsgs.privmsg('#foo', s) for s in inChannel] badmsg = ircmsgs.privmsg('#foo', '%s:foo' % nick) with self.assertWarnsRegex(DeprecationWarning, 'Irc object instead'): self.assertFalse(callbacks.addressed(nick, badmsg)) badmsg = ircmsgs.privmsg('#foo', '%s^: foo' % nick) with self.assertWarnsRegex(DeprecationWarning, 'Irc object instead'): self.assertFalse(callbacks.addressed(nick, badmsg)) for msg in inChannel: with self.assertWarns(DeprecationWarning): self.assertEqual('foo', callbacks.addressed(nick, msg), msg) msg = ircmsgs.privmsg(nick, 'foo') irc._tagMsg(msg) with self.assertWarns(DeprecationWarning): self.assertEqual('foo', callbacks.addressed(nick, msg)) conf.supybot.reply.whenAddressedBy.chars.set(oldprefixchars) msg = ircmsgs.privmsg('#foo', '%s::::: bar' % nick) with self.assertWarns(DeprecationWarning): self.assertEqual('bar', callbacks.addressed(nick, msg)) msg = ircmsgs.privmsg('#foo', '%s: foo' % nick.upper()) with self.assertWarns(DeprecationWarning): self.assertEqual('foo', callbacks.addressed(nick, msg)) badmsg = ircmsgs.privmsg('#foo', '%s`: foo' % nick) with self.assertWarns(DeprecationWarning): self.assertFalse(callbacks.addressed(nick, badmsg))
def testAddressed(self): irc = getTestIrc() oldprefixchars = str(conf.supybot.reply.whenAddressedBy.chars) nick = irc.nick conf.supybot.reply.whenAddressedBy.chars.set('~!@') inChannel = [ '~foo', '@foo', '!foo', '%s: foo' % nick, '%s foo' % nick, '%s: foo' % nick.capitalize(), '%s: foo' % nick.upper() ] inChannel = [ircmsgs.privmsg('#foo', s) for s in inChannel] badmsg = ircmsgs.privmsg('#foo', '%s:foo' % nick) self.assertFalse(callbacks.addressed(irc, badmsg)) badmsg = ircmsgs.privmsg('#foo', '%s^: foo' % nick) self.assertFalse(callbacks.addressed(irc, badmsg)) for msg in inChannel: self.assertEqual('foo', callbacks.addressed(irc, msg), msg) msg = ircmsgs.privmsg(nick, 'foo') irc._tagMsg(msg) self.assertEqual('foo', callbacks.addressed(irc, msg)) conf.supybot.reply.whenAddressedBy.chars.set(oldprefixchars) msg = ircmsgs.privmsg('#foo', '%s::::: bar' % nick) self.assertEqual('bar', callbacks.addressed(irc, msg)) msg = ircmsgs.privmsg('#foo', '%s: foo' % nick.upper()) self.assertEqual('foo', callbacks.addressed(irc, msg)) badmsg = ircmsgs.privmsg('#foo', '%s`: foo' % nick) self.assertFalse(callbacks.addressed(irc, badmsg))
def testAddressed(self): oldprefixchars = str(conf.supybot.reply.whenAddressedBy.chars) nick = "supybot" conf.supybot.reply.whenAddressedBy.chars.set("~!@") inChannel = [ "~foo", "@foo", "!foo", "%s: foo" % nick, "%s foo" % nick, "%s: foo" % nick.capitalize(), "%s: foo" % nick.upper(), ] inChannel = [ircmsgs.privmsg("#foo", s) for s in inChannel] badmsg = ircmsgs.privmsg("#foo", "%s:foo" % nick) self.failIf(callbacks.addressed(nick, badmsg)) badmsg = ircmsgs.privmsg("#foo", "%s^: foo" % nick) self.failIf(callbacks.addressed(nick, badmsg)) for msg in inChannel: self.assertEqual("foo", callbacks.addressed(nick, msg), msg) msg = ircmsgs.privmsg(nick, "foo") self.assertEqual("foo", callbacks.addressed(nick, msg)) conf.supybot.reply.whenAddressedBy.chars.set(oldprefixchars) msg = ircmsgs.privmsg("#foo", "%s::::: bar" % nick) self.assertEqual("bar", callbacks.addressed(nick, msg)) msg = ircmsgs.privmsg("#foo", "%s: foo" % nick.upper()) self.assertEqual("foo", callbacks.addressed(nick, msg)) badmsg = ircmsgs.privmsg("#foo", "%s`: foo" % nick) self.failIf(callbacks.addressed(nick, badmsg))
def doPrivmsg(self, irc, msg): (targets, t) = msg.args text = escape(t) if msg.prefix == irc.prefix: return for channel in targets.split(','): if irc.isChannel(channel) and channel in irc.state.channels: learn = self.registryValue('learn', channel=channel) replyRandom = self.registryValue('replyPercent', channel=channel) > 0.00 replyAddressed = self.registryValue('replyWhenAddressed', channel=channel) called = False if ircdb.checkIgnored(msg.prefix, channel): continue if not learn and not replyRandom and not replyAddressed: continue if replyAddressed and msg.addressed: text = escape(callbacks.addressed(irc.nick, msg)) m = None if learn: m = self.callHailo(channel, '-L', text) else: m = self.callHailo(channel, '-r', text) if m != None and len(m): if self.registryValue('checkSimilarity', channel=channel): if similar(m, text) < self.registryValue( 'similarity', channel=channel): irc.queueMsg(ircmsgs.privmsg(channel, m)) else: m = self.callHailo(channel, '-R', '') if m != None and len(m): irc.queueMsg(ircmsgs.privmsg(channel, m)) else: irc.queueMsg(ircmsgs.privmsg(channel, m)) called = True if not msg.addressed and replyRandom and randint( 1, 99) < self.registryValue('replyPercent', channel=channel) * 100: m = None if learn: m = self.callHailo(channel, '-L', text) else: m = self.callHailo(channel, '-r', text) called = True if m != None and len(m): if self.registryValue('checkSimilarity', channel=channel): if similar(m, text) < self.registryValue( 'similarity', channel=channel): irc.queueMsg(ircmsgs.privmsg(channel, m)) else: irc.queueMsg(ircmsgs.privmsg(channel, m)) if not called and learn: self.callHailo(channel, '-l', text)
def getName(self, nick, msg, match): addressed = callbacks.addressed(nick, msg) name = callbacks.addressed( nick, ircmsgs.IrcMsg(prefix='', args=(msg.args[0], match.group(1)), msg=msg)) if not name: name = match.group(1) if not addressed: if not self.registryValue('allowUnaddressedKarma'): return '' if not msg.args[1].startswith(match.group(1)): return '' name = match.group(1) elif addressed: if not addressed.startswith(name): return '' name = name.strip('()') return name
def _doPrivmsgs(self, irc, msg): """If the given message is a command, triggers Limnoria's command-dispatching for that command. Takes the same arguments as ``doPrivmsg`` would, but ``msg`` can potentially be an artificial message synthesized in doBatch from a multiline batch. Usually, a command is a single message, so ``payload=msg.params[0]`` However, when ``msg`` is part of a multiline message, the payload is the concatenation of multiple messages. See <https://ircv3.net/specs/extensions/multiline>. """ assert self is irc.callbacks[0], \ 'Owner isn\'t first callback: %r' % irc.callbacks if ircmsgs.isCtcp(msg): return s = callbacks.addressed(irc, msg) if s: ignored = ircdb.checkIgnored(msg.prefix) if ignored: self.log.info('Ignoring command from %s.', msg.prefix) return maximum = conf.supybot.abuse.flood.command.maximum() self.commands.enqueue(msg) if conf.supybot.abuse.flood.command() \ and self.commands.len(msg) > maximum \ and not ircdb.checkCapability(msg.prefix, 'trusted'): punishment = conf.supybot.abuse.flood.command.punishment() banmask = conf.supybot.protocols.irc.banmask \ .makeBanmask(msg.prefix) self.log.info( 'Ignoring %s for %s seconds due to an apparent ' 'command flood.', banmask, punishment) ircdb.ignores.add(banmask, time.time() + punishment) if conf.supybot.abuse.flood.command.notify(): irc.reply('You\'ve given me %s 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 try: tokens = callbacks.tokenize(s, channel=msg.channel, network=irc.network) self.Proxy(irc, msg, tokens) except SyntaxError as e: if conf.supybot.reply.error.detailed(): irc.error(str(e)) else: irc.replyError(msg=msg) self.log.info('Syntax error: %s', e)
def birthday(self,irc,msg,match): r'(.+)?[Hh]appy(.+)?[Bb]irthday(.*)\!' channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return text1 = "HAPPY BIRTHDAY!!!!!!" colors = utils.iter.cycle([4, 7, 8, 3, 2, 12, 6]) L = [self._color(c, fg=colors.next()) for c in text1] irc.reply(''.join(L) + '\x03')
def doPrivmsg(self, irc, msg): try: if ircmsgs.isCtcp(msg): self.log.debug('Returning early from doPrivmsg: isCtcp(msg).') return s = callbacks.addressed(irc.nick, msg) payload = self.normalize(s or msg.args[1], irc.nick, msg.nick) if s: msg.tag('addressed', payload) msg = ircmsgs.IrcMsg(args=(msg.args[0], payload), msg=msg) self.__parent.doPrivmsg(irc, msg) finally: self.changed = False self.added = False
def doPrivmsg(self, irc, msg): if ircmsgs.isCtcp(msg) and not ircmsgs.isAction(msg): return channel = msg.args[0] if callbacks.addressed(irc.nick, msg): return if self.registryValue('titleSnarfer', channel): if irc.isChannel(channel): if ircmsgs.isAction(msg): text = ircmsgs.unAction(msg) else: text = msg.args[1] for info in present_links(text, color=True): irc.reply(info, prefixNick=False, private=False, notice=False)
def doPrivmsg(self, irc, msg): channel = msg.args[0] if callbacks.addressed(irc.nick, msg): return if not irc.isChannel(channel): channel = msg.nick self.game.setdefault(channel, None) if self.game[channel]: command = msg.args[1] self.game[channel].sendline(command) response = self.output(self.game[channel]) for line in response[1:]: if line.strip() and line.strip() != ".": irc.reply(line, prefixNick=False)
def doPrivmsg (self,irc,msg): (targets, t) = msg.args text = escape(t) if msg.prefix == irc.prefix: return for channel in targets.split(','): if irc.isChannel(channel) and channel in irc.state.channels: learn = self.registryValue('learn',channel=channel) replyRandom = self.registryValue('replyPercent',channel=channel) > 0.00 replyAddressed = self.registryValue('replyWhenAddressed',channel=channel) called = False if ircdb.checkIgnored(msg.prefix,channel): continue if not learn and not replyRandom and not replyAddressed: continue if replyAddressed and msg.addressed: text = escape(callbacks.addressed(irc.nick,msg)) m = None if learn: m = self.callHailo(channel,'-L',text) else: m = self.callHailo(channel,'-r',text) if m != None and len(m): if self.registryValue('checkSimilarity',channel=channel): if similar(m,text) < self.registryValue('similarity',channel=channel): irc.queueMsg(ircmsgs.privmsg(channel,m)) else: m = self.callHailo(channel,'-R','') if m != None and len(m): irc.queueMsg(ircmsgs.privmsg(channel,m)) else: irc.queueMsg(ircmsgs.privmsg(channel,m)) called = True if not msg.addressed and replyRandom and randint(1,99) < self.registryValue('replyPercent',channel=channel)*100: m = None if learn: m = self.callHailo(channel,'-L',text) else: m = self.callHailo(channel,'-r',text) called = True if m != None and len(m): if self.registryValue('checkSimilarity',channel=channel): if similar(m,text) < self.registryValue('similarity',channel=channel): irc.queueMsg(ircmsgs.privmsg(channel,m)) else: irc.queueMsg(ircmsgs.privmsg(channel,m)) if not called and learn: self.callHailo(channel,'-l',text)
def mediaWikiTitleSnarfer(self, irc, msg, match): r"\[\[(.+?)\]\]" #self.log.info("snarfed title with match: %s" % match.groups()) channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return # workaround for stupid line-breaking in config file after 80 chars -.- url = self.registryValue('mediaWikiUrl', channel).translate(None, " \t\n\r") if url: if not url.endswith("/"): url += "/" # apparently, this function is only called for the first match at all :( page = match.group(1).strip() irc.reply(url + self.mwUrlTitleEncode(page), prefixNick=False)
def mediaWikiTemplateSnarfer(self, irc, msg, match): r"\{\{(.+?)\}\}" #self.log.info("snarfed with match: %s" % match.groups()) channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return url = self.registryValue('mediaWikiUrl', channel).translate(None, " \t\n\r") if url: if not url.endswith("/"): url += "/" # apparently, this function is only called for the first match at all :( page = match.group(1).strip() irc.reply(url + "Template:" + self.mwUrlTitleEncode(page), prefixNick=False)
def titleSnarfer(self, irc, msg, match): channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return ign = self.registryValue('ignoredNicks', channel) if msg.nick in ign: return if self.registryValue('titleSnarfer', channel): url = match.group(0) r = self.registryValue('nonSnarfingRegexp', channel) if r and r.search(url): self.log.debug('Not titleSnarfing %q.', url) return try: size = conf.supybot.protocols.http.peekSize() fd = utils.web.getUrlFd(url) text = fd.read(size) fd.close() except socket.timeout as e: self.log.info('Couldn\'t snarf title of %u: %s.', url, e) if self.registryValue('snarferReportIOExceptions', channel): irc.reply(url+" : "+utils.web.TIMED_OUT, prefixNick=False) return try: text = text.decode(utils.web.getEncoding(text) or 'utf8', 'replace') except: pass parser = Title() try: parser.feed(text) except HTMLParser.HTMLParseError: self.log.debug('Encountered a problem parsing %u. Title may ' 'already be set, though', url) if parser.title: domain = utils.web.getDomain(fd.geturl() if self.registryValue('snarferShowTargetDomain', channel) else url) title = utils.web.htmlToText(parser.title.strip()) if sys.version_info[0] < 3: if isinstance(title, unicode): title = title.encode('utf8', 'replace') s = format(_('Title: %s (at %s)'), title, domain) irc.reply(s, prefixNick=False)
def doPrivmsg(self, irc, msg): channel = msg.args[0] text = msg.args[1] prefix = msg.prefix nick = prefix.split('!')[0] if callbacks.addressed(irc.nick, msg): #message is direct command return checker = SpellChecker(text, self.registryValue('level', channel)) errors = checker.getErrors() if len(errors) == 0: return elif len(errors) == 1: reason = 'Erreur : %s' % errors[0] else: reason = 'Erreurs : %s' % ' | '.join(errors) msg = ircmsgs.kick(channel, nick, reason) irc.queueMsg(msg)
def titleSnarfer(self, irc, msg, match): channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return if self.registryValue('titleSnarfer', channel): url = match.group(0) r = self.registryValue('nonSnarfingRegexp', channel) if r and r.search(url): self.log.debug('Not titleSnarfing %q.', url) return try: size = conf.supybot.protocols.http.peekSize() fd = utils.web.getUrlFd(url) text = fd.read(size) fd.close() except socket.timeout as e: self.log.info('Couldn\'t snarf title of %u: %s.', url, e) if self.registryValue('snarferReportIOExceptions', channel): irc.reply(url + " : " + utils.web.TIMED_OUT, prefixNick=False) return try: text = text.decode( utils.web.getEncoding(text) or 'utf8', 'replace') except: pass parser = Title() try: parser.feed(text) except HTMLParser.HTMLParseError: self.log.debug( 'Encountered a problem parsing %u. Title may ' 'already be set, though', url) if parser.title: domain = utils.web.getDomain(fd.geturl() if self.registryValue( 'snarferShowTargetDomain', channel) else url) title = utils.web.htmlToText(parser.title.strip()) if sys.version_info[0] < 3: if isinstance(title, unicode): title = title.encode('utf8', 'replace') s = format(_('Title: %s (at %s)'), title, domain) irc.reply(s, prefixNick=False)
def doPrivmsg(self, irc, msg): channel = msg.args[0] s = msg.args[1] s, args = self.getPrivmsgData(channel, msg.nick, s, self.registryValue('color', channel)) if channel not in irc.state.channels: # in private # cuts off the end of commands, so that passwords # won't be revealed in relayed PM's if callbacks.addressed(irc.nick, msg): if self.registryValue('color', channel): color = '\x03' + self.registryValue( 'colors.truncated', channel) match = '(>\017 \w+) .*' else: color = '' match = '(> \w+) .*' s = re.sub(match, '\\1 %s[%s]' % (color, _('truncated')), s) s = '(via PM) %s' % s self.sendToOthers(irc, channel, s, args, isPrivmsg=True)
def usernameSnarfer(self, irc, msg, match): if callbacks.addressed(irc, msg): return if not self.registryValue("snarfers.username", msg.channel, irc.network): return if not self._has_webfinger_support(match.group("hostname")): self.log.debug( "Not snarfing, host doesn't have Webfinger support.") return try: actor = self._get_actor(irc, match.group(0)) except ap.ActivityPubError as e: self.log.info("Could not fetch %s: %s", match.group(0), e) # Be silent on errors return irc.reply(self._format_profile(irc, msg, actor), prefixNick=False)
def titleSnarfer(self, irc, msg, match): channel = msg.args[0] if not irc.isChannel(channel): return if callbacks.addressed(irc.nick, msg): return if self.registryValue('titleSnarfer', channel): url = match.group(0) if not self._checkURLWhitelist(url): return r = self.registryValue('nonSnarfingRegexp', channel) if r and r.search(url): self.log.debug('Not titleSnarfing %q.', url) return title = self.getTitle(url) if title: domain = utils.web.getDomain(fd.geturl() if self.registryValue( 'snarferShowTargetDomain', channel) else url) s = format(_('Title: %s (at %s)'), title, domain) irc.reply(s, prefixNick=False)