Merge branch 'master' into 'use-boolean'

# Conflicts:
#   slixfeed/xmpp/client.py
This commit is contained in:
Schimon Jehudah 2024-02-19 21:06:17 +00:00
commit 22e8808d69
9 changed files with 595 additions and 113 deletions

View file

@ -184,15 +184,15 @@ def main():
logging.info('Reading configuration from {}'.format(config_dir)) logging.info('Reading configuration from {}'.format(config_dir))
print('Reading configuration from {}'.format(config_dir)) print('Reading configuration from {}'.format(config_dir))
values = config.get_value('accounts', 'XMPP Proxy', # values = config.get_value('accounts', 'XMPP Proxy',
['socks5_host', 'socks5_port']) # ['socks5_host', 'socks5_port'])
if values[0] and values[1]: # if values[0] and values[1]:
host = values[0] # host = values[0]
port = values[1] # port = values[1]
s = socks.socksocket() # s = socks.socksocket()
s.set_proxy(socks.SOCKS5, host, port) # s.set_proxy(socks.SOCKS5, host, port)
# socks.set_default_proxy(socks.SOCKS5, host, port) # # socks.set_default_proxy(socks.SOCKS5, host, port)
# socket.socket = socks.socksocket # # socket.socket = socks.socksocket
# Setup the command line arguments. # Setup the command line arguments.
parser = ArgumentParser(description=Slixfeed.__doc__) parser = ArgumentParser(description=Slixfeed.__doc__)

View file

