|
@@ -36,6 +36,83 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ function queryForArchivedMessages (_converse, options, callback, errback) {
|
|
|
+ /* Internal function, called by the "archive.query" API method.
|
|
|
+ */
|
|
|
+ let date;
|
|
|
+ if (_.isFunction(options)) {
|
|
|
+ callback = options;
|
|
|
+ errback = callback;
|
|
|
+ }
|
|
|
+ const queryid = _converse.connection.getUniqueId();
|
|
|
+ const attrs = {'type':'set'};
|
|
|
+ if (!_.isUndefined(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 (!_.isUndefined(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, _.keys(options)).length) {
|
|
|
+ stanza.cnode(new Strophe.RSM(options).toXML());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const messages = [];
|
|
|
+ const message_handler = _converse.connection.addHandler(function (message) {
|
|
|
+ const result = message.querySelector('result');
|
|
|
+ if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
|
|
+ messages.push(message);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }, Strophe.NS.MAM);
|
|
|
+
|
|
|
+ _converse.connection.sendIQ(
|
|
|
+ stanza,
|
|
|
+ function (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});
|
|
|
+ _.extend(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
|
|
+ }
|
|
|
+ callback(messages, rsm);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ function () {
|
|
|
+ _converse.connection.deleteHandler(message_handler);
|
|
|
+ if (_.isFunction(errback)) { errback.apply(this, arguments); }
|
|
|
+ },
|
|
|
+ _converse.message_archiving_timeout
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
converse.plugins.add('converse-mam', {
|
|
|
|
|
@@ -150,7 +227,7 @@
|
|
|
return;
|
|
|
}
|
|
|
this.addSpinner();
|
|
|
- _converse.queryForArchivedMessages(
|
|
|
+ _converse.api.archive.query(
|
|
|
_.extend({
|
|
|
'before': '', // Page backwards from the most recent message
|
|
|
'max': _converse.archived_messages_page_size,
|
|
@@ -283,97 +360,6 @@
|
|
|
message_archiving_timeout: 8000, // Time (in milliseconds) to wait before aborting MAM request
|
|
|
});
|
|
|
|
|
|
- _converse.queryForArchivedMessages = function (options, callback, errback) {
|
|
|
- /* Do a MAM (XEP-0313) query for archived messages.
|
|
|
- *
|
|
|
- * Parameters:
|
|
|
- * (Object) options - Query parameters, either MAM-specific or also for Result Set Management.
|
|
|
- * (Function) callback - A function to call whenever we receive query-relevant stanza.
|
|
|
- * (Function) errback - A function to call when an error stanza is received.
|
|
|
- *
|
|
|
- * The options parameter can also be an instance of
|
|
|
- * Strophe.RSM to enable easy querying between results pages.
|
|
|
- *
|
|
|
- * The callback function may be called multiple times, first
|
|
|
- * for the initial IQ result and then for each message
|
|
|
- * returned. The last time 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.
|
|
|
- */
|
|
|
- let date;
|
|
|
- if (_.isFunction(options)) {
|
|
|
- callback = options;
|
|
|
- errback = callback;
|
|
|
- }
|
|
|
- const queryid = _converse.connection.getUniqueId();
|
|
|
- const attrs = {'type':'set'};
|
|
|
- if (!_.isUndefined(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 (!_.isUndefined(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, _.keys(options)).length) {
|
|
|
- stanza.cnode(new Strophe.RSM(options).toXML());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const messages = [];
|
|
|
- const message_handler = _converse.connection.addHandler(function (message) {
|
|
|
- const result = message.querySelector('result');
|
|
|
- if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
|
|
|
- messages.push(message);
|
|
|
- }
|
|
|
- return true;
|
|
|
- }, Strophe.NS.MAM);
|
|
|
-
|
|
|
- _converse.connection.sendIQ(
|
|
|
- stanza,
|
|
|
- function (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});
|
|
|
- _.extend(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
|
|
|
- }
|
|
|
- callback(messages, rsm);
|
|
|
- }
|
|
|
- },
|
|
|
- function () {
|
|
|
- _converse.connection.deleteHandler(message_handler);
|
|
|
- if (_.isFunction(errback)) { errback.apply(this, arguments); }
|
|
|
- },
|
|
|
- _converse.message_archiving_timeout
|
|
|
- );
|
|
|
- };
|
|
|
|
|
|
_converse.onMAMError = function (iq) {
|
|
|
if (iq.querySelectorAll('feature-not-implemented').length) {
|
|
@@ -457,11 +443,29 @@
|
|
|
/* Extend default converse.js API to add methods specific to MAM
|
|
|
*/
|
|
|
'archive': {
|
|
|
- 'query': function () {
|
|
|
+ 'query': function (options, callback, errback) {
|
|
|
+ /* Do a MAM (XEP-0313) query for archived messages.
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * (Object) options - Query parameters, either
|
|
|
+ * MAM-specific or also for Result Set Management.
|
|
|
+ * (Function) callback - A function to call whenever
|
|
|
+ * we receive query-relevant stanza.
|
|
|
+ * (Function) errback - A function to call when an
|
|
|
+ * error stanza is received.
|
|
|
+ *
|
|
|
+ * The options parameter can also be an instance of
|
|
|
+ * Strophe.RSM to enable easy querying between results pages.
|
|
|
+ *
|
|
|
+ * When the 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.
|
|
|
+ */
|
|
|
if (!_converse.api.connection.connected()) {
|
|
|
throw new Error('Can\'t call `api.archive.query` before having established an XMPP session');
|
|
|
}
|
|
|
- return _converse.queryForArchivedMessages.apply(this, arguments);
|
|
|
+ return queryForArchivedMessages(_converse, options, callback, errback);
|
|
|
}
|
|
|
}
|
|
|
});
|