mirror of
https://github.com/jlu5/SupyPlugins.git
synced 2025-04-26 04:51:08 -05:00
NoTrigger: make list of prefixes/suffixes and bell (\x07) blocking configurable, docs+test case updates
This commit is contained in:
parent
7f5cea73ad
commit
8e8a3a30a5
@ -1,12 +1,16 @@
|
||||
NoTrigger is an anti-abuse script that modifies outFilter to prevent triggering other bots.
|
||||
NoTrigger is an anti-abuse plugin that modifies outFilter to prevent triggering other bots.
|
||||
|
||||
## Short description
|
||||
In short, NoTrigger works by:
|
||||
|
||||
- Prepending messages that start with a symbol (```!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~```) with a [zero width space](https://en.wikipedia.org/wiki/Zero-width_space) (ZWSP), since these are often used as prefixes for bots. This has the effect of being completely invisible, and tricks most bots into ignoring yours!
|
||||
- Prepending messages that start with a symbol (```!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~```) or any configured prefixes with a [zero width space](https://en.wikipedia.org/wiki/Zero-width_space) (ZWSP), since these are often used as prefixes for bots. This has the effect of being completely invisible, and tricks most bots into ignoring yours!
|
||||
- Prepending messages with a ZWSP if the channel is set to block colors and a message begins with a formatting code (sneaky attackers can otherwise do something like `\x02!echo hello` to bypass filters).
|
||||
- Optionally, prepending messages with a ZWSP if they match `<something>: ` or `<something>, `, since some bots are taught to respond to their nicks.
|
||||
- Optionally, blocking all channel-wide CTCPs (except for ACTION).
|
||||
- Optionally, stripping the bell character from any outgoing messages.
|
||||
- Optionally, appending messages that end with any configured suffixes with a ZWSP.
|
||||
|
||||
To enable NoTrigger, set the `plugins.NoTrigger.enable` config option `True` for the channels in question. You can find a list of NoTrigger's options (toggling the things mentioned above) by running `config list plugins.NoTrigger`.
|
||||
|
||||
## Longer description/Backstory on why I wrote this
|
||||
Sometimes when you have a public development channel with many bots residing in it, someone will come along and do something really evil: that is, create a huge message loop by chaining all your innocent bots together!
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
###
|
||||
|
||||
import string
|
||||
|
||||
import supybot.conf as conf
|
||||
import supybot.registry as registry
|
||||
try:
|
||||
@ -38,7 +40,6 @@ except:
|
||||
# without the i18n module
|
||||
_ = lambda x: x
|
||||
|
||||
|
||||
def configure(advanced):
|
||||
# This will be called by supybot to configure this module. advanced is
|
||||
# a bool that specifies whether the user identified himself as an advanced
|
||||
@ -52,22 +53,32 @@ NoTrigger = conf.registerPlugin('NoTrigger')
|
||||
conf.registerChannelValue(NoTrigger, 'enable',
|
||||
registry.Boolean(True, _("""Enable protection against triggering other bots.""")))
|
||||
conf.registerChannelValue(NoTrigger, 'spaceBeforeNicks',
|
||||
registry.Boolean(False, _("""Add a space before messages beginning with
|
||||
registry.Boolean(False, _("""Add a space before messages beginning with
|
||||
"blah: " or "blah, ", preventing the bot from triggering other bots that
|
||||
respond to nick. This can cause some weird spacings with error messages and
|
||||
other command replies, so I wouldn't recommend enabling it unless absolutely
|
||||
necessary.""")))
|
||||
respond to nick.""")))
|
||||
|
||||
conf.registerChannelValue(NoTrigger, 'colorAware',
|
||||
registry.Boolean(True, _("""Toggles whether the bot should be aware of colour-stripping
|
||||
modes. (+c or +S on most IRCds)""")))
|
||||
conf.registerGroup(NoTrigger, 'colorAware')
|
||||
registry.Boolean(True, _("""Toggles whether the bot should be aware of color-stripping
|
||||
channel modes (+c or +S on most IRCds).""")))
|
||||
conf.registerChannelValue(NoTrigger.colorAware, 'modes',
|
||||
registry.SpaceSeparatedListOfStrings("c S", _("""Determines a list of modes that should
|
||||
be treated as colour-blocking modes. This is usually +c (block) and +S (stripcolour) on
|
||||
UnrealIRCd/InspIRCd, and just +c (stripcolour) on charybdis-based daemons.""")))
|
||||
registry.SpaceSeparatedListOfStrings("c S", _("""Defines a space-separated list of modes that should
|
||||
be treated as color-blocking modes. This is usually +c (block) and +S (stripcolour) on
|
||||
UnrealIRCd/InspIRCd, and just +c (stripcolor) on charybdis-based daemons.""")))
|
||||
|
||||
conf.registerChannelValue(NoTrigger, 'blockCtcp',
|
||||
registry.Boolean(False, _("""Determines whether the bot should block all CTCPs (\001 codes)
|
||||
registry.Boolean(False, _("""Determines whether the bot should block all outbound channel CTCPs
|
||||
except CTCP actions. If you are using the Ctcp plugin, you will want to turn this off.""")))
|
||||
|
||||
conf.registerChannelValue(NoTrigger, 'prefixes',
|
||||
registry.SpaceSeparatedListOfStrings(' '.join(string.punctuation),
|
||||
_("""Defines a space-separated list of prefix triggers the bot should ignore.""")))
|
||||
|
||||
conf.registerChannelValue(NoTrigger, 'suffixes',
|
||||
registry.SpaceSeparatedListOfStrings('',
|
||||
_("""Defines a space-separated list of suffix triggers the bot should ignore.""")))
|
||||
|
||||
conf.registerChannelValue(NoTrigger, 'blockBell',
|
||||
registry.Boolean(True,
|
||||
_("""Determines whether the bot should strip bell characters (\x07) from any messages it sends.""")))
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
||||
|
@ -46,13 +46,13 @@ except ImportError:
|
||||
|
||||
|
||||
class NoTrigger(callbacks.Plugin):
|
||||
"""Mods outFilter to prevent the bot from triggering other bots."""
|
||||
"""Modifies outFilter to prevent the bot from triggering other bots."""
|
||||
|
||||
def __init__(self, irc):
|
||||
self.__parent = super(NoTrigger, self)
|
||||
self.__parent.__init__(irc)
|
||||
# This uses Unicode Character 'ZERO WIDTH SPACE' (U+200B) for
|
||||
# padding, which looks nicer (it's invisible) and does the trick.
|
||||
# This appends the Unicode character 'ZERO WIDTH SPACE' (U+200B) for
|
||||
# which is absolutely invisible and stops bots from being triggered by us.
|
||||
if version_info[0] >= 3:
|
||||
self.padchar = "\u200B"
|
||||
else:
|
||||
@ -60,6 +60,8 @@ class NoTrigger(callbacks.Plugin):
|
||||
self.padchar = u('\u200B')[0]
|
||||
|
||||
def isChanStripColor(self, irc, channel):
|
||||
"""Returns whether the given channel has a color-stripping mode (usually
|
||||
+c or +S, but configurable) set."""
|
||||
try:
|
||||
c = irc.state.channels[channel]
|
||||
for item in self.registryValue('colorAware.modes'):
|
||||
@ -74,9 +76,8 @@ class NoTrigger(callbacks.Plugin):
|
||||
ircutils.isChannel(msg.args[0]) and \
|
||||
self.registryValue('enable', msg.args[0]):
|
||||
s = msg.args[1]
|
||||
prefixes = string.punctuation
|
||||
rpairs = {"\007": ""}
|
||||
suffixes = ("moo")
|
||||
prefixes = self.registryValue('prefixes', msg.args[0])
|
||||
suffixes = self.registryValue('suffixes', msg.args[0])
|
||||
if self.registryValue('colorAware') and \
|
||||
self.isChanStripColor(irc, msg.args[0]) and \
|
||||
s.startswith(("\003", "\002", "\017", "\037", "\026")):
|
||||
@ -105,11 +106,13 @@ class NoTrigger(callbacks.Plugin):
|
||||
"CTCP due to config "
|
||||
"plugins.notrigger.blockCtcp.", msg.args[0],
|
||||
irc.network)
|
||||
for k, v in rpairs.items():
|
||||
s = s.replace(k, v)
|
||||
if self.registryValue('blockBell', msg.args[0]):
|
||||
self.log.debug("NoTrigger (%s/%s): removing bell character"
|
||||
"from outgoing message.", msg.args[0], irc.network)
|
||||
s = s.replace('\x07', '')
|
||||
if s.startswith(tuple(prefixes)):
|
||||
s = self.padchar + s
|
||||
if s.endswith(suffixes):
|
||||
if s.endswith(tuple(suffixes)):
|
||||
s += self.padchar
|
||||
msg = ircmsgs.privmsg(msg.args[0], s, msg=msg)
|
||||
return msg
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
from supybot.test import *
|
||||
|
||||
|
||||
class NoTriggerTestCase(ChannelPluginTestCase):
|
||||
plugins = ('NoTrigger', 'Utilities', 'Reply')
|
||||
config = {'supybot.plugins.notrigger.enable': True,
|
||||
@ -39,13 +38,30 @@ class NoTriggerTestCase(ChannelPluginTestCase):
|
||||
|
||||
def testSpaceBeforePrefixes(self):
|
||||
self.assertNotRegexp('echo !test', '^!test$')
|
||||
self.assertNotRegexp('echo $test', '^\$test$')
|
||||
|
||||
def testSpaceBeforeNicks(self):
|
||||
self.assertNotRegexp('echo example: hello', '^example: hello$')
|
||||
self.assertNotRegexp('echo user1, hello', '^user1, hello$')
|
||||
|
||||
def testCTCPBlocking(self):
|
||||
def testBlockCTCP(self):
|
||||
self.assertResponse('echo \x01PING abcd\x01', 'PING abcd')
|
||||
self.assertAction('reply action jumps around', 'jumps around')
|
||||
|
||||
def testBlockBell(self):
|
||||
self.assertResponse('echo \x07', '')
|
||||
self.assertResponse('echo evil bell char\x07', 'evil bell char')
|
||||
|
||||
def testConfigurablePrefixes(self):
|
||||
with conf.supybot.plugins.notrigger.prefixes.context("moo !"):
|
||||
self.assertNotRegexp('echo moo test', '^moo test$')
|
||||
self.assertNotRegexp('echo !test', '^!test$')
|
||||
self.assertResponse('echo .test', '.test')
|
||||
|
||||
def testConfigurableSuffixes(self):
|
||||
with conf.supybot.plugins.notrigger.suffixes.context("abcd +"):
|
||||
self.assertNotRegexp('echo moo test+', '^moo test+$')
|
||||
self.assertNotRegexp('echo 1234 abcd', '^!1234 abcd$')
|
||||
self.assertResponse('echo test-', 'test-')
|
||||
|
||||
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
||||
|
Loading…
x
Reference in New Issue
Block a user