Removed crazy-buggy rate limiting stuff.

This commit is contained in:
Jeremy Fincher 2003-11-04 08:05:16 +00:00
parent 94e3726b82
commit 65e469ba38
2 changed files with 16 additions and 117 deletions

View File

@ -109,8 +109,6 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
callbacks.Privmsg.handled = False callbacks.Privmsg.handled = False
if ircdb.checkIgnored(msg.prefix, msg.args[0]):
return
s = callbacks.addressed(irc.nick, msg) s = callbacks.addressed(irc.nick, msg)
if s: if s:
try: try:

View File

@ -135,78 +135,6 @@ def getSyntax(method, name=None):
doclines = method.__doc__.splitlines() doclines = method.__doc__.splitlines()
return '%s %s' % (name, doclines[0]) return '%s %s' % (name, doclines[0])
class RateLimiter:
"""This class is used to rate limit replies to certain people, in order to
prevent abuse of the bot. Basically, you put messages in with the .put
method, and then take a message out with the .get method. .get may return
None if there is no message waiting that isn't being rate limited.
"""
# lastRequest must be class-global, so each instance of it uses the same
# information. Otherwise, if it was an instance variable, then rate
# limiting would only work within a single plugin.
lastRequest = {}
def __init__(self):
self.limited = []
self.unlimited = []
def get(self):
"""Returns the next un-ratelimited message, or the next rate-limited
message whose time has come up."""
if self.unlimited:
return self.unlimited.pop(0)
elif self.limited:
for i in range(len(self.limited)):
msg = self.limited[i]
if not self._limit(msg, penalize=False):
return self.limited.pop(i)
return None
else:
return None
def put(self, msg):
"""Puts a message in for possible ratelimiting."""
t = self._limit(msg)
if t and not world.testing:
s = 'Limiting message from %s for %s seconds' % (msg.prefix, t)
debug.msg(s, 'normal')
self.limited.append(msg)
else:
self.unlimited.append(msg)
def _limit(self, msg, penalize=True):
if msg.prefix and ircutils.isUserHostmask(msg.prefix):
(nick, user, host) = ircutils.splitHostmask(msg.prefix)
key = '@'.join((user, host))
now = time.time()
if ircdb.checkCapabilities(msg.prefix, ('owner', 'admin')):
return 0
if key in self.lastRequest:
# Here's how we throttle requests. We keep a dictionary of
# (lastRequest, wait period) tuples. When a request arrives,
# we check to see if we have a lastRequest tuple, and if so,
# we check to make sure that lastRequest was more than wait
# seconds ago. If not, we're getting flooded, and we set
# the lastRequest time to the current time and increment wait,
# thus making it even harder for the flooder to get us to
# send them messages.
(t, wait) = self.lastRequest[key]
if now - t <= wait:
if penalize:
newWait = wait + conf.throttleTime
else:
newWait = wait - (now - t)
self.lastRequest[key] = (now, newWait)
return newWait
else:
self.lastRequest[key] = (now, conf.throttleTime)
return 0
else:
self.lastRequest[key] = (now, conf.throttleTime)
return 0
else:
return 0
class Error(Exception): class Error(Exception):
"""Generic class for errors in Privmsg callbacks.""" """Generic class for errors in Privmsg callbacks."""
pass pass
@ -597,10 +525,10 @@ class Privmsg(irclib.IrcCallback):
public = True public = True
handled = False handled = False
alwaysCall = () alwaysCall = ()
noIgnore = False
commandArgs = ['self', 'irc', 'msg', 'args'] commandArgs = ['self', 'irc', 'msg', 'args']
_mores = {} # This must be class-scope, so all subclasses use the same one. _mores = {} # This must be class-scope, so all subclasses use the same one.
def __init__(self): def __init__(self):
self.rateLimiter = RateLimiter()
self.Proxy = IrcObjectProxy self.Proxy = IrcObjectProxy
canonicalname = canonicalName(self.name()) canonicalname = canonicalName(self.name())
self._original = getattr(self, canonicalname, None) self._original = getattr(self, canonicalname, None)
@ -658,17 +586,13 @@ class Privmsg(irclib.IrcCallback):
world.startup = False world.startup = False
def __call__(self, irc, msg): def __call__(self, irc, msg):
irclib.IrcCallback.__call__(self, irc, msg) if msg.command == 'PRIVMSG':
# Now, if there's anything in the rateLimiter... if self.noIgnore or not ircdb.checkIgnored(msg.prefix,msg.args[0]):
msg = self.rateLimiter.get() irclib.IrcCallback.__call__(self, irc, msg)
while msg: else:
s = addressed(irc.nick, msg) debug.msg('Ignoring %s.' % msg.prefix)
try: else:
args = tokenize(s) irclib.IrcCallback.__call__(self, irc, msg)
self.Proxy(irc, msg, args)
except SyntaxError, e:
irc.queueMsg(reply(msg, str(e)))
msg = self.rateLimiter.get()
def isCommand(self, methodName): def isCommand(self, methodName):
# This function is ugly, but I don't want users to call methods like # This function is ugly, but I don't want users to call methods like
@ -734,7 +658,6 @@ class PrivmsgRegexp(Privmsg):
better class to use, at the very least for consistency's sake, but also better class to use, at the very least for consistency's sake, but also
because it's much more easily coded and maintained. because it's much more easily coded and maintained.
""" """
threaded = False # Again, like Privmsg...
flags = re.I flags = re.I
commandArgs = ['self', 'irc', 'msg', 'match'] commandArgs = ['self', 'irc', 'msg', 'match']
def __init__(self): def __init__(self):
@ -763,10 +686,6 @@ class PrivmsgRegexp(Privmsg):
irc.error(msg, debug.exnToString(e)) irc.error(msg, debug.exnToString(e))
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
if ircdb.checkIgnored(msg.prefix, msg.args[0]):
debug.msg('PrivmsgRegexp.doPrivmsg: ignoring %s' % msg.prefix)
return
fed = False
for (r, method) in self.res: for (r, method) in self.res:
spans = sets.Set() spans = sets.Set()
for m in r.finditer(msg.args[1]): for m in r.finditer(msg.args[1]):
@ -775,13 +694,8 @@ class PrivmsgRegexp(Privmsg):
break break
else: else:
spans.add(m.span()) spans.add(m.span())
if not fed: proxy = IrcObjectProxyRegexp(irc)
fed = True self.callCommand(method, proxy, msg, m)
self.rateLimiter.put(msg)
msg = self.rateLimiter.get()
if msg:
proxy = IrcObjectProxyRegexp(irc)
self.callCommand(method, proxy, msg, m)
class PrivmsgCommandAndRegexp(Privmsg): class PrivmsgCommandAndRegexp(Privmsg):
@ -790,8 +704,8 @@ class PrivmsgCommandAndRegexp(Privmsg):
(or list) attribute "regexps". (or list) attribute "regexps".
""" """
flags = re.I flags = re.I
regexps = () # Use sets.Set() in your own callbacks. regexps = ()
addressedRegexps = () # Ditto on the sets.Sets() idea. addressedRegexps = ()
def __init__(self): def __init__(self):
Privmsg.__init__(self) Privmsg.__init__(self)
self.res = [] self.res = []
@ -816,22 +730,14 @@ class PrivmsgCommandAndRegexp(Privmsg):
raise raise
def doPrivmsg(self, irc, msg): def doPrivmsg(self, irc, msg):
if ircdb.checkIgnored(msg.prefix, msg.args[0]):
return
fed = False
for (r, method) in self.res: for (r, method) in self.res:
originalHandled = self.handled originalHandled = self.handled
name = method.__name__ name = method.__name__
for m in r.finditer(msg.args[1]): for m in r.finditer(msg.args[1]):
if originalHandled and name not in self.alwaysCall: if originalHandled and name not in self.alwaysCall:
continue continue
if not fed: proxy = IrcObjectProxyRegexp(irc)
fed = True self.callCommand(method, proxy, msg, m, catchErrors=True)
self.rateLimiter.put(msg)
msg = self.rateLimiter.get()
if msg:
proxy = IrcObjectProxyRegexp(irc)
self.callCommand(method, proxy, msg, m, catchErrors=True)
s = addressed(irc.nick, msg) s = addressed(irc.nick, msg)
if s: if s:
for (r, method) in self.addressedRes: for (r, method) in self.addressedRes:
@ -840,13 +746,8 @@ class PrivmsgCommandAndRegexp(Privmsg):
for m in r.finditer(s): for m in r.finditer(s):
if originalHandled and name not in self.alwaysCall: if originalHandled and name not in self.alwaysCall:
continue continue
if not fed: proxy = IrcObjectProxyRegexp(irc)
fed = True self.callCommand(method,proxy,msg,m,catchErrors=True)
self.rateLimiter.put(msg)
msg = self.rateLimiter.get()
if msg:
proxy = IrcObjectProxyRegexp(irc)
self.callCommand(method,proxy,msg,m,catchErrors=True)
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: