Stay Classy, Facebook
FBgraph is a nodejs module that provides easy access to the facebook graph api
Oh nooooooesss - MOAR facebook
I created this, because I wanted to access FB's graph from node.
The libraries I found, felt clunky to me, and I needed an excuse to create a node module.
All calls will return json. Facebook sometimes decides to just return a string or true or redirects directly to the image.
I say nay-nay! Let's make it Disney, and keep things consistent!
Installation via npm
$ npm install fbgraph
var graph = require('fbgraph');
Authentication
If you get an accesstoken via some other Oauth module like everyauth ,
connect-auth or node-oauth you can just set
the access token directly. Most get calls, and pretty much all post calls will require an access_token
graph.setAccessToken(access_token);
This is how you would get authenticated using only the fbgraph module.
More details below on the express app section
// get authorization url
var authUrl = graph.getOauthUrl({
"client_id": conf.client_id
, "redirect_uri": conf.redirect_uri
});
// shows dialog
res.redirect(authUrl);
// after user click, auth `code` will be set
// we'll send that and get the access token
graph.authorize({
"client_id": conf.client_id
, "redirect_uri": conf.redirect_uri
, "client_secret": conf.client_secret
, "code": req.query.code
}, function (err, facebookRes) {
res.redirect('/loggedIn');
});
How requests are made
All calls are made using the request nodejs module
Why? something to do with wheels and re-invention.
Request options are directly mapped and can be set like so:
var options = {
timeout: 3000
, pool: { maxSockets: Infinity }
, headers: { connection: "keep-alive" }
};
graph
.setOptions(options)
.get("zuck", function(err, res) {
console.log(res); // { id: '4', name: 'Mark Zuckerberg'... }
});
Possible options can be found on the request github page
followRedirect cannot be overriden and has a default value of false
encoding will have utf-8 as default if nothing is set
Read data from the Graph Api
graph.get("zuck", function(err, res) {
console.log(res); // { id: '4', name: 'Mark Zuckerberg'... }
});
params in the url
graph.get("zuck?fields=picture", function(err, res) {
console.log(res); // { picture: 'http://profile.ak.fbcdn.net/'... }
});
params as an object
var params = { fields: picture };
graph.get("zuck", params, function(err, res) {
console.log(res); // { picture: "http://profile.ak.fbcdn.net/..." }
});
GraphApi calls that redirect directly to an image will return a json response with relevant fields
graph.get("/zuck/picture", function(err, res) {
console.log(res); // { image: true, location: "http://profile.ak.fb..." }
});
Search data from the Graph Api
Search for public posts that contain brogramming
var searchOptions = {
q: "brogramming"
, type: "post"
};
graph.search(searchOptions, function(err, res) {
console.log(res); // {data: [{id: xxx, from: ...}, {id: xxx, from: ...}]}
});
Publish data to the Graph Api
All publish requests will require an access token
only needs to be set once
graph.setAccessToken(accessToken);
Post a message on a friend's wall
var wallPost = {
message: "I'm gonna come at you like a spider monkey, chip!"
};
graph.post(userId + "/feed", wallPost, function(err, res) {
// returns the post id
console.log(res); // { id: xxxxx}
});
Delete a Graph object
To delete a graph object, provide an object id and the
response will return {data: true} or {data:false}
graph.del(postID, function(err, res) {
console.log(res); // {data:true}/{data:false}
});
Performing a FQL query
A single FQL query is done by sending a query as a string
var query = "SELECT name FROM user WHERE uid = me()";
graph.fql(query, function(err, res) {
console.log(res); // { data: [ { name: 'Ricky Bobby' } ] }
});
Performing a FQL Multi-Query
FQL Multi-Queries are done by sending in an object containing the separate queries
var query = {
name: "SELECT name FROM user WHERE uid = me()"
, permissions: "SELECT email, user_about_me, user_birthday FROM permissions WHERE uid = me()"
};
graph.fql(query, function(err, res) {
console.log(res);
// { data: [
// { name: 'name', fql_result_set: [{name: 'Ricky Bobby'}] },
// { name: 'permissions', fql_result_set: [{email: 1, user_about_me: 1...}] }
// ]}
});
Rockin' it on an Express App
This example assumes that you have a link on the main page / that points to /auth/facebook.
The user will click this link and get into the facebook authorization flow ( if the user hasn't already connected)
After authorizing the app the user will be redirected to /UserHasLoggedIn
/**
* Module dependencies.
*/
var express = require('express')
, graph = require('fbgraph')
, app = module.exports = express.createServer();
// this should really be in a config file!
var conf = {
client_id: 'YOUR FACEBOOK APP ID'
, client_secret: 'YOU FACEBOOK APP SECRET'
, scope: 'email, user_about_me, user_birthday, user_location, publish_stream'
, redirect_uri: 'http://localhost:3000/auth/facebook'
};
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', function(req, res){
res.render("index", { title: "click link to connect" });
});
app.get('/auth/facebook', function(req, res) {
// we don't have a code yet
// so we'll redirect to the oauth dialog
if (!req.query.code) {
var authUrl = graph.getOauthUrl({
"client_id": conf.client_id
, "redirect_uri": conf.redirect_uri
});
res.redirect(authUrl);
return;
}
// if the `user` hasn't denied the request
if (req.query.error) {
// auth `code` is set
// we'll send that and get the access token
graph.authorize({
"client_id": conf.client_id
, "redirect_uri": conf.redirect_uri
, "client_secret": conf.client_secret
, "code": req.query.code
}, function (err, facebookRes) {
res.redirect('/loggedIn');
});
} else {
// handle request denial here:
res.redirect('/');
}
});
// user gets sent here after being authorized
app.get('/UserHasLoggedIn', function(req, res) {
res.render("index", { title: "Logged In" });
});
var port = process.env.PORT || 3000;
app.listen(port, function() {
console.log("Express server listening on port %d", port);
});
Running tests
Before running the test suite, add your Facebook appId and appSecret to tests/config.js
This is needed to create test users and to get a test access_token
$ npm install
$ make test
Tests might fail if the Facebook api has an issue.