2016-02-16 08:46:47 +01:00
|
|
|
// Converse.js (A browser based XMPP chat client)
|
|
|
|
// http://conversejs.org
|
|
|
|
//
|
2017-02-13 15:37:17 +01:00
|
|
|
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
|
2016-02-16 08:46:47 +01:00
|
|
|
// Licensed under the Mozilla Public License (MPLv2)
|
|
|
|
//
|
2017-04-21 15:52:16 +02:00
|
|
|
/*global define */
|
2016-02-16 08:46:47 +01:00
|
|
|
|
2016-02-13 23:58:50 +01:00
|
|
|
/* This is a Converse.js plugin which add support for multi-user chat rooms, as
|
|
|
|
* specified in XEP-0045 Multi-user chat.
|
|
|
|
*/
|
2016-02-16 08:46:47 +01:00
|
|
|
(function (root, factory) {
|
2017-02-13 15:37:17 +01:00
|
|
|
define([
|
2017-08-16 15:19:41 +02:00
|
|
|
"form-utils",
|
2017-02-14 15:08:39 +01:00
|
|
|
"converse-core",
|
2017-08-15 16:46:55 +02:00
|
|
|
"lodash.fp",
|
2017-07-21 12:41:16 +02:00
|
|
|
"converse-chatview",
|
2017-11-10 21:20:13 +01:00
|
|
|
"converse-disco",
|
2017-12-20 20:29:57 +01:00
|
|
|
"backbone.overview",
|
|
|
|
"backbone.orderedlistview",
|
2017-11-10 21:20:13 +01:00
|
|
|
"backbone.vdomview"
|
2016-02-28 20:24:06 +01:00
|
|
|
], factory);
|
2018-02-21 22:40:51 +01:00
|
|
|
}(this, function (u, converse, fp) {
|
2016-02-19 11:43:46 +01:00
|
|
|
"use strict";
|
2016-11-02 23:08:20 +01:00
|
|
|
|
2017-12-14 18:43:00 +01:00
|
|
|
const MUC_ROLE_WEIGHTS = {
|
|
|
|
'moderator': 1,
|
|
|
|
'participant': 2,
|
|
|
|
'visitor': 3,
|
|
|
|
'none': 4,
|
|
|
|
};
|
|
|
|
|
2017-08-16 15:19:41 +02:00
|
|
|
const { Strophe, Backbone, Promise, $iq, $build, $msg, $pres, b64_sha1, sizzle, _, moment } = converse.env;
|
2016-02-16 08:46:47 +01:00
|
|
|
|
|
|
|
// Add Strophe Namespaces
|
|
|
|
Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");
|
|
|
|
Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC + "#owner");
|
|
|
|
Strophe.addNamespace('MUC_REGISTER', "jabber:iq:register");
|
|
|
|
Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig");
|
|
|
|
Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user");
|
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
converse.CHATROOMS_TYPE = 'chatroom';
|
|
|
|
|
|
|
|
converse.ROOM_FEATURES = [
|
2017-02-28 22:34:16 +01:00
|
|
|
'passwordprotected', 'unsecured', 'hidden',
|
2017-11-05 18:47:30 +01:00
|
|
|
'publicroom', 'membersonly', 'open', 'persistent',
|
2017-02-28 22:34:16 +01:00
|
|
|
'temporary', 'nonanonymous', 'semianonymous',
|
|
|
|
'moderated', 'unmoderated', 'mam_enabled'
|
|
|
|
];
|
2017-07-21 15:05:22 +02:00
|
|
|
|
|
|
|
converse.ROOMSTATUS = {
|
2017-02-24 11:54:54 +01:00
|
|
|
CONNECTED: 0,
|
|
|
|
CONNECTING: 1,
|
2017-03-02 23:28:22 +01:00
|
|
|
NICKNAME_REQUIRED: 2,
|
2017-04-04 16:45:50 +02:00
|
|
|
PASSWORD_REQUIRED: 3,
|
|
|
|
DISCONNECTED: 4,
|
|
|
|
ENTERED: 5
|
2017-02-24 11:54:54 +01:00
|
|
|
};
|
|
|
|
|
2016-12-20 11:42:20 +01:00
|
|
|
converse.plugins.add('converse-muc', {
|
2016-06-10 00:05:55 +02:00
|
|
|
/* Optional dependencies are other plugins which might be
|
2017-03-08 12:15:19 +01:00
|
|
|
* overridden or relied upon, and therefore need to be loaded before
|
|
|
|
* this plugin. They are called "optional" because they might not be
|
|
|
|
* available, in which case any overrides applicable to them will be
|
|
|
|
* ignored.
|
2016-06-09 11:01:54 +02:00
|
|
|
*
|
2017-03-08 12:15:19 +01:00
|
|
|
* It's possible however to make optional dependencies non-optional.
|
|
|
|
* If the setting "strict_plugin_dependencies" is set to true,
|
2016-06-10 00:05:55 +02:00
|
|
|
* an error will be raised if the plugin is not found.
|
2016-06-09 11:01:54 +02:00
|
|
|
*
|
2016-06-10 00:05:55 +02:00
|
|
|
* NB: These plugins need to have already been loaded via require.js.
|
2016-06-09 11:01:54 +02:00
|
|
|
*/
|
2018-01-10 13:59:45 +01:00
|
|
|
dependencies: ["converse-controlbox", "converse-chatview"],
|
2016-02-16 08:46:47 +01:00
|
|
|
|
|
|
|
overrides: {
|
|
|
|
// Overrides mentioned here will be picked up by converse.js's
|
|
|
|
// plugin architecture they will replace existing methods on the
|
|
|
|
// relevant objects or classes.
|
|
|
|
//
|
|
|
|
// New functions which don't exist yet can also be added.
|
2016-02-13 23:58:50 +01:00
|
|
|
|
2017-07-10 17:46:22 +02:00
|
|
|
_tearDown () {
|
2018-02-21 22:40:51 +01:00
|
|
|
const rooms = this.chatboxes.where({'type': converse.CHATROOMS_TYPE});
|
2017-06-23 18:21:50 +02:00
|
|
|
_.each(rooms, function (room) {
|
2017-12-06 14:59:01 +01:00
|
|
|
u.safeSave(room, {'connection_status': converse.ROOMSTATUS.DISCONNECTED});
|
2017-06-23 18:21:50 +02:00
|
|
|
});
|
|
|
|
this.__super__._tearDown.call(this, arguments);
|
|
|
|
},
|
|
|
|
|
2017-05-23 18:16:47 +02:00
|
|
|
ChatBoxes: {
|
2017-07-10 17:46:22 +02:00
|
|
|
model (attrs, options) {
|
|
|
|
const { _converse } = this.__super__;
|
2018-02-21 22:40:51 +01:00
|
|
|
if (attrs.type == converse.CHATROOMS_TYPE) {
|
2017-05-23 18:36:40 +02:00
|
|
|
return new _converse.ChatRoom(attrs, options);
|
2017-05-23 18:16:47 +02:00
|
|
|
} else {
|
|
|
|
return this.__super__.model.apply(this, arguments);
|
|
|
|
}
|
|
|
|
},
|
2016-02-28 20:24:06 +01:00
|
|
|
}
|
2016-02-16 08:46:47 +01:00
|
|
|
},
|
|
|
|
|
2017-07-10 17:46:22 +02:00
|
|
|
initialize () {
|
2016-02-16 08:46:47 +01:00
|
|
|
/* The initialize function gets called as soon as the plugin is
|
|
|
|
* loaded by converse.js's plugin machinery.
|
|
|
|
*/
|
2017-07-10 17:46:22 +02:00
|
|
|
const { _converse } = this,
|
2017-09-26 18:27:41 +02:00
|
|
|
{ __ } = _converse;
|
|
|
|
|
|
|
|
function ___ (str) {
|
|
|
|
/* This is part of a hack to get gettext to scan strings to be
|
|
|
|
* translated. Strings we cannot send to the function above because
|
|
|
|
* they require variable interpolation and we don't yet have the
|
|
|
|
* variables at scan time.
|
|
|
|
*
|
|
|
|
* See actionInfoMessages further below.
|
|
|
|
*/
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2016-12-04 17:53:35 +01:00
|
|
|
// XXX: Inside plugins, all calls to the translation machinery
|
2017-12-06 14:59:01 +01:00
|
|
|
// (e.g. u.__) should only be done in the initialize function.
|
2016-12-04 17:53:35 +01:00
|
|
|
// If called before, we won't know what language the user wants,
|
2017-02-19 10:58:30 +01:00
|
|
|
// and it'll fall back to English.
|
2016-12-04 17:53:35 +01:00
|
|
|
|
|
|
|
/* http://xmpp.org/extensions/xep-0045.html
|
|
|
|
* ----------------------------------------
|
|
|
|
* 100 message Entering a room Inform user that any occupant is allowed to see the user's full JID
|
|
|
|
* 101 message (out of band) Affiliation change Inform user that his or her affiliation changed while not in the room
|
|
|
|
* 102 message Configuration change Inform occupants that room now shows unavailable members
|
|
|
|
* 103 message Configuration change Inform occupants that room now does not show unavailable members
|
|
|
|
* 104 message Configuration change Inform occupants that a non-privacy-related room configuration change has occurred
|
|
|
|
* 110 presence Any room presence Inform user that presence refers to one of its own room occupants
|
|
|
|
* 170 message or initial presence Configuration change Inform occupants that room logging is now enabled
|
|
|
|
* 171 message Configuration change Inform occupants that room logging is now disabled
|
|
|
|
* 172 message Configuration change Inform occupants that the room is now non-anonymous
|
|
|
|
* 173 message Configuration change Inform occupants that the room is now semi-anonymous
|
|
|
|
* 174 message Configuration change Inform occupants that the room is now fully-anonymous
|
|
|
|
* 201 presence Entering a room Inform user that a new room has been created
|
|
|
|
* 210 presence Entering a room Inform user that the service has assigned or modified the occupant's roomnick
|
|
|
|
* 301 presence Removal from room Inform user that he or she has been banned from the room
|
|
|
|
* 303 presence Exiting a room Inform all occupants of new room nickname
|
|
|
|
* 307 presence Removal from room Inform user that he or she has been kicked from the room
|
|
|
|
* 321 presence Removal from room Inform user that he or she is being removed from the room because of an affiliation change
|
|
|
|
* 322 presence Removal from room Inform user that he or she is being removed from the room because the room has been changed to members-only and the user is not a member
|
|
|
|
* 332 presence Removal from room Inform user that he or she is being removed from the room because of a system shutdown
|
|
|
|
*/
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.muc = {
|
2016-12-04 17:53:35 +01:00
|
|
|
info_messages: {
|
|
|
|
100: __('This room is not anonymous'),
|
|
|
|
102: __('This room now shows unavailable members'),
|
|
|
|
103: __('This room does not show unavailable members'),
|
|
|
|
104: __('The room configuration has changed'),
|
|
|
|
170: __('Room logging is now enabled'),
|
|
|
|
171: __('Room logging is now disabled'),
|
|
|
|
172: __('This room is now no longer anonymous'),
|
|
|
|
173: __('This room is now semi-anonymous'),
|
|
|
|
174: __('This room is now fully-anonymous'),
|
|
|
|
201: __('A new room has been created')
|
|
|
|
},
|
|
|
|
|
|
|
|
disconnect_messages: {
|
|
|
|
301: __('You have been banned from this room'),
|
|
|
|
307: __('You have been kicked from this room'),
|
|
|
|
321: __("You have been removed from this room because of an affiliation change"),
|
|
|
|
322: __("You have been removed from this room because the room has changed to members-only and you're not a member"),
|
2017-09-22 10:45:03 +02:00
|
|
|
332: __("You have been removed from this room because the MUC (Multi-user chat) service is being shut down")
|
2016-12-04 17:53:35 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
action_info_messages: {
|
|
|
|
/* XXX: Note the triple underscore function and not double
|
|
|
|
* underscore.
|
|
|
|
*
|
|
|
|
* This is a hack. We can't pass the strings to __ because we
|
|
|
|
* don't yet know what the variable to interpolate is.
|
|
|
|
*
|
|
|
|
* Triple underscore will just return the string again, but we
|
|
|
|
* can then at least tell gettext to scan for it so that these
|
|
|
|
* strings are picked up by the translation machinery.
|
|
|
|
*/
|
2017-02-13 09:23:42 +01:00
|
|
|
301: ___("%1$s has been banned"),
|
|
|
|
303: ___("%1$s's nickname has changed"),
|
|
|
|
307: ___("%1$s has been kicked out"),
|
|
|
|
321: ___("%1$s has been removed because of an affiliation change"),
|
|
|
|
322: ___("%1$s has been removed for not being a member")
|
2016-12-04 17:53:35 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
new_nickname_messages: {
|
2017-09-24 20:36:39 +02:00
|
|
|
210: ___('Your nickname has been automatically set to %1$s'),
|
|
|
|
303: ___('Your nickname has been changed to %1$s')
|
2016-12-04 17:53:35 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-02-16 08:46:47 +01:00
|
|
|
// Configuration values for this plugin
|
2016-08-11 18:03:02 +02:00
|
|
|
// ====================================
|
|
|
|
// Refer to docs/source/configuration.rst for explanations of these
|
|
|
|
// configuration settings.
|
2017-07-05 11:03:13 +02:00
|
|
|
_converse.api.settings.update({
|
2016-02-13 23:58:50 +01:00
|
|
|
allow_muc: true,
|
2016-08-11 18:03:02 +02:00
|
|
|
allow_muc_invitations: true,
|
|
|
|
auto_join_on_invite: false,
|
|
|
|
auto_join_rooms: [],
|
2016-03-17 13:24:26 +01:00
|
|
|
auto_list_rooms: false,
|
2016-02-19 10:36:01 +01:00
|
|
|
hide_muc_server: false,
|
2016-12-07 14:48:47 +01:00
|
|
|
muc_disable_moderator_commands: false,
|
2016-10-26 15:21:36 +02:00
|
|
|
muc_domain: undefined,
|
2016-08-11 18:03:02 +02:00
|
|
|
muc_history_max_stanzas: undefined,
|
|
|
|
muc_instant_rooms: true,
|
2016-10-27 13:30:58 +02:00
|
|
|
muc_nickname_from_jid: false,
|
2017-02-24 11:54:54 +01:00
|
|
|
muc_show_join_leave: true,
|
2016-10-27 13:30:58 +02:00
|
|
|
visible_toolbar_buttons: {
|
|
|
|
'toggle_occupants': true
|
|
|
|
},
|
2016-03-13 17:16:53 +01:00
|
|
|
});
|
2018-02-21 22:40:51 +01:00
|
|
|
_converse.api.promises.add(['roomsAutoJoined']);
|
2017-09-29 00:07:16 +02:00
|
|
|
|
2017-10-31 22:08:06 +01:00
|
|
|
|
2017-10-31 23:04:46 +01:00
|
|
|
function openRoom (jid) {
|
2018-01-29 14:51:49 +01:00
|
|
|
if (!u.isValidMUCJID(jid)) {
|
|
|
|
return _converse.log(
|
2017-10-31 23:04:46 +01:00
|
|
|
`Invalid JID "${jid}" provided in URL fragment`,
|
|
|
|
Strophe.LogLevel.WARN
|
|
|
|
);
|
|
|
|
}
|
2017-10-31 22:08:06 +01:00
|
|
|
const promises = [_converse.api.waitUntil('roomsAutoJoined')]
|
2018-02-07 17:30:44 +01:00
|
|
|
if (_converse.allow_bookmarks) {
|
|
|
|
promises.push( _converse.api.waitUntil('bookmarksInitialized'));
|
|
|
|
}
|
2017-10-31 22:08:06 +01:00
|
|
|
Promise.all(promises).then(() => {
|
2017-10-31 23:04:46 +01:00
|
|
|
_converse.api.rooms.open(jid);
|
2017-10-31 22:08:06 +01:00
|
|
|
});
|
|
|
|
}
|
2017-10-31 23:04:46 +01:00
|
|
|
_converse.router.route('converse/room?jid=:jid', openRoom);
|
2017-09-29 00:07:16 +02:00
|
|
|
|
2017-05-07 20:16:13 +02:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
_converse.openChatRoom = function (jid, settings, bring_to_foreground) {
|
2017-06-15 16:22:49 +02:00
|
|
|
/* Opens a chat room, making sure that certain attributes
|
2016-12-04 10:43:39 +01:00
|
|
|
* are correct, for example that the "type" is set to
|
|
|
|
* "chatroom".
|
|
|
|
*/
|
2018-02-21 22:40:51 +01:00
|
|
|
settings.type = converse.CHATROOMS_TYPE;
|
|
|
|
settings.id = jid;
|
|
|
|
settings.box_id = b64_sha1(jid)
|
|
|
|
const chatbox = _converse.chatboxes.getChatBox(jid, settings, true);
|
|
|
|
chatbox.trigger('show', true);
|
|
|
|
return chatbox;
|
2017-10-31 22:07:40 +01:00
|
|
|
}
|
2016-02-16 08:46:47 +01:00
|
|
|
|
2017-05-23 18:36:40 +02:00
|
|
|
_converse.ChatRoom = _converse.ChatBox.extend({
|
|
|
|
|
2017-07-10 17:46:22 +02:00
|
|
|
defaults () {
|
2017-06-15 16:22:49 +02:00
|
|
|
return _.assign(
|
|
|
|
_.clone(_converse.ChatBox.prototype.defaults),
|
2018-02-21 22:40:51 +01:00
|
|
|
_.zipObject(converse.ROOM_FEATURES, _.map(converse.ROOM_FEATURES, _.stubFalse)),
|
2017-06-15 16:22:49 +02:00
|
|
|
{
|
|
|
|
// For group chats, we distinguish between generally unread
|
|
|
|
// messages and those ones that specifically mention the
|
|
|
|
// user.
|
|
|
|
//
|
|
|
|
// To keep things simple, we reuse `num_unread` from
|
|
|
|
// _converse.ChatBox to indicate unread messages which
|
|
|
|
// mention the user and `num_unread_general` to indicate
|
|
|
|
// generally unread messages (which *includes* mentions!).
|
|
|
|
'num_unread_general': 0,
|
|
|
|
|
|
|
|
'affiliation': null,
|
2017-07-21 15:05:22 +02:00
|
|
|
'connection_status': converse.ROOMSTATUS.DISCONNECTED,
|
2017-07-19 08:30:04 +02:00
|
|
|
'name': '',
|
2017-06-15 16:22:49 +02:00
|
|
|
'description': '',
|
|
|
|
'features_fetched': false,
|
|
|
|
'roomconfig': {},
|
2018-02-21 22:40:51 +01:00
|
|
|
'type': converse.CHATROOMS_TYPE,
|
2017-06-15 16:22:49 +02:00
|
|
|
}
|
|
|
|
);
|
2017-06-07 17:47:06 +02:00
|
|
|
},
|
2017-05-24 08:40:09 +02:00
|
|
|
|
2017-07-10 17:46:22 +02:00
|
|
|
isUserMentioned (message) {
|
2017-05-23 18:36:40 +02:00
|
|
|
/* Returns a boolean to indicate whether the current user
|
|
|
|
* was mentioned in a message.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (String): The text message
|
|
|
|
*/
|
2017-07-10 17:46:22 +02:00
|
|
|
return (new RegExp(`\\b${this.get('nick')}\\b`)).test(message);
|
2017-05-23 18:36:40 +02:00
|
|
|
},
|
|
|
|
|
2017-07-10 17:46:22 +02:00
|
|
|
incrementUnreadMsgCounter (stanza) {
|
2017-05-23 18:36:40 +02:00
|
|
|
/* Given a newly received message, update the unread counter if
|
|
|
|
* necessary.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (XMLElement): The <messsage> stanza
|
|
|
|
*/
|
2017-06-12 20:30:58 +02:00
|
|
|
const body = stanza.querySelector('body');
|
2017-05-23 18:36:40 +02:00
|
|
|
if (_.isNull(body)) {
|
|
|
|
return; // The message has no text
|
|
|
|
}
|
2017-12-06 14:59:01 +01:00
|
|
|
if (u.isNewMessage(stanza) && this.newMessageWillBeHidden()) {
|
2017-05-24 08:40:09 +02:00
|
|
|
this.save({'num_unread_general': this.get('num_unread_general') + 1});
|
|
|
|
if (this.isUserMentioned(body.textContent)) {
|
|
|
|
this.save({'num_unread': this.get('num_unread') + 1});
|
|
|
|
_converse.incrementMsgCounter();
|
|
|
|
}
|
2017-05-23 18:36:40 +02:00
|
|
|
}
|
|
|
|
},
|
2017-05-24 08:40:09 +02:00
|
|
|
|
2017-07-10 17:46:22 +02:00
|
|
|
clearUnreadMsgCounter() {
|
2017-12-06 14:59:01 +01:00
|
|
|
u.safeSave(this, {
|
2017-06-19 11:08:57 +02:00
|
|
|
'num_unread': 0,
|
|
|
|
'num_unread_general': 0
|
|
|
|
});
|
2017-05-24 08:40:09 +02:00
|
|
|
}
|
2017-05-23 18:36:40 +02:00
|
|
|
});
|
|
|
|
|
2016-02-16 08:46:47 +01:00
|
|
|
|
2018-02-21 22:29:21 +01:00
|
|
|
_converse.ChatRoomOccupant = Backbone.Model.extend({
|
|
|
|
initialize (attributes) {
|
|
|
|
this.set(_.extend({
|
|
|
|
'id': _converse.connection.getUniqueId(),
|
|
|
|
}, attributes));
|
|
|
|
}
|
|
|
|
});
|
2017-12-14 14:07:39 +01:00
|
|
|
|
2017-12-07 07:05:37 +01:00
|
|
|
|
2018-02-21 22:29:21 +01:00
|
|
|
_converse.ChatRoomOccupants = Backbone.Collection.extend({
|
|
|
|
model: _converse.ChatRoomOccupant,
|
2017-02-18 11:03:26 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
comparator (occupant1, occupant2) {
|
|
|
|
const role1 = occupant1.get('role') || 'none';
|
|
|
|
const role2 = occupant2.get('role') || 'none';
|
|
|
|
if (MUC_ROLE_WEIGHTS[role1] === MUC_ROLE_WEIGHTS[role2]) {
|
|
|
|
const nick1 = occupant1.get('nick').toLowerCase();
|
|
|
|
const nick2 = occupant2.get('nick').toLowerCase();
|
|
|
|
return nick1 < nick2 ? -1 : (nick1 > nick2? 1 : 0);
|
|
|
|
} else {
|
|
|
|
return MUC_ROLE_WEIGHTS[role1] < MUC_ROLE_WEIGHTS[role2] ? -1 : 1;
|
2017-02-17 22:17:19 +01:00
|
|
|
}
|
|
|
|
},
|
2018-02-21 22:40:51 +01:00
|
|
|
});
|
2017-02-17 22:17:19 +01:00
|
|
|
|
2017-12-20 11:02:01 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
_converse.RoomsPanelModel = Backbone.Model.extend({
|
|
|
|
defaults: {
|
|
|
|
'muc_domain': '',
|
2017-02-17 22:17:19 +01:00
|
|
|
},
|
2018-02-21 22:40:51 +01:00
|
|
|
});
|
2017-02-17 22:17:19 +01:00
|
|
|
|
2017-02-15 21:30:32 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
_converse.onDirectMUCInvitation = function (message) {
|
|
|
|
/* A direct MUC invitation to join a room has been received
|
|
|
|
* See XEP-0249: Direct MUC invitations.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* (XMLElement) message: The message stanza containing the
|
|
|
|
* invitation.
|
|
|
|
*/
|
|
|
|
const x_el = message.querySelector('x[xmlns="jabber:x:conference"]'),
|
|
|
|
from = Strophe.getBareJidFromJid(message.getAttribute('from')),
|
|
|
|
room_jid = x_el.getAttribute('jid'),
|
|
|
|
reason = x_el.getAttribute('reason');
|
2016-10-27 13:30:58 +02:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
let contact = _converse.roster.get(from),
|
|
|
|
result;
|
2016-03-28 13:42:33 +02:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
if (_converse.auto_join_on_invite) {
|
|
|
|
result = true;
|
|
|
|
} else {
|
|
|
|
// Invite request might come from someone not your roster list
|
|
|
|
contact = contact? contact.get('fullname'): Strophe.getNodeFromJid(from);
|
|
|
|
if (!reason) {
|
|
|
|
result = confirm(
|
|
|
|
__("%1$s has invited you to join a chat room: %2$s", contact, room_jid)
|
|
|
|
);
|
2017-12-14 18:30:05 +01:00
|
|
|
} else {
|
2018-02-21 22:40:51 +01:00
|
|
|
result = confirm(
|
|
|
|
__('%1$s has invited you to join a chat room: %2$s, and left the following reason: "%3$s"',
|
|
|
|
contact, room_jid, reason)
|
2017-07-10 17:46:22 +02:00
|
|
|
);
|
2016-12-06 16:18:33 +01:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
}
|
|
|
|
if (result === true) {
|
|
|
|
const chatroom = _converse.openChatRoom(
|
|
|
|
room_jid, {'password': x_el.getAttribute('password') });
|
2016-12-07 11:34:02 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
if (chatroom.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) {
|
|
|
|
_converse.chatboxviews.get(room_jid).join();
|
2016-12-06 21:04:08 +01:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
}
|
|
|
|
};
|
2016-12-06 21:04:08 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
if (_converse.allow_muc_invitations) {
|
|
|
|
const registerDirectInvitationHandler = function () {
|
|
|
|
_converse.connection.addHandler(
|
|
|
|
function (message) {
|
|
|
|
_converse.onDirectMUCInvitation(message);
|
|
|
|
return true;
|
|
|
|
}, 'jabber:x:conference', 'message');
|
|
|
|
};
|
|
|
|
_converse.on('connected', registerDirectInvitationHandler);
|
|
|
|
_converse.on('reconnected', registerDirectInvitationHandler);
|
|
|
|
}
|
2016-12-06 16:18:33 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
const getChatRoom = function (jid, attrs, create) {
|
|
|
|
jid = jid.toLowerCase();
|
|
|
|
attrs.type = converse.CHATROOMS_TYPE;
|
|
|
|
attrs.id = jid;
|
|
|
|
attrs.box_id = b64_sha1(jid)
|
|
|
|
return _converse.chatboxes.getChatBox(jid, attrs, create);
|
|
|
|
};
|
2016-02-16 08:46:47 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
const createChatRoom = function (jid, attrs) {
|
|
|
|
return getChatRoom(jid, attrs, true);
|
|
|
|
};
|
2016-08-12 14:52:33 +02:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
function autoJoinRooms () {
|
|
|
|
/* Automatically join chat rooms, based on the
|
|
|
|
* "auto_join_rooms" configuration setting, which is an array
|
|
|
|
* of strings (room JIDs) or objects (with room JID and other
|
|
|
|
* settings).
|
|
|
|
*/
|
|
|
|
_.each(_converse.auto_join_rooms, function (room) {
|
|
|
|
if (_converse.chatboxes.where({'jid': room}).length) {
|
2017-02-17 22:17:19 +01:00
|
|
|
return;
|
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
if (_.isString(room)) {
|
|
|
|
_converse.api.rooms.open(room);
|
|
|
|
} else if (_.isObject(room)) {
|
|
|
|
_converse.api.rooms.open(room.jid, room.nick);
|
|
|
|
} else {
|
|
|
|
_converse.log(
|
|
|
|
'Invalid room criteria specified for "auto_join_rooms"',
|
|
|
|
Strophe.LogLevel.ERROR);
|
2016-08-12 16:40:04 +02:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
});
|
|
|
|
_converse.emit('roomsAutoJoined');
|
|
|
|
}
|
2016-02-16 08:46:47 +01:00
|
|
|
|
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
function reconnectToChatRooms () {
|
|
|
|
/* Upon a reconnection event from converse, join again
|
|
|
|
* all the open chat rooms.
|
|
|
|
*/
|
|
|
|
_converse.chatboxviews.each(function (view) {
|
|
|
|
if (view.model.get('type') === converse.CHATROOMS_TYPE) {
|
|
|
|
view.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
|
|
|
|
view.registerHandlers();
|
|
|
|
view.join();
|
|
|
|
view.fetchMessages();
|
2016-02-16 08:46:47 +01:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
});
|
|
|
|
}
|
2016-02-16 08:46:47 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
function disconnectChatRooms () {
|
|
|
|
/* When disconnecting, or reconnecting, mark all chat rooms as
|
|
|
|
* disconnected, so that they will be properly entered again
|
|
|
|
* when fetched from session storage.
|
|
|
|
*/
|
|
|
|
_converse.chatboxes.each(function (model) {
|
|
|
|
if (model.get('type') === converse.CHATROOMS_TYPE) {
|
|
|
|
model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
|
2016-03-16 10:03:00 +01:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
});
|
|
|
|
}
|
2016-03-16 10:03:00 +01:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
/************************ BEGIN Event Handlers ************************/
|
|
|
|
_converse.on('addClientFeatures', () => {
|
|
|
|
if (_converse.allow_muc) {
|
|
|
|
_converse.connection.disco.addFeature(Strophe.NS.MUC);
|
|
|
|
}
|
|
|
|
if (_converse.allow_muc_invitations) {
|
|
|
|
_converse.connection.disco.addFeature('jabber:x:conference'); // Invites
|
|
|
|
}
|
|
|
|
});
|
|
|
|
_converse.on('chatBoxesFetched', autoJoinRooms);
|
|
|
|
_converse.on('reconnected', reconnectToChatRooms);
|
|
|
|
_converse.on('reconnecting', disconnectChatRooms);
|
|
|
|
_converse.on('disconnecting', disconnectChatRooms);
|
|
|
|
/************************ END Event Handlers ************************/
|
2016-12-03 17:39:59 +01:00
|
|
|
|
2016-04-05 13:23:16 +02:00
|
|
|
|
2018-02-21 22:40:51 +01:00
|
|
|
/************************ BEGIN API ************************/
|
|
|
|
// We extend the default converse.js API to add methods specific to MUC chat rooms.
|
2016-12-20 10:30:20 +01:00
|
|
|
_.extend(_converse.api, {
|
2016-02-16 08:46:47 +01:00
|
|
|
'rooms': {
|
2017-07-10 17:46:22 +02:00
|
|
|
'close' (jids) {
|
2017-01-26 15:49:02 +01:00
|
|
|
if (_.isUndefined(jids)) {
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.chatboxviews.each(function (view) {
|
2016-06-03 10:22:31 +02:00
|
|
|
if (view.is_chatroom && view.model) {
|
|
|
|
view.close();
|
|
|
|
}
|
|
|
|
});
|
2017-01-26 15:49:02 +01:00
|
|
|
} else if (_.isString(jids)) {
|
2017-06-12 20:30:58 +02:00
|
|
|
const view = _converse.chatboxviews.get(jids);
|
2016-06-03 10:22:31 +02:00
|
|
|
if (view) { view.close(); }
|
|
|
|
} else {
|
2017-01-26 15:49:02 +01:00
|
|
|
_.each(jids, function (jid) {
|
2017-06-12 20:30:58 +02:00
|
|
|
const view = _converse.chatboxviews.get(jid);
|
2016-06-03 10:22:31 +02:00
|
|
|
if (view) { view.close(); }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2018-02-21 22:40:51 +01:00
|
|
|
'create' (jids, attrs) {
|
2017-01-26 15:49:02 +01:00
|
|
|
if (_.isString(attrs)) {
|
2016-08-19 17:16:36 +02:00
|
|
|
attrs = {'nick': attrs};
|
2017-01-26 15:49:02 +01:00
|
|
|
} else if (_.isUndefined(attrs)) {
|
2016-08-19 17:16:36 +02:00
|
|
|
attrs = {};
|
|
|
|
}
|
2016-11-30 11:00:12 +01:00
|
|
|
if (_.isUndefined(attrs.maximize)) {
|
|
|
|
attrs.maximize = false;
|
|
|
|
}
|
2016-12-20 10:30:20 +01:00
|
|
|
if (!attrs.nick && _converse.muc_nickname_from_jid) {
|
|
|
|
attrs.nick = Strophe.getNodeFromJid(_converse.bare_jid);
|
2016-10-13 18:22:37 +02:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
if (_.isUndefined(jids)) {
|
|
|
|
throw new TypeError('rooms.create: You need to provide at least one JID');
|
|
|
|
} else if (_.isString(jids)) {
|
|
|
|
return createChatRoom(jids, attrs);
|
|
|
|
}
|
|
|
|
return _.map(jids, _.partial(createChatRoom, _, attrs));
|
|
|
|
},
|
|
|
|
'open' (jids, attrs) {
|
2017-01-26 15:49:02 +01:00
|
|
|
if (_.isUndefined(jids)) {
|
2016-02-16 08:46:47 +01:00
|
|
|
throw new TypeError('rooms.open: You need to provide at least one JID');
|
2017-01-26 15:49:02 +01:00
|
|
|
} else if (_.isString(jids)) {
|
2018-02-21 22:40:51 +01:00
|
|
|
return _converse.api.rooms.create(jids, attrs).trigger('show');
|
2016-02-16 08:46:47 +01:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
return _.map(jids, (jid) => _converse.api.rooms.create(jid, attrs).trigger('show'));
|
2016-02-16 08:46:47 +01:00
|
|
|
},
|
2017-07-10 17:46:22 +02:00
|
|
|
'get' (jids, attrs, create) {
|
2017-01-26 15:49:02 +01:00
|
|
|
if (_.isString(attrs)) {
|
2016-08-19 17:16:36 +02:00
|
|
|
attrs = {'nick': attrs};
|
2017-01-26 15:49:02 +01:00
|
|
|
} else if (_.isUndefined(attrs)) {
|
2016-08-19 17:16:36 +02:00
|
|
|
attrs = {};
|
|
|
|
}
|
2017-01-26 15:49:02 +01:00
|
|
|
if (_.isUndefined(jids)) {
|
2017-06-12 20:30:58 +02:00
|
|
|
const result = [];
|
2016-12-20 10:30:20 +01:00
|
|
|
_converse.chatboxes.each(function (chatbox) {
|
2018-02-21 22:40:51 +01:00
|
|
|
if (chatbox.get('type') === converse.CHATROOMS_TYPE) {
|
|
|
|
result.push(chatbox);
|
2016-06-24 10:54:39 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
2016-08-19 17:16:36 +02:00
|
|
|
if (!attrs.nick) {
|
2016-12-20 10:30:20 +01:00
|
|
|
attrs.nick = Strophe.getNodeFromJid(_converse.bare_jid);
|
2016-06-16 17:20:11 +02:00
|
|
|
}
|
2017-01-26 15:49:02 +01:00
|
|
|
if (_.isString(jids)) {
|
2018-02-21 22:40:51 +01:00
|
|
|
return _converse.getChatRoom(jids, attrs);
|
2017-11-10 15:53:59 +01:00
|
|
|
}
|
2018-02-21 22:40:51 +01:00
|
|
|
return _.map(jids, _.partial(_converse.getChatRoom, _, attrs));
|
2017-11-10 15:53:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2018-02-21 22:40:51 +01:00
|
|
|
/************************ END API ************************/
|
2016-02-16 08:46:47 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}));
|