diff --git a/mongo.js b/mongo.js new file mode 100644 index 0000000..e9da099 --- /dev/null +++ b/mongo.js @@ -0,0 +1,53 @@ +var util = require('util') + , EventEmitter = require('events').EventEmitter + , mongodb = require('mongodb') + , Db = mongodb.Db + , Connection = mongodb.Connection + , Server = mongodb.Server + , BSON = mongodb.BSONNative; + +function Mongo(options) { + var self = this + , env = options.env || process.env.NODE_ENV || 'development' + , name = options.name + , host = options.host || 'localhost' + , port = options.port || Connection.DEFAULT_PORT + , collections = options.collections + , server = new Server(host, port, {}) + , db = new Db(name + '_' + env, server, { native_parser: true }) + , objs = { + server: server, + connection: db, + lib: mongodb, + BSON: BSON } + , ready = false; + + EventEmitter.call(this); + + db.open(function(err, db) { + if (err) self.emit('error', err); + var threads = collections.length; + + // load collections + collections.forEach(function(name) { + db.collection(name, function(err, collection) { + if (err) self.emit('error', err); + + objs[name] = collection; + console.log('loaded collection ' + name); + + if (--threads === 0) { + ready = true; + self.emit('ready', objs); + } + }); + }); + }); + + self.on('newListener', function(evt, listener) { + if ((evt === 'ready') && ready) listener(objs); + }); +}; +util.inherits(Mongo, EventEmitter); + +module.exports = function(options) { return new Mongo(options); }; diff --git a/package.json b/package.json new file mode 100644 index 0000000..844b798 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "common-tweet", + "description": "Extract common themes from tweets", + "author": "Fortnight Labs, LLC", + "version": "0.0.1", + "licenses": [{ + "type": "MIT", + "url": "http://opensource.org/licenses/mit-license.php" + }], + "engines": { + "node": ">=0.4.2" + }, + "dependencies": { + "express": ">=2.0.0beta", + "jade": ">=0.8.5", + "stylus": ">=0.7.3", + "twitter-js": ">=0.0.5", + "pos": ">=0", + "snowball": ">=0", + "mongodb": ">=0.9.1" + }, + "main": "./server.js" +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..1847480 --- /dev/null +++ b/server.js @@ -0,0 +1,61 @@ +var express = require('express') + , twitter = require('twitter-js')( + '5MvHhIgH1arjKA5HdZecw', + 'z8KAFzE1QM9EVXz5AkjMtvJgb2mMelhhP3nJRQ1ws', + 'http://localhost:8000/auth') + , mongo = require('./mongo')({ + name: 'commontweet', + collections: ['users', 'statuses'] }) + , app = express.createServer( + express.logger(), + express.bodyParser(), + express.cookieParser(), + express.session({ secret: "rm5NxTVdmcpHquM9b9e4eZY3kD5uSaY" }), + express.methodOverride(), + express.errorHandler({ dumpExceptions: true, showStack: true })) + , noop = function() {}; + +mongo.on('ready', function(db) { + + app.get('/', function(req, res) { + if (!req.session.twitter_id) return res.redirect('/auth'); + + db.users.findOne({ twitter_id: req.session.twitter_id }, function(error, user) { + if (error) throw error; + + twitter.apiCall('GET', '/statuses/friends_timeline.json', { token: user.token, count: 200, include_rts: 1 }, function(error, statuses) { + if (error) throw error; + + res.render('index.jade', { locals: { user: user, statuses: statuses }}); + }); + }); + }); + + app.get('/auth', function(req, res) { + twitter.getAccessToken(req, res, function(error, token) { + if (error) throw error; + + twitter.apiCall('GET', '/account/verify_credentials.json', { token: token }, function(error, user) { + if (error) throw error; + + var id = user.id; + delete user.id; + user.twitter_id = id; + + user.token = token; + + db.users.update({ twitter_id: id }, user, { upsert: true }, function(error, record) { + if (error) throw error; + + req.session.twitter_id = id; + res.redirect('/'); + }); + }); + }); + }); + + app.listen(parseInt(process.env.PORT) || 8000); + + db.users.ensureIndex('twitter_id', true, noop); + db.statuses.ensureIndex('twitter_id', true, noop); +}); diff --git a/views/index.jade b/views/index.jade new file mode 100644 index 0000000..7faa571 --- /dev/null +++ b/views/index.jade @@ -0,0 +1,3 @@ +h1= user.name +- each status in statuses + p= status.text diff --git a/views/layout.jade b/views/layout.jade new file mode 100644 index 0000000..6941aeb --- /dev/null +++ b/views/layout.jade @@ -0,0 +1,5 @@ +!!! 5 +html(lang="en") + head + title Common Tweet + body!= body