Merge branch 'develop' into refactor-content

This commit is contained in:
Blade Barringer
2015-09-25 12:22:11 -05:00
40 changed files with 3335 additions and 3210 deletions

View File

@@ -1,15 +0,0 @@
{
"globals": {
"confirm": false
},
"browser": true,
"node": true,
"mocha": true,
"esnext": true,
"asi": true,
"boss": true,
"newcap": false
}

View File

@@ -1,6 +1,6 @@
.2014_Fall_HealerPROMO2 { .2014_Fall_HealerPROMO2 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -640px -843px; background-position: -564px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -18,7 +18,7 @@
} }
.2014_Fall_Warrior_PROMO { .2014_Fall_Warrior_PROMO {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -367px -843px; background-position: -473px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -42,7 +42,7 @@
} }
.promo_dilatoryDistress { .promo_dilatoryDistress {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -94px -843px; background-position: -837px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -54,7 +54,7 @@
} }
.promo_enchanted_armoire_201507 { .promo_enchanted_armoire_201507 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -882px -641px; background-position: -882px -550px;
width: 217px; width: 217px;
height: 90px; height: 90px;
} }
@@ -66,7 +66,7 @@
} }
.promo_enchanted_armoire_201509 { .promo_enchanted_armoire_201509 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -276px -843px; background-position: -291px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -76,6 +76,18 @@
width: 175px; width: 175px;
height: 175px; height: 175px;
} }
.promo_haunted_hair {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1023px -402px;
width: 100px;
height: 137px;
}
.customize-option. {
background-image: url();
background-position: ;
width: ;
height: ;
}
.promo_item_notif { .promo_item_notif {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -882px 0px; background-position: -882px 0px;
@@ -84,7 +96,7 @@
} }
.promo_mystery_201405 { .promo_mystery_201405 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -822px -843px; background-position: -200px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -96,7 +108,7 @@
} }
.promo_mystery_201407 { .promo_mystery_201407 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -934px; background-position: -195px -949px;
width: 42px; width: 42px;
height: 62px; height: 62px;
} }
@@ -108,7 +120,7 @@
} }
.promo_mystery_201409 { .promo_mystery_201409 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -549px -843px; background-position: -746px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -120,13 +132,13 @@
} }
.promo_mystery_201411 { .promo_mystery_201411 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -731px -843px; background-position: -928px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.promo_mystery_201412 { .promo_mystery_201412 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -1065px -843px; background-position: -152px -949px;
width: 42px; width: 42px;
height: 66px; height: 66px;
} }
@@ -138,25 +150,25 @@
} }
.promo_mystery_201502 { .promo_mystery_201502 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -185px -843px; background-position: -382px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.promo_mystery_201503 { .promo_mystery_201503 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -913px -843px; background-position: 0px -949px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.promo_mystery_201504 { .promo_mystery_201504 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -1004px -843px; background-position: -91px -949px;
width: 60px; width: 60px;
height: 69px; height: 69px;
} }
.promo_mystery_201505 { .promo_mystery_201505 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -458px -843px; background-position: -655px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -174,19 +186,25 @@
} }
.promo_mystery_201508 { .promo_mystery_201508 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -843px; background-position: -106px -843px;
width: 93px; width: 93px;
height: 90px; height: 90px;
} }
.promo_mystery_201509 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1019px -843px;
width: 90px;
height: 90px;
}
.promo_mystery_3014 { .promo_mystery_3014 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -882px -550px; background-position: -882px -641px;
width: 217px; width: 217px;
height: 90px; height: 90px;
} }
.promo_orca { .promo_orca {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -1023px -402px; background-position: 0px -843px;
width: 105px; width: 105px;
height: 105px; height: 105px;
} }
@@ -198,7 +216,7 @@
} }
.promo_pastel_skin { .promo_pastel_skin {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -331px -668px; background-position: 0px -668px;
width: 330px; width: 330px;
height: 83px; height: 83px;
} }
@@ -222,7 +240,7 @@
} }
.promo_shimmer_hair { .promo_shimmer_hair {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -668px; background-position: -331px -668px;
width: 330px; width: 330px;
height: 83px; height: 83px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 146 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 132 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 KiB

After

Width:  |  Height:  |  Size: 321 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 153 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 148 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 150 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -336,6 +336,8 @@
"armorMystery201506Notes": "Snorkel through a coral reef in this brightly-colored swim suit! Confers no benefit. June 2015 Subscriber Item.", "armorMystery201506Notes": "Snorkel through a coral reef in this brightly-colored swim suit! Confers no benefit. June 2015 Subscriber Item.",
"armorMystery201508Text": "Cheetah Costume", "armorMystery201508Text": "Cheetah Costume",
"armorMystery201508Notes": "Run fast as a flash in the fluffy Cheetah Costume! Confers no benefit. August 2015 Subscriber Item.", "armorMystery201508Notes": "Run fast as a flash in the fluffy Cheetah Costume! Confers no benefit. August 2015 Subscriber Item.",
"armorMystery201509Text": "Werewolf Costume",
"armorMystery201509Notes": "This IS a costume, right? Confers no benefit. September 2015 Subscriber Item.",
"armorMystery301404Text": "Steampunk Suit", "armorMystery301404Text": "Steampunk Suit",
"armorMystery301404Notes": "Dapper and dashing, wot! Confers no benefit. February 3015 Subscriber Item.", "armorMystery301404Notes": "Dapper and dashing, wot! Confers no benefit. February 3015 Subscriber Item.",
@@ -509,6 +511,8 @@
"headMystery201505Notes": "The green plume on this iron helm waves proudly. Confers no benefit. May 2015 Subscriber Item.", "headMystery201505Notes": "The green plume on this iron helm waves proudly. Confers no benefit. May 2015 Subscriber Item.",
"headMystery201508Text": "Cheetah Hat", "headMystery201508Text": "Cheetah Hat",
"headMystery201508Notes": "This cozy cheetah hat is very fuzzy! Confers no benefit. August 2015 Subscriber Item.", "headMystery201508Notes": "This cozy cheetah hat is very fuzzy! Confers no benefit. August 2015 Subscriber Item.",
"headMystery201509Text": "Werewolf Mask",
"headMystery201509Notes": "This IS a mask, right? Confers no benefit. September 2015 Subscriber Item.",
"headMystery301404Text": "Fancy Top Hat", "headMystery301404Text": "Fancy Top Hat",
"headMystery301404Notes": "A fancy top hat for the finest of gentlefolk! January 3015 Subscriber Item. Confers no benefit.", "headMystery301404Notes": "A fancy top hat for the finest of gentlefolk! January 3015 Subscriber Item. Confers no benefit.",
"headMystery301405Text": "Basic Top Hat", "headMystery301405Text": "Basic Top Hat",

View File

@@ -1834,6 +1834,11 @@ api.wrap = (user, main=true) ->
user.stats.mp += _.max([10,.1 * user._statsComputed.maxMP]) * dailyChecked / (dailyDueUnchecked + dailyChecked) user.stats.mp += _.max([10,.1 * user._statsComputed.maxMP]) * dailyChecked / (dailyDueUnchecked + dailyChecked)
user.stats.mp = user._statsComputed.maxMP if user.stats.mp > user._statsComputed.maxMP user.stats.mp = user._statsComputed.maxMP if user.stats.mp > user._statsComputed.maxMP
# After all is said and done, progress up user's effect on quest, return those values & reset the user's
progress = user.party.quest.progress; _progress = _.cloneDeep progress
_.merge progress, {down:0,up:0}
progress.collect = _.transform progress.collect, ((m,v,k)->m[k]=0)
# Analytics # Analytics
user.flags.cronCount?=0 user.flags.cronCount?=0
user.flags.cronCount++ user.flags.cronCount++
@@ -1845,14 +1850,12 @@ api.wrap = (user, main=true) ->
uuid: user._id, uuid: user._id,
user: user, user: user,
resting: user.preferences.sleep, resting: user.preferences.sleep,
cronCount: user.flags.cronCount cronCount: user.flags.cronCount,
progressUp: _progress.up,
progressDown: _progress.down
} }
options.analytics?.track('Cron', analyticsData) options.analytics?.track('Cron', analyticsData)
# After all is said and done, progress up user's effect on quest, return those values & reset the user's
progress = user.party.quest.progress; _progress = _.cloneDeep progress
_.merge progress, {down:0,up:0}
progress.collect = _.transform progress.collect, ((m,v,k)->m[k]=0)
_progress _progress
# Registered users with some history # Registered users with some history

