changeset 19:9ff8f951da99

Add Gravatar fallback.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sat, 16 Jul 2011 12:47:44 +0200
parents 92d6e1b40df5
children e4916f1763e5
files avatar.js configuration.js.example
diffstat 2 files changed, 49 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/avatar.js
+++ b/avatar.js
@@ -26,6 +26,9 @@ var util = require('util');
 var fs = require('fs');
 var http = require('http');
 
+if (config.useGravatar)
+	var hash = require('crypto').createHash;
+
 var xmpp = require('node-xmpp');
 var conn = new xmpp.Client(config);
 var Element = require('ltx').Element;
@@ -70,7 +73,7 @@ var jids = {};
 var sent = {};
 
 var svgError = function(res, message) {
-	res.writeHead(500, {'Content-Type': 'image/svg+xml'});
+	res.writeHead(200, {'Content-Type': 'image/svg+xml'});
 	res.write('<?xml version="1.0" encoding="UTF-8"?>\n');
 	res.write('<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 -36 64 64">\n');
 	res.write('\t<title>'+message+'</title>\n');
@@ -88,6 +91,40 @@ var makeError = function(response) {
 	return response;
 }
 
+if (config.useGravatar)
+	var noAvatar = function(res, from, message) {
+		var options = {
+			host: 'gravatar.com',
+			port: 80,
+			path: '/avatar/' + hash('md5').update(from).digest('hex') + '?d=404',
+			method: 'GET'
+		};
+
+		var r = http.request(options, function(r) {
+			if (r.statusCode != 200)
+				return svgError(res, message + ' Additionaly, no gravatar available.');
+
+			res.writeHead(200, r.headers['Content-Type']);
+			r.setEncoding('utf8');
+			r.on('data', function(chunk) {
+				res.write(chunk);
+			});
+			r.on('end', function() {
+				res.end();
+			});
+		});
+
+		r.on('error', function(e) {
+			return svgError(res, message + ' Additionaly, problem with gravatar request: ' + e.message);
+		});
+
+		return r.end();
+	};
+else
+	var noAvatar = function(res, _, message) {
+		return svgError(res, message);
+	};
+
 function onIq(stanza) {
 	var type = stanza.getAttribute('type');
 	var from = stanza.getAttribute('to');
@@ -110,12 +147,13 @@ function onIq(stanza) {
 		} catch (e) {
 			var err = 'none';
 		}
-		return svgError(res, 'Error during query of this user’s vCard: “'+err+'”.');
+
+		return noAvatar(res, from, 'Error during query of this user’s vCard: “'+err+'”.');
 	}
 
 	var vCard = stanza.getChild('vCard', 'vcard-temp');
 	if (!vCard)
-		return svgError(res, 'Error: this user doesn’t have a vCard.');
+		return noAvatar(res, from, 'Error: this user doesn’t have a vCard.');
 
 	try {
 		var photo = vCard.getChild('PHOTO', 'vcard-temp');
@@ -127,7 +165,7 @@ function onIq(stanza) {
 			if (config.guessType)
 				type = 'image/png'; // FIXME: use magic.
 			else
-				return svgError(res, 'Error: this user’s vCard doesn’t specify the MIME type of its avatar.');
+				return noAvatar(res, from, 'Error: this user’s vCard doesn’t specify the MIME type of its avatar.');
 		}
 
 		var ext;
@@ -138,7 +176,7 @@ function onIq(stanza) {
 		// Here we don’t try to guess the extension even if the option is set.
 		if (ext === undefined) {
 			console.log('Unknown MIME type: '+type);
-			return svgError(res, 'Error: this user’s avatar is in an unknown format.');
+			return noAvatar(res, from, 'Error: this user’s avatar is in an unknown format.');
 		}
 
 		var binval = new Buffer(base64.replace(/\n/g, ''), 'base64');
@@ -148,7 +186,7 @@ function onIq(stanza) {
 			showImage(to, res);
 		});
 	} catch (e) {
-		svgError(res, 'Error: this user doesn’t have an avatar in his/her vCard.');
+		return noAvatar(res, from, 'Error: this user doesn’t have an avatar in his/her vCard.');
 	}
 }
 
@@ -239,7 +277,8 @@ http.createServer(function (req, res) {
 		if (re.test(req.url)) {
 			fs.readFile(file, function(err, content) {
 				if (err)
-					return svgError(res, 'Error: ' + (ee.error || file + ' unavailable.'));
+					return noAvatar(res, from, 'Error: ' + (ee.error || file + ' unavailable.'));
+
 				res.writeHead(200, {'Content-Type': ee.mime || 'text/plain'});
 				res.end(content);
 			});
--- a/configuration.js.example
+++ b/configuration.js.example
@@ -53,3 +53,6 @@ config.extensions = {
 	jpg: 'image/jpeg',
 	gif: 'image/gif'
 };
+
+// Try Gravatar if there is a problem during XMPP avatar retrieving.
+config.useGravatar = true;