Browse files

First version to pass the basic tests from pubnub-client foss vows.

  • Loading branch information...
1 parent ba0ea75 commit 63bc0a331a5299c6d22516ea8714bf5d2fe677a9 @arnaudsj committed Sep 29, 2010
Showing with 356 additions and 0 deletions.
  1. +5 −0 .gitignore
  2. +9 −0 .gitmodules
  3. +19 −0 LICENSE
  4. +28 −0 Makefile
  5. +51 −0 README.md
  6. +241 −0 app.js
  7. +1 −0 deps/node
  8. +1 −0 deps/npm
  9. +1 −0 deps/redis
View
5 .gitignore
@@ -0,0 +1,5 @@
+bin
+include
+share
+.node_libraries
+
View
9 .gitmodules
@@ -0,0 +1,9 @@
+[submodule "deps/node"]
+ path = deps/node
+ url = git://github.com/ry/node.git
+[submodule "deps/npm"]
+ path = deps/npm
+ url = git://github.com/isaacs/npm.git
+[submodule "deps/redis"]
+ path = deps/redis
+ url = git://github.com/antirez/redis.git
View
19 LICENSE
@@ -0,0 +1,19 @@
+© 2010 by Limey Frog LLC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
28 Makefile
@@ -0,0 +1,28 @@
+all: git nodejs redis npm npmmods
+
+clean:
+ rm -Rf ${PWD}/.node_libraries; rm -Rf ${PWD}/bin; rm -Rf ${PWD}/share; rm -Rf ${PWD}/include;
+
+tests:
+ bin/vows --spec
+
+git:
+ git submodule init; git submodule update
+
+nodejs:
+ cd deps/node; make clean; ./configure --prefix=${PWD}; make; make install;
+ rm -Rf ${PWD}/lib/node;
+
+redis:
+ cd deps/redis; make install PREFIX=${PWD}
+
+npm:
+ rm -Rf ${PWD}/.node_libraries;
+ cd deps/npm; export PATH=${PWD}/bin:$(PATH); make
+ bin/npm config set root ${PWD}/.node_libraries
+
+npmmods:
+ bin/npm install vows@latest;
+ bin/npm install express;
+ bin/npm install redis;
+
View
51 README.md
@@ -0,0 +1,51 @@
+# Pubnub server for Node.js
+
+## In a nutshell
+
+- Talk to PubNub API from Node.js
+
+## Synopsis
+
+When working from a git clone:
+
+ var sys = require("sys");
+ var client = require("../lib/redis-client").createClient();
+ client.info(function (err, info) {
+ if (err) throw new Error(err);
+ sys.puts("Redis Version is: " + info.redis_version);
+ client.close();
+ });
+
+- Refer to the many tests in `test/test.js` for many usage examples.
+- Refer to the `examples/` directory for focused examples.
+
+## Installation
+
+This version requires at least `Node.js v0.2.0`.
+
+Tested with Node.js `v0.2.0`.
+
+You have a number of choices:
+
+- git clone this repo or download a tarball and simply copy `lib/pubnub-client.js` into your project
+- use git submodule
+- use the [npm]() package manager for Node.js
+
+## Running the tests
+
+A good way to learn about this client is to read the test code.
+
+To run the tests, install and run redis on the localhost on port 6379 (defaults).
+Then run `node test/test.js [-v|-q]` where `-v` is for "verbose" and `-q` is for "quiet".
+
+ $ node test/test.js
+ ..................................................................
+ ...........................++++++++++++++++++++++++++++++++++++
+
+ [INFO] All tests have passed.
+
+## Documentation
+
+
+
+
View
241 app.js
@@ -0,0 +1,241 @@
+require.paths.unshift('./.node_libraries');
+
+var sys = require('sys'),
+ express = require('express'),
+ redis = require("redis");
+
+var redPublisher = redis.createClient();
+var redSubscribers = {};
+
+var app = express.createServer();
+
+
+app.configure(function(){
+ app.use(express.methodOverride());
+ app.use(express.bodyDecoder());
+ //app.use(express.cookieDecoder());
+ //app.use(express.session());
+ app.use(app.router);
+ //app.use(express.staticProvider(__dirname + '/public'));
+ app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
+ redPublisher.flushdb();
+});
+
+
+// TODO: purge when number of messages > 100 on any channel: ZREMRANGEBYSCORE
+
+
+
+
+
+
+
+
+app.get('/pubnub-time', function(req, res)
+{
+ pubnubResponse = {
+ status: 200,
+ time: (+new Date)
+ }
+
+ res.contentType('application/json');
+ res.send('window[""](' + JSON.stringify(pubnubResponse) + ')', 200);
+});
+
+app.get('/pubnub-uuid', function(req, res)
+{
+ var generate = function(l)
+ {
+ var result = "";
+ for (var i=0; i<l; i++)
+ {
+ var rand = Math.floor(Math.random(+new Date)*16);
+ result += String.fromCharCode(48 + (rand<10?rand:rand+39) );
+ }
+ return result;
+ }
+
+ var pubnubResponse = {
+ status: 200,
+ uuid: (generate(8)+'-'+generate(4)+'-'+generate(4)+'-'+generate(4)+'-'+generate(12))
+ }
+
+ res.contentType('application/json');
+ res.send('window[""](' + JSON.stringify(pubnubResponse) + ')', 200);
+});
+
+// TODO: "/pubnub-publish?channel=" + this.SUBSCRIBE_KEY +"/" + channel + "&message=" + JSON.stringify(message) +"&publish_key=" + this.PUBLISH_KEY + "&unique=" + unique;
+app.get('/pubnub-publish', function(req, res)
+{
+ var channel = req.param("channel");
+ var message = req.param("message");
+ var unique = req.param("unique");
+
+ // TODO: Check subscribe key & publish key
+
+
+ // We only need ONE redisClient in async to publish!
+ redPublisher.publish(channel, message);
+
+ var pubnubResponse = {
+ status: 200
+ };
+
+ res.contentType('application/json');
+ res.send('window["'+unique+'"](' + JSON.stringify(pubnubResponse) + ')', 200);
+});
+
+// TODO: "/pubnub-subscribe?channel=" + this.SUBSCRIBE_KEY +"/" + channel + "&unique=" + unique;
+app.get('/pubnub-subscribe', function(req, res)
+{
+ //console.log('/pubnub-subscribe');
+
+ var channel = req.param("channel");
+ var unique = req.param("unique");
+
+ if (typeof redSubscribers[channel] === 'undefined')
+ {
+ redSubscribers[channel] = redis.createClient();
+ }
+
+ redSubscribers[channel].on("subscribe", function(channel, count)
+ {
+ redSubscribers[channel].on("message", function (channel, message)
+ {
+ var timeToken = +new Date;
+ var messageString = JSON.stringify(
+ {
+ timeToken: timeToken,
+ message: message.toString()
+ }
+ );
+
+ redPublisher.zadd( channel, timeToken.toString(), messageString,
+ function(error, replies)
+ {
+ redPublisher.publish('#' + channel, messageString,
+ function ()
+ {
+ //console.log("broadcasting on #"+channel+" message: "+messageString);
+ }
+ );
+ }
+ );
+
+ });
+
+ res.contentType('application/json');
+ res.send('window["'+unique+'"](' + JSON.stringify({status: 200, server: "127.0.0.1:8080"}) + ')', 200);
+ });
+
+
+ redSubscribers[channel].subscribe(channel);
+});
+
+
+app.get('/', function(req, res)
+{
+ var channel = req.param("channel"),
+ timeToken = req.param("timetoken") || 0,
+ unique = req.param("unique"),
+ tempRedisClient = redis.createClient();
+
+ // Make sure we send a reply within 30 sec if nothing happens!
+ setTimeout( function()
+ {
+ tempRedisClient.unsubscribe();
+ var messageString = JSON.stringify({
+ messages : ['xdr.timeout'],
+ timetoken: +new Date
+ });
+ res.contentType('application/json');
+ res.send('window["'+unique+'"]('+messageString+')', 200);
+ },
+ 30000)
+
+ redPublisher.zrangebyscore(channel, timeToken+1, "+inf", function(error, replies)
+ {
+ if (replies !== null)
+ {
+ tempRedisClient.end();
+
+ var messages = JSON.parse('['+replies.toString()+']');
+ var maxTimeToken = 0;
+ var messageList = [];
+
+ for (var i=0; i<messages.length; i++)
+ {
+ if (messages[i].timeToken > maxTimeToken)
+ {
+ maxTimeToken = messages[i].timeToken;
+ }
+
+ messageList.push(JSON.parse(messages[i].message));
+ }
+
+ var messageString = JSON.stringify({
+ messages : messageList,
+ timetoken: maxTimeToken
+ });
+
+ res.contentType('application/json');
+ //console.log('window["'+unique+'"]('+messageString+')');
+ res.send('window["'+unique+'"]('+messageString+')', 200);
+ }
+ else
+ {
+ tempRedisClient.on("unsubscribe",
+ function (channel, count)
+ {
+ tempRedisClient.end();
+ }
+ );
+
+
+ tempRedisClient.on("subscribe",
+ function(channel, count)
+ {
+ tempRedisClient.on("message",
+ function(channel, replies)
+ {
+ tempRedisClient.unsubscribe();
+
+ var messages = JSON.parse('['+replies.toString()+']');
+ var maxTimeToken = 0;
+ var messageList = [];
+
+ for (var i=0; i<messages.length; i++)
+ {
+ if (messages[i].timeToken > maxTimeToken)
+ {
+ maxTimeToken = messages[i].timeToken;
+ }
+
+ messageList.push(JSON.parse(messages[i].message));
+ }
+
+ var messageString = JSON.stringify({
+ messages : messageList,
+ timetoken: maxTimeToken
+ });
+
+ res.contentType('application/json');
+ //console.log('window["'+unique+'"]('+messageString+')');
+ res.send('window["'+unique+'"]('+messageString+')', 200);
+
+ }
+ );
+ }
+ );
+
+ // Now we start listening!
+ tempRedisClient.subscribe('#'+channel);
+ }
+ });
+
+
+});
+
+app.listen(process.argv[2]);
+
+sys.log("nodejs app.js is now running on port " +process.argv[2]);
1 deps/node
@@ -0,0 +1 @@
+Subproject commit 353e2565d5867f457c03e5e011b5e13a2254b96f
1 deps/npm
@@ -0,0 +1 @@
+Subproject commit 16cbd139abc10d7eb6c8b73f6ddeb9705696a2e3
1 deps/redis
@@ -0,0 +1 @@
+Subproject commit 4610b0332c199563e58de005eb1b10ed54e1ec9c

0 comments on commit 63bc0a3

Please sign in to comment.