Improve display of comments of discussion nodes;
Add a list of instances (Thank you roughnecks).
This commit is contained in:
parent
b26958acae
commit
028fdacc39
3 changed files with 154 additions and 6 deletions
|
@ -10,6 +10,10 @@ Rivista includes [XSLT ](https://www.w3.org/TR/xslt/) stylesheets that transform
|
||||||
|
|
||||||
Rivista was inspired from Tigase and was motivated by Movim.
|
Rivista was inspired from Tigase and was motivated by Movim.
|
||||||
|
|
||||||
|
## Instances
|
||||||
|
|
||||||
|
* https://rivista.woodpeckersnest.eu/
|
||||||
|
|
||||||
## Preview
|
## Preview
|
||||||
|
|
||||||
[<img alt="berlin-xmpp-meetup" src="screenshot/berlin-xmpp-meetup.png" width="200px"/>](screenshot/berlin-xmpp-meetup.png)
|
[<img alt="berlin-xmpp-meetup" src="screenshot/berlin-xmpp-meetup.png" width="200px"/>](screenshot/berlin-xmpp-meetup.png)
|
||||||
|
|
|
@ -108,7 +108,7 @@ async def view_node_items(request: Request):
|
||||||
iq = await get_node_item(pubsub, node, item_id)
|
iq = await get_node_item(pubsub, node, item_id)
|
||||||
if iq:
|
if iq:
|
||||||
link = form_an_item_link(pubsub, node, item_id)
|
link = form_an_item_link(pubsub, node, item_id)
|
||||||
xml_atom = generate_atom(iq, link)
|
xml_atom = generate_atom_comment(iq, link) if 'urn:xmpp:microblog:0:comments/' in node else generate_atom_post(iq, link)
|
||||||
iq = await get_node_items(pubsub, node)
|
iq = await get_node_items(pubsub, node)
|
||||||
if not '/' in node:
|
if not '/' in node:
|
||||||
if iq:
|
if iq:
|
||||||
|
@ -146,7 +146,7 @@ async def view_node_items(request: Request):
|
||||||
iq = await get_node_items(pubsub, node)
|
iq = await get_node_items(pubsub, node)
|
||||||
if iq:
|
if iq:
|
||||||
link = form_a_node_link(pubsub, node)
|
link = form_a_node_link(pubsub, node)
|
||||||
xml_atom = generate_atom(iq, link)
|
xml_atom = generate_atom_comment(iq, link) if 'urn:xmpp:microblog:0:comments/' in node else generate_atom_post(iq, link)
|
||||||
else:
|
else:
|
||||||
text = 'Please ensure that PubSub node "{}" is valid and accessible.'.format(node)
|
text = 'Please ensure that PubSub node "{}" is valid and accessible.'.format(node)
|
||||||
xml_atom = error_message(text)
|
xml_atom = error_message(text)
|
||||||
|
@ -177,7 +177,7 @@ async def view_node_items(request: Request):
|
||||||
iq = await get_node_items(pubsub, node)
|
iq = await get_node_items(pubsub, node)
|
||||||
if iq:
|
if iq:
|
||||||
link = form_a_node_link(pubsub, node)
|
link = form_a_node_link(pubsub, node)
|
||||||
xml_atom = generate_atom(iq, link)
|
xml_atom = generate_atom_post(iq, link)
|
||||||
else:
|
else:
|
||||||
text = 'Please ensure that PubSub node "{}" is valid and accessible.'.format(node)
|
text = 'Please ensure that PubSub node "{}" is valid and accessible.'.format(node)
|
||||||
xml_atom = error_message(text)
|
xml_atom = error_message(text)
|
||||||
|
@ -187,7 +187,7 @@ async def view_node_items(request: Request):
|
||||||
iq = await get_node_items(pubsub, node)
|
iq = await get_node_items(pubsub, node)
|
||||||
if iq:
|
if iq:
|
||||||
link = form_a_node_link(pubsub, node)
|
link = form_a_node_link(pubsub, node)
|
||||||
xml_atom = generate_atom(iq, link)
|
xml_atom = generate_atom_post(iq, link)
|
||||||
else:
|
else:
|
||||||
text = 'Please ensure that PubSub node "{}" is valid and accessible.'.format(node)
|
text = 'Please ensure that PubSub node "{}" is valid and accessible.'.format(node)
|
||||||
xml_atom = error_message(text)
|
xml_atom = error_message(text)
|
||||||
|
@ -263,7 +263,7 @@ def error_message(text):
|
||||||
return ET.tostring(feed, encoding='unicode')
|
return ET.tostring(feed, encoding='unicode')
|
||||||
|
|
||||||
# generate_rfc_4287
|
# generate_rfc_4287
|
||||||
def generate_atom(iq, link):
|
def generate_atom_post(iq, link):
|
||||||
"""Generate an Atom Syndication Format (RFC 4287) from a Publish-Subscribe (XEP-0060) node items."""
|
"""Generate an Atom Syndication Format (RFC 4287) from a Publish-Subscribe (XEP-0060) node items."""
|
||||||
pubsub = iq['from'].bare
|
pubsub = iq['from'].bare
|
||||||
node = iq['pubsub']['items']['node']
|
node = iq['pubsub']['items']['node']
|
||||||
|
@ -295,8 +295,8 @@ def generate_atom(iq, link):
|
||||||
links = item_payload.find(namespace + 'link')
|
links = item_payload.find(namespace + 'link')
|
||||||
if (not isinstance(title, ET.Element) and
|
if (not isinstance(title, ET.Element) and
|
||||||
not isinstance(links, ET.Element)): continue
|
not isinstance(links, ET.Element)): continue
|
||||||
title_text = None if title == None else title.text
|
|
||||||
e_entry = ET.SubElement(e_feed, 'entry')
|
e_entry = ET.SubElement(e_feed, 'entry')
|
||||||
|
title_text = None if title == None else title.text
|
||||||
ET.SubElement(e_entry, 'title').text = title_text
|
ET.SubElement(e_entry, 'title').text = title_text
|
||||||
if isinstance(links, ET.Element):
|
if isinstance(links, ET.Element):
|
||||||
for link in item_payload.findall(namespace + 'link'):
|
for link in item_payload.findall(namespace + 'link'):
|
||||||
|
@ -372,6 +372,139 @@ def generate_atom(iq, link):
|
||||||
# ET.SubElement(e_entry, 'summary', {'type': summary_type_text}).text = summary_text
|
# ET.SubElement(e_entry, 'summary', {'type': summary_type_text}).text = summary_text
|
||||||
return ET.tostring(e_feed, encoding='unicode')
|
return ET.tostring(e_feed, encoding='unicode')
|
||||||
|
|
||||||
|
# generate_rfc_4287
|
||||||
|
def generate_atom_comment(iq, link):
|
||||||
|
"""Generate an Atom Syndication Format (RFC 4287) from a Publish-Subscribe (XEP-0060) node items."""
|
||||||
|
pubsub = iq['from'].bare
|
||||||
|
node = iq['pubsub']['items']['node']
|
||||||
|
title = node
|
||||||
|
link = link
|
||||||
|
# link = form_a_node_link(pubsub, node)
|
||||||
|
# subtitle = 'XMPP PubSub Syndication Feed'
|
||||||
|
subtitle = pubsub
|
||||||
|
description = ('This is a syndication feed generated with Rivista, an XMPP '
|
||||||
|
'Journal Publisher, which conveys XEP-0060: Publish-'
|
||||||
|
'Subscribe nodes to standard RFC 4287: The Atom Syndication '
|
||||||
|
'Format.')
|
||||||
|
language = iq['pubsub']['items']['lang']
|
||||||
|
items = iq['pubsub']['items']
|
||||||
|
e_feed = ET.Element("feed")
|
||||||
|
e_feed.set('xmlns', 'http://www.w3.org/2005/Atom')
|
||||||
|
ET.SubElement(e_feed, 'title', {'type': 'text'}).text = title
|
||||||
|
ET.SubElement(e_feed, 'subtitle', {'type': 'text'}).text = subtitle
|
||||||
|
ET.SubElement(e_feed, 'link', {'rel': 'self', 'href': link})
|
||||||
|
ET.SubElement(e_feed, 'generator', {
|
||||||
|
'uri': 'https://git.xmpp-it.net/sch/Rivista',
|
||||||
|
'version': '0.1'}).text = 'Rivista XJP'
|
||||||
|
ET.SubElement(e_feed, 'updated').text = datetime.datetime.now(datetime.UTC).isoformat()
|
||||||
|
for item in list(items)[::-1]:
|
||||||
|
item_id = item['id']
|
||||||
|
item_payload = item['payload']
|
||||||
|
namespace = '{http://www.w3.org/2005/Atom}'
|
||||||
|
authors = item_payload.find(namespace + 'author')
|
||||||
|
links = item_payload.find(namespace + 'link')
|
||||||
|
if (not isinstance(authors, ET.Element) and
|
||||||
|
not isinstance(links, ET.Element)): continue
|
||||||
|
e_entry = ET.SubElement(e_feed, 'entry')
|
||||||
|
author_text = None
|
||||||
|
for author in item_payload.findall(namespace + 'author'):
|
||||||
|
author_email = author.find(namespace + 'email')
|
||||||
|
if author_email is not None:
|
||||||
|
author_text = author_email.text
|
||||||
|
if not author_text:
|
||||||
|
author_uri = author.find(namespace + 'uri')
|
||||||
|
if author_uri is not None:
|
||||||
|
author_text = author_uri.text
|
||||||
|
if not author_text:
|
||||||
|
author_name = author.find(namespace + 'name')
|
||||||
|
if author_name is not None and author_name.text:
|
||||||
|
author_text = author_name.text
|
||||||
|
if not author_text:
|
||||||
|
for uri in item_payload.iter(namespace + 'author'):
|
||||||
|
author_text = uri.text
|
||||||
|
if author_text:
|
||||||
|
ET.SubElement(e_entry, 'title').text = author_text
|
||||||
|
break
|
||||||
|
if isinstance(links, ET.Element):
|
||||||
|
for link in item_payload.findall(namespace + 'link'):
|
||||||
|
link_href = link.attrib['href'] if 'href' in link.attrib else ''
|
||||||
|
link_type = link.attrib['type'] if 'type' in link.attrib else ''
|
||||||
|
link_rel = link.attrib['rel'] if 'rel' in link.attrib else ''
|
||||||
|
ET.SubElement(e_entry, 'link', {'href': link_href, 'rel': link_rel, 'type': link_type})
|
||||||
|
else:
|
||||||
|
ET.SubElement(e_entry, 'content', {'href': ''})
|
||||||
|
link_xmpp = form_an_item_link(pubsub, node, item_id)
|
||||||
|
ET.SubElement(e_entry, 'link', {'href': link_xmpp, 'rel': 'alternate', 'type': 'x-scheme-handler/xmpp'})
|
||||||
|
contents = item_payload.find(namespace + 'content')
|
||||||
|
if isinstance(contents, ET.Element):
|
||||||
|
for content in item_payload.findall(namespace + 'content'):
|
||||||
|
if not content.text: continue
|
||||||
|
content_text = content.text
|
||||||
|
content_type = content.attrib['type'] if 'type' in content.attrib else 'html'
|
||||||
|
content_type_text = 'html' if 'html' in content_type else 'text'
|
||||||
|
ET.SubElement(e_entry, 'content', {'type': content_type_text}).text = content_text
|
||||||
|
else:
|
||||||
|
summary = item_payload.find(namespace + 'summary')
|
||||||
|
summary_text = summary.text if summary else None
|
||||||
|
if summary_text:
|
||||||
|
summary_type = summary.attrib['type'] if 'type' in summary.attrib else 'html'
|
||||||
|
summary_type_text = 'html' if 'html' in summary_type else 'text'
|
||||||
|
ET.SubElement(e_entry, 'content', {'type': summary_type_text}).text = summary_text
|
||||||
|
else:
|
||||||
|
title = item_payload.find(namespace + 'title')
|
||||||
|
title_text = None if title == None else title.text
|
||||||
|
if title_text:
|
||||||
|
ET.SubElement(e_entry, 'content').text = title_text
|
||||||
|
else:
|
||||||
|
ET.SubElement(e_entry, 'content').text = 'No content.'
|
||||||
|
published = item_payload.find(namespace + 'published')
|
||||||
|
published_text = None if published == None else published.text
|
||||||
|
ET.SubElement(e_entry, 'published').text = published_text
|
||||||
|
updated = item_payload.find(namespace + 'updated')
|
||||||
|
updated_text = None if updated == None else updated.text
|
||||||
|
ET.SubElement(e_entry, 'updated').text = updated_text
|
||||||
|
authors = item_payload.find(namespace + 'author')
|
||||||
|
if isinstance(authors, ET.Element):
|
||||||
|
contact_text = None
|
||||||
|
for author in item_payload.findall(namespace + 'author'):
|
||||||
|
author_email = author.find(namespace + 'email')
|
||||||
|
if author_email is not None:
|
||||||
|
contact_text = author_email.text
|
||||||
|
if not contact_text:
|
||||||
|
author_uri = author.find(namespace + 'uri')
|
||||||
|
if author_uri is not None:
|
||||||
|
contact_text = author_uri.text
|
||||||
|
if not contact_text:
|
||||||
|
for uri in item_payload.iter(namespace + 'author'):
|
||||||
|
contact_text = uri.text
|
||||||
|
if contact_text:
|
||||||
|
if contact_text.startswith('xmpp:'):
|
||||||
|
contact_type = 'x-scheme-handler/xmpp'
|
||||||
|
elif contact_text.startswith('mailto:'):
|
||||||
|
contact_type = 'x-scheme-handler/mailto'
|
||||||
|
else:
|
||||||
|
contact_type = None
|
||||||
|
if contact_type:
|
||||||
|
ET.SubElement(e_entry, 'link', {'href': contact_text, 'rel': 'contact', 'type': contact_type})
|
||||||
|
else:
|
||||||
|
ET.SubElement(e_entry, 'link', {'href': contact_text, 'rel': 'contact'})
|
||||||
|
break
|
||||||
|
categories = item_payload.find(namespace + 'category')
|
||||||
|
if isinstance(categories, ET.Element):
|
||||||
|
for category in item_payload.findall(namespace + 'category'):
|
||||||
|
if 'term' in category.attrib and category.attrib['term']:
|
||||||
|
category_term = category.attrib['term']
|
||||||
|
ET.SubElement(e_entry, 'category', {'term': category_term})
|
||||||
|
|
||||||
|
|
||||||
|
identifier = item_payload.find(namespace + 'id')
|
||||||
|
if identifier and identifier.attrib: print(identifier.attrib)
|
||||||
|
|
||||||
|
identifier_text = None if identifier == None else identifier.text
|
||||||
|
ET.SubElement(e_entry, 'id').text = identifier_text
|
||||||
|
# ET.SubElement(e_entry, 'summary', {'type': summary_type_text}).text = summary_text
|
||||||
|
return ET.tostring(e_feed, encoding='unicode')
|
||||||
|
|
||||||
def generate_json(iq):
|
def generate_json(iq):
|
||||||
"""Create a JSON file from node items."""
|
"""Create a JSON file from node items."""
|
||||||
json_data = []
|
json_data = []
|
||||||
|
|
|
@ -299,6 +299,17 @@ xmlns:atom='http://www.w3.org/2005/Atom'>
|
||||||
(XMPP)
|
(XMPP)
|
||||||
</xsl:element>
|
</xsl:element>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
|
<xsl:if test='atom:link[@rel="contact"]'>
|
||||||
|
<xsl:element name='a'>
|
||||||
|
<xsl:attribute name='href'>
|
||||||
|
<xsl:value-of select='atom:link[@rel="contact"]/@href'/>
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:attribute name='class'>
|
||||||
|
<xsl:text>contact-uri</xsl:text>
|
||||||
|
</xsl:attribute>
|
||||||
|
🪪️ Contact
|
||||||
|
</xsl:element>
|
||||||
|
</xsl:if>
|
||||||
<xsl:if test='atom:link[@rel="replies"]'>
|
<xsl:if test='atom:link[@rel="replies"]'>
|
||||||
<xsl:element name='a'>
|
<xsl:element name='a'>
|
||||||
<xsl:attribute name='href'>
|
<xsl:attribute name='href'>
|
||||||
|
|
Loading…
Reference in a new issue