/* Jappix - An open social platform These are the messages JS scripts for Jappix ------------------------------------------------- License: AGPL Authors: Valérian Saliou, Maranda Last revision: 04/05/12 */ // Handles the incoming message packets function handleMessage(message) { // Error packet? Stop! if(handleErrorReply(message)) return; // MAM-forwarded message? var c_mam = message.getChild('result', NS_URN_MAM); if(c_mam) { var c_mam_delay = $(c_mam).find('delay[xmlns="' + NS_URN_DELAY + '"]'); var c_mam_forward = $(c_mam).find('forwarded[xmlns="' + NS_URN_FORWARD + '"]'); if(c_mam_forward.size()) { handleMessageMAM(c_mam_forward, c_mam_delay); } return; } // We get the message items var from = fullXID(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 = bareXID(from); var resource = thisResource(from); var hash = hex_md5(xid); var xHTML = $(node).find('html body').size(); var GCUser = false; // This message comes from a groupchat user if(isPrivate(xid) && ((type == 'chat') || !type) && resource) { GCUser = true; xid = from; hash = hex_md5(xid); } // Get message date var time, stamp; var delay = readMessageDelay(node); // Any delay? if(delay) { time = relativeDate(delay); stamp = extractStamp(Date.jab2date(delay)); } else { time = getCompleteTime(); stamp = extractStamp(new Date()); } // Received message if(hasReceived(message)) return messageReceived(hash, id); // Chatstate message if(node && !delay && ((((type == 'chat') || !type) && !exists('#page-switch .' + hash + ' .unavailable')) || (type == 'groupchat'))) { /* REF: http://xmpp.org/extensions/xep-0085.html */ // Re-process the hash var chatstate_hash = hash; if(type == 'groupchat') chatstate_hash = hex_md5(from); // Do something depending of the received state if($(node).find('active').size()) { displayChatState('active', chatstate_hash, type); // Tell Jappix the entity supports chatstates $('#' + chatstate_hash + ' .message-area').attr('data-chatstates', 'true'); logThis('Active chatstate received from: ' + from); } else if($(node).find('composing').size()) { displayChatState('composing', chatstate_hash, type); logThis('Composing chatstate received from: ' + from); } else if($(node).find('paused').size()) { displayChatState('paused', chatstate_hash, type); logThis('Paused chatstate received from: ' + from); } else if($(node).find('inactive').size()){ displayChatState('inactive', chatstate_hash, type); logThis('Inactive chatstate received from: ' + from); } else if($(node).find('gone').size()){ displayChatState('gone', chatstate_hash, type); logThis('Gone chatstate received from: ' + from); } } // Jappix App message if(message.getChild('app', 'jappix:app')) { // Get notification data var jappix_app_node = $(node).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 newNotification(jappix_me_notification_ns, xid, [jappix_app_name_value, jappix_app_data_url_value], body); logThis('Jappix Me notification from: ' + xid + ' with namespace: ' + jappix_me_notification_ns); return false; } } } // Invite message if($(node).find('x[xmlns="' + NS_MUC_USER + '"] invite').size()) { // We get the needed values var iFrom = $(node).find('x[xmlns="' + NS_MUC_USER + '"] invite').attr('from'); var iRoom = $(node).find('x[xmlns="' + NS_XCONFERENCE + '"]').attr('jid'); // Old invite method? if(!iRoom) iRoom = from; // We display the notification newNotification('invite_room', iFrom, [iRoom], body); logThis('Invite Request from: ' + iFrom + ' to join: ' + iRoom); return false; } // Request message if(message.getChild('confirm', NS_HTTP_AUTH)) { // Open a new notification newNotification('request', xid, [message], body); logThis('HTTP Request from: ' + xid); return false; } // OOB message if(message.getChild('x', NS_XOOB)) { handleOOB(from, id, 'x', node); logThis('Message OOB request from: ' + xid); return false; } // Roster Item Exchange message if(message.getChild('x', NS_ROSTERX)) { // Open a new notification newNotification('rosterx', xid, [message], body); logThis('Roster Item Exchange from: ' + xid); return false; } // Normal message if((type == 'normal') && body) { // Message date var messageDate = delay; // No message date? if(!messageDate) messageDate = getXMPPTime('utc'); // Message ID var messageID = hex_md5(xid + subject + messageDate); // We store the received message storeInboxMessage(xid, subject, body, 'unread', messageID, messageDate); // Display the inbox message if(exists('#inbox')) displayInboxMessage(xid, subject, body, 'unread', messageID, messageDate); // Check we have new messages (play a sound if any unread messages) if(checkInboxMessages()) soundPlay(2); // Send it to the server storeInbox(); return false; } // PubSub event if($(node).find('event').attr('xmlns') == NS_PUBSUB_EVENT) { // We get the needed values var iParse = $(node).find('event items'); var iNode = iParse.attr('node'); // Turn around the different result cases if(iNode) { switch(iNode) { // Mood case NS_MOOD: // Retrieve the values var iMood = iParse.find('mood'); var fValue = ''; var tText = ''; // There's something if(iMood.children().size()) { // Read the value fValue = node.getElementsByTagName('mood').item(0).childNodes.item(0).nodeName; // Read the text tText = iMood.find('text').text(); // Avoid errors if(!fValue) fValue = ''; } // Store the PEP event (and display it) storePEP(xid, 'mood', fValue, tText); break; // Activity case NS_ACTIVITY: // Retrieve the values var iActivity = iParse.find('activity'); var sValue = ''; var tText = ''; // There's something if(iActivity.children().size()) { // Read the value fValue = node.getElementsByTagName('activity').item(0).childNodes.item(0).nodeName; // Read the text tText = iActivity.find('text').text(); // Avoid errors if(!fValue) fValue = ''; } // Store the PEP event (and display it) storePEP(xid, 'activity', fValue, tText); break; // Tune case NS_TUNE: // Retrieve the values var iTune = iParse.find('tune'); var tArtist = iTune.find('artist').text(); var tSource = iTune.find('source').text(); var tTitle = iTune.find('title').text(); var tURI = iTune.find('uri').text(); // Store the PEP event (and display it) storePEP(xid, 'tune', tArtist, tTitle, tSource, tURI); break; // Geolocation case NS_GEOLOC: // Retrieve the values var iGeoloc = iParse.find('geoloc'); var tLat = iGeoloc.find('lat').text(); var tLon = iGeoloc.find('lon').text(); // Any extra-values? var tLocality = iGeoloc.find('locality').text(); var tRegion = iGeoloc.find('region').text(); var tCountry = iGeoloc.find('country').text(); var tHuman = humanPosition(tLocality, tRegion, tCountry); // Store the PEP event (and display it) storePEP(xid, 'geoloc', tLat, tLon, tHuman); break; // Microblog case NS_URN_MBLOG: displayMicroblog(message, xid, hash, 'mixed', 'push'); break; // Inbox case NS_URN_INBOX: // Do not handle friend's notifications if(xid == getXID()) handleNotifications(message); break; } } return false; } // If this is a room topic message if(subject && (type == 'groupchat')) { // Filter the vars var filter_subject = subject.replace(/\n+/g, ' '); var filteredSubject = filterThisMessage(filter_subject, resource, true); var filteredName = resource.htmlEnc(); // Display the new subject at the top $('#' + hash + ' .top .name .bc-infos .muc-topic').replaceWith('' + filteredSubject + ''); // Display the new subject as a system message if(resource) { var topic_body = filteredName + ' ' + _e("changed the subject to:") + ' ' + filterThisMessage(subject, resource, true); displayMessage(type, from, hash, filteredName, topic_body, time, stamp, 'system-message', false); } } // 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 = filterThisXHTML(node); } // Groupchat message if(type == 'groupchat') { /* REF: http://xmpp.org/extensions/xep-0045.html */ // We generate the message type and time var message_type = 'user-message'; // This is an old message if(delay && resource) message_type = 'old-message'; // This is a system message else if(!resource) message_type = 'system-message'; var nickQuote = ''; // If this is not an old message if(message_type == 'user-message') { var myNick = getMUCNick(hash); // If an user quoted our nick (with some checks) var regex = new RegExp('((^)|( )|(@))' + 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) { messageNotify(hash, 'personal'); quickBoard(from, 'groupchat', raw_body, resource); soundPlay(1); } // We notify the user there's a new unread MUC message else { messageNotify(hash, 'unread'); // Play sound to all users in the MUC, except user who sent the message. if(myNick != resource) soundPlay(1); } } // Display the received message displayMessage(type, from, hash, resource.htmlEnc(), body, time, stamp, message_type, html_escape, nickQuote); } // Chat message else { // Gets the nickname of the user var fromName = resource; var chatType = 'chat'; // Must send a receipt notification? if(hasReceipt(message) && (id != null)) sendReceived(type, from, id); // It does not come from a groupchat user, get the full name if(!GCUser) fromName = getBuddyName(xid); else chatType = 'private'; // If the chat isn't yet opened, open it ! if(!exists('#' + hash)) { // We create a new chat chatCreate(hash, xid, fromName, chatType); // We tell the user that a new chat has started soundPlay(0); } else { soundPlay(1); } // Display the received message displayMessage(type, xid, hash, fromName.htmlEnc(), body, time, stamp, 'user-message', html_escape, '', 'him'); // We notify the user messageNotify(hash, 'personal'); quickBoard(xid, 'chat', raw_body, fromName); } return false; } return false; } // Sends a given message function sendMessage(hash, type) { // Get the values var message_area = $('#' + hash + ' .message-area'); var body = trim(message_area.val()); var xid = unescape(message_area.attr('data-to')); // If the user didn't entered any message, stop if(!body || !xid) return false; try { // We send the message through the XMPP network var aMsg = new JSJaCMessage(); aMsg.setTo(xid); // Set an ID var id = genID(); aMsg.setID(id); // /help shortcut if(body.match(/^\/help\s*(.*)/)) { // Help text var help_text = '
';
help_text += '' + _e("Available shortcuts:") + '';
// Shortcuts array
var shortcuts = [];
// Common shortcuts
shortcuts.push(printf(_e("%s removes the chat logs"), '/clear'));
shortcuts.push(printf(_e("%s joins a groupchat"), '/join jid'));
shortcuts.push(printf(_e("%s closes the chat"), '/part'));
shortcuts.push(printf(_e("%s shows the user profile"), '/whois jid'));
// Groupchat shortcuts
if(type == 'groupchat') {
shortcuts.push(printf(_e("%s sends a message to the room"), '/say message'));
shortcuts.push(printf(_e("%s changes your nickname"), '/nick nickname'));
shortcuts.push(printf(_e("%s sends a message to someone in the room"), '/msg nickname message'));
shortcuts.push(printf(_e("%s changes the room topic"), '/topic subject'));
shortcuts.push(printf(_e("%s kicks a user of the room"), '/kick [reason:] nickname'));
shortcuts.push(printf(_e("%s bans a user of the room"), '/ban [reason:] nickname'));
shortcuts.push(printf(_e("%s invites someone to join the room"), '/invite jid message'));
}
// Generate the code from the array
shortcuts = shortcuts.sort();
for(s in shortcuts)
help_text += shortcuts[s] + '
';
help_text += '
' + cLine + '
')); } } return 'XHTML'; } return 'PLAIN'; } // Displays a given message in a chat tab function displayMessage(type, xid, hash, name, body, time, stamp, message_type, html_escape, nick_quote, mode, id, c_target_sel, no_scroll) { // Target if(typeof c_target_sel === 'undefined') { c_target_sel = $('#' + hash + ' .content'); } // 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 + '"'; } // Filter the message var filteredMessage = filterThisMessage(body, name, html_escape); // Display the received message in the room var messageCode = ' '; // Must group it? if(!grouped) { // Generate message headers var message_head = ''; // Any avatar to add? if(has_avatar) { message_head += ''; } // Add the date & the name message_head += '' + time + '' + name + ''; // Generate message code messageCode = '