UNPKG

@jsxc/jsxc

Version:

Real-time XMPP chat application with video calls, file transfer and encrypted communication

156 lines (125 loc) 4.8 kB
import JID from '../../JID'; import { IConnection } from '../Connection.interface'; import * as NS from './namespace'; import XMPPHandler from './handler'; import Log from '../../util/Log'; import Account from '../../Account'; import { AbstractConnection, ExtensivePresence, Presence, STANZA_IQ_KEY, STANZA_KEY } from '../AbstractConnection'; import XMPPJingleHandler from './JingleHandler'; import Client from '../../Client'; export default class XMPPConnection extends AbstractConnection implements IConnection { private handler: XMPPHandler; constructor(account: Account, protected connection) { super(account); this.handler = new XMPPHandler(account, connection); this.handler.registerHandler(); NS.register('METADATA_NOTIFY', 'urn:xmpp:avatar:metadata+notify'); this.processPendingStorageConnections(); this.listenToStorageConnections(); Client.getPresenceController().registerTargetPresenceHook(this.targetPresenceHandler); } private processPendingStorageConnections() { let storage = this.getStorage(); let pendingStanzaItems = storage.getItemsWithKeyPrefix(STANZA_KEY); let pendingStanzaIQItems = storage.getItemsWithKeyPrefix(STANZA_IQ_KEY); for (let key in pendingStanzaItems) { this.onIncomingStorageStanza(key, pendingStanzaItems[key]); } for (let key in pendingStanzaIQItems) { this.onIncomingStorageStanzaIQ(key, pendingStanzaIQItems[key]); } } private listenToStorageConnections() { this.getStorage().registerHook(STANZA_KEY, (newValue, oldValue, key) => { if (newValue && !oldValue) { this.onIncomingStorageStanza(key, newValue); } }); this.getStorage().registerHook(STANZA_IQ_KEY, (newValue, oldValue, key) => { if (newValue && !oldValue) { this.onIncomingStorageStanzaIQ(key, newValue); } }); } private targetPresenceHandler = ({ presence, status }: ExtensivePresence) => { if (presence === Presence.offline) { this.connection.disconnect('forced'); } else { this.account.getConnection().sendPresence(presence, status); } }; public registerHandler( handler: (stanza: string) => boolean, ns?: string, name?: string, type?: string, id?: string, from?: string ) { this.connection.addHandler.apply(this.connection, arguments); } public pause() { this.connection.pause(); } public close() { Client.getPresenceController().unregisterTargetPresenceHook(this.targetPresenceHandler); } public getJingleHandler() { if (!this.jingleHandler) { this.jingleHandler = new XMPPJingleHandler(this.account, this); } return this.jingleHandler; } public getCapabilitiesByJid(jid: JID): any { Log.error('Deprecated function called: getCapabilitiesByJid'); } public hasFeatureByJid(jid: JID, feature: string); public hasFeatureByJid(jid: JID, feature: string[]); public hasFeatureByJid() {} public logout() {} public send(stanzaElement: Element); public send(stanzaElement: Strophe.Builder); public send() { this.connection.send(arguments[0]); } public sendIQ(stanzaElement: Element): Promise<Element>; public sendIQ(stanzaElement: Strophe.Builder): Promise<Element>; public sendIQ() { let stanzaElement = arguments[0]; return new Promise((resolve, reject) => { this.connection.sendIQ(stanzaElement, resolve, reject); }); } private onIncomingStorageStanza(key: string, stanzaString: string) { let stanzaElement = new DOMParser().parseFromString(stanzaString, 'text/xml').documentElement; if ($(stanzaElement).find('parsererror').length > 0) { Log.error('Could not parse stanza string from storage.'); return; } this.send(stanzaElement); this.getStorage().removeItem(key); } private onIncomingStorageStanzaIQ(key: string, stanzaString: string) { let stanzaElement = new DOMParser().parseFromString(stanzaString, 'text/xml').documentElement; if ($(stanzaElement).find('parsererror').length > 0) { Log.error('Could not parse stanza string from storage.'); return; } this.sendIQ(stanzaElement) .then((stanza: HTMLElement) => { this.getStorage().setItem(key, { type: 'success', stanza: stanza.outerHTML, }); }) .catch(stanza => { this.getStorage().setItem(key, { type: 'error', stanza: stanza.outerHTML, }); }) .then(() => { this.getStorage().removeItem(key); }); } }