Created
July 23, 2009 22:22
-
-
Save juranki/153684 to your computer and use it in GitHub Desktop.
Ubiquity UI to RabbitMQ chat demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($) { | |
var factoryServiceDefaults = { | |
factoryServiceUrl: "/rpc/rabbitmq", | |
timeout: 30000 | |
}; | |
var channelDefaults = { | |
rpcServiceUrlBase: "/rpc/", | |
username: "guest", | |
password: "guest", | |
virtualHost: null, | |
realm: "/data", | |
channelTimeout: 10 /* seconds; zero means "do not specify" */ | |
}; | |
var accessRequestDefaults = { | |
realm:"/data", | |
exclusive:false, | |
passive:true, | |
active:true, | |
write:true, | |
read:true | |
}; | |
var exchangeDefaults = { | |
type:"direct", | |
passive:false, | |
durable:false, | |
auto_delete:false, | |
internal:false, | |
nowait:false, | |
args:{} | |
}; | |
var queueDefaults = { | |
passive:false, | |
durable:false, | |
exclusive:false, | |
auto_delete:false, | |
nowait:false, | |
args:{} | |
}; | |
var consumerDefaults = { | |
consumer_tag: "", | |
no_local: false, | |
no_ack: false, | |
exclusive: false | |
}; | |
var rpcDefaults = { | |
timeout:0, | |
type: "POST", | |
contentType: "application/json", | |
processData: false, | |
dataType: "json", | |
error: function (xhr,status,error) { | |
try { | |
CmdUtils.log({rpc_error:error, | |
status:status, | |
xhr:xhr}); | |
console.log({rpc_error:error, | |
status:status, | |
xhr:xhr}); } | |
catch (err) {} | |
} | |
}; | |
var rpcId = 1; | |
var rpc = function(url, method, params, options) { | |
var req = {version: "1.1", id: rpcId++, method: method, params: params}; | |
// var ajaxOpts = $.extend({url: url,data: JSON.stringify(req)}, | |
var ajaxOpts = $.extend({url: url,data: Utils.encodeJson(req)}, | |
rpcDefaults,options); | |
ajaxOpts["beforeSend"] = function(xhr){ | |
xhr.setRequestHeader("Accept","application/json"); | |
if(ajaxOpts.timeout) { | |
xhr.setRequestHeader("X-JSON-RPC-Timeout","" + ajaxOpts.timeout); | |
} | |
}; | |
return $.ajax(ajaxOpts); | |
}; | |
var args2list = function(args) { | |
var l = []; | |
var i; | |
for(i = 0; i < args.length; i++) { | |
l.push(args[i]); | |
} | |
return l; | |
}; | |
var rpcService = function(url,readyCB,options) { | |
return rpc(url,"system.describe",[],{ | |
success: function(sd) { | |
var res = sd.result; | |
var svc = {}; | |
$.each(res.procs, function(i,desc) { | |
svc[desc.name] = function() { | |
var args = args2list(arguments); | |
var userCB = args.shift(); | |
var cb = function(reply) { | |
if (reply.error) { | |
try {console.log(reply.error);} catch(err){} | |
} else { | |
userCB(reply.result); | |
} | |
}; | |
var opts = $.extend({},options,{success:cb}); | |
while(args.length < desc.params.length) { | |
args.push(null); | |
} | |
//CmdUtils.log("rpc: " + desc.name); | |
return rpc(url,desc.name,args,opts); | |
}; | |
}); | |
readyCB(svc); | |
} | |
}); | |
}; | |
$.openRabbitChannel = function(fnReady,options) { | |
var opts = $.extend({}, factoryServiceDefaults, options||{}); | |
rpcService(opts.factoryServiceUrl, | |
function(factorySvc) { | |
new RabbitChannel(factorySvc,fnReady,opts); | |
}, | |
opts); | |
}; | |
var RabbitChannel = function(factorySvc,fnReady,opts) { | |
this.options = $.extend({},channelDefaults,opts); | |
this.consumers = {}; | |
this.alive = true; | |
this.ticket = null; | |
this.svc = null; | |
this.async_handlers = { | |
"basic.deliver": function(args, content, props) { | |
var consumer = this.consumers[args[0]]; | |
if (consumer) { | |
try { | |
consumer({ | |
content: content, | |
delivery_tag: args[1], | |
redelivered: args[2], | |
exchange: args[3], | |
routing_key: args[4], | |
props: this._js_props(props)}); | |
} catch (err) {} | |
} | |
} | |
}; | |
var that = this; | |
factorySvc.open(chanCreatedCB, | |
this.options.username, | |
this.options.password, | |
this.options.channelTimeout, | |
this.options.virtualHost); | |
function chanCreatedCB(result) { | |
rpcService(that.options.rpcServiceUrlBase + result.service, | |
readyCB, {timeout: that.options.channelTimeout * 1000}); | |
} | |
function readyCB(svc) { | |
that.svc = svc; | |
that.poll_tophalf(); | |
that.accessRequest(fnReady,{realm:that.options.realm}); | |
}; | |
}; | |
RabbitChannel.prototype.accessRequest = function(cb,opts) { | |
var that = this; | |
var o = $.extend({},accessRequestDefaults,opts||{}); | |
this._call(function(result) { | |
that.ticket = result.args[0]; | |
cb(that); | |
}, | |
"access.request", | |
[o.realm,o.exclusive,o.passive,o.active,o.write,o.read]); | |
}; | |
RabbitChannel.prototype.exchangeDeclare = function(cb,name,opts) { | |
var that = this; | |
var o = $.extend({},exchangeDefaults,opts||{}); | |
this._call(cb,"exchange.declare",[this.ticket, | |
name, | |
o.type, | |
o.passive, | |
o.durable, | |
o.auto_delete, | |
o.internal, | |
o.nowait, | |
o.args]) | |
}; | |
RabbitChannel.prototype.queueDeclare = function(cb,name,opts) { | |
var that = this; | |
var o = $.extend({},queueDefaults,opts||{}); | |
var cbwrap = function(result) {cb(result.args[0]);}; | |
this._call(cbwrap,"queue.declare",[this.ticket, | |
name||"", | |
o.passive, | |
o.durable, | |
o.exclusive, | |
o.auto_delete, | |
o.nowait, | |
o.args]); | |
}; | |
RabbitChannel.prototype.queueDelete = function(cb,name,if_unused,if_empty) { | |
var that = this; | |
var cbwrap = function(result) {cb(result.args[0]);}; | |
this._call(cbwrap,"queue.delete",[this.ticket, | |
name||"", | |
if_unused||false, | |
if_empty||false, | |
false //nowait | |
]); | |
}; | |
RabbitChannel.prototype.queueBind = function(cb,q,e,routing_key,args) { | |
var that = this; | |
this._call(cb,"queue.bind", [this.ticket, | |
q, | |
e, | |
routing_key||"", | |
false,//nowait | |
args||{}]); | |
}; | |
RabbitChannel.prototype.basicConsume = function(cb,q,consumeCB,options) { | |
var that = this; | |
var o = $.extend({},consumerDefaults,options||{}); | |
var cbwrap = function(result) { | |
var tag = result.args[0]; | |
that.consumers[tag] = consumeCB; | |
cb(tag); | |
}; | |
this._call(cbwrap, "basic.consume", [this.ticket, | |
q, | |
o.consumer_tag, | |
o.no_local, | |
o.no_ack, | |
o.exclusive, | |
false // nowait | |
]); | |
}; | |
RabbitChannel.prototype.basicPublish = function(x, routing_key, message, | |
props, mandatory, immediate) { | |
this._cast("basic.publish", [this.ticket, | |
x, | |
routing_key, | |
mandatory||false, | |
immediate||false], | |
message, this._amqp_props(props || {})); | |
}; | |
RabbitChannel.prototype.basicAck = function(delivery_tag, multiple) { | |
this._cast("basic.ack", [delivery_tag, multiple||false]); | |
}; | |
RabbitChannel.prototype.basicCancel = function(cb,consumer_tag) { | |
var that = this; | |
var cbwrap = function(result) { | |
var tag = result.args[0]; | |
delete that.consumers[tag]; | |
cb(tag); | |
}; | |
this._call(cbwrap, "basic.cancel", [consumer_tag, false /*nowait*/]); | |
}; | |
RabbitChannel.prototype.poll_tophalf = function() { | |
var that = this; | |
if (this.alive) { | |
this.svc.poll(function(result) { | |
that.handlePollResult(result); | |
that.poll_tophalf(); | |
}); | |
} | |
}; | |
RabbitChannel.prototype.close = function() { | |
var that = this; | |
if (this.alive) { | |
this.alive = false; | |
this.svc.close(function(result) { | |
that.handlePollResult(result); | |
}); | |
} | |
}; | |
RabbitChannel.prototype.handlePollResult = function(result) { | |
var that = this; | |
if (result === "stop") { | |
this.alive = false; | |
} else { | |
$.each(result,function(i,msg) { | |
that.handleAsyncMessage(msg); | |
}); | |
} | |
}; | |
RabbitChannel.prototype.handleAsyncMessage = function(msg) { | |
var handler = this.async_handlers[msg.method]; | |
if(handler) { | |
handler.apply(this,[msg.args,msg.content,msg.props]); | |
} else { | |
try {console.log({async: msg});} catch(err) {} | |
} | |
}; | |
RabbitChannel.prototype._call = function(cb,method,args) { | |
if (this.alive) { | |
this.svc.call(cb,method,args); | |
} | |
}; | |
RabbitChannel.prototype._cast = function(method,args,content,props) { | |
var that = this; | |
if (this.alive) { | |
this.svc.cast(function(r) {that.handlePollResult(r);}, | |
method,args,content,props); | |
} | |
}; | |
RabbitChannel.prototype._js_props = function(props) { | |
return { content_type: props[0], | |
content_encoding: props[1], | |
headers: props[2], | |
delivery_mode: props[3], | |
priority: props[4], | |
correlation_id: props[5], | |
reply_to: props[6], | |
expiration: props[7], | |
message_id: props[8], | |
timestamp: props[9], | |
type: props[10], | |
user_id: props[11], | |
app_id: props[12], | |
cluster_id: props[13] }; | |
}; | |
RabbitChannel.prototype._amqp_props = function(props) { | |
return [props.content_type, | |
props.content_encoding, | |
props.headers, | |
props.delivery_mode, | |
props.priority, | |
props.correlation_id, | |
props.reply_to, | |
props.expiration, | |
props.message_id, | |
props.timestamp, | |
props.type, | |
props.user_id, | |
props.app_id, | |
props.cluster_id]; | |
}; | |
})(jQuery); | |
(function() { | |
var icon_url = "http://www.downloadatoz.com/_imgbank/ra/rabbitmq/RabbitMQ.icon.gif"; | |
var channel = null; | |
var qName = null; | |
var xName = null; | |
var messages = []; | |
var nic = "user" + Math.floor(Math.random() * 1e10); | |
var prepareArgs = function(args) { | |
var txt = (args.object ? args.object.text : ''); | |
var nick = (args.alias ? args.alias.text : null); | |
var goal = (args.goal ? args.goal.text : null); | |
if (!nick) {nick = nic;} | |
return {txt:txt,nick:nick,goal:goal}; | |
}; | |
var update = function(elem,args) { | |
$(elem).html(""); | |
$(elem).append("<h3>RabbitMQ Chat</h3>"); | |
if(!channel) { | |
$(elem).append("Not connected. <b>chat-toggle</b> to connect"); | |
} else { | |
$(elem).append("<p>You're in <b>" + xName + "</b> as <b>" + nic + "</b></p>"); | |
$.each(messages, function(i,m) { | |
var d = $("<div></div>"); | |
d.append("<span style='margin-right:0.5em;font-weight:bold'>" + m.nic + | |
"</span><span>" + m.msg + "</span>"); | |
$(elem).append(d); | |
}); | |
if(args) { | |
var {txt,nick,goal} = prepareArgs(args); | |
if(txt) { | |
var d = $("<div style='border:1px groove #555;padding:2px;background:#888;color:black;text-shadow:0 0.1em 0.05em #aaa'></div>"); | |
d.append("<span style='margin-right:0.5em;font-weight:bold'>" + nick + | |
"</span><span>" + txt + "</span>"); | |
if(goal) { | |
d.append("<span style='margin-left:0.5em;font-weight:bold;font-size:90%'>(to " + goal + ")</span>"); | |
} | |
$(elem).append(d); | |
} | |
} | |
} | |
}; | |
var disconnect = function() { | |
if(channel) { | |
channel.close(); | |
channel = null; | |
displayMessage("Disconnected"); | |
} | |
}; | |
var changeChannel = function(newXName, cb) { | |
if(!channel) { return; } | |
var onQBound = function() { | |
$("#chatoutput").html(); | |
displayMessage("In room '" + xName + "'"); | |
channel.basicConsume(function() {}, | |
qName, | |
function(delivery) { | |
messages.push({nic:delivery.routing_key, | |
msg:delivery.content}); | |
if (messages.length > 8) { | |
messages.shift(); | |
} | |
displayMessage(delivery.routing_key + ": " + | |
delivery.content); | |
}, | |
{ no_ack: true }); | |
if(cb) {cb();} | |
}; | |
var declareFreshQ = function() { | |
channel.queueDeclare(function(name) { | |
displayMessage("Q declared"); | |
qName = name; | |
channel.queueBind(onQBound,qName,xName); | |
}); | |
}; | |
var onXDeclared = function() { | |
displayMessage("X declared"); | |
if(qName) { | |
channel.queueDelete(declareFreshQ,qName); | |
} else { | |
declareFreshQ(); | |
} | |
}; | |
xName = newXName; | |
if (channel.exchangeDeclare) { | |
//CmdUtils.log("declaring"); | |
displayMessage("declaring " + xName); | |
channel.exchangeDeclare(onXDeclared,xName,{type:"fanout"}); | |
} | |
}; | |
var send = function(text) { | |
if (!channel) {return;} | |
channel.basicPublish(xName, nic, text, { content_type: "text/plain" }); | |
}; | |
var connect = function() { | |
displayMessage("Connecting..."); | |
$.openRabbitChannel(function(chan) { | |
channel = chan; | |
displayMessage("Joining room 'rabbit'..."); | |
Utils.setTimeout(function() {changeChannel("rabbit");},100); | |
}, | |
{ | |
factoryServiceUrl: "http://chat.juranki.com/rpc/rabbitmq", | |
rpcServiceUrlBase: "http://chat.juranki.com/rpc/", | |
virtualHost: "/chat" | |
}); | |
}; | |
var reopen = function(ubi) { | |
Utils.setTimeout(function() { | |
var t = ubi.textBox; | |
ubi.openWindow(); | |
$(t).val("chat-send "); | |
Utils.setTimeout(function() {t.setSelectionRange(10,10);},100); | |
},100); | |
}; | |
var toggle_cmd = { | |
names:["chat-toggle", "chat-on/off"], | |
icon: icon_url, | |
description: "Toggle chat on and off", | |
preview: update, | |
execute: function execute() { | |
if(channel) { | |
disconnect(); | |
} else { | |
connect(); | |
} | |
} | |
}; | |
var send_cmd = { | |
names:["chat-send"], | |
icon: icon_url, | |
description: "Send chat message", | |
arguments: [{role: 'object', nountype: noun_arb_text, label:'text'}, | |
{role: 'alias', nountype: noun_arb_text, label:'nick'}, | |
{role: 'goal', nountype: noun_arb_text, label:'room'}], | |
preview: update, | |
execute: function execute(args) { | |
var {txt,nick,goal} = prepareArgs(args); | |
var {gUbiquity} = context.chromeWindow; | |
if (nick) { nic = nick; } | |
if (goal) { | |
changeChannel(goal, function() {send(txt);}); | |
} else { | |
send(txt); | |
} | |
reopen(gUbiquity); | |
} | |
}; | |
CmdUtils.CreateCommand(toggle_cmd); | |
// CmdUtils.CreateCommand(disconnect_cmd); | |
//CmdUtils.CreateCommand(room_cmd); | |
CmdUtils.CreateCommand(send_cmd); | |
// CmdUtils.CreateCommand(nick_cmd); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment