Skip to content

Instantly share code, notes, and snippets.

@tim-evans
Created December 22, 2011 16:45
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tim-evans/1510948 to your computer and use it in GitHub Desktop.
Save tim-evans/1510948 to your computer and use it in GitHub Desktop.
Cascade XMPP Data Source
XMPP = {};
// ...............................................
// Models
//
XMPP.BOSHConnection = SC.Record.extend({
primaryKey: 'jid',
jid: SC.Record.attr(String),
password: SC.Record.attr(String),
connectionStatus: SC.Record.attr(Number)
});
XMPP.ChatMessage = SC.Record.extend({
to: SC.Record.attr(String),
from: SC.Record.attr(String),
body: SC.Record.attr(String)
});
// ...............................................
// Data Sources
//
XMPP.BOSHConnectionDataSource = SC.DataSource.extend({
createRecord: function (store, storeKey) {
if (SC.guidFor(store.recordTypeFor(storeKey)) !== SC.guidFor(XMPP.BOSHConnection)) {
return NO;
}
var hash = store.readDataHash(storeKey),
self = this;
this.get('bosh').connect(hash.jid, hash.password, function () {
self.connectionStatusDidChange.apply(self, [store, storeKey].concat(SC.A(arguments)));
});
return YES;
},
destroyRecord: function (store, storeKey) {
if (SC.guidFor(store.recordTypeFor(storeKey)) !== SC.guidFor(XMPP.BOSHConnection)) {
return NO;
}
var hash = store.readDataHash(storeKey);
this.get('bosh').disconnect();
if (hash.connectionStatus === Strophe.Status.DISCONNECTED) {
store.dataSourceDidDestroy(storeKey);
}
return YES;
},
connectionStatusDidChange: function (store, storeKey, statusCode, errorCondition) {
var hash = SC.clone(store.readDataHash(storeKey)),
status = store.peekStatus(storeKey),
K = SC.Record,
S = Strophe.Status;
if (hash) {
hash.connectionStatus = statusCode;
}
if (status !== K.ERROR &&
(statusCode === S.CONNFAIL ||
statusCode === S.AUTHFAIL ||
statusCode === S.ERROR)) {
var e = SC.Error.create({
label: "Connection error",
code: errorCondition,
message: "Strophe has encountered a connection level error",
errorValue: connection
});
if (status & K.BUSY) {
store.dataSourceDidError(storeKey, e);
} else {
store.pushError(XMPP.BOSHConnection, null, e, storeKey);
}
} else if (status === K.BUSY_CREATING &&
statusCode === S.CONNECTED) {
store.dataSourceDidComplete(storeKey, hash);
} else if (statusCode === S.DISCONNECTED) {
if (status === K.BUSY_DESTROYING) {
store.dataSourceDidDestroy(storeKey);
} else {
if (status === K.BUSY_CREATING) {
store.writeStatus(storeKey, K.READY_CLEAN);
}
store.pushDestroy(XMPP.BOSHConnection, null, storeKey);
}
}
}
});
XMPP.ChatMessageDataSource = SC.DataSource.extend(SC.DataSourceDelegate, {
init: function () {
var self = this;
this.get('bosh').addHandler(function () {
self.didRecieveChat.apply(self, arguments);
}, null, 'message', 'chat', null, null, null);
},
createRecord: function (store, storeKey) {
if (SC.guidFor(store.recordTypeFor(storeKey)) !== SC.guidFor(XMPP.ChatMessage)) {
return NO;
}
var hash = store.readDataHash(storeKey);
this.get('bosh').send(
$msg({
to: hash.to,
from: this.get('bosh').jid,
type: 'chat'
}).c('body', hash.body)
.tree());
return YES;
},
didRecieveChat: function (stanza) {
var store = this.get('store'),
body = stanza.getElementsByTagName('body');
store.pushRetrieve(XMPP.ChatMessage, {
guid: SC.guidFor(stanza),
to: stanza.getAttribute('to'),
from: stanza.getAttribute('from'),
body: body && body.length && Strophe.getText(body[0])
});
}
});
// ...............................................
// Use it!
XMPP.store = SC.Store.create();
XMPP.bosh = new Strophe.Connection('/http-bind/');
XMPP.dataSource = SC.CascadeDataSource.create({
dataSources: 'chats bosh'.w(),
chats: XMPP.ChatMessageDataSource.create({ store: XMPP.store, bosh: bosh }),
bosh: XMPP.BOSHDataSource.create({ store: XMPP.store, bosh: bosh })
});
XMPP.store.set('dataSource', XMPP.dataSource);
// replace with your own JID & password
var bosh = XMPP.store.createRecord(XMPP.BOSHConnection, {
jid: 'swedish.chef@muppe.tz',
password: 'bork!'
}).commitRecord();
bosh.addObserver('status', function () {
if (bosh.get('status') === SC.Record.READY_CLEAN) {
// replace with another JID (ie. a gmail account!)
XMPP.store.createRecord(XMPP.ChatMessage, {
to: 'camilla@muppe.tz',
body: 'Bork bork bork!'
}).commitRecord();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment