diff --git a/plugins/BadWords/config.py b/plugins/BadWords/config.py index e66ea4602..8a3e9c225 100644 --- a/plugins/BadWords/config.py +++ b/plugins/BadWords/config.py @@ -44,15 +44,27 @@ def configure(advanced): 'spaces)')) conf.supybot.plugins.BadWords.words.set(words) -class LastModifiedSetOfStrings(registry.SpaceSeparatedSetOfStrings): +class LastModifiedSpaceSeparatedSetOfStrings(registry.SpaceSeparatedSetOfStrings): lastModified = 0 def setValue(self, v): self.lastModified = time.time() registry.SpaceSeparatedListOfStrings.setValue(self, v) +class LastModifiedCommaSeparatedSetOfStrings(registry.CommaSeparatedSetOfStrings): + lastModified = 0 + def set(self, v): + if not v.strip(): + self.setValue(set()) + else: + super().set(v) + + def setValue(self, v): + self.lastModified = time.time() + registry.CommaSeparatedListOfStrings.setValue(self, v) + BadWords = conf.registerPlugin('BadWords') conf.registerGlobalValue(BadWords, 'words', - LastModifiedSetOfStrings([], _("""Determines what words are + LastModifiedSpaceSeparatedSetOfStrings([], _("""Determines what words are considered to be 'bad' so the bot won't say them."""))) conf.registerChannelValue(BadWords,'requireWordBoundaries', registry.Boolean(False, _("""Determines whether the bot will require bad @@ -62,6 +74,9 @@ conf.registerChannelValue(BadWords,'requireWordBoundaries', false. After changing this setting, the BadWords regexp needs to be regenerated by adding/removing a word to the list, or reloading the plugin."""))) +conf.registerGlobalValue(BadWords, 'phrases', + LastModifiedCommaSeparatedSetOfStrings([], _("""Comma-separated groups + of words that are considered to be 'bad'."""))) class String256(registry.String): def __call__(self): diff --git a/plugins/BadWords/plugin.py b/plugins/BadWords/plugin.py index cffaedccd..d19871927 100644 --- a/plugins/BadWords/plugin.py +++ b/plugins/BadWords/plugin.py @@ -53,6 +53,7 @@ class BadWords(callbacks.Privmsg): self.filtering = True self.lastModified = 0 self.words = conf.supybot.plugins.BadWords.words + self.phrases = conf.supybot.plugins.BadWords.phrases def callCommand(self, name, irc, msg, *args, **kwargs): if ircdb.checkCapability(msg.prefix, 'admin'): @@ -71,7 +72,7 @@ class BadWords(callbacks.Privmsg): 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' and self.words(): + if msg.command == 'PRIVMSG' and (self.words() or self.phrases()): channel = msg.channel self.updateRegexp(channel, irc.network) s = ircutils.stripFormatting(msg.args[1]) @@ -96,12 +97,14 @@ class BadWords(callbacks.Privmsg): return msg def updateRegexp(self, channel, network): - if self.lastModified < self.words.lastModified: - self.makeRegexp(self.words(), channel, network) + if self.lastModified < self.words.lastModified \ + or self.lastModified < self.phrases.lastModified: + self.makeRegexp(self.words() | self.phrases(), channel, network) self.lastModified = time.time() def outFilter(self, irc, msg): - if self.filtering and msg.command == 'PRIVMSG' and self.words(): + if self.filtering and msg.command == 'PRIVMSG' \ + and (self.words() or self.phrases()): channel = msg.channel self.updateRegexp(channel, irc.network) s = msg.args[1] @@ -124,7 +127,7 @@ class BadWords(callbacks.Privmsg): Returns the list of words being censored. """ - L = list(self.words()) + L = list(self.words() | self.phrases()) if L: self.filtering = False utils.sortBy(str.lower, L) @@ -134,29 +137,42 @@ class BadWords(callbacks.Privmsg): list = wrap(list, ['admin']) @internationalizeDocstring - def add(self, irc, msg, args, words): + def add(self, irc, msg, args, new_words): """ [ ...] Adds all s to the list of words being censored. """ - set = self.words() - set.update(words) - self.words.setValue(set) + words = self.words() + phrases = self.phrases() + for word in new_words: + if ' ' in word: + phrases.add(word) + else: + words.add(word) + + self.words.setValue(words) + self.phrases.setValue(phrases) + irc.replySuccess() - add = wrap(add, ['admin', many('somethingWithoutSpaces')]) + add = wrap(add, ['admin', many('something')]) @internationalizeDocstring - def remove(self, irc, msg, args, words): + def remove(self, irc, msg, args, old_words): """ [ ...] Removes s from the list of words being censored. """ - set = self.words() - for word in words: - set.discard(word) - self.words.setValue(set) + words = self.words() + phrases = self.phrases() + for word in old_words: + words.discard(word) + phrases.discard(word) + self.words.setValue(words) + self.phrases.setValue(phrases) + + irc.replySuccess() - remove = wrap(remove, ['admin', many('somethingWithoutSpaces')]) + remove = wrap(remove, ['admin', many('something')]) Class = BadWords diff --git a/plugins/BadWords/test.py b/plugins/BadWords/test.py index 06efc0d3a..753842877 100644 --- a/plugins/BadWords/test.py +++ b/plugins/BadWords/test.py @@ -76,7 +76,8 @@ class BadWordsTestCase(PluginTestCase): self.assertNotError('badwords list') self.assertNotError('badwords add shit') self.assertNotError('badwords add ass') - self.assertResponse('badwords list', 'ass and shit') + self.assertNotError('badwords add "fuck you"') + self.assertResponse('badwords list', 'ass, fuck you, and shit') # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: