From 7dda347ebcbfcc82196ddd50bcc4ecca58c24ef7 Mon Sep 17 00:00:00 2001 From: "Schimon Jehudah, Adv." Date: Tue, 22 Oct 2024 16:34:39 +0300 Subject: [PATCH] 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. --- clients.toml | 50 +- fasi.py | 427 ++++++----- img/plant.svg | 1 + img/reactos.svg | 1619 ++++++++++++++++++++++++++++++++++++++++++ xhtml/download.xhtml | 129 ++-- 5 files changed, 1958 insertions(+), 268 deletions(-) create mode 100644 img/plant.svg create mode 100644 img/reactos.svg diff --git a/clients.toml b/clients.toml index 56d2f7b..39f1a5a 100644 --- a/clients.toml +++ b/clients.toml @@ -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"] diff --git a/fasi.py b/fasi.py index 0dd17fa..45597c9 100644 --- a/fasi.py +++ b/fasi.py @@ -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: @@ -1298,12 +1347,12 @@ class XmppXep0030: elif 'urn:xmpp:mix:core:1' in features: jid_kind = 'mix' elif ('muc_moderated' in features or - 'muc_open' in features or - 'muc_persistent' in features or - 'muc_public' in features or - 'muc_semianonymous' in features or - 'muc_unmoderated' in features or - 'muc_unsecured' in features): + 'muc_open' in features or + 'muc_persistent' in features or + 'muc_public' in features or + 'muc_semianonymous' in features or + 'muc_unmoderated' in features or + 'muc_unsecured' in features): jid_kind = 'muc' else: for identity in iq_disco_info['identities']: @@ -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' - else: - result = None - except IqTimeout as e: - result = e + 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: + 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, diff --git a/img/plant.svg b/img/plant.svg new file mode 100644 index 0000000..26b7202 --- /dev/null +++ b/img/plant.svg @@ -0,0 +1 @@ + diff --git a/img/reactos.svg b/img/reactos.svg new file mode 100644 index 0000000..7a77846 --- /dev/null +++ b/img/reactos.svg @@ -0,0 +1,1619 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xhtml/download.xhtml b/xhtml/download.xhtml index d590381..68985bf 100644 --- a/xhtml/download.xhtml +++ b/xhtml/download.xhtml @@ -31,7 +31,7 @@
- + Android @@ -46,7 +46,7 @@ Linux - + Win
@@ -55,79 +55,92 @@

XMPP Clients For {{title}}

{% if title == 'Apple' %}
- - - - - - Please refer to the section XMPP - Clients For Haiku, if you are using the Haiku operating - system. + + + + + + Please refer to the section XMPP + Clients For Haiku, if you are using the Haiku operating + system. + -
{% endif %} - {% if title == 'DivestOS' %} + {% if title == 'Android' %}
- - - - - - 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 DivestOS Mobile to - guarantee a flawless and secure communication experience. + + + + + + We advise installing an XMPP client with the + F-Droid 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. + (recommended) + - - - - - - - Due to recent incidents of censoring of XMPP clients from the - Android store, including of an outrageous banning of the app - blabber.im for grotesque and - preposterous alligations, you are further advised to obtain - your XMPP client from the open source store - F-Droid. + + + + + + We further suggest using an updated Android system. If your + smartphone manufacturer has ceased to provide updates, + please visit DivestOS + Mobile or + CustomRomBay to find an updated version for your device. + (optional) + -
{% endif %} {% if title == 'Haiku' %}
- - - - Most of the software that are listed here should be available - for you to install directly from desktop with HaikuDepot. + + + + Most of the software that are listed here should be available + for you to install directly from desktop with HaikuDepot. + -
{% endif %} {% if title == 'Linux' %}
- - - - The listed XMPP clients, herein, are also usable with the - Linux systems that are designed for mobile devices, e.g. - Droidian, - Mobian and - postmarketOS. + + + + The listed XMPP clients, herein, are also usable with the + Linux systems that are designed for mobile devices, e.g. + Droidian, + Mobian and + postmarketOS. + - - - - - - - Please refer to this page, if - you prefer software with text based (i.e. console) interface. + + + + + + Please refer to the section XMPP + Clients For POSIX, if you prefer software with text + based (i.e. console) interface. + + +
+ {% endif %} + {% if title == 'Windows' %} +
+ + + + The listed XMPP clients, herein, are compatible with the + ReactOS operating system. + -
{% endif %}