Python : Improve handling of PubSub nodes, modularize code, and restore XMPP error message;

SVG    : Add icons of a plant and ReactOS;
TOML   : Modify references of DivestOS and ReactOS;
XHTML  : Modify F-Droid and DivestOS notices, and add a notice about ReactOS.
This commit is contained in:
Schimon Jehudah, Adv. 2024-10-22 16:34:39 +03:00
parent 644842ab6d
commit 7dda347ebc
5 changed files with 1958 additions and 268 deletions

View file

@ -6,7 +6,7 @@
##
#An encrypted instant messaging with video call and GPS features for Divest OS.
#"""
#divestos = "https://f-droid.org/packages/org.atalk.android/"
#android = "https://f-droid.org/packages/org.atalk.android/"
#features = ["chat", "fdroid", "graphical", "mobile", "omemo", "otr", "zrtp"]
[aparte]
@ -40,7 +40,7 @@ about = """
blabber.im is a fork of Conversations. The changes aim to improve usability \
and ease transition from pre-installed and other widespread messengers.
"""
divestos = "https://blabber.im"
android = "https://blabber.im"
features = ["adhoc", "chat", "graphical", "mobile", "omemo", "openpgp"]
#[bruno]
@ -52,7 +52,7 @@ features = ["adhoc", "chat", "graphical", "mobile", "omemo", "openpgp"]
#
#You can use Bruno if the other IM apps are just not stylish enough.
#"""
#divestos = "https://yaxim.org/download/"
#android = "https://yaxim.org/download/"
#features = ["chat", "graphical", "mobile"]
#[candy]
@ -104,7 +104,7 @@ The Cheogram Android app allows you to join a worldwide communication network.
It especially focuses on features useful to people who want to contact those \
on other networks as well, such as SMS-enabled phone numbers.
"""
divestos = "https://f-droid.org/packages/com.cheogram.android"
android = "https://f-droid.org/packages/com.cheogram.android"
features = ["adhoc", "chat", "fdroid", "graphical", "mobile", "omemo", "openpgp"]
[conversations]
@ -117,7 +117,7 @@ mobile device.
It is easy to use, reliable, battery friendly. With built-in support for \
images, group chats and e2e encryption.
"""
divestos = "https://f-droid.org/packages/eu.siacs.conversations"
android = "https://f-droid.org/packages/eu.siacs.conversations"
features = ["chat", "fdroid", "graphical", "mobile", "omemo", "openpgp", "pwa"]
[conversations-classic]
@ -129,7 +129,7 @@ The very last word in instant messaging.
Conversations is a Jabber/XMPP client for Android 5.0+ smartphones that has \
been optimized to provide a unique mobile experience.
"""
divestos = "https://f-droid.org/packages/eu.siacs.conversations.classic"
android = "https://f-droid.org/packages/eu.siacs.conversations.classic"
features = ["chat", "fdroid", "graphical", "mobile", "omemo", "openpgp"]
[conversejs]
@ -142,7 +142,7 @@ and desktops.
browser = "https://conversejs.org"
apple = "https://github.com/conversejs/converse-desktop/releases"
linux = "https://github.com/conversejs/converse-desktop/releases"
reactos = "https://github.com/conversejs/converse-desktop/releases"
windows = "https://github.com/conversejs/converse-desktop/releases"
features = ["adhoc", "chat", "desktop", "graphical", "omemo"]
#[coyim]
@ -167,7 +167,7 @@ features = ["adhoc", "chat", "desktop", "graphical", "omemo"]
#"""
#apple = "https://coy.im/#download-section"
#linux = "https://coy.im/#download-section"
#reactos = "https://coy.im/#download-section"
#windows = "https://coy.im/#download-section"
#features = ["chat", "desktop", "graphical", "otr"]
[dino]
@ -202,7 +202,7 @@ on your mobile device.
"""
apple = "https://gajim.org/download/#macos"
linux = "https://gajim.org/download/#linux"
reactos = "https://gajim.org/download/#windows"
windows = "https://gajim.org/download/#windows"
features = ["adhoc", "admin", "chat", "desktop", "graphical", "omemo", "openpgp"]
[irssi]
@ -225,9 +225,9 @@ jabber.el is an XMPP client for Emacs. XMPP (also known as 'Jabber') is an \
IETF-standard federated instant messaging protocol.
"""
apple = "https://codeberg.org/emacs-jabber/emacs-jabber#how-to-install"
divestos = "https://codeberg.org/emacs-jabber/emacs-jabber#how-to-install"
android = "https://codeberg.org/emacs-jabber/emacs-jabber#how-to-install"
posix = "https://codeberg.org/emacs-jabber/emacs-jabber#how-to-install"
reactos = "https://codeberg.org/emacs-jabber/emacs-jabber#how-to-install"
windows = "https://codeberg.org/emacs-jabber/emacs-jabber#how-to-install"
features = ["admin", "chat", "console", "desktop"]
[jsxc]
@ -253,7 +253,7 @@ It uses the open communication protocol XMPP (Jabber).
Unlike other chat apps, you are not dependent on one specific service \
provider, and your privacy is gauranteed more than ever before.
"""
divestos = "https://kaidan.im/download/#android-experimental"
android = "https://kaidan.im/download/#android-experimental"
linux = "https://kaidan.im/download/#linux"
features = ["chat", "desktop", "graphical", "mobile", "omemo"]
@ -281,7 +281,7 @@ client Miranda IM.
It is very light on system resources and extremely fast.
"""
reactos = "https://miranda-ng.org/downloads/"
windows = "https://miranda-ng.org/downloads/"
features = ["adhoc", "chat", "desktop", "graphical", "omemo", "openpgp", "otr"]
[monal]
@ -306,7 +306,7 @@ monocles chat is a modern and secure Android XMPP chat client.
It is based on blabber.im and Conversations, yet has a lot of changes and \
offers additional features to improve usability and security.
"""
divestos = "https://f-droid.org/packages/de.monocles.chat"
android = "https://f-droid.org/packages/de.monocles.chat"
features = ["adhoc", "chat", "fdroid", "graphical", "mobile", "omemo", "openpgp", "otr"]
[movim]
@ -327,7 +327,7 @@ desktop computer.
"""
apple = "https://join.movim.eu"
browser = "https://join.movim.eu"
divestos = "https://join.movim.eu"
android = "https://join.movim.eu"
features = ["adhoc", "chat", "desktop", "graphical", "mobile", "omemo", "pubsub", "pwa"]
[moxxy]
@ -339,7 +339,7 @@ Moxxy is an experimental XMPP client that aims to be modern and easy to use.
It is currently alpha software. This means that there will be issues with some \
functionalities. Please do not use Moxxy for anything important at this moment.
"""
divestos = "https://apt.izzysoft.de/fdroid/index/apk/org.moxxy.moxxyv2"
android = "https://apt.izzysoft.de/fdroid/index/apk/org.moxxy.moxxyv2"
features = ["chat", "graphical", "izzyondroid", "mobile", "omemo"]
#[pade]
@ -408,7 +408,7 @@ supported operating system.
"""
apple = "https://psi-im.org"
linux = "https://psi-im.org"
reactos = "https://psi-im.org"
windows = "https://psi-im.org"
features = ["adhoc", "admin", "chat", "desktop", "graphical", "omemo", "openpgp", "otr"]
[psi-plus]
@ -424,7 +424,7 @@ plugins for transferring them to upstream.
apple = "https://psi-plus.com/wiki/en:downloads#macos"
haiku = "https://depot.haiku-os.org/psi_plus"
linux = "https://psi-plus.com/wiki/en:downloads#linux"
reactos = "https://psi-plus.com/wiki/en:downloads#ms_windows"
windows = "https://psi-plus.com/wiki/en:downloads#ms_windows"
features = ["adhoc", "admin", "chat", "desktop", "graphical", "haikudepot", "omemo", "openpgp", "otr"]
[reeder]
@ -476,7 +476,7 @@ features = ["chat", "desktop", "graphical", "haikudepot"]
#"""
#apple = "https://igniterealtime.org/projects/spark/"
#linux = "https://igniterealtime.org/projects/spark/"
#reactos = "https://igniterealtime.org/projects/spark/"
#windows = "https://igniterealtime.org/projects/spark/"
#features = ["chat", "desktop", "graphical", "omemo"]
#[speeqe]
@ -508,7 +508,7 @@ Stork IM by Tigase, Inc. is a lightweight and powerful XMPP client for Android.
It provides an easy way to talk and share moments with your friends.
"""
divestos = "https://stork.im/#about"
android = "https://stork.im/#about"
features = ["chat", "graphical", "mobile", "omemo"]
[swift]
@ -525,7 +525,7 @@ from Isode.
"""
apple = "https://swift.im/downloads.html"
linux = "https://swift.im/downloads.html"
reactos = "https://swift.im/downloads.html"
windows = "https://swift.im/downloads.html"
features = ["chat", "desktop", "graphical"]
[uwpx]
@ -543,7 +543,7 @@ chat markers and experimental OMEMO support.
For a complete list of features, please refer to the project: \
https://github.com/UWPX/UWPX-Client?tab=readme-ov-file#features
"""
reactos = "https://uwpx.org"
windows = "https://uwpx.org"
features = ["chat", "desktop", "graphical", "mobile", "omemo"]
[weechat]
@ -555,7 +555,7 @@ XMPP for power users and digital masochists.
weechat-xmpp is a WeeChat plugin that extends WeeChat to support XMPP, and it \
currently has a minimal but ideally maximal set of XEPs.
"""
divestos = "https://github.com/bqv/weechat-xmpp"
android = "https://github.com/bqv/weechat-xmpp"
haiku = "https://depot.haiku-os.org/weechat"
posix = "https://github.com/bqv/weechat-xmpp"
features = ["chat", "console", "desktop", "omemo", "openpgp"]
@ -572,7 +572,7 @@ to provide people with a simple, fast and secure messaging, based on \
interoperable open standards.
"""
browser = "https://xabber.com"
divestos = "https://xabber.com"
android = "https://xabber.com"
features = ["chat", "desktop", "graphical", "omemo", "mobile"]
#[xmpp-web]
@ -594,5 +594,5 @@ Android.
It aims at usability, low overhead and security, and works on low-end Android \
devices starting with Android 4.0.
"""
divestos = "https://yaxim.org/download/"
android = "https://yaxim.org/download/"
features = ["chat", "graphical", "mobile"]

