From e1ff749af5e6fa7f31308d685f3a67b487f8f170 Mon Sep 17 00:00:00 2001 From: kaliko Date: Sat, 18 Mar 2023 09:16:40 +0100 Subject: [PATCH] Add rtbl pluglin --- sid/rtbl.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 sid/rtbl.py diff --git a/sid/rtbl.py b/sid/rtbl.py new file mode 100644 index 0000000..d701aa5 --- /dev/null +++ b/sid/rtbl.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: 2014, 2020, 2023 kaliko +# SPDX-FileCopyrightText: 2007-2012 Thomas Perl +# SPDX-License-Identifier: GPL-3.0-or-later + +from hashlib import sha256 + +from slixmpp.exceptions import XMPPError +from slixmpp.xmlstream import tostring + +from .plugin import Plugin + + +class RTBL(Plugin): + """Spam guard for MUC + """ + pubsub_server = 'example.org' + node = 'muc_bans_sha256' + + def __init__(self, bot): + Plugin.__init__(self, bot) + bot.register_plugin('xep_0059') # Mediated Information eXchange (MIX) + bot.register_plugin('xep_0060') # Publish-Subscribe + self.handlers = [ + ('session_start', self._subscribe), + ('pubsub_retract', self._retract), + ('pubsub_publish', self._publish) + ] + self.add_handlers() + self.blocklist = None + self.bot = bot + + def _exit(self): + self.rm_handlers() + self.bot.unregister_bot_plugin(self) + + async def _subscribe(self, *args, **kwargs): + try: + nodes = await self.bot['xep_0060'].get_nodes(self.pubsub_server) + nodes_av = [_.get('node') for _ in nodes['disco_items']] + self.log.debug(f'nodes available: {nodes_av}') + if self.node not in nodes_av: + self.log.error(f'{self.node} node not available on {self.pubsub_server}') + await self._create() + iq = await self.bot['xep_0060'].subscribe(self.pubsub_server, self.node) + subscription = iq['pubsub']['subscription'] + self.log.info('Subscribed %s to node %s', subscription['jid'], subscription['node']) + except XMPPError as error: + self.log.error('Could not subscribe %s to node %s: %s', + self.bot.boundjid.bare, self.node, error.format()) + self._exit() + return + self.blocklist = await self.bot['xep_0060'].get_items(self.pubsub_server, self.node) + message = f'Got {len(self.blocklist["pubsub"]["items"])} items in block list' + self.log.info(message) + # Add got_online handler once the blocklist is set + self.bot.add_event_handler(f'muc::{self.bot.room}::got_online', self.got_online) + + async def _create(self): + """Try to create node""" + try: + await self.bot['xep_0060'].create_node(self.pubsub_server, self.node) + self.log.info('Created node %s', self.node) + except XMPPError as err: + self.log.error('Could not create node %s: %s', self.node, err.format()) + raise XMPPError(f'Could not create node {self.node}') from err + + def _retract(self, msg): + """Handler receiving a retract item event.""" + self.log.debug('Retracted item %s from %s' % ( + msg['pubsub_event']['items']['retract']['id'], + msg['pubsub_event']['items']['node'])) + + async def _publish(self, msg): + """Handler receiving a publish item event.""" + self.log.debug('Published item %s to %s:' % ( + msg['pubsub_event']['items']['item']['id'], + msg['pubsub_event']['items']['node'])) + data = msg['pubsub_event']['items']['item']['payload'] + if data is not None: + self.log.debug(tostring(data)) + else: + self.log.debug('No item content') + self.blocklist = await self.bot['xep_0060'].get_items(self.pubsub_server, self.node) + + async def got_online(self, pres): + """Handler method for new MUC participants""" + bjid = pres['muc']['jid'].bare + bjid_hash = sha256(bjid.encode('utf-8')).hexdigest() + if bjid_hash in [_['id'] for _ in self.blocklist['pubsub']['items']]: + self.log.debug(f'About to ban {bjid}') + await self.ban(bjid, reason='rtbl ') + +# VIM MODLINE +# vim: ai ts=4 sw=4 sts=4 expandtab -- 2.39.2