Add functionality to download article via ad-hoc.
Add helper for URL.
This commit is contained in:
parent
6e2a7305c2
commit
9bb37bc932
6 changed files with 315 additions and 195 deletions
|
@ -1224,87 +1224,6 @@ async def scan(db_file, url):
|
||||||
new_entries)
|
new_entries)
|
||||||
|
|
||||||
|
|
||||||
async def download_document(self, message, jid, jid_file, message_text, ix_url,
|
|
||||||
readability):
|
|
||||||
ext = ' '.join(message_text.split(' ')[1:])
|
|
||||||
ext = ext if ext else 'pdf'
|
|
||||||
url = None
|
|
||||||
error = None
|
|
||||||
response = None
|
|
||||||
if ext in ('epub', 'html', 'markdown', 'md', 'pdf', 'text', 'txt'):
|
|
||||||
match ext:
|
|
||||||
case 'markdown':
|
|
||||||
ext = 'md'
|
|
||||||
case 'text':
|
|
||||||
ext = 'txt'
|
|
||||||
status_type = 'dnd'
|
|
||||||
status_message = ('📃️ Procesing request to produce {} document...'
|
|
||||||
.format(ext.upper()))
|
|
||||||
XmppPresence.send(self, jid, status_message, status_type=status_type)
|
|
||||||
db_file = config.get_pathname_to_database(jid_file)
|
|
||||||
cache_dir = config.get_default_cache_directory()
|
|
||||||
if ix_url:
|
|
||||||
if not os.path.isdir(cache_dir):
|
|
||||||
os.mkdir(cache_dir)
|
|
||||||
if not os.path.isdir(cache_dir + '/readability'):
|
|
||||||
os.mkdir(cache_dir + '/readability')
|
|
||||||
try:
|
|
||||||
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:
|
|
||||||
url = ix_url
|
|
||||||
if url:
|
|
||||||
logging.info('Original URL: {}'
|
|
||||||
.format(url))
|
|
||||||
url = uri.remove_tracking_parameters(url)
|
|
||||||
logging.info('Processed URL (tracker removal): {}'
|
|
||||||
.format(url))
|
|
||||||
url = (uri.replace_hostname(url, 'link')) or url
|
|
||||||
logging.info('Processed URL (replace hostname): {}'
|
|
||||||
.format(url))
|
|
||||||
result = await fetch.http(url)
|
|
||||||
if not result['error']:
|
|
||||||
data = result['content']
|
|
||||||
code = result['status_code']
|
|
||||||
title = get_document_title(data)
|
|
||||||
title = title.strip().lower()
|
|
||||||
for i in (' ', '-'):
|
|
||||||
title = title.replace(i, '_')
|
|
||||||
for i in ('?', '"', '\'', '!'):
|
|
||||||
title = title.replace(i, '')
|
|
||||||
filename = os.path.join(
|
|
||||||
cache_dir, 'readability',
|
|
||||||
title + '_' + dt.timestamp() + '.' + ext)
|
|
||||||
error = generate_document(data, url, ext, filename,
|
|
||||||
readability)
|
|
||||||
if error:
|
|
||||||
response = ('> {}\n'
|
|
||||||
'Failed to export {}. Reason: {}'
|
|
||||||
.format(url, ext.upper(), error))
|
|
||||||
else:
|
|
||||||
url = await XmppUpload.start(self, jid, filename)
|
|
||||||
chat_type = await get_chat_type(self, jid)
|
|
||||||
XmppMessage.send_oob(self, jid, url, chat_type)
|
|
||||||
else:
|
|
||||||
response = ('> {}\n'
|
|
||||||
'Failed to fetch URL. Reason: {}'
|
|
||||||
.format(url, code))
|
|
||||||
await task.start_tasks_xmpp(self, jid, ['status'])
|
|
||||||
else:
|
|
||||||
response = 'Missing entry index number.'
|
|
||||||
else:
|
|
||||||
response = ('Unsupported filetype.\n'
|
|
||||||
'Try: epub, html, md (markdown), '
|
|
||||||
'pdf, or txt (text)')
|
|
||||||
if response:
|
|
||||||
logging.warning('Error for URL {}: {}'.format(url, error))
|
|
||||||
XmppMessage.send_reply(self, message, response)
|
|
||||||
|
|
||||||
|
|
||||||
def get_document_title(data):
|
def get_document_title(data):
|
||||||
try:
|
try:
|
||||||
document = Document(data)
|
document = Document(data)
|
||||||
|
|
|
@ -190,6 +190,17 @@ https://codeberg.org/poezio/slixmpp
|
||||||
|
|
||||||
software = [
|
software = [
|
||||||
"""
|
"""
|
||||||
|
Canto
|
||||||
|
|
||||||
|
Canto is an Atom/RSS feed reader for the console that is meant to \
|
||||||
|
be quick, concise, and colorful. It’s meant to provide a minimal, yet \
|
||||||
|
information packed interface. No navigating menus. No dense blocks of \
|
||||||
|
unreadable white text. An interface with almost infinite customization \
|
||||||
|
and extensibility using the excellent Python programming language.
|
||||||
|
|
||||||
|
https://codezen.org/canto-ng/
|
||||||
|
|
||||||
|
|
||||||
CommaFeed
|
CommaFeed
|
||||||
|
|
||||||
A self-hosted RSS reader, based on Dropwizard and React/TypeScript.
|
A self-hosted RSS reader, based on Dropwizard and React/TypeScript.
|
||||||
|
@ -233,6 +244,24 @@ and more reliably from the sites you trust.
|
||||||
https://netnewswire.com/
|
https://netnewswire.com/
|
||||||
|
|
||||||
|
|
||||||
|
QuiteRSS
|
||||||
|
|
||||||
|
QuiteRSS is a free and convenient program for reading RSS/Atom news \
|
||||||
|
feeds.
|
||||||
|
|
||||||
|
http://quiterss.org/
|
||||||
|
|
||||||
|
|
||||||
|
Raven Reader
|
||||||
|
|
||||||
|
Raven is a open source desktop news reader with flexible settings to \
|
||||||
|
optimize your experience. No login is required, and no personal data \
|
||||||
|
is collected. Just select the websites you want to curate articles \
|
||||||
|
from and enjoy!
|
||||||
|
|
||||||
|
https://ravenreader.app/
|
||||||
|
|
||||||
|
|
||||||
Spot-On
|
Spot-On
|
||||||
|
|
||||||
Spot-On is a software carnival which brings chat, email, news, \
|
Spot-On is a software carnival which brings chat, email, news, \
|
||||||
|
|
|
@ -5,14 +5,10 @@
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
0) Move functions send_status and send_update to module action
|
|
||||||
|
|
||||||
1) Deprecate "add" (see above) and make it interactive.
|
1) Deprecate "add" (see above) and make it interactive.
|
||||||
Slixfeed: Do you still want to add this URL to subscription list?
|
Slixfeed: Do you still want to add this URL to subscription list?
|
||||||
See: case _ if message_lowercase.startswith("add"):
|
See: case _ if message_lowercase.startswith("add"):
|
||||||
|
|
||||||
2) Use loop (with gather) instead of TaskGroup.
|
|
||||||
|
|
||||||
3) Assure message delivery before calling a new task.
|
3) Assure message delivery before calling a new task.
|
||||||
See https://slixmpp.readthedocs.io/en/latest/event_index.html#term-marker_acknowledged
|
See https://slixmpp.readthedocs.io/en/latest/event_index.html#term-marker_acknowledged
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
__version__ = '0.1.14'
|
__version__ = '0.1.15'
|
||||||
__version_info__ = (0, 1, 14)
|
__version_info__ = (0, 1, 15)
|
||||||
|
|
|
@ -49,8 +49,8 @@ from slixmpp.plugins.xep_0048.stanza import Bookmarks
|
||||||
import slixfeed.action as action
|
import slixfeed.action as action
|
||||||
import slixfeed.config as config
|
import slixfeed.config as config
|
||||||
import slixfeed.crawl as crawl
|
import slixfeed.crawl as crawl
|
||||||
|
import slixfeed.dt as dt
|
||||||
import slixfeed.fetch as fetch
|
import slixfeed.fetch as fetch
|
||||||
from slixfeed.dt import timestamp
|
|
||||||
import slixfeed.sqlite as sqlite
|
import slixfeed.sqlite as sqlite
|
||||||
import slixfeed.url as uri
|
import slixfeed.url as uri
|
||||||
from slixfeed.version import __version__
|
from slixfeed.version import __version__
|
||||||
|
@ -600,6 +600,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
label='URL',
|
label='URL',
|
||||||
desc='Enter subscription URL.',
|
desc='Enter subscription URL.',
|
||||||
|
value='http://',
|
||||||
required=True)
|
required=True)
|
||||||
# form.add_field(var='scan',
|
# form.add_field(var='scan',
|
||||||
# ftype='boolean',
|
# ftype='boolean',
|
||||||
|
@ -647,7 +648,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
db_file = config.get_pathname_to_database(jid_file)
|
db_file = config.get_pathname_to_database(jid_file)
|
||||||
title = sqlite.get_entry_title(db_file, ix)
|
title = sqlite.get_entry_title(db_file, ix)
|
||||||
title = title[0] if title else 'Untitled'
|
title = title[0] if title else 'Untitled'
|
||||||
form = self['xep_0004'].make_form('result', 'Updates')
|
form = self['xep_0004'].make_form('form', 'Article')
|
||||||
url = sqlite.get_entry_url(db_file, ix)
|
url = sqlite.get_entry_url(db_file, ix)
|
||||||
url = url[0]
|
url = url[0]
|
||||||
logging.info('Original URL: {}'.format(url))
|
logging.info('Original URL: {}'.format(url))
|
||||||
|
@ -665,6 +666,9 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
label=title,
|
label=title,
|
||||||
value=summary)
|
value=summary)
|
||||||
field_url = form.add_field(var='url',
|
field_url = form.add_field(var='url',
|
||||||
|
ftype='hidden',
|
||||||
|
value=url)
|
||||||
|
field_url = form.add_field(var='url_link',
|
||||||
label='Link',
|
label='Link',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=url)
|
value=url)
|
||||||
|
@ -678,7 +682,19 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=feed_url)
|
value=feed_url)
|
||||||
field_feed['validate']['datatype'] = 'xs:anyURI'
|
field_feed['validate']['datatype'] = 'xs:anyURI'
|
||||||
|
options = form.add_field(var='filetype',
|
||||||
|
ftype='list-single',
|
||||||
|
label='Save as',
|
||||||
|
desc=('Select file type.'),
|
||||||
|
value='pdf',
|
||||||
|
required=True)
|
||||||
|
options.addOption('ePUB', 'epub')
|
||||||
|
options.addOption('HTML', 'html')
|
||||||
|
options.addOption('Markdown', 'md')
|
||||||
|
options.addOption('PDF', 'pdf')
|
||||||
|
options.addOption('Plain Text', 'txt')
|
||||||
form['instructions'] = 'Proceed to download article.'
|
form['instructions'] = 'Proceed to download article.'
|
||||||
|
session['allow_complete'] = False
|
||||||
session['allow_prev'] = True
|
session['allow_prev'] = True
|
||||||
session['has_next'] = True
|
session['has_next'] = True
|
||||||
session['next'] = self._handle_recent_action
|
session['next'] = self._handle_recent_action
|
||||||
|
@ -688,9 +704,52 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_recent_action(self, payload, session):
|
async def _handle_recent_action(self, payload, session):
|
||||||
# TODO await action.download_document
|
ext = payload['values']['filetype']
|
||||||
text_note = 'This feature is not yet available.'
|
url = payload['values']['url'][0]
|
||||||
session['notes'] = [['info', text_note]]
|
jid = session['from'].bare
|
||||||
|
jid_file = jid
|
||||||
|
db_file = config.get_pathname_to_database(jid_file)
|
||||||
|
cache_dir = config.get_default_cache_directory()
|
||||||
|
if not os.path.isdir(cache_dir):
|
||||||
|
os.mkdir(cache_dir)
|
||||||
|
if not os.path.isdir(cache_dir + '/readability'):
|
||||||
|
os.mkdir(cache_dir + '/readability')
|
||||||
|
url = uri.remove_tracking_parameters(url)
|
||||||
|
url = (uri.replace_hostname(url, 'link')) or url
|
||||||
|
result = await fetch.http(url)
|
||||||
|
if not result['error']:
|
||||||
|
data = result['content']
|
||||||
|
code = result['status_code']
|
||||||
|
title = action.get_document_title(data)
|
||||||
|
title = title.strip().lower()
|
||||||
|
for i in (' ', '-'):
|
||||||
|
title = title.replace(i, '_')
|
||||||
|
for i in ('?', '"', '\'', '!'):
|
||||||
|
title = title.replace(i, '')
|
||||||
|
filename = os.path.join(
|
||||||
|
cache_dir, 'readability',
|
||||||
|
title + '_' + dt.timestamp() + '.' + ext)
|
||||||
|
error = action.generate_document(data, url, ext, filename,
|
||||||
|
readability=True)
|
||||||
|
if error:
|
||||||
|
text_error = ('Failed to export {} fot {}'
|
||||||
|
'\n\n'
|
||||||
|
'Reason: {}'.format(ext.upper(), url, error))
|
||||||
|
session['notes'] = [['error', text_error]]
|
||||||
|
else:
|
||||||
|
url = await XmppUpload.start(self, jid, filename)
|
||||||
|
form = self['xep_0004'].make_form('result', 'Download')
|
||||||
|
form['instructions'] = ('Download {} document.'
|
||||||
|
.format(ext.upper()))
|
||||||
|
field_url = form.add_field(var='url',
|
||||||
|
label='Link',
|
||||||
|
ftype='text-single',
|
||||||
|
value=url)
|
||||||
|
field_url['validate']['datatype'] = 'xs:anyURI'
|
||||||
|
session['payload'] = form
|
||||||
|
session['allow_complete'] = True
|
||||||
|
session['next'] = None
|
||||||
|
session['prev'] = None
|
||||||
return session
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
@ -700,89 +759,119 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
db_file = config.get_pathname_to_database(jid_file)
|
db_file = config.get_pathname_to_database(jid_file)
|
||||||
# scan = payload['values']['scan']
|
# scan = payload['values']['scan']
|
||||||
url = payload['values']['subscription']
|
url = payload['values']['subscription']
|
||||||
result = await action.add_feed(db_file, url)
|
if isinstance(url, list) and len(url) > 1:
|
||||||
if isinstance(result, list):
|
urls = url
|
||||||
results = result
|
agree_count = 0
|
||||||
form = self['xep_0004'].make_form('form', 'Subscriptions')
|
error_count = 0
|
||||||
form['instructions'] = ('Discovered {} subscriptions for {}'
|
exist_count = 0
|
||||||
.format(len(results), url))
|
for url in urls:
|
||||||
options = form.add_field(var='subscription',
|
result = await action.add_feed(db_file, url)
|
||||||
ftype='list-single',
|
if result['error']:
|
||||||
label='Subscribe',
|
error_count += 1
|
||||||
desc=('Select a subscription to add.'),
|
elif result['exist']:
|
||||||
required=True)
|
exist_count += 1
|
||||||
for result in results:
|
else:
|
||||||
options.addOption(result['name'], result['link'])
|
agree_count += 1
|
||||||
# NOTE Disabling "allow_prev" until Cheogram would allow to display
|
form = self['xep_0004'].make_form('form', 'Subscription')
|
||||||
# items of list-single as buttons when button "back" is enabled.
|
if agree_count:
|
||||||
# session['allow_prev'] = True
|
response = ('Added {} new subscription(s) out of {}'
|
||||||
session['has_next'] = True
|
.format(agree_count, len(url)))
|
||||||
session['next'] = self._handle_subscription_new
|
session['notes'] = [['info', response]]
|
||||||
session['payload'] = form
|
else:
|
||||||
# session['prev'] = self._handle_subscription_add
|
response = ('No new subscription was added. '
|
||||||
elif result['error']:
|
'Exist: {} Error: {}.'
|
||||||
response = ('Failed to load URL <{}> Reason: {}'
|
.format(exist_count, error_count))
|
||||||
.format(url, result['code']))
|
session['notes'] = [['error', response]]
|
||||||
session['allow_prev'] = True
|
session['allow_prev'] = True
|
||||||
session['next'] = None
|
session['next'] = None
|
||||||
session['notes'] = [['error', response]]
|
|
||||||
session['payload'] = None
|
session['payload'] = None
|
||||||
session['prev'] = self._handle_subscription_add
|
session['prev'] = self._handle_subscription_add
|
||||||
elif result['exist']:
|
|
||||||
# response = ('News source "{}" is already listed '
|
|
||||||
# 'in the subscription list at index '
|
|
||||||
# '{}.\n{}'.format(result['name'], result['index'],
|
|
||||||
# result['link']))
|
|
||||||
# session['notes'] = [['warn', response]] # Not supported by Gajim
|
|
||||||
# session['notes'] = [['info', response]]
|
|
||||||
form = self['xep_0004'].make_form('form', 'Subscription')
|
|
||||||
form['instructions'] = ('Subscription is assigned at index {}.'
|
|
||||||
'\n'
|
|
||||||
'{}'
|
|
||||||
.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
|
|
||||||
session['has_next'] = True
|
|
||||||
session['next'] = self._handle_subscription_editor
|
|
||||||
session['payload'] = form
|
|
||||||
# session['has_next'] = False
|
|
||||||
else:
|
else:
|
||||||
# response = ('News source "{}" has been '
|
if isinstance(url, list):
|
||||||
# 'added to subscription list.\n{}'
|
url = url[0]
|
||||||
# .format(result['name'], result['link']))
|
result = await action.add_feed(db_file, url)
|
||||||
# session['notes'] = [['info', response]]
|
if isinstance(result, list):
|
||||||
form = self['xep_0004'].make_form('form', 'Subscription')
|
results = result
|
||||||
# form['instructions'] = ('✅️ News source "{}" has been added to '
|
form = self['xep_0004'].make_form('form', 'Subscriptions')
|
||||||
# 'subscription list as index {}'
|
form['instructions'] = ('Discovered {} subscriptions for {}'
|
||||||
# '\n\n'
|
.format(len(results), url))
|
||||||
# 'Choose next to continue to subscription '
|
options = form.add_field(var='subscription',
|
||||||
# 'editor.'
|
ftype='list-multi',
|
||||||
# .format(result['name'], result['index']))
|
label='Subscribe',
|
||||||
form['instructions'] = ('New subscription'
|
desc=('Select subscriptions to add.'),
|
||||||
'\n'
|
required=True)
|
||||||
'"{}"'
|
for result in results:
|
||||||
.format(result['name']))
|
options.addOption(result['name'], result['link'])
|
||||||
form.add_field(ftype='boolean',
|
# NOTE Disabling "allow_prev" until Cheogram would allow to display
|
||||||
var='edit',
|
# items of list-single as buttons when button "back" is enabled.
|
||||||
label='Continue to edit subscription?')
|
# session['allow_prev'] = True
|
||||||
form.add_field(var='subscription',
|
session['has_next'] = True
|
||||||
ftype='hidden',
|
session['next'] = self._handle_subscription_new
|
||||||
value=result['link'])
|
session['payload'] = form
|
||||||
session['allow_complete'] = True
|
# session['prev'] = self._handle_subscription_add
|
||||||
session['allow_prev'] = False
|
elif result['error']:
|
||||||
# Gajim: Will offer next dialog but as a result, not as form.
|
response = ('Failed to load URL <{}> Reason: {}'
|
||||||
# session['has_next'] = False
|
.format(url, result['code']))
|
||||||
session['has_next'] = True
|
session['allow_prev'] = True
|
||||||
session['next'] = self._handle_subscription_editor
|
session['next'] = None
|
||||||
session['payload'] = form
|
session['notes'] = [['error', response]]
|
||||||
session['prev'] = None
|
session['payload'] = None
|
||||||
|
session['prev'] = self._handle_subscription_add
|
||||||
|
elif result['exist']:
|
||||||
|
# response = ('News source "{}" is already listed '
|
||||||
|
# 'in the subscription list at index '
|
||||||
|
# '{}.\n{}'.format(result['name'], result['index'],
|
||||||
|
# result['link']))
|
||||||
|
# session['notes'] = [['warn', response]] # Not supported by Gajim
|
||||||
|
# session['notes'] = [['info', response]]
|
||||||
|
form = self['xep_0004'].make_form('form', 'Subscription')
|
||||||
|
form['instructions'] = ('Subscription is already assigned at index {}.'
|
||||||
|
'\n'
|
||||||
|
'{}'
|
||||||
|
.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
|
||||||
|
session['has_next'] = True
|
||||||
|
session['next'] = self._handle_subscription_editor
|
||||||
|
session['payload'] = form
|
||||||
|
# session['has_next'] = False
|
||||||
|
else:
|
||||||
|
# response = ('News source "{}" has been '
|
||||||
|
# 'added to subscription list.\n{}'
|
||||||
|
# .format(result['name'], result['link']))
|
||||||
|
# session['notes'] = [['info', response]]
|
||||||
|
form = self['xep_0004'].make_form('form', 'Subscription')
|
||||||
|
# form['instructions'] = ('✅️ News source "{}" has been added to '
|
||||||
|
# 'subscription list as index {}'
|
||||||
|
# '\n\n'
|
||||||
|
# 'Choose next to continue to subscription '
|
||||||
|
# 'editor.'
|
||||||
|
# .format(result['name'], result['index']))
|
||||||
|
form['instructions'] = ('New subscription'
|
||||||
|
'\n'
|
||||||
|
'"{}"'
|
||||||
|
.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'] = False
|
||||||
|
session['has_next'] = True
|
||||||
|
# session['allow_prev'] = False
|
||||||
|
# Gajim: Will offer next dialog but as a result, not as form.
|
||||||
|
# session['has_next'] = False
|
||||||
|
session['next'] = self._handle_subscription_editor
|
||||||
|
session['payload'] = form
|
||||||
|
# session['prev'] = None
|
||||||
return session
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
@ -985,8 +1074,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
ftype='list-single',
|
ftype='list-single',
|
||||||
label='Action',
|
label='Action',
|
||||||
desc='Select action type.',
|
desc='Select action type.',
|
||||||
required=True,
|
required=True)
|
||||||
value='edit')
|
|
||||||
options.addOption('Enable subscriptions', 'enable')
|
options.addOption('Enable subscriptions', 'enable')
|
||||||
options.addOption('Disable subscriptions', 'disable')
|
options.addOption('Disable subscriptions', 'disable')
|
||||||
options.addOption('Modify subscriptions', 'edit')
|
options.addOption('Modify subscriptions', 'edit')
|
||||||
|
@ -1279,8 +1367,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
options = form.add_field(var='option',
|
options = form.add_field(var='option',
|
||||||
ftype='list-single',
|
ftype='list-single',
|
||||||
label='Choose',
|
label='Choose',
|
||||||
required=True,
|
required=True)
|
||||||
value='import')
|
|
||||||
# options.addOption('Activity', 'activity')
|
# options.addOption('Activity', 'activity')
|
||||||
# options.addOption('Filters', 'filter')
|
# options.addOption('Filters', 'filter')
|
||||||
# options.addOption('Statistics', 'statistics')
|
# options.addOption('Statistics', 'statistics')
|
||||||
|
@ -1337,7 +1424,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
'Details:\n'
|
'Details:\n'
|
||||||
' Jabber ID: {}\n'
|
' Jabber ID: {}\n'
|
||||||
' Timestamp: {}\n'
|
' Timestamp: {}\n'
|
||||||
.format(jid, timestamp()))
|
.format(jid, dt.timestamp()))
|
||||||
text_warn = 'This resource is restricted.'
|
text_warn = 'This resource is restricted.'
|
||||||
session['notes'] = [['warn', text_warn]]
|
session['notes'] = [['warn', text_warn]]
|
||||||
session['has_next'] = False
|
session['has_next'] = False
|
||||||
|
@ -1403,8 +1490,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
options = form.add_field(var='option',
|
options = form.add_field(var='option',
|
||||||
ftype='list-single',
|
ftype='list-single',
|
||||||
label='About',
|
label='About',
|
||||||
required=True,
|
required=True)
|
||||||
value='')
|
|
||||||
options.addOption('Slixfeed', 'about')
|
options.addOption('Slixfeed', 'about')
|
||||||
options.addOption('RSS Task Force', 'rtf')
|
options.addOption('RSS Task Force', 'rtf')
|
||||||
# options.addOption('Manual', 'manual')
|
# options.addOption('Manual', 'manual')
|
||||||
|
@ -1609,16 +1695,25 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# TODO Attempt to look up for feeds of hostname of JID (i.e. scan
|
# TODO Attempt to look up for feeds of hostname of JID (i.e. scan
|
||||||
# jabber.de for feeds for juliet@jabber.de)
|
# jabber.de for feeds for juliet@jabber.de)
|
||||||
async def _handle_promoted(self, iq, session):
|
async def _handle_promoted(self, iq, session):
|
||||||
url = action.pick_a_feed()
|
|
||||||
form = self['xep_0004'].make_form('form', 'Subscribe')
|
form = self['xep_0004'].make_form('form', 'Subscribe')
|
||||||
# NOTE Refresh button would be of use
|
# NOTE Refresh button would be of use
|
||||||
form['instructions'] = 'Featured subscriptions'
|
form['instructions'] = 'Featured subscriptions'
|
||||||
|
url = action.pick_a_feed()
|
||||||
|
# options = form.add_field(var='choice',
|
||||||
|
# ftype="boolean",
|
||||||
|
# label='Subscribe to {}?'.format(url['name']),
|
||||||
|
# desc='Click to subscribe.')
|
||||||
|
# form.add_field(var='subscription',
|
||||||
|
# ftype='hidden',
|
||||||
|
# value=url['link'])
|
||||||
options = form.add_field(var='subscription',
|
options = form.add_field(var='subscription',
|
||||||
ftype="list-single",
|
ftype="list-single",
|
||||||
label='Subscribe',
|
label='Subscribe',
|
||||||
desc='Click to subscribe.',
|
desc='Click to subscribe.')
|
||||||
value=url['link'])
|
for i in range(10):
|
||||||
options.addOption(url['name'], url['link'])
|
url = action.pick_a_feed()
|
||||||
|
options.addOption(url['name'], url['link'])
|
||||||
jid = session['from'].bare
|
jid = session['from'].bare
|
||||||
if '@' in jid:
|
if '@' in jid:
|
||||||
hostname = jid.split('@')[1]
|
hostname = jid.split('@')[1]
|
||||||
|
@ -1638,7 +1733,7 @@ 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_complete'] = False
|
||||||
session['allow_prev'] = True
|
session['allow_prev'] = True
|
||||||
# singpolyma: Don't use complete action if there may be more steps
|
# singpolyma: Don't use complete action if there may be more steps
|
||||||
# https://gitgud.io/sjehuda/slixfeed/-/merge_requests/13
|
# https://gitgud.io/sjehuda/slixfeed/-/merge_requests/13
|
||||||
|
@ -1690,7 +1785,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
options = form.add_field(var='action',
|
options = form.add_field(var='action',
|
||||||
ftype='list-single',
|
ftype='list-single',
|
||||||
label='Action',
|
label='Action',
|
||||||
value='view')
|
required=True)
|
||||||
options.addOption('Display', 'view')
|
options.addOption('Display', 'view')
|
||||||
options.addOption('Edit', 'edit')
|
options.addOption('Edit', 'edit')
|
||||||
session['has_next'] = True
|
session['has_next'] = True
|
||||||
|
@ -1701,7 +1796,8 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
options = form.add_field(var='action',
|
options = form.add_field(var='action',
|
||||||
ftype='list-single',
|
ftype='list-single',
|
||||||
label='Action',
|
label='Action',
|
||||||
value='message')
|
value='message',
|
||||||
|
required=True)
|
||||||
options.addOption('Request authorization From', 'from')
|
options.addOption('Request authorization From', 'from')
|
||||||
options.addOption('Resend authorization To', 'to')
|
options.addOption('Resend authorization To', 'to')
|
||||||
options.addOption('Send message', 'message')
|
options.addOption('Send message', 'message')
|
||||||
|
|
|
@ -511,16 +511,96 @@ async def message(self, message):
|
||||||
response = 'Gemini and Gopher are not supported yet.'
|
response = 'Gemini and Gopher are not supported yet.'
|
||||||
XmppMessage.send_reply(self, message, response)
|
XmppMessage.send_reply(self, message, response)
|
||||||
# TODO xHTML, HTMLZ, MHTML
|
# TODO xHTML, HTMLZ, MHTML
|
||||||
case _ if (message_lowercase.startswith('page')):
|
case _ if (message_lowercase.startswith('content') or
|
||||||
message_text = message_text[5:]
|
message_lowercase.startswith('page')):
|
||||||
|
if message_lowercase.startswith('content'):
|
||||||
|
message_text = message_text[8:]
|
||||||
|
readability = True
|
||||||
|
else:
|
||||||
|
message_text = message_text[5:]
|
||||||
|
readability = False
|
||||||
ix_url = message_text.split(' ')[0]
|
ix_url = message_text.split(' ')[0]
|
||||||
await action.download_document(self, message, jid, jid_file,
|
ext = ' '.join(message_text.split(' ')[1:])
|
||||||
message_text, ix_url, False)
|
ext = ext if ext else 'pdf'
|
||||||
case _ if (message_lowercase.startswith('content')):
|
url = None
|
||||||
message_text = message_text[8:]
|
error = None
|
||||||
ix_url = message_text.split(' ')[0]
|
response = None
|
||||||
await action.download_document(self, message, jid, jid_file,
|
if ext in ('epub', 'html', 'markdown', 'md', 'pdf', 'text',
|
||||||
message_text, ix_url, True)
|
'txt'):
|
||||||
|
match ext:
|
||||||
|
case 'markdown':
|
||||||
|
ext = 'md'
|
||||||
|
case 'text':
|
||||||
|
ext = 'txt'
|
||||||
|
status_type = 'dnd'
|
||||||
|
status_message = ('📃️ Procesing request to produce {} '
|
||||||
|
'document...'.format(ext.upper()))
|
||||||
|
XmppPresence.send(self, jid, status_message,
|
||||||
|
status_type=status_type)
|
||||||
|
db_file = config.get_pathname_to_database(jid_file)
|
||||||
|
cache_dir = config.get_default_cache_directory()
|
||||||
|
if not os.path.isdir(cache_dir):
|
||||||
|
os.mkdir(cache_dir)
|
||||||
|
if not os.path.isdir(cache_dir + '/readability'):
|
||||||
|
os.mkdir(cache_dir + '/readability')
|
||||||
|
if ix_url:
|
||||||
|
try:
|
||||||
|
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:
|
||||||
|
url = ix_url
|
||||||
|
if url:
|
||||||
|
url = uri.remove_tracking_parameters(url)
|
||||||
|
url = (uri.replace_hostname(url, 'link')) or url
|
||||||
|
result = await fetch.http(url)
|
||||||
|
if not result['error']:
|
||||||
|
data = result['content']
|
||||||
|
code = result['status_code']
|
||||||
|
title = get_document_title(data)
|
||||||
|
title = title.strip().lower()
|
||||||
|
for i in (' ', '-'):
|
||||||
|
title = title.replace(i, '_')
|
||||||
|
for i in ('?', '"', '\'', '!'):
|
||||||
|
title = title.replace(i, '')
|
||||||
|
filename = os.path.join(
|
||||||
|
cache_dir, 'readability',
|
||||||
|
title + '_' + dt.timestamp() + '.' + ext)
|
||||||
|
error = action.generate_document(data, url,
|
||||||
|
ext, filename,
|
||||||
|
readability)
|
||||||
|
if error:
|
||||||
|
response = ('> {}\n'
|
||||||
|
'Failed to export {}. '
|
||||||
|
'Reason: {}'.format(url,
|
||||||
|
ext.upper(),
|
||||||
|
error))
|
||||||
|
else:
|
||||||
|
url = await XmppUpload.start(self, jid,
|
||||||
|
filename)
|
||||||
|
chat_type = await get_chat_type(self, jid)
|
||||||
|
XmppMessage.send_oob(self, jid, url,
|
||||||
|
chat_type)
|
||||||
|
else:
|
||||||
|
response = ('> {}\n'
|
||||||
|
'Failed to fetch URL. Reason: {}'
|
||||||
|
.format(url, code))
|
||||||
|
await task.start_tasks_xmpp(self, jid, ['status'])
|
||||||
|
else:
|
||||||
|
response = ('No action has been taken.'
|
||||||
|
'\n'
|
||||||
|
'Missing argument. '
|
||||||
|
'Enter URL or entry index number.')
|
||||||
|
else:
|
||||||
|
response = ('Unsupported filetype.\n'
|
||||||
|
'Try: epub, html, md (markdown), '
|
||||||
|
'pdf, or txt (text)')
|
||||||
|
if response:
|
||||||
|
logging.warning('Error for URL {}: {}'.format(url, error))
|
||||||
|
XmppMessage.send_reply(self, message, response)
|
||||||
case _ if (message_lowercase.startswith('http')) and(
|
case _ if (message_lowercase.startswith('http')) and(
|
||||||
message_lowercase.endswith('.opml')):
|
message_lowercase.endswith('.opml')):
|
||||||
url = message_text
|
url = message_text
|
||||||
|
|
Loading…
Reference in a new issue