#!/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 from feedparser import parse import logging import os import slixfeed.action as action import slixfeed.config as config import slixfeed.crawl as crawl from slixfeed.config import Config import slixfeed.dt as dt import slixfeed.fetch as fetch import slixfeed.sqlite as sqlite import slixfeed.task as task import slixfeed.url as uri from slixfeed.version import __version__ from slixfeed.xmpp.bookmark import XmppBookmark from slixfeed.xmpp.commands import XmppCommands from slixfeed.xmpp.muc import XmppGroupchat from slixfeed.xmpp.message import XmppMessage from slixfeed.xmpp.presence import XmppPresence from slixfeed.xmpp.publish import XmppPubsub from slixfeed.xmpp.upload import XmppUpload from slixfeed.xmpp.privilege import is_moderator, is_operator, is_access from slixfeed.xmpp.utility import get_chat_type import time from random import randrange try: import tomllib except: import tomli as tomllib # for task in main_task: # task.cancel() # Deprecated in favour of event "presence_available" # if not main_task: # await select_file() class Chat: async def process_message(self, message): """ 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. """ if message['type'] in ('chat', 'groupchat', 'normal'): jid_bare = message['from'].bare command = ' '.join(message['body'].split()) command_time_start = time.time() # if (message['type'] == 'groupchat' and # message['muc']['nick'] == self.alias): # return # FIXME Code repetition. See below. # TODO Check alias by nickname associated with conference if message['type'] == 'groupchat': if (message['muc']['nick'] == self.alias): return jid_full = str(message['from']) if not is_moderator(self, jid_bare, jid_full): return if message['type'] == 'groupchat': # nick = message['from'][message['from'].index('/')+1:] # nick = str(message['from']) # nick = nick[nick.index('/')+1:] if (message['muc']['nick'] == self.alias or not message['body'].startswith('!')): return # token = await initdb( # jid_bare, # sqlite.get_setting_value, # 'token' # ) # if token == 'accepted': # operator = await initdb( # jid_bare, # sqlite.get_setting_value, # 'masters' # ) # if operator: # if nick not in operator: # return # approved = False jid_full = str(message['from']) if not is_moderator(self, jid_bare, jid_full): return # if role == 'moderator': # approved = True # TODO Implement a list of temporary operators # Once an operator is appointed, the control would last # untile the participant has been disconnected from MUC # An operator is a function to appoint non moderators. # Changing nickname is fine and consist of no problem. # if not approved: # operator = await initdb( # jid_bare, # sqlite.get_setting_value, # 'masters' # ) # if operator: # if nick in operator: # approved = True # if not approved: # return # # Begin processing new JID # # Deprecated in favour of event 'presence_available' # db_dir = config.get_default_data_directory() # os.chdir(db_dir) # if jid + '.db' not in os.listdir(): # await task_jid(jid) # await compose.message(self, jid_bare, message) if message['type'] == 'groupchat': command = command[1:] command_lowercase = command.lower() logging.debug([str(message['from']), ':', 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 = str(message['from']) if (jid_bare == jid_full[:jid_full.index('/')]): # TODO Count and alert of MUC-PM attempts return response = None db_file = config.get_pathname_to_database(jid_bare) match command_lowercase: case 'help': command_list = XmppCommands.print_help() response = ('Available command keys:\n' '```\n{}\n```\n' 'Usage: `help `' .format(command_list)) case 'help all': command_list = action.manual('commands.toml', section='all') response = ('Complete list of commands:\n' '```\n{}\n```' .format(command_list)) 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 = action.manual('commands.toml', section=command_root, command=command_name) if command_list: command_list = ''.join(command_list) response = (command_list) else: response = ('KeyError for {} {}' .format(command_root, command_name)) elif len(command) == 1: command = command[0] command_list = action.manual('commands.toml', command) if command_list: command_list = ' '.join(command_list) response = ('Available command `{}` keys:\n' '```\n{}\n```\n' 'Usage: `help {} `' .format(command, command_list, command)) else: response = 'KeyError for {}'.format(command) else: response = ('Invalid. Enter command key ' 'or command key & name') case 'info': entries = XmppCommands.print_info_list() response = ('Available command options:\n' '```\n{}\n```\n' 'Usage: `info