var Session; var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; Session = (function() { function Session() { this.xmpp = new Strophe.Connection('/xmpp'); this.roster = {}; this.listeners = { card: [], message: [], presence: [], roster: [] }; } Session.prototype.connect = function(jid, password, callback) { return this.xmpp.connect(jid, password, __bind(function(status) { switch (status) { case Strophe.Status.CONNFAIL: return callback(false); case Strophe.Status.CONNECTED: this.xmpp.addHandler((__bind(function(el) { return this.handleIq(el); }, this)), null, 'iq'); this.xmpp.addHandler((__bind(function(el) { return this.handleMessage(el); }, this)), null, 'message'); this.xmpp.addHandler((__bind(function(el) { return this.handlePresence(el); }, this)), null, 'presence'); callback(true); return this.findRoster(__bind(function() { this.notify('roster'); this.xmpp.send($pres().tree()); return this.findCards(); }, this)); } }, this)); }; Session.prototype.disconnect = function() { return this.xmpp.disconnect(); }; Session.prototype.onCard = function(callback) { return this.listeners['card'].push(callback); }; Session.prototype.onRoster = function(callback) { return this.listeners['roster'].push(callback); }; Session.prototype.onMessage = function(callback) { return this.listeners['message'].push(callback); }; Session.prototype.onPresence = function(callback) { return this.listeners['presence'].push(callback); }; Session.prototype.connected = function() { return this.xmpp.jid && this.xmpp.jid.length > 0; }; Session.prototype.jid = function() { return this.xmpp.jid; }; Session.prototype.bareJid = function() { return this.xmpp.jid.split('/')[0]; }; Session.prototype.avatar = function(jid) { var card; card = this.loadCard(jid); if (card && card.photo) { return "data:" + card.photo.type + ";base64," + card.photo.binval; } else { return '/lib/images/default-user.png'; } }; Session.prototype.loadCard = function(jid) { var found; jid = jid.split('/')[0]; found = localStorage['vcard:' + jid]; if (found) { return JSON.parse(found); } }; Session.prototype.storeCard = function(card) { return localStorage['vcard:' + card.jid] = JSON.stringify(card); }; Session.prototype.findCards = function() { var contacts, jid, jids, success; jids = (function() { var _ref, _results; _ref = this.roster; _results = []; for (jid in _ref) { contacts = _ref[jid]; if (!this.loadCard(jid)) { _results.push(jid); } } return _results; }).call(this); if (!this.loadCard(this.bareJid())) { jids.push(this.bareJid()); } success = __bind(function(card) { this.findCard(jids.shift(), success); if (card) { this.storeCard(card); return this.notify('card', card); } }, this); return this.findCard(jids.shift(), success); }; Session.prototype.findCard = function(jid, callback) { var handler, iq; if (!jid) { return; } handler = function(result) { var bin, card, photo, type, vcard; card = $('vCard', result); photo = $('PHOTO', card); type = $('TYPE', photo).text(); bin = $('BINVAL', photo).text(); photo = type && bin ? { type: type, binval: bin.replace(/\n/g, '') } : null; vcard = { jid: jid, photo: photo, retrieved: new Date() }; return callback(card.size() > 0 ? vcard : null); }; iq = $iq({ type: 'get', to: jid, id: this.xmpp.getUniqueId() }).c('vCard', { xmlns: 'vcard-temp' }).up(); return this.xmpp.sendIQ(iq, handler, handler, 5000); }; Session.prototype.parseRoster = function(node) { return $('item', node).map(function() { return new Contact(this); }).get(); }; Session.prototype.findRoster = function(callback) { var handler, iq; handler = __bind(function(result) { var contact, contacts, _i, _len; contacts = this.parseRoster(result); for (_i = 0, _len = contacts.length; _i < _len; _i++) { contact = contacts[_i]; this.roster[contact.jid] = contact; } return callback(); }, this); iq = $iq({ type: 'get', id: this.xmpp.getUniqueId() }).c('query', { xmlns: 'jabber:iq:roster' }).up(); return this.xmpp.sendIQ(iq, handler, handler, 5000); }; Session.prototype.sendMessage = function(jid, message) { var stanza; stanza = $msg({ to: jid, from: this.xmpp.jid, type: 'chat' }).c('body').t(message).up(); return this.xmpp.send(stanza.tree()); }; Session.prototype.sendPresence = function(away, status) { var stanza; stanza = $pres(); if (away) { stanza.c('show').t('xa').up(); if (status !== 'Away') { stanza.c('status').t(status); } } else { if (status !== 'Available') { stanza.c('status').t(status); } } return this.xmpp.send(stanza.tree()); }; Session.prototype.updateContact = function(contact, add) { var group, iq, _i, _len, _ref; iq = $iq({ type: 'set', id: this.xmpp.getUniqueId() }).c('query', { xmlns: 'jabber:iq:roster' }).c('item', { jid: contact.jid, name: contact.name }); _ref = contact.groups; for (_i = 0, _len = _ref.length; _i < _len; _i++) { group = _ref[_i]; iq.c('group', group).up(); } this.xmpp.send(iq.up().tree()); if (add) { return this.xmpp.send($pres({ type: 'subscribe', to: contact.jid }).tree()); } }; Session.prototype.removeContact = function(jid) { var iq; iq = $iq({ type: 'set', id: this.xmpp.getUniqueId() }).c('query', { xmlns: 'jabber:iq:roster' }).c('item', { jid: jid, subscription: 'remove' }).up().up(); return this.xmpp.send(iq.tree()); }; Session.prototype.sendSubscribe = function(jid) { return this.xmpp.send($pres({ type: 'subscribe', to: jid, id: this.xmpp.getUniqueId() }).tree()); }; Session.prototype.sendSubscribed = function(jid) { return this.xmpp.send($pres({ type: 'subscribed', to: jid, id: this.xmpp.getUniqueId() }).tree()); }; Session.prototype.sendUnsubscribed = function(jid) { return this.xmpp.send($pres({ type: 'unsubscribed', to: jid, id: this.xmpp.getUniqueId() }).tree()); }; Session.prototype.handleIq = function(node) { var contact, contacts, ns, old, type, _i, _len; node = $(node); type = node.attr('type'); ns = node.find('query').attr('xmlns'); if (type === 'set' && ns === 'jabber:iq:roster') { contacts = this.parseRoster(node); for (_i = 0, _len = contacts.length; _i < _len; _i++) { contact = contacts[_i]; if (contact.subscription === 'remove') { delete this.roster[contact.jid]; } else { old = this.roster[contact.jid]; if (old) { contact.presence = old.presence; } this.roster[contact.jid] = contact; } } this.notify('roster'); } return true; }; Session.prototype.handleMessage = function(node) { var body, from, to, type; node = $(node); to = node.attr('to'); from = node.attr('from'); type = node.attr('type'); body = node.find('body').first(); if (type === 'chat' && body.size() > 0) { this.notify('message', { to: to, from: from, type: type, text: body.text(), received: new Date() }); } return true; }; Session.prototype.handlePresence = function(node) { var contact, from, presence, show, status, to, type; node = $(node); to = node.attr('to'); from = node.attr('from'); type = node.attr('type'); show = node.find('show').first(); status = node.find('status').first(); presence = { to: to, from: from, status: status.text(), show: show.text(), type: type, offline: type === 'unavailable' || type === 'error', away: show.text() === 'away' || show.text() === 'xa', dnd: show.text() === 'dnd' }; contact = this.roster[from.split('/')[0]]; if (contact) { contact.update(presence); } this.notify('presence', presence); return true; }; Session.prototype.notify = function(type, obj) { var callback, _i, _len, _ref, _results; _ref = this.listeners[type] || []; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { callback = _ref[_i]; _results.push(callback(obj)); } return _results; }; return Session; })();