$ npm install -g express
$ express xml2jsonp
$ cd xml2jsonp
$ npm install
$ npm install oauth socket.io --save
app.js
/**
* Module dependencies.
*/
var express = require('express');
var socketio = require('socket.io');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var Twitter = require('./libs/twitter');
var settings = require('./libs/oauth_settings');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
var io = socketio.listen(server);
var tw = new Twitter(settings);
tw.streaming('sample', function(stream){
stream.on('data',function(data){
console.log(data.text);
if(data.text){
io.sockets.emit('tweet', data.text);
}
});
});
routes/index.js
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Twitter Public Timeline' });
};
libs/twitter.js
var OAuth = require('oauth').OAuth
, querystring = require('querystring')
, events = require('events');
module.exports = Twitter;
function Twitter(oauthInfo) {
if (!oauthInfo) throw new Error('Oauth情報を指定してください');
this.options = {
consumer_key : oauthInfo.consumer_key,
consumer_secret : oauthInfo.consumer_secret,
access_token : oauthInfo.access_token,
access_token_secret: oauthInfo.access_token_secret,
headers: {
'Accept' : '*/*',
'User-Agent': 'node.js book sample'
},
request_token_url: 'https://api.twitter.com/oauth/request_token',
access_token_url : 'https://api.twitter.com/oauth/access_token',
authorize_url : 'https://api.twitter.com/oauth/authorize',
callback_url : oauthInfo.callback_url,
restapi_base_url: 'http://api.twitter.com/1/',
stream_base_url : 'https://stream.twitter.com/1/statuses/'
};
this.oauth = new OAuth(
this.options.request_token_url,
this.options.access_token_url,
this.options.consumer_key,
this.options.consumer_secret,
'1.0a',
this.options.callback_url,
'HMAC-SHA1',
null,
this.options.headers
);
}
Twitter.prototype.streaming = function(method, params, callback) {
if (typeof params === 'function') {
callback = params;
params = null;
}
var url = this.options.stream_base_url + method + '.json?' + querystring.stringify(params);
var stream = new events.EventEmitter();
var CRLF = '\r\n';
var CRLF_LENGTH = 2;
var request = this.oauth.get(
url,
this.options.access_token,
this.options.access_token_secret
);
request.on('response', function(response) {
response.setEncoding('utf8');
var buffer = '';
response.on('data', function(chunk) {
buffer += chunk;
var index, json;
while((index = buffer.indexOf(CRLF)) > -1) {
json = buffer.slice(0, index);
buffer = buffer.slice(index + CRLF_LENGTH);
if (json.length > 0) {
console.log(json);
try {
stream.emit('data', JSON.parse(json));
} catch (error) {
stream.emit('error', new Error('Parse Error: ' + error.message));
}
}
}
});
response.on('end', function() {
stream.emit('end');
});
});
request.end();
callback(stream);
return this;
}
libs/oauth_settings.js
module.exports = {
'consumer_key' : 'YOUR CONSUMER KEY',
'consumer_secret' : 'YOUR CONSUMER SECRET',
'access_token' : 'YOUR ACESS TOKEN',
'access_token_secret': 'YOUR ACCESS TOKEN SECRET'
}
views/layout.jade
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
script(src='http://code.jquery.com/jquery-1.11.0.min.js')
script(src='/socket.io/socket.io.js')
script
:js
var socket = io.connect();
socket.on('tweet', function(tweet){
if($('.tweet').size() > 20){
$('.tweet:last').remove();
}
$('#timeline').prepend('<p class="tweet">' + tweet + '</p>')
});
body
block content
views/index.jade
extends layout
block content
h1= title
p Welcome to #{title}
#timeline