#!/usr/bin/python # -*- coding: utf-8 -*- from jabbercard.config import Cache from jabbercard.utilities.graphics import Graphics from jabbercard.utilities.toml import Toml from jabbercard.xmpp.instance import XmppInstance from jabbercard.xmpp.xep_0030 import XmppXep0030 from jabbercard.xmpp.xep_0045 import XmppXep0045 from jabbercard.xmpp.xep_0054 import XmppXep0054 from jabbercard.xmpp.xep_0060 import XmppXep0060 from jabbercard.xmpp.xep_0369 import XmppXep0369 import os from dateutil import parser from slixmpp import stanza import xml.etree.ElementTree as ET class XmppUtilities: async def cache_vcard_data( jabber_id, password, jid_bare, node_name_vcard4, item_id_vcard4): # Start an XMPP instance and retrieve information xmpp_instance = XmppInstance(jabber_id, password, jid_bare) xmpp_instance.connect() vcard4_data = await XmppXep0060.get_node_items( xmpp_instance, jid_bare, node_name_vcard4, item_ids=[item_id_vcard4]) xmpp_instance.disconnect() if vcard4_data: directory_cache = Cache.get_directory() supdirectory = os.path.join(directory_cache, 'xep_0060', jid_bare) if not os.path.exists(supdirectory): os.mkdir(supdirectory) directory = os.path.join(directory_cache, 'xep_0060', jid_bare, node_name_vcard4) if not os.path.exists(directory): os.mkdir(directory) if isinstance(vcard4_data['iq'], stanza.iq.Iq): iq = vcard4_data['iq'] for item in iq['pubsub']['items']: filename = directory + item_id_vcard4 + '.xml' xml_item_as_string = str(item) Toml.save_to_file(filename, xml_item_as_string) #item_payload = item['payload'] #vcard4_info = Syndication.extract_vcard4_items(item_payload) async def cache_node_data( jabber_id, password, jid_bare, node_name): # Start an XMPP instance and retrieve information xmpp_instance = XmppInstance(jabber_id, password, jid_bare) xmpp_instance.connect() node_items = await XmppXep0060.get_node_items( xmpp_instance, jid_bare, node_name) xmpp_instance.disconnect() if node_items: supdirectory = 'xep_0060/{}/'.format(jid_bare) if not os.path.exists(supdirectory): os.mkdir(supdirectory) directory = os.path.join(directory_cache, 'xep_0060', jid_bare, node_name) if not os.path.exists(directory): os.mkdir(directory) if isinstance(node_items['iq'], stanza.iq.Iq): iq = node_items['iq'] namespace = '{http://www.w3.org/2005/Atom}' for item in iq['pubsub']['items']: item_payload = item['payload'] date_element = item_payload.find(namespace + 'updated') if not date_element: date_element = item_payload.find(namespace + 'published') if isinstance(date_element, ET.Element): date = date_element.text modification_time = parser.parse(date).timestamp() filename = directory + item['id'] + '.xml' xml_item_as_string = str(item) Toml.save_to_file(filename, xml_item_as_string) if isinstance(date_element, ET.Element): file_statistics = os.stat(filename) access_time = file_statistics.st_atime os.utime(filename, (access_time, modification_time)) #item_payload = item['payload'] #entry = Syndication.extract_atom_items(item_payload) 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_note = node_title = title = '' jid_vcard = { 'name' : '', 'note' : '', 'type' : '', 'bin' : ''} #filename = 'details/{}.toml'.format(jid_bare) #if os.path.exists(filename): jid_details = Toml.open_file_toml(filename) # Start an XMPP instance and retrieve information xmpp_instance = XmppInstance(jabber_id, password, jid_bare) xmpp_instance.connect() # JID kind print('JID kind') instance = message = node_id = None jid_info = await XmppXep0030.get_jid_info(xmpp_instance, jid_bare) jid_info_iq = jid_info['iq'] jid_kind = jid_info['kind'] # Set node name to 'urn:xmpp:microblog:0' if JID is an account if jid_kind == 'account' and not node_name: node_name = 'urn:xmpp:microblog:0' # vCard4 data node_name_vcard4 = 'urn:xmpp:vcard4' item_id_vcard4 = 'current' vcard4_data = await XmppXep0060.get_node_items( xmpp_instance, jid_bare, node_name_vcard4, item_ids=[item_id_vcard4]) if vcard4_data: directory_cache = Cache.get_directory() supdirectory = os.path.join(directory_cache, 'xep_0060', jid_bare) if not os.path.exists(supdirectory): os.mkdir(supdirectory) directory = os.path.join(directory_cache, 'xep_0060', jid_bare, node_name_vcard4) if not os.path.exists(directory): os.mkdir(directory) if isinstance(vcard4_data['iq'], stanza.iq.Iq): iq = vcard4_data['iq'] for item in iq['pubsub']['items']: filename = directory + item_id_vcard4 + '.xml' xml_item_as_string = str(item) Toml.save_to_file(filename, xml_item_as_string) #item_payload = item['payload'] #vcard4_info = Syndication.extract_vcard4_items(item_payload) # JID info print('JID info') # NOTE Group chat of Psi+ Project at jabber.ru has a note in its vCard. vcard_data = await XmppXep0054.get_vcard_data(xmpp_instance, jid_bare) if not vcard_data['error']: conference_title = None if jid_kind in ('mix', 'muc'): for identity in jid_info_iq['disco_info']['identities']: if identity[3]: conference_title = identity[3] break vcard_temp = vcard_data['iq']['vcard_temp'] jid_vcard = { 'name' : vcard_temp['FN'] or conference_title or '', 'note' : vcard_temp['notes'] or node_id or '', 'type' : vcard_temp['PHOTO']['TYPE'] or '', 'bin' : vcard_temp['PHOTO']['BINVAL'] or ''} # TODO /d/pubsub.nicoco.fr/blog/urn-uuid-53e43061-1962-3112-bb8a-1473dca61719 count = '' jid_items = await XmppXep0030.get_jid_items(xmpp_instance, jid_bare) if isinstance(jid_items['iq'], stanza.iq.Iq): iq = jid_items['iq'] iq_disco_items = iq['disco_items'] iq_disco_items_items = iq_disco_items['items'] #iq_disco_items_set = {''} iq_disco_items_list = [] iq_disco_items_items_list = [] for item in iq_disco_items_items: if jid_kind == 'muc': #iq_disco_items_set.update([item[2]]) iq_disco_items_list.append(item[2]) else: #iq_disco_items_set.update([item[1]]) iq_disco_items_list.append(item[1]) iq_disco_items_items_list.append( [item[0] or '', item[1] or '', item[2] or '']) #count = len(iq_disco_items_set) count = len(iq_disco_items_list) # Title print('Title') if (jid_kind not in ('conference', 'mix', 'muc') and '@' in jid_bare and not node_name): # NOTE Variables node_name and node_title do not appear to be utilized. node_name = 'urn:xmpp:microblog:0' node_title = 'Journal' elif jid_kind == 'pubsub': category = 'unsorted' for item in iq_disco_items_items: if item[2] and item[1] == node_name: node_title = item[2] break else: jid_items = None if jid_kind == 'server': if jid_info_iq: for identity in jid_info_iq['disco_info']['identities']: if jid_kind == identity[0] and identity[1] == 'im' and identity[3]: title = identity[3] print(jid_bare) print(identity) print(jid_info) # String 'undefined' is sourced from JID discuss@conference.conversejs.org if not title: if jid_vcard['name'] and not 'undefined' in jid_vcard['name']: title = jid_vcard['name'] else: title = jid_bare.split('@')[0] # JID item count #count = await XmppUtilities.count_jid_items(xmpp_instance, jid_bare, node_name, jid_kind) #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): # 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): # count = len(node_item_ids['disco_items']['items']) # Group chat messages print('Group chat messages') messages = [] subject = '' if jid_kind == 'muc': #action = 'Join' # TODO Create configurations for group chat preview room_info_muc = await XmppXep0045.get_room_information( xmpp_instance, jid_bare, alias, maxstanzas=50) # NOTE Do not mix error messages with node titles and descriptions etc. if isinstance(room_info_muc['iq'], tuple): 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 = 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']) elif jid_kind == 'mix': room_info_muc = await XmppXep0369.get_room_information( xmpp_instance, jid_bare, alias) if isinstance(room_info_muc['iq'], tuple): 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 = iq[1]['subject'] #title = title or node_name if not node_title: node_title = node_name node_note = jid_bare else: message = '{}: {} (XEP-0369)'.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' 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(iq['disco_items']['items']) nodes[node_name]['item_ids'] = [] 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 '']) item_ids = [] for item in nodes[node_name]['item_ids']: item_ids.append(item[2]) node_items = await XmppXep0060.get_node_items( xmpp_instance, jid_bare, node_name) if node_items: directory_cache = Cache.get_directory() supdirectory = os.path.join(directory_cache, 'xep_0060', jid_bare) if not os.path.exists(supdirectory): os.mkdir(supdirectory) directory = os.path.join(directory_cache, 'xep_0060', jid_bare, node_name) if not os.path.exists(directory): os.mkdir(directory) if isinstance(node_items['iq'], stanza.iq.Iq): iq = node_items['iq'] namespace = '{http://www.w3.org/2005/Atom}' for item in iq['pubsub']['items']: item_payload = item['payload'] date_element = item_payload.find(namespace + 'updated') if not date_element: date_element = item_payload.find(namespace + 'published') if isinstance(date_element, ET.Element): date = date_element.text modification_time = parser.parse(date).timestamp() filename = directory + item['id'] + '.xml' xml_item_as_string = str(item) Toml.save_to_file(filename, xml_item_as_string) if isinstance(date_element, ET.Element): file_statistics = os.stat(filename) access_time = file_statistics.st_atime os.utime(filename, (access_time, modification_time)) #item_payload = item['payload'] #entry = Syndication.extract_atom_items(item_payload) xmpp_instance.disconnect() # Notes print('Notes') jid_vcard_note = jid_vcard['note'] if isinstance(jid_vcard_note, list) and len(jid_vcard_note): note = jid_vcard_note[0]['NOTE'] else: note = jid_vcard_note #if not note and jid_vcard['name'] and not 'undefined' in jid_vcard['name'] and title != jid_vcard['name']: # note = jid_vcard['name'] jid_details = { 'count' : count or '', 'error' : jid_info['error'], 'error_text' : jid_info['text'] or '', 'error_condition' : jid_info['condition'] or '', 'image_type' : jid_vcard['type'], 'items' : iq_disco_items_items_list, 'kind' : jid_kind or '', 'messages' : messages or '', 'name' : title, 'nodes' : nodes, 'note' : note or '', 'subject' : subject or ''} print(jid_details) # Query URI href link_href = XmppUtilities.get_link_href(jid_bare, jid_kind, node_name) Graphics.handle_photo(jid_bare, jid_vcard, link_href) directory_cache = Cache.get_directory() filename = os.path.join(directory_cache, 'details', jid_bare + '.toml') Toml.save_to_toml(filename, jid_details) return jid_details 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' elif jid_kind in ('mix', 'muc'): action = 'Join' instance = 'occupants' elif jid_kind == 'pubsub': if node_name: action = 'Subscribe' instance = 'articles' else: action = 'Browse' instance = 'nodes' 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' : 'xmpp:{}?message'.format(jid_bare), 'iden' : 'message'}) links.append({'name' : 'Add', 'href' : 'xmpp:{}?roster'.format(jid_bare), 'iden' : 'add'}) 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), 'iden' : 'subscribe'}) links.append({'name' : 'View', 'href' : 'xmpp:{}?pubsub;node={};item={}'.format(jid_bare, node_name, item_id), 'iden' : 'view'}) elif node_name: links.append({'name' : 'Subscribe', 'href' : 'xmpp:{}?pubsub;node={};action=subscribe'.format(jid_bare, node_name), 'iden' : 'subscribe'}) links.append({'name' : 'View', 'href' : 'xmpp:{}?pubsub;node={}'.format(jid_bare, node_name), 'iden' : 'view'}) links.append({'name' : 'vCard', 'href' : 'xmpp:{}?vcard'.format(jid_bare), 'iden' : 'vcard'}) return links