BadWords: Add the option to redact messages containing bad words

instead of or in addition to kicking
This commit is contained in:
Valentin Lorentz 2023-05-26 21:15:12 +02:00
parent 10152d79ee
commit f00ecdeaef
3 changed files with 94 additions and 21 deletions

View File

@ -119,6 +119,11 @@ conf.registerChannelValue(BadWords, 'selfCensor',
conf.registerChannelValue(BadWords, 'kick', conf.registerChannelValue(BadWords, 'kick',
registry.Boolean(False, _("""Determines whether the bot will kick people with registry.Boolean(False, _("""Determines whether the bot will kick people with
a warning when they use bad words."""))) a warning when they use bad words.""")))
conf.registerChannelValue(BadWords, 'redact',
registry.Boolean(False, _("""Determines whether the bot will redact
messages containing bad words (only on servers supporting IRCv3
draft/message-redaction; requires supybot.protocols.irc.experimentalExtensions).
""")))
conf.registerChannelValue(BadWords.kick, 'message', conf.registerChannelValue(BadWords.kick, 'message',
registry.NormalizedString(_("""You have been kicked for using a word registry.NormalizedString(_("""You have been kicked for using a word
prohibited in the presence of this bot. Please use more appropriate prohibited in the presence of this bot. Please use more appropriate

View File

@ -1,7 +1,7 @@
### ###
# Copyright (c) 2002-2004, Jeremiah Fincher # Copyright (c) 2002-2004, Jeremiah Fincher
# Copyright (c) 2009, James McCoy # Copyright (c) 2009, James McCoy
# Copyright (c) 2010-2021, Valentin Lorentz # Copyright (c) 2010-2023, Valentin Lorentz
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -77,24 +77,49 @@ class BadWords(callbacks.Privmsg):
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])
if irc.isChannel(channel) \ if not irc.isChannel(channel):
and self.registryValue('kick', channel, irc.network): # not a channel, don't bother checking
if self.regexp.search(s): return msg
c = irc.state.channels[channel]
cap = ircdb.makeChannelCapability(channel, 'op') may_kick = self.registryValue('kick', channel, irc.network)
if c.isHalfopPlus(irc.nick): msgid = msg.server_tags.get("msgid")
if c.isHalfopPlus(msg.nick) or \ may_redact = (
ircdb.checkCapability(msg.prefix, cap): "draft/message-redaction" in irc.state.capabilities_ack
self.log.debug("Not kicking %s from %s, because " and msgid
"they are halfop+ or can't be " and conf.supybot.protocols.irc.experimentalExtensions()
"kicked.", msg.nick, channel) and self.registryValue('redact', channel, irc.network)
else: )
message = self.registryValue('kick.message',
channel, irc.network) if not may_kick and not may_redact:
irc.queueMsg(ircmsgs.kick(channel, msg.nick, message)) # no configured action, don't bother checking
else: return msg
self.log.warning('Should kick %s from %s, but not opped.',
msg.nick, channel) if not self.regexp.search(s):
# message does not contain a bad word
return msg
c = irc.state.channels[channel]
cap = ircdb.makeChannelCapability(channel, 'op')
if not c.isHalfopPlus(irc.nick):
self.log.warning(
'Should kick and/or redact %s from %s, but not opped.',
msg.nick, channel)
return msg
if may_redact:
irc.queueMsg(ircmsgs.IrcMsg(
command="REDACT", args=(channel, msgid)))
if may_kick:
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.network)
irc.queueMsg(ircmsgs.kick(channel, msg.nick, message))
return msg return msg
def updateRegexp(self, channel, network): def updateRegexp(self, channel, network):

View File

@ -1,6 +1,6 @@
### ###
# Copyright (c) 2002-2004, Jeremiah Fincher # Copyright (c) 2002-2004, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz # Copyright (c) 2010-2023, Valentin Lorentz
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -31,7 +31,7 @@
import supybot.conf as conf import supybot.conf as conf
from supybot.test import * from supybot.test import *
class BadWordsTestCase(PluginTestCase): class BadWordsOutfilterTestCase(PluginTestCase):
plugins = ('BadWords', 'Utilities', 'Format', 'Filter') plugins = ('BadWords', 'Utilities', 'Format', 'Filter')
badwords = ('shit', 'ass', 'fuck') badwords = ('shit', 'ass', 'fuck')
def tearDown(self): def tearDown(self):
@ -80,5 +80,48 @@ class BadWordsTestCase(PluginTestCase):
self.assertNotError('badwords add "fuck you"') self.assertNotError('badwords add "fuck you"')
self.assertResponse('badwords list', 'ass, fuck you, and shit') self.assertResponse('badwords list', 'ass, fuck you, and shit')
class BadWordsInfilterTestCase(ChannelPluginTestCase):
plugins = ('BadWords',)
badwords = ('shit', 'ass', 'fuck')
def tearDown(self):
# .default() doesn't seem to be working for BadWords.words
#default = conf.supybot.plugins.BadWords.words.default()
#conf.supybot.plugins.BadWords.words.setValue(default)
conf.supybot.plugins.BadWords.words.setValue([])
def testKick(self):
self.irc.feedMsg(ircmsgs.op(self.channel, self.nick))
self.assertNotError('badwords add shit')
with conf.supybot.plugins.BadWords.kick \
.getSpecific(self.irc.network, self.channel).context(True):
self.irc.feedMsg(ircmsgs.privmsg(self.channel,
'oh shit',
prefix='foobar!user@__no_testcap__'))
m = self.getMsg(' ')
self.assertIsNotNone(m)
self.assertEqual(m.command, 'KICK', m)
self.assertEqual(m.args[0], self.channel, m)
self.assertEqual(m.args[1], 'foobar', m)
def testRedact(self):
self.irc.feedMsg(ircmsgs.op(self.channel, self.nick))
self.irc.state.capabilities_ack.add('draft/message-redaction')
self.assertNotError('badwords add shit')
with conf.supybot.plugins.BadWords.redact \
.getSpecific(self.irc.network, self.channel).context(True):
with conf.supybot.protocols.irc.experimentalExtensions.context(True):
self.irc.feedMsg(ircmsgs.IrcMsg(
command='PRIVMSG',
args=(self.channel, 'oh shit'),
prefix='foobar!user@__no_testcap__',
server_tags={'msgid': 'abcde'}))
m = self.getMsg(' ', timeout=0.5)
self.assertIsNotNone(m)
self.assertEqual(m.command, 'REDACT', m)
self.assertEqual(m.args, (self.channel, 'abcde'), m)
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: