support-chat/js/xmpp_muc.js

Fri, 16 Apr 2010 18:43:48 +0100

author
matthew@heavyhorse.vm.bytemark.co.uk
date
Fri, 16 Apr 2010 18:43:48 +0100
changeset 57
42f5669be677
parent 48
12b42931151a
permissions
-rw-r--r--

xmpp_muc.js: Support for callback on occupant leave

// Wraps a function so that its 'this' is always 'context' when called
var recontext = function (context, f) { return function () { return f.apply(context, arguments); }; };

// Returns a child element given a tag name and xmlns
function get_child(stanza, name, xmlns)
{
	var children = stanza.getElementsByTagName(name);
	for(var i=0;i<=children.length;i++)
	{
		if(children[i].getAttribute("xmlns") == xmlns || !xmlns)
			return children[i];
	}
	return null;
}



var MUC = function (conn, callbacks)
{
	/* Set our properties */
	this.conn = conn;
	this.callbacks = callbacks;

	this.occupants = {};

	/* Initialize stanza handlers */
	conn.addHandler(recontext(this, this.handle_join), null, "presence", null, null, null);
	conn.addHandler(recontext(this, this.handle_leave), null, "presence", "unavailable", null, null);
	conn.addHandler(recontext(this, this.handle_error), null, "presence", "error", null, null);
	conn.addHandler(recontext(this, this.handle_message), null, "message", "groupchat", null, null);

	/* Return newly-created object */
	return this;
}

MUC.prototype =
{
	/** General methods */

	join: function (jid, nick, status_text)
	{
		this.jid = jid;
		this.nick = nick;
		var pres = $pres({to: jid+'/'+nick});
		if(status)
			pres.c("status").t(status);
		return this.send_stanza(pres);
	},

	part: function (status_text)
	{
		var pres = $pres({to: this.jid+'/'+this.nick, type: "unavailable"});
		if(status)
			pres.c("status").t(status);
		return this.send_stanza(pres);
	},

	send_message: function (message)
	{
		return this.send_stanza($msg({to: this.jid, type: "groupchat"})
			.c("body").t(message||""));
	},

	send_private_message: function (nick, message)
	{
		return this.send_stanza($msg({to: this.jid+"/"+nick, type: "chat"})
			.c("body").t(message||""));
	},

	send_invite: function (jid, message)
	{
		return this.send_stanza($msg({to: jid})
			.c("x", { xmlns: "http://jabber.org/protocol/muc#user" })
			.c("invite", { to: jid })
			.c("reason").t(message||""));
	},

	send_stanza: function (stanza)
	{
		return this.conn.send(stanza.tree());
	},

	/** Incoming stanza handlers */

	handle_join: function (stanza)
	{
		var nick = Strophe.getResourceFromJid(stanza.getAttribute("from"));
		if(stanza.getAttribute("type") != "unavailable" && stanza.getAttribute("type") != "error"
		     && Strophe.getBareJidFromJid(stanza.getAttribute("from")) == this.jid)
			if(!this.occupants[nick])
			{
				var text = stanza.getElementsByTagName("status")[0];
				if(text) text = Strophe.getText(text);
				this.occupants[nick] = { nick: nick, status: text };
				var item = get_child(stanza, "x", "http://jabber.org/protocol/muc#user");
				if(item)
				{
					item = item.getElementsByTagName("item")[0];
					this.occupants[nick].affiliation = item.getAttribute("affiliation");
					this.occupants[nick].role = item.getAttribute("role");
				}
				if(this.callbacks.joined)
					this.callbacks.joined(stanza, this, this.occupants[nick]);
				if(this.status_handler)
				{
					this.status_handler(stanza);
				}
			}
		return true;
	},

	handle_leave: function (stanza)
	{
		var nick = Strophe.getResourceFromJid(stanza.getAttribute("from"));
		if(Strophe.getBareJidFromJid(stanza.getAttribute("from")) == this.jid)
			if(this.occupants[nick])
			{
				var text = stanza.getElementsByTagName("status")[0];
				if(text)
				{
					text = Strophe.getText(text);
					this.occupants[nick].status = text;
				}
				if(this.callbacks.left)
					this.callbacks.left(stanza, this, this.occupants[nick]);
				if(this.status_handler)
				{
					this.status_handler(stanza);
				}
				delete this.occupants[nick];
			}
		return true;
	},

	handle_error: function (stanza)
	{
		if(this.callbacks.error
			&& Strophe.getBareJidFromJid(stanza.getAttribute("from")) == this.jid)
		{
			var e = stanza.getElementsByTagName("error");
			if(e.length > 0)
			{
				var err = null;
				Strophe.forEachChild(e[0], null, function (child)
					{
						if(child.getAttribute("xmlns") == "urn:ietf:params:xml:ns:xmpp-stanzas")
							err = child.nodeName;
					});
				this.callbacks.error(stanza, this, err);
			}
		}
		return true;
	},
	
	handle_message: function (stanza)
	{
		if(!this.callbacks.message)
			return true;
		
		if(stanza.getAttribute("type") == "groupchat" && Strophe.getBareJidFromJid(stanza.getAttribute("from")) == this.jid)
		{
			var body = stanza.getElementsByTagName("body");
			if(body.length > 0 && stanza.getElementsByTagName("delay").length == 0)
				this.callbacks.message(stanza, this, Strophe.getResourceFromJid(stanza.getAttribute("from")), Strophe.getText(body[0]));
		}
		return true;
	}

};

mercurial