Permalink
Browse files

Allow the profile collection to handle avatar requests (WIP).

NOT working right now, needs some changes to how we deal with fakeweb /
how the collection is written to faciltate testing.
  • Loading branch information...
1 parent 7fa2031 commit 6cc5b15e9a7c86c68d8a9e6b017227c9b0066e79 @othiym23 othiym23 committed Feb 28, 2012
@@ -91,10 +91,10 @@ function needsToConnectMore(installedConnectors) {
}
app.all('*', function(req, res, next) {
- lutil.avatarUrlFromMap(process.cwd, locker.lockerBase, function (err, url) {
+ request.get({url:locker.lockerBase + "/Me/profiles/avatar"}, function (err, res, url) {
if (!err) profileImage = url;
});
- request.get({url:locker.lockerBase + "/synclets/github/getCurrent/profile"}, function(err, res, body) {
+ request.get({url:locker.lockerBase + "/synclets/github/getCurrent/profile"}, function (err, res, body) {
try {
body = JSON.parse(body);
if (body[0].login) {
@@ -11,6 +11,7 @@ var express = require('express')
, connect = require('connect')
, request = require('request')
, url = require('url')
+ , path = require('path')
, locker = require('locker')
, lutil = require('lutil')
, logger
@@ -19,7 +20,7 @@ var express = require('express')
var app = express.createServer(connect.bodyParser());
-function fetchmap(callback) {
+function fetchMap(callback) {
request.get(lockerInfo.lockerUrl + '/map', function (req, res) {
var map;
try {
@@ -32,8 +33,8 @@ function fetchmap(callback) {
});
}
-function fetchprofiles(callback) {
- fetchmap(function (map) {
+function fetchMappedByIDRs(callback) {
+ fetchMap(function (map) {
var profiles = {};
for (var key in map) {
@@ -56,27 +57,84 @@ function fetchprofiles(callback) {
});
}
+function fetchMappedByHandles(callback) {
+ fetchMap(function (map) {
+ var profiles = {};
+
+ for (var key in map) {
+ if (!map[key].auth || !map[key].auth.profile) continue;
+
+ if (profiles[key]) {
+ profiles[key].push(map[key].auth.profile);
+ } else {
+ profiles[key] = [map[key].auth.profile];
+ }
+ }
+ return callback(profiles);
+ });
+}
+
app.get('/', function (req, res) {
- fetchprofiles(function (profiles) {
+ fetchMappedByIDRs(function (profiles) {
return res.send(profiles);
});
});
app.get('/handle/:handle', function (req, res, next) {
- fetchprofiles(function (profiles) {
- var remapped = lutil.idrsToServices(profiles);
+ fetchMappedByHandles(function (profiles) {
var handle = req.param('handle');
- return res.send(remapped[handle]);
+ var profile = profiles[handle];
+ if (!profile) return res.send({}, 404);
+
+ return res.send(profile);
+ });
+});
+
+
+/*
+ * Avatars
+ */
+
+app.get('/avatar', function (req, res, next) {
+ // always override if a local avatar exists
+ if (path.existsSync(path.join(lockerInfo.workingDirectory, 'avatar.png'))) return res.send(lockerInfo.externalBase + '/avatar.png');
+
+ fetchMappedByHandles(function (profiles) {
+ if (profiles.twitter) return res.send(profiles.twitter[0].profile_image_url_https);
+ if (profiles.facebook) return res.send('http://graph.facebook.com/' + profiles.facebook[0].username + '/picture');
+ if (profiles.github) return res.send(profiles.github[0].avatar_url);
+ if (profiles.foursquare) return res.send(profiles.foursquare[0].photo);
+ if (profiles.instagram) return res.send(profiles.instagram[0].profile_picture);
+ if (profiles.lastfm) {
+ var lastImages = profiles.lastfm[0].image;
+ for (var i in lastImages) {
+ if (lastImages[i].size === 'small') return res.send(null, lastImages[i]['#text']);
+ }
+ }
+
+ return res.send('no avatar available', 404);
});
});
-// Process the startup JSON object
+app.get('/avatar.png', function (req, res) {
+ if (!path.existsSync(path.join(lockerInfo.workingDirectory, 'avatar.png'))) {
+ return res.send('not found', 404);
+ } else {
+ return res.sendfile(path.join(lockerInfo.workingDirectory, 'avatar.png'));
+ }
+});
+
+
+/*
+ * Startup
+ */
+
process.stdin.resume();
process.stdin.on('data', function (data) {
lockerInfo = JSON.parse(data);
locker.initClient(lockerInfo);
if (!lockerInfo || !lockerInfo.workingDirectory) {
- process.stderr.write('Was not passed valid startup information.'+data+'\n');
+ process.stderr.write('Was not passed valid startup information.' + data + '\n');
process.exit(1);
}
process.chdir(lockerInfo.workingDirectory);
@@ -86,12 +144,9 @@ process.stdin.on('data', function (data) {
logger = require('logger.js');
locker.connectToMongo(function (mongo) {
- //sync.init(lockerInfo.lockerUrl, mongo.collections.contact, mongo, lconfig);
app.listen(0, function () {
var returnedInfo = {port: app.address().port};
process.stdout.write(JSON.stringify(returnedInfo));
});
});
});
-
-
@@ -28,7 +28,7 @@ ModuleConsoleLogger.prototype.log = function(level, msg, meta, callback) {
}
this.doLog(level, msg, meta, callback);
-}
+};
// This is a copy of the normal file logger so that we can work around a winston bug that spews warnings on too many listeners
function FileBugLogger(options) {
@@ -61,7 +61,7 @@ if (lconfig.logging.file) {
} else {
realWrite.call(fileLogger.stream, data, "utf8");
}
- }
+ };
});
transports.push(fileLogger);
}
@@ -79,4 +79,4 @@ fullLogger.log = function(level, msg) {
__realLog.call(fullLogger, level, msg);
};
*/
-module.exports = fullLogger
+module.exports = fullLogger;
View
@@ -238,10 +238,10 @@ exports.streamFromUrl = function(url, cbEach, cbDone) {
*/
exports.fetchAndResizeImageURL = function (sourceUrl, rawFile, destFile, callback) {
request.get({uri: sourceUrl, encoding: 'binary'}, function (err, resp, body) {
- if (err) return callback("Unable to download avatar from source URL: " + err);
+ if (err) return callback('Unable to download avatar from source URL: ' + err);
fs.writeFile(rawFile, body, 'binary', function (err) {
- if (err) return callback("Unable to save downloaded raw avatar: " + err);
+ if (err) return callback('Unable to save downloaded raw avatar: ' + err);
im.resize({srcPath : rawFile
, dstPath : destFile
@@ -256,52 +256,6 @@ exports.fetchAndResizeImageURL = function (sourceUrl, rawFile, destFile, callbac
});
};
-exports.idrsToServices = function (dict) {
- var profileMap = {};
- for (var idr in dict) {
- var service = url.parse(idr).host;
- if (profileMap[service]) {
- profileMap[service].push(dict[idr]);
- }
- else {
- profileMap[service] = [dict[idr]];
- }
- }
- return profileMap;
-};
-
-exports.avatarUrlFromMap = function (storagePath, lockerBase, callback) {
- // always override if a local avatar exists
- if (path.existsSync(path.join(storagePath, 'avatar.png'))) return callback(null, 'avatar.png');
-
- request.get({url:lockerBase + '/Me/profiles/'}, function (err, res, body) {
- if (err) return callback(err);
-
- var profiles;
- try {
- profiles = JSON.parse(body);
- }
- catch (E) {
- return callback(E);
- }
-
- var profileMap = exports.idrsToServices(profiles);
- if (profileMap.twitter) return callback(null, profileMap.twitter[0].profile_image_url_https);
- if (profileMap.facebook) return callback(null, 'http://graph.facebook.com/' + profileMap.facebook[0].username + '/picture');
- if (profileMap.github) return callback(null, profileMap.github[0].avatar_url);
- if (profileMap.foursquare) return callback(null, profileMap.foursquare[0].photo);
- if (profileMap.instagram) return callback(null, profileMap.instagram[0].profile_picture);
- if (profileMap.lastfm) {
- var lastImages = profileMap.lastfm[0].image;
- for (var i in lastImages) {
- if (lastImages[i].size === 'small') return callback(null, lastImages[i]['#text']);
- }
- }
-
- return callback('no avatar available');
- });
-};
-
exports.parseAuthor = function(js) {
if (!js.author || typeof js.author !== 'string') return;
js.author = exports.strip(js.author);
@@ -0,0 +1,129 @@
+var should = require('should')
+ , path = require('path')
+ , fakeweb = require('node-fakeweb')
+ ;
+
+describe("profiles", function () {
+ describe("avatar", function () {
+ var url = 'https://me.lvh.me:8443/Me/profiles';
+
+ beforeEach(function (done) {
+ fakeweb.allowNetConnect = false;
+ fakeweb.registerUri({
+ uri : mapUrl,
+ file : path.join(__dirname, '..', 'fixtures', 'common', 'profiles.json')
+ });
+ return done();
+ });
+
+ it("should return avatar.png by default if available", function (done) {
+ lutil.avatarUrlFromMap(path.join(__dirname, '..', 'fixtures', 'common'), 'https://me.lvh.me:8443', function (err, url) {
+ should.not.exist(err);
+
+ url.should.equal('avatar.png');
+ return done();
+ });
+ });
+
+ describe("when avatar.png isn't available", function () {
+ it("should return the Twitter avatar first", function (done) {
+ lutil.avatarUrlFromMap('nonexistent', 'https://me.lvh.me:8443', function (err, url) {
+ should.not.exist(err);
+
+ url.should.equal('https://si0.twimg.com/profile_images/20377992/pony2_normal.png');
+ return done();
+ });
+ });
+
+ it("should fall back to Facebook when Twitter isn't available", function (done) {
+ var sampleMap = {
+ "contact://facebook/#1199931943" : {username : "othiym23"}
+ , "contact://foursquare/#13763756" : {photo : "https://img-s.foursquare.com/userpix_thumbs/1CLNJDDV10X5VXHV.png"}
+ , "contact://github/#othiym23" : {avatar_url : "https://secure.gravatar.com/avatar/76f12edae9553fa4dac4e985d8253b97?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png"}
+ , "contact://instagram/#11444169" : {profile_picture : "http://images.instagram.com/profiles/profile_11444169_75sq_1319161944.jpg"}
+ , "contact://lastfm/#othiym23" : {image : [{"#text" : "http://userserve-ak.last.fm/serve/34/1026294.jpg", size : "small"}]}
+ };
+ fakeweb.registerUri({
+ uri : mapUrl,
+ body : JSON.stringify(sampleMap)
+ });
+ lutil.avatarUrlFromMap('nonexistent', 'https://me.lvh.me:8443', function (err, url) {
+ should.not.exist(err);
+
+ url.should.equal('http://graph.facebook.com/othiym23/picture');
+ return done();
+ });
+ });
+
+ it("should fall back to Github when Facebook isn't available", function (done) {
+ var sampleMap = {
+ "contact://foursquare/#13763756" : {photo : "https://img-s.foursquare.com/userpix_thumbs/1CLNJDDV10X5VXHV.png"}
+ , "contact://github/#othiym23" : {avatar_url : "https://secure.gravatar.com/avatar/76f12edae9553fa4dac4e985d8253b97?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png"}
+ , "contact://instagram/#11444169" : {profile_picture : "http://images.instagram.com/profiles/profile_11444169_75sq_1319161944.jpg"}
+ , "contact://lastfm/#othiym23" : {image : [{"#text" : "http://userserve-ak.last.fm/serve/34/1026294.jpg", size : "small"}]}
+ };
+ fakeweb.registerUri({
+ uri : mapUrl,
+ body : JSON.stringify(sampleMap)
+ });
+ lutil.avatarUrlFromMap('nonexistent', 'https://me.lvh.me:8443', function (err, url) {
+ should.not.exist(err);
+
+ url.should.equal('https://secure.gravatar.com/avatar/76f12edae9553fa4dac4e985d8253b97?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png');
+ return done();
+ });
+ });
+
+ it("should fall back to Foursquare when Github isn't available", function (done) {
+ var sampleMap = {
+ "contact://foursquare/#13763756" : {photo : "https://img-s.foursquare.com/userpix_thumbs/1CLNJDDV10X5VXHV.png"}
+ , "contact://instagram/#11444169" : {profile_picture : "http://images.instagram.com/profiles/profile_11444169_75sq_1319161944.jpg"}
+ , "contact://lastfm/#othiym23" : {image : [{"#text" : "http://userserve-ak.last.fm/serve/34/1026294.jpg", size : "small"}]}
+ };
+ fakeweb.registerUri({
+ uri : mapUrl,
+ body : JSON.stringify(sampleMap)
+ });
+ lutil.avatarUrlFromMap('nonexistent', 'https://me.lvh.me:8443', function (err, url) {
+ should.not.exist(err);
+
+ url.should.equal('https://img-s.foursquare.com/userpix_thumbs/1CLNJDDV10X5VXHV.png');
+ return done();
+ });
+ });
+
+ it("should fall back to Instagram when Foursquare isn't available", function (done) {
+ var sampleMap = {
+ "contact://instagram/#11444169" : {profile_picture : "http://images.instagram.com/profiles/profile_11444169_75sq_1319161944.jpg"}
+ , "contact://lastfm/#othiym23" : {image : [{"#text" : "http://userserve-ak.last.fm/serve/34/1026294.jpg", size : "small"}]}
+ };
+ fakeweb.registerUri({
+ uri : mapUrl,
+ body : JSON.stringify(sampleMap)
+ });
+ lutil.avatarUrlFromMap('nonexistent', 'https://me.lvh.me:8443', function (err, url) {
+ should.not.exist(err);
+
+ url.should.equal('http://images.instagram.com/profiles/profile_11444169_75sq_1319161944.jpg');
+ return done();
+ });
+ });
+
+ it("should give last.fm a shot if all else fails (sure why not)", function (done) {
+ var sampleMap = {
+ "contact://lastfm/#othiym23" : {image : [{"#text" : "http://userserve-ak.last.fm/serve/34/1026294.jpg", size : "small"}]}
+ };
+ fakeweb.registerUri({
+ uri : mapUrl,
+ body : JSON.stringify(sampleMap)
+ });
+ lutil.avatarUrlFromMap('nonexistent', 'https://me.lvh.me:8443', function (err, url) {
+ should.not.exist(err);
+
+ url.should.equal('http://userserve-ak.last.fm/serve/34/1026294.jpg');
+ return done();
+ });
+ });
+ });
+ });
+});
Oops, something went wrong. Retry.

0 comments on commit 6cc5b15

Please sign in to comment.