mirror of
https://github.com/jlu5/SupyPlugins.git
synced 2025-04-27 05:21:10 -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
|
## Short description
|
||||||
In short, NoTrigger works by:
|
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).
|
- 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, 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, 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
|
## 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!
|
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.conf as conf
|
||||||
import supybot.registry as registry
|
import supybot.registry as registry
|
||||||
try:
|
try:
|
||||||
@ -38,7 +40,6 @@ except:
|
|||||||
# without the i18n module
|
# without the i18n module
|
||||||
_ = lambda x: x
|
_ = lambda x: x
|
||||||
|
|
||||||
|
|
||||||
def configure(advanced):
|
def configure(advanced):
|
||||||
# This will be called by supybot to configure this module. advanced is
|
# This will be called by supybot to configure this module. advanced is
|
||||||
# a bool that specifies whether the user identified himself as an advanced
|
# a bool that specifies whether the user identified himself as an advanced
|
||||||
@ -54,20 +55,30 @@ conf.registerChannelValue(NoTrigger, 'enable',
|
|||||||
conf.registerChannelValue(NoTrigger, 'spaceBeforeNicks',
|
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
|
"blah: " or "blah, ", preventing the bot from triggering other bots that
|
||||||
respond to nick. This can cause some weird spacings with error messages and
|
respond to nick.""")))
|
||||||
other command replies, so I wouldn't recommend enabling it unless absolutely
|
|
||||||
necessary.""")))
|
|
||||||
conf.registerChannelValue(NoTrigger, 'colorAware',
|
conf.registerChannelValue(NoTrigger, 'colorAware',
|
||||||
registry.Boolean(True, _("""Toggles whether the bot should be aware of colour-stripping
|
registry.Boolean(True, _("""Toggles whether the bot should be aware of color-stripping
|
||||||
modes. (+c or +S on most IRCds)""")))
|
channel modes (+c or +S on most IRCds).""")))
|
||||||
conf.registerGroup(NoTrigger, 'colorAware')
|
|
||||||
conf.registerChannelValue(NoTrigger.colorAware, 'modes',
|
conf.registerChannelValue(NoTrigger.colorAware, 'modes',
|
||||||
registry.SpaceSeparatedListOfStrings("c S", _("""Determines a list of modes that should
|
registry.SpaceSeparatedListOfStrings("c S", _("""Defines a space-separated list of modes that should
|
||||||
be treated as colour-blocking modes. This is usually +c (block) and +S (stripcolour) on
|
be treated as color-blocking modes. This is usually +c (block) and +S (stripcolour) on
|
||||||
UnrealIRCd/InspIRCd, and just +c (stripcolour) on charybdis-based daemons.""")))
|
UnrealIRCd/InspIRCd, and just +c (stripcolor) on charybdis-based daemons.""")))
|
||||||
|
|
||||||
conf.registerChannelValue(NoTrigger, 'blockCtcp',
|
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.""")))
|
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:
|
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
||||||
|
@ -46,13 +46,13 @@ except ImportError:
|
|||||||
|
|
||||||
|
|
||||||
class NoTrigger(callbacks.Plugin):
|
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):
|
def __init__(self, irc):
|
||||||
self.__parent = super(NoTrigger, self)
|
self.__parent = super(NoTrigger, self)
|
||||||
self.__parent.__init__(irc)
|
self.__parent.__init__(irc)
|
||||||
# This uses Unicode Character 'ZERO WIDTH SPACE' (U+200B) for
|
# This appends the Unicode character 'ZERO WIDTH SPACE' (U+200B) for
|
||||||
# padding, which looks nicer (it's invisible) and does the trick.
|
# which is absolutely invisible and stops bots from being triggered by us.
|
||||||
if version_info[0] >= 3:
|
if version_info[0] >= 3:
|
||||||
self.padchar = "\u200B"
|
self.padchar = "\u200B"
|
||||||
else:
|
else:
|
||||||
@ -60,6 +60,8 @@ class NoTrigger(callbacks.Plugin):
|
|||||||
self.padchar = u('\u200B')[0]
|
self.padchar = u('\u200B')[0]
|
||||||
|
|
||||||
def isChanStripColor(self, irc, channel):
|
def isChanStripColor(self, irc, channel):
|
||||||
|
"""Returns whether the given channel has a color-stripping mode (usually
|
||||||
|
+c or +S, but configurable) set."""
|
||||||
try:
|
try:
|
||||||
c = irc.state.channels[channel]
|
c = irc.state.channels[channel]
|
||||||
for item in self.registryValue('colorAware.modes'):
|
for item in self.registryValue('colorAware.modes'):
|
||||||
@ -74,9 +76,8 @@ class NoTrigger(callbacks.Plugin):
|
|||||||
ircutils.isChannel(msg.args[0]) and \
|
ircutils.isChannel(msg.args[0]) and \
|
||||||
self.registryValue('enable', msg.args[0]):
|
self.registryValue('enable', msg.args[0]):
|
||||||
s = msg.args[1]
|
s = msg.args[1]
|
||||||
prefixes = string.punctuation
|
prefixes = self.registryValue('prefixes', msg.args[0])
|
||||||
rpairs = {"\007": ""}
|
suffixes = self.registryValue('suffixes', msg.args[0])
|
||||||
suffixes = ("moo")
|
|
||||||
if self.registryValue('colorAware') and \
|
if self.registryValue('colorAware') and \
|
||||||
self.isChanStripColor(irc, msg.args[0]) and \
|
self.isChanStripColor(irc, msg.args[0]) and \
|
||||||
s.startswith(("\003", "\002", "\017", "\037", "\026")):
|
s.startswith(("\003", "\002", "\017", "\037", "\026")):
|
||||||
@ -105,11 +106,13 @@ class NoTrigger(callbacks.Plugin):
|
|||||||
"CTCP due to config "
|
"CTCP due to config "
|
||||||
"plugins.notrigger.blockCtcp.", msg.args[0],
|
"plugins.notrigger.blockCtcp.", msg.args[0],
|
||||||
irc.network)
|
irc.network)
|
||||||
for k, v in rpairs.items():
|
if self.registryValue('blockBell', msg.args[0]):
|
||||||
s = s.replace(k, v)
|
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)):
|
if s.startswith(tuple(prefixes)):
|
||||||
s = self.padchar + s
|
s = self.padchar + s
|
||||||
if s.endswith(suffixes):
|
if s.endswith(tuple(suffixes)):
|
||||||
s += self.padchar
|
s += self.padchar
|
||||||
msg = ircmsgs.privmsg(msg.args[0], s, msg=msg)
|
msg = ircmsgs.privmsg(msg.args[0], s, msg=msg)
|
||||||
return msg
|
return msg
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
|
|
||||||
from supybot.test import *
|
from supybot.test import *
|
||||||
|
|
||||||
|
|
||||||
class NoTriggerTestCase(ChannelPluginTestCase):
|
class NoTriggerTestCase(ChannelPluginTestCase):
|
||||||
plugins = ('NoTrigger', 'Utilities', 'Reply')
|
plugins = ('NoTrigger', 'Utilities', 'Reply')
|
||||||
config = {'supybot.plugins.notrigger.enable': True,
|
config = {'supybot.plugins.notrigger.enable': True,
|
||||||
@ -39,13 +38,30 @@ class NoTriggerTestCase(ChannelPluginTestCase):
|
|||||||
|
|
||||||
def testSpaceBeforePrefixes(self):
|
def testSpaceBeforePrefixes(self):
|
||||||
self.assertNotRegexp('echo !test', '^!test$')
|
self.assertNotRegexp('echo !test', '^!test$')
|
||||||
|
self.assertNotRegexp('echo $test', '^\$test$')
|
||||||
|
|
||||||
def testSpaceBeforeNicks(self):
|
def testSpaceBeforeNicks(self):
|
||||||
self.assertNotRegexp('echo example: hello', '^example: hello$')
|
self.assertNotRegexp('echo example: hello', '^example: hello$')
|
||||||
self.assertNotRegexp('echo user1, hello', '^user1, hello$')
|
self.assertNotRegexp('echo user1, hello', '^user1, hello$')
|
||||||
|
|
||||||
def testCTCPBlocking(self):
|
def testBlockCTCP(self):
|
||||||
self.assertResponse('echo \x01PING abcd\x01', 'PING abcd')
|
self.assertResponse('echo \x01PING abcd\x01', 'PING abcd')
|
||||||
self.assertAction('reply action jumps around', 'jumps around')
|
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:
|
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user