mirror of
https://github.com/YunoHost-Apps/jappix_ynh.git
synced 2024-09-03 19:26:19 +02:00
2064 lines
63 KiB
JavaScript
2064 lines
63 KiB
JavaScript
/*
|
|
|
|
Jappix - An open social platform
|
|
These are the messages JS scripts for Jappix
|
|
|
|
-------------------------------------------------
|
|
|
|
License: AGPL
|
|
Authors: Valérian Saliou, Maranda
|
|
|
|
*/
|
|
|
|
// Bundle
|
|
var Message = (function () {
|
|
|
|
/**
|
|
* Alias of this
|
|
* @private
|
|
*/
|
|
var self = {};
|
|
|
|
|
|
/**
|
|
* Handles MAM forwared messages
|
|
* @private
|
|
* @param {object} c_mam
|
|
* @return {boolean}
|
|
*/
|
|
self._handleMAM = function(c_mam) {
|
|
|
|
try {
|
|
var c_mam_sel = $(c_mam);
|
|
var c_mam_delay = c_mam_sel.find('delay[xmlns="' + NS_URN_DELAY + '"]');
|
|
var c_mam_forward = c_mam_sel.find('forwarded[xmlns="' + NS_URN_FORWARD + '"]');
|
|
|
|
if(c_mam_forward.size()) {
|
|
MAM.handleMessage(c_mam_forward, c_mam_delay);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._handleMAM', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles chatstate messages
|
|
* @private
|
|
* @param {string} from
|
|
* @param {string} hash
|
|
* @param {string} type
|
|
* @param {object} node
|
|
* @return {undefined}
|
|
*/
|
|
self._handleChatstate = function(from, hash, type, node) {
|
|
|
|
try {
|
|
/* REF: http://xmpp.org/extensions/xep-0085.html */
|
|
|
|
var node_sel = $(node);
|
|
|
|
// Re-process the hash?
|
|
var chatstate_hash = (type == 'groupchat') ? hex_md5(from) : hash;
|
|
|
|
// Do something depending of the received state
|
|
if(node_sel.find('active').size()) {
|
|
ChatState.display('active', chatstate_hash, type);
|
|
|
|
// Tell Jappix the entity supports chatstates
|
|
$('#' + chatstate_hash + ' .message-area').attr('data-chatstates', 'true');
|
|
|
|
Console.log('Active chatstate received from: ' + from);
|
|
} else if(node_sel.find('composing').size()) {
|
|
ChatState.display('composing', chatstate_hash, type);
|
|
|
|
Console.log('Composing chatstate received from: ' + from);
|
|
} else if(node_sel.find('paused').size()) {
|
|
ChatState.display('paused', chatstate_hash, type);
|
|
|
|
Console.log('Paused chatstate received from: ' + from);
|
|
} else if(node_sel.find('inactive').size()){
|
|
ChatState.display('inactive', chatstate_hash, type);
|
|
|
|
Console.log('Inactive chatstate received from: ' + from);
|
|
} else if(node_sel.find('gone').size()){
|
|
ChatState.display('gone', chatstate_hash, type);
|
|
|
|
Console.log('Gone chatstate received from: ' + from);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._doThat', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles Jappix App messages
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} body
|
|
* @param {object} node
|
|
* @return {boolean}
|
|
*/
|
|
self._handleJappixApp = function(xid, body, node) {
|
|
|
|
var is_exit = false;
|
|
|
|
try {
|
|
var node_sel = $(node);
|
|
|
|
// Get notification data
|
|
var jappix_app_node = node_sel.find('app[xmlns="jappix:app"]');
|
|
var jappix_app_name = jappix_app_node.find('name');
|
|
|
|
var jappix_app_name_id = jappix_app_name.attr('id');
|
|
var jappix_app_name_value = jappix_app_name.text();
|
|
|
|
// Jappix Me notification?
|
|
if(jappix_app_name_id == 'me') {
|
|
// Get more notification data
|
|
var jappix_app_data = jappix_app_node.find('data[xmlns="jappix:app:me"]');
|
|
var jappix_app_data_action = jappix_app_data.find('action');
|
|
var jappix_app_data_url = jappix_app_data.find('url');
|
|
|
|
var jappix_app_data_action_type = jappix_app_data_action.attr('type');
|
|
var jappix_app_data_action_success = jappix_app_data_action.attr('success');
|
|
var jappix_app_data_action_job = jappix_app_data_action.attr('job');
|
|
var jappix_app_data_url_value = jappix_app_data_url.text();
|
|
|
|
// Validate data
|
|
if(jappix_app_data_action_type && jappix_app_data_action_success && jappix_app_data_action_job) {
|
|
// Filter success
|
|
jappix_app_data_action_success = parseInt(jappix_app_data_action_success) == 1 ? 'success' : 'error';
|
|
|
|
// Generate notification namespace
|
|
var jappix_me_notification_ns = jappix_app_name_id + '_' + jappix_app_data_action_type + '_' + jappix_app_data_action_job + '_' + jappix_app_data_action_success;
|
|
|
|
// Open a new notification
|
|
Notification.create(jappix_me_notification_ns, xid, [jappix_app_name_value, jappix_app_data_url_value], body);
|
|
|
|
Console.log('Jappix Me notification from: ' + xid + ' with namespace: ' + jappix_me_notification_ns);
|
|
|
|
is_exit = true;
|
|
}
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._handleJappixApp', e);
|
|
} finally {
|
|
return is_exit;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles invite messages
|
|
* @private
|
|
* @param {string} body
|
|
* @param {object} node
|
|
* @return {boolean}
|
|
*/
|
|
self._handleInvite = function(body, node) {
|
|
|
|
try {
|
|
var node_sel = $(node);
|
|
|
|
// We get the needed values
|
|
var iFrom = node_sel.find('x[xmlns="' + NS_MUC_USER + '"] invite').attr('from');
|
|
var iRoom = node_sel.find('x[xmlns="' + NS_XCONFERENCE + '"]').attr('jid') || from;
|
|
|
|
// We display the notification
|
|
Notification.create('invite_room', iFrom, [iRoom], body);
|
|
|
|
Console.log('Invite Request from: ' + iFrom + ' to join: ' + iRoom);
|
|
} catch(e) {
|
|
Console.error('Message._handleInvite', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles request messages
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {object} message
|
|
* @param {string} body
|
|
* @return {boolean}
|
|
*/
|
|
self._handleRequest = function(xid, message, body) {
|
|
|
|
try {
|
|
// Open a new notification
|
|
Notification.create('request', xid, [message], body);
|
|
|
|
Console.log('HTTP Request from: ' + xid);
|
|
} catch(e) {
|
|
Console.error('Message._handleRequest', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles OOB messages
|
|
* @private
|
|
* @param {string} from
|
|
* @param {string} xid
|
|
* @param {string} id
|
|
* @param {object} node
|
|
* @return {boolean}
|
|
*/
|
|
self._handleOOB = function(from, xid, id, node) {
|
|
|
|
try {
|
|
OOB.handle(from, id, 'x', node);
|
|
|
|
Console.log('Message OOB request from: ' + xid);
|
|
} catch(e) {
|
|
Console.error('Message._handleOOB', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles Roster Item Exchange messages
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {object} message
|
|
* @param {string} body
|
|
* @return {boolean}
|
|
*/
|
|
self._handleRosterItemExchange = function(xid, message, body) {
|
|
|
|
try {
|
|
// Open a new notification
|
|
Notification.create('rosterx', xid, [message], body);
|
|
|
|
Console.log('Roster Item Exchange from: ' + xid);
|
|
} catch(e) {
|
|
Console.error('Message._handleRosterItemExchange', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles attention messages
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} body
|
|
* @return {boolean}
|
|
*/
|
|
self._handleAttention = function(xid, body) {
|
|
|
|
try {
|
|
Attention.receive(xid, body);
|
|
} catch(e) {
|
|
Console.error('Message._handleAttention', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles normal messages
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} subject
|
|
* @param {string} body
|
|
* @param {string} delay
|
|
* @return {boolean}
|
|
*/
|
|
self._handleNormal = function(xid, subject, body, delay) {
|
|
|
|
try {
|
|
var message_date = delay || DateUtils.getXMPPTime('utc');
|
|
var message_id = hex_md5(xid + subject + message_date);
|
|
|
|
// Store the received message
|
|
Inbox.storeMessage(xid, subject, body, 'unread', message_id, message_date);
|
|
|
|
// Display the inbox message
|
|
if(Common.exists('#inbox')) {
|
|
Inbox.displayMessage(xid, subject, body, 'unread', message_id, message_date);
|
|
}
|
|
|
|
// Check we have new messages (play a sound if any unread messages)
|
|
if(Inbox.checkMessages()) {
|
|
Audio.play('notification');
|
|
}
|
|
|
|
// Send it to the server
|
|
Inbox.store();
|
|
} catch(e) {
|
|
Console.error('Message._handleNormal', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles Pubsub event messages
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {object} message
|
|
* @param {object} node
|
|
* @return {boolean}
|
|
*/
|
|
self._handlePubsub = function(xid, hash, message, node) {
|
|
|
|
try {
|
|
// We get the needed values
|
|
var items_sel = $(node).find('event items');
|
|
var node_attr = items_sel.attr('node');
|
|
var text;
|
|
|
|
// Turn around the different result cases
|
|
if(node_attr) {
|
|
switch(node_attr) {
|
|
// Mood
|
|
case NS_MOOD:
|
|
// Retrieve the values
|
|
var mood = items_sel.find('mood');
|
|
var value = '';
|
|
text = '';
|
|
|
|
// There's something
|
|
if(mood.children().size()) {
|
|
value = node.getElementsByTagName('mood').item(0).childNodes.item(0).nodeName || '';
|
|
text = mood.find('text').text();
|
|
}
|
|
|
|
// Store the PEP event (and display it)
|
|
PEP.store(xid, 'mood', value, text);
|
|
|
|
break;
|
|
|
|
// Activity
|
|
case NS_ACTIVITY:
|
|
// Retrieve the values
|
|
var activity_sel = items_sel.find('activity');
|
|
text = '';
|
|
|
|
// There's something
|
|
if(activity_sel.children().size()) {
|
|
value = node.getElementsByTagName('activity').item(0).childNodes.item(0).nodeName || '';
|
|
text = activity_sel.find('text').text();
|
|
}
|
|
|
|
// Store the PEP event (and display it)
|
|
PEP.store(xid, 'activity', value, text);
|
|
|
|
break;
|
|
|
|
// Tune
|
|
case NS_TUNE:
|
|
// Retrieve the values
|
|
var tune_sel = items_sel.find('tune');
|
|
var artist = tune_sel.find('artist').text();
|
|
var source = tune_sel.find('source').text();
|
|
var title = tune_sel.find('title').text();
|
|
var uri = tune_sel.find('uri').text();
|
|
|
|
// Store the PEP event (and display it)
|
|
PEP.store(xid, 'tune', artist, title, source, uri);
|
|
|
|
break;
|
|
|
|
// Geolocation
|
|
case NS_GEOLOC:
|
|
// Retrieve the values
|
|
var geoloc_sel = items_sel.find('geoloc');
|
|
var lat = geoloc_sel.find('lat').text();
|
|
var lon = geoloc_sel.find('lon').text();
|
|
|
|
// Any extra-values?
|
|
var locality = geoloc_sel.find('locality').text();
|
|
var region = geoloc_sel.find('region').text();
|
|
var country = geoloc_sel.find('country').text();
|
|
var human = PEP.humanPosition(locality, region, country);
|
|
|
|
// Store the PEP event (and display it)
|
|
PEP.store(xid, 'geoloc', lat, lon, human);
|
|
|
|
break;
|
|
|
|
// Microblog
|
|
case NS_URN_MBLOG:
|
|
Microblog.display(message, xid, hash, 'mixed', 'push');
|
|
|
|
break;
|
|
|
|
// Inbox
|
|
case NS_URN_INBOX:
|
|
// Do not handle friend's notifications
|
|
if(xid == Common.getXID()) {
|
|
Notification.handle(message);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._handlePubsub', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles room topic messages
|
|
* @private
|
|
* @param {string} type
|
|
* @param {string} from
|
|
* @param {string} hash
|
|
* @param {string} subject
|
|
* @param {string} resource
|
|
* @param {string} time
|
|
* @param {string} stamp
|
|
* @return {undefined}
|
|
*/
|
|
self._handleRoomTopic = function(type, from, hash, subject, resource, time, stamp) {
|
|
|
|
try {
|
|
// Filter the vars
|
|
var filter_subject = subject.replace(/\n+/g, ' ');
|
|
var filteredSubject = Filter.message(filter_subject, resource, true);
|
|
var filteredName = resource.htmlEnc();
|
|
|
|
// Display the new subject at the top
|
|
$('#' + hash + ' .top .name .bc-infos .muc-topic').replaceWith(
|
|
'<span class="muc-topic" title="' + filter_subject + '">' + filteredSubject + '</span>'
|
|
);
|
|
|
|
// Display the new subject as a system message
|
|
if(resource) {
|
|
var topic_body = filteredName + ' ' + Common._e("changed the subject to:") + ' ' + Filter.message(subject, resource, true);
|
|
self.display(type, from, hash, filteredName, topic_body, time, stamp, 'system-message', false);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._handleRoomTopic', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles groupchat messages
|
|
* @private
|
|
* @param {string} from
|
|
* @param {string} hash
|
|
* @param {string} type
|
|
* @param {string} resource
|
|
* @param {string} id
|
|
* @param {string} body
|
|
* @param {string} raw_body
|
|
* @param {string} time
|
|
* @param {number} stamp
|
|
* @param {boolean} html_escape
|
|
* @param {string} delay
|
|
* @param {object} message_edit
|
|
* @param {boolean} is_storable
|
|
* @return {undefined}
|
|
*/
|
|
self._handleGroupchat = function(from, hash, type, resource, id, body, raw_body, time, stamp, html_escape, delay, message_edit, is_storable) {
|
|
|
|
try {
|
|
/* REF: http://xmpp.org/extensions/xep-0045.html */
|
|
|
|
// Message type
|
|
var message_type = 'user-message';
|
|
|
|
if(delay && resource) {
|
|
// Old message
|
|
message_type = 'old-message';
|
|
} else if(!resource) {
|
|
// System message
|
|
message_type = 'system-message';
|
|
}
|
|
|
|
var nickQuote = '';
|
|
|
|
// If this is not an old message
|
|
if(message_type == 'user-message') {
|
|
var myNick = Name.getMUCNick(hash);
|
|
|
|
// If an user quoted our nick (with some checks)
|
|
var regex = new RegExp('((^)|( )|(@))' + Common.escapeRegex(myNick) + '(($)|(:)|(,)|( ))', 'gi');
|
|
|
|
if(body.match(regex) && (myNick != resource) && (message_type == 'user-message')) {
|
|
nickQuote = ' my-nick';
|
|
}
|
|
|
|
// We notify the user if there's a new personal message
|
|
if(nickQuote) {
|
|
Interface.messageNotify(hash, 'personal');
|
|
Board.quick(from, 'groupchat', raw_body, resource);
|
|
Audio.play('receive-message');
|
|
}
|
|
|
|
// We notify the user there's a new unread MUC message
|
|
else {
|
|
Interface.messageNotify(hash, 'unread');
|
|
|
|
// Play sound to all users in the MUC, except user who sent the message.
|
|
if(myNick != resource) {
|
|
Audio.play('receive-message');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Display the received message
|
|
self.display(
|
|
type,
|
|
from,
|
|
hash,
|
|
resource.htmlEnc(),
|
|
body,
|
|
time,
|
|
stamp,
|
|
message_type,
|
|
html_escape,
|
|
nickQuote,
|
|
undefined,
|
|
id,
|
|
undefined,
|
|
undefined,
|
|
message_edit.is_edited,
|
|
message_edit.next_count,
|
|
is_storable
|
|
);
|
|
} catch(e) {
|
|
Console.error('Message._handleGroupchat', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles chat messages
|
|
* @private
|
|
* @param {string} from
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} type
|
|
* @param {string} resource
|
|
* @param {string} id
|
|
* @param {string} body
|
|
* @param {string} raw_body
|
|
* @param {string} time
|
|
* @param {number} stamp
|
|
* @param {boolean} html_escape
|
|
* @param {object} message_edit
|
|
* @param {boolean} is_storable
|
|
* @param {boolean} is_markable
|
|
* @param {boolean} is_groupchat_user
|
|
* @param {object} message
|
|
* @return {undefined}
|
|
*/
|
|
self._handleChat = function(from, xid, hash, type, resource, id, body, raw_body, time, stamp, html_escape, message_edit, is_storable, is_markable, is_groupchat_user, message) {
|
|
|
|
try {
|
|
// Gets the nickname of the user
|
|
var fromName = resource;
|
|
var chatType = 'chat';
|
|
|
|
// Must send a receipt notification?
|
|
if(Receipts.has(message) && (id !== null)) {
|
|
Receipts.sendReceived(type, from, id);
|
|
}
|
|
|
|
// It does not come from a groupchat user, get the full name
|
|
if(!is_groupchat_user) {
|
|
fromName = Name.getBuddy(xid);
|
|
} else {
|
|
chatType = 'private';
|
|
}
|
|
|
|
// If the chat isn't yet opened, open it !
|
|
if(!Common.exists('#' + hash)) {
|
|
// We create a new chat
|
|
Chat.create(hash, xid, fromName, chatType);
|
|
|
|
// We tell the user that a new chat has started
|
|
Audio.play('new-chat');
|
|
} else {
|
|
Audio.play('receive-message');
|
|
}
|
|
|
|
// Display the received message
|
|
var message_sel = self.display(
|
|
type,
|
|
xid,
|
|
hash,
|
|
fromName.htmlEnc(),
|
|
body,
|
|
time,
|
|
stamp,
|
|
'user-message',
|
|
html_escape,
|
|
'',
|
|
'him',
|
|
id,
|
|
undefined,
|
|
undefined,
|
|
message_edit.is_edited,
|
|
message_edit.next_count,
|
|
is_storable,
|
|
is_markable
|
|
);
|
|
|
|
// We notify the user
|
|
Interface.messageNotify(hash, 'personal');
|
|
Board.quick(xid, 'chat', raw_body, fromName);
|
|
|
|
// Mark the message
|
|
if(is_markable === true && Markers.hasSupport(xid)) {
|
|
var mark_type = Markers.MARK_TYPE_RECEIVED;
|
|
|
|
if(Interface.hasChanFocus(hash) === true) {
|
|
mark_type = Markers.MARK_TYPE_DISPLAYED;
|
|
}
|
|
|
|
Markers.change(from, mark_type, id, message_sel);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._handleChat', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends an help message
|
|
* @private
|
|
* @param {string} type
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @return {undefined}
|
|
*/
|
|
self._sendHelp = function(type, xid, hash) {
|
|
|
|
try {
|
|
// Help text
|
|
var help_text = '<p class="help" xmlns="http://www.w3.org/1999/xhtml">';
|
|
help_text += '<b>' + Common._e("Available shortcuts:") + '</b>';
|
|
|
|
// Shortcuts array
|
|
var shortcuts = [];
|
|
|
|
// Common shortcuts
|
|
shortcuts.push(Common.printf(Common._e("%s removes the chat logs"), '<em>/clear</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s joins a groupchat"), '<em>/join jid</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s closes the chat"), '<em>/part</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s shows the user profile"), '<em>/whois jid</em>'));
|
|
|
|
// Groupchat shortcuts
|
|
if(type == 'groupchat') {
|
|
shortcuts.push(Common.printf(Common._e("%s sends a message to the room"), '<em>/say message</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s changes your nickname"), '<em>/nick nickname</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s sends a message to someone in the room"), '<em>/msg nickname message</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s changes the room topic"), '<em>/topic subject</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s kicks a user of the room"), '<em>/kick [reason:] nickname</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s bans a user of the room"), '<em>/ban [reason:] nickname</em>'));
|
|
shortcuts.push(Common.printf(Common._e("%s invites someone to join the room"), '<em>/invite jid message</em>'));
|
|
}
|
|
|
|
// Generate the code from the array
|
|
shortcuts = shortcuts.sort();
|
|
|
|
for(var s in shortcuts) {
|
|
help_text += shortcuts[s] + '<br />';
|
|
}
|
|
|
|
help_text += '</p>';
|
|
|
|
// Display the message
|
|
self.display(type, xid, hash, 'help', help_text, DateUtils.getCompleteTime(), DateUtils.getTimeStamp(), 'system-message', false);
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendHelp', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a clear message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @return {undefined}
|
|
*/
|
|
self._sendClear = function(xid, hash) {
|
|
|
|
try {
|
|
Chat.clean(hex_md5(xid));
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendClear', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a join message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} e_1
|
|
* @param {string} e_2
|
|
* @return {undefined}
|
|
*/
|
|
self._sendJoin = function(xid, hash, e_1, e_2) {
|
|
|
|
try {
|
|
// Join
|
|
var room_gen = Common.generateXID(e_1, 'groupchat');
|
|
var pass = e_2;
|
|
|
|
Chat.checkCreate(room_gen, 'groupchat');
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendJoin', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a part message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} type
|
|
* @return {undefined}
|
|
*/
|
|
self._sendPart = function(xid, type) {
|
|
|
|
try {
|
|
Interface.quitThisChat(xid, hex_md5(xid), type);
|
|
} catch(e) {
|
|
Console.error('Message._sendPart', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a WHOIS message
|
|
* @private
|
|
* @param {string} type
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} e_3
|
|
* @return {undefined}
|
|
*/
|
|
self._sendWHOIS = function(type, xid, hash, e_3) {
|
|
|
|
try {
|
|
var whois_xid = RegExp.$3;
|
|
|
|
// Groupchat WHOIS
|
|
if(type == 'groupchat') {
|
|
nXID = Utils.getMUCUserXID(xid, whois_xid);
|
|
|
|
if(!nXID) {
|
|
Board.openThisInfo(6);
|
|
} else {
|
|
UserInfos.open(nXID);
|
|
}
|
|
}
|
|
|
|
// Chat or private WHOIS
|
|
else {
|
|
if(!whois_xid) {
|
|
UserInfos.open(xid);
|
|
} else {
|
|
UserInfos.open(whois_xid);
|
|
}
|
|
}
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendWHOIS', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends an attention message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} e_2
|
|
* @return {undefined}
|
|
*/
|
|
self._sendAttention = function(xid, e_2) {
|
|
|
|
try {
|
|
Attention.send(
|
|
xid,
|
|
$.trim(e_2)
|
|
);
|
|
} catch(e) {
|
|
Console.error('Message._sendAttention', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a chat message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} id
|
|
* @param {string} body
|
|
* @param {object} message_packet
|
|
* @return {undefined}
|
|
*/
|
|
self._sendChat = function(xid, hash, id, body, message_packet) {
|
|
|
|
try {
|
|
message_packet.setType('chat');
|
|
|
|
// Generates the correct message depending of the choosen style
|
|
var genMsg = self.generate(message_packet, body, hash);
|
|
var html_escape = (genMsg !== 'XHTML');
|
|
|
|
// Receipt request
|
|
var receipt_request = Receipts.request(hash);
|
|
|
|
if(receipt_request) {
|
|
message_packet.appendNode('request', {
|
|
'xmlns': NS_URN_RECEIPTS
|
|
});
|
|
}
|
|
|
|
// Chatstate
|
|
message_packet.appendNode('active', {
|
|
'xmlns': NS_CHATSTATES
|
|
});
|
|
|
|
// Markable message?
|
|
var has_markers = Markers.hasSupport(xid);
|
|
|
|
if(has_markers === true) {
|
|
Markers.mark(message_packet);
|
|
}
|
|
|
|
// Send it!
|
|
con.send(message_packet, Errors.handleReply);
|
|
|
|
// Filter the xHTML message (for us!)
|
|
if(!html_escape) {
|
|
body = Filter.xhtml(message_packet.getNode());
|
|
}
|
|
|
|
// Finally we display the message we just sent
|
|
var my_xid = Common.getXID();
|
|
|
|
var message_sel = self.display(
|
|
'chat',
|
|
my_xid,
|
|
hash,
|
|
Name.getBuddy(my_xid).htmlEnc(),
|
|
body,
|
|
DateUtils.getCompleteTime(),
|
|
DateUtils.getTimeStamp(),
|
|
'user-message',
|
|
html_escape,
|
|
'',
|
|
'me',
|
|
id
|
|
);
|
|
|
|
if(has_markers === true) {
|
|
message_sel.addClass('is-sending');
|
|
message_sel.find('.message-marker').text(
|
|
Common._e("Sending...")
|
|
).show();
|
|
}
|
|
|
|
// Receipt timer
|
|
if(receipt_request) {
|
|
Receipts.checkReceived(hash, id);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._sendChat', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat say message
|
|
* @private
|
|
* @param {string} hash
|
|
* @param {string} body
|
|
* @param {object} message_packet
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatSat = function(hash, body, message_packet) {
|
|
|
|
try {
|
|
body = body.replace(/^\/say (.+)/, '$1');
|
|
|
|
message_packet.setType('groupchat');
|
|
self.generate(message_packet, body, hash);
|
|
|
|
con.send(message_packet, Errors.handleReply);
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatSat', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat nick message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} nick
|
|
* @param {string} body
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatNick = function(xid, hash, e_1, body) {
|
|
|
|
try {
|
|
var nick = $.trim(e_1);
|
|
|
|
// Does not exist yet?
|
|
if(nick && !Utils.getMUCUserXID(xid, nick)) {
|
|
// Send a new presence
|
|
Presence.send(
|
|
(xid + '/' + nick),
|
|
'',
|
|
Presence.getUserShow(),
|
|
Presence.getUserStatus(),
|
|
'',
|
|
false,
|
|
false,
|
|
Errors.handleReply
|
|
);
|
|
|
|
// Change the stored nickname
|
|
$('#' + hex_md5(xid)).attr('data-nick', escape(nick));
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatNick', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat msg message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} e_1
|
|
* @param {string} e_2
|
|
* @param {object} message_packet
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatMsg = function(xid, hash, e_1, e_2, message_packet) {
|
|
|
|
try {
|
|
var msg_nick = e_1;
|
|
var msg_body = e_2;
|
|
var nick_xid = Utils.getMUCUserXID(xid, msg_nick);
|
|
|
|
// We check if the user exists
|
|
if(!nick_xid) {
|
|
Board.openThisInfo(6);
|
|
} else if(msg_body) {
|
|
message_packet.setType('chat');
|
|
message_packet.setTo(nick_xid);
|
|
self.generate(message_packet, msg_body, hash);
|
|
|
|
con.send(message_packet, Errors.handleReply);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatMsg', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat XXX message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} body
|
|
* @param {object} message_packet
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatTopic = function(xid, hash, body, message_packet) {
|
|
|
|
try {
|
|
var topic = body.replace(/^\/topic (.+)/, '$1');
|
|
|
|
message_packet.setType('groupchat');
|
|
message_packet.setSubject(topic);
|
|
|
|
con.send(message_packet, Errors.handleMessage);
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatTopic', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat XXX message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} body
|
|
* @param {string} e_1
|
|
* @param {string} e_2
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatBan = function(xid, hash, body, e_1, e_2) {
|
|
|
|
try {
|
|
var ban_nick = $.trim(e_1);
|
|
var ban_reason = '';
|
|
|
|
// We check if the user exists, if not it may be because a reason is given
|
|
// we do not check it at first because the nickname could contain ':'
|
|
var ban_xid = Utils.getMUCUserRealXID(xid, ban_nick);
|
|
|
|
if(!ban_xid && (body.match(/^\/ban ([^:]+)[:]*(.*)/))) {
|
|
ban_reason = $.trim(e_1);
|
|
ban_nick = $.trim(e_2);
|
|
|
|
if(ban_nick.length === 0) {
|
|
ban_nick = ban_reason;
|
|
ban_reason = '';
|
|
}
|
|
|
|
ban_xid = Utils.getMUCUserXID(xid, ban_nick);
|
|
}
|
|
|
|
Groupchat.banUser(xid, ban_xid, ban_reason);
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatBan', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat XXX message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} body
|
|
* @param {string} e_1
|
|
* @param {string} e_2
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatKick = function(xid, hash, body, e_1, e_2) {
|
|
|
|
try {
|
|
var kick_nick = $.trim(e_1);
|
|
var kick_reason = '';
|
|
|
|
// We check if the user exists, if not it may be because a reason is given
|
|
// we do not check it at first because the nickname could contain ':'
|
|
var kick_xid = Utils.getMUCUserRealXID(xid, kick_nick);
|
|
|
|
if(!kick_xid && (body.match(/^\/kick ([^:]+)[:]*(.*)/))) {
|
|
kick_reason = $.trim(e_1);
|
|
kick_nick = $.trim(e_2);
|
|
|
|
if(kick_nick.length === 0) {
|
|
kick_nick = kick_reason;
|
|
kick_reason = '';
|
|
}
|
|
|
|
kick_xid = Utils.getMUCUserXID(xid, kick_nick);
|
|
}
|
|
|
|
Groupchat.kickUser(xid, kick_xid, kick_nick, kick_reason);
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatKick', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat XXX message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} e_1
|
|
* @param {string} e_2
|
|
* @param {object} message_packet
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatInvite = function(xid, hash, e_1, e_2, message_packet) {
|
|
|
|
try {
|
|
var i_xid = e_1;
|
|
var invite_reason = e_2;
|
|
|
|
var x = message_packet.appendNode('x', {
|
|
'xmlns': NS_MUC_USER
|
|
});
|
|
|
|
var node = x.appendChild(message_packet.buildNode('invite', {
|
|
'to': i_xid,
|
|
'xmlns': NS_MUC_USER
|
|
}));
|
|
|
|
if(invite_reason) {
|
|
node.appendChild(message_packet.buildNode('reason', {
|
|
'xmlns': NS_MUC_USER
|
|
}, invite_reason));
|
|
}
|
|
|
|
con.send(message_packet, Errors.handleReply);
|
|
|
|
// Reset chatstate
|
|
ChatState.send('active', xid, hash);
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatInvite', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat XXX message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} type
|
|
* @param {string} body
|
|
* @param {object} message_packet
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchatMessage = function(xid, hash, type, body, message_packet) {
|
|
|
|
try {
|
|
message_packet.setType('groupchat');
|
|
|
|
// Chatstate
|
|
message_packet.appendNode('active', {
|
|
'xmlns': NS_CHATSTATES
|
|
});
|
|
|
|
self.generate(message_packet, body, hash);
|
|
|
|
con.send(message_packet, Errors.handleMessage);
|
|
|
|
Console.info('Message sent to: ' + xid + ' / ' + type);
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchatMessage', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a groupchat message
|
|
* @private
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} type
|
|
* @param {string} body
|
|
* @param {object} message_packet
|
|
* @return {undefined}
|
|
*/
|
|
self._sendGroupchat = function(xid, hash, type, body, message_packet) {
|
|
|
|
try {
|
|
// /say shortcut
|
|
if(body.match(/^\/say (.+)/)) {
|
|
self._sendGroupchatSat(
|
|
hash,
|
|
body,
|
|
message_packet
|
|
);
|
|
}
|
|
|
|
// /nick shortcut
|
|
else if(body.match(/^\/nick (.+)/)) {
|
|
self._sendGroupchatNick(
|
|
xid,
|
|
hash,
|
|
RegExp.$1,
|
|
body
|
|
);
|
|
}
|
|
|
|
// /msg shortcut
|
|
else if(body.match(/^\/msg (\S+)\s+(.+)/)) {
|
|
self._sendGroupchatMsg(
|
|
xid,
|
|
hash,
|
|
RegExp.$1,
|
|
RegExp.$2,
|
|
message_packet
|
|
);
|
|
}
|
|
|
|
// /topic shortcut
|
|
else if(body.match(/^\/topic (.+)/)) {
|
|
self._sendGroupchatTopic(
|
|
xid,
|
|
hash,
|
|
body,
|
|
message_packet
|
|
);
|
|
}
|
|
|
|
// /ban shortcut
|
|
else if(body.match(/^\/ban (.*)/)) {
|
|
self._sendGroupchatBan(
|
|
xid,
|
|
hash,
|
|
body,
|
|
RegExp.$1,
|
|
RegExp.$2
|
|
);
|
|
}
|
|
|
|
// /kick shortcut
|
|
else if(body.match(/^\/kick (.*)/)) {
|
|
self._sendGroupchatKick(
|
|
xid,
|
|
hash,
|
|
body,
|
|
RegExp.$1,
|
|
RegExp.$2
|
|
);
|
|
}
|
|
|
|
// /invite shortcut
|
|
else if(body.match(/^\/invite (\S+)\s*(.*)/)) {
|
|
self._sendGroupchatInvite(
|
|
xid,
|
|
hash,
|
|
RegExp.$1,
|
|
RegExp.$2,
|
|
message_packet
|
|
);
|
|
}
|
|
|
|
// No shortcut, this is a message
|
|
else {
|
|
self._sendGroupchatMessage(
|
|
xid,
|
|
hash,
|
|
type,
|
|
body,
|
|
message_packet
|
|
);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message._sendGroupchat', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Handles the incoming message packets
|
|
* @public
|
|
* @param {object} message
|
|
* @return {boolean}
|
|
*/
|
|
self.handle = function(message) {
|
|
|
|
try {
|
|
// Error packet? Stop!
|
|
if(Errors.handleReply(message)) {
|
|
return;
|
|
}
|
|
|
|
// Carbon-forwarded message?
|
|
if(message.getChild('sent', NS_URN_CARBONS)) {
|
|
Carbons.handleSent(message); return;
|
|
}
|
|
if(message.getChild('received', NS_URN_CARBONS)) {
|
|
Carbons.handleReceived(message); return;
|
|
}
|
|
|
|
// MAM-forwarded message?
|
|
var c_mam = message.getChild('result', NS_URN_MAM);
|
|
|
|
if(c_mam) {
|
|
return self._handleMAM(c_mam);
|
|
}
|
|
|
|
// We get the message items
|
|
var from = Common.fullXID(Common.getStanzaFrom(message));
|
|
var id = message.getID();
|
|
var type = message.getType();
|
|
var body = $.trim(message.getBody());
|
|
var node = message.getNode();
|
|
var subject = $.trim(message.getSubject());
|
|
|
|
// Keep raw message body
|
|
var raw_body = body;
|
|
|
|
// We generate some values
|
|
var xid = Common.bareXID(from);
|
|
var resource = Common.thisResource(from);
|
|
var hash = hex_md5(xid);
|
|
var xHTML = $(node).find('html body').size();
|
|
var is_groupchat_user = false;
|
|
|
|
// This message comes from a Muji room (ignore)
|
|
if(Muji.is_room(xid)) {
|
|
return false;
|
|
}
|
|
|
|
// This message comes from a groupchat user
|
|
if(Utils.isPrivate(xid) && ((type == 'chat') || !type) && resource) {
|
|
is_groupchat_user = true;
|
|
xid = from;
|
|
hash = hex_md5(xid);
|
|
}
|
|
|
|
// Get message date
|
|
var time, stamp;
|
|
var delay = DateUtils.readMessageDelay(node);
|
|
|
|
// Any delay?
|
|
if(delay) {
|
|
time = DateUtils.relative(delay);
|
|
stamp = DateUtils.extractStamp(Date.jab2date(delay));
|
|
} else {
|
|
time = DateUtils.getCompleteTime();
|
|
stamp = DateUtils.extractStamp(new Date());
|
|
}
|
|
|
|
// Received message
|
|
if(Receipts.hasReceived(message)) {
|
|
return Receipts.messageReceived(hash, id);
|
|
}
|
|
|
|
// Chatstate message
|
|
if(node && !delay &&
|
|
((((type == 'chat') || !type) && !Common.exists('#page-switch .' + hash + ' .unavailable')) || (type == 'groupchat'))) {
|
|
self._handleChatstate(from, hash, type, node);
|
|
}
|
|
|
|
// Jappix App message
|
|
if(message.getChild('app', 'jappix:app')) {
|
|
if(self._handleJappixApp(xid, body, node) === true) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Invite message
|
|
if($(node).find('x[xmlns="' + NS_MUC_USER + '"] invite').size()) {
|
|
return self._handleInvite(body, node);
|
|
}
|
|
|
|
// Request message
|
|
if(message.getChild('confirm', NS_HTTP_AUTH)) {
|
|
return self._handleRequest(xid, message, body);
|
|
}
|
|
|
|
// OOB message
|
|
if(message.getChild('x', NS_XOOB)) {
|
|
return self._handleOOB(from, xid, id, node);
|
|
}
|
|
|
|
// Roster Item Exchange message
|
|
if(message.getChild('x', NS_ROSTERX)) {
|
|
return self._handleRosterItemExchange(xid, message, body);
|
|
}
|
|
|
|
// Attention message
|
|
if(message.getChild('attention', NS_URN_ATTENTION)) {
|
|
return self._handleAttention(xid, body);
|
|
}
|
|
|
|
// Normal message
|
|
if((type == 'normal') && body) {
|
|
return self._handleNormal(xid, subject, body, delay);
|
|
}
|
|
|
|
// PubSub event
|
|
if($(node).find('event').attr('xmlns') == NS_PUBSUB_EVENT) {
|
|
return self._handlePubsub(xid, hash, message, node);
|
|
}
|
|
|
|
// If this is a room topic message
|
|
if(subject && (type == 'groupchat')) {
|
|
self._handleRoomTopic(type, from, hash, subject, resource, time, stamp);
|
|
}
|
|
|
|
// If the message has a content
|
|
if(xHTML || body) {
|
|
var filteredMessage;
|
|
var html_escape = true;
|
|
|
|
// IE bug fix
|
|
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) {
|
|
xHTML = 0;
|
|
}
|
|
|
|
// If this is a xHTML message
|
|
if(xHTML) {
|
|
html_escape = false;
|
|
|
|
// Filter the xHTML message
|
|
body = Filter.xhtml(node);
|
|
}
|
|
|
|
// Catch message edit (XEP-0308)
|
|
var message_edit = Correction.catch(message, hash, type);
|
|
|
|
// Storable message?
|
|
var is_storable = message.getChild('no-permanent-storage', NS_URN_HINTS) ? false : true;
|
|
|
|
// Groupchat message
|
|
if(type == 'groupchat') {
|
|
self._handleGroupchat(
|
|
from,
|
|
hash,
|
|
type,
|
|
resource,
|
|
id,
|
|
body,
|
|
raw_body,
|
|
time,
|
|
stamp,
|
|
html_escape,
|
|
delay,
|
|
message_edit,
|
|
is_storable
|
|
);
|
|
} else {
|
|
// Markable message?
|
|
var is_markable = Markers.hasRequestMarker(node);
|
|
|
|
self._handleChat(
|
|
from,
|
|
xid,
|
|
hash,
|
|
type,
|
|
resource,
|
|
id,
|
|
body,
|
|
raw_body,
|
|
time,
|
|
stamp,
|
|
html_escape,
|
|
message_edit,
|
|
is_storable,
|
|
is_markable,
|
|
is_groupchat_user,
|
|
message
|
|
);
|
|
}
|
|
}
|
|
|
|
// Message marker?
|
|
if(Markers.hasResponseMarker(node)) {
|
|
return Markers.handle(from, node);
|
|
}
|
|
|
|
return false;
|
|
} catch(e) {
|
|
Console.error('Message.handle', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Sends a given message
|
|
* @public
|
|
* @param {string} hash
|
|
* @param {string} type
|
|
* @return {boolean}
|
|
*/
|
|
self.send = function(hash, type) {
|
|
|
|
try {
|
|
// Get the values
|
|
var message_area = $('#' + hash + ' .message-area');
|
|
var body = $.trim(message_area.val());
|
|
var xid = unescape(message_area.attr('data-to'));
|
|
var nXID;
|
|
|
|
// If the user didn't entered any message, stop
|
|
if(!body || !xid) {
|
|
return false;
|
|
}
|
|
|
|
// We send the message through the XMPP network
|
|
var message_packet = new JSJaCMessage();
|
|
message_packet.setTo(xid);
|
|
|
|
// Set an ID
|
|
var id = genID();
|
|
message_packet.setID(id);
|
|
|
|
// /help shortcut
|
|
if(body.match(/^\/help\s*(.*)/)) {
|
|
self._sendHelp(type, xid, hash);
|
|
}
|
|
|
|
// /clear shortcut
|
|
else if(body.match(/^\/clear/)) {
|
|
self._sendClear(xid, hash);
|
|
}
|
|
|
|
// /join shortcut
|
|
else if(body.match(/^\/join (\S+)\s*(.*)/)) {
|
|
self._sendJoin(xid, hash, RegExp.$1, RegExp.$2);
|
|
}
|
|
|
|
// /part shortcut
|
|
else if(body.match(/^\/part\s*(.*)/) &&
|
|
(!Utils.isAnonymous() || (Utils.isAnonymous() &&
|
|
(xid != Common.generateXID(ANONYMOUS_ROOM, 'groupchat'))))) {
|
|
self._sendPart(xid, type);
|
|
}
|
|
|
|
// /whois shortcut
|
|
else if(body.match(/^\/whois(( (\S+))|($))/)) {
|
|
self._sendWHOIS(type, xid, hash, RegExp.$3);
|
|
}
|
|
|
|
// /attention shortcut
|
|
else if(body.match(/^\/attention( (.*))?/) && type == 'chat') {
|
|
self._sendAttention(xid, RegExp.$2);
|
|
}
|
|
|
|
// Chat message type
|
|
else if(type == 'chat') {
|
|
self._sendChat(
|
|
xid,
|
|
hash,
|
|
id,
|
|
body,
|
|
message_packet
|
|
);
|
|
}
|
|
|
|
// Groupchat message type
|
|
else if(type == 'groupchat') {
|
|
self._sendGroupchat(
|
|
xid,
|
|
hash,
|
|
type,
|
|
body,
|
|
message_packet
|
|
);
|
|
}
|
|
|
|
// We reset the message input
|
|
$('#' + hash + ' .message-area').val('');
|
|
} catch(e) {
|
|
Console.error('Message.send', e);
|
|
} finally {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Generates the correct message area style
|
|
* @public
|
|
* @param {string} hash
|
|
* @return {string}
|
|
*/
|
|
self.generateStyle = function() {
|
|
|
|
try {
|
|
// Initialize the vars
|
|
var styles = '#' + hash + ' div.bubble-style';
|
|
var font = styles + ' a.font-current';
|
|
var fontsize = styles + ' a.fontsize-current';
|
|
var checkbox = styles + ' input[type="checkbox"]';
|
|
var color = '#' + hash + ' .message-area[data-color]';
|
|
var style = '';
|
|
|
|
// Get the font value
|
|
$(font).filter('[data-font]').each(function() {
|
|
style += 'font-family: ' + $(this).attr('data-font') + ';';
|
|
});
|
|
|
|
// Get the font value
|
|
$(fontsize).filter('[data-value]').each(function() {
|
|
style += 'font-size: ' + $(this).attr('data-value') + 'px;';
|
|
});
|
|
|
|
// Loop the input values
|
|
$(checkbox).filter(':checked').each(function() {
|
|
// If there is a previous element
|
|
if(style) {
|
|
style += ' ';
|
|
}
|
|
|
|
// Get the current style
|
|
switch($(this).attr('class')) {
|
|
case 'bold':
|
|
style += 'font-weight: bold;';
|
|
break;
|
|
|
|
case 'italic':
|
|
style += 'font-style: italic;';
|
|
break;
|
|
|
|
case 'underline':
|
|
style += 'text-decoration: underline;';
|
|
break;
|
|
}
|
|
});
|
|
|
|
// Get the color value
|
|
$(color).each(function() {
|
|
style += 'color: #' + $(this).attr('data-color');
|
|
});
|
|
|
|
return style;
|
|
} catch(e) {
|
|
Console.error('Message.generateStyle', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Read messages from local archive
|
|
* @public
|
|
* @param {string} hash
|
|
* @return {string}
|
|
*/
|
|
self.readLocalArchive = function(hash) {
|
|
|
|
try {
|
|
return DataStore.getPersistent(Common.getXID(), 'history', hash);
|
|
} catch(e) {
|
|
Console.error('Message.readLocalArchive', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Stores message in local archive
|
|
* @public
|
|
* @param {string} hash
|
|
* @param {string} store_html
|
|
* @return {undefined}
|
|
*/
|
|
self.storeLocalArchive = function(hash, store_html) {
|
|
|
|
try {
|
|
if(DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives') != '0') {
|
|
DataStore.setPersistent(Common.getXID(), 'history', hash, store_html);
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message.storeLocalArchive', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Removes messages from local archive
|
|
* @public
|
|
* @param {string} hash
|
|
* @return {undefined}
|
|
*/
|
|
self.removeLocalArchive = function(hash) {
|
|
|
|
try {
|
|
DataStore.removePersistent(Common.getXID(), 'history', hash);
|
|
} catch(e) {
|
|
Console.error('Message.removeLocalArchive', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Flushes local messages archive
|
|
* @public
|
|
* @return {undefined}
|
|
*/
|
|
self.flushLocalArchive = function() {
|
|
|
|
try {
|
|
var flush_count = 0;
|
|
var db_regex = new RegExp(('^' + Common.getXID() + '_') + ('history_'));
|
|
|
|
for(var i = 0; i < JappixDataStore.storagePersistent.length; i++) {
|
|
var db_current = JappixDataStore.storagePersistent.key(i);
|
|
|
|
if(db_regex.exec(db_current)) {
|
|
JappixDataStore.storagePersistent.removeItem(db_current);
|
|
flush_count++;
|
|
}
|
|
}
|
|
|
|
Console.info('Flushed ' + flush_count + ' archives in total.');
|
|
} catch(e) {
|
|
Console.error('Message.flushLocalArchive', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Generates the correct message code
|
|
* @public
|
|
* @param {object} message_packet
|
|
* @param {string} body
|
|
* @param {string} hash
|
|
* @return {string}
|
|
*/
|
|
self.generate = function(message_packet, body, hash) {
|
|
|
|
try {
|
|
// Create the classical body
|
|
message_packet.setBody(body);
|
|
|
|
// Get the style
|
|
var style = $('#' + hash + ' .message-area').attr('style');
|
|
|
|
// A message style is choosen
|
|
if(style) {
|
|
// Explode the message body new lines (to create one <p /> element by line)
|
|
var new_lines = new Array(body);
|
|
|
|
if(body.match(/\n/)) {
|
|
new_lines = body.split('\n');
|
|
}
|
|
|
|
// Create the XML elements
|
|
var html_node = message_packet.appendNode('html', {
|
|
'xmlns': NS_XHTML_IM
|
|
});
|
|
|
|
var body_node = html_node.appendChild(message_packet.buildNode('body', {
|
|
'xmlns': NS_XHTML
|
|
}));
|
|
|
|
// Use the exploded body array to create one element per entry
|
|
for(var i in new_lines) {
|
|
// Current line
|
|
var cLine = new_lines[i];
|
|
|
|
// Blank line, we put a <br />
|
|
if(cLine.match(/(^)(\s+)($)/) || !cLine) {
|
|
body_node.appendChild(message_packet.buildNode('br', {'xmlns': NS_XHTML}));
|
|
}
|
|
|
|
// Line with content, we put a <p />
|
|
else {
|
|
// HTML encode the line
|
|
cLine = cLine.htmlEnc();
|
|
|
|
// Filter the links
|
|
cLine = Links.apply(cLine, 'xhtml-im', style);
|
|
|
|
// Append the filtered line
|
|
$(body_node).append($('<p style="' + style + '">' + cLine + '</p>'));
|
|
}
|
|
}
|
|
|
|
return 'XHTML';
|
|
}
|
|
|
|
return 'PLAIN';
|
|
} catch(e) {
|
|
Console.error('Message.generate', e);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Displays a given message in a chat tab
|
|
* @public
|
|
* @param {string} type
|
|
* @param {string} xid
|
|
* @param {string} hash
|
|
* @param {string} name
|
|
* @param {string} body
|
|
* @param {string} time
|
|
* @param {string} stamp
|
|
* @param {string} message_type
|
|
* @param {boolean} html_escape
|
|
* @param {string} nick_quote
|
|
* @param {string} mode
|
|
* @param {string} id
|
|
* @param {object} c_target_sel
|
|
* @param {boolean} no_scroll
|
|
* @param {boolean} is_edited
|
|
* @param {number} edit_count
|
|
* @param {boolean} is_storable
|
|
* @param {boolean} is_markable
|
|
* @return {object}
|
|
*/
|
|
self.display = function(type, xid, hash, name, body, time, stamp, message_type, html_escape, nick_quote, mode, id, c_target_sel, no_scroll, is_edited, edit_count, is_storable, is_markable) {
|
|
|
|
var message_sel = null;
|
|
|
|
try {
|
|
// Target
|
|
if(typeof c_target_sel === 'undefined') {
|
|
c_target_sel = $('#' + hash + ' .content');
|
|
}
|
|
|
|
// Auto-calculate mode for groupchat?
|
|
if(type == 'groupchat' && !mode) {
|
|
var own_groupchat_nickname = $('#' + hash).attr('data-nick') || '';
|
|
own_groupchat_nickname = unescape(own_groupchat_nickname);
|
|
|
|
if(name == own_groupchat_nickname) {
|
|
mode = 'me';
|
|
} else {
|
|
mode = 'him';
|
|
}
|
|
}
|
|
|
|
// Generate some stuffs
|
|
var has_avatar = false;
|
|
var xid_hash = '';
|
|
|
|
if(!nick_quote) {
|
|
nick_quote = '';
|
|
}
|
|
|
|
if(message_type != 'system-message') {
|
|
has_avatar = true;
|
|
xid_hash = hex_md5(xid);
|
|
}
|
|
|
|
// Can scroll?
|
|
var cont_scroll = document.getElementById('chat-content-' + hash);
|
|
var can_scroll = false;
|
|
|
|
if((!cont_scroll.scrollTop || ((cont_scroll.clientHeight + cont_scroll.scrollTop) == cont_scroll.scrollHeight)) && no_scroll !== true) {
|
|
can_scroll = true;
|
|
}
|
|
|
|
// Any ID?
|
|
var data_id = '';
|
|
|
|
if(id) {
|
|
data_id = ' data-id="' + id + '"';
|
|
}
|
|
|
|
// Edited state?
|
|
var data_edited = '';
|
|
var data_edit_count = '';
|
|
|
|
if(is_edited === true) {
|
|
data_edited = ' data-edited="true"';
|
|
data_edit_count = ' data-edit-count="' + (edit_count || 0) + '"';
|
|
}
|
|
|
|
// Markable state?
|
|
var data_markable = (is_markable === true) ? ' data-markable="true"' : '';
|
|
|
|
// Filter the message
|
|
var filteredMessage = Filter.message(body, name, html_escape);
|
|
|
|
// Display the received message in the room
|
|
var message_code = '<div class="one-line ' + message_type + nick_quote + '" data-stamp="' + stamp + '" data-mode="' + mode + '"' + data_id + data_edited + data_markable + data_edit_count + '><div class="message-content">';
|
|
|
|
// Name color attribute
|
|
if(type == 'groupchat') {
|
|
attribute = ' style="color: ' + Common.generateColor(name) + ';" class="name';
|
|
} else {
|
|
attribute = ' class="name';
|
|
|
|
if(mode) {
|
|
attribute += ' ' + mode;
|
|
}
|
|
}
|
|
|
|
// Close the class attribute
|
|
if(message_type == 'system-message') {
|
|
attribute += ' hidden"';
|
|
} else {
|
|
attribute += '"';
|
|
}
|
|
|
|
// Filter the previous displayed message
|
|
var last = c_target_sel.find('.one-group:not(.from-history):last');
|
|
var last_name = last.find('b.name').attr('data-xid');
|
|
var last_type = last.attr('data-type');
|
|
var last_stamp = parseInt(last.attr('data-stamp'));
|
|
var grouped = false;
|
|
|
|
// We can group it with another previous message
|
|
if((last_name == xid) && (message_type == last_type) && ((stamp - last_stamp) <= 1800)) {
|
|
grouped = true;
|
|
}
|
|
|
|
// Is it a /me command?
|
|
if(body.match(/(^|>)(\/me )([^<]+)/)) {
|
|
filteredMessage = '<i>' + filteredMessage + '</i>';
|
|
}
|
|
|
|
message_code += filteredMessage + '</div>';
|
|
|
|
// Message correction containers
|
|
if(message_type == 'user-message') {
|
|
// Message edit properties
|
|
message_code += '<a class="correction-edit" href="#">' + Common._e("Edit") + '</a>';
|
|
|
|
if(is_edited === true) {
|
|
var edit_text = Common._e("Edited");
|
|
|
|
if(edit_count > 1) {
|
|
edit_text = Common._e(Common.printf("Edited (%s)", edit_count));
|
|
}
|
|
|
|
message_code += '<span class="corrected-info">' + edit_text + '</span>';
|
|
}
|
|
}
|
|
|
|
// Message marker container
|
|
if(type == 'chat') {
|
|
message_code += '<span class="message-marker"></span>';
|
|
}
|
|
|
|
message_code += '</div>';
|
|
|
|
// Must group it?
|
|
if(!grouped) {
|
|
// Generate message headers
|
|
var message_head = '';
|
|
|
|
// Any avatar to add?
|
|
if(has_avatar) {
|
|
message_head += '<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>';
|
|
}
|
|
|
|
// Add the date & the name
|
|
message_head += '<span class="date">' + time + '</span><b data-xid="' + Common.encodeQuotes(xid) + '" ' + attribute + '>' + name + '</b>';
|
|
|
|
// Generate message code
|
|
message_code = '<div class="one-group ' + xid_hash + '" data-type="' + message_type + '" data-stamp="' + stamp + '">' + message_head + message_code + '</div>';
|
|
}
|
|
|
|
// Write the code in the DOM
|
|
if(grouped) {
|
|
c_target_sel.find('.one-group:last').append(message_code);
|
|
} else {
|
|
c_target_sel.append(message_code);
|
|
}
|
|
|
|
message_sel = c_target_sel.find('.one-line:last');
|
|
|
|
// Store the last MAM.REQ_MAX message groups
|
|
if(!Features.enabledMAM() && (type == 'chat') && (message_type == 'user-message')) {
|
|
// Filter the DOM
|
|
var dom_filter = $('#' + hash + ' .content').clone().contents();
|
|
var default_avatar = ('./images/others/default-avatar.png').replace(/&/g, '&'); // Fixes #252
|
|
|
|
$(dom_filter).find('.system-message').parent().remove();
|
|
$(dom_filter).find('.avatar-container img.avatar').attr('src', default_avatar);
|
|
$(dom_filter).find('.one-line').parent().slice(0, $(dom_filter).find('.one-line').parent().size() - MAM.REQ_MAX).remove();
|
|
|
|
var store_html = $(dom_filter).parent().html();
|
|
|
|
// Store the data
|
|
if(store_html && is_storable !== false) {
|
|
self.storeLocalArchive(hash, store_html);
|
|
}
|
|
|
|
if(is_storable === false) {
|
|
Console.info('Message.display', 'Won\'t store message since it\'s labeled as not storable (' + xid + ')');
|
|
}
|
|
}
|
|
|
|
// Must get the avatar?
|
|
if(has_avatar && xid && !grouped) {
|
|
Avatar.get(xid, 'cache', 'true', 'forget');
|
|
}
|
|
|
|
// Scroll to this message
|
|
if(can_scroll) {
|
|
Interface.autoScroll(hash);
|
|
}
|
|
|
|
// Add click events
|
|
var xid_to = $('#' + hash).attr('data-xid');
|
|
|
|
if(xid_to) {
|
|
xid_to = unescape(xid_to);
|
|
|
|
$('#' + hash + ' .content .one-line:last .correction-edit').click(function() {
|
|
Correction.enter(xid_to);
|
|
return false;
|
|
});
|
|
}
|
|
} catch(e) {
|
|
Console.error('Message.display', e);
|
|
} finally {
|
|
return message_sel;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Return class scope
|
|
*/
|
|
return self;
|
|
|
|
})();
|