diff --git a/slixfeed/action.py b/slixfeed/action.py index 46b3b62..876d87d 100644 --- a/slixfeed/action.py +++ b/slixfeed/action.py @@ -24,7 +24,7 @@ TODO """ -import asyncio +# import asyncio from asyncio.exceptions import IncompleteReadError from bs4 import BeautifulSoup from feedparser import parse @@ -34,6 +34,7 @@ from slixfeed.log import Logger from lxml import html import os import slixfeed.config as config +from slixfeed.config import Config import slixfeed.crawl as crawl import slixfeed.dt as dt import slixfeed.fetch as fetch @@ -122,7 +123,8 @@ async def xmpp_send_status(self, jid): status_text = '📜️ Slixfeed RSS News Bot' jid_file = jid.replace('/', '_') db_file = config.get_pathname_to_database(jid_file) - enabled = config.get_setting_value(db_file, 'enabled') + setting = Config(db_file) + enabled = setting.enabled if not enabled: status_mode = 'xa' status_text = '📪️ Send "Start" to receive updates' @@ -174,11 +176,12 @@ async def xmpp_send_update(self, jid, num=None): logger.debug('{}: jid: {} num: {}'.format(function_name, jid, num)) jid_file = jid.replace('/', '_') db_file = config.get_pathname_to_database(jid_file) - enabled = config.get_setting_value(db_file, 'enabled') + setting = Config(db_file) + enabled = setting.enabled if enabled: - show_media = config.get_setting_value(db_file, 'media') + show_media = setting.media if not num: - num = config.get_setting_value(db_file, 'quantum') + num = setting.quantum else: num = int(num) results = await sqlite.get_unread_entries(db_file, num) @@ -461,7 +464,8 @@ def list_unread_entries(result, feed_title, jid_file): summary = summary.replace(' ', ' ') summary = summary.replace(' ', ' ') db_file = config.get_pathname_to_database(jid_file) - length = config.get_setting_value(db_file, "length") + setting = Config(db_file) + length = setting.length length = int(length) summary = summary[:length] + " […]" # summary = summary.strip().split('\n') @@ -472,7 +476,7 @@ def list_unread_entries(result, feed_title, jid_file): link = (replace_hostname(link, "link")) or link # news_item = ("\n{}\n{}\n{} [{}]\n").format(str(title), str(link), # str(feed_title), str(ix)) - formatting = config.get_setting_value(db_file, 'formatting') + formatting = setting.formatting news_item = formatting.format(feed_title=feed_title, title=title, summary=summary, @@ -540,10 +544,11 @@ async def list_statistics(db_file): entries_all = entries + archive feeds_active = await sqlite.get_number_of_feeds_active(db_file) feeds_all = await sqlite.get_number_of_items(db_file, 'feeds') - key_archive = config.get_setting_value(db_file, 'archive') - key_interval = config.get_setting_value(db_file, 'interval') - key_quantum = config.get_setting_value(db_file, 'quantum') - key_enabled = config.get_setting_value(db_file, 'enabled') + setting = Config(db_file) + key_archive = setting.archive + key_interval = setting.interval + key_quantum = setting.quantum + key_enabled = setting.enabled # msg = """You have {} unread news items out of {} from {} news sources. # """.format(unread_entries, entries, feeds) @@ -712,6 +717,7 @@ async def add_feed(db_file, url): function_name = sys._getframe().f_code.co_name logger.debug('{}: db_file: {} url: {}' .format(function_name, db_file, url)) + setting = Config(db_file) while True: exist = await sqlite.get_feed_id_and_name(db_file, url) if not exist: @@ -754,7 +760,7 @@ async def add_feed(db_file, url): status_code=status_code, updated=updated) await scan(db_file, url) - old = config.get_setting_value(db_file, "old") + old = setting.old feed_id = await sqlite.get_feed_id(db_file, url) feed_id = feed_id[0] if not old: @@ -804,7 +810,7 @@ async def add_feed(db_file, url): status_code=status_code, updated=updated) await scan_json(db_file, url) - old = config.get_setting_value(db_file, "old") + old = setting.old if not old: feed_id = await sqlite.get_feed_id(db_file, url) feed_id = feed_id[0] @@ -1570,6 +1576,8 @@ async def remove_nonexistent_entries(db_file, url, feed): feed_id = feed_id[0] items = await sqlite.get_entries_of_feed(db_file, feed_id) entries = feed.entries + setting = Config(db_file) + limit = setting.archive for item in items: ix = item[0] entry_title = item[1] @@ -1652,7 +1660,6 @@ async def remove_nonexistent_entries(db_file, url, feed): else: # print(">>> ARCHIVING:", entry_title) await sqlite.archive_entry(db_file, ix) - limit = config.get_setting_value(db_file, "archive") await sqlite.maintain_archive(db_file, limit) @@ -1679,6 +1686,8 @@ async def remove_nonexistent_entries_json(db_file, url, feed): feed_id = feed_id[0] items = await sqlite.get_entries_of_feed(db_file, feed_id) entries = feed["items"] + setting = Config(db_file) + limit = setting.archive for item in items: ix = item[0] entry_title = item[1] @@ -1728,5 +1737,4 @@ async def remove_nonexistent_entries_json(db_file, url, feed): await sqlite.delete_entry_by_id(db_file, ix) else: await sqlite.archive_entry(db_file, ix) - limit = config.get_setting_value(db_file, "archive") await sqlite.maintain_archive(db_file, limit) diff --git a/slixfeed/config.py b/slixfeed/config.py index 4e146a4..4d5336f 100644 --- a/slixfeed/config.py +++ b/slixfeed/config.py @@ -37,6 +37,21 @@ try: except: import tomli as tomllib +# TODO Consider a class ConfigDefault for default values to be initiate at most +# basic level possible and a class ConfigJID for each JID (i.e. db_file) to be +# also initiated at same level or at least at event call, then check whether +# setting_jid.setting_key has value, otherwise resort to setting_default.setting_key. +class Config: + def __init__(self, db_file): + self.archive = get_setting_value(db_file, 'archive') + self.enabled = get_setting_value(db_file, 'enabled') + self.formatting = get_setting_value(db_file, 'formatting') + self.interval = get_setting_value(db_file, 'interval') + self.length = get_setting_value(db_file, 'length') + self.media = get_setting_value(db_file, 'media') + self.old = get_setting_value(db_file, 'old') + self.quantum = get_setting_value(db_file, 'quantum') + async def set_setting_value(db_file, key, val): key = key.lower() @@ -51,7 +66,7 @@ def get_setting_value(db_file, key): if value: value = value[0] else: - value = get_value("settings", "Settings", key) + value = get_value('settings', 'Settings', key) # try: # value = int(value) # except ValueError as e: diff --git a/slixfeed/version.py b/slixfeed/version.py index ee29bcd..ead6e31 100644 --- a/slixfeed/version.py +++ b/slixfeed/version.py @@ -1,2 +1,2 @@ -__version__ = '0.1.27' -__version_info__ = (0, 1, 27) +__version__ = '0.1.28' +__version_info__ = (0, 1, 28) diff --git a/slixfeed/xmpp/client.py b/slixfeed/xmpp/client.py index 11eab1d..bb14b6f 100644 --- a/slixfeed/xmpp/client.py +++ b/slixfeed/xmpp/client.py @@ -64,6 +64,7 @@ import logging import os import slixfeed.action as action import slixfeed.config as config +from slixfeed.config import Config import slixfeed.crawl as crawl import slixfeed.dt as dt import slixfeed.fetch as fetch @@ -703,6 +704,7 @@ class Slixfeed(slixmpp.ClientXMPP): jid_bare = session['from'].bare jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) form = self['xep_0004'].make_form('form', 'Profile') form['instructions'] = ('Displaying information\nJabber ID {}' .format(jid_bare)) @@ -728,35 +730,35 @@ class Slixfeed(slixmpp.ClientXMPP): value=unread) form.add_field(ftype='fixed', value='Options') - key_archive = str(config.get_setting_value(db_file, 'archive')) + key_archive = str(setting.archive) form.add_field(label='Archive', ftype='text-single', value=key_archive) - key_enabled = str(config.get_setting_value(db_file, 'enabled')) + key_enabled = str(setting.enabled) form.add_field(label='Enabled', ftype='text-single', value=key_enabled) - key_interval = str(config.get_setting_value(db_file, 'interval')) + key_interval = str(setting.interval) form.add_field(label='Interval', ftype='text-single', value=key_interval) - key_length = str(config.get_setting_value(db_file, 'length')) + key_length = str(setting.length) form.add_field(label='Length', ftype='text-single', value=key_length) - key_media = str(config.get_setting_value(db_file, 'media')) + key_media = str(setting.media) form.add_field(label='Media', ftype='text-single', value=key_media) - key_old = str(config.get_setting_value(db_file, 'old')) + key_old = str(setting.old) form.add_field(label='Old', ftype='text-single', value=key_old) - key_quantum = str(config.get_setting_value(db_file, 'quantum')) + key_quantum = str(setting.quantum) form.add_field(label='Quantum', ftype='text-single', value=key_quantum) - update_interval = config.get_setting_value(db_file, 'interval') + update_interval = str(setting.interval) update_interval = 60 * int(update_interval) last_update_time = await sqlite.get_last_update_time(db_file) if last_update_time: @@ -2667,10 +2669,10 @@ class Slixfeed(slixmpp.ClientXMPP): if chat_type == 'chat' or moderator: jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) form = self['xep_0004'].make_form('form', 'Settings') form['instructions'] = 'Editing settings' - - value = config.get_setting_value(db_file, 'enabled') + value = str(setting.enabled) value = int(value) if value: value = True @@ -2682,7 +2684,7 @@ class Slixfeed(slixmpp.ClientXMPP): desc='Enable news updates.', value=value) - value = config.get_setting_value(db_file, 'media') + value = str(setting.media) value = int(value) if value: value = True @@ -2694,7 +2696,7 @@ class Slixfeed(slixmpp.ClientXMPP): label='Display media', value=value) - value = config.get_setting_value(db_file, 'old') + value = str(setting.old) value = int(value) if value: value = True @@ -2707,7 +2709,7 @@ class Slixfeed(slixmpp.ClientXMPP): label='Include old news', value=value) - value = config.get_setting_value(db_file, 'interval') + value = str(setting.interval) value = int(value) value = value/60 value = int(value) @@ -2728,7 +2730,7 @@ class Slixfeed(slixmpp.ClientXMPP): else: i += 1 - value = config.get_setting_value(db_file, 'quantum') + value = str(setting.quantum) value = str(value) options = form.add_field(var='quantum', ftype='list-single', @@ -2743,7 +2745,7 @@ class Slixfeed(slixmpp.ClientXMPP): options.addOption(x, x) i += 1 - value = config.get_setting_value(db_file, 'archive') + value = str(setting.archive) value = str(value) options = form.add_field(var='archive', ftype='list-single', @@ -2777,6 +2779,7 @@ class Slixfeed(slixmpp.ClientXMPP): form = payload jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) # In this case (as is typical), the payload is a form values = payload['values'] for value in values: @@ -2789,7 +2792,7 @@ class Slixfeed(slixmpp.ClientXMPP): val = val * 60 if (key == 'enabled' and val == 1 and - config.get_setting_value(db_file, 'enabled') == 0): + str(setting.enabled) == 0): logger.info('Slixfeed has been enabled for {}'.format(jid_bare)) status_type = 'available' status_message = '📫️ Welcome back!' @@ -2800,7 +2803,7 @@ class Slixfeed(slixmpp.ClientXMPP): await task.start_tasks_xmpp(self, jid_bare, key_list) if (key == 'enabled' and val == 0 and - config.get_setting_value(db_file, 'enabled') == 1): + str(setting.enabled) == 1): logger.info('Slixfeed has been disabled for {}'.format(jid_bare)) key_list = ['interval', 'status'] task.clean_tasks_xmpp(self, jid_bare, key_list) @@ -2809,12 +2812,13 @@ class Slixfeed(slixmpp.ClientXMPP): XmppPresence.send(self, jid_bare, status_message, status_type=status_type) + # These three ilnes (getting value after setting it) might be removed await config.set_setting_value(db_file, key, val) val = sqlite.get_setting_value(db_file, key) val = val[0] # if key == 'enabled': - # if config.get_setting_value(db_file, 'enabled') == 0: + # if str(setting.enabled) == 0: # status_type = 'available' # status_message = '📫️ Welcome back!' # XmppPresence.send(self, jid, status_message, diff --git a/slixfeed/xmpp/command.py b/slixfeed/xmpp/command.py index 5cef9de..9b875ca 100644 --- a/slixfeed/xmpp/command.py +++ b/slixfeed/xmpp/command.py @@ -7,6 +7,7 @@ import logging import os import slixfeed.action as action import slixfeed.config as config +from slixfeed.config import Config import slixfeed.crawl as crawl import slixfeed.dt as dt import slixfeed.fetch as fetch @@ -30,6 +31,8 @@ class XmppCommand: def adhoc_commands(self): + function_name = sys._getframe().f_code.co_name + logger.debug('{}'.format(function_name)) # self["xep_0050"].add_command( # node="updates_enable", # name="Enable/Disable News Updates", @@ -79,12 +82,17 @@ class XmppCommand: # http://jabber.org/protocol/commands#actions async def _handle_profile(self, iq, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) form = self['xep_0004'].make_form('form', 'Profile') form['instructions'] = ('Displaying information\nJabber ID {}' - .format(jid)) + .format(jid_bare)) form.add_field(ftype='fixed', value='News') feeds_all = str(await sqlite.get_number_of_items(db_file, 'feeds')) @@ -107,35 +115,35 @@ class XmppCommand: value=unread) form.add_field(ftype='fixed', value='Options') - key_archive = str(config.get_setting_value(db_file, 'archive')) + key_archive = str(setting.archive) form.add_field(label='Archive', ftype='text-single', value=key_archive) - key_enabled = str(config.get_setting_value(db_file, 'enabled')) + key_enabled = str(setting.enabled) form.add_field(label='Enabled', ftype='text-single', value=key_enabled) - key_interval = str(config.get_setting_value(db_file, 'interval')) + key_interval = str(setting.interval) form.add_field(label='Interval', ftype='text-single', value=key_interval) - key_length = str(config.get_setting_value(db_file, 'length')) + key_length = str(setting.length) form.add_field(label='Length', ftype='text-single', value=key_length) - key_media = str(config.get_setting_value(db_file, 'media')) + key_media = str(setting.media) form.add_field(label='Media', ftype='text-single', value=key_media) - key_old = str(config.get_setting_value(db_file, 'old')) + key_old = str(setting.old) form.add_field(label='Old', ftype='text-single', value=key_old) - key_quantum = str(config.get_setting_value(db_file, 'quantum')) + key_quantum = str(setting.quantum) form.add_field(label='Quantum', ftype='text-single', value=key_quantum) - update_interval = config.get_setting_value(db_file, 'interval') + update_interval = str(setting.interval) update_interval = 60 * int(update_interval) last_update_time = await sqlite.get_last_update_time(db_file) if last_update_time: @@ -170,11 +178,14 @@ class XmppCommand: return session async def _handle_filters(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: jid = session['from'].bare jid_file = jid @@ -220,13 +231,17 @@ class XmppCommand: session. Additional, custom data may be saved here to persist across handler callbacks. """ + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) # Text is not displayed; only labels form = payload - jid = session['from'].bare + jid_bare = session['from'].bare # form = self['xep_0004'].make_form('result', 'Done') # form['instructions'] = ('✅️ Filters have been updated') - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) # In this case (as is typical), the payload is a form values = payload['values'] @@ -254,11 +269,14 @@ class XmppCommand: async def _handle_subscription_add(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Subscription') form['instructions'] = 'Adding subscription' @@ -286,12 +304,16 @@ class XmppCommand: session['payload'] = form else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session async def _handle_recent(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = self['xep_0004'].make_form('form', 'Updates') form['instructions'] = 'Browse and read news' options = form.add_field(var='action', @@ -313,15 +335,19 @@ class XmppCommand: async def _handle_recent_result(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) num = 100 match payload['values']['action']: case 'all': - results = await sqlite.get_entries(db_file, num) + results = await sqlite.get_entries(db_file, num) # FIXME case 'rejected': - results = await sqlite.get_entries_rejected(db_file, num) + results = await sqlite.get_entries_rejected(db_file, num) # FIXME case 'unread': results = await sqlite.get_unread_entries(db_file, num) if results: @@ -348,21 +374,25 @@ class XmppCommand: async def _handle_recent_select(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] ix = values['update'] - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) title = sqlite.get_entry_title(db_file, ix) title = title[0] if title else 'Untitled' form = self['xep_0004'].make_form('form', 'Article') url = sqlite.get_entry_url(db_file, ix) url = url[0] - logging.info('Original URL: {}'.format(url)) + logger.debug('Original URL: {}'.format(url)) url = uri.remove_tracking_parameters(url) - logging.info('Processed URL (tracker removal): {}'.format(url)) + logger.debug('Processed URL (tracker removal): {}'.format(url)) url = (uri.replace_hostname(url, 'link')) or url - logging.info('Processed URL (replace hostname): {}'.format(url)) + logger.debug('Processed URL (replace hostname): {}'.format(url)) result = await fetch.http(url) if 'content' in result: data = result['content'] @@ -411,10 +441,14 @@ class XmppCommand: async def _handle_recent_action(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) ext = payload['values']['filetype'] url = payload['values']['url'][0] - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) cache_dir = config.get_default_cache_directory() if not os.path.isdir(cache_dir): @@ -444,7 +478,7 @@ class XmppCommand: 'Reason: {}'.format(ext.upper(), url, error)) session['notes'] = [['error', text_error]] else: - url = await XmppUpload.start(self, jid, filename) + url = await XmppUpload.start(self, jid_bare, filename) form = self['xep_0004'].make_form('result', 'Download') form['instructions'] = ('Download {} document.' .format(ext.upper())) @@ -461,8 +495,12 @@ class XmppCommand: async def _handle_subscription_new(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) # scan = payload['values']['scan'] url = payload['values']['subscription'] @@ -584,9 +622,13 @@ class XmppCommand: async def _handle_subscription_enable(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) ixs = payload['values']['subscriptions'] form.add_field(ftype='fixed', @@ -614,9 +656,13 @@ class XmppCommand: async def _handle_subscription_disable(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) ixs = payload['values']['subscriptions'] form.add_field(ftype='fixed', @@ -644,9 +690,13 @@ class XmppCommand: async def _handle_subscription_del_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) ixs = payload['values']['subscriptions'] form.add_field(ftype='fixed', @@ -674,6 +724,10 @@ class XmppCommand: def _handle_cancel(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) text_note = ('Operation has been cancelled.' '\n' '\n' @@ -683,11 +737,14 @@ class XmppCommand: async def _handle_discover(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Discover & Search') form['instructions'] = 'Discover news subscriptions of all kinds' @@ -706,12 +763,16 @@ class XmppCommand: session['prev'] = None else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session def _handle_discover_type(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] search_type = values['search_type'] config_dir = config.get_default_config_directory() @@ -764,6 +825,10 @@ class XmppCommand: async def _handle_discover_category(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] category = values['category'] config_dir = config.get_default_config_directory() @@ -790,11 +855,14 @@ class XmppCommand: async def _handle_subscriptions(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Subscriptions') form['instructions'] = 'Managing subscriptions' @@ -814,14 +882,18 @@ class XmppCommand: session['has_next'] = True else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session async def _handle_subscriptions_result(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) form = self['xep_0004'].make_form('form', 'Subscriptions') match payload['values']['action']: @@ -920,8 +992,12 @@ class XmppCommand: async def _handle_subscription_tag(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) tag_id = payload['values']['tag'] tag_name = sqlite.get_tag_name(db_file, tag_id)[0] @@ -950,13 +1026,17 @@ class XmppCommand: # FIXME There are feeds that are missing (possibly because of sortings) async def _handle_subscription(self, iq, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare form = self['xep_0004'].make_form('form', 'Subscription editor') form['instructions'] = '📰️ Edit subscription preferences and properties' # form.addField(var='interval', # ftype='text-single', # label='Interval period') - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) subscriptions = await sqlite.get_feeds(db_file) # subscriptions = set(subscriptions) @@ -973,7 +1053,7 @@ class XmppCommand: categorized_subscriptions[letter].append(subscription) # title[0].capitalize()].append(subscription) except Exception as e: - logging.warning('Title might be empty:', str(e)) + logger.warning('Title might be empty:', str(e)) for category in sorted(categorized_subscriptions): options = form.add_field(var=category, ftype='list-single', @@ -993,8 +1073,12 @@ class XmppCommand: async def _handle_subscription_editor(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) if 'edit' in payload['values'] and not payload['values']['edit']: session['payload'] = None @@ -1085,9 +1169,13 @@ class XmppCommand: # TODO Create a new form. Do not "recycle" the last form. async def _handle_subscription_complete(self, payload, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare values = payload['values'] - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) # url = values['url'] # feed_id = await sqlite.get_feed_id(db_file, url) @@ -1146,7 +1234,11 @@ class XmppCommand: async def _handle_subscription_selector(self, payload, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare form = self['xep_0004'].make_form('form', 'Add Subscription') form['instructions'] = ('📰️ Select a subscription to add\n' 'Subsciptions discovered for {}' @@ -1160,7 +1252,7 @@ class XmppCommand: desc=('Select subscriptions to perform ' 'actions upon.'), required=True) - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) subscriptions = await sqlite.get_feeds(db_file) subscriptions = sorted(subscriptions, key=lambda x: x[0]) @@ -1184,11 +1276,14 @@ class XmppCommand: async def _handle_advanced(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Advanced') form['instructions'] = 'Extended options' @@ -1216,6 +1311,10 @@ class XmppCommand: async def _handle_advanced_result(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) match payload['values']['option']: case 'activity': # TODO dialog for JID and special dialog for operator @@ -1225,8 +1324,8 @@ class XmppCommand: case 'admin': # NOTE Even though this check is already conducted on previous # form, this check is being done just in case. - jid = session['from'].bare - if jid == config.get_value('accounts', 'XMPP', 'operator'): + jid_bare = session['from'].bare + if jid_bare == config.get_value('accounts', 'XMPP', 'operator'): if self.is_component: # NOTE This will be changed with XEP-0222 XEP-0223 text_info = ('Subscriber management options are ' @@ -1254,12 +1353,9 @@ class XmppCommand: session['next'] = self._handle_admin_action session['has_next'] = True else: - logging.warning('An unauthorized attempt to access bookmarks has ' - 'been detected!\n' - 'Details:\n' - ' Jabber ID: {}\n' - ' Timestamp: {}\n' - .format(jid, dt.timestamp())) + logger.warning('An unauthorized attempt to access ' + 'bookmarks has been detected for JID {} at ' + '{}'.format(jid_bare, dt.timestamp())) text_warn = 'This resource is restricted.' session['notes'] = [['warn', text_warn]] session['has_next'] = False @@ -1320,6 +1416,10 @@ class XmppCommand: async def _handle_about(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = self['xep_0004'].make_form('form', 'About') form['instructions'] = 'Information about Slixfeed and related projects' options = form.add_field(var='option', @@ -1345,6 +1445,10 @@ class XmppCommand: async def _handle_about_result(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) match payload['values']['option']: case 'about': title = 'About' @@ -1424,6 +1528,10 @@ class XmppCommand: async def _handle_motd(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) # TODO add functionality to attach image. # Here you can add groupchat rules,post schedule, tasks or # anything elaborated you might deem fit. Good luck! @@ -1433,6 +1541,11 @@ class XmppCommand: async def _handle_help(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + import tomllib config_dir = config.get_default_config_directory() with open(config_dir + '/' + 'commands.toml', mode="rb") as commands: @@ -1470,11 +1583,15 @@ class XmppCommand: async def _handle_import_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload url = payload['values']['url'] if url.startswith('http') and url.endswith('.opml'): - jid = session['from'].bare - jid_file = jid.replace('/', '_') + jid_bare = session['from'].bare + jid_file = jid_bare.replace('/', '_') db_file = config.get_pathname_to_database(jid_file) count = await action.import_opml(db_file, url) try: @@ -1503,22 +1620,26 @@ class XmppCommand: async def _handle_export_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid.replace('/', '_') + jid_bare = session['from'].bare + jid_file = jid_bare.replace('/', '_') # form = self['xep_0004'].make_form('result', 'Done') # form['instructions'] = ('✅️ Feeds have been exported') exts = payload['values']['filetype'] for ext in exts: - filename = await action.export_feeds(self, jid, jid_file, ext) - url = await XmppUpload.start(self, jid, filename) + filename = await action.export_feeds(self, jid_bare, jid_file, ext) + url = await XmppUpload.start(self, jid_bare, filename) url_field = form.add_field(var=ext.upper(), ftype='text-single', label=ext, value=url) url_field['validate']['datatype'] = 'xs:anyURI' - chat_type = await get_chat_type(self, jid) - XmppMessage.send_oob(self, jid, url, chat_type) + chat_type = await get_chat_type(self, jid_bare) + XmppMessage.send_oob(self, jid_bare, url, chat_type) form['type'] = 'result' form['title'] = 'Done' form['instructions'] = ('Completed successfully!') @@ -1532,11 +1653,15 @@ class XmppCommand: # TODO Attempt to look up for feeds of hostname of JID (i.e. scan # jabber.de for feeds for juliet@jabber.de) async def _handle_promoted(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_full = str(session['from']) + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Subscribe') # NOTE Refresh button would be of use @@ -1595,8 +1720,16 @@ class XmppCommand: async def _handle_admin_action(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) subscriptions = await sqlite.get_feeds(db_file) subscriptions = sorted(subscriptions, key=lambda x: x[0]) @@ -1675,40 +1808,44 @@ class XmppCommand: async def _handle_subscribers_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] - jid = values['jid'] + jid_bare = values['jid'] value_subject = values['subject'] message_subject = value_subject if value_subject else None value_message = values['message'] message_body = value_message if value_message else None match values['action']: case 'from': - XmppPresence.subscription(self, jid, 'subscribe') + XmppPresence.subscription(self, jid_bare, 'subscribe') if not message_subject: message_subject = 'System Message' if not message_body: - message_body = ('This user wants to subscribe to your presence' - '. Click the button labelled "Add/Auth" to ' - 'authorize the subscription. This will also ' - 'add the person to your contact list if it is ' - 'not already there.') + message_body = ('This user wants to subscribe to your ' + 'presence. Click the button labelled ' + '"Add/Auth" toauthorize the subscription. ' + 'This will also add the person to your ' + 'contact list if it is not already there.') case 'remove': - XmppRoster.remove(self, jid) + XmppRoster.remove(self, jid_bare) if not message_subject: message_subject = 'System Message' if not message_body: message_body = 'Your authorization has been removed!' case 'to': - XmppPresence.subscription(self, jid, 'subscribed') + XmppPresence.subscription(self, jid_bare, 'subscribed') if not message_subject: message_subject = 'System Message' if not message_body: message_body = 'Your authorization has been approved!' if message_subject: - XmppMessage.send_headline(self, jid, message_subject, message_body, - 'chat') + XmppMessage.send_headline(self, jid_bare, message_subject, + message_body, 'chat') elif message_body: - XmppMessage.send(self, jid, message_body, 'chat') + XmppMessage.send(self, jid_bare, message_body, 'chat') form = payload form['title'] = 'Done' form['instructions'] = ('has been completed!') @@ -1719,19 +1856,23 @@ class XmppCommand: async def _handle_contact_action(self, payload, session): - jid = payload['values']['jid'] + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = payload['values']['jid'] form = self['xep_0004'].make_form('form', 'Contacts') session['allow_complete'] = True roster = await XmppRoster.get_contacts(self) - properties = roster[jid] + properties = roster[jid_bare] match payload['values']['action']: case 'edit': form['instructions'] = 'Editing contact' options = form.add_field(var='jid', ftype='list-single', label='Jabber ID', - value=jid) - options.addOption(jid, jid) + value=jid_bare) + options.addOption(jid_bare, jid_bare) form.add_field(var='name', ftype='text-single', label='Name', @@ -1741,7 +1882,7 @@ class XmppCommand: case 'view': form['instructions'] = 'Viewing contact' contact_name = properties['name'] - contact_name = contact_name if contact_name else jid + contact_name = contact_name if contact_name else jid_bare form.add_field(var='name', ftype='text-single', label='Name', @@ -1782,17 +1923,21 @@ class XmppCommand: def _handle_contacts_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] - jid = values['jid'] + jid_bare = values['jid'] name = values['name'] - name_old = XmppRoster.get_contact_name(self, jid) + name_old = XmppRoster.get_contact_name(self, jid_bare) if name == name_old: message = ('No action has been taken. Reason: New ' 'name is identical to the current one.') session['payload'] = None session['notes'] = [['info', message]] else: - XmppRoster.set_contact_name(self, jid, name) + XmppRoster.set_contact_name(self, jid_bare, name) form = payload form['title'] = 'Done' form['instructions'] = ('has been completed!') @@ -1802,8 +1947,12 @@ class XmppCommand: async def _handle_bookmarks_editor(self, payload, session): - jid = payload['values']['jid'] - properties = await XmppBookmark.properties(self, jid) + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = payload['values']['jid'] + properties = await XmppBookmark.properties(self, jid_bare) form = self['xep_0004'].make_form('form', 'Bookmarks') form['instructions'] = 'Editing bookmark' jid_split = properties['jid'].split('@') @@ -1812,8 +1961,8 @@ class XmppCommand: options = form.addField(var='jid', ftype='list-single', label='Jabber ID', - value=jid) - options.addOption(jid, jid) + value=jid_bare) + options.addOption(jid_bare, jid_bare) form.addField(var='name', ftype='text-single', label='Name', @@ -1863,6 +2012,10 @@ class XmppCommand: async def _handle_bookmarks_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) # form = self['xep_0004'].make_form('result', 'Done') # form['instructions'] = ('✅️ Bookmark has been saved') # # In this case (as is typical), the payload is a form @@ -1894,18 +2047,21 @@ class XmppCommand: session. Additional, custom data may be saved here to persist across handler callbacks. """ - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) form = self['xep_0004'].make_form('form', 'Settings') form['instructions'] = 'Editing settings' - - value = config.get_setting_value(db_file, 'enabled') + value = str(setting.enabled) value = int(value) if value: value = True @@ -1917,7 +2073,7 @@ class XmppCommand: desc='Enable news updates.', value=value) - value = config.get_setting_value(db_file, 'media') + value = str(setting.media) value = int(value) if value: value = True @@ -1929,7 +2085,7 @@ class XmppCommand: label='Display media', value=value) - value = config.get_setting_value(db_file, 'old') + value = str(setting.old) value = int(value) if value: value = True @@ -1942,7 +2098,7 @@ class XmppCommand: label='Include old news', value=value) - value = config.get_setting_value(db_file, 'interval') + value = str(setting.interval) value = int(value) value = value/60 value = int(value) @@ -1963,7 +2119,7 @@ class XmppCommand: else: i += 1 - value = config.get_setting_value(db_file, 'quantum') + value = str(setting.quantum) value = str(value) options = form.add_field(var='quantum', ftype='list-single', @@ -1978,7 +2134,7 @@ class XmppCommand: options.addOption(x, x) i += 1 - value = config.get_setting_value(db_file, 'archive') + value = str(setting.archive) value = str(value) options = form.add_field(var='archive', ftype='list-single', @@ -1998,16 +2154,21 @@ class XmppCommand: session['payload'] = form else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session async def _handle_settings_complete(self, payload, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare form = payload - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) # In this case (as is typical), the payload is a form values = payload['values'] for value in values: @@ -2020,31 +2181,33 @@ class XmppCommand: val = val * 60 if (key == 'enabled' and val == 1 and - config.get_setting_value(db_file, 'enabled') == 0): - logging.info('Slixfeed has been enabled for {}'.format(jid)) + str(setting.enabled) == 0): + logger.info('Slixfeed has been enabled for {}'.format(jid_bare)) status_type = 'available' status_message = '📫️ Welcome back!' - XmppPresence.send(self, jid, status_message, + XmppPresence.send(self, jid_bare, status_message, status_type=status_type) await asyncio.sleep(5) - await task.start_tasks_xmpp(self, jid, ['check', 'status', - 'interval']) + key_list = ['check', 'status', 'interval'] + await task.start_tasks_xmpp(self, jid_bare, key_list) if (key == 'enabled' and val == 0 and - config.get_setting_value(db_file, 'enabled') == 1): - logging.info('Slixfeed has been disabled for {}'.format(jid)) - task.clean_tasks_xmpp(self, jid, ['interval', 'status']) + str(setting.enabled) == 1): + logger.info('Slixfeed has been disabled for {}'.format(jid_bare)) + key_list = ['interval', 'status'] + task.clean_tasks_xmpp(self, jid_bare, key_list) status_type = 'xa' status_message = '📪️ Send "Start" to receive updates' - XmppPresence.send(self, jid, status_message, + XmppPresence.send(self, jid_bare, status_message, status_type=status_type) + # These three ilnes (getting value after setting it) might be removed await config.set_setting_value(db_file, key, val) val = sqlite.get_setting_value(db_file, key) val = val[0] # if key == 'enabled': - # if config.get_setting_value(db_file, 'enabled') == 0: + # if str(setting.enabled) == 0: # status_type = 'available' # status_message = '📫️ Welcome back!' # XmppPresence.send(self, jid, status_message, diff --git a/slixfeed/xmpp/component.py b/slixfeed/xmpp/component.py index c7ed620..d57e858 100644 --- a/slixfeed/xmpp/component.py +++ b/slixfeed/xmpp/component.py @@ -31,6 +31,7 @@ import slixfeed.task as task # from lxml import etree import slixfeed.config as config +from slixfeed.log import Logger from slixfeed.version import __version__ from slixfeed.xmpp.connect import XmppConnect # NOTE MUC is possible for component @@ -44,6 +45,9 @@ from slixfeed.xmpp.presence import XmppPresence # from slixmpp.xmlstream import ET # from slixmpp.xmlstream.handler import Callback # from slixmpp.xmlstream.matcher import MatchXPath +from slixfeed.xmpp.utility import get_chat_type +import sys +import time import asyncio from datetime import datetime @@ -51,6 +55,7 @@ import logging import os import slixfeed.action as action import slixfeed.config as config +from slixfeed.config import Config import slixfeed.crawl as crawl import slixfeed.dt as dt import slixfeed.fetch as fetch @@ -80,6 +85,7 @@ loop = asyncio.get_event_loop() # current_time = now.strftime("%H:%M:%S") # return current_time +logger = Logger(__name__) class SlixfeedComponent(slixmpp.ComponentXMPP): """ @@ -188,11 +194,23 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def on_connection_failed(self, event): + time_begin = time.time() + function_name = sys._getframe().f_code.co_name + message_log = '{}' + logger.debug(message_log.format(function_name)) message = 'Connection has failed. Reason: {}'.format(event) XmppConnect.recover(self, message) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_session_start(self, event): + time_begin = time.time() + function_name = sys._getframe().f_code.co_name + message_log = '{}' + logger.debug(message_log.format(function_name)) # self.send_presence() profile.set_identity(self, 'service') # XmppCommand.adhoc_commands(self) @@ -206,35 +224,60 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # XmppGroupchat.autojoin(self, bookmarks) if config.get_value('accounts', 'XMPP', 'operator'): jid_op = config.get_value('accounts', 'XMPP', 'operator') - message_body = 'Slixfeed version {}'.format(__version__) - XmppMessage.send(self, jid_op, message_body, 'chat') + status_message = 'Slixfeed version {}'.format(__version__) + XmppPresence.send(self, jid_op, status_message) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) def on_session_resumed(self, event): + time_begin = time.time() + function_name = sys._getframe().f_code.co_name + message_log = '{}' + logger.debug(message_log.format(function_name)) # self.send_presence() profile.set_identity(self, 'service') self['xep_0115'].update_caps() # await XmppGroupchat.autojoin(self) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_disco_info(self, DiscoInfo): - jid = DiscoInfo['from'] + time_begin = time.time() + jid_full = str(DiscoInfo['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) # self.service_reactions() # self.send_presence(pto=jid) - await self['xep_0115'].update_caps(jid=jid) + await self['xep_0115'].update_caps(jid=jid_full) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_message(self, message): - jid = message['from'].bare - if jid == self.boundjid.bare: + time_begin = time.time() + jid_full = str(message['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = message['from'].bare + if jid_bare == self.boundjid.bare: status_type = 'dnd' status_message = ('Slixfeed is not designed to receive messages ' 'from itself') - XmppPresence.send(self, jid, status_message, + XmppPresence.send(self, jid_bare, status_message, status_type=status_type) await asyncio.sleep(5) status_message = ('Slixfeed news bot from RSS Task Force') - XmppPresence.send(self, jid, status_message) + XmppPresence.send(self, jid_bare, status_message) else: # TODO Request for subscription # if "chat" == await XmppUtility.get_chat_type(self, jid): @@ -250,86 +293,146 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # chat_type = message["type"] # message_body = message["body"] # message_reply = message.reply + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_changed_status(self, presence): + time_begin = time.time() + jid_full = str(presence['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) # await task.check_readiness(self, presence) - jid = presence['from'].bare - if jid in self.boundjid.bare: + jid_bare = presence['from'].bare + if jid_bare in self.boundjid.bare: return if presence['show'] in ('away', 'dnd', 'xa'): - task.clean_tasks_xmpp(self, jid, ['interval']) - await task.start_tasks_xmpp(self, jid, ['status', 'check']) + key_list = ['interval'] + task.clean_tasks_xmpp(self, jid_bare, key_list) + key_list = ['status', 'check'] + await task.start_tasks_xmpp(self, jid_bare, key_list) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_presence_subscribe(self, presence): - jid = presence['from'].bare - if not self.client_roster[jid]['to']: + time_begin = time.time() + jid_full = str(presence['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = presence['from'].bare + if not self.client_roster[jid_bare]['to']: # XmppPresence.subscription(self, jid, 'subscribe') - XmppPresence.subscription(self, jid, 'subscribed') - await XmppRoster.add(self, jid) + XmppPresence.subscription(self, jid_bare, 'subscribed') + await XmppRoster.add(self, jid_bare) status_message = '✒️ Share online status to receive updates' - XmppPresence.send(self, jid, status_message) + XmppPresence.send(self, jid_bare, status_message) message_subject = 'RSS News Bot' message_body = 'Share online status to receive updates.' - XmppMessage.send_headline(self, jid, message_subject, message_body, - 'chat') + XmppMessage.send_headline(self, jid_bare, message_subject, + message_body, 'chat') + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) def on_presence_subscribed(self, presence): - jid = presence['from'].bare - # XmppPresence.subscription(self, jid, 'subscribed') + time_begin = time.time() + jid_full = str(presence['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) message_subject = 'RSS News Bot' message_body = ('Greetings! I am {}, the news anchor.\n' 'My job is to bring you the latest ' 'news from sources you provide me with.\n' 'You may always reach me via xmpp:{}?message' .format(self.alias, self.boundjid.bare)) - XmppMessage.send_headline(self, jid, message_subject, message_body, - 'chat') + jid_bare = presence['from'].bare + # XmppPresence.subscription(self, jid, 'subscribed') + XmppMessage.send_headline(self, jid_bare, message_subject, + message_body, 'chat') + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_presence_available(self, presence): + time_begin = time.time() + jid_full = str(presence['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) # TODO Add function to check whether task is already running or not # await task.start_tasks(self, presence) # NOTE Already done inside the start-task function - jid = presence['from'].bare - if jid in self.boundjid.bare: + jid_bare = presence['from'].bare + if jid_bare in self.boundjid.bare: return logging.info('JID {} is available'.format(jid)) # FIXME TODO Find out what is the source responsible for a couple presences with empty message # NOTE This is a temporary solution await asyncio.sleep(10) - await task.start_tasks_xmpp(self, jid) + await task.start_tasks_xmpp(self, jid_bare) self.add_event_handler("presence_unavailable", self.on_presence_unavailable) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{}: jid_full: {} (time: {})' + .format(function_name, jid_full, + difference)) def on_presence_unsubscribed(self, presence): - jid = presence['from'].bare + time_begin = time.time() + jid_full = str(presence['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = presence['from'].bare message_body = 'You have been unsubscribed.' # status_message = '🖋️ Subscribe to receive updates' # status_message = None - XmppMessage.send(self, jid, message_body, 'chat') - XmppPresence.subscription(self, jid, 'unsubscribed') + XmppMessage.send(self, jid_bare, message_body, 'chat') + XmppPresence.subscription(self, jid_bare, 'unsubscribed') # XmppPresence.send(self, jid, status_message, # presence_type='unsubscribed') - # XmppRoster.remove(self, jid) + XmppRoster.remove(self, jid_bare) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) def on_presence_unavailable(self, presence): - jid = presence['from'].bare - logging.info('JID {} is unavailable'.format(jid)) + time_begin = time.time() + jid_full = str(presence['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = presence['from'].bare # await task.stop_tasks(self, jid) - task.clean_tasks_xmpp(self, jid) + task.clean_tasks_xmpp(self, jid_bare) # NOTE Albeit nice to ~have~ see, this would constantly # send presence messages to server to no end. status_message = 'Farewell' - XmppPresence.send(self, jid, status_message, + XmppPresence.send(self, jid_bare, status_message, presence_type='unavailable') self.del_event_handler("presence_unavailable", self.on_presence_unavailable) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) # TODO @@ -338,9 +441,17 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # If roster, remove contact JID into file # If bookmarks, remove groupchat JID into file def on_presence_error(self, presence): - jid = presence["from"].bare - logging.info('JID {} (error)'.format(jid)) - task.clean_tasks_xmpp(self, jid) + time_begin = time.time() + jid_full = str(presence['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = presence["from"].bare + task.clean_tasks_xmpp(self, jid_bare) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) def on_reactions(self, message): @@ -349,8 +460,13 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def on_chatstate_active(self, message): - jid = message['from'].bare - if jid in self.boundjid.bare: + time_begin = time.time() + jid_full = str(message['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = message['from'].bare + if jid_bare in self.boundjid.bare: return if message['type'] in ('chat', 'normal'): # NOTE: Required for Cheogram @@ -358,12 +474,22 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # self.send_presence(pto=jid) # task.clean_tasks_xmpp(self, jid, ['status']) await asyncio.sleep(5) - await task.start_tasks_xmpp(self, jid, ['status']) + key_list = ['status'] + await task.start_tasks_xmpp(self, jid_bare, key_list) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_chatstate_composing(self, message): + time_begin = time.time() + jid_full = str(message['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) if message['type'] in ('chat', 'normal'): - jid = message['from'].bare + jid_bare = message['from'].bare # NOTE: Required for Cheogram # await self['xep_0115'].update_caps(jid=jid) # self.send_presence(pto=jid) @@ -371,34 +497,68 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): await asyncio.sleep(5) status_message = ('💡 Send "help" for manual, or "info" for ' 'information.') - XmppPresence.send(self, jid, status_message) + XmppPresence.send(self, jid_bare, status_message) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_chatstate_gone(self, message): - jid = message['from'].bare - if jid in self.boundjid.bare: + time_begin = time.time() + jid_full = str(message['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = message['from'].bare + if jid_bare in self.boundjid.bare: return if message['type'] in ('chat', 'normal'): # task.clean_tasks_xmpp(self, jid, ['status']) - await task.start_tasks_xmpp(self, jid, ['status']) + key_list = ['status'] + await task.start_tasks_xmpp(self, jid_bare, key_list) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_chatstate_inactive(self, message): - jid = message['from'].bare - if jid in self.boundjid.bare: + time_begin = time.time() + jid_full = str(message['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = message['from'].bare + if jid_bare in self.boundjid.bare: return if message['type'] in ('chat', 'normal'): # task.clean_tasks_xmpp(self, jid, ['status']) - await task.start_tasks_xmpp(self, jid, ['status']) + key_list = ['status'] + await task.start_tasks_xmpp(self, jid_bare, key_list) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) async def on_chatstate_paused(self, message): - jid = message['from'].bare - if jid in self.boundjid.bare: + time_begin = time.time() + jid_full = str(message['from']) + function_name = sys._getframe().f_code.co_name + message_log = '{}: jid_full: {}' + logger.debug(message_log.format(function_name, jid_full)) + jid_bare = message['from'].bare + if jid_bare in self.boundjid.bare: return if message['type'] in ('chat', 'normal'): # task.clean_tasks_xmpp(self, jid, ['status']) - await task.start_tasks_xmpp(self, jid, ['status']) + key_list = ['status'] + await task.start_tasks_xmpp(self, jid_bare, key_list) + time_end = time.time() + difference = time_end - time_begin + if difference > 1: logger.warning('{} (time: {})'.format(function_name, + difference)) @@ -443,12 +603,12 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): None. """ - form = self['xep_0004'].make_form( - 'form', 'Reactions Information' - ) + form = self['xep_0004'].make_form('form', 'Reactions Information') def adhoc_commands(self): + function_name = sys._getframe().f_code.co_name + logger.debug('{}'.format(function_name)) # self["xep_0050"].add_command( # node="updates_enable", # name="Enable/Disable News Updates", @@ -498,12 +658,17 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # http://jabber.org/protocol/commands#actions async def _handle_profile(self, iq, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) form = self['xep_0004'].make_form('form', 'Profile') form['instructions'] = ('Displaying information\nJabber ID {}' - .format(jid)) + .format(jid_bare)) form.add_field(ftype='fixed', value='News') feeds_all = str(await sqlite.get_number_of_items(db_file, 'feeds')) @@ -526,35 +691,35 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): value=unread) form.add_field(ftype='fixed', value='Options') - key_archive = str(config.get_setting_value(db_file, 'archive')) + key_archive = str(setting.archive) form.add_field(label='Archive', ftype='text-single', value=key_archive) - key_enabled = str(config.get_setting_value(db_file, 'enabled')) + key_enabled = str(setting.enabled) form.add_field(label='Enabled', ftype='text-single', value=key_enabled) - key_interval = str(config.get_setting_value(db_file, 'interval')) + key_interval = str(setting.interval) form.add_field(label='Interval', ftype='text-single', value=key_interval) - key_length = str(config.get_setting_value(db_file, 'length')) + key_length = str(setting.length) form.add_field(label='Length', ftype='text-single', value=key_length) - key_media = str(config.get_setting_value(db_file, 'media')) + key_media = str(setting.media) form.add_field(label='Media', ftype='text-single', value=key_media) - key_old = str(config.get_setting_value(db_file, 'old')) + key_old = str(setting.old) form.add_field(label='Old', ftype='text-single', value=key_old) - key_quantum = str(config.get_setting_value(db_file, 'quantum')) + key_quantum = str(setting.quantum) form.add_field(label='Quantum', ftype='text-single', value=key_quantum) - update_interval = config.get_setting_value(db_file, 'interval') + update_interval = str(setting.interval) update_interval = 60 * int(update_interval) last_update_time = await sqlite.get_last_update_time(db_file) if last_update_time: @@ -589,11 +754,14 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): return session async def _handle_filters(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: jid = session['from'].bare jid_file = jid @@ -639,13 +807,17 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): session. Additional, custom data may be saved here to persist across handler callbacks. """ + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) # Text is not displayed; only labels form = payload - jid = session['from'].bare + jid_bare = session['from'].bare # form = self['xep_0004'].make_form('result', 'Done') # form['instructions'] = ('✅️ Filters have been updated') - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) # In this case (as is typical), the payload is a form values = payload['values'] @@ -673,11 +845,14 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_add(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Subscription') form['instructions'] = 'Adding subscription' @@ -705,12 +880,16 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): session['payload'] = form else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session async def _handle_recent(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = self['xep_0004'].make_form('form', 'Updates') form['instructions'] = 'Browse and read news' options = form.add_field(var='action', @@ -732,15 +911,19 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_recent_result(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) num = 100 match payload['values']['action']: case 'all': - results = await sqlite.get_entries(db_file, num) + results = await sqlite.get_entries(db_file, num) # FIXME case 'rejected': - results = await sqlite.get_entries_rejected(db_file, num) + results = await sqlite.get_entries_rejected(db_file, num) # FIXME case 'unread': results = await sqlite.get_unread_entries(db_file, num) if results: @@ -767,21 +950,25 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_recent_select(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] ix = values['update'] - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) title = sqlite.get_entry_title(db_file, ix) title = title[0] if title else 'Untitled' form = self['xep_0004'].make_form('form', 'Article') url = sqlite.get_entry_url(db_file, ix) url = url[0] - logging.info('Original URL: {}'.format(url)) + logger.debug('Original URL: {}'.format(url)) url = uri.remove_tracking_parameters(url) - logging.info('Processed URL (tracker removal): {}'.format(url)) + logger.debug('Processed URL (tracker removal): {}'.format(url)) url = (uri.replace_hostname(url, 'link')) or url - logging.info('Processed URL (replace hostname): {}'.format(url)) + logger.debug('Processed URL (replace hostname): {}'.format(url)) result = await fetch.http(url) if 'content' in result: data = result['content'] @@ -830,10 +1017,14 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_recent_action(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) ext = payload['values']['filetype'] url = payload['values']['url'][0] - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) cache_dir = config.get_default_cache_directory() if not os.path.isdir(cache_dir): @@ -863,7 +1054,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): 'Reason: {}'.format(ext.upper(), url, error)) session['notes'] = [['error', text_error]] else: - url = await XmppUpload.start(self, jid, filename) + url = await XmppUpload.start(self, jid_bare, filename) form = self['xep_0004'].make_form('result', 'Download') form['instructions'] = ('Download {} document.' .format(ext.upper())) @@ -880,8 +1071,12 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_new(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) # scan = payload['values']['scan'] url = payload['values']['subscription'] @@ -1003,9 +1198,13 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_enable(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) ixs = payload['values']['subscriptions'] form.add_field(ftype='fixed', @@ -1033,9 +1232,13 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_disable(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) ixs = payload['values']['subscriptions'] form.add_field(ftype='fixed', @@ -1063,9 +1266,13 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_del_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) ixs = payload['values']['subscriptions'] form.add_field(ftype='fixed', @@ -1093,6 +1300,10 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): def _handle_cancel(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) text_note = ('Operation has been cancelled.' '\n' '\n' @@ -1102,11 +1313,14 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_discover(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Discover & Search') form['instructions'] = 'Discover news subscriptions of all kinds' @@ -1125,12 +1339,16 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): session['prev'] = None else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session def _handle_discover_type(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] search_type = values['search_type'] config_dir = config.get_default_config_directory() @@ -1183,6 +1401,10 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_discover_category(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] category = values['category'] config_dir = config.get_default_config_directory() @@ -1209,11 +1431,14 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscriptions(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Subscriptions') form['instructions'] = 'Managing subscriptions' @@ -1233,14 +1458,18 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): session['has_next'] = True else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session async def _handle_subscriptions_result(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) form = self['xep_0004'].make_form('form', 'Subscriptions') match payload['values']['action']: @@ -1339,8 +1568,12 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_tag(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) tag_id = payload['values']['tag'] tag_name = sqlite.get_tag_name(db_file, tag_id)[0] @@ -1369,13 +1602,17 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # FIXME There are feeds that are missing (possibly because of sortings) async def _handle_subscription(self, iq, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare form = self['xep_0004'].make_form('form', 'Subscription editor') form['instructions'] = '📰️ Edit subscription preferences and properties' # form.addField(var='interval', # ftype='text-single', # label='Interval period') - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) subscriptions = await sqlite.get_feeds(db_file) # subscriptions = set(subscriptions) @@ -1392,7 +1629,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): categorized_subscriptions[letter].append(subscription) # title[0].capitalize()].append(subscription) except Exception as e: - logging.warning('Title might be empty:', str(e)) + logger.warning('Title might be empty:', str(e)) for category in sorted(categorized_subscriptions): options = form.add_field(var=category, ftype='list-single', @@ -1412,8 +1649,12 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_editor(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) if 'edit' in payload['values'] and not payload['values']['edit']: session['payload'] = None @@ -1504,9 +1745,13 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # TODO Create a new form. Do not "recycle" the last form. async def _handle_subscription_complete(self, payload, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare values = payload['values'] - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) # url = values['url'] # feed_id = await sqlite.get_feed_id(db_file, url) @@ -1565,7 +1810,11 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscription_selector(self, payload, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare form = self['xep_0004'].make_form('form', 'Add Subscription') form['instructions'] = ('📰️ Select a subscription to add\n' 'Subsciptions discovered for {}' @@ -1579,7 +1828,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): desc=('Select subscriptions to perform ' 'actions upon.'), required=True) - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) subscriptions = await sqlite.get_feeds(db_file) subscriptions = sorted(subscriptions, key=lambda x: x[0]) @@ -1603,11 +1852,14 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_advanced(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Advanced') form['instructions'] = 'Extended options' @@ -1635,6 +1887,10 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_advanced_result(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) match payload['values']['option']: case 'activity': # TODO dialog for JID and special dialog for operator @@ -1644,8 +1900,8 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): case 'admin': # NOTE Even though this check is already conducted on previous # form, this check is being done just in case. - jid = session['from'].bare - if jid == config.get_value('accounts', 'XMPP', 'operator'): + jid_bare = session['from'].bare + if jid_bare == config.get_value('accounts', 'XMPP', 'operator'): if self.is_component: # NOTE This will be changed with XEP-0222 XEP-0223 text_info = ('Subscriber management options are ' @@ -1673,12 +1929,9 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): session['next'] = self._handle_admin_action session['has_next'] = True else: - logging.warning('An unauthorized attempt to access bookmarks has ' - 'been detected!\n' - 'Details:\n' - ' Jabber ID: {}\n' - ' Timestamp: {}\n' - .format(jid, dt.timestamp())) + logger.warning('An unauthorized attempt to access ' + 'bookmarks has been detected for JID {} at ' + '{}'.format(jid_bare, dt.timestamp())) text_warn = 'This resource is restricted.' session['notes'] = [['warn', text_warn]] session['has_next'] = False @@ -1739,6 +1992,10 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_about(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = self['xep_0004'].make_form('form', 'About') form['instructions'] = 'Information about Slixfeed and related projects' options = form.add_field(var='option', @@ -1764,6 +2021,10 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_about_result(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) match payload['values']['option']: case 'about': title = 'About' @@ -1843,6 +2104,10 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_motd(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) # TODO add functionality to attach image. # Here you can add groupchat rules,post schedule, tasks or # anything elaborated you might deem fit. Good luck! @@ -1852,6 +2117,11 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_help(self, iq, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + import tomllib config_dir = config.get_default_config_directory() with open(config_dir + '/' + 'commands.toml', mode="rb") as commands: @@ -1889,11 +2159,15 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_import_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload url = payload['values']['url'] if url.startswith('http') and url.endswith('.opml'): - jid = session['from'].bare - jid_file = jid.replace('/', '_') + jid_bare = session['from'].bare + jid_file = jid_bare.replace('/', '_') db_file = config.get_pathname_to_database(jid_file) count = await action.import_opml(db_file, url) try: @@ -1922,22 +2196,26 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_export_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) form = payload - jid = session['from'].bare - jid_file = jid.replace('/', '_') + jid_bare = session['from'].bare + jid_file = jid_bare.replace('/', '_') # form = self['xep_0004'].make_form('result', 'Done') # form['instructions'] = ('✅️ Feeds have been exported') exts = payload['values']['filetype'] for ext in exts: - filename = await action.export_feeds(self, jid, jid_file, ext) - url = await XmppUpload.start(self, jid, filename) + filename = await action.export_feeds(self, jid_bare, jid_file, ext) + url = await XmppUpload.start(self, jid_bare, filename) url_field = form.add_field(var=ext.upper(), ftype='text-single', label=ext, value=url) url_field['validate']['datatype'] = 'xs:anyURI' - chat_type = await get_chat_type(self, jid) - XmppMessage.send_oob(self, jid, url, chat_type) + chat_type = await get_chat_type(self, jid_bare) + XmppMessage.send_oob(self, jid_bare, url, chat_type) form['type'] = 'result' form['title'] = 'Done' form['instructions'] = ('Completed successfully!') @@ -1951,11 +2229,15 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): # TODO Attempt to look up for feeds of hostname of JID (i.e. scan # jabber.de for feeds for juliet@jabber.de) async def _handle_promoted(self, iq, session): - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_full = str(session['from']) + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: form = self['xep_0004'].make_form('form', 'Subscribe') # NOTE Refresh button would be of use @@ -2014,8 +2296,12 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_admin_action(self, payload, session): - jid = session['from'].bare - jid_file = jid + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) subscriptions = await sqlite.get_feeds(db_file) subscriptions = sorted(subscriptions, key=lambda x: x[0]) @@ -2094,40 +2380,44 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_subscribers_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] - jid = values['jid'] + jid_bare = values['jid'] value_subject = values['subject'] message_subject = value_subject if value_subject else None value_message = values['message'] message_body = value_message if value_message else None match values['action']: case 'from': - XmppPresence.subscription(self, jid, 'subscribe') + XmppPresence.subscription(self, jid_bare, 'subscribe') if not message_subject: message_subject = 'System Message' if not message_body: - message_body = ('This user wants to subscribe to your presence' - '. Click the button labelled "Add/Auth" to ' - 'authorize the subscription. This will also ' - 'add the person to your contact list if it is ' - 'not already there.') + message_body = ('This user wants to subscribe to your ' + 'presence. Click the button labelled ' + '"Add/Auth" toauthorize the subscription. ' + 'This will also add the person to your ' + 'contact list if it is not already there.') case 'remove': - XmppRoster.remove(self, jid) + XmppRoster.remove(self, jid_bare) if not message_subject: message_subject = 'System Message' if not message_body: message_body = 'Your authorization has been removed!' case 'to': - XmppPresence.subscription(self, jid, 'subscribed') + XmppPresence.subscription(self, jid_bare, 'subscribed') if not message_subject: message_subject = 'System Message' if not message_body: message_body = 'Your authorization has been approved!' if message_subject: - XmppMessage.send_headline(self, jid, message_subject, message_body, - 'chat') + XmppMessage.send_headline(self, jid_bare, message_subject, + message_body, 'chat') elif message_body: - XmppMessage.send(self, jid, message_body, 'chat') + XmppMessage.send(self, jid_bare, message_body, 'chat') form = payload form['title'] = 'Done' form['instructions'] = ('has been completed!') @@ -2138,19 +2428,23 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_contact_action(self, payload, session): - jid = payload['values']['jid'] + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = payload['values']['jid'] form = self['xep_0004'].make_form('form', 'Contacts') session['allow_complete'] = True roster = await XmppRoster.get_contacts(self) - properties = roster[jid] + properties = roster[jid_bare] match payload['values']['action']: case 'edit': form['instructions'] = 'Editing contact' options = form.add_field(var='jid', ftype='list-single', label='Jabber ID', - value=jid) - options.addOption(jid, jid) + value=jid_bare) + options.addOption(jid_bare, jid_bare) form.add_field(var='name', ftype='text-single', label='Name', @@ -2160,7 +2454,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): case 'view': form['instructions'] = 'Viewing contact' contact_name = properties['name'] - contact_name = contact_name if contact_name else jid + contact_name = contact_name if contact_name else jid_bare form.add_field(var='name', ftype='text-single', label='Name', @@ -2201,17 +2495,21 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): def _handle_contacts_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) values = payload['values'] - jid = values['jid'] + jid_bare = values['jid'] name = values['name'] - name_old = XmppRoster.get_contact_name(self, jid) + name_old = XmppRoster.get_contact_name(self, jid_bare) if name == name_old: message = ('No action has been taken. Reason: New ' 'name is identical to the current one.') session['payload'] = None session['notes'] = [['info', message]] else: - XmppRoster.set_contact_name(self, jid, name) + XmppRoster.set_contact_name(self, jid_bare, name) form = payload form['title'] = 'Done' form['instructions'] = ('has been completed!') @@ -2221,8 +2519,12 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_bookmarks_editor(self, payload, session): - jid = payload['values']['jid'] - properties = await XmppBookmark.properties(self, jid) + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = payload['values']['jid'] + properties = await XmppBookmark.properties(self, jid_bare) form = self['xep_0004'].make_form('form', 'Bookmarks') form['instructions'] = 'Editing bookmark' jid_split = properties['jid'].split('@') @@ -2231,8 +2533,8 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): options = form.addField(var='jid', ftype='list-single', label='Jabber ID', - value=jid) - options.addOption(jid, jid) + value=jid_bare) + options.addOption(jid_bare, jid_bare) form.addField(var='name', ftype='text-single', label='Name', @@ -2282,6 +2584,10 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): async def _handle_bookmarks_complete(self, payload, session): + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) # form = self['xep_0004'].make_form('result', 'Done') # form['instructions'] = ('✅️ Bookmark has been saved') # # In this case (as is typical), the payload is a form @@ -2313,18 +2619,21 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): session. Additional, custom data may be saved here to persist across handler callbacks. """ - jid = session['from'].bare jid_full = str(session['from']) - chat_type = await get_chat_type(self, jid) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare + chat_type = await get_chat_type(self, jid_bare) if chat_type == 'groupchat': - moderator = is_moderator(self, jid, jid_full) + moderator = is_moderator(self, jid_bare, jid_full) if chat_type == 'chat' or moderator: - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) form = self['xep_0004'].make_form('form', 'Settings') form['instructions'] = 'Editing settings' - - value = config.get_setting_value(db_file, 'enabled') + value = str(setting.enabled) value = int(value) if value: value = True @@ -2336,7 +2645,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): desc='Enable news updates.', value=value) - value = config.get_setting_value(db_file, 'media') + value = str(setting.media) value = int(value) if value: value = True @@ -2348,7 +2657,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): label='Display media', value=value) - value = config.get_setting_value(db_file, 'old') + value = str(setting.old) value = int(value) if value: value = True @@ -2361,7 +2670,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): label='Include old news', value=value) - value = config.get_setting_value(db_file, 'interval') + value = str(setting.interval) value = int(value) value = value/60 value = int(value) @@ -2382,7 +2691,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): else: i += 1 - value = config.get_setting_value(db_file, 'quantum') + value = str(setting.quantum) value = str(value) options = form.add_field(var='quantum', ftype='list-single', @@ -2397,7 +2706,7 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): options.addOption(x, x) i += 1 - value = config.get_setting_value(db_file, 'archive') + value = str(setting.archive) value = str(value) options = form.add_field(var='archive', ftype='list-single', @@ -2417,16 +2726,21 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): session['payload'] = form else: text_warn = ('This resource is restricted to moderators of {}.' - .format(jid)) + .format(jid_bare)) session['notes'] = [['warn', text_warn]] return session async def _handle_settings_complete(self, payload, session): - jid = session['from'].bare + jid_full = str(session['from']) + function_name = sys._getframe().f_code.co_name + logger.debug('{}: jid_full: {}' + .format(function_name, jid_full)) + jid_bare = session['from'].bare form = payload - jid_file = jid + jid_file = jid_bare db_file = config.get_pathname_to_database(jid_file) + setting = Config(db_file) # In this case (as is typical), the payload is a form values = payload['values'] for value in values: @@ -2439,31 +2753,33 @@ class SlixfeedComponent(slixmpp.ComponentXMPP): val = val * 60 if (key == 'enabled' and val == 1 and - config.get_setting_value(db_file, 'enabled') == 0): - logging.info('Slixfeed has been enabled for {}'.format(jid)) + str(setting.enabled) == 0): + logger.info('Slixfeed has been enabled for {}'.format(jid_bare)) status_type = 'available' status_message = '📫️ Welcome back!' - XmppPresence.send(self, jid, status_message, + XmppPresence.send(self, jid_bare, status_message, status_type=status_type) await asyncio.sleep(5) - await task.start_tasks_xmpp(self, jid, ['check', 'status', - 'interval']) + key_list = ['check', 'status', 'interval'] + await task.start_tasks_xmpp(self, jid_bare, key_list) if (key == 'enabled' and val == 0 and - config.get_setting_value(db_file, 'enabled') == 1): - logging.info('Slixfeed has been disabled for {}'.format(jid)) - task.clean_tasks_xmpp(self, jid, ['interval', 'status']) + str(setting.enabled) == 1): + logger.info('Slixfeed has been disabled for {}'.format(jid_bare)) + key_list = ['interval', 'status'] + task.clean_tasks_xmpp(self, jid_bare, key_list) status_type = 'xa' status_message = '📪️ Send "Start" to receive updates' - XmppPresence.send(self, jid, status_message, + XmppPresence.send(self, jid_bare, status_message, status_type=status_type) + # These three ilnes (getting value after setting it) might be removed await config.set_setting_value(db_file, key, val) val = sqlite.get_setting_value(db_file, key) val = val[0] # if key == 'enabled': - # if config.get_setting_value(db_file, 'enabled') == 0: + # if str(setting.enabled) == 0: # status_type = 'available' # status_message = '📫️ Welcome back!' # XmppPresence.send(self, jid, status_message, diff --git a/slixfeed/xmpp/process.py b/slixfeed/xmpp/process.py index 66f22bd..8b81b94 100644 --- a/slixfeed/xmpp/process.py +++ b/slixfeed/xmpp/process.py @@ -28,6 +28,7 @@ import logging import os import slixfeed.action as action import slixfeed.config as config +# from slixfeed.config import Config import slixfeed.dt as dt import slixfeed.fetch as fetch import slixfeed.sqlite as sqlite @@ -303,6 +304,8 @@ async def message(self, message): if not exist: await sqlite.insert_feed(db_file, url, title) await action.scan(db_file, url) + # setting = Config(db_file) + # old = setting.old old = config.get_setting_value(db_file, "old") if old: # task.clean_tasks_xmpp(self, jid, ['status'])