Commit acef8fea authored by JC Brand's avatar JC Brand

Refactoring of fetching of reserved nick

- Move `getDefaultNickName` to the model and rename to `getDefaultNick`
- Let `checkForReservedNick` return a promise and save `nick` once received
- Updated `openAndEnterChatRoom` to wait appropriately and remove presence-wrapper
- Update tests to wait appropriately
- Remove presence-wrapper in `getRoomFeatures`
parent 2df9b242
...@@ -68983,31 +68983,19 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -68983,31 +68983,19 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
* If so, we'll use that, otherwise we render the nickname form. * If so, we'll use that, otherwise we render the nickname form.
*/ */
this.showSpinner(); this.showSpinner();
this.model.checkForReservedNick(this.onReservedNicknameFound.bind(this), this.onReservedNicknameNotFound.bind(this)); this.model.checkForReservedNick().then(this.onReservedNickFound.bind(this)).catch(this.onReservedNickNotFound.bind(this));
}, },
onReservedNicknameFound(iq) { onReservedNickFound(iq) {
/* We've received an IQ response from the server which if (this.model.get('nick')) {
* might contain the user's reserved nickname. this.join();
* If no nickname is found we either render a form for
* them to specify one, or we try to join the groupchat with the
* node of the user's JID.
*
* Parameters:
* (XMLElement) iq: The received IQ stanza
*/
const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity'),
nick = identity_el ? identity_el.getAttribute('name') : null;
if (!nick) {
this.onNickNameNotFound();
} else { } else {
this.join(nick); this.onReservedNickNotFound();
} }
}, },
onReservedNicknameNotFound(message) { onReservedNickNotFound(message) {
const nick = this.getDefaultNickName(); const nick = this.model.getDefaultNick();
if (nick) { if (nick) {
this.join(nick); this.join(nick);
...@@ -69016,21 +69004,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -69016,21 +69004,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
} }
}, },
getDefaultNickName() {
/* The default nickname (used when muc_nickname_from_jid is true)
* is the node part of the user's JID.
* We put this in a separate method so that it can be
* overridden by plugins.
*/
const nick = _converse.xmppstatus.vcard.get('nickname');
if (nick) {
return nick;
} else if (_converse.muc_nickname_from_jid) {
return Strophe.unescapeNode(Strophe.getNodeFromJid(_converse.bare_jid));
}
},
onNicknameClash(presence) { onNicknameClash(presence) {
/* When the nickname is already taken, we either render a /* When the nickname is already taken, we either render a
* form for the user to choose a new nickname, or we * form for the user to choose a new nickname, or we
...@@ -69043,7 +69016,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -69043,7 +69016,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
if (_converse.muc_nickname_from_jid) { if (_converse.muc_nickname_from_jid) {
const nick = presence.getAttribute('from').split('/')[1]; const nick = presence.getAttribute('from').split('/')[1];
if (nick === this.getDefaultNickName()) { if (nick === this.model.getDefaultNick()) {
this.join(nick + '-2'); this.join(nick + '-2');
} else { } else {
const del = nick.lastIndexOf("-"); const del = nick.lastIndexOf("-");
...@@ -70110,8 +70083,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } ...@@ -70110,8 +70083,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
}, },
async onConnectionStatusChanged() { async onConnectionStatusChanged() {
if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED && _converse.auto_register_muc_nickname) { if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED && _converse.auto_register_muc_nickname && this.get('reserved_nick')) {
debugger;
const result = await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid')); const result = await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid'));
if (result.length) { if (result.length) {
...@@ -70361,17 +70333,15 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } ...@@ -70361,17 +70333,15 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
getRoomFeatures() { getRoomFeatures() {
/* Fetch the groupchat disco info, parse it and then save it. /* Fetch the groupchat disco info, parse it and then save it.
*/ */
return new Promise((resolve, reject) => { // XXX: Currently we store disco info on the room itself.
_converse.api.disco.info(this.get('jid'), null).then(stanza => { // A better design would probably be to create a
this.parseRoomFeatures(stanza); // DiscoEntity for this room, and then to let
resolve(); // converse-disco manage all disco-related tasks.
}).catch(err => { // Then we can also use _converse.api.disco.supports.
_converse.log("Could not parse the groupchat features", Strophe.LogLevel.WARN); return _converse.api.disco.info(this.get('jid'), null).then(stanza => this.parseRoomFeatures(stanza)).catch(err => {
_converse.log("Could not parse the groupchat features", Strophe.LogLevel.WARN);
_converse.log(err, Strophe.LogLevel.WARN);
_converse.log(err, Strophe.LogLevel.WARN);
reject(err);
});
}); });
}, },
...@@ -70801,7 +70771,22 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } ...@@ -70801,7 +70771,22 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
this.getJidsWithAffiliations(affiliations).then(old_members => this.setAffiliations(deltaFunc(members, old_members))).then(() => this.occupants.fetchMembers()).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)); this.getJidsWithAffiliations(affiliations).then(old_members => this.setAffiliations(deltaFunc(members, old_members))).then(() => this.occupants.fetchMembers()).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
}, },
checkForReservedNick(callback, errback) { getDefaultNick() {
/* The default nickname (used when muc_nickname_from_jid is true)
* is the node part of the user's JID.
* We put this in a separate method so that it can be
* overridden by plugins.
*/
const nick = _converse.xmppstatus.vcard.get('nickname');
if (nick) {
return nick;
} else if (_converse.muc_nickname_from_jid) {
return Strophe.unescapeNode(Strophe.getNodeFromJid(_converse.bare_jid));
}
},
checkForReservedNick() {
/* Use service-discovery to ask the XMPP server whether /* Use service-discovery to ask the XMPP server whether
* this user has a reserved nickname for this groupchat. * this user has a reserved nickname for this groupchat.
* If so, we'll use that, otherwise we render the nickname form. * If so, we'll use that, otherwise we render the nickname form.
...@@ -70810,16 +70795,24 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } ...@@ -70810,16 +70795,24 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
* (Function) callback: Callback upon succesful IQ response * (Function) callback: Callback upon succesful IQ response
* (Function) errback: Callback upon error IQ response * (Function) errback: Callback upon error IQ response
*/ */
_converse.connection.sendIQ($iq({ return _converse.api.sendIQ($iq({
'to': this.get('jid'), 'to': this.get('jid'),
'from': _converse.connection.jid, 'from': _converse.connection.jid,
'type': "get" 'type': "get"
}).c("query", { }).c("query", {
'xmlns': Strophe.NS.DISCO_INFO, 'xmlns': Strophe.NS.DISCO_INFO,
'node': 'x-roomuser-item' 'node': 'x-roomuser-item'
}), callback, errback); })).then(iq => {
const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity'),
return this; nick = identity_el ? identity_el.getAttribute('name') : null;
this.save({
'reserved_nick': nick,
'nick': nick
}, {
'silent': true
});
return iq;
});
}, },
async registerNickname() { async registerNickname() {
...@@ -354,8 +354,8 @@ ...@@ -354,8 +354,8 @@
}).c('error', {'type': 'cancel'}) }).c('error', {'type': 'cancel'})
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}); .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
return test_utils.waitUntil(() => view.el.querySelector('input[name="nick"]'));
var input = view.el.querySelector('input[name="nick"]'); }).then(input => {
input.value = 'nicky'; input.value = 'nicky';
view.el.querySelector('input[type=submit]').click(); view.el.querySelector('input[type=submit]').click();
expect(view.submitNickname).toHaveBeenCalled(); expect(view.submitNickname).toHaveBeenCalled();
...@@ -402,7 +402,7 @@ ...@@ -402,7 +402,7 @@
"<query xmlns='http://jabber.org/protocol/muc#owner'><x xmlns='jabber:x:data' type='submit'/>"+ "<query xmlns='http://jabber.org/protocol/muc#owner'><x xmlns='jabber:x:data' type='submit'/>"+
"</query></iq>"); "</query></iq>");
done(); done();
}); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
})); }));
}); });
...@@ -1899,7 +1899,8 @@ ...@@ -1899,7 +1899,8 @@
* </x> * </x>
* </presence> * </presence>
*/ */
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy').then(function () { test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => {
var presence = $pres().attrs({ var presence = $pres().attrs({
from:'lounge@localhost/dummy', from:'lounge@localhost/dummy',
to:'dummy@localhost/pda', to:'dummy@localhost/pda',
......
...@@ -6,39 +6,73 @@ ...@@ -6,39 +6,73 @@
Strophe = converse.env.Strophe, Strophe = converse.env.Strophe,
u = converse.env.utils; u = converse.env.utils;
describe("The _converse.api.rooms API", function () { describe("Chatrooms", function () {
describe("The auto_register_muc_nickname option", function () {
it("allows you to register a user with a room", it("allows you to automatically register your nickname when joining a room",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {'auto_register_muc_nickname': true},
function (done, _converse) { function (done, _converse) {
let view; let view;
const room_jid = 'coven@chat.shakespeare.lit'; const room_jid = 'coven@chat.shakespeare.lit';
test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'romeo') test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'romeo')
.then(() => { .then(() => {
view = _converse.chatboxviews.get(room_jid); return test_utils.waitUntil(() => _.get(_.filter(
_converse.api.rooms.register(room_jid, _converse.bare_jid, 'romeo'); _converse.connection.IQ_stanzas,
return test_utils.waitUntil(() => _.get(_.filter( iq => iq.nodeTree.querySelector(
_converse.connection.IQ_stanzas, `iq[to="coven@chat.shakespeare.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]`
iq => iq.nodeTree.querySelector(`iq[to="coven@chat.shakespeare.lit"] query[xmlns="jabber:iq:register"]`) )
).pop(), 'nodeTree')); ).pop(), 'nodeTree'));
}).then(stanza => {
expect(stanza.outerHTML) }).then(stanza => {
.toBe(`<iq from="dummy@localhost" to="coven@chat.shakespeare.lit" `+ view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
`type="get" xmlns="jabber:client" id="${stanza.getAttribute('id')}">`+ spyOn(view.model, 'parseRoomFeatures').and.callThrough();
`<query xmlns="jabber:iq:register"/></iq>`); const features_stanza = $iq({
// Room does not exist 'from': room_jid,
const result = $iq({ 'id': stanza.getAttribute('id'),
'from': view.model.get('jid'), 'to': 'dummy@localhost/desktop',
'id': stanza.getAttribute('id'), 'type': 'result'
'to': _converse.bare_jid, })
'type': 'error', .c('query', { 'xmlns': 'http://jabber.org/protocol/disco#info'})
}).c('error', {'type': "cancel"}) .c('identity', {
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}) 'category': 'conference',
_converse.connection._dataRecv(test_utils.createRequest(result)); 'name': 'A Dark Cave',
done(); 'type': 'text'
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); }).up()
})); .c('feature', {'var': 'http://jabber.org/protocol/muc'}).up()
.c('feature', {'var': 'jabber:iq:register'}).up()
.c('feature', {'var': 'muc_passwordprotected'}).up()
.c('feature', {'var': 'muc_hidden'}).up()
.c('feature', {'var': 'muc_temporary'}).up()
.c('feature', {'var': 'muc_open'}).up()
.c('feature', {'var': 'muc_unmoderated'}).up()
.c('feature', {'var': 'muc_nonanonymous'});
_converse.connection._dataRecv(test_utils.createRequest(features_stanza));
return test_utils.waitUntil(() => view.model.parseRoomFeatures.calls.count(), 300)
}).then(() => {
return test_utils.waitUntil(() => _.get(_.filter(
_converse.connection.IQ_stanzas,
iq => iq.nodeTree.querySelector(`iq[to="coven@chat.shakespeare.lit"] query[xmlns="jabber:iq:register"]`)
).pop(), 'nodeTree'));
}).then(stanza => {
expect(stanza.outerHTML)
.toBe(`<iq from="dummy@localhost" to="coven@chat.shakespeare.lit" `+
`type="get" xmlns="jabber:client" id="${stanza.getAttribute('id')}">`+
`<query xmlns="jabber:iq:register"/></iq>`);
// Room does not exist
view = _converse.chatboxviews.get(room_jid);
const result = $iq({
'from': view.model.get('jid'),
'id': stanza.getAttribute('id'),
'to': _converse.bare_jid,
'type': 'error',
}).c('error', {'type': "cancel"})
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"})
_converse.connection._dataRecv(test_utils.createRequest(result));
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}));
});
}); });
})); }));
...@@ -262,7 +262,7 @@ ...@@ -262,7 +262,7 @@
type: 'groupchat' type: 'groupchat'
}).c('body').t('romeo: Your attention is required').tree() }).c('body').t('romeo: Your attention is required').tree()
); );
return test_utils.waitUntil(() => _converse.rooms_list_view.el.querySelectorAll(".msgs-indicator")); return test_utils.waitUntil(() => _converse.rooms_list_view.el.querySelectorAll(".msgs-indicator").length);
}).then(() => { }).then(() => {
spyOn(view.model, 'incrementUnreadMsgCounter').and.callThrough(); spyOn(view.model, 'incrementUnreadMsgCounter').and.callThrough();
const indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator"); const indicator_el = _converse.rooms_list_view.el.querySelector(".msgs-indicator");
......
...@@ -1203,33 +1203,21 @@ ...@@ -1203,33 +1203,21 @@
* If so, we'll use that, otherwise we render the nickname form. * If so, we'll use that, otherwise we render the nickname form.
*/ */
this.showSpinner(); this.showSpinner();
this.model.checkForReservedNick( this.model.checkForReservedNick()
this.onReservedNicknameFound.bind(this), .then(this.onReservedNickFound.bind(this))
this.onReservedNicknameNotFound.bind(this) .catch(this.onReservedNickNotFound.bind(this));
) },
},
onReservedNickFound (iq) {
onReservedNicknameFound (iq) { if (this.model.get('nick')) {
/* We've received an IQ response from the server which this.join();
* might contain the user's reserved nickname.
* If no nickname is found we either render a form for
* them to specify one, or we try to join the groupchat with the
* node of the user's JID.
*
* Parameters:
* (XMLElement) iq: The received IQ stanza
*/
const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity'),
nick = identity_el ? identity_el.getAttribute('name') : null;
if (!nick) {
this.onNickNameNotFound();
} else { } else {
this.join(nick); this.onReservedNickNotFound();
} }
}, },
onReservedNicknameNotFound (message) { onReservedNickNotFound (message) {
const nick = this.getDefaultNickName(); const nick = this.model.getDefaultNick();
if (nick) { if (nick) {
this.join(nick); this.join(nick);
} else { } else {
...@@ -1237,20 +1225,6 @@ ...@@ -1237,20 +1225,6 @@
} }
}, },
getDefaultNickName () {
/* The default nickname (used when muc_nickname_from_jid is true)
* is the node part of the user's JID.
* We put this in a separate method so that it can be
* overridden by plugins.
*/
const nick = _converse.xmppstatus.vcard.get('nickname');
if (nick) {
return nick;
} else if (_converse.muc_nickname_from_jid) {
return Strophe.unescapeNode(Strophe.getNodeFromJid(_converse.bare_jid));
}
},
onNicknameClash (presence) { onNicknameClash (presence) {
/* When the nickname is already taken, we either render a /* When the nickname is already taken, we either render a
* form for the user to choose a new nickname, or we * form for the user to choose a new nickname, or we
...@@ -1262,7 +1236,7 @@ ...@@ -1262,7 +1236,7 @@
*/ */
if (_converse.muc_nickname_from_jid) { if (_converse.muc_nickname_from_jid) {
const nick = presence.getAttribute('from').split('/')[1]; const nick = presence.getAttribute('from').split('/')[1];
if (nick === this.getDefaultNickName()) { if (nick === this.model.getDefaultNick()) {
this.join(nick + '-2'); this.join(nick + '-2');
} else { } else {
const del= nick.lastIndexOf("-"); const del= nick.lastIndexOf("-");
......
...@@ -406,17 +406,17 @@ ...@@ -406,17 +406,17 @@
getRoomFeatures () { getRoomFeatures () {
/* Fetch the groupchat disco info, parse it and then save it. /* Fetch the groupchat disco info, parse it and then save it.
*/ */
return new Promise((resolve, reject) => { // XXX: Currently we store disco info on the room itself.
_converse.api.disco.info(this.get('jid'), null) // A better design would probably be to create a
.then((stanza) => { // DiscoEntity for this room, and then to let
this.parseRoomFeatures(stanza); // converse-disco manage all disco-related tasks.
resolve() // Then we can also use _converse.api.disco.supports.
}).catch((err) => { return _converse.api.disco.info(this.get('jid'), null)
_converse.log("Could not parse the groupchat features", Strophe.LogLevel.WARN); .then(stanza => this.parseRoomFeatures(stanza))
_converse.log(err, Strophe.LogLevel.WARN); .catch(err => {
reject(err); _converse.log("Could not parse the groupchat features", Strophe.LogLevel.WARN);
}); _converse.log(err, Strophe.LogLevel.WARN);
}); });
}, },
getRoomJIDAndNick (nick) { getRoomJIDAndNick (nick) {
...@@ -791,7 +791,21 @@ ...@@ -791,7 +791,21 @@
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR)); .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
}, },
checkForReservedNick (callback, errback) { getDefaultNick () {
/* The default nickname (used when muc_nickname_from_jid is true)
* is the node part of the user's JID.
* We put this in a separate method so that it can be
* overridden by plugins.
*/
const nick = _converse.xmppstatus.vcard.get('nickname');
if (nick) {
return nick;
} else if (_converse.muc_nickname_from_jid) {
return Strophe.unescapeNode(Strophe.getNodeFromJid(_converse.bare_jid));
}
},
checkForReservedNick () {
/* Use service-discovery to ask the XMPP server whether /* Use service-discovery to ask the XMPP server whether
* this user has a reserved nickname for this groupchat. * this user has a reserved nickname for this groupchat.
* If so, we'll use that, otherwise we render the nickname form. * If so, we'll use that, otherwise we render the nickname form.
...@@ -800,7 +814,7 @@ ...@@ -800,7 +814,7 @@
* (Function) callback: Callback upon succesful IQ response * (Function) callback: Callback upon succesful IQ response
* (Function) errback: Callback upon error IQ response * (Function) errback: Callback upon error IQ response
*/ */
_converse.connection.sendIQ( return _converse.api.sendIQ(
$iq({ $iq({
'to': this.get('jid'), 'to': this.get('jid'),
'from': _converse.connection.jid, 'from': _converse.connection.jid,
...@@ -808,9 +822,16 @@ ...@@ -808,9 +822,16 @@
}).c("query", { }).c("query", {
'xmlns': Strophe.NS.DISCO_INFO, 'xmlns': Strophe.NS.DISCO_INFO,
'node': 'x-roomuser-item' 'node': 'x-roomuser-item'
}), })
callback, errback); ).then(iq => {
return this; const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity'),
nick = identity_el ? identity_el.getAttribute('name') : null;
this.save({
'reserved_nick': nick,
'nick': nick
}, {'silent': true});
return iq;
});
}, },
async registerNickname () { async registerNickname () {
......
...@@ -126,61 +126,60 @@ ...@@ -126,61 +126,60 @@
}; };
utils.openAndEnterChatRoom = function (_converse, room, server, nick) { utils.openAndEnterChatRoom = function (_converse, room, server, nick) {
let last_stanza; let last_stanza, view;
return new Promise((resolve, reject) => { return _converse.api.rooms.open(`${room}@${server}`).then(() => {
return _converse.api.rooms.open(`${room}@${server}`).then(() => { view = _converse.chatboxviews.get((room+'@'+server).toLowerCase());
const view = _converse.chatboxviews.get((room+'@'+server).toLowerCase()); // We pretend this is a new room, so no disco info is returned.
// We pretend this is a new room, so no disco info is returned. last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree;
let last_stanza = _.last(_converse.connection.IQ_stanzas).nodeTree; const IQ_id = last_stanza.getAttribute('id');
const IQ_id = last_stanza.getAttribute('id'); const features_stanza = $iq({
const features_stanza = $iq({ 'from': room+'@'+server,
'from': room+'@'+server, 'id': IQ_id,
'id': IQ_id, 'to': nick+'@'+server,
'to': nick+'@'+server, 'type': 'error'
'type': 'error' }).c('error', {'type': 'cancel'})
}).c('error', {'type': 'cancel'}) .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}); _converse.connection._dataRecv(utils.createRequest(features_stanza));
_converse.connection._dataRecv(utils.createRequest(features_stanza)); return utils.waitUntil(() => {
return _.filter(
utils.waitUntil(() => { _converse.connection.IQ_stanzas, (node) => {
return _.filter( const query = node.nodeTree.querySelector('query');
_converse.connection.IQ_stanzas, (node) => { if (query && query.getAttribute('node') === 'x-roomuser-item') {
const query = node.nodeTree.querySelector('query'); last_stanza = node.nodeTree;
if (query && query.getAttribute('node') === 'x-roomuser-item') { return true;
last_stanza = node.nodeTree; }
return true; }).length
} });
}).length }).then(() => {
}).then(function () { // The XMPP server returns the reserved nick for this user.
// The XMPP server returns the reserved nick for this user. const IQ_id = last_stanza.getAttribute('id');
const IQ_id = last_stanza.getAttribute('id'); const stanza = $iq({
const stanza = $iq({ 'type': 'result',
'type': 'result', 'id': IQ_id,
'id': IQ_id, 'from': view.model.get('jid'),
'from': view.model.get('jid'), 'to': _converse.connection.jid
'to': _converse.connection.jid }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info', 'node': 'x-roomuser-item'})
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info', 'node': 'x-roomuser-item'}) .c('identity', {'category': 'conference', 'name': nick, 'type': 'text'});
.c('identity', {'category': 'conference', 'name': nick, 'type': 'text'}); _converse.connection._dataRecv(utils.createRequest(stanza));
_converse.connection._dataRecv(utils.createRequest(stanza)); return utils.waitUntil(() => view.model.get('nick'));
// The user has just entered the room (because join was called) }).then(() => {
// and receives their own presence from the server. // The user has just entered the room (because join was called)
// See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres // and receives their own presence from the server.
var presence = $pres({ // See example 24: http://xmpp.org/extensions/xep-0045.html#enter-pres
to: _converse.connection.jid, var presence = $pres({
from: room+'@'+server+'/'+nick, to: _converse.connection.jid,
id: 'DC352437-C019-40EC-B590-AF29E879AF97' from: room+'@'+server+'/'+nick,
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'}) id: 'DC352437-C019-40EC-B590-AF29E879AF97'
.c('item').attrs({ }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
affiliation: 'owner', .c('item').attrs({
jid: _converse.bare_jid, affiliation: 'owner',
role: 'moderator' jid: _converse.bare_jid,
}).up() role: 'moderator'
.c('status').attrs({code:'110'}); }).up()
_converse.connection._dataRecv(utils.createRequest(presence)); .c('status').attrs({code:'110'});
resolve(); _converse.connection._dataRecv(utils.createRequest(presence));
}).catch(_.partial(console.error, _)); return utils.waitUntil(() => view.model.get('connection_status') === converse.ROOMSTATUS.ENTERED);
}).catch(_.partial(console.error, _));
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment