diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js index bae6423be0..233000372d 100644 --- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js +++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js @@ -1,8 +1,8 @@ import { generateUser, - translate as t, } from '../../../../../helpers/api-integration/v3'; import paypalPayments from '../../../../../../website/server/libs/payments/paypal'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('payments : paypal #checkoutSuccess', () => { let endpoint = '/paypal/checkout/success'; @@ -17,7 +17,7 @@ describe('payments : paypal #checkoutSuccess', () => { .to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: t('missingPaymentId'), + message: apiMessages('missingPaymentId'), }); }); @@ -26,7 +26,7 @@ describe('payments : paypal #checkoutSuccess', () => { .to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: t('missingCustomerId'), + message: apiMessages('missingCustomerId'), }); }); diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js index 3146eb0c5d..b6c6a765b7 100644 --- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js +++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js @@ -1,9 +1,9 @@ import { generateUser, - translate as t, } from '../../../../../helpers/api-integration/v3'; import paypalPayments from '../../../../../../website/server/libs/payments/paypal'; import shared from '../../../../../../website/common'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('payments : paypal #subscribe', () => { let endpoint = '/paypal/subscribe'; @@ -17,7 +17,7 @@ describe('payments : paypal #subscribe', () => { await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: t('missingSubKey'), + message: apiMessages('missingSubKey'), }); }); diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js index bace51302a..f858851848 100644 --- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js +++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js @@ -1,7 +1,7 @@ import { generateUser, - translate as t, } from '../../../../../helpers/api-integration/v3'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; import paypalPayments from '../../../../../../website/server/libs/payments/paypal'; describe('payments : paypal #subscribeSuccess', () => { @@ -16,7 +16,7 @@ describe('payments : paypal #subscribeSuccess', () => { await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: t('missingPaypalBlock'), + message: apiMessages('missingPaypalBlock'), }); }); diff --git a/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js b/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js index 7757c4c2ac..ccda410914 100644 --- a/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js @@ -5,6 +5,7 @@ import { } from '../../../../helpers/api-v3-integration.helper'; import { v4 as generateUUID } from 'uuid'; import { quests as questScrolls } from '../../../../../website/common/script/content'; +import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('POST /groups/:groupId/quests/invite/:questKey', () => { let questingGroup; @@ -68,7 +69,7 @@ describe('POST /groups/:groupId/quests/invite/:questKey', () => { await expect(leader.post(`/groups/${questingGroup._id}/quests/invite/${FAKE_QUEST}`)).to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: t('questNotFound', {key: FAKE_QUEST}), + message: apiMessages('questNotFound', {key: FAKE_QUEST}), }); }); diff --git a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js index a141a31145..ba73fcd6d7 100644 --- a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js +++ b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js @@ -9,6 +9,7 @@ import { import { v4 as generateUUID } from 'uuid'; import { find } from 'lodash'; +import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('POST /user/class/cast/:spellId', () => { let user; @@ -24,7 +25,7 @@ describe('POST /user/class/cast/:spellId', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: t('spellNotFound', {spellId}), + message: apiMessages('spellNotFound', {spellId}), }); }); @@ -34,7 +35,7 @@ describe('POST /user/class/cast/:spellId', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: t('spellNotFound', {spellId}), + message: apiMessages('spellNotFound', {spellId}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy.test.js b/test/api/v3/integration/user/buy/POST-user_buy.test.js index 37670d115b..848f787618 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy.test.js @@ -5,6 +5,7 @@ import { translate as t, } from '../../../../../helpers/api-integration/v3'; import shared from '../../../../../../website/common/script'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; let content = shared.content; @@ -24,7 +25,7 @@ describe('POST /user/buy/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: t('itemNotFound', {key: 'notExisting'}), + message: apiMessages('itemNotFound', {key: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js b/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js index d3992ed1fe..2af190f493 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js @@ -2,8 +2,8 @@ import { generateUser, - translate as t, } from '../../../../../helpers/api-integration/v3'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('POST /user/buy-gear/:key', () => { let user; @@ -21,7 +21,7 @@ describe('POST /user/buy-gear/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: t('itemNotFound', {key: 'notExisting'}), + message: apiMessages('itemNotFound', {key: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js b/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js index f539a29a5a..4224ff9cb1 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js @@ -3,6 +3,7 @@ import { translate as t, } from '../../../../../helpers/api-integration/v3'; import shared from '../../../../../../website/common/script'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; let content = shared.content; @@ -20,7 +21,7 @@ describe('POST /user/buy-quest/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: t('questNotFound', {key: 'notExisting'}), + message: apiMessages('questNotFound', {key: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js b/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js index f6c16febee..a132b57a59 100644 --- a/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js +++ b/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js @@ -3,6 +3,7 @@ import { translate as t, } from '../../../../../helpers/api-integration/v3'; import shared from '../../../../../../website/common/script'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; let content = shared.content; @@ -20,7 +21,7 @@ describe('POST /user/buy-special-spell/:key', () => { .to.eventually.be.rejected.and.eql({ code: 404, error: 'NotFound', - message: t('spellNotFound', {spellId: 'notExisting'}), + message: apiMessages('spellNotFound', {spellId: 'notExisting'}), }); }); diff --git a/test/api/v3/integration/user/stats/POST-user_allocate.test.js b/test/api/v3/integration/user/stats/POST-user_allocate.test.js index 6487641c79..fce5e10a6f 100644 --- a/test/api/v3/integration/user/stats/POST-user_allocate.test.js +++ b/test/api/v3/integration/user/stats/POST-user_allocate.test.js @@ -2,6 +2,7 @@ import { generateUser, translate as t, } from '../../../../../helpers/api-integration/v3'; +import apiMessages from '../../../../../../website/server/libs/apiMessages'; describe('POST /user/allocate', () => { let user; @@ -17,7 +18,7 @@ describe('POST /user/allocate', () => { .to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: t('invalidAttribute', {attr: 'invalid'}), + message: apiMessages('invalidAttribute', {attr: 'invalid'}), }); }); diff --git a/test/api/v3/integration/webhook/POST-user_add_webhook.test.js b/test/api/v3/integration/webhook/POST-user_add_webhook.test.js index accb834dc4..fdb95cf6a1 100644 --- a/test/api/v3/integration/webhook/POST-user_add_webhook.test.js +++ b/test/api/v3/integration/webhook/POST-user_add_webhook.test.js @@ -3,6 +3,7 @@ import { translate as t, } from '../../../../helpers/api-integration/v3'; import { v4 as generateUUID } from 'uuid'; +import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('POST /user/webhook', () => { let user, body; @@ -200,7 +201,7 @@ describe('POST /user/webhook', () => { await expect(user.post('/user/webhook', body)).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: t('groupIdRequired'), + message: apiMessages('groupIdRequired'), }); }); diff --git a/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js b/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js index 994eff6750..097dc3b174 100644 --- a/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js +++ b/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js @@ -3,6 +3,7 @@ import { translate as t, } from '../../../../helpers/api-integration/v3'; import { v4 as generateUUID} from 'uuid'; +import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('PUT /user/webhook/:id', () => { let user, webhookToUpdate; @@ -126,7 +127,7 @@ describe('PUT /user/webhook/:id', () => { await expect(user.put(`/user/webhook/${webhookToUpdate.id}`, {type, options})).to.eventually.be.rejected.and.eql({ code: 400, error: 'BadRequest', - message: t('groupIdRequired'), + message: apiMessages('groupIdRequired'), }); }); }); diff --git a/test/api/v3/unit/models/webhook.test.js b/test/api/v3/unit/models/webhook.test.js index ddb63e9caf..9ca8e63c1e 100644 --- a/test/api/v3/unit/models/webhook.test.js +++ b/test/api/v3/unit/models/webhook.test.js @@ -1,6 +1,7 @@ import { model as Webhook } from '../../../../../website/server/models/webhook'; import { BadRequest } from '../../../../../website/server/libs/errors'; import { v4 as generateUUID } from 'uuid'; +import apiMessages from '../../../../../website/server/libs/apiMessages'; describe('Webhook Model', () => { context('Instance Methods', () => { @@ -135,8 +136,8 @@ describe('Webhook Model', () => { wh.formatOptions(res); } catch (err) { expect(err).to.be.an.instanceOf(BadRequest); - expect(res.t).to.be.calledOnce; - expect(res.t).to.be.calledWith('groupIdRequired'); + + expect(err.message).to.eql(apiMessages('groupIdRequired')); done(); } }); diff --git a/test/common/ops/buy/buy.js b/test/common/ops/buy/buy.js index ab72d1f2b7..15c41382cf 100644 --- a/test/common/ops/buy/buy.js +++ b/test/common/ops/buy/buy.js @@ -8,6 +8,7 @@ import { } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; import content from '../../../../website/common/script/content/index'; +import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buy', () => { let user; @@ -40,7 +41,7 @@ describe('shared.ops.buy', () => { buy(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('missingKeyParam')); + expect(err.message).to.equal(apiMessages('missingKeyParam')); done(); } }); diff --git a/test/common/ops/buy/buyMarketGear.js b/test/common/ops/buy/buyMarketGear.js index 48ce22ea1d..5170682c6e 100644 --- a/test/common/ops/buy/buyMarketGear.js +++ b/test/common/ops/buy/buyMarketGear.js @@ -10,6 +10,7 @@ import { BadRequest, NotAuthorized, NotFound, } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; +import apiMessages from '../../../../website/server/libs/apiMessages'; function buyGear (user, req, analytics) { let buyOp = new BuyMarketGearOperation(user, req, analytics); @@ -190,7 +191,7 @@ describe('shared.ops.buyMarketGear', () => { buyGear(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('missingKeyParam')); + expect(err.message).to.equal(apiMessages('missingKeyParam')); done(); } }); @@ -202,7 +203,7 @@ describe('shared.ops.buyMarketGear', () => { buyGear(user, {params}); } catch (err) { expect(err).to.be.an.instanceof(NotFound); - expect(err.message).to.equal(i18n.t('itemNotFound', params)); + expect(err.message).to.equal(apiMessages('itemNotFound', params)); done(); } }); diff --git a/test/common/ops/buy/buyMysterySet.js b/test/common/ops/buy/buyMysterySet.js index 5334d3e671..ced59589da 100644 --- a/test/common/ops/buy/buyMysterySet.js +++ b/test/common/ops/buy/buyMysterySet.js @@ -10,6 +10,7 @@ import { NotFound, } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; +import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buyMysterySet', () => { let user; @@ -70,7 +71,7 @@ describe('shared.ops.buyMysterySet', () => { buyMysterySet(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('missingKeyParam')); + expect(err.message).to.equal(apiMessages('missingKeyParam')); done(); } }); diff --git a/test/common/ops/buy/buyQuest.js b/test/common/ops/buy/buyQuest.js index 390b65ee01..6ab79c3546 100644 --- a/test/common/ops/buy/buyQuest.js +++ b/test/common/ops/buy/buyQuest.js @@ -8,6 +8,7 @@ import { NotFound, } from '../../../../website/common/script/libs/errors'; import i18n from '../../../../website/common/script/i18n'; +import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buyQuest', () => { let user; @@ -106,7 +107,7 @@ describe('shared.ops.buyQuest', () => { }); } catch (err) { expect(err).to.be.an.instanceof(NotFound); - expect(err.message).to.equal(i18n.t('questNotFound', {key: 'snarfblatter'})); + expect(err.message).to.equal(apiMessages('questNotFound', {key: 'snarfblatter'})); expect(user.items.quests).to.eql({}); expect(user.stats.gp).to.equal(9999); done(); @@ -151,7 +152,7 @@ describe('shared.ops.buyQuest', () => { buyQuest(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('missingKeyParam')); + expect(err.message).to.equal(apiMessages('missingKeyParam')); done(); } }); diff --git a/test/common/ops/buy/buySpecialSpell.js b/test/common/ops/buy/buySpecialSpell.js index 97aade05ae..45ac2be1f2 100644 --- a/test/common/ops/buy/buySpecialSpell.js +++ b/test/common/ops/buy/buySpecialSpell.js @@ -9,6 +9,7 @@ import { generateUser, } from '../../../helpers/common.helper'; import content from '../../../../website/common/script/content/index'; +import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.buySpecialSpell', () => { let user; @@ -28,7 +29,7 @@ describe('shared.ops.buySpecialSpell', () => { buySpecialSpell(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('missingKeyParam')); + expect(err.message).to.equal(apiMessages('missingKeyParam')); done(); } }); @@ -42,7 +43,7 @@ describe('shared.ops.buySpecialSpell', () => { }); } catch (err) { expect(err).to.be.an.instanceof(NotFound); - expect(err.message).to.equal(i18n.t('spellNotFound', {spellId: 'notExisting'})); + expect(err.message).to.equal(apiMessages('spellNotFound', {spellId: 'notExisting'})); done(); } }); diff --git a/test/common/ops/buy/hourglassPurchase.js b/test/common/ops/buy/hourglassPurchase.js index 3684f7d416..2b768efddb 100644 --- a/test/common/ops/buy/hourglassPurchase.js +++ b/test/common/ops/buy/hourglassPurchase.js @@ -8,6 +8,7 @@ import content from '../../../../website/common/script/content/index'; import { generateUser, } from '../../../helpers/common.helper'; +import apiMessages from '../../../../website/server/libs/apiMessages'; describe('common.ops.hourglassPurchase', () => { let user; @@ -28,7 +29,7 @@ describe('common.ops.hourglassPurchase', () => { hourglassPurchase(user, {params: {}}); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.eql(i18n.t('missingKeyParam')); + expect(err.message).to.eql(apiMessages('missingKeyParam')); done(); } }); @@ -38,7 +39,7 @@ describe('common.ops.hourglassPurchase', () => { hourglassPurchase(user, {params: {key: 'Base'}}); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.eql(i18n.t('missingTypeParam')); + expect(err.message).to.eql(apiMessages('missingTypeParam')); done(); } }); diff --git a/test/common/ops/feed.js b/test/common/ops/feed.js index 91c6a9cee9..140464ede5 100644 --- a/test/common/ops/feed.js +++ b/test/common/ops/feed.js @@ -9,6 +9,7 @@ import i18n from '../../../website/common/script/i18n'; import { generateUser, } from '../../helpers/common.helper'; +import apiMessages from '../../../website/server/libs/apiMessages'; describe('shared.ops.feed', () => { let user; @@ -23,7 +24,7 @@ describe('shared.ops.feed', () => { feed(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('missingPetFoodFeed')); + expect(err.message).to.equal(apiMessages('missingPetFoodFeed')); done(); } }); diff --git a/test/common/ops/hatch.js b/test/common/ops/hatch.js index fc6c7875f9..076966f4d3 100644 --- a/test/common/ops/hatch.js +++ b/test/common/ops/hatch.js @@ -8,6 +8,7 @@ import i18n from '../../../website/common/script/i18n'; import { generateUser, } from '../../helpers/common.helper'; +import apiMessages from '../../../website/server/libs/apiMessages'; describe('shared.ops.hatch', () => { let user; @@ -24,7 +25,7 @@ describe('shared.ops.hatch', () => { hatch(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('missingEggHatchingPotionHatch')); + expect(err.message).to.equal(apiMessages('missingEggHatchingPotion')); expect(user.items.pets).to.be.empty; } }); diff --git a/test/common/ops/stats/allocate.js b/test/common/ops/stats/allocate.js index 1eaa14f88d..2f3625acd6 100644 --- a/test/common/ops/stats/allocate.js +++ b/test/common/ops/stats/allocate.js @@ -7,6 +7,7 @@ import i18n from '../../../../website/common/script/i18n'; import { generateUser, } from '../../../helpers/common.helper'; +import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.allocate', () => { let user; @@ -22,7 +23,7 @@ describe('shared.ops.allocate', () => { }); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('invalidAttribute', {attr: 'notValid'})); + expect(err.message).to.equal(apiMessages('invalidAttribute', {attr: 'notValid'})); done(); } }); diff --git a/test/common/ops/stats/allocateBulk.js b/test/common/ops/stats/allocateBulk.js index e91de8cf9e..f505c6478a 100644 --- a/test/common/ops/stats/allocateBulk.js +++ b/test/common/ops/stats/allocateBulk.js @@ -7,6 +7,7 @@ import i18n from '../../../../website/common/script/i18n'; import { generateUser, } from '../../../helpers/common.helper'; +import apiMessages from '../../../../website/server/libs/apiMessages'; describe('shared.ops.allocateBulk', () => { let user; @@ -27,7 +28,7 @@ describe('shared.ops.allocateBulk', () => { }); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('invalidAttribute', {attr: 'invalid'})); + expect(err.message).to.equal(apiMessages('invalidAttribute', {attr: 'invalid'})); done(); } }); @@ -37,7 +38,7 @@ describe('shared.ops.allocateBulk', () => { allocateBulk(user); } catch (err) { expect(err).to.be.an.instanceof(BadRequest); - expect(err.message).to.equal(i18n.t('statsObjectRequired')); + expect(err.message).to.equal(apiMessages('statsObjectRequired')); done(); } }); diff --git a/website/common/locales/en/character.json b/website/common/locales/en/character.json index 162fa6e701..7bfe47d255 100644 --- a/website/common/locales/en/character.json +++ b/website/common/locales/en/character.json @@ -201,7 +201,6 @@ "showQuickAllocation": "Show Stat Allocation", "hideQuickAllocation": "Hide Stat Allocation", "quickAllocationLevelPopover": "Each level earns you one Point to assign to a Stat of your choice. You can do so manually, or let the game decide for you using one of the Automatic Allocation options found in User Icon > Stats.", - "invalidAttribute": "\"<%= attr %>\" is not a valid Stat.", "notEnoughAttrPoints": "You don't have enough Stat Points.", "style": "Style", "facialhair": "Facial", @@ -224,6 +223,5 @@ "allocated": "Allocated", "buffs": "Buffs", "pointsAvailable": "Points Available", - "pts": "pts", - "statsObjectRequired": "Stats update is required" + "pts": "pts" } diff --git a/website/common/locales/en/contrib.json b/website/common/locales/en/contrib.json index 4977277a27..87b27f5d9a 100644 --- a/website/common/locales/en/contrib.json +++ b/website/common/locales/en/contrib.json @@ -49,7 +49,6 @@ "UUID": "User ID", "loadUser": "Load User", "noAdminAccess": "You don't have admin access.", - "pageMustBeNumber": "req.query.page must be a number", "userNotFound": "User not found.", "invalidUUID": "UUID must be valid", "title": "Title", diff --git a/website/common/locales/en/groups.json b/website/common/locales/en/groups.json index 1b2ea93bd8..495bb8c4a5 100644 --- a/website/common/locales/en/groups.json +++ b/website/common/locales/en/groups.json @@ -210,7 +210,6 @@ "partyOnName": "Party On", "partyUpText": "Joined a Party with another person! Have fun battling monsters and supporting each other.", "partyOnText": "Joined a Party with at least four people! Enjoy your increased accountability as you unite with your friends to vanquish your foes!", - "groupIdRequired": "\"groupId\" must be a valid UUID", "groupNotFound": "Group not found or you don't have access.", "groupTypesRequired": "You must supply a valid \"type\" query string.", "questLeaderCannotLeaveGroup": "You cannot leave your Party when you have started a quest. Abort the quest first.", @@ -220,8 +219,6 @@ "memberCannotRemoveYourself": "You cannot remove yourself!", "groupMemberNotFound": "User not found among group's members", "mustBeGroupMember": "Must be member of the group.", - "keepOrRemoveAll": "req.query.keep must be either \"keep-all\" or \"remove-all\"", - "keepOrRemove": "req.query.keep must be either \"keep\" or \"remove\"", "canOnlyInviteEmailUuid": "Can only invite using uuids or emails.", "inviteMissingEmail": "Missing email address in invite.", "inviteMissingUuid": "Missing user id in invite", @@ -328,7 +325,6 @@ "cantDeleteAssignedGroupTasks": "Can't delete group tasks that are assigned to you.", "confirmGuildPlanCreation": "Create this group?", "onlyGroupLeaderCanInviteToGroupPlan": "Only the group leader can invite users to a group with a subscription.", - "remainOrLeaveChallenges": "req.query.keep must be either 'remain-in-challenges' or 'leave-challenges'", "paymentDetails": "Payment Details", "aboutToJoinCancelledGroupPlan": "You are about to join a group with a canceled plan. You will NOT receive a free subscription.", "cannotChangeLeaderWithActiveGroupPlan": "You can not change the leader while the group has an active plan.", diff --git a/website/common/locales/en/npc.json b/website/common/locales/en/npc.json index ee6ed35624..8e5651d04e 100644 --- a/website/common/locales/en/npc.json +++ b/website/common/locales/en/npc.json @@ -82,14 +82,8 @@ "ianBrokenText": "Welcome to the Quest Shop... Here you can use Quest Scrolls to battle monsters with your friends... Be sure to check out our fine array of Quest Scrolls for purchase on the right...", "featuredQuests": "Featured Quests!", - "missingKeyParam": "\"req.params.key\" is required.", - "itemNotFound": "Item \"<%= key %>\" not found.", "cannotBuyItem": "You can't buy this item.", - "missingTypeKeyEquip": "\"key\" and \"type\" are required parameters.", - "missingPetFoodFeed": "\"pet\" and \"food\" are required parameters.", "invalidPetName": "Invalid pet name supplied.", - "missingEggHatchingPotionHatch": "\"egg\" and \"hatchingPotion\" are required parameters.", - "invalidTypeEquip": "\"type\" must be one of 'equipped', 'pet', 'mount', 'costume'.", "mustPurchaseToSet": "Must purchase <%= val %> to set it on <%= key %>.", "typeRequired": "Type is required", "positiveAmountRequired": "Positive amount is required", diff --git a/website/common/locales/en/quests.json b/website/common/locales/en/quests.json index 0bfac41b6c..5c09433384 100644 --- a/website/common/locales/en/quests.json +++ b/website/common/locales/en/quests.json @@ -96,7 +96,6 @@ "questInvitationDoesNotExist": "No quest invitation has been sent out yet.", "questInviteNotFound": "No quest invitation found.", "guildQuestsNotSupported": "Guilds cannot be invited on quests.", - "questNotFound": "Quest \"<%= key %>\" not found.", "questNotOwned": "You don't own that quest scroll.", "questNotGoldPurchasable": "Quest \"<%= key %>\" is not a Gold-purchasable quest.", "questLevelTooHigh": "You must be level <%= level %> to begin this quest.", diff --git a/website/common/locales/en/spells.json b/website/common/locales/en/spells.json index 773e3301ba..d67816a19a 100644 --- a/website/common/locales/en/spells.json +++ b/website/common/locales/en/spells.json @@ -72,7 +72,6 @@ "spellSpecialSandText": "Sand", "spellSpecialSandNotes": "Reverse the spell that made you a sea star.", - "spellNotFound": "Skill \"<%= spellId %>\" not found.", "partyNotFound": "Party not found", "targetIdUUID": "\"targetId\" must be a valid User ID.", "challengeTasksNoCast": "Casting a skill on challenge tasks is not allowed.", diff --git a/website/common/locales/en/subscriber.json b/website/common/locales/en/subscriber.json index 948f4c9852..6095d37471 100644 --- a/website/common/locales/en/subscriber.json +++ b/website/common/locales/en/subscriber.json @@ -176,12 +176,6 @@ "invalidCoupon": "Invalid coupon code.", "couponUsed": "Coupon code already used.", "couponCodeRequired": "The coupon code is required.", - "eventRequired": "\"req.params.event\" is required.", - "countRequired": "\"req.query.count\" is required.", - "missingPaymentId": "Missing req.query.paymentId", - "missingCustomerId": "Missing req.query.customerId", - "missingPaypalBlock": "Missing req.session.paypalBlock", - "missingSubKey": "Missing req.query.sub", "paypalCanceled": "Your subscription has been canceled", "earnGemsMonthly": "Earn up to **<%= cap %> Gems** per month", "receiveMysticHourglass": "Receive a Mystic Hourglass!", diff --git a/website/common/locales/en/tasks.json b/website/common/locales/en/tasks.json index 9990119356..afaba0032a 100644 --- a/website/common/locales/en/tasks.json +++ b/website/common/locales/en/tasks.json @@ -145,7 +145,6 @@ "rewardHelp3": "Special equipment will appear here during World Events.", "rewardHelp4": "Don't be afraid to set custom Rewards! Check out some samples here.", "clickForHelp": "Click for help", - "taskIdRequired": "\"taskId\" must be a valid UUID.", "taskAliasAlreadyUsed": "Task alias already used on another task.", "taskNotFound": "Task not found.", "invalidTaskType": "Task type must be one of \"habit\", \"daily\", \"todo\", \"reward\".", diff --git a/website/common/script/ops/buy/buy.js b/website/common/script/ops/buy/buy.js index b8f56aab7b..938fa443af 100644 --- a/website/common/script/ops/buy/buy.js +++ b/website/common/script/ops/buy/buy.js @@ -1,4 +1,3 @@ -import i18n from '../../i18n'; import get from 'lodash/get'; import { BadRequest, @@ -11,6 +10,7 @@ import {BuyQuestWithGoldOperation} from './buyQuest'; import buySpecialSpell from './buySpecialSpell'; import purchaseOp from './purchase'; import hourglassPurchase from './hourglassPurchase'; +import apiMessages from '../../../../server/libs/apiMessages'; // @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 @@ -19,7 +19,7 @@ import hourglassPurchase from './hourglassPurchase'; module.exports = function buy (user, req = {}, analytics) { let key = get(req, 'params.key'); - if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); + if (!key) throw new BadRequest(apiMessages('missingKeyParam')); // @TODO: Slowly remove the need for key and use type instead // This should evenutally be the 'factory' function with vendor classes diff --git a/website/common/script/ops/buy/buyMarketGear.js b/website/common/script/ops/buy/buyMarketGear.js index 06fe881e48..478369bce0 100644 --- a/website/common/script/ops/buy/buyMarketGear.js +++ b/website/common/script/ops/buy/buyMarketGear.js @@ -13,6 +13,7 @@ import ultimateGear from '../../fns/ultimateGear'; import {removePinnedGearAddPossibleNewOnes} from '../pinnedGearUtils'; import { AbstractGoldItemOperation } from './abstractBuyOperation'; +import apiMessages from '../../../../server/libs/apiMessages'; export class BuyMarketGearOperation extends AbstractGoldItemOperation { constructor (user, req, analytics) { @@ -25,9 +26,10 @@ export class BuyMarketGearOperation extends AbstractGoldItemOperation { extractAndValidateParams (user, req) { let key = this.key = get(req, 'params.key'); - if (!key) throw new BadRequest(this.i18n('missingKeyParam')); + if (!key) throw new BadRequest(apiMessages('missingKeyParam')); + let item = content.gear.flat[key]; - if (!item) throw new NotFound(this.i18n('itemNotFound', {key})); + if (!item) throw new NotFound(apiMessages('itemNotFound', {key})); this.canUserPurchase(user, item); diff --git a/website/common/script/ops/buy/buyMysterySet.js b/website/common/script/ops/buy/buyMysterySet.js index 3a8b17a011..4ba3a53185 100644 --- a/website/common/script/ops/buy/buyMysterySet.js +++ b/website/common/script/ops/buy/buyMysterySet.js @@ -7,10 +7,11 @@ import { NotAuthorized, NotFound, } from '../../libs/errors'; +import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function buyMysterySet (user, req = {}, analytics) { let key = get(req, 'params.key'); - if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); + if (!key) throw new BadRequest(apiMessages('missingKeyParam')); if (!(user.purchased.plan.consecutive.trinkets > 0)) { throw new NotAuthorized(i18n.t('notEnoughHourglasses', req.language)); diff --git a/website/common/script/ops/buy/buyQuest.js b/website/common/script/ops/buy/buyQuest.js index e30513347b..a9cd2ff80c 100644 --- a/website/common/script/ops/buy/buyQuest.js +++ b/website/common/script/ops/buy/buyQuest.js @@ -5,6 +5,7 @@ import { } from '../../libs/errors'; import content from '../../content/index'; import get from 'lodash/get'; +import apiMessages from '../../../../server/libs/apiMessages'; import {AbstractGoldItemOperation} from './abstractBuyOperation'; @@ -30,7 +31,7 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation { extractAndValidateParams (user, req) { let key = this.key = get(req, 'params.key'); - if (!key) throw new BadRequest(this.i18n('missingKeyParam')); + if (!key) throw new BadRequest(apiMessages('missingKeyParam')); if (key === 'lostMasterclasser1' && !this.userAbleToStartMasterClasser(user)) { throw new NotAuthorized(this.i18n('questUnlockLostMasterclasser')); @@ -38,7 +39,7 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation { let item = content.quests[key]; - if (!item) throw new NotFound(this.i18n('questNotFound', {key})); + if (!item) throw new NotFound(apiMessages('questNotFound', {key})); if (!(item.category === 'gold' && item.goldValue)) { throw new NotAuthorized(this.i18n('questNotGoldPurchasable', {key})); diff --git a/website/common/script/ops/buy/buySpecialSpell.js b/website/common/script/ops/buy/buySpecialSpell.js index d6a8492c81..09d012d28a 100644 --- a/website/common/script/ops/buy/buySpecialSpell.js +++ b/website/common/script/ops/buy/buySpecialSpell.js @@ -8,15 +8,16 @@ import { NotAuthorized, NotFound, } from '../../libs/errors'; +import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function buySpecialSpell (user, req = {}, analytics) { let key = get(req, 'params.key'); let quantity = req.quantity || 1; - if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); + if (!key) throw new BadRequest(apiMessages('missingKeyParam')); let item = content.special[key]; - if (!item) throw new NotFound(i18n.t('spellNotFound', {spellId: key}, req.language)); + if (!item) throw new NotFound(apiMessages('spellNotFound', {spellId: key})); if (user.stats.gp < item.value * quantity) { throw new NotAuthorized(i18n.t('messageNotEnoughGold', req.language)); diff --git a/website/common/script/ops/buy/hourglassPurchase.js b/website/common/script/ops/buy/hourglassPurchase.js index d9afc4b440..4e80068d18 100644 --- a/website/common/script/ops/buy/hourglassPurchase.js +++ b/website/common/script/ops/buy/hourglassPurchase.js @@ -7,13 +7,14 @@ import { BadRequest, NotAuthorized, } from '../../libs/errors'; +import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function purchaseHourglass (user, req = {}, analytics) { let key = get(req, 'params.key'); - if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language)); + if (!key) throw new BadRequest(apiMessages('missingKeyParam')); let type = get(req, 'params.type'); - if (!type) throw new BadRequest(i18n.t('missingTypeParam', req.language)); + if (!type) throw new BadRequest(apiMessages('missingTypeParam')); if (!content.timeTravelStable[type]) { throw new NotAuthorized(i18n.t('typeNotAllowedHourglass', {allowedTypes: keys(content.timeTravelStable).toString()}, req.language)); diff --git a/website/common/script/ops/equip.js b/website/common/script/ops/equip.js index 02f13e935c..dca83d2f9c 100644 --- a/website/common/script/ops/equip.js +++ b/website/common/script/ops/equip.js @@ -6,6 +6,7 @@ import { BadRequest, } from '../libs/errors'; import get from 'lodash/get'; +import apiMessages from '../../../server/libs/apiMessages'; module.exports = function equip (user, req = {}) { // Being type a parameter followed by another parameter @@ -13,9 +14,9 @@ module.exports = function equip (user, req = {}) { let type = get(req, 'params.type', 'equipped'); let key = get(req, 'params.key'); - if (!key || !type) throw new BadRequest(i18n.t('missingTypeKeyEquip', req.language)); + if (!key || !type) throw new BadRequest(apiMessages('missingTypeKeyEquip')); if (['mount', 'pet', 'costume', 'equipped'].indexOf(type) === -1) { - throw new BadRequest(i18n.t('invalidTypeEquip', req.language)); + throw new BadRequest(apiMessages('invalidTypeEquip')); } let message; diff --git a/website/common/script/ops/feed.js b/website/common/script/ops/feed.js index cbe0e347f9..5d49e0e67e 100644 --- a/website/common/script/ops/feed.js +++ b/website/common/script/ops/feed.js @@ -6,6 +6,7 @@ import { NotAuthorized, NotFound, } from '../libs/errors'; +import apiMessages from '../../../server/libs/apiMessages'; function evolve (user, pet, req) { user.items.pets[pet.key] = -1; @@ -24,7 +25,7 @@ module.exports = function feed (user, req = {}) { let pet = get(req, 'params.pet'); let foodK = get(req, 'params.food'); - if (!pet || !foodK) throw new BadRequest(i18n.t('missingPetFoodFeed', req.language)); + if (!pet || !foodK) throw new BadRequest(apiMessages('missingPetFoodFeed')); pet = content.petInfo[pet]; diff --git a/website/common/script/ops/hatch.js b/website/common/script/ops/hatch.js index 15129e03f0..1efc41991e 100644 --- a/website/common/script/ops/hatch.js +++ b/website/common/script/ops/hatch.js @@ -6,13 +6,14 @@ import { NotAuthorized, NotFound, } from '../libs/errors'; +import apiMessages from '../../../server/libs/apiMessages'; module.exports = function hatch (user, req = {}) { let egg = get(req, 'params.egg'); let hatchingPotion = get(req, 'params.hatchingPotion'); if (!(egg && hatchingPotion)) { - throw new BadRequest(i18n.t('missingEggHatchingPotionHatch', req.language)); + throw new BadRequest(apiMessages('missingEggHatchingPotion')); } if (!(user.items.eggs[egg] > 0 && user.items.hatchingPotions[hatchingPotion] > 0)) { diff --git a/website/common/script/ops/stats/allocate.js b/website/common/script/ops/stats/allocate.js index 70b5944c92..707c34fcf1 100644 --- a/website/common/script/ops/stats/allocate.js +++ b/website/common/script/ops/stats/allocate.js @@ -7,12 +7,13 @@ import { NotAuthorized, } from '../../libs/errors'; import i18n from '../../i18n'; +import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function allocate (user, req = {}) { let stat = get(req, 'query.stat', 'str'); if (ATTRIBUTES.indexOf(stat) === -1) { - throw new BadRequest(i18n.t('invalidAttribute', {attr: stat}, req.language)); + throw new BadRequest(apiMessages('invalidAttribute', {attr: stat})); } if (user.stats.points > 0) { diff --git a/website/common/script/ops/stats/allocateBulk.js b/website/common/script/ops/stats/allocateBulk.js index f44800a813..d38b25c012 100644 --- a/website/common/script/ops/stats/allocateBulk.js +++ b/website/common/script/ops/stats/allocateBulk.js @@ -7,17 +7,18 @@ import { NotAuthorized, } from '../../libs/errors'; import i18n from '../../i18n'; +import apiMessages from '../../../../server/libs/apiMessages'; module.exports = function allocateBulk (user, req = {}) { const stats = get(req, 'body.stats'); - if (!stats) throw new BadRequest(i18n.t('statsObjectRequired', req.language)); + if (!stats) throw new BadRequest(apiMessages('statsObjectRequired')); const statKeys = Object.keys(stats); const invalidStats = statKeys.filter(statKey => { return ATTRIBUTES.indexOf(statKey) === -1; }); if (invalidStats.length > 0) { - throw new BadRequest(i18n.t('invalidAttribute', {attr: invalidStats.join(',')}, req.language)); + throw new BadRequest(apiMessages('invalidAttribute', {attr: invalidStats.join(',')})); } if (user.stats.points <= 0) { diff --git a/website/server/controllers/api-v3/challenges.js b/website/server/controllers/api-v3/challenges.js index 27b721f583..2e23cb2524 100644 --- a/website/server/controllers/api-v3/challenges.js +++ b/website/server/controllers/api-v3/challenges.js @@ -27,6 +27,7 @@ import { createChallenge, cleanUpTask, } from '../../libs/challenges'; +import apiMessages from '../../libs/apiMessages'; let api = {}; @@ -187,7 +188,7 @@ api.createChallenge = { async handler (req, res) { let user = res.locals.user; - req.checkBody('group', res.t('groupIdRequired')).notEmpty(); + req.checkBody('group', apiMessages('groupIdRequired')).notEmpty(); const validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -444,7 +445,7 @@ api.getGroupChallenges = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/chat.js b/website/server/controllers/api-v3/chat.js index df622ced54..1c0a495fde 100644 --- a/website/server/controllers/api-v3/chat.js +++ b/website/server/controllers/api-v3/chat.js @@ -18,6 +18,7 @@ import bannedWords from '../../libs/bannedWords'; import guildsAllowingBannedWords from '../../libs/guildsAllowingBannedWords'; import { getMatchesByWordArray } from '../../libs/stringUtils'; import bannedSlurs from '../../libs/bannedSlurs'; +import apiMessages from '../../libs/apiMessages'; const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => { return { email, canSend: true }; @@ -65,7 +66,7 @@ api.getChat = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -104,7 +105,7 @@ api.postChat = { let groupId = req.params.groupId; let chatUpdated; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); req.sanitize('message').trim(); req.checkBody('message', res.t('messageGroupChatBlankMessage')).notEmpty(); @@ -224,7 +225,7 @@ api.likeChat = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); req.checkParams('chatId', res.t('chatIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); @@ -317,7 +318,7 @@ api.clearChatFlags = { let groupId = req.params.groupId; let chatId = req.params.chatId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); req.checkParams('chatId', res.t('chatIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); @@ -390,7 +391,7 @@ api.seenChat = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -457,7 +458,7 @@ api.deleteChat = { let groupId = req.params.groupId; let chatId = req.params.chatId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); req.checkParams('chatId', res.t('chatIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); diff --git a/website/server/controllers/api-v3/coupon.js b/website/server/controllers/api-v3/coupon.js index 5fc0f4cbf1..02681698d6 100644 --- a/website/server/controllers/api-v3/coupon.js +++ b/website/server/controllers/api-v3/coupon.js @@ -7,6 +7,7 @@ import { ensureSudo } from '../../middlewares/ensureAccessRight'; import { model as Coupon } from '../../models/coupon'; import _ from 'lodash'; import couponCode from 'coupon-code'; +import apiMessages from '../../libs/apiMessages'; let api = {}; @@ -69,8 +70,8 @@ api.generateCoupons = { url: '/coupons/generate/:event', middlewares: [authWithHeaders(), ensureSudo], async handler (req, res) { - req.checkParams('event', res.t('eventRequired')).notEmpty(); - req.checkQuery('count', res.t('countRequired')).notEmpty().isNumeric(); + req.checkParams('event', apiMessages('eventRequired')).notEmpty(); + req.checkQuery('count', apiMessages('countRequired')).notEmpty().isNumeric(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js index f1264ca17c..9fd2bfb949 100644 --- a/website/server/controllers/api-v3/groups.js +++ b/website/server/controllers/api-v3/groups.js @@ -275,7 +275,7 @@ api.createGroupPlan = { * * @apiError (400) {BadRequest} groupTypesRequired Group types are required * @apiError (400) {BadRequest} guildsPaginateBooleanString Paginate query parameter must be a boolean (true or false) - * @apiError (400) {BadRequest} guildsPageInteger Page query parameter must be a positive integer + * @apiError (400) {BadRequest} queryPageInteger Page query parameter must be a positive integer * @apiError (400) {BadRequest} guildsOnlyPaginate Only public guilds support pagination * * @apiSuccess {Object[]} data An array of the requested groups (See /website/server/models/group.js) @@ -296,7 +296,7 @@ api.getGroups = { req.checkQuery('type', res.t('groupTypesRequired')).notEmpty(); // pagination options, can only be used with public guilds req.checkQuery('paginate').optional().isIn(['true', 'false'], apiMessages('guildsPaginateBooleanString')); - req.checkQuery('page').optional().isInt({min: 0}, apiMessages('guildsPageInteger')); + req.checkQuery('page').optional().isInt({min: 0}, apiMessages('queryPageInteger')); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -381,7 +381,7 @@ api.getGroup = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -439,7 +439,7 @@ api.updateGroup = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -503,7 +503,7 @@ api.joinGroup = { let user = res.locals.user; let inviter; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -673,7 +673,7 @@ api.rejectGroupInvite = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party' let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -747,10 +747,10 @@ api.leaveGroup = { middlewares: [authWithHeaders()], async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); // When removing the user from challenges, should we keep the tasks? - req.checkQuery('keep', res.t('keepOrRemoveAll')).optional().isIn(['keep-all', 'remove-all']); - req.checkBody('keepChallenges', res.t('remainOrLeaveChallenges')).optional().isIn(['remain-in-challenges', 'leave-challenges']); + req.checkQuery('keep', apiMessages('keepOrRemoveAll')).optional().isIn(['keep-all', 'remove-all']); + req.checkBody('keepChallenges', apiMessages('groupRemainOrLeaveChallenges')).optional().isIn(['remain-in-challenges', 'leave-challenges']); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -835,7 +835,7 @@ api.removeGroupMember = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); req.checkParams('memberId', res.t('userIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -1155,7 +1155,7 @@ api.inviteToGroup = { if (user.flags.chatRevoked) throw new NotAuthorized(res.t('cannotInviteWhenMuted')); - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); if (user.invitesSent >= MAX_EMAIL_INVITES_BY_USER) throw new NotAuthorized(res.t('inviteLimitReached', { techAssistanceEmail: TECH_ASSISTANCE_EMAIL })); diff --git a/website/server/controllers/api-v3/hall.js b/website/server/controllers/api-v3/hall.js index 5d836407b3..adfccf7dc9 100644 --- a/website/server/controllers/api-v3/hall.js +++ b/website/server/controllers/api-v3/hall.js @@ -5,6 +5,7 @@ import { NotFound, } from '../../libs/errors'; import _ from 'lodash'; +import apiMessages from '../../libs/apiMessages'; let api = {}; @@ -62,7 +63,7 @@ api.getPatrons = { url: '/hall/patrons', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkQuery('page', res.t('pageMustBeNumber')).optional().isNumeric(); + req.checkQuery('page').optional().isInt({min: 0}, apiMessages('queryPageInteger')); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/quests.js b/website/server/controllers/api-v3/quests.js index 7ae92b1b3a..d9c39b37cd 100644 --- a/website/server/controllers/api-v3/quests.js +++ b/website/server/controllers/api-v3/quests.js @@ -17,6 +17,7 @@ import { } from '../../libs/email'; import common from '../../../common'; import { sendNotification as sendPushNotification } from '../../libs/pushNotifications'; +import apiMessages from '../../libs/apiMessages'; const questScrolls = common.content.quests; @@ -60,7 +61,7 @@ api.inviteToQuest = { let questKey = req.params.questKey; let quest = questScrolls[questKey]; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -69,7 +70,7 @@ api.inviteToQuest = { if (!group) throw new NotFound(res.t('groupNotFound')); if (group.type !== 'party') throw new NotAuthorized(res.t('guildQuestsNotSupported')); - if (!quest) throw new NotFound(res.t('questNotFound', { key: questKey })); + if (!quest) throw new NotFound(apiMessages('questNotFound', { key: questKey })); if (!user.items.quests[questKey]) throw new NotAuthorized(res.t('questNotOwned')); if (user.stats.lvl < quest.lvl) throw new NotAuthorized(res.t('questLevelTooHigh', { level: quest.lvl })); if (group.quest.key) throw new NotAuthorized(res.t('questAlreadyUnderway')); @@ -172,7 +173,7 @@ api.acceptQuest = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -231,7 +232,7 @@ api.rejectQuest = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -294,7 +295,7 @@ api.forceStart = { async handler (req, res) { let user = res.locals.user; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -356,7 +357,7 @@ api.cancelQuest = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -408,7 +409,7 @@ api.abortQuest = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -466,7 +467,7 @@ api.leaveQuest = { let user = res.locals.user; let groupId = req.params.groupId; - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js index 348a9e6870..7497761565 100644 --- a/website/server/controllers/api-v3/tasks.js +++ b/website/server/controllers/api-v3/tasks.js @@ -23,6 +23,7 @@ import common from '../../../common'; import _ from 'lodash'; import logger from '../../libs/logger'; import moment from 'moment'; +import apiMessages from '../../libs/apiMessages'; const MAX_SCORE_NOTES_LENGTH = 256; @@ -429,7 +430,7 @@ api.updateTask = { let user = res.locals.user; let challenge; - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -710,7 +711,7 @@ api.moveTask = { url: '/tasks/:taskId/move/to/:position', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); req.checkParams('position', res.t('positionRequired')).notEmpty().isNumeric(); let validationErrors = req.validationErrors(); @@ -783,7 +784,7 @@ api.addChecklistItem = { let challenge; let group; - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -841,7 +842,7 @@ api.scoreCheckListItem = { async handler (req, res) { let user = res.locals.user; - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -891,7 +892,7 @@ api.updateChecklistItem = { let challenge; let group; - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -956,7 +957,7 @@ api.removeChecklistItem = { let challenge; let group; - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -1017,7 +1018,7 @@ api.addTagToTask = { async handler (req, res) { let user = res.locals.user; - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); let userTags = user.tags.map(tag => tag.id); req.checkParams('tagId', res.t('tagIdRequired')).notEmpty().isUUID().isIn(userTags); @@ -1066,7 +1067,7 @@ api.removeTagFromTask = { async handler (req, res) { let user = res.locals.user; - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); req.checkParams('tagId', res.t('tagIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); @@ -1110,7 +1111,7 @@ api.unlinkAllTasks = { middlewares: [authWithHeaders()], async handler (req, res) { req.checkParams('challengeId', res.t('challengeIdRequired')).notEmpty().isUUID(); - req.checkQuery('keep', res.t('keepOrRemoveAll')).notEmpty().isIn(['keep-all', 'remove-all']); + req.checkQuery('keep', apiMessages('keepOrRemoveAll')).notEmpty().isIn(['keep-all', 'remove-all']); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -1176,8 +1177,8 @@ api.unlinkOneTask = { url: '/tasks/unlink-one/:taskId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); - req.checkQuery('keep', res.t('keepOrRemove')).notEmpty().isIn(['keep', 'remove']); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); + req.checkQuery('keep', apiMessages('keepOrRemove')).notEmpty().isIn(['keep', 'remove']); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js index 45eb8839da..7cd64e4ef8 100644 --- a/website/server/controllers/api-v3/tasks/groups.js +++ b/website/server/controllers/api-v3/tasks/groups.js @@ -12,6 +12,7 @@ import { getTasks, moveTask, } from '../../../libs/taskManager'; +import apiMessages from '../../../libs/apiMessages'; let requiredGroupFields = '_id leader tasksOrder name'; let types = Tasks.tasksTypes.map(type => `${type}s`); @@ -40,7 +41,7 @@ api.createGroupTasks = { url: '/tasks/group/:groupId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); if (reqValidationErrors) throw reqValidationErrors; @@ -84,7 +85,7 @@ api.getGroupTasks = { url: '/tasks/group/:groupId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty().isUUID(); req.checkQuery('type', res.t('invalidTasksType')).optional().isIn(types); let validationErrors = req.validationErrors(); @@ -117,7 +118,7 @@ api.groupMoveTask = { url: '/group-tasks/:taskId/move/to/:position', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty(); req.checkParams('position', res.t('positionRequired')).notEmpty().isNumeric(); let reqValidationErrors = req.validationErrors(); @@ -168,7 +169,7 @@ api.assignTask = { url: '/tasks/:taskId/assign/:assignedUserId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); req.checkParams('assignedUserId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -226,7 +227,7 @@ api.unassignTask = { url: '/tasks/:taskId/unassign/:assignedUserId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); req.checkParams('assignedUserId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -276,7 +277,7 @@ api.approveTask = { url: '/tasks/:taskId/approve/:userId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); req.checkParams('userId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -372,7 +373,7 @@ api.taskNeedsWork = { url: '/tasks/:taskId/needs-work/:userId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID(); + req.checkParams('taskId', apiMessages('taskIdRequired')).notEmpty().isUUID(); req.checkParams('userId', res.t('userIdRequired')).notEmpty().isUUID(); let reqValidationErrors = req.validationErrors(); @@ -469,7 +470,7 @@ api.getGroupApprovals = { url: '/approvals/group/:groupId', middlewares: [authWithHeaders()], async handler (req, res) { - req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID(); + req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty().isUUID(); let validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/user/spells.js b/website/server/controllers/api-v3/user/spells.js index 35415137eb..98cab96a74 100644 --- a/website/server/controllers/api-v3/user/spells.js +++ b/website/server/controllers/api-v3/user/spells.js @@ -14,6 +14,7 @@ import { castPartySpell, castUserSpell, } from '../../../libs/spells'; +import apiMessages from '../../../libs/apiMessages'; const partyMembersFields = 'profile.name stats achievements items.special'; @@ -85,7 +86,7 @@ api.castSpell = { let klass = common.content.spells.special[spellId] ? 'special' : user.stats.class; let spell = common.content.spells[klass][spellId]; - if (!spell) throw new NotFound(res.t('spellNotFound', {spellId})); + if (!spell) throw new NotFound(apiMessages('spellNotFound', {spellId})); if (spell.mana > user.stats.mp) throw new NotAuthorized(res.t('notEnoughMana')); if (spell.value > user.stats.gp && !spell.previousPurchase) throw new NotAuthorized(res.t('messageNotEnoughGold')); if (spell.lvl > user.stats.lvl) throw new NotAuthorized(res.t('spellLevelTooHigh', {level: spell.lvl})); diff --git a/website/server/controllers/top-level/payments/paypal.js b/website/server/controllers/top-level/payments/paypal.js index 36b7b7a189..44a130256d 100644 --- a/website/server/controllers/top-level/payments/paypal.js +++ b/website/server/controllers/top-level/payments/paypal.js @@ -8,8 +8,7 @@ import { import { BadRequest, } from '../../../libs/errors'; - -const i18n = shared.i18n; +import apiMessages from '../../../libs/apiMessages'; let api = {}; @@ -54,8 +53,8 @@ api.checkoutSuccess = { let gift = req.session.gift ? JSON.parse(req.session.gift) : undefined; delete req.session.gift; - if (!paymentId) throw new BadRequest(i18n.t('missingPaymentId')); - if (!customerId) throw new BadRequest(i18n.t('missingCustomerId')); + if (!paymentId) throw new BadRequest(apiMessages('missingPaymentId')); + if (!customerId) throw new BadRequest(apiMessages('missingCustomerId')); await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId}); @@ -78,7 +77,7 @@ api.subscribe = { url: '/paypal/subscribe', middlewares: [authWithUrl], async handler (req, res) { - if (!req.query.sub) throw new BadRequest(i18n.t('missingSubKey')); + if (!req.query.sub) throw new BadRequest(apiMessages('missingSubKey')); let sub = shared.content.subscriptionBlocks[req.query.sub]; let coupon = req.query.coupon; @@ -109,7 +108,7 @@ api.subscribeSuccess = { async handler (req, res) { let user = res.locals.user; - if (!req.session.paypalBlock) throw new BadRequest(i18n.t('missingPaypalBlock')); + if (!req.session.paypalBlock) throw new BadRequest(apiMessages('missingPaypalBlock')); let block = shared.content.subscriptionBlocks[req.session.paypalBlock]; let groupId = req.session.groupId; diff --git a/website/server/libs/apiMessages.js b/website/server/libs/apiMessages.js index f368228dbb..cd6dd7ed54 100644 --- a/website/server/libs/apiMessages.js +++ b/website/server/libs/apiMessages.js @@ -5,12 +5,38 @@ import _ from 'lodash'; // When this file grows, it can be split into multiple ones. const messages = { + taskIdRequired: 'req.params.taskId must contain a task id.', + keepOrRemove: 'req.query.keep must be either "keep" or "remove".', + keepOrRemoveAll: 'req.query.keep must be either "keep-all" or "remove-all".', + invalidAttribute: '"<%= attr %>" is not a valid Stat.', + + statsObjectRequired: '"stats" update is required', + queryPageInteger: 'req.query.page must be an integer greater than or equal to 0.', + + missingTypeParam: '"req.params.type" is required.', + missingKeyParam: '"req.params.key" is required.', + itemNotFound: 'Item "<%= key %>" not found.', + questNotFound: 'Quest "<%= key %>" not found.', + spellNotFound: 'Skill "<%= spellId %>" not found.', + missingTypeKeyEquip: '"key" and "type" are required parameters.', + invalidTypeEquip: '"type" must be one of "equipped", "pet", "mount", "costume"', + missingPetFoodFeed: '"pet" and "food" are required parameters.', + missingEggHatchingPotion: '"egg" and "hatchingPotion" are required parameters.', + guildsOnlyPaginate: 'Only public guilds support pagination.', guildsPaginateBooleanString: 'req.query.paginate must be a boolean string.', - guildsPageInteger: 'req.query.page must be an integer greater than or equal to 0.', groupIdRequired: 'req.params.groupId must contain a groupId.', + groupRemainOrLeaveChallenges: 'req.query.keep must be either "remain-in-challenges" or "leave-challenges"', managerIdRequired: 'req.body.managerId must contain a user ID.', - noSudoAccess: 'You don\'t have sudo access', + noSudoAccess: 'You don\'t have sudo access.', + + eventRequired: '"req.params.event" is required.', + countRequired: '"req.query.count" is required.', + + missingPaymentId: 'Missing "req.query.paymentId"', + missingCustomerId: 'Missing "req.query.customerId"', + missingPaypalBlock: 'Missing "req.session.paypalBlock"', + missingSubKey: 'Missing "req.query.sub"', }; export default function (msgKey, vars = {}) { diff --git a/website/server/libs/chatReporting/groupChatReporter.js b/website/server/libs/chatReporting/groupChatReporter.js index fc2b61d88d..583a9f77ff 100644 --- a/website/server/libs/chatReporting/groupChatReporter.js +++ b/website/server/libs/chatReporting/groupChatReporter.js @@ -9,6 +9,7 @@ import { import { getGroupUrl, sendTxn } from '../email'; import slack from '../slack'; import { model as Group } from '../../models/group'; +import apiMessages from '../apiMessages'; const COMMUNITY_MANAGER_EMAIL = nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL'); const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => { @@ -24,7 +25,7 @@ export default class GroupChatReporter extends ChatReporter { } async validate () { - this.req.checkParams('groupId', this.res.t('groupIdRequired')).notEmpty(); + this.req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); this.req.checkParams('chatId', this.res.t('chatIdRequired')).notEmpty(); let validationErrors = this.req.validationErrors(); diff --git a/website/server/models/webhook.js b/website/server/models/webhook.js index 7398592080..bf4210c8bc 100644 --- a/website/server/models/webhook.js +++ b/website/server/models/webhook.js @@ -6,6 +6,7 @@ import {v4 as uuid} from 'uuid'; import _ from 'lodash'; import { BadRequest } from '../libs/errors'; import nconf from 'nconf'; +import apiMessages from '../libs/apiMessages'; const IS_PRODUCTION = nconf.get('IS_PROD'); const Schema = mongoose.Schema; @@ -79,7 +80,7 @@ schema.methods.formatOptions = function formatOptions (res) { this.options = _.pick(this.options, 'groupId'); if (!validator.isUUID(String(this.options.groupId))) { - throw new BadRequest(res.t('groupIdRequired')); + throw new BadRequest(apiMessages('groupIdRequired')); } } };