Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
33600eee
Commit
33600eee
authored
Mar 07, 2019
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
No need for a separate `archive_id` value.
With MAM2 we can just use stanza-id
parent
be6a5d9c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
363 additions
and
312 deletions
+363
-312
dist/converse.js
dist/converse.js
+108
-106
spec/mam.js
spec/mam.js
+141
-90
spec/messages.js
spec/messages.js
+15
-9
src/headless/converse-chatboxes.js
src/headless/converse-chatboxes.js
+32
-35
src/headless/converse-mam.js
src/headless/converse-mam.js
+40
-42
src/headless/converse-muc.js
src/headless/converse-muc.js
+27
-30
No files found.
dist/converse.js
View file @
33600eee
...
@@ -61911,6 +61911,9 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
...
@@ -61911,6 +61911,9 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
return this.vcard.get('fullname') || this.get('jid');
return this.vcard.get('fullname') || this.get('jid');
},
},
updateMessage(message, stanza) {// Overridden in converse-muc and converse-mam
},
handleMessageCorrection(stanza) {
handleMessageCorrection(stanza) {
const replace = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop();
const replace = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop();
...
@@ -61942,11 +61945,15 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
...
@@ -61942,11 +61945,15 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
return false;
return false;
},
},
getDuplicateMessage(stanza) {
return this.findDuplicateFromOriginID(stanza) || this.findDuplicateFromStanzaID(stanza);
},
findDuplicateFromOriginID(stanza) {
findDuplicateFromOriginID(stanza) {
const origin_id = sizzle(`origin-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
const origin_id = sizzle(`origin-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
if (!origin_id) {
if (!origin_id) {
return
false
;
return
null
;
}
}
return this.messages.findWhere({
return this.messages.findWhere({
...
@@ -61955,27 +61962,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
...
@@ -61955,27 +61962,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
});
});
},
},
async hasDuplicateArchiveID(stanza) {
async findDuplicateFromStanzaID(stanza) {
const result = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, stanza).pop();
if (!result) {
return false;
}
const by_jid = stanza.getAttribute('from') || this.get('jid');
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, by_jid);
if (!supported.length) {
return false;
}
const query = {};
query[`stanza_id ${by_jid}`] = result.getAttribute('id');
const msg = this.messages.findWhere(query);
return !_.isNil(msg);
},
async hasDuplicateStanzaID(stanza) {
const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
if (!stanza_id) {
if (!stanza_id) {
...
@@ -61991,8 +61978,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
...
@@ -61991,8 +61978,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
const query = {};
const query = {};
query[`stanza_id ${by_jid}`] = stanza_id.getAttribute('id');
query[`stanza_id ${by_jid}`] = stanza_id.getAttribute('id');
const msg = this.messages.findWhere(query);
return this.messages.findWhere(query);
return !_.isNil(msg);
},
},
sendMarker(to_jid, id, type) {
sendMarker(to_jid, id, type) {
...
@@ -62349,6 +62335,10 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
...
@@ -62349,6 +62335,10 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
return attrs;
return attrs;
},
},
isArchived(original_stanza) {
return !_.isNil(sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop());
},
getMessageAttributesFromStanza(stanza, original_stanza) {
getMessageAttributesFromStanza(stanza, original_stanza) {
/* Parses a passed in message stanza and returns an object
/* Parses a passed in message stanza and returns an object
* of attributes.
* of attributes.
...
@@ -62361,15 +62351,14 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
...
@@ -62361,15 +62351,14 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
* that contains the message stanza, if it was
* that contains the message stanza, if it was
* contained, otherwise it's the message stanza itself.
* contained, otherwise it's the message stanza itself.
*/
*/
const archive = sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop(),
const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(),
delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(),
delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(),
text = _converse.chatboxes.getMessageBody(stanza) || undefined,
text = _converse.chatboxes.getMessageBody(stanza) || undefined,
chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE;
chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE;
const attrs = _.extend({
const attrs = _.extend({
'chat_state': chat_state,
'chat_state': chat_state,
'is_archived':
!_.isNil(archive
),
'is_archived':
this.isArchived(original_stanza
),
'is_delayed': !_.isNil(delay),
'is_delayed': !_.isNil(delay),
'is_spoiler': !_.isNil(spoiler),
'is_spoiler': !_.isNil(spoiler),
'is_single_emoji': text ? u.isSingleEmoji(text) : false,
'is_single_emoji': text ? u.isSingleEmoji(text) : false,
...
@@ -62637,12 +62626,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
...
@@ -62637,12 +62626,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
'nickname': roster_nick
'nickname': roster_nick
}, has_body);
}, has_body);
if (chatbox
&& !chatbox.findDuplicateFromOriginID(stanza) && !(await chatbox.hasDuplicateArchiveID(original_stanza)) && !(await chatbox.hasDuplicateStanzaID(stanza)) && !chatbox.handleMessageCorrection(stanza) && !chatbox.handleReceipt(stanza, from_jid, is_carbon, is_me) && !chatbox.handleChatMarker(stanza, from_jid, is_carbon, is_roster_contact)
) {
if (chatbox) {
const
attrs = await chatbox.getMessageAttributesFromStanza(stanza, original_
stanza);
const
message = await chatbox.getDuplicateMessage(
stanza);
if (attrs['chat_state'] || !u.isEmptyMessage(attrs)) {
if (message) {
const msg = chatbox.messages.create(attrs);
chatbox.updateMessage(message, original_stanza);
chatbox.incrementUnreadMsgCounter(msg);
}
if (!message && !chatbox.handleMessageCorrection(stanza) && !chatbox.handleReceipt(stanza, from_jid, is_carbon, is_me) && !chatbox.handleChatMarker(stanza, from_jid, is_carbon, is_roster_contact)) {
const attrs = await chatbox.getMessageAttributesFromStanza(stanza, original_stanza);
if (attrs['chat_state'] || !u.isEmptyMessage(attrs)) {
const msg = chatbox.messages.create(attrs);
chatbox.incrementUnreadMsgCounter(msg);
}
}
}
}
}
...
@@ -65603,18 +65600,6 @@ const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'cou
...
@@ -65603,18 +65600,6 @@ const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'cou
const MAM_ATTRIBUTES = ['with', 'start', 'end'];
const MAM_ATTRIBUTES = ['with', 'start', 'end'];
function getMessageArchiveID(stanza) {
// See https://xmpp.org/extensions/xep-0313.html#results
//
// The result messages MUST contain a <result/> element with an 'id'
// attribute that gives the current message's archive UID
const result = sizzle__WEBPACK_IMPORTED_MODULE_3___default()(`result[xmlns="${Strophe.NS.MAM}"]`, stanza).pop();
if (!_.isUndefined(result)) {
return result.getAttribute('id');
}
}
function queryForArchivedMessages(_converse, options, callback, errback) {
function queryForArchivedMessages(_converse, options, callback, errback) {
/* Internal function, called by the "archive.query" API method.
/* Internal function, called by the "archive.query" API method.
*/
*/
...
@@ -65739,10 +65724,44 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
...
@@ -65739,10 +65724,44 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
//
//
// New functions which don't exist yet can also be added.
// New functions which don't exist yet can also be added.
ChatBox: {
ChatBox: {
async getMessageAttributesFromStanza(message, original_stanza) {
async findDuplicateFromArchiveID(stanza) {
const attrs = await this.__super__.getMessageAttributesFromStanza.apply(this, arguments);
const _converse = this.__super__._converse;
attrs.archive_id = getMessageArchiveID(original_stanza);
const result = sizzle__WEBPACK_IMPORTED_MODULE_3___default()(`result[xmlns="${Strophe.NS.MAM}"]`, stanza).pop();
return attrs;
if (!result) {
return null;
}
const by_jid = stanza.getAttribute('from') || this.get('jid');
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, by_jid);
if (!supported.length) {
return null;
}
const query = {};
query[`stanza_id ${by_jid}`] = result.getAttribute('id');
return this.messages.findWhere(query);
},
async getDuplicateMessage(stanza) {
const message = await this.__super__.getDuplicateMessage.apply(this, arguments);
if (!message) {
return this.findDuplicateFromArchiveID(stanza);
}
return message;
},
updateMessage(message, stanza) {
this.__super__.updateMessage.apply(this, arguments);
if (message && !message.get('is_archived')) {
message.save(_.extend({
'is_archived': this.isArchived(stanza)
}, this.getStanzaIDs(stanza)));
}
}
}
},
},
...
@@ -65771,11 +65790,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
...
@@ -65771,11 +65790,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
if (_.isNil(most_recent_msg)) {
if (_.isNil(most_recent_msg)) {
this.fetchArchivedMessages();
this.fetchArchivedMessages();
} else {
} else {
const
archive_id = most_recent_msg.get('archive_id'
);
const
stanza_id = most_recent_msg.get(`stanza_id ${this.model.get('jid')}`
);
if (
archive
_id) {
if (
stanza
_id) {
this.fetchArchivedMessages({
this.fetchArchivedMessages({
'after':
most_recent_msg.get('archive_id')
'after':
stanza_id
});
});
} else {
} else {
this.fetchArchivedMessages({
this.fetchArchivedMessages({
...
@@ -65874,11 +65893,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
...
@@ -65874,11 +65893,12 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
if (this.content.scrollTop === 0 && this.model.messages.length) {
if (this.content.scrollTop === 0 && this.model.messages.length) {
const oldest_message = this.model.messages.at(0);
const oldest_message = this.model.messages.at(0);
const archive_id = oldest_message.get('archive_id');
const by_jid = this.model.get('jid');
const stanza_id = oldest_message.get(`stanza_id ${by_jid}`);
if (
archive
_id) {
if (
stanza
_id) {
this.fetchArchivedMessages({
this.fetchArchivedMessages({
'before':
archive
_id
'before':
stanza
_id
});
});
} else {
} else {
this.fetchArchivedMessages({
this.fetchArchivedMessages({
...
@@ -65888,24 +65908,6 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
...
@@ -65888,24 +65908,6 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-mam
}
}
}
}
},
ChatRoom: {
isDuplicate(message, original_stanza) {
const result = this.__super__.isDuplicate.apply(this, arguments);
if (result) {
return result;
}
const archive_id = getMessageArchiveID(original_stanza);
if (archive_id) {
return this.messages.filter({
'archive_id': archive_id
}).length > 0;
}
}
},
},
ChatRoomView: {
ChatRoomView: {
initialize() {
initialize() {
...
@@ -67350,39 +67352,6 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
...
@@ -67350,39 +67352,6 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
acknowledged[xmlns="${Strophe.NS.MARKERS}"]`, stanza).length > 0;
acknowledged[xmlns="${Strophe.NS.MARKERS}"]`, stanza).length > 0;
},
},
handleReflection(stanza) {
/* Handle a MUC reflected message and return true if so.
*
* Parameters:
* (XMLElement) stanza: The message stanza
*/
const from = stanza.getAttribute('from');
const own_message = Strophe.getResourceFromJid(from) == this.get('nick');
if (own_message) {
const msg = this.findDuplicateFromOriginID(stanza);
if (msg) {
const attrs = {};
const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
const by_jid = stanza_id ? stanza_id.getAttribute('by') : undefined;
if (by_jid) {
const key = `stanza_id ${by_jid}`;
attrs[key] = stanza_id.getAttribute('id');
}
if (!msg.get('received')) {
attrs.received = moment().format();
}
msg.save(attrs);
}
return msg ? true : false;
}
},
subjectChangeHandled(attrs) {
subjectChangeHandled(attrs) {
/* Handle a subject change and return `true` if so.
/* Handle a subject change and return `true` if so.
*
*
...
@@ -67419,6 +67388,33 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
...
@@ -67419,6 +67388,33 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
return is_csn && (attrs.is_delayed || own_message);
return is_csn && (attrs.is_delayed || own_message);
},
},
updateMessage(message, stanza) {
/* Make sure that the already cached message is updated with
* the stanza ID.
*/
_converse.ChatBox.prototype.updateMessage.call(this, message, stanza);
const from = stanza.getAttribute('from');
const own_message = Strophe.getResourceFromJid(from) == this.get('nick');
if (own_message) {
const attrs = {};
const stanza_id = sizzle(`stanza-id[xmlns="${Strophe.NS.SID}"]`, stanza).pop();
const by_jid = stanza_id ? stanza_id.getAttribute('by') : undefined;
if (by_jid) {
const key = `stanza_id ${by_jid}`;
attrs[key] = stanza_id.getAttribute('id');
}
if (!message.get('received')) {
attrs.received = moment().format();
}
message.save(attrs);
}
},
async onMessage(stanza) {
async onMessage(stanza) {
/* Handler for all MUC messages sent to this groupchat.
/* Handler for all MUC messages sent to this groupchat.
*
*
...
@@ -67433,7 +67429,13 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
...
@@ -67433,7 +67429,13 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
stanza = forwarded.querySelector('message');
stanza = forwarded.querySelector('message');
}
}
if (this.handleReflection(stanza) || (await this.hasDuplicateArchiveID(original_stanza)) || (await this.hasDuplicateStanzaID(stanza)) || this.handleMessageCorrection(stanza) || this.isReceipt(stanza) || this.isChatMarker(stanza)) {
const message = await this.getDuplicateMessage(original_stanza);
if (message) {
this.updateMessage(message, original_stanza);
}
if (message || this.handleMessageCorrection(stanza) || this.isReceipt(stanza) || this.isChatMarker(stanza)) {
return _converse.emit('message', {
return _converse.emit('message', {
'stanza': original_stanza
'stanza': original_stanza
});
});
spec/mam.js
View file @
33600eee
...
@@ -14,96 +14,147 @@
...
@@ -14,96 +14,147 @@
describe
(
"
Message Archive Management
"
,
function
()
{
describe
(
"
Message Archive Management
"
,
function
()
{
// Implement the protocol defined in https://xmpp.org/extensions/xep-0313.html#config
// Implement the protocol defined in https://xmpp.org/extensions/xep-0313.html#config
describe
(
"
Archived Messages
"
,
function
()
{
describe
(
"
An archived message
"
,
function
()
{
it
(
"
aren't shown as duplicates by comparing their stanza id and archive id
"
,
describe
(
"
when recieved
"
,
function
()
{
mock
.
initConverse
(
null
,
[
'
discoInitialized
'
],
{},
it
(
"
updates the is_archived value of an already cached version
"
,
async
function
(
done
,
_converse
)
{
mock
.
initConverse
(
null
,
[
'
discoInitialized
'
],
{},
await
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
trek-radio
'
,
'
conference.lightwitch.org
'
,
'
jcbrand
'
);
async
function
(
done
,
_converse
)
{
const
view
=
_converse
.
chatboxviews
.
get
(
'
trek-radio@conference.lightwitch.org
'
);
let
stanza
=
u
.
toStanza
(
await
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
trek-radio
'
,
'
conference.lightwitch.org
'
,
'
dummy
'
);
`<message xmlns="jabber:client" to="jcbrand@lightwitch.org/converse.js-73057452" type="groupchat" from="trek-radio@conference.lightwitch.org/comndrdukath#0805 (STO)">
<body>negan</body>
const
view
=
_converse
.
chatboxviews
.
get
(
'
trek-radio@conference.lightwitch.org
'
);
<stanza-id xmlns="urn:xmpp:sid:0" id="45fbbf2a-1059-479d-9283-c8effaf05621" by="trek-radio@conference.lightwitch.org"/>
let
stanza
=
u
.
toStanza
(
</message>`
);
`<message xmlns="jabber:client" to="dummy@localhost/resource" type="groupchat" from="trek-radio@conference.lightwitch.org/some1">
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
<body>Hello</body>
await
test_utils
.
waitUntil
(()
=>
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
);
<stanza-id xmlns="urn:xmpp:sid:0" id="45fbbf2a-1059-479d-9283-c8effaf05621" by="trek-radio@conference.lightwitch.org"/>
// Not sure whether such a race-condition might pose a problem
</message>`
);
// in "real-world" situations.
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
stanza
=
u
.
toStanza
(
await
test_utils
.
waitUntil
(()
=>
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
);
`<message xmlns="jabber:client"
expect
(
view
.
model
.
messages
.
length
).
toBe
(
1
);
to="jcbrand@lightwitch.org/converse.js-73057452"
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
is_archived
'
)).
toBe
(
false
);
from="trek-radio@conference.lightwitch.org">
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
stanza_id trek-radio@conference.lightwitch.org
'
)).
toBe
(
'
45fbbf2a-1059-479d-9283-c8effaf05621
'
);
<result xmlns="urn:xmpp:mam:2" queryid="82d9db27-6cf8-4787-8c2c-5a560263d823" id="45fbbf2a-1059-479d-9283-c8effaf05621">
<forwarded xmlns="urn:xmpp:forward:0">
stanza
=
u
.
toStanza
(
<delay xmlns="urn:xmpp:delay" stamp="2018-01-09T06:17:23Z"/>
`<message xmlns="jabber:client"
<message from="trek-radio@conference.lightwitch.org/comndrdukath#0805 (STO)" type="groupchat">
to="dummy@localhost/resource"
<body>negan</body>
from="trek-radio@conference.lightwitch.org">
</message>
<result xmlns="urn:xmpp:mam:2" queryid="82d9db27-6cf8-4787-8c2c-5a560263d823" id="45fbbf2a-1059-479d-9283-c8effaf05621">
</forwarded>
<forwarded xmlns="urn:xmpp:forward:0">
</result>
<delay xmlns="urn:xmpp:delay" stamp="2018-01-09T06:17:23Z"/>
</message>`
);
<message from="trek-radio@conference.lightwitch.org/some1" type="groupchat">
spyOn
(
view
.
model
,
'
hasDuplicateArchiveID
'
).
and
.
callThrough
();
<body>Hello</body>
view
.
model
.
onMessage
(
stanza
);
</message>
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
hasDuplicateArchiveID
.
calls
.
count
());
</forwarded>
expect
(
view
.
model
.
hasDuplicateArchiveID
.
calls
.
count
()).
toBe
(
1
);
</result>
const
result
=
await
view
.
model
.
hasDuplicateArchiveID
.
calls
.
all
()[
0
].
returnValue
</message>`
);
expect
(
result
).
toBe
(
true
);
spyOn
(
view
.
model
,
'
findDuplicateFromArchiveID
'
).
and
.
callThrough
();
expect
(
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
spyOn
(
view
.
model
,
'
updateMessage
'
).
and
.
callThrough
();
done
();
view
.
model
.
onMessage
(
stanza
);
}));
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
count
());
expect
(
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
count
()).
toBe
(
1
);
it
(
"
aren't shown as duplicates by comparing only their archive id
"
,
const
result
=
await
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
all
()[
0
].
returnValue
mock
.
initConverse
(
expect
(
result
instanceof
_converse
.
Message
).
toBe
(
true
);
null
,
[
'
discoInitialized
'
],
{},
expect
(
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
async
function
(
done
,
_converse
)
{
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
updateMessage
.
calls
.
count
());
await
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
discuss
'
,
'
conference.conversejs.org
'
,
'
dummy
'
);
expect
(
view
.
model
.
messages
.
length
).
toBe
(
1
);
const
view
=
_converse
.
chatboxviews
.
get
(
'
discuss@conference.conversejs.org
'
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
is_archived
'
)).
toBe
(
true
);
let
stanza
=
u
.
toStanza
(
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
stanza_id trek-radio@conference.lightwitch.org
'
)).
toBe
(
'
45fbbf2a-1059-479d-9283-c8effaf05621
'
);
`<message xmlns="jabber:client" to="dummy@localhost/resource" from="discuss@conference.conversejs.org">
done
();
<result xmlns="urn:xmpp:mam:2" queryid="06fea9ca-97c9-48c4-8583-009ff54ea2e8" id="7a9fde91-4387-4bf8-b5d3-978dab8f6bf3">
}));
<forwarded xmlns="urn:xmpp:forward:0">
<delay xmlns="urn:xmpp:delay" stamp="2018-12-05T04:53:12Z"/>
it
(
"
isn't shown as duplicate by comparing its stanza id or archive id
"
,
<message xmlns="jabber:client" to="discuss@conference.conversejs.org" type="groupchat" xml:lang="en" from="discuss@conference.conversejs.org/prezel">
mock
.
initConverse
(
<body>looks like omemo fails completely with "bundle is undefined" when there is a device in the devicelist that has no keys published</body>
null
,
[
'
discoInitialized
'
],
{},
<x xmlns="http://jabber.org/protocol/muc#user">
async
function
(
done
,
_converse
)
{
<item affiliation="none" jid="prezel@blubber.im" role="participant"/>
</x>
await
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
trek-radio
'
,
'
conference.lightwitch.org
'
,
'
jcbrand
'
);
</message>
const
view
=
_converse
.
chatboxviews
.
get
(
'
trek-radio@conference.lightwitch.org
'
);
</forwarded>
let
stanza
=
u
.
toStanza
(
</result>
`<message xmlns="jabber:client" to="jcbrand@lightwitch.org/converse.js-73057452" type="groupchat" from="trek-radio@conference.lightwitch.org/comndrdukath#0805 (STO)">
</message>`
);
<body>negan</body>
view
.
model
.
onMessage
(
stanza
);
<stanza-id xmlns="urn:xmpp:sid:0" id="45fbbf2a-1059-479d-9283-c8effaf05621" by="trek-radio@conference.lightwitch.org"/>
await
test_utils
.
waitUntil
(()
=>
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
);
</message>`
);
expect
(
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
await
test_utils
.
waitUntil
(()
=>
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
);
stanza
=
u
.
toStanza
(
// Not sure whether such a race-condition might pose a problem
`<message xmlns="jabber:client" to="dummy@localhost/resource" from="discuss@conference.conversejs.org">
// in "real-world" situations.
<result xmlns="urn:xmpp:mam:2" queryid="06fea9ca-97c9-48c4-8583-009ff54ea2e8" id="7a9fde91-4387-4bf8-b5d3-978dab8f6bf3">
stanza
=
u
.
toStanza
(
<forwarded xmlns="urn:xmpp:forward:0">
`<message xmlns="jabber:client"
<delay xmlns="urn:xmpp:delay" stamp="2018-12-05T04:53:12Z"/>
to="jcbrand@lightwitch.org/converse.js-73057452"
<message xmlns="jabber:client" to="discuss@conference.conversejs.org" type="groupchat" xml:lang="en" from="discuss@conference.conversejs.org/prezel">
from="trek-radio@conference.lightwitch.org">
<body>looks like omemo fails completely with "bundle is undefined" when there is a device in the devicelist that has no keys published</body>
<result xmlns="urn:xmpp:mam:2" queryid="82d9db27-6cf8-4787-8c2c-5a560263d823" id="45fbbf2a-1059-479d-9283-c8effaf05621">
<x xmlns="http://jabber.org/protocol/muc#user">
<forwarded xmlns="urn:xmpp:forward:0">
<item affiliation="none" jid="prezel@blubber.im" role="participant"/>
<delay xmlns="urn:xmpp:delay" stamp="2018-01-09T06:17:23Z"/>
</x>
<message from="trek-radio@conference.lightwitch.org/comndrdukath#0805 (STO)" type="groupchat">
</message>
<body>negan</body>
</forwarded>
</message>
</result>
</forwarded>
</message>`
);
</result>
</message>`
);
spyOn
(
view
.
model
,
'
hasDuplicateArchiveID
'
).
and
.
callThrough
();
spyOn
(
view
.
model
,
'
findDuplicateFromArchiveID
'
).
and
.
callThrough
();
view
.
model
.
onMessage
(
stanza
);
view
.
model
.
onMessage
(
stanza
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
hasDuplicateArchiveID
.
calls
.
count
());
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
count
());
expect
(
view
.
model
.
hasDuplicateArchiveID
.
calls
.
count
()).
toBe
(
1
);
expect
(
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
count
()).
toBe
(
1
);
const
result
=
await
view
.
model
.
hasDuplicateArchiveID
.
calls
.
all
()[
0
].
returnValue
const
result
=
await
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
all
()[
0
].
returnValue
expect
(
result
).
toBe
(
true
);
expect
(
result
instanceof
_converse
.
Message
).
toBe
(
true
);
expect
(
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
expect
(
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
done
();
done
();
}))
}));
it
(
"
isn't shown as duplicate by comparing only the archive id
"
,
mock
.
initConverse
(
null
,
[
'
discoInitialized
'
],
{},
async
function
(
done
,
_converse
)
{
await
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
discuss
'
,
'
conference.conversejs.org
'
,
'
dummy
'
);
const
view
=
_converse
.
chatboxviews
.
get
(
'
discuss@conference.conversejs.org
'
);
let
stanza
=
u
.
toStanza
(
`<message xmlns="jabber:client" to="dummy@localhost/resource" from="discuss@conference.conversejs.org">
<result xmlns="urn:xmpp:mam:2" queryid="06fea9ca-97c9-48c4-8583-009ff54ea2e8" id="7a9fde91-4387-4bf8-b5d3-978dab8f6bf3">
<forwarded xmlns="urn:xmpp:forward:0">
<delay xmlns="urn:xmpp:delay" stamp="2018-12-05T04:53:12Z"/>
<message xmlns="jabber:client" to="discuss@conference.conversejs.org" type="groupchat" xml:lang="en" from="discuss@conference.conversejs.org/prezel">
<body>looks like omemo fails completely with "bundle is undefined" when there is a device in the devicelist that has no keys published</body>
<x xmlns="http://jabber.org/protocol/muc#user">
<item affiliation="none" jid="prezel@blubber.im" role="participant"/>
</x>
</message>
</forwarded>
</result>
</message>`
);
view
.
model
.
onMessage
(
stanza
);
await
test_utils
.
waitUntil
(()
=>
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
);
expect
(
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
stanza
=
u
.
toStanza
(
`<message xmlns="jabber:client" to="dummy@localhost/resource" from="discuss@conference.conversejs.org">
<result xmlns="urn:xmpp:mam:2" queryid="06fea9ca-97c9-48c4-8583-009ff54ea2e8" id="7a9fde91-4387-4bf8-b5d3-978dab8f6bf3">
<forwarded xmlns="urn:xmpp:forward:0">
<delay xmlns="urn:xmpp:delay" stamp="2018-12-05T04:53:12Z"/>
<message xmlns="jabber:client" to="discuss@conference.conversejs.org" type="groupchat" xml:lang="en" from="discuss@conference.conversejs.org/prezel">
<body>looks like omemo fails completely with "bundle is undefined" when there is a device in the devicelist that has no keys published</body>
<x xmlns="http://jabber.org/protocol/muc#user">
<item affiliation="none" jid="prezel@blubber.im" role="participant"/>
</x>
</message>
</forwarded>
</result>
</message>`
);
spyOn
(
view
.
model
,
'
findDuplicateFromArchiveID
'
).
and
.
callThrough
();
view
.
model
.
onMessage
(
stanza
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
count
());
expect
(
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
count
()).
toBe
(
1
);
const
result
=
await
view
.
model
.
findDuplicateFromArchiveID
.
calls
.
all
()[
0
].
returnValue
expect
(
result
instanceof
_converse
.
Message
).
toBe
(
true
);
expect
(
view
.
content
.
querySelectorAll
(
'
.chat-msg
'
).
length
).
toBe
(
1
);
done
();
}))
});
});
});
describe
(
"
The archive.query API
"
,
function
()
{
describe
(
"
The archive.query API
"
,
function
()
{
...
...
spec/messages.js
View file @
33600eee
...
@@ -2223,7 +2223,7 @@
...
@@ -2223,7 +2223,7 @@
await
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
room
'
,
'
muc.example.com
'
,
'
dummy
'
);
await
test_utils
.
openAndEnterChatRoom
(
_converse
,
'
room
'
,
'
muc.example.com
'
,
'
dummy
'
);
const
view
=
_converse
.
chatboxviews
.
get
(
'
room@muc.example.com
'
);
const
view
=
_converse
.
chatboxviews
.
get
(
'
room@muc.example.com
'
);
spyOn
(
view
.
model
,
'
hasDuplicate
StanzaID
'
).
and
.
callThrough
();
spyOn
(
view
.
model
,
'
findDuplicateFrom
StanzaID
'
).
and
.
callThrough
();
let
stanza
=
u
.
toStanza
(
`
let
stanza
=
u
.
toStanza
(
`
<message xmlns="jabber:client"
<message xmlns="jabber:client"
from="room@muc.example.com/some1"
from="room@muc.example.com/some1"
...
@@ -2238,9 +2238,9 @@
...
@@ -2238,9 +2238,9 @@
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
await
test_utils
.
waitUntil
(()
=>
_converse
.
api
.
chats
.
get
().
length
);
await
test_utils
.
waitUntil
(()
=>
_converse
.
api
.
chats
.
get
().
length
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
messages
.
length
===
1
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
messages
.
length
===
1
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
hasDuplicate
StanzaID
.
calls
.
count
()
===
1
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
findDuplicateFrom
StanzaID
.
calls
.
count
()
===
1
);
let
result
=
await
view
.
model
.
hasDuplicate
StanzaID
.
calls
.
all
()[
0
].
returnValue
;
let
result
=
await
view
.
model
.
findDuplicateFrom
StanzaID
.
calls
.
all
()[
0
].
returnValue
;
expect
(
result
).
toBe
(
false
);
expect
(
result
).
toBe
(
undefined
);
stanza
=
u
.
toStanza
(
`
stanza
=
u
.
toStanza
(
`
<message xmlns="jabber:client"
<message xmlns="jabber:client"
...
@@ -2254,9 +2254,9 @@
...
@@ -2254,9 +2254,9 @@
<origin-id xmlns="urn:xmpp:sid:0" id="de305d54-75b4-431b-adb2-eb6b9e546013"/>
<origin-id xmlns="urn:xmpp:sid:0" id="de305d54-75b4-431b-adb2-eb6b9e546013"/>
</message>`
);
</message>`
);
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
hasDuplicate
StanzaID
.
calls
.
count
()
===
2
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
findDuplicateFrom
StanzaID
.
calls
.
count
()
===
2
);
result
=
await
view
.
model
.
hasDuplicate
StanzaID
.
calls
.
all
()[
1
].
returnValue
;
result
=
await
view
.
model
.
findDuplicateFrom
StanzaID
.
calls
.
all
()[
1
].
returnValue
;
expect
(
result
).
toBe
(
true
);
expect
(
result
instanceof
_converse
.
Message
).
toBe
(
true
);
expect
(
view
.
model
.
messages
.
length
).
toBe
(
1
);
expect
(
view
.
model
.
messages
.
length
).
toBe
(
1
);
done
();
done
();
}));
}));
...
@@ -2477,7 +2477,13 @@
...
@@ -2477,7 +2477,13 @@
<origin-id xmlns="urn:xmpp:sid:0" id="
${
msg_obj
.
get
(
'
origin_id
'
)}
"/>
<origin-id xmlns="urn:xmpp:sid:0" id="
${
msg_obj
.
get
(
'
origin_id
'
)}
"/>
</message>`
);
</message>`
);
await
view
.
model
.
onMessage
(
stanza
);
await
view
.
model
.
onMessage
(
stanza
);
await
test_utils
.
waitUntil
(()
=>
view
.
el
.
querySelectorAll
(
'
.chat-msg__receipt
'
).
length
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg__receipt
'
).
length
).
toBe
(
1
);
expect
(
view
.
el
.
querySelectorAll
(
'
.chat-msg__receipt
'
).
length
).
toBe
(
1
);
expect
(
view
.
model
.
messages
.
length
).
toBe
(
1
);
const
message
=
view
.
model
.
messages
.
at
(
0
);
expect
(
message
.
get
(
'
stanza_id lounge@localhost
'
)).
toBe
(
'
5f3dbc5e-e1d3-4077-a492-693f3769c7ad
'
);
expect
(
message
.
get
(
'
origin_id
'
)).
toBe
(
msg_obj
.
get
(
'
origin_id
'
));
done
();
done
();
}));
}));
...
@@ -2518,9 +2524,9 @@
...
@@ -2518,9 +2524,9 @@
by="room@muc.example.com"/>
by="room@muc.example.com"/>
<origin-id xmlns="urn:xmpp:sid:0" id="
${
attrs
.
origin_id
}
"/>
<origin-id xmlns="urn:xmpp:sid:0" id="
${
attrs
.
origin_id
}
"/>
</message>`
);
</message>`
);
spyOn
(
view
.
model
,
'
handleReflection
'
).
and
.
callThrough
();
spyOn
(
view
.
model
,
'
updateMessage
'
).
and
.
callThrough
();
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
_converse
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
handleReflection
.
calls
.
count
()
===
1
);
await
test_utils
.
waitUntil
(()
=>
view
.
model
.
updateMessage
.
calls
.
count
()
===
1
);
expect
(
view
.
model
.
messages
.
length
).
toBe
(
1
);
expect
(
view
.
model
.
messages
.
length
).
toBe
(
1
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
stanza_id room@muc.example.com
'
)).
toBe
(
"
5f3dbc5e-e1d3-4077-a492-693f3769c7ad
"
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
stanza_id room@muc.example.com
'
)).
toBe
(
"
5f3dbc5e-e1d3-4077-a492-693f3769c7ad
"
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
origin_id
'
)).
toBe
(
attrs
.
origin_id
);
expect
(
view
.
model
.
messages
.
at
(
0
).
get
(
'
origin_id
'
)).
toBe
(
attrs
.
origin_id
);
...
...
src/headless/converse-chatboxes.js
View file @
33600eee
...
@@ -290,6 +290,10 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -290,6 +290,10 @@ converse.plugins.add('converse-chatboxes', {
return
this
.
vcard
.
get
(
'
fullname
'
)
||
this
.
get
(
'
jid
'
);
return
this
.
vcard
.
get
(
'
fullname
'
)
||
this
.
get
(
'
jid
'
);
},
},
updateMessage
(
message
,
stanza
)
{
// Overridden in converse-muc and converse-mam
},
handleMessageCorrection
(
stanza
)
{
handleMessageCorrection
(
stanza
)
{
const
replace
=
sizzle
(
`replace[xmlns="
${
Strophe
.
NS
.
MESSAGE_CORRECT
}
"]`
,
stanza
).
pop
();
const
replace
=
sizzle
(
`replace[xmlns="
${
Strophe
.
NS
.
MESSAGE_CORRECT
}
"]`
,
stanza
).
pop
();
if
(
replace
)
{
if
(
replace
)
{
...
@@ -316,10 +320,14 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -316,10 +320,14 @@ converse.plugins.add('converse-chatboxes', {
return
false
;
return
false
;
},
},
getDuplicateMessage
(
stanza
)
{
return
this
.
findDuplicateFromOriginID
(
stanza
)
||
this
.
findDuplicateFromStanzaID
(
stanza
);
},
findDuplicateFromOriginID
(
stanza
)
{
findDuplicateFromOriginID
(
stanza
)
{
const
origin_id
=
sizzle
(
`origin-id[xmlns="
${
Strophe
.
NS
.
SID
}
"]`
,
stanza
).
pop
();
const
origin_id
=
sizzle
(
`origin-id[xmlns="
${
Strophe
.
NS
.
SID
}
"]`
,
stanza
).
pop
();
if
(
!
origin_id
)
{
if
(
!
origin_id
)
{
return
false
;
return
null
;
}
}
return
this
.
messages
.
findWhere
({
return
this
.
messages
.
findWhere
({
'
origin_id
'
:
origin_id
.
getAttribute
(
'
id
'
),
'
origin_id
'
:
origin_id
.
getAttribute
(
'
id
'
),
...
@@ -327,23 +335,7 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -327,23 +335,7 @@ converse.plugins.add('converse-chatboxes', {
});
});
},
},
async
hasDuplicateArchiveID
(
stanza
)
{
async
findDuplicateFromStanzaID
(
stanza
)
{
const
result
=
sizzle
(
`result[xmlns="
${
Strophe
.
NS
.
MAM
}
"]`
,
stanza
).
pop
();
if
(
!
result
)
{
return
false
;
}
const
by_jid
=
stanza
.
getAttribute
(
'
from
'
)
||
this
.
get
(
'
jid
'
);
const
supported
=
await
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
MAM
,
by_jid
);
if
(
!
supported
.
length
)
{
return
false
;
}
const
query
=
{};
query
[
`stanza_id
${
by_jid
}
`
]
=
result
.
getAttribute
(
'
id
'
);
const
msg
=
this
.
messages
.
findWhere
(
query
);
return
!
_
.
isNil
(
msg
);
},
async
hasDuplicateStanzaID
(
stanza
)
{
const
stanza_id
=
sizzle
(
`stanza-id[xmlns="
${
Strophe
.
NS
.
SID
}
"]`
,
stanza
).
pop
();
const
stanza_id
=
sizzle
(
`stanza-id[xmlns="
${
Strophe
.
NS
.
SID
}
"]`
,
stanza
).
pop
();
if
(
!
stanza_id
)
{
if
(
!
stanza_id
)
{
return
false
;
return
false
;
...
@@ -355,8 +347,7 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -355,8 +347,7 @@ converse.plugins.add('converse-chatboxes', {
}
}
const
query
=
{};
const
query
=
{};
query
[
`stanza_id
${
by_jid
}
`
]
=
stanza_id
.
getAttribute
(
'
id
'
);
query
[
`stanza_id
${
by_jid
}
`
]
=
stanza_id
.
getAttribute
(
'
id
'
);
const
msg
=
this
.
messages
.
findWhere
(
query
);
return
this
.
messages
.
findWhere
(
query
);
return
!
_
.
isNil
(
msg
);
},
},
...
@@ -654,6 +645,10 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -654,6 +645,10 @@ converse.plugins.add('converse-chatboxes', {
return
attrs
;
return
attrs
;
},
},
isArchived
(
original_stanza
)
{
return
!
_
.
isNil
(
sizzle
(
`result[xmlns="
${
Strophe
.
NS
.
MAM
}
"]`
,
original_stanza
).
pop
());
},
getMessageAttributesFromStanza
(
stanza
,
original_stanza
)
{
getMessageAttributesFromStanza
(
stanza
,
original_stanza
)
{
/* Parses a passed in message stanza and returns an object
/* Parses a passed in message stanza and returns an object
* of attributes.
* of attributes.
...
@@ -666,8 +661,7 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -666,8 +661,7 @@ converse.plugins.add('converse-chatboxes', {
* that contains the message stanza, if it was
* that contains the message stanza, if it was
* contained, otherwise it's the message stanza itself.
* contained, otherwise it's the message stanza itself.
*/
*/
const
archive
=
sizzle
(
`result[xmlns="
${
Strophe
.
NS
.
MAM
}
"]`
,
original_stanza
).
pop
(),
const
spoiler
=
sizzle
(
`spoiler[xmlns="
${
Strophe
.
NS
.
SPOILER
}
"]`
,
original_stanza
).
pop
(),
spoiler
=
sizzle
(
`spoiler[xmlns="
${
Strophe
.
NS
.
SPOILER
}
"]`
,
original_stanza
).
pop
(),
delay
=
sizzle
(
`delay[xmlns="
${
Strophe
.
NS
.
DELAY
}
"]`
,
original_stanza
).
pop
(),
delay
=
sizzle
(
`delay[xmlns="
${
Strophe
.
NS
.
DELAY
}
"]`
,
original_stanza
).
pop
(),
text
=
_converse
.
chatboxes
.
getMessageBody
(
stanza
)
||
undefined
,
text
=
_converse
.
chatboxes
.
getMessageBody
(
stanza
)
||
undefined
,
chat_state
=
stanza
.
getElementsByTagName
(
_converse
.
COMPOSING
).
length
&&
_converse
.
COMPOSING
||
chat_state
=
stanza
.
getElementsByTagName
(
_converse
.
COMPOSING
).
length
&&
_converse
.
COMPOSING
||
...
@@ -678,7 +672,7 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -678,7 +672,7 @@ converse.plugins.add('converse-chatboxes', {
const
attrs
=
_
.
extend
({
const
attrs
=
_
.
extend
({
'
chat_state
'
:
chat_state
,
'
chat_state
'
:
chat_state
,
'
is_archived
'
:
!
_
.
isNil
(
archive
),
'
is_archived
'
:
this
.
isArchived
(
original_stanza
),
'
is_delayed
'
:
!
_
.
isNil
(
delay
),
'
is_delayed
'
:
!
_
.
isNil
(
delay
),
'
is_spoiler
'
:
!
_
.
isNil
(
spoiler
),
'
is_spoiler
'
:
!
_
.
isNil
(
spoiler
),
'
is_single_emoji
'
:
text
?
u
.
isSingleEmoji
(
text
)
:
false
,
'
is_single_emoji
'
:
text
?
u
.
isSingleEmoji
(
text
)
:
false
,
...
@@ -926,18 +920,21 @@ converse.plugins.add('converse-chatboxes', {
...
@@ -926,18 +920,21 @@ converse.plugins.add('converse-chatboxes', {
roster_nick
=
_
.
get
(
_converse
.
api
.
contacts
.
get
(
contact_jid
),
'
attributes.nickname
'
),
roster_nick
=
_
.
get
(
_converse
.
api
.
contacts
.
get
(
contact_jid
),
'
attributes.nickname
'
),
chatbox
=
this
.
getChatBox
(
contact_jid
,
{
'
nickname
'
:
roster_nick
},
has_body
);
chatbox
=
this
.
getChatBox
(
contact_jid
,
{
'
nickname
'
:
roster_nick
},
has_body
);
if
(
chatbox
&&
if
(
chatbox
)
{
!
chatbox
.
findDuplicateFromOriginID
(
stanza
)
&&
const
message
=
await
chatbox
.
getDuplicateMessage
(
stanza
);
!
await
chatbox
.
hasDuplicateArchiveID
(
original_stanza
)
&&
if
(
message
)
{
!
await
chatbox
.
hasDuplicateStanzaID
(
stanza
)
&&
chatbox
.
updateMessage
(
message
,
original_stanza
);
!
chatbox
.
handleMessageCorrection
(
stanza
)
&&
}
!
chatbox
.
handleReceipt
(
stanza
,
from_jid
,
is_carbon
,
is_me
)
&&
if
(
!
message
&&
!
chatbox
.
handleChatMarker
(
stanza
,
from_jid
,
is_carbon
,
is_roster_contact
))
{
!
chatbox
.
handleMessageCorrection
(
stanza
)
&&
!
chatbox
.
handleReceipt
(
stanza
,
from_jid
,
is_carbon
,
is_me
)
&&
const
attrs
=
await
chatbox
.
getMessageAttributesFromStanza
(
stanza
,
original_stanza
);
!
chatbox
.
handleChatMarker
(
stanza
,
from_jid
,
is_carbon
,
is_roster_contact
))
{
if
(
attrs
[
'
chat_state
'
]
||
!
u
.
isEmptyMessage
(
attrs
))
{
const
msg
=
chatbox
.
messages
.
create
(
attrs
);
const
attrs
=
await
chatbox
.
getMessageAttributesFromStanza
(
stanza
,
original_stanza
);
chatbox
.
incrementUnreadMsgCounter
(
msg
);
if
(
attrs
[
'
chat_state
'
]
||
!
u
.
isEmptyMessage
(
attrs
))
{
const
msg
=
chatbox
.
messages
.
create
(
attrs
);
chatbox
.
incrementUnreadMsgCounter
(
msg
);
}
}
}
}
}
_converse
.
emit
(
'
message
'
,
{
'
stanza
'
:
original_stanza
,
'
chatbox
'
:
chatbox
});
_converse
.
emit
(
'
message
'
,
{
'
stanza
'
:
original_stanza
,
'
chatbox
'
:
chatbox
});
...
...
src/headless/converse-mam.js
View file @
33600eee
...
@@ -23,17 +23,6 @@ const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'cou
...
@@ -23,17 +23,6 @@ const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'cou
const
MAM_ATTRIBUTES
=
[
'
with
'
,
'
start
'
,
'
end
'
];
const
MAM_ATTRIBUTES
=
[
'
with
'
,
'
start
'
,
'
end
'
];
function
getMessageArchiveID
(
stanza
)
{
// See https://xmpp.org/extensions/xep-0313.html#results
//
// The result messages MUST contain a <result/> element with an 'id'
// attribute that gives the current message's archive UID
const
result
=
sizzle
(
`result[xmlns="
${
Strophe
.
NS
.
MAM
}
"]`
,
stanza
).
pop
();
if
(
!
_
.
isUndefined
(
result
))
{
return
result
.
getAttribute
(
'
id
'
);
}
}
function
queryForArchivedMessages
(
_converse
,
options
,
callback
,
errback
)
{
function
queryForArchivedMessages
(
_converse
,
options
,
callback
,
errback
)
{
/* Internal function, called by the "archive.query" API method.
/* Internal function, called by the "archive.query" API method.
*/
*/
...
@@ -128,10 +117,38 @@ converse.plugins.add('converse-mam', {
...
@@ -128,10 +117,38 @@ converse.plugins.add('converse-mam', {
// New functions which don't exist yet can also be added.
// New functions which don't exist yet can also be added.
ChatBox
:
{
ChatBox
:
{
async
getMessageAttributesFromStanza
(
message
,
original_stanza
)
{
async
findDuplicateFromArchiveID
(
stanza
)
{
const
attrs
=
await
this
.
__super__
.
getMessageAttributesFromStanza
.
apply
(
this
,
arguments
);
const
{
_converse
}
=
this
.
__super__
;
attrs
.
archive_id
=
getMessageArchiveID
(
original_stanza
);
const
result
=
sizzle
(
`result[xmlns="
${
Strophe
.
NS
.
MAM
}
"]`
,
stanza
).
pop
();
return
attrs
;
if
(
!
result
)
{
return
null
;
}
const
by_jid
=
stanza
.
getAttribute
(
'
from
'
)
||
this
.
get
(
'
jid
'
);
const
supported
=
await
_converse
.
api
.
disco
.
supports
(
Strophe
.
NS
.
MAM
,
by_jid
);
if
(
!
supported
.
length
)
{
return
null
;
}
const
query
=
{};
query
[
`stanza_id
${
by_jid
}
`
]
=
result
.
getAttribute
(
'
id
'
);
return
this
.
messages
.
findWhere
(
query
);
},
async
getDuplicateMessage
(
stanza
)
{
const
message
=
await
this
.
__super__
.
getDuplicateMessage
.
apply
(
this
,
arguments
);
if
(
!
message
)
{
return
this
.
findDuplicateFromArchiveID
(
stanza
);
}
return
message
;
},
updateMessage
(
message
,
stanza
)
{
this
.
__super__
.
updateMessage
.
apply
(
this
,
arguments
);
if
(
message
&&
!
message
.
get
(
'
is_archived
'
))
{
message
.
save
(
_
.
extend
({
'
is_archived
'
:
this
.
isArchived
(
stanza
)
},
this
.
getStanzaIDs
(
stanza
)));
}
}
}
},
},
...
@@ -155,15 +172,11 @@ converse.plugins.add('converse-mam', {
...
@@ -155,15 +172,11 @@ converse.plugins.add('converse-mam', {
if
(
_
.
isNil
(
most_recent_msg
))
{
if
(
_
.
isNil
(
most_recent_msg
))
{
this
.
fetchArchivedMessages
();
this
.
fetchArchivedMessages
();
}
else
{
}
else
{
const
archive_id
=
most_recent_msg
.
get
(
'
archive_id
'
);
const
stanza_id
=
most_recent_msg
.
get
(
`stanza_id
${
this
.
model
.
get
(
'
jid
'
)}
`
);
if
(
archive_id
)
{
if
(
stanza_id
)
{
this
.
fetchArchivedMessages
({
this
.
fetchArchivedMessages
({
'
after
'
:
stanza_id
});
'
after
'
:
most_recent_msg
.
get
(
'
archive_id
'
)
});
}
else
{
}
else
{
this
.
fetchArchivedMessages
({
this
.
fetchArchivedMessages
({
'
start
'
:
most_recent_msg
.
get
(
'
time
'
)});
'
start
'
:
most_recent_msg
.
get
(
'
time
'
)
});
}
}
}
}
},
},
...
@@ -250,11 +263,10 @@ converse.plugins.add('converse-mam', {
...
@@ -250,11 +263,10 @@ converse.plugins.add('converse-mam', {
const
{
_converse
}
=
this
.
__super__
;
const
{
_converse
}
=
this
.
__super__
;
if
(
this
.
content
.
scrollTop
===
0
&&
this
.
model
.
messages
.
length
)
{
if
(
this
.
content
.
scrollTop
===
0
&&
this
.
model
.
messages
.
length
)
{
const
oldest_message
=
this
.
model
.
messages
.
at
(
0
);
const
oldest_message
=
this
.
model
.
messages
.
at
(
0
);
const
archive_id
=
oldest_message
.
get
(
'
archive_id
'
);
const
by_jid
=
this
.
model
.
get
(
'
jid
'
);
if
(
archive_id
)
{
const
stanza_id
=
oldest_message
.
get
(
`stanza_id
${
by_jid
}
`
);
this
.
fetchArchivedMessages
({
if
(
stanza_id
)
{
'
before
'
:
archive_id
this
.
fetchArchivedMessages
({
'
before
'
:
stanza_id
});
});
}
else
{
}
else
{
this
.
fetchArchivedMessages
({
this
.
fetchArchivedMessages
({
'
end
'
:
oldest_message
.
get
(
'
time
'
)
'
end
'
:
oldest_message
.
get
(
'
time
'
)
...
@@ -264,20 +276,6 @@ converse.plugins.add('converse-mam', {
...
@@ -264,20 +276,6 @@ converse.plugins.add('converse-mam', {
},
},
},
},
ChatRoom
:
{
isDuplicate
(
message
,
original_stanza
)
{
const
result
=
this
.
__super__
.
isDuplicate
.
apply
(
this
,
arguments
);
if
(
result
)
{
return
result
;
}
const
archive_id
=
getMessageArchiveID
(
original_stanza
);
if
(
archive_id
)
{
return
this
.
messages
.
filter
({
'
archive_id
'
:
archive_id
}).
length
>
0
;
}
}
},
ChatRoomView
:
{
ChatRoomView
:
{
initialize
()
{
initialize
()
{
...
...
src/headless/converse-muc.js
View file @
33600eee
...
@@ -972,33 +972,6 @@ converse.plugins.add('converse-muc', {
...
@@ -972,33 +972,6 @@ converse.plugins.add('converse-muc', {
acknowledged[xmlns="
${
Strophe
.
NS
.
MARKERS
}
"]`
,
stanza
).
length
>
0
;
acknowledged[xmlns="
${
Strophe
.
NS
.
MARKERS
}
"]`
,
stanza
).
length
>
0
;
},
},
handleReflection
(
stanza
)
{
/* Handle a MUC reflected message and return true if so.
*
* Parameters:
* (XMLElement) stanza: The message stanza
*/
const
from
=
stanza
.
getAttribute
(
'
from
'
);
const
own_message
=
Strophe
.
getResourceFromJid
(
from
)
==
this
.
get
(
'
nick
'
);
if
(
own_message
)
{
const
msg
=
this
.
findDuplicateFromOriginID
(
stanza
);
if
(
msg
)
{
const
attrs
=
{};
const
stanza_id
=
sizzle
(
`stanza-id[xmlns="
${
Strophe
.
NS
.
SID
}
"]`
,
stanza
).
pop
();
const
by_jid
=
stanza_id
?
stanza_id
.
getAttribute
(
'
by
'
)
:
undefined
;
if
(
by_jid
)
{
const
key
=
`stanza_id
${
by_jid
}
`
;
attrs
[
key
]
=
stanza_id
.
getAttribute
(
'
id
'
);
}
if
(
!
msg
.
get
(
'
received
'
))
{
attrs
.
received
=
moment
().
format
();
}
msg
.
save
(
attrs
);
}
return
msg
?
true
:
false
;
}
},
subjectChangeHandled
(
attrs
)
{
subjectChangeHandled
(
attrs
)
{
/* Handle a subject change and return `true` if so.
/* Handle a subject change and return `true` if so.
*
*
...
@@ -1029,6 +1002,28 @@ converse.plugins.add('converse-muc', {
...
@@ -1029,6 +1002,28 @@ converse.plugins.add('converse-muc', {
return
is_csn
&&
(
attrs
.
is_delayed
||
own_message
);
return
is_csn
&&
(
attrs
.
is_delayed
||
own_message
);
},
},
updateMessage
(
message
,
stanza
)
{
/* Make sure that the already cached message is updated with
* the stanza ID.
*/
_converse
.
ChatBox
.
prototype
.
updateMessage
.
call
(
this
,
message
,
stanza
);
const
from
=
stanza
.
getAttribute
(
'
from
'
);
const
own_message
=
Strophe
.
getResourceFromJid
(
from
)
==
this
.
get
(
'
nick
'
);
if
(
own_message
)
{
const
attrs
=
{};
const
stanza_id
=
sizzle
(
`stanza-id[xmlns="
${
Strophe
.
NS
.
SID
}
"]`
,
stanza
).
pop
();
const
by_jid
=
stanza_id
?
stanza_id
.
getAttribute
(
'
by
'
)
:
undefined
;
if
(
by_jid
)
{
const
key
=
`stanza_id
${
by_jid
}
`
;
attrs
[
key
]
=
stanza_id
.
getAttribute
(
'
id
'
);
}
if
(
!
message
.
get
(
'
received
'
))
{
attrs
.
received
=
moment
().
format
();
}
message
.
save
(
attrs
);
}
},
async
onMessage
(
stanza
)
{
async
onMessage
(
stanza
)
{
/* Handler for all MUC messages sent to this groupchat.
/* Handler for all MUC messages sent to this groupchat.
*
*
...
@@ -1042,9 +1037,11 @@ converse.plugins.add('converse-muc', {
...
@@ -1042,9 +1037,11 @@ converse.plugins.add('converse-muc', {
if
(
forwarded
)
{
if
(
forwarded
)
{
stanza
=
forwarded
.
querySelector
(
'
message
'
);
stanza
=
forwarded
.
querySelector
(
'
message
'
);
}
}
if
(
this
.
handleReflection
(
stanza
)
||
const
message
=
await
this
.
getDuplicateMessage
(
original_stanza
);
await
this
.
hasDuplicateArchiveID
(
original_stanza
)
||
if
(
message
)
{
await
this
.
hasDuplicateStanzaID
(
stanza
)
||
this
.
updateMessage
(
message
,
original_stanza
);
}
if
(
message
||
this
.
handleMessageCorrection
(
stanza
)
||
this
.
handleMessageCorrection
(
stanza
)
||
this
.
isReceipt
(
stanza
)
||
this
.
isReceipt
(
stanza
)
||
this
.
isChatMarker
(
stanza
))
{
this
.
isChatMarker
(
stanza
))
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment