# HG changeset patch # User Emmanuel Gil Peyrot # Date 1310813264 -7200 # Node ID 9ff8f951da990003b7dcfbffdd0f1a8b2ec5b29c # Parent 92d6e1b40df54abce407b49f3aab93cef468c78f Add Gravatar fallback. diff --git a/avatar.js b/avatar.js --- 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('\n'); res.write('\n'); res.write('\t'+message+'\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); }); diff --git a/configuration.js.example b/configuration.js.example --- 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;