@ -745,9 +745,9 @@ async def add_feed(db_file, url):
updated=updated) updated=updated)
await scan(db_file, url) await scan(db_file, url)
old = config.get_setting_value(db_file, "old") old = config.get_setting_value(db_file, "old")
if not old:
feed_id = await sqlite.get_feed_id(db_file, url) feed_id = await sqlite.get_feed_id(db_file, url)
feed_id = feed_id[0] feed_id = feed_id[0]
if not old:
await sqlite.mark_feed_as_read(db_file, feed_id) await sqlite.mark_feed_as_read(db_file, feed_id)
result_final = {'link' : url, result_final = {'link' : url,
'index' : feed_id, 'index' : feed_id,
@ -1301,6 +1301,7 @@ async def download_document(self, message, jid, jid_file, message_text, ix_url,
ix = int(ix_url) ix = int(ix_url)
try: try:
url = sqlite.get_entry_url(db_file, ix) url = sqlite.get_entry_url(db_file, ix)
url = url[0]
except: except:
response = 'No entry with index {}'.format(ix) response = 'No entry with index {}'.format(ix)
except: except:
@ -1363,6 +1364,27 @@ def get_document_title(data):
return title 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): def generate_document(data, url, ext, filename, readability=False):
error = None error = None
if readability: if readability:

View file

@ -116,10 +116,6 @@ key = """
help <key> help <key>
Print list of commands for selected command type. Print list of commands for selected command type.
""" """
support = """
support
Join xmpp:slixfeed@chat.woodpeckersnest.space?join
"""
[mastership] [mastership]
demaster = """ demaster = """

View file

@ -107,6 +107,10 @@ in order to remove all threads.
https://codeberg.org/poezio/slixmpp https://codeberg.org/poezio/slixmpp
""" """
support = """
xmpp:slixfeed@chat.woodpeckersnest.space?join
"""
terms = """ terms = """
Slixfeed is free software; you can redistribute it and/or \ Slixfeed is free software; you can redistribute it and/or \
modify it under the terms of the MIT License. modify it under the terms of the MIT License.

View file

@ -734,8 +734,8 @@ async def get_unread_entries(db_file, num):
UNION ALL UNION ALL
SELECT id, title, link, enclosure, feed_id, timestamp SELECT id, title, link, enclosure, feed_id, timestamp
FROM archive FROM archive
ORDER BY timestamp ORDER BY timestamp DESC
DESC LIMIT :num LIMIT :num
""" """
) )
par = (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: with create_connection(db_file) as conn:
cur = conn.cursor() cur = conn.cursor()
sql = ( sql = (
""" """
SELECT name SELECT name
FROM feeds FROM feeds
WHERE id = :feed_id WHERE id = :ix
""" """
) )
par = (feed_id,) par = (ix,)
title = cur.execute(sql, par).fetchone() title = cur.execute(sql, par).fetchone()
return title return title
@ -963,6 +963,21 @@ async def set_feed_title(db_file, feed_id, name):
cur.execute(sql, par) 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): def get_entry_url(db_file, ix):
with create_connection(db_file) as conn: with create_connection(db_file) as conn:
cur = conn.cursor() cur = conn.cursor()
@ -974,21 +989,21 @@ def get_entry_url(db_file, ix):
""" """
) )
par = (ix,) par = (ix,)
url = cur.execute(sql, par).fetchone()[0] url = cur.execute(sql, par).fetchone()
return url return url
def get_feed_url(db_file, feed_id): def get_feed_url(db_file, ix):
with create_connection(db_file) as conn: with create_connection(db_file) as conn:
cur = conn.cursor() cur = conn.cursor()
sql = ( sql = (
""" """
SELECT url SELECT url
FROM feeds FROM feeds
WHERE id = :feed_id WHERE id = :ix
""" """
) )
par = (feed_id,) par = (ix,)
url = cur.execute(sql, par).fetchone() url = cur.execute(sql, par).fetchone()
return url return url
@ -2202,3 +2217,175 @@ async def update_last_update_time(db_file):
"value": time.time() "value": time.time()
} }
cur.execute(sql, par) 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

View file

@ -1,2 +1,2 @@
__version__ = '0.1.12' __version__ = '0.1.13'
__version_info__ = (0, 1, 12) __version_info__ = (0, 1, 13)

View file

@ -32,7 +32,7 @@ NOTE
import asyncio import asyncio
import logging import logging
# import os import os
from random import randrange from random import randrange
import slixmpp import slixmpp
import slixfeed.task as task import slixfeed.task as task
@ -197,12 +197,12 @@ class Slixfeed(slixmpp.ClientXMPP):
async def on_session_end(self, event): async def on_session_end(self, event):
message = 'Session has ended.' message = 'Session has ended.'
await XmppConnect.recover(self, message) XmppConnect.recover(self, message)
async def on_connection_failed(self, event): async def on_connection_failed(self, event):
message = 'Connection has failed. Reason: {}'.format(event) message = 'Connection has failed. Reason: {}'.format(event)
await XmppConnect.recover(self, message) XmppConnect.recover(self, message)
async def on_session_start(self, event): async def on_session_start(self, event):
@ -466,18 +466,24 @@ class Slixfeed(slixmpp.ClientXMPP):
# ) # )
# if jid == config.get_value('accounts', 'XMPP', 'operator'): # 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', self['xep_0050'].add_command(node='subscriptions',
name='📰️ Subscriptions', name='🗞 Subscriptions',
handler=self._handle_subscriptions) handler=self._handle_subscriptions)
self['xep_0050'].add_command(node='promoted', self['xep_0050'].add_command(node='promoted',
name='🔮️ Featured', name='🔮️ Featured',
handler=self._handle_promoted) handler=self._handle_promoted)
self['xep_0050'].add_command(node='discover', self['xep_0050'].add_command(node='discover',
name='🔍️ Discover', name='🔍️ Discover',
handler=self._handle_promoted) handler=self._handle_discover)
self['xep_0050'].add_command(node='subscription', self['xep_0050'].add_command(node='remove',
name='🔗️ Add', # 🪶️ name='🗑️ Remove',
handler=self._handle_subscription_add) handler=self._handle_subscription_del)
# self['xep_0050'].add_command(node='subscriptions_cat', # self['xep_0050'].add_command(node='subscriptions_cat',
# name='🔖️ Categories', # name='🔖️ Categories',
# handler=self._handle_subscription) # handler=self._handle_subscription)
@ -650,6 +656,71 @@ class Slixfeed(slixmpp.ClientXMPP):
return session 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): async def _handle_subscription_new(self, payload, session):
jid = session['from'].bare jid = session['from'].bare
jid_file = jid jid_file = jid
@ -692,15 +763,16 @@ class Slixfeed(slixmpp.ClientXMPP):
# session['notes'] = [['warn', response]] # Not supported by Gajim # session['notes'] = [['warn', response]] # Not supported by Gajim
# session['notes'] = [['info', response]] # session['notes'] = [['info', response]]
form = self['xep_0004'].make_form('form', 'Subscription') form = self['xep_0004'].make_form('form', 'Subscription')
form['instructions'] = ('Subscription already exists at index {}.' form['instructions'] = ('Subscription is assigned at index {}.'
.format(result['index'])) '\n'
'{}'
.format(result['index'], result['name']))
form.add_field(ftype='boolean', form.add_field(ftype='boolean',
var='edit', var='edit',
label='Would you want to edit this subscription?') label='Would you want to edit this subscription?')
form.add_field(var='subscription', form.add_field(var='subscription',
ftype='hidden', ftype='hidden',
value=result['link']) value=result['link'])
# NOTE Should we allow "Complete"? # NOTE Should we allow "Complete"?
# Do all clients provide button "Cancel". # Do all clients provide button "Cancel".
session['allow_complete'] = False session['allow_complete'] = False
@ -723,7 +795,7 @@ class Slixfeed(slixmpp.ClientXMPP):
form['instructions'] = ('New subscription' form['instructions'] = ('New subscription'
'\n' '\n'
'"{}"' '"{}"'
.format(result['name'], result['index'])) .format(result['name']))
form.add_field(ftype='boolean', form.add_field(ftype='boolean',
var='edit', var='edit',
label='Continue to edit subscription?') label='Continue to edit subscription?')
@ -732,13 +804,175 @@ class Slixfeed(slixmpp.ClientXMPP):
value=result['link']) value=result['link'])
session['allow_complete'] = True session['allow_complete'] = True
session['allow_prev'] = False 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['next'] = self._handle_subscription_editor
session['payload'] = form session['payload'] = form
session['prev'] = None session['prev'] = None
return session 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): async def _handle_subscriptions(self, iq, session):
jid = session['from'].bare jid = session['from'].bare
form = self['xep_0004'].make_form('form', 'Subscriptions') form = self['xep_0004'].make_form('form', 'Subscriptions')
@ -749,8 +983,8 @@ class Slixfeed(slixmpp.ClientXMPP):
options = form.add_field(var='subscriptions', options = form.add_field(var='subscriptions',
# ftype='list-multi', # TODO To be added soon # ftype='list-multi', # TODO To be added soon
ftype='list-single', ftype='list-single',
label='Subscriptions', label='Subscription',
desc=('Select subscriptions to perform ' desc=('Select a subscription to perform '
'actions upon.'), 'actions upon.'),
required=True) required=True)
jid_file = jid jid_file = jid
@ -1017,14 +1251,16 @@ class Slixfeed(slixmpp.ClientXMPP):
async def _handle_activity(self, iq, session): async def _handle_activity(self, iq, session):
# TODO dialog for JID and special dialog for operator # TODO dialog for JID and special dialog for operator
text = ('Here you can monitor activity') # Here you can monitor activity
session['notes'] = [['info', text]] text_note = 'This feature is not yet available.'
session['notes'] = [['info', text_note]]
return session return session
async def _handle_statistics(self, iq, session): async def _handle_statistics(self, iq, session):
text = ('Here you can monitor statistics') # TODO Here you can monitor statistics
session['notes'] = [['info', text]] text_note = 'This feature is not yet available.'
session['notes'] = [['info', text_note]]
return session return session
@ -1107,12 +1343,14 @@ class Slixfeed(slixmpp.ClientXMPP):
for ext in exts: for ext in exts:
filename = await action.export_feeds(self, jid, jid_file, ext) filename = await action.export_feeds(self, jid, jid_file, ext)
url = await XmppUpload.start(self, jid, filename) url = await XmppUpload.start(self, jid, filename)
form.add_field(var=ext.upper(), url_field = form.add_field(var=ext.upper(),
ftype='text-single', ftype='text-single',
label=ext, label=ext,
value=url) value=url)
url_field['validate']['datatype'] = 'xs:anyURI'
form['type'] = 'result'
form['title'] = 'Done' form['title'] = 'Done'
form['instructions'] = ('has been completed!') form['instructions'] = ('Completed successfully!')
session["has_next"] = False session["has_next"] = False
session['next'] = None session['next'] = None
session['payload'] = form session['payload'] = form
@ -1128,10 +1366,9 @@ class Slixfeed(slixmpp.ClientXMPP):
async def _handle_schedule(self, iq, session): async def _handle_schedule(self, iq, session):
text = ('Schedule') # TODO Set days and hours to receive news
text += '\n\n' text_note = 'This feature is not yet available.'
text += 'Set days and hours to receive news.' session['notes'] = [['info', text_note]]
session['notes'] = [['info', text]]
return session return session
@ -1168,8 +1405,15 @@ class Slixfeed(slixmpp.ClientXMPP):
url = result url = result
# Automatically set priority to 5 (highest) # Automatically set priority to 5 (highest)
if url['link']: options.addOption(url['name'], url['link']) if url['link']: options.addOption(url['name'], url['link'])
session['allow_complete'] = True
session['allow_prev'] = 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['next'] = self._handle_subscription_new
session['payload'] = form session['payload'] = form
session['prev'] = self._handle_promoted session['prev'] = self._handle_promoted
@ -1178,18 +1422,19 @@ class Slixfeed(slixmpp.ClientXMPP):
async def _handle_motd(self, iq, session): async def _handle_motd(self, iq, session):
# TODO add functionality to attach image. # TODO add functionality to attach image.
text = ('Here you can add groupchat rules,post schedule, tasks or ' # Here you can add groupchat rules,post schedule, tasks or
'anything elaborated you might deem fit. Good luck!') # anything elaborated you might deem fit. Good luck!
session['notes'] = [['info', text]] text_note = 'This feature is not yet available.'
session['notes'] = [['info', text_note]]
return session return session
async def _handle_totd(self, iq, session): async def _handle_totd(self, iq, session):
text = ('Tips and tricks you might have not known about Slixfeed and XMPP!') # Tips and tricks you might have not known about Slixfeed and XMPP!
session['notes'] = [['info', text]] text_note = 'This feature is not yet available.'
session['notes'] = [['info', text_note]]
return session return session
async def _handle_credit(self, iq, session): async def _handle_credit(self, iq, session):
wrjx = action.manual('information.toml', 'thanks') wrjx = action.manual('information.toml', 'thanks')
form = self['xep_0004'].make_form('result', 'Credits') form = self['xep_0004'].make_form('result', 'Credits')
@ -1248,6 +1493,14 @@ class Slixfeed(slixmpp.ClientXMPP):
if jid == config.get_value('accounts', 'XMPP', 'operator'): if jid == config.get_value('accounts', 'XMPP', 'operator'):
form = self['xep_0004'].make_form('form', 'Subscribers') form = self['xep_0004'].make_form('form', 'Subscribers')
form['instructions'] = 'Committing subscriber action' 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', options = form.add_field(var='jid',
ftype='list-single', ftype='list-single',
label='Jabber ID', label='Jabber ID',
@ -1258,21 +1511,17 @@ class Slixfeed(slixmpp.ClientXMPP):
contact_name = contacts[contact]['name'] contact_name = contacts[contact]['name']
contact_name = contact_name if contact_name else contact contact_name = contact_name if contact_name else contact
options.addOption(contact_name, contact) options.addOption(contact_name, contact)
options = form.add_field(var='action', form.add_field(var='subject',
ftype='list-single', ftype='text-single',
label='Action', label='Subject')
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='message', form.add_field(var='message',
ftype='text-multi', ftype='text-multi',
label='Message', label='Message',
desc='Add a descriptive message.') desc='Add a descriptive message.')
session['payload'] = form session['allow_complete'] = True
session['has_next'] = False
session['next'] = self._handle_subscribers_complete session['next'] = self._handle_subscribers_complete
session['has_next'] = True session['payload'] = form
else: else:
logging.warning('An unauthorized attempt to access bookmarks has ' logging.warning('An unauthorized attempt to access bookmarks has '
'been detected!\n' 'been detected!\n'
@ -1284,8 +1533,31 @@ class Slixfeed(slixmpp.ClientXMPP):
return session return session
async def _handle_subscribers_complete(self, iq, session): async def _handle_subscribers_complete(self, payload, session):
values = payload['values']
jid = values['jid']
match values['action']:
case 'from':
pass 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): async def _handle_contacts(self, iq, session):
@ -1626,43 +1898,43 @@ class Slixfeed(slixmpp.ClientXMPP):
async def _handle_settings_complete(self, payload, session): async def _handle_settings_complete(self, payload, session):
jid = session['from'].bare jid = session['from'].bare
form = payload form = payload
# jid_file = jid jid_file = jid
# db_file = config.get_pathname_to_database(jid_file) db_file = config.get_pathname_to_database(jid_file)
# # In this case (as is typical), the payload is a form # In this case (as is typical), the payload is a form
# values = payload['values'] values = payload['values']
# for value in values: for value in values:
# key = value key = value
# val = values[value] val = values[value]
# if key == 'interval': if key == 'interval':
# val = int(val) val = int(val)
# if val < 1: val = 1 if val < 1: val = 1
# val = val * 60 val = val * 60
# if sqlite.is_setting_key(db_file, key): if sqlite.is_setting_key(db_file, key):
# await sqlite.update_setting_value(db_file, [key, val]) await sqlite.update_setting_value(db_file, [key, val])
# else: else:
# await sqlite.set_setting_value(db_file, [key, val]) await sqlite.set_setting_value(db_file, [key, val])
# val = sqlite.get_setting_value(db_file, key) val = sqlite.get_setting_value(db_file, key)
# val = val[0] val = val[0]
# if key in ('enabled', 'media', 'old'): if key in ('enabled', 'media', 'old'):
# if val == '1': if val == '1':
# val = 'Yes' val = 'Yes'
# elif val == '0': elif val == '0':
# val = 'No' val = 'No'
# if key == 'interval': if key == 'interval':
# val = int(val) val = int(val)
# val = val/60 val = val/60
# val = int(val) val = int(val)
# val = str(val) val = str(val)
# # match value: # match value:
# # case 'enabled': # case 'enabled':
# # pass # pass
# # case 'interval': # case 'interval':
# # pass # pass
# result = '{}: {}'.format(key.capitalize(), val) # result = '{}: {}'.format(key.capitalize(), val)

View file

@ -54,10 +54,11 @@ class XmppConnect:
if not rtt: if not rtt:
logging.info('Disconnecting...') logging.info('Disconnecting...')
self.disconnect() self.disconnect()
break
await asyncio.sleep(60 * 1) await asyncio.sleep(60 * 1)
async def recover(self, message): def recover(self, message):
logging.warning(message) logging.warning(message)
print(current_time(), message, 'Attempting to reconnect.') print(current_time(), message, 'Attempting to reconnect.')
self.connection_attempts += 1 self.connection_attempts += 1
@ -76,7 +77,7 @@ class XmppConnect:
self.reconnect(wait=5.0) self.reconnect(wait=5.0)
async def inspect(self): def inspect(self):
print('Disconnected\n' print('Disconnected\n'
'Reconnecting...') 'Reconnecting...')
try: try:

View file

@ -711,7 +711,7 @@ async def message(self, message):
await sqlite.update_setting_value(db_file, [key, val]) await sqlite.update_setting_value(db_file, [key, val])
else: else:
await sqlite.set_setting_value(db_file, [key, val]) 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) XmppMessage.send_reply(self, message, response)
# TODO Will you add support for number of messages? # TODO Will you add support for number of messages?
case 'next': case 'next':
@ -734,7 +734,7 @@ async def message(self, message):
await sqlite.update_setting_value(db_file, [key, val]) await sqlite.update_setting_value(db_file, [key, val])
else: else:
await sqlite.set_setting_value(db_file, [key, val]) 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) XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('quantum'): case _ if message_lowercase.startswith('quantum'):
key = message_text[:7] key = message_text[:7]