Rename project to XMPP Journal Publisher;
Retrieve dates of PubSub node items; Improve CSS stylesheet; Fix JS error.
This commit is contained in:
parent
16bd475be2
commit
e07ff6e838
5 changed files with 41 additions and 30 deletions
26
README.md
26
README.md
|
@ -1,12 +1,14 @@
|
||||||
# XMPP PubSub To Atom
|
# XMPP Journal Publisher
|
||||||
|
|
||||||
XMPP PubSub To Atom ("XPTA") is a simple Python script that parses XMPP Pubsub Nodes and sends them as Atom Syndication Format or OPML over HTTP.
|
Previously, XMPP PubSub To Atom ("XPTA").
|
||||||
|
|
||||||
XPTA generates Atom syndication feeds ([RFC 4287](https://www.rfc-editor.org/rfc/rfc4287)) from XMPP PubSub nodes ([XEP-0060](http://xmpp.org/extensions/xep-0060.html)).
|
XMPP Journal Publisher ("XJP") is a software that parses XMPP Pubsub Nodes and sends them as Atom Syndication Format or OPML over HTTP.
|
||||||
|
|
||||||
XPTA includes [XSLT ](https://www.w3.org/TR/xslt/) stylesheets that transforms PubSub nodes into static XHTML journal sites.
|
XJP generates Atom syndication feeds ([RFC 4287](https://www.rfc-editor.org/rfc/rfc4287)) from XMPP PubSub nodes ([XEP-0060](http://xmpp.org/extensions/xep-0060.html)).
|
||||||
|
|
||||||
XPTA was inspired from Tigase and was motivated by Movim.
|
XJP includes [XSLT ](https://www.w3.org/TR/xslt/) stylesheets that transforms PubSub nodes into static XHTML journal sites.
|
||||||
|
|
||||||
|
XJP was inspired from Tigase and was motivated by Movim.
|
||||||
|
|
||||||
## Preview
|
## Preview
|
||||||
|
|
||||||
|
@ -17,14 +19,14 @@ XPTA was inspired from Tigase and was motivated by Movim.
|
||||||
|
|
||||||
## Motivation
|
## Motivation
|
||||||
|
|
||||||
PubSub To Atom is a syndication project which makes journals and publications that are hosted on XMPP PubSub nodes, available
|
XMPP Journal Publisher is a syndication project which makes journals and publications that are hosted on XMPP PubSub nodes, available
|
||||||
from HTTP to both, XML news readers and even HTML browsers.
|
from HTTP to both, XML news readers and even HTML browsers.
|
||||||
|
|
||||||
This means that instead of hosting a journal or publication site in the old fashion (i.e. HTML documents hosted on an HTTP server), one only has to have an HTTP server to operate PubSub To Atom, and the rest of the content is delivered from an XMPP server (i.e. PubSub nodes).
|
This means that instead of hosting a journal or publication site in the old fashion (i.e. HTML documents hosted on an HTTP server), one only has to have an HTTP server to operate XMPP Journal Publisher, and the rest of the content is delivered from an XMPP server (i.e. PubSub nodes).
|
||||||
|
|
||||||
The project also showcases the non-necessity of HTML, as it automatically generates valid XHTML pages by HTML browsers (client-side) from XSLT stylesheets.
|
The project also showcases the non-necessity of HTML, as it automatically generates valid XHTML pages by HTML browsers (client-side) from XSLT stylesheets.
|
||||||
|
|
||||||
Because PubSub To Atom reads XMPP PubSub nodes, it is possible to view a complete set of node items, and even a single node item, which means, that a considered and carefully earnest use of PubSub To Atom would save bandwidth and system overhead, which includes CPU, I/O and RAM usage.
|
Because XMPP Journal Publisher reads XMPP PubSub nodes, it is possible to view a complete set of node items, and even a single node item, which means, that a considered and carefully earnest use of XMPP Journal Publisher would save bandwidth and system overhead, which includes CPU, I/O and RAM usage.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
@ -49,8 +51,8 @@ Because PubSub To Atom reads XMPP PubSub nodes, it is possible to view a complet
|
||||||
Extract the source package to a directory that you have permission to run software.
|
Extract the source package to a directory that you have permission to run software.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ git clone https://git.xmpp-it.net/sch/PubSubToAtom
|
$ git clone https://git.xmpp-it.net/sch/XJP
|
||||||
$ cd PubSubToAtom/
|
$ cd XJP/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configure
|
### Configure
|
||||||
|
@ -59,7 +61,7 @@ Add account credentials to file `configuration.toml`.
|
||||||
|
|
||||||
### Start
|
### Start
|
||||||
|
|
||||||
Execute PubSub To Atom with one of the following commands:
|
Execute XMPP Journal Publisher with one of the following commands:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ python -m uvicorn pubsub_to_atom:app --reload
|
$ python -m uvicorn pubsub_to_atom:app --reload
|
||||||
|
@ -132,7 +134,7 @@ Thank you to to Mr. Timothée Jaussoin ([edhelas](https://edhelas.movim.eu/)) wh
|
||||||
|
|
||||||
A special thank you to the gentlemen "d3x" and "cchianel" from IRC channel #python on irc.libera.chat for initial references concerning code, servers and FastAPI.
|
A special thank you to the gentlemen "d3x" and "cchianel" from IRC channel #python on irc.libera.chat for initial references concerning code, servers and FastAPI.
|
||||||
|
|
||||||
And an important thank you to Mr. Simone Canaletti ([roughnecks](https://blog.woodpeckersnest.space/)) for testing and deploying PubSub To Atom into production.
|
And an important thank you to Mr. Simone Canaletti ([roughnecks](https://blog.woodpeckersnest.space/)) for testing and deploying XMPP Journal Publisher into production.
|
||||||
|
|
||||||
## Similar Projects
|
## Similar Projects
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# An account to connect PubSubToAtom to the XMPP network.
|
# An account to connect XMPP Journal Publisher to the XMPP network.
|
||||||
[account]
|
[account]
|
||||||
xmpp = "" # Jabber ID.
|
xmpp = "" # Jabber ID.
|
||||||
pass = "" # Password.
|
pass = "" # Password.
|
||||||
|
|
|
@ -42,6 +42,7 @@ h1#title, h2#subtitle, #actions, #references {
|
||||||
#note {
|
#note {
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
margin-top: 0.67em;
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -59,7 +60,7 @@ h1#title, h2#subtitle, #actions, #references {
|
||||||
margin-left: 2%;
|
margin-left: 2%;
|
||||||
margin-right: 2%;
|
margin-right: 2%;
|
||||||
min-width: 350px;
|
min-width: 350px;
|
||||||
padding-bottom: 50px;
|
padding-bottom: 0.67em;
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ h1#title, h2#subtitle, #actions, #references {
|
||||||
}
|
}
|
||||||
|
|
||||||
#articles > ul > li > div.entry {
|
#articles > ul > li > div.entry {
|
||||||
padding-bottom: 50px;
|
padding-bottom: 0.67em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#articles > ul > li > div.entry h1 {
|
#articles > ul > li > div.entry h1 {
|
||||||
|
@ -145,7 +146,6 @@ h1#title, h2#subtitle, #actions, #references {
|
||||||
#articles #journal {
|
#articles #journal {
|
||||||
margin-left: unset;
|
margin-left: unset;
|
||||||
margin-right: unset;
|
margin-right: unset;
|
||||||
padding-bottom: 50px;
|
|
||||||
min-width: unset;
|
min-width: unset;
|
||||||
width: unset;
|
width: unset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
#import datetime
|
import datetime
|
||||||
from fastapi import FastAPI, Request, Response
|
from fastapi import FastAPI, Request, Response
|
||||||
from fastapi.responses import FileResponse
|
from fastapi.responses import FileResponse
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
@ -65,8 +65,14 @@ async def view_pubsub(request: Request):
|
||||||
generate_json(iq, node)
|
generate_json(iq, node)
|
||||||
else:
|
else:
|
||||||
operator = get_configuration('settings')['operator']
|
operator = get_configuration('settings')['operator']
|
||||||
json_data = [{'title' : 'Timeout Error: Press here to contact the operator.',
|
json_data = [{'title' : 'Error retrieving items list.',
|
||||||
'link' : 'xmpp:{}?message'.format(operator)}]
|
'link' : ('javascript:alert("XJP: XMPP Journal Publisher has experienced an error '
|
||||||
|
'while attempting to retrieve the list of items for Node {} of PubSub {}.")')
|
||||||
|
.format(node, pubsub)},
|
||||||
|
{'title' : 'Contact the operator.',
|
||||||
|
'link' : ('xmpp:{}?message;subject=XJP: XMPP Journal Publisher;body=Greetings! '
|
||||||
|
'I am contacting you to inform you that there is an error listing '
|
||||||
|
'node items for Node {} on PubSub {}.').format(operator, node, pubsub)}]
|
||||||
filename = 'data/{}.json'.format(node)
|
filename = 'data/{}.json'.format(node)
|
||||||
with open(filename, 'w', encoding='utf-8') as f:
|
with open(filename, 'w', encoding='utf-8') as f:
|
||||||
json.dump(json_data, f, ensure_ascii=False, indent=4)
|
json.dump(json_data, f, ensure_ascii=False, indent=4)
|
||||||
|
@ -172,12 +178,13 @@ def form_a_link(pubsub, node):
|
||||||
def error_message(text):
|
def error_message(text):
|
||||||
"""Error message in RFC 4287: The Atom Syndication Format."""
|
"""Error message in RFC 4287: The Atom Syndication Format."""
|
||||||
feed = feedgenerator.Atom1Feed(
|
feed = feedgenerator.Atom1Feed(
|
||||||
description = ('This is a syndication feed generated with PubSub To '
|
description = ('This is a syndication feed generated with XMPP Journal '
|
||||||
'Atom, which conveys XEP-0060: Publish-Subscribe nodes '
|
'Publisher (XJP), which conveys XEP-0060: Publish-'
|
||||||
'to standard RFC 4287: The Atom Syndication Format.'),
|
'Subscribe nodes to standard RFC 4287: The Atom '
|
||||||
|
'Syndication Format.'),
|
||||||
language = 'en',
|
language = 'en',
|
||||||
link = '',
|
link = '',
|
||||||
subtitle = 'XMPP PubSub To Atom',
|
subtitle = 'XMPP Journal Publisher',
|
||||||
title = 'StreamBurner')
|
title = 'StreamBurner')
|
||||||
namespace = '{http://www.w3.org/2005/Atom}'
|
namespace = '{http://www.w3.org/2005/Atom}'
|
||||||
feed_url = 'gemini://schimon.i2p/'
|
feed_url = 'gemini://schimon.i2p/'
|
||||||
|
@ -194,7 +201,7 @@ def error_message(text):
|
||||||
xml_atom_extended = append_element(
|
xml_atom_extended = append_element(
|
||||||
xml_atom,
|
xml_atom,
|
||||||
'generator',
|
'generator',
|
||||||
'XPTA: XMPP PubSub To Atom')
|
'XMPP Journal Publisher (XJP)')
|
||||||
return xml_atom_extended
|
return xml_atom_extended
|
||||||
|
|
||||||
def generate_rfc_4287(iq, link):
|
def generate_rfc_4287(iq, link):
|
||||||
|
@ -216,7 +223,9 @@ def generate_rfc_4287(iq, link):
|
||||||
title = None if title == None else title.text
|
title = None if title == None else title.text
|
||||||
updated = item.find(namespace + 'updated')
|
updated = item.find(namespace + 'updated')
|
||||||
updated = None if updated == None else updated.text
|
updated = None if updated == None else updated.text
|
||||||
# if updated: updated = datetime.datetime.fromisoformat(updated)
|
published = item.find(namespace + 'published')
|
||||||
|
published = None if published == None else published.text
|
||||||
|
if not updated and not published: updated = datetime.datetime.utcnow().isoformat()
|
||||||
content = item.find(namespace + 'content')
|
content = item.find(namespace + 'content')
|
||||||
content = 'No content' if content == None else content.text
|
content = 'No content' if content == None else content.text
|
||||||
link = item.find(namespace + 'link')
|
link = item.find(namespace + 'link')
|
||||||
|
@ -229,14 +238,14 @@ def generate_rfc_4287(iq, link):
|
||||||
description = content,
|
description = content,
|
||||||
# enclosure = feedgenerator.Enclosure(enclosure, enclosure_size, enclosure_type) if args.entry_enclosure else None,
|
# enclosure = feedgenerator.Enclosure(enclosure, enclosure_size, enclosure_type) if args.entry_enclosure else None,
|
||||||
link = link,
|
link = link,
|
||||||
# pubdate = updated,
|
pubdate = published or updated,
|
||||||
title = title,
|
title = title,
|
||||||
unique_id = link)
|
unique_id = link)
|
||||||
xml_atom = feed.writeString('utf-8')
|
xml_atom = feed.writeString('utf-8')
|
||||||
xml_atom_extended = append_element(
|
xml_atom_extended = append_element(
|
||||||
xml_atom,
|
xml_atom,
|
||||||
'generator',
|
'generator',
|
||||||
'XPTA: XMPP PubSub To Atom')
|
'XMPP Journal Publisher (XJP)')
|
||||||
return xml_atom_extended
|
return xml_atom_extended
|
||||||
|
|
||||||
def generate_json(iq, node):
|
def generate_json(iq, node):
|
||||||
|
|
|
@ -51,11 +51,11 @@ window.onload = async function(){
|
||||||
let elementUl2 = document.createElement('ul');
|
let elementUl2 = document.createElement('ul');
|
||||||
elementDiv.appendChild(elementUl2);
|
elementDiv.appendChild(elementUl2);
|
||||||
links = [
|
links = [
|
||||||
{'text' : 'Subscribe from an XMPP client...',
|
{'text' : 'Subscribe from an XMPP client.',
|
||||||
'href' : `xmpp:${pubsub}?pubsub;action=subscribe;node=${node}`},
|
'href' : `xmpp:${pubsub}?pubsub;action=subscribe;node=${node}`},
|
||||||
{'text' : 'Subscribe with a News Reader...',
|
{'text' : 'Subscribe with a News Reader.',
|
||||||
'href' : `feed://${location.host}/atom?pubsub=${pubsub}&node=${node}`},
|
'href' : `feed://${location.host}/atom?pubsub=${pubsub}&node=${node}`},
|
||||||
{'text' : 'Browse the journal...',
|
{'text' : 'Browse the journal.',
|
||||||
'href' : `atom?pubsub=${pubsub}&node=${node}`}
|
'href' : `atom?pubsub=${pubsub}&node=${node}`}
|
||||||
]
|
]
|
||||||
for (let link of links) {
|
for (let link of links) {
|
||||||
|
|
Loading…
Reference in a new issue