BadWords: Re-allow words with a space (aka 'phrases')

I disallowed it in f3f628ddba because they
couldn't be deserialized properly.

This commit adds a new 'phrases' config var in addition to 'words',
that is comma-separated instead of space-separated.
This commit is contained in:
Valentin Lorentz 2020-09-05 22:21:11 +02:00
parent 23417b0675
commit bdbb74f046
3 changed files with 51 additions and 19 deletions

View File

@ -44,15 +44,27 @@ def configure(advanced):
'spaces)')) 'spaces)'))
conf.supybot.plugins.BadWords.words.set(words) conf.supybot.plugins.BadWords.words.set(words)
class LastModifiedSetOfStrings(registry.SpaceSeparatedSetOfStrings): class LastModifiedSpaceSeparatedSetOfStrings(registry.SpaceSeparatedSetOfStrings):
lastModified = 0 lastModified = 0
def setValue(self, v): def setValue(self, v):
self.lastModified = time.time() self.lastModified = time.time()
registry.SpaceSeparatedListOfStrings.setValue(self, v) 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') BadWords = conf.registerPlugin('BadWords')
conf.registerGlobalValue(BadWords, 'words', 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."""))) considered to be 'bad' so the bot won't say them.""")))
conf.registerChannelValue(BadWords,'requireWordBoundaries', conf.registerChannelValue(BadWords,'requireWordBoundaries',
registry.Boolean(False, _("""Determines whether the bot will require bad 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 false. After changing this setting, the BadWords regexp needs to be
regenerated by adding/removing a word to the list, or reloading the regenerated by adding/removing a word to the list, or reloading the
plugin."""))) plugin.""")))
conf.registerGlobalValue(BadWords, 'phrases',
LastModifiedCommaSeparatedSetOfStrings([], _("""Comma-separated groups
of words that are considered to be 'bad'.""")))
class String256(registry.String): class String256(registry.String):
def __call__(self): def __call__(self):

View File

@ -53,6 +53,7 @@ class BadWords(callbacks.Privmsg):
self.filtering = True self.filtering = True
self.lastModified = 0 self.lastModified = 0
self.words = conf.supybot.plugins.BadWords.words self.words = conf.supybot.plugins.BadWords.words
self.phrases = conf.supybot.plugins.BadWords.phrases
def callCommand(self, name, irc, msg, *args, **kwargs): def callCommand(self, name, irc, msg, *args, **kwargs):
if ircdb.checkCapability(msg.prefix, 'admin'): if ircdb.checkCapability(msg.prefix, 'admin'):
@ -71,7 +72,7 @@ class BadWords(callbacks.Privmsg):
self.filtering = True self.filtering = True
# We need to check for bad words here rather than in doPrivmsg because # We need to check for bad words here rather than in doPrivmsg because
# messages don't get to doPrivmsg if the user is ignored. # messages don't get to doPrivmsg if the user is ignored.
if msg.command == 'PRIVMSG' and self.words(): if msg.command == 'PRIVMSG' and (self.words() or self.phrases()):
channel = msg.channel channel = msg.channel
self.updateRegexp(channel, irc.network) self.updateRegexp(channel, irc.network)
s = ircutils.stripFormatting(msg.args[1]) s = ircutils.stripFormatting(msg.args[1])
@ -96,12 +97,14 @@ class BadWords(callbacks.Privmsg):
return msg return msg
def updateRegexp(self, channel, network): def updateRegexp(self, channel, network):
if self.lastModified < self.words.lastModified: if self.lastModified < self.words.lastModified \
self.makeRegexp(self.words(), channel, network) or self.lastModified < self.phrases.lastModified:
self.makeRegexp(self.words() | self.phrases(), channel, network)
self.lastModified = time.time() self.lastModified = time.time()
def outFilter(self, irc, msg): def outFilter(self, irc, msg):
if self.filtering and msg.command == 'PRIVMSG' and self.words(): if self.filtering and msg.command == 'PRIVMSG' \
and (self.words() or self.phrases()):
channel = msg.channel channel = msg.channel
self.updateRegexp(channel, irc.network) self.updateRegexp(channel, irc.network)
s = msg.args[1] s = msg.args[1]
@ -124,7 +127,7 @@ class BadWords(callbacks.Privmsg):
Returns the list of words being censored. Returns the list of words being censored.
""" """
L = list(self.words()) L = list(self.words() | self.phrases())
if L: if L:
self.filtering = False self.filtering = False
utils.sortBy(str.lower, L) utils.sortBy(str.lower, L)
@ -134,29 +137,42 @@ class BadWords(callbacks.Privmsg):
list = wrap(list, ['admin']) list = wrap(list, ['admin'])
@internationalizeDocstring @internationalizeDocstring
def add(self, irc, msg, args, words): def add(self, irc, msg, args, new_words):
"""<word> [<word> ...] """<word> [<word> ...]
Adds all <word>s to the list of words being censored. Adds all <word>s to the list of words being censored.
""" """
set = self.words() words = self.words()
set.update(words) phrases = self.phrases()
self.words.setValue(set) 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() irc.replySuccess()
add = wrap(add, ['admin', many('somethingWithoutSpaces')]) add = wrap(add, ['admin', many('something')])
@internationalizeDocstring @internationalizeDocstring
def remove(self, irc, msg, args, words): def remove(self, irc, msg, args, old_words):
"""<word> [<word> ...] """<word> [<word> ...]
Removes <word>s from the list of words being censored. Removes <word>s from the list of words being censored.
""" """
set = self.words() words = self.words()
for word in words: phrases = self.phrases()
set.discard(word) for word in old_words:
self.words.setValue(set) words.discard(word)
phrases.discard(word)
self.words.setValue(words)
self.phrases.setValue(phrases)
irc.replySuccess() irc.replySuccess()
remove = wrap(remove, ['admin', many('somethingWithoutSpaces')]) remove = wrap(remove, ['admin', many('something')])
Class = BadWords Class = BadWords

View File

@ -76,7 +76,8 @@ class BadWordsTestCase(PluginTestCase):
self.assertNotError('badwords list') self.assertNotError('badwords list')
self.assertNotError('badwords add shit') self.assertNotError('badwords add shit')
self.assertNotError('badwords add ass') 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: # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: