1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/jappix_ynh.git synced 2024-09-03 19:26:19 +02:00
jappix_ynh/source/app/javascripts/groupchat.js
2014-04-08 20:14:28 +02:00

680 lines
No EOL
21 KiB
JavaScript

/*
Jappix - An open social platform
These are the groupchat JS scripts for Jappix
-------------------------------------------------
License: AGPL
Authors: Valérian Saliou, Maranda, Eric
*/
// Bundle
var Groupchat = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/* Variables */
var JOIN_SUGGEST = [];
/**
* Displays the MUC admin elements
* @public
* @param {string} affiliation
* @param {string} id
* @param {string} xid
* @param {number} statuscode
* @return {undefined}
*/
self.openAdmin = function(affiliation, id, xid, statuscode) {
try {
// We must be in the "login" mode
if(Utils.isAnonymous())
return;
// We check if the user is a room owner or administrator to give him privileges
if(affiliation == 'owner' || affiliation == 'admin')
$('#' + id + ' .tools-mucadmin').show();
// We check if the room hasn't been yet created
if(statuscode == 201)
Board.openThisInfo(4);
// We add the click event
$('#' + id + ' .tools-mucadmin').click(function() {
MUCAdmin.open(xid, affiliation);
});
} catch(e) {
Console.error('Groupchat.openAdmin', e);
}
};
/**
* Initializes a connection with a MUC groupchat
* @public
* @param {string} room
* @param {string} nickname
* @param {string} password
* @return {boolean}
*/
self.getMUC = function(room, nickname, password) {
try {
// Room hash
var hash = hex_md5(room);
// Reset the elements
$('#' + hash + ' .muc-ask').remove();
$('#' + hash + ' .compose').show();
// No nickname?
if(!nickname) {
// Get some values
if(!Utils.isAnonymous())
nickname = Name.getNick();
else
nickname = ANONYMOUS_NICK;
// If the nickname could not be retrieved, ask it
if(!nickname)
self.generateMUCAsk('nickname', room, hash, nickname, password);
}
// Got our nickname?
if(nickname) {
// Get our general presence
var show = DataStore.getDB(Connection.desktop_hash, 'presence-show', 1);
var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status');
// Set my nick
$('#' + hash).attr('data-nick', escape(nickname));
// Send the appropriate presence
Presence.send(room + '/' + nickname, '', show, status, '', true, password, self.handleMUC);
}
} catch(e) {
Console.error('Groupchat.getMUC', e);
} finally {
return false;
}
};
/**
* Handles the MUC main elements
* @public
* @param {object} presence
* @return {undefined}
*/
self.handleMUC = function(presence) {
try {
// We get the xml content
var xml = presence.getNode();
var from = Common.fullXID(Common.getStanzaFrom(presence));
var room = Common.bareXID(from);
var nickname = Common.thisResource(from);
var hash = hex_md5(room);
// No ID: must fix M-Link bug
if(presence.getID() === null) {
presence.setID(1);
}
Console.info('First MUC presence: ' + from);
// Catch the errors
if(!Errors.handle(xml)) {
// Define some stuffs
var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]');
var affiliation = muc_user.find('item').attr('affiliation');
var statuscode = parseInt(muc_user.find('status').attr('code'));
// Handle my presence
Presence.handle(presence);
// Check if I am a room owner
self.openAdmin(affiliation, hash, room, statuscode);
// Tell the MUC we can notify the incoming presences
$(document).oneTime('15s', function() {
$('#' + hash).attr('data-initial', 'true');
});
// Enable the chatting input
$(document).oneTime(10, function() {
$('#' + hash + ' .message-area').removeAttr('disabled').focus();
});
}
// A password is required
else if($(xml).find('error[type="auth"] not-authorized').size()) {
self.generateMUCAsk('password', room, hash, nickname);
}
// There's a nickname conflict
else if($(xml).find('error[type="cancel"] conflict').size()) {
self.generateMUCAsk('nickname', room, hash);
}
} catch(e) {
Console.error('Groupchat.handleMUC', e);
}
};
/**
* Generates a correct MUC asker
* @public
* @param {string} type
* @param {string} room
* @param {string} hash
* @param {string} nickname
* @param {string} password
* @return {undefined}
*/
self.generateMUCAsk = function(type, room, hash, nickname, password) {
try {
// Generate the path to the elements
var path_to = '#' + hash + ' .muc-ask';
// Define the label text
var label_text;
switch(type) {
case 'nickname':
label_text = Common._e("Nickname");
break;
case 'password':
label_text = Common._e("Password");
break;
}
// Create the HTML markup
$('#' + hash + ' .compose').hide();
$('#' + hash).append(
'<div class="muc-ask text">' +
'<label>' + label_text + '</label>' +
'<input class="focusable" type="text" />' +
'</div>'
);
// When a key is pressed in the input
$(path_to + ' input').keyup(function(e) {
var value_input = $(this).val();
// Enter key pressed
if(e.keyCode == 13) {
// $.trim() fixes #304
if(type == 'nickname' && $.trim(value_input)) {
nickname = $.trim(value_input);
return self.getMUC(room, nickname, password);
}
if(type == 'password' && value_input) {
password = value_input;
return self.getMUC(room, nickname, password);
}
}
});
// Focus on the input
$(document).oneTime(10, function() {
$(path_to + ' input').focus();
});
} catch(e) {
Console.error('Groupchat.generateMUCAsk', e);
}
};
/**
* Creates a new groupchat
* @public
* @param {string} hash
* @param {string} room
* @param {string} chan
* @param {string} nickname
* @param {string} password
* @return {undefined}
*/
self.create = function(hash, room, chan, nickname, password) {
/* REF: http://xmpp.org/extensions/xep-0045.html */
try {
Console.info('New groupchat: ' + room);
// Create the chat content
Chat.generate('groupchat', hash, room, chan);
// Create the chat switcher
Chat.generateSwitch('groupchat', hash, room, chan);
// The icons-hover functions
Tooltip.icons(room, hash);
// Click event on the add tool
$('#' + hash + ' .tools-add').click(function() {
// Hide the icon (to tell the user all is okay)
$(this).hide();
// Add the groupchat to the user favorites
Favorites.addThis(room, chan);
});
// Must show the add button?
if(!DataStore.existDB('favorites', room))
$('#' + hash + ' .tools-add').show();
// The event handlers
var inputDetect = $('#' + hash + ' .message-area');
// Focus event
inputDetect.focus(function() {
// Clean notifications for this chat
Interface.chanCleanNotify(hash);
// Store focus on this chat!
Interface.chat_focus_hash = hash;
});
// Blur event
inputDetect.blur(function() {
// Reset storage about focus on this chat!
if(Interface.chat_focus_hash == hash)
Interface.chat_focus_hash = null;
// Reset autocompletion
Autocompletion.reset(hash);
});
// Lock to the input
inputDetect.keydown(function(e) {
// Enter key
if(e.keyCode == 13) {
// If shift key (without any others modifiers) was pressed, add a new line
if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
inputDetect.val(inputDetect.val() + '\n');
// Send the message
else {
Message.send(hash, 'groupchat');
// Reset the composing database entry
DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off');
}
return false;
}
// Tabulation key (without any modifiers)
else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) {
Autocompletion.create(hash);
return false;
}
// Reset the autocompleter
else {
Autocompletion.reset(hash);
}
});
// Chatstate events
ChatState.events(inputDetect, room, hash, 'groupchat');
// Get the current muc informations and content
self.getMUC(room, nickname, password);
} catch(e) {
Console.error('Groupchat.create', e);
}
};
/**
* Generates a groupchat to join array
* @public
* @return {object}
*/
self.arrayJoin = function() {
try {
// Values array
var muc_arr = [GROUPCHATS_JOIN];
var new_arr = [];
// Try to split it
if(GROUPCHATS_JOIN.indexOf(',') != -1)
muc_arr = GROUPCHATS_JOIN.split(',');
for(var i in muc_arr) {
// Get the current value
var muc_current = $.trim(muc_arr[i]);
// No current value?
if(!muc_current)
continue;
// Filter the current value
muc_current = Common.generateXID(muc_current, 'groupchat');
// Add the current value
if(!Utils.existArrayValue(new_arr, muc_current))
new_arr.push(muc_current);
}
return new_arr;
} catch(e) {
Console.error('Groupchat.arrayJoin', e);
}
};
/**
* Joins the defined groupchats
* @public
* @return {undefined}
*/
self.joinConf = function() {
try {
// Nothing to join?
if(!JOIN_SUGGEST)
return;
// Join the chats
if(JOIN_SUGGEST.length) {
for(var g in JOIN_SUGGEST) {
Chat.checkCreate(JOIN_SUGGEST[g], 'groupchat');
}
}
} catch(e) {
Console.error('Groupchat.joinConf', e);
}
};
/**
* Checks suggest utility
* @public
* @return {undefined}
*/
self.suggestCheck = function() {
try {
var groupchat_arr = self.arrayJoin();
// Must suggest the user?
if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) {
if(Common.exists('#suggest'))
return;
// Create HTML code
var html = '<div id="suggest" class="removable">';
html += '<div class="title">' + Common._e("Suggested chatrooms") + '</div>';
html += '<div class="content">';
for(var g in groupchat_arr) {
html += '<a class="one" href="#" data-xid="' + Common.encodeQuotes(groupchat_arr[g]) + '">';
html += '<span class="icon talk-images"></span>';
html += '<span class="name">' + Utils.capitaliseFirstLetter(Common.getXIDNick(groupchat_arr[g]).htmlEnc()) + '</span>';
html += '<span class="state talk-images"></span>';
html += '<span class="clear"></span>';
html += '</a>';
}
html += '</div>';
html += '<div class="bottom">';
html += '<a class="next continue disabled" href="#">' + Common._e("Continue") + '</a>';
html += '<a class="next skip" href="#">' + Common._e("Skip") + '</a>';
html += '</div>';
html += '</div>';
// Append HTML code
$('body').append(html);
// Click events
$('#suggest .content a.one').click(function() {
// Add/remove the active class
$(this).toggleClass('active');
// We require at least one room to be chosen
if(Common.exists('#suggest .content a.one.active'))
$('#suggest a.next').removeClass('disabled');
else
$('#suggest a.next').addClass('disabled');
return false;
});
$('#suggest a.next').click(function() {
// Disabled?
if($(this).hasClass('disabled')) {
return false;
}
// Store groupchats to join?
if($(this).is('.continue')) {
$('#suggest .content a.one.active').each(function() {
JOIN_SUGGEST.push($(this).attr('data-xid'));
});
}
// Switch to talk UI
$('#suggest').remove();
Connection.triggerConnected();
return false;
});
} else {
JOIN_SUGGEST = groupchat_arr;
Connection.triggerConnected();
}
} catch(e) {
Console.error('Groupchat.suggestCheck', e);
}
};
/**
* Bans a user from given room
* @public
* @param {string} room_xid
* @param {string} ban_xid
* @param {string} reason
* @return {object}
*/
self.banUser = function(room_xid, ban_xid, reason) {
try {
// We check if the user exists
if(!ban_xid) {
Board.openThisInfo(6);
Console.warning('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
} else {
// We generate the ban IQ
var iq = new JSJaCIQ();
iq.setTo(room_xid);
iq.setType('set');
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
var item = iqQuery.appendChild(iq.buildNode('item', {'affiliation': 'outcast', 'jid': ban_xid, 'xmlns': NS_MUC_ADMIN}));
if(reason) {
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
}
con.send(iq, Errors.handleReply);
Console.log('Banned user with XID: ' + ban_xid + ' from room: ' + room_xid);
}
} catch(e) {
Console.error('Groupchat.banUser', e);
}
};
/**
* Kicks a user from given room
* @public
* @param {string} room_xid
* @param {string} kick_xid
* @param {string} nick
* @param {string} reason
* @return {object}
*/
self.kickUser = function(room_xid, kick_xid, nick, reason) {
try {
// We check if the user exists
if(!room_xid) {
Board.openThisInfo(6);
Console.warning('Could not kick user "' + nick + '" from room: ' + room_xid);
} else {
// We generate the kick IQ
var iq = new JSJaCIQ();
iq.setTo(room_xid);
iq.setType('set');
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
var item = iqQuery.appendChild(iq.buildNode('item', {'nick': nick, 'role': 'none', 'xmlns': NS_MUC_ADMIN}));
if(reason) {
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
}
con.send(iq, Errors.handleReply);
Console.info('Kicked user "' + nick + '" from room: ' + room_xid);
}
} catch(e) {
Console.error('Groupchat.kickUser', e);
}
};
/**
* Promotes an user as groupchat moderator
* @public
* @param {string} muc_xid
* @param {string} user_xid
* @return {object}
*/
self.promoteModerator = function(muc_xid, user_xid) {
try {
MUCAdmin.setAffiliation(muc_xid, user_xid, 'admin');
} catch(e) {
Console.error('Groupchat.promoteModerator', e);
}
};
/**
* Demotes an user as being groupchat moderator
* @public
* @param {string} muc_xid
* @param {string} user_xid
* @return {object}
*/
self.demoteModerator = function(muc_xid, user_xid) {
try {
MUCAdmin.setAffiliation(muc_xid, user_xid, 'none');
} catch(e) {
Console.error('Groupchat.demoteModerator', e);
}
};
/**
* Returns user affiliation in groupchat
* @public
* @param {string} muc_xid
* @param {string} nick
* @return {object}
*/
self.affiliationUser = function(muc_xid, nick) {
try {
// Initial data
var affiliations = ['none', 'member', 'admin', 'owner'];
var affiliation = {
code: 0,
name: affiliations[0]
};
// Get user data
var user_sel = $('#' + hex_md5(muc_xid) + ' .list .user[data-nick="' + escape(nick) + '"]');
if(user_sel.size()) {
var user_affiliation = user_sel.attr('data-affiliation');
if(user_affiliation && Utils.existArrayValue(affiliations, user_affiliation)) {
affiliation.code = Utils.indexArrayValue(affiliations, user_affiliation);
affiliation.name = user_affiliation;
}
}
return affiliation;
} catch(e) {
Console.error('Groupchat.affiliationUser', e);
}
};
/**
* Returns our affiliation in groupchat
* @public
* @param {string} muc_xid
* @return {object}
*/
self.affiliationMe = function(muc_xid) {
try {
// Get my nick
var my_nick = unescape($('#' + hex_md5(muc_xid)).attr('data-nick') || '');
// Return my affiliation
return self.affiliationUser(muc_xid, my_nick);
} catch(e) {
Console.error('Groupchat.affiliationMe', e);
}
};
/**
* Return class scope
*/
return self;
})();