From 32d765b4828980a64357b53fcb7ba86a788303ef Mon Sep 17 00:00:00 2001 From: Schimon Jehudah Date: Mon, 19 Feb 2024 20:50:53 +0000 Subject: [PATCH] Fix fetching items upon setting "old". Add form Browse Add form Discover and Search (experimental) Add form Remove --- slixfeed/__main__.py | 18 +- slixfeed/action.py | 26 +- slixfeed/assets/commands.toml | 4 - slixfeed/assets/information.toml | 4 + slixfeed/sqlite.py | 205 +++++++++++++- slixfeed/version.py | 4 +- slixfeed/xmpp/client.py | 470 ++++++++++++++++++++++++------- slixfeed/xmpp/connect.py | 5 +- slixfeed/xmpp/process.py | 4 +- 9 files changed, 610 insertions(+), 130 deletions(-) diff --git a/slixfeed/__main__.py b/slixfeed/__main__.py index 03ef0cc..0eb0166 100644 --- a/slixfeed/__main__.py +++ b/slixfeed/__main__.py @@ -184,15 +184,15 @@ def main(): logging.info('Reading configuration from {}'.format(config_dir)) print('Reading configuration from {}'.format(config_dir)) - values = config.get_value('accounts', 'XMPP Proxy', - ['socks5_host', 'socks5_port']) - if values[0] and values[1]: - host = values[0] - port = values[1] - s = socks.socksocket() - s.set_proxy(socks.SOCKS5, host, port) - # socks.set_default_proxy(socks.SOCKS5, host, port) - # socket.socket = socks.socksocket + # values = config.get_value('accounts', 'XMPP Proxy', + # ['socks5_host', 'socks5_port']) + # if values[0] and values[1]: + # host = values[0] + # port = values[1] + # s = socks.socksocket() + # s.set_proxy(socks.SOCKS5, host, port) + # # socks.set_default_proxy(socks.SOCKS5, host, port) + # # socket.socket = socks.socksocket # Setup the command line arguments. parser = ArgumentParser(description=Slixfeed.__doc__) diff --git a/slixfeed/action.py b/slixfeed/action.py index 23fc050..04983d9 100644 --- a/slixfeed/action.py +++ b/slixfeed/action.py @@ -745,9 +745,9 @@ async def add_feed(db_file, url): updated=updated) await scan(db_file, url) old = config.get_setting_value(db_file, "old") + feed_id = await sqlite.get_feed_id(db_file, url) + feed_id = feed_id[0] if not old: - feed_id = await sqlite.get_feed_id(db_file, url) - feed_id = feed_id[0] await sqlite.mark_feed_as_read(db_file, feed_id) result_final = {'link' : url, 'index' : feed_id, @@ -1301,6 +1301,7 @@ async def download_document(self, message, jid, jid_file, message_text, ix_url, ix = int(ix_url) try: url = sqlite.get_entry_url(db_file, ix) + url = url[0] except: response = 'No entry with index {}'.format(ix) except: @@ -1363,6 +1364,27 @@ def get_document_title(data): return title +def get_document_content(data): + try: + document = Document(data) + content = document.summary() + except: + document = BeautifulSoup(data, 'html.parser') + content = data + return content + + +def get_document_content_as_text(data): + try: + document = Document(data) + content = document.summary() + except: + document = BeautifulSoup(data, 'html.parser') + content = data + text = remove_html_tags(content) + return text + + def generate_document(data, url, ext, filename, readability=False): error = None if readability: diff --git a/slixfeed/assets/commands.toml b/slixfeed/assets/commands.toml index 522b593..903f953 100644 --- a/slixfeed/assets/commands.toml +++ b/slixfeed/assets/commands.toml @@ -116,10 +116,6 @@ key = """ help Print list of commands for selected command type. """ -support = """ -support -Join xmpp:slixfeed@chat.woodpeckersnest.space?join -""" [mastership] demaster = """ diff --git a/slixfeed/assets/information.toml b/slixfeed/assets/information.toml index cd8e1ad..4a7b139 100644 --- a/slixfeed/assets/information.toml +++ b/slixfeed/assets/information.toml @@ -107,6 +107,10 @@ in order to remove all threads. https://codeberg.org/poezio/slixmpp """ +support = """ +xmpp:slixfeed@chat.woodpeckersnest.space?join +""" + terms = """ Slixfeed is free software; you can redistribute it and/or \ modify it under the terms of the MIT License. diff --git a/slixfeed/sqlite.py b/slixfeed/sqlite.py index 360b1bb..fdf1629 100644 --- a/slixfeed/sqlite.py +++ b/slixfeed/sqlite.py @@ -734,8 +734,8 @@ async def get_unread_entries(db_file, num): UNION ALL SELECT id, title, link, enclosure, feed_id, timestamp FROM archive - ORDER BY timestamp - DESC LIMIT :num + ORDER BY timestamp DESC + LIMIT :num """ ) par = (num,) @@ -918,17 +918,17 @@ async def archive_entry(db_file, ix): ) -def get_feed_title(db_file, feed_id): +def get_feed_title(db_file, ix): with create_connection(db_file) as conn: cur = conn.cursor() sql = ( """ SELECT name FROM feeds - WHERE id = :feed_id + WHERE id = :ix """ ) - par = (feed_id,) + par = (ix,) title = cur.execute(sql, par).fetchone() return title @@ -963,6 +963,21 @@ async def set_feed_title(db_file, feed_id, name): cur.execute(sql, par) +def get_entry_title(db_file, ix): + with create_connection(db_file) as conn: + cur = conn.cursor() + sql = ( # TODO Handletable archive too + """ + SELECT title + FROM entries + WHERE id = :ix + """ + ) + par = (ix,) + title = cur.execute(sql, par).fetchone() + return title + + def get_entry_url(db_file, ix): with create_connection(db_file) as conn: cur = conn.cursor() @@ -974,21 +989,21 @@ def get_entry_url(db_file, ix): """ ) par = (ix,) - url = cur.execute(sql, par).fetchone()[0] + url = cur.execute(sql, par).fetchone() return url -def get_feed_url(db_file, feed_id): +def get_feed_url(db_file, ix): with create_connection(db_file) as conn: cur = conn.cursor() sql = ( """ SELECT url FROM feeds - WHERE id = :feed_id + WHERE id = :ix """ ) - par = (feed_id,) + par = (ix,) url = cur.execute(sql, par).fetchone() return url @@ -2202,3 +2217,175 @@ async def update_last_update_time(db_file): "value": time.time() } cur.execute(sql, par) + +######################################## + +######### EXPERIMENTAL TABLE ########### + +######################################## + +def get_categories(db_file): + """ + Get list of categories. + + Parameters + ---------- + db_file : tuple + Path to database file. + + Returns + ------- + categories : str + List of categories. + """ + with create_connection(db_file) as conn: + cur = conn.cursor() + sql = ( + """ + SELECT DISTINCT category + FROM entries + ORDER BY category ASC + """ + ) + categories = cur.execute(sql).fetchall() + return categories + + +def get_locales(db_file): + """ + Get list of locales. + + Parameters + ---------- + db_file : str + Path to database file. + + Returns + ------- + locales : tuple + List of locales. + """ + with create_connection(db_file) as conn: + cur = conn.cursor() + sql = ( + """ + SELECT DISTINCT locale + FROM entries + ORDER BY locale ASC + """ + ) + locales = cur.execute(sql).fetchall() + return locales + + +def get_nations(db_file): + """ + Get list of nations. + + Parameters + ---------- + db_file : str + Path to database file. + + Returns + ------- + nations : tuple + List of nations. + """ + with create_connection(db_file) as conn: + cur = conn.cursor() + sql = ( + """ + SELECT DISTINCT nation + FROM entries + ORDER BY nation ASC + """ + ) + locales = cur.execute(sql).fetchall() + return locales + + +def get_tags(db_file): + """ + Get list of title and urls. + + Parameters + ---------- + db_file : str + Path to database file. + + Returns + ------- + titles_urls : tuple + List of titles and urls. + """ + with create_connection(db_file) as conn: + cur = conn.cursor() + sql = ( + """ + SELECT tags + FROM entries + ORDER BY tags ASC + """ + ) + titles_urls = cur.execute(sql).fetchall() + return titles_urls + + +def get_titles_tags_urls(db_file): + """ + Get list of title and urls. + + Parameters + ---------- + db_file : str + Path to database file. + + Returns + ------- + titles_urls : tuple + List of titles and urls. + """ + with create_connection(db_file) as conn: + cur = conn.cursor() + sql = ( + """ + SELECT title, tags, url + FROM entries + ORDER BY title ASC + LIMIT 800 + """ + ) + titles_tags_urls = cur.execute(sql).fetchall() + return titles_tags_urls + + +def get_titles_tags_urls_by_category(db_file, category): + """ + Get list of title and urls of given category. + + Parameters + ---------- + db_file : str + Path to database file. + + Returns + ------- + titles_urls : tuple + List of titles and urls. + """ + with create_connection(db_file) as conn: + cur = conn.cursor() + sql = ( + """ + SELECT title, tags, url + FROM entries + WHERE category = :category + ORDER BY title ASC + """ + ) + par = { + "category": category + } + titles_tags_urls = cur.execute(sql, par).fetchall() + return titles_tags_urls diff --git a/slixfeed/version.py b/slixfeed/version.py index 3a8f7af..13f9fbe 100644 --- a/slixfeed/version.py +++ b/slixfeed/version.py @@ -1,2 +1,2 @@ -__version__ = '0.1.12' -__version_info__ = (0, 1, 12) +__version__ = '0.1.13' +__version_info__ = (0, 1, 13) diff --git a/slixfeed/xmpp/client.py b/slixfeed/xmpp/client.py index c95b75b..fe7674c 100644 --- a/slixfeed/xmpp/client.py +++ b/slixfeed/xmpp/client.py @@ -32,7 +32,7 @@ NOTE import asyncio import logging -# import os +import os from random import randrange import slixmpp import slixfeed.task as task @@ -197,12 +197,12 @@ class Slixfeed(slixmpp.ClientXMPP): async def on_session_end(self, event): message = 'Session has ended.' - await XmppConnect.recover(self, message) + XmppConnect.recover(self, message) async def on_connection_failed(self, event): message = 'Connection has failed. Reason: {}'.format(event) - await XmppConnect.recover(self, message) + XmppConnect.recover(self, message) async def on_session_start(self, event): @@ -466,18 +466,24 @@ class Slixfeed(slixmpp.ClientXMPP): # ) # if jid == config.get_value('accounts', 'XMPP', 'operator'): + self['xep_0050'].add_command(node='subscription', + name='đŸĒļī¸ Subscribe...', + handler=self._handle_subscription_add) + self['xep_0050'].add_command(node='recent', + name='📰ī¸ Browse', + handler=self._handle_recent) self['xep_0050'].add_command(node='subscriptions', - name='📰ī¸ Subscriptions', + name='🗞ī¸ Subscriptions', handler=self._handle_subscriptions) self['xep_0050'].add_command(node='promoted', name='🔮ī¸ Featured', handler=self._handle_promoted) self['xep_0050'].add_command(node='discover', name='🔍ī¸ Discover', - handler=self._handle_promoted) - self['xep_0050'].add_command(node='subscription', - name='🔗ī¸ Add', # đŸĒļī¸ - handler=self._handle_subscription_add) + handler=self._handle_discover) + self['xep_0050'].add_command(node='remove', + name='🗑ī¸ Remove', + handler=self._handle_subscription_del) # self['xep_0050'].add_command(node='subscriptions_cat', # name='🔖ī¸ Categories', # handler=self._handle_subscription) @@ -650,6 +656,71 @@ class Slixfeed(slixmpp.ClientXMPP): return session + async def _handle_recent(self, iq, session): + jid = session['from'].bare + jid_file = jid + db_file = config.get_pathname_to_database(jid_file) + num = 100 + results = await sqlite.get_unread_entries(db_file, num) + form = self['xep_0004'].make_form('form', 'Updates') + form['instructions'] = 'Recent {} updates'.format(num) + options = form.add_field(var='update', + ftype='list-single', + label='News', + desc=('Select a news update to read.'), + required=True) + for result in results: + title = result[1] + ix = str(result[0]) + options.addOption(title, ix) + session['allow_prev'] = False # Cheogram changes style if that button - which should not be on this form - is present + session['has_next'] = True + session['next'] = self._handle_recent_select + session['payload'] = form + session['prev'] = None # Cheogram works as expected with 'allow_prev' set to False Just in case + return session + + + async def _handle_recent_select(self, payload, session): + values = payload['values'] + ix = values['update'] + jid = session['from'].bare + jid_file = jid + db_file = config.get_pathname_to_database(jid_file) + title = sqlite.get_entry_title(db_file, ix) + form = self['xep_0004'].make_form('result', 'Updates') + form['instructions'] = title[0] if title else 'Untitled' + url = sqlite.get_entry_url(db_file, ix) + if url: + url = url[0] + result = await fetch.http(url) + if 'content' in result: + data = result['content'] + summary = action.get_document_content_as_text(data) + else: + summary = 'No content to show.' + form.add_field(ftype="text-multi", + value=summary) + form['instructions'] = url + form.add_field(var='url', + ftype='hidden', + value=url) + form['instructions'] = 'Proceed to download article.' + session['allow_prev'] = True + session['has_next'] = True + session['next'] = self._handle_recent_action + session['payload'] = form + session['prev'] = self._handle_recent + return session + + + async def _handle_recent_action(self, payload, session): + # TODO await action.download_document + text_note = 'This feature is not yet available.' + session['notes'] = [['info', text_note]] + return session + + async def _handle_subscription_new(self, payload, session): jid = session['from'].bare jid_file = jid @@ -692,16 +763,16 @@ class Slixfeed(slixmpp.ClientXMPP): # session['notes'] = [['warn', response]] # Not supported by Gajim # session['notes'] = [['info', response]] form = self['xep_0004'].make_form('form', 'Subscription') - form['instructions'] = ('Subscription already exists at index {}.' + form['instructions'] = ('Subscription is assigned at index {}.' '\n' - 'Would you want to edit this subscription?' - .format(result['index'])) - options = form.add_field(var='subscription', - ftype='list-single', - label='Subscription', - desc='Continue to edit subscription.', - value=result['link']) - options.addOption(result['name'], result['link']) + '{}' + .format(result['index'], result['name'])) + form.add_field(ftype='boolean', + var='edit', + label='Would you want to edit this subscription?') + form.add_field(var='subscription', + ftype='hidden', + value=result['link']) # NOTE Should we allow "Complete"? # Do all clients provide button "Cancel". session['allow_complete'] = False @@ -724,27 +795,184 @@ class Slixfeed(slixmpp.ClientXMPP): form['instructions'] = ('New subscription' '\n' '"{}"' - '\n\n' - 'Continue to edit subscription?' - .format(result['name'], result['index'])) - options = form.add_field(var='subscription', - ftype='list-single', - # Should Gajim allows editing text-single - # field when form is of type "result"? - # ftype='text-single', - label='Subscription', - desc='Continue to edit subscription.', - value=result['link']) - options.addOption(result['name'], result['link']) + .format(result['name'])) + form.add_field(ftype='boolean', + var='edit', + label='Continue to edit subscription?') + form.add_field(var='subscription', + ftype='hidden', + value=result['link']) session['allow_complete'] = True session['allow_prev'] = False - session['has_next'] = False + # Gajim: Will offer next dialog but as a result, not as form. + # session['has_next'] = False + session['has_next'] = True session['next'] = self._handle_subscription_editor session['payload'] = form session['prev'] = None return session + async def _handle_subscription_del(self, iq, session): + jid = session['from'].bare + form = self['xep_0004'].make_form('form', 'Subscriptions') + form['instructions'] = 'Removing subscriptions' + # form.addField(var='interval', + # ftype='text-single', + # label='Interval period') + options = form.add_field(var='subscriptions', + ftype='list-multi', + label='Subscription', + desc=('Select subscriptions to remove.'), + required=True) + jid_file = jid + db_file = config.get_pathname_to_database(jid_file) + subscriptions = await sqlite.get_feeds(db_file) + subscriptions = sorted(subscriptions, key=lambda x: x[0]) + for subscription in subscriptions: + title = subscription[0] + ix = str(subscription[2]) + options.addOption(title, ix) + session['allow_complete'] = True + session['cancel'] = self._handle_cancel + session['has_next'] = False + session['next'] = self._handle_subscription_remove + session['payload'] = form + return session + + + async def _handle_subscription_remove(self, payload, session): + form = payload + jid = session['from'].bare + jid_file = jid + db_file = config.get_pathname_to_database(jid_file) + ixs = payload['values']['subscriptions'] + form.add_field(ftype='fixed', + value='Deleted subscriptions') + for ix in ixs: + name = sqlite.get_feed_title(db_file, ix) + url = sqlite.get_feed_url(db_file, ix) + await sqlite.remove_feed_by_index(db_file, ix) + # text = (ix,) + name + url + # text = ' - '.join(text) + name = name[0] if name else 'Subscription #{}'.format(ix) + url = url[0] + text = '{} <{}>'.format(name, url) + form.add_field(var=ix, + ftype='text-single', + label=url, + value=text) + form['type'] = 'result' + form['title'] = 'Done' + form['instructions'] = ('Completed successfully!') + session["has_next"] = False + session['next'] = None + session['payload'] = form + return session + + + def _handle_cancel(self, payload, session): + text_note = ('Operation has been cancelled.' + '\n' + '\n' + 'No action was taken.') + session['notes'] = [['info', text_note]] + return session + + + def _handle_discover(self, iq, session): + form = self['xep_0004'].make_form('form', 'Discover & Search') + options = form.add_field(var='search_type', + ftype='list-single', + label='Browse', + desc=('Select type of search.'), + required=True) + options.addOption('All', 'all') + options.addOption('Categories', 'cat') # Should we write this in a singular form + # options.addOption('Tags', 'tag') + session['allow_prev'] = False + session['has_next'] = True + session['next'] = self._handle_discover_type + session['payload'] = form + session['prev'] = None + return session + + + def _handle_discover_type(self, payload, session): + values = payload['values'] + search_type = values['search_type'] + config_dir = config.get_default_config_directory() + db_file = config_dir + '/feeds.sqlite' + if os.path.isfile(db_file): + form = self['xep_0004'].make_form('form', 'Discover & Search') + match search_type: + case 'all': + options = form.add_field(var='subscription', + # ftype='list-multi', # TODO To be added soon + ftype='list-single', + label='Subscription', + desc=('Select a subscription to add.'), + required=True) + results = sqlite.get_titles_tags_urls(db_file) + for result in results: + title = result[0] + tag = result[1] + url = result[2] + text = '{} ({})'.format(title, tag) + options.addOption(text, url) + # session['allow_complete'] = True + session['next'] = self._handle_subscription_new + case 'cat': + session['next'] = self._handle_discover_category + options = form.add_field(var='category', + ftype='list-single', + label='Categories', + desc=('Select a category to browse.'), + required=True) # NOTE Uncategories or no option for entries without category + categories = sqlite.get_categories(db_file) + for category in categories: + category = category[0] + options.addOption(category, category) + # case 'tag': + session['allow_prev'] = True + session['has_next'] = True + session['payload'] = form + session['prev'] = self._handle_discover + else: + text_note = ('Database is missing.' + '\n' + 'Contact operator.') + session['next'] = None + session['notes'] = [['info', text_note]] + session['payload'] = None + return session + + + async def _handle_discover_category(self, payload, session): + values = payload['values'] + category = values['category'] + config_dir = config.get_default_config_directory() + db_file = config_dir + '/feeds.sqlite' + form = self['xep_0004'].make_form('form', 'Discover & Search') + options = form.add_field(var='subscription', + # ftype='list-multi', # TODO To be added soon + ftype='list-single', + label='Subscription', + desc=('Select a subscription to add.'), + required=True) + results = sqlite.get_titles_tags_urls_by_category(db_file, category) + for result in results: + title = result[0] + tag = result[1] + url = result[2] + text = '{} ({})'.format(title, tag) + options.addOption(text, url) + # session['allow_complete'] = True + session['next'] = self._handle_subscription_new + session['payload'] = form + return session + + async def _handle_subscriptions(self, iq, session): jid = session['from'].bare form = self['xep_0004'].make_form('form', 'Subscriptions') @@ -755,8 +983,8 @@ class Slixfeed(slixmpp.ClientXMPP): options = form.add_field(var='subscriptions', # ftype='list-multi', # TODO To be added soon ftype='list-single', - label='Subscriptions', - desc=('Select subscriptions to perform ' + label='Subscription', + desc=('Select a subscription to perform ' 'actions upon.'), required=True) jid_file = jid @@ -844,6 +1072,10 @@ class Slixfeed(slixmpp.ClientXMPP): jid = session['from'].bare jid_file = jid db_file = config.get_pathname_to_database(jid_file) + if 'edit' in payload['values'] and not payload['values']['edit']: + session['payload'] = None + session['next'] = None + return session if 'subscription' in payload['values']: urls = payload['values']['subscription'] elif 'subscriptions' in payload['values']: @@ -1019,14 +1251,16 @@ class Slixfeed(slixmpp.ClientXMPP): async def _handle_activity(self, iq, session): # TODO dialog for JID and special dialog for operator - text = ('Here you can monitor activity') - session['notes'] = [['info', text]] + # Here you can monitor activity + text_note = 'This feature is not yet available.' + session['notes'] = [['info', text_note]] return session async def _handle_statistics(self, iq, session): - text = ('Here you can monitor statistics') - session['notes'] = [['info', text]] + # TODO Here you can monitor statistics + text_note = 'This feature is not yet available.' + session['notes'] = [['info', text_note]] return session @@ -1109,12 +1343,14 @@ class Slixfeed(slixmpp.ClientXMPP): for ext in exts: filename = await action.export_feeds(self, jid, jid_file, ext) url = await XmppUpload.start(self, jid, filename) - form.add_field(var=ext.upper(), - ftype='text-single', - label=ext, - value=url) + url_field = form.add_field(var=ext.upper(), + ftype='text-single', + label=ext, + value=url) + url_field['validate']['datatype'] = 'xs:anyURI' + form['type'] = 'result' form['title'] = 'Done' - form['instructions'] = ('has been completed!') + form['instructions'] = ('Completed successfully!') session["has_next"] = False session['next'] = None session['payload'] = form @@ -1130,10 +1366,9 @@ class Slixfeed(slixmpp.ClientXMPP): async def _handle_schedule(self, iq, session): - text = ('Schedule') - text += '\n\n' - text += 'Set days and hours to receive news.' - session['notes'] = [['info', text]] + # TODO Set days and hours to receive news + text_note = 'This feature is not yet available.' + session['notes'] = [['info', text_note]] return session @@ -1170,8 +1405,15 @@ class Slixfeed(slixmpp.ClientXMPP): url = result # Automatically set priority to 5 (highest) if url['link']: options.addOption(url['name'], url['link']) + session['allow_complete'] = True session['allow_prev'] = True - session['has_next'] = False + # singpolyma: Don't use complete action if there may be more steps + # https://gitgud.io/sjehuda/slixfeed/-/merge_requests/13 + # Gajim: On next form Gajim offers no button other than "Commands". + # Psi: Psi closes the dialog. + # Conclusion, change session['has_next'] from False to True + # session['has_next'] = False + session['has_next'] = True session['next'] = self._handle_subscription_new session['payload'] = form session['prev'] = self._handle_promoted @@ -1180,18 +1422,19 @@ class Slixfeed(slixmpp.ClientXMPP): async def _handle_motd(self, iq, session): # TODO add functionality to attach image. - text = ('Here you can add groupchat rules,post schedule, tasks or ' - 'anything elaborated you might deem fit. Good luck!') - session['notes'] = [['info', text]] + # Here you can add groupchat rules,post schedule, tasks or + # anything elaborated you might deem fit. Good luck! + text_note = 'This feature is not yet available.' + session['notes'] = [['info', text_note]] return session async def _handle_totd(self, iq, session): - text = ('Tips and tricks you might have not known about Slixfeed and XMPP!') - session['notes'] = [['info', text]] + # Tips and tricks you might have not known about Slixfeed and XMPP! + text_note = 'This feature is not yet available.' + session['notes'] = [['info', text_note]] return session - async def _handle_credit(self, iq, session): wrjx = action.manual('information.toml', 'thanks') form = self['xep_0004'].make_form('result', 'Credits') @@ -1250,6 +1493,14 @@ class Slixfeed(slixmpp.ClientXMPP): if jid == config.get_value('accounts', 'XMPP', 'operator'): form = self['xep_0004'].make_form('form', 'Subscribers') form['instructions'] = 'Committing subscriber action' + options = form.add_field(var='action', + ftype='list-single', + label='Action', + value='message') + options.addOption('Resend authorization To', 'to') + options.addOption('Request authorization From', 'from') + options.addOption('Send message', 'message') + options.addOption('Remove', 'remove') options = form.add_field(var='jid', ftype='list-single', label='Jabber ID', @@ -1260,21 +1511,17 @@ class Slixfeed(slixmpp.ClientXMPP): contact_name = contacts[contact]['name'] contact_name = contact_name if contact_name else contact options.addOption(contact_name, contact) - options = form.add_field(var='action', - ftype='list-single', - label='Action', - value='message') - options.addOption('Resend authorization To', 'to') - options.addOption('Request authorization From', 'from') - options.addOption('Send message', 'message') - options.addOption('Remove', 'remove') + form.add_field(var='subject', + ftype='text-single', + label='Subject') form.add_field(var='message', ftype='text-multi', label='Message', desc='Add a descriptive message.') - session['payload'] = form + session['allow_complete'] = True + session['has_next'] = False session['next'] = self._handle_subscribers_complete - session['has_next'] = True + session['payload'] = form else: logging.warning('An unauthorized attempt to access bookmarks has ' 'been detected!\n' @@ -1286,8 +1533,31 @@ class Slixfeed(slixmpp.ClientXMPP): return session - async def _handle_subscribers_complete(self, iq, session): - pass + async def _handle_subscribers_complete(self, payload, session): + values = payload['values'] + jid = values['jid'] + match values['action']: + case 'from': + pass + case 'remove': + XmppRoster.remove(self, jid) + case 'to': + pass + value_message = values['message'] + message_body = value_message if value_message else None + value_subject = values['subject'] + message_subject = value_subject if value_subject else None + if message_subject: + XmppMessage.send_headline(self, jid, message_subject, message_body, + 'chat') + elif message_body: + XmppMessage.send(self, jid, message_body, 'chat') + form = payload + form['title'] = 'Done' + form['instructions'] = ('has been completed!') + # session["has_next"] = False + session['next'] = None + session['payload'] = form async def _handle_contacts(self, iq, session): @@ -1628,49 +1898,49 @@ class Slixfeed(slixmpp.ClientXMPP): async def _handle_settings_complete(self, payload, session): jid = session['from'].bare form = payload - # jid_file = jid - # db_file = config.get_pathname_to_database(jid_file) - # # In this case (as is typical), the payload is a form - # values = payload['values'] - # for value in values: - # key = value - # val = values[value] + jid_file = jid + db_file = config.get_pathname_to_database(jid_file) + # In this case (as is typical), the payload is a form + values = payload['values'] + for value in values: + key = value + val = values[value] - # if key == 'interval': - # val = int(val) - # if val < 1: val = 1 - # val = val * 60 + if key == 'interval': + val = int(val) + if val < 1: val = 1 + val = val * 60 - # if sqlite.is_setting_key(db_file, key): - # await sqlite.update_setting_value(db_file, [key, val]) - # else: - # await sqlite.set_setting_value(db_file, [key, val]) + if sqlite.is_setting_key(db_file, key): + await sqlite.update_setting_value(db_file, [key, val]) + else: + await sqlite.set_setting_value(db_file, [key, val]) - # val = sqlite.get_setting_value(db_file, key) - # val = val[0] - # if key in ('enabled', 'media', 'old'): - # if val == '1': - # val = 'Yes' - # elif val == '0': - # val = 'No' + val = sqlite.get_setting_value(db_file, key) + val = val[0] + if key in ('enabled', 'media', 'old'): + if val == '1': + val = 'Yes' + elif val == '0': + val = 'No' - # if key == 'interval': - # val = int(val) - # val = val/60 - # val = int(val) - # val = str(val) + if key == 'interval': + val = int(val) + val = val/60 + val = int(val) + val = str(val) - # # match value: - # # case 'enabled': - # # pass - # # case 'interval': - # # pass + # match value: + # case 'enabled': + # pass + # case 'interval': + # pass - # result = '{}: {}'.format(key.capitalize(), val) + # result = '{}: {}'.format(key.capitalize(), val) - # form.add_field(var=key, - # ftype='fixed', - # value=result) + # form.add_field(var=key, + # ftype='fixed', + # value=result) form['title'] = 'Done' form['instructions'] = 'has been completed!' session['next'] = None diff --git a/slixfeed/xmpp/connect.py b/slixfeed/xmpp/connect.py index 35220e2..a3eb29b 100644 --- a/slixfeed/xmpp/connect.py +++ b/slixfeed/xmpp/connect.py @@ -54,10 +54,11 @@ class XmppConnect: if not rtt: logging.info('Disconnecting...') self.disconnect() + break await asyncio.sleep(60 * 1) - async def recover(self, message): + def recover(self, message): logging.warning(message) print(current_time(), message, 'Attempting to reconnect.') self.connection_attempts += 1 @@ -76,7 +77,7 @@ class XmppConnect: self.reconnect(wait=5.0) - async def inspect(self): + def inspect(self): print('Disconnected\n' 'Reconnecting...') try: diff --git a/slixfeed/xmpp/process.py b/slixfeed/xmpp/process.py index db8377d..510c4d6 100644 --- a/slixfeed/xmpp/process.py +++ b/slixfeed/xmpp/process.py @@ -711,7 +711,7 @@ async def message(self, message): await sqlite.update_setting_value(db_file, [key, val]) else: await sqlite.set_setting_value(db_file, [key, val]) - response = 'Only new items of newly added feeds will be sent.' + response = 'Only new items of newly added feeds be delivered.' XmppMessage.send_reply(self, message, response) # TODO Will you add support for number of messages? case 'next': @@ -734,7 +734,7 @@ async def message(self, message): await sqlite.update_setting_value(db_file, [key, val]) else: await sqlite.set_setting_value(db_file, [key, val]) - response = 'All items of newly added feeds will be sent.' + response = 'All items of newly added feeds be delivered.' XmppMessage.send_reply(self, message, response) case _ if message_lowercase.startswith('quantum'): key = message_text[:7]