From 86679f18e8f442471b2c4fb0d747e19e7d3dc2b9 Mon Sep 17 00:00:00 2001 From: "Schimon Jehudah, Adv." Date: Sun, 15 Sep 2024 15:52:10 +0300 Subject: [PATCH] Add whitelist mechanism; Improve affiliation and role recognition; Atomize functions into module observation. --- kaikout/assets/commands.toml | 14 ++ kaikout/version.py | 4 +- kaikout/xmpp/chat.py | 32 +++++ kaikout/xmpp/client.py | 241 +++-------------------------------- kaikout/xmpp/observation.py | 215 +++++++++++++++++++++++++++++++ kaikout/xmpp/utilities.py | 49 +++---- 6 files changed, 296 insertions(+), 259 deletions(-) create mode 100644 kaikout/xmpp/observation.py diff --git a/kaikout/assets/commands.toml b/kaikout/assets/commands.toml index a038711..f2bd957 100644 --- a/kaikout/assets/commands.toml +++ b/kaikout/assets/commands.toml @@ -51,6 +51,20 @@ goodbye Leave groupchat and delete it from bookmarks. """ +[list] +blacklist = """ +blacklist [+|-] +Jabber IDs to blacklist +comma-separated keywords +'+' appends to, '-' removes from. +""" +whitelist = """ +whitelist [+|-] +Jabber IDs to whitelist +comma-separated keywords +'+' appends to, '-' removes from. +""" + [manual] all = """ help all diff --git a/kaikout/version.py b/kaikout/version.py index d5f14d3..05585a8 100644 --- a/kaikout/version.py +++ b/kaikout/version.py @@ -1,2 +1,2 @@ -__version__ = '0.0.2' -__version_info__ = (0, 0, 2) +__version__ = '0.0.3' +__version_info__ = (0, 0, 3) diff --git a/kaikout/xmpp/chat.py b/kaikout/xmpp/chat.py index 0381595..8a2ec7f 100644 --- a/kaikout/xmpp/chat.py +++ b/kaikout/xmpp/chat.py @@ -194,6 +194,22 @@ class XmppChat: response = None match command_lowercase: + case _ if command_lowercase.startswith('blacklist +'): + value = command[11:].strip() + if value: + response = XmppCommands.set_filter( + self, room, db_file, value, 'jid_blacklist', True) + else: + response = ('No action has been taken. ' + 'Missing Jabber IDs.') + case _ if command_lowercase.startswith('blacklist -'): + value = command[11:].strip() + if value: + response = XmppCommands.set_filter( + self, room, db_file, value, 'jid_blacklist', False) + else: + response = ('No action has been taken. ' + 'Missing Jabber IDs.') case 'help': command_list = XmppCommands.print_help() response = ('Available command keys:\n' @@ -539,6 +555,22 @@ class XmppChat: response = str(self.settings[room]['timer']) case 'version': response = XmppCommands.print_version() + case _ if command_lowercase.startswith('whitelist +'): + value = command[11:].strip() + if value: + response = XmppCommands.set_filter( + self, room, db_file, value, 'jid_whitelist', True) + else: + response = ('No action has been taken. ' + 'Missing Jabber IDs.') + case _ if command_lowercase.startswith('whitelist -'): + value = command[11:].strip() + if value: + response = XmppCommands.set_filter( + self, room, db_file, value, 'jid_whitelist', False) + else: + response = ('No action has been taken. ' + 'Missing Jabber IDs.') case _ if command_lowercase.startswith('xmpp:'): response = await XmppCommands.muc_join(self, command) case _: diff --git a/kaikout/xmpp/client.py b/kaikout/xmpp/client.py index 3a22c6d..8aad441 100644 --- a/kaikout/xmpp/client.py +++ b/kaikout/xmpp/client.py @@ -12,8 +12,8 @@ from kaikout.xmpp.chat import XmppChat from kaikout.xmpp.commands import XmppCommands from kaikout.xmpp.groupchat import XmppGroupchat from kaikout.xmpp.message import XmppMessage -from kaikout.xmpp.moderation import XmppModeration from kaikout.xmpp.muc import XmppMuc +from kaikout.xmpp.observation import XmppObservation from kaikout.xmpp.pubsub import XmppPubsub from kaikout.xmpp.status import XmppStatus import slixmpp @@ -188,71 +188,16 @@ class XmppClient(slixmpp.ClientXMPP): # await XmppChat.process_message(self, message) if (XmppMuc.is_moderator(self, room, self.alias) and self.settings[room]['enabled'] and - alias != self.alias): + alias != self.alias and + jid_bare and + jid_bare not in self.settings[room]['jid_whitelist']): identifier = message['id'] fields = [alias, message_body, identifier, timestamp] Log.toml(self, room, fields, 'message') # Check for message - if self.settings[room]['check_message']: - reason = XmppModeration.moderate_message(self, message_body, room) - if reason: - score_max = self.settings[room]['score_messages'] - score = XmppCommands.raise_score(self, room, alias, db_file, reason) - if score > score_max: - if self.settings[room]['action']: - jid_bare = await XmppCommands.outcast(self, room, alias, reason) - # admins = await XmppMuc.get_affiliation_list(self, room, 'admin') - # owners = await XmppMuc.get_affiliation_list(self, room, 'owner') - moderators = await XmppMuc.get_role_list( - self, room, 'moderator') - # Report to the moderators. - message_to_moderators = ( - 'Participant {} ({}) has been banned from ' - 'groupchat {}.'.format(alias, jid_bare, room)) - for alias in moderators: - jid_full = XmppMuc.get_full_jid(self, room, alias) - XmppMessage.send(self, jid_full, message_to_moderators, 'chat') - # Inform the subject - message_to_participant = ( - 'You were banned from groupchat {}. Please ' - 'contact the moderators if you think this was ' - 'a mistake.'.format(room)) - XmppMessage.send(self, jid_bare, message_to_participant, 'chat') - else: - await XmppCommands.devoice(self, room, alias, reason) + await XmppObservation.observe_message(self, db_file, alias, message_body, room) # Check for inactivity - if self.settings[room]['check_inactivity']: - roster_muc = XmppMuc.get_roster(self, room) - for alias in roster_muc: - if alias != self.alias: - jid_bare = XmppMuc.get_full_jid(self, room, alias).split('/')[0] - result, span = XmppModeration.moderate_last_activity( - self, room, jid_bare, timestamp) - if result: - message_to_participant = None - if 'inactivity_notice' not in self.settings[room]: - self.settings[room]['inactivity_notice'] = [] - noticed_jids = self.settings[room]['inactivity_notice'] - if result == 'Inactivity': - if jid_bare in noticed_jids: noticed_jids.remove(jid_bare) - await XmppCommands.kick(self, room, alias, reason) - message_to_participant = ( - 'You were expelled from groupchat {} due to ' - 'being inactive for {} days.'.format(room, span)) - elif result == 'Warning' and jid_bare not in noticed_jids: - noticed_jids.append(jid_bare) - time_left = int(span) - if not time_left: time_left = 'an' - message_to_participant = ( - 'This is an inactivity-warning.\n' - 'You are expected to be expelled from ' - 'groupchat {} within {} hour time.' - .format(room, int(span) or 'an')) - Toml.update_jid_settings( - self, room, db_file, 'inactivity_notice', noticed_jids) - if message_to_participant: - XmppMessage.send( - self, jid_bare, message_to_participant, 'chat') + await XmppObservation.observe_inactivity(self, db_file, room) async def on_muc_got_online(self, presence): @@ -265,20 +210,12 @@ class XmppClient(slixmpp.ClientXMPP): fields = ['message', timestamp_iso, alias, presence_body, lang, identifier] filename = datetime.today().strftime('%Y-%m-%d') + '_' + room Log.csv(filename, fields) + jid_bare = presence['muc']['jid'].bare if (XmppMuc.is_moderator(self, room, self.alias) and - self.settings[room]['enabled']): - jid = presence['muc']['jid'] - from hashlib import sha256 - jid_to_sha256 = sha256(jid.bare.encode('utf-8')).hexdigest() - for jid in self.blocklist['entries']: - if jid not in self.settings[room]['rtbl_ignore']: - for node in self.blocklist['entries'][jid]: - for item_id in self.blocklist['entries'][jid][node]: - if jid_to_sha256 == item_id: - reason = 'Jabber ID has been marked by RTBL: Publisher: {}; Node: {}.'.format( - jid, node) - await XmppCommands.devoice(self, room, alias, reason) - break + self.settings[room]['enabled'] and + jid_bare and + jid_bare not in self.settings[room]['jid_whitelist']): + await XmppObservation.observe_jid(self, alias, jid_bare, room) # message_body = 'Greetings {} and welcome to groupchat {}'.format(alias, room) # XmppMessage.send(self, jid.bare, message_body, 'chat') # Send MUC-PM in case there is no indication for reception of 1:1 @@ -289,8 +226,7 @@ class XmppClient(slixmpp.ClientXMPP): async def on_muc_presence(self, presence): alias = presence['muc']['nick'] identifier = presence['id'] - jid_full = presence['muc']['jid'] - jid_bare = jid_full.bare + jid_bare = presence['muc']['jid'].bare lang = presence['lang'] status_codes = presence['muc']['status_codes'] actor_alias = presence['muc']['item']['actor']['nick'] @@ -309,159 +245,18 @@ class XmppClient(slixmpp.ClientXMPP): db_file = Toml.instantiate(self, room) if (XmppMuc.is_moderator(self, room, self.alias) and self.settings[room]['enabled'] and - alias != self.alias): + alias != self.alias and + jid_bare and + jid_bare not in self.settings[room]['jid_whitelist']): timestamp = time.time() fields = [alias, presence_body, identifier, timestamp] Log.toml(self, room, fields, 'presence') # Count bans and kicks - if self.settings[room]['check_moderation']: - status_codes = presence['muc']['status_codes'] - if (301 in status_codes or 307 in status_codes): - actor_jid_bare = presence['muc']['item']['actor']['jid'].bare - actor_alias = presence['muc']['item']['actor']['nick'] - if 301 in status_codes: - presence_body = 'User has been banned by {}'.format(actor_alias) - XmppCommands.update_score_ban(self, room, actor_jid_bare, db_file) - elif 307 in status_codes: - presence_body = 'User has been kicked by {}'.format(actor_alias) - XmppCommands.update_score_kick(self, room, actor_jid_bare, db_file) - if 'score_ban' in self.settings[room] and actor_jid_bare in self.settings[room]['score_ban']: - score_ban = self.settings[room]['score_ban'][actor_jid_bare] - else: - score_ban = 0 - if 'score_kick' in self.settings[room] and actor_jid_bare in self.settings[room]['score_kick']: - score_kick = self.settings[room]['score_kick'][actor_jid_bare] - else: - score_kick = 0 - score_outcast = score_ban + score_kick - if score_outcast > self.settings[room]['score_outcast']: - reason = 'Moderation abuse has been triggered' - await XmppMuc.set_affiliation(self, room, 'member', jid=actor_jid_bare, reason=reason) - await XmppMuc.set_role(self, room, actor_alias, 'participant', reason) + await XmppObservation.observe_strikes(self, db_file, presence, room) # Check for status message - if self.settings[room]['check_status']: - reason, timer = XmppModeration.moderate_status_message(self, presence_body, room) - if reason and timer and not (room in self.tasks and - jid_bare in self.tasks[room] and - 'countdown' in self.tasks[room][jid_bare]): - print('reason and timer for jid: ' + jid_bare + ' at room ' + room) - score_max = self.settings[room]['score_presence'] - score = XmppCommands.raise_score(self, room, alias, db_file, reason) - if room not in self.tasks: - self.tasks[room] = {} - if jid_bare not in self.tasks[room]: - self.tasks[room][jid_bare] = {} - # if 'countdown' in self.tasks[room][jid_bare]: - # self.tasks[room][jid_bare]['countdown'].cancel() - if 'countdown' not in self.tasks[room][jid_bare]: - seconds = self.settings[room]['timer'] - self.tasks[room][jid_bare]['countdown'] = asyncio.create_task( - XmppCommands.countdown(self, seconds, room, alias, reason)) - message_to_participant = ( - 'Your status message "{}" violates policies of groupchat ' - '{}.\n' - 'You have {} seconds to change your status message, in ' - 'order to avoid consequent actions.' - .format(presence_body, room, seconds)) - XmppMessage.send(self, jid_bare, message_to_participant, 'chat') - elif reason and not (room in self.tasks - and jid_bare in self.tasks[room] and - 'countdown' in self.tasks[room][jid_bare]): - print('reason for jid: ' + jid_bare + ' at room ' + room) - score_max = self.settings[room]['score_presence'] - score = XmppCommands.raise_score(self, room, alias, db_file, reason) - if score > score_max: - if self.settings[room]['action']: - jid_bare = await XmppCommands.outcast( - self, room, alias, reason) - # admins = await XmppMuc.get_affiliation_list(self, room, 'admin') - # owners = await XmppMuc.get_affiliation_list(self, room, 'owner') - moderators = await XmppMuc.get_role_list( - self, room, 'moderator') - # Report to the moderators. - message_to_moderators = ( - 'Participant {} ({}) has been banned from ' - 'groupchat {}.'.format(alias, jid_bare, room)) - for alias in moderators: - # jid_full = presence['muc']['jid'] - jid_full = XmppMuc.get_full_jid(self, room, alias) - XmppMessage.send(self, jid_full, message_to_moderators, 'chat') - # Inform the subject. - message_to_participant = ( - 'You were banned from groupchat {}. Please ' - 'contact the moderators if you think this was a ' - 'mistake.'.format(room)) - XmppMessage.send(self, jid_bare, message_to_participant, 'chat') - else: - await XmppCommands.devoice(self, room, alias, reason) - elif (room in self.tasks and - jid_bare in self.tasks[room] and - 'countdown' in self.tasks[room][jid_bare]) and not reason: - print('cancel task for jid: ' + jid_bare + ' at room ' + room) - print(self.tasks[room][jid_bare]['countdown']) - if self.tasks[room][jid_bare]['countdown'].cancel(): - print(self.tasks[room][jid_bare]['countdown']) - message_to_participant = 'Thank you for your cooperation.' - XmppMessage.send(self, jid_bare, message_to_participant, 'chat') - del self.tasks[room][jid_bare]['countdown'] + await XmppObservation.observe_status_message(self, alias, db_file, jid_bare, presence_body, room) # Check for inactivity - if self.settings[room]['check_inactivity']: - roster_muc = XmppMuc.get_roster(self, room) - for alias in roster_muc: - if alias != self.alias: - jid_bare = XmppMuc.get_full_jid(self, room, alias).split('/')[0] - result, span = XmppModeration.moderate_last_activity( - self, room, jid_bare, timestamp) - if result: - message_to_participant = None - if 'inactivity_notice' not in self.settings[room]: - self.settings[room]['inactivity_notice'] = [] - noticed_jids = self.settings[room]['inactivity_notice'] - if result == 'Inactivity': - if jid_bare in noticed_jids: noticed_jids.remove(jid_bare) - # FIXME Counting and creating of key entry "score_inactivity" appear not to occur. - score_inactivity = XmppCommands.raise_score_inactivity(self, room, jid_bare, db_file) - if score_inactivity > 10: - jid_bare = await XmppCommands.outcast(self, room, alias, reason) - # admins = await XmppMuc.get_affiliation_list(self, room, 'admin') - # owners = await XmppMuc.get_affiliation_list(self, room, 'owner') - moderators = await XmppMuc.get_role_list( - self, room, 'moderator') - # Report to the moderators. - message_to_moderators = ( - 'Participant {} ({}) has been banned from ' - 'groupchat {} due to being inactive for over {} times.'.format( - alias, jid_bare, room, score_inactivity)) - for alias in moderators: - # jid_full = presence['muc']['jid'] - jid_full = XmppMuc.get_full_jid(self, room, alias) - XmppMessage.send(self, jid_full, message_to_moderators, 'chat') - # Inform the subject. - message_to_participant = ( - 'You were banned from groupchat {} due to being ' - 'inactive for over {} times. Please contact the ' - ' moderators if you think this was a mistake' - .format(room, score_inactivity)) - else: - await XmppCommands.kick(self, room, alias, reason) - message_to_participant = ( - 'You were expelled from groupchat {} due to ' - 'being inactive for over {} days.'.format(room, span)) - XmppCommands.remove_last_activity(self, room, jid_bare, db_file) - elif result == 'Warning' and jid_bare not in noticed_jids: - noticed_jids.append(jid_bare) - time_left = int(span) - if not time_left: time_left = 'an' - message_to_participant = ( - 'This is an inactivity-warning.\n' - 'You are expected to be expelled from ' - 'groupchat {} within {} hour time.' - .format(room, int(span) or 'an')) - Toml.update_jid_settings( - self, room, db_file, 'inactivity_notice', noticed_jids) - if message_to_participant: - XmppMessage.send( - self, jid_bare, message_to_participant, 'chat') + await XmppObservation.observe_inactivity(self, db_file, room) def on_muc_self_presence(self, presence): diff --git a/kaikout/xmpp/observation.py b/kaikout/xmpp/observation.py new file mode 100644 index 0000000..66efdc4 --- /dev/null +++ b/kaikout/xmpp/observation.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import asyncio +from hashlib import sha256 +from kaikout.database import Toml +from kaikout.log import Logger +from kaikout.xmpp.commands import XmppCommands +from kaikout.xmpp.message import XmppMessage +from kaikout.xmpp.moderation import XmppModeration +from kaikout.xmpp.muc import XmppMuc + +logger = Logger(__name__) + +class XmppObservation: + + + async def observe_inactivity(self, db_file, room): + # Check for inactivity + if self.settings[room]['check_inactivity']: + roster_muc = XmppMuc.get_roster(self, room) + for alias in roster_muc: + if alias != self.alias: + jid_bare = XmppMuc.get_full_jid(self, room, alias).split('/')[0] + result, span = XmppModeration.moderate_last_activity( + self, room, jid_bare, timestamp) + if result: + message_to_participant = None + if 'inactivity_notice' not in self.settings[room]: + self.settings[room]['inactivity_notice'] = [] + noticed_jids = self.settings[room]['inactivity_notice'] + if result == 'Inactivity': + if jid_bare in noticed_jids: noticed_jids.remove(jid_bare) + # FIXME Counting and creating of key entry "score_inactivity" appear not to occur. + score_inactivity = XmppCommands.raise_score_inactivity(self, room, jid_bare, db_file) + reason = 'Inactivity detected' + if score_inactivity > 10: + jid_bare = await XmppCommands.outcast(self, room, alias, reason) + # admins = await XmppMuc.get_affiliation_list(self, room, 'admin') + # owners = await XmppMuc.get_affiliation_list(self, room, 'owner') + moderators = await XmppMuc.get_role_list( + self, room, 'moderator') + # Report to the moderators. + message_to_moderators = ( + 'Participant {} ({}) has been banned from ' + 'groupchat {} due to being inactive for over {} times.'.format( + alias, jid_bare, room, score_inactivity)) + for alias in moderators: + # jid_full = presence['muc']['jid'] + jid_full = XmppMuc.get_full_jid(self, room, alias) + XmppMessage.send(self, jid_full, message_to_moderators, 'chat') + # Inform the subject. + message_to_participant = ( + 'You were banned from groupchat {} due to being ' + 'inactive for over {} times. Please contact the ' + ' moderators if you think this was a mistake' + .format(room, score_inactivity)) + else: + await XmppCommands.kick(self, room, alias, reason) + message_to_participant = ( + 'You were expelled from groupchat {} due to ' + 'being inactive for over {} days.'.format(room, span)) + XmppCommands.remove_last_activity(self, room, jid_bare, db_file) + elif result == 'Warning' and jid_bare not in noticed_jids: + noticed_jids.append(jid_bare) + time_left = int(span) + if not time_left: time_left = 'an' + message_to_participant = ( + 'This is an inactivity-warning.\n' + 'You are expected to be expelled from ' + 'groupchat {} within {} hour time.' + .format(room, int(span) or 'an')) + Toml.update_jid_settings( + self, room, db_file, 'inactivity_notice', noticed_jids) + if message_to_participant: + XmppMessage.send( + self, jid_bare, message_to_participant, 'chat') + + + async def observe_jid(self, alias, jid_bare, room): + jid_to_sha256 = sha256(jid_bare.encode('utf-8')).hexdigest() + for jid in self.blocklist['entries']: + if jid not in self.settings[room]['rtbl_ignore']: + for node in self.blocklist['entries'][jid]: + for item_id in self.blocklist['entries'][jid][node]: + if jid_to_sha256 == item_id: + reason = 'Jabber ID has been marked by RTBL: Publisher: {}; Node: {}.'.format( + jid, node) + await XmppCommands.devoice(self, room, alias, reason) + break + + + async def observe_message(self, db_file, alias, message_body, room): + if self.settings[room]['check_message']: + reason = XmppModeration.moderate_message(self, message_body, room) + if reason: + score_max = self.settings[room]['score_messages'] + score = XmppCommands.raise_score(self, room, alias, db_file, reason) + if score > score_max: + if self.settings[room]['action']: + jid_bare = await XmppCommands.outcast(self, room, alias, reason) + # admins = await XmppMuc.get_affiliation_list(self, room, 'admin') + # owners = await XmppMuc.get_affiliation_list(self, room, 'owner') + moderators = await XmppMuc.get_role_list( + self, room, 'moderator') + # Report to the moderators. + message_to_moderators = ( + 'Participant {} ({}) has been banned from ' + 'groupchat {}.'.format(alias, jid_bare, room)) + for alias in moderators: + jid_full = XmppMuc.get_full_jid(self, room, alias) + XmppMessage.send(self, jid_full, message_to_moderators, 'chat') + # Inform the subject + message_to_participant = ( + 'You were banned from groupchat {}. Please ' + 'contact the moderators if you think this was ' + 'a mistake.'.format(room)) + XmppMessage.send(self, jid_bare, message_to_participant, 'chat') + else: + await XmppCommands.devoice(self, room, alias, reason) + + + async def observe_status_message(self, alias, db_file, jid_bare, presence_body, room): + if self.settings[room]['check_status']: + reason, timer = XmppModeration.moderate_status_message(self, presence_body, room) + if reason and timer and not (room in self.tasks and + jid_bare in self.tasks[room] and + 'countdown' in self.tasks[room][jid_bare]): + print('reason and timer for jid: ' + jid_bare + ' at room ' + room) + score_max = self.settings[room]['score_presence'] + score = XmppCommands.raise_score(self, room, alias, db_file, reason) + if room not in self.tasks: + self.tasks[room] = {} + if jid_bare not in self.tasks[room]: + self.tasks[room][jid_bare] = {} + # if 'countdown' in self.tasks[room][jid_bare]: + # self.tasks[room][jid_bare]['countdown'].cancel() + if 'countdown' not in self.tasks[room][jid_bare]: + seconds = self.settings[room]['timer'] + self.tasks[room][jid_bare]['countdown'] = asyncio.create_task( + XmppCommands.countdown(self, seconds, room, alias, reason)) + message_to_participant = ( + 'Your status message "{}" violates policies of groupchat ' + '{}.\n' + 'You have {} seconds to change your status message, in ' + 'order to avoid consequent actions.' + .format(presence_body, room, seconds)) + XmppMessage.send(self, jid_bare, message_to_participant, 'chat') + elif reason and not (room in self.tasks + and jid_bare in self.tasks[room] and + 'countdown' in self.tasks[room][jid_bare]): + print('reason for jid: ' + jid_bare + ' at room ' + room) + score_max = self.settings[room]['score_presence'] + score = XmppCommands.raise_score(self, room, alias, db_file, reason) + if score > score_max: + if self.settings[room]['action']: + jid_bare = await XmppCommands.outcast( + self, room, alias, reason) + # admins = await XmppMuc.get_affiliation_list(self, room, 'admin') + # owners = await XmppMuc.get_affiliation_list(self, room, 'owner') + moderators = await XmppMuc.get_role_list( + self, room, 'moderator') + # Report to the moderators. + message_to_moderators = ( + 'Participant {} ({}) has been banned from ' + 'groupchat {}.'.format(alias, jid_bare, room)) + for alias in moderators: + # jid_full = presence['muc']['jid'] + jid_full = XmppMuc.get_full_jid(self, room, alias) + XmppMessage.send(self, jid_full, message_to_moderators, 'chat') + # Inform the subject. + message_to_participant = ( + 'You were banned from groupchat {}. Please ' + 'contact the moderators if you think this was a ' + 'mistake.'.format(room)) + XmppMessage.send(self, jid_bare, message_to_participant, 'chat') + else: + await XmppCommands.devoice(self, room, alias, reason) + elif (room in self.tasks and + jid_bare in self.tasks[room] and + 'countdown' in self.tasks[room][jid_bare]) and not reason: + print('cancel task for jid: ' + jid_bare + ' at room ' + room) + print(self.tasks[room][jid_bare]['countdown']) + if self.tasks[room][jid_bare]['countdown'].cancel(): + print(self.tasks[room][jid_bare]['countdown']) + message_to_participant = 'Thank you for your cooperation.' + XmppMessage.send(self, jid_bare, message_to_participant, 'chat') + del self.tasks[room][jid_bare]['countdown'] + + + async def observe_strikes(self, db_file, presence, room): + if self.settings[room]['check_moderation']: + status_codes = presence['muc']['status_codes'] + if (301 in status_codes or 307 in status_codes): + actor_jid_bare = presence['muc']['item']['actor']['jid'].bare + actor_alias = presence['muc']['item']['actor']['nick'] + if 301 in status_codes: + presence_body = 'User has been banned by {}'.format(actor_alias) + XmppCommands.update_score_ban(self, room, actor_jid_bare, db_file) + elif 307 in status_codes: + presence_body = 'User has been kicked by {}'.format(actor_alias) + XmppCommands.update_score_kick(self, room, actor_jid_bare, db_file) + if 'score_ban' in self.settings[room] and actor_jid_bare in self.settings[room]['score_ban']: + score_ban = self.settings[room]['score_ban'][actor_jid_bare] + else: + score_ban = 0 + if 'score_kick' in self.settings[room] and actor_jid_bare in self.settings[room]['score_kick']: + score_kick = self.settings[room]['score_kick'][actor_jid_bare] + else: + score_kick = 0 + score_outcast = score_ban + score_kick + if score_outcast > self.settings[room]['score_outcast']: + reason = 'Moderation abuse has been triggered' + await XmppMuc.set_affiliation(self, room, 'member', jid=actor_jid_bare, reason=reason) + await XmppMuc.set_role(self, room, actor_alias, 'participant', reason) diff --git a/kaikout/xmpp/utilities.py b/kaikout/xmpp/utilities.py index ec85216..02f1cd1 100644 --- a/kaikout/xmpp/utilities.py +++ b/kaikout/xmpp/utilities.py @@ -10,7 +10,6 @@ logger = Logger(__name__) class XmppUtilities: - async def is_jid_of_moderators(self, room, jid_full): # try: moderators = await XmppMuc.get_role_list(self, room, 'moderator') @@ -26,7 +25,7 @@ class XmppUtilities: async def get_chat_type(self, jid): """ Check chat (i.e. JID) type. - + If iqresult["disco_info"]["features"] contains XML namespace of 'http://jabber.org/protocol/muc', then it is a 'groupchat'. @@ -34,12 +33,12 @@ class XmppUtilities: a chat which is conducted through a groupchat. Otherwise, determine type 'chat'. - + Parameters ---------- jid : str Jabber ID. - + Returns ------- result : str @@ -69,8 +68,6 @@ class XmppUtilities: # logger.info('Chat type is:', chat_type) return result - - def is_access(self, jid_bare, jid_full, chat_type): """Determine access privilege""" operator = XmppUtilities.is_operator(self, jid_bare) @@ -83,8 +80,7 @@ class XmppUtilities: else: access = False return access - - + def is_operator(self, jid_bare): """Check if given JID is an operator""" result = False @@ -94,44 +90,29 @@ class XmppUtilities: # operator_name = operator['name'] break return result - - + def is_admin(self, room, alias): """Check if given JID is an administrator""" - role = self.plugin['xep_0045'].get_jid_property(room, alias, 'affiliation') - if role == 'admin': - result = True - else: - result = False + affiliation = self.plugin['xep_0045'].get_jid_property(room, alias, 'affiliation') + result = True if affiliation == 'admin' else False return result - - + def is_owner(self, room, alias): """Check if given JID is an owner""" - role = self.plugin['xep_0045'].get_jid_property(room, alias, 'affiliation') - if role == 'owner': - result = True - else: - result = False + affiliation = self.plugin['xep_0045'].get_jid_property(room, alias, 'affiliation') + result = True if affiliation == 'owner' else False return result - - + def is_moderator(self, room, alias): """Check if given JID is a moderator""" role = self.plugin['xep_0045'].get_jid_property(room, alias, 'role') - if role == 'moderator': - result = True - else: - result = False + result = True if role == 'moderator' else False return result - - + + # NOTE Would this properly work when Alias and Local differ? def is_member(self, jid_bare, jid_full): """Check if given JID is a member""" alias = jid_full[jid_full.index('/')+1:] affiliation = self.plugin['xep_0045'].get_jid_property(jid_bare, alias, 'affiliation') - if affiliation == 'member': - result = True - else: - result = False + result = True if affiliation == 'member' else False return result