Michael H 8756b22f5a [V3] Report Tool (#1281)
* Okay, let's fix the issues here hopefully.

* This is working now

* Unfinished, and needs a lot of testing.

* more work

* working

* minor thing to remove

* improve i18n and usage feedback
2018-04-16 13:56:14 -08:00

63 lines
2.0 KiB
Python

from datetime import datetime, timedelta
from typing import Tuple, List
from collections import namedtuple
Interval = Tuple[timedelta, int]
AntiSpamInterval = namedtuple('AntiSpamInterval', ['period', 'frequency'])
class AntiSpam:
"""
Custom class which is more flexible than using discord.py's
`commands.cooldown()`
Can be intialized with a custom set of intervals
These should be provided as a list of tuples in the form
(timedelta, quantity)
Where quantity represents the maximum amount of times
something should be allowed in an interval.
"""
# TODO : Decorator interface for command check using `spammy`
# with insertion of the antispam element into context
# for manual stamping on succesful command completion
default_intervals = [
(timedelta(seconds=5), 3),
(timedelta(minutes=1), 5),
(timedelta(hours=1), 10),
(timedelta(days=1), 24)
]
def __init__(self, intervals: List[Interval]):
self.__event_timestamps = []
_itvs = intervals if intervals else self.default_intervals
self.__intervals = [
AntiSpamInterval(*x) for x in _itvs
]
self.__discard_after = max([x.period for x in self.__intervals])
def __interval_check(self, interval: AntiSpamInterval):
return len(
[t for t in self.__event_timestamps
if (t + interval.period) > datetime.utcnow()]
) >= interval.frequency
@property
def spammy(self):
"""
use this to check if any interval criteria are met
"""
return any(self.__interval_check(x) for x in self.__intervals)
def stamp(self):
"""
Use this to mark an event that counts against the intervals
as happening now
"""
self.__event_timestamps.append(datetime.utcnow())
self.__event_timestamps = [
t for t in self.__event_timestamps
if t + self.__discard_after > datetime.utcnow()
]