#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ TODO 1) Deprecate "add" (see above) and make it interactive. Slixfeed: Do you still want to add this URL to subscription list? See: case _ if command_lowercase.startswith("add"): 2) If subscription is inadequate (see XmppPresence.request), send a message that says so. elif not self.client_roster[jid]["to"]: breakpoint() message.reply("Share online status to activate bot.").send() return 3) Set timeout for moderator interaction. If moderator interaction has been made, and moderator approves the bot, then the bot will add the given groupchat to bookmarks; otherwise, the bot will send a message that it was not approved and therefore leaves the groupchat. """ import asyncio import os from pathlib import Path from random import randrange # pending_tasks: Use a list and read the first index (i.e. index 0). from slixfeed.config import Config import slixfeed.fetch as fetch from slixfeed.fetch import Http from slixfeed.log import Logger import slixfeed.sqlite as sqlite from slixfeed.syndication import FeedTask from slixfeed.utilities import Database, Documentation, Html, MD, Task, Url from slixfeed.xmpp.commands import XmppCommands from slixfeed.xmpp.message import XmppMessage from slixfeed.xmpp.presence import XmppPresence from slixfeed.xmpp.status import XmppStatusTask from slixfeed.xmpp.upload import XmppUpload from slixfeed.xmpp.utilities import XmppUtilities from slixmpp import JID from slixmpp.stanza import Message import sys import time from typing import Optional try: from slixfeed.xmpp.encryption import XmppOmemo except Exception as e: print('Encryption of type OMEMO is not enabled. Reason: ' + str(e)) logger = Logger(__name__) # for task in main_task: # task.cancel() # Deprecated in favour of event "presence_available" # if not main_task: # await select_file() class XmppChat: async def process_message( self, message: Message, allow_untrusted: bool = False) -> None: """ Process incoming message stanzas. Be aware that this also includes MUC messages and error messages. It is usually a good practice to check the messages's type before processing or sending replies. Parameters ---------- message : str The received message stanza. See the documentation for stanza objects and the Message stanza to see how it may be used. """ message_from = message['from'] message_type = message['type'] if message_type in ('chat', 'groupchat', 'normal'): jid_bare = message_from.bare message_body = message['body'] command = ' '.join(message_body.split()) command_time_start = time.time() if self.omemo_present and self['xep_0384'].is_encrypted(message): command, omemo_decrypted = await XmppOmemo.decrypt( self, message) else: omemo_decrypted = None # FIXME Code repetition. See below. if message_type == 'groupchat': alias = message['muc']['nick'] self_alias = XmppUtilities.get_self_alias(self, jid_bare) if (alias == self_alias or not XmppUtilities.is_moderator(self, jid_bare, alias) or (not message_body.startswith(self_alias + ' ') and not message_body.startswith(self_alias + ',') and not message_body.startswith(self_alias + ':'))): return # Adding one to the length because of # assumption that a comma or a dot is added self_alias_length = len(self_alias) + 1 command = command[self_alias_length:].lstrip() if isinstance(command, Message): command = command['body'] command_lowercase = command.lower() # This is a work-around to empty messages that are caused by function # self.register_handler(CoroutineCallback( of module client.py. # The code was taken from the cho bot xample of slixmpp-omemo. #if not command_lowercase: return logger.debug([message_from.full, ':', command]) # Support private message via groupchat # See https://codeberg.org/poezio/slixmpp/issues/3506 if message_type == 'chat' and message.get_plugin('muc', check=True): # jid_bare = message_from.bare jid_full = message_from.full if (jid_bare == jid_full[:jid_full.index('/')]): # TODO Count and alert of MUC-PM attempts return response = None db_file = Database.instantiate(self.dir_data, jid_bare) match command_lowercase: case 'help': command_list = XmppCommands.print_help(self.dir_config) response = ('Available command keys:\n' f'```\n{command_list}\n```\n' 'Usage: `help `') case 'help all': command_list = Documentation.manual( self.dir_config, section='all') response = ('Complete list of commands:\n' f'```\n{command_list}\n```' .format()) case _ if command_lowercase.startswith('help'): command = command[5:].lower() command = command.split(' ') if len(command) == 2: command_root = command[0] command_name = command[1] command_list = Documentation.manual( self.dir_config, section=command_root, command=command_name) if command_list: command_list = ''.join(command_list) response = (command_list) else: response = f'KeyError for {command_root} {command_name}' elif len(command) == 1: command = command[0] command_list = Documentation.manual( self.dir_config, command) if command_list: command_list = ' '.join(command_list) response = (f'Available command `{command}` keys:\n' f'```\n{command_list}\n```\n' f'Usage: `help {command} `') else: response = f'KeyError for {command}' else: response = ('Invalid. Enter command key ' 'or command key & name') case 'info': entries = XmppCommands.print_info_list(self) response = ('Available command options:\n' f'```\n{entries}\n```\n' 'Usage: `info