c3d2-web/content/static/candy/src/core/action.js

420 lines
12 KiB
JavaScript

/** File: action.js
* Candy - Chats are not dead yet.
*
* Authors:
* - Patrick Stadler <patrick.stadler@gmail.com>
* - Michael Weibel <michael.weibel@gmail.com>
*
* Copyright:
* (c) 2011 Amiado Group AG. All rights reserved.
* (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved.
*/
'use strict';
/* global Candy, $iq, navigator, Candy, $pres, Strophe, jQuery, $msg */
/** Class: Candy.Core.Action
* Chat Actions (basicly a abstraction of Jabber commands)
*
* Parameters:
* (Candy.Core.Action) self - itself
* (Strophe) Strophe - Strophe
* (jQuery) $ - jQuery
*/
Candy.Core.Action = (function(self, Strophe, $) {
/** Class: Candy.Core.Action.Jabber
* Jabber actions
*/
self.Jabber = {
/** Function: Version
* Replies to a version request
*
* Parameters:
* (jQuery.element) msg - jQuery element
*/
Version: function(msg) {
Candy.Core.getConnection().sendIQ($iq({
type: 'result',
to: Candy.Util.escapeJid(msg.attr('from')),
from: Candy.Util.escapeJid(msg.attr('to')),
id: msg.attr('id')
}).c('query', {
name: Candy.about.name,
version: Candy.about.version,
os: navigator.userAgent
}));
},
/** Function: SetNickname
* Sets the supplied nickname for all rooms (if parameter "room" is not specified) or
* sets it only for the specified rooms
*
* Parameters:
* (String) nickname - New nickname
* (Array) rooms - Rooms
*/
SetNickname: function(nickname, rooms) {
rooms = rooms instanceof Array ? rooms : Candy.Core.getRooms();
var roomNick, presence,
conn = Candy.Core.getConnection();
$.each(rooms, function(roomJid) {
roomNick = Candy.Util.escapeJid(roomJid + '/' + nickname);
presence = $pres({
to: roomNick,
from: conn.jid,
id: 'pres:' + conn.getUniqueId()
});
Candy.Core.getConnection().send(presence);
});
},
/** Function: Roster
* Sends a request for a roster
*/
Roster: function() {
Candy.Core.getConnection().sendIQ($iq({
type: 'get',
xmlns: Strophe.NS.CLIENT
}).c('query', {xmlns: Strophe.NS.ROSTER}).tree());
},
/** Function: Presence
* Sends a request for presence
*
* Parameters:
* (Object) attr - Optional attributes
* (Strophe.Builder) el - Optional element to include in presence stanza
*/
Presence: function(attr, el) {
var conn = Candy.Core.getConnection();
attr = attr || {};
if(!attr.id) {
attr.id = 'pres:' + conn.getUniqueId();
}
var pres = $pres(attr).c('priority').t(Candy.Core.getOptions().presencePriority.toString())
.up().c('c', conn.caps.generateCapsAttrs())
.up();
if(el) {
pres.node.appendChild(el.node);
}
conn.send(pres.tree());
},
/** Function: Services
* Sends a request for disco items
*/
Services: function() {
Candy.Core.getConnection().sendIQ($iq({
type: 'get',
xmlns: Strophe.NS.CLIENT
}).c('query', {xmlns: Strophe.NS.DISCO_ITEMS}).tree());
},
/** Function: Autojoin
* When Candy.Core.getOptions().autojoin is true, request autojoin bookmarks (OpenFire)
*
* Otherwise, if Candy.Core.getOptions().autojoin is an array, join each channel specified.
* Channel can be in jid:password format to pass room password if needed.
* Triggers:
* candy:core.autojoin-missing in case no autojoin info has been found
*/
Autojoin: function() {
// Request bookmarks
if(Candy.Core.getOptions().autojoin === true) {
Candy.Core.getConnection().sendIQ($iq({
type: 'get',
xmlns: Strophe.NS.CLIENT
})
.c('query', {xmlns: Strophe.NS.PRIVATE})
.c('storage', {xmlns: Strophe.NS.BOOKMARKS})
.tree());
var pubsubBookmarkRequest = Candy.Core.getConnection().getUniqueId('pubsub');
Candy.Core.addHandler(Candy.Core.Event.Jabber.Bookmarks, Strophe.NS.PUBSUB, 'iq', 'result', pubsubBookmarkRequest);
Candy.Core.getConnection().sendIQ($iq({
type: 'get',
id: pubsubBookmarkRequest
})
.c('pubsub', { xmlns: Strophe.NS.PUBSUB })
.c('items', { node: Strophe.NS.BOOKMARKS })
.tree());
// Join defined rooms
} else if($.isArray(Candy.Core.getOptions().autojoin)) {
$.each(Candy.Core.getOptions().autojoin, function() {
self.Jabber.Room.Join.apply(null, this.valueOf().split(':',2));
});
} else {
/** Event: candy:core.autojoin-missing
* Triggered when no autojoin information has been found
*/
$(Candy).triggerHandler('candy:core.autojoin-missing');
}
},
/** Function: ResetIgnoreList
* Create new ignore privacy list (and reset the previous one, if it exists).
*/
ResetIgnoreList: function() {
Candy.Core.getConnection().sendIQ($iq({
type: 'set',
from: Candy.Core.getUser().getEscapedJid()
})
.c('query', {xmlns: Strophe.NS.PRIVACY })
.c('list', {name: 'ignore'})
.c('item', {'action': 'allow', 'order': '0'})
.tree());
},
/** Function: RemoveIgnoreList
* Remove an existing ignore list.
*/
RemoveIgnoreList: function() {
Candy.Core.getConnection().sendIQ($iq({
type: 'set',
from: Candy.Core.getUser().getEscapedJid()
})
.c('query', {xmlns: Strophe.NS.PRIVACY })
.c('list', {name: 'ignore'}).tree());
},
/** Function: GetIgnoreList
* Get existing ignore privacy list when connecting.
*/
GetIgnoreList: function() {
var iq = $iq({
type: 'get',
from: Candy.Core.getUser().getEscapedJid()
})
.c('query', {xmlns: Strophe.NS.PRIVACY})
.c('list', {name: 'ignore'}).tree();
var iqId = Candy.Core.getConnection().sendIQ(iq);
// add handler (<#200 at https://github.com/candy-chat/candy/issues/200>)
Candy.Core.addHandler(Candy.Core.Event.Jabber.PrivacyList, null, 'iq', null, iqId);
},
/** Function: SetIgnoreListActive
* Set ignore privacy list active
*/
SetIgnoreListActive: function() {
Candy.Core.getConnection().sendIQ($iq({
type: 'set',
from: Candy.Core.getUser().getEscapedJid()})
.c('query', {xmlns: Strophe.NS.PRIVACY })
.c('active', {name:'ignore'}).tree());
},
/** Function: GetJidIfAnonymous
* On anonymous login, initially we don't know the jid and as a result, Candy.Core._user doesn't have a jid.
* Check if user doesn't have a jid and get it if necessary from the connection.
*/
GetJidIfAnonymous: function() {
if (!Candy.Core.getUser().getJid()) {
Candy.Core.log("[Jabber] Anonymous login");
Candy.Core.getUser().data.jid = Candy.Core.getConnection().jid;
}
},
/** Class: Candy.Core.Action.Jabber.Room
* Room-specific commands
*/
Room: {
/** Function: Join
* Requests disco of specified room and joins afterwards.
*
* TODO:
* maybe we should wait for disco and later join the room?
* but what if we send disco but don't want/can join the room
*
* Parameters:
* (String) roomJid - Room to join
* (String) password - [optional] Password for the room
*/
Join: function(roomJid, password) {
self.Jabber.Room.Disco(roomJid);
roomJid = Candy.Util.escapeJid(roomJid);
var conn = Candy.Core.getConnection(),
roomNick = roomJid + '/' + Candy.Core.getUser().getNick(),
pres = $pres({ to: roomNick, id: 'pres:' + conn.getUniqueId() })
.c('x', {xmlns: Strophe.NS.MUC});
if (password) {
pres.c('password').t(password);
}
pres.up().c('c', conn.caps.generateCapsAttrs());
conn.send(pres.tree());
},
/** Function: Leave
* Leaves a room.
*
* Parameters:
* (String) roomJid - Room to leave
*/
Leave: function(roomJid) {
var user = Candy.Core.getRoom(roomJid).getUser();
roomJid = Candy.Util.escapeJid(roomJid);
if (user) {
Candy.Core.getConnection().muc.leave(roomJid, user.getNick(), function() {});
}
},
/** Function: Disco
* Requests <disco info of a room at http://xmpp.org/extensions/xep-0045.html#disco-roominfo>.
*
* Parameters:
* (String) roomJid - Room to get info for
*/
Disco: function(roomJid) {
Candy.Core.getConnection().sendIQ($iq({
type: 'get',
from: Candy.Core.getUser().getEscapedJid(),
to: Candy.Util.escapeJid(roomJid)
}).c('query', {xmlns: Strophe.NS.DISCO_INFO}).tree());
},
/** Function: Message
* Send message
*
* Parameters:
* (String) roomJid - Room to which send the message into
* (String) msg - Message
* (String) type - "groupchat" or "chat" ("chat" is for private messages)
* (String) xhtmlMsg - XHTML formatted message [optional]
*
* Returns:
* (Boolean) - true if message is not empty after trimming, false otherwise.
*/
Message: function(roomJid, msg, type, xhtmlMsg) {
// Trim message
msg = $.trim(msg);
if(msg === '') {
return false;
}
var nick = null;
if(type === 'chat') {
nick = Strophe.getResourceFromJid(roomJid);
roomJid = Strophe.getBareJidFromJid(roomJid);
}
// muc takes care of the escaping now.
Candy.Core.getConnection().muc.message(roomJid, nick, msg, xhtmlMsg, type);
return true;
},
/** Function: Invite
* Sends an invite stanza to multiple JIDs
*
* Parameters:
* (String) roomJid - Room to which send the message into
* (Array) invitees - Array of JIDs to be invited to the room
* (String) reason - Message to include with the invitation [optional]
* (String) password - Password for the MUC, if required [optional]
*/
Invite: function(roomJid, invitees, reason, password) {
reason = $.trim(reason);
var message = $msg({to: roomJid});
var x = message.c('x', {xmlns: Strophe.NS.MUC_USER});
$.each(invitees, function(i, invitee) {
invitee = Strophe.getBareJidFromJid(invitee);
x.c('invite', {to: invitee});
if (typeof reason !== 'undefined' && reason !== '') {
x.c('reason', reason);
}
});
if (typeof password !== 'undefined' && password !== '') {
x.c('password', password);
}
Candy.Core.getConnection().send(message);
},
/** Function: IgnoreUnignore
* Checks if the user is already ignoring the target user, if yes: unignore him, if no: ignore him.
*
* Uses the ignore privacy list set on connecting.
*
* Parameters:
* (String) userJid - Target user jid
*/
IgnoreUnignore: function(userJid) {
Candy.Core.getUser().addToOrRemoveFromPrivacyList('ignore', userJid);
Candy.Core.Action.Jabber.Room.UpdatePrivacyList();
},
/** Function: UpdatePrivacyList
* Updates privacy list according to the privacylist in the currentUser
*/
UpdatePrivacyList: function() {
var currentUser = Candy.Core.getUser(),
iq = $iq({type: 'set', from: currentUser.getEscapedJid()})
.c('query', {xmlns: 'jabber:iq:privacy' })
.c('list', {name: 'ignore'}),
privacyList = currentUser.getPrivacyList('ignore');
if (privacyList.length > 0) {
$.each(privacyList, function(index, jid) {
iq.c('item', {type:'jid', value: Candy.Util.escapeJid(jid), action: 'deny', order : index})
.c('message').up().up();
});
} else {
iq.c('item', {action: 'allow', order : '0'});
}
Candy.Core.getConnection().sendIQ(iq.tree());
},
/** Class: Candy.Core.Action.Jabber.Room.Admin
* Room administration commands
*/
Admin: {
/** Function: UserAction
* Kick or ban a user
*
* Parameters:
* (String) roomJid - Room in which the kick/ban should be done
* (String) userJid - Victim
* (String) type - "kick" or "ban"
* (String) msg - Reason
*
* Returns:
* (Boolean) - true if sent successfully, false if type is not one of "kick" or "ban".
*/
UserAction: function(roomJid, userJid, type, reason) {
roomJid = Candy.Util.escapeJid(roomJid);
userJid = Candy.Util.escapeJid(userJid);
var itemObj = {nick: Strophe.getResourceFromJid(userJid)};
switch(type) {
case 'kick':
itemObj.role = 'none';
break;
case 'ban':
itemObj.affiliation = 'outcast';
break;
default:
return false;
}
Candy.Core.getConnection().sendIQ($iq({
type: 'set',
from: Candy.Core.getUser().getEscapedJid(),
to: roomJid
}).c('query', {xmlns: Strophe.NS.MUC_ADMIN })
.c('item', itemObj).c('reason').t(reason).tree());
return true;
},
/** Function: SetSubject
* Sets subject (topic) of a room.
*
* Parameters:
* (String) roomJid - Room
* (String) subject - Subject to set
*/
SetSubject: function(roomJid, subject) {
Candy.Core.getConnection().muc.setTopic(Candy.Util.escapeJid(roomJid), subject);
}
}
}
};
return self;
}(Candy.Core.Action || {}, Strophe, jQuery));