Skip to content

Instantly share code, notes, and snippets.

@zliuva
Created December 24, 2010 06:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zliuva/753961 to your computer and use it in GitHub Desktop.
Save zliuva/753961 to your computer and use it in GitHub Desktop.
A node.js command line client for Fanfou.com
#!/usr/bin/env node
/**
* fanfou.js
* A node.js Fanfou client
* © 2010 softboysxp.com
*/
/**
* Copyright 2010 softboysxp.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var http = require('http');
var fs = require('fs');
var credentials = {
encodedCredentials: '',
encodeCredentials: function(username, password) {
this.encodedCredentials = 'Basic ' + (new Buffer(username + ':' + password)).toString('base64');
return this.encodedCredentials;
},
loadCredentials: function() {
try {
this.encodedCredentials = fs.readFileSync(process.env['HOME'] + '/.fanfou_auth', 'utf-8');
} catch (exception) {
return null;
}
return this.encodedCredentials;
},
saveCredentials: function(username, password) {
fs.writeFileSync(process.env['HOME'] + '/.fanfou_auth', this.encodeCredentials(username, password), 'utf-8');
}
}
var fanfouClient = {
FANFOU_API_PROTOCOL: 'http',
FANFOU_API_HOST: 'api.fanfou.com',
FANFOU_API_PUBLIC_TIMELINE: '/statuses/public_timeline.json',
FANFOU_API_USER_TIMELINE: '/statuses/user_timeline.json',
FANFOU_API_FRIENDS_TIMELINE: '/statuses/friends_timeline.json',
FANFOU_API_REPLIES: '/statuses/replies.json',
FANFOU_API_UPDATE: '/statuses/update.json',
client: null,
callAPI: function(method, api, params, callback) {
if (!this.client) {
this.client = http.createClient(80, this.FANFOU_API_HOST, this.FANFOU_API_PROTOCOL == 'https')
}
var request = this.client.request(method, api, {
'Host': this.FANFOU_API_HOST,
'Authorization': credentials.encodedCredentials,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': params ? params.length : 0
});
request.end(params, 'utf-8');
request.on('response', function(response) {
var body = '';
response.on('data', function(chunk) {
body += chunk;
});
response.on('end', function() {
if (response.statusCode != 200) {
var obj = eval('(' + body + ')');
if (obj && obj.error) {
console.log("ERROR: " + obj.error);
} else {
console.log("ERROR: " + body);
}
process.exit(-1);
}
if (body) {
callback(eval('(' + body + ')'));
}
});
});
},
getUserTimeline: function(callback) {
this.callAPI('GET', this.FANFOU_API_USER_TIMELINE, null, callback);
},
getFriendsTimeline: function(callback) {
this.callAPI('GET', this.FANFOU_API_FRIENDS_TIMELINE, null, callback);
},
getPublicTimeline: function(callback) {
this.callAPI('GET', this.FANFOU_API_PUBLIC_TIMELINE, null, callback);
},
getReplies: function(callback) {
this.callAPI('GET', this.FANFOU_API_REPLIES, null, callback);
},
postStatus: function(status, callback) {
this.callAPI('POST', this.FANFOU_API_UPDATE, 'status=' + encodeURIComponent(status), callback);
}
}
var fanfoujs = {
list: function() {
var displayStatus = function(statuses) {
statuses.forEach(function(status) {
console.log(status.user.screen_name + ': ' + status.text);
});
};
var type = process.argv[3] ? process.argv[3] : "friends";
switch(type) {
case 'friends':
fanfouClient.getFriendsTimeline(displayStatus);
break;
case 'public':
fanfouClient.getPublicTimeline(displayStatus);
break;
case 'self':
fanfouClient.getUserTimeline(displayStatus);
break;
case 'replies':
fanfouClient.getReplies(displayStatus);
break;
default:
this.usage();
}
},
post: function() {
if (process.argv.length != 4) {
this.usage();
}
var status = process.argv[3];
fanfouClient.postStatus(status, function(status) {
console.log(status.user.screen_name + ': ' + status.text);
});
},
usage: function() {
console.log('Usage: "fanfou.js setup <username> <password>"');
console.log('Usage: "fanfou.js list [friends(Default)/public/self/replies]"');
console.log('Usage: "fanfou.js post <status>"');
process.exit(0);
},
setup: function() {
if (process.argv.length != 5) {
this.usage();
}
credentials.saveCredentials(process.argv[3], process.argv[4]);
},
main: function() {
if (process.argv.length < 3) {
this.usage();
}
var command = process.argv[2];
switch (command) {
case 'setup':
this.setup();
break;
case 'list':
case 'post':
if (!credentials.loadCredentials()) {
console.log('Please run "node fanfou.js setup" first');
process.exit(-1);
}
eval('this.' + command + '();');
break;
default:
this.usage();
}
}
}
fanfoujs.main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment