mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-15 21:57:22 +01:00
AbstractGemItemOperation - BuyQuestWithGemOperation (#10476)
This commit is contained in:
@@ -24,6 +24,24 @@ export class AbstractBuyOperation {
|
||||
if (isNaN(this.quantity)) throw new BadRequest(this.i18n('invalidQuantity'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item value
|
||||
* @param item
|
||||
* @returns {number}
|
||||
*/
|
||||
getItemValue (item) {
|
||||
return item.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item key
|
||||
* @param item
|
||||
* @returns {String}
|
||||
*/
|
||||
getIemKey (item) {
|
||||
return item.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to get the translated string without passing `req.language`
|
||||
* @param {String} key - translation key
|
||||
@@ -100,14 +118,6 @@ export class AbstractGoldItemOperation extends AbstractBuyOperation {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
|
||||
getItemValue (item) {
|
||||
return item.value;
|
||||
}
|
||||
|
||||
getIemKey (item) {
|
||||
return item.key;
|
||||
}
|
||||
|
||||
canUserPurchase (user, item) {
|
||||
this.item = item;
|
||||
let itemValue = this.getItemValue(item);
|
||||
@@ -138,3 +148,37 @@ export class AbstractGoldItemOperation extends AbstractBuyOperation {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class AbstractGemItemOperation extends AbstractBuyOperation {
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
|
||||
canUserPurchase (user, item) {
|
||||
this.item = item;
|
||||
let itemValue = this.getItemValue(item);
|
||||
|
||||
if (!item.canBuy(user)) {
|
||||
throw new NotAuthorized(this.i18n('messageNotAvailable'));
|
||||
}
|
||||
|
||||
if (!user.balance || user.balance < itemValue * this.quantity) {
|
||||
throw new NotAuthorized(this.i18n('notEnoughGems'));
|
||||
}
|
||||
}
|
||||
|
||||
subtractCurrency (user, item) {
|
||||
let itemValue = this.getItemValue(item);
|
||||
|
||||
user.balance -= itemValue * this.quantity;
|
||||
}
|
||||
|
||||
analyticsData () {
|
||||
return {
|
||||
itemKey: this.getIemKey(this.item),
|
||||
itemType: 'Market',
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: this.getItemValue(this.item) * 4,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import purchaseOp from './purchase';
|
||||
import hourglassPurchase from './hourglassPurchase';
|
||||
import errorMessage from '../../libs/errorMessage';
|
||||
import {BuyGemOperation} from './buyGem';
|
||||
import {BuyQuestWithGemOperation} from './buyQuestGem';
|
||||
|
||||
// @TODO: remove the req option style. Dependency on express structure is an anti-pattern
|
||||
// We should either have more parms or a set structure validated by a Type checker
|
||||
@@ -52,10 +53,15 @@ module.exports = function buy (user, req = {}, analytics) {
|
||||
buyRes = buyOp.purchase();
|
||||
break;
|
||||
}
|
||||
case 'quests': {
|
||||
const buyOp = new BuyQuestWithGemOperation(user, req, analytics);
|
||||
|
||||
buyRes = buyOp.purchase();
|
||||
break;
|
||||
}
|
||||
case 'eggs':
|
||||
case 'hatchingPotions':
|
||||
case 'food':
|
||||
case 'quests':
|
||||
case 'gear':
|
||||
case 'bundles':
|
||||
buyRes = purchaseOp(user, req, analytics);
|
||||
|
||||
57
website/common/script/ops/buy/buyQuestGem.js
Normal file
57
website/common/script/ops/buy/buyQuestGem.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
BadRequest,
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
} from '../../libs/errors';
|
||||
import content from '../../content/index';
|
||||
import get from 'lodash/get';
|
||||
|
||||
import errorMessage from '../../libs/errorMessage';
|
||||
import {AbstractGemItemOperation} from './abstractBuyOperation';
|
||||
|
||||
export class BuyQuestWithGemOperation extends AbstractGemItemOperation {
|
||||
constructor (user, req, analytics) {
|
||||
super(user, req, analytics);
|
||||
}
|
||||
|
||||
multiplePurchaseAllowed () {
|
||||
return true;
|
||||
}
|
||||
|
||||
getItemKey () {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
getItemValue (item) {
|
||||
return item.value / 4;
|
||||
}
|
||||
|
||||
extractAndValidateParams (user, req) {
|
||||
let key = this.key = get(req, 'params.key');
|
||||
if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
|
||||
|
||||
let item = content.quests[key];
|
||||
|
||||
if (!item) throw new NotFound(errorMessage('questNotFound', {key}));
|
||||
|
||||
if (item.category === 'gold') {
|
||||
throw new NotAuthorized(this.i18n('questNotGemPurchasable', {key}));
|
||||
}
|
||||
|
||||
this.canUserPurchase(user, item);
|
||||
}
|
||||
|
||||
executeChanges (user, item, req) {
|
||||
user.items.quests[item.key] = user.items.quests[item.key] || 0;
|
||||
user.items.quests[item.key] += this.quantity;
|
||||
|
||||
this.subtractCurrency(user, item, this.quantity);
|
||||
|
||||
return [
|
||||
user.items.quests,
|
||||
this.i18n('messageBought', {
|
||||
itemText: item.text(req.language),
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ function purchaseItem (user, item, price, type, key) {
|
||||
}
|
||||
}
|
||||
|
||||
const acceptedTypes = ['eggs', 'hatchingPotions', 'food', 'quests', 'gear', 'bundles'];
|
||||
const acceptedTypes = ['eggs', 'hatchingPotions', 'food', 'gear', 'bundles'];
|
||||
const singlePurchaseTypes = ['gear'];
|
||||
module.exports = function purchase (user, req = {}, analytics) {
|
||||
let type = get(req.params, 'type');
|
||||
|
||||
Reference in New Issue
Block a user