View File

@@ -593,8 +593,13 @@ let head = {
text: t('headMystery201508Text'), text: t('headMystery201508Text'),
notes: t('headMystery201508Notes'), notes: t('headMystery201508Notes'),
mystery: '201508', mystery: '201508',
value: 0, value: 0
int: 0 },
201509: {
text: t('headMystery201509Text'),
notes: t('headMystery201509Notes'),
mystery:'201509',
value: 0
}, },
301404: { 301404: {
text: t('headMystery301404Text'), text: t('headMystery301404Text'),

View File

@@ -84,8 +84,13 @@ export var armor = {
text: t('armorMystery201508Text'), text: t('armorMystery201508Text'),
notes: t('armorMystery201508Notes'), notes: t('armorMystery201508Notes'),
mystery: '201508', mystery: '201508',
value: 0, value: 0
int: 0 },
201509: {
text: t('armorMystery201509Text'),
notes: t('armorMystery201509Notes'),
mystery: '201509',
value: 0
}, },
301404: { 301404: {
text: t('armorMystery301404Text'), text: t('armorMystery301404Text'),

View File

@@ -97,6 +97,11 @@ let mysterySets = {
end: '2015-09-02', end: '2015-09-02',
text: 'Cheetah Costume Set' text: 'Cheetah Costume Set'
}, },
201509: {
start:'2015-09-24',
end:'2015-10-02',
text:'Werewolf Set'
},
301404: { 301404: {
start: '3014-03-24', start: '3014-03-24',
end: '3014-04-02', end: '3014-04-02',

View File

@@ -2,7 +2,7 @@ var _id = '';
var update = { var update = {
$addToSet: { $addToSet: {
'purchased.plan.mysteryItems':{ 'purchased.plan.mysteryItems':{
$each:['head_mystery_201508','armor_mystery_201508'] $each:['head_mystery_201509','armor_mystery_201509']
} }
} }
}; };

View File

@@ -34,6 +34,7 @@
"grunt-karma": "~0.6.2", "grunt-karma": "~0.6.2",
"gulp": "^3.9.0", "gulp": "^3.9.0",
"gulp-clean": "^0.3.1", "gulp-clean": "^0.3.1",
"gulp-eslint": "^1.0.0",
"gulp-grunt": "^0.5.2", "gulp-grunt": "^0.5.2",
"gulp-imagemin": "^2.3.0", "gulp-imagemin": "^2.3.0",
"gulp-nodemon": "^2.0.4", "gulp-nodemon": "^2.0.4",

45
tasks/gulp-eslint.js Normal file
View File

@@ -0,0 +1,45 @@
import gulp from 'gulp';
import eslint from 'gulp-eslint';
import _ from 'lodash';
// TODO remove once we upgrade to lodash 3
const defaultsDeep = _.partialRight(_.merge, _.defaults);
const shared = {
rules: {
indent: [2, 2],
quotes: [2, 'single'],
'linebreak-style': [2, 'unix'],
semi: [2, 'always']
},
extends: 'eslint:recommended',
env: {
es6: true
}
};
gulp.task('lint:client', () => {
// Ignore .coffee files
return gulp.src(['./website/public/js/**/*.js'])
.pipe(eslint(defaultsDeep({
env: {
node: true
}
}, shared)))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
gulp.task('lint:server', () => {
// Ignore .coffee files
return gulp.src(['./website/src/**/*.js'])
.pipe(eslint(defaultsDeep({
env: {
browser: true
}
}, shared)))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
});
gulp.task('lint', ['lint:server', 'lint:client']);

View File

@@ -7,7 +7,7 @@ var User = require('mongoose').model('User');
var shared = require('../../../../common'); var shared = require('../../../../common');
var payments = require('./index'); var payments = require('./index');
var cc = require('coupon-code'); var cc = require('coupon-code');
var isProd = nconf.get("NODE_ENV") === 'production'; var isProd = nconf.get('NODE_ENV') === 'production';
var amzPayment = amazonPayments.connect({ var amzPayment = amazonPayments.connect({
environment: amazonPayments.Environment[isProd ? 'Production' : 'Sandbox'], environment: amazonPayments.Environment[isProd ? 'Production' : 'Sandbox'],
@@ -122,7 +122,7 @@ exports.checkout = function(req, res, next){
executePayment: function(cb){ executePayment: function(cb){
async.waterfall([ async.waterfall([
function(cb2){ User.findById(gift ? gift.uuid : undefined, cb2) }, function(cb2){ User.findById(gift ? gift.uuid : undefined, cb2); },
function(member, cb2){ function(member, cb2){
var data = {user:user, paymentMethod:'Amazon Payments'}; var data = {user:user, paymentMethod:'Amazon Payments'};
var method = 'buyGems'; var method = 'buyGems';
@@ -151,7 +151,7 @@ exports.subscribe = function(req, res, next){
return res.json(400, {err: 'Billing Agreement Id not supplied.'}); return res.json(400, {err: 'Billing Agreement Id not supplied.'});
} }
var billingAgreementId = req.body.billingAgreementId var billingAgreementId = req.body.billingAgreementId;
var sub = req.body.subscription ? shared.content.subscriptionBlocks[req.body.subscription] : false; var sub = req.body.subscription ? shared.content.subscriptionBlocks[req.body.subscription] : false;
var coupon = req.body.coupon; var coupon = req.body.coupon;
var user = res.locals.user; var user = res.locals.user;
@@ -167,7 +167,7 @@ exports.subscribe = function(req, res, next){
mongoose.model('Coupon').findOne({_id:cc.validate(coupon), event:sub.key}, function(err, coupon){ mongoose.model('Coupon').findOne({_id:cc.validate(coupon), event:sub.key}, function(err, coupon){
if(err) return cb(err); if(err) return cb(err);
if(!coupon) return cb(new Error('Coupon code not found.')); if(!coupon) return cb(new Error('Coupon code not found.'));
cb() cb();
}); });
}, },
@@ -236,7 +236,7 @@ exports.subscribe = function(req, res, next){
exports.subscribeCancel = function(req, res, next){ exports.subscribeCancel = function(req, res, next){
var user = res.locals.user; var user = res.locals.user;
if (!user.purchased.plan.customerId) if (!user.purchased.plan.customerId)
return res.json(401, {err: "User does not have a plan subscription"}); return res.json(401, {err: 'User does not have a plan subscription'});
var billingAgreementId = user.purchased.plan.customerId; var billingAgreementId = user.purchased.plan.customerId;

View File

@@ -6,7 +6,7 @@ var nconf = require('nconf');
var inAppPurchase = require('in-app-purchase'); var inAppPurchase = require('in-app-purchase');
inAppPurchase.config({ inAppPurchase.config({
// this is the path to the directory containing iap-sanbox/iap-live files // this is the path to the directory containing iap-sanbox/iap-live files
googlePublicKeyPath: nconf.get("IAP_GOOGLE_KEYDIR") googlePublicKeyPath: nconf.get('IAP_GOOGLE_KEYDIR')
}); });
// Validation ERROR Codes // Validation ERROR Codes
@@ -101,7 +101,7 @@ exports.iosVerify = function(req, res, next) {
if (iap.isValidated(appleRes)) { if (iap.isValidated(appleRes)) {
var purchaseDataList = iap.getPurchaseData(appleRes); var purchaseDataList = iap.getPurchaseData(appleRes);
if (purchaseDataList.length > 0) { if (purchaseDataList.length > 0) {
if (purchaseDataList[0].productId === "com.habitrpg.ios.Habitica.20gems") { if (purchaseDataList[0].productId === 'com.habitrpg.ios.Habitica.20gems') {
//Correct receipt //Correct receipt
payments.buyGems({user:user, paymentMethod:'IAP AppleStore'}); payments.buyGems({user:user, paymentMethod:'IAP AppleStore'});
var resObj = { var resObj = {
@@ -117,7 +117,7 @@ exports.iosVerify = function(req, res, next) {
ok: false, ok: false,
data: { data: {
code: INVALID_PAYLOAD, code: INVALID_PAYLOAD,
message: "Incorrect receipt content" message: 'Incorrect receipt content'
} }
}; };
return res.json(resObj); return res.json(resObj);
@@ -127,7 +127,7 @@ exports.iosVerify = function(req, res, next) {
ok: false, ok: false,
data: { data: {
code: INVALID_PAYLOAD, code: INVALID_PAYLOAD,
message: "Invalid receipt" message: 'Invalid receipt'
} }
}; };

View File

@@ -1,5 +1,5 @@
var nconf = require('nconf'); var nconf = require('nconf');
var stripe = require("stripe")(nconf.get('STRIPE_API_KEY')); var stripe = require('stripe')(nconf.get('STRIPE_API_KEY'));
var async = require('async'); var async = require('async');
var payments = require('./index'); var payments = require('./index');
var User = require('mongoose').model('User'); var User = require('mongoose').model('User');
@@ -38,10 +38,10 @@ exports.checkout = function(req, res, next) {
], cb); ], cb);
} else { } else {
stripe.charges.create({ stripe.charges.create({
amount: !gift ? "500" //"500" = $5 amount: !gift ? '500' //"500" = $5
: gift.type=='subscription' ? ""+shared.content.subscriptionBlocks[gift.subscription.key].price*100 : gift.type=='subscription' ? ''+shared.content.subscriptionBlocks[gift.subscription.key].price*100
: ""+gift.gems.amount/4*100, : ''+gift.gems.amount/4*100,
currency: "usd", currency: 'usd',
card: token card: token
}, cb); }, cb);
} }
@@ -49,7 +49,7 @@ exports.checkout = function(req, res, next) {
function(response, cb) { function(response, cb) {
if (sub) return payments.createSubscription({user:user, customerId:response.id, paymentMethod:'Stripe', sub:sub}, cb); if (sub) return payments.createSubscription({user:user, customerId:response.id, paymentMethod:'Stripe', sub:sub}, cb);
async.waterfall([ async.waterfall([
function(cb2){ User.findById(gift ? gift.uuid : undefined, cb2) }, function(cb2){ User.findById(gift ? gift.uuid : undefined, cb2); },
function(member, cb2){ function(member, cb2){
var data = {user:user, customerId:response.id, paymentMethod:'Stripe', gift:gift}; var data = {user:user, customerId:response.id, paymentMethod:'Stripe', gift:gift};
var method = 'buyGems'; var method = 'buyGems';
@@ -72,7 +72,7 @@ exports.checkout = function(req, res, next) {
exports.subscribeCancel = function(req, res, next) { exports.subscribeCancel = function(req, res, next) {
var user = res.locals.user; var user = res.locals.user;
if (!user.purchased.plan.customerId) if (!user.purchased.plan.customerId)
return res.json(401, {err: "User does not have a plan subscription"}); return res.json(401, {err: 'User does not have a plan subscription'});
async.auto({ async.auto({
get_cus: function(cb){ get_cus: function(cb){

View File

@@ -22,7 +22,7 @@ module.exports = function(server,mongoose) {
apdexBad = score < .75 || score == 1, apdexBad = score < .75 || score == 1,
memory = os.freemem() / os.totalmem(), memory = os.freemem() / os.totalmem(),
memoryHigh = memory < 0.1; memoryHigh = memory < 0.1;
if (/*apdexBad || */memoryHigh) throw "[Memory Leak] Apdex="+score+" Memory="+parseFloat(memory).toFixed(3)+" Time="+moment().format(); if (/*apdexBad || */memoryHigh) throw '[Memory Leak] Apdex='+score+' Memory='+parseFloat(memory).toFixed(3)+' Time='+moment().format();
}); });
}, mins*60*1000); }, mins*60*1000);
} }

View File

@@ -1,7 +1,7 @@
var nconf = require('nconf'); var nconf = require('nconf');
var IS_PROD = nconf.get('NODE_ENV') === 'production'; var IS_PROD = nconf.get('NODE_ENV') === 'production';
var ignoreRedirect = nconf.get('IGNORE_REDIRECT'); var ignoreRedirect = nconf.get('IGNORE_REDIRECT');
var BASE_URL = nconf.get("BASE_URL"); var BASE_URL = nconf.get('BASE_URL');
function isHTTP(req) { function isHTTP(req) {
return ( return (

View File

@@ -10,7 +10,7 @@ var i18n = require('../i18n');
// -------- App -------- // -------- App --------
router.get('/', i18n.getUserLanguage, locals, function(req, res) { router.get('/', i18n.getUserLanguage, locals, function(req, res) {
if (!req.headers['x-api-user'] && !req.headers['x-api-key'] && !(req.session && req.session.userId)) if (!req.headers['x-api-user'] && !req.headers['x-api-key'] && !(req.session && req.session.userId))
return res.redirect('/static/front') return res.redirect('/static/front');
return res.render('index', { return res.render('index', {
title: 'Habitica | Your Life The Role Playing Game', title: 'Habitica | Your Life The Role Playing Game',
@@ -29,7 +29,7 @@ _.each(pages, function(name){
marked: require('marked') marked: require('marked')
}); });
}); });
}) });
// --------- Redirects -------- // --------- Redirects --------

View File

@@ -12,10 +12,10 @@ router.get('/paypal/subscribe/success', i18n.getUserLanguage, payments.paypalSub
router.get('/paypal/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.paypalSubscribeCancel); router.get('/paypal/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.paypalSubscribeCancel);
router.post('/paypal/ipn', i18n.getUserLanguage, payments.paypalIPN); // misc ipn handling router.post('/paypal/ipn', i18n.getUserLanguage, payments.paypalIPN); // misc ipn handling
router.post("/stripe/checkout", auth.auth, i18n.getUserLanguage, payments.stripeCheckout); router.post('/stripe/checkout', auth.auth, i18n.getUserLanguage, payments.stripeCheckout);
router.post("/stripe/subscribe/edit", auth.auth, i18n.getUserLanguage, payments.stripeSubscribeEdit) router.post('/stripe/subscribe/edit', auth.auth, i18n.getUserLanguage, payments.stripeSubscribeEdit);
//router.get("/stripe/subscribe", auth.authWithUrl, i18n.getUserLanguage, payments.stripeSubscribe); // checkout route is used (above) with ?plan= instead //router.get('/stripe/subscribe', auth.authWithUrl, i18n.getUserLanguage, payments.stripeSubscribe); // checkout route is used (above) with ?plan= instead
router.get("/stripe/subscribe/cancel", auth.authWithUrl, i18n.getUserLanguage, payments.stripeSubscribeCancel); router.get('/stripe/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.stripeSubscribeCancel);
router.post('/amazon/verifyAccessToken', auth.auth, i18n.getUserLanguage, payments.amazonVerifyAccessToken); router.post('/amazon/verifyAccessToken', auth.auth, i18n.getUserLanguage, payments.amazonVerifyAccessToken);
router.post('/amazon/createOrderReferenceId', auth.auth, i18n.getUserLanguage, payments.amazonCreateOrderReferenceId); router.post('/amazon/createOrderReferenceId', auth.auth, i18n.getUserLanguage, payments.amazonCreateOrderReferenceId);
@@ -23,9 +23,9 @@ router.post('/amazon/checkout', auth.auth, i18n.getUserLanguage, payments.amazon
router.post('/amazon/subscribe', auth.auth, i18n.getUserLanguage, payments.amazonSubscribe); router.post('/amazon/subscribe', auth.auth, i18n.getUserLanguage, payments.amazonSubscribe);
router.get('/amazon/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.amazonSubscribeCancel); router.get('/amazon/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.amazonSubscribeCancel);
router.post("/iap/android/verify", auth.authWithUrl, /*i18n.getUserLanguage, */payments.iapAndroidVerify); router.post('/iap/android/verify', auth.authWithUrl, /*i18n.getUserLanguage, */payments.iapAndroidVerify);
router.post("/iap/ios/verify", auth.auth, /*i18n.getUserLanguage, */ payments.iapIosVerify); router.post('/iap/ios/verify', auth.auth, /*i18n.getUserLanguage, */ payments.iapIosVerify);
router.get("/api/v2/coupons/valid-discount/:code", /*auth.authWithUrl, i18n.getUserLanguage, */ payments.validCoupon); router.get('/api/v2/coupons/valid-discount/:code', /*auth.authWithUrl, i18n.getUserLanguage, */ payments.validCoupon);
module.exports = router; module.exports = router;

View File

@@ -84,7 +84,7 @@ mixin customizeProfile(mobile)
button(type='button', ng-if='user.purchased.hair.color.#{color}', class='customize-option hair hair_bangs_1_#{color}', ng-click='unlock("hair.color.#{color}")', ng-class='{selectableInventory: user.preferences.hair.color == "#{color}"}') button(type='button', ng-if='user.purchased.hair.color.#{color}', class='customize-option hair hair_bangs_1_#{color}', ng-click='unlock("hair.color.#{color}")', ng-class='{selectableInventory: user.preferences.hair.color == "#{color}"}')
+buyPref('hair.color', ['rainbow','yellow','green','purple','blue','TRUred'], 'rainbowColors') +buyPref('hair.color', ['rainbow','yellow','green','purple','blue','TRUred'], 'rainbowColors')
+buyPref('hair.color', ['pblue2','pgreen2','porange2','ppink2','ppurple2','pyellow2'], 'shimmerColors', 'disabled') +buyPref('hair.color', ['pblue2','pgreen2','porange2','ppink2','ppurple2','pyellow2'], 'shimmerColors', 'disabled')
+buyPref('hair.color', ['candycorn','ghostwhite','halloween','midnight','pumpkin','zombie'], 'hauntedColors', 'disabled') +buyPref('hair.color', ['candycorn','ghostwhite','halloween','midnight','pumpkin','zombie'], 'hauntedColors')
+buyPref('hair.color', ['aurora','festive','hollygreen','peppermint','snowy','winterstar'], 'winteryColors', 'disabled') +buyPref('hair.color', ['aurora','festive','hollygreen','peppermint','snowy','winterstar'], 'winteryColors', 'disabled')
li.customize-menu li.customize-menu
@@ -152,7 +152,7 @@ mixin customizeProfile(mobile)
// Seasonal event skins. Note that Spooky Skins are a legacy set and should always be disabled for purchase // Seasonal event skins. Note that Spooky Skins are a legacy set and should always be disabled for purchase
+buyPref('skin', ['pastelPink','pastelOrange','pastelYellow','pastelGreen','pastelBlue','pastelPurple','pastelRainbowChevron','pastelRainbowDiagonal'], 'pastelSkins', 'disabled') +buyPref('skin', ['pastelPink','pastelOrange','pastelYellow','pastelGreen','pastelBlue','pastelPurple','pastelRainbowChevron','pastelRainbowDiagonal'], 'pastelSkins', 'disabled')
+buyPref('skin', ['monster','pumpkin','skeleton','zombie','ghost','shadow'], 'spookySkins', 'disabled') +buyPref('skin', ['monster','pumpkin','skeleton','zombie','ghost','shadow'], 'spookySkins', 'disabled')
+buyPref('skin', ['candycorn','ogre','pumpkin2','reptile','shadow2','skeleton2','transparent','zombie2'], 'supernaturalSkins', 'disabled') +buyPref('skin', ['candycorn','ogre','pumpkin2','reptile','shadow2','skeleton2','transparent','zombie2'], 'supernaturalSkins')
+buyPref('skin', ['clownfish','deepocean','merblue','mergold','mergreen','merruby','shark','tropicalwater'], 'splashySkins', 'disabled') +buyPref('skin', ['clownfish','deepocean','merblue','mergold','mergreen','merruby','shark','tropicalwater'], 'splashySkins', 'disabled')

View File

@@ -1,41 +1,65 @@
h2 9/21/2015 - FALL FESTIVAL! LIMITED-EDITION OUTFITS, SEASONAL SHOP, CANDY FOOD DROPS, AND NPC DRESS-UP h2 9/24/2015 - HAUNTED HAIR COLORS, SUPERNATURAL SKIN SET, AND WEREWOLF SUBSCRIBER ITEM! PLUS, THE FALL PLOT-LINE CONTINUES...
hr hr
tr tr
td td
h3 Fall Festival Begins h3 Haunted Hair Colors and Supernatural Skin Set
p We've moved to the Flourishing Fields for the Fall Festival! The air is crisp, the leaves are red, and everyone is sweet and spooky. Come celebrate the Fall Festival with us... if you dare! .promo_haunted_hair.pull-right
p The Seasonal Edition Haunted Hair Colors are now available for purchase in <a href='/#/options/profile/avatar'>the avatar customizations page</a>! Now you can dye your avatar's hair Pumpkin, Midnight, Candy Corn, Ghost White, Zombie, or Halloween. Get them before October 31st!
br
p The Supernatural Skin Set is also available until October 31st! Now your avatar can become an Ogre, Skeleton, Pumpkin, Candy Corn, Reptile, or Dread Shade.
br
p Seasonal Edition items recur unchanged every year, but they are only available to purchase during a short period of time. Get them now, or you'll have to wait until next year!
p.small.muted by Lemoness, mariahm, and crystal phoenix
tr tr
td td
.promo_classes_fall_2015.pull-right h3 September Subscriber Items Revealed
h3 Limited Edition Class Outfits .promo_mystery_201509.pull-right
p Habiticans everywhere are dressing up. From now until October 31st, limited edition outfits are available in the Rewards column. Depending on your class, you can be a Scarecrow Warrior, Bat-tle Rogue, Potioner, or Stitch Witch! You'd better get productive to earn enough Gold before your time runs out... p The September Subscriber Item has been revealed: the Werewolf Armor Set! All September subscribers will receive the Werewolf Mask and the Werewolf Costume. You still have six days to <a href='/#/options/settings/subscription'>subscribe</a> and receive the item set! Thank you so much for your support - we really do rely on you to keep Habitica free to use and running smoothly.
p.small.muted by Lemoness and UncommonCriminal
tr
td
.promo_classes_fall_2014.pull-right
h3 Seasonal Shop Opens
p The <a href='/#/options/inventory/seasonalshop'>Seasonal Shop</a> has opened! It's stocking autumnal Seasonal Edition goodies at the moment, including last year's fall outfits. Everything there will be available to purchase during the Fall Festival event each year, but it's only open until October 31st, so be sure to stock up now, or you'll have to wait a year to buy these items again!
p.small.muted by Lemoness p.small.muted by Lemoness
tr tr
td td
.Pet_Food_Candy_Base.pull-right h3 Fall Plot-Line Continues
h3 Candy Food Drops! p In general, we've all been enjoying the Flourishing Fields. Habiticans are posing in fun costumes, taking pictures of the orange-and-black wildlife, and casting Spooky Sparkles on each other.
p For the duration of the Fall Festival, you may randomly find candy drops when you complete your tasks. These candies function just like normal food drops - can you guess which flavors your pets will like best? br
p.small.muted by Lemoness and SabreCat p Unfortunately, there does seem to be a serious problem with production for the first time in the history of the Fields. Deadlines are being missed. Shipments are not arriving. As you walk down the street, you overhear worried whispers among the citizens, speculating on the cause.
tr br
td p Some blame the unseasonal heat wave that has begun in the past few days. Others point to the difficulty of the tasks, and their ever-increasing quantity. And a few people -- just a few -- murmur that some of the hardest-working citizens have been disappearing, one by one, leaving their obligations abandoned. But surely that is nothing more than rumor?
.seasonalshop_open.pull-right
h3 NPC Dress Up
p The NPCs have decided to blend in with the locals of the Flourishing Fields by dressing up for the Fall Festival! Browse through the site to admire their new costumes.
p.small.muted by Lemoness
if menuItem !== 'oldNews' if menuItem !== 'oldNews'
hr hr
a(href='/static/old-news', target='_blank') Read older news a(href='/static/old-news', target='_blank') Read older news
mixin oldNews mixin oldNews
h2 9/21/2015 - FALL FESTIVAL! LIMITED-EDITION OUTFITS, SEASONAL SHOP, CANDY FOOD DROPS, AND NPC DRESS-UP
tr
td
h3 Fall Festival Begins
p We've moved to the Flourishing Fields for the Fall Festival! The air is crisp, the leaves are red, and everyone is sweet and spooky. Come celebrate the Fall Festival with us... if you dare!
tr
td
.promo_classes_fall_2015.pull-right
h3 Limited Edition Class Outfits
p Habiticans everywhere are dressing up. From now until October 31st, limited edition outfits are available in the Rewards column. Depending on your class, you can be a Scarecrow Warrior, Bat-tle Rogue, Potioner, or Stitch Witch! You'd better get productive to earn enough Gold before your time runs out...
p.small.muted by Lemoness and UncommonCriminal
tr
td
.promo_classes_fall_2014.pull-right
h3 Seasonal Shop Opens
p The <a href='/#/options/inventory/seasonalshop'>Seasonal Shop</a> has opened! It's stocking autumnal Seasonal Edition goodies at the moment, including last year's fall outfits. Everything there will be available to purchase during the Fall Festival event each year, but it's only open until October 31st, so be sure to stock up now, or you'll have to wait a year to buy these items again!
p.small.muted by Lemoness
tr
td
.Pet_Food_Candy_Base.pull-right
h3 Candy Food Drops!
p For the duration of the Fall Festival, you may randomly find candy drops when you complete your tasks. These candies function just like normal food drops - can you guess which flavors your pets will like best?
p.small.muted by Lemoness and SabreCat
tr
td
.seasonalshop_open.pull-right
h3 NPC Dress Up
p The NPCs have decided to blend in with the locals of the Flourishing Fields by dressing up for the Fall Festival! Browse through the site to admire their new costumes.
p.small.muted by Lemoness
h2 9/16/2015 - MAMMOTHS AND MANTIS SHRIMPS IN TIME TRAVELER SHOP! PLUS, FALL FESTIVAL PLOT-LINE CONTINUES h2 9/16/2015 - MAMMOTHS AND MANTIS SHRIMPS IN TIME TRAVELER SHOP! PLUS, FALL FESTIVAL PLOT-LINE CONTINUES
hr
tr tr
td td
.Pet-MantisShrimp-Base.pull-right .Pet-MantisShrimp-Base.pull-right