413
fasi.py
View file

@ -118,9 +118,7 @@ class HttpInstance:
jid_details = await FileUtilities.cache_jid_data(
jabber_id, password, jid_bare, node_name, alias=alias)
action = jid_details['action']
count = jid_details['count']
instance = jid_details['instance']
items = jid_details['items']
jid_info = {
'error' : jid_details['error'],
@ -131,14 +129,11 @@ class HttpInstance:
'name' : jid_details['name'],
'note' : jid_details['note'],
'type' : jid_details['image_type']}
link_href = jid_details['link_href']
messages = jid_details['messages']
nodes = jid_details['nodes']
note = jid_details['note']
subject = jid_details['subject']
title = jid_details['name']
xmpp_uri = jid_details['uri']
view_href = jid_details['view_href']
# Group chat messages
# NOTE TODO
@ -157,9 +152,21 @@ class HttpInstance:
number_of_pages = int(len(messages) / 10)
if number_of_pages < len(messages) / 10: number_of_pages += 1
if jid_kind:
# Action and instance type
action, instance = XmppUtilities.set_action_instance_type(jid_kind, node_name)
else: # jid_info['error']
action = 'Contact'
instance = view_href = ''
message = '{}: {} (XEP-0030)'.format(jid_info['text'], jid_info['condition'])
xmpp_uri = jid_bare
# Query URI links
action, instance, link_href, links, view_href, xmpp_uri = XmppUtilities.set_query_uri_link(
jid_bare, jid_info, jid_kind, node_name)
print('Query URI links')
links = XmppUtilities.get_query_uri_links(jid_bare, jid_kind, node_name)
link_href = XmppUtilities.get_link_href(jid_bare, jid_kind, node_name)
view_href = XmppUtilities.get_view_href(jid_bare, jid_kind, node_name)
xmpp_uri = XmppUtilities.get_xmpp_uri(jid_bare, jid_kind, node_name)
# Graphic files
filename, filepath, filetype, selection = FileUtilities.handle_photo(jid_bare, jid_vcard, link_href)
@ -221,7 +228,7 @@ class HttpInstance:
if True:
entries = []
exception = jid_vcard = note = node_note = number_of_pages = \
page_number = previous = selection = services_sorted = None
page_number = previous = selection = None
filename = 'details/{}.toml'.format(jid_bare)
if os.path.exists(filename) and os.path.getsize(filename) > 0:
@ -230,10 +237,32 @@ class HttpInstance:
jid_details = await FileUtilities.cache_jid_data(
jabber_id, password, jid_bare, node_name, item_id)
action = jid_details['action']
count = jid_details['count']
instance = jid_details['instance']
xmpp_instance = XmppInstance(jabber_id, password, jid_bare)
xmpp_instance.connect()
# Node item IDs
nodes = jid_details['nodes']
items = jid_details['items']
if node_name not in nodes:
nodes[node_name] = {}
node_item_ids = await XmppXep0060.get_node_item_ids(
xmpp_instance, jid_bare, node_name)
#node_item_ids = await XmppUtilities.get_item_ids_of_node(
# jabber_id, password, jid_bare, node_name, nodes)
if isinstance(node_item_ids['iq'], stanza.iq.Iq):
iq = node_item_ids['iq']
iq_disco_items_items = iq['disco_items']['items']
for item in items:
if item[1] == node_name:
nodes[node_name]['title'] = item[2]
break
nodes[node_name]['count'] = len(iq_disco_items_items)
nodes[node_name]['item_ids'] = []
for item in iq_disco_items_items:
nodes[node_name]['item_ids'].append(
[item[0] or '', item[1] or '', item[2] or ''])
count = jid_details['count']
jid_info = {
'error' : jid_details['error'],
'text' : jid_details['error_text'],
@ -243,40 +272,17 @@ class HttpInstance:
'name' : jid_details['name'],
'note' : jid_details['note'],
'type' : jid_details['image_type']}
link_href = jid_details['link_href']
messages = jid_details['messages']
node_title = jid_details['name']
nodes = jid_details['nodes']
node_title = nodes[node_name]['title']
note = jid_details['note']
#title = nodes[node_name]['title'] if node_name else jid_details['name']
title = nodes[node_name]['title']
xmpp_uri = jid_details['uri']
view_href = jid_details['view_href']
title = jid_details['name']
#link_href = 'xmpp:{}?pubsub;node={};action=subscribe'.format(
# jid_bare, node_name)
#link_text = 'Subscribe'
#xmpp_uri = '{}?;node={}'.format(jid_bare, node_name)
xmpp_instance = XmppInstance(jabber_id, password, jid_bare)
xmpp_instance.connect()
# Node item IDs
if node_name not in nodes:
nodes[node_name] = {}
node_item_ids = await XmppXep0060.get_node_item_ids(
xmpp_instance, jid_bare, node_name)
#node_item_ids = await XmppUtilities.get_item_ids_of_node(
# jabber_id, password, jid_bare, node_name, nodes)
if isinstance(node_item_ids['iq'], stanza.iq.Iq):
iq_disco_items_items = node_item_ids['iq']['disco_items']['items']
#nodes[node_name]['title'] =
nodes[node_name]['count'] = len(iq_disco_items_items)
nodes[node_name]['item_ids'] = []
for item in iq_disco_items_items:
nodes[node_name]['item_ids'].append(
[item[0] or '', item[1] or '', item[2] or ''])
# Node items
if item_id:
previous = True
@ -304,40 +310,42 @@ class HttpInstance:
if number_of_pages < len(item_ids) / 10: number_of_pages += 1
node_items = await XmppXep0060.get_node_items(
xmpp_instance, jid_bare, node_name, item_ids=item_ids_10)
if not node_items:
action = 'Warning'
node_title = jid_info['condition']
node_note = jid_info['text']
services = services_sorted = None
elif isinstance(node_items, IqTimeout):
action = 'Warning'
node_title = 'Timeout'
node_note = 'Timeout error'
services = services_sorted = None
elif isinstance(node_items, IqError):
action = 'Warning'
breakpoint()
node_title = node_items['condition']
node_note = node_items['text']
services = services_sorted = None
else:
if isinstance(node_items['iq'], stanza.iq.Iq):
#title = title or node_name
if not node_title: node_title = node_name
#node_note = nodes[node_name]['title'] if node_name else jid_details['name']
node_note = xmpp_uri # jid_bare
for item in node_items['pubsub']['items']:
#node_note = xmpp_uri # jid_bare
iq = node_items['iq']
for item in iq['pubsub']['items']:
item_payload = item['payload']
entry = Syndication.extract_items(item_payload)
if entry: entry['id'] = item['id']
entries.append(entry)
#if len(entries) > 10: break
else:
message = '{}: {} (XEP-0060)'.format(node_items['condition'], node_items['text'])
if entries: entries.reverse()
xmpp_instance.disconnect()
if jid_kind:
# Action and instance type
action, instance = XmppUtilities.set_action_instance_type(jid_kind, node_name)
else: # jid_info['error']
action = 'Contact'
instance = view_href = ''
message = '{}: {} (XEP-0030)'.format(jid_info['text'], jid_info['condition'])
xmpp_uri = jid_bare
# Query URI links
action, instance, link_href, links, view_href, xmpp_uri = XmppUtilities.set_query_uri_link(
jid_bare, jid_info, jid_kind, node_name, item_id)
print('Query URI links')
links = XmppUtilities.get_query_uri_links(jid_bare, jid_kind, node_name, item_id)
link_href = XmppUtilities.get_link_href(jid_bare, jid_kind, node_name)
view_href = XmppUtilities.get_view_href(jid_bare, jid_kind, node_name)
xmpp_uri = XmppUtilities.get_xmpp_uri(jid_bare, jid_kind, node_name)
node_note = xmpp_uri
# Graphic files
filename, filepath, filetype, selection = FileUtilities.handle_photo(jid_bare, jid_vcard, link_href)
@ -350,7 +358,7 @@ class HttpInstance:
xmpp_uri = note = jid
filename = jid_bare = link_href = link_tex = node_note = \
node_title = number_of_pages = page_number = previous = \
selection = services = services_sorted = url = None
selection = url = None
#if title == 'remote-server-timeout':
# raise HTTPException(status_code=408, detail='remote-server-timeout')
@ -457,9 +465,7 @@ class HttpInstance:
services_sorted = {k: v for k, v in services.items() if k != 'unavailable'}
if 'unavailable' in services: services_sorted['unavailable'] = services['unavailable']
else:
action = 'Warning'
title = jid_info['condition']
note = jid_info['text']
message = '{}: {} (XEP-0030)'.format(jid_info['condition'], jid_info['text'])
services = services_sorted = None
xmpp_instance.disconnect()
@ -550,8 +556,6 @@ class HttpInstance:
else:
count = nodes[node_name]['count'] if node_name in nodes else jid_details['count']
action = jid_details['action']
instance = jid_details['instance']
items = jid_details['items']
jid_info = {
'error' : jid_details['error'],
@ -561,20 +565,52 @@ class HttpInstance:
'name' : jid_details['name'],
'note' : jid_details['note'],
'type' : jid_details['image_type']}
link_href = jid_details['link_href']
messages = jid_details['messages']
note = nodes[node_name]['title'] if node_name else jid_details['note']
title = jid_details['name']
xmpp_uri = jid_details['uri']
view_href = jid_details['view_href']
#note = nodes[node_name]['title'] if node_name in nodes else jid_details['note']
note = jid_details['note']
# TODO Append results to file
# Node item IDs
if node_name not in nodes:
nodes[node_name] = await XmppUtilities.get_item_ids_of_node(
jabber_id, password, jid_bare, node_name, nodes)
if isinstance(nodes[node_name]['iq'], stanza.iq.Iq):
iq = nodes[node_name]['iq']
iq_disco_items = iq['disco_items']
if iq_disco_items['items']:
count = len(nodes[node_name]['iq']['disco_items']['items'])
else:
count = 0
else:
count = 0
if jid_kind == 'pubsub' and node_name:
items = jid_details['items']
for item in items:
if item[1] == node_name:
#nodes[node_name]['title'] = item[2]
title = item[2]
break
if not title: title = node_name
else:
title = jid_details['name']
# TODO Consider also the existence of a node /j/pubsub.movim.eu/i2p
if jid_kind:
# Action and instance type
action, instance = XmppUtilities.set_action_instance_type(jid_kind, node_name)
link_href = XmppUtilities.get_link_href(jid_bare, jid_kind, node_name)
view_href = XmppUtilities.get_view_href(jid_bare, jid_kind, node_name)
xmpp_uri = XmppUtilities.get_xmpp_uri(jid_bare, jid_kind, node_name)
else: # jid_info['error']
action = 'Contact'
instance = view_href = ''
message = '{}: {} (XEP-0030)'.format(jid_info['text'], jid_info['condition'])
xmpp_uri = jid_bare
# Query URI links
action, instance, link_href, links, view_href, xmpp_uri = XmppUtilities.set_query_uri_link(
jid_bare, jid_info, jid_kind, node_name)
print('Query URI links')
links = XmppUtilities.get_query_uri_links(jid_bare, jid_kind, node_name)
# Graphic files
filename, filepath, filetype, selection = FileUtilities.handle_photo(jid_bare, jid_vcard, link_href)
@ -589,6 +625,10 @@ class HttpInstance:
count = filename = jid_bare = jid_vcard = jid_kind = links = \
message = selection = url = None
# NOTE Handling of variables "title" and "note" in case of '/j/{jid}/{node_name}' is confusing.
# TODO Add new keys that are of 'node' and be utilized for nodes, instead of reusing a variable for several roles.
# FIXME If no title be provided to 'node name', use 'node name' itself as title (to be done at FileUtilities.cache_jid_data).
template_file = 'jid.xhtml'
template_dict = {
'action' : action,
@ -603,10 +643,10 @@ class HttpInstance:
'jid_kind' : jid_kind,
'links' : links,
'message' : message,
'note' : note,
'note' : note, # TODO node_note or title of PubSub JID
'request' : request,
'selection' : selection,
'title' : title,
'title' : title, # TODO node_title
'url' : request.url._url,
'view_href' : view_href,
'xmpp_uri' : xmpp_uri}
@ -631,17 +671,14 @@ class HttpInstance:
case _ if 'haiku' in user_agent_lower:
software = 'haiku'
case _ if 'android' in user_agent_lower:
software = 'divestos'
software = 'android'
case _ if 'reactos' in user_agent_lower or 'windows' in user_agent_lower:
software = 'reactos'
software = 'windows'
case _ if 'ios' in user_agent_lower or 'macos' in user_agent_lower:
software = 'apple'
name = software.title()
if software == 'posix':
name = 'POSIX'
elif 'os' in software:
name = name.replace('os', 'OS')
if software == 'posix': name = 'POSIX'
filename_clients = 'clients.toml'
clients = Data.open_file_toml(filename_clients)
@ -735,7 +772,7 @@ class FileUtilities:
async def cache_jid_data(jabber_id, password, jid_bare, node_name=None, item_id=None, alias=None):
iq_disco_items_list = iq_disco_items_items_list = node_title = title = ''
iq_disco_items_list = iq_disco_items_items_list = node_note = node_title = title = ''
jid_vcard = {
'name' : '',
'note' : '',
@ -756,11 +793,6 @@ class FileUtilities:
jid_info_iq = jid_info['iq']
jid_kind = jid_info['kind']
# Query URI links
print('Query URI links')
action, instance, link_href, links, view_href, xmpp_uri = XmppUtilities.set_query_uri_link(
jid_bare, jid_info, jid_kind, node_name)
# JID info
print('JID info')
# NOTE Group chat of Psi+ Project at jabber.ru has a note in its vCard.
@ -838,7 +870,8 @@ class FileUtilities:
#if jid_kind in ('mix', 'muc', 'conference', 'server'):
# jid_items = await XmppXep0030.get_jid_items(xmpp_instance, jid_bare)
# if isinstance(jid_items['iq'], stanza.iq.Iq):
# count = len(jid_items['iq']['disco_items']['items'])
# iq = jid_items['iq']
# count = len(iq['disco_items']['items'])
#elif jid_kind in ('account', 'pubsub'):
# node_item_ids = await XmppXep0060.get_node_item_ids(xmpp_instance, jid_bare, node_name)
# if isinstance(node_item_ids, stanza.iq.Iq):
@ -849,56 +882,41 @@ class FileUtilities:
messages = []
subject = ''
if jid_kind == 'muc':
action = 'Join'
#action = 'Join'
# TODO Create configurations for group chat preview
room_info_muc = await XmppXep0045.get_room_information(xmpp_instance, jid_bare, alias, maxstanzas=50)
if not room_info_muc:
action = 'Warning'
node_title = jid_info['condition']
node_note = jid_info['text']
services = services_sorted = None
elif isinstance(room_info_muc['iq'], TimeoutError):
action = 'Warning'
node_title = 'Timeout'
node_note = 'Request timeout has reached'
services = services_sorted = None
elif isinstance(room_info_muc['iq'], IqTimeout):
action = 'Warning'
node_title = 'Timeout'
node_note = 'Timeout error'
services = services_sorted = None
elif isinstance(room_info_muc['iq'], IqError):
action = 'Warning'
breakpoint()
node_title = room_info_muc['condition']
node_note = room_info_muc['text']
services = services_sorted = None
else:
for message in room_info_muc['iq'][3]:
room_info_muc = await XmppXep0045.get_room_information(
xmpp_instance, jid_bare, alias, maxstanzas=50)
# NOTE Don not mix error messages with node titles and descriptions etc.
if isinstance(room_info_muc['iq'], stanza.iq.Iq):
iq = room_info_muc['iq']
for message in iq[3]:
messages.append({
'id' : message['id'],
'alias' : message['mucnick'],
'body' : message['body'],
'timestamp' : message['delay']['stamp'].__str__()})
messages.reverse()
subject = room_info_muc['iq'][1]['subject']
subject = iq[1]['subject']
#title = title or node_name
if not node_title: node_title = node_name
node_note = jid_bare
else:
message = '{}: {} (XEP-0045)'.format(room_info_muc['condition'], room_info_muc['text'])
# Node items
print('Node items')
nodes = {}
#if node_name and node_name in iq_disco_items_set:
if iq_disco_items_list and node_name and node_name in iq_disco_items_list:
action = 'Browse'
#action = 'Browse'
node_item_ids = await XmppXep0060.get_node_item_ids(xmpp_instance, jid_bare, node_name)
if isinstance(node_item_ids['iq'], stanza.iq.Iq):
iq = node_item_ids['iq']
nodes[node_name] = {}
nodes[node_name]['title'] = node_title
nodes[node_name]['count'] = len(node_item_ids['iq']['disco_items']['items'])
nodes[node_name]['count'] = len(iq['disco_items']['items'])
nodes[node_name]['item_ids'] = []
for item_id in node_item_ids['iq']['disco_items']['items']:
for item_id in iq['disco_items']['items']:
nodes[node_name]['item_ids'].append(
[item_id[0] or '', item_id[1] or '', item_id[2] or ''])
@ -915,26 +933,24 @@ class FileUtilities:
# note = jid_vcard['name']
jid_details = {
'action' : action or '',
'count' : count or '',
'error' : jid_info['error'],
'error_text' : jid_info['text'] or '',
'error_condition' : jid_info['condition'] or '',
'image_type' : jid_vcard['type'],
'instance' : instance or '',
'items' : iq_disco_items_items_list,
'kind' : jid_kind or '',
'link_href' : link_href,
'messages' : messages or '',
'name' : title,
'nodes' : nodes,
'note' : note or '',
'subject' : subject or '',
'uri' : xmpp_uri or '',
'view_href' : view_href}
'subject' : subject or ''}
print(jid_details)
# Query URI href
link_href = XmppUtilities.get_link_href(jid_bare, jid_kind, node_name)
FileUtilities.handle_photo(jid_bare, jid_vcard, link_href)
filename = 'details/{}.toml'.format(jid_bare)
@ -1166,75 +1182,108 @@ class XmppUtilities:
xmpp_instance.disconnect()
return node_item_ids
def set_query_uri_link(jid_bare, jid_info, jid_kind, node_name=None, item_id=None):
links = []
if jid_info['error']:
message = '{}: {} (XEP-0030)'.format(jid_info['text'], jid_info['condition'])
action = 'Connect with'
link_href = 'xmpp:{}'.format(jid_bare)
links.append({'name' : 'Connect',
'href' : link_href,
'iden' : 'connect'})
links.append({'name' : 'Add',
'href' : 'xmpp:{}?roster'.format(jid_bare),
'iden' : 'add'})
xmpp_uri = jid_bare
instance = view_href = ''
elif jid_kind in ('conference', 'server'):
def set_action_instance_type(jid_kind, node_name=None):
if jid_kind in ('conference', 'server'):
action = 'Discover'
if jid_kind == 'conference':
instance = 'conferences'
elif jid_kind == 'server':
instance = 'services'
link_href = 'xmpp:{}?disco;type=get;request=items'.format(jid_bare)
links.append({'name' : 'Discover',
'href' : link_href,
'iden' : 'discover'})
view_href = '/d/' + jid_bare
xmpp_uri = jid_bare
elif jid_kind in ('mix', 'muc'):
#title = 'Group Chat ' + title
# TODO Set group chat subject as description.
action = 'Join'
instance = 'participants'
link_href = 'xmpp:{}?join'.format(jid_bare)
links.append({'name' : 'Join',
'href' : link_href,
'iden' : 'join'})
view_href = '/v/' + jid_bare
xmpp_uri = jid_bare
# room_info = await XmppXep0045.get_room_data(xmpp_instance, jid_bare)
# breakpoint()
instance = 'occupants'
elif jid_kind == 'pubsub':
#node_name = request.query_params.get('node', '')
if node_name:
action = 'Subscribe'
instance = 'articles'
link_href = 'xmpp:{}?pubsub;node={};action=subscribe'.format(jid_bare, node_name)
view_href = '/d/{}/{}'.format(jid_bare, node_name)
xmpp_uri = '{}?;node={}'.format(jid_bare, node_name)
else:
action = 'Browse'
instance = 'nodes'
link_href = 'xmpp:{}?disco;type=get;request=items'.format(jid_bare)
links.append({'name' : 'Browse',
'href' : link_href,
'iden' : 'browse'})
view_href = '/d/' + jid_bare
xmpp_uri = jid_bare
else:
elif jid_kind == 'account':
action = 'Message'
instance = 'articles'
else: # jid_info['error']
action = 'Contact'
return action, instance
def get_link_href(jid_bare, jid_kind, node_name=None):
if jid_kind in ('conference', 'server'):
link_href = 'xmpp:{}?disco;type=get;request=items'.format(jid_bare)
elif jid_kind in ('mix', 'muc'):
link_href = 'xmpp:{}?join'.format(jid_bare)
elif jid_kind == 'pubsub':
if node_name:
link_href = 'xmpp:{}?pubsub;node={};action=subscribe'.format(jid_bare, node_name)
else:
link_href = 'xmpp:{}?disco;type=get;request=items'.format(jid_bare)
elif jid_kind == 'account':
link_href = 'xmpp:{}?message'.format(jid_bare)
else: # jid_info['error']
link_href = 'xmpp:{}'.format(jid_bare)
return link_href
def get_view_href(jid_bare, jid_kind, node_name=None):
links = []
view_href = None
if jid_kind in ('conference', 'server'):
view_href = '/d/' + jid_bare
elif jid_kind in ('mix', 'muc'):
view_href = '/v/' + jid_bare
elif jid_kind == 'pubsub':
if node_name:
view_href = '/d/{}/{}'.format(jid_bare, node_name)
else:
view_href = '/d/' + jid_bare
elif jid_kind == 'account':
view_href = '/d/{}/{}'.format(jid_bare, node_name)
return view_href
def get_xmpp_uri(jid_bare, jid_kind, node_name=None):
links = []
view_href = None
xmpp_uri = jid_bare
if jid_kind in ('conference', 'server'):
xmpp_uri = jid_bare
elif jid_kind in ('mix', 'muc'):
xmpp_uri = jid_bare
elif jid_kind == 'pubsub':
if node_name:
xmpp_uri = '{}?;node={}'.format(jid_bare, node_name)
else:
xmpp_uri = jid_bare
elif jid_kind == 'account':
xmpp_uri = jid_bare
return xmpp_uri
def get_query_uri_links(jid_bare, jid_kind, node_name=None, item_id=None):
links = []
if jid_kind in ('conference', 'server'):
links.append({'name' : 'Discover',
'href' : 'xmpp:{}?disco;type=get;request=items'.format(jid_bare),
'iden' : 'discover'})
xmpp_uri = jid_bare
elif jid_kind in ('mix', 'muc'):
links.append({'name' : 'Join',
'href' : 'xmpp:{}?join'.format(jid_bare),
'iden' : 'join'})
elif jid_kind == 'pubsub':
links.append({'name' : 'Browse',
'href' : 'xmpp:{}?disco;type=get;request=items'.format(jid_bare),
'iden' : 'browse'})
elif jid_kind == 'account':
links.append({'name' : 'Message',
'href' : link_href,
'href' : 'xmpp:{}?message'.format(jid_bare),
'iden' : 'message'})
links.append({'name' : 'Add',
'href' : 'xmpp:{}?roster'.format(jid_bare),
'iden' : 'add'})
#node_name = 'urn:xmpp:microblog:0'
view_href = '/d/{}/{}'.format(jid_bare, node_name)
xmpp_uri = jid_bare
else: # jid_info['error']
links.append({'name' : 'Connect',
'href' : 'xmpp:{}'.format(jid_bare),
'iden' : 'connect'})
links.append({'name' : 'Add',
'href' : 'xmpp:{}?roster'.format(jid_bare),
'iden' : 'add'})
if item_id:
links.append({'name' : 'Subscribe',
'href' : 'xmpp:{}?pubsub;node={};item={};action=subscribe'.format(jid_bare, node_name, item_id),
@ -1252,7 +1301,7 @@ class XmppUtilities:
links.append({'name' : 'vCard',
'href' : 'xmpp:{}?vcard'.format(jid_bare),
'iden' : 'vcard'})
return action, instance, link_href, links, view_href, xmpp_uri
return links
class XmppXep0030:
@ -1437,6 +1486,8 @@ class XmppXep0060:
async def get_node_items(self, jid_bare, node_name, item_ids=None, max_items=None):
try:
error = False
condition = text = None
if max_items:
iq = await self['xep_0060'].get_items(
jid_bare, node_name, timeout=5)
@ -1452,15 +1503,21 @@ class XmppXep0060:
iq = await self['xep_0060'].get_items(
jid_bare, node_name, timeout=5, item_ids=item_ids)
result = iq
except IqError as e:
if e.iq['error']['text'] == 'Node not found':
result = 'Node not found'
elif e.iq['error']['condition'] == 'item-not-found':
result = 'Item not found'
except (IqError, IqTimeout) as e:
error = True
iq = None
condition = e.iq['error']['condition']
text = e.iq['error']['text']
if not text:
if condition:
text = 'Could not retrieve node items'
else:
result = None
except IqTimeout as e:
result = e
text = 'Unknown Error'
result = {
'error' : error,
'condition' : condition,
'text' : text,
'iq' : iq}
return result
async def get_node_item_ids(self, jid_bare, node_name):
@ -1474,14 +1531,14 @@ class XmppXep0060:
# jid_bare, node_name, timeout=5)
except (IqError, IqTimeout) as e:
error = True
iq = None
condition = e.iq['error']['condition']
text = e.iq['error']['text']
if not text:
if condition:
text = 'Could not retrieve node items'
text = 'Could not retrieve node item IDs'
else:
text = 'Unknown Error'
iq = None
result = {
'error' : error,
'condition' : condition,

1
img/plant.svg Normal file
View file

@ -0,0 +1 @@
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"><path style="fill:#22bb22;stroke:none" d="M104 132h-1c-5-21-20-42-38-54-3-3-21-10-19-15s10 0 13 1c6 4 33 33 33 12 1-31-31-39-56-43-6-1-25-4-29 2-6 6-1 26 0 33 5 30 21 54 54 49 8-1 15-4 22-7 7 20 14 37 17 58 1 8-2 17 8 18l7-63 9-27c11 2 21 6 33 4 26-3 34-30 37-52 1-6 4-25-1-31-4-5-23-1-29-1-30 3-60 17-54 52 0 5 4 8 8 5 9-6 15-18 23-25 2-1 11-9 13-4s-16 17-19 20c-17 18-28 44-31 68z"/></svg>

After

Width:  |  Height:  |  Size: 457 B

1619
img/reactos.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -31,7 +31,7 @@
</a>
</div>
<div id="action-bar">
<a href="/download/divestos" id="divestos">
<a href="/download/android" id="android">
Android
</a>
<a href="/download/apple" id="apple">
@ -46,7 +46,7 @@
<a href="/download/linux" id="linux">
Linux
</a>
<a href="/download/reactos" id="reactos">
<a href="/download/windows" id="windows">
Win
</a>
</div>
@ -67,31 +67,32 @@
</span>
</div>
{% endif %}
{% if title == 'DivestOS' %}
{% if title == 'Android' %}
<div id="security-notices">
<span class="notice">
<a href="https://divestos.org">
<img src="/img/divestos.svg" />
</a>
<span>
Due to constant attempts by smartphone manufacturers to
sabotage the functionalities of Android-based XMPP chat
clients; you are advised to install a secure Android ROM such
as <a href="https://divestos.org">DivestOS Mobile</a> to
guarantee a flawless and secure communication experience.
</span>
</span>
<span class="notice">
<a href="https://f-droid.org">
<img src="/img/fdroid.svg" />
</a>
<span>
Due to recent incidents of censoring of XMPP clients from the
Android store, including of an outrageous banning of the app
<a href="https://blabber.im/">blabber.im</a> for grotesque and
preposterous alligations, you are further advised to obtain
your XMPP client from the open source store
<a href="https://f-droid.org">F-Droid</a>.
We advise installing an XMPP client with the
<a href="https://f-droid.org">F-Droid</a> repository, to
ensure that you are always using the most updated and secure
version of your XMPP chat client of choice, with the latest
and best that XMPP has to offer.
<strong>(recommended)</strong>
</span>
</span>
<span class="notice">
<a href="https://customrombay.org">
<img src="/img/plant.svg" />
</a>
<span>
We further suggest using an updated Android system. If your
smartphone manufacturer has ceased to provide updates,
please visit <a href="https://divestos.org">DivestOS
Mobile</a> or <a href="https://customrombay.org">
CustomRomBay</a> to find an updated version for your device.
<strong>(optional)</strong>
</span>
</span>
</div>
@ -124,8 +125,20 @@
<img src="/img/posix.svg" />
</a>
<span>
Please refer to <a href="/download/posix">this page</a>, if
you prefer software with text based (i.e. console) interface.
Please refer to the section <a href="/download/posix">XMPP
Clients For POSIX</a>, if you prefer software with text
based (i.e. console) interface.
</span>
</span>
</div>
{% endif %}
{% if title == 'Windows' %}
<div id="security-notices">
<span class="notice">
<img src="/img/reactos.svg" />
<span>
The listed XMPP clients, herein, are compatible with the
<a href="https://reactos.org">ReactOS</a> operating system.
</span>
</span>
</div>