Skip to content

Instantly share code, notes, and snippets.

@19h
Last active August 29, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 19h/10321006 to your computer and use it in GitHub Desktop.
Save 19h/10321006 to your computer and use it in GitHub Desktop.
Facebook social network grapher using d3, hyperlevel and Legify Opengraph. Run npm i hyperlevel opengraph before using.
var level = require("hyperlevel");
og = require("opengraph"),
gHost = "local.sly.mn",
gMethod = "http",
FBconf = {
client_id: "---------",
client_secret: "--------------------------------",
scope: "email, user_about_me, user_birthday, user_location, publish_actions, offline_access",
redirect_uri: gMethod + "://" + gHost + "/auth/fb"
};
var qs = require("querystring"),
url = require("url"),
http = require("http"),
fs = require("fs");
var db = level("ids");
var queries = [
// replaced by /me/friends
//"SELECT first_name, last_name, pic_small, uid FROM user WHERE uid IN(SELECT uid1 FROM friend WHERE uid2=me() AND uid1 IN (SELECT uid2 FROM friend WHERE uid1=me()))"
];
var graphUI = Buffer([
'<!DOCTYPE html>',
'<html>',
' <head>',
' <meta charset="utf-8">',
' <style>',
' .link {',
' stroke: #ccc;',
' }',
' .node text {',
' pointer-events: none;',
' font: 10px sans-serif;',
' }',
' #graph {',
' width: 1500px;',
' height: 1000px;',
' }',
' </style>',
' </head>',
' <body>',
' <script src="http://d3js.org/d3.v3.min.js"></script>',
' <script>',
' d3.json(location.pathname + "/payload", function(error, graph) {',
' // Create a force layout to display nodes.',
' var force = d3.layout.force()',
' .charge(-120)',
' .linkDistance(40)',
' .nodes(graph.nodes)',
' .links(graph.edges)',
' .size([parseInt(d3.select(\'#graph\').style(\'width\'), 10),',
' parseInt(d3.select(\'#graph\').style(\'height\'), 10)]);',
' // Append an <svg> element to body for rendering (warning: SVG sucks and will',
' // probably hang Firefox, so use Chrome).',
' var svg = d3.select(\'body\')',
' .append(\'svg\')',
' .attr(\'width\', parseInt(d3.select(\'#graph\').style(\'width\'), 10))',
' .attr(\'height\', parseInt(d3.select(\'#graph\').style(\'height\'), 10));',
' // Add the edges to the SVG.',
' var edge = svg.selectAll(\'line.edge\')',
' .data(graph.edges)',
' .enter().append(\'line\')',
' .attr(\'class\', \'edge\')',
' .style(\'stroke\', \'rgba(200, 200, 200, 0.2)\')',
' .style(\'stroke-width\', 0.5);',
' // Add the nodes to the SVG.',
' var node = svg.selectAll(\'circle.node\')',
' .data(graph.nodes)',
' .enter().append(\'circle\')',
' .attr(\'class\', \'node\')',
' .attr(\'r\', 3)',
' .style(\'fill\', \'#333\')',
' .style(\'cursor\', \'pointer\')',
' .call(force.drag)',
' // Hook up some events to D3.js.',
' force.on(\'tick\', function() {',
' node.attr(\'cx\', function(d) { return d.x; })',
' .attr(\'cy\', function(d) { return d.y; });',
' edge.attr(\'x1\', function(d) { return d.source.x; })',
' .attr(\'y1\', function(d) { return d.source.y; })',
' .attr(\'x2\', function(d) { return d.target.x; })',
' .attr(\'y2\', function(d) { return d.target.y; });',
' });',
' // Start the visualization.',
' force.start();',
' });',
' </script>',
' <div id="graph" style="display: none"></div>',
' </body>',
'</html>'
].join("\n"));
http.createServer(function (request, response) {
if ( !request.url.indexOf("/graph/") ) {
var lquery = request.url.substr(7),
query = lquery.split("/")[0],
rquery = lquery.split("/")[1];
return db.get(query, function (err, data) {
if (err) return response.end("Not found")
if ( rquery === "payload" ) {
try {
data = JSON.parse(data);
data = data.payload;
} catch(e) {}
if ( typeof data === "object" )
data = JSON.stringify(data);
return response.writeHead(200, {
"Content-type": "text/javascript"
}), response.end(data);
}
return response.end(graphUI)
})
}
_handle = function(data) {
return og.authorize({
"client_id": FBconf.client_id,
"redirect_uri": FBconf.redirect_uri,
"client_secret": FBconf.client_secret,
"code": data.code
}, function(err, user) {
if (err) return _default(true);
var _ = og.setAccessToken(user.access_token)
_.get("/me", function (err, data) {
var id = data.id;
var set = {
friends: {},
payload: {
nodes: [],
edges: []
}
};
_.get("/me/friends", function(err, res) {
if (err) return response.end("Error in first query :(");
var friends = res.data.reduce(function(acc, x) {
acc[x.id] = x.name;
return acc;
}, {});
// Extract the list of friend IDs.
var fids = Object.keys(friends);
// Add some nodes to the graph.
set.payload.nodes = fids.map(function(fid) {
return {
id: fid,
name: friends[fid]
}
});
_.get('/fql?q=' + escape('SELECT uid1, uid2 ' +
'FROM friend ' +
'WHERE uid1 IN (SELECT uid2 FROM friend WHERE uid1=me()) AND ' +
' uid2 IN (SELECT uid2 FROM friend WHERE uid1=me())'), function(err, res) {
set.payload.edges = res.data.map(function(rel) {
return {
source: fids.indexOf(rel.uid1),
target: fids.indexOf(rel.uid2)
};
});
var ctx = Buffer(JSON.stringify(set));
return db.put(id, ctx, function (err, data) {
return response.writeHead(302, {
Location: "/graph/" + id
}), response.end();
});
});
});
})
});
}
var _default = function(err, data) {
var authUrl = og.getOauthUrl({
"client_id": FBconf.client_id,
"redirect_uri": FBconf.redirect_uri,
"scope": FBconf.scope
});
if (err || (data && data["error"])) {
response.writeHead(302, {
"Location": authUrl
}), response.end();
} else {
response.writeHead(302, {
"Location": gMethod + "://" + gHost + "/"
}), response.end();
}
return;
}
if (request.method === "POST") {
var r = "";
request.on('data', function(c) {
r.length > 4096 && response.end(response.writeHead(413));
r += c
});
request.on('end', function() {
var data = qs.parse(r);
if (!data.code)
return _default(false, data);
return _handle(data);
});
} else if (url.parse(request.url).search) {
var data = {}, query = url.parse(request.url).query;
// ref passing
query && ~query.indexOf("/") && (request.session._ref = query);
query.split("&").forEach(function(v) {
data[v.split("=")[0]] = v.split("=")[1]
});
return data.code ? _handle(data) : _default(false, data);
} else return _default(true);
}).listen(80);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment