Improve display of comments of discussion nodes;

Add a list of instances (Thank you roughnecks).
This commit is contained in:
Schimon Jehudah, Adv. 2024-09-05 11:08:26 +03:00
parent b26958acae
commit 028fdacc39
3 changed files with 154 additions and 6 deletions

View file

@ -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)

View file

@ -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 = []

View file

@ -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'>