diff --git a/migrations/archive/2023/20230808_guild_gems_fix.js b/migrations/archive/2023/20230808_guild_gems_fix.js new file mode 100644 index 0000000000..e51bfc3086 --- /dev/null +++ b/migrations/archive/2023/20230808_guild_gems_fix.js @@ -0,0 +1,62 @@ +/* eslint-disable no-console */ +import { model as User } from '../../../website/server/models/user'; +import { TransactionModel as Transaction } from '../../../website/server/models/transaction'; + +const transactionsPerRun = 500; +const progressCount = 1000; +const transactionsQuery = { + transactionType: 'create_guild', + amount: { $gt: 0 }, +}; + +let count = 0; +async function updateTransaction (transaction) { + count++; + if (count % progressCount === 0) { + console.warn(`${count} ${transaction._id}`); + } + + const leader = await User + .findOne({ _id: transaction.userId }) + .select({ _id: true }) + .exec(); + + if (!leader) { + return console.warn(`User not found for transaction ${transaction._id}`); + } + + return leader.updateOne( + { $inc: { balance: transaction.amount }}, + ).exec(); +} + +export default async function processTransactions () { + const transactionFields = { + _id: 1, + userId: 1, + currency: 1, + amount: 1, + }; + + while (true) { // eslint-disable-line no-constant-condition + const foundTransactions = await Transaction // eslint-disable-line no-await-in-loop + .find(transactionsQuery) + .limit(transactionsPerRun) + .sort({ _id: 1 }) + .select(transactionFields) + .lean() + .exec(); + + if (foundTransactions.length === 0) { + console.warn('All appropriate transactions found and modified.'); + console.warn(`\n${count} transactions processed\n`); + break; + } else { + transactionsQuery._id = { + $gt: foundTransactions[foundTransactions.length - 1], + }; + } + + await Promise.all(foundTransactions.map(txn => updateTransaction(txn))); // eslint-disable-line no-await-in-loop + } +}; diff --git a/migrations/archive/2023/20230801_veteran_pet_ladder.js b/migrations/archive/2023/20230808_veteran_pet_ladder.js similarity index 97% rename from migrations/archive/2023/20230801_veteran_pet_ladder.js rename to migrations/archive/2023/20230808_veteran_pet_ladder.js index 23b87ec215..fa64363cff 100644 --- a/migrations/archive/2023/20230801_veteran_pet_ladder.js +++ b/migrations/archive/2023/20230808_veteran_pet_ladder.js @@ -1,5 +1,5 @@ /* eslint-disable no-console */ -const MIGRATION_NAME = '20230801_veteran_pet_ladder'; +const MIGRATION_NAME = '20230808_veteran_pet_ladder'; import { model as User } from '../../../website/server/models/user'; const progressCount = 1000; @@ -110,7 +110,7 @@ async function updateUser (user) { export default async function processUsers () { let query = { migration: {$ne: MIGRATION_NAME}, - 'auth.timestamps.loggedin': { $gt: new Date('2023-07-01') }, + // 'auth.timestamps.loggedin': { $gt: new Date('2023-07-08') }, }; const fields = { diff --git a/package-lock.json b/package-lock.json index 0f21a3fa64..591fecb9d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "habitica", - "version": "5.0.0", + "version": "5.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 676450c215..641249e44f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "habitica", "description": "A habit tracker app which treats your goals like a Role Playing Game.", - "version": "5.0.0", + "version": "5.1.0", "main": "./website/server/index.js", "dependencies": { "@babel/core": "^7.22.5", diff --git a/website/client/src/router/index.js b/website/client/src/router/index.js index b9921675d2..7b4ce20bfe 100644 --- a/website/client/src/router/index.js +++ b/website/client/src/router/index.js @@ -460,6 +460,21 @@ router.beforeEach(async (to, from, next) => { }); } + // Redirect from Guild link to Group Plan where possible + if (to.name === 'guild') { + await store.dispatch('guilds:getGroupPlans'); + const { groupPlans } = store.state; + const groupPlanIds = groupPlans.data.map(groupPlan => groupPlan._id); + if (groupPlanIds.indexOf(to.params.groupId) !== -1) { + return next({ + name: 'groupPlanDetailInformation', + params: { + groupId: to.params.groupId, + }, + }); + } + } + // Redirect old challenge urls if (to.hash.indexOf('#/options/groups/challenges/') !== -1) { const splits = to.hash.split('/'); diff --git a/website/common/locales/en/backgrounds.json b/website/common/locales/en/backgrounds.json index 34331adc45..828863293c 100644 --- a/website/common/locales/en/backgrounds.json +++ b/website/common/locales/en/backgrounds.json @@ -899,6 +899,15 @@ "backgroundBoardwalkIntoSunsetText": "Boardwalk into the Sunset", "backgroundBoardwalkIntoSunsetNotes": "Stroll on a Boardwalk into the Sunset.", + "backgrounds082023": "SET 111: Released August 2023", + "backgroundBonsaiCollectionText": "Bonsai Collection", + "backgroundBonsaiCollectionNotes": "Admire a gorgeous Bonsai Collection.", + "backgroundDreamyIslandText": "Dreamy Island", + "backgroundDreamyIslandNotes": "Enjoy the scenery on a Dreamy Island.", + "backgroundRockGardenText": "Rock Garden", + "backgroundRockGardenNotes": "Relax in a Rock Garden.", + + "timeTravelBackgrounds": "Steampunk Backgrounds", "backgroundAirshipText": "Airship", "backgroundAirshipNotes": "Become a sky sailor on board your very own Airship.", diff --git a/website/common/locales/en/gear.json b/website/common/locales/en/gear.json index 7cf4f468e7..f742d32c1d 100644 --- a/website/common/locales/en/gear.json +++ b/website/common/locales/en/gear.json @@ -1489,6 +1489,8 @@ "armorArmoireDiagonalRainbowShirtNotes": "A splash of color with a dash of style. Be joyful! Increases Constitution and Perception by <%= attrs %> each. Enchanted Armoire: Rainbow Set (Item 2 of 2).", "armorArmoireAdmiralsUniformText": "Admiral's Uniform", "armorArmoireAdmiralsUniformNotes": "We salute you! This naval uniform signals that you’re ready to take command of your tasks as well as a ship. Increases Constitution and Strength by <%= attrs %> each. Enchanted Armoire: Admiral’s Set (Item 2 of 2).", + "armorArmoireKarateGiText": "Karate Gi", + "armorArmoireKarateGiNotes": "This lightweight karate uniform is perfect for practice or competition. Increases Strength by <%= str %>. Enchanted Armoire: Karate Set (Item 1 of 10).", "headgear": "helm", "headgearCapitalized": "Headgear", @@ -2873,6 +2875,24 @@ "bodyArmoireLifeguardWhistleNotes": "Call that misbehaving habit to order! It should know the rules! Increases Intelligence by <%= int %>. Enchanted Armoire: Lifeguard Set (Item 3 of 3).", "bodyArmoireClownsBowtieText": "Clown's Bow-Tie", "bodyArmoireClownsBowtieNotes": "A nice bow-tie is no joking matter, even for a clown. Increases Strength, Intelligence, Constitution and Perception by <%= attrs %> each. Enchanted Armoire: Clown Set (Item 5 of 5).", + "bodyArmoireKarateWhiteBeltText": "White Belt", + "bodyArmoireKarateWhiteBeltNotes": "This lowest level belt is for those who are just beginning their journey. Increases Intelligence by <%= int %>. Enchanted Armoire: Karate Set (Item 2 of 10).", + "bodyArmoireKarateYellowBeltText": "Yellow Belt", + "bodyArmoireKarateYellowBeltNotes": "This belt is for beginners who have learned the basics. Increases Perception by <%= per %>. Enchanted Armoire: Karate Set (Item 3 of 10).", + "bodyArmoireKarateOrangeBeltText": "Orange Belt", + "bodyArmoireKarateOrangeBeltNotes": "This belt is for those who have grown and mastered the beginner level. Increases Constitution by <%= con %>. Enchanted Armoire: Karate Set (Item 4 of 10).", + "bodyArmoireKarateGreenBeltText": "Green Belt", + "bodyArmoireKarateGreenBeltNotes": "This belt is for those at the intermediate level learning to strengthen their skills. Increases Strength by <%= str %>. Enchanted Armoire: Karate Set (Item 5 of 10).", + "bodyArmoireKarateBlueBeltText": "Blue Belt", + "bodyArmoireKarateBlueBeltNotes": "This belt is for those who are learning more and developing their minds and bodies. Increases Constitution by <%= con %>. Enchanted Armoire: Karate Set (Item 6 of 10).", + "bodyArmoireKaratePurpleBeltText": "Purple Belt", + "bodyArmoireKaratePurpleBeltNotes": "This belt is for those ready to embark toward advanced study. Increases Constitution by <%= con %>. Enchanted Armoire: Karate Set (Item 7 of 10).", + "bodyArmoireKarateRedBeltText": "Red Belt", + "bodyArmoireKarateRedBeltNotes": "This belt is for those who have learned to be cautious in their practice. Increases Perception by <%= per %>. Enchanted Armoire: Karate Set (Item 8 of 10).", + "bodyArmoireKarateBrownBeltText": "Brown Belt", + "bodyArmoireKarateBrownBeltNotes": "This belt is for those whose techniques and skills have matured. Increases Strength by <%= str %>. Enchanted Armoire: Karate Set (Item 9 of 10).", + "bodyArmoireKarateBlackBeltText": "Black Belt", + "bodyArmoireKarateBlackBeltNotes": "This highest level belt is for those who seek a deeper understanding and can pass their knowledge on to others. Increases Intelligence by <%= int %>. Enchanted Armoire: Karate Set (Item 10 of 10).", "headAccessory": "Head Accessory", "accessories": "Accessories", diff --git a/website/common/script/content/appearance/backgrounds.js b/website/common/script/content/appearance/backgrounds.js index e924af759a..c42f28cdd7 100644 --- a/website/common/script/content/appearance/backgrounds.js +++ b/website/common/script/content/appearance/backgrounds.js @@ -570,6 +570,11 @@ const backgrounds = { colorful_coral: { }, boardwalk_into_sunset: { }, }, + backgrounds082023: { + bonsai_collection: { }, + dreamy_island: { }, + rock_garden: { }, + }, eventBackgrounds: { birthday_bash: { price: 0, diff --git a/website/common/script/content/gear/sets/armoire.js b/website/common/script/content/gear/sets/armoire.js index 8edeb5bc1c..6706b8ddd6 100644 --- a/website/common/script/content/gear/sets/armoire.js +++ b/website/common/script/content/gear/sets/armoire.js @@ -439,6 +439,10 @@ const armor = { str: 7, set: 'admiralsSet', }, + karateGi: { + str: 10, + set: 'karateSet', + }, }; const body = { @@ -458,6 +462,42 @@ const body = { per: 2, set: 'clown', }, + karateYellowBelt: { + per: 3, + set: 'karateSet', + }, + karateWhiteBelt: { + int: 3, + set: 'karateSet', + }, + karateRedBelt: { + per: 3, + set: 'karateSet', + }, + karatePurpleBelt: { + con: 3, + set: 'karateSet', + }, + karateOrangeBelt: { + con: 3, + set: 'karateSet', + }, + karateGreenBelt: { + str: 3, + set: 'karateSet', + }, + karateBrownBelt: { + str: 3, + set: 'karateSet', + }, + karateBlueBelt: { + con: 3, + set: 'karateSet', + }, + karateBlackBelt: { + int: 3, + set: 'karateSet', + }, }; const eyewear = {