Merge pull request #4236 from HabitRPG/share-avatar

Share avatar
This commit is contained in:
Tyler Renelle 2014-11-12 14:42:48 -07:00
commit 114cbe2760
13 changed files with 184 additions and 43 deletions

2
.buildpacks Normal file
View file

@ -0,0 +1,2 @@
https://github.com/heroku/heroku-buildpack-nodejs.git
https://github.com/stomita/heroku-buildpack-phantomjs.git

View file

@ -25,5 +25,11 @@
"PAYPAL_SIGNATURE": "PAYPAL_SIGNATURE",
"EMAIL_SERVER_URL": "http://example.com",
"EMAIL_SERVER_AUTH_USER": "user",
"EMAIL_SERVER_AUTH_PASSWORD": "password"
"EMAIL_SERVER_AUTH_PASSWORD": "password",
"S3":{
"bucket":"bucket",
"accessKeyId":"accessKeyId",
"secretAccessKey":"secretAccessKey"
}
}

View file

@ -5,6 +5,7 @@
"main": "./src/server.js",
"dependencies": {
"async": "~0.9.0",
"aws-sdk": "^2.0.25",
"bower": "~1.3.12",
"coffee-script": "1.6.x",
"connect-ratelimit": "0.0.7",
@ -25,17 +26,18 @@
"grunt-nodemon": "~0.3.0",
"habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared#develop",
"icalendar": "git://github.com/lefnire/node-icalendar#master",
"jade": "~1.7.0",
"js2xmlparser": "~0.1.2",
"lodash": "~2.4.1",
"jade": "~1.7.0",
"method-override": "~2.2.0",
"mongoose": "~3.8.17",
"moment": "~2.8.3",
"mongoose": "~3.8.17",
"mongoose-id-autoinc": "~2013.7.14-4",
"nconf": "~0.6.9",
"newrelic": "~1.11.2",
"nib": "~1.0.1",
"nodemailer": "~0.5.2",
"pageres": "^1.0.1",
"passport": "~0.2.1",
"passport-facebook": "Fonger/passport-facebook#a8f98adcddad99caa9a918bc7b76462c92c5c9fd",
"paypal-express-checkout": "git://github.com/HabitRPG/node-paypal-express-checkout#habitrpg",
@ -43,6 +45,7 @@
"paypal-recurring": "git://github.com/jaybryant/paypal-recurring#656b496f43440893c984700191666a5c5c535dca",
"pretty-data": "git://github.com/vkiryukhin/pretty-data#master",
"request": "~2.44.0",
"s3-upload-stream": "^1.0.6",
"stripe": "*",
"swagger-node-express": "git://github.com/lefnire/swagger-node-express#habitrpg",
"universal-analytics": "~0.3.2",

View file

@ -75,6 +75,16 @@ future re: pets and whatnot, this is just temporary.
&:hover, &:focus
background: lighten($color-herobox, 16.18%)
.addthis_pill_style
width: 50px !important
.addthis_native_toolbox
position: absolute
top:2px
right:2px
opacity:0
&:hover .addthis_native_toolbox
opacity:1
//Need to find a way to indicate who is leader without using background-color as it won't work when a background image is applied
//.herobox.isLeader.noBackgroundImage
//background: lighten($color-herobox, 10%)

View file

@ -39,7 +39,17 @@
// Scripts only for desktop
if (!window.env.IS_MOBILE) {
// Add This
$.getScript("//s7.addthis.com/js/250/addthis_widget.js#pubid=lefnire");
//$.getScript("//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4"); //FIXME why isn't this working when here? instead it's now in <head>
var addthisServices = 'facebook,twitter,googleplus,tumblr,'+window.env.BASE_URL.replace('https://','').replace('http://','');
window.addthis_config = {
services_custom:{
name: "Download",
url: window.env.BASE_URL+"/export/avatar-"+User.user._id+".png",
icon: window.env.BASE_URL+"/favicon.ico"
},
services_expanded:addthisServices,
services_compact:addthisServices
};
// Google Charts
$.getScript("//www.google.com/jsapi", function() {

View file

@ -6,6 +6,21 @@ window.habitrpgStatic = angular.module('habitrpgStatic', ['notificationServices'
.constant("STORAGE_SETTINGS_ID", 'habit-mobile-settings')
.constant("MOBILE_APP", false)
.controller("RootCtrl", ['$scope', '$location', '$modal', '$http', function($scope, $location, $modal, $http){
// must be #?memberId=xx, see https://github.com/angular/angular.js/issues/7239
var memberId = $location.search()['memberId'];
if (memberId) {
$http.get('/api/v2/members/'+memberId).success(function(data, status, headers, config){
$scope.profile = data;
$scope.Content = window.habitrpgShared.content;
$modal.open({
templateUrl: 'modals/member.html',
scope: $scope
});
})
}
}])
.controller("PlansCtrl", ['$rootScope',
function($rootScope) {
$rootScope.clickContact = function(){

View file

@ -99,6 +99,8 @@
"bower_components/bootstrap/dist/css/bootstrap.css",
"bower_components/css-social-buttons/css/zocial.css",
"bower_components/jquery-colorbox/example1/colorbox.css",
"app.css",
"bower_components/habitrpg-shared/dist/habitrpg-shared.css",
"static.css"
]
}

View file

@ -8,6 +8,13 @@ var js2xmlparser = require("js2xmlparser");
var pd = require('pretty-data').pd;
var User = require('../models/user').model;
// Avatar screenshot/static-page includes
var Pageres = require('pageres'); //https://github.com/sindresorhus/pageres
var AWS = require('aws-sdk');
AWS.config.update({accessKeyId: nconf.get("S3:accessKeyId"), secretAccessKey: nconf.get("S3:secretAccessKey")});
var s3Stream = require('s3-upload-stream')(new AWS.S3()); //https://github.com/nathanpeck/s3-upload-stream
var bucket = nconf.get("S3:bucket");
var request = require('request');
/*
------------------------------------------------------------------------
@ -83,3 +90,49 @@ expressres.jsonstring = function(obj, headers, status) {
body = pd.json(JSON.stringify(obj));
return this.send(body, headers, status);
};
/*
------------------------------------------------------------------------
Static page and image screenshot of avatar
------------------------------------------------------------------------
*/
dataexport.avatarPage = function(req, res) {
User.findById(req.params.uuid).select('stats profile items achievements preferences backer contributor').exec(function(err, user){
res.render('avatar-static', {
title: user.profile.name,
env: _.defaults({user:user},res.locals.habitrpg)
});
})
};
dataexport.avatarImage = function(req, res, next) {
var filename = 'avatar-'+req.params.uuid+'.png';
request.head('https://'+bucket+'.s3.amazonaws.com/'+filename, function(err,response,body) {
// cache images for 10 minutes on aws, else upload a new one
if (response.statusCode==200 && moment().diff(response.headers['last-modified'], 'minutes') < 10)
return res.redirect(301, 'https://' + bucket + '.s3.amazonaws.com/' + filename);
new Pageres()//{delay:1}
.src(nconf.get('BASE_URL') + '/export/avatar-' + req.params.uuid + '.html', ['140x147'], {crop: true, filename: filename.replace('.png', '')})
.run(function (err, file) {
if (err) return next(err);
// see http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createMultipartUpload-property
var upload = s3Stream.upload({
Bucket: bucket,
Key: filename,
ACL: "public-read",
StorageClass: "REDUCED_REDUNDANCY",
ContentType: "image/png",
Expires: +moment().add({minutes: 3})
});
upload.on('error', function (err) {
next(err);
});
upload.on('uploaded', function (details) {
res.redirect(details.Location);
});
file[0].pipe(upload);
});
})
};

View file

@ -3,11 +3,14 @@ var router = new express.Router();
var dataexport = require('../controllers/dataexport');
var auth = require('../controllers/auth');
var nconf = require('nconf');
var i18n = require('../i18n')
var i18n = require('../i18n');
var middleware = require('../middleware.js');
/* Data export */
router.get('/history.csv',auth.authWithSession,i18n.getUserLanguage,dataexport.history); //[todo] encode data output options in the data controller and use these to build routes
router.get('/userdata.xml',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.xml);
router.get('/userdata.json',auth.authWithSession,i18n.getUserLanguage,dataexport.leanuser,dataexport.userdata.json);
router.get('/avatar-:uuid.html', i18n.getUserLanguage, middleware.locals, dataexport.avatarPage);
router.get('/avatar-:uuid.png', i18n.getUserLanguage, middleware.locals, dataexport.avatarImage);
module.exports = router;

28
views/avatar-static.jade Normal file
View file

@ -0,0 +1,28 @@
doctype html
html(ng-app="habitrpg")
head
title=title
link(rel='shortcut icon', href='#{env.getBuildUrl("favicon.ico")}?v=3')
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1.0')
meta(name='apple-mobile-web-app-capable', content='yes')
script(type='text/javascript').
window.env = !{JSON.stringify(env)};
!= env.getManifestFiles("app")
script(type='text/javascript').
window.habitrpg
.controller('StaticAvatarCtrl', ['$scope', function($scope){
$scope.profile = window.env.user;
}])
//webfonts
link(href='//fonts.googleapis.com/css?family=Lato:300,400,700,400italic,700italic', rel='stylesheet', type='text/css')
body(ng-cloak)
include ./shared/header/avatar
div(ng-controller='StaticAvatarCtrl')
+herobox({main:true})

View file

@ -10,6 +10,9 @@ html(ng-app="habitrpg", ng-controller="RootCtrl", ng-class='{"applying-action":a
meta(name='viewport', content='width=device-width, initial-scale=1.0')
meta(name='apple-mobile-web-app-capable', content='yes')
//FIXME for some reason this won't load when in footerCtrl.js#deferredScripts()
script(type="text/javascript", src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5016f6cc44ad68a4", async="async")
script(type='text/javascript').
window.env = !{JSON.stringify(env)};

View file

@ -7,6 +7,8 @@ mixin avatar(opts)
.character-sprites
.addthis_native_toolbox(ng-if='profile._id==user._id', data-url="#{env.BASE_URL}/static/front/#?memberId={{profile._id}}", data-title="Check out my HabitRPG progress!")
// Mount Body
if !opts.minimal
span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}')

View file

@ -8,6 +8,10 @@ block title
title=env.t('titleFront')
block content
div(ng-controller='RootCtrl')
include ../shared/header/avatar
include ../shared/modals/members
.marketing
//we need to use something that's not jumbotron for this, but still keep it centered
//could someone write something else to make it pretty?