Add a journal list to pages with a single item;
Add an option to enable PubSubToAtom as a service; Add an option to confine queries to a specified hostname.
This commit is contained in:
parent
a4c7ada540
commit
a1e4cf0f71
6 changed files with 295 additions and 41 deletions
|
@ -6,7 +6,9 @@ from fastapi import FastAPI, Request, Response
|
|||
from fastapi.responses import FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
import feedgenerator
|
||||
import json
|
||||
from slixmpp import ClientXMPP
|
||||
from slixmpp.exceptions import IqError, IqTimeout
|
||||
import xml.etree.ElementTree as ET
|
||||
#import importlib.resources
|
||||
|
||||
|
@ -28,6 +30,7 @@ xmpp = None
|
|||
|
||||
# Mount static graphic, script and stylesheet directories
|
||||
app.mount("/css", StaticFiles(directory="css"), name="css")
|
||||
app.mount("/data", StaticFiles(directory="data"), name="data")
|
||||
app.mount("/graphic", StaticFiles(directory="graphic"), name="graphic")
|
||||
app.mount("/script", StaticFiles(directory="script"), name="script")
|
||||
app.mount("/xsl", StaticFiles(directory="xsl"), name="xsl")
|
||||
|
@ -40,40 +43,136 @@ async def favicon():
|
|||
async def view_pubsub(request: Request):
|
||||
global xmpp
|
||||
if not xmpp:
|
||||
with open('configuration.toml', mode="rb") as configuration:
|
||||
credentials = tomllib.load(configuration)['account']
|
||||
credentials = get_configuration('account')
|
||||
xmpp = XmppInstance(credentials['xmpp'], credentials['pass'])
|
||||
# xmpp.connect()
|
||||
|
||||
pubsub = request.query_params.get('pubsub', '')
|
||||
node = request.query_params.get('node', '')
|
||||
item_id = request.query_params.get('item', '')
|
||||
if pubsub and node and item_id:
|
||||
iq = await xmpp.plugin['xep_0060'].get_item(pubsub, node, item_id)
|
||||
link = 'xmpp:{pubsub}?;node={node};item={item}'.format(
|
||||
pubsub=pubsub, node=node, item=item_id)
|
||||
xml_atom = pubsub_to_atom(iq, link)
|
||||
result = append_stylesheet(xml_atom)
|
||||
elif pubsub and node:
|
||||
iq = await xmpp.plugin['xep_0060'].get_items(pubsub, node)
|
||||
link = 'xmpp:{pubsub}?;node={node}'.format(pubsub=pubsub, node=node)
|
||||
xml_atom = pubsub_to_atom(iq, link)
|
||||
result = append_stylesheet(xml_atom)
|
||||
elif pubsub:
|
||||
iq = await xmpp.plugin['xep_0060'].get_nodes(pubsub)
|
||||
link = 'xmpp:{pubsub}'.format(pubsub=pubsub)
|
||||
result = pubsub_to_opml(iq)
|
||||
elif node:
|
||||
result = 'PubSub parameter is missing.'
|
||||
else:
|
||||
result = ('Mandatory parameter PubSub and '
|
||||
'optional parameter Node are missing.')
|
||||
return Response(content=result, media_type="application/xml")
|
||||
settings = get_configuration('settings')
|
||||
result = None
|
||||
if settings['service']:
|
||||
if settings['include'] in pubsub or not settings['include']:
|
||||
if pubsub and node and item_id:
|
||||
iq = await xmpp.plugin['xep_0060'].get_item(pubsub, node, item_id)
|
||||
link = 'xmpp:{pubsub}?;node={node};item={item}'.format(
|
||||
pubsub=pubsub, node=node, item=item_id)
|
||||
xml_atom = generate_rfc_4287(iq, link)
|
||||
result = append_stylesheet(xml_atom)
|
||||
iq = await get_node_items(pubsub, node)
|
||||
if iq:
|
||||
generate_json(iq, node)
|
||||
else:
|
||||
operator = get_configuration('settings')['operator']
|
||||
json_data = [{'title' : 'Timeout Error: Press here to contact the operator.',
|
||||
'link' : 'xmpp:{}?message'.format(operator)}]
|
||||
filename = 'data/{}.json'.format(node)
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
json.dump(json_data, f, ensure_ascii=False, indent=4)
|
||||
# try:
|
||||
# iq = await get_node_items(pubsub, node)
|
||||
# generate_json(iq, node)
|
||||
# except:
|
||||
# operator = get_configuration('settings')['operator']
|
||||
# json_data = [{'title' : 'Timeout retrieving node items from {}'.format(node),
|
||||
# 'link' : 'xmpp:{}?message'.format(operator)}]
|
||||
# filename = 'data/{}.json'.format(node)
|
||||
# with open(filename, 'w', encoding='utf-8') as f:
|
||||
# json.dump(json_data, f, ensure_ascii=False, indent=4)
|
||||
elif pubsub and node:
|
||||
iq = await get_node_items(pubsub, node)
|
||||
link = form_a_link(pubsub, node)
|
||||
xml_atom = generate_rfc_4287(iq, link)
|
||||
result = append_stylesheet(xml_atom)
|
||||
elif pubsub:
|
||||
iq = await xmpp.plugin['xep_0060'].get_nodes(pubsub)
|
||||
link = 'xmpp:{pubsub}'.format(pubsub=pubsub)
|
||||
result = pubsub_to_opml(iq)
|
||||
elif node:
|
||||
text = 'PubSub parameter is missing.'
|
||||
xml_atom = error_message(text)
|
||||
result = append_stylesheet(xml_atom)
|
||||
# else:
|
||||
# result = ('Mandatory parameter PubSub and '
|
||||
# 'optional parameter Node are missing.')
|
||||
else:
|
||||
text = 'The given domain {} is not allowed.'.format(pubsub)
|
||||
xml_atom = error_message(text)
|
||||
result = append_stylesheet(xml_atom)
|
||||
default = get_configuration('default')
|
||||
if not result:
|
||||
if default['pubsub'] and default['nodeid']:
|
||||
if not pubsub and not node:
|
||||
pubsub = default['pubsub']
|
||||
node = default['nodeid']
|
||||
iq = await get_node_items(pubsub, node)
|
||||
link = form_a_link(pubsub, node)
|
||||
xml_atom = generate_rfc_4287(iq, link)
|
||||
result = append_stylesheet(xml_atom)
|
||||
elif not settings['service']:
|
||||
pubsub = default['pubsub']
|
||||
node = default['nodeid']
|
||||
iq = await get_node_items(pubsub, node)
|
||||
link = form_a_link(pubsub, node)
|
||||
xml_atom = generate_rfc_4287(iq, link)
|
||||
result = append_stylesheet(xml_atom)
|
||||
else:
|
||||
text = 'Please contact the administrator and ask him to set default PubSub and Node ID.'
|
||||
xml_atom = error_message(text)
|
||||
result = append_stylesheet(xml_atom)
|
||||
response = Response(content=result, media_type="application/xml")
|
||||
return response
|
||||
|
||||
def pubsub_to_atom(iq, link):
|
||||
def get_configuration(section):
|
||||
with open('configuration.toml', mode="rb") as configuration:
|
||||
result = tomllib.load(configuration)[section]
|
||||
return result
|
||||
|
||||
#@timeout(5)
|
||||
async def get_node_items(pubsub, node):
|
||||
try:
|
||||
iq = await xmpp.plugin['xep_0060'].get_items(pubsub, node, timeout=5)
|
||||
return iq
|
||||
except IqTimeout as e:
|
||||
print(e)
|
||||
|
||||
def form_a_link(pubsub, node):
|
||||
link = 'xmpp:{pubsub}?;node={node}'.format(pubsub=pubsub, node=node)
|
||||
return link
|
||||
|
||||
def error_message(text):
|
||||
"""Error message in RFC 4287: The Atom Syndication Format."""
|
||||
feed = feedgenerator.Atom1Feed(
|
||||
description = ('This is a syndication feed generated with PubSub To '
|
||||
'Atom, which conveys XEP-0060: Publish-Subscribe nodes '
|
||||
'to standard RFC 4287: The Atom Syndication Format.'),
|
||||
language = 'en',
|
||||
link = '',
|
||||
subtitle = 'XMPP PubSub To Atom',
|
||||
title = 'StreamBurner')
|
||||
namespace = '{http://www.w3.org/2005/Atom}'
|
||||
feed_url = 'gemini://schimon.i2p/'
|
||||
# create entry
|
||||
feed.add_item(
|
||||
description = text,
|
||||
# enclosure = feedgenerator.Enclosure(enclosure, enclosure_size, enclosure_type) if args.entry_enclosure else None,
|
||||
link = '',
|
||||
# pubdate = updated,
|
||||
title = 'Error',
|
||||
# unique_id = ''
|
||||
)
|
||||
xml_atom = feed.writeString('utf-8')
|
||||
xml_atom_extended = append_element(
|
||||
xml_atom,
|
||||
'generator',
|
||||
'XPTA: XMPP PubSub To Atom')
|
||||
return xml_atom_extended
|
||||
|
||||
def generate_rfc_4287(iq, link):
|
||||
"""Convert XEP-0060: Publish-Subscribe to RFC 4287: The Atom Syndication Format."""
|
||||
feed = feedgenerator.Atom1Feed(
|
||||
description = ('This is a syndication feed generated with PubSub to '
|
||||
description = ('This is a syndication feed generated with PubSub To '
|
||||
'Atom, which conveys XEP-0060: Publish-Subscribe nodes '
|
||||
'to standard RFC 4287: The Atom Syndication Format.'),
|
||||
language = iq['pubsub']['items']['lang'],
|
||||
|
@ -87,7 +186,6 @@ def pubsub_to_atom(iq, link):
|
|||
namespace = '{http://www.w3.org/2005/Atom}'
|
||||
title = item.find(namespace + 'title')
|
||||
title = None if title == None else title.text
|
||||
feed_url = 'gemini://schimon.i2p/'
|
||||
updated = item.find(namespace + 'updated')
|
||||
updated = None if updated == None else updated.text
|
||||
# if updated: updated = datetime.datetime.fromisoformat(updated)
|
||||
|
@ -113,6 +211,28 @@ def pubsub_to_atom(iq, link):
|
|||
'XPTA: XMPP PubSub To Atom')
|
||||
return xml_atom_extended
|
||||
|
||||
def generate_json(iq, node):
|
||||
"""Create a JSON file from node items."""
|
||||
json_data = []
|
||||
entries = iq['pubsub']['items']
|
||||
for entry in entries:
|
||||
item = entry['payload']
|
||||
namespace = '{http://www.w3.org/2005/Atom}'
|
||||
title = item.find(namespace + 'title')
|
||||
title = None if title == None else title.text
|
||||
# updated = item.find(namespace + 'updated')
|
||||
# updated = None if updated == None else updated.text
|
||||
# if updated: updated = datetime.datetime.fromisoformat(updated)
|
||||
link = item.find(namespace + 'link')
|
||||
link = '' if link == None else link.attrib['href']
|
||||
json_data_entry = {'title' : title,
|
||||
'link' : link}
|
||||
json_data.append(json_data_entry)
|
||||
if len(json_data) > 6: break
|
||||
filename = 'data/{}.json'.format(node)
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
json.dump(json_data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
"""Patch function to append elements which are not provided by feedgenerator"""
|
||||
def append_element(xml_data, element, text):
|
||||
root = ET.fromstring(xml_data)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue