|
@@ -3,15 +3,14 @@
|
|
|
* @typedef {import('./entities').default} DiscoEntities
|
|
|
* @typedef {import('@converse/skeletor').Collection} Collection
|
|
|
*/
|
|
|
+import { getOpenPromise } from '@converse/openpromise';
|
|
|
import _converse from '../../shared/_converse.js';
|
|
|
import api from '../../shared/api/index.js';
|
|
|
import converse from '../../shared/api/public.js';
|
|
|
-import log from "../../log.js";
|
|
|
-import { getOpenPromise } from '@converse/openpromise';
|
|
|
+import log from '../../log.js';
|
|
|
|
|
|
const { Strophe, $iq } = converse.env;
|
|
|
|
|
|
-
|
|
|
export default {
|
|
|
/**
|
|
|
* The XEP-0030 service discovery API
|
|
@@ -34,12 +33,12 @@ export default {
|
|
|
* @param { String } xmlns The XML namespace
|
|
|
* @example _converse.api.disco.stream.getFeature('ver', 'urn:xmpp:features:rosterver')
|
|
|
*/
|
|
|
- async getFeature (name, xmlns) {
|
|
|
+ async getFeature(name, xmlns) {
|
|
|
await api.waitUntil('streamFeaturesAdded');
|
|
|
|
|
|
- const stream_features = /** @type {Collection} */(_converse.state.stream_features);
|
|
|
+ const stream_features = /** @type {Collection} */ (_converse.state.stream_features);
|
|
|
if (!name || !xmlns) {
|
|
|
- throw new Error("name and xmlns need to be provided when calling disco.stream.getFeature");
|
|
|
+ throw new Error('name and xmlns need to be provided when calling disco.stream.getFeature');
|
|
|
}
|
|
|
if (stream_features === undefined && !api.connection.connected()) {
|
|
|
// Happens during tests when disco lookups happen asynchronously after teardown.
|
|
@@ -47,8 +46,8 @@ export default {
|
|
|
log.warn(msg);
|
|
|
return;
|
|
|
}
|
|
|
- return stream_features.findWhere({'name': name, 'xmlns': xmlns});
|
|
|
- }
|
|
|
+ return stream_features.findWhere({ 'name': name, 'xmlns': xmlns });
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -65,32 +64,34 @@ export default {
|
|
|
* Lets you add new identities for this client (i.e. instance of Converse)
|
|
|
* @method api.disco.own.identities.add
|
|
|
*
|
|
|
- * @param { String } category - server, client, gateway, directory, etc.
|
|
|
- * @param { String } type - phone, pc, web, etc.
|
|
|
- * @param { String } name - "Converse"
|
|
|
- * @param { String } lang - en, el, de, etc.
|
|
|
+ * @param {String} category - server, client, gateway, directory, etc.
|
|
|
+ * @param {String} type - phone, pc, web, etc.
|
|
|
+ * @param {String} name - "Converse"
|
|
|
+ * @param {String} lang - en, el, de, etc.
|
|
|
*
|
|
|
* @example _converse.api.disco.own.identities.clear();
|
|
|
*/
|
|
|
- add (category, type, name, lang) {
|
|
|
- const disco = /** @type {DiscoState} */(_converse.state.disco);
|
|
|
- for (var i=0; i<disco._identities.length; i++) {
|
|
|
- if (disco._identities[i].category == category &&
|
|
|
- disco._identities[i].type == type &&
|
|
|
- disco._identities[i].name == name &&
|
|
|
- disco._identities[i].lang == lang) {
|
|
|
+ add(category, type, name, lang) {
|
|
|
+ const disco = /** @type {DiscoState} */ (_converse.state.disco);
|
|
|
+ for (var i = 0; i < disco._identities.length; i++) {
|
|
|
+ if (
|
|
|
+ disco._identities[i].category == category &&
|
|
|
+ disco._identities[i].type == type &&
|
|
|
+ disco._identities[i].name == name &&
|
|
|
+ disco._identities[i].lang == lang
|
|
|
+ ) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
- disco._identities.push({category: category, type: type, name: name, lang: lang});
|
|
|
+ disco._identities.push({ category: category, type: type, name: name, lang: lang });
|
|
|
},
|
|
|
/**
|
|
|
* Clears all previously registered identities.
|
|
|
* @method api.disco.own.identities.clear
|
|
|
* @example _converse.api.disco.own.identities.clear();
|
|
|
*/
|
|
|
- clear () {
|
|
|
- /** @type {DiscoState} */(_converse.state.disco)._identities = []
|
|
|
+ clear() {
|
|
|
+ /** @type {DiscoState} */ (_converse.state.disco)._identities = [];
|
|
|
},
|
|
|
/**
|
|
|
* Returns all of the identities registered for this client
|
|
@@ -98,9 +99,9 @@ export default {
|
|
|
* @method api.disco.identities.get
|
|
|
* @example const identities = api.disco.own.identities.get();
|
|
|
*/
|
|
|
- get () {
|
|
|
- return /** @type {DiscoState} */(_converse.state.disco)._identities;
|
|
|
- }
|
|
|
+ get() {
|
|
|
+ return /** @type {DiscoState} */ (_converse.state.disco)._identities;
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -114,10 +115,12 @@ export default {
|
|
|
* @param { String } name - e.g. http://jabber.org/protocol/caps
|
|
|
* @example _converse.api.disco.own.features.add("http://jabber.org/protocol/caps");
|
|
|
*/
|
|
|
- add (name) {
|
|
|
- const disco = /** @type {DiscoState} */(_converse.state.disco);
|
|
|
- for (let i=0; i<disco._features.length; i++) {
|
|
|
- if (disco._features[i] == name) { return false; }
|
|
|
+ add(name) {
|
|
|
+ const disco = /** @type {DiscoState} */ (_converse.state.disco);
|
|
|
+ for (let i = 0; i < disco._features.length; i++) {
|
|
|
+ if (disco._features[i] == name) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
disco._features.push(name);
|
|
|
},
|
|
@@ -126,38 +129,38 @@ export default {
|
|
|
* @method api.disco.own.features.clear
|
|
|
* @example _converse.api.disco.own.features.clear();
|
|
|
*/
|
|
|
- clear () {
|
|
|
- const disco = /** @type {DiscoState} */(_converse.state.disco);
|
|
|
- disco._features = []
|
|
|
+ clear() {
|
|
|
+ const disco = /** @type {DiscoState} */ (_converse.state.disco);
|
|
|
+ disco._features = [];
|
|
|
},
|
|
|
/**
|
|
|
* Returns all of the features registered for this client (i.e. instance of Converse).
|
|
|
* @method api.disco.own.features.get
|
|
|
* @example const features = api.disco.own.features.get();
|
|
|
*/
|
|
|
- get () {
|
|
|
- return /** @type {DiscoState} */(_converse.state.disco)._features;
|
|
|
- }
|
|
|
- }
|
|
|
+ get() {
|
|
|
+ return /** @type {DiscoState} */ (_converse.state.disco)._features;
|
|
|
+ },
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* Query for information about an XMPP entity
|
|
|
*
|
|
|
* @method api.disco.info
|
|
|
- * @param { string } jid The Jabber ID of the entity to query
|
|
|
- * @param { string } [node] A specific node identifier associated with the JID
|
|
|
+ * @param {string} jid The Jabber ID of the entity to query
|
|
|
+ * @param {string} [node] A specific node identifier associated with the JID
|
|
|
* @returns {promise} Promise which resolves once we have a result from the server.
|
|
|
*/
|
|
|
- info (jid, node) {
|
|
|
- const attrs = {xmlns: Strophe.NS.DISCO_INFO};
|
|
|
+ info(jid, node) {
|
|
|
+ const attrs = { xmlns: Strophe.NS.DISCO_INFO };
|
|
|
if (node) {
|
|
|
attrs.node = node;
|
|
|
}
|
|
|
const info = $iq({
|
|
|
'from': api.connection.get().jid,
|
|
|
- 'to':jid,
|
|
|
- 'type':'get'
|
|
|
+ 'to': jid,
|
|
|
+ 'type': 'get',
|
|
|
}).c('query', attrs);
|
|
|
return api.sendIQ(info);
|
|
|
},
|
|
@@ -166,20 +169,20 @@ export default {
|
|
|
* Query for items associated with an XMPP entity
|
|
|
*
|
|
|
* @method api.disco.items
|
|
|
- * @param { string } jid The Jabber ID of the entity to query for items
|
|
|
- * @param { string } [node] A specific node identifier associated with the JID
|
|
|
+ * @param {string} jid The Jabber ID of the entity to query for items
|
|
|
+ * @param {string} [node] A specific node identifier associated with the JID
|
|
|
* @returns {promise} Promise which resolves once we have a result from the server.
|
|
|
*/
|
|
|
- items (jid, node) {
|
|
|
- const attrs = {'xmlns': Strophe.NS.DISCO_ITEMS};
|
|
|
+ items(jid, node) {
|
|
|
+ const attrs = { 'xmlns': Strophe.NS.DISCO_ITEMS };
|
|
|
if (node) {
|
|
|
attrs.node = node;
|
|
|
}
|
|
|
return api.sendIQ(
|
|
|
$iq({
|
|
|
'from': api.connection.get().jid,
|
|
|
- 'to':jid,
|
|
|
- 'type':'get'
|
|
|
+ 'to': jid,
|
|
|
+ 'type': 'get',
|
|
|
}).c('query', attrs)
|
|
|
);
|
|
|
},
|
|
@@ -195,13 +198,13 @@ export default {
|
|
|
* Get the corresponding `DiscoEntity` instance.
|
|
|
*
|
|
|
* @method api.disco.entities.get
|
|
|
- * @param { string } jid The Jabber ID of the entity
|
|
|
- * @param { boolean } [create] Whether the entity should be created if it doesn't exist.
|
|
|
+ * @param {string} jid The Jabber ID of the entity
|
|
|
+ * @param {boolean} [create] Whether the entity should be created if it doesn't exist.
|
|
|
* @example _converse.api.disco.entities.get(jid);
|
|
|
*/
|
|
|
- async get (jid, create=false) {
|
|
|
+ async get(jid, create = false) {
|
|
|
await api.waitUntil('discoInitialized');
|
|
|
- const disco_entities = /** @type {DiscoEntities} */(_converse.state.disco_entities);
|
|
|
+ const disco_entities = /** @type {DiscoEntities} */ (_converse.state.disco_entities);
|
|
|
if (!jid) {
|
|
|
return disco_entities;
|
|
|
}
|
|
@@ -221,12 +224,12 @@ export default {
|
|
|
* Return any disco items advertised on this entity
|
|
|
*
|
|
|
* @method api.disco.entities.items
|
|
|
- * @param { string } jid - The Jabber ID of the entity for which we want to fetch items
|
|
|
+ * @param {string} jid - The Jabber ID of the entity for which we want to fetch items
|
|
|
* @example api.disco.entities.items(jid);
|
|
|
*/
|
|
|
- items (jid) {
|
|
|
- const disco_entities = /** @type {DiscoEntities} */(_converse.state.disco_entities);
|
|
|
- return disco_entities.filter(e => e.get('parent_jids')?.includes(jid));
|
|
|
+ items(jid) {
|
|
|
+ const disco_entities = /** @type {DiscoEntities} */ (_converse.state.disco_entities);
|
|
|
+ return disco_entities.filter((e) => e.get('parent_jids')?.includes(jid));
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -238,19 +241,19 @@ export default {
|
|
|
* `ignore_cache: true` in the options parameter.
|
|
|
*
|
|
|
* @method api.disco.entities.create
|
|
|
- * @param { object } data
|
|
|
- * @param { string } data.jid - The Jabber ID of the entity
|
|
|
- * @param { string } data.parent_jid - The Jabber ID of the parent entity
|
|
|
- * @param { string } data.name
|
|
|
- * @param { object } [options] - Additional options
|
|
|
- * @param { boolean } [options.ignore_cache]
|
|
|
+ * @param {object} data
|
|
|
+ * @param {string} data.jid - The Jabber ID of the entity
|
|
|
+ * @param {string} data.parent_jid - The Jabber ID of the parent entity
|
|
|
+ * @param {string} data.name
|
|
|
+ * @param {object} [options] - Additional options
|
|
|
+ * @param {boolean} [options.ignore_cache]
|
|
|
* If true, fetch all features from the XMPP server instead of restoring them from cache
|
|
|
* @example _converse.api.disco.entities.create({ jid }, {'ignore_cache': true});
|
|
|
*/
|
|
|
- create (data, options) {
|
|
|
- const disco_entities = /** @type {DiscoEntities} */(_converse.state.disco_entities);
|
|
|
+ create(data, options) {
|
|
|
+ const disco_entities = /** @type {DiscoEntities} */ (_converse.state.disco_entities);
|
|
|
return disco_entities.create(data, options);
|
|
|
- }
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -262,37 +265,40 @@ export default {
|
|
|
* Return a given feature of a disco entity
|
|
|
*
|
|
|
* @method api.disco.features.get
|
|
|
- * @param { string } feature The feature that might be
|
|
|
+ * @param {string} feature The feature that might be
|
|
|
* supported. In the XML stanza, this is the `var`
|
|
|
* attribute of the `<feature>` element. For
|
|
|
* example: `http://jabber.org/protocol/muc`
|
|
|
- * @param { string } jid The JID of the entity
|
|
|
+ * @param {string} jid The JID of the entity
|
|
|
* (and its associated items) which should be queried
|
|
|
- * @returns {promise} A promise which resolves with a list containing
|
|
|
+ * @returns {Promise<import('@converse/skeletor').Model|import('@converse/skeletor').Model[]>}
|
|
|
+ * A promise which resolves with a list containing
|
|
|
* _converse.Entity instances representing the entity
|
|
|
* itself or those items associated with the entity if
|
|
|
* they support the given feature.
|
|
|
* @example
|
|
|
* api.disco.features.get(Strophe.NS.MAM, _converse.bare_jid);
|
|
|
*/
|
|
|
- async get (feature, jid) {
|
|
|
- if (!jid) throw new TypeError('You need to provide an entity JID');
|
|
|
+ async get(feature, jid) {
|
|
|
+ if (!jid) throw new TypeError('api.disco.features.get: You need to provide an entity JID');
|
|
|
|
|
|
const entity = await api.disco.entities.get(jid, true);
|
|
|
|
|
|
if (_converse.state.disco_entities === undefined && !api.connection.connected()) {
|
|
|
// Happens during tests when disco lookups happen asynchronously after teardown.
|
|
|
- log.warn(`Tried to get feature ${feature} for ${jid} but `+
|
|
|
- `_converse.disco_entities has been torn down`);
|
|
|
+ log.warn(
|
|
|
+ `Tried to get feature ${feature} for ${jid} but ` +
|
|
|
+ `_converse.disco_entities has been torn down`
|
|
|
+ );
|
|
|
return [];
|
|
|
}
|
|
|
|
|
|
const promises = [
|
|
|
entity.getFeature(feature),
|
|
|
- ...api.disco.entities.items(jid).map(i => i.getFeature(feature))
|
|
|
+ ...api.disco.entities.items(jid).map((i) => i.getFeature(feature)),
|
|
|
];
|
|
|
const result = await Promise.all(promises);
|
|
|
- return result.filter(f => (f instanceof Object));
|
|
|
+ return result.filter((f) => f instanceof Object);
|
|
|
},
|
|
|
|
|
|
/**
|
|
@@ -300,18 +306,18 @@ export default {
|
|
|
* associated items, supports a given feature.
|
|
|
*
|
|
|
* @method api.disco.features.has
|
|
|
- * @param { string } feature The feature that might be
|
|
|
+ * @param {string} feature The feature that might be
|
|
|
* supported. In the XML stanza, this is the `var`
|
|
|
* attribute of the `<feature>` element. For
|
|
|
* example: `http://jabber.org/protocol/muc`
|
|
|
- * @param { string } jid The JID of the entity
|
|
|
+ * @param {string} jid The JID of the entity
|
|
|
* (and its associated items) which should be queried
|
|
|
- * @returns {Promise} A promise which resolves with a boolean
|
|
|
+ * @returns {Promise<boolean>} A promise which resolves with a boolean
|
|
|
* @example
|
|
|
* api.disco.features.has(Strophe.NS.MAM, _converse.bare_jid);
|
|
|
*/
|
|
|
- async has (feature, jid) {
|
|
|
- if (!jid) throw new TypeError('You need to provide an entity JID');
|
|
|
+ async has(feature, jid) {
|
|
|
+ if (!jid) throw new TypeError('api.disco.feature.has: You need to provide an entity JID');
|
|
|
|
|
|
const entity = await api.disco.entities.get(jid, true);
|
|
|
|
|
@@ -325,22 +331,22 @@ export default {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- const result = await Promise.all(api.disco.entities.items(jid).map(i => i.getFeature(feature)));
|
|
|
- return result.map(f => (f instanceof Object)).includes(true);
|
|
|
- }
|
|
|
+ const result = await Promise.all(api.disco.entities.items(jid).map((i) => i.getFeature(feature)));
|
|
|
+ return result.map((f) => f instanceof Object).includes(true);
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* Used to determine whether an entity supports a given feature.
|
|
|
*
|
|
|
* @method api.disco.supports
|
|
|
- * @param { string } feature The feature that might be
|
|
|
+ * @param {string} feature The feature that might be
|
|
|
* supported. In the XML stanza, this is the `var`
|
|
|
* attribute of the `<feature>` element. For
|
|
|
* example: `http://jabber.org/protocol/muc`
|
|
|
- * @param { string } jid The JID of the entity
|
|
|
+ * @param {string} jid The JID of the entity
|
|
|
* (and its associated items) which should be queried
|
|
|
- * @returns {promise} A promise which resolves with `true` or `false`.
|
|
|
+ * @returns {Promise<boolean>|boolean} A promise which resolves with `true` or `false`.
|
|
|
* @example
|
|
|
* if (await api.disco.supports(Strophe.NS.MAM, _converse.bare_jid)) {
|
|
|
* // The feature is supported
|
|
@@ -348,23 +354,28 @@ export default {
|
|
|
* // The feature is not supported
|
|
|
* }
|
|
|
*/
|
|
|
- supports (feature, jid) {
|
|
|
- return api.disco.features.has(feature, jid);
|
|
|
+ supports(feature, jid) {
|
|
|
+ try {
|
|
|
+ return api.disco.features.has(feature, jid);
|
|
|
+ } catch (e) {
|
|
|
+ log.error(e);
|
|
|
+ debugger;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
* Refresh the features, fields and identities associated with a
|
|
|
* disco entity by refetching them from the server
|
|
|
* @method api.disco.refresh
|
|
|
- * @param { string } jid The JID of the entity whose features are refreshed.
|
|
|
- * @returns {promise} A promise which resolves once the features have been refreshed
|
|
|
+ * @param {string} jid The JID of the entity whose features are refreshed.
|
|
|
+ * @returns {Promise} A promise which resolves once the features have been refreshed
|
|
|
* @example
|
|
|
* await api.disco.refresh('room@conference.example.org');
|
|
|
*/
|
|
|
- async refresh (jid) {
|
|
|
- if (!jid) {
|
|
|
- throw new TypeError('api.disco.refresh: You need to provide an entity JID');
|
|
|
- }
|
|
|
+ async refresh(jid) {
|
|
|
+ if (!jid) throw new TypeError('api.disco.refresh: You need to provide an entity JID');
|
|
|
+
|
|
|
await api.waitUntil('discoInitialized');
|
|
|
let entity = await api.disco.entities.get(jid);
|
|
|
if (entity) {
|
|
@@ -372,12 +383,12 @@ export default {
|
|
|
entity.fields.reset();
|
|
|
entity.identities.reset();
|
|
|
if (!entity.waitUntilFeaturesDiscovered.isPending) {
|
|
|
- entity.waitUntilFeaturesDiscovered = getOpenPromise()
|
|
|
+ entity.waitUntilFeaturesDiscovered = getOpenPromise();
|
|
|
}
|
|
|
entity.queryInfo();
|
|
|
} else {
|
|
|
// Create it if it doesn't exist
|
|
|
- entity = await api.disco.entities.create({ jid }, {'ignore_cache': true});
|
|
|
+ entity = await api.disco.entities.create({ jid }, { 'ignore_cache': true });
|
|
|
}
|
|
|
return entity.waitUntilFeaturesDiscovered;
|
|
|
},
|
|
@@ -391,10 +402,9 @@ export default {
|
|
|
* @example
|
|
|
* const features = await api.disco.getFeatures('room@conference.example.org');
|
|
|
*/
|
|
|
- async getFeatures (jid) {
|
|
|
- if (!jid) {
|
|
|
- throw new TypeError('api.disco.getFeatures: You need to provide an entity JID');
|
|
|
- }
|
|
|
+ async getFeatures(jid) {
|
|
|
+ if (!jid) throw new TypeError('api.disco.getFeatures: You need to provide an entity JID');
|
|
|
+
|
|
|
await api.waitUntil('discoInitialized');
|
|
|
let entity = await api.disco.entities.get(jid, true);
|
|
|
entity = await entity.waitUntilFeaturesDiscovered;
|
|
@@ -412,10 +422,9 @@ export default {
|
|
|
* @example
|
|
|
* const fields = await api.disco.getFields('room@conference.example.org');
|
|
|
*/
|
|
|
- async getFields (jid) {
|
|
|
- if (!jid) {
|
|
|
- throw new TypeError('api.disco.getFields: You need to provide an entity JID');
|
|
|
- }
|
|
|
+ async getFields(jid) {
|
|
|
+ if (!jid) throw new TypeError('api.disco.getFields: You need to provide an entity JID');
|
|
|
+
|
|
|
await api.waitUntil('discoInitialized');
|
|
|
let entity = await api.disco.entities.get(jid, true);
|
|
|
entity = await entity.waitUntilFeaturesDiscovered;
|
|
@@ -453,16 +462,17 @@ export default {
|
|
|
* }
|
|
|
* ).catch(e => log.error(e));
|
|
|
*/
|
|
|
- async getIdentity (category, type, jid) {
|
|
|
+ async getIdentity(category, type, jid) {
|
|
|
const e = await api.disco.entities.get(jid, true);
|
|
|
if (e === undefined && !api.connection.connected()) {
|
|
|
// Happens during tests when disco lookups happen asynchronously after teardown.
|
|
|
- const msg = `Tried to look up category ${category} for ${jid} `+
|
|
|
+ const msg =
|
|
|
+ `Tried to look up category ${category} for ${jid} ` +
|
|
|
`but _converse.disco_entities has been torn down`;
|
|
|
log.warn(msg);
|
|
|
return;
|
|
|
}
|
|
|
return e.getIdentity(category, type);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|