mirror of
https://github.com/jlu5/SupyPlugins.git
synced 2025-04-30 07:21:12 -05:00
RelayNext: yet another crappy antiflood mechanism
Also, catch errors in outFilter so they don't block all of the bot's output.
This commit is contained in:
parent
d0ff6c9a16
commit
f62c6eef73
@ -61,6 +61,20 @@ conf.registerChannelValue(RelayNext, 'noHighlight',
|
||||
registry.Boolean(False, _("""Determines whether the bot should prefix nicks
|
||||
with a hyphen (-) to prevent excess highlights (in PRIVMSGs and actions).""")))
|
||||
|
||||
conf.registerGroup(RelayNext, 'antiflood')
|
||||
conf.registerChannelValue(RelayNext.antiflood, 'enable',
|
||||
registry.Boolean(False, _("""Determines whether flood prevention should be enabled
|
||||
for the given channel.""")))
|
||||
conf.registerChannelValue(RelayNext.antiflood, 'seconds',
|
||||
registry.PositiveInteger(20, _("""Determines how many seconds messages should be queued
|
||||
for flood protection.""")))
|
||||
conf.registerChannelValue(RelayNext.antiflood, 'maximum',
|
||||
registry.PositiveInteger(15, _("""Determines the maximum amount of incoming messages
|
||||
the bot will allow from a relay channel before flood protection is triggered.""")))
|
||||
conf.registerChannelValue(RelayNext.antiflood, 'timeout',
|
||||
registry.PositiveInteger(60, _("""Determines the amount of time in seconds the bot should
|
||||
block messages if flood protection is triggered.""")))
|
||||
|
||||
conf.registerGroup(RelayNext, 'events')
|
||||
|
||||
_events = ('quit', 'join', 'part', 'nick', 'mode', 'kick')
|
||||
|
@ -31,6 +31,7 @@
|
||||
from copy import deepcopy
|
||||
import pickle
|
||||
import re
|
||||
import traceback
|
||||
|
||||
import supybot.world as world
|
||||
import supybot.irclib as irclib
|
||||
@ -41,6 +42,7 @@ from supybot.commands import *
|
||||
import supybot.plugins as plugins
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.callbacks as callbacks
|
||||
from supybot.utils.structures import TimeoutQueue
|
||||
try:
|
||||
from supybot.i18n import PluginInternationalization
|
||||
_ = PluginInternationalization('RelayNext')
|
||||
@ -91,6 +93,10 @@ class RelayNext(callbacks.Plugin):
|
||||
self.ircstates = {}
|
||||
self.lastmsg = {}
|
||||
|
||||
# This part facilitates flood protection
|
||||
self.msgcounters = {}
|
||||
self.floodTriggered = False
|
||||
|
||||
self.db = {}
|
||||
self.loadDB()
|
||||
world.flushers.append(self.exportDB)
|
||||
@ -144,7 +150,7 @@ class RelayNext(callbacks.Plugin):
|
||||
results.append(cn[0])
|
||||
return results
|
||||
|
||||
def _format(self, irc, msg):
|
||||
def _format(self, irc, msg, announcement=False):
|
||||
s = ''
|
||||
nick = msg.nick
|
||||
userhost = ''
|
||||
@ -166,7 +172,10 @@ class RelayNext(callbacks.Plugin):
|
||||
userhost = ' (%s)' % msg.prefix.split('!', 1)[1]
|
||||
except:
|
||||
pass
|
||||
|
||||
if announcement:
|
||||
# Announcements use a special syntax
|
||||
s = '*** %s' % announcement
|
||||
else:
|
||||
if msg.command == 'NICK':
|
||||
newnick = msg.args[0]
|
||||
if color:
|
||||
@ -199,6 +208,12 @@ class RelayNext(callbacks.Plugin):
|
||||
s = s.replace("- -", "-", 1)
|
||||
return s
|
||||
|
||||
def checkFlood(self, channel, source, command):
|
||||
maximum = self.registryValue("antiflood.maximum", channel)
|
||||
enabled = self.registryValue("antiflood.enable", channel)
|
||||
if enabled and len(self.msgcounters[(source, command)]) > maximum:
|
||||
return True
|
||||
|
||||
def relay(self, irc, msg, channel=None):
|
||||
channel = channel or msg.args[0]
|
||||
# Get the source channel
|
||||
@ -206,6 +221,29 @@ class RelayNext(callbacks.Plugin):
|
||||
source = source.lower()
|
||||
out_s = self._format(irc, msg)
|
||||
if out_s:
|
||||
### Begin Flood checking clause
|
||||
timeout = self.registryValue("antiflood.timeout", channel)
|
||||
seconds = self.registryValue("antiflood.seconds", channel)
|
||||
maximum = self.registryValue("antiflood.maximum", channel)
|
||||
try:
|
||||
self.msgcounters[(source, msg.command)].enqueue(msg.prefix)
|
||||
except KeyError:
|
||||
self.msgcounters[(source, msg.command)] = TimeoutQueue(seconds)
|
||||
if self.checkFlood(channel, source, msg.command):
|
||||
self.log.debug("RelayNext (%s): message from %s blocked by "
|
||||
"flood preotection.", irc.network, channel)
|
||||
if self.floodTriggered:
|
||||
return
|
||||
c = msg.command.lower()
|
||||
e = format("Flood detected on %s (%s %ss/%s seconds), "
|
||||
"not relaying %ss for %s seconds!", channel,
|
||||
maximum, c, seconds, c, timeout)
|
||||
out_s = self._format(irc, msg, announcement=e)
|
||||
self.log.info("RelayNext (%s): %s", irc.network, e)
|
||||
self.floodTriggered = True
|
||||
else:
|
||||
self.floodTriggered = False
|
||||
### End Flood checking clause
|
||||
for relay in self.db.values():
|
||||
if source in relay: # If our channel is in a relay
|
||||
# Remove ourselves so we don't get duplicated messages
|
||||
@ -255,11 +293,17 @@ class RelayNext(callbacks.Plugin):
|
||||
def outFilter(self, irc, msg):
|
||||
# Catch our own messages and send them into the relay (this is
|
||||
# useful because Supybot is often a multi-purpose bot!)
|
||||
try:
|
||||
if msg.command == 'PRIVMSG' and not msg.relayedMsg:
|
||||
if msg.args[0] in self._getAllRelaysForNetwork(irc):
|
||||
new_msg = deepcopy(msg)
|
||||
new_msg.nick = irc.nick
|
||||
self.relay(irc, new_msg, channel=msg.args[0])
|
||||
except Exception as e:
|
||||
# We want to log errors, but not block the bot's output
|
||||
traceback.print_exc()
|
||||
log.error(str(e))
|
||||
finally:
|
||||
return msg
|
||||
|
||||
### User commands
|
||||
|
Loading…
x
Reference in New Issue
Block a user