_converse.api.archive.query
now returns a Promise
instead of accepting a callback functions.
This commit is contained in:
parent
8bb852b139
commit
15b2273631
@ -17,6 +17,7 @@
|
||||
|
||||
- **Breaking changes**:
|
||||
- Rename `muc_disable_moderator_commands` to [muc_disable_slash_commands](https://conversejs.org/docs/html/configuration.html#muc-disable-slash-commands).
|
||||
- `_converse.api.archive.query` now returns a Promise instead of accepting a callback functions.
|
||||
|
||||
### API changes
|
||||
|
||||
|
402
dist/converse.js
vendored
402
dist/converse.js
vendored
@ -52121,26 +52121,27 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||
}
|
||||
|
||||
this.addSpinner();
|
||||
let result;
|
||||
|
||||
_converse.api.archive.query(Object.assign({
|
||||
'groupchat': is_groupchat,
|
||||
'before': '',
|
||||
// Page backwards from the most recent message
|
||||
'max': _converse.archived_messages_page_size,
|
||||
'with': this.model.get('jid')
|
||||
}, options), messages => {
|
||||
// Success
|
||||
this.clearSpinner();
|
||||
|
||||
_.each(messages, message_handler);
|
||||
}, e => {
|
||||
// Error
|
||||
this.clearSpinner();
|
||||
|
||||
try {
|
||||
result = await _converse.api.archive.query(Object.assign({
|
||||
'groupchat': is_groupchat,
|
||||
'before': '',
|
||||
// Page backwards from the most recent message
|
||||
'max': _converse.archived_messages_page_size,
|
||||
'with': this.model.get('jid')
|
||||
}, options));
|
||||
} catch (e) {
|
||||
_converse.log("Error or timeout while trying to fetch " + "archived messages", Strophe.LogLevel.ERROR);
|
||||
|
||||
_converse.log(e, Strophe.LogLevel.ERROR);
|
||||
});
|
||||
} finally {
|
||||
this.clearSpinner();
|
||||
}
|
||||
|
||||
if (result.messages) {
|
||||
result.messages.forEach(message_handler);
|
||||
}
|
||||
},
|
||||
|
||||
onScroll(ev) {
|
||||
@ -66323,121 +66324,6 @@ const u = _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].env.utils;
|
||||
const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count']; // XEP-0313 Message Archive Management
|
||||
|
||||
const MAM_ATTRIBUTES = ['with', 'start', 'end'];
|
||||
|
||||
function queryForArchivedMessages(_converse, options, callback, errback) {
|
||||
/* Internal function, called by the "archive.query" API method.
|
||||
*/
|
||||
let date;
|
||||
|
||||
if (_.isFunction(options)) {
|
||||
callback = options;
|
||||
errback = callback;
|
||||
options = null;
|
||||
}
|
||||
|
||||
const queryid = _converse.connection.getUniqueId();
|
||||
|
||||
const attrs = {
|
||||
'type': 'set'
|
||||
};
|
||||
|
||||
if (options && options.groupchat) {
|
||||
if (!options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
throw new Error('You need to specify a "with" value containing ' + 'the chat room JID, when querying groupchat messages.');
|
||||
}
|
||||
|
||||
attrs.to = options['with']; // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
const stanza = $iq(attrs).c('query', {
|
||||
'xmlns': Strophe.NS.MAM,
|
||||
'queryid': queryid
|
||||
});
|
||||
|
||||
if (options) {
|
||||
stanza.c('x', {
|
||||
'xmlns': Strophe.NS.XFORM,
|
||||
'type': 'submit'
|
||||
}).c('field', {
|
||||
'var': 'FORM_TYPE',
|
||||
'type': 'hidden'
|
||||
}).c('value').t(Strophe.NS.MAM).up().up();
|
||||
|
||||
if (options['with'] && !options.groupchat) {
|
||||
// eslint-disable-line dot-notation
|
||||
stanza.c('field', {
|
||||
'var': 'with'
|
||||
}).c('value').t(options['with']).up().up(); // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
_.each(['start', 'end'], function (t) {
|
||||
if (options[t]) {
|
||||
date = moment(options[t]);
|
||||
|
||||
if (date.isValid()) {
|
||||
stanza.c('field', {
|
||||
'var': t
|
||||
}).c('value').t(date.format()).up().up();
|
||||
} else {
|
||||
throw new TypeError(`archive.query: invalid date provided for: ${t}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
stanza.up();
|
||||
|
||||
if (options instanceof Strophe.RSM) {
|
||||
stanza.cnode(options.toXML());
|
||||
} else if (_.intersection(RSM_ATTRIBUTES, Object.keys(options)).length) {
|
||||
stanza.cnode(new Strophe.RSM(options).toXML());
|
||||
}
|
||||
}
|
||||
|
||||
const messages = [];
|
||||
|
||||
const message_handler = _converse.connection.addHandler(message => {
|
||||
if (options.groupchat && message.getAttribute('from') !== options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
return true;
|
||||
}
|
||||
|
||||
const result = message.querySelector('result');
|
||||
|
||||
if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, Strophe.NS.MAM);
|
||||
|
||||
_converse.api.sendIQ(stanza, _converse.message_archiving_timeout).then(iq => {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
if (_.isFunction(callback)) {
|
||||
const set = iq.querySelector('set');
|
||||
let rsm;
|
||||
|
||||
if (!_.isUndefined(set)) {
|
||||
rsm = new Strophe.RSM({
|
||||
xml: set
|
||||
});
|
||||
Object.assign(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
||||
}
|
||||
|
||||
callback(messages, rsm);
|
||||
}
|
||||
}).catch(e => {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
if (_.isFunction(errback)) {
|
||||
errback.apply(this, arguments);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
_converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam', {
|
||||
dependencies: ['converse-muc'],
|
||||
overrides: {
|
||||
@ -66613,15 +66499,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* * `before`
|
||||
* * `index`
|
||||
* * `count`
|
||||
* @param {Function} callback A function to call whenever
|
||||
* we receive query-relevant stanza.
|
||||
* When the callback is called, a Strophe.RSM object is
|
||||
* returned on which "next" or "previous" can be called
|
||||
* before passing it in again to this method, to
|
||||
* get the next or previous page in the result set.
|
||||
* @param {Function} errback A function to call when an
|
||||
* error stanza is received, for example when it
|
||||
* doesn't support message archiving.
|
||||
* @throws {Error} An error is thrown if the XMPP server responds with an error.
|
||||
* @returns {Promise<Object>} A promise which resolves to an object which
|
||||
* will have keys `messages` and `rsm` which contains a Strophe.RSM object
|
||||
* on which "next" or "previous" can be called before passing it in again
|
||||
* to this method, to get the next or previous page in the result set.
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages
|
||||
@ -66629,41 +66511,17 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* //
|
||||
* // The simplest query that can be made is to simply not pass in any parameters.
|
||||
* // Such a query will return all archived messages for the current user.
|
||||
* //
|
||||
* // Generally, you'll however always want to pass in a callback method, to receive
|
||||
* // the returned messages.
|
||||
*
|
||||
* this._converse.api.archive.query(
|
||||
* (messages) => {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* },
|
||||
* (iq) => {
|
||||
* // The query was not successful, perhaps inform the user?
|
||||
* // The IQ stanza returned by the XMPP server is passed in, so that you
|
||||
* // may inspect it and determine what the problem was.
|
||||
* }
|
||||
* )
|
||||
* @example
|
||||
* // Waiting until server support has been determined
|
||||
* // ================================================
|
||||
* //
|
||||
* // The query method will only work if Converse has been able to determine that
|
||||
* // the server supports MAM queries, otherwise the following error will be raised:
|
||||
* //
|
||||
* // "This server does not support XEP-0313, Message Archive Management"
|
||||
* //
|
||||
* // The very first time Converse loads in a browser tab, if you call the query
|
||||
* // API too quickly, the above error might appear because service discovery has not
|
||||
* // yet been completed.
|
||||
* //
|
||||
* // To work solve this problem, you can first listen for the `serviceDiscovered` event,
|
||||
* // through which you can be informed once support for MAM has been determined.
|
||||
*
|
||||
* _converse.api.listen.on('serviceDiscovered', function (feature) {
|
||||
* if (feature.get('var') === converse.env.Strophe.NS.MAM) {
|
||||
* _converse.api.archive.query()
|
||||
* }
|
||||
* });
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query();
|
||||
* } catch (e) {
|
||||
* // The query was not successful, perhaps inform the user?
|
||||
* // The IQ stanza returned by the XMPP server is passed in, so that you
|
||||
* // may inspect it and determine what the problem was.
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages for a particular contact or room
|
||||
@ -66674,10 +66532,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // room under the `with` key.
|
||||
*
|
||||
* // For a particular user
|
||||
* this._converse.api.archive.query({'with': 'john@doe.net'}, callback, errback);)
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net'});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* // For a particular room
|
||||
* this._converse.api.archive.query({'with': 'discuss@conference.doglovers.net'}, callback, errback);)
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'discuss@conference.doglovers.net'});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages before or after a certain date
|
||||
@ -66692,7 +66560,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* 'start': '2010-06-07T00:00:00Z',
|
||||
* 'end': '2010-07-07T13:23:54Z'
|
||||
* };
|
||||
* this._converse.api.archive.query(options, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(options);
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Limiting the amount of messages returned
|
||||
@ -66702,7 +66575,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // By default, the messages are returned from oldest to newest.
|
||||
*
|
||||
* // Return maximum 10 archived messages
|
||||
* this._converse.api.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net', 'max':10});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Paging forwards through a set of archived messages
|
||||
@ -66712,8 +66590,8 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // repeatedly make a further query to fetch the next batch of messages.
|
||||
* //
|
||||
* // To simplify this usecase for you, the callback method receives not only an array
|
||||
* // with the returned archived messages, but also a special RSM (*Result Set
|
||||
* // Management*) object which contains the query parameters you passed in, as well
|
||||
* // with the returned archived messages, but also a special Strophe.RSM (*Result Set Management*)
|
||||
* // object which contains the query parameters you passed in, as well
|
||||
* // as two utility methods `next`, and `previous`.
|
||||
* //
|
||||
* // When you call one of these utility methods on the returned RSM object, and then
|
||||
@ -66721,14 +66599,24 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // archived messages. Please note, when calling these methods, pass in an integer
|
||||
* // to limit your results.
|
||||
*
|
||||
* const callback = function (messages, rsm) {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* // ...
|
||||
* // You can now use the returned "rsm" object, to fetch the next batch of messages:
|
||||
* _converse.api.archive.query(rsm.next(10), callback, errback))
|
||||
*
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net', 'max':10});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* while (result.rsm) {
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(rsm.next(10));
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
* }
|
||||
* _converse.api.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
|
||||
*
|
||||
* @example
|
||||
* // Paging backwards through a set of archived messages
|
||||
@ -66739,22 +66627,142 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // `before` parameter. If you simply want to page backwards from the most recent
|
||||
* // message, pass in the `before` parameter with an empty string value `''`.
|
||||
*
|
||||
* _converse.api.archive.query({'before': '', 'max':5}, function (message, rsm) {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* // ...
|
||||
* // You can now use the returned "rsm" object, to fetch the previous batch of messages:
|
||||
* rsm.previous(5); // Call previous method, to update the object's parameters,
|
||||
* // passing in a limit value of 5.
|
||||
* // Now we query again, to get the previous batch.
|
||||
* _converse.api.archive.query(rsm, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'before': '', 'max':5});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* // Now we query again, to get the previous batch.
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(rsm.previous(5););
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
*/
|
||||
'query': function query(options, callback, errback) {
|
||||
'query': async function query(options) {
|
||||
if (!_converse.api.connection.connected()) {
|
||||
throw new Error('Can\'t call `api.archive.query` before having established an XMPP session');
|
||||
}
|
||||
|
||||
return queryForArchivedMessages(_converse, options, callback, errback);
|
||||
const attrs = {
|
||||
'type': 'set'
|
||||
};
|
||||
|
||||
if (options && options.groupchat) {
|
||||
if (!options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
throw new Error('You need to specify a "with" value containing ' + 'the chat room JID, when querying groupchat messages.');
|
||||
}
|
||||
|
||||
attrs.to = options['with']; // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
const jid = attrs.to || _converse.bare_jid;
|
||||
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, jid);
|
||||
|
||||
if (!supported.length) {
|
||||
_converse.log(`Did not fetch MAM archive for ${jid} because it doesn't support ${Strophe.NS.MAM}`);
|
||||
|
||||
return {
|
||||
'messages': []
|
||||
};
|
||||
}
|
||||
|
||||
const queryid = _converse.connection.getUniqueId();
|
||||
|
||||
const stanza = $iq(attrs).c('query', {
|
||||
'xmlns': Strophe.NS.MAM,
|
||||
'queryid': queryid
|
||||
});
|
||||
|
||||
if (options) {
|
||||
stanza.c('x', {
|
||||
'xmlns': Strophe.NS.XFORM,
|
||||
'type': 'submit'
|
||||
}).c('field', {
|
||||
'var': 'FORM_TYPE',
|
||||
'type': 'hidden'
|
||||
}).c('value').t(Strophe.NS.MAM).up().up();
|
||||
|
||||
if (options['with'] && !options.groupchat) {
|
||||
// eslint-disable-line dot-notation
|
||||
stanza.c('field', {
|
||||
'var': 'with'
|
||||
}).c('value').t(options['with']).up().up(); // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
['start', 'end'].forEach(t => {
|
||||
if (options[t]) {
|
||||
const date = moment(options[t]);
|
||||
|
||||
if (date.isValid()) {
|
||||
stanza.c('field', {
|
||||
'var': t
|
||||
}).c('value').t(date.format()).up().up();
|
||||
} else {
|
||||
throw new TypeError(`archive.query: invalid date provided for: ${t}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
stanza.up();
|
||||
|
||||
if (options instanceof Strophe.RSM) {
|
||||
stanza.cnode(options.toXML());
|
||||
} else if (_.intersection(RSM_ATTRIBUTES, Object.keys(options)).length) {
|
||||
stanza.cnode(new Strophe.RSM(options).toXML());
|
||||
}
|
||||
}
|
||||
|
||||
const messages = [];
|
||||
|
||||
const message_handler = _converse.connection.addHandler(message => {
|
||||
if (options.groupchat && message.getAttribute('from') !== options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
return true;
|
||||
}
|
||||
|
||||
const result = message.querySelector('result');
|
||||
|
||||
if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, Strophe.NS.MAM);
|
||||
|
||||
let iq;
|
||||
|
||||
try {
|
||||
iq = await _converse.api.sendIQ(stanza, _converse.message_archiving_timeout);
|
||||
} catch (e) {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
const set = iq.querySelector('set');
|
||||
let rsm;
|
||||
|
||||
if (!_.isNull(set)) {
|
||||
rsm = new Strophe.RSM({
|
||||
'xml': set
|
||||
});
|
||||
Object.assign(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
||||
}
|
||||
|
||||
return {
|
||||
messages,
|
||||
rsm
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
124
spec/mam.js
124
spec/mam.js
@ -162,18 +162,17 @@
|
||||
it("can be used to query for all archived messages",
|
||||
mock.initConverse(
|
||||
null, ['discoInitialized'], {},
|
||||
function (done, _converse) {
|
||||
async function (done, _converse) {
|
||||
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
sent_stanza = iq;
|
||||
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||
});
|
||||
if (!_converse.disco_entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
_converse.api.archive.query();
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client"><query queryid="${queryid}" xmlns="urn:xmpp:mam:2"/></iq>`);
|
||||
@ -185,10 +184,7 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
@ -196,6 +192,7 @@
|
||||
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||
});
|
||||
_converse.api.archive.query({'with':'juliet@capulet.lit'});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client">`+
|
||||
@ -218,22 +215,16 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
|
||||
await test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'nicky', [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
sent_stanza = iq;
|
||||
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||
});
|
||||
const callback = jasmine.createSpy('callback');
|
||||
|
||||
_converse.api.archive.query({'with': 'coven@chat.shakespeare.lit', 'groupchat': true}, callback);
|
||||
_converse.api.archive.query({'with': 'coven@chat.shakespeare.lit', 'groupchat': true});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" to="coven@chat.shakespeare.lit" type="set" xmlns="jabber:client">`+
|
||||
`<query queryid="${queryid}" xmlns="urn:xmpp:mam:2">`+
|
||||
@ -252,19 +243,15 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'nicky', [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
sent_stanza = iq;
|
||||
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||
});
|
||||
const callback = jasmine.createSpy('callback');
|
||||
|
||||
_converse.api.archive.query({'with': 'coven@chat.shakespear.lit', 'groupchat': true, 'max':'10'}, callback);
|
||||
const promise = _converse.api.archive.query({'with': 'coven@chat.shakespear.lit', 'groupchat': true, 'max':'10'});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
|
||||
/* <message id='iasd207' from='coven@chat.shakespeare.lit' to='hag66@shakespeare.lit/pda'>
|
||||
@ -318,10 +305,8 @@
|
||||
.c('count').t('16');
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
|
||||
await test_utils.waitUntil(() => callback.calls.count());
|
||||
expect(callback).toHaveBeenCalled();
|
||||
const args = callback.calls.argsFor(0);
|
||||
expect(args[0].length).toBe(0);
|
||||
const result = await promise;
|
||||
expect(result.messages.length).toBe(0);
|
||||
done();
|
||||
}));
|
||||
|
||||
@ -330,23 +315,20 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
sent_stanza = iq;
|
||||
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||
});
|
||||
const entities = await _converse.api.disco.entities.get();
|
||||
if (!entities.get(_converse.domain).features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
const start = '2010-06-07T00:00:00Z';
|
||||
const end = '2010-07-07T13:23:54Z';
|
||||
_converse.api.archive.query({
|
||||
'start': start,
|
||||
'end': end
|
||||
|
||||
});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client">`+
|
||||
@ -373,13 +355,12 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
try {
|
||||
await _converse.api.archive.query({'start': 'not a real date'});
|
||||
} catch (e) {
|
||||
expect(() => {throw e}).toThrow(new TypeError('archive.query: invalid date provided for: start'));
|
||||
}
|
||||
expect(_.partial(_converse.api.archive.query, {'start': 'not a real date'})).toThrow(
|
||||
new TypeError('archive.query: invalid date provided for: start')
|
||||
);
|
||||
done();
|
||||
}));
|
||||
|
||||
@ -388,10 +369,7 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
@ -403,6 +381,7 @@
|
||||
}
|
||||
const start = '2010-06-07T00:00:00Z';
|
||||
_converse.api.archive.query({'start': start});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client">`+
|
||||
@ -426,10 +405,7 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
@ -438,6 +414,7 @@
|
||||
});
|
||||
const start = '2010-06-07T00:00:00Z';
|
||||
_converse.api.archive.query({'start': start, 'max':10});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client">`+
|
||||
@ -464,10 +441,7 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
@ -480,6 +454,7 @@
|
||||
'after': '09af3-cc343-b409f',
|
||||
'max':10
|
||||
});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client">`+
|
||||
@ -506,10 +481,7 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
@ -517,6 +489,7 @@
|
||||
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||
});
|
||||
_converse.api.archive.query({'before': '', 'max':10});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client">`+
|
||||
@ -540,10 +513,7 @@
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
@ -558,7 +528,7 @@
|
||||
rsm['with'] = 'romeo@montague.lit'; // eslint-disable-line dot-notation
|
||||
rsm.start = '2010-06-07T00:00:00Z';
|
||||
_converse.api.archive.query(rsm);
|
||||
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
expect(sent_stanza.toString()).toBe(
|
||||
`<iq id="${IQ_id}" type="set" xmlns="jabber:client">`+
|
||||
@ -582,24 +552,20 @@
|
||||
done();
|
||||
}));
|
||||
|
||||
it("accepts a callback function, which it passes the messages and a Strophe.RSM object",
|
||||
it("returns an object which includes the messages and a Strophe.RSM object",
|
||||
mock.initConverse(
|
||||
null, [], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
const entity = await _converse.api.disco.entities.get(_converse.domain);
|
||||
if (!entity.features.findWhere({'var': Strophe.NS.MAM})) {
|
||||
_converse.disco_entities.get(_converse.domain).features.create({'var': Strophe.NS.MAM});
|
||||
}
|
||||
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||
let sent_stanza, IQ_id;
|
||||
const sendIQ = _converse.connection.sendIQ;
|
||||
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||
sent_stanza = iq;
|
||||
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||
});
|
||||
const callback = jasmine.createSpy('callback');
|
||||
|
||||
_converse.api.archive.query({'with': 'romeo@capulet.lit', 'max':'10'}, callback);
|
||||
const promise = _converse.api.archive.query({'with': 'romeo@capulet.lit', 'max':'10'});
|
||||
await test_utils.waitUntil(() => sent_stanza);
|
||||
const queryid = sent_stanza.nodeTree.querySelector('query').getAttribute('queryid');
|
||||
|
||||
/* <message id='aeb213' to='juliet@capulet.lit/chamber'>
|
||||
@ -659,17 +625,15 @@
|
||||
.c('count').t('16');
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
|
||||
await test_utils.waitUntil(() => callback.calls.count());
|
||||
expect(callback).toHaveBeenCalled();
|
||||
const args = callback.calls.argsFor(0);
|
||||
expect(args[0].length).toBe(2);
|
||||
expect(args[0][0].outerHTML).toBe(msg1.nodeTree.outerHTML);
|
||||
expect(args[0][1].outerHTML).toBe(msg2.nodeTree.outerHTML);
|
||||
expect(args[1]['with']).toBe('romeo@capulet.lit'); // eslint-disable-line dot-notation
|
||||
expect(args[1].max).toBe('10');
|
||||
expect(args[1].count).toBe('16');
|
||||
expect(args[1].first).toBe('23452-4534-1');
|
||||
expect(args[1].last).toBe('09af3-cc343-b409f');
|
||||
const result = await promise;
|
||||
expect(result.messages.length).toBe(2);
|
||||
expect(result.messages[0].outerHTML).toBe(msg1.nodeTree.outerHTML);
|
||||
expect(result.messages[1].outerHTML).toBe(msg2.nodeTree.outerHTML);
|
||||
expect(result.rsm['with']).toBe('romeo@capulet.lit'); // eslint-disable-line dot-notation
|
||||
expect(result.rsm.max).toBe('10');
|
||||
expect(result.rsm.count).toBe('16');
|
||||
expect(result.rsm.first).toBe('23452-4534-1');
|
||||
expect(result.rsm.last).toBe('09af3-cc343-b409f');
|
||||
done()
|
||||
}));
|
||||
});
|
||||
|
@ -82,10 +82,10 @@ converse.plugins.add('converse-mam-views', {
|
||||
|
||||
async fetchArchivedMessages (options) {
|
||||
const { _converse } = this.__super__;
|
||||
if (this.disable_mam) { return; }
|
||||
|
||||
if (this.disable_mam) {
|
||||
return;
|
||||
}
|
||||
const is_groupchat = this.model.get('type') === CHATROOMS_TYPE;
|
||||
|
||||
let mam_jid, message_handler;
|
||||
if (is_groupchat) {
|
||||
mam_jid = this.model.get('jid');
|
||||
@ -94,32 +94,31 @@ converse.plugins.add('converse-mam-views', {
|
||||
mam_jid = _converse.bare_jid;
|
||||
message_handler = _converse.chatboxes.onMessage.bind(_converse.chatboxes)
|
||||
}
|
||||
|
||||
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, mam_jid);
|
||||
if (!supported.length) {
|
||||
return;
|
||||
}
|
||||
this.addSpinner();
|
||||
_converse.api.archive.query(
|
||||
Object.assign({
|
||||
'groupchat': is_groupchat,
|
||||
'before': '', // Page backwards from the most recent message
|
||||
'max': _converse.archived_messages_page_size,
|
||||
'with': this.model.get('jid'),
|
||||
}, options),
|
||||
|
||||
messages => { // Success
|
||||
this.clearSpinner();
|
||||
_.each(messages, message_handler);
|
||||
},
|
||||
e => { // Error
|
||||
this.clearSpinner();
|
||||
_converse.log(
|
||||
"Error or timeout while trying to fetch "+
|
||||
"archived messages", Strophe.LogLevel.ERROR);
|
||||
_converse.log(e, Strophe.LogLevel.ERROR);
|
||||
}
|
||||
);
|
||||
let result;
|
||||
try {
|
||||
result = await _converse.api.archive.query(
|
||||
Object.assign({
|
||||
'groupchat': is_groupchat,
|
||||
'before': '', // Page backwards from the most recent message
|
||||
'max': _converse.archived_messages_page_size,
|
||||
'with': this.model.get('jid'),
|
||||
}, options));
|
||||
} catch (e) {
|
||||
_converse.log(
|
||||
"Error or timeout while trying to fetch "+
|
||||
"archived messages", Strophe.LogLevel.ERROR);
|
||||
_converse.log(e, Strophe.LogLevel.ERROR);
|
||||
} finally {
|
||||
this.clearSpinner();
|
||||
}
|
||||
if (result.messages) {
|
||||
result.messages.forEach(message_handler);
|
||||
}
|
||||
},
|
||||
|
||||
onScroll (ev) {
|
||||
|
@ -21,88 +21,6 @@ const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'cou
|
||||
const MAM_ATTRIBUTES = ['with', 'start', 'end'];
|
||||
|
||||
|
||||
function queryForArchivedMessages (_converse, options, callback, errback) {
|
||||
/* Internal function, called by the "archive.query" API method.
|
||||
*/
|
||||
let date;
|
||||
if (_.isFunction(options)) {
|
||||
callback = options;
|
||||
errback = callback;
|
||||
options = null;
|
||||
}
|
||||
const queryid = _converse.connection.getUniqueId();
|
||||
const attrs = {'type':'set'};
|
||||
if (options && options.groupchat) {
|
||||
if (!options['with']) { // eslint-disable-line dot-notation
|
||||
throw new Error(
|
||||
'You need to specify a "with" value containing '+
|
||||
'the chat room JID, when querying groupchat messages.');
|
||||
}
|
||||
attrs.to = options['with']; // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
const stanza = $iq(attrs).c('query', {'xmlns':Strophe.NS.MAM, 'queryid':queryid});
|
||||
if (options) {
|
||||
stanza.c('x', {'xmlns':Strophe.NS.XFORM, 'type': 'submit'})
|
||||
.c('field', {'var':'FORM_TYPE', 'type': 'hidden'})
|
||||
.c('value').t(Strophe.NS.MAM).up().up();
|
||||
|
||||
if (options['with'] && !options.groupchat) { // eslint-disable-line dot-notation
|
||||
stanza.c('field', {'var':'with'}).c('value')
|
||||
.t(options['with']).up().up(); // eslint-disable-line dot-notation
|
||||
}
|
||||
_.each(['start', 'end'], function (t) {
|
||||
if (options[t]) {
|
||||
date = moment(options[t]);
|
||||
if (date.isValid()) {
|
||||
stanza.c('field', {'var':t}).c('value').t(date.format()).up().up();
|
||||
} else {
|
||||
throw new TypeError(`archive.query: invalid date provided for: ${t}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
stanza.up();
|
||||
if (options instanceof Strophe.RSM) {
|
||||
stanza.cnode(options.toXML());
|
||||
} else if (_.intersection(RSM_ATTRIBUTES, Object.keys(options)).length) {
|
||||
stanza.cnode(new Strophe.RSM(options).toXML());
|
||||
}
|
||||
}
|
||||
|
||||
const messages = [];
|
||||
const message_handler = _converse.connection.addHandler((message) => {
|
||||
if (options.groupchat && message.getAttribute('from') !== options['with']) { // eslint-disable-line dot-notation
|
||||
return true;
|
||||
}
|
||||
const result = message.querySelector('result');
|
||||
if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
||||
messages.push(message);
|
||||
}
|
||||
return true;
|
||||
}, Strophe.NS.MAM);
|
||||
|
||||
_converse.api.sendIQ(stanza, _converse.message_archiving_timeout)
|
||||
.then(iq => {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
if (_.isFunction(callback)) {
|
||||
const set = iq.querySelector('set');
|
||||
let rsm;
|
||||
if (!_.isUndefined(set)) {
|
||||
rsm = new Strophe.RSM({xml: set});
|
||||
Object.assign(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
||||
}
|
||||
callback(messages, rsm);
|
||||
}
|
||||
}).catch(e => {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
if (_.isFunction(errback)) {
|
||||
errback.apply(this, arguments);
|
||||
}
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
converse.plugins.add('converse-mam', {
|
||||
|
||||
dependencies: ['converse-muc'],
|
||||
@ -260,15 +178,11 @@ converse.plugins.add('converse-mam', {
|
||||
* * `before`
|
||||
* * `index`
|
||||
* * `count`
|
||||
* @param {Function} callback A function to call whenever
|
||||
* we receive query-relevant stanza.
|
||||
* When the callback is called, a Strophe.RSM object is
|
||||
* returned on which "next" or "previous" can be called
|
||||
* before passing it in again to this method, to
|
||||
* get the next or previous page in the result set.
|
||||
* @param {Function} errback A function to call when an
|
||||
* error stanza is received, for example when it
|
||||
* doesn't support message archiving.
|
||||
* @throws {Error} An error is thrown if the XMPP server responds with an error.
|
||||
* @returns {Promise<Object>} A promise which resolves to an object which
|
||||
* will have keys `messages` and `rsm` which contains a Strophe.RSM object
|
||||
* on which "next" or "previous" can be called before passing it in again
|
||||
* to this method, to get the next or previous page in the result set.
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages
|
||||
@ -276,41 +190,17 @@ converse.plugins.add('converse-mam', {
|
||||
* //
|
||||
* // The simplest query that can be made is to simply not pass in any parameters.
|
||||
* // Such a query will return all archived messages for the current user.
|
||||
* //
|
||||
* // Generally, you'll however always want to pass in a callback method, to receive
|
||||
* // the returned messages.
|
||||
*
|
||||
* this._converse.api.archive.query(
|
||||
* (messages) => {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* },
|
||||
* (iq) => {
|
||||
* // The query was not successful, perhaps inform the user?
|
||||
* // The IQ stanza returned by the XMPP server is passed in, so that you
|
||||
* // may inspect it and determine what the problem was.
|
||||
* }
|
||||
* )
|
||||
* @example
|
||||
* // Waiting until server support has been determined
|
||||
* // ================================================
|
||||
* //
|
||||
* // The query method will only work if Converse has been able to determine that
|
||||
* // the server supports MAM queries, otherwise the following error will be raised:
|
||||
* //
|
||||
* // "This server does not support XEP-0313, Message Archive Management"
|
||||
* //
|
||||
* // The very first time Converse loads in a browser tab, if you call the query
|
||||
* // API too quickly, the above error might appear because service discovery has not
|
||||
* // yet been completed.
|
||||
* //
|
||||
* // To work solve this problem, you can first listen for the `serviceDiscovered` event,
|
||||
* // through which you can be informed once support for MAM has been determined.
|
||||
*
|
||||
* _converse.api.listen.on('serviceDiscovered', function (feature) {
|
||||
* if (feature.get('var') === converse.env.Strophe.NS.MAM) {
|
||||
* _converse.api.archive.query()
|
||||
* }
|
||||
* });
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query();
|
||||
* } catch (e) {
|
||||
* // The query was not successful, perhaps inform the user?
|
||||
* // The IQ stanza returned by the XMPP server is passed in, so that you
|
||||
* // may inspect it and determine what the problem was.
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages for a particular contact or room
|
||||
@ -321,10 +211,20 @@ converse.plugins.add('converse-mam', {
|
||||
* // room under the `with` key.
|
||||
*
|
||||
* // For a particular user
|
||||
* this._converse.api.archive.query({'with': 'john@doe.net'}, callback, errback);)
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net'});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* // For a particular room
|
||||
* this._converse.api.archive.query({'with': 'discuss@conference.doglovers.net'}, callback, errback);)
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'discuss@conference.doglovers.net'});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages before or after a certain date
|
||||
@ -339,7 +239,12 @@ converse.plugins.add('converse-mam', {
|
||||
* 'start': '2010-06-07T00:00:00Z',
|
||||
* 'end': '2010-07-07T13:23:54Z'
|
||||
* };
|
||||
* this._converse.api.archive.query(options, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(options);
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Limiting the amount of messages returned
|
||||
@ -349,7 +254,12 @@ converse.plugins.add('converse-mam', {
|
||||
* // By default, the messages are returned from oldest to newest.
|
||||
*
|
||||
* // Return maximum 10 archived messages
|
||||
* this._converse.api.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net', 'max':10});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Paging forwards through a set of archived messages
|
||||
@ -359,8 +269,8 @@ converse.plugins.add('converse-mam', {
|
||||
* // repeatedly make a further query to fetch the next batch of messages.
|
||||
* //
|
||||
* // To simplify this usecase for you, the callback method receives not only an array
|
||||
* // with the returned archived messages, but also a special RSM (*Result Set
|
||||
* // Management*) object which contains the query parameters you passed in, as well
|
||||
* // with the returned archived messages, but also a special Strophe.RSM (*Result Set Management*)
|
||||
* // object which contains the query parameters you passed in, as well
|
||||
* // as two utility methods `next`, and `previous`.
|
||||
* //
|
||||
* // When you call one of these utility methods on the returned RSM object, and then
|
||||
@ -368,14 +278,24 @@ converse.plugins.add('converse-mam', {
|
||||
* // archived messages. Please note, when calling these methods, pass in an integer
|
||||
* // to limit your results.
|
||||
*
|
||||
* const callback = function (messages, rsm) {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* // ...
|
||||
* // You can now use the returned "rsm" object, to fetch the next batch of messages:
|
||||
* _converse.api.archive.query(rsm.next(10), callback, errback))
|
||||
*
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net', 'max':10});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* while (result.rsm) {
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(rsm.next(10));
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
* }
|
||||
* _converse.api.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
|
||||
*
|
||||
* @example
|
||||
* // Paging backwards through a set of archived messages
|
||||
@ -386,21 +306,107 @@ converse.plugins.add('converse-mam', {
|
||||
* // `before` parameter. If you simply want to page backwards from the most recent
|
||||
* // message, pass in the `before` parameter with an empty string value `''`.
|
||||
*
|
||||
* _converse.api.archive.query({'before': '', 'max':5}, function (message, rsm) {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* // ...
|
||||
* // You can now use the returned "rsm" object, to fetch the previous batch of messages:
|
||||
* rsm.previous(5); // Call previous method, to update the object's parameters,
|
||||
* // passing in a limit value of 5.
|
||||
* // Now we query again, to get the previous batch.
|
||||
* _converse.api.archive.query(rsm, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'before': '', 'max':5});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* // Now we query again, to get the previous batch.
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(rsm.previous(5););
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
*/
|
||||
'query': function (options, callback, errback) {
|
||||
'query': async function (options) {
|
||||
if (!_converse.api.connection.connected()) {
|
||||
throw new Error('Can\'t call `api.archive.query` before having established an XMPP session');
|
||||
}
|
||||
return queryForArchivedMessages(_converse, options, callback, errback);
|
||||
const attrs = {'type':'set'};
|
||||
if (options && options.groupchat) {
|
||||
if (!options['with']) { // eslint-disable-line dot-notation
|
||||
throw new Error(
|
||||
'You need to specify a "with" value containing '+
|
||||
'the chat room JID, when querying groupchat messages.');
|
||||
}
|
||||
attrs.to = options['with']; // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
const jid = attrs.to || _converse.bare_jid;
|
||||
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, jid);
|
||||
if (!supported.length) {
|
||||
_converse.log(`Did not fetch MAM archive for ${jid} because it doesn't support ${Strophe.NS.MAM}`);
|
||||
return {
|
||||
'messages': []
|
||||
};
|
||||
}
|
||||
|
||||
const queryid = _converse.connection.getUniqueId();
|
||||
const stanza = $iq(attrs).c('query', {'xmlns':Strophe.NS.MAM, 'queryid':queryid});
|
||||
if (options) {
|
||||
stanza.c('x', {'xmlns':Strophe.NS.XFORM, 'type': 'submit'})
|
||||
.c('field', {'var':'FORM_TYPE', 'type': 'hidden'})
|
||||
.c('value').t(Strophe.NS.MAM).up().up();
|
||||
|
||||
if (options['with'] && !options.groupchat) { // eslint-disable-line dot-notation
|
||||
stanza.c('field', {'var':'with'}).c('value')
|
||||
.t(options['with']).up().up(); // eslint-disable-line dot-notation
|
||||
}
|
||||
['start', 'end'].forEach(t => {
|
||||
if (options[t]) {
|
||||
const date = moment(options[t]);
|
||||
if (date.isValid()) {
|
||||
stanza.c('field', {'var':t}).c('value').t(date.format()).up().up();
|
||||
} else {
|
||||
throw new TypeError(`archive.query: invalid date provided for: ${t}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
stanza.up();
|
||||
if (options instanceof Strophe.RSM) {
|
||||
stanza.cnode(options.toXML());
|
||||
} else if (_.intersection(RSM_ATTRIBUTES, Object.keys(options)).length) {
|
||||
stanza.cnode(new Strophe.RSM(options).toXML());
|
||||
}
|
||||
}
|
||||
|
||||
const messages = [];
|
||||
const message_handler = _converse.connection.addHandler(message => {
|
||||
if (options.groupchat && message.getAttribute('from') !== options['with']) { // eslint-disable-line dot-notation
|
||||
return true;
|
||||
}
|
||||
const result = message.querySelector('result');
|
||||
if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
||||
messages.push(message);
|
||||
}
|
||||
return true;
|
||||
}, Strophe.NS.MAM);
|
||||
|
||||
let iq;
|
||||
try {
|
||||
iq = await _converse.api.sendIQ(stanza, _converse.message_archiving_timeout)
|
||||
} catch (e) {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
throw(e);
|
||||
}
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
const set = iq.querySelector('set');
|
||||
let rsm;
|
||||
if (!_.isNull(set)) {
|
||||
rsm = new Strophe.RSM({'xml': set});
|
||||
Object.assign(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
||||
}
|
||||
return {
|
||||
messages,
|
||||
rsm
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
369
src/headless/dist/converse-headless.js
vendored
369
src/headless/dist/converse-headless.js
vendored
@ -44571,121 +44571,6 @@ const u = _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].env.utils;
|
||||
const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count']; // XEP-0313 Message Archive Management
|
||||
|
||||
const MAM_ATTRIBUTES = ['with', 'start', 'end'];
|
||||
|
||||
function queryForArchivedMessages(_converse, options, callback, errback) {
|
||||
/* Internal function, called by the "archive.query" API method.
|
||||
*/
|
||||
let date;
|
||||
|
||||
if (_.isFunction(options)) {
|
||||
callback = options;
|
||||
errback = callback;
|
||||
options = null;
|
||||
}
|
||||
|
||||
const queryid = _converse.connection.getUniqueId();
|
||||
|
||||
const attrs = {
|
||||
'type': 'set'
|
||||
};
|
||||
|
||||
if (options && options.groupchat) {
|
||||
if (!options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
throw new Error('You need to specify a "with" value containing ' + 'the chat room JID, when querying groupchat messages.');
|
||||
}
|
||||
|
||||
attrs.to = options['with']; // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
const stanza = $iq(attrs).c('query', {
|
||||
'xmlns': Strophe.NS.MAM,
|
||||
'queryid': queryid
|
||||
});
|
||||
|
||||
if (options) {
|
||||
stanza.c('x', {
|
||||
'xmlns': Strophe.NS.XFORM,
|
||||
'type': 'submit'
|
||||
}).c('field', {
|
||||
'var': 'FORM_TYPE',
|
||||
'type': 'hidden'
|
||||
}).c('value').t(Strophe.NS.MAM).up().up();
|
||||
|
||||
if (options['with'] && !options.groupchat) {
|
||||
// eslint-disable-line dot-notation
|
||||
stanza.c('field', {
|
||||
'var': 'with'
|
||||
}).c('value').t(options['with']).up().up(); // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
_.each(['start', 'end'], function (t) {
|
||||
if (options[t]) {
|
||||
date = moment(options[t]);
|
||||
|
||||
if (date.isValid()) {
|
||||
stanza.c('field', {
|
||||
'var': t
|
||||
}).c('value').t(date.format()).up().up();
|
||||
} else {
|
||||
throw new TypeError(`archive.query: invalid date provided for: ${t}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
stanza.up();
|
||||
|
||||
if (options instanceof Strophe.RSM) {
|
||||
stanza.cnode(options.toXML());
|
||||
} else if (_.intersection(RSM_ATTRIBUTES, Object.keys(options)).length) {
|
||||
stanza.cnode(new Strophe.RSM(options).toXML());
|
||||
}
|
||||
}
|
||||
|
||||
const messages = [];
|
||||
|
||||
const message_handler = _converse.connection.addHandler(message => {
|
||||
if (options.groupchat && message.getAttribute('from') !== options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
return true;
|
||||
}
|
||||
|
||||
const result = message.querySelector('result');
|
||||
|
||||
if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, Strophe.NS.MAM);
|
||||
|
||||
_converse.api.sendIQ(stanza, _converse.message_archiving_timeout).then(iq => {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
if (_.isFunction(callback)) {
|
||||
const set = iq.querySelector('set');
|
||||
let rsm;
|
||||
|
||||
if (!_.isUndefined(set)) {
|
||||
rsm = new Strophe.RSM({
|
||||
xml: set
|
||||
});
|
||||
Object.assign(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
||||
}
|
||||
|
||||
callback(messages, rsm);
|
||||
}
|
||||
}).catch(e => {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
if (_.isFunction(errback)) {
|
||||
errback.apply(this, arguments);
|
||||
}
|
||||
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
_converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam', {
|
||||
dependencies: ['converse-muc'],
|
||||
overrides: {
|
||||
@ -44861,15 +44746,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* * `before`
|
||||
* * `index`
|
||||
* * `count`
|
||||
* @param {Function} callback A function to call whenever
|
||||
* we receive query-relevant stanza.
|
||||
* When the callback is called, a Strophe.RSM object is
|
||||
* returned on which "next" or "previous" can be called
|
||||
* before passing it in again to this method, to
|
||||
* get the next or previous page in the result set.
|
||||
* @param {Function} errback A function to call when an
|
||||
* error stanza is received, for example when it
|
||||
* doesn't support message archiving.
|
||||
* @throws {Error} An error is thrown if the XMPP server responds with an error.
|
||||
* @returns {Promise<Object>} A promise which resolves to an object which
|
||||
* will have keys `messages` and `rsm` which contains a Strophe.RSM object
|
||||
* on which "next" or "previous" can be called before passing it in again
|
||||
* to this method, to get the next or previous page in the result set.
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages
|
||||
@ -44877,41 +44758,17 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* //
|
||||
* // The simplest query that can be made is to simply not pass in any parameters.
|
||||
* // Such a query will return all archived messages for the current user.
|
||||
* //
|
||||
* // Generally, you'll however always want to pass in a callback method, to receive
|
||||
* // the returned messages.
|
||||
*
|
||||
* this._converse.api.archive.query(
|
||||
* (messages) => {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* },
|
||||
* (iq) => {
|
||||
* // The query was not successful, perhaps inform the user?
|
||||
* // The IQ stanza returned by the XMPP server is passed in, so that you
|
||||
* // may inspect it and determine what the problem was.
|
||||
* }
|
||||
* )
|
||||
* @example
|
||||
* // Waiting until server support has been determined
|
||||
* // ================================================
|
||||
* //
|
||||
* // The query method will only work if Converse has been able to determine that
|
||||
* // the server supports MAM queries, otherwise the following error will be raised:
|
||||
* //
|
||||
* // "This server does not support XEP-0313, Message Archive Management"
|
||||
* //
|
||||
* // The very first time Converse loads in a browser tab, if you call the query
|
||||
* // API too quickly, the above error might appear because service discovery has not
|
||||
* // yet been completed.
|
||||
* //
|
||||
* // To work solve this problem, you can first listen for the `serviceDiscovered` event,
|
||||
* // through which you can be informed once support for MAM has been determined.
|
||||
*
|
||||
* _converse.api.listen.on('serviceDiscovered', function (feature) {
|
||||
* if (feature.get('var') === converse.env.Strophe.NS.MAM) {
|
||||
* _converse.api.archive.query()
|
||||
* }
|
||||
* });
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query();
|
||||
* } catch (e) {
|
||||
* // The query was not successful, perhaps inform the user?
|
||||
* // The IQ stanza returned by the XMPP server is passed in, so that you
|
||||
* // may inspect it and determine what the problem was.
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages for a particular contact or room
|
||||
@ -44922,10 +44779,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // room under the `with` key.
|
||||
*
|
||||
* // For a particular user
|
||||
* this._converse.api.archive.query({'with': 'john@doe.net'}, callback, errback);)
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net'});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* // For a particular room
|
||||
* this._converse.api.archive.query({'with': 'discuss@conference.doglovers.net'}, callback, errback);)
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'discuss@conference.doglovers.net'});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Requesting all archived messages before or after a certain date
|
||||
@ -44940,7 +44807,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* 'start': '2010-06-07T00:00:00Z',
|
||||
* 'end': '2010-07-07T13:23:54Z'
|
||||
* };
|
||||
* this._converse.api.archive.query(options, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(options);
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Limiting the amount of messages returned
|
||||
@ -44950,7 +44822,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // By default, the messages are returned from oldest to newest.
|
||||
*
|
||||
* // Return maximum 10 archived messages
|
||||
* this._converse.api.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net', 'max':10});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
* // Paging forwards through a set of archived messages
|
||||
@ -44960,8 +44837,8 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // repeatedly make a further query to fetch the next batch of messages.
|
||||
* //
|
||||
* // To simplify this usecase for you, the callback method receives not only an array
|
||||
* // with the returned archived messages, but also a special RSM (*Result Set
|
||||
* // Management*) object which contains the query parameters you passed in, as well
|
||||
* // with the returned archived messages, but also a special Strophe.RSM (*Result Set Management*)
|
||||
* // object which contains the query parameters you passed in, as well
|
||||
* // as two utility methods `next`, and `previous`.
|
||||
* //
|
||||
* // When you call one of these utility methods on the returned RSM object, and then
|
||||
@ -44969,14 +44846,24 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // archived messages. Please note, when calling these methods, pass in an integer
|
||||
* // to limit your results.
|
||||
*
|
||||
* const callback = function (messages, rsm) {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* // ...
|
||||
* // You can now use the returned "rsm" object, to fetch the next batch of messages:
|
||||
* _converse.api.archive.query(rsm.next(10), callback, errback))
|
||||
*
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'with': 'john@doe.net', 'max':10});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* while (result.rsm) {
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(rsm.next(10));
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
* }
|
||||
* _converse.api.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
|
||||
*
|
||||
* @example
|
||||
* // Paging backwards through a set of archived messages
|
||||
@ -44987,22 +44874,142 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
|
||||
* // `before` parameter. If you simply want to page backwards from the most recent
|
||||
* // message, pass in the `before` parameter with an empty string value `''`.
|
||||
*
|
||||
* _converse.api.archive.query({'before': '', 'max':5}, function (message, rsm) {
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* // ...
|
||||
* // You can now use the returned "rsm" object, to fetch the previous batch of messages:
|
||||
* rsm.previous(5); // Call previous method, to update the object's parameters,
|
||||
* // passing in a limit value of 5.
|
||||
* // Now we query again, to get the previous batch.
|
||||
* _converse.api.archive.query(rsm, callback, errback);
|
||||
* let result;
|
||||
* try {
|
||||
* result = await _converse.api.archive.query({'before': '', 'max':5});
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
* // Now we query again, to get the previous batch.
|
||||
* try {
|
||||
* result = await _converse.api.archive.query(rsm.previous(5););
|
||||
* } catch (e) {
|
||||
* // The query was not successful
|
||||
* }
|
||||
* // Do something with the messages, like showing them in your webpage.
|
||||
* result.messages.forEach(m => this.showMessage(m));
|
||||
*
|
||||
*/
|
||||
'query': function query(options, callback, errback) {
|
||||
'query': async function query(options) {
|
||||
if (!_converse.api.connection.connected()) {
|
||||
throw new Error('Can\'t call `api.archive.query` before having established an XMPP session');
|
||||
}
|
||||
|
||||
return queryForArchivedMessages(_converse, options, callback, errback);
|
||||
const attrs = {
|
||||
'type': 'set'
|
||||
};
|
||||
|
||||
if (options && options.groupchat) {
|
||||
if (!options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
throw new Error('You need to specify a "with" value containing ' + 'the chat room JID, when querying groupchat messages.');
|
||||
}
|
||||
|
||||
attrs.to = options['with']; // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
const jid = attrs.to || _converse.bare_jid;
|
||||
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, jid);
|
||||
|
||||
if (!supported.length) {
|
||||
_converse.log(`Did not fetch MAM archive for ${jid} because it doesn't support ${Strophe.NS.MAM}`);
|
||||
|
||||
return {
|
||||
'messages': []
|
||||
};
|
||||
}
|
||||
|
||||
const queryid = _converse.connection.getUniqueId();
|
||||
|
||||
const stanza = $iq(attrs).c('query', {
|
||||
'xmlns': Strophe.NS.MAM,
|
||||
'queryid': queryid
|
||||
});
|
||||
|
||||
if (options) {
|
||||
stanza.c('x', {
|
||||
'xmlns': Strophe.NS.XFORM,
|
||||
'type': 'submit'
|
||||
}).c('field', {
|
||||
'var': 'FORM_TYPE',
|
||||
'type': 'hidden'
|
||||
}).c('value').t(Strophe.NS.MAM).up().up();
|
||||
|
||||
if (options['with'] && !options.groupchat) {
|
||||
// eslint-disable-line dot-notation
|
||||
stanza.c('field', {
|
||||
'var': 'with'
|
||||
}).c('value').t(options['with']).up().up(); // eslint-disable-line dot-notation
|
||||
}
|
||||
|
||||
['start', 'end'].forEach(t => {
|
||||
if (options[t]) {
|
||||
const date = moment(options[t]);
|
||||
|
||||
if (date.isValid()) {
|
||||
stanza.c('field', {
|
||||
'var': t
|
||||
}).c('value').t(date.format()).up().up();
|
||||
} else {
|
||||
throw new TypeError(`archive.query: invalid date provided for: ${t}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
stanza.up();
|
||||
|
||||
if (options instanceof Strophe.RSM) {
|
||||
stanza.cnode(options.toXML());
|
||||
} else if (_.intersection(RSM_ATTRIBUTES, Object.keys(options)).length) {
|
||||
stanza.cnode(new Strophe.RSM(options).toXML());
|
||||
}
|
||||
}
|
||||
|
||||
const messages = [];
|
||||
|
||||
const message_handler = _converse.connection.addHandler(message => {
|
||||
if (options.groupchat && message.getAttribute('from') !== options['with']) {
|
||||
// eslint-disable-line dot-notation
|
||||
return true;
|
||||
}
|
||||
|
||||
const result = message.querySelector('result');
|
||||
|
||||
if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
||||
messages.push(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, Strophe.NS.MAM);
|
||||
|
||||
let iq;
|
||||
|
||||
try {
|
||||
iq = await _converse.api.sendIQ(stanza, _converse.message_archiving_timeout);
|
||||
} catch (e) {
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
_converse.connection.deleteHandler(message_handler);
|
||||
|
||||
const set = iq.querySelector('set');
|
||||
let rsm;
|
||||
|
||||
if (!_.isNull(set)) {
|
||||
rsm = new Strophe.RSM({
|
||||
'xml': set
|
||||
});
|
||||
Object.assign(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
||||
}
|
||||
|
||||
return {
|
||||
messages,
|
||||
rsm
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user