Add initial flood prevention

This commit is contained in:
Tulir Asokan 2019-06-23 14:14:28 +03:00
parent 8e16575d3b
commit 85a7967888
3 changed files with 39 additions and 2 deletions

View file

@ -29,6 +29,10 @@ templates:
default_flags:
- ignorecase
antispam:
max: 2
delay: 60
rules:
twim_cookies:
rooms: ["!FPUfgzXYWTKgIrwKxW:matrix.org"]

View file

@ -13,9 +13,12 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Type, Tuple
from typing import Type, Tuple, Dict
import time
from mautrix.types import EventType, MessageType
from attr import dataclass
from mautrix.types import EventType, MessageType, UserID, RoomID
from mautrix.util.config import BaseProxyConfig
from maubot import Plugin, MessageEvent
@ -24,8 +27,27 @@ from maubot.handlers import event
from .config import Config, ConfigError
@dataclass
class FloodInfo:
rb: 'ReactBot'
count: int
last_message: int
def bump(self) -> bool:
now = int(time.time())
if self.last_message + self.rb.config["antispam.delay"] < now:
self.count = 0
self.count += 1
if self.count > self.rb.config["antispam.max"]:
return True
self.last_message = now
return False
class ReactBot(Plugin):
allowed_msgtypes: Tuple[MessageType, ...] = (MessageType.TEXT, MessageType.EMOTE)
user_flood: Dict[UserID, FloodInfo]
room_flood: Dict[RoomID, FloodInfo]
@classmethod
def get_config_class(cls) -> Type[BaseProxyConfig]:
@ -33,6 +55,8 @@ class ReactBot(Plugin):
async def start(self) -> None:
await super().start()
self.user_flood = {}
self.room_flood = {}
self.on_external_config_update()
def on_external_config_update(self) -> None:
@ -42,6 +66,11 @@ class ReactBot(Plugin):
except ConfigError:
self.log.exception("Failed to load config")
def is_flood(self, evt: MessageEvent) -> bool:
uf = self.user_flood.setdefault(evt.sender, FloodInfo(rb=self, count=0, last_message=0))
rf = self.room_flood.setdefault(evt.room_id, FloodInfo(rb=self, count=0, last_message=0))
return uf.bump() or rf.bump()
@event.on(EventType.ROOM_MESSAGE)
async def event_handler(self, evt: MessageEvent) -> None:
if evt.sender == self.client.mxid or evt.content.msgtype not in self.allowed_msgtypes:
@ -49,6 +78,8 @@ class ReactBot(Plugin):
for name, rule in self.config.rules.items():
match = rule.match(evt)
if match is not None:
if self.is_flood(evt):
return
try:
await rule.execute(evt, match)
except Exception:

View file

@ -37,6 +37,8 @@ class Config(BaseProxyConfig):
helper.copy("rules")
helper.copy("templates")
helper.copy("default_flags")
helper.copy("antispam.max")
helper.copy("antispam.delay")
def parse_data(self) -> None:
self.default_flags = re.RegexFlag(0)