From b1b2b02ee289efed85d3e2fa7e0ee7bcf6430edc Mon Sep 17 00:00:00 2001 From: Loren West Date: Mon, 21 Oct 2013 17:45:32 -0700 Subject: [PATCH] More avatar types --- app.js | 4 +- lib/BBFProbe.js | 79 +++++++++++++- public/bbf.js | 277 +++++++++--------------------------------------- 3 files changed, 130 insertions(+), 230 deletions(-) diff --git a/app.js b/app.js index 31942a2..181b48a 100644 --- a/app.js +++ b/app.js @@ -2,9 +2,9 @@ var express = require('express'); var http = require('http'); var path = require('path'); var config = require('config'); -var Monitor = require('monitor-min'); var BBFProbe = require('./lib/BBFProbe'); var ConfigMonitor = require('config-monitor'); +var Monitor = require('monitor-min').start(); var app = express(); @@ -18,7 +18,7 @@ var appServer = http.createServer(app).listen(config.BBF.serverPort, function(){ ' / _ / / _ `/ / _ / // / __/ __/ _ \\/ _ \\ / _// _ `/ __/ __/ _ \\/ __/ // / \n' + '/____/_/\\_, / /____/\\_,_/\\__/\\__/\\___/_//_/ /_/ \\_,_/\\__/\\__/\\___/_/ \\_, / \n' + ' /___/ /___/'); - console.log('Express server listening on port ' + config.BBF.serverPort); + console.log('Serving buttons on port ' + config.BBF.serverPort); // Add the monitor-min service to the existing app server var monitorService = new Monitor.Server({server:appServer}); diff --git a/lib/BBFProbe.js b/lib/BBFProbe.js index 3b7b7d4..e86f3b3 100644 --- a/lib/BBFProbe.js +++ b/lib/BBFProbe.js @@ -7,6 +7,8 @@ Probe = Monitor.Probe, _ = Monitor._, log = Monitor.getLogger('BBFProbe'), + crypto = require('crypto'), + exec = require('child_process').exec, CONFIG = require('config'); // Constants @@ -67,6 +69,9 @@ for (var trayNum = 0; trayNum < NUM_TRAYS; trayNum++) { t.newTray(trayNum); } + + // Expose this probe to global + global.BBFProbe = t; }, /** @@ -108,8 +113,9 @@ * @param options {object} Options * @param options.buttonId {String} ID of the button pushed * @param options.photoUrl {String} The URL of the person that pushed the button + * @param [callback] {function(err)} Callback */ - buttonPushed_control: function(options) { + buttonPushed_control: function(options, callback) { var t = this, trayId = options.buttonId.substr(1,1); @@ -131,8 +137,79 @@ t.newTray(trayId); } + callback(); }, 100); + }, + + /** + * This attempts to convert a name into a photo URL for that person + * + * The 'github' type is the github name. 'gravatar' type is the gravatar + * email address, and 'twitter' is their twitter name without the '@'. + * + * @param options {object} Options + * @param options.type {String} One of "github", "gravatar", or "twitter" + * @param options.name {String} The URL of the person that pushed the button + * @param callback {Function(err, url)} The callback function + * @param callback.err {Object} The error object if an error occurred + * @param callback.url {String} The photo URL for that person + */ + findPhotoUrl_control: function(options, callback) { + var t = this, + type = options.type, + name = options.name, + url = null; + + // Gravatar: Return the MD5 hash of their lowercased, trimmed email + if (type === 'gravatar') { + var md5 = crypto.createHash('md5'); + md5.update(name.toLowerCase().trim()); + url = 'http://www.gravatar.com/avatar/' + md5.digest('hex') + '.jpg'; + return callback(null, url); + } + + // Twitter name + else if (type === 'twitter') { + url = 'https://twitter.com/' + name; + t.getAvatarImgLine(url, 'avatar size73', function(err, avatarUrl) { + if (err) { + return callback(err); + } + + // Parse the http portion + var part = avatarUrl.substr(avatarUrl.indexOf('http')); + part = part.substr(0, part.indexOf('"')); + return callback(err, part); + }); + } + + // Github name + else if (type === 'github') { + url = 'https://github.com/' + name; + t.getAvatarImgLine(url, '>>(32-iShiftBits)); - } - - function AddUnsigned(lX,lY) { - var lX4,lY4,lX8,lY8,lResult; - lX8 = (lX & 0x80000000); - lY8 = (lY & 0x80000000); - lX4 = (lX & 0x40000000); - lY4 = (lY & 0x40000000); - lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF); - if (lX4 & lY4) { - return (lResult ^ 0x80000000 ^ lX8 ^ lY8); - } - if (lX4 | lY4) { - if (lResult & 0x40000000) { - return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); - } else { - return (lResult ^ 0x40000000 ^ lX8 ^ lY8); - } - } else { - return (lResult ^ lX8 ^ lY8); - } - } - - function F(x,y,z) { return (x & y) | ((~x) & z); } - function G(x,y,z) { return (x & z) | (y & (~z)); } - function H(x,y,z) { return (x ^ y ^ z); } - function I(x,y,z) { return (y ^ (x | (~z))); } - function FF(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function GG(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function HH(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function II(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function ConvertToWordArray(string) { - var lWordCount; - var lMessageLength = string.length; - var lNumberOfWords_temp1=lMessageLength + 8; - var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64; - var lNumberOfWords = (lNumberOfWords_temp2+1)*16; - var lWordArray=Array(lNumberOfWords-1); - var lBytePosition = 0; - var lByteCount = 0; - while ( lByteCount < lMessageLength ) { - lWordCount = (lByteCount-(lByteCount % 4))/4; - lBytePosition = (lByteCount % 4)*8; - lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29; - return lWordArray; - }; - - function WordToHex(lValue) { - var WordToHexValue="",WordToHexValue_temp="",lByte,lCount; - for (lCount = 0;lCount<=3;lCount++) { - lByte = (lValue>>>(lCount*8)) & 255; - WordToHexValue_temp = "0" + lByte.toString(16); - WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2); - } - return WordToHexValue; - }; - - function Utf8Encode(string) { - string = string.replace(/\r\n/g,"\n"); - var utftext = ""; - - for (var n = 0; n < string.length; n++) { - - var c = string.charCodeAt(n); + // Process the user name into their photo URL + $('#begin').click(function(){ + var userName = $('#name').val().trim(), + nameType = null; - if (c < 128) { - utftext += String.fromCharCode(c); - } - else if((c > 127) && (c < 2048)) { - utftext += String.fromCharCode((c >> 6) | 192); - utftext += String.fromCharCode((c & 63) | 128); - } - else { - utftext += String.fromCharCode((c >> 12) | 224); - utftext += String.fromCharCode(((c >> 6) & 63) | 128); - utftext += String.fromCharCode((c & 63) | 128); - } + // Get the user name and + if (!userName) { + return; + } - } + // Is it an url to a photo? + if (userName.match(/^http[s]+:\/\//i)) { + return showPhoto(userName, userName); + } - return utftext; - }; + // It's a twitter name if it starts with a @ + if (userName.match(/^@/)) { + userName = userName.substr(1); + nameType = 'twitter'; + } - var x=Array(); - var k,AA,BB,CC,DD,a,b,c,d; - var S11=7, S12=12, S13=17, S14=22; - var S21=5, S22=9 , S23=14, S24=20; - var S31=4, S32=11, S33=16, S34=23; - var S41=6, S42=10, S43=15, S44=21; + // It's a gravatar name if it contains an @ + else if (userName.match(/@/)) { + nameType = 'gravatar'; + } - string = Utf8Encode(string); + // Otherwise it's a github name + else { + nameType = 'github'; + } - x = ConvertToWordArray(string); + // Tell the backend the button was pushed + BBFMonitor.control('findPhotoUrl', {type: nameType, name: userName}, function(err, photoUrl){ + if (err) { + alert('Error while finding user photo: ' + JSON.stringify(err)); + return; + } + showPhoto(userName, photoUrl); + }); - a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; + }); + $('#name').focus(); - for (k=0;k