mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 07:07:35 +01:00
v3: start to fix unlocking
This commit is contained in:
@@ -160,7 +160,8 @@
|
|||||||
"sold": "You sold a <%= key %> <%= type %>",
|
"sold": "You sold a <%= key %> <%= type %>",
|
||||||
"pathRequired": "Path string is required",
|
"pathRequired": "Path string is required",
|
||||||
"unlocked": "Items have been unlocked",
|
"unlocked": "Items have been unlocked",
|
||||||
"alreadyUnlocked": "Item already unlocked",
|
"alreadyUnlocked": "Full set already unlocked.",
|
||||||
|
"alreadyUnlockedPart": "Full set already partially unlocked.",
|
||||||
"cannotRevive": "Cannot revive if not dead",
|
"cannotRevive": "Cannot revive if not dead",
|
||||||
"rebirthComplete": "You have been reborn!",
|
"rebirthComplete": "You have been reborn!",
|
||||||
"petNotOwned": "You do not own this pet.",
|
"petNotOwned": "You do not own this pet.",
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import {
|
|||||||
BadRequest,
|
BadRequest,
|
||||||
} from '../libs/errors';
|
} from '../libs/errors';
|
||||||
|
|
||||||
|
// If item is already purchased -> equip it
|
||||||
|
// Otherwise unlock it
|
||||||
module.exports = function unlock (user, req = {}, analytics) {
|
module.exports = function unlock (user, req = {}, analytics) {
|
||||||
let path = _.get(req.query, 'path');
|
let path = _.get(req.query, 'path');
|
||||||
|
|
||||||
@@ -14,9 +16,9 @@ module.exports = function unlock (user, req = {}, analytics) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isFullSet = path.indexOf(',') !== -1;
|
let isFullSet = path.indexOf(',') !== -1;
|
||||||
let cost;
|
|
||||||
let isBackground = path.indexOf('background.') !== -1;
|
let isBackground = path.indexOf('background.') !== -1;
|
||||||
|
|
||||||
|
let cost;
|
||||||
if (isBackground && isFullSet) {
|
if (isBackground && isFullSet) {
|
||||||
cost = 3.75;
|
cost = 3.75;
|
||||||
} else if (isBackground) {
|
} else if (isBackground) {
|
||||||
@@ -27,21 +29,39 @@ module.exports = function unlock (user, req = {}, analytics) {
|
|||||||
cost = 0.5;
|
cost = 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
let alreadyOwns = !isFullSet && _.get(user, `purchased.${path}`) === true;
|
let setPaths;
|
||||||
|
let alreadyOwns;
|
||||||
|
|
||||||
|
if (isFullSet) {
|
||||||
|
setPaths = path.split(',');
|
||||||
|
let alreadyOwnedItems = 0;
|
||||||
|
|
||||||
|
_.each(setPaths, singlePath => {
|
||||||
|
if (_.get(user, `purchased.${singlePath}`) === true) {
|
||||||
|
alreadyOwnedItems++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (alreadyOwnedItems === setPaths.length) {
|
||||||
|
throw new NotAuthorized(i18n.t('alreadyUnlocked', req.language));
|
||||||
|
} else if (alreadyOwnedItems > 0) {
|
||||||
|
throw new NotAuthorized(i18n.t('alreadyUnlockedPart', req.language));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alreadyOwns = _.get(user, `purchased.${path}`) === true;
|
||||||
|
}
|
||||||
|
|
||||||
if ((!user.balance || user.balance < cost) && !alreadyOwns) {
|
if ((!user.balance || user.balance < cost) && !alreadyOwns) {
|
||||||
throw new NotAuthorized(i18n.t('notEnoughGems', req.language));
|
throw new NotAuthorized(i18n.t('notEnoughGems', req.language));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFullSet) {
|
if (isFullSet) {
|
||||||
_.each(path.split(','), function markItemsAsPurchased (pathPart) {
|
_.each(setPaths, function markItemsAsPurchased (pathPart) {
|
||||||
if (path.indexOf('gear.') !== -1) {
|
if (path.indexOf('gear.') !== -1) {
|
||||||
_.set(user, pathPart, true);
|
_.set(user, pathPart, true);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_.set(user, `purchased.${pathPart}`, true);
|
_.set(user, `purchased.${pathPart}`, true);
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (alreadyOwns) {
|
if (alreadyOwns) {
|
||||||
@@ -51,35 +71,38 @@ module.exports = function unlock (user, req = {}, analytics) {
|
|||||||
if (key === 'background' && value === user.preferences.background) {
|
if (key === 'background' && value === user.preferences.background) {
|
||||||
value = '';
|
value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
_.set(user, `preferences.${key}`, value);
|
_.set(user, `preferences.${key}`, value);
|
||||||
|
} else {
|
||||||
throw new NotAuthorized(i18n.t('alreadyUnlocked', req.language));
|
_.set(user, `purchased.${path}`, true);
|
||||||
}
|
}
|
||||||
_.set(user, `purchased.${path}`, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.indexOf('gear.') === -1) {
|
if (!alreadyOwns) {
|
||||||
user.markModified('purchased');
|
if (path.indexOf('gear.') === -1) {
|
||||||
}
|
user.markModified('purchased');
|
||||||
|
}
|
||||||
|
|
||||||
user.balance -= cost;
|
user.balance -= cost;
|
||||||
|
|
||||||
if (analytics) {
|
if (analytics) {
|
||||||
analytics.track('acquire item', {
|
analytics.track('acquire item', {
|
||||||
uuid: user._id,
|
uuid: user._id,
|
||||||
itemKey: path,
|
itemKey: path,
|
||||||
itemType: 'customization',
|
itemType: 'customization',
|
||||||
acquireMethod: 'Gems',
|
acquireMethod: 'Gems',
|
||||||
gemCost: cost / 0.25,
|
gemCost: cost / 0.25,
|
||||||
category: 'behavior',
|
category: 'behavior',
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = {
|
let response = {
|
||||||
data: _.pick(user, splitWhitespace('purchased preferences items')),
|
data: _.pick(user, splitWhitespace('purchased preferences items')),
|
||||||
message: i18n.t('unlocked'),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!alreadyOwns) response.message = i18n.t('unlocked', req.language);
|
||||||
|
|
||||||
if (req.v2 === true) {
|
if (req.v2 === true) {
|
||||||
return response.data;
|
return response.data;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -43,10 +43,10 @@ describe('shared.ops.unlock', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns an error when user already owns an item', (done) => {
|
it('returns an error when user already owns a full set', (done) => {
|
||||||
try {
|
try {
|
||||||
unlock(user, {query: {path: backgroundUnlockPath}});
|
unlock(user, {query: {path: unlockPath}});
|
||||||
unlock(user, {query: {path: backgroundUnlockPath}});
|
unlock(user, {query: {path: unlockPath}});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
expect(err).to.be.an.instanceof(NotAuthorized);
|
expect(err).to.be.an.instanceof(NotAuthorized);
|
||||||
expect(err.message).to.equal(i18n.t('alreadyUnlocked'));
|
expect(err.message).to.equal(i18n.t('alreadyUnlocked'));
|
||||||
@@ -54,6 +54,42 @@ describe('shared.ops.unlock', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns an error when user already owns items in a full set', (done) => {
|
||||||
|
try {
|
||||||
|
unlock(user, {query: {path: unlockPath}});
|
||||||
|
unlock(user, {query: {path: unlockPath}});
|
||||||
|
} catch (err) {
|
||||||
|
expect(err).to.be.an.instanceof(NotAuthorized);
|
||||||
|
expect(err.message).to.equal(i18n.t('alreadyUnlocked'));
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('equips an item already owned', () => {
|
||||||
|
expect(user.purchased.background.giant_florals).to.not.exists;
|
||||||
|
|
||||||
|
unlock(user, {query: {path: backgroundUnlockPath}});
|
||||||
|
let afterBalance = user.balance;
|
||||||
|
let response = unlock(user, {query: {path: backgroundUnlockPath}});
|
||||||
|
expect(user.balance).to.equal(afterBalance); // do not bill twice
|
||||||
|
|
||||||
|
expect(response.message).to.not.exists;
|
||||||
|
expect(user.preferences.background).to.equal('giant_florals');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('un-equips an item already equipped', () => {
|
||||||
|
expect(user.purchased.background.giant_florals).to.not.exists;
|
||||||
|
|
||||||
|
unlock(user, {query: {path: backgroundUnlockPath}}); // unlock
|
||||||
|
let afterBalance = user.balance;
|
||||||
|
unlock(user, {query: {path: backgroundUnlockPath}}); // equip
|
||||||
|
let response = unlock(user, {query: {path: backgroundUnlockPath}});
|
||||||
|
expect(user.balance).to.equal(afterBalance); // do not bill twice
|
||||||
|
|
||||||
|
expect(response.message).to.not.exists;
|
||||||
|
expect(user.preferences.background).to.equal('');
|
||||||
|
});
|
||||||
|
|
||||||
it('unlocks a full set', () => {
|
it('unlocks a full set', () => {
|
||||||
let response = unlock(user, {query: {path: unlockPath}});
|
let response = unlock(user, {query: {path: unlockPath}});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user