From 74ba55c20b28c19bcc6f5a7d6938b5a59fdfb116 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Sat, 17 Feb 2018 18:11:24 +0100 Subject: [PATCH] Upgrade tests tools and lint migrations and scripts (part 2) (#9998) * upgrade gulp-babel * upgrade babel-eslint * upgrade eslint-friendly-formatter * start upgrading chai * start to upgrade eslint * restore skipped tests * start to upgrqde monk * fix linting and remove unused file * fix mocha notifications, and common tests * fix unit tests * start to fix initrgration tests * more integration tests fixes * upgrade monk to latest version * lint /scripts * migrations: start moving to /archive unused migrations and run eslint with --fix * lint migrations * fix more integration tests * fix test --- .eslintignore | 11 +- migrations/.eslintrc | 7 + migrations/20130128_add_missing_crons.js | 5 - .../20130128_merge_completed_todo_ids.js | 15 - .../20130129_add_missing_preferences.js | 5 - .../20130204_user_public_private_paths.js | 102 --- migrations/20130208_idLists_to_typeIds.js | 19 - migrations/20130208_user_customizations.js | 20 - migrations/20130307_exp_overflow.js | 39 - migrations/20130307_normalize_algo_values.js | 47 -- migrations/20130307_remove_duff_histories.js | 28 - migrations/20130326_migrate_pets.js | 98 --- migrations/20130327_apply_tokens.js | 110 --- migrations/20130503_max_gear_achievement.js | 22 - migrations/20130508_add_backer_pets.js | 1 - migrations/20130602_survey_rewards.js | 31 - .../20130612_survey_rewards_individual.js | 9 - migrations/20130615_add_extra_indexes.js | 4 - migrations/20130908_cleanup_corrupt_tags.js | 16 - migrations/20131022_purchased_and_newStuff.js | 5 - migrations/20131022_restore_ads.js | 12 - migrations/20131102_restore_task_ids.js | 25 - migrations/20131104_remove_invalid_dues.js | 7 - migrations/20131105_remove_history_ids.js | 21 - migrations/20131108_add_gems_for_contribs.js | 4 - migrations/20131111_task_NaN.js | 15 - .../20131114_migrate_websites_to_blurb.js | 14 - .../20131115_update_gear_preferences.js | 10 - migrations/20131117_fix_task_types.js | 18 - migrations/20131117_remove_undefined_pets.js | 12 - migrations/20131122_deleted_tags.js | 13 - .../20131123_set_default_party_order.js | 8 - migrations/20131126_clean_dayStart.js | 5 - migrations/20131126_turkey_pet.js | 1 - migrations/20131127_restore_dayStart.js | 38 - migrations/20131221_restore_NaN_history.js | 51 -- migrations/20131225_restore_streaks.js | 38 - ...20140119_task_creation_completion_dates.js | 8 - migrations/20140130_birthdayEnd.js | 1 - migrations/20140130_birthdayStart.js | 12 - migrations/20140220_challenge_memberCount.js | 3 - migrations/20140301_missing_mysteries.js | 14 - migrations/20140610_missing_backer_mount.js | 1 - migrations/20140712_wiped_quest_membership.js | 11 - ...20140803_remove_undefined_notifications.js | 13 - ...0140829_change_headAccessory_to_eyewear.js | 81 -- ...ncrease_gems_for_previous_contributions.js | 131 ---- .../20140914_upgrade_admin_contrib_tiers.js | 79 -- migrations/20140922_free_candy.js | 18 - migrations/20141006_jackolantern_pet.js | 1 - migrations/20141126_turkey_mounts.js | 11 - migrations/20141211_NaN_consecutives.js | 4 - migrations/20141230_new_years_hats.js | 11 - migrations/20150107_plan_dateUpdated_null.js | 8 - migrations/20150124_mountmaster_fix.js | 88 --- migrations/20150130_birthday_goodies.js | 36 - ...150131_birthday_goodies_fix_remove_robe.js | 78 -- ...ert_creation_date_from_string_to_object.js | 112 --- .../20150201_recapture_emails_phase_update.js | 7 - migrations/20150218_interactive_tour.js | 10 - migrations/20150224_force_resting_in_inn.js | 64 -- migrations/20150310_survey_achievements.js | 5 - migrations/20150604_ultimateGearSets.js | 138 ---- migrations/20150731_purple_gryphon.js | 5 - migrations/20150731_veteran_tiger.js | 5 - migrations/20150731_veteran_wolf.js | 7 - migrations/20150906_groups_fix_leaders.js | 79 -- .../20150906_groups_remove_deleted_users.js | 87 --- migrations/20150906_groups_remove_empty.js | 21 - .../20150906_sync_groups_with_firebase.js | 43 -- migrations/20151013_jackolanterns.js | 67 -- .../20151021_usernames_emails_lowercase.js | 63 -- migrations/20151105_tutorial_flags.js | 63 -- migrations/20151116_costume_contest_award.js | 102 --- .../20151116_costume_contest_to_number.js | 64 -- migrations/20151125_turkey_ladder.js | 71 -- migrations/20151229_new_years_hats.js | 70 -- migrations/20160521_veteran_ladder.js | 82 -- migrations/20160527_fix_empty_checklist_id.js | 84 -- migrations/20160731_naming_day.js | 82 -- migrations/20160731_takeThis.js | 71 -- migrations/20160831_takeThis.js | 72 -- migrations/20161002_takeThis.js | 73 -- migrations/20161030-jackolanterns.js | 86 --- migrations/20161102_takeThis.js | 75 -- migrations/20161122_turkey_ladder.js | 74 -- migrations/20161230_nye_hats.js | 73 -- migrations/20170120_missing_incentive.js | 113 --- migrations/20170131_habit_birthday.js | 109 --- migrations/20170418_subscriber_jackalopes.js | 88 --- migrations/20170711_orcas.js | 90 --- migrations/20170731_naming_day.js | 109 --- migrations/20170928_redesign_guilds.js | 97 --- migrations/20171030_jackolanterns.js | 111 --- migrations/20171230_nye_hats.js | 103 --- migrations/api_v3/challenges.js | 218 ------ migrations/api_v3/challengesMembers.js | 149 ---- migrations/api_v3/coupons.js | 142 ---- migrations/api_v3/emailUnsubscriptions.js | 143 ---- migrations/api_v3/groups.js | 217 ------ migrations/api_v3/users.js | 268 ------- migrations/apology_gems.js | 1 - .../2013/20130128_add_missing_crons.js | 5 + .../2013/20130128_merge_completed_todo_ids.js | 15 + .../2013/20130129_add_missing_preferences.js | 5 + .../2013}/20130204_count_habits.js | 20 +- .../20130204_user_public_private_paths.js | 101 +++ .../2013/20130208_idLists_to_typeIds.js | 19 + .../2013/20130208_user_customizations.js | 18 + .../archive/2013/20130307_exp_overflow.js | 37 + .../2013/20130307_normalize_algo_values.js | 46 ++ .../2013/20130307_remove_duff_histories.js | 28 + .../archive/2013/20130326_migrate_pets.js | 98 +++ .../archive/2013/20130327_apply_tokens.js | 109 +++ .../2013/20130503_max_gear_achievement.js | 23 + .../2013}/20130507_fix_broken_tags.js | 11 +- .../archive/2013/20130508_add_backer_pets.js | 1 + .../20130508_fix_duff_party_subscriptions.js | 41 +- .../2013}/20130518_setup_groups.js | 42 +- .../archive/2013/20130602_survey_rewards.js | 31 + .../20130612_survey_rewards_individual.js | 9 + .../2013/20130615_add_extra_indexes.js | 4 + .../2013/20130908_cleanup_corrupt_tags.js | 16 + .../20130908_cleanup_derby_corruption.js | 35 +- .../2013}/20130908_remove_staged_users.js | 12 +- .../2013/20131022_purchased_and_newStuff.js | 5 + .../archive/2013/20131022_restore_ads.js | 12 + .../20131028_task_subdocs_tags_invites.js | 91 ++- .../archive/2013/20131102_restore_task_ids.js | 25 + .../2013/20131104_remove_invalid_dues.js | 7 + .../2013}/20131104_restore_lost_task_data.js | 46 +- .../2013/20131105_remove_history_ids.js | 21 + .../20131107_from_backer_to_contributor.js | 10 +- .../2013/20131108_add_gems_for_contribs.js | 4 + .../2013}/20131109_refactor_pets.js | 17 +- migrations/archive/2013/20131111_task_NaN.js | 15 + .../20131114_migrate_websites_to_blurb.js | 14 + .../2013/20131115_update_gear_preferences.js | 10 + .../archive/2013/20131117_fix_task_types.js | 18 + .../2013/20131117_remove_undefined_pets.js | 12 + .../archive/2013/20131122_deleted_tags.js | 13 + .../2013/20131123_set_default_party_order.js | 8 + .../archive/2013/20131126_clean_dayStart.js | 5 + .../archive/2013/20131126_turkey_pet.js | 1 + .../archive/2013/20131127_restore_dayStart.js | 42 + .../2013}/20131214_classes.coffee | 0 .../2013}/20131217_unearned_backer_gear.js | 16 +- .../2013/20131221_restore_NaN_history.js | 55 ++ .../archive/2013/20131225_restore_streaks.js | 42 + ...20140119_task_creation_completion_dates.js | 8 + .../archive/2014/20140130_birthdayEnd.js | 1 + .../archive/2014/20140130_birthdayStart.js | 12 + .../2014/20140220_challenge_memberCount.js | 3 + .../2014/20140301_missing_mysteries.js | 14 + .../2014/20140610_missing_backer_mount.js | 1 + .../2014/20140712_wiped_quest_membership.js | 11 + ...20140803_remove_undefined_notifications.js | 13 + ...emove_undefined_and_false_notifications.js | 38 +- ...0140829_change_headAccessory_to_eyewear.js | 83 ++ ...ncrease_gems_for_previous_contributions.js | 144 ++++ .../20140914_upgrade_admin_contrib_tiers.js | 86 +++ .../archive/2014/20140922_free_candy.js | 18 + .../archive/2014/20141006_jackolantern_pet.js | 1 + .../2014}/20141117_consecutive_months.js | 16 +- .../archive/2014/20141126_turkey_mounts.js | 11 + .../archive/2014/20141211_NaN_consecutives.js | 4 + .../archive/2014/20141230_new_years_hats.js | 11 + .../2015/20150107_plan_dateUpdated_null.js | 8 + .../archive/2015/20150124_mountmaster_fix.js | 95 +++ .../archive/2015/20150130_birthday_goodies.js | 36 + ...150131_birthday_goodies_fix_remove_robe.js | 85 +++ ...ert_creation_date_from_string_to_object.js | 119 +++ .../20150201_recapture_emails_phase_update.js | 7 + .../archive/2015/20150218_interactive_tour.js | 10 + .../2015/20150224_force_resting_in_inn.js | 71 ++ .../2015/20150310_survey_achievements.js | 5 + .../{ => archive/2015}/20150325_egg_quest.js | 6 +- .../archive/2015/20150604_ultimateGearSets.js | 141 ++++ .../2015}/20150706_orca_mounts.js | 4 +- .../archive/2015/20150731_purple_gryphon.js | 5 + .../archive/2015/20150731_veteran_tiger.js | 5 + .../archive/2015/20150731_veteran_wolf.js | 7 + .../2015/20150906_groups_fix_leaders.js | 79 ++ .../20150906_groups_remove_deleted_users.js | 86 +++ .../2015/20150906_groups_remove_empty.js | 21 + .../20150906_sync_groups_with_firebase.js | 43 ++ .../archive/2015/20151013_jackolanterns.js | 74 ++ .../20151021_usernames_emails_lowercase.js | 63 ++ .../archive/2015/20151105_tutorial_flags.js | 70 ++ .../2015/20151116_costume_contest_award.js | 109 +++ .../20151116_costume_contest_to_number.js | 71 ++ .../archive/2015/20151125_turkey_ladder.js | 78 ++ .../archive/2015/20151229_new_years_hats.js | 77 ++ ...enges_condense_same_day_history_entries.js | 81 +- .../2016}/20160129_habit_birthday.js | 83 +- .../archive/2016/20160521_veteran_ladder.js | 89 +++ .../2016/20160527_fix_empty_checklist_id.js | 91 +++ .../2016}/20160529_fix_challenges.js | 36 +- ...ks_from_null_value_in_challenges_broken.js | 34 +- .../20160602_convert_quest_collection.js | 32 +- ...20160605_convert_quest_collection_again.js | 30 +- .../2016}/20160615_fix_bad_emails.js | 24 +- .../archive/2016/20160731_naming_day.js | 89 +++ migrations/archive/2016/20160731_takeThis.js | 78 ++ migrations/archive/2016/20160831_takeThis.js | 79 ++ .../20161002_add_missing_webhook_type.js | 30 +- migrations/archive/2016/20161002_takeThis.js | 80 ++ .../archive/2016/20161030-jackolanterns.js | 93 +++ migrations/archive/2016/20161102_takeThis.js | 82 ++ .../archive/2016/20161122_turkey_ladder.js | 81 ++ migrations/archive/2016/20161230_nye_hats.js | 80 ++ ...unce_collection_quest_change_in_parties.js | 40 +- .../2017/20170120_missing_incentive.js | 118 +++ .../archive/2017/20170131_habit_birthday.js | 114 +++ .../2017/20170418_subscriber_jackalopes.js | 93 +++ .../2017}/20170425_missing_incentives.js | 101 +-- .../2017}/20170616_achievements.js | 79 +- migrations/archive/2017/20170711_orcas.js | 95 +++ .../archive/2017/20170731_naming_day.js | 114 +++ .../archive/2017/20170928_redesign_guilds.js | 102 +++ .../2017}/20170928_redesign_launch.js | 89 ++- .../archive/2017/20171030_jackolanterns.js | 116 +++ .../2017}/20171117_turkey_ladder.js | 81 +- migrations/archive/2017/20171230_nye_hats.js | 108 +++ .../2018}/20180110_nextPaymentProcessing.js | 61 +- .../2018}/20180125_clean_new_notifications.js | 0 .../2018}/20180125_notifications.js | 0 .../2018}/20180130_habit_birthday.js | 109 +-- migrations/archive/README.md | 4 + migrations/archive/api_v3/challenges.js | 218 ++++++ .../archive/api_v3/challengesMembers.js | 149 ++++ migrations/archive/api_v3/coupons.js | 142 ++++ .../archive/api_v3/emailUnsubscriptions.js | 143 ++++ migrations/archive/api_v3/groups.js | 217 ++++++ migrations/{ => archive}/api_v3/indexes.js | 0 migrations/archive/api_v3/users.js | 268 +++++++ .../{ => archive}/manual_password_reset.js | 34 +- migrations/archive/metrics.js | 85 +++ migrations/challenges/sync-all-challenges.js | 6 +- migrations/command-line/.eslintrc | 10 + migrations/command-line/apology_gems.js | 1 + .../{ => command-line}/cancelSubscription.js | 4 +- migrations/command-line/contribs_plan.js | 23 + .../{ => command-line}/current_period_end.js | 6 +- .../duplicatedTasksFindAndRemove.js | 44 +- .../{ => command-line}/facebook_to_local.js | 10 +- .../{ => command-line}/find_unique_user.js | 8 +- migrations/{ => command-line}/freeMonth.js | 20 +- migrations/command-line/habitica_day.js | 5 + migrations/command-line/missing_gems.js | 1 + .../{ => command-line}/mystery_items.js | 30 +- migrations/contribs_plan.js | 23 - .../groups/add-unlimited-subscription.js | 46 +- migrations/groups/create-group.js | 33 +- migrations/groups/habitrpg-jackalopes.js | 21 +- .../groups/update-groups-with-group-plans.js | 16 +- migrations/habitica_day.js | 5 - migrations/metrics.js | 86 --- migrations/migration-runner.js | 12 +- migrations/missing_gems.js | 1 - migrations/new_stuff.js | 73 +- migrations/restock_armoire.js | 71 +- .../restock_armoire_for_users_that_need_it.js | 89 ++- migrations/restore-profile-data.js | 84 +- migrations/s3-upload.js | 18 +- migrations/takeThis.js | 100 +-- migrations/tasks/tasks-set-everyX.js | 75 +- migrations/tasks/tasks-set-yesterdailies.js | 171 +++-- migrations/users/account-transfer.js | 18 +- migrations/users/achievement-restore.js | 20 +- migrations/users/users-to-test.js | 69 +- migrations/utils/connect.js | 8 +- migrations/utils/logger.js | 14 +- migrations/utils/timer.js | 2 +- package-lock.json | 715 ++++++++++-------- package.json | 22 +- scripts/paypalBillingSetup.js | 147 ++-- ...lenges_challengeId_winner_winnerId.test.js | 2 +- .../api/v3/integration/chat/POST-chat.test.js | 20 +- .../integration/content/GET-content.test.js | 6 +- .../debug/POST-debug_addTenGems.test.js | 10 +- .../debug/POST-debug_make-admin.test.js | 10 +- .../debug/POST-debug_modify-inventory.test.js | 10 +- .../debug/POST-debug_quest-progress.test.js | 20 +- .../debug/POST-debug_set-cron.test.js | 10 +- .../v3/integration/groups/GET-groups.test.js | 4 +- .../groups/POST-groups_groupId_join.test.js | 38 +- .../groups/POST-groups_groupId_leave.js | 4 +- .../groups/POST-groups_groupId_reject.test.js | 6 +- .../POST-groups_id_removeMember.test.js | 4 +- .../groups/POST-groups_invite.test.js | 206 ++--- .../news/POST-news_tell_me_later.test.js | 2 +- .../apple/POST-payments_apple_verifyiap.js | 6 +- .../POST-groups_groupId_quests_accept.test.js | 60 +- ...-groups_groupId_quests_force-start.test.js | 50 +- .../POST-groups_groupid_quests_abort.test.js | 20 +- .../POST-groups_groupid_quests_cancel.test.js | 40 +- .../POST-groups_groupid_quests_leave.test.js | 30 +- .../POST-groups_groupid_quests_reject.test.js | 60 +- .../POST-tasks_id_score_direction.test.js | 20 +- .../POST-tasks_unlink-all_challengeId.test.js | 32 +- .../POST-tasks_unlink-one_taskId.test.js | 50 +- .../v3/integration/tasks/PUT-tasks_id.test.js | 6 +- ...lenge_challengeId_taskId_checklist.test.js | 10 +- .../PUT-tasks_challenge_challengeId.test.js | 2 +- ...allengeId_tasksId_checklist_itemId.test.js | 20 +- .../tags/POST-tasks_taskId_tags.test.js | 1 + .../user/POST-user_release_both.test.js | 6 +- .../DELETE-user_auth_social_network.test.js | 8 +- .../user/auth/POST-register_local.test.js | 2 +- .../world-state/GET-world-state.test.js | 2 +- test/api/v3/unit/libs/apiMessages.js | 6 +- .../unit/libs/collectionManipulators.test.js | 2 +- test/api/v3/unit/libs/cron.test.js | 8 +- .../libs/payments/amazon/checkout.test.js | 10 +- .../libs/payments/amazon/subscribe.test.js | 40 +- .../group-plans/group-payments-create.test.js | 4 +- .../libs/payments/paypal/checkout.test.js | 10 +- .../stripe/cancel-subscription.test.js | 30 +- .../stripe/checkout-subscription.test.js | 30 +- .../libs/payments/stripe/checkout.test.js | 10 +- .../payments/stripe/edit-subscription.test.js | 40 +- .../payments/stripe/handle-webhook.test.js | 6 +- test/api/v3/unit/libs/taskManager.js | 14 +- test/api/v3/unit/middlewares/cors.test.js | 2 +- .../api/v3/unit/middlewares/cronMiddleware.js | 12 +- .../unit/middlewares/maintenanceMode.test.js | 2 +- test/api/v3/unit/middlewares/redirects.js | 16 +- test/api/v3/unit/models/challenge.test.js | 4 +- test/api/v3/unit/models/group_tasks.test.js | 6 +- test/api/v3/unit/models/task.test.js | 2 +- test/api/v3/unit/models/user.test.js | 2 +- test/client/e2e/specs/test.js | 2 +- test/common/libs/taskClasses.test.js | 82 -- test/common/ops/releaseBoth.js | 2 +- test/mocha.opts | 1 - .../client/components/groups/membersModal.vue | 8 +- .../components/inventory/items/index.vue | 2 +- website/client/components/static/faq.vue | 4 +- website/client/store/actions/common.js | 12 +- website/client/store/actions/shops.js | 20 +- .../common/script/content/appearance/skin.js | 2 +- .../script/content/shop-featuredItems.js | 2 +- website/common/script/index.js | 3 - website/common/script/libs/taskClasses.js | 83 -- website/server/controllers/api-v3/auth.js | 10 +- .../server/controllers/api-v3/challenges.js | 10 +- website/server/controllers/api-v3/groups.js | 6 +- website/server/controllers/api-v3/hall.js | 32 +- website/server/controllers/api-v3/i18n.js | 10 +- website/server/controllers/api-v3/members.js | 4 +- website/server/controllers/api-v3/quests.js | 4 +- .../server/controllers/api-v3/tasks/groups.js | 4 +- .../controllers/top-level/dataexport.js | 12 +- website/server/libs/logger.js | 8 +- website/server/libs/password.js | 12 +- website/server/libs/payments.js | 8 +- website/server/libs/pushNotifications.js | 44 +- website/server/middlewares/analytics.js | 6 +- website/server/middlewares/auth.js | 44 +- website/server/middlewares/language.js | 14 +- website/server/models/group.js | 18 +- 362 files changed, 8041 insertions(+), 7813 deletions(-) create mode 100644 migrations/.eslintrc delete mode 100644 migrations/20130128_add_missing_crons.js delete mode 100644 migrations/20130128_merge_completed_todo_ids.js delete mode 100644 migrations/20130129_add_missing_preferences.js delete mode 100644 migrations/20130204_user_public_private_paths.js delete mode 100644 migrations/20130208_idLists_to_typeIds.js delete mode 100644 migrations/20130208_user_customizations.js delete mode 100644 migrations/20130307_exp_overflow.js delete mode 100644 migrations/20130307_normalize_algo_values.js delete mode 100644 migrations/20130307_remove_duff_histories.js delete mode 100644 migrations/20130326_migrate_pets.js delete mode 100644 migrations/20130327_apply_tokens.js delete mode 100644 migrations/20130503_max_gear_achievement.js delete mode 100644 migrations/20130508_add_backer_pets.js delete mode 100644 migrations/20130602_survey_rewards.js delete mode 100644 migrations/20130612_survey_rewards_individual.js delete mode 100644 migrations/20130615_add_extra_indexes.js delete mode 100644 migrations/20130908_cleanup_corrupt_tags.js delete mode 100644 migrations/20131022_purchased_and_newStuff.js delete mode 100644 migrations/20131022_restore_ads.js delete mode 100644 migrations/20131102_restore_task_ids.js delete mode 100644 migrations/20131104_remove_invalid_dues.js delete mode 100644 migrations/20131105_remove_history_ids.js delete mode 100644 migrations/20131108_add_gems_for_contribs.js delete mode 100644 migrations/20131111_task_NaN.js delete mode 100644 migrations/20131114_migrate_websites_to_blurb.js delete mode 100644 migrations/20131115_update_gear_preferences.js delete mode 100644 migrations/20131117_fix_task_types.js delete mode 100644 migrations/20131117_remove_undefined_pets.js delete mode 100644 migrations/20131122_deleted_tags.js delete mode 100644 migrations/20131123_set_default_party_order.js delete mode 100644 migrations/20131126_clean_dayStart.js delete mode 100644 migrations/20131126_turkey_pet.js delete mode 100644 migrations/20131127_restore_dayStart.js delete mode 100644 migrations/20131221_restore_NaN_history.js delete mode 100644 migrations/20131225_restore_streaks.js delete mode 100644 migrations/20140119_task_creation_completion_dates.js delete mode 100644 migrations/20140130_birthdayEnd.js delete mode 100644 migrations/20140130_birthdayStart.js delete mode 100644 migrations/20140220_challenge_memberCount.js delete mode 100644 migrations/20140301_missing_mysteries.js delete mode 100644 migrations/20140610_missing_backer_mount.js delete mode 100644 migrations/20140712_wiped_quest_membership.js delete mode 100644 migrations/20140803_remove_undefined_notifications.js delete mode 100644 migrations/20140829_change_headAccessory_to_eyewear.js delete mode 100644 migrations/20140831_increase_gems_for_previous_contributions.js delete mode 100644 migrations/20140914_upgrade_admin_contrib_tiers.js delete mode 100644 migrations/20140922_free_candy.js delete mode 100644 migrations/20141006_jackolantern_pet.js delete mode 100644 migrations/20141126_turkey_mounts.js delete mode 100644 migrations/20141211_NaN_consecutives.js delete mode 100644 migrations/20141230_new_years_hats.js delete mode 100644 migrations/20150107_plan_dateUpdated_null.js delete mode 100644 migrations/20150124_mountmaster_fix.js delete mode 100644 migrations/20150130_birthday_goodies.js delete mode 100644 migrations/20150131_birthday_goodies_fix_remove_robe.js delete mode 100644 migrations/20150201_convert_creation_date_from_string_to_object.js delete mode 100644 migrations/20150201_recapture_emails_phase_update.js delete mode 100644 migrations/20150218_interactive_tour.js delete mode 100644 migrations/20150224_force_resting_in_inn.js delete mode 100644 migrations/20150310_survey_achievements.js delete mode 100644 migrations/20150604_ultimateGearSets.js delete mode 100644 migrations/20150731_purple_gryphon.js delete mode 100644 migrations/20150731_veteran_tiger.js delete mode 100644 migrations/20150731_veteran_wolf.js delete mode 100644 migrations/20150906_groups_fix_leaders.js delete mode 100644 migrations/20150906_groups_remove_deleted_users.js delete mode 100644 migrations/20150906_groups_remove_empty.js delete mode 100644 migrations/20150906_sync_groups_with_firebase.js delete mode 100644 migrations/20151013_jackolanterns.js delete mode 100644 migrations/20151021_usernames_emails_lowercase.js delete mode 100644 migrations/20151105_tutorial_flags.js delete mode 100644 migrations/20151116_costume_contest_award.js delete mode 100644 migrations/20151116_costume_contest_to_number.js delete mode 100644 migrations/20151125_turkey_ladder.js delete mode 100644 migrations/20151229_new_years_hats.js delete mode 100644 migrations/20160521_veteran_ladder.js delete mode 100644 migrations/20160527_fix_empty_checklist_id.js delete mode 100644 migrations/20160731_naming_day.js delete mode 100644 migrations/20160731_takeThis.js delete mode 100644 migrations/20160831_takeThis.js delete mode 100644 migrations/20161002_takeThis.js delete mode 100644 migrations/20161030-jackolanterns.js delete mode 100644 migrations/20161102_takeThis.js delete mode 100644 migrations/20161122_turkey_ladder.js delete mode 100644 migrations/20161230_nye_hats.js delete mode 100644 migrations/20170120_missing_incentive.js delete mode 100644 migrations/20170131_habit_birthday.js delete mode 100644 migrations/20170418_subscriber_jackalopes.js delete mode 100644 migrations/20170711_orcas.js delete mode 100644 migrations/20170731_naming_day.js delete mode 100644 migrations/20170928_redesign_guilds.js delete mode 100644 migrations/20171030_jackolanterns.js delete mode 100644 migrations/20171230_nye_hats.js delete mode 100644 migrations/api_v3/challenges.js delete mode 100644 migrations/api_v3/challengesMembers.js delete mode 100644 migrations/api_v3/coupons.js delete mode 100644 migrations/api_v3/emailUnsubscriptions.js delete mode 100644 migrations/api_v3/groups.js delete mode 100644 migrations/api_v3/users.js delete mode 100644 migrations/apology_gems.js create mode 100644 migrations/archive/2013/20130128_add_missing_crons.js create mode 100644 migrations/archive/2013/20130128_merge_completed_todo_ids.js create mode 100644 migrations/archive/2013/20130129_add_missing_preferences.js rename migrations/{ => archive/2013}/20130204_count_habits.js (55%) create mode 100644 migrations/archive/2013/20130204_user_public_private_paths.js create mode 100644 migrations/archive/2013/20130208_idLists_to_typeIds.js create mode 100644 migrations/archive/2013/20130208_user_customizations.js create mode 100644 migrations/archive/2013/20130307_exp_overflow.js create mode 100644 migrations/archive/2013/20130307_normalize_algo_values.js create mode 100644 migrations/archive/2013/20130307_remove_duff_histories.js create mode 100644 migrations/archive/2013/20130326_migrate_pets.js create mode 100644 migrations/archive/2013/20130327_apply_tokens.js create mode 100644 migrations/archive/2013/20130503_max_gear_achievement.js rename migrations/{ => archive/2013}/20130507_fix_broken_tags.js (58%) create mode 100644 migrations/archive/2013/20130508_add_backer_pets.js rename migrations/{ => archive/2013}/20130508_fix_duff_party_subscriptions.js (51%) rename migrations/{ => archive/2013}/20130518_setup_groups.js (54%) create mode 100644 migrations/archive/2013/20130602_survey_rewards.js create mode 100644 migrations/archive/2013/20130612_survey_rewards_individual.js create mode 100644 migrations/archive/2013/20130615_add_extra_indexes.js create mode 100644 migrations/archive/2013/20130908_cleanup_corrupt_tags.js rename migrations/{ => archive/2013}/20130908_cleanup_derby_corruption.js (61%) rename migrations/{ => archive/2013}/20130908_remove_staged_users.js (86%) create mode 100644 migrations/archive/2013/20131022_purchased_and_newStuff.js create mode 100644 migrations/archive/2013/20131022_restore_ads.js rename migrations/{ => archive/2013}/20131028_task_subdocs_tags_invites.js (51%) create mode 100644 migrations/archive/2013/20131102_restore_task_ids.js create mode 100644 migrations/archive/2013/20131104_remove_invalid_dues.js rename migrations/{ => archive/2013}/20131104_restore_lost_task_data.js (55%) create mode 100644 migrations/archive/2013/20131105_remove_history_ids.js rename migrations/{ => archive/2013}/20131107_from_backer_to_contributor.js (63%) create mode 100644 migrations/archive/2013/20131108_add_gems_for_contribs.js rename migrations/{ => archive/2013}/20131109_refactor_pets.js (61%) create mode 100644 migrations/archive/2013/20131111_task_NaN.js create mode 100644 migrations/archive/2013/20131114_migrate_websites_to_blurb.js create mode 100644 migrations/archive/2013/20131115_update_gear_preferences.js create mode 100644 migrations/archive/2013/20131117_fix_task_types.js create mode 100644 migrations/archive/2013/20131117_remove_undefined_pets.js create mode 100644 migrations/archive/2013/20131122_deleted_tags.js create mode 100644 migrations/archive/2013/20131123_set_default_party_order.js create mode 100644 migrations/archive/2013/20131126_clean_dayStart.js create mode 100644 migrations/archive/2013/20131126_turkey_pet.js create mode 100644 migrations/archive/2013/20131127_restore_dayStart.js rename migrations/{ => archive/2013}/20131214_classes.coffee (100%) rename migrations/{ => archive/2013}/20131217_unearned_backer_gear.js (51%) create mode 100644 migrations/archive/2013/20131221_restore_NaN_history.js create mode 100644 migrations/archive/2013/20131225_restore_streaks.js create mode 100644 migrations/archive/2014/20140119_task_creation_completion_dates.js create mode 100644 migrations/archive/2014/20140130_birthdayEnd.js create mode 100644 migrations/archive/2014/20140130_birthdayStart.js create mode 100644 migrations/archive/2014/20140220_challenge_memberCount.js create mode 100644 migrations/archive/2014/20140301_missing_mysteries.js create mode 100644 migrations/archive/2014/20140610_missing_backer_mount.js create mode 100644 migrations/archive/2014/20140712_wiped_quest_membership.js create mode 100644 migrations/archive/2014/20140803_remove_undefined_notifications.js rename migrations/{ => archive/2014}/20140823_remove_undefined_and_false_notifications.js (53%) create mode 100644 migrations/archive/2014/20140829_change_headAccessory_to_eyewear.js create mode 100644 migrations/archive/2014/20140831_increase_gems_for_previous_contributions.js create mode 100644 migrations/archive/2014/20140914_upgrade_admin_contrib_tiers.js create mode 100644 migrations/archive/2014/20140922_free_candy.js create mode 100644 migrations/archive/2014/20141006_jackolantern_pet.js rename migrations/{ => archive/2014}/20141117_consecutive_months.js (54%) create mode 100644 migrations/archive/2014/20141126_turkey_mounts.js create mode 100644 migrations/archive/2014/20141211_NaN_consecutives.js create mode 100644 migrations/archive/2014/20141230_new_years_hats.js create mode 100644 migrations/archive/2015/20150107_plan_dateUpdated_null.js create mode 100644 migrations/archive/2015/20150124_mountmaster_fix.js create mode 100644 migrations/archive/2015/20150130_birthday_goodies.js create mode 100644 migrations/archive/2015/20150131_birthday_goodies_fix_remove_robe.js create mode 100644 migrations/archive/2015/20150201_convert_creation_date_from_string_to_object.js create mode 100644 migrations/archive/2015/20150201_recapture_emails_phase_update.js create mode 100644 migrations/archive/2015/20150218_interactive_tour.js create mode 100644 migrations/archive/2015/20150224_force_resting_in_inn.js create mode 100644 migrations/archive/2015/20150310_survey_achievements.js rename migrations/{ => archive/2015}/20150325_egg_quest.js (56%) create mode 100644 migrations/archive/2015/20150604_ultimateGearSets.js rename migrations/{ => archive/2015}/20150706_orca_mounts.js (52%) create mode 100644 migrations/archive/2015/20150731_purple_gryphon.js create mode 100644 migrations/archive/2015/20150731_veteran_tiger.js create mode 100644 migrations/archive/2015/20150731_veteran_wolf.js create mode 100644 migrations/archive/2015/20150906_groups_fix_leaders.js create mode 100644 migrations/archive/2015/20150906_groups_remove_deleted_users.js create mode 100644 migrations/archive/2015/20150906_groups_remove_empty.js create mode 100644 migrations/archive/2015/20150906_sync_groups_with_firebase.js create mode 100644 migrations/archive/2015/20151013_jackolanterns.js create mode 100644 migrations/archive/2015/20151021_usernames_emails_lowercase.js create mode 100644 migrations/archive/2015/20151105_tutorial_flags.js create mode 100644 migrations/archive/2015/20151116_costume_contest_award.js create mode 100644 migrations/archive/2015/20151116_costume_contest_to_number.js create mode 100644 migrations/archive/2015/20151125_turkey_ladder.js create mode 100644 migrations/archive/2015/20151229_new_years_hats.js rename migrations/{ => archive/2016}/20160111_challenges_condense_same_day_history_entries.js (56%) rename migrations/{ => archive/2016}/20160129_habit_birthday.js (50%) create mode 100644 migrations/archive/2016/20160521_veteran_ladder.js create mode 100644 migrations/archive/2016/20160527_fix_empty_checklist_id.js rename migrations/{ => archive/2016}/20160529_fix_challenges.js (87%) rename migrations/{ => archive/2016}/20160530_fix_tasks_from_null_value_in_challenges_broken.js (88%) rename migrations/{ => archive/2016}/20160602_convert_quest_collection.js (87%) rename migrations/{ => archive/2016}/20160605_convert_quest_collection_again.js (86%) rename migrations/{ => archive/2016}/20160615_fix_bad_emails.js (82%) create mode 100644 migrations/archive/2016/20160731_naming_day.js create mode 100644 migrations/archive/2016/20160731_takeThis.js create mode 100644 migrations/archive/2016/20160831_takeThis.js rename migrations/{ => archive/2016}/20161002_add_missing_webhook_type.js (81%) create mode 100644 migrations/archive/2016/20161002_takeThis.js create mode 100644 migrations/archive/2016/20161030-jackolanterns.js create mode 100644 migrations/archive/2016/20161102_takeThis.js create mode 100644 migrations/archive/2016/20161122_turkey_ladder.js create mode 100644 migrations/archive/2016/20161230_nye_hats.js rename migrations/{ => archive/2017}/20170111_announce_collection_quest_change_in_parties.js (78%) create mode 100644 migrations/archive/2017/20170120_missing_incentive.js create mode 100644 migrations/archive/2017/20170131_habit_birthday.js create mode 100644 migrations/archive/2017/20170418_subscriber_jackalopes.js rename migrations/{ => archive/2017}/20170425_missing_incentives.js (70%) rename migrations/{ => archive/2017}/20170616_achievements.js (56%) create mode 100644 migrations/archive/2017/20170711_orcas.js create mode 100644 migrations/archive/2017/20170731_naming_day.js create mode 100644 migrations/archive/2017/20170928_redesign_guilds.js rename migrations/{ => archive/2017}/20170928_redesign_launch.js (50%) create mode 100644 migrations/archive/2017/20171030_jackolanterns.js rename migrations/{ => archive/2017}/20171117_turkey_ladder.js (57%) create mode 100644 migrations/archive/2017/20171230_nye_hats.js rename migrations/{ => archive/2018}/20180110_nextPaymentProcessing.js (50%) rename migrations/{ => archive/2018}/20180125_clean_new_notifications.js (100%) rename migrations/{ => archive/2018}/20180125_notifications.js (100%) rename migrations/{ => archive/2018}/20180130_habit_birthday.js (51%) create mode 100644 migrations/archive/README.md create mode 100644 migrations/archive/api_v3/challenges.js create mode 100644 migrations/archive/api_v3/challengesMembers.js create mode 100644 migrations/archive/api_v3/coupons.js create mode 100644 migrations/archive/api_v3/emailUnsubscriptions.js create mode 100644 migrations/archive/api_v3/groups.js rename migrations/{ => archive}/api_v3/indexes.js (100%) create mode 100644 migrations/archive/api_v3/users.js rename migrations/{ => archive}/manual_password_reset.js (54%) create mode 100644 migrations/archive/metrics.js create mode 100644 migrations/command-line/.eslintrc create mode 100644 migrations/command-line/apology_gems.js rename migrations/{ => command-line}/cancelSubscription.js (77%) create mode 100644 migrations/command-line/contribs_plan.js rename migrations/{ => command-line}/current_period_end.js (52%) rename migrations/{ => command-line}/duplicatedTasksFindAndRemove.js (75%) rename migrations/{ => command-line}/facebook_to_local.js (51%) rename migrations/{ => command-line}/find_unique_user.js (74%) rename migrations/{ => command-line}/freeMonth.js (65%) create mode 100644 migrations/command-line/habitica_day.js create mode 100644 migrations/command-line/missing_gems.js rename migrations/{ => command-line}/mystery_items.js (51%) delete mode 100644 migrations/contribs_plan.js delete mode 100644 migrations/habitica_day.js delete mode 100644 migrations/metrics.js delete mode 100644 migrations/missing_gems.js delete mode 100644 test/common/libs/taskClasses.test.js delete mode 100644 website/common/script/libs/taskClasses.js diff --git a/.eslintignore b/.eslintignore index 7b618cca64..d2db8508cf 100644 --- a/.eslintignore +++ b/.eslintignore @@ -10,12 +10,5 @@ apidoc_build/ content_cache/ node_modules/ -# Not linted -website/client-old/ -test/client-old/spec/**/* - -# Temporarilly disabled. These should be removed when the linting errors are fixed TODO -migrations/* -scripts/* -website/common/browserify.js -Gruntfile.js +# Old migrations, disabled +migrations/archive/* \ No newline at end of file diff --git a/migrations/.eslintrc b/migrations/.eslintrc new file mode 100644 index 0000000000..6509e9ee6b --- /dev/null +++ b/migrations/.eslintrc @@ -0,0 +1,7 @@ +{ + "root": false, + "rules": { + "no-console": 0, + "no-use-before-define": ["error", { "functions": false }] + } +} diff --git a/migrations/20130128_add_missing_crons.js b/migrations/20130128_add_missing_crons.js deleted file mode 100644 index 1a4c919cc2..0000000000 --- a/migrations/20130128_add_missing_crons.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.update( - { lastCron: { $exists: false} }, - { $set: { lastCron: +new Date } }, - { multi: true } -); \ No newline at end of file diff --git a/migrations/20130128_merge_completed_todo_ids.js b/migrations/20130128_merge_completed_todo_ids.js deleted file mode 100644 index d362a4b771..0000000000 --- a/migrations/20130128_merge_completed_todo_ids.js +++ /dev/null @@ -1,15 +0,0 @@ -db.users.find({ completedIds: { $exists: true } }).forEach(function(user) { - var newTodoIds = user.todoIds; - user.completedIds.forEach(function(value) { - if (newTodoIds.indexOf(value) === -1) { - newTodoIds.push(value) - } - }); - db.users.update( - { _id: user._id }, - { - $set: { todoIds: newTodoIds }, - $unset: { completedIds: 1 } - } - ); -}); \ No newline at end of file diff --git a/migrations/20130129_add_missing_preferences.js b/migrations/20130129_add_missing_preferences.js deleted file mode 100644 index f4e7b55762..0000000000 --- a/migrations/20130129_add_missing_preferences.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.update( - {preferences:{$exists:false}}, - {$set:{preferences:{gender: 'm', armorSet: 'v1'}}}, - {multi:true} -) diff --git a/migrations/20130204_user_public_private_paths.js b/migrations/20130204_user_public_private_paths.js deleted file mode 100644 index 7f43148350..0000000000 --- a/migrations/20130204_user_public_private_paths.js +++ /dev/null @@ -1,102 +0,0 @@ -// %mongo server:27017/dbname underscore.js my_commands.js -// %mongo server:27017/dbname underscore.js --shell - -//db.users.find({'auth.facebook.email': 'tylerrenelle@gmail.com'}).forEach(function(user){ -db.users.find().forEach(function(user){ - - if (!user._id) { - print("User has null _id"); - return; // need to figure out how to delete these buggers if they don't have an id to delete from - } - - if (!!user.idLists) { - print("User " + user._id + " has already been migrated") - return - } - - if (user._id.indexOf("$") === 0) { - print("User id starts with $ (" + user._id + ")") - return; - } - - // even though we're clobbering user later, sometimes these are undefined and crash the script - // this saves us some ternaries - user.stats = user.stats || {}; - user.items = user.items || {}; - user.preferences = user.preferences || {}; - user.notifications = user.notifications || {}; - user.flags = user.flags || {}; - user.habitIds = user.habitIds || []; - user.dailyIds = user.dailyIds || []; - user.todoIds = user.todoIds || []; - user.rewardIds = user.rewardIds|| []; - - _.each(user.tasks, function(task, key){ - if (!task.type) { - delete user.tasks[key]; - // idList will take care of itself on page-load - return - } - if (key == '$spec') { - print("$spec was found: " + user._id); - return - } - if (key.indexOf("$_") === 0) { - var newKey = key.replace("$_", ''), - index = user[task.type + "Ids"].indexOf(key) - user[task.type + "Ids"][index] = newKey; - task.id = newKey - user.tasks[newKey] = task - // TODO make sure this is ok, that we're not deleting the original - // Otherwise use lodash.cloneDeep - delete user.tasks[key] - } - }); - - // New user schema has public and private paths, so we can setup proper access control with racer - // Note 'public' and 'private' are reserved words - var newUser = { - auth: user.auth, // we need this top-level due to derby-auth - apiToken: user.preferences.api_token || null, // set on update, we need derby.uuid() - preferences: { - armorSet: user.preferences.armorSet || 'v1', - gender: user.preferences.gender || 'm' - }, - balance: user.balance || 2, - lastCron: user.lastCron || +new Date, - history: user.history || [], - stats: { - gp: user.stats.money || 0, - hp: user.stats.hp || 50, - exp: user.stats.exp || 0, - lvl: user.stats.lvl || 1 - }, - items: { - armor: user.items.armor || 0, - weapon: user.items.weapon || 0 - }, - tasks: user.tasks || {}, - idLists: { - habit: user.habitIds || [], - daily: user.dailyIds || [], - todo: user.todoIds || [], - reward: user.rewardIds || [] - }, - flags: { - partyEnabled: false, - itemsEnabled: user.items.itemsEnabled || false, - kickstarter: user.notifications.kickstarter || 'show', - ads: user.flags.ads || null // null because it's set on registration - }, - party: { - current: null, - invitation: null - } - }; - - try { - db.users.update({_id:user._id}, newUser); - } catch(e) { - print(e); - } -}) \ No newline at end of file diff --git a/migrations/20130208_idLists_to_typeIds.js b/migrations/20130208_idLists_to_typeIds.js deleted file mode 100644 index f22dc25be7..0000000000 --- a/migrations/20130208_idLists_to_typeIds.js +++ /dev/null @@ -1,19 +0,0 @@ -// move idList back to root-level, is what's causing the sort bug - see https://github.com/codeparty/racer/pull/73 - -// We could just delete user.idLists, since it's re-created on refresh. However, users's first refresh will scare them -// since everything will dissappear - second refresh will bring everything back. -db.users.find().forEach(function(user){ - if (!user.idLists) return; - db.users.update( - {_id:user._id}, - { - $set:{ - 'habitIds':user.idLists.habit, - 'dailyIds':user.idLists.daily, - 'todoIds':user.idLists.todo, - 'rewardIds':user.idLists.reward - } - //$unset:{idLists:true} // run this after the code has been pushed - } - ) -}) \ No newline at end of file diff --git a/migrations/20130208_user_customizations.js b/migrations/20130208_user_customizations.js deleted file mode 100644 index 07b1dfb08f..0000000000 --- a/migrations/20130208_user_customizations.js +++ /dev/null @@ -1,20 +0,0 @@ -db.users.update( - {items:{$exists:0}}, - {$set:{items:{weapon: 0, armor: 0, head: 0, shield: 0 }}}, - {multi:true} -); - -db.users.find().forEach(function(user){ - - var updates = { - // I'm not racist, these were just the defaults before ;) - 'preferences.skin': 'white', - 'preferences.hair': 'blond', - - 'items.head': user.items.armor, - 'items.shield': user.items.armor, - } - - db.users.update({_id:user._id}, {$set:updates}); - -}) \ No newline at end of file diff --git a/migrations/20130307_exp_overflow.js b/migrations/20130307_exp_overflow.js deleted file mode 100644 index 44fb2904b4..0000000000 --- a/migrations/20130307_exp_overflow.js +++ /dev/null @@ -1,39 +0,0 @@ -// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130307_normalize_algo_values.js - -/** - * Make sure people aren't overflowing their exp with the new system - */ -db.users.find().forEach(function(user){ - function oldTnl(level) { - return (Math.pow(level,2)*10)+(level*10)+80 - } - - function newTnl(level) { - var value = 0; - if (level >= 100) { - value = 0 - } else { - value = Math.round(((Math.pow(level,2)*0.25)+(10 * level) + 139.75)/10)*10; // round to nearest 10 - } - return value - } - - var newTnl = newTnl(user.stats.lvl); - if (user.stats.exp > newTnl) { - var percent = user.stats.exp / oldTnl(user.stats.lvl); - percent = (percent>1) ? 1 : percent; - user.stats.exp = newTnl * percent; - - try { - db.users.update( - {_id:user._id}, - {$set: {'stats.exp': user.stats.exp}}, - {multi:true} - ); - } catch(e) { - print(e); - } - - } - -}) \ No newline at end of file diff --git a/migrations/20130307_normalize_algo_values.js b/migrations/20130307_normalize_algo_values.js deleted file mode 100644 index e42faded43..0000000000 --- a/migrations/20130307_normalize_algo_values.js +++ /dev/null @@ -1,47 +0,0 @@ -// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130307_normalize_algo_values.js - -/** - * Users were experiencing a lot of extreme Exp multiplication (https://github.com/lefnire/habitrpg/issues/594). - * This sets things straight, and in preparation for another algorithm overhaul - */ -db.users.find().forEach(function(user){ - if (user.stats.exp >= 3580) { - user.stats.exp = 0; - } - - if (user.stats.lvl > 100) { - user.stats.lvl = 100; - } - - _.each(user.tasks, function(task, key){ - // remove corrupt tasks - if (!task) { - delete user.tasks[key]; - return; - } - - // Fix busted values - if (task.value > 21.27) { - task.value = 21.27; - } - else if (task.value < -47.27) { - task.value = -47.27; - } - }); - - try { - db.users.update( - {_id:user._id}, - {$set: - { - 'stats.lvl': user.stats.lvl, - 'stats.exp': user.stats.exp, - 'tasks' : user.tasks - } - }, - {multi:true} - ); - } catch(e) { - print(e); - } -}) \ No newline at end of file diff --git a/migrations/20130307_remove_duff_histories.js b/migrations/20130307_remove_duff_histories.js deleted file mode 100644 index 6211693a1f..0000000000 --- a/migrations/20130307_remove_duff_histories.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Remove duff histories for dailies - */ -// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130307_remove_duff_histories.js -db.users.find().forEach(function(user){ - - - _.each(user.tasks, function(task, key){ - if (task.type === "daily") { - // remove busted history entries - task.history = _.filter(task.history, function(h){return !!h.value}) - } - }); - - try { - db.users.update( - {_id:user._id}, - {$set: - { - 'tasks' : user.tasks - } - }, - {multi:true} - ); - } catch(e) { - print(e); - } -}) \ No newline at end of file diff --git a/migrations/20130326_migrate_pets.js b/migrations/20130326_migrate_pets.js deleted file mode 100644 index 2e0f0a395b..0000000000 --- a/migrations/20130326_migrate_pets.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Migrate old pets to new system - */ -// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130326_migrate_pets.js - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var mapping = { - bearcub: {name:'BearCub', modifier: 'Base'}, - cactus: {name:'Cactus', modifier:'Base'}, - dragon: {name:'Dragon', modifier:'Base'}, - flyingpig: {name:'FlyingPig', modifier:'Base'}, - fox: {name:'Fox', modifier:'Base'}, - lioncub: {name:'LionCub', modifier:'Base'}, - pandacub: {name:'PandaCub', modifier:'Base'}, - tigercub: {name:'TigerCub', modifier:'Base'}, - wolfBorder: {name:'Wolf', modifier:'Base'}, - wolfDesert: {name:'Wolf', modifier:'Desert'}, - wolfGolden: {name:'Wolf', modifier:'Golden'}, - wolfRed: {name:'Wolf', modifier:'Red'}, - wolfShade: {name:'Wolf', modifier:'Shade'}, - wolfSkeleton: {name:'Wolf', modifier:'Skeleton'}, - wolfVeteran: {name:'Wolf', modifier:'Veteran'}, - wolfWhite: {name:'Wolf', modifier:'White'}, - wolfZombie: {name:'Wolf', modifier:'Zombie'} -} - -/** - == Old Style == - pet: Object - icon: "Pet-Wolf-White.png" - index: 14 - name: "wolfWhite" - text: "White Wolf" - value: 3 - pets: Object - bearcub: true - cactus: true - - == New Style == - currentPet: Object - modifier: "Red" - name: "Wolf" - notes: "Find some Hatching Powder to sprinkle on this egg, and one day it will hatch into a loyal pet." - str: "Wolf-Red" - text: "Wolf" - value: 3 - pets: Array - 0: "PandaCub-Base" - 1: "Wolf-Base" - */ - - -db.users.find().forEach(function(user){ - if (!user.items || (!user.items.pets && !user.items.pet)) return; - - // migrate items.pet to items.currentPet - if (!!user.items.pet) { - var mapped = mapping[user.items.pet.name]; - delete user.items.pet; - user.items.currentPet = { - modifier: mapped.modifier, - name: mapped.name, - str: mapped.name + "-" + mapped.modifier, - text: '' // FIXME? - } - } - - // migrate items.pets - if (!!user.items.pets) { - var newPets = []; - _.each(user.items.pets, function(val, key){ - if (_.isNumber(key)) { - newPets.push(val) - //FIXME why is this happening? seems the user gets migrated already... - //throw "Error: User appears already migrated, this shouldn't be happening!" - } else { - newPets.push(mapping[key].name + "-" + mapping[key].modifier); - } - }); - user.items.pets = newPets; - } - - try { - db.users.update( - {_id:user._id}, - {$set: - { 'items' : user.items } - } - ); - } catch(e) { - print(e); - } -}) \ No newline at end of file diff --git a/migrations/20130327_apply_tokens.js b/migrations/20130327_apply_tokens.js deleted file mode 100644 index e277db38fd..0000000000 --- a/migrations/20130327_apply_tokens.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Applies backer tokens & items (this file will be updated periodically - */ - -// mongo habitrpg ./node_modules/underscore/underscore.js migrations/20130327_apply_tokens.js - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var mapping = [ - { - tier: 1, - tokens: 0, - users: [] - }, - { - tier: 5, - tokens: 20, - users: [] - }, - { - tier: 10, - tokens: 50, - users: [] - }, - { - tier: 15, - tokens: 100, - users: [] - }, - { - tier: 30, - tokens: 150, - users: [] - }, - { - tier: 45, - tokens: 170, - users: [] - }, - { - tier: 60, - tokens: 200, - users: [] - }, - { - tier: 70, - tokens: 240, - users: [] - }, - { - tier: 80, - tokens: 240, - users: [] - }, - { - tier: 90, - tokens: 280, - users: [] - }, - { - tier: 300, - tokens: 500, - users: [] - }, - { - tier: 800, - tokens: 500, - users: [] - } -]; - -db.users.find().forEach(function(user){ - if (!user._id) return; - - var possibleUserIds = [user._id]; - if (!!user.local) { - if (!!user.local.username) possibleUserIds.push(user.local.username); - if (!!user.local.email) possibleUserIds.push(user.local.email); - } - - _.each(mapping, function(tier){ - var userInTier = !_.isEmpty(_.intersection(tier.users, possibleUserIds)); - if (userInTier) { - var tokenInc = 0, - backer = user.backer || {}; - if (!backer.tokensApplied) { - tokenInc = tier.tokens; - backer.tokensApplied = true; - } - backer.tier = tier.tier; - - try { - db.users.update( - {_id:user._id}, - { - $set: { backer: backer, 'flags.ads': 'hide' }, - $inc: { balance: (tokenInc/4) } - } - ); - } catch(e) { - print(e); - } - } - }) - -}) \ No newline at end of file diff --git a/migrations/20130503_max_gear_achievement.js b/migrations/20130503_max_gear_achievement.js deleted file mode 100644 index d6be25558a..0000000000 --- a/migrations/20130503_max_gear_achievement.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * For users who already have max gear, they earned the achievement - */ -// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130503_max_gear_achievement.js -db.users.find().forEach(function(user){ - var items = user.items; - if (!items) { return; } - if ( parseInt(items.armor) == 5 && - parseInt(items.head) == 5 && - parseInt(items.shield) == 5 && - parseInt(items.weapon) == 6) { - - try { - db.users.update( - {_id:user._id}, - {$set: {'achievements.ultimateGear':true}} - ); - } catch(e) { - print(e); - } - } -}) \ No newline at end of file diff --git a/migrations/20130508_add_backer_pets.js b/migrations/20130508_add_backer_pets.js deleted file mode 100644 index 2a9744af2a..0000000000 --- a/migrations/20130508_add_backer_pets.js +++ /dev/null @@ -1 +0,0 @@ -db.users.update({'backer.tier':{$gte:80}}, {$push:{'items.pets':'Wolf-Cerberus'}}, {multi:true}); \ No newline at end of file diff --git a/migrations/20130602_survey_rewards.js b/migrations/20130602_survey_rewards.js deleted file mode 100644 index 98ae8106c2..0000000000 --- a/migrations/20130602_survey_rewards.js +++ /dev/null @@ -1,31 +0,0 @@ -//mongo habitrpg ./node_modules/lodash/lodash.js migrations/20130602_survey_rewards.js - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var members = [] -members = _.uniq(members); - -var query = { - _id: {$exists:1}, - $or:[ - {_id: {$in: members}}, - //{'profile.name': {$in: members}}, - {'auth.facebook.name': {$in: members}}, - {'auth.local.username': {$in: members}}, - {'auth.local.email': {$in: members}} - ] -}; - -print(db.users.count(query)); - -db.users.update(query, - { - $set: { 'achievements.helpedHabit': true }, - $inc: { balance: 2.5 } - }, - {multi:true} -) \ No newline at end of file diff --git a/migrations/20130612_survey_rewards_individual.js b/migrations/20130612_survey_rewards_individual.js deleted file mode 100644 index 1d3fbf3317..0000000000 --- a/migrations/20130612_survey_rewards_individual.js +++ /dev/null @@ -1,9 +0,0 @@ -//mongo habitrpg migrations/20130612_survey_rewards_individual.js - -var query = {_id: ""}; - -db.users.update(query, - { - $set: { 'achievements.helpedHabit': true }, - $inc: { balance: 2.5 } - }) \ No newline at end of file diff --git a/migrations/20130615_add_extra_indexes.js b/migrations/20130615_add_extra_indexes.js deleted file mode 100644 index 2673568184..0000000000 --- a/migrations/20130615_add_extra_indexes.js +++ /dev/null @@ -1,4 +0,0 @@ -db.users.ensureIndex( { _id: 1, apiToken: 1 }, {background: true} ) -db.groups.ensureIndex( { members: 1 }, {background: true} ) -db.groups.ensureIndex( { type: 1 }, {background: true} ) -db.groups.ensureIndex( { type: 1, privacy: 1 }, {background: true} ) \ No newline at end of file diff --git a/migrations/20130908_cleanup_corrupt_tags.js b/migrations/20130908_cleanup_corrupt_tags.js deleted file mode 100644 index 2dce073bbc..0000000000 --- a/migrations/20130908_cleanup_corrupt_tags.js +++ /dev/null @@ -1,16 +0,0 @@ -//mongo habitrpg ./node_modules/lodash/lodash.js migrations/20130908_cleanup_corrupt_tags.js - -// Racer was notorious for adding duplicates, randomly deleting documents, etc. Once we pull the plug on old.habit, -// run this migration to cleanup all the corruption - -db.users.find().forEach(function(user){ - user.tags = _.filter(user.tags, (function(t) { - return !!t ? t.id : false; - })); - - try { - db.users.update({_id:user._id}, {$set:{tags:user.tags}}); - } catch(e) { - print(e); - } -}) diff --git a/migrations/20131022_purchased_and_newStuff.js b/migrations/20131022_purchased_and_newStuff.js deleted file mode 100644 index 862d9e107f..0000000000 --- a/migrations/20131022_purchased_and_newStuff.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.find().forEach(function(user){ - if (!user.purchased) user.purchased = {hair: {}, skin: {}}; - user.purchased.ads = user.flags && !!user.flags.ads; - db.users.update({_id:user._id}, {$set:{'purchased': user.purchased, 'flags.newStuff': true}, $unset: {'flags.ads':1}}); -}); \ No newline at end of file diff --git a/migrations/20131022_restore_ads.js b/migrations/20131022_restore_ads.js deleted file mode 100644 index 6261990664..0000000000 --- a/migrations/20131022_restore_ads.js +++ /dev/null @@ -1,12 +0,0 @@ -// node .migrations/20131022_restore_ads.js -var mongo = require('mongoskin'); -var _ = require('lodash'); -var dbBackup = mongo.db('localhost:27017/habitrpg?auto_reconnect'); -var dbLive = mongo.db('localhost:27017/habitrpg2?auto_reconnect'); -var count = 89474; -dbBackup.collection('users').findEach({$or: [{'flags.ads':'show'}, {'flags.ads': null}]}, {batchSize:10}, function(err, item) { - if (err) return console.error({err:err}); - if (!item || !item._id) return console.error('blank user'); - dbLive.collection('users').update({_id:item._id}, {$set:{'purchased.ads':false}, $unset: {'flags.ads': 1}}); - if (--count <= 0) console.log("DONE!"); -}); \ No newline at end of file diff --git a/migrations/20131102_restore_task_ids.js b/migrations/20131102_restore_task_ids.js deleted file mode 100644 index 260675fbf5..0000000000 --- a/migrations/20131102_restore_task_ids.js +++ /dev/null @@ -1,25 +0,0 @@ -// mongo habitrpg ./node_modules/lodash/lodash.js ./migrations/20131028_task_subdocs_tags_invites.js - -db.challenges.find().forEach(function(chal){ - _.each(chal.habits.concat(chal.dailys).concat(chal.todos).concat(chal.rewards), function(task){ - task.id = task.id || task._id; - }) - try { - db.challenges.update({_id:chal._id}, chal); - db.groups.update({_id:chal.group}, {$addToSet:{challenges:chal._id}}) - } catch(e) { - print(e); - } -}); - -db.users.find().forEach(function(user){ - _.each(user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards), function(task){ - task.id = task.id || task._id; - }) - try { - db.users.update({_id:user._id}, user); - } catch(e) { - print(e); - } -}); - diff --git a/migrations/20131104_remove_invalid_dues.js b/migrations/20131104_remove_invalid_dues.js deleted file mode 100644 index 8ebf89afaf..0000000000 --- a/migrations/20131104_remove_invalid_dues.js +++ /dev/null @@ -1,7 +0,0 @@ -db.users.find({},{todos:1}).forEach(function(user){ - _.each(user.todos, function(task){ - if (moment(task.date).toDate() == 'Invalid Date') - task.date = moment().format('MM/DD/YYYY'); - }) - db.users.update({_id:user._id}, {$set:{todos: user.todos}}); -}); \ No newline at end of file diff --git a/migrations/20131105_remove_history_ids.js b/migrations/20131105_remove_history_ids.js deleted file mode 100644 index 9ddbff620e..0000000000 --- a/migrations/20131105_remove_history_ids.js +++ /dev/null @@ -1,21 +0,0 @@ -function deleteId(h){ - delete h._id; -} - -db.users.find({},{habits:1,dailys:1,history:1}).forEach(function(user){ - if (user.history) { - _.each(['todos','exp'], function(type){ - if (user.history[type]) { - _.each(user.history.exp, deleteId); - } - }) - } else { - user.history = {exp:[],todos:[]}; - } - - _.each(['habits', 'dailys'], function(type){ - _.each(user[type].history, deleteId); - }); - - db.users.update({_id:user._id}, {$set:{history: user.history, habits: user.habits, dailys: user.dailys}}); -}); \ No newline at end of file diff --git a/migrations/20131108_add_gems_for_contribs.js b/migrations/20131108_add_gems_for_contribs.js deleted file mode 100644 index 03ff44e721..0000000000 --- a/migrations/20131108_add_gems_for_contribs.js +++ /dev/null @@ -1,4 +0,0 @@ -// Increase everyone's gems per their contribution level -db.users.find({'contributor.level':{$gt:0}},{contributor:1, balance:1}).forEach(function(user){ - db.users.update({_id:user._id}, {$inc: {balance: (user.contributor.level * .5)} }); -}); \ No newline at end of file diff --git a/migrations/20131111_task_NaN.js b/migrations/20131111_task_NaN.js deleted file mode 100644 index 16e6788003..0000000000 --- a/migrations/20131111_task_NaN.js +++ /dev/null @@ -1,15 +0,0 @@ -// This migration has already been run in the past. It's vital to fix these users presently, but we need to find -// out why task values are ever getting in as NaN. My guess is API PUT /tasks/:tid routes -db.users.find({},{habits:1,dailys:1,todos:1,rewards:1}).forEach(function(user){ - _.each(['habits','dailys','todos','rewards'], function(type){ - _.each(user[type], function(task){ - task.value = +task.value; - if (_.isNaN(task.value)) { - task.value = 0; - print(user._id); - } - }) - }) - - db.users.update({_id:user._id}, {$set:{habits: user.habits, dailys: user.dailys, todos: user.todos, rewards: user.rewards}}); -}); \ No newline at end of file diff --git a/migrations/20131114_migrate_websites_to_blurb.js b/migrations/20131114_migrate_websites_to_blurb.js deleted file mode 100644 index e2bbdd9fcb..0000000000 --- a/migrations/20131114_migrate_websites_to_blurb.js +++ /dev/null @@ -1,14 +0,0 @@ -// Migrate all users websites to the profile blurb field -db.users.find({'profile.websites':{$exists: true}}).forEach(function(user){ - db.users.update({_id: user._id}, { - $set: {"profile.blurb": user.profile.blurb + '\n * ' + user.profile.websites.join('\n * ')}, - $unset: {'profile.websites': 1} - }) -}) - -db.groups.find({'websites.0':{$exists: true}}).forEach(function(group){ - db.groups.update({_id: group._id}, { - $set: {"description": group.description + '\n * ' + group.websites.join('\n * ')}, - $unset: {websites: 1} - }) -}) diff --git a/migrations/20131115_update_gear_preferences.js b/migrations/20131115_update_gear_preferences.js deleted file mode 100644 index 9ec1264b2f..0000000000 --- a/migrations/20131115_update_gear_preferences.js +++ /dev/null @@ -1,10 +0,0 @@ -//Add defaults to show gears in all users -db.users.update( - {}, - {$set:{ - 'preferences.showWeapon': true, - 'preferences.showShield': true, - 'preferences.showArmor': true, - }}, - {multi:true} -) diff --git a/migrations/20131117_fix_task_types.js b/migrations/20131117_fix_task_types.js deleted file mode 100644 index 14d86cb55f..0000000000 --- a/migrations/20131117_fix_task_types.js +++ /dev/null @@ -1,18 +0,0 @@ -// TODO figure out why this is happening in the first place - -db.users.find({},{habits:1, dailys:1, todos:1, rewards:1}).forEach(function(user){ - _.each(user.habits, function(task){ - task.type = 'habit'; - }) - _.each(user.dailys, function(task){ - task.type = 'daily'; - }) - _.each(user.todos, function(task){ - task.type = 'todo'; - }) - _.each(user.rewards, function(task){ - task.type = 'reward'; - }) - - db.users.update({_id:user._id}, {$set:{habits: user.habits, dailys: user.dailys, todos: user.todos, rewards: user.rewards}}); -}); diff --git a/migrations/20131117_remove_undefined_pets.js b/migrations/20131117_remove_undefined_pets.js deleted file mode 100644 index f908621a75..0000000000 --- a/migrations/20131117_remove_undefined_pets.js +++ /dev/null @@ -1,12 +0,0 @@ -// once and for all! - -db.users.find({'items.pets':{$exists:1}},{'items.pets':1}).forEach(function(user){ - _.reduce(user.items.pets, function(m,v,k){ - if (!k.indexOf('undefined')) m.push(k); - return m; - }, []).forEach(function(key){ - delete user.items.pets[key]; - }) - - db.users.update({_id:user._id}, { $set:{'items.pets':user.items.pets} }); -}); diff --git a/migrations/20131122_deleted_tags.js b/migrations/20131122_deleted_tags.js deleted file mode 100644 index e915390041..0000000000 --- a/migrations/20131122_deleted_tags.js +++ /dev/null @@ -1,13 +0,0 @@ -// Cleanup broken tags -// ------------------------- -db.users.find().forEach(function(user){ - var tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards); - - _.each(tasks, function(task){ - _.each(task.tags, function(value, key){ //value is true, key is tag.id - if (!_.find(user.tags,{id:key})) delete task.tags[key]; - }); - }); - - db.users.update({_id:user._id}, user); -}); \ No newline at end of file diff --git a/migrations/20131123_set_default_party_order.js b/migrations/20131123_set_default_party_order.js deleted file mode 100644 index 970e37e05b..0000000000 --- a/migrations/20131123_set_default_party_order.js +++ /dev/null @@ -1,8 +0,0 @@ -//Add default to randomize party members list -db.users.update( - {}, - {$set:{ - 'party.order': 'random', - }}, - {multi:true} -) diff --git a/migrations/20131126_clean_dayStart.js b/migrations/20131126_clean_dayStart.js deleted file mode 100644 index b2001ec7c2..0000000000 --- a/migrations/20131126_clean_dayStart.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.find({'preferences.dayStart':{$exists:1}},{'preferences.dayStart':1}).forEach(function(user){ - var dayStart = +user.preferences.dayStart; - dayStart = (_.isNaN(dayStart) || dayStart < 0 || dayStart > 24) ? 0 : dayStart; - db.users.update({_id:user._id}, {$set:{'preferences.dayStart':dayStart}}); -}); diff --git a/migrations/20131126_turkey_pet.js b/migrations/20131126_turkey_pet.js deleted file mode 100644 index 568e38b237..0000000000 --- a/migrations/20131126_turkey_pet.js +++ /dev/null @@ -1 +0,0 @@ -db.users.update({},{$set:{'items.pets.Turkey-Base':5, 'flags.newStuff':true}}, {multi:true}); \ No newline at end of file diff --git a/migrations/20131127_restore_dayStart.js b/migrations/20131127_restore_dayStart.js deleted file mode 100644 index fd9aba3618..0000000000 --- a/migrations/20131127_restore_dayStart.js +++ /dev/null @@ -1,38 +0,0 @@ -// node .migrations/20131127_restore_dayStart.js - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); -var liveUsers = mongo.db('localhost:27017/habitrpg_new?auto_reconnect').collection('users'); - -var query = {'preferences.dayStart':{$exists:1,$ne:0}}; -var select = {'preferences.dayStart': 1}; - -backupUsers.count(query, function(err, count){ - if (err) return console.error(err); - backupUsers.findEach(query, select, {batchSize:20}, function(err, before){ - if (err) return console.error(err); - if (!before) { count--; return console.log('!before'); } - liveUsers.findById(before._id, function(err, after){ - if (err) return console.error(err); - if (!after) { count--; return console.log(before._id + ' deleted?'); } - - var dayStart = +before.preferences.dayStart; - if (after.preferences.dayStart == 0 && dayStart != 0){ - dayStart = (_.isNaN(dayStart) || dayStart < 0 || dayStart > 24) ? 0 : dayStart; - } else { - dayStart = after.preferences.dayStart; - } - - liveUsers.update({_id:after._id}, {$inc:{_v:1}, $set:{'preferences.dayStart':dayStart}}); - if (--count <= 0) console.log("DONE!"); - }) - }); -}); \ No newline at end of file diff --git a/migrations/20131221_restore_NaN_history.js b/migrations/20131221_restore_NaN_history.js deleted file mode 100644 index f0d6d90093..0000000000 --- a/migrations/20131221_restore_NaN_history.js +++ /dev/null @@ -1,51 +0,0 @@ -// node .migrations/20131221_restore_NaN_history.js - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -/** - * After the classes migration, users lost some history entries - */ -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); -var liveUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); - -function filterNaNs(h) { - return h && _.isNumber(+h.value) && !_.isNaN(+h.value); -} - -var fields = {history:1,habits:1,dailys:1,migration:1}; -var count = 0; -liveUsers.findEach({migration: {$ne:'20131221_restore_NaN_history'}}, fields, {batchSize:500}, function(err, after){ - if (!after) err = '!after'; - if (err) {count++;return console.error(err);} - - backupUsers.findById(after._id, fields, function(err, before){ - if (err) {count++;return console.error(err);} - - _.each(['todos','exp'],function(type){ - if (!_.isEmpty(after.history[type])) - after.history[type] = _.filter(after.history[type], filterNaNs); - if (before && !_.isEmpty(before.history[type])) - after.history[type] = before.history[type].concat(after.history[type]); - }) - - _.each(['habits','dailys'], function(type){ - _.each(after[type], function(t){ - t.history = _.filter(t.history, filterNaNs); - var found = before && _.find(before[type],{id:t.id}); - if (found && found.history) t.history = found.history.concat(t.history); - }) - }) - - liveUsers.update({_id:after._id}, {$set:{history:after.history, dailys:after.dailys, habits:after.habits, migration:'20131221_restore_NaN_history'}, $inc:{_v:1}}); - //if (--count <= 0) console.log("DONE! " + after._id); - if (++count%1000 == 0) console.log(count); - if (after._id == '9') console.log('lefnire processed'); - }) -}); \ No newline at end of file diff --git a/migrations/20131225_restore_streaks.js b/migrations/20131225_restore_streaks.js deleted file mode 100644 index c07a3828f3..0000000000 --- a/migrations/20131225_restore_streaks.js +++ /dev/null @@ -1,38 +0,0 @@ -// node .migrations/20131225_restore_streaks.js - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -/** - * After the classes migration, users lost some history entries - */ -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); -var liveUsers = mongo.db('lefnire:mAdn3s5s@charlotte.mongohq.com:10015/habitrpg_large?auto_reconnect').collection('users'); - -var fields = {dailys:1,migration:1}; -var count = 0; -liveUsers.findEach({migration: {$ne:'20131225_restore_streaks'}}, fields, {batchSize:250}, function(err, after){ - if (!after) err = '!after'; - if (err) {count++;return console.error(err);} - - backupUsers.findById(after._id, fields, function(err, before){ - if (!before) err = '!before'; - if (err) {count++;return console.error(err);} - - _.each(before.dailys,function(d){ - var found = _.find(after.dailys,{id: d.id}); - if (found && !found.streak) found.streak = d.streak; - }) - - liveUsers.update({_id:after._id}, {$set:{dailys:after.dailys, migration:'20131225_restore_streaks'}, $inc:{_v:1}}); - //if (--count <= 0) console.log("DONE! " + after._id); - if (++count%1000 == 0) console.log(count); - if (after._id == '9') console.log('lefnire processed'); - }) -}); \ No newline at end of file diff --git a/migrations/20140119_task_creation_completion_dates.js b/migrations/20140119_task_creation_completion_dates.js deleted file mode 100644 index 9176b744ac..0000000000 --- a/migrations/20140119_task_creation_completion_dates.js +++ /dev/null @@ -1,8 +0,0 @@ -db.users.find({},{todos:1,dailys:1,rewards:1,habits:1}).forEach(function(user){ - _.each(user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards), function(t){ - t.dateCreated = t.created || new Date; - delete t.created; - if (t.type == 'todo' && t.completed) t.dateCompleted = new Date; - }) - db.users.update({_id:user._id}, {$set:{habits:user.habits,dailys:user.dailys,todos:user.todos,rewards:user.rewards}}); -}); diff --git a/migrations/20140130_birthdayEnd.js b/migrations/20140130_birthdayEnd.js deleted file mode 100644 index a9a8eb93bc..0000000000 --- a/migrations/20140130_birthdayEnd.js +++ /dev/null @@ -1 +0,0 @@ -db.users.update({},{$set:{'achievements.habitBirthday':true}},{multi:1}) diff --git a/migrations/20140130_birthdayStart.js b/migrations/20140130_birthdayStart.js deleted file mode 100644 index f022168bcd..0000000000 --- a/migrations/20140130_birthdayStart.js +++ /dev/null @@ -1,12 +0,0 @@ -db.users.update({},{$set:{ - 'items.food.Cake_Skeleton':1, - 'items.food.Cake_Base':1, - 'items.food.Cake_CottonCandyBlue':1, - 'items.food.Cake_CottonCandyPink':1, - 'items.food.Cake_Shade':1, - 'items.food.Cake_White':1, - 'items.food.Cake_Golden':1, - 'items.food.Cake_Zombie':1, - 'items.food.Cake_Desert':1, - 'items.food.Cake_Red':1 -}},{multi:1}) diff --git a/migrations/20140220_challenge_memberCount.js b/migrations/20140220_challenge_memberCount.js deleted file mode 100644 index 1b83408943..0000000000 --- a/migrations/20140220_challenge_memberCount.js +++ /dev/null @@ -1,3 +0,0 @@ -db.challenges.find({},{members:1}).forEach(function(chal){ - db.challenges.update({_id:chal._id}, {$set:{memberCount:chal.members.length}}); -}); diff --git a/migrations/20140301_missing_mysteries.js b/migrations/20140301_missing_mysteries.js deleted file mode 100644 index a244e3f3db..0000000000 --- a/migrations/20140301_missing_mysteries.js +++ /dev/null @@ -1,14 +0,0 @@ -db.users.update( - { - 'purchased.plan.dateCreated':{$gte:new Date('2014-02-22'),$lt:new Date('2014-02-29')}, - 'items.gear.owned.armor_mystery_201402':null, - 'items.gear.owned.head_mystery_201402': null, - 'items.gear.owned.back_mystery_201402': null, - 'purchased.plan.mysteryItems':{$nin:['armor_mystery_201402','head_mystery_201402','back_mystery_201402']} - }, - //{_id:1,'purchased.plan':1,'items.gear.owned':1} - {$push: {'purchased.plan.mysteryItems':{$each:['armor_mystery_201402','head_mystery_201402','back_mystery_201402']}}}, - {multi:true} -)/*.forEach(function(user){ - printjson(user); - });*/ diff --git a/migrations/20140610_missing_backer_mount.js b/migrations/20140610_missing_backer_mount.js deleted file mode 100644 index 5dd28af9da..0000000000 --- a/migrations/20140610_missing_backer_mount.js +++ /dev/null @@ -1 +0,0 @@ -db.users.update({'backer.tier':{$gt:69}},{$set:{'items.mounts.LionCub-Ethereal':true}},{multi:1}) \ No newline at end of file diff --git a/migrations/20140712_wiped_quest_membership.js b/migrations/20140712_wiped_quest_membership.js deleted file mode 100644 index f8985e7c77..0000000000 --- a/migrations/20140712_wiped_quest_membership.js +++ /dev/null @@ -1,11 +0,0 @@ -//mongo habitrpg node_modules/lodash/lodash.js ./migrations/20140712_wiped_quest_membership.js -db.groups.find({type:'party','quest.key':{$ne:null},'quest.active':true},{quest:1}).forEach(function(group){ - var activeMembers = _.reduce(group.quest.members, function(m,v,k){ - if (v===true) m.push(k); return m; - },[]); - db.users.update( - {_id:{$in: activeMembers}}, - {$set:{'party.quest.key':group.quest.key,'party.quest.completed':null}}, - {multi:true} - ); -}); diff --git a/migrations/20140803_remove_undefined_notifications.js b/migrations/20140803_remove_undefined_notifications.js deleted file mode 100644 index fe0d143a56..0000000000 --- a/migrations/20140803_remove_undefined_notifications.js +++ /dev/null @@ -1,13 +0,0 @@ -var _ = require('lodash'); - -db.users.find({}).forEach(function(user){ - var newNewMessages = {}; - - _.each(user.newMessages, function(val, key){ - if(key != "undefined"){ - newNewMessages[key] = val; - }; - }); - - db.users.update({_id: user._id}, {$set: {'newMessages': newNewMessages}}); -}); diff --git a/migrations/20140829_change_headAccessory_to_eyewear.js b/migrations/20140829_change_headAccessory_to_eyewear.js deleted file mode 100644 index 9940fb5013..0000000000 --- a/migrations/20140829_change_headAccessory_to_eyewear.js +++ /dev/null @@ -1,81 +0,0 @@ -// node .migrations/20140829_change_headAccessory_to_eyewear.js - -var migrationName = '20140829_change_headAccessory_to_eyewear'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -/** - * https://github.com/HabitRPG/habitrpg/issues/3645 - */ -var mongo = require('mongoskin'); -var _ = require('lodash'); -var liveUsers = mongo.db('localhost:27017/habitrpg2?auto_reconnect').collection('users'); - -var fields = {'migration':1, - 'items.gear.costume.headAccessory':1, - 'items.gear.equipped.headAccessory':1, - 'items.gear.owned.headAccessory_special_wondercon_black':1, - 'items.gear.owned.headAccessory_special_wondercon_red':1, - 'items.gear.owned.headAccessory_special_summerRogue':1, - 'items.gear.owned.headAccessory_special_summerWarrior':1 - }; - -var progressCount = 1000; -var count = 0; -liveUsers.findEach({ $and: [ - { migration: {$ne:migrationName} }, - { $or: [ - {'items.gear.owned.headAccessory_special_summerRogue': {'$exists':true}}, - {'items.gear.owned.headAccessory_special_summerWarrior':{'$exists':true}}, - {'items.gear.owned.headAccessory_special_wondercon_red':{'$exists':true}}, - {'items.gear.owned.headAccessory_special_wondercon_black':{'$exists':true}} - ]} -]}, fields, {batchSize:250}, function(err, user){ - count++; - if (!user) err = '!user'; - if (err) {return console.error(err);} - - var set = {'migration': migrationName}; - var unset = {}; - - var oldToNew = { - 'headAccessory_special_summerRogue': 'eyewear_special_summerRogue', - 'headAccessory_special_summerWarrior': 'eyewear_special_summerWarrior', - 'headAccessory_special_wondercon_red': 'eyewear_special_wondercon_red', - 'headAccessory_special_wondercon_black':'eyewear_special_wondercon_black' - }; - - // items.gear.costume, items.gear.equipped: - _.each(['costume','equipped'],function(type){ - _.each(oldToNew,function(newName,oldName){ - if (user.items.gear[type].headAccessory === oldName) { - unset['items.gear.'+type+'.headAccessory'] = ""; - set['items.gear.'+type+'.eyewear'] = newName; - } - }); - }); - - // items.gear.owned: - _.each(oldToNew,function(newName,oldName){ - if (oldName in user.items.gear.owned) { - unset['items.gear.owned.'+oldName] = ""; - set['items.gear.owned.'+newName] = user.items.gear.owned[oldName]; - } - }); - - //console.log(JSON.stringify(user, null, " ")); - //console.log("set: " + JSON.stringify(set, null, " ")); - //console.log("unset: " + JSON.stringify(unset, null, " ")); - - liveUsers.update({_id:user._id}, {$set:set, $unset:unset, $inc:{_v:1}}); - - if (count%progressCount == 0) console.log(count + ' ' + user._id); - if (user._id == '9') console.log('lefnire processed'); - if (user._id == authorUuid) console.log(authorName + ' processed'); -}); diff --git a/migrations/20140831_increase_gems_for_previous_contributions.js b/migrations/20140831_increase_gems_for_previous_contributions.js deleted file mode 100644 index 164dda444b..0000000000 --- a/migrations/20140831_increase_gems_for_previous_contributions.js +++ /dev/null @@ -1,131 +0,0 @@ -// IMPORTANT: -// -// run like this to capture all output: -// -// node 20140831_increase_gems_for_previous_contributions.js > 20140831_increase_gems_for_previous_contributions_output.txt - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var migrationName = '20140831_increase_gems_for_previous_contributions'; - -/** - * https://github.com/HabitRPG/habitrpg/issues/3933 - * Increase Number of Gems for Contributors - * author: Alys (d904bd62-da08-416b-a816-ba797c9ee265) - * - * Increase everyone's gems per their contribution level. - * Originally they were given 2 gems per tier. - * Now they are given 3 gems per tier for tiers 1,2,3 - * and 4 gems per tier for tiers 4,5,6,7 - * So that means an EXTRA 1 for tier 1, - * 2 for tier 2, - * 3 for tier 3, - * 5 for tier 4, - * 7 for tier 5, - * 9 for tier 6, - * 11 for tier 7, - * 11 for tier 8 (moderators = tier 7 + admin privileges), - * none for tier 9 (staff) - */ - -var mongo = require('mongoskin'); -var _ = require('lodash'); - - -var dbUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); - - -var query = { - 'contributor.level': {$gt: 0, $lt: 9}, - 'migration': {$ne: migrationName} -}; - -var fields = { - 'migration':1, - 'contributor.level':1, - 'balance':1 -}; - -var userResults = {}; // each key is a UUID, each value is a string - // describing what changed for that user - -console.warn('Updating users...'); -var progressCount = 50; -var count = 0; -dbUsers.findEach(query, fields, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All users found. Fetching final balances...'); - return fetchFinalBalances(); - } - count++; - - var set = {'migration': migrationName}; - - var tier = user.contributor.level; - var extraGems = tier; // tiers 1,2,3 - if (tier > 3) { extraGems = 3 + (tier - 3) * 2; } - if (tier == 8) { extraGems = 11; } - var extraBalance = extraGems / 4; - set['balance'] = user.balance + extraBalance; - - // Capture current state of user: - userResults[user._id] = - user._id + ' ' + ':\n' + - ' contrib tier : ' + tier + '\n' + - ' balance before : ' + user.balance + '\n' + - ' balance (gems) added : ' + extraBalance + ' (' + - extraGems + ')' + '\n' + - ' expected balance after: ' + (user.balance + extraBalance) + '\n'; - - // Update user: - dbUsers.update({_id:user._id}, {$set:set, $inc:{_v:1}}); - if (count%progressCount == 0) console.warn(count + ' ' + user._id); -}); - - -function fetchFinalBalances() { - var query = {_id: {$in: Object.keys(userResults)}}; - var fields = { - 'balance':1, - }; - - var count1 = 0; - dbUsers.findEach(query, fields, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All final balances found.'); - return displayData(); - } - count1++; - userResults[user._id] = userResults[user._id] + - user._id + ' ' + ':\n' + - ' actual balance after : ' + user.balance + '\n'; - if (count1%progressCount == 0) console.warn(count1 + ' ' + user._id); - }); -} - - -function displayData() { - _.each(userResults, function(text, uuid) { - console.log(text); // text contains uuid - }); - console.log('\n' + count + - ' users processed (should be roughly 335 according to the Hall)\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20140914_upgrade_admin_contrib_tiers.js b/migrations/20140914_upgrade_admin_contrib_tiers.js deleted file mode 100644 index 7962b7dfde..0000000000 --- a/migrations/20140914_upgrade_admin_contrib_tiers.js +++ /dev/null @@ -1,79 +0,0 @@ -var migrationName = '20140914_upgrade_admin_contrib_tiers'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -/** - * https://github.com/HabitRPG/habitrpg/issues/3801 - * Convert Tier 8 contributors to Tier 9 (staff) (all current Tier 8s are admins). - * Convert Tier 7 contributors with admin flag to Tier 8 (moderators). - */ - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); - -var query = - { 'contributor.level':{$gte:7}, 'contributor.admin':true, 'migration': {$ne: migrationName} }; - -var fields = {'migration':1, - 'contributor.admin':1, - 'contributor.level':1, - 'auth.local.username':1, - 'profile.name':1, - }; - -var userResults = {}; // each key is a UUID, each value is a username; - // contains only the users changed - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - var set = {'migration': migrationName}; - var inc = {'contributor.level':1, _v:1}; - - userResults[user._id] = user.profile.name; - - dbUsers.update({_id:user._id}, {$set:set, $inc:inc}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); - if (user._id == '9' ) console.warn('lefnire' + ' processed'); -}); - - -function displayData() { - console.log('users modified:'); - _.each(userResults, function(name, uuid) { - console.log(name); - }); - console.warn('\n' + count + - ' users processed (should be 11 according to the Hall)\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20140922_free_candy.js b/migrations/20140922_free_candy.js deleted file mode 100644 index 77cc221462..0000000000 --- a/migrations/20140922_free_candy.js +++ /dev/null @@ -1,18 +0,0 @@ -db.users.update( - {}, - { - $inc: { - 'items.food.Candy_Base':1, - 'items.food.Candy_CottonCandyBlue':1, - 'items.food.Candy_CottonCandyPink':1, - 'items.food.Candy_Desert':1, - 'items.food.Candy_Golden':1, - 'items.food.Candy_Red':1, - 'items.food.Candy_Shade':1, - 'items.food.Candy_Skeleton':1, - 'items.food.Candy_White':1, - 'items.food.Candy_Zombie':1 - } - }, - {multi:1} -); \ No newline at end of file diff --git a/migrations/20141006_jackolantern_pet.js b/migrations/20141006_jackolantern_pet.js deleted file mode 100644 index f09c38d9f3..0000000000 --- a/migrations/20141006_jackolantern_pet.js +++ /dev/null @@ -1 +0,0 @@ -db.users.update({_id:'9'},{$set:{'items.pets.JackOLantern-Base':5, 'flags.newStuff':true}}, {multi:true}); \ No newline at end of file diff --git a/migrations/20141126_turkey_mounts.js b/migrations/20141126_turkey_mounts.js deleted file mode 100644 index 1270390c06..0000000000 --- a/migrations/20141126_turkey_mounts.js +++ /dev/null @@ -1,11 +0,0 @@ -db.users.update( - {'items.pets.Turkey-Base':{$ne:null}}, - {$set:{'items.mounts.Turkey-Base':true}}, - {multi:1} -) - -db.users.update( - {'items.pets.Turkey-Base':null}, - {$set:{'items.pets.Turkey-Base':5}}, - {multi:1} -) \ No newline at end of file diff --git a/migrations/20141211_NaN_consecutives.js b/migrations/20141211_NaN_consecutives.js deleted file mode 100644 index 2822df0267..0000000000 --- a/migrations/20141211_NaN_consecutives.js +++ /dev/null @@ -1,4 +0,0 @@ -db.users.update({'purchased.plan.consecutive.count':NaN}, {$set:{'purchased.plan.consecutive.count':0}}, {multi:1}); -db.users.update({'purchased.plan.consecutive.offset':NaN}, {$set:{'purchased.plan.consecutive.offset':0}}, {multi:1}); -db.users.update({'purchased.plan.consecutive.gemCapExtra':NaN}, {$set:{'purchased.plan.consecutive.gemCapExtra':0}}, {multi:1}); -db.users.update({'purchased.plan.consecutive.trinkets':NaN}, {$set:{'purchased.plan.consecutive.trinkets':0}}, {multi:1}); \ No newline at end of file diff --git a/migrations/20141230_new_years_hats.js b/migrations/20141230_new_years_hats.js deleted file mode 100644 index 595027be0a..0000000000 --- a/migrations/20141230_new_years_hats.js +++ /dev/null @@ -1,11 +0,0 @@ -db.users.update( - {'items.gear.owned.head_special_nye':{$ne:null}}, - {$set:{'items.gear.owned.head_special_nye2014':false}}, - {multi:1} -) - -db.users.update( - {'items.gear.owned.head_special_nye':null}, - {$set:{'items.gear.owned.head_special_nye':false}}, - {multi:1} -) diff --git a/migrations/20150107_plan_dateUpdated_null.js b/migrations/20150107_plan_dateUpdated_null.js deleted file mode 100644 index 6e03b41a55..0000000000 --- a/migrations/20150107_plan_dateUpdated_null.js +++ /dev/null @@ -1,8 +0,0 @@ -db.users.update( - {'purchased.plan.customerId':{$ne:null}, 'purchased.plan.dateUpdated':null}, - { - $set: {'purchased.plan.dateUpdated': new Date('12/01/2014')}, - $unset: {'purchased.plan.datedUpdated':''} - }, - {multi:true} -); diff --git a/migrations/20150124_mountmaster_fix.js b/migrations/20150124_mountmaster_fix.js deleted file mode 100644 index 874faea22c..0000000000 --- a/migrations/20150124_mountmaster_fix.js +++ /dev/null @@ -1,88 +0,0 @@ -var migrationName = '20150124_mountmaster_fix.js'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -/** - * https://github.com/HabitRPG/habitrpg/pull/4374#issuecomment-71038795 - * Convert false to null for mounts that used to be owned. - */ - -var dbserver = 'localhost:27017' // CHANGE THIS FOR PRODUCTION DATABASE - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/habitrpg?auto_reconnect').collection('users'); - -var query = { - 'items.mounts':{$exists:true} - }; - -var fields = { - 'items.mounts':1 - }; - -var animals = [ "Wolf-Base", "Wolf-White", "Wolf-Desert", "Wolf-Red", "Wolf-Shade", "Wolf-Skeleton", "Wolf-Zombie", "Wolf-CottonCandyPink", "Wolf-CottonCandyBlue", "Wolf-Golden", "TigerCub-Base", "TigerCub-White", "TigerCub-Desert", "TigerCub-Red", "TigerCub-Shade", "TigerCub-Skeleton", "TigerCub-Zombie", "TigerCub-CottonCandyPink", "TigerCub-CottonCandyBlue", "TigerCub-Golden", "PandaCub-Base", "PandaCub-White", "PandaCub-Desert", "PandaCub-Red", "PandaCub-Shade", "PandaCub-Skeleton", "PandaCub-Zombie", "PandaCub-CottonCandyPink", "PandaCub-CottonCandyBlue", "PandaCub-Golden", "LionCub-Base", "LionCub-White", "LionCub-Desert", "LionCub-Red", "LionCub-Shade", "LionCub-Skeleton", "LionCub-Zombie", "LionCub-CottonCandyPink", "LionCub-CottonCandyBlue", "LionCub-Golden", "Fox-Base", "Fox-White", "Fox-Desert", "Fox-Red", "Fox-Shade", "Fox-Skeleton", "Fox-Zombie", "Fox-CottonCandyPink", "Fox-CottonCandyBlue", "Fox-Golden", "FlyingPig-Base", "FlyingPig-White", "FlyingPig-Desert", "FlyingPig-Red", "FlyingPig-Shade", "FlyingPig-Skeleton", "FlyingPig-Zombie", "FlyingPig-CottonCandyPink", "FlyingPig-CottonCandyBlue", "FlyingPig-Golden", "Dragon-Base", "Dragon-White", "Dragon-Desert", "Dragon-Red", "Dragon-Shade", "Dragon-Skeleton", "Dragon-Zombie", "Dragon-CottonCandyPink", "Dragon-CottonCandyBlue", "Dragon-Golden", "Cactus-Base", "Cactus-White", "Cactus-Desert", "Cactus-Red", "Cactus-Shade", "Cactus-Skeleton", "Cactus-Zombie", "Cactus-CottonCandyPink", "Cactus-CottonCandyBlue", "Cactus-Golden", "BearCub-Base", "BearCub-White", "BearCub-Desert", "BearCub-Red", "BearCub-Shade", "BearCub-Skeleton", "BearCub-Zombie", "BearCub-CottonCandyPink", "BearCub-CottonCandyBlue", "BearCub-Golden" ]; // all Gen1 mounts - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - var mounts = user.items.mounts; - var changed = false; - for(var a in animals) { - if(mounts[animals[a]] == false) { - mounts[animals[a]] = null; - changed = true; - } - } - - if (changed) { - dbUsers.update( - { _id: user._id}, - { - $set: { "migration": migrationName, - "items.mounts" : mounts - } - } - ); - } - - // var set = {'migration': migrationName}; - // var inc = {'xyz':1, _v:1}; - // dbUsers.update({_id:user._id}, {$set:set, $inc:inc}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); - if (user._id == '9' ) console.warn('lefnire' + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20150130_birthday_goodies.js b/migrations/20150130_birthday_goodies.js deleted file mode 100644 index 6c7c2e08c5..0000000000 --- a/migrations/20150130_birthday_goodies.js +++ /dev/null @@ -1,36 +0,0 @@ -db.users.update( - {'items.gear.owned.armor_special_birthday':{$ne:null}}, - {$set:{'items.gear.owned.armor_special_birthday2015':false}}, - {multi:1} -) - -db.users.update( - {'items.gear.owned.armor_special_birthday':null}, - {$set:{'items.gear.owned.armor_special_birthday':false}}, - {multi:1} -) - -db.users.update({},{$inc:{ - 'items.food.Cake_Skeleton':1, - 'items.food.Cake_Base':1, - 'items.food.Cake_CottonCandyBlue':1, - 'items.food.Cake_CottonCandyPink':1, - 'items.food.Cake_Shade':1, - 'items.food.Cake_White':1, - 'items.food.Cake_Golden':1, - 'items.food.Cake_Zombie':1, - 'items.food.Cake_Desert':1, - 'items.food.Cake_Red':1 -}},{multi:1}) - -db.users.update( - {'achievements.habitBirthday':true}, - {$set:{'achievements.habitBirthdays':1}}, - {multi:1} -) - -db.users.update( - {}, - {$inc:{'achievements.habitBirthdays':1}}, - {multi:1} -) \ No newline at end of file diff --git a/migrations/20150131_birthday_goodies_fix_remove_robe.js b/migrations/20150131_birthday_goodies_fix_remove_robe.js deleted file mode 100644 index 54b39030ba..0000000000 --- a/migrations/20150131_birthday_goodies_fix_remove_robe.js +++ /dev/null @@ -1,78 +0,0 @@ -var migrationName = '20150131_birthday_goodies_fix__one_birthday__1'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -/* - * remove new birthday robes and second achievement from people who shouldn't have them - */ - -var dbserver = 'localhost:27017' // CHANGE THIS FOR PRODUCTION DATABASE - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/habitrpg?auto_reconnect').collection('users'); - - // 'auth.timestamps.created':{$gt:new Date('2014-02-01')}, -var query = { - 'achievements.habitBirthdays':1, - 'auth.timestamps.loggedin':{$gt:new Date('2014-12-20')} - }; - - // '_id': 'c03e41bd-501f-438c-9553-a7afdf52a08c', - // 'achievements.habitBirthday':{$exists:false}, - // 'items.gear.owned.armor_special_birthday2015':1 - -var fields = { - // 'auth.timestamps.created':1, - // 'achievements.habitBirthday':1, - // 'achievements.habitBirthdays':1, - 'items.gear.owned.armor_special_birthday2015':1, - // 'items.gear.owned.armor_special':1 - }; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - var unset = {'items.gear.owned.armor_special_birthday2015': 1}; - // var set = {'migration':migrationName, 'achievements.habitBirthdays':1 }; - // var inc = {'xyz':1, _v:1}; - dbUsers.update({_id:user._id}, {$unset:unset}); // , $inc:inc}); - // dbUsers.update({_id:user._id}, {$unset:unset, $set:set}); - // console.warn(user.auth.timestamps.created); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); - if (user._id == '9' ) console.warn('lefnire' + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20150201_convert_creation_date_from_string_to_object.js b/migrations/20150201_convert_creation_date_from_string_to_object.js deleted file mode 100644 index 72a31e8020..0000000000 --- a/migrations/20150201_convert_creation_date_from_string_to_object.js +++ /dev/null @@ -1,112 +0,0 @@ -var migrationName = '20150201_convert_creation_date_from_string_to_object__no_date_recent_signup'; -//// var migrationName = '20150201_convert_creation_date_from_string_to_object'; - -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -/* - * For users that have no value for auth.timestamps.created, assign them - * a recent value. - * - * NOTE: - * Before this script was used as described above, it was first used to - * find all users that have a auth.timestamps.created field that is a string - * rather than a date object and set it to be a date object. The code used - * for this has been commented out with four slashes: //// - * - * https://github.com/HabitRPG/habitrpg/issues/4601#issuecomment-72339846 - */ - -var dbserver = 'localhost:27017' // CHANGE THIS FOR PRODUCTION DATABASE - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var mongo = require('mongoskin'); -var _ = require('lodash'); -var moment = require('moment'); - -var dbUsers = mongo.db(dbserver + '/habitrpg?auto_reconnect').collection('users'); - -var uuidArrayRecent=[ // recent users with no creation dates -'1a0d4b75-73ed-4937-974d-d504d6398884', -'1c7ebe27-1250-4f95-ba10-965580adbfd7', -'5f972121-4a6d-411c-95e9-7093d3e89b66', -'ae85818a-e336-4ccd-945e-c15cef975102', -'ba273976-d9fc-466c-975f-38559d34a824', -]; - -var query = { - '_id':{$in: uuidArrayRecent} - //// 'auth':{$exists:true}, - //// 'auth.timestamps':{$exists:true}, - //// 'auth.timestamps.created':{$not: {$lt:new Date('2018-01-01')}} - }; - -var fields = { - '_id':1, - 'auth.timestamps.created':1 - }; - // 'achievements.habitBirthdays':1 - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - //// var oldDate = user.auth.timestamps.created; - //// var newDate = moment(oldDate).toDate(); - var oldDate = 'none'; - var newDate = moment('2015-01-11').toDate(); - console.warn(user._id + ' == ' + oldDate + ' == ' + newDate); - - //// var set = { 'migration': migrationName, - //// 'auth.timestamps.created': newDate, - //// 'achievements.habitBirthdays': 2, - //// 'items.gear.owned.head_special_nye':true, - //// 'items.gear.owned.head_special_nye2014':true, - //// 'items.gear.owned.armor_special_birthday':true, - //// 'items.gear.owned.armor_special_birthday2015':true, - //// }; - - var set = { 'migration': migrationName, - 'auth.timestamps.created': newDate, - 'achievements.habitBirthdays': 1, - 'items.gear.owned.armor_special_birthday':true, - }; - - // var unset = {'items.gear.owned.armor_special_birthday2015': 1}; - // var inc = {'xyz':1, _v:1}; - dbUsers.update({_id:user._id}, {$set:set}); - // dbUsers.update({_id:user._id}, {$unset:unset, $set:set, $inc:inc}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); - if (user._id == '9' ) console.warn('lefnire' + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20150201_recapture_emails_phase_update.js b/migrations/20150201_recapture_emails_phase_update.js deleted file mode 100644 index 51fd73a6fa..0000000000 --- a/migrations/20150201_recapture_emails_phase_update.js +++ /dev/null @@ -1,7 +0,0 @@ -db.users.update({ - 'flags.recaptureEmailsPhase': { - $gt: 0 - } -},{$inc:{ - 'flags.recaptureEmailsPhase':1 -}},{multi:1}) \ No newline at end of file diff --git a/migrations/20150218_interactive_tour.js b/migrations/20150218_interactive_tour.js deleted file mode 100644 index 91769742ed..0000000000 --- a/migrations/20150218_interactive_tour.js +++ /dev/null @@ -1,10 +0,0 @@ -db.users.update({},{$set:{ - 'flags.tour.intro':-2, - //'flags.tour.classes':-2, - 'flags.tour.stats':-2, - 'flags.tour.tavern':-2, - 'flags.tour.party':-2, - 'flags.tour.guilds':-2, - 'flags.tour.challenges':-2, - 'flags.tour.market':-2 -}},{multi:1}) \ No newline at end of file diff --git a/migrations/20150224_force_resting_in_inn.js b/migrations/20150224_force_resting_in_inn.js deleted file mode 100644 index 1b704fb411..0000000000 --- a/migrations/20150224_force_resting_in_inn.js +++ /dev/null @@ -1,64 +0,0 @@ -var migrationName = '20150224_force_resting_in_inn'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -/* - * force all active players to rest in the inn due to massive server fail - */ - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var dbserver = 'localhost:27017' // CHANGE THIS FOR PRODUCTION DATABASE - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/habitrpg?auto_reconnect').collection('users'); - -var query = { - 'auth.timestamps.loggedin':{$gt:new Date('2015-02-22')} - }; - -var fields = { - 'preferences.sleep':1, - }; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - var set = {'migration':migrationName, 'preferences.sleep':1 }; - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); - if (user._id == '9' ) console.warn('lefnire' + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20150310_survey_achievements.js b/migrations/20150310_survey_achievements.js deleted file mode 100644 index 9678b6c3c4..0000000000 --- a/migrations/20150310_survey_achievements.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.update( - {'achievements.helpedHabit':true}, - {$set:{'achievements.habitSurveys':1}}, - {multi:1} -) \ No newline at end of file diff --git a/migrations/20150604_ultimateGearSets.js b/migrations/20150604_ultimateGearSets.js deleted file mode 100644 index 64ff0142d3..0000000000 --- a/migrations/20150604_ultimateGearSets.js +++ /dev/null @@ -1,138 +0,0 @@ -// var migrationName = '20150604_ultimateGearSets'; -// var authorName = 'Sabe'; // in case script author needs to know when their ... -// var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -var migrationName = '20150620_ultimateGearSets'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -/* - * grant the new ultimateGearSets achievement for existing users' collected equipment - * - * - * Changed by Alys on 20150620 to assign false values to - * 'achievements.ultimateGearSets' when true values are not appropriate, - * because of https://github.com/HabitRPG/habitrpg/issues/5427 - * - * Minimal changes were made so the code isn't as efficient or clean - * as it could be, but it's (hopefully) one-use-only and minimal changes - * means minimal new testing. - */ - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var dbserver = 'localhost:27017' // FOR TEST DATABASE -// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379' // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -var fields = { - 'achievements.ultimateGearSets':1, - 'items.gear.owned':1 -}; - - -// Changes 20150620: All users have to be processed now (non-achievers need -// false values). -var query = { -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - var achievements = {}; - var changeUser = false; - // Changes 20150620: 'changeUser' now indicates that the user must have the - // Enchanted Armoire unlocked. - if ( (typeof user.items.gear.owned.weapon_wizard_6 !== 'undefined') - && (typeof user.items.gear.owned.armor_wizard_5 !== 'undefined') - && (typeof user.items.gear.owned.head_wizard_5 !== 'undefined') - ) { - achievements['wizard'] = true; - changeUser = true; - } - else { - // Changes 20150620: false added for all classes (here and below) - achievements['wizard'] = false; - } - - if ( (typeof user.items.gear.owned.weapon_warrior_6 !== 'undefined') - && (typeof user.items.gear.owned.armor_warrior_5 !== 'undefined') - && (typeof user.items.gear.owned.head_warrior_5 !== 'undefined') - && (typeof user.items.gear.owned.shield_warrior_5 !== 'undefined') - ) { - achievements['warrior'] = true; - changeUser = true; - } - else { - achievements['warrior'] = false; - } - - if ( (typeof user.items.gear.owned.weapon_healer_6 !== 'undefined') - && (typeof user.items.gear.owned.armor_healer_5 !== 'undefined') - && (typeof user.items.gear.owned.head_healer_5 !== 'undefined') - && (typeof user.items.gear.owned.shield_healer_5 !== 'undefined') - ) { - achievements['healer'] = true; - changeUser = true; - } - else { - achievements['healer'] = false; - } - - if ( (typeof user.items.gear.owned.weapon_rogue_6 !== 'undefined') - && (typeof user.items.gear.owned.armor_rogue_5 !== 'undefined') - && (typeof user.items.gear.owned.head_rogue_5 !== 'undefined') - && (typeof user.items.gear.owned.shield_rogue_6 !== 'undefined') - ) { - achievements['rogue'] = true; - changeUser = true; - } - else { - achievements['rogue'] = false; - } - - // Changes 20150620: $set is now run for all users. - var set = {'migration':migrationName, 'achievements.ultimateGearSets':achievements}; - if (changeUser) { // user has at least one Ultimate Gear achievement - set['flags.armoireEnabled'] = true; - } - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); - if (user._id == '9' ) console.warn('lefnire' + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20150731_purple_gryphon.js b/migrations/20150731_purple_gryphon.js deleted file mode 100644 index 8e44361ae0..0000000000 --- a/migrations/20150731_purple_gryphon.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.update( - {}, - {$set:{'items.mounts.Gryphon-RoyalPurple':true}}, - {multi:true} -); diff --git a/migrations/20150731_veteran_tiger.js b/migrations/20150731_veteran_tiger.js deleted file mode 100644 index 55e46fb1af..0000000000 --- a/migrations/20150731_veteran_tiger.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.update( - {'items.pets.Wolf-Veteran':{$ne:null}}, - {$set:{'items.pets.Tiger-Veteran':5}}, - {multi:true} -); diff --git a/migrations/20150731_veteran_wolf.js b/migrations/20150731_veteran_wolf.js deleted file mode 100644 index 9d31d4591d..0000000000 --- a/migrations/20150731_veteran_wolf.js +++ /dev/null @@ -1,7 +0,0 @@ -// Run after the Veteran Tiger script, not before! - -db.users.update( - {'items.pets.Wolf-Veteran':{$exists:false}}, - {$set:{'items.pets.Wolf-Veteran':5}}, - {multi:true} -); diff --git a/migrations/20150906_groups_fix_leaders.js b/migrations/20150906_groups_fix_leaders.js deleted file mode 100644 index 0a1a226c91..0000000000 --- a/migrations/20150906_groups_fix_leaders.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Make sure leaders are existing users - */ - -var mongo = require('mongoskin'); -var async = require('async'); - -var dbserver = 'url'; -var dbname = 'dbname'; -var countGroups = 0; -var countUsers = 0; - -var db = mongo.db(dbserver + '/' + dbname + '?auto_reconnect'); -var dbUsers = db.collection('users'); -var dbGroups = db.collection('groups'); - -console.log('Begins work on db'); - -function findGroups(gt){ - var query = {}; - if(gt) query._id = {$gt: gt}; - - console.log(query) - - dbGroups.find(query, { - fields: {_id: 1, members: 1, leader: 1}, - limit: 10000, - sort: { - _id: 1 - } - }).toArray(function(err, groups){ - if(err) throw err; - - var lastGroup = null; - if(groups.length === 10000){ - lastGroup = groups[groups.length - 1]; - } - - async.eachLimit(groups, 30, function(group, cb1){ - countGroups++; - console.log('Group: ', countGroups, group._id); - - var members = group.members; - - dbUsers.findOne({_id: group.leader}, {fields: {_id: 1}}, function(err, user){ - if(err) return cb1(err); - - // If leader has deleted account - if(!user && (group._id !== 'habitrpg') && members && members[0]) { - dbGroups.update({ - _id: group._id - }, { - $set: { - // Set first user as new leader - leader: members[0] - } - }, { - multi: false - }, function(err, res){ - if(err) return cb1(err); - - console.log('Updated: ', res); - return cb1(); - }); - }else{ - return cb1(); - } - }); - }, function(err){ - if(err) throw err; - - if(lastGroup && lastGroup._id){ - findGroups(lastGroup._id); - } - }); - }); -}; - -findGroups(); \ No newline at end of file diff --git a/migrations/20150906_groups_remove_deleted_users.js b/migrations/20150906_groups_remove_deleted_users.js deleted file mode 100644 index 96146a8c0e..0000000000 --- a/migrations/20150906_groups_remove_deleted_users.js +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Remove deleted accounts from groups - */ - -var mongo = require('mongoskin'); -var async = require('async'); - -var dbserver = 'url'; -var dbname = 'dbname'; -var countGroups = 0; -var countUsers = 0; - -var db = mongo.db(dbserver + '/' + dbname + '?auto_reconnect'); -var dbUsers = db.collection('users'); -var dbGroups = db.collection('groups'); - -console.log('Begins work on db'); - -function findGroups(gt){ - var query = {}; - if(gt) query._id = {$gt: gt}; - - console.log(query) - - dbGroups.find(query, { - fields: {_id: 1, members: 1}, - limit: 10000, - sort: { - _id: 1 - } - }).toArray(function(err, groups){ - if(err) throw err; - - var lastGroup = null; - if(groups.length === 10000){ - lastGroup = groups[groups.length - 1]; - } - - async.eachLimit(groups, 3, function(group, cb1){ - countGroups++; - console.log('Group: ', countGroups, group._id); - - var members = group.members; - - // Remove users who deleted their account - async.eachLimit(members, 15, function(member, cb2){ - dbUsers.findOne({_id: member}, {fields: {_id: 1}}, function(err, user){ - if(err) return cb2(err); - - if(!user){ - countUsers++; - console.log('User removed n. ', countUsers, 'user id ', member, 'group id ', group._id); - - dbGroups.update({ - _id: group._id - }, { - $pull: {members: member}, - $inc: {memberCount: -1} - }, { - multi: false - }, function(err, res){ - if(err) return cb2(err); - - console.log('Updated: ', res); - return cb2(); - }); - }else{ - cb2(); - } - }); - }, function(err){ - if(err) return cb1(err); - - cb1(); - }); - - }, function(err){ - if(err) throw err; - - if(lastGroup && lastGroup._id){ - findGroups(lastGroup._id); - } - }); - }); -}; - -findGroups(); \ No newline at end of file diff --git a/migrations/20150906_groups_remove_empty.js b/migrations/20150906_groups_remove_empty.js deleted file mode 100644 index 44da0b600c..0000000000 --- a/migrations/20150906_groups_remove_empty.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Remove empty private groups - */ - -var mongo = require('mongoskin'); - -var dbserver = 'url'; -var dbname = 'name'; - -var db = mongo.db(dbserver + '/' + dbname + '?auto_reconnect'); -var dbGroups = db.collection('groups'); - -console.log('Begins work on db'); - -dbGroups.findEach({ - memberCount: 0, -}, {_id: 1}, function(err, res){ - if(err) throw err; - - console.log(res); -}); \ No newline at end of file diff --git a/migrations/20150906_sync_groups_with_firebase.js b/migrations/20150906_sync_groups_with_firebase.js deleted file mode 100644 index d7b4f12174..0000000000 --- a/migrations/20150906_sync_groups_with_firebase.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Sync groups with Firebase - */ - -var mongo = require('mongoskin'); -var Firebase = require('Firebase'); - -var dbserver = 'mongodb://url'; -var dbname = 'db'; - -var db = mongo.db(dbserver + '/' + dbname + '?auto_reconnect'); -var dbGroups = db.collection('groups'); -var countGroups = 0; - -var firebaseRef = new Firebase('https://' + 'firebase-app' + '.firebaseio.com'); - -// TODO handle sync errors with firebase? -firebaseRef.authWithCustomToken('firebase-secret', function(err, authData){ - if(err) throw new Error('Impossible to authenticate Firebase'); - - console.log('Firebase connected, begins work on db'); - - dbGroups.findEach({}, {_id: 1, members: 1}, {batchSize: 100}, function(err, group){ - if(err) throw err; - if(group._id !== 'habitrpg') return; - - countGroups++; - console.log('Group: ', countGroups); - - firebaseRef.child('rooms/' + group._id) - .set({ - name: group.name - }); - - group.members.forEach(function(member){ - firebaseRef.child('members/' + group._id + '/' + userId) - .set(true); - - firebaseRef.child('users/' + member + '/rooms/' + group._id) - .set(true); - }); - }); -}); \ No newline at end of file diff --git a/migrations/20151013_jackolanterns.js b/migrations/20151013_jackolanterns.js deleted file mode 100644 index 67ff0ac9a2..0000000000 --- a/migrations/20151013_jackolanterns.js +++ /dev/null @@ -1,67 +0,0 @@ -var migrationName = '20151013_jackolanterns.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Jack-O'-Lantern mounts to users who already have the pet version, award pet if they don't - */ - -var dbserver = 'localhost:27017'; // FOR TEST DATABASE -// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.pets.JackOLantern-Base':1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - // specify user data to change: - var set = {}; - if (user.items.pets['JackOLantern-Base']) { - set = {'migration':migrationName, 'items.mounts.JackOLantern-Base':true}; - } else { - set = {'migration':migrationName, 'items.pets.JackOLantern-Base':5}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20151021_usernames_emails_lowercase.js b/migrations/20151021_usernames_emails_lowercase.js deleted file mode 100644 index b40aaad9d7..0000000000 --- a/migrations/20151021_usernames_emails_lowercase.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Migrate email to lowerCase version and add auth.local.lowerCaseUsername email - */ - -var mongo = require('mongoskin'); -var async = require('async'); - -var dbserver = 'url'; -var dbname = 'dbname'; -var countUsers = 0; - -var db = mongo.db(dbserver + '/' + dbname + '?auto_reconnect'); -var dbUsers = db.collection('users'); - -console.log('Begins work on db'); - -function findUsers(gt){ - var query = {}; - if(gt) query._id = {$gt: gt}; - - console.log(query) - - dbUsers.find(query, { - fields: {_id: 1, auth: 1}, - limit: 10000, - sort: { - _id: 1 - } - }).toArray(function(err, users){ - if(err) throw err; - - var lastUser = null; - if(users.length === 10000){ - lastUser = users[users.length - 1]; - } - - async.eachLimit(users, 20, function(user, cb){ - countUsers++; - console.log('User: ', countUsers, user._id); - - var update = { - $set: {} - }; - - if(user.auth && user.auth.local) { - if(user.auth.local.username) update['$set']['auth.local.lowerCaseUsername'] = user.auth.local.username.toLowerCase(); - if(user.auth.local.email) update['$set']['auth.local.email'] = user.auth.local.email.toLowerCase(); - } - - dbUsers.update({ - _id: user._id - }, update, cb); - }, function(err){ - if(err) throw err; - - if(lastUser && lastUser._id){ - findUsers(lastUser._id); - } - }); - }); -}; - -findUsers(); diff --git a/migrations/20151105_tutorial_flags.js b/migrations/20151105_tutorial_flags.js deleted file mode 100644 index 6af069965c..0000000000 --- a/migrations/20151105_tutorial_flags.js +++ /dev/null @@ -1,63 +0,0 @@ -var migrationName = '20151105_tutorial_flags_v1'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done - -/* - * set flags.tutorial.ios and flags.tutorial.main flags to true in preparation - * for the release of a new iOS tutorial - * - */ - -// var dbserver = 'localhost:27017' // FOR TEST DATABASE -var dbserver = 'alys:@ds031379-a0.mongolab.com:31379' // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -var fields = { -}; - - -var query = { - 'auth.timestamps.loggedin':{$gt:new Date('2015-10-20')} -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - // var set = {'migration':migrationName, 'flags.tutorial.ios':true, 'flags.tutorial.main':true }; - var set = {'migration':migrationName, 'flags.tutorial.ios':{} }; - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20151116_costume_contest_award.js b/migrations/20151116_costume_contest_award.js deleted file mode 100644 index 25891f9215..0000000000 --- a/migrations/20151116_costume_contest_award.js +++ /dev/null @@ -1,102 +0,0 @@ -var migrationName = '20151116_costume_contest.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Costume Contest achievement to 2015 winners - */ - -var dbserver = 'localhost:27017'; // FOR TEST DATABASE -// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - _id: { - $in: [ - 'e411dab3-a4ca-414d-bdbd-b6940b3bdeb3', - '35ced5cc-c33a-45c8-93dc-16000ee66fde', - 'ab3f0549-7247-4fd5-975b-efcff98c79c3', - 'b1261fd2-eb25-46b4-97a9-ae7a0dc8a131', - '1f27893f-3808-4724-9725-f46dab93faca', - '216a0c23-6afd-4a5e-b434-d386a10862a2', - '2d6ef231-50b4-4a22-90e7-45eb97147a2c', - '98b8cf4f-89bd-4b0a-988d-02629a217232', - 'c5183dfa-c741-43ce-935e-c6d89b41a030', - '262a7afb-6b57-4d81-88e0-80d2e9f6cbdc', - '33991e0a-de55-4986-ac81-af78491a84de', - '7adf6ada-3c05-4054-b5df-fa7d49d3b9eb', - '235a1cbd-48c5-41b1-afb4-59d2f8645c57', - 'b7617a61-188b-4332-bf4d-32268fa77f2b', - '672c1ce0-9f47-44f0-a3f3-8cc3c6c5a9cb', - 'd0a3217a-7b92-48d6-b39a-b1b1be96702e', - '5ef910dc-1d22-47d9-aa38-a60132c60679', - '370a44c8-e94a-4a2c-91f2-33166926db1f', - '1b0b3ef3-28bd-4046-a49b-e1c83e281baf', - '75b93321-66b9-49bd-9076-052499c1d2bf', - 'd97516e4-81d0-4f60-bf03-95f7330925ab', - '3e13cc79-de38-420d-822e-9e9da309ce6b', - '0e471dc1-ecb0-4388-a891-b873a237d2cf', - 'ca3da398-4f73-4304-b838-af3669ed4cbb', - '44cdf105-8bda-4197-9d1a-1bcb83b4dc84', - '5419830c-b837-4573-ae82-4718ab95b7f1', - 'ac6fbe37-b0dc-40d8-ba14-77dde66fbfa8', - '8789ba18-a498-46b9-b367-3b929a0acb94', - '52fce1a9-9b0a-4e26-95dc-adc12f52e752', - '21bf71ac-399c-470b-abe0-cc49a03b6a8b', - 'f1618ce2-552e-4f23-bc76-e73d63ebedd0', - '4cc0c749-d943-4090-b529-42bc665b7244', - 'e259682e-cb5c-4d94-b472-ceedc66d7484', - 'fa197a4b-e065-4551-803a-c8a5b9970f9d' - ] - } -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - // specify user data to change: - var set = {'migration':migrationName}; - var inc = {'achievements.costumeContests':1}; - - dbUsers.update({_id:user._id}, {$set:set}); - dbUsers.update({_id:user._id}, {$inc:inc}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20151116_costume_contest_to_number.js b/migrations/20151116_costume_contest_to_number.js deleted file mode 100644 index 7121e9bc31..0000000000 --- a/migrations/20151116_costume_contest_to_number.js +++ /dev/null @@ -1,64 +0,0 @@ -var migrationName = '20151116_costume_contest_to_number.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Change Costume Contest achievement from Boolean to Number, so people can win repeatedly - */ - -var dbserver = 'localhost:27017'; // FOR TEST DATABASE -// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'achievements.costumeContest':true -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'achievements.costumeContest':1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - // specify user data to change: - var set = {'achievements.costumeContests':1}; - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20151125_turkey_ladder.js b/migrations/20151125_turkey_ladder.js deleted file mode 100644 index e028b4f882..0000000000 --- a/migrations/20151125_turkey_ladder.js +++ /dev/null @@ -1,71 +0,0 @@ -var migrationName = '20151125_turkey_ladder.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Gilded Turkey pet to Turkey mount owners, Turkey Mount if they only have Turkey Pet, - * and Turkey Pet otherwise - */ - -var dbserver = 'localhost:27017'; // FOR TEST DATABASE -// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.pets.Turkey-Base': 1, - 'items.mounts.Turkey-Base': 1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - // specify user data to change: - var set = {}; - if (user.items.mounts['Turkey-Base']) { - set = {'migration':migrationName, 'items.pets.Turkey-Gilded':5}; - } else if (user.items.pets['Turkey-Base']) { - set = {'migration':migrationName, 'items.mounts.Turkey-Base':true}; - } else { - set = {'migration':migrationName, 'items.pets.Turkey-Base':5}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20151229_new_years_hats.js b/migrations/20151229_new_years_hats.js deleted file mode 100644 index 895e545dd0..0000000000 --- a/migrations/20151229_new_years_hats.js +++ /dev/null @@ -1,70 +0,0 @@ -var migrationName = '20151229_new_years_hats.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award 2015 party hat if user has 2014 hat, 2014 hat if they have the 2013 hat, - * and 2013 hat otherwise - */ - -var dbserver = 'localhost:27017'; // FOR TEST DATABASE -// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.gear.owned': 1, -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - // specify user data to change: - var set = {}; - if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('head_special_nye2014')) { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2015':false}; - } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('head_special_nye')) { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2014':false}; - } else { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye':false}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20160521_veteran_ladder.js b/migrations/20160521_veteran_ladder.js deleted file mode 100644 index 0cc19e4514..0000000000 --- a/migrations/20160521_veteran_ladder.js +++ /dev/null @@ -1,82 +0,0 @@ -var migrationName = '20160521_veteran_ladder.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Gilded Turkey pet to Turkey mount owners, Turkey Mount if they only have Turkey Pet, - * and Turkey Pet otherwise - */ - -var dbserver = 'localhost:27017'; // FOR TEST DATABASE -// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; - -var mongo = require('mongoskin'); -var _ = require('lodash'); - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'auth.timestamps.loggedin':{$gt:new Date('2016-05-01')} // remove when running migration a second time -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'migration': 1, - 'items.pets.Wolf-Veteran': 1, - 'items.pets.Tiger-Veteran': 1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - return displayData(); - } - count++; - - // specify user data to change: - var set = {}; - if (user.migration !== migrationName) { - if (user.items.pets['Tiger-Veteran']) { - set = {'migration':migrationName, 'items.pets.Lion-Veteran':5}; - } else if (user.items.pets['Wolf-Veteran']) { - set = {'migration':migrationName, 'items.pets.Tiger-Veteran':5}; - } else { - set = {'migration':migrationName, 'items.pets.Wolf-Veteran':5}; - } - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20160527_fix_empty_checklist_id.js b/migrations/20160527_fix_empty_checklist_id.js deleted file mode 100644 index 0276d3241e..0000000000 --- a/migrations/20160527_fix_empty_checklist_id.js +++ /dev/null @@ -1,84 +0,0 @@ -var uuid = require('uuid').v4; -var mongo = require('mongodb').MongoClient; -var _ = require('lodash'); - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -var taskIds = require('checklists-no-id.json').map(function (obj) { - return obj._id; -}); - -// Fix empty task.checklistt.id - -var progressCount = 100; -var count = 0; - -function displayData() { - console.warn('\n' + count + ' tasks processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } -} - -mongo.connect('db url') -.then(function (db) { - var dbTasks = db.collection('tasks'); - - // specify a query to limit the affected tasks (empty for all tasks): - var query = { - '_id':{ $in: taskIds }, - }; - - // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - var fields = { - 'checklist': 1, - }; - - console.warn('Updating tasks...'); - - dbTasks.find(query, fields, {batchSize: 250}).toArray(function(err, tasks) { - if (err) { return exiting(1, 'ERROR! ' + err); } - - tasks.forEach(function (task) { - var checklist = task.checklist || []; - checklist.forEach(function (item) { - if (!item.id || item.id === "") { - item.id = uuid(); - } - }); - - // specify user data to change: - var set = { - checklist: checklist, - }; - //console.log(set); - - dbTasks.update({_id: task._id}, {$set: set}, function (err, res) { - if (err) console.error('Error while updating', err); - }); - - count++; - if (count % progressCount == 0) console.warn(count + ' ' + task._id); - }); - - if (count === tasks.length) { - console.warn('All appropriate tasks found and modified.'); - return displayData(); - } - }); -}) -.catch(function (err) { - throw err; -}); \ No newline at end of file diff --git a/migrations/20160731_naming_day.js b/migrations/20160731_naming_day.js deleted file mode 100644 index 601798d14c..0000000000 --- a/migrations/20160731_naming_day.js +++ /dev/null @@ -1,82 +0,0 @@ -var migrationName = '20160731_naming_day.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Royal Purple Gryphon pet to Royal Purple Gryphon mount owners, mount to everyone else - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin':{$gt:new Date('2016-07-30')} // Extend timeframe each run of migration -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.mounts': 1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - var inc = {}; - inc = { - 'achievements.habiticaDays': 1, - 'items.food.Cake_Skeleton': 1, - 'items.food.Cake_Base': 1, - 'items.food.Cake_CottonCandyBlue': 1, - 'items.food.Cake_CottonCandyPink': 1, - 'items.food.Cake_Shade': 1, - 'items.food.Cake_White': 1, - 'items.food.Cake_Golden': 1, - 'items.food.Cake_Zombie': 1, - 'items.food.Cake_Desert': 1, - 'items.food.Cake_Red': 1 - }; - if (user.items.mounts['Gryphon-RoyalPurple']) { - set = {'migration':migrationName, 'items.pets.Gryphon-RoyalPurple':5}; - } else { - set = {'migration':migrationName, 'items.mounts.Gryphon-RoyalPurple':true}; - } - - dbUsers.update({_id:user._id}, {$set:set, $inc:inc}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20160731_takeThis.js b/migrations/20160731_takeThis.js deleted file mode 100644 index b08700a4bd..0000000000 --- a/migrations/20160731_takeThis.js +++ /dev/null @@ -1,71 +0,0 @@ -var migrationName = '20160731_takeThis.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Take This Sword to Take This challenge participants who already own the Shield - * and Take This Shield to the rest of the list - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin':{$gt:new Date('2016-07-30')}, // Extend timeframe each run of migration - 'challenges':{$in:['da8859b2-5c6e-4aa5-b8b2-8db93d5de9fc']} -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.gear.owned': 1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - - if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.weapon_special_takeThis':false}; - } else { - set = {'migration':migrationName, 'items.gear.owned.shield_special_takeThis':false}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20160831_takeThis.js b/migrations/20160831_takeThis.js deleted file mode 100644 index 853ade4044..0000000000 --- a/migrations/20160831_takeThis.js +++ /dev/null @@ -1,72 +0,0 @@ -var migrationName = '20160831_takeThis.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Take This Sword to Take This challenge participants who already own the Shield - * and Take This Shield to the rest of the list - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'migration':{$ne:migrationName}, - 'challenges':{$in:['ee2b3c87-13f0-422a-af3c-309102d4f7e6']} -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.gear.owned': 1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - - if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.armor_special_takeThis':false}; - } else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.weapon_special_takeThis':false}; - } else { - set = {'migration':migrationName, 'items.gear.owned.shield_special_takeThis':false}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20161002_takeThis.js b/migrations/20161002_takeThis.js deleted file mode 100644 index a3dafa3042..0000000000 --- a/migrations/20161002_takeThis.js +++ /dev/null @@ -1,73 +0,0 @@ -var migrationName = '20161002_takeThis.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Take This ladder items to participants in this month's challenge - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'migration':{$ne:migrationName}, - 'challenges':{$in:['4bbf63b5-10bc-49f9-8e95-5bd2ac99cd1c']} -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.gear.owned': 1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - - if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_takeThis':false}; - } else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.armor_special_takeThis':false}; - } else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.weapon_special_takeThis':false}; - } else { - set = {'migration':migrationName, 'items.gear.owned.shield_special_takeThis':false}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20161030-jackolanterns.js b/migrations/20161030-jackolanterns.js deleted file mode 100644 index bbea4d3455..0000000000 --- a/migrations/20161030-jackolanterns.js +++ /dev/null @@ -1,86 +0,0 @@ -var migrationName = '20161030-jackolanterns.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * set the newStuff flag in all user accounts so they see a Bailey message - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'auth.timestamps.loggedin':{$gt:new Date('2016-10-01')} // remove when running migration a second time -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'migration': 1, - 'items.pets.JackOLantern-Base': 1, - 'items.mounts.JackOLantern-Base': 1, -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - var inc = {}; - if (user.migration !== migrationName) { - if (user.items.mounts['JackOLantern-Base']) { - set = {'migration':migrationName, 'items.pets.JackOLantern-Ghost':5}; - } else if (user.items.pets['JackOLantern-Base']) { - set = {'migration':migrationName, 'items.mounts.JackOLantern-Base':true}; - } else { - set = {'migration':migrationName, 'items.pets.JackOLantern-Base':5}; - } - inc = { - 'items.food.Candy_Base': 1, - 'items.food.Candy_CottonCandyBlue': 1, - 'items.food.Candy_CottonCandyPink': 1, - 'items.food.Candy_Desert': 1, - 'items.food.Candy_Golden': 1, - 'items.food.Candy_Red': 1, - 'items.food.Candy_Shade': 1, - 'items.food.Candy_Skeleton': 1, - 'items.food.Candy_White': 1, - 'items.food.Candy_Zombie': 1, - } - } - - dbUsers.update({_id:user._id}, {$set:set, $inc:inc}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20161102_takeThis.js b/migrations/20161102_takeThis.js deleted file mode 100644 index d13d180ccf..0000000000 --- a/migrations/20161102_takeThis.js +++ /dev/null @@ -1,75 +0,0 @@ -var migrationName = '20161102_takeThis.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Take This ladder items to participants in this month's challenge - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'migration':{$ne:migrationName}, - 'challenges':{$in:['d1be0965-e909-4d30-82fa-9a0011f885b2']} -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.gear.owned': 1 -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - - if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.body_special_takeThis':false}; - } else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_takeThis':false}; - } else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.armor_special_takeThis':false}; - } else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.weapon_special_takeThis':false}; - } else { - set = {'migration':migrationName, 'items.gear.owned.shield_special_takeThis':false}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20161122_turkey_ladder.js b/migrations/20161122_turkey_ladder.js deleted file mode 100644 index 4992ed272f..0000000000 --- a/migrations/20161122_turkey_ladder.js +++ /dev/null @@ -1,74 +0,0 @@ -var migrationName = '20161122_turkey_ladder.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Yearly Turkey Day award. Turkey pet, Turkey mount, Gilded Turkey pet, Gilded Turkey mount - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin':{$gt:new Date('2016-10-31')} // Extend timeframe each run of migration -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'migration': 1, - 'items.mounts': 1, - 'items.pets': 1, -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - - if (user.items.pets['Turkey-Gilded']) { - set = {'migration':migrationName, 'items.mounts.Turkey-Gilded':true}; - } else if (user.items.mounts['Turkey-Base']) { - set = {'migration':migrationName, 'items.pets.Turkey-Gilded':5}; - } else if (user.items.pets['Turkey-Base']) { - set = {'migration':migrationName, 'items.mounts.Turkey-Base':true}; - } else { - set = {'migration':migrationName, 'items.pets.Turkey-Base':5}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} diff --git a/migrations/20161230_nye_hats.js b/migrations/20161230_nye_hats.js deleted file mode 100644 index 7eeb8dd7da..0000000000 --- a/migrations/20161230_nye_hats.js +++ /dev/null @@ -1,73 +0,0 @@ -var migrationName = '20161230_nye_hats.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Yearly New Year's party hat award - */ - -var mongo = require('mongoskin'); - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE - -var dbUsers = mongo.db(connectionString).collection('users'); - -// specify a query to limit the affected users (empty for all users): -var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin':{$gt:new Date('2016-11-30')} // Remove after first run -}; - -// specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { - 'items.gear.owned': 1, -}; - -console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } - if (!user) { - console.warn('All appropriate users found and modified.'); - setTimeout(displayData, 300000); - return; - } - count++; - - // specify user data to change: - var set = {}; - - if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2016':false}; - } else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2015':false}; - } else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2014':false}; - } else { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye':false}; - } - - dbUsers.update({_id:user._id}, {$set:set}); - - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -}); - - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - diff --git a/migrations/20170120_missing_incentive.js b/migrations/20170120_missing_incentive.js deleted file mode 100644 index 8ee3c82c1b..0000000000 --- a/migrations/20170120_missing_incentive.js +++ /dev/null @@ -1,113 +0,0 @@ -var migrationName = '20170120_missing_incentive.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award missing Royal Purple Hatching Potion to users with 55+ check-ins - * Reduce users with impossible check-in counts to a reasonable number - */ - -import monk from 'monk'; -import common from '../website/common'; - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); - -function processUsers(lastId) { - // specify a query to limit the affected users (empty for all users): - var query = { - 'loginIncentives': {$gt:54}, - 'migration': {$ne: migrationName}, - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - var language = user.preferences.language || 'en'; - var set = {'migration': migrationName}; - var inc = {'items.hatchingPotions.RoyalPurple': 1}; - if (user.loginIncentives > 58) { - set = {'migration': migrationName, 'loginIncentives': 58}; - } - var push = { - 'notifications': { - 'type': 'LOGIN_INCENTIVE', - 'data': { - 'nextRewardAt': 60, - 'rewardKey': [ - 'Pet_HatchingPotion_Purple', - ], - 'rewardText': common.i18n.t('potion', {potionType: common.i18n.t('hatchingPotionRoyalPurple', language)}, language), - 'reward': [ - { - 'premium': true, - 'key': 'RoyalPurple', - 'limited': true, - 'value': 2, - } - ], - 'message': common.i18n.t('unlockedCheckInReward', language), - }, - 'id': common.uuid(), - } - }; - - dbUsers.update({_id: user._id}, {$set:set, $push:push, $inc:inc}); - - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/20170131_habit_birthday.js b/migrations/20170131_habit_birthday.js deleted file mode 100644 index bb1571c71b..0000000000 --- a/migrations/20170131_habit_birthday.js +++ /dev/null @@ -1,109 +0,0 @@ -var migrationName = '20170131_habit_birthday.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award 2017 party robes if user has 2016 robes, 2016 robes if they have the 2015 robes, - * 2015 robes if they have the 2014 robes, and 2014 robes otherwise. Also cake! - */ - -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); - -function processUsers(lastId) { - // specify a query to limit the affected users (empty for all users): - var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin':{$gt:new Date('2017-01-24')}, // remove after first run to cover remaining users - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data) - 'items.gear.owned' - ], - }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - var set = {'migration':migrationName}; - if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2016')) { - set['items.gear.owned.armor_special_birthday2017'] = false; - } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2015')) { - set['items.gear.owned.armor_special_birthday2016'] = false; - } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday')) { - set['items.gear.owned.armor_special_birthday2015'] = false; - } else { - set['items.gear.owned.armor_special_birthday'] = false; - } - - var inc = { - 'items.food.Cake_Skeleton':1, - 'items.food.Cake_Base':1, - 'items.food.Cake_CottonCandyBlue':1, - 'items.food.Cake_CottonCandyPink':1, - 'items.food.Cake_Shade':1, - 'items.food.Cake_White':1, - 'items.food.Cake_Golden':1, - 'items.food.Cake_Zombie':1, - 'items.food.Cake_Desert':1, - 'items.food.Cake_Red':1, - 'achievements.habitBirthdays':1 - }; - - dbUsers.update({_id: user._id}, {$set:set, $inc:inc}); - - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/20170418_subscriber_jackalopes.js b/migrations/20170418_subscriber_jackalopes.js deleted file mode 100644 index d32867de98..0000000000 --- a/migrations/20170418_subscriber_jackalopes.js +++ /dev/null @@ -1,88 +0,0 @@ -var migrationName = '20170418_subscriber_jackalopes.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Royal Purple Jackalope pet to all current subscribers - */ - -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); -var now = new Date(); - -function processUsers(lastId) { - // specify a query to limit the affected users (empty for all users): - var query = { - 'purchased.plan.customerId': {$type: 2}, - $or: [ - {'purchased.plan.dateTerminated': null}, - {'purchased.plan.dateTerminated': {$exists: false}}, - {'purchased.plan.dateTerminated': {$gt: now}}, - ] - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - var set = {'items.pets.Jackalope-RoyalPurple': 5}; - - dbUsers.update({_id: user._id}, {$set:set}); - - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/20170711_orcas.js b/migrations/20170711_orcas.js deleted file mode 100644 index fbecd0cecd..0000000000 --- a/migrations/20170711_orcas.js +++ /dev/null @@ -1,90 +0,0 @@ -var migrationName = '20170711_orcas.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Orca pets to owners of Orca mount, and Orca mount to everyone else - */ - -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); - -function processUsers(lastId) { - // specify a query to limit the affected users (empty for all users): - var query = { - 'migration':{$ne:migrationName}, - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [ - 'items.mounts', - ] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - var set = {}; - - if (user.items.mounts['Orca-Base']) { - set = {'migration':migrationName, 'items.pets.Orca-Base': 5}; - } else { - set = {'migration':migrationName, 'items.mounts.Orca-Base': true}; - } - - dbUsers.update({_id: user._id}, {$set:set}); - - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/20170731_naming_day.js b/migrations/20170731_naming_day.js deleted file mode 100644 index a87ff6cb5a..0000000000 --- a/migrations/20170731_naming_day.js +++ /dev/null @@ -1,109 +0,0 @@ -var migrationName = '20170731_naming_day.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award Royal Purple Gryphon Helm to Royal Purple Gryphon pet owners, - * award Royal Purple Gryphon pet to Royal Purple Gryphon mount owners, - * award Royal Purple Gryphon mount to everyone else - */ - -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); - -function processUsers(lastId) { - // specify a query to limit the affected users (empty for all users): - var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin': {$gt: new Date('2017-01-01')}, - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [ - 'items.mounts', - 'items.pets', - ] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - var set = {}; - var inc = { - 'achievements.habiticaDays': 1, - 'items.food.Cake_Skeleton': 1, - 'items.food.Cake_Base': 1, - 'items.food.Cake_CottonCandyBlue': 1, - 'items.food.Cake_CottonCandyPink': 1, - 'items.food.Cake_Shade': 1, - 'items.food.Cake_White': 1, - 'items.food.Cake_Golden': 1, - 'items.food.Cake_Zombie': 1, - 'items.food.Cake_Desert': 1, - 'items.food.Cake_Red': 1 - }; - - if (user.items.pets['Gryphon-RoyalPurple']) { - set = {'migration':migrationName, 'items.gear.owned.head_special_namingDay2017': false}; - } else if (user.items.mounts['Gryphon-RoyalPurple']) { - set = {'migration':migrationName, 'items.pets.Gryphon-RoyalPurple': 5}; - } else { - set = {'migration':migrationName, 'items.mounts.Gryphon-RoyalPurple': true}; - } - - dbUsers.update({_id: user._id}, {$set: set, $inc: inc}); - - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/20170928_redesign_guilds.js b/migrations/20170928_redesign_guilds.js deleted file mode 100644 index 62d68d4ac4..0000000000 --- a/migrations/20170928_redesign_guilds.js +++ /dev/null @@ -1,97 +0,0 @@ -var migrationName = '20170928_redesign_guilds.js'; - -/* - * Copy Guild Leader messages to end of Guild descriptions - * Copy Guild logos to beginning of Guild descriptions - */ - -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbGroups = monk(connectionString).get('groups', { castIds: false }); - -function processGroups(lastId) { - // specify a query to limit the affected groups (empty for all groups): - var query = { - }; - - var fields = { - 'description': 1, - 'logo': 1, - 'leaderMessage': 1, - } - - if (lastId) { - query._id = { - $gt: lastId - } - } - - return dbGroups.find(query, { - fields: fields, - sort: {_id: 1}, - limit: 250, - }) - .then(updateGroups) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateGroups (groups) { - if (!groups || groups.length === 0) { - console.warn('All appropriate groups found and modified.'); - displayData(); - return; - } - - var groupPromises = groups.map(updateGroup); - var lastGroup = groups[groups.length - 1]; - - return Promise.all(groupPromises) - .then(function () { - processGroups(lastGroup._id); - }); -} - -function updateGroup (group) { - count++; - - var description = group.description; - - if (group.logo) { - description = '![Guild Logo](' + group.logo + ')\n\n \n\n' + description; - } - - if (group.leaderMessage) { - description = description + '\n\n \n\n' + group.leaderMessage; - } - - var set = { - description: description, - }; - - if (count % progressCount == 0) console.warn(count + ' ' + group._id); - - return dbGroups.update({_id: group._id}, {$set:set}); -} - -function displayData() { - console.warn('\n' + count + ' groups processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processGroups; diff --git a/migrations/20171030_jackolanterns.js b/migrations/20171030_jackolanterns.js deleted file mode 100644 index 63be6de265..0000000000 --- a/migrations/20171030_jackolanterns.js +++ /dev/null @@ -1,111 +0,0 @@ -var migrationName = '20171030_jackolanterns.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award the Jack-O'-Lantern ladder: - * Ghost Jack-O-Lantern Mount to owners of Ghost Jack-O-Lantern Pet - * Ghost Jack-O-Lantern Pet to owners of Jack-O-Lantern Mount - * Jack-O-Lantern Mount to owners of Jack-O-Lantern Pet - * Jack-O-Lantern Pet to everyone else - */ - -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); - -function processUsers(lastId) { - // specify a query to limit the affected users (empty for all users): - var query = { - 'migration':{$ne:migrationName}, - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [ - 'items.pets', - 'items.mounts', - ] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - var set = {}; - var inc = { - 'items.food.Candy_Skeleton': 1, - 'items.food.Candy_Base': 1, - 'items.food.Candy_CottonCandyBlue': 1, - 'items.food.Candy_CottonCandyPink': 1, - 'items.food.Candy_Shade': 1, - 'items.food.Candy_White': 1, - 'items.food.Candy_Golden': 1, - 'items.food.Candy_Zombie': 1, - 'items.food.Candy_Desert': 1, - 'items.food.Candy_Red': 1, - }; - - if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Ghost']) { - set = {'migration':migrationName, 'items.mounts.JackOLantern-Ghost': true}; - } else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Base']) { - set = {'migration':migrationName, 'items.pets.JackOLantern-Ghost': 5}; - } else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Base']) { - set = {'migration':migrationName, 'items.mounts.JackOLantern-Base': true}; - } else { - set = {'migration':migrationName, 'items.pets.JackOLantern-Base': 5}; - } - - dbUsers.update({_id: user._id}, {$set:set, $inc:inc}); - - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/20171230_nye_hats.js b/migrations/20171230_nye_hats.js deleted file mode 100644 index 08db9a4158..0000000000 --- a/migrations/20171230_nye_hats.js +++ /dev/null @@ -1,103 +0,0 @@ -var migrationName = '20171230_nye_hats.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done - -/* - * Award New Year's Eve party hats to users in sequence - */ - -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); - -function processUsers(lastId) { - // specify a query to limit the affected users (empty for all users): - var query = { - 'migration': {$ne:migrationName}, - 'auth.timestamps.loggedin': {$gt:new Date('2017-11-30')}, - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [ - 'items.gear.owned', - ] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - var set = {}; - var push = {}; - - if (typeof user.items.gear.owned.head_special_nye2016 !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2017':false}; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2017', '_id': monk.id()}}; - } else if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2016':false}; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2016', '_id': monk.id()}}; - } else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2015':false}; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2015', '_id': monk.id()}}; - } else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye2014':false}; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2014', '_id': monk.id()}}; - } else { - set = {'migration':migrationName, 'items.gear.owned.head_special_nye':false}; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye', '_id': monk.id()}}; - } - - dbUsers.update({_id: user._id}, {$set: set, $push: push}); - - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' users processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/api_v3/challenges.js b/migrations/api_v3/challenges.js deleted file mode 100644 index 94adbed6e5..0000000000 --- a/migrations/api_v3/challenges.js +++ /dev/null @@ -1,218 +0,0 @@ -// Migrate challenges collection to new schema (except for members) - -// The console-stamp module must be installed (not included in package.json) - -// It requires two environment variables: MONGODB_OLD and MONGODB_NEW - -// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). -// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 -console.log('Starting migrations/api_v3/challenges.js.'); - -require('babel-register'); -require('babel-polyfill'); - -var Bluebird = require('bluebird'); -var MongoDB = require('mongodb'); -var nconf = require('nconf'); -var mongoose = require('mongoose'); -var _ = require('lodash'); -var uuid = require('uuid'); -var consoleStamp = require('console-stamp'); -var fs = require('fs'); - -// Add timestamps to console messages -consoleStamp(console); - -// Initialize configuration -require('../../website/server/libs/api-v3/setupNconf')(); - -var MONGODB_OLD = nconf.get('MONGODB_OLD'); -var MONGODB_NEW = nconf.get('MONGODB_NEW'); - -var MongoClient = MongoDB.MongoClient; - -mongoose.Promise = Bluebird; // otherwise mongoose models won't work - -// Load new models -var NewChallenge = require('../../website/server/models/challenge').model; -var Tasks = require('../../website/server/models/task'); - -// To be defined later when MongoClient connects -var mongoDbOldInstance; -var oldChallengeCollection; - -var mongoDbNewInstance; -var newChallengeCollection; -var newTaskCollection; - -var BATCH_SIZE = 1000; - -var processedChallenges = 0; -var totoalProcessedTasks = 0; - -var newTasksIds = {}; // a map of old id -> [new id, challengeId] - -// Only process challenges that fall in a interval ie -> up to 0000-4000-0000-0000 -var AFTER_CHALLENGE_ID = nconf.get('AFTER_CHALLENGE_ID'); -var BEFORE_CHALLENGE_ID = nconf.get('BEFORE_CHALLENGE_ID'); - -function processChallenges (afterId) { - var processedTasks = 0; - var lastChallenge = null; - var oldChallenges; - - var query = {}; - - if (BEFORE_CHALLENGE_ID) { - query._id = {$lte: BEFORE_CHALLENGE_ID}; - } - - if ((afterId || AFTER_CHALLENGE_ID) && !query._id) { - query._id = {}; - } - - if (afterId) { - query._id.$gt = afterId; - } else if (AFTER_CHALLENGE_ID) { - query._id.$gt = AFTER_CHALLENGE_ID; - } - - var batchInsertTasks = newTaskCollection.initializeUnorderedBulkOp(); - var batchInsertChallenges = newChallengeCollection.initializeUnorderedBulkOp(); - - console.log(`Executing challenges query.\nMatching challenges after ${afterId ? afterId : AFTER_CHALLENGE_ID} and before ${BEFORE_CHALLENGE_ID} (included).`); - - return oldChallengeCollection - .find(query) - .sort({_id: 1}) - .limit(BATCH_SIZE) - .toArray() - .then(function (oldChallengesR) { - oldChallenges = oldChallengesR; - - console.log(`Processing ${oldChallenges.length} challenges. Already processed ${processedChallenges} challenges and ${totoalProcessedTasks} tasks.`); - - if (oldChallenges.length === BATCH_SIZE) { - lastChallenge = oldChallenges[oldChallenges.length - 1]._id; - } - - oldChallenges.forEach(function (oldChallenge) { - var oldTasks = oldChallenge.habits.concat(oldChallenge.dailys).concat(oldChallenge.rewards).concat(oldChallenge.todos); - delete oldChallenge.habits; - delete oldChallenge.dailys; - delete oldChallenge.rewards; - delete oldChallenge.todos; - - var createdAt = oldChallenge.timestamp; - - oldChallenge.memberCount = oldChallenge.members.length; - if (oldChallenge.prize <= 0) oldChallenge.prize = 0; - if (!oldChallenge.name) oldChallenge.name = 'challenge name'; - if (!oldChallenge.shortName) oldChallenge.name = 'challenge-name'; - - if (!oldChallenge.group) throw new Error('challenge.group is required'); - if (!oldChallenge.leader) throw new Error('challenge.leader is required'); - - - if (oldChallenge.leader === '9') { - oldChallenge.leader = '00000000-0000-4000-9000-000000000000'; - } - - if (oldChallenge.group === 'habitrpg') { - oldChallenge.group = '00000000-0000-4000-A000-000000000000'; - } - - delete oldChallenge.id; - - var newChallenge = new NewChallenge(oldChallenge); - - newChallenge.createdAt = createdAt; - - oldTasks.forEach(function (oldTask) { - oldTask._id = uuid.v4(); - oldTask._legacyId = oldTask.id; // store the old task id - delete oldTask.id; - - oldTask.challenge = oldTask.challenge || {}; - oldTask.challenge.id = newChallenge._id; - - if (newTasksIds[oldTask._legacyId + '-' + newChallenge._id]) { - throw new Error('duplicate :('); - } else { - newTasksIds[oldTask._legacyId + '-' + newChallenge._id] = oldTask._id; - } - - oldTask.tags = _.map(oldTask.tags || {}, function (tagPresent, tagId) { - return tagPresent && tagId; - }).filter(function (tag) { - return tag !== false; - }); - - if (!oldTask.text) oldTask.text = 'task text'; // required - - oldTask.createdAt = oldTask.dateCreated; - - newChallenge.tasksOrder[`${oldTask.type}s`].push(oldTask._id); - if (oldTask.completed) oldTask.completed = false; - - var newTask = new Tasks[oldTask.type](oldTask); - - batchInsertTasks.insert(newTask.toObject()); - processedTasks++; - }); - - batchInsertChallenges.insert(newChallenge.toObject()); - }); - - console.log(`Saving ${oldChallenges.length} challenges and ${processedTasks} tasks.`); - - return Bluebird.all([ - batchInsertChallenges.execute(), - batchInsertTasks.execute(), - ]); - }) - .then(function () { - totoalProcessedTasks += processedTasks; - processedChallenges += oldChallenges.length; - - console.log(`Saved ${oldChallenges.length} challenges and their tasks.`); - - if (lastChallenge) { - return processChallenges(lastChallenge); - } else { - console.log('Writing newTasksIds.json...') - fs.writeFileSync('newTasksIds.json', JSON.stringify(newTasksIds, null, 4), 'utf8'); - return console.log('Done!'); - } - }); -} - -// Connect to the databases -Bluebird.all([ - MongoClient.connect(MONGODB_OLD), - MongoClient.connect(MONGODB_NEW), -]) -.then(function (result) { - var oldInstance = result[0]; - var newInstance = result[1]; - - mongoDbOldInstance = oldInstance; - oldChallengeCollection = mongoDbOldInstance.collection('challenges'); - - mongoDbNewInstance = newInstance; - newChallengeCollection = mongoDbNewInstance.collection('challenges'); - newTaskCollection = mongoDbNewInstance.collection('tasks'); - - console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); - - return processChallenges(); -}) -.catch(function (err) { - console.error(err.stack || err); -}); diff --git a/migrations/api_v3/challengesMembers.js b/migrations/api_v3/challengesMembers.js deleted file mode 100644 index 349abde57b..0000000000 --- a/migrations/api_v3/challengesMembers.js +++ /dev/null @@ -1,149 +0,0 @@ -// Migrate challenges members -// Run AFTER users migration - -// The console-stamp module must be installed (not included in package.json) - -// It requires two environment variables: MONGODB_OLD and MONGODB_NEW - -// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). -// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM -console.log('Starting migrations/api_v3/challengesMembers.js.'); - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -require('babel-register'); -require('babel-polyfill'); - -var Bluebird = require('bluebird'); -var MongoDB = require('mongodb'); -var nconf = require('nconf'); -var mongoose = require('mongoose'); -var _ = require('lodash'); -var uuid = require('uuid'); -var consoleStamp = require('console-stamp'); - -// Add timestamps to console messages -consoleStamp(console); - -// Initialize configuration -require('../../website/server/libs/api-v3/setupNconf')(); - -var MONGODB_OLD = nconf.get('MONGODB_OLD'); -var MONGODB_NEW = nconf.get('MONGODB_NEW'); - -var MongoClient = MongoDB.MongoClient; - -mongoose.Promise = Bluebird; // otherwise mongoose models won't work - -// To be defined later when MongoClient connects -var mongoDbOldInstance; -var oldChallengeCollection; - -var mongoDbNewInstance; -var newUserCollection; - -var BATCH_SIZE = 1000; - -var processedChallenges = 0; - -// Only process challenges that fall in a interval ie -> up to 0000-4000-0000-0000 -var AFTER_CHALLENGE_ID = nconf.get('AFTER_CHALLENGE_ID'); -var BEFORE_CHALLENGE_ID = nconf.get('BEFORE_CHALLENGE_ID'); - -function processChallenges (afterId) { - var processedTasks = 0; - var lastChallenge = null; - var oldChallenges; - - var query = {}; - - if (BEFORE_CHALLENGE_ID) { - query._id = {$lte: BEFORE_CHALLENGE_ID}; - } - - if ((afterId || AFTER_CHALLENGE_ID) && !query._id) { - query._id = {}; - } - - if (afterId) { - query._id.$gt = afterId; - } else if (AFTER_CHALLENGE_ID) { - query._id.$gt = AFTER_CHALLENGE_ID; - } - - console.log(`Executing challenges query.\nMatching challenges after ${afterId ? afterId : AFTER_CHALLENGE_ID} and before ${BEFORE_CHALLENGE_ID} (included).`); - - return oldChallengeCollection - .find(query) - .sort({_id: 1}) - .limit(BATCH_SIZE) - .toArray() - .then(function (oldChallengesR) { - oldChallenges = oldChallengesR; - - var promises = []; - - console.log(`Processing ${oldChallenges.length} challenges. Already processed ${processedChallenges} challenges.`); - - if (oldChallenges.length === BATCH_SIZE) { - lastChallenge = oldChallenges[oldChallenges.length - 1]._id; - } - - oldChallenges.forEach(function (oldChallenge) { - // Tyler Renelle - oldChallenge.members.forEach(function (id, index) { - if (id === '9') { - oldChallenge.members[index] = '00000000-0000-4000-9000-000000000000'; - } - }); - - promises.push(newUserCollection.updateMany({ - _id: {$in: oldChallenge.members || []}, - }, { - $push: {challenges: oldChallenge._id}, - }, {multi: true})); - }); - - console.log(`Migrating members of ${oldChallenges.length} challenges.`); - - return Bluebird.all(promises); - }) - .then(function () { - processedChallenges += oldChallenges.length; - - console.log(`Migrated members of ${oldChallenges.length} challenges.`); - - if (lastChallenge) { - return processChallenges(lastChallenge); - } else { - return console.log('Done!'); - } - }); -} - -// Connect to the databases -Bluebird.all([ - MongoClient.connect(MONGODB_OLD), - MongoClient.connect(MONGODB_NEW), -]) -.then(function (result) { - var oldInstance = result[0]; - var newInstance = result[1]; - - mongoDbOldInstance = oldInstance; - oldChallengeCollection = mongoDbOldInstance.collection('challenges'); - - mongoDbNewInstance = newInstance; - newUserCollection = mongoDbNewInstance.collection('users'); - - console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); - - return processChallenges(); -}) -.catch(function (err) { - console.error(err.stack || err); -}); diff --git a/migrations/api_v3/coupons.js b/migrations/api_v3/coupons.js deleted file mode 100644 index 8b79deba8d..0000000000 --- a/migrations/api_v3/coupons.js +++ /dev/null @@ -1,142 +0,0 @@ -// Migrate coupons collection to new schema - -// The console-stamp module must be installed (not included in package.json) - -// It requires two environment variables: MONGODB_OLD and MONGODB_NEW - -// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). -// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM -console.log('Starting migrations/api_v3/coupons.js.'); - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -require('babel-register'); -require('babel-polyfill'); - -var Bluebird = require('bluebird'); -var MongoDB = require('mongodb'); -var nconf = require('nconf'); -var mongoose = require('mongoose'); -var _ = require('lodash'); -var uuid = require('uuid'); -var consoleStamp = require('console-stamp'); - -// Add timestamps to console messages -consoleStamp(console); - -// Initialize configuration -require('../../website/server/libs/api-v3/setupNconf')(); - -var MONGODB_OLD = nconf.get('MONGODB_OLD'); -var MONGODB_NEW = nconf.get('MONGODB_NEW'); - -var MongoClient = MongoDB.MongoClient; - -mongoose.Promise = Bluebird; // otherwise mongoose models won't work - -// Load new models -var Coupon = require('../../website/server/models/coupon').model; - -// To be defined later when MongoClient connects -var mongoDbOldInstance; -var oldCouponCollection; - -var mongoDbNewInstance; -var newCouponCollection; - -var BATCH_SIZE = 1000; - -var processedCoupons = 0; - -// Only process coupons that fall in a interval ie -> up to 0000-4000-0000-0000 -var AFTER_COUPON_ID = nconf.get('AFTER_COUPON_ID'); -var BEFORE_COUPON_ID = nconf.get('BEFORE_COUPON_ID'); - -function processCoupons (afterId) { - var processedTasks = 0; - var lastCoupon = null; - var oldCoupons; - - var query = {}; - - if (BEFORE_COUPON_ID) { - query._id = {$lte: BEFORE_COUPON_ID}; - } - - if ((afterId || AFTER_COUPON_ID) && !query._id) { - query._id = {}; - } - - if (afterId) { - query._id.$gt = afterId; - } else if (AFTER_COUPON_ID) { - query._id.$gt = AFTER_COUPON_ID; - } - - var batchInsertCoupons = newCouponCollection.initializeUnorderedBulkOp(); - - console.log(`Executing coupons query.\nMatching coupons after ${afterId ? afterId : AFTER_COUPON_ID} and before ${BEFORE_COUPON_ID} (included).`); - - return oldCouponCollection - .find(query) - .sort({_id: 1}) - .limit(BATCH_SIZE) - .toArray() - .then(function (oldCouponsR) { - oldCoupons = oldCouponsR; - - console.log(`Processing ${oldCoupons.length} coupons. Already processed ${processedCoupons} coupons.`); - - if (oldCoupons.length === BATCH_SIZE) { - lastCoupon = oldCoupons[oldCoupons.length - 1]._id; - } - - oldCoupons.forEach(function (oldCoupon) { - var newCoupon = new Coupon(oldCoupon); - - batchInsertCoupons.insert(newCoupon.toObject()); - }); - - console.log(`Saving ${oldCoupons.length} coupons.`); - - return batchInsertCoupons.execute(); - }) - .then(function () { - processedCoupons += oldCoupons.length; - - console.log(`Saved ${oldCoupons.length} coupons.`); - - if (lastCoupon) { - return processCoupons(lastCoupon); - } else { - return console.log('Done!'); - } - }); -} - -// Connect to the databases -Bluebird.all([ - MongoClient.connect(MONGODB_OLD), - MongoClient.connect(MONGODB_NEW), -]) -.then(function (result) { - var oldInstance = result[0]; - var newInstance = result[1]; - - mongoDbOldInstance = oldInstance; - oldCouponCollection = mongoDbOldInstance.collection('coupons'); - - mongoDbNewInstance = newInstance; - newCouponCollection = mongoDbNewInstance.collection('coupons'); - - console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); - - return processCoupons(); -}) -.catch(function (err) { - console.error(err.stack || err); -}); diff --git a/migrations/api_v3/emailUnsubscriptions.js b/migrations/api_v3/emailUnsubscriptions.js deleted file mode 100644 index 3e1629563e..0000000000 --- a/migrations/api_v3/emailUnsubscriptions.js +++ /dev/null @@ -1,143 +0,0 @@ -// Migrate unsubscriptions collection to new schema - -// The console-stamp module must be installed (not included in package.json) - -// It requires two environment variables: MONGODB_OLD and MONGODB_NEW - -// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). -// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM -console.log('Starting migrations/api_v3/unsubscriptions.js.'); - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -require('babel-register'); -require('babel-polyfill'); - -var Bluebird = require('bluebird'); -var MongoDB = require('mongodb'); -var nconf = require('nconf'); -var mongoose = require('mongoose'); -var _ = require('lodash'); -var uuid = require('uuid'); -var consoleStamp = require('console-stamp'); - -// Add timestamps to console messages -consoleStamp(console); - -// Initialize configuration -require('../../website/server/libs/api-v3/setupNconf')(); - -var MONGODB_OLD = nconf.get('MONGODB_OLD'); -var MONGODB_NEW = nconf.get('MONGODB_NEW'); - -var MongoClient = MongoDB.MongoClient; - -mongoose.Promise = Bluebird; // otherwise mongoose models won't work - -// Load new models -var EmailUnsubscription = require('../../website/server/models/emailUnsubscription').model; - -// To be defined later when MongoClient connects -var mongoDbOldInstance; -var oldUnsubscriptionCollection; - -var mongoDbNewInstance; -var newUnsubscriptionCollection; - -var BATCH_SIZE = 1000; - -var processedUnsubscriptions = 0; - -// Only process unsubscriptions that fall in a interval ie -> up to 0000-4000-0000-0000 -var AFTER_UNSUBSCRIPTION_ID = nconf.get('AFTER_UNSUBSCRIPTION_ID'); -var BEFORE_UNSUBSCRIPTION_ID = nconf.get('BEFORE_UNSUBSCRIPTION_ID'); - -function processUnsubscriptions (afterId) { - var processedTasks = 0; - var lastUnsubscription = null; - var oldUnsubscriptions; - - var query = {}; - - if (BEFORE_UNSUBSCRIPTION_ID) { - query._id = {$lte: BEFORE_UNSUBSCRIPTION_ID}; - } - - if ((afterId || AFTER_UNSUBSCRIPTION_ID) && !query._id) { - query._id = {}; - } - - if (afterId) { - query._id.$gt = afterId; - } else if (AFTER_UNSUBSCRIPTION_ID) { - query._id.$gt = AFTER_UNSUBSCRIPTION_ID; - } - - var batchInsertUnsubscriptions = newUnsubscriptionCollection.initializeUnorderedBulkOp(); - - console.log(`Executing unsubscriptions query.\nMatching unsubscriptions after ${afterId ? afterId : AFTER_UNSUBSCRIPTION_ID} and before ${BEFORE_UNSUBSCRIPTION_ID} (included).`); - - return oldUnsubscriptionCollection - .find(query) - .sort({_id: 1}) - .limit(BATCH_SIZE) - .toArray() - .then(function (oldUnsubscriptionsR) { - oldUnsubscriptions = oldUnsubscriptionsR; - - console.log(`Processing ${oldUnsubscriptions.length} unsubscriptions. Already processed ${processedUnsubscriptions} unsubscriptions.`); - - if (oldUnsubscriptions.length === BATCH_SIZE) { - lastUnsubscription = oldUnsubscriptions[oldUnsubscriptions.length - 1]._id; - } - - oldUnsubscriptions.forEach(function (oldUnsubscription) { - oldUnsubscription.email = oldUnsubscription.email.toLowerCase(); - var newUnsubscription = new EmailUnsubscription(oldUnsubscription); - - batchInsertUnsubscriptions.insert(newUnsubscription.toObject()); - }); - - console.log(`Saving ${oldUnsubscriptions.length} unsubscriptions.`); - - return batchInsertUnsubscriptions.execute(); - }) - .then(function () { - processedUnsubscriptions += oldUnsubscriptions.length; - - console.log(`Saved ${oldUnsubscriptions.length} unsubscriptions.`); - - if (lastUnsubscription) { - return processUnsubscriptions(lastUnsubscription); - } else { - return console.log('Done!'); - } - }); -} - -// Connect to the databases -Bluebird.all([ - MongoClient.connect(MONGODB_OLD), - MongoClient.connect(MONGODB_NEW), -]) -.then(function (result) { - var oldInstance = result[0]; - var newInstance = result[1]; - - mongoDbOldInstance = oldInstance; - oldUnsubscriptionCollection = mongoDbOldInstance.collection('emailunsubscriptions'); - - mongoDbNewInstance = newInstance; - newUnsubscriptionCollection = mongoDbNewInstance.collection('emailunsubscriptions'); - - console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); - - return processUnsubscriptions(); -}) -.catch(function (err) { - console.error(err.stack || err); -}); diff --git a/migrations/api_v3/groups.js b/migrations/api_v3/groups.js deleted file mode 100644 index e623b9d062..0000000000 --- a/migrations/api_v3/groups.js +++ /dev/null @@ -1,217 +0,0 @@ -/* - members are not stored anymore - invites are not stored anymore - - tavern id and leader must be updated -*/ - -// Migrate groups collection to new schema -// Run AFTER users migration - -// The console-stamp module must be installed (not included in package.json) - -// It requires two environment variables: MONGODB_OLD and MONGODB_NEW - -// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). -// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM -console.log('Starting migrations/api_v3/groups.js.'); - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -require('babel-register'); -require('babel-polyfill'); - -var Bluebird = require('bluebird'); -var MongoDB = require('mongodb'); -var nconf = require('nconf'); -var mongoose = require('mongoose'); -var _ = require('lodash'); -var uuid = require('uuid'); -var consoleStamp = require('console-stamp'); - -// Add timestamps to console messages -consoleStamp(console); - -// Initialize configuration -require('../../website/server/libs/api-v3/setupNconf')(); - -var MONGODB_OLD = nconf.get('MONGODB_OLD'); -var MONGODB_NEW = nconf.get('MONGODB_NEW'); - -var MongoClient = MongoDB.MongoClient; - -mongoose.Promise = Bluebird; // otherwise mongoose models won't work - -// Load new models -var NewGroup = require('../../website/server/models/group').model; - -var TAVERN_ID = require('../../website/server/models/group').TAVERN_ID; - -// To be defined later when MongoClient connects -var mongoDbOldInstance; -var oldGroupCollection; - -var mongoDbNewInstance; -var newGroupCollection; -var newUserCollection; - -var BATCH_SIZE = 1000; - -var processedGroups = 0; - -// Only process groups that fall in a interval ie -> up to 0000-4000-0000-0000 -var AFTER_GROUP_ID = nconf.get('AFTER_GROUP_ID'); -var BEFORE_GROUP_ID = nconf.get('BEFORE_GROUP_ID'); - -function processGroups (afterId) { - var processedTasks = 0; - var lastGroup = null; - var oldGroups; - - var query = {}; - - if (BEFORE_GROUP_ID) { - query._id = {$lte: BEFORE_GROUP_ID}; - } - - if ((afterId || AFTER_GROUP_ID) && !query._id) { - query._id = {}; - } - - if (afterId) { - query._id.$gt = afterId; - } else if (AFTER_GROUP_ID) { - query._id.$gt = AFTER_GROUP_ID; - } - - var batchInsertGroups = newGroupCollection.initializeUnorderedBulkOp(); - - console.log(`Executing groups query.\nMatching groups after ${afterId ? afterId : AFTER_GROUP_ID} and before ${BEFORE_GROUP_ID} (included).`); - - return oldGroupCollection - .find(query) - .sort({_id: 1}) - .limit(BATCH_SIZE) - .toArray() - .then(function (oldGroupsR) { - oldGroups = oldGroupsR; - - var promises = []; - - console.log(`Processing ${oldGroups.length} groups. Already processed ${processedGroups} groups.`); - - if (oldGroups.length === BATCH_SIZE) { - lastGroup = oldGroups[oldGroups.length - 1]._id; - } - - oldGroups.forEach(function (oldGroup) { - if ((!oldGroup.privacy || oldGroup.privacy === 'private') && (!oldGroup.members || oldGroup.members.length === 0)) return; // delete empty private groups TODO must also delete challenges or this won't work - - oldGroup.members = oldGroup.members || []; - oldGroup.memberCount = oldGroup.members ? oldGroup.members.length : 0; - oldGroup.challengeCount = oldGroup.challenges ? oldGroup.challenges.length : 0; - - if (oldGroup.balance <= 0) oldGroup.balance = 0; - if (!oldGroup.name) oldGroup.name = 'group name'; - if (!oldGroup.leaderOnly) oldGroup.leaderOnly = {}; - if (!oldGroup.leaderOnly.challenges) oldGroup.leaderOnly.challenges = false; - - // Tavern - if (oldGroup._id === 'habitrpg') { - oldGroup._id = TAVERN_ID; - oldGroup.leader = '7bde7864-ebc5-4ee2-a4b7-1070d464cdb0'; // Siena Leslie - } - - if (!oldGroup.type) { - // throw new Error('group.type is required'); - oldGroup.type = 'guild'; - } - - if (!oldGroup.leader) { - if (oldGroup.members && oldGroup.members.length > 0) { - oldGroup.leader = oldGroup.members[0]; - } else { - throw new Error('group.leader is required and no member available!'); - } - } - - if (!oldGroup.privacy) { - // throw new Error('group.privacy is required'); - oldGroup.privacy = 'private'; - } - - var updateMembers = {}; - - if (oldGroup.type === 'guild') { - updateMembers.$push = {guilds: oldGroup._id}; - } else if (oldGroup.type === 'party') { - updateMembers.$set = {'party._id': oldGroup._id}; - } - - if (oldGroup.members) { - // Tyler Renelle - oldGroup.members.forEach(function (id, index) { - if (id === '9') { - oldGroup.members[index] = '00000000-0000-4000-9000-000000000000'; - } - }); - - promises.push(newUserCollection.updateMany({ - _id: {$in: oldGroup.members}, - }, updateMembers, {multi: true})); - } - - var newGroup = new NewGroup(oldGroup); - - batchInsertGroups.insert(newGroup.toObject()); - }); - - console.log(`Saving ${oldGroups.length} groups and migrating members to users collection.`); - - promises.push(batchInsertGroups.execute()); - return Bluebird.all(promises); - }) - .then(function () { - processedGroups += oldGroups.length; - - console.log(`Saved ${oldGroups.length} groups and migrated their members to the user collection.`); - - if (lastGroup) { - return processGroups(lastGroup); - } else { - return console.log('Done!'); - } - }); -} - -// Connect to the databases -Bluebird.all([ - MongoClient.connect(MONGODB_OLD), - MongoClient.connect(MONGODB_NEW), -]) -.then(function (result) { - var oldInstance = result[0]; - var newInstance = result[1]; - - mongoDbOldInstance = oldInstance; - oldGroupCollection = mongoDbOldInstance.collection('groups'); - - mongoDbNewInstance = newInstance; - newGroupCollection = mongoDbNewInstance.collection('groups'); - newUserCollection = mongoDbNewInstance.collection('users'); - - console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); - - // First delete the tavern group created by having required the group model - return newGroupCollection.deleteOne({_id: TAVERN_ID}); -}) -.then(function () { - return processGroups(); -}) -.catch(function (err) { - console.error(err.stack || err); -}); diff --git a/migrations/api_v3/users.js b/migrations/api_v3/users.js deleted file mode 100644 index f2c8e2f52f..0000000000 --- a/migrations/api_v3/users.js +++ /dev/null @@ -1,268 +0,0 @@ -// Migrate users collection to new schema -// This should run AFTER challenges migration - -// The console-stamp module must be installed (not included in package.json) - -// It requires two environment variables: MONGODB_OLD and MONGODB_NEW - -// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). -// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM -console.log('Starting migrations/api_v3/users.js.'); - -// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. -// We've now upgraded to lodash v4 but the code used in this migration has not been -// adapted to work with it. Before this migration is used again any lodash method should -// be checked for compatibility against the v4 changelog and changed if necessary. -// https://github.com/lodash/lodash/wiki/Changelog#v400 - -require('babel-register'); -require('babel-polyfill'); - -var Bluebird = require('bluebird'); -var MongoDB = require('mongodb'); -var nconf = require('nconf'); -var mongoose = require('mongoose'); -var _ = require('lodash'); -var uuid = require('uuid'); -var consoleStamp = require('console-stamp'); -var common = require('../../common'); -var moment = require('moment'); - -// Add timestamps to console messages -consoleStamp(console); - -// Initialize configuration -require('../../website/server/libs/api-v3/setupNconf')(); - -var MONGODB_OLD = nconf.get('MONGODB_OLD'); -var MONGODB_NEW = nconf.get('MONGODB_NEW'); - -var taskDefaults = common.taskDefaults; -var MongoClient = MongoDB.MongoClient; - -mongoose.Promise = Bluebird; // otherwise mongoose models won't work - -// Load new models -var NewUser = require('../../website/server/models/user').model; -var NewTasks = require('../../website/server/models/task'); - -// To be defined later when MongoClient connects -var mongoDbOldInstance; -var oldUserCollection; - -var mongoDbNewInstance; -var newUserCollection; -var newTaskCollection; - -var BATCH_SIZE = 1000; - -var processedUsers = 0; -var totoalProcessedTasks = 0; - -var challengeTaskWithMatchingId = 0; -var challengeTaskNoMatchingId = 0; - -// Load the new tasks ids for challenges tasks -var newTasksIds = require('./newTasksIds.json'); - -// Only process users that fall in a interval ie up to -> 0000-4000-0000-0000 -var AFTER_USER_ID = nconf.get('AFTER_USER_ID'); -var BEFORE_USER_ID = nconf.get('BEFORE_USER_ID'); - -function processUsers (afterId) { - var processedTasks = 0; - var lastUser = null; - var oldUsers; - - var now = new Date(); - - var query = {}; - - if (BEFORE_USER_ID) { - query._id = {$lte: BEFORE_USER_ID}; - } - - if ((afterId || AFTER_USER_ID) && !query._id) { - query._id = {}; - } - - if (afterId) { - query._id.$gt = afterId; - } else if (AFTER_USER_ID) { - query._id.$gt = AFTER_USER_ID; - } - - var batchInsertTasks = newTaskCollection.initializeUnorderedBulkOp(); - var batchInsertUsers = newUserCollection.initializeUnorderedBulkOp(); - - console.log(`Executing users query.\nMatching users after ${afterId ? afterId : AFTER_USER_ID} and before ${BEFORE_USER_ID} (included).`); - - return oldUserCollection - .find(query) - .sort({_id: 1}) - .limit(BATCH_SIZE) - .toArray() - .then(function (oldUsersR) { - oldUsers = oldUsersR; - - console.log(`Processing ${oldUsers.length} users. Already processed ${processedUsers} users and ${totoalProcessedTasks} tasks.`); - - if (oldUsers.length === BATCH_SIZE) { - lastUser = oldUsers[oldUsers.length - 1]._id; - } - - oldUsers.forEach(function (oldUser) { - var oldTasks = oldUser.habits.concat(oldUser.dailys).concat(oldUser.rewards).concat(oldUser.todos); - delete oldUser.habits; - delete oldUser.dailys; - delete oldUser.rewards; - delete oldUser.todos; - - delete oldUser.id; - - // spookDust -> spookySparkles - - if (oldUser.achievements && oldUser.achievements.spookDust) { - oldUser.achievements.spookySparkles = oldUser.achievements.spookDust; - delete oldUser.achievements.spookDust; - } - - if (oldUser.items && oldUser.items.special && oldUser.items.special.spookDust) { - oldUser.items.special.spookySparkles = oldUser.items.special.spookDust; - delete oldUser.items.special.spookDust; - } - - if (oldUser.stats && oldUser.stats.buffs && oldUser.stats.buffs.spookySparkles) { - oldUser.stats.buffs.spookySparkles = oldUser.stats.buffs.spookDust; - delete oldUser.stats.buffs.spookDust; - } - - // end spookDust -> spookySparkles - - oldUser.tags = oldUser.tags.map(function (tag) { - return { - id: tag.id, - name: tag.name || 'tag name', - challenge: tag.challenge, - }; - }); - - if (oldUser._id === '9') { // Tyler Renelle - oldUser._id = '00000000-0000-4000-9000-000000000000'; - } - - var newUser = new NewUser(oldUser); - var isSubscribed = newUser.isSubscribed(); - - oldTasks.forEach(function (oldTask) { - oldTask._id = uuid.v4(); // create a new unique uuid - oldTask.userId = newUser._id; - oldTask._legacyId = oldTask.id; // store the old task id - delete oldTask.id; - - oldTask.challenge = oldTask.challenge || {}; - if (oldTask.challenge.id) { - if (oldTask.challenge.broken) { - oldTask.challenge.taskId = oldTask._legacyId; - } else { - var newId = newTasksIds[oldTask._legacyId + '-' + oldTask.challenge.id]; - - // Challenges' tasks ids changed - if (!newId && !oldTask.challenge.broken) { - challengeTaskNoMatchingId++; - oldTask.challenge.taskId = oldTask._legacyId; - oldTask.challenge.broken = 'CHALLENGE_TASK_NOT_FOUND'; - } else { - challengeTaskWithMatchingId++; - oldTask.challenge.taskId = newId; - } - } - } - - // Delete old completed todos - if (oldTask.type === 'todo' && oldTask.completed && (!oldTask.challenge.id || oldTask.challenge.broken)) { - if (moment(now).subtract(isSubscribed ? 90 : 30, 'days').toDate() > moment(oldTask.dateCompleted).toDate()) { - return; - } - } - - oldTask.createdAt = oldTask.dateCreated; - - if (!oldTask.text) oldTask.text = 'task text'; // required - oldTask.tags = _.map(oldTask.tags, function (tagPresent, tagId) { - return tagPresent && tagId; - }).filter(function (tag) { - return tag !== false; - }); - - if (oldTask.type !== 'todo' || (oldTask.type === 'todo' && !oldTask.completed)) { - newUser.tasksOrder[`${oldTask.type}s`].push(oldTask._id); - } - - var allTasksFields = ['_id', 'type', 'text', 'notes', 'tags', 'value', 'priority', 'attribute', 'challenge', 'reminders', 'userId', '_legacyId', 'createdAt']; - // using mongoose models is too slow - if (oldTask.type === 'habit') { - oldTask = _.pick(oldTask, allTasksFields.concat(['history', 'up', 'down'])); - } else if (oldTask.type === 'daily') { - oldTask = _.pick(oldTask, allTasksFields.concat(['completed', 'collapseChecklist', 'checklist', 'history', 'frequency', 'everyX', 'startDate', 'repeat', 'streak'])); - } else if (oldTask.type === 'todo') { - oldTask = _.pick(oldTask, allTasksFields.concat(['completed', 'collapseChecklist', 'checklist', 'date', 'dateCompleted'])); - } else if (oldTask.type === 'reward') { - oldTask = _.pick(oldTask, allTasksFields); - } else { - throw new Error('Task with no or invalid type!'); - } - - batchInsertTasks.insert(taskDefaults(oldTask)); - processedTasks++; - }); - - batchInsertUsers.insert(newUser.toObject()); - }); - - console.log(`Saving ${oldUsers.length} users and ${processedTasks} tasks.`); - - return Bluebird.all([ - batchInsertUsers.execute(), - batchInsertTasks.execute(), - ]); - }) - .then(function () { - totoalProcessedTasks += processedTasks; - processedUsers += oldUsers.length; - - console.log(`Saved ${oldUsers.length} users and their tasks.`); - console.log('Challenges\' tasks no matching id: ', challengeTaskNoMatchingId); - console.log('Challenges\' tasks with matching id: ', challengeTaskWithMatchingId); - - if (lastUser) { - return processUsers(lastUser); - } else { - return console.log('Done!'); - } - }); -} - -// Connect to the databases -Bluebird.all([ - MongoClient.connect(MONGODB_OLD), - MongoClient.connect(MONGODB_NEW), -]) -.then(function (result) { - var oldInstance = result[0]; - var newInstance = result[1]; - - mongoDbOldInstance = oldInstance; - oldUserCollection = mongoDbOldInstance.collection('users'); - - mongoDbNewInstance = newInstance; - newUserCollection = mongoDbNewInstance.collection('users'); - newTaskCollection = mongoDbNewInstance.collection('tasks'); - - console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); - - return processUsers(); -}) -.catch(function (err) { - console.error(err.stack || err); -}); diff --git a/migrations/apology_gems.js b/migrations/apology_gems.js deleted file mode 100644 index e22a428047..0000000000 --- a/migrations/apology_gems.js +++ /dev/null @@ -1 +0,0 @@ -db.users.update({_id:{$in:['']}},{$inc:{balance:0.5}},{multi:true}); \ No newline at end of file diff --git a/migrations/archive/2013/20130128_add_missing_crons.js b/migrations/archive/2013/20130128_add_missing_crons.js new file mode 100644 index 0000000000..5a28b83e69 --- /dev/null +++ b/migrations/archive/2013/20130128_add_missing_crons.js @@ -0,0 +1,5 @@ +db.users.update( + { lastCron: { $exists: false} }, + { $set: { lastCron: Number(new Date()) } }, + { multi: true } +); \ No newline at end of file diff --git a/migrations/archive/2013/20130128_merge_completed_todo_ids.js b/migrations/archive/2013/20130128_merge_completed_todo_ids.js new file mode 100644 index 0000000000..6b3f3d39af --- /dev/null +++ b/migrations/archive/2013/20130128_merge_completed_todo_ids.js @@ -0,0 +1,15 @@ +db.users.find({ completedIds: { $exists: true } }).forEach(function (user) { + let newTodoIds = user.todoIds; + user.completedIds.forEach(function (value) { + if (newTodoIds.indexOf(value) === -1) { + newTodoIds.push(value); + } + }); + db.users.update( + { _id: user._id }, + { + $set: { todoIds: newTodoIds }, + $unset: { completedIds: 1 }, + } + ); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130129_add_missing_preferences.js b/migrations/archive/2013/20130129_add_missing_preferences.js new file mode 100644 index 0000000000..d2710a5dbf --- /dev/null +++ b/migrations/archive/2013/20130129_add_missing_preferences.js @@ -0,0 +1,5 @@ +db.users.update( + {preferences: {$exists: false}}, + {$set: {preferences: {gender: 'm', armorSet: 'v1'}}}, + {multi: true} +); diff --git a/migrations/20130204_count_habits.js b/migrations/archive/2013/20130204_count_habits.js similarity index 55% rename from migrations/20130204_count_habits.js rename to migrations/archive/2013/20130204_count_habits.js index 172bee9e60..b5e3b50d6c 100644 --- a/migrations/20130204_count_habits.js +++ b/migrations/archive/2013/20130204_count_habits.js @@ -7,14 +7,14 @@ // be checked for compatibility against the v4 changelog and changed if necessary. // https://github.com/lodash/lodash/wiki/Changelog#v400 -var habits = 0, - dailies = 0, - todos = 0, - registered = { $or: [ { 'auth.local': { $exists: true } }, { 'auth.facebook': { $exists: true} } ]}; +let habits = 0, + dailies = 0, + todos = 0, + registered = { $or: [{ 'auth.local': { $exists: true } }, { 'auth.facebook': { $exists: true} }]}; -db.user.find(registered).forEach(function(u){ - //TODO this isn't working?? - habits += _.where(u.tasks, {type:'habit'}).length; - dailies += _.where(u.tasks, {type:'daily'}).length; - todos += _.where(u.tasks, {type:'todo'}).length; -}) +db.user.find(registered).forEach(function (u) { + // TODO this isn't working?? + habits += _.where(u.tasks, {type: 'habit'}).length; + dailies += _.where(u.tasks, {type: 'daily'}).length; + todos += _.where(u.tasks, {type: 'todo'}).length; +}); diff --git a/migrations/archive/2013/20130204_user_public_private_paths.js b/migrations/archive/2013/20130204_user_public_private_paths.js new file mode 100644 index 0000000000..698187985c --- /dev/null +++ b/migrations/archive/2013/20130204_user_public_private_paths.js @@ -0,0 +1,101 @@ +// %mongo server:27017/dbname underscore.js my_commands.js +// %mongo server:27017/dbname underscore.js --shell + +// db.users.find({'auth.facebook.email': 'tylerrenelle@gmail.com'}).forEach(function(user){ +db.users.find().forEach(function (user) { + if (!user._id) { + print('User has null _id'); + return; // need to figure out how to delete these buggers if they don't have an id to delete from + } + + if (user.idLists) { + print(`User ${ user._id } has already been migrated`); + return; + } + + if (user._id.indexOf('$') === 0) { + print(`User id starts with $ (${ user._id })`); + return; + } + + // even though we're clobbering user later, sometimes these are undefined and crash the script + // this saves us some ternaries + user.stats = user.stats || {}; + user.items = user.items || {}; + user.preferences = user.preferences || {}; + user.notifications = user.notifications || {}; + user.flags = user.flags || {}; + user.habitIds = user.habitIds || []; + user.dailyIds = user.dailyIds || []; + user.todoIds = user.todoIds || []; + user.rewardIds = user.rewardIds || []; + + _.each(user.tasks, function (task, key) { + if (!task.type) { + delete user.tasks[key]; + // idList will take care of itself on page-load + return; + } + if (key === '$spec') { + print(`$spec was found: ${ user._id}`); + return; + } + if (key.indexOf('$_') === 0) { + let newKey = key.replace('$_', ''), + index = user[`${task.type }Ids`].indexOf(key); + user[`${task.type }Ids`][index] = newKey; + task.id = newKey; + user.tasks[newKey] = task; + // TODO make sure this is ok, that we're not deleting the original + // Otherwise use lodash.cloneDeep + delete user.tasks[key]; + } + }); + + // New user schema has public and private paths, so we can setup proper access control with racer + // Note 'public' and 'private' are reserved words + let newUser = { + auth: user.auth, // we need this top-level due to derby-auth + apiToken: user.preferences.api_token || null, // set on update, we need derby.uuid() + preferences: { + armorSet: user.preferences.armorSet || 'v1', + gender: user.preferences.gender || 'm', + }, + balance: user.balance || 2, + lastCron: user.lastCron || Number(new Date()), + history: user.history || [], + stats: { + gp: user.stats.money || 0, + hp: user.stats.hp || 50, + exp: user.stats.exp || 0, + lvl: user.stats.lvl || 1, + }, + items: { + armor: user.items.armor || 0, + weapon: user.items.weapon || 0, + }, + tasks: user.tasks || {}, + idLists: { + habit: user.habitIds || [], + daily: user.dailyIds || [], + todo: user.todoIds || [], + reward: user.rewardIds || [], + }, + flags: { + partyEnabled: false, + itemsEnabled: user.items.itemsEnabled || false, + kickstarter: user.notifications.kickstarter || 'show', + ads: user.flags.ads || null, // null because it's set on registration + }, + party: { + current: null, + invitation: null, + }, + }; + + try { + db.users.update({_id: user._id}, newUser); + } catch (e) { + print(e); + } +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130208_idLists_to_typeIds.js b/migrations/archive/2013/20130208_idLists_to_typeIds.js new file mode 100644 index 0000000000..ecf13fb341 --- /dev/null +++ b/migrations/archive/2013/20130208_idLists_to_typeIds.js @@ -0,0 +1,19 @@ +// move idList back to root-level, is what's causing the sort bug - see https://github.com/codeparty/racer/pull/73 + +// We could just delete user.idLists, since it's re-created on refresh. However, users's first refresh will scare them +// since everything will dissappear - second refresh will bring everything back. +db.users.find().forEach(function (user) { + if (!user.idLists) return; + db.users.update( + {_id: user._id}, + { + $set: { + habitIds: user.idLists.habit, + dailyIds: user.idLists.daily, + todoIds: user.idLists.todo, + rewardIds: user.idLists.reward, + }, + // $unset:{idLists:true} // run this after the code has been pushed + } + ); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130208_user_customizations.js b/migrations/archive/2013/20130208_user_customizations.js new file mode 100644 index 0000000000..93dee7aaf2 --- /dev/null +++ b/migrations/archive/2013/20130208_user_customizations.js @@ -0,0 +1,18 @@ +db.users.update( + {items: {$exists: 0}}, + {$set: {items: {weapon: 0, armor: 0, head: 0, shield: 0 }}}, + {multi: true} +); + +db.users.find().forEach(function (user) { + let updates = { + // I'm not racist, these were just the defaults before ;) + 'preferences.skin': 'white', + 'preferences.hair': 'blond', + + 'items.head': user.items.armor, + 'items.shield': user.items.armor, + }; + + db.users.update({_id: user._id}, {$set: updates}); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130307_exp_overflow.js b/migrations/archive/2013/20130307_exp_overflow.js new file mode 100644 index 0000000000..113a8989b2 --- /dev/null +++ b/migrations/archive/2013/20130307_exp_overflow.js @@ -0,0 +1,37 @@ +// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130307_normalize_algo_values.js + +/** + * Make sure people aren't overflowing their exp with the new system + */ +db.users.find().forEach(function (user) { + function oldTnl (level) { + return Math.pow(level, 2) * 10 + level * 10 + 80; + } + + function newTnl (level) { + let value = 0; + if (level >= 100) { + value = 0; + } else { + value = Math.round((Math.pow(level, 2) * 0.25 + 10 * level + 139.75) / 10) * 10; // round to nearest 10 + } + return value; + } + + var newTnl = newTnl(user.stats.lvl); + if (user.stats.exp > newTnl) { + let percent = user.stats.exp / oldTnl(user.stats.lvl); + percent = percent > 1 ? 1 : percent; + user.stats.exp = newTnl * percent; + + try { + db.users.update( + {_id: user._id}, + {$set: {'stats.exp': user.stats.exp}}, + {multi: true} + ); + } catch (e) { + print(e); + } + } +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130307_normalize_algo_values.js b/migrations/archive/2013/20130307_normalize_algo_values.js new file mode 100644 index 0000000000..a6f96754cc --- /dev/null +++ b/migrations/archive/2013/20130307_normalize_algo_values.js @@ -0,0 +1,46 @@ +// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130307_normalize_algo_values.js + +/** + * Users were experiencing a lot of extreme Exp multiplication (https://github.com/lefnire/habitrpg/issues/594). + * This sets things straight, and in preparation for another algorithm overhaul + */ +db.users.find().forEach(function (user) { + if (user.stats.exp >= 3580) { + user.stats.exp = 0; + } + + if (user.stats.lvl > 100) { + user.stats.lvl = 100; + } + + _.each(user.tasks, function (task, key) { + // remove corrupt tasks + if (!task) { + delete user.tasks[key]; + return; + } + + // Fix busted values + if (task.value > 21.27) { + task.value = 21.27; + } else if (task.value < -47.27) { + task.value = -47.27; + } + }); + + try { + db.users.update( + {_id: user._id}, + {$set: + { + 'stats.lvl': user.stats.lvl, + 'stats.exp': user.stats.exp, + tasks: user.tasks, + }, + }, + {multi: true} + ); + } catch (e) { + print(e); + } +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130307_remove_duff_histories.js b/migrations/archive/2013/20130307_remove_duff_histories.js new file mode 100644 index 0000000000..c2971df4ae --- /dev/null +++ b/migrations/archive/2013/20130307_remove_duff_histories.js @@ -0,0 +1,28 @@ +/** + * Remove duff histories for dailies + */ +// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130307_remove_duff_histories.js +db.users.find().forEach(function (user) { + _.each(user.tasks, function (task, key) { + if (task.type === 'daily') { + // remove busted history entries + task.history = _.filter(task.history, function (h) { + return Boolean(h.value); + }); + } + }); + + try { + db.users.update( + {_id: user._id}, + {$set: + { + tasks: user.tasks, + }, + }, + {multi: true} + ); + } catch (e) { + print(e); + } +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130326_migrate_pets.js b/migrations/archive/2013/20130326_migrate_pets.js new file mode 100644 index 0000000000..57c6ad7534 --- /dev/null +++ b/migrations/archive/2013/20130326_migrate_pets.js @@ -0,0 +1,98 @@ +/** + * Migrate old pets to new system + */ +// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130326_migrate_pets.js + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let mapping = { + bearcub: {name: 'BearCub', modifier: 'Base'}, + cactus: {name: 'Cactus', modifier: 'Base'}, + dragon: {name: 'Dragon', modifier: 'Base'}, + flyingpig: {name: 'FlyingPig', modifier: 'Base'}, + fox: {name: 'Fox', modifier: 'Base'}, + lioncub: {name: 'LionCub', modifier: 'Base'}, + pandacub: {name: 'PandaCub', modifier: 'Base'}, + tigercub: {name: 'TigerCub', modifier: 'Base'}, + wolfBorder: {name: 'Wolf', modifier: 'Base'}, + wolfDesert: {name: 'Wolf', modifier: 'Desert'}, + wolfGolden: {name: 'Wolf', modifier: 'Golden'}, + wolfRed: {name: 'Wolf', modifier: 'Red'}, + wolfShade: {name: 'Wolf', modifier: 'Shade'}, + wolfSkeleton: {name: 'Wolf', modifier: 'Skeleton'}, + wolfVeteran: {name: 'Wolf', modifier: 'Veteran'}, + wolfWhite: {name: 'Wolf', modifier: 'White'}, + wolfZombie: {name: 'Wolf', modifier: 'Zombie'}, +}; + +/** + === Old Style == + pet: Object + icon: "Pet-Wolf-White.png" + index: 14 + name: "wolfWhite" + text: "White Wolf" + value: 3 + pets: Object + bearcub: true + cactus: true + + === New Style == + currentPet: Object + modifier: "Red" + name: "Wolf" + notes: "Find some Hatching Powder to sprinkle on this egg, and one day it will hatch into a loyal pet." + str: "Wolf-Red" + text: "Wolf" + value: 3 + pets: Array + 0: "PandaCub-Base" + 1: "Wolf-Base" + */ + + +db.users.find().forEach(function (user) { + if (!user.items || !user.items.pets && !user.items.pet) return; + + // migrate items.pet to items.currentPet + if (user.items.pet) { + let mapped = mapping[user.items.pet.name]; + delete user.items.pet; + user.items.currentPet = { + modifier: mapped.modifier, + name: mapped.name, + str: `${mapped.name }-${ mapped.modifier}`, + text: '', // FIXME? + }; + } + + // migrate items.pets + if (user.items.pets) { + let newPets = []; + _.each(user.items.pets, function (val, key) { + if (_.isNumber(key)) { + newPets.push(val); + // FIXME why is this happening? seems the user gets migrated already... + // throw "Error: User appears already migrated, this shouldn't be happening!" + } else { + newPets.push(`${mapping[key].name }-${ mapping[key].modifier}`); + } + }); + user.items.pets = newPets; + } + + try { + db.users.update( + {_id: user._id}, + {$set: + { items: user.items }, + } + ); + } catch (e) { + print(e); + } +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130327_apply_tokens.js b/migrations/archive/2013/20130327_apply_tokens.js new file mode 100644 index 0000000000..5a6a519b28 --- /dev/null +++ b/migrations/archive/2013/20130327_apply_tokens.js @@ -0,0 +1,109 @@ +/** + * Applies backer tokens & items (this file will be updated periodically + */ + +// mongo habitrpg ./node_modules/underscore/underscore.js migrations/20130327_apply_tokens.js + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let mapping = [ + { + tier: 1, + tokens: 0, + users: [], + }, + { + tier: 5, + tokens: 20, + users: [], + }, + { + tier: 10, + tokens: 50, + users: [], + }, + { + tier: 15, + tokens: 100, + users: [], + }, + { + tier: 30, + tokens: 150, + users: [], + }, + { + tier: 45, + tokens: 170, + users: [], + }, + { + tier: 60, + tokens: 200, + users: [], + }, + { + tier: 70, + tokens: 240, + users: [], + }, + { + tier: 80, + tokens: 240, + users: [], + }, + { + tier: 90, + tokens: 280, + users: [], + }, + { + tier: 300, + tokens: 500, + users: [], + }, + { + tier: 800, + tokens: 500, + users: [], + }, +]; + +db.users.find().forEach(function (user) { + if (!user._id) return; + + let possibleUserIds = [user._id]; + if (user.local) { + if (user.local.username) possibleUserIds.push(user.local.username); + if (user.local.email) possibleUserIds.push(user.local.email); + } + + _.each(mapping, function (tier) { + let userInTier = !_.isEmpty(_.intersection(tier.users, possibleUserIds)); + if (userInTier) { + let tokenInc = 0, + backer = user.backer || {}; + if (!backer.tokensApplied) { + tokenInc = tier.tokens; + backer.tokensApplied = true; + } + backer.tier = tier.tier; + + try { + db.users.update( + {_id: user._id}, + { + $set: { backer, 'flags.ads': 'hide' }, + $inc: { balance: tokenInc / 4 }, + } + ); + } catch (e) { + print(e); + } + } + }); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130503_max_gear_achievement.js b/migrations/archive/2013/20130503_max_gear_achievement.js new file mode 100644 index 0000000000..44cfe0a877 --- /dev/null +++ b/migrations/archive/2013/20130503_max_gear_achievement.js @@ -0,0 +1,23 @@ +/** + * For users who already have max gear, they earned the achievement + */ +// mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130503_max_gear_achievement.js +db.users.find().forEach(function (user) { + let items = user.items; + if (!items) { + return; + } + if (parseInt(items.armor) === 5 && + parseInt(items.head) === 5 && + parseInt(items.shield) === 5 && + parseInt(items.weapon) === 6) { + try { + db.users.update( + {_id: user._id}, + {$set: {'achievements.ultimateGear': true}} + ); + } catch (e) { + print(e); + } + } +}); \ No newline at end of file diff --git a/migrations/20130507_fix_broken_tags.js b/migrations/archive/2013/20130507_fix_broken_tags.js similarity index 58% rename from migrations/20130507_fix_broken_tags.js rename to migrations/archive/2013/20130507_fix_broken_tags.js index 1818442acd..9005a12dc4 100644 --- a/migrations/20130507_fix_broken_tags.js +++ b/migrations/archive/2013/20130507_fix_broken_tags.js @@ -4,9 +4,8 @@ * mongo habitrpg ./node_modules/underscore/underscore.js ./migrations/20130507_fix_broken_tags.js */ -db.users.find().forEach(function(user){ - if(!_.isArray(user.tags)) { - db.users.update({_id:user._id}, {$set:{tags:[]}}); - } - -}) \ No newline at end of file +db.users.find().forEach(function (user) { + if (!_.isArray(user.tags)) { + db.users.update({_id: user._id}, {$set: {tags: []}}); + } +}); \ No newline at end of file diff --git a/migrations/archive/2013/20130508_add_backer_pets.js b/migrations/archive/2013/20130508_add_backer_pets.js new file mode 100644 index 0000000000..c6541580e7 --- /dev/null +++ b/migrations/archive/2013/20130508_add_backer_pets.js @@ -0,0 +1 @@ +db.users.update({'backer.tier': {$gte: 80}}, {$push: {'items.pets': 'Wolf-Cerberus'}}, {multi: true}); \ No newline at end of file diff --git a/migrations/20130508_fix_duff_party_subscriptions.js b/migrations/archive/2013/20130508_fix_duff_party_subscriptions.js similarity index 51% rename from migrations/20130508_fix_duff_party_subscriptions.js rename to migrations/archive/2013/20130508_fix_duff_party_subscriptions.js index 918e323e42..c6c53a3e79 100644 --- a/migrations/20130508_fix_duff_party_subscriptions.js +++ b/migrations/archive/2013/20130508_fix_duff_party_subscriptions.js @@ -13,29 +13,28 @@ // https://github.com/lodash/lodash/wiki/Changelog#v400 // since our primary subscription will first hit parties now, we *definitely* need an index there -db.parties.ensureIndex( { 'members': 1}, {background: true} ); +db.parties.ensureIndex({ members: 1}, {background: true}); -db.parties.find().forEach(function(party){ +db.parties.find().forEach(function (party) { + if (!party.members) { + return db.parties.remove({_id: party._id}); + } - if(!party.members) { - return db.parties.remove({_id:party._id}); + // Find all members + db.users.find({_id: {$in: party.members} }, {_id: 1, party: 1}).forEach(function (user) { + // user somehow is subscribed to this party in the background, but they're it's not their primary party + if (user.party && user.party.current !== party._id) { + let i = party.members.indexOf(user._id); + party.members.splice(i, 1); } - // Find all members - db.users.find( {_id: {$in:party.members} }, {_id:1,party:1} ).forEach(function(user){ - // user somehow is subscribed to this party in the background, but they're it's not their primary party - if (user.party && user.party.current !== party._id) { - var i = party.members.indexOf(user._id); - party.members.splice(i, 1); - } + // if after we remove the user, the party is empty - delete this party + if (_.isEmpty(party.members)) { + db.parties.remove({_id: party._id}); - // if after we remove the user, the party is empty - delete this party - if (_.isEmpty(party.members)) { - db.parties.remove({_id:party._id}); - - // else just set it - } else { - db.parties.update({_id:party._id}, {$set:{members:party.members}}); - } - }) -}) + // else just set it + } else { + db.parties.update({_id: party._id}, {$set: {members: party.members}}); + } + }); +}); diff --git a/migrations/20130518_setup_groups.js b/migrations/archive/2013/20130518_setup_groups.js similarity index 54% rename from migrations/20130518_setup_groups.js rename to migrations/archive/2013/20130518_setup_groups.js index 0e04bfa1b9..3240c1f809 100644 --- a/migrations/20130518_setup_groups.js +++ b/migrations/archive/2013/20130518_setup_groups.js @@ -15,34 +15,34 @@ * 5) subscribe everyone to habitrpg (be sure to set that for default user too!) */ -db.parties.renameCollection('groups',true); -//db.parties.dropCollection(); // doesn't seem to do this step during rename... -//db.parties.ensureIndex( { 'members': 1, 'background': 1} ); +db.parties.renameCollection('groups', true); +// db.parties.dropCollection(); // doesn't seem to do this step during rename... +// db.parties.ensureIndex( { 'members': 1, 'background': 1} ); -db.groups.update({}, {$set:{type:'party'}}, {multi:true}); +db.groups.update({}, {$set: {type: 'party'}}, {multi: true}); -//migrate invitation mechanisms +// migrate invitation mechanisms db.users.update( - {}, - { - $remove:{party:1}, - $set:{invitations:{party:null,guilds:[]}} - }, - {multi:1} + {}, + { + $remove: {party: 1}, + $set: {invitations: {party: null, guilds: []}}, + }, + {multi: 1} ); tavern = db.tavern.findOne(); db.tavern.drop(); -//TODO make as a callback of previous, or make sure group.type is still 'guild' for habitrpg in the end +// TODO make as a callback of previous, or make sure group.type is still 'guild' for habitrpg in the end db.groups.insert({ - _id: "habitrpg", - leader: '9', - type: 'guild', - name: "HabitRPG", - chat: tavern.messages, - info: { - blurb: '', - websites: [] - } + _id: 'habitrpg', + leader: '9', + type: 'guild', + name: 'HabitRPG', + chat: tavern.messages, + info: { + blurb: '', + websites: [], + }, }); \ No newline at end of file diff --git a/migrations/archive/2013/20130602_survey_rewards.js b/migrations/archive/2013/20130602_survey_rewards.js new file mode 100644 index 0000000000..4c819c6e2e --- /dev/null +++ b/migrations/archive/2013/20130602_survey_rewards.js @@ -0,0 +1,31 @@ +// mongo habitrpg ./node_modules/lodash/lodash.js migrations/20130602_survey_rewards.js + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let members = []; +members = _.uniq(members); + +let query = { + _id: {$exists: 1}, + $or: [ + {_id: {$in: members}}, + // {'profile.name': {$in: members}}, + {'auth.facebook.name': {$in: members}}, + {'auth.local.username': {$in: members}}, + {'auth.local.email': {$in: members}}, + ], +}; + +print(db.users.count(query)); + +db.users.update(query, + { + $set: { 'achievements.helpedHabit': true }, + $inc: { balance: 2.5 }, + }, + {multi: true} +); \ No newline at end of file diff --git a/migrations/archive/2013/20130612_survey_rewards_individual.js b/migrations/archive/2013/20130612_survey_rewards_individual.js new file mode 100644 index 0000000000..3a2e1fbed4 --- /dev/null +++ b/migrations/archive/2013/20130612_survey_rewards_individual.js @@ -0,0 +1,9 @@ +// mongo habitrpg migrations/20130612_survey_rewards_individual.js + +let query = {_id: ''}; + +db.users.update(query, + { + $set: { 'achievements.helpedHabit': true }, + $inc: { balance: 2.5 }, + }); \ No newline at end of file diff --git a/migrations/archive/2013/20130615_add_extra_indexes.js b/migrations/archive/2013/20130615_add_extra_indexes.js new file mode 100644 index 0000000000..233f266835 --- /dev/null +++ b/migrations/archive/2013/20130615_add_extra_indexes.js @@ -0,0 +1,4 @@ +db.users.ensureIndex({ _id: 1, apiToken: 1 }, {background: true}); +db.groups.ensureIndex({ members: 1 }, {background: true}); +db.groups.ensureIndex({ type: 1 }, {background: true}); +db.groups.ensureIndex({ type: 1, privacy: 1 }, {background: true}); \ No newline at end of file diff --git a/migrations/archive/2013/20130908_cleanup_corrupt_tags.js b/migrations/archive/2013/20130908_cleanup_corrupt_tags.js new file mode 100644 index 0000000000..8fdb6f9f54 --- /dev/null +++ b/migrations/archive/2013/20130908_cleanup_corrupt_tags.js @@ -0,0 +1,16 @@ +// mongo habitrpg ./node_modules/lodash/lodash.js migrations/20130908_cleanup_corrupt_tags.js + +// Racer was notorious for adding duplicates, randomly deleting documents, etc. Once we pull the plug on old.habit, +// run this migration to cleanup all the corruption + +db.users.find().forEach(function (user) { + user.tags = _.filter(user.tags, function (t) { + return t ? t.id : false; + }); + + try { + db.users.update({_id: user._id}, {$set: {tags: user.tags}}); + } catch (e) { + print(e); + } +}); diff --git a/migrations/20130908_cleanup_derby_corruption.js b/migrations/archive/2013/20130908_cleanup_derby_corruption.js similarity index 61% rename from migrations/20130908_cleanup_derby_corruption.js rename to migrations/archive/2013/20130908_cleanup_derby_corruption.js index 6cac534587..d25eea6de9 100644 --- a/migrations/20130908_cleanup_derby_corruption.js +++ b/migrations/archive/2013/20130908_cleanup_derby_corruption.js @@ -1,4 +1,4 @@ -//mongo habitrpg ./node_modules/lodash/lodash.js migrations/20130908_cleanup_derby_corruption.js +// mongo habitrpg ./node_modules/lodash/lodash.js migrations/20130908_cleanup_derby_corruption.js // Racer was notorious for adding duplicates, randomly deleting documents, etc. Once we pull the plug on old.habit, // run this migration to cleanup all the corruption @@ -9,49 +9,48 @@ // be checked for compatibility against the v4 changelog and changed if necessary. // https://github.com/lodash/lodash/wiki/Changelog#v400 -db.users.find().forEach(function(user){ - +db.users.find().forEach(function (user) { // remove corrupt tasks, which will either be null-value or no id - user.tasks = _.reduce(user.tasks, function(m,task,k) { + user.tasks = _.reduce(user.tasks, function (m, task, k) { if (!task || !task.id) return m; - if (isNaN(+task.value)) task.value = 0; + if (isNaN(Number(task.value))) task.value = 0; m[k] = task; return m; }, {}); // fix NaN stats - _.each(user.stats, function(v,k) { - if (!v || isNaN(+v)) user.stats[k] = 0; + _.each(user.stats, function (v, k) { + if (!v || isNaN(Number(v))) user.stats[k] = 0; return true; }); // remove duplicates, restore ghost tasks - ['habit', 'daily', 'todo', 'reward'].forEach(function(type) { - var idList = user[type + "Ids"]; - var taskIds = _.pluck(_.where(user.tasks, {type: type}), 'id'); - var union = _.union(idList, taskIds); - var preened = _.filter(union, function(id) { + ['habit', 'daily', 'todo', 'reward'].forEach(function (type) { + let idList = user[`${type }Ids`]; + let taskIds = _.pluck(_.where(user.tasks, {type}), 'id'); + let union = _.union(idList, taskIds); + let preened = _.filter(union, function (id) { return id && _.contains(taskIds, id); }); if (!_.isEqual(idList, preened)) { - user[type + "Ids"] = preened; + user[`${type }Ids`] = preened; } }); // temporarily remove broken eggs. we'll need to write a migration script to grant gems for and remove these instead if (user.items && user.items.eggs) { - user.items.eggs = _.filter(user.items.eggs,function(egg){ + user.items.eggs = _.filter(user.items.eggs, function (egg) { if (_.isString(egg)) { user.balance += 0.75; // give them 3 gems for each broken egg } else { return true; } - }) + }); } try { - db.users.update({_id:user._id}, user); - } catch(e) { + db.users.update({_id: user._id}, user); + } catch (e) { print(e); } -}) +}); diff --git a/migrations/20130908_remove_staged_users.js b/migrations/archive/2013/20130908_remove_staged_users.js similarity index 86% rename from migrations/20130908_remove_staged_users.js rename to migrations/archive/2013/20130908_remove_staged_users.js index 7bf75c0096..a9b575c5dd 100644 --- a/migrations/20130908_remove_staged_users.js +++ b/migrations/archive/2013/20130908_remove_staged_users.js @@ -8,7 +8,7 @@ * If we experience any troubles with removed staging users, come back to a snapshot and restore accounts. This will * give a peak into possible conflict accounts: */ -/*db.users.count({ +/* db.users.count({ "auth.local": {$exists: false}, "auth.facebook": {$exists: false}, "history.exp.5": {$exists: 1}, @@ -22,9 +22,9 @@ * in we'll be using localStorage anyway instead of creating a new database record */ db.users.remove({ - // Un-registered users - "auth.local": {$exists: false}, - "auth.facebook": {$exists: false} + // Un-registered users + 'auth.local': {$exists: false}, + 'auth.facebook': {$exists: false}, }); /** @@ -32,6 +32,6 @@ db.users.remove({ * Another vestige of Racer. Empty parties shouldn't be being created anymore in the new site */ db.groups.remove({ - 'type': 'party', - $where: "return this.members.length === 0" + type: 'party', + $where: 'return this.members.length === 0', }); \ No newline at end of file diff --git a/migrations/archive/2013/20131022_purchased_and_newStuff.js b/migrations/archive/2013/20131022_purchased_and_newStuff.js new file mode 100644 index 0000000000..0de25a7fe1 --- /dev/null +++ b/migrations/archive/2013/20131022_purchased_and_newStuff.js @@ -0,0 +1,5 @@ +db.users.find().forEach(function (user) { + if (!user.purchased) user.purchased = {hair: {}, skin: {}}; + user.purchased.ads = user.flags && Boolean(user.flags.ads); + db.users.update({_id: user._id}, {$set: {purchased: user.purchased, 'flags.newStuff': true}, $unset: {'flags.ads': 1}}); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20131022_restore_ads.js b/migrations/archive/2013/20131022_restore_ads.js new file mode 100644 index 0000000000..141d6ea1cd --- /dev/null +++ b/migrations/archive/2013/20131022_restore_ads.js @@ -0,0 +1,12 @@ +// node .migrations/20131022_restore_ads.js +let mongo = require('mongoskin'); +let _ = require('lodash'); +let dbBackup = mongo.db('localhost:27017/habitrpg?auto_reconnect'); +let dbLive = mongo.db('localhost:27017/habitrpg2?auto_reconnect'); +let count = 89474; +dbBackup.collection('users').findEach({$or: [{'flags.ads': 'show'}, {'flags.ads': null}]}, {batchSize: 10}, function (err, item) { + if (err) return console.error({err}); + if (!item || !item._id) return console.error('blank user'); + dbLive.collection('users').update({_id: item._id}, {$set: {'purchased.ads': false}, $unset: {'flags.ads': 1}}); + if (--count <= 0) console.log('DONE!'); +}); \ No newline at end of file diff --git a/migrations/20131028_task_subdocs_tags_invites.js b/migrations/archive/2013/20131028_task_subdocs_tags_invites.js similarity index 51% rename from migrations/20131028_task_subdocs_tags_invites.js rename to migrations/archive/2013/20131028_task_subdocs_tags_invites.js index f4a8b720c2..7e4c38b286 100644 --- a/migrations/20131028_task_subdocs_tags_invites.js +++ b/migrations/archive/2013/20131028_task_subdocs_tags_invites.js @@ -3,7 +3,7 @@ // TODO it might be better we just find() and save() all user objects using mongoose, and rely on our defined pre('save') // and default values to "migrate" users. This way we can make sure those parts are working properly too // @see http://stackoverflow.com/questions/14867697/mongoose-full-collection-scan -//Also, what do we think of a Mongoose Migration module? something like https://github.com/madhums/mongoose-migrate +// Also, what do we think of a Mongoose Migration module? something like https://github.com/madhums/mongoose-migrate // IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. // We've now upgraded to lodash v4 but the code used in this migration has not been @@ -11,28 +11,27 @@ // be checked for compatibility against the v4 changelog and changed if necessary. // https://github.com/lodash/lodash/wiki/Changelog#v400 -db.users.find().forEach(function(user){ - +db.users.find().forEach(function (user) { // Add invites to groups // ------------------------- - if(user.invitations){ - if(user.invitations.party){ - db.groups.update({_id: user.invitations.party.id}, {$addToSet:{invites:user._id}}); + if (user.invitations) { + if (user.invitations.party) { + db.groups.update({_id: user.invitations.party.id}, {$addToSet: {invites: user._id}}); } - if(user.invitations.guilds){ - _.each(user.invitations.guilds, function(guild){ - db.groups.update({_id: guild.id}, {$addToSet:{invites:user._id}}); + if (user.invitations.guilds) { + _.each(user.invitations.guilds, function (guild) { + db.groups.update({_id: guild.id}, {$addToSet: {invites: user._id}}); }); } } // Cleanup broken tags // ------------------------- - _.each(user.tasks, function(task){ - _.each(task.tags, function(val, key){ - _.each(user.tags, function(tag){ - if(key == tag.id) delete task.tags[key]; + _.each(user.tasks, function (task) { + _.each(task.tags, function (val, key) { + _.each(user.tags, function (tag) { + if (key === tag.id) delete task.tags[key]; }); }); }); @@ -40,25 +39,25 @@ db.users.find().forEach(function(user){ // Fix corrupt dates // ------------------------- user.lastCron = new Date(user.lastCron); - if (user.lastCron == 'Invalid Date') user.lastCron = new Date(); + if (user.lastCron === 'Invalid Date') user.lastCron = new Date(); if (user.auth) { // what to do with !auth? - _.defaults(user.auth, {timestamps: {created:undefined, loggedin: undefined}}); + _.defaults(user.auth, {timestamps: {created: undefined, loggedin: undefined}}); _.defaults(user.auth.timestamps, {created: new Date(user.lastCron), loggedin: new Date(user.lastCron)}); } // Fix missing history // ------------------------- - _.defaults(user, {history:{}}); - _.defaults(user.history,{exp:[], todos:[]}); + _.defaults(user, {history: {}}); + _.defaults(user.history, {exp: [], todos: []}); // Add username // ------------------------- - if (!user.profile) user.profile = {name:undefined}; + if (!user.profile) user.profile = {name: undefined}; if (_.isEmpty(user.profile.name) && user.auth) { - var fb = user.auth.facebook; + let fb = user.auth.facebook; user.profile.name = - (user.auth.local && user.auth.local.username) || - (fb && (fb.displayName || fb.name || fb.username || (fb.first_name && fb.first_name + ' ' + fb.last_name))) || + user.auth.local && user.auth.local.username || + fb && (fb.displayName || fb.name || fb.username || fb.first_name && `${fb.first_name } ${ fb.last_name}`) || 'Anonymous'; } @@ -71,62 +70,62 @@ db.users.find().forEach(function(user){ print(user._id); } } else { - _.each(['habit', 'daily', 'todo', 'reward'], function(type) { + _.each(['habit', 'daily', 'todo', 'reward'], function (type) { // we use _.transform instead of a simple _.where in order to maintain sort-order - user[type + "s"] = _.reduce(user[type + "Ids"], function(m, tid) { - var task = user.tasks[tid], + user[`${type }s`] = _.reduce(user[`${type }Ids`], function (m, tid) { + let task = user.tasks[tid], newTask = {}; if (!task) return m; // remove null tasks // Cleanup tasks for TaskSchema newTask._id = newTask.id = task.id; - newTask.text = (_.isString(task.text)) ? task.text : ''; + newTask.text = _.isString(task.text) ? task.text : ''; if (_.isString(task.notes)) newTask.notes = task.notes; - newTask.tags = (_.isObject(task.tags)) ? task.tags : {}; - newTask.type = (_.isString(task.type)) ? task.type : 'habit'; - newTask.value = (_.isNumber(task.value)) ? task.value : 0; - newTask.priority = (_.isString(task.priority)) ? task.priority : '!'; + newTask.tags = _.isObject(task.tags) ? task.tags : {}; + newTask.type = _.isString(task.type) ? task.type : 'habit'; + newTask.value = _.isNumber(task.value) ? task.value : 0; + newTask.priority = _.isString(task.priority) ? task.priority : '!'; switch (newTask.type) { case 'habit': - newTask.up = (_.isBoolean(task.up)) ? task.up : true; - newTask.down = (_.isBoolean(task.down)) ? task.down : true; - newTask.history = (_.isArray(task.history)) ? task.history : []; + newTask.up = _.isBoolean(task.up) ? task.up : true; + newTask.down = _.isBoolean(task.down) ? task.down : true; + newTask.history = _.isArray(task.history) ? task.history : []; break; case 'daily': - newTask.repeat = (_.isObject(task.repeat)) ? task.repeat : {m:1, t:1, w:1, th:1, f:1, s:1, su:1}; - newTask.streak = (_.isNumber(task.streak)) ? task.streak : 0; - newTask.completed = (_.isBoolean(task.completed)) ? task.completed : false; - newTask.history = (_.isArray(task.history)) ? task.history : []; + newTask.repeat = _.isObject(task.repeat) ? task.repeat : {m: 1, t: 1, w: 1, th: 1, f: 1, s: 1, su: 1}; + newTask.streak = _.isNumber(task.streak) ? task.streak : 0; + newTask.completed = _.isBoolean(task.completed) ? task.completed : false; + newTask.history = _.isArray(task.history) ? task.history : []; break; case 'todo': - newTask.completed = (_.isBoolean(task.completed)) ? task.completed : false; + newTask.completed = _.isBoolean(task.completed) ? task.completed : false; break; } m.push(newTask); return m; }, []); - delete user[type + 'Ids']; + delete user[`${type }Ids`]; }); delete user.tasks; } try { - db.users.update({_id:user._id}, user); - } catch(e) { + db.users.update({_id: user._id}, user); + } catch (e) { print(e); } }); // Remove old groups.*.challenges, they're not compatible with the new system, set member counts // ------------------------- -db.groups.find().forEach(function(group){ - db.groups.update({_id:group._id}, { - $set:{memberCount: _.size(group.members)}, - $pull:{challenges:1} - }) +db.groups.find().forEach(function (group) { + db.groups.update({_id: group._id}, { + $set: {memberCount: _.size(group.members)}, + $pull: {challenges: 1}, + }); }); // HabitRPG => Tavern // ------------------------- -db.groups.update({_id:'habitrpg'}, {$set:{name:'Tavern'}}); \ No newline at end of file +db.groups.update({_id: 'habitrpg'}, {$set: {name: 'Tavern'}}); \ No newline at end of file diff --git a/migrations/archive/2013/20131102_restore_task_ids.js b/migrations/archive/2013/20131102_restore_task_ids.js new file mode 100644 index 0000000000..89361a4777 --- /dev/null +++ b/migrations/archive/2013/20131102_restore_task_ids.js @@ -0,0 +1,25 @@ +// mongo habitrpg ./node_modules/lodash/lodash.js ./migrations/20131028_task_subdocs_tags_invites.js + +db.challenges.find().forEach(function (chal) { + _.each(chal.habits.concat(chal.dailys).concat(chal.todos).concat(chal.rewards), function (task) { + task.id = task.id || task._id; + }); + try { + db.challenges.update({_id: chal._id}, chal); + db.groups.update({_id: chal.group}, {$addToSet: {challenges: chal._id}}); + } catch (e) { + print(e); + } +}); + +db.users.find().forEach(function (user) { + _.each(user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards), function (task) { + task.id = task.id || task._id; + }); + try { + db.users.update({_id: user._id}, user); + } catch (e) { + print(e); + } +}); + diff --git a/migrations/archive/2013/20131104_remove_invalid_dues.js b/migrations/archive/2013/20131104_remove_invalid_dues.js new file mode 100644 index 0000000000..696a18004e --- /dev/null +++ b/migrations/archive/2013/20131104_remove_invalid_dues.js @@ -0,0 +1,7 @@ +db.users.find({}, {todos: 1}).forEach(function (user) { + _.each(user.todos, function (task) { + if (moment(task.date).toDate() === 'Invalid Date') + task.date = moment().format('MM/DD/YYYY'); + }); + db.users.update({_id: user._id}, {$set: {todos: user.todos}}); +}); \ No newline at end of file diff --git a/migrations/20131104_restore_lost_task_data.js b/migrations/archive/2013/20131104_restore_lost_task_data.js similarity index 55% rename from migrations/20131104_restore_lost_task_data.js rename to migrations/archive/2013/20131104_restore_lost_task_data.js index e77f57de3f..26b8692401 100644 --- a/migrations/20131104_restore_lost_task_data.js +++ b/migrations/archive/2013/20131104_restore_lost_task_data.js @@ -5,8 +5,8 @@ * schemas became more strict. See conversation at https://github.com/HabitRPG/habitrpg/issues/1712 , * this restores task tags, streaks, due-dates, values */ -var mongo = require('mongoskin'); -var _ = require('lodash'); +let mongo = require('mongoskin'); +let _ = require('lodash'); // IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. // We've now upgraded to lodash v4 but the code used in this migration has not been @@ -14,47 +14,47 @@ var _ = require('lodash'); // be checked for compatibility against the v4 changelog and changed if necessary. // https://github.com/lodash/lodash/wiki/Changelog#v400 -var backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); -var liveUsers = mongo.db('localhost:27017/habitrpg_new?auto_reconnect').collection('users'); +let backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); +let liveUsers = mongo.db('localhost:27017/habitrpg_new?auto_reconnect').collection('users'); -backupUsers.count(function(err, count){ +backupUsers.count(function (err, count) { if (err) return console.error(err); - backupUsers.findEach({}, {batchSize:250}, function(err, before){ + backupUsers.findEach({}, {batchSize: 250}, function (err, before) { if (err) return console.error(err); if (!before) return console.log('!before'); - liveUsers.findById(before._id, function(err, after){ + liveUsers.findOne({_id: before._id}, function (err, after) { if (err) return console.error(err); if (!after) { count--; - return console.log(before._id + ' deleted?'); + return console.log(`${before._id } deleted?`); } - if (before._id == '9') console.log('lefnire processed'); - _.each(before.tasks, function(tBefore){ - var tAfter = _.find(after[tBefore.type+'s'], {id:tBefore.id}); + if (before._id === '9') console.log('lefnire processed'); + _.each(before.tasks, function (tBefore) { + let tAfter = _.find(after[`${tBefore.type}s`], {id: tBefore.id}); if (!tAfter) return; // task has been deleted since launch // Restore deleted tags if (!_.isEmpty(tBefore.tags) && _.isEmpty(tAfter.tags)) tAfter.tags = tBefore.tags; // Except tags which are no longer available on the updated user - _.each(tAfter.tags, function(v,k){ //value is true, key is tag.id - if (!_.find(after.tags,{id:k})) delete tAfter.tags[k]; - }) + _.each(tAfter.tags, function (v, k) { // value is true, key is tag.id + if (!_.find(after.tags, {id: k})) delete tAfter.tags[k]; + }); // Restore deleted streaks - if (+tBefore.streak > tAfter.streak) - tAfter.streak = +tBefore.streak; + if (Number(tBefore.streak) > tAfter.streak) + tAfter.streak = Number(tBefore.streak); - if (!!tBefore.date && !tAfter.date) + if (Boolean(tBefore.date) && !tAfter.date) tAfter.date = tBefore.date; // Restore deleted values - if (+tBefore.value != 0 && tAfter.value == 0) - tAfter.value = +tBefore.value; - }) + if (Number(tBefore.value) != 0 && tAfter.value === 0) + tAfter.value = Number(tBefore.value); + }); after._v++; - liveUsers.update({_id:after._id}, after); - if (--count <= 0) console.log("DONE!"); - }) + liveUsers.update({_id: after._id}, after); + if (--count <= 0) console.log('DONE!'); + }); }); }); \ No newline at end of file diff --git a/migrations/archive/2013/20131105_remove_history_ids.js b/migrations/archive/2013/20131105_remove_history_ids.js new file mode 100644 index 0000000000..c7e09a334a --- /dev/null +++ b/migrations/archive/2013/20131105_remove_history_ids.js @@ -0,0 +1,21 @@ +function deleteId (h) { + delete h._id; +} + +db.users.find({}, {habits: 1, dailys: 1, history: 1}).forEach(function (user) { + if (user.history) { + _.each(['todos', 'exp'], function (type) { + if (user.history[type]) { + _.each(user.history.exp, deleteId); + } + }); + } else { + user.history = {exp: [], todos: []}; + } + + _.each(['habits', 'dailys'], function (type) { + _.each(user[type].history, deleteId); + }); + + db.users.update({_id: user._id}, {$set: {history: user.history, habits: user.habits, dailys: user.dailys}}); +}); \ No newline at end of file diff --git a/migrations/20131107_from_backer_to_contributor.js b/migrations/archive/2013/20131107_from_backer_to_contributor.js similarity index 63% rename from migrations/20131107_from_backer_to_contributor.js rename to migrations/archive/2013/20131107_from_backer_to_contributor.js index d5a4ee851b..1c083ad6ff 100644 --- a/migrations/20131107_from_backer_to_contributor.js +++ b/migrations/archive/2013/20131107_from_backer_to_contributor.js @@ -1,9 +1,9 @@ db.users.find({ $or: [ - {'backer.admin':{$exists:1}}, - {'backer.contributor':{$exists:1}} - ] -},{backer:1}).forEach(function(user){ + {'backer.admin': {$exists: 1}}, + {'backer.contributor': {$exists: 1}}, + ], +}, {backer: 1}).forEach(function (user) { user.contributor = {}; user.contributor.admin = user.backer.admin; delete user.backer.admin; @@ -14,5 +14,5 @@ db.users.find({ delete user.backer.contributor; } - db.users.update({_id:user._id}, {$set:{backer:user.backer, contributor:user.contributor}}); + db.users.update({_id: user._id}, {$set: {backer: user.backer, contributor: user.contributor}}); }); \ No newline at end of file diff --git a/migrations/archive/2013/20131108_add_gems_for_contribs.js b/migrations/archive/2013/20131108_add_gems_for_contribs.js new file mode 100644 index 0000000000..c05c88c4ec --- /dev/null +++ b/migrations/archive/2013/20131108_add_gems_for_contribs.js @@ -0,0 +1,4 @@ +// Increase everyone's gems per their contribution level +db.users.find({'contributor.level': {$gt: 0}}, {contributor: 1, balance: 1}).forEach(function (user) { + db.users.update({_id: user._id}, {$inc: {balance: user.contributor.level * 0.5} }); +}); \ No newline at end of file diff --git a/migrations/20131109_refactor_pets.js b/migrations/archive/2013/20131109_refactor_pets.js similarity index 61% rename from migrations/20131109_refactor_pets.js rename to migrations/archive/2013/20131109_refactor_pets.js index f5d9f7d567..2d73442077 100644 --- a/migrations/20131109_refactor_pets.js +++ b/migrations/archive/2013/20131109_refactor_pets.js @@ -1,10 +1,11 @@ db.users.find( - {$where: "Array.isArray(this.items.pets) || Array.isArray(this.items.eggs) || Array.isArray(this.items.hatchingPotions)"}, - {backer: 1, items:1} -).forEach(function(user){ - + {$where: 'Array.isArray(this.items.pets) || Array.isArray(this.items.eggs) || Array.isArray(this.items.hatchingPotions)'}, + {backer: 1, items: 1} +).forEach(function (user) { if (_.isArray(user.items.pets)) { - user.items.pets = _.reduce(user.items.pets, function(m,v){ m[v] = 5; return m;}, {}); + user.items.pets = _.reduce(user.items.pets, function (m, v) { + m[v] = 5; return m; + }, {}); } if (!_.isString(user.items.currentPet)) { @@ -12,7 +13,7 @@ db.users.find( } if (_.isArray(user.items.eggs)) { - user.items.eggs = _.reduce(user.items.eggs, function(m,v){ + user.items.eggs = _.reduce(user.items.eggs, function (m, v) { if (!m[v.name]) m[v.name] = 0; m[v.name]++; return m; @@ -20,7 +21,7 @@ db.users.find( } if (_.isArray(user.items.hatchingPotions)) { - user.items.hatchingPotions = _.reduce(user.items.hatchingPotions, function(m,v){ + user.items.hatchingPotions = _.reduce(user.items.hatchingPotions, function (m, v) { if (!m[v]) m[v] = 0; m[v]++; return m; @@ -35,5 +36,5 @@ db.users.find( user.items.mounts['LionCub-Ethereal'] = true; } - db.users.update({_id:user._id}, {$set:{items:user.items}}); + db.users.update({_id: user._id}, {$set: {items: user.items}}); }); diff --git a/migrations/archive/2013/20131111_task_NaN.js b/migrations/archive/2013/20131111_task_NaN.js new file mode 100644 index 0000000000..e4df7c5ca6 --- /dev/null +++ b/migrations/archive/2013/20131111_task_NaN.js @@ -0,0 +1,15 @@ +// This migration has already been run in the past. It's vital to fix these users presently, but we need to find +// out why task values are ever getting in as NaN. My guess is API PUT /tasks/:tid routes +db.users.find({}, {habits: 1, dailys: 1, todos: 1, rewards: 1}).forEach(function (user) { + _.each(['habits', 'dailys', 'todos', 'rewards'], function (type) { + _.each(user[type], function (task) { + task.value = Number(task.value); + if (_.isNaN(task.value)) { + task.value = 0; + print(user._id); + } + }); + }); + + db.users.update({_id: user._id}, {$set: {habits: user.habits, dailys: user.dailys, todos: user.todos, rewards: user.rewards}}); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20131114_migrate_websites_to_blurb.js b/migrations/archive/2013/20131114_migrate_websites_to_blurb.js new file mode 100644 index 0000000000..f398be79a2 --- /dev/null +++ b/migrations/archive/2013/20131114_migrate_websites_to_blurb.js @@ -0,0 +1,14 @@ +// Migrate all users websites to the profile blurb field +db.users.find({'profile.websites': {$exists: true}}).forEach(function (user) { + db.users.update({_id: user._id}, { + $set: {'profile.blurb': `${user.profile.blurb }\n * ${ user.profile.websites.join('\n * ')}`}, + $unset: {'profile.websites': 1}, + }); +}); + +db.groups.find({'websites.0': {$exists: true}}).forEach(function (group) { + db.groups.update({_id: group._id}, { + $set: {description: `${group.description }\n * ${ group.websites.join('\n * ')}`}, + $unset: {websites: 1}, + }); +}); diff --git a/migrations/archive/2013/20131115_update_gear_preferences.js b/migrations/archive/2013/20131115_update_gear_preferences.js new file mode 100644 index 0000000000..d6bb363762 --- /dev/null +++ b/migrations/archive/2013/20131115_update_gear_preferences.js @@ -0,0 +1,10 @@ +// Add defaults to show gears in all users +db.users.update( + {}, + {$set: { + 'preferences.showWeapon': true, + 'preferences.showShield': true, + 'preferences.showArmor': true, + }}, + {multi: true} +); diff --git a/migrations/archive/2013/20131117_fix_task_types.js b/migrations/archive/2013/20131117_fix_task_types.js new file mode 100644 index 0000000000..570f315bb1 --- /dev/null +++ b/migrations/archive/2013/20131117_fix_task_types.js @@ -0,0 +1,18 @@ +// TODO figure out why this is happening in the first place + +db.users.find({}, {habits: 1, dailys: 1, todos: 1, rewards: 1}).forEach(function (user) { + _.each(user.habits, function (task) { + task.type = 'habit'; + }); + _.each(user.dailys, function (task) { + task.type = 'daily'; + }); + _.each(user.todos, function (task) { + task.type = 'todo'; + }); + _.each(user.rewards, function (task) { + task.type = 'reward'; + }); + + db.users.update({_id: user._id}, {$set: {habits: user.habits, dailys: user.dailys, todos: user.todos, rewards: user.rewards}}); +}); diff --git a/migrations/archive/2013/20131117_remove_undefined_pets.js b/migrations/archive/2013/20131117_remove_undefined_pets.js new file mode 100644 index 0000000000..bcfbe3d216 --- /dev/null +++ b/migrations/archive/2013/20131117_remove_undefined_pets.js @@ -0,0 +1,12 @@ +// once and for all! + +db.users.find({'items.pets': {$exists: 1}}, {'items.pets': 1}).forEach(function (user) { + _.reduce(user.items.pets, function (m, v, k) { + if (!k.indexOf('undefined')) m.push(k); + return m; + }, []).forEach(function (key) { + delete user.items.pets[key]; + }); + + db.users.update({_id: user._id}, { $set: {'items.pets': user.items.pets} }); +}); diff --git a/migrations/archive/2013/20131122_deleted_tags.js b/migrations/archive/2013/20131122_deleted_tags.js new file mode 100644 index 0000000000..0ca01616dc --- /dev/null +++ b/migrations/archive/2013/20131122_deleted_tags.js @@ -0,0 +1,13 @@ +// Cleanup broken tags +// ------------------------- +db.users.find().forEach(function (user) { + let tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards); + + _.each(tasks, function (task) { + _.each(task.tags, function (value, key) { // value is true, key is tag.id + if (!_.find(user.tags, {id: key})) delete task.tags[key]; + }); + }); + + db.users.update({_id: user._id}, user); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20131123_set_default_party_order.js b/migrations/archive/2013/20131123_set_default_party_order.js new file mode 100644 index 0000000000..07a222035b --- /dev/null +++ b/migrations/archive/2013/20131123_set_default_party_order.js @@ -0,0 +1,8 @@ +// Add default to randomize party members list +db.users.update( + {}, + {$set: { + 'party.order': 'random', + }}, + {multi: true} +); diff --git a/migrations/archive/2013/20131126_clean_dayStart.js b/migrations/archive/2013/20131126_clean_dayStart.js new file mode 100644 index 0000000000..12a0eb0b8f --- /dev/null +++ b/migrations/archive/2013/20131126_clean_dayStart.js @@ -0,0 +1,5 @@ +db.users.find({'preferences.dayStart': {$exists: 1}}, {'preferences.dayStart': 1}).forEach(function (user) { + let dayStart = Number(user.preferences.dayStart); + dayStart = _.isNaN(dayStart) || dayStart < 0 || dayStart > 24 ? 0 : dayStart; + db.users.update({_id: user._id}, {$set: {'preferences.dayStart': dayStart}}); +}); diff --git a/migrations/archive/2013/20131126_turkey_pet.js b/migrations/archive/2013/20131126_turkey_pet.js new file mode 100644 index 0000000000..f93848e926 --- /dev/null +++ b/migrations/archive/2013/20131126_turkey_pet.js @@ -0,0 +1 @@ +db.users.update({}, {$set: {'items.pets.Turkey-Base': 5, 'flags.newStuff': true}}, {multi: true}); \ No newline at end of file diff --git a/migrations/archive/2013/20131127_restore_dayStart.js b/migrations/archive/2013/20131127_restore_dayStart.js new file mode 100644 index 0000000000..e23bc00b59 --- /dev/null +++ b/migrations/archive/2013/20131127_restore_dayStart.js @@ -0,0 +1,42 @@ +// node .migrations/20131127_restore_dayStart.js + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); +let liveUsers = mongo.db('localhost:27017/habitrpg_new?auto_reconnect').collection('users'); + +let query = {'preferences.dayStart': {$exists: 1, $ne: 0}}; +let select = {'preferences.dayStart': 1}; + +backupUsers.count(query, function (err, count) { + if (err) return console.error(err); + backupUsers.findEach(query, select, {batchSize: 20}, function (err, before) { + if (err) return console.error(err); + if (!before) { + count--; return console.log('!before'); + } + liveUsers.findOne({_id: before._id}, function (err, after) { + if (err) return console.error(err); + if (!after) { + count--; return console.log(`${before._id } deleted?`); + } + + let dayStart = Number(before.preferences.dayStart); + if (after.preferences.dayStart === 0 && dayStart != 0) { + dayStart = _.isNaN(dayStart) || dayStart < 0 || dayStart > 24 ? 0 : dayStart; + } else { + dayStart = after.preferences.dayStart; + } + + liveUsers.update({_id: after._id}, {$inc: {_v: 1}, $set: {'preferences.dayStart': dayStart}}); + if (--count <= 0) console.log('DONE!'); + }); + }); +}); \ No newline at end of file diff --git a/migrations/20131214_classes.coffee b/migrations/archive/2013/20131214_classes.coffee similarity index 100% rename from migrations/20131214_classes.coffee rename to migrations/archive/2013/20131214_classes.coffee diff --git a/migrations/20131217_unearned_backer_gear.js b/migrations/archive/2013/20131217_unearned_backer_gear.js similarity index 51% rename from migrations/20131217_unearned_backer_gear.js rename to migrations/archive/2013/20131217_unearned_backer_gear.js index 2c1baf9dc7..dd010912e5 100644 --- a/migrations/20131217_unearned_backer_gear.js +++ b/migrations/archive/2013/20131217_unearned_backer_gear.js @@ -1,20 +1,20 @@ -var query = { - '$or': [ +let query = { + $or: [ {'items.gear.owned.weapon_special_0': true}, {'items.gear.owned.armor_special_0': true}, {'items.gear.owned.head_special_0': true}, - {'items.gear.owned.shield_special_0': true} - ] + {'items.gear.owned.shield_special_0': true}, + ], }; -db.users.find(query, {'items.gear.owned':1,backer:1}).forEach(function(user){ - var owned = user.items.gear.owned; - var tier = (user.backer && user.backer.tier) || 0; +db.users.find(query, {'items.gear.owned': 1, backer: 1}).forEach(function (user) { + let owned = user.items.gear.owned; + let tier = user.backer && user.backer.tier || 0; if (tier < 70) delete owned.weapon_special_0; if (tier < 45) delete owned.armor_special_0; if (tier < 45) delete owned.head_special_0; if (tier < 45) delete owned.shield_special_0; - db.users.update({_id:user._id}, {$set:{'items.gear.owned':owned}}); + db.users.update({_id: user._id}, {$set: {'items.gear.owned': owned}}); }); diff --git a/migrations/archive/2013/20131221_restore_NaN_history.js b/migrations/archive/2013/20131221_restore_NaN_history.js new file mode 100644 index 0000000000..babb7c3a9e --- /dev/null +++ b/migrations/archive/2013/20131221_restore_NaN_history.js @@ -0,0 +1,55 @@ +// node .migrations/20131221_restore_NaN_history.js + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +/** + * After the classes migration, users lost some history entries + */ +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); +let liveUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); + +function filterNaNs (h) { + return h && _.isNumber(Number(h.value)) && !_.isNaN(Number(h.value)); +} + +let fields = {history: 1, habits: 1, dailys: 1, migration: 1}; +let count = 0; +liveUsers.findEach({migration: {$ne: '20131221_restore_NaN_history'}}, fields, {batchSize: 500}, function (err, after) { + if (!after) err = '!after'; + if (err) { + count++; return console.error(err); + } + + backupUsers.findOne({_id: after._id}, fields, function (err, before) { + if (err) { + count++; return console.error(err); + } + + _.each(['todos', 'exp'], function (type) { + if (!_.isEmpty(after.history[type])) + after.history[type] = _.filter(after.history[type], filterNaNs); + if (before && !_.isEmpty(before.history[type])) + after.history[type] = before.history[type].concat(after.history[type]); + }); + + _.each(['habits', 'dailys'], function (type) { + _.each(after[type], function (t) { + t.history = _.filter(t.history, filterNaNs); + let found = before && _.find(before[type], {id: t.id}); + if (found && found.history) t.history = found.history.concat(t.history); + }); + }); + + liveUsers.update({_id: after._id}, {$set: {history: after.history, dailys: after.dailys, habits: after.habits, migration: '20131221_restore_NaN_history'}, $inc: {_v: 1}}); + // if (--count <= 0) console.log("DONE! " + after._id); + if (++count % 1000 === 0) console.log(count); + if (after._id === '9') console.log('lefnire processed'); + }); +}); \ No newline at end of file diff --git a/migrations/archive/2013/20131225_restore_streaks.js b/migrations/archive/2013/20131225_restore_streaks.js new file mode 100644 index 0000000000..e161ee1c91 --- /dev/null +++ b/migrations/archive/2013/20131225_restore_streaks.js @@ -0,0 +1,42 @@ +// node .migrations/20131225_restore_streaks.js + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +/** + * After the classes migration, users lost some history entries + */ +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let backupUsers = mongo.db('localhost:27017/habitrpg_old?auto_reconnect').collection('users'); +let liveUsers = mongo.db('lefnire:mAdn3s5s@charlotte.mongohq.com:10015/habitrpg_large?auto_reconnect').collection('users'); + +let fields = {dailys: 1, migration: 1}; +let count = 0; +liveUsers.findEach({migration: {$ne: '20131225_restore_streaks'}}, fields, {batchSize: 250}, function (err, after) { + if (!after) err = '!after'; + if (err) { + count++; return console.error(err); + } + + backupUsers.findOne({_id: after._id}, fields, function (err, before) { + if (!before) err = '!before'; + if (err) { + count++; return console.error(err); + } + + _.each(before.dailys, function (d) { + let found = _.find(after.dailys, {id: d.id}); + if (found && !found.streak) found.streak = d.streak; + }); + + liveUsers.update({_id: after._id}, {$set: {dailys: after.dailys, migration: '20131225_restore_streaks'}, $inc: {_v: 1}}); + // if (--count <= 0) console.log("DONE! " + after._id); + if (++count % 1000 === 0) console.log(count); + if (after._id === '9') console.log('lefnire processed'); + }); +}); \ No newline at end of file diff --git a/migrations/archive/2014/20140119_task_creation_completion_dates.js b/migrations/archive/2014/20140119_task_creation_completion_dates.js new file mode 100644 index 0000000000..9414117cd8 --- /dev/null +++ b/migrations/archive/2014/20140119_task_creation_completion_dates.js @@ -0,0 +1,8 @@ +db.users.find({}, {todos: 1, dailys: 1, rewards: 1, habits: 1}).forEach(function (user) { + _.each(user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards), function (t) { + t.dateCreated = t.created || new Date(); + delete t.created; + if (t.type === 'todo' && t.completed) t.dateCompleted = new Date(); + }); + db.users.update({_id: user._id}, {$set: {habits: user.habits, dailys: user.dailys, todos: user.todos, rewards: user.rewards}}); +}); diff --git a/migrations/archive/2014/20140130_birthdayEnd.js b/migrations/archive/2014/20140130_birthdayEnd.js new file mode 100644 index 0000000000..4c235d52eb --- /dev/null +++ b/migrations/archive/2014/20140130_birthdayEnd.js @@ -0,0 +1 @@ +db.users.update({}, {$set: {'achievements.habitBirthday': true}}, {multi: 1}); diff --git a/migrations/archive/2014/20140130_birthdayStart.js b/migrations/archive/2014/20140130_birthdayStart.js new file mode 100644 index 0000000000..93283c720b --- /dev/null +++ b/migrations/archive/2014/20140130_birthdayStart.js @@ -0,0 +1,12 @@ +db.users.update({}, {$set: { + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, +}}, {multi: 1}); diff --git a/migrations/archive/2014/20140220_challenge_memberCount.js b/migrations/archive/2014/20140220_challenge_memberCount.js new file mode 100644 index 0000000000..4444165e86 --- /dev/null +++ b/migrations/archive/2014/20140220_challenge_memberCount.js @@ -0,0 +1,3 @@ +db.challenges.find({}, {members: 1}).forEach(function (chal) { + db.challenges.update({_id: chal._id}, {$set: {memberCount: chal.members.length}}); +}); diff --git a/migrations/archive/2014/20140301_missing_mysteries.js b/migrations/archive/2014/20140301_missing_mysteries.js new file mode 100644 index 0000000000..f5fb4019ed --- /dev/null +++ b/migrations/archive/2014/20140301_missing_mysteries.js @@ -0,0 +1,14 @@ +db.users.update( + { + 'purchased.plan.dateCreated': {$gte: new Date('2014-02-22'), $lt: new Date('2014-02-29')}, + 'items.gear.owned.armor_mystery_201402': null, + 'items.gear.owned.head_mystery_201402': null, + 'items.gear.owned.back_mystery_201402': null, + 'purchased.plan.mysteryItems': {$nin: ['armor_mystery_201402', 'head_mystery_201402', 'back_mystery_201402']}, + }, + // {_id:1,'purchased.plan':1,'items.gear.owned':1} + {$push: {'purchased.plan.mysteryItems': {$each: ['armor_mystery_201402', 'head_mystery_201402', 'back_mystery_201402']}}}, + {multi: true} +);/* .forEach(function(user){ + printjson(user); + });*/ diff --git a/migrations/archive/2014/20140610_missing_backer_mount.js b/migrations/archive/2014/20140610_missing_backer_mount.js new file mode 100644 index 0000000000..6b678d5869 --- /dev/null +++ b/migrations/archive/2014/20140610_missing_backer_mount.js @@ -0,0 +1 @@ +db.users.update({'backer.tier': {$gt: 69}}, {$set: {'items.mounts.LionCub-Ethereal': true}}, {multi: 1}); \ No newline at end of file diff --git a/migrations/archive/2014/20140712_wiped_quest_membership.js b/migrations/archive/2014/20140712_wiped_quest_membership.js new file mode 100644 index 0000000000..8ccd44bb40 --- /dev/null +++ b/migrations/archive/2014/20140712_wiped_quest_membership.js @@ -0,0 +1,11 @@ +// mongo habitrpg node_modules/lodash/lodash.js ./migrations/20140712_wiped_quest_membership.js +db.groups.find({type: 'party', 'quest.key': {$ne: null}, 'quest.active': true}, {quest: 1}).forEach(function (group) { + let activeMembers = _.reduce(group.quest.members, function (m, v, k) { + if (v === true) m.push(k); return m; + }, []); + db.users.update( + {_id: {$in: activeMembers}}, + {$set: {'party.quest.key': group.quest.key, 'party.quest.completed': null}}, + {multi: true} + ); +}); diff --git a/migrations/archive/2014/20140803_remove_undefined_notifications.js b/migrations/archive/2014/20140803_remove_undefined_notifications.js new file mode 100644 index 0000000000..1033244adc --- /dev/null +++ b/migrations/archive/2014/20140803_remove_undefined_notifications.js @@ -0,0 +1,13 @@ +let _ = require('lodash'); + +db.users.find({}).forEach(function (user) { + let newNewMessages = {}; + + _.each(user.newMessages, function (val, key) { + if (key != 'undefined') { + newNewMessages[key] = val; + } + }); + + db.users.update({_id: user._id}, {$set: {newMessages: newNewMessages}}); +}); diff --git a/migrations/20140823_remove_undefined_and_false_notifications.js b/migrations/archive/2014/20140823_remove_undefined_and_false_notifications.js similarity index 53% rename from migrations/20140823_remove_undefined_and_false_notifications.js rename to migrations/archive/2014/20140823_remove_undefined_and_false_notifications.js index a6eed2b838..5f949e4399 100644 --- a/migrations/20140823_remove_undefined_and_false_notifications.js +++ b/migrations/archive/2014/20140823_remove_undefined_and_false_notifications.js @@ -1,9 +1,9 @@ // node .migrations/20140823_remove_undefined_and_false_notifications.js -var migrationName = '20140823_remove_undefined_and_false_notifications'; +let migrationName = '20140823_remove_undefined_and_false_notifications'; -var authorName = 'Alys'; // in case script author needs to know when their ... -var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done // IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. // We've now upgraded to lodash v4 but the code used in this migration has not been @@ -15,8 +15,8 @@ var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done * https://github.com/HabitRPG/habitrpg/pull/3907 */ -var mongo = require('mongoskin'); -var _ = require('lodash'); +let mongo = require('mongoskin'); +let _ = require('lodash'); // XXX @lefnire, choose wisely: // var liveUsers = mongo.db('lefnire:mAdn3s5s@charlotte.mongohq.com:10015/habitrpg_large?auto_reconnect').collection('users'); @@ -26,26 +26,28 @@ var _ = require('lodash'); // var liveUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); -var fields = {migration:1,newMessages:1}; -var progressCount = 1000; +let fields = {migration: 1, newMessages: 1}; +let progressCount = 1000; // var progressCount = 1; -var count = 0; -liveUsers.findEach({migration: {$ne:migrationName}}, fields, {batchSize:250}, function(err, user){ +let count = 0; +liveUsers.findEach({migration: {$ne: migrationName}}, fields, {batchSize: 250}, function (err, user) { count++; if (!user) err = '!user'; - if (err) {return console.error(err);} + if (err) { + return console.error(err); + } - var newNewMessages = {}; - _.each(user.newMessages,function(val,key){ + let newNewMessages = {}; + _.each(user.newMessages, function (val, key) { // console.log(key + " " + val.name); - if(key != "undefined" && val['value']){ + if (key != 'undefined' && val.value) { newNewMessages[key] = val; } - }) + }); - liveUsers.update({_id:user._id}, {$set:{newMessages:newNewMessages, migration:migrationName}, $inc:{_v:1}}); + liveUsers.update({_id: user._id}, {$set: {newMessages: newNewMessages, migration: migrationName}, $inc: {_v: 1}}); - if (count%progressCount == 0) console.log(count + ' ' + user._id); - if (user._id == '9') console.log('lefnire processed'); - if (user._id == authorUuid) console.log(authorName + ' processed'); + if (count % progressCount === 0) console.log(`${count } ${ user._id}`); + if (user._id === '9') console.log('lefnire processed'); + if (user._id === authorUuid) console.log(`${authorName } processed`); }); diff --git a/migrations/archive/2014/20140829_change_headAccessory_to_eyewear.js b/migrations/archive/2014/20140829_change_headAccessory_to_eyewear.js new file mode 100644 index 0000000000..4d73a951ce --- /dev/null +++ b/migrations/archive/2014/20140829_change_headAccessory_to_eyewear.js @@ -0,0 +1,83 @@ +// node .migrations/20140829_change_headAccessory_to_eyewear.js + +let migrationName = '20140829_change_headAccessory_to_eyewear'; +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +/** + * https://github.com/HabitRPG/habitrpg/issues/3645 + */ +let mongo = require('mongoskin'); +let _ = require('lodash'); +let liveUsers = mongo.db('localhost:27017/habitrpg2?auto_reconnect').collection('users'); + +let fields = {migration: 1, + 'items.gear.costume.headAccessory': 1, + 'items.gear.equipped.headAccessory': 1, + 'items.gear.owned.headAccessory_special_wondercon_black': 1, + 'items.gear.owned.headAccessory_special_wondercon_red': 1, + 'items.gear.owned.headAccessory_special_summerRogue': 1, + 'items.gear.owned.headAccessory_special_summerWarrior': 1, +}; + +let progressCount = 1000; +let count = 0; +liveUsers.findEach({ $and: [ + { migration: {$ne: migrationName} }, + { $or: [ + {'items.gear.owned.headAccessory_special_summerRogue': {$exists: true}}, + {'items.gear.owned.headAccessory_special_summerWarrior': {$exists: true}}, + {'items.gear.owned.headAccessory_special_wondercon_red': {$exists: true}}, + {'items.gear.owned.headAccessory_special_wondercon_black': {$exists: true}}, + ]}, +]}, fields, {batchSize: 250}, function (err, user) { + count++; + if (!user) err = '!user'; + if (err) { + return console.error(err); + } + + let set = {migration: migrationName}; + let unset = {}; + + let oldToNew = { + headAccessory_special_summerRogue: 'eyewear_special_summerRogue', + headAccessory_special_summerWarrior: 'eyewear_special_summerWarrior', + headAccessory_special_wondercon_red: 'eyewear_special_wondercon_red', + headAccessory_special_wondercon_black: 'eyewear_special_wondercon_black', + }; + + // items.gear.costume, items.gear.equipped: + _.each(['costume', 'equipped'], function (type) { + _.each(oldToNew, function (newName, oldName) { + if (user.items.gear[type].headAccessory === oldName) { + unset[`items.gear.${type}.headAccessory`] = ''; + set[`items.gear.${type}.eyewear`] = newName; + } + }); + }); + + // items.gear.owned: + _.each(oldToNew, function (newName, oldName) { + if (oldName in user.items.gear.owned) { + unset[`items.gear.owned.${oldName}`] = ''; + set[`items.gear.owned.${newName}`] = user.items.gear.owned[oldName]; + } + }); + + // console.log(JSON.stringify(user, null, " ")); + // console.log("set: " + JSON.stringify(set, null, " ")); + // console.log("unset: " + JSON.stringify(unset, null, " ")); + + liveUsers.update({_id: user._id}, {$set: set, $unset: unset, $inc: {_v: 1}}); + + if (count % progressCount === 0) console.log(`${count } ${ user._id}`); + if (user._id === '9') console.log('lefnire processed'); + if (user._id === authorUuid) console.log(`${authorName } processed`); +}); diff --git a/migrations/archive/2014/20140831_increase_gems_for_previous_contributions.js b/migrations/archive/2014/20140831_increase_gems_for_previous_contributions.js new file mode 100644 index 0000000000..a90a85ae36 --- /dev/null +++ b/migrations/archive/2014/20140831_increase_gems_for_previous_contributions.js @@ -0,0 +1,144 @@ +// IMPORTANT: +// +// run like this to capture all output: +// +// node 20140831_increase_gems_for_previous_contributions.js > 20140831_increase_gems_for_previous_contributions_output.txt + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let migrationName = '20140831_increase_gems_for_previous_contributions'; + +/** + * https://github.com/HabitRPG/habitrpg/issues/3933 + * Increase Number of Gems for Contributors + * author: Alys (d904bd62-da08-416b-a816-ba797c9ee265) + * + * Increase everyone's gems per their contribution level. + * Originally they were given 2 gems per tier. + * Now they are given 3 gems per tier for tiers 1,2,3 + * and 4 gems per tier for tiers 4,5,6,7 + * So that means an EXTRA 1 for tier 1, + * 2 for tier 2, + * 3 for tier 3, + * 5 for tier 4, + * 7 for tier 5, + * 9 for tier 6, + * 11 for tier 7, + * 11 for tier 8 (moderators = tier 7 + admin privileges), + * none for tier 9 (staff) + */ + +let mongo = require('mongoskin'); +let _ = require('lodash'); + + +let dbUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); + + +let query = { + 'contributor.level': {$gt: 0, $lt: 9}, + migration: {$ne: migrationName}, +}; + +let fields = { + migration: 1, + 'contributor.level': 1, + balance: 1, +}; + +let userResults = {}; // each key is a UUID, each value is a string +// describing what changed for that user + +console.warn('Updating users...'); +let progressCount = 50; +let count = 0; +dbUsers.findEach(query, fields, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All users found. Fetching final balances...'); + return fetchFinalBalances(); + } + count++; + + let set = {migration: migrationName}; + + let tier = user.contributor.level; + let extraGems = tier; // tiers 1,2,3 + if (tier > 3) { + extraGems = 3 + (tier - 3) * 2; + } + if (tier === 8) { + extraGems = 11; + } + let extraBalance = extraGems / 4; + set.balance = user.balance + extraBalance; + + // Capture current state of user: + userResults[user._id] = + `${user._id } ` + ':\n' + + ` contrib tier : ${ tier }\n` + + ` balance before : ${ user.balance }\n` + + ` balance (gems) added : ${ extraBalance } (${ + extraGems })` + '\n' + + ` expected balance after: ${ user.balance + extraBalance }\n`; + + // Update user: + dbUsers.update({_id: user._id}, {$set: set, $inc: {_v: 1}}); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); +}); + + +function fetchFinalBalances () { + let query = {_id: {$in: Object.keys(userResults)}}; + let fields = { + balance: 1, + }; + + let count1 = 0; + dbUsers.findEach(query, fields, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All final balances found.'); + return displayData(); + } + count1++; + userResults[user._id] = `${userResults[user._id] + + user._id } ` + ':\n' + + ` actual balance after : ${ user.balance }\n`; + if (count1 % progressCount === 0) console.warn(`${count1 } ${ user._id}`); + }); +} + + +function displayData () { + _.each(userResults, function (text, uuid) { + console.log(text); // text contains uuid + }); + console.log(`\n${ count + } users processed (should be roughly 335 according to the Hall)\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2014/20140914_upgrade_admin_contrib_tiers.js b/migrations/archive/2014/20140914_upgrade_admin_contrib_tiers.js new file mode 100644 index 0000000000..d2187d48ef --- /dev/null +++ b/migrations/archive/2014/20140914_upgrade_admin_contrib_tiers.js @@ -0,0 +1,86 @@ +let migrationName = '20140914_upgrade_admin_contrib_tiers'; +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +/** + * https://github.com/HabitRPG/habitrpg/issues/3801 + * Convert Tier 8 contributors to Tier 9 (staff) (all current Tier 8s are admins). + * Convert Tier 7 contributors with admin flag to Tier 8 (moderators). + */ + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db('localhost:27017/habitrpg?auto_reconnect').collection('users'); + +let query = + { 'contributor.level': {$gte: 7}, 'contributor.admin': true, migration: {$ne: migrationName} }; + +let fields = {migration: 1, + 'contributor.admin': 1, + 'contributor.level': 1, + 'auth.local.username': 1, + 'profile.name': 1, +}; + +let userResults = {}; // each key is a UUID, each value is a username; +// contains only the users changed + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + let set = {migration: migrationName}; + let inc = {'contributor.level': 1, _v: 1}; + + userResults[user._id] = user.profile.name; + + dbUsers.update({_id: user._id}, {$set: set, $inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); + if (user._id === '9') console.warn('lefnire' + ' processed'); +}); + + +function displayData () { + console.log('users modified:'); + _.each(userResults, function (name, uuid) { + console.log(name); + }); + console.warn(`\n${ count + } users processed (should be 11 according to the Hall)\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2014/20140922_free_candy.js b/migrations/archive/2014/20140922_free_candy.js new file mode 100644 index 0000000000..c503fed034 --- /dev/null +++ b/migrations/archive/2014/20140922_free_candy.js @@ -0,0 +1,18 @@ +db.users.update( + {}, + { + $inc: { + 'items.food.Candy_Base': 1, + 'items.food.Candy_CottonCandyBlue': 1, + 'items.food.Candy_CottonCandyPink': 1, + 'items.food.Candy_Desert': 1, + 'items.food.Candy_Golden': 1, + 'items.food.Candy_Red': 1, + 'items.food.Candy_Shade': 1, + 'items.food.Candy_Skeleton': 1, + 'items.food.Candy_White': 1, + 'items.food.Candy_Zombie': 1, + }, + }, + {multi: 1} +); \ No newline at end of file diff --git a/migrations/archive/2014/20141006_jackolantern_pet.js b/migrations/archive/2014/20141006_jackolantern_pet.js new file mode 100644 index 0000000000..f55debe7ee --- /dev/null +++ b/migrations/archive/2014/20141006_jackolantern_pet.js @@ -0,0 +1 @@ +db.users.update({_id: '9'}, {$set: {'items.pets.JackOLantern-Base': 5, 'flags.newStuff': true}}, {multi: true}); \ No newline at end of file diff --git a/migrations/20141117_consecutive_months.js b/migrations/archive/2014/20141117_consecutive_months.js similarity index 54% rename from migrations/20141117_consecutive_months.js rename to migrations/archive/2014/20141117_consecutive_months.js index 7b2f418d94..6a416a7079 100644 --- a/migrations/20141117_consecutive_months.js +++ b/migrations/archive/2014/20141117_consecutive_months.js @@ -6,15 +6,15 @@ // require moment, lodash db.users.find( - {'purchased.plan.customerId':{$ne:null}}, - {_id:1, 'purchased.plan':1} -).forEach(function(user){ - var p = user.purchased.plan - , latestMonth = p.dateTerminated || new Date() // their last sub date, or on-going (now) - , count = moment(latestMonth).diff(p.dateCreated, 'months'); + {'purchased.plan.customerId': {$ne: null}}, + {_id: 1, 'purchased.plan': 1} +).forEach(function (user) { + let p = user.purchased.plan, + latestMonth = p.dateTerminated || new Date(), // their last sub date, or on-going (now) + count = moment(latestMonth).diff(p.dateCreated, 'months'); db.users.update({_id: user._id}, {$set: { 'purchased.plan.consecutive.count': count, - 'purchased.plan.consecutive.gemCapExtra': _.min([ Math.floor(count/3)*5, 25 ]), - 'purchased.plan.consecutive.trinkets': Math.floor(count/3) + 'purchased.plan.consecutive.gemCapExtra': _.min([Math.floor(count / 3) * 5, 25]), + 'purchased.plan.consecutive.trinkets': Math.floor(count / 3), }}); }); diff --git a/migrations/archive/2014/20141126_turkey_mounts.js b/migrations/archive/2014/20141126_turkey_mounts.js new file mode 100644 index 0000000000..a72e9e57a9 --- /dev/null +++ b/migrations/archive/2014/20141126_turkey_mounts.js @@ -0,0 +1,11 @@ +db.users.update( + {'items.pets.Turkey-Base': {$ne: null}}, + {$set: {'items.mounts.Turkey-Base': true}}, + {multi: 1} +); + +db.users.update( + {'items.pets.Turkey-Base': null}, + {$set: {'items.pets.Turkey-Base': 5}}, + {multi: 1} +); \ No newline at end of file diff --git a/migrations/archive/2014/20141211_NaN_consecutives.js b/migrations/archive/2014/20141211_NaN_consecutives.js new file mode 100644 index 0000000000..a718304d75 --- /dev/null +++ b/migrations/archive/2014/20141211_NaN_consecutives.js @@ -0,0 +1,4 @@ +db.users.update({'purchased.plan.consecutive.count': NaN}, {$set: {'purchased.plan.consecutive.count': 0}}, {multi: 1}); +db.users.update({'purchased.plan.consecutive.offset': NaN}, {$set: {'purchased.plan.consecutive.offset': 0}}, {multi: 1}); +db.users.update({'purchased.plan.consecutive.gemCapExtra': NaN}, {$set: {'purchased.plan.consecutive.gemCapExtra': 0}}, {multi: 1}); +db.users.update({'purchased.plan.consecutive.trinkets': NaN}, {$set: {'purchased.plan.consecutive.trinkets': 0}}, {multi: 1}); \ No newline at end of file diff --git a/migrations/archive/2014/20141230_new_years_hats.js b/migrations/archive/2014/20141230_new_years_hats.js new file mode 100644 index 0000000000..d2244135d7 --- /dev/null +++ b/migrations/archive/2014/20141230_new_years_hats.js @@ -0,0 +1,11 @@ +db.users.update( + {'items.gear.owned.head_special_nye': {$ne: null}}, + {$set: {'items.gear.owned.head_special_nye2014': false}}, + {multi: 1} +); + +db.users.update( + {'items.gear.owned.head_special_nye': null}, + {$set: {'items.gear.owned.head_special_nye': false}}, + {multi: 1} +); diff --git a/migrations/archive/2015/20150107_plan_dateUpdated_null.js b/migrations/archive/2015/20150107_plan_dateUpdated_null.js new file mode 100644 index 0000000000..865da3ed60 --- /dev/null +++ b/migrations/archive/2015/20150107_plan_dateUpdated_null.js @@ -0,0 +1,8 @@ +db.users.update( + {'purchased.plan.customerId': {$ne: null}, 'purchased.plan.dateUpdated': null}, + { + $set: {'purchased.plan.dateUpdated': new Date('12/01/2014')}, + $unset: {'purchased.plan.datedUpdated': ''}, + }, + {multi: true} +); diff --git a/migrations/archive/2015/20150124_mountmaster_fix.js b/migrations/archive/2015/20150124_mountmaster_fix.js new file mode 100644 index 0000000000..5a0bbce030 --- /dev/null +++ b/migrations/archive/2015/20150124_mountmaster_fix.js @@ -0,0 +1,95 @@ +let migrationName = '20150124_mountmaster_fix.js'; +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +/** + * https://github.com/HabitRPG/habitrpg/pull/4374#issuecomment-71038795 + * Convert false to null for mounts that used to be owned. + */ + +let dbserver = 'localhost:27017'; // CHANGE THIS FOR PRODUCTION DATABASE + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/habitrpg?auto_reconnect`).collection('users'); + +let query = { + 'items.mounts': {$exists: true}, +}; + +let fields = { + 'items.mounts': 1, +}; + +let animals = ['Wolf-Base', 'Wolf-White', 'Wolf-Desert', 'Wolf-Red', 'Wolf-Shade', 'Wolf-Skeleton', 'Wolf-Zombie', 'Wolf-CottonCandyPink', 'Wolf-CottonCandyBlue', 'Wolf-Golden', 'TigerCub-Base', 'TigerCub-White', 'TigerCub-Desert', 'TigerCub-Red', 'TigerCub-Shade', 'TigerCub-Skeleton', 'TigerCub-Zombie', 'TigerCub-CottonCandyPink', 'TigerCub-CottonCandyBlue', 'TigerCub-Golden', 'PandaCub-Base', 'PandaCub-White', 'PandaCub-Desert', 'PandaCub-Red', 'PandaCub-Shade', 'PandaCub-Skeleton', 'PandaCub-Zombie', 'PandaCub-CottonCandyPink', 'PandaCub-CottonCandyBlue', 'PandaCub-Golden', 'LionCub-Base', 'LionCub-White', 'LionCub-Desert', 'LionCub-Red', 'LionCub-Shade', 'LionCub-Skeleton', 'LionCub-Zombie', 'LionCub-CottonCandyPink', 'LionCub-CottonCandyBlue', 'LionCub-Golden', 'Fox-Base', 'Fox-White', 'Fox-Desert', 'Fox-Red', 'Fox-Shade', 'Fox-Skeleton', 'Fox-Zombie', 'Fox-CottonCandyPink', 'Fox-CottonCandyBlue', 'Fox-Golden', 'FlyingPig-Base', 'FlyingPig-White', 'FlyingPig-Desert', 'FlyingPig-Red', 'FlyingPig-Shade', 'FlyingPig-Skeleton', 'FlyingPig-Zombie', 'FlyingPig-CottonCandyPink', 'FlyingPig-CottonCandyBlue', 'FlyingPig-Golden', 'Dragon-Base', 'Dragon-White', 'Dragon-Desert', 'Dragon-Red', 'Dragon-Shade', 'Dragon-Skeleton', 'Dragon-Zombie', 'Dragon-CottonCandyPink', 'Dragon-CottonCandyBlue', 'Dragon-Golden', 'Cactus-Base', 'Cactus-White', 'Cactus-Desert', 'Cactus-Red', 'Cactus-Shade', 'Cactus-Skeleton', 'Cactus-Zombie', 'Cactus-CottonCandyPink', 'Cactus-CottonCandyBlue', 'Cactus-Golden', 'BearCub-Base', 'BearCub-White', 'BearCub-Desert', 'BearCub-Red', 'BearCub-Shade', 'BearCub-Skeleton', 'BearCub-Zombie', 'BearCub-CottonCandyPink', 'BearCub-CottonCandyBlue', 'BearCub-Golden']; // all Gen1 mounts + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + let mounts = user.items.mounts; + let changed = false; + for (let a in animals) { + if (mounts[animals[a]] === false) { + mounts[animals[a]] = null; + changed = true; + } + } + + if (changed) { + dbUsers.update( + { _id: user._id}, + { + $set: { migration: migrationName, + 'items.mounts': mounts, + }, + } + ); + } + + // var set = {'migration': migrationName}; + // var inc = {'xyz':1, _v:1}; + // dbUsers.update({_id:user._id}, {$set:set, $inc:inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); + if (user._id === '9') console.warn('lefnire' + ' processed'); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2015/20150130_birthday_goodies.js b/migrations/archive/2015/20150130_birthday_goodies.js new file mode 100644 index 0000000000..e9a141c0af --- /dev/null +++ b/migrations/archive/2015/20150130_birthday_goodies.js @@ -0,0 +1,36 @@ +db.users.update( + {'items.gear.owned.armor_special_birthday': {$ne: null}}, + {$set: {'items.gear.owned.armor_special_birthday2015': false}}, + {multi: 1} +); + +db.users.update( + {'items.gear.owned.armor_special_birthday': null}, + {$set: {'items.gear.owned.armor_special_birthday': false}}, + {multi: 1} +); + +db.users.update({}, {$inc: { + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, +}}, {multi: 1}); + +db.users.update( + {'achievements.habitBirthday': true}, + {$set: {'achievements.habitBirthdays': 1}}, + {multi: 1} +); + +db.users.update( + {}, + {$inc: {'achievements.habitBirthdays': 1}}, + {multi: 1} +); \ No newline at end of file diff --git a/migrations/archive/2015/20150131_birthday_goodies_fix_remove_robe.js b/migrations/archive/2015/20150131_birthday_goodies_fix_remove_robe.js new file mode 100644 index 0000000000..2ed8b2dc34 --- /dev/null +++ b/migrations/archive/2015/20150131_birthday_goodies_fix_remove_robe.js @@ -0,0 +1,85 @@ +let migrationName = '20150131_birthday_goodies_fix__one_birthday__1'; +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +/* + * remove new birthday robes and second achievement from people who shouldn't have them + */ + +let dbserver = 'localhost:27017'; // CHANGE THIS FOR PRODUCTION DATABASE + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/habitrpg?auto_reconnect`).collection('users'); + +// 'auth.timestamps.created':{$gt:new Date('2014-02-01')}, +let query = { + 'achievements.habitBirthdays': 1, + 'auth.timestamps.loggedin': {$gt: new Date('2014-12-20')}, +}; + +// '_id': 'c03e41bd-501f-438c-9553-a7afdf52a08c', +// 'achievements.habitBirthday':{$exists:false}, +// 'items.gear.owned.armor_special_birthday2015':1 + +let fields = { + // 'auth.timestamps.created':1, + // 'achievements.habitBirthday':1, + // 'achievements.habitBirthdays':1, + 'items.gear.owned.armor_special_birthday2015': 1, + // 'items.gear.owned.armor_special':1 +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + let unset = {'items.gear.owned.armor_special_birthday2015': 1}; + // var set = {'migration':migrationName, 'achievements.habitBirthdays':1 }; + // var inc = {'xyz':1, _v:1}; + dbUsers.update({_id: user._id}, {$unset: unset}); // , $inc:inc}); + // dbUsers.update({_id:user._id}, {$unset:unset, $set:set}); + // console.warn(user.auth.timestamps.created); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); + if (user._id === '9') console.warn('lefnire' + ' processed'); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2015/20150201_convert_creation_date_from_string_to_object.js b/migrations/archive/2015/20150201_convert_creation_date_from_string_to_object.js new file mode 100644 index 0000000000..f5c9a87b06 --- /dev/null +++ b/migrations/archive/2015/20150201_convert_creation_date_from_string_to_object.js @@ -0,0 +1,119 @@ +let migrationName = '20150201_convert_creation_date_from_string_to_object__no_date_recent_signup'; +// // var migrationName = '20150201_convert_creation_date_from_string_to_object'; + +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +/* + * For users that have no value for auth.timestamps.created, assign them + * a recent value. + * + * NOTE: + * Before this script was used as described above, it was first used to + * find all users that have a auth.timestamps.created field that is a string + * rather than a date object and set it to be a date object. The code used + * for this has been commented out with four slashes: //// + * + * https://github.com/HabitRPG/habitrpg/issues/4601#issuecomment-72339846 + */ + +let dbserver = 'localhost:27017'; // CHANGE THIS FOR PRODUCTION DATABASE + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let mongo = require('mongoskin'); +let _ = require('lodash'); +let moment = require('moment'); + +let dbUsers = mongo.db(`${dbserver }/habitrpg?auto_reconnect`).collection('users'); + +let uuidArrayRecent = [ // recent users with no creation dates + '1a0d4b75-73ed-4937-974d-d504d6398884', + '1c7ebe27-1250-4f95-ba10-965580adbfd7', + '5f972121-4a6d-411c-95e9-7093d3e89b66', + 'ae85818a-e336-4ccd-945e-c15cef975102', + 'ba273976-d9fc-466c-975f-38559d34a824', +]; + +let query = { + _id: {$in: uuidArrayRecent}, + // // 'auth':{$exists:true}, + // // 'auth.timestamps':{$exists:true}, + // // 'auth.timestamps.created':{$not: {$lt:new Date('2018-01-01')}} +}; + +let fields = { + _id: 1, + 'auth.timestamps.created': 1, +}; +// 'achievements.habitBirthdays':1 + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // // var oldDate = user.auth.timestamps.created; + // // var newDate = moment(oldDate).toDate(); + let oldDate = 'none'; + let newDate = moment('2015-01-11').toDate(); + console.warn(`${user._id } === ${ oldDate } === ${ newDate}`); + + // // var set = { 'migration': migrationName, + // // 'auth.timestamps.created': newDate, + // // 'achievements.habitBirthdays': 2, + // // 'items.gear.owned.head_special_nye':true, + // // 'items.gear.owned.head_special_nye2014':true, + // // 'items.gear.owned.armor_special_birthday':true, + // // 'items.gear.owned.armor_special_birthday2015':true, + // // }; + + let set = { migration: migrationName, + 'auth.timestamps.created': newDate, + 'achievements.habitBirthdays': 1, + 'items.gear.owned.armor_special_birthday': true, + }; + + // var unset = {'items.gear.owned.armor_special_birthday2015': 1}; + // var inc = {'xyz':1, _v:1}; + dbUsers.update({_id: user._id}, {$set: set}); + // dbUsers.update({_id:user._id}, {$unset:unset, $set:set, $inc:inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); + if (user._id === '9') console.warn('lefnire' + ' processed'); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2015/20150201_recapture_emails_phase_update.js b/migrations/archive/2015/20150201_recapture_emails_phase_update.js new file mode 100644 index 0000000000..26cf9a25d1 --- /dev/null +++ b/migrations/archive/2015/20150201_recapture_emails_phase_update.js @@ -0,0 +1,7 @@ +db.users.update({ + 'flags.recaptureEmailsPhase': { + $gt: 0, + }, +}, {$inc: { + 'flags.recaptureEmailsPhase': 1, +}}, {multi: 1}); \ No newline at end of file diff --git a/migrations/archive/2015/20150218_interactive_tour.js b/migrations/archive/2015/20150218_interactive_tour.js new file mode 100644 index 0000000000..6223f17d6a --- /dev/null +++ b/migrations/archive/2015/20150218_interactive_tour.js @@ -0,0 +1,10 @@ +db.users.update({}, {$set: { + 'flags.tour.intro': -2, + // 'flags.tour.classes':-2, + 'flags.tour.stats': -2, + 'flags.tour.tavern': -2, + 'flags.tour.party': -2, + 'flags.tour.guilds': -2, + 'flags.tour.challenges': -2, + 'flags.tour.market': -2, +}}, {multi: 1}); \ No newline at end of file diff --git a/migrations/archive/2015/20150224_force_resting_in_inn.js b/migrations/archive/2015/20150224_force_resting_in_inn.js new file mode 100644 index 0000000000..d148419628 --- /dev/null +++ b/migrations/archive/2015/20150224_force_resting_in_inn.js @@ -0,0 +1,71 @@ +let migrationName = '20150224_force_resting_in_inn'; +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +/* + * force all active players to rest in the inn due to massive server fail + */ + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let dbserver = 'localhost:27017'; // CHANGE THIS FOR PRODUCTION DATABASE + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/habitrpg?auto_reconnect`).collection('users'); + +let query = { + 'auth.timestamps.loggedin': {$gt: new Date('2015-02-22')}, +}; + +let fields = { + 'preferences.sleep': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + let set = {migration: migrationName, 'preferences.sleep': 1 }; + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); + if (user._id === '9') console.warn('lefnire' + ' processed'); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2015/20150310_survey_achievements.js b/migrations/archive/2015/20150310_survey_achievements.js new file mode 100644 index 0000000000..ea343416d5 --- /dev/null +++ b/migrations/archive/2015/20150310_survey_achievements.js @@ -0,0 +1,5 @@ +db.users.update( + {'achievements.helpedHabit': true}, + {$set: {'achievements.habitSurveys': 1}}, + {multi: 1} +); \ No newline at end of file diff --git a/migrations/20150325_egg_quest.js b/migrations/archive/2015/20150325_egg_quest.js similarity index 56% rename from migrations/20150325_egg_quest.js rename to migrations/archive/2015/20150325_egg_quest.js index 43ca0ad1b7..d28b7dccea 100644 --- a/migrations/20150325_egg_quest.js +++ b/migrations/archive/2015/20150325_egg_quest.js @@ -3,6 +3,6 @@ */ db.users.update( {}, - {$inc:{'items.quests.egg':1}}, - {multi:1} -) \ No newline at end of file + {$inc: {'items.quests.egg': 1}}, + {multi: 1} +); \ No newline at end of file diff --git a/migrations/archive/2015/20150604_ultimateGearSets.js b/migrations/archive/2015/20150604_ultimateGearSets.js new file mode 100644 index 0000000000..aa69647666 --- /dev/null +++ b/migrations/archive/2015/20150604_ultimateGearSets.js @@ -0,0 +1,141 @@ +// var migrationName = '20150604_ultimateGearSets'; +// var authorName = 'Sabe'; // in case script author needs to know when their ... +// var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done + +let migrationName = '20150620_ultimateGearSets'; +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +/* + * grant the new ultimateGearSets achievement for existing users' collected equipment + * + * + * Changed by Alys on 20150620 to assign false values to + * 'achievements.ultimateGearSets' when true values are not appropriate, + * because of https://github.com/HabitRPG/habitrpg/issues/5427 + * + * Minimal changes were made so the code isn't as efficient or clean + * as it could be, but it's (hopefully) one-use-only and minimal changes + * means minimal new testing. + */ + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let dbserver = 'localhost:27017'; // FOR TEST DATABASE +// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379' // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +let fields = { + 'achievements.ultimateGearSets': 1, + 'items.gear.owned': 1, +}; + + +// Changes 20150620: All users have to be processed now (non-achievers need +// false values). +let query = { +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + let achievements = {}; + let changeUser = false; + // Changes 20150620: 'changeUser' now indicates that the user must have the + // Enchanted Armoire unlocked. + if (typeof user.items.gear.owned.weapon_wizard_6 !== 'undefined' && + typeof user.items.gear.owned.armor_wizard_5 !== 'undefined' && + typeof user.items.gear.owned.head_wizard_5 !== 'undefined' + ) { + achievements.wizard = true; + changeUser = true; + } else { + // Changes 20150620: false added for all classes (here and below) + achievements.wizard = false; + } + + if (typeof user.items.gear.owned.weapon_warrior_6 !== 'undefined' && + typeof user.items.gear.owned.armor_warrior_5 !== 'undefined' && + typeof user.items.gear.owned.head_warrior_5 !== 'undefined' && + typeof user.items.gear.owned.shield_warrior_5 !== 'undefined' + ) { + achievements.warrior = true; + changeUser = true; + } else { + achievements.warrior = false; + } + + if (typeof user.items.gear.owned.weapon_healer_6 !== 'undefined' && + typeof user.items.gear.owned.armor_healer_5 !== 'undefined' && + typeof user.items.gear.owned.head_healer_5 !== 'undefined' && + typeof user.items.gear.owned.shield_healer_5 !== 'undefined' + ) { + achievements.healer = true; + changeUser = true; + } else { + achievements.healer = false; + } + + if (typeof user.items.gear.owned.weapon_rogue_6 !== 'undefined' && + typeof user.items.gear.owned.armor_rogue_5 !== 'undefined' && + typeof user.items.gear.owned.head_rogue_5 !== 'undefined' && + typeof user.items.gear.owned.shield_rogue_6 !== 'undefined' + ) { + achievements.rogue = true; + changeUser = true; + } else { + achievements.rogue = false; + } + + // Changes 20150620: $set is now run for all users. + let set = {migration: migrationName, 'achievements.ultimateGearSets': achievements}; + if (changeUser) { // user has at least one Ultimate Gear achievement + set['flags.armoireEnabled'] = true; + } + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); + if (user._id === '9') console.warn('lefnire' + ' processed'); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/20150706_orca_mounts.js b/migrations/archive/2015/20150706_orca_mounts.js similarity index 52% rename from migrations/20150706_orca_mounts.js rename to migrations/archive/2015/20150706_orca_mounts.js index e8b6fe662a..92dc55e77c 100644 --- a/migrations/20150706_orca_mounts.js +++ b/migrations/archive/2015/20150706_orca_mounts.js @@ -3,6 +3,6 @@ */ db.users.update( {}, - {$set:{'items.mounts.Orca-Base':true}}, - {multi:true} + {$set: {'items.mounts.Orca-Base': true}}, + {multi: true} ); diff --git a/migrations/archive/2015/20150731_purple_gryphon.js b/migrations/archive/2015/20150731_purple_gryphon.js new file mode 100644 index 0000000000..e75f8e9c97 --- /dev/null +++ b/migrations/archive/2015/20150731_purple_gryphon.js @@ -0,0 +1,5 @@ +db.users.update( + {}, + {$set: {'items.mounts.Gryphon-RoyalPurple': true}}, + {multi: true} +); diff --git a/migrations/archive/2015/20150731_veteran_tiger.js b/migrations/archive/2015/20150731_veteran_tiger.js new file mode 100644 index 0000000000..1494dd0ad8 --- /dev/null +++ b/migrations/archive/2015/20150731_veteran_tiger.js @@ -0,0 +1,5 @@ +db.users.update( + {'items.pets.Wolf-Veteran': {$ne: null}}, + {$set: {'items.pets.Tiger-Veteran': 5}}, + {multi: true} +); diff --git a/migrations/archive/2015/20150731_veteran_wolf.js b/migrations/archive/2015/20150731_veteran_wolf.js new file mode 100644 index 0000000000..f060100957 --- /dev/null +++ b/migrations/archive/2015/20150731_veteran_wolf.js @@ -0,0 +1,7 @@ +// Run after the Veteran Tiger script, not before! + +db.users.update( + {'items.pets.Wolf-Veteran': {$exists: false}}, + {$set: {'items.pets.Wolf-Veteran': 5}}, + {multi: true} +); diff --git a/migrations/archive/2015/20150906_groups_fix_leaders.js b/migrations/archive/2015/20150906_groups_fix_leaders.js new file mode 100644 index 0000000000..252328571d --- /dev/null +++ b/migrations/archive/2015/20150906_groups_fix_leaders.js @@ -0,0 +1,79 @@ +/* + * Make sure leaders are existing users + */ + +let mongo = require('mongoskin'); +let async = require('async'); + +let dbserver = 'url'; +let dbname = 'dbname'; +let countGroups = 0; +let countUsers = 0; + +let db = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`); +let dbUsers = db.collection('users'); +let dbGroups = db.collection('groups'); + +console.log('Begins work on db'); + +function findGroups (gt) { + let query = {}; + if (gt) query._id = {$gt: gt}; + + console.log(query); + + dbGroups.find(query, { + fields: {_id: 1, members: 1, leader: 1}, + limit: 10000, + sort: { + _id: 1, + }, + }).toArray(function (err, groups) { + if (err) throw err; + + let lastGroup = null; + if (groups.length === 10000) { + lastGroup = groups[groups.length - 1]; + } + + async.eachLimit(groups, 30, function (group, cb1) { + countGroups++; + console.log('Group: ', countGroups, group._id); + + let members = group.members; + + dbUsers.findOne({_id: group.leader}, {fields: {_id: 1}}, function (err, user) { + if (err) return cb1(err); + + // If leader has deleted account + if (!user && group._id !== 'habitrpg' && members && members[0]) { + dbGroups.update({ + _id: group._id, + }, { + $set: { + // Set first user as new leader + leader: members[0], + }, + }, { + multi: false, + }, function (err, res) { + if (err) return cb1(err); + + console.log('Updated: ', res); + return cb1(); + }); + } else { + return cb1(); + } + }); + }, function (err) { + if (err) throw err; + + if (lastGroup && lastGroup._id) { + findGroups(lastGroup._id); + } + }); + }); +} + +findGroups(); \ No newline at end of file diff --git a/migrations/archive/2015/20150906_groups_remove_deleted_users.js b/migrations/archive/2015/20150906_groups_remove_deleted_users.js new file mode 100644 index 0000000000..d04b91341b --- /dev/null +++ b/migrations/archive/2015/20150906_groups_remove_deleted_users.js @@ -0,0 +1,86 @@ +/* + * Remove deleted accounts from groups + */ + +let mongo = require('mongoskin'); +let async = require('async'); + +let dbserver = 'url'; +let dbname = 'dbname'; +let countGroups = 0; +let countUsers = 0; + +let db = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`); +let dbUsers = db.collection('users'); +let dbGroups = db.collection('groups'); + +console.log('Begins work on db'); + +function findGroups (gt) { + let query = {}; + if (gt) query._id = {$gt: gt}; + + console.log(query); + + dbGroups.find(query, { + fields: {_id: 1, members: 1}, + limit: 10000, + sort: { + _id: 1, + }, + }).toArray(function (err, groups) { + if (err) throw err; + + let lastGroup = null; + if (groups.length === 10000) { + lastGroup = groups[groups.length - 1]; + } + + async.eachLimit(groups, 3, function (group, cb1) { + countGroups++; + console.log('Group: ', countGroups, group._id); + + let members = group.members; + + // Remove users who deleted their account + async.eachLimit(members, 15, function (member, cb2) { + dbUsers.findOne({_id: member}, {fields: {_id: 1}}, function (err, user) { + if (err) return cb2(err); + + if (!user) { + countUsers++; + console.log('User removed n. ', countUsers, 'user id ', member, 'group id ', group._id); + + dbGroups.update({ + _id: group._id, + }, { + $pull: {members: member}, + $inc: {memberCount: -1}, + }, { + multi: false, + }, function (err, res) { + if (err) return cb2(err); + + console.log('Updated: ', res); + return cb2(); + }); + } else { + cb2(); + } + }); + }, function (err) { + if (err) return cb1(err); + + cb1(); + }); + }, function (err) { + if (err) throw err; + + if (lastGroup && lastGroup._id) { + findGroups(lastGroup._id); + } + }); + }); +} + +findGroups(); \ No newline at end of file diff --git a/migrations/archive/2015/20150906_groups_remove_empty.js b/migrations/archive/2015/20150906_groups_remove_empty.js new file mode 100644 index 0000000000..b82313e014 --- /dev/null +++ b/migrations/archive/2015/20150906_groups_remove_empty.js @@ -0,0 +1,21 @@ +/* + * Remove empty private groups + */ + +let mongo = require('mongoskin'); + +let dbserver = 'url'; +let dbname = 'name'; + +let db = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`); +let dbGroups = db.collection('groups'); + +console.log('Begins work on db'); + +dbGroups.findEach({ + memberCount: 0, +}, {_id: 1}, function (err, res) { + if (err) throw err; + + console.log(res); +}); \ No newline at end of file diff --git a/migrations/archive/2015/20150906_sync_groups_with_firebase.js b/migrations/archive/2015/20150906_sync_groups_with_firebase.js new file mode 100644 index 0000000000..9b17d02a09 --- /dev/null +++ b/migrations/archive/2015/20150906_sync_groups_with_firebase.js @@ -0,0 +1,43 @@ +/* + * Sync groups with Firebase + */ + +let mongo = require('mongoskin'); +let Firebase = require('Firebase'); + +let dbserver = 'mongodb://url'; +let dbname = 'db'; + +let db = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`); +let dbGroups = db.collection('groups'); +let countGroups = 0; + +let firebaseRef = new Firebase('https://' + 'firebase-app' + '.firebaseio.com'); + +// TODO handle sync errors with firebase? +firebaseRef.authWithCustomToken('firebase-secret', function (err, authData) { + if (err) throw new Error('Impossible to authenticate Firebase'); + + console.log('Firebase connected, begins work on db'); + + dbGroups.findEach({}, {_id: 1, members: 1}, {batchSize: 100}, function (err, group) { + if (err) throw err; + if (group._id !== 'habitrpg') return; + + countGroups++; + console.log('Group: ', countGroups); + + firebaseRef.child(`rooms/${ group._id}`) + .set({ + name: group.name, + }); + + group.members.forEach(function (member) { + firebaseRef.child(`members/${ group._id }/${ userId}`) + .set(true); + + firebaseRef.child(`users/${ member }/rooms/${ group._id}`) + .set(true); + }); + }); +}); \ No newline at end of file diff --git a/migrations/archive/2015/20151013_jackolanterns.js b/migrations/archive/2015/20151013_jackolanterns.js new file mode 100644 index 0000000000..358678f2fa --- /dev/null +++ b/migrations/archive/2015/20151013_jackolanterns.js @@ -0,0 +1,74 @@ +let migrationName = '20151013_jackolanterns.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Jack-O'-Lantern mounts to users who already have the pet version, award pet if they don't + */ + +let dbserver = 'localhost:27017'; // FOR TEST DATABASE +// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.pets.JackOLantern-Base': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // specify user data to change: + let set = {}; + if (user.items.pets['JackOLantern-Base']) { + set = {migration: migrationName, 'items.mounts.JackOLantern-Base': true}; + } else { + set = {migration: migrationName, 'items.pets.JackOLantern-Base': 5}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2015/20151021_usernames_emails_lowercase.js b/migrations/archive/2015/20151021_usernames_emails_lowercase.js new file mode 100644 index 0000000000..ec46c5642b --- /dev/null +++ b/migrations/archive/2015/20151021_usernames_emails_lowercase.js @@ -0,0 +1,63 @@ +/* + * Migrate email to lowerCase version and add auth.local.lowerCaseUsername email + */ + +let mongo = require('mongoskin'); +let async = require('async'); + +let dbserver = 'url'; +let dbname = 'dbname'; +let countUsers = 0; + +let db = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`); +let dbUsers = db.collection('users'); + +console.log('Begins work on db'); + +function findUsers (gt) { + let query = {}; + if (gt) query._id = {$gt: gt}; + + console.log(query); + + dbUsers.find(query, { + fields: {_id: 1, auth: 1}, + limit: 10000, + sort: { + _id: 1, + }, + }).toArray(function (err, users) { + if (err) throw err; + + let lastUser = null; + if (users.length === 10000) { + lastUser = users[users.length - 1]; + } + + async.eachLimit(users, 20, function (user, cb) { + countUsers++; + console.log('User: ', countUsers, user._id); + + let update = { + $set: {}, + }; + + if (user.auth && user.auth.local) { + if (user.auth.local.username) update.$set['auth.local.lowerCaseUsername'] = user.auth.local.username.toLowerCase(); + if (user.auth.local.email) update.$set['auth.local.email'] = user.auth.local.email.toLowerCase(); + } + + dbUsers.update({ + _id: user._id, + }, update, cb); + }, function (err) { + if (err) throw err; + + if (lastUser && lastUser._id) { + findUsers(lastUser._id); + } + }); + }); +} + +findUsers(); diff --git a/migrations/archive/2015/20151105_tutorial_flags.js b/migrations/archive/2015/20151105_tutorial_flags.js new file mode 100644 index 0000000000..7023af9fae --- /dev/null +++ b/migrations/archive/2015/20151105_tutorial_flags.js @@ -0,0 +1,70 @@ +let migrationName = '20151105_tutorial_flags_v1'; +let authorName = 'Alys'; // in case script author needs to know when their ... +let authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; // ... own data is done + +/* + * set flags.tutorial.ios and flags.tutorial.main flags to true in preparation + * for the release of a new iOS tutorial + * + */ + +// var dbserver = 'localhost:27017' // FOR TEST DATABASE +let dbserver = 'alys:@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +let fields = { +}; + + +let query = { + 'auth.timestamps.loggedin': {$gt: new Date('2015-10-20')}, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // var set = {'migration':migrationName, 'flags.tutorial.ios':true, 'flags.tutorial.main':true }; + let set = {migration: migrationName, 'flags.tutorial.ios': {} }; + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2015/20151116_costume_contest_award.js b/migrations/archive/2015/20151116_costume_contest_award.js new file mode 100644 index 0000000000..556697f6ba --- /dev/null +++ b/migrations/archive/2015/20151116_costume_contest_award.js @@ -0,0 +1,109 @@ +let migrationName = '20151116_costume_contest.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Costume Contest achievement to 2015 winners + */ + +let dbserver = 'localhost:27017'; // FOR TEST DATABASE +// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + _id: { + $in: [ + 'e411dab3-a4ca-414d-bdbd-b6940b3bdeb3', + '35ced5cc-c33a-45c8-93dc-16000ee66fde', + 'ab3f0549-7247-4fd5-975b-efcff98c79c3', + 'b1261fd2-eb25-46b4-97a9-ae7a0dc8a131', + '1f27893f-3808-4724-9725-f46dab93faca', + '216a0c23-6afd-4a5e-b434-d386a10862a2', + '2d6ef231-50b4-4a22-90e7-45eb97147a2c', + '98b8cf4f-89bd-4b0a-988d-02629a217232', + 'c5183dfa-c741-43ce-935e-c6d89b41a030', + '262a7afb-6b57-4d81-88e0-80d2e9f6cbdc', + '33991e0a-de55-4986-ac81-af78491a84de', + '7adf6ada-3c05-4054-b5df-fa7d49d3b9eb', + '235a1cbd-48c5-41b1-afb4-59d2f8645c57', + 'b7617a61-188b-4332-bf4d-32268fa77f2b', + '672c1ce0-9f47-44f0-a3f3-8cc3c6c5a9cb', + 'd0a3217a-7b92-48d6-b39a-b1b1be96702e', + '5ef910dc-1d22-47d9-aa38-a60132c60679', + '370a44c8-e94a-4a2c-91f2-33166926db1f', + '1b0b3ef3-28bd-4046-a49b-e1c83e281baf', + '75b93321-66b9-49bd-9076-052499c1d2bf', + 'd97516e4-81d0-4f60-bf03-95f7330925ab', + '3e13cc79-de38-420d-822e-9e9da309ce6b', + '0e471dc1-ecb0-4388-a891-b873a237d2cf', + 'ca3da398-4f73-4304-b838-af3669ed4cbb', + '44cdf105-8bda-4197-9d1a-1bcb83b4dc84', + '5419830c-b837-4573-ae82-4718ab95b7f1', + 'ac6fbe37-b0dc-40d8-ba14-77dde66fbfa8', + '8789ba18-a498-46b9-b367-3b929a0acb94', + '52fce1a9-9b0a-4e26-95dc-adc12f52e752', + '21bf71ac-399c-470b-abe0-cc49a03b6a8b', + 'f1618ce2-552e-4f23-bc76-e73d63ebedd0', + '4cc0c749-d943-4090-b529-42bc665b7244', + 'e259682e-cb5c-4d94-b472-ceedc66d7484', + 'fa197a4b-e065-4551-803a-c8a5b9970f9d', + ], + }, +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // specify user data to change: + let set = {migration: migrationName}; + let inc = {'achievements.costumeContests': 1}; + + dbUsers.update({_id: user._id}, {$set: set}); + dbUsers.update({_id: user._id}, {$inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2015/20151116_costume_contest_to_number.js b/migrations/archive/2015/20151116_costume_contest_to_number.js new file mode 100644 index 0000000000..68660941f3 --- /dev/null +++ b/migrations/archive/2015/20151116_costume_contest_to_number.js @@ -0,0 +1,71 @@ +let migrationName = '20151116_costume_contest_to_number.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Change Costume Contest achievement from Boolean to Number, so people can win repeatedly + */ + +let dbserver = 'localhost:27017'; // FOR TEST DATABASE +// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + 'achievements.costumeContest': true, +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'achievements.costumeContest': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // specify user data to change: + let set = {'achievements.costumeContests': 1}; + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2015/20151125_turkey_ladder.js b/migrations/archive/2015/20151125_turkey_ladder.js new file mode 100644 index 0000000000..6328030f25 --- /dev/null +++ b/migrations/archive/2015/20151125_turkey_ladder.js @@ -0,0 +1,78 @@ +let migrationName = '20151125_turkey_ladder.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Gilded Turkey pet to Turkey mount owners, Turkey Mount if they only have Turkey Pet, + * and Turkey Pet otherwise + */ + +let dbserver = 'localhost:27017'; // FOR TEST DATABASE +// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.pets.Turkey-Base': 1, + 'items.mounts.Turkey-Base': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // specify user data to change: + let set = {}; + if (user.items.mounts['Turkey-Base']) { + set = {migration: migrationName, 'items.pets.Turkey-Gilded': 5}; + } else if (user.items.pets['Turkey-Base']) { + set = {migration: migrationName, 'items.mounts.Turkey-Base': true}; + } else { + set = {migration: migrationName, 'items.pets.Turkey-Base': 5}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2015/20151229_new_years_hats.js b/migrations/archive/2015/20151229_new_years_hats.js new file mode 100644 index 0000000000..74788369a1 --- /dev/null +++ b/migrations/archive/2015/20151229_new_years_hats.js @@ -0,0 +1,77 @@ +let migrationName = '20151229_new_years_hats.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award 2015 party hat if user has 2014 hat, 2014 hat if they have the 2013 hat, + * and 2013 hat otherwise + */ + +let dbserver = 'localhost:27017'; // FOR TEST DATABASE +// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.gear.owned': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // specify user data to change: + let set = {}; + if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('head_special_nye2014')) { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2015': false}; + } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('head_special_nye')) { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2014': false}; + } else { + set = {migration: migrationName, 'items.gear.owned.head_special_nye': false}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/20160111_challenges_condense_same_day_history_entries.js b/migrations/archive/2016/20160111_challenges_condense_same_day_history_entries.js similarity index 56% rename from migrations/20160111_challenges_condense_same_day_history_entries.js rename to migrations/archive/2016/20160111_challenges_condense_same_day_history_entries.js index 69411e8530..76a7e14dfb 100644 --- a/migrations/20160111_challenges_condense_same_day_history_entries.js +++ b/migrations/archive/2016/20160111_challenges_condense_same_day_history_entries.js @@ -1,11 +1,11 @@ -var migrationName = '20160111_challenges_condense_same_day_history_entries.js'; +let migrationName = '20160111_challenges_condense_same_day_history_entries.js'; /* * Compress challenges tasks history entries so that only one entry per day is kept */ -var dbserver = ''; -var dbname = ''; +let dbserver = ''; +let dbname = ''; // IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. // We've now upgraded to lodash v4 but the code used in this migration has not been @@ -13,34 +13,34 @@ var dbname = ''; // be checked for compatibility against the v4 changelog and changed if necessary. // https://github.com/lodash/lodash/wiki/Changelog#v400 -var mongo = require('mongoskin'); -var _ = require('lodash'); -var moment = require('moment'); +let mongo = require('mongoskin'); +let _ = require('lodash'); +let moment = require('moment'); -var dbChallenges = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('challenges'); +let dbChallenges = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('challenges'); // Find all challenges -var query = { +let query = { }; // we only want habits and dailies (rewards and todos don't have history) -var fields = { - 'habits': 1, - 'dailys': 1, +let fields = { + habits: 1, + dailys: 1, }; function compressEntries (history) { return _.chain(history) - .filter(function(entry) { - return !!entry; + .filter(function (entry) { + return Boolean(entry); }) - .groupBy(function(entry) { // group by day + .groupBy(function (entry) { // group by day return moment(entry.date).format('YYYYMMDD'); }) - .sortBy(function(entry, key) { // sort by date and transform back to array of array of entries + .sortBy(function (entry, key) { // sort by date and transform back to array of array of entries return key; }) - .map(function(entries) { // aggregate the value + .map(function (entries) { // aggregate the value return { date: Number(entries[0].date), value: _.reduce(entries, function (previousValue, entry) { @@ -49,14 +49,16 @@ function compressEntries (history) { }; }) .value(); -}; +} console.warn('Updating challenges...'); -var progressCount = 100; -var count = 0; +let progressCount = 100; +let count = 0; -dbChallenges.findEach(query, fields, {batchSize: 250}, function(err, challenge) { - if (err) { return exiting(1, 'ERROR! ' + err); } +dbChallenges.findEach(query, fields, {batchSize: 250}, function (err, challenge) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } if (!challenge) { console.warn('All appropriate challenges found.'); return displayData(); @@ -64,49 +66,54 @@ dbChallenges.findEach(query, fields, {batchSize: 250}, function(err, challenge) count++; // specify challenge data to change: - var set = {}; + let set = {}; if (challenge.habits && challenge.habits.length > 0) { - challenge.habits.forEach(function(habit, index) { + challenge.habits.forEach(function (habit, index) { if (habit.history && habit.history.length > 1) { - var originalL = habit.history.length; + let originalL = habit.history.length; habit.history = compressEntries(habit.history); if (originalL > 1000) console.log(originalL, habit.history.length); - set['habits.' + index + '.history'] = habit.history; + set[`habits.${ index }.history`] = habit.history; } }); } if (challenge.dailys && challenge.dailys.length > 0) { - challenge.dailys.forEach(function(daily, index) { + challenge.dailys.forEach(function (daily, index) { if (daily.history && daily.history.length > 1) { - var originalL = daily.history.length; + let originalL = daily.history.length; daily.history = compressEntries(daily.history); if (originalL > 1000) console.log(originalL, daily.history.length); - set['dailys.' + index + '.history'] = daily.history; + set[`dailys.${ index }.history`] = daily.history; } }); } - dbChallenges.update({_id: challenge._id}, {$set: set}, function(err) { - if(err) throw err; + dbChallenges.update({_id: challenge._id}, {$set: set}, function (err) { + if (err) throw err; console.log('updated a challenge'); }); - if (count%progressCount == 0) console.warn(count + ' ' + challenge._id); + if (count % progressCount === 0) console.warn(`${count } ${ challenge._id}`); }); -function displayData() { - console.warn('\n' + count + ' challenges processed\n'); +function displayData () { + console.warn(`\n${ count } challenges processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/20160129_habit_birthday.js b/migrations/archive/2016/20160129_habit_birthday.js similarity index 50% rename from migrations/20160129_habit_birthday.js rename to migrations/archive/2016/20160129_habit_birthday.js index f4be13c50e..25e50ea0dd 100644 --- a/migrations/20160129_habit_birthday.js +++ b/migrations/archive/2016/20160129_habit_birthday.js @@ -1,15 +1,15 @@ -var migrationName = '20160129_habit_birthday.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +let migrationName = '20160129_habit_birthday.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Award 2016 party robes if user has 2015 robes, 2015 robes if they have the 2014 robes, * and 2014 robes otherwise */ -var dbserver = 'localhost:27017'; // FOR TEST DATABASE +let dbserver = 'localhost:27017'; // FOR TEST DATABASE // var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE -var dbname = 'habitrpg'; +let dbname = 'habitrpg'; // IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. // We've now upgraded to lodash v4 but the code used in this migration has not been @@ -17,25 +17,27 @@ var dbname = 'habitrpg'; // be checked for compatibility against the v4 changelog and changed if necessary. // https://github.com/lodash/lodash/wiki/Changelog#v400 -var mongo = require('mongoskin'); -var _ = require('lodash'); +let mongo = require('mongoskin'); +let _ = require('lodash'); -var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users'); +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); // specify a query to limit the affected users (empty for all users): -var query = { +let query = { }; // specify fields we are interested in to limit retrieved data (empty if we're not reading data): -var fields = { +let fields = { 'items.gear.owned': 1, }; console.warn('Updating users...'); -var progressCount = 1000; -var count = 0; -dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { - if (err) { return exiting(1, 'ERROR! ' + err); } +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } if (!user) { console.warn('All appropriate users found and modified.'); return displayData(); @@ -43,7 +45,7 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { count++; // specify user data to change: - var set = {'migration':migrationName}; + let set = {migration: migrationName}; if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2015')) { set['items.gear.owned.armor_special_birthday2016'] = false; } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday')) { @@ -52,40 +54,45 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { set['items.gear.owned.armor_special_birthday'] = false; } - var inc = { - 'items.food.Cake_Skeleton':1, - 'items.food.Cake_Base':1, - 'items.food.Cake_CottonCandyBlue':1, - 'items.food.Cake_CottonCandyPink':1, - 'items.food.Cake_Shade':1, - 'items.food.Cake_White':1, - 'items.food.Cake_Golden':1, - 'items.food.Cake_Zombie':1, - 'items.food.Cake_Desert':1, - 'items.food.Cake_Red':1, - 'achievements.habitBirthdays':1 + let inc = { + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, + 'achievements.habitBirthdays': 1, }; - dbUsers.update({_id:user._id}, {$set:set}); - dbUsers.update({_id:user._id}, {$inc:inc}); + dbUsers.update({_id: user._id}, {$set: set}); + dbUsers.update({_id: user._id}, {$inc: inc}); - if (count%progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); }); -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); -} +} diff --git a/migrations/archive/2016/20160521_veteran_ladder.js b/migrations/archive/2016/20160521_veteran_ladder.js new file mode 100644 index 0000000000..cc538faf6d --- /dev/null +++ b/migrations/archive/2016/20160521_veteran_ladder.js @@ -0,0 +1,89 @@ +let migrationName = '20160521_veteran_ladder.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Gilded Turkey pet to Turkey mount owners, Turkey Mount if they only have Turkey Pet, + * and Turkey Pet otherwise + */ + +let dbserver = 'localhost:27017'; // FOR TEST DATABASE +// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE +let dbname = 'habitrpg'; + +let mongo = require('mongoskin'); +let _ = require('lodash'); + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let dbUsers = mongo.db(`${dbserver }/${ dbname }?auto_reconnect`).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + 'auth.timestamps.loggedin': {$gt: new Date('2016-05-01')}, // remove when running migration a second time +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + migration: 1, + 'items.pets.Wolf-Veteran': 1, + 'items.pets.Tiger-Veteran': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + // specify user data to change: + let set = {}; + if (user.migration !== migrationName) { + if (user.items.pets['Tiger-Veteran']) { + set = {migration: migrationName, 'items.pets.Lion-Veteran': 5}; + } else if (user.items.pets['Wolf-Veteran']) { + set = {migration: migrationName, 'items.pets.Tiger-Veteran': 5}; + } else { + set = {migration: migrationName, 'items.pets.Wolf-Veteran': 5}; + } + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2016/20160527_fix_empty_checklist_id.js b/migrations/archive/2016/20160527_fix_empty_checklist_id.js new file mode 100644 index 0000000000..eacb7498de --- /dev/null +++ b/migrations/archive/2016/20160527_fix_empty_checklist_id.js @@ -0,0 +1,91 @@ +let uuid = require('uuid').v4; +let mongo = require('mongodb').MongoClient; +let _ = require('lodash'); + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +let taskIds = require('checklists-no-id.json').map(function (obj) { + return obj._id; +}); + +// Fix empty task.checklistt.id + +let progressCount = 100; +let count = 0; + +function displayData () { + console.warn(`\n${ count } tasks processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } +} + +mongo.connect('db url') + .then(function (db) { + let dbTasks = db.collection('tasks'); + + // specify a query to limit the affected tasks (empty for all tasks): + let query = { + _id: { $in: taskIds }, + }; + + // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + let fields = { + checklist: 1, + }; + + console.warn('Updating tasks...'); + + dbTasks.find(query, fields, {batchSize: 250}).toArray(function (err, tasks) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + + tasks.forEach(function (task) { + let checklist = task.checklist || []; + checklist.forEach(function (item) { + if (!item.id || item.id === '') { + item.id = uuid(); + } + }); + + // specify user data to change: + let set = { + checklist, + }; + // console.log(set); + + dbTasks.update({_id: task._id}, {$set: set}, function (err, res) { + if (err) console.error('Error while updating', err); + }); + + count++; + if (count % progressCount === 0) console.warn(`${count } ${ task._id}`); + }); + + if (count === tasks.length) { + console.warn('All appropriate tasks found and modified.'); + return displayData(); + } + }); + }) + .catch(function (err) { + throw err; + }); \ No newline at end of file diff --git a/migrations/20160529_fix_challenges.js b/migrations/archive/2016/20160529_fix_challenges.js similarity index 87% rename from migrations/20160529_fix_challenges.js rename to migrations/archive/2016/20160529_fix_challenges.js index 51c31ee0c9..035a5c30ed 100644 --- a/migrations/20160529_fix_challenges.js +++ b/migrations/archive/2016/20160529_fix_challenges.js @@ -1,6 +1,6 @@ 'use strict'; -/**************************************** +/** ************************************** * Reason: After the api v3 maintenance migration, some challenge tasks * became unlinked from their challenges. We're still not sure why, * but this re-links them @@ -33,7 +33,7 @@ const TASK_UPDATE_DATA = require('../challenge_fixes.json'); let db; let count = 0; -var timer = setInterval(function(){ +let timer = setInterval(function () { count++; if (count % 30 === 0) { logger.warn('Process has been running for', count / 60, 'minutes'); @@ -48,7 +48,7 @@ connectToDb() // .then(correctUserTasks) .then(updateTasks) .then(closeDb) - .catch(reportError) + .catch(reportError); function connectToDb () { return new Promise((resolve, reject) => { @@ -81,11 +81,11 @@ function findBrokenChallengeTasks () { logger.info('Looking for broken tasks...'); // return db.collection('tasks').find({'challenge.broken': 'CHALLENGE_TASK_NOT_FOUND'}).toArray() - return db.collection('tasks').find({'_id': { '$in': TASK_IDS }}).toArray() - .then((tasks) => { - logger.success('Found', tasks.length, 'broken tasks.'); - return Promise.resolve(tasks); - }); + return db.collection('tasks').find({_id: { $in: TASK_IDS }}).toArray() + .then((tasks) => { + logger.success('Found', tasks.length, 'broken tasks.'); + return Promise.resolve(tasks); + }); } function getDataFromTasks (tasks) { @@ -114,12 +114,12 @@ function getDataFromTasks (tasks) { function getUserChallenges (data) { logger.info('Collecting user challenges...'); - return db.collection('users').find({_id: { '$in': data.users }}, {challenges: 1}).toArray().then((docs) => { + return db.collection('users').find({_id: { $in: data.users }}, {challenges: 1}).toArray().then((docs) => { logger.success('Found', docs.length, 'users from broken challenge tasks.'); let challenges = []; docs.forEach((user) => { - challenges.push.apply(challenges, user.challenges); + challenges.push(...user.challenges); }); challenges = unique(challenges); @@ -146,7 +146,7 @@ function getUserChallenges (data) { function getChallengeTasks (data) { logger.info('Looking up original challenge tasks...'); - return db.collection('tasks').find({'userId': null, 'challenge.id': { '$in': data.challenges }}, [ 'text', 'type', 'challenge', '_legacyId' ]).toArray().then((docs) => { + return db.collection('tasks').find({userId: null, 'challenge.id': { $in: data.challenges }}, ['text', 'type', 'challenge', '_legacyId']).toArray().then((docs) => { logger.success('Found', docs.length, 'challenge tasks.'); let challengeTasks = {}; @@ -190,14 +190,14 @@ function correctUserTasks (data) { let foundTask = userTasks.find((task) => { return TASK_IDS.indexOf(task._id) > -1 && task._legacyId === legacyId && task.type === type && task.text === text; - }) + }); if (foundTask && !tasksToUpdate[foundTask._id]) { tasksToUpdate[foundTask._id] = { id: chal, broken: null, // NOTE: this caused a lot of problems taskId, - } + }; } else if (foundTask && taskId !== tasksToUpdate[foundTask._id].taskId) { logger.error('Duplicate task found, id:', foundTask._id); duplicateTasks[foundTask._id] = duplicateTasks[foundTask._id] || [tasksToUpdate[foundTask._id].taskId]; @@ -236,12 +236,12 @@ function updateTasks (data) { logger.info(promiseCount, 'updates started'); } - return db.collection('tasks').findOneAndUpdate({_id: taskId, 'challenge.broken': 'CHALLENGE_TASK_NOT_FOUND'}, {$set: {challenge: tasksToUpdate[taskId]}}, {returnOriginal: false}) + return db.collection('tasks').findOneAndUpdate({_id: taskId, 'challenge.broken': 'CHALLENGE_TASK_NOT_FOUND'}, {$set: {challenge: tasksToUpdate[taskId]}}, {returnOriginal: false}); } return Promise.map(taskIdsToUpdate, queue.wrap(updateTaskById)).then((result) => { - let updates = result.filter(res => res.lastErrorObject.updatedExisting) - let failures = result.filter(res => !res.lastErrorObject.updatedExisting); + let updates = result.filter(res => res && res.lastErrorObject.updatedExisting); + let failures = result.filter(res => res && !res.lastErrorObject.updatedExisting); logger.success(updates.length, 'tasks have been fixed'); @@ -256,9 +256,9 @@ function updateTasks (data) { } function closeDb (data) { - logger.success('The process took ' + count + ' seconds'); + logger.success(`The process took ${ count } seconds`); - clearInterval(timer) + clearInterval(timer); db.close(); } diff --git a/migrations/20160530_fix_tasks_from_null_value_in_challenges_broken.js b/migrations/archive/2016/20160530_fix_tasks_from_null_value_in_challenges_broken.js similarity index 88% rename from migrations/20160530_fix_tasks_from_null_value_in_challenges_broken.js rename to migrations/archive/2016/20160530_fix_tasks_from_null_value_in_challenges_broken.js index f5ae6c9925..e010e34b35 100644 --- a/migrations/20160530_fix_tasks_from_null_value_in_challenges_broken.js +++ b/migrations/archive/2016/20160530_fix_tasks_from_null_value_in_challenges_broken.js @@ -1,6 +1,6 @@ 'use strict'; -/**************************************** +/** ************************************** * Reason: After running the 20160529_fix_challenges.js migration * challenge.broken was set to null, which is not a valid value * which caused cron to fail and run many times, messing up daily values, @@ -28,7 +28,7 @@ const NEW_DB_URI = 'mongodb://username:password@dsXXXXXX-a0.mlab.com:XXXXX,dsXXX let oldDb, newDb, OldTasks, NewTasks, OldUsers, NewUsers; let count = 0; -var timer = setInterval(function(){ +let timer = setInterval(function () { count++; if (count % 30 === 0) { logger.warn('Process has been running for', count / 60, 'minutes'); @@ -46,7 +46,7 @@ Promise.all([ .then(getValuesOfOldTasksFromBackup) .then(updateNewTasks) .then(closeDb) - .catch(reportError) + .catch(reportError); function connectToDb (dbUri, type) { return new Promise((resolve, reject) => { @@ -92,14 +92,12 @@ function getAffectedUsersEmail () { users.forEach((user) => { if (user.preferences.emailNotifications.newPM && user.inbox.optOut !== true) { pmsWithEmail.push(user._id); + } else if (user.auth && user.auth.local && user.auth.local.email) { + emails.push(user.auth.local.email); + } else if (user.auth && user.auth.facebook && user.auth.facebook.email) { + emails.push(user.auth.facebook.email); } else { - if (user.auth && user.auth.local && user.auth.local.email) { - emails.push(user.auth.local.email); - } else if (user.auth && user.auth.facebook && user.auth.facebook.email) { - emails.push(user.auth.facebook.email); - } else { - missing.push(user._id); - } + missing.push(user._id); } }); @@ -156,7 +154,9 @@ function determineIfTasksNeedAdjusting (tasks) { let prodTask = tasks[i]; let backupTask = backupTasksAsObject[prodTask._id]; - if (!backupTask) { continue; } + if (!backupTask) { + continue; + } let historyDifference = prodTask.history.length - backupTask.history.length; @@ -194,16 +194,16 @@ function updateNewTasks (oldTasks) { function updateTaskById (task) { promiseCount++; - if (promiseCount % 100=== 0) { + if (promiseCount % 100 === 0) { logger.info(promiseCount, 'updates started'); } - return NewTasks.findOneAndUpdate({_id: task._id}, {$set: {value: task.value, streak: task.streak, history: task.history}}, {returnOriginal: false}) + return NewTasks.findOneAndUpdate({_id: task._id}, {$set: {value: task.value, streak: task.streak, history: task.history}}, {returnOriginal: false}); } return Promise.map(oldTasks, queue.wrap(updateTaskById)).then((result) => { - let updates = result.filter(res => res.lastErrorObject && res.lastErrorObject.updatedExisting) - let failures = result.filter(res => !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); + let updates = result.filter(res => res && res.lastErrorObject && res.lastErrorObject.updatedExisting); + let failures = result.filter(res => res && !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); logger.success(updates.length, 'tasks have been fixed'); @@ -220,9 +220,9 @@ function unique (array) { } function closeDb () { - logger.success('The process took ' + count + ' seconds'); + logger.success(`The process took ${ count } seconds`); - clearInterval(timer) + clearInterval(timer); oldDb.close(); newDb.close(); diff --git a/migrations/20160602_convert_quest_collection.js b/migrations/archive/2016/20160602_convert_quest_collection.js similarity index 87% rename from migrations/20160602_convert_quest_collection.js rename to migrations/archive/2016/20160602_convert_quest_collection.js index 172575cf1e..04db90f1c2 100644 --- a/migrations/20160602_convert_quest_collection.js +++ b/migrations/archive/2016/20160602_convert_quest_collection.js @@ -1,6 +1,6 @@ 'use strict'; -/**************************************** +/** ************************************** * Author: Blade Barringer @crookedneighbor * * Reason: Collection quest data on the client is unreliable @@ -33,7 +33,7 @@ const COLLECTION_QUESTS = [ 'moonstone1', 'goldenknight1', 'dilatoryDistress1', -] +]; let Users, Groups; @@ -43,14 +43,14 @@ connectToDb(DB_URI).then((db) => { return Promise.resolve(); }) -.then(findUsersWithCollectionData) -.then(getUsersCollectionData) -.then(transformCollectionData) -.then(cleanUpEmptyCollectionData) -.then(() => { - timer.stop(); - closeDb(); -}).catch(reportError); + .then(findUsersWithCollectionData) + .then(getUsersCollectionData) + .then(transformCollectionData) + .then(cleanUpEmptyCollectionData) + .then(() => { + timer.stop(); + closeDb(); + }).catch(reportError); function reportError (err) { logger.error('Uh oh, an error occurred'); @@ -68,14 +68,14 @@ function findUsersWithCollectionData () { let members = groups.reduce((array, party) => { let questers = Object.keys(party.quest.members); - array.push.apply(array, questers); + array.push(...questers); return array; }, []); logger.success('Found', members.length, 'users on collection quests'); return Promise.resolve(members); - }) + }); } function getUsersCollectionData (users) { @@ -89,7 +89,7 @@ function getUsersCollectionData (users) { if (!collect) return array; if (typeof collect === 'number') return array; - for (var i in collect) { + for (let i in collect) { if (collect.hasOwnProperty(i)) { total += collect[i]; } @@ -104,7 +104,7 @@ function getUsersCollectionData (users) { } function updateUserById (user) { - return Users.findOneAndUpdate({_id: user._id}, {$set: {'party.quest.progress.collect': user.collect}}, {returnOriginal: false}) + return Users.findOneAndUpdate({_id: user._id}, {$set: {'party.quest.progress.collect': user.collect}}, {returnOriginal: false}); } @@ -114,8 +114,8 @@ function transformCollectionData (users) { logger.info('About to update', users.length, 'user collection items...'); return Promise.map(users, queue.wrap(updateUserById)).then((result) => { - let updates = result.filter(res => res.lastErrorObject && res.lastErrorObject.updatedExisting) - let failures = result.filter(res => !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); + let updates = result.filter(res => res && res.lastErrorObject && res.lastErrorObject.updatedExisting); + let failures = result.filter(res => res && !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); logger.success(updates.length, 'users have been fixed'); diff --git a/migrations/20160605_convert_quest_collection_again.js b/migrations/archive/2016/20160605_convert_quest_collection_again.js similarity index 86% rename from migrations/20160605_convert_quest_collection_again.js rename to migrations/archive/2016/20160605_convert_quest_collection_again.js index a4e2e0b29e..5b9cc1e95c 100644 --- a/migrations/20160605_convert_quest_collection_again.js +++ b/migrations/archive/2016/20160605_convert_quest_collection_again.js @@ -1,6 +1,6 @@ 'use strict'; -/**************************************** +/** ************************************** * Author: Blade Barringer @crookedneighbor * * Reason: The android app uses quest.progress.collect @@ -30,7 +30,7 @@ const COLLECTION_QUESTS = [ 'moonstone1', 'goldenknight1', 'dilatoryDistress1', -] +]; let Users, Groups; @@ -40,14 +40,14 @@ connectToDb(DB_URI).then((db) => { return Promise.resolve(); }) -.then(findUsersWithCollectionData) -.then(getUsersCollectionData) -.then(transferCollectionData) -.then(cleanUpBadCollectionData) -.then(() => { - timer.stop(); - closeDb(); -}).catch(reportError); + .then(findUsersWithCollectionData) + .then(getUsersCollectionData) + .then(transferCollectionData) + .then(cleanUpBadCollectionData) + .then(() => { + timer.stop(); + closeDb(); + }).catch(reportError); function reportError (err) { logger.error('Uh oh, an error occurred'); @@ -65,14 +65,14 @@ function findUsersWithCollectionData () { let members = groups.reduce((array, party) => { let questers = Object.keys(party.quest.members); - array.push.apply(array, questers); + array.push(...questers); return array; }, []); logger.success('Found', members.length, 'users on collection quests'); return Promise.resolve(members); - }) + }); } function getUsersCollectionData (users) { @@ -95,7 +95,7 @@ function getUsersCollectionData (users) { } function updateUserById (user) { - return Users.findOneAndUpdate({_id: user._id}, {$set: {'party.quest.progress.collectedItems': user.collect}}, {returnOriginal: false}) + return Users.findOneAndUpdate({_id: user._id}, {$set: {'party.quest.progress.collectedItems': user.collect}}, {returnOriginal: false}); } @@ -105,8 +105,8 @@ function transferCollectionData (users) { logger.info('About to update', users.length, 'user collection items...'); return Promise.map(users, queue.wrap(updateUserById)).then((result) => { - let updates = result.filter(res => res.lastErrorObject && res.lastErrorObject.updatedExisting) - let failures = result.filter(res => !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); + let updates = result.filter(res => res && res.lastErrorObject && res.lastErrorObject.updatedExisting); + let failures = result.filter(res => res && !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); logger.success(updates.length, 'users have been fixed'); diff --git a/migrations/20160615_fix_bad_emails.js b/migrations/archive/2016/20160615_fix_bad_emails.js similarity index 82% rename from migrations/20160615_fix_bad_emails.js rename to migrations/archive/2016/20160615_fix_bad_emails.js index 0413452e31..97f29cefcf 100644 --- a/migrations/20160615_fix_bad_emails.js +++ b/migrations/archive/2016/20160615_fix_bad_emails.js @@ -1,6 +1,6 @@ 'use strict'; -/**************************************** +/** ************************************** * Author: Blade Barringer @crookedneighbor * * Reason: Old code didn't properly validate email @@ -33,11 +33,11 @@ connectToDb(DB_URI).then((db) => { }) // cached the lookup as a json file // .then(findUsersWithBadEmails) -.then(correctEmails) -.then(() => { - timer.stop(); - closeDb(); -}).catch(reportError); + .then(correctEmails) + .then(() => { + timer.stop(); + closeDb(); + }).catch(reportError); function reportError (err) { logger.error('Uh oh, an error occurred'); @@ -58,8 +58,8 @@ function findUsersWithBadEmails (users) { return { _id: user._id, email: user.auth.local.email }; }); - logger.warn('number of invalid emails:', invalidEmails.length) - console.log(result) + logger.warn('number of invalid emails:', invalidEmails.length); + console.log(result); return Promise.resolve(invalidEmails); }); @@ -68,8 +68,8 @@ function findUsersWithBadEmails (users) { function updateUserById (user) { return Users.findOneAndUpdate({ _id: user._id}, - {$set: {'auth.local.email': user._id + '@example.com'} - }, {returnOriginal: false}) + {$set: {'auth.local.email': `${user._id }@example.com`}, + }, {returnOriginal: false}); } // cached lookup of bad emails @@ -81,8 +81,8 @@ function correctEmails () { logger.warn('About to update', emails.length, 'user email addresses...'); return Promise.map(emails, queue.wrap(updateUserById)).then((result) => { - let updates = result.filter(res => res.lastErrorObject && res.lastErrorObject.updatedExisting) - let failures = result.filter(res => !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); + let updates = result.filter(res => res && res.lastErrorObject && res.lastErrorObject.updatedExisting); + let failures = result.filter(res => res && !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); logger.warn(updates.length, 'users have been fixed'); diff --git a/migrations/archive/2016/20160731_naming_day.js b/migrations/archive/2016/20160731_naming_day.js new file mode 100644 index 0000000000..dfbbf362b9 --- /dev/null +++ b/migrations/archive/2016/20160731_naming_day.js @@ -0,0 +1,89 @@ +let migrationName = '20160731_naming_day.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Royal Purple Gryphon pet to Royal Purple Gryphon mount owners, mount to everyone else + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2016-07-30')}, // Extend timeframe each run of migration +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.mounts': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + let inc = {}; + inc = { + 'achievements.habiticaDays': 1, + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, + }; + if (user.items.mounts['Gryphon-RoyalPurple']) { + set = {migration: migrationName, 'items.pets.Gryphon-RoyalPurple': 5}; + } else { + set = {migration: migrationName, 'items.mounts.Gryphon-RoyalPurple': true}; + } + + dbUsers.update({_id: user._id}, {$set: set, $inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2016/20160731_takeThis.js b/migrations/archive/2016/20160731_takeThis.js new file mode 100644 index 0000000000..6a7e858840 --- /dev/null +++ b/migrations/archive/2016/20160731_takeThis.js @@ -0,0 +1,78 @@ +let migrationName = '20160731_takeThis.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Take This Sword to Take This challenge participants who already own the Shield + * and Take This Shield to the rest of the list + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2016-07-30')}, // Extend timeframe each run of migration + challenges: {$in: ['da8859b2-5c6e-4aa5-b8b2-8db93d5de9fc']}, +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.gear.owned': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + + if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.weapon_special_takeThis': false}; + } else { + set = {migration: migrationName, 'items.gear.owned.shield_special_takeThis': false}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2016/20160831_takeThis.js b/migrations/archive/2016/20160831_takeThis.js new file mode 100644 index 0000000000..733b514b19 --- /dev/null +++ b/migrations/archive/2016/20160831_takeThis.js @@ -0,0 +1,79 @@ +let migrationName = '20160831_takeThis.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Take This Sword to Take This challenge participants who already own the Shield + * and Take This Shield to the rest of the list + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + migration: {$ne: migrationName}, + challenges: {$in: ['ee2b3c87-13f0-422a-af3c-309102d4f7e6']}, +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.gear.owned': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + + if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.armor_special_takeThis': false}; + } else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.weapon_special_takeThis': false}; + } else { + set = {migration: migrationName, 'items.gear.owned.shield_special_takeThis': false}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/20161002_add_missing_webhook_type.js b/migrations/archive/2016/20161002_add_missing_webhook_type.js similarity index 81% rename from migrations/20161002_add_missing_webhook_type.js rename to migrations/archive/2016/20161002_add_missing_webhook_type.js index f3f7b93422..8a0dd5ecbe 100644 --- a/migrations/20161002_add_missing_webhook_type.js +++ b/migrations/archive/2016/20161002_add_missing_webhook_type.js @@ -1,6 +1,6 @@ 'use strict'; -/**************************************** +/** ************************************** * Author: Blade Barringer @crookedneighbor * * Reason: Webhooks have been moved from @@ -24,7 +24,7 @@ const MIGRATION_NAME = '20161002_add_missing_webhook_type.js'; const DB_URI = 'mongodb://localhost/prod-copy-1'; const LOGGEDIN_DATE_RANGE = { - $gte: new Date("2016-09-30T00:00:00.000Z"), + $gte: new Date('2016-09-30T00:00:00.000Z'), // $lte: new Date("2016-09-25T00:00:00.000Z"), }; @@ -33,12 +33,12 @@ let Users; connectToDb(DB_URI).then((db) => { Users = db.collection('users'); }) -.then(findUsersWithWebhooks) -.then(correctWebhooks) -.then(() => { - timer.stop(); - closeDb(); -}).catch(reportError); + .then(findUsersWithWebhooks) + .then(correctWebhooks) + .then(() => { + timer.stop(); + closeDb(); + }).catch(reportError); function reportError (err) { logger.error('Uh oh, an error occurred'); @@ -53,14 +53,14 @@ const USER_IDS = require('../../ids_of_webhooks_to_update.json'); function findUsersWithWebhooks () { logger.warn('Fetching users with webhooks...'); - return Users.find({'_id': {$in: USER_IDS}}, ['preferences.webhooks']).toArray().then((docs) => { + return Users.find({_id: {$in: USER_IDS}}, ['preferences.webhooks']).toArray().then((docs) => { // return Users.find({'preferences.webhooks': {$ne: {} }}, ['preferences.webhooks']).toArray().then((docs) => { // TODO: Run this after the initial migration to catch any webhooks that may have been aded since the prod backup download // return Users.find({'preferences.webhooks': {$ne: {} }, 'auth.timestamps.loggedin': LOGGEDIN_DATE_RANGE}, ['preferences.webhooks']).toArray().then((docs) => { let updates = docs.map((user) => { let oldWebhooks = user.preferences.webhooks; let webhooks = Object.keys(oldWebhooks).map((id) => { - let webhook = oldWebhooks[id] + let webhook = oldWebhooks[id]; webhook.type = 'taskActivity'; webhook.label = ''; @@ -79,7 +79,7 @@ function findUsersWithWebhooks () { return { webhooks, id: user._id, - } + }; }); return Promise.resolve(updates); @@ -92,8 +92,8 @@ function updateUserById (user) { return Users.findOneAndUpdate({ _id: userId}, - {$set: {webhooks: webhooks, migration: MIGRATION_NAME} - }, {returnOriginal: false}) + {$set: {webhooks, migration: MIGRATION_NAME}, + }, {returnOriginal: false}); } function correctWebhooks (users) { @@ -102,8 +102,8 @@ function correctWebhooks (users) { logger.warn('About to update', users.length, 'users...'); return Promise.map(users, queue.wrap(updateUserById)).then((result) => { - let updates = result.filter(res => res.lastErrorObject && res.lastErrorObject.updatedExisting) - let failures = result.filter(res => !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); + let updates = result.filter(res => res && res.lastErrorObject && res.lastErrorObject.updatedExisting); + let failures = result.filter(res => res && !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); logger.warn(updates.length, 'users have been fixed'); diff --git a/migrations/archive/2016/20161002_takeThis.js b/migrations/archive/2016/20161002_takeThis.js new file mode 100644 index 0000000000..f8880a6c7b --- /dev/null +++ b/migrations/archive/2016/20161002_takeThis.js @@ -0,0 +1,80 @@ +let migrationName = '20161002_takeThis.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Take This ladder items to participants in this month's challenge + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + migration: {$ne: migrationName}, + challenges: {$in: ['4bbf63b5-10bc-49f9-8e95-5bd2ac99cd1c']}, +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.gear.owned': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + + if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_takeThis': false}; + } else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.armor_special_takeThis': false}; + } else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.weapon_special_takeThis': false}; + } else { + set = {migration: migrationName, 'items.gear.owned.shield_special_takeThis': false}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2016/20161030-jackolanterns.js b/migrations/archive/2016/20161030-jackolanterns.js new file mode 100644 index 0000000000..6be94e311f --- /dev/null +++ b/migrations/archive/2016/20161030-jackolanterns.js @@ -0,0 +1,93 @@ +let migrationName = '20161030-jackolanterns.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * set the newStuff flag in all user accounts so they see a Bailey message + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + 'auth.timestamps.loggedin': {$gt: new Date('2016-10-01')}, // remove when running migration a second time +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + migration: 1, + 'items.pets.JackOLantern-Base': 1, + 'items.mounts.JackOLantern-Base': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + let inc = {}; + if (user.migration !== migrationName) { + if (user.items.mounts['JackOLantern-Base']) { + set = {migration: migrationName, 'items.pets.JackOLantern-Ghost': 5}; + } else if (user.items.pets['JackOLantern-Base']) { + set = {migration: migrationName, 'items.mounts.JackOLantern-Base': true}; + } else { + set = {migration: migrationName, 'items.pets.JackOLantern-Base': 5}; + } + inc = { + 'items.food.Candy_Base': 1, + 'items.food.Candy_CottonCandyBlue': 1, + 'items.food.Candy_CottonCandyPink': 1, + 'items.food.Candy_Desert': 1, + 'items.food.Candy_Golden': 1, + 'items.food.Candy_Red': 1, + 'items.food.Candy_Shade': 1, + 'items.food.Candy_Skeleton': 1, + 'items.food.Candy_White': 1, + 'items.food.Candy_Zombie': 1, + }; + } + + dbUsers.update({_id: user._id}, {$set: set, $inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2016/20161102_takeThis.js b/migrations/archive/2016/20161102_takeThis.js new file mode 100644 index 0000000000..137dc17dee --- /dev/null +++ b/migrations/archive/2016/20161102_takeThis.js @@ -0,0 +1,82 @@ +let migrationName = '20161102_takeThis.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Take This ladder items to participants in this month's challenge + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + migration: {$ne: migrationName}, + challenges: {$in: ['d1be0965-e909-4d30-82fa-9a0011f885b2']}, +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.gear.owned': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + + if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.body_special_takeThis': false}; + } else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_takeThis': false}; + } else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.armor_special_takeThis': false}; + } else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.weapon_special_takeThis': false}; + } else { + set = {migration: migrationName, 'items.gear.owned.shield_special_takeThis': false}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/archive/2016/20161122_turkey_ladder.js b/migrations/archive/2016/20161122_turkey_ladder.js new file mode 100644 index 0000000000..9853af9212 --- /dev/null +++ b/migrations/archive/2016/20161122_turkey_ladder.js @@ -0,0 +1,81 @@ +let migrationName = '20161122_turkey_ladder.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Yearly Turkey Day award. Turkey pet, Turkey mount, Gilded Turkey pet, Gilded Turkey mount + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2016-10-31')}, // Extend timeframe each run of migration +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + migration: 1, + 'items.mounts': 1, + 'items.pets': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + + if (user.items.pets['Turkey-Gilded']) { + set = {migration: migrationName, 'items.mounts.Turkey-Gilded': true}; + } else if (user.items.mounts['Turkey-Base']) { + set = {migration: migrationName, 'items.pets.Turkey-Gilded': 5}; + } else if (user.items.pets['Turkey-Base']) { + set = {migration: migrationName, 'items.mounts.Turkey-Base': true}; + } else { + set = {migration: migrationName, 'items.pets.Turkey-Base': 5}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} diff --git a/migrations/archive/2016/20161230_nye_hats.js b/migrations/archive/2016/20161230_nye_hats.js new file mode 100644 index 0000000000..a4c9b491a6 --- /dev/null +++ b/migrations/archive/2016/20161230_nye_hats.js @@ -0,0 +1,80 @@ +let migrationName = '20161230_nye_hats.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Yearly New Year's party hat award + */ + +let mongo = require('mongoskin'); + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE + +let dbUsers = mongo.db(connectionString).collection('users'); + +// specify a query to limit the affected users (empty for all users): +let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2016-11-30')}, // Remove after first run +}; + +// specify fields we are interested in to limit retrieved data (empty if we're not reading data): +let fields = { + 'items.gear.owned': 1, +}; + +console.warn('Updating users...'); +let progressCount = 1000; +let count = 0; +dbUsers.findEach(query, fields, {batchSize: 250}, function (err, user) { + if (err) { + return exiting(1, `ERROR! ${ err}`); + } + if (!user) { + console.warn('All appropriate users found and modified.'); + setTimeout(displayData, 300000); + return; + } + count++; + + // specify user data to change: + let set = {}; + + if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2016': false}; + } else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2015': false}; + } else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2014': false}; + } else { + set = {migration: migrationName, 'items.gear.owned.head_special_nye': false}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +}); + + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + diff --git a/migrations/20170111_announce_collection_quest_change_in_parties.js b/migrations/archive/2017/20170111_announce_collection_quest_change_in_parties.js similarity index 78% rename from migrations/20170111_announce_collection_quest_change_in_parties.js rename to migrations/archive/2017/20170111_announce_collection_quest_change_in_parties.js index aabd6703f8..35361d4094 100644 --- a/migrations/20170111_announce_collection_quest_change_in_parties.js +++ b/migrations/archive/2017/20170111_announce_collection_quest_change_in_parties.js @@ -1,6 +1,6 @@ 'use strict'; -/**************************************** +/** ************************************** * Author: @Alys * * Reason: Collection quests are being changed @@ -43,13 +43,13 @@ connectToDb(DB_URI).then((db) => { return Promise.resolve(); }) -.then(findPartiesWithCollectionQuest) + .then(findPartiesWithCollectionQuest) // .then(displayGroups) // for testing only -.then(addMessageToGroups) -.then(() => { - timer.stop(); - closeDb(); -}).catch(reportError); + .then(addMessageToGroups) + .then(() => { + timer.stop(); + closeDb(); + }).catch(reportError); function reportError (err) { logger.error('Uh oh, an error occurred'); @@ -61,11 +61,11 @@ function reportError (err) { function findPartiesWithCollectionQuest () { logger.info('Looking up groups on collection quests...'); - return Groups.find({'quest.key': {$in: COLLECTION_QUESTS}}, ['name','quest']).toArray().then((groups) => { + return Groups.find({'quest.key': {$in: COLLECTION_QUESTS}}, ['name', 'quest']).toArray().then((groups) => { logger.success('Found', groups.length, 'parties on collection quests'); return Promise.resolve(groups); - }) + }); } function displayGroups (groups) { // for testing only @@ -75,16 +75,16 @@ function displayGroups (groups) { // for testing only } function updateGroupById (group) { - var newMessage = { - 'id' : uuid.v4(), - 'text' : message, - 'timestamp': Date.now(), - 'likes': {}, - 'flags': {}, - 'flagCount': 0, - 'uuid': 'system' + let newMessage = { + id: uuid.v4(), + text: message, + timestamp: Date.now(), + likes: {}, + flags: {}, + flagCount: 0, + uuid: 'system', }; - return Groups.findOneAndUpdate({_id: group._id}, {$push:{"chat" :{$each: [newMessage], $position:0}}}, {returnOriginal: false}); + return Groups.findOneAndUpdate({_id: group._id}, {$push: {chat: {$each: [newMessage], $position: 0}}}, {returnOriginal: false}); // Does not set the newMessage flag for all party members because I don't think it's essential and // I don't want to run the extra code (extra database load, extra opportunity for bugs). } @@ -95,8 +95,8 @@ function addMessageToGroups (groups) { logger.info('About to update', groups.length, 'parties...'); return Promise.map(groups, queue.wrap(updateGroupById)).then((result) => { - let updates = result.filter(res => res.lastErrorObject && res.lastErrorObject.updatedExisting) - let failures = result.filter(res => !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); + let updates = result.filter(res => res && res.lastErrorObject && res.lastErrorObject.updatedExisting); + let failures = result.filter(res => res && !(res.lastErrorObject && res.lastErrorObject.updatedExisting)); logger.success(updates.length, 'parties have been notified'); diff --git a/migrations/archive/2017/20170120_missing_incentive.js b/migrations/archive/2017/20170120_missing_incentive.js new file mode 100644 index 0000000000..626fd900eb --- /dev/null +++ b/migrations/archive/2017/20170120_missing_incentive.js @@ -0,0 +1,118 @@ +let migrationName = '20170120_missing_incentive.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award missing Royal Purple Hatching Potion to users with 55+ check-ins + * Reduce users with impossible check-in counts to a reasonable number + */ + +import monk from 'monk'; +import common from '../website/common'; + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); + +function processUsers (lastId) { + // specify a query to limit the affected users (empty for all users): + let query = { + loginIncentives: {$gt: 54}, + migration: {$ne: migrationName}, + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbUsers.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + }) + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateUsers (users) { + if (!users || users.length === 0) { + console.warn('All appropriate users found and modified.'); + displayData(); + return; + } + + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; + + return Promise.all(userPromises) + .then(function () { + processUsers(lastUser._id); + }); +} + +function updateUser (user) { + count++; + + let language = user.preferences.language || 'en'; + let set = {migration: migrationName}; + let inc = {'items.hatchingPotions.RoyalPurple': 1}; + if (user.loginIncentives > 58) { + set = {migration: migrationName, loginIncentives: 58}; + } + let push = { + notifications: { + type: 'LOGIN_INCENTIVE', + data: { + nextRewardAt: 60, + rewardKey: [ + 'Pet_HatchingPotion_Purple', + ], + rewardText: common.i18n.t('potion', {potionType: common.i18n.t('hatchingPotionRoyalPurple', language)}, language), + reward: [ + { + premium: true, + key: 'RoyalPurple', + limited: true, + value: 2, + }, + ], + message: common.i18n.t('unlockedCheckInReward', language), + }, + id: common.uuid(), + }, + }; + + dbUsers.update({_id: user._id}, {$set: set, $push: push, $inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +} + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processUsers; diff --git a/migrations/archive/2017/20170131_habit_birthday.js b/migrations/archive/2017/20170131_habit_birthday.js new file mode 100644 index 0000000000..01efd5ce6a --- /dev/null +++ b/migrations/archive/2017/20170131_habit_birthday.js @@ -0,0 +1,114 @@ +let migrationName = '20170131_habit_birthday.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award 2017 party robes if user has 2016 robes, 2016 robes if they have the 2015 robes, + * 2015 robes if they have the 2014 robes, and 2014 robes otherwise. Also cake! + */ + +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); + +function processUsers (lastId) { + // specify a query to limit the affected users (empty for all users): + let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2017-01-24')}, // remove after first run to cover remaining users + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbUsers.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data) + 'items.gear.owned', + ], + }) + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateUsers (users) { + if (!users || users.length === 0) { + console.warn('All appropriate users found and modified.'); + displayData(); + return; + } + + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; + + return Promise.all(userPromises) + .then(function () { + processUsers(lastUser._id); + }); +} + +function updateUser (user) { + count++; + + let set = {migration: migrationName}; + if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2016')) { + set['items.gear.owned.armor_special_birthday2017'] = false; + } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2015')) { + set['items.gear.owned.armor_special_birthday2016'] = false; + } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday')) { + set['items.gear.owned.armor_special_birthday2015'] = false; + } else { + set['items.gear.owned.armor_special_birthday'] = false; + } + + let inc = { + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, + 'achievements.habitBirthdays': 1, + }; + + dbUsers.update({_id: user._id}, {$set: set, $inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +} + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processUsers; diff --git a/migrations/archive/2017/20170418_subscriber_jackalopes.js b/migrations/archive/2017/20170418_subscriber_jackalopes.js new file mode 100644 index 0000000000..856f35bd13 --- /dev/null +++ b/migrations/archive/2017/20170418_subscriber_jackalopes.js @@ -0,0 +1,93 @@ +let migrationName = '20170418_subscriber_jackalopes.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Royal Purple Jackalope pet to all current subscribers + */ + +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); +let now = new Date(); + +function processUsers (lastId) { + // specify a query to limit the affected users (empty for all users): + let query = { + 'purchased.plan.customerId': {$type: 2}, + $or: [ + {'purchased.plan.dateTerminated': null}, + {'purchased.plan.dateTerminated': {$exists: false}}, + {'purchased.plan.dateTerminated': {$gt: now}}, + ], + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbUsers.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + }) + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateUsers (users) { + if (!users || users.length === 0) { + console.warn('All appropriate users found and modified.'); + displayData(); + return; + } + + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; + + return Promise.all(userPromises) + .then(function () { + processUsers(lastUser._id); + }); +} + +function updateUser (user) { + count++; + + let set = {'items.pets.Jackalope-RoyalPurple': 5}; + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +} + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processUsers; diff --git a/migrations/20170425_missing_incentives.js b/migrations/archive/2017/20170425_missing_incentives.js similarity index 70% rename from migrations/20170425_missing_incentives.js rename to migrations/archive/2017/20170425_missing_incentives.js index be8c224719..9c431b5661 100644 --- a/migrations/20170425_missing_incentives.js +++ b/migrations/archive/2017/20170425_missing_incentives.js @@ -1,6 +1,6 @@ -var migrationName = '20170425_missing_incentives'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +let migrationName = '20170425_missing_incentives'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Award missing Royal Purple Hatching Potion to users with 55+ check-ins @@ -10,36 +10,36 @@ var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done import monk from 'monk'; import common from '../website/common'; -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'loginIncentives': {$gt:99}, - 'migration': {$ne: migrationName}, + let query = { + loginIncentives: {$gt: 99}, + migration: {$ne: migrationName}, }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { sort: {_id: 1}, limit: 250, - fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -48,20 +48,20 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(function () { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var language = user.preferences.language || 'en'; - var set = {'migration': migrationName}; - var inc = { + let language = user.preferences.language || 'en'; + let set = {migration: migrationName}; + let inc = { 'items.eggs.BearCub': 0, 'items.eggs.Cactus': 0, 'items.eggs.Dragon': 0, @@ -93,7 +93,7 @@ function updateUser (user) { 'items.hatchingPotions.White': 0, 'items.hatchingPotions.Zombie': 0, }; - var nextReward; + let nextReward; if (user.loginIncentives >= 105) { inc['items.hatchingPotions.RoyalPurple'] += 1; @@ -167,39 +167,44 @@ function updateUser (user) { nextReward = 160; } - var push = { - 'notifications': { - 'type': 'LOGIN_INCENTIVE', - 'data': { - 'nextRewardAt': nextReward, - 'rewardKey': [ + let push = { + notifications: { + type: 'LOGIN_INCENTIVE', + data: { + nextRewardAt: nextReward, + rewardKey: [ 'shop_armoire', ], - 'rewardText': common.i18n.t('checkInRewards', language), - 'reward': [], - 'message': common.i18n.t('backloggedCheckInRewards', language), + rewardText: common.i18n.t('checkInRewards', language), + reward: [], + message: common.i18n.t('backloggedCheckInRewards', language), }, - 'id': common.uuid(), - } + id: common.uuid(), + }, }; - dbUsers.update({_id: user._id}, {$set:set, $push:push, $inc:inc}); + dbUsers.update({_id: user._id}, {$set: set, $push: push, $inc: inc}); - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/20170616_achievements.js b/migrations/archive/2017/20170616_achievements.js similarity index 56% rename from migrations/20170616_achievements.js rename to migrations/archive/2017/20170616_achievements.js index a780c33f3d..53b8be3b73 100644 --- a/migrations/20170616_achievements.js +++ b/migrations/archive/2017/20170616_achievements.js @@ -1,6 +1,6 @@ -var migrationName = '20170616_achievements'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +let migrationName = '20170616_achievements'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Updates to achievements for June 16, 2017 biweekly merge @@ -10,27 +10,27 @@ var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done import monk from 'monk'; -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { + let query = { $or: [ - {'achievements.quests.dilatoryDistress1': {$gt:0}}, - {'achievements.quests.egg': {$gt:0}}, - {'achievements.quests.goldenknight1': {$gt:0}}, - {'achievements.quests.moonstone1': {$gt:0}}, - {'achievements.quests.vice2': {$gt:0}}, + {'achievements.quests.dilatoryDistress1': {$gt: 0}}, + {'achievements.quests.egg': {$gt: 0}}, + {'achievements.quests.goldenknight1': {$gt: 0}}, + {'achievements.quests.moonstone1': {$gt: 0}}, + {'achievements.quests.vice2': {$gt: 0}}, {'achievements.challenges': {$exists: true, $ne: []}}, - {'challenges': {$exists: true, $ne: []}}, + {challenges: {$exists: true, $ne: []}}, ], }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { @@ -41,15 +41,15 @@ function processUsers(lastId) { 'challenges', ], }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -58,18 +58,18 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(function () { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = {'migration': migrationName}; + let set = {migration: migrationName}; if (user.challenges.length > 0 || user.achievements.challenges.length > 0) { set['achievements.joinedChallenge'] = true; @@ -90,23 +90,28 @@ function updateUser (user) { set['achievements.quests.vice2'] = Math.ceil(user.achievements.quests.vice2 * 1.5); } - dbUsers.update({_id: user._id}, {$set:set}); + dbUsers.update({_id: user._id}, {$set: set}); - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/archive/2017/20170711_orcas.js b/migrations/archive/2017/20170711_orcas.js new file mode 100644 index 0000000000..8c9793fe43 --- /dev/null +++ b/migrations/archive/2017/20170711_orcas.js @@ -0,0 +1,95 @@ +let migrationName = '20170711_orcas.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Orca pets to owners of Orca mount, and Orca mount to everyone else + */ + +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); + +function processUsers (lastId) { + // specify a query to limit the affected users (empty for all users): + let query = { + migration: {$ne: migrationName}, + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbUsers.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [ + 'items.mounts', + ], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + }) + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateUsers (users) { + if (!users || users.length === 0) { + console.warn('All appropriate users found and modified.'); + displayData(); + return; + } + + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; + + return Promise.all(userPromises) + .then(function () { + processUsers(lastUser._id); + }); +} + +function updateUser (user) { + count++; + + let set = {}; + + if (user.items.mounts['Orca-Base']) { + set = {migration: migrationName, 'items.pets.Orca-Base': 5}; + } else { + set = {migration: migrationName, 'items.mounts.Orca-Base': true}; + } + + dbUsers.update({_id: user._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +} + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processUsers; diff --git a/migrations/archive/2017/20170731_naming_day.js b/migrations/archive/2017/20170731_naming_day.js new file mode 100644 index 0000000000..0aac178dba --- /dev/null +++ b/migrations/archive/2017/20170731_naming_day.js @@ -0,0 +1,114 @@ +let migrationName = '20170731_naming_day.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award Royal Purple Gryphon Helm to Royal Purple Gryphon pet owners, + * award Royal Purple Gryphon pet to Royal Purple Gryphon mount owners, + * award Royal Purple Gryphon mount to everyone else + */ + +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); + +function processUsers (lastId) { + // specify a query to limit the affected users (empty for all users): + let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2017-01-01')}, + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbUsers.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [ + 'items.mounts', + 'items.pets', + ], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + }) + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateUsers (users) { + if (!users || users.length === 0) { + console.warn('All appropriate users found and modified.'); + displayData(); + return; + } + + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; + + return Promise.all(userPromises) + .then(function () { + processUsers(lastUser._id); + }); +} + +function updateUser (user) { + count++; + + let set = {}; + let inc = { + 'achievements.habiticaDays': 1, + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, + }; + + if (user.items.pets['Gryphon-RoyalPurple']) { + set = {migration: migrationName, 'items.gear.owned.head_special_namingDay2017': false}; + } else if (user.items.mounts['Gryphon-RoyalPurple']) { + set = {migration: migrationName, 'items.pets.Gryphon-RoyalPurple': 5}; + } else { + set = {migration: migrationName, 'items.mounts.Gryphon-RoyalPurple': true}; + } + + dbUsers.update({_id: user._id}, {$set: set, $inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +} + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processUsers; diff --git a/migrations/archive/2017/20170928_redesign_guilds.js b/migrations/archive/2017/20170928_redesign_guilds.js new file mode 100644 index 0000000000..89bd8f5261 --- /dev/null +++ b/migrations/archive/2017/20170928_redesign_guilds.js @@ -0,0 +1,102 @@ +let migrationName = '20170928_redesign_guilds.js'; + +/* + * Copy Guild Leader messages to end of Guild descriptions + * Copy Guild logos to beginning of Guild descriptions + */ + +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbGroups = monk(connectionString).get('groups', { castIds: false }); + +function processGroups (lastId) { + // specify a query to limit the affected groups (empty for all groups): + let query = { + }; + + let fields = { + description: 1, + logo: 1, + leaderMessage: 1, + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + return dbGroups.find(query, { + fields, + sort: {_id: 1}, + limit: 250, + }) + .then(updateGroups) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateGroups (groups) { + if (!groups || groups.length === 0) { + console.warn('All appropriate groups found and modified.'); + displayData(); + return; + } + + let groupPromises = groups.map(updateGroup); + let lastGroup = groups[groups.length - 1]; + + return Promise.all(groupPromises) + .then(function () { + processGroups(lastGroup._id); + }); +} + +function updateGroup (group) { + count++; + + let description = group.description; + + if (group.logo) { + description = `![Guild Logo](${ group.logo })\n\n \n\n${ description}`; + } + + if (group.leaderMessage) { + description = `${description }\n\n \n\n${ group.leaderMessage}`; + } + + let set = { + description, + }; + + if (count % progressCount === 0) console.warn(`${count } ${ group._id}`); + + return dbGroups.update({_id: group._id}, {$set: set}); +} + +function displayData () { + console.warn(`\n${ count } groups processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processGroups; diff --git a/migrations/20170928_redesign_launch.js b/migrations/archive/2017/20170928_redesign_launch.js similarity index 50% rename from migrations/20170928_redesign_launch.js rename to migrations/archive/2017/20170928_redesign_launch.js index 1139652050..e83d838413 100644 --- a/migrations/20170928_redesign_launch.js +++ b/migrations/archive/2017/20170928_redesign_launch.js @@ -1,53 +1,53 @@ import { selectGearToPin } from '../website/common/script/ops/pinnedGearUtils'; -var getItemInfo = require('../website/common/script/libs/getItemInfo'); +let getItemInfo = require('../website/common/script/libs/getItemInfo'); -var migrationName = '20170928_redesign_launch.js'; -var authorName = 'paglias'; // in case script author needs to know when their ... -var authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; //... own data is done +let migrationName = '20170928_redesign_launch.js'; +let authorName = 'paglias'; // in case script author needs to know when their ... +let authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done /* * Migrate existing in app rewards lists to pinned items * Award Veteran Pets */ -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'migration': {$ne:migrationName}, + let query = { + migration: {$ne: migrationName}, 'auth.timestamps.loggedin': {$gt: new Date('2017-09-21')}, }; - var fields = { + let fields = { 'items.pets': 1, 'items.gear': 1, 'stats.class': 1, - } + }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } return dbUsers.find(query, { - fields: fields, + fields, sort: {_id: 1}, limit: 250, }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -56,22 +56,22 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(function () { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = {'migration': migrationName}; + let set = {migration: migrationName}; - var oldRewardsList = selectGearToPin(user); - var newPinnedItems = [ + let oldRewardsList = selectGearToPin(user); + let newPinnedItems = [ { type: 'armoire', path: 'armoire', @@ -83,13 +83,13 @@ function updateUser (user) { ]; oldRewardsList.forEach(item => { - var type = 'marketGear'; + let type = 'marketGear'; - var itemInfo = getItemInfo(user, 'marketGear', item); + let itemInfo = getItemInfo(user, 'marketGear', item); newPinnedItems.push({ type, path: itemInfo.path, - }) + }); }); set.pinnedItems = newPinnedItems; @@ -104,23 +104,28 @@ function updateUser (user) { set['items.pets.Wolf-Veteran'] = 5; } - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); - return dbUsers.update({_id: user._id}, {$set:set}); + return dbUsers.update({_id: user._id}, {$set: set}); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/archive/2017/20171030_jackolanterns.js b/migrations/archive/2017/20171030_jackolanterns.js new file mode 100644 index 0000000000..1b07ed1fb2 --- /dev/null +++ b/migrations/archive/2017/20171030_jackolanterns.js @@ -0,0 +1,116 @@ +let migrationName = '20171030_jackolanterns.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award the Jack-O'-Lantern ladder: + * Ghost Jack-O-Lantern Mount to owners of Ghost Jack-O-Lantern Pet + * Ghost Jack-O-Lantern Pet to owners of Jack-O-Lantern Mount + * Jack-O-Lantern Mount to owners of Jack-O-Lantern Pet + * Jack-O-Lantern Pet to everyone else + */ + +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); + +function processUsers (lastId) { + // specify a query to limit the affected users (empty for all users): + let query = { + migration: {$ne: migrationName}, + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbUsers.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [ + 'items.pets', + 'items.mounts', + ], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + }) + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateUsers (users) { + if (!users || users.length === 0) { + console.warn('All appropriate users found and modified.'); + displayData(); + return; + } + + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; + + return Promise.all(userPromises) + .then(function () { + processUsers(lastUser._id); + }); +} + +function updateUser (user) { + count++; + + let set = {}; + let inc = { + 'items.food.Candy_Skeleton': 1, + 'items.food.Candy_Base': 1, + 'items.food.Candy_CottonCandyBlue': 1, + 'items.food.Candy_CottonCandyPink': 1, + 'items.food.Candy_Shade': 1, + 'items.food.Candy_White': 1, + 'items.food.Candy_Golden': 1, + 'items.food.Candy_Zombie': 1, + 'items.food.Candy_Desert': 1, + 'items.food.Candy_Red': 1, + }; + + if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Ghost']) { + set = {migration: migrationName, 'items.mounts.JackOLantern-Ghost': true}; + } else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Base']) { + set = {migration: migrationName, 'items.pets.JackOLantern-Ghost': 5}; + } else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Base']) { + set = {migration: migrationName, 'items.mounts.JackOLantern-Base': true}; + } else { + set = {migration: migrationName, 'items.pets.JackOLantern-Base': 5}; + } + + dbUsers.update({_id: user._id}, {$set: set, $inc: inc}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +} + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processUsers; diff --git a/migrations/20171117_turkey_ladder.js b/migrations/archive/2017/20171117_turkey_ladder.js similarity index 57% rename from migrations/20171117_turkey_ladder.js rename to migrations/archive/2017/20171117_turkey_ladder.js index 814109af5f..f4414f58ac 100644 --- a/migrations/20171117_turkey_ladder.js +++ b/migrations/archive/2017/20171117_turkey_ladder.js @@ -1,6 +1,6 @@ -var migrationName = '20171117_turkey_ladder.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +let migrationName = '20171117_turkey_ladder.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Award the Turkey Day ladder: @@ -11,21 +11,21 @@ var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done * Grant Base Turkey pet to those who have none of the above yet */ -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin':{$gt:new Date('2017-11-01')}, + let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2017-11-01')}, }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { @@ -34,17 +34,17 @@ function processUsers(lastId) { fields: [ 'items.pets', 'items.mounts', - ] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + ], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -53,19 +53,19 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(function () { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = {}; + let set = {}; if (user && user.items && user.items.mounts && user.items.mounts['Turkey-Gilded']) { set = { @@ -92,13 +92,13 @@ function updateUser (user) { }, ]; } else if (user && user.items && user.items.pets && user.items.pets['Turkey-Gilded']) { - set = {'migration':migrationName, 'items.mounts.Turkey-Gilded':true}; + set = {migration: migrationName, 'items.mounts.Turkey-Gilded': true}; } else if (user && user.items && user.items.mounts && user.items.mounts['Turkey-Base']) { - set = {'migration':migrationName, 'items.pets.Turkey-Gilded':5}; + set = {migration: migrationName, 'items.pets.Turkey-Gilded': 5}; } else if (user && user.items && user.items.pets && user.items.pets['Turkey-Base']) { - set = {'migration':migrationName, 'items.mounts.Turkey-Base':true}; + set = {migration: migrationName, 'items.mounts.Turkey-Base': true}; } else { - set = {'migration':migrationName, 'items.pets.Turkey-Base':5}; + set = {migration: migrationName, 'items.pets.Turkey-Base': 5}; } dbUsers.update({_id: user._id}, {$set: set}); @@ -106,21 +106,26 @@ function updateUser (user) { dbUsers.update({_id: user._id}, {$push: {pinnedItems: {$each: push}}}); } - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/archive/2017/20171230_nye_hats.js b/migrations/archive/2017/20171230_nye_hats.js new file mode 100644 index 0000000000..12c4287dc5 --- /dev/null +++ b/migrations/archive/2017/20171230_nye_hats.js @@ -0,0 +1,108 @@ +let migrationName = '20171230_nye_hats.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done + +/* + * Award New Year's Eve party hats to users in sequence + */ + +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); + +function processUsers (lastId) { + // specify a query to limit the affected users (empty for all users): + let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2017-11-30')}, + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbUsers.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [ + 'items.gear.owned', + ], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + }) + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +let progressCount = 1000; +let count = 0; + +function updateUsers (users) { + if (!users || users.length === 0) { + console.warn('All appropriate users found and modified.'); + displayData(); + return; + } + + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; + + return Promise.all(userPromises) + .then(function () { + processUsers(lastUser._id); + }); +} + +function updateUser (user) { + count++; + + let set = {}; + let push = {}; + + if (typeof user.items.gear.owned.head_special_nye2016 !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2017': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2017', _id: monk.id()}}; + } else if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2016': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2016', _id: monk.id()}}; + } else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2015': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2015', _id: monk.id()}}; + } else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') { + set = {migration: migrationName, 'items.gear.owned.head_special_nye2014': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye2014', _id: monk.id()}}; + } else { + set = {migration: migrationName, 'items.gear.owned.head_special_nye': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_nye', _id: monk.id()}}; + } + + dbUsers.update({_id: user._id}, {$set: set, $push: push}); + + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); +} + +function displayData () { + console.warn(`\n${ count } users processed\n`); + return exiting(0); +} + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +module.exports = processUsers; diff --git a/migrations/20180110_nextPaymentProcessing.js b/migrations/archive/2018/20180110_nextPaymentProcessing.js similarity index 50% rename from migrations/20180110_nextPaymentProcessing.js rename to migrations/archive/2018/20180110_nextPaymentProcessing.js index 293dcb354c..c56cca690f 100644 --- a/migrations/20180110_nextPaymentProcessing.js +++ b/migrations/archive/2018/20180110_nextPaymentProcessing.js @@ -2,36 +2,36 @@ * Convert purchased.plan.nextPaymentProcessing from a double to a date field for Apple subscribers */ -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'purchased.plan.paymentMethod': "Apple", + let query = { + 'purchased.plan.paymentMethod': 'Apple', 'purchased.plan.nextPaymentProcessing': {$type: 'double'}, }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { sort: {_id: 1}, limit: 250, }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 100; -var count = 0; +let progressCount = 100; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -40,38 +40,43 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(function () { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = { + let set = { 'purchased.plan.nextPaymentProcessing': new Date(user.purchased.plan.nextPaymentProcessing), }; dbUsers.update({_id: user._id}, {$set: set}); - if (count % progressCount == 0) console.warn(count + ' ' + user._id); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/20180125_clean_new_notifications.js b/migrations/archive/2018/20180125_clean_new_notifications.js similarity index 100% rename from migrations/20180125_clean_new_notifications.js rename to migrations/archive/2018/20180125_clean_new_notifications.js diff --git a/migrations/20180125_notifications.js b/migrations/archive/2018/20180125_notifications.js similarity index 100% rename from migrations/20180125_notifications.js rename to migrations/archive/2018/20180125_notifications.js diff --git a/migrations/20180130_habit_birthday.js b/migrations/archive/2018/20180130_habit_birthday.js similarity index 51% rename from migrations/20180130_habit_birthday.js rename to migrations/archive/2018/20180130_habit_birthday.js index 05a3dc1c02..f28a42eaa8 100644 --- a/migrations/20180130_habit_birthday.js +++ b/migrations/archive/2018/20180130_habit_birthday.js @@ -1,44 +1,44 @@ -var migrationName = '20180130_habit_birthday.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +let migrationName = '20180130_habit_birthday.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Award party robes: most recent user doesn't have of 2014-2018. Also cake! */ -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'migration':{$ne:migrationName}, - 'auth.timestamps.loggedin':{$gt:new Date('2018-01-01')}, // remove after first run to cover remaining users + let query = { + migration: {$ne: migrationName}, + 'auth.timestamps.loggedin': {$gt: new Date('2018-01-01')}, // remove after first run to cover remaining users }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { sort: {_id: 1}, limit: 250, fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data) - 'items.gear.owned' + 'items.gear.owned', ], }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch(function (err) { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -47,69 +47,74 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(function () { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var push; - var set = {'migration':migrationName}; + let push; + let set = {migration: migrationName}; if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2017')) { set['items.gear.owned.armor_special_birthday2018'] = false; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2018', '_id': monk.id()}}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2018', _id: monk.id()}}; } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2016')) { set['items.gear.owned.armor_special_birthday2017'] = false; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2017', '_id': monk.id()}}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2017', _id: monk.id()}}; } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2015')) { set['items.gear.owned.armor_special_birthday2016'] = false; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2016', '_id': monk.id()}}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2016', _id: monk.id()}}; } else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday')) { set['items.gear.owned.armor_special_birthday2015'] = false; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2015', '_id': monk.id()}}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2015', _id: monk.id()}}; } else { set['items.gear.owned.armor_special_birthday'] = false; - push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday', '_id': monk.id()}}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday', _id: monk.id()}}; } - var inc = { - 'items.food.Cake_Skeleton':1, - 'items.food.Cake_Base':1, - 'items.food.Cake_CottonCandyBlue':1, - 'items.food.Cake_CottonCandyPink':1, - 'items.food.Cake_Shade':1, - 'items.food.Cake_White':1, - 'items.food.Cake_Golden':1, - 'items.food.Cake_Zombie':1, - 'items.food.Cake_Desert':1, - 'items.food.Cake_Red':1, - 'achievements.habitBirthdays':1 + let inc = { + 'items.food.Cake_Skeleton': 1, + 'items.food.Cake_Base': 1, + 'items.food.Cake_CottonCandyBlue': 1, + 'items.food.Cake_CottonCandyPink': 1, + 'items.food.Cake_Shade': 1, + 'items.food.Cake_White': 1, + 'items.food.Cake_Golden': 1, + 'items.food.Cake_Zombie': 1, + 'items.food.Cake_Desert': 1, + 'items.food.Cake_Red': 1, + 'achievements.habitBirthdays': 1, }; dbUsers.update({_id: user._id}, {$set: set, $inc: inc, $push: push}); - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/archive/README.md b/migrations/archive/README.md new file mode 100644 index 0000000000..9330a6dbf8 --- /dev/null +++ b/migrations/archive/README.md @@ -0,0 +1,4 @@ +If you need to use a migration from this folder, move it to /migrations. + +Note that /migrations files (excluding /archive) are linted, so to pass test you'll have to make sure +that the file is written correctly. \ No newline at end of file diff --git a/migrations/archive/api_v3/challenges.js b/migrations/archive/api_v3/challenges.js new file mode 100644 index 0000000000..80315db9f1 --- /dev/null +++ b/migrations/archive/api_v3/challenges.js @@ -0,0 +1,218 @@ +// Migrate challenges collection to new schema (except for members) + +// The console-stamp module must be installed (not included in package.json) + +// It requires two environment variables: MONGODB_OLD and MONGODB_NEW + +// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). +// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 +console.log('Starting migrations/api_v3/challenges.js.'); + +require('babel-register'); +require('babel-polyfill'); + +let Bluebird = require('bluebird'); +let MongoDB = require('mongodb'); +let nconf = require('nconf'); +let mongoose = require('mongoose'); +let _ = require('lodash'); +let uuid = require('uuid'); +let consoleStamp = require('console-stamp'); +let fs = require('fs'); + +// Add timestamps to console messages +consoleStamp(console); + +// Initialize configuration +require('../../website/server/libs/api-v3/setupNconf')(); + +let MONGODB_OLD = nconf.get('MONGODB_OLD'); +let MONGODB_NEW = nconf.get('MONGODB_NEW'); + +let MongoClient = MongoDB.MongoClient; + +mongoose.Promise = Bluebird; // otherwise mongoose models won't work + +// Load new models +let NewChallenge = require('../../website/server/models/challenge').model; +let Tasks = require('../../website/server/models/task'); + +// To be defined later when MongoClient connects +let mongoDbOldInstance; +let oldChallengeCollection; + +let mongoDbNewInstance; +let newChallengeCollection; +let newTaskCollection; + +let BATCH_SIZE = 1000; + +let processedChallenges = 0; +let totoalProcessedTasks = 0; + +let newTasksIds = {}; // a map of old id -> [new id, challengeId] + +// Only process challenges that fall in a interval ie -> up to 0000-4000-0000-0000 +let AFTER_CHALLENGE_ID = nconf.get('AFTER_CHALLENGE_ID'); +let BEFORE_CHALLENGE_ID = nconf.get('BEFORE_CHALLENGE_ID'); + +function processChallenges (afterId) { + let processedTasks = 0; + let lastChallenge = null; + let oldChallenges; + + let query = {}; + + if (BEFORE_CHALLENGE_ID) { + query._id = {$lte: BEFORE_CHALLENGE_ID}; + } + + if ((afterId || AFTER_CHALLENGE_ID) && !query._id) { + query._id = {}; + } + + if (afterId) { + query._id.$gt = afterId; + } else if (AFTER_CHALLENGE_ID) { + query._id.$gt = AFTER_CHALLENGE_ID; + } + + let batchInsertTasks = newTaskCollection.initializeUnorderedBulkOp(); + let batchInsertChallenges = newChallengeCollection.initializeUnorderedBulkOp(); + + console.log(`Executing challenges query.\nMatching challenges after ${afterId ? afterId : AFTER_CHALLENGE_ID} and before ${BEFORE_CHALLENGE_ID} (included).`); + + return oldChallengeCollection + .find(query) + .sort({_id: 1}) + .limit(BATCH_SIZE) + .toArray() + .then(function (oldChallengesR) { + oldChallenges = oldChallengesR; + + console.log(`Processing ${oldChallenges.length} challenges. Already processed ${processedChallenges} challenges and ${totoalProcessedTasks} tasks.`); + + if (oldChallenges.length === BATCH_SIZE) { + lastChallenge = oldChallenges[oldChallenges.length - 1]._id; + } + + oldChallenges.forEach(function (oldChallenge) { + let oldTasks = oldChallenge.habits.concat(oldChallenge.dailys).concat(oldChallenge.rewards).concat(oldChallenge.todos); + delete oldChallenge.habits; + delete oldChallenge.dailys; + delete oldChallenge.rewards; + delete oldChallenge.todos; + + let createdAt = oldChallenge.timestamp; + + oldChallenge.memberCount = oldChallenge.members.length; + if (oldChallenge.prize <= 0) oldChallenge.prize = 0; + if (!oldChallenge.name) oldChallenge.name = 'challenge name'; + if (!oldChallenge.shortName) oldChallenge.name = 'challenge-name'; + + if (!oldChallenge.group) throw new Error('challenge.group is required'); + if (!oldChallenge.leader) throw new Error('challenge.leader is required'); + + + if (oldChallenge.leader === '9') { + oldChallenge.leader = '00000000-0000-4000-9000-000000000000'; + } + + if (oldChallenge.group === 'habitrpg') { + oldChallenge.group = '00000000-0000-4000-A000-000000000000'; + } + + delete oldChallenge.id; + + let newChallenge = new NewChallenge(oldChallenge); + + newChallenge.createdAt = createdAt; + + oldTasks.forEach(function (oldTask) { + oldTask._id = uuid.v4(); + oldTask._legacyId = oldTask.id; // store the old task id + delete oldTask.id; + + oldTask.challenge = oldTask.challenge || {}; + oldTask.challenge.id = newChallenge._id; + + if (newTasksIds[`${oldTask._legacyId }-${ newChallenge._id}`]) { + throw new Error('duplicate :('); + } else { + newTasksIds[`${oldTask._legacyId }-${ newChallenge._id}`] = oldTask._id; + } + + oldTask.tags = _.map(oldTask.tags || {}, function (tagPresent, tagId) { + return tagPresent && tagId; + }).filter(function (tag) { + return tag !== false; + }); + + if (!oldTask.text) oldTask.text = 'task text'; // required + + oldTask.createdAt = oldTask.dateCreated; + + newChallenge.tasksOrder[`${oldTask.type}s`].push(oldTask._id); + if (oldTask.completed) oldTask.completed = false; + + let newTask = new Tasks[oldTask.type](oldTask); + + batchInsertTasks.insert(newTask.toObject()); + processedTasks++; + }); + + batchInsertChallenges.insert(newChallenge.toObject()); + }); + + console.log(`Saving ${oldChallenges.length} challenges and ${processedTasks} tasks.`); + + return Bluebird.all([ + batchInsertChallenges.execute(), + batchInsertTasks.execute(), + ]); + }) + .then(function () { + totoalProcessedTasks += processedTasks; + processedChallenges += oldChallenges.length; + + console.log(`Saved ${oldChallenges.length} challenges and their tasks.`); + + if (lastChallenge) { + return processChallenges(lastChallenge); + } else { + console.log('Writing newTasksIds.json...'); + fs.writeFileSync('newTasksIds.json', JSON.stringify(newTasksIds, null, 4), 'utf8'); + return console.log('Done!'); + } + }); +} + +// Connect to the databases +Bluebird.all([ + MongoClient.connect(MONGODB_OLD), + MongoClient.connect(MONGODB_NEW), +]) + .then(function (result) { + let oldInstance = result[0]; + let newInstance = result[1]; + + mongoDbOldInstance = oldInstance; + oldChallengeCollection = mongoDbOldInstance.collection('challenges'); + + mongoDbNewInstance = newInstance; + newChallengeCollection = mongoDbNewInstance.collection('challenges'); + newTaskCollection = mongoDbNewInstance.collection('tasks'); + + console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); + + return processChallenges(); + }) + .catch(function (err) { + console.error(err.stack || err); + }); diff --git a/migrations/archive/api_v3/challengesMembers.js b/migrations/archive/api_v3/challengesMembers.js new file mode 100644 index 0000000000..2691896b18 --- /dev/null +++ b/migrations/archive/api_v3/challengesMembers.js @@ -0,0 +1,149 @@ +// Migrate challenges members +// Run AFTER users migration + +// The console-stamp module must be installed (not included in package.json) + +// It requires two environment variables: MONGODB_OLD and MONGODB_NEW + +// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). +// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM +console.log('Starting migrations/api_v3/challengesMembers.js.'); + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +require('babel-register'); +require('babel-polyfill'); + +let Bluebird = require('bluebird'); +let MongoDB = require('mongodb'); +let nconf = require('nconf'); +let mongoose = require('mongoose'); +let _ = require('lodash'); +let uuid = require('uuid'); +let consoleStamp = require('console-stamp'); + +// Add timestamps to console messages +consoleStamp(console); + +// Initialize configuration +require('../../website/server/libs/api-v3/setupNconf')(); + +let MONGODB_OLD = nconf.get('MONGODB_OLD'); +let MONGODB_NEW = nconf.get('MONGODB_NEW'); + +let MongoClient = MongoDB.MongoClient; + +mongoose.Promise = Bluebird; // otherwise mongoose models won't work + +// To be defined later when MongoClient connects +let mongoDbOldInstance; +let oldChallengeCollection; + +let mongoDbNewInstance; +let newUserCollection; + +let BATCH_SIZE = 1000; + +let processedChallenges = 0; + +// Only process challenges that fall in a interval ie -> up to 0000-4000-0000-0000 +let AFTER_CHALLENGE_ID = nconf.get('AFTER_CHALLENGE_ID'); +let BEFORE_CHALLENGE_ID = nconf.get('BEFORE_CHALLENGE_ID'); + +function processChallenges (afterId) { + let processedTasks = 0; + let lastChallenge = null; + let oldChallenges; + + let query = {}; + + if (BEFORE_CHALLENGE_ID) { + query._id = {$lte: BEFORE_CHALLENGE_ID}; + } + + if ((afterId || AFTER_CHALLENGE_ID) && !query._id) { + query._id = {}; + } + + if (afterId) { + query._id.$gt = afterId; + } else if (AFTER_CHALLENGE_ID) { + query._id.$gt = AFTER_CHALLENGE_ID; + } + + console.log(`Executing challenges query.\nMatching challenges after ${afterId ? afterId : AFTER_CHALLENGE_ID} and before ${BEFORE_CHALLENGE_ID} (included).`); + + return oldChallengeCollection + .find(query) + .sort({_id: 1}) + .limit(BATCH_SIZE) + .toArray() + .then(function (oldChallengesR) { + oldChallenges = oldChallengesR; + + let promises = []; + + console.log(`Processing ${oldChallenges.length} challenges. Already processed ${processedChallenges} challenges.`); + + if (oldChallenges.length === BATCH_SIZE) { + lastChallenge = oldChallenges[oldChallenges.length - 1]._id; + } + + oldChallenges.forEach(function (oldChallenge) { + // Tyler Renelle + oldChallenge.members.forEach(function (id, index) { + if (id === '9') { + oldChallenge.members[index] = '00000000-0000-4000-9000-000000000000'; + } + }); + + promises.push(newUserCollection.updateMany({ + _id: {$in: oldChallenge.members || []}, + }, { + $push: {challenges: oldChallenge._id}, + }, {multi: true})); + }); + + console.log(`Migrating members of ${oldChallenges.length} challenges.`); + + return Bluebird.all(promises); + }) + .then(function () { + processedChallenges += oldChallenges.length; + + console.log(`Migrated members of ${oldChallenges.length} challenges.`); + + if (lastChallenge) { + return processChallenges(lastChallenge); + } else { + return console.log('Done!'); + } + }); +} + +// Connect to the databases +Bluebird.all([ + MongoClient.connect(MONGODB_OLD), + MongoClient.connect(MONGODB_NEW), +]) + .then(function (result) { + let oldInstance = result[0]; + let newInstance = result[1]; + + mongoDbOldInstance = oldInstance; + oldChallengeCollection = mongoDbOldInstance.collection('challenges'); + + mongoDbNewInstance = newInstance; + newUserCollection = mongoDbNewInstance.collection('users'); + + console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); + + return processChallenges(); + }) + .catch(function (err) { + console.error(err.stack || err); + }); diff --git a/migrations/archive/api_v3/coupons.js b/migrations/archive/api_v3/coupons.js new file mode 100644 index 0000000000..22da730515 --- /dev/null +++ b/migrations/archive/api_v3/coupons.js @@ -0,0 +1,142 @@ +// Migrate coupons collection to new schema + +// The console-stamp module must be installed (not included in package.json) + +// It requires two environment variables: MONGODB_OLD and MONGODB_NEW + +// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). +// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM +console.log('Starting migrations/api_v3/coupons.js.'); + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +require('babel-register'); +require('babel-polyfill'); + +let Bluebird = require('bluebird'); +let MongoDB = require('mongodb'); +let nconf = require('nconf'); +let mongoose = require('mongoose'); +let _ = require('lodash'); +let uuid = require('uuid'); +let consoleStamp = require('console-stamp'); + +// Add timestamps to console messages +consoleStamp(console); + +// Initialize configuration +require('../../website/server/libs/api-v3/setupNconf')(); + +let MONGODB_OLD = nconf.get('MONGODB_OLD'); +let MONGODB_NEW = nconf.get('MONGODB_NEW'); + +let MongoClient = MongoDB.MongoClient; + +mongoose.Promise = Bluebird; // otherwise mongoose models won't work + +// Load new models +let Coupon = require('../../website/server/models/coupon').model; + +// To be defined later when MongoClient connects +let mongoDbOldInstance; +let oldCouponCollection; + +let mongoDbNewInstance; +let newCouponCollection; + +let BATCH_SIZE = 1000; + +let processedCoupons = 0; + +// Only process coupons that fall in a interval ie -> up to 0000-4000-0000-0000 +let AFTER_COUPON_ID = nconf.get('AFTER_COUPON_ID'); +let BEFORE_COUPON_ID = nconf.get('BEFORE_COUPON_ID'); + +function processCoupons (afterId) { + let processedTasks = 0; + let lastCoupon = null; + let oldCoupons; + + let query = {}; + + if (BEFORE_COUPON_ID) { + query._id = {$lte: BEFORE_COUPON_ID}; + } + + if ((afterId || AFTER_COUPON_ID) && !query._id) { + query._id = {}; + } + + if (afterId) { + query._id.$gt = afterId; + } else if (AFTER_COUPON_ID) { + query._id.$gt = AFTER_COUPON_ID; + } + + let batchInsertCoupons = newCouponCollection.initializeUnorderedBulkOp(); + + console.log(`Executing coupons query.\nMatching coupons after ${afterId ? afterId : AFTER_COUPON_ID} and before ${BEFORE_COUPON_ID} (included).`); + + return oldCouponCollection + .find(query) + .sort({_id: 1}) + .limit(BATCH_SIZE) + .toArray() + .then(function (oldCouponsR) { + oldCoupons = oldCouponsR; + + console.log(`Processing ${oldCoupons.length} coupons. Already processed ${processedCoupons} coupons.`); + + if (oldCoupons.length === BATCH_SIZE) { + lastCoupon = oldCoupons[oldCoupons.length - 1]._id; + } + + oldCoupons.forEach(function (oldCoupon) { + let newCoupon = new Coupon(oldCoupon); + + batchInsertCoupons.insert(newCoupon.toObject()); + }); + + console.log(`Saving ${oldCoupons.length} coupons.`); + + return batchInsertCoupons.execute(); + }) + .then(function () { + processedCoupons += oldCoupons.length; + + console.log(`Saved ${oldCoupons.length} coupons.`); + + if (lastCoupon) { + return processCoupons(lastCoupon); + } else { + return console.log('Done!'); + } + }); +} + +// Connect to the databases +Bluebird.all([ + MongoClient.connect(MONGODB_OLD), + MongoClient.connect(MONGODB_NEW), +]) + .then(function (result) { + let oldInstance = result[0]; + let newInstance = result[1]; + + mongoDbOldInstance = oldInstance; + oldCouponCollection = mongoDbOldInstance.collection('coupons'); + + mongoDbNewInstance = newInstance; + newCouponCollection = mongoDbNewInstance.collection('coupons'); + + console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); + + return processCoupons(); + }) + .catch(function (err) { + console.error(err.stack || err); + }); diff --git a/migrations/archive/api_v3/emailUnsubscriptions.js b/migrations/archive/api_v3/emailUnsubscriptions.js new file mode 100644 index 0000000000..21eae2a13c --- /dev/null +++ b/migrations/archive/api_v3/emailUnsubscriptions.js @@ -0,0 +1,143 @@ +// Migrate unsubscriptions collection to new schema + +// The console-stamp module must be installed (not included in package.json) + +// It requires two environment variables: MONGODB_OLD and MONGODB_NEW + +// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). +// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM +console.log('Starting migrations/api_v3/unsubscriptions.js.'); + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +require('babel-register'); +require('babel-polyfill'); + +let Bluebird = require('bluebird'); +let MongoDB = require('mongodb'); +let nconf = require('nconf'); +let mongoose = require('mongoose'); +let _ = require('lodash'); +let uuid = require('uuid'); +let consoleStamp = require('console-stamp'); + +// Add timestamps to console messages +consoleStamp(console); + +// Initialize configuration +require('../../website/server/libs/api-v3/setupNconf')(); + +let MONGODB_OLD = nconf.get('MONGODB_OLD'); +let MONGODB_NEW = nconf.get('MONGODB_NEW'); + +let MongoClient = MongoDB.MongoClient; + +mongoose.Promise = Bluebird; // otherwise mongoose models won't work + +// Load new models +let EmailUnsubscription = require('../../website/server/models/emailUnsubscription').model; + +// To be defined later when MongoClient connects +let mongoDbOldInstance; +let oldUnsubscriptionCollection; + +let mongoDbNewInstance; +let newUnsubscriptionCollection; + +let BATCH_SIZE = 1000; + +let processedUnsubscriptions = 0; + +// Only process unsubscriptions that fall in a interval ie -> up to 0000-4000-0000-0000 +let AFTER_UNSUBSCRIPTION_ID = nconf.get('AFTER_UNSUBSCRIPTION_ID'); +let BEFORE_UNSUBSCRIPTION_ID = nconf.get('BEFORE_UNSUBSCRIPTION_ID'); + +function processUnsubscriptions (afterId) { + let processedTasks = 0; + let lastUnsubscription = null; + let oldUnsubscriptions; + + let query = {}; + + if (BEFORE_UNSUBSCRIPTION_ID) { + query._id = {$lte: BEFORE_UNSUBSCRIPTION_ID}; + } + + if ((afterId || AFTER_UNSUBSCRIPTION_ID) && !query._id) { + query._id = {}; + } + + if (afterId) { + query._id.$gt = afterId; + } else if (AFTER_UNSUBSCRIPTION_ID) { + query._id.$gt = AFTER_UNSUBSCRIPTION_ID; + } + + let batchInsertUnsubscriptions = newUnsubscriptionCollection.initializeUnorderedBulkOp(); + + console.log(`Executing unsubscriptions query.\nMatching unsubscriptions after ${afterId ? afterId : AFTER_UNSUBSCRIPTION_ID} and before ${BEFORE_UNSUBSCRIPTION_ID} (included).`); + + return oldUnsubscriptionCollection + .find(query) + .sort({_id: 1}) + .limit(BATCH_SIZE) + .toArray() + .then(function (oldUnsubscriptionsR) { + oldUnsubscriptions = oldUnsubscriptionsR; + + console.log(`Processing ${oldUnsubscriptions.length} unsubscriptions. Already processed ${processedUnsubscriptions} unsubscriptions.`); + + if (oldUnsubscriptions.length === BATCH_SIZE) { + lastUnsubscription = oldUnsubscriptions[oldUnsubscriptions.length - 1]._id; + } + + oldUnsubscriptions.forEach(function (oldUnsubscription) { + oldUnsubscription.email = oldUnsubscription.email.toLowerCase(); + let newUnsubscription = new EmailUnsubscription(oldUnsubscription); + + batchInsertUnsubscriptions.insert(newUnsubscription.toObject()); + }); + + console.log(`Saving ${oldUnsubscriptions.length} unsubscriptions.`); + + return batchInsertUnsubscriptions.execute(); + }) + .then(function () { + processedUnsubscriptions += oldUnsubscriptions.length; + + console.log(`Saved ${oldUnsubscriptions.length} unsubscriptions.`); + + if (lastUnsubscription) { + return processUnsubscriptions(lastUnsubscription); + } else { + return console.log('Done!'); + } + }); +} + +// Connect to the databases +Bluebird.all([ + MongoClient.connect(MONGODB_OLD), + MongoClient.connect(MONGODB_NEW), +]) + .then(function (result) { + let oldInstance = result[0]; + let newInstance = result[1]; + + mongoDbOldInstance = oldInstance; + oldUnsubscriptionCollection = mongoDbOldInstance.collection('emailunsubscriptions'); + + mongoDbNewInstance = newInstance; + newUnsubscriptionCollection = mongoDbNewInstance.collection('emailunsubscriptions'); + + console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); + + return processUnsubscriptions(); + }) + .catch(function (err) { + console.error(err.stack || err); + }); diff --git a/migrations/archive/api_v3/groups.js b/migrations/archive/api_v3/groups.js new file mode 100644 index 0000000000..1d1d7e3b0c --- /dev/null +++ b/migrations/archive/api_v3/groups.js @@ -0,0 +1,217 @@ +/* + members are not stored anymore + invites are not stored anymore + + tavern id and leader must be updated +*/ + +// Migrate groups collection to new schema +// Run AFTER users migration + +// The console-stamp module must be installed (not included in package.json) + +// It requires two environment variables: MONGODB_OLD and MONGODB_NEW + +// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). +// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM +console.log('Starting migrations/api_v3/groups.js.'); + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +require('babel-register'); +require('babel-polyfill'); + +let Bluebird = require('bluebird'); +let MongoDB = require('mongodb'); +let nconf = require('nconf'); +let mongoose = require('mongoose'); +let _ = require('lodash'); +let uuid = require('uuid'); +let consoleStamp = require('console-stamp'); + +// Add timestamps to console messages +consoleStamp(console); + +// Initialize configuration +require('../../website/server/libs/api-v3/setupNconf')(); + +let MONGODB_OLD = nconf.get('MONGODB_OLD'); +let MONGODB_NEW = nconf.get('MONGODB_NEW'); + +let MongoClient = MongoDB.MongoClient; + +mongoose.Promise = Bluebird; // otherwise mongoose models won't work + +// Load new models +let NewGroup = require('../../website/server/models/group').model; + +let TAVERN_ID = require('../../website/server/models/group').TAVERN_ID; + +// To be defined later when MongoClient connects +let mongoDbOldInstance; +let oldGroupCollection; + +let mongoDbNewInstance; +let newGroupCollection; +let newUserCollection; + +let BATCH_SIZE = 1000; + +let processedGroups = 0; + +// Only process groups that fall in a interval ie -> up to 0000-4000-0000-0000 +let AFTER_GROUP_ID = nconf.get('AFTER_GROUP_ID'); +let BEFORE_GROUP_ID = nconf.get('BEFORE_GROUP_ID'); + +function processGroups (afterId) { + let processedTasks = 0; + let lastGroup = null; + let oldGroups; + + let query = {}; + + if (BEFORE_GROUP_ID) { + query._id = {$lte: BEFORE_GROUP_ID}; + } + + if ((afterId || AFTER_GROUP_ID) && !query._id) { + query._id = {}; + } + + if (afterId) { + query._id.$gt = afterId; + } else if (AFTER_GROUP_ID) { + query._id.$gt = AFTER_GROUP_ID; + } + + let batchInsertGroups = newGroupCollection.initializeUnorderedBulkOp(); + + console.log(`Executing groups query.\nMatching groups after ${afterId ? afterId : AFTER_GROUP_ID} and before ${BEFORE_GROUP_ID} (included).`); + + return oldGroupCollection + .find(query) + .sort({_id: 1}) + .limit(BATCH_SIZE) + .toArray() + .then(function (oldGroupsR) { + oldGroups = oldGroupsR; + + let promises = []; + + console.log(`Processing ${oldGroups.length} groups. Already processed ${processedGroups} groups.`); + + if (oldGroups.length === BATCH_SIZE) { + lastGroup = oldGroups[oldGroups.length - 1]._id; + } + + oldGroups.forEach(function (oldGroup) { + if ((!oldGroup.privacy || oldGroup.privacy === 'private') && (!oldGroup.members || oldGroup.members.length === 0)) return; // delete empty private groups TODO must also delete challenges or this won't work + + oldGroup.members = oldGroup.members || []; + oldGroup.memberCount = oldGroup.members ? oldGroup.members.length : 0; + oldGroup.challengeCount = oldGroup.challenges ? oldGroup.challenges.length : 0; + + if (oldGroup.balance <= 0) oldGroup.balance = 0; + if (!oldGroup.name) oldGroup.name = 'group name'; + if (!oldGroup.leaderOnly) oldGroup.leaderOnly = {}; + if (!oldGroup.leaderOnly.challenges) oldGroup.leaderOnly.challenges = false; + + // Tavern + if (oldGroup._id === 'habitrpg') { + oldGroup._id = TAVERN_ID; + oldGroup.leader = '7bde7864-ebc5-4ee2-a4b7-1070d464cdb0'; // Siena Leslie + } + + if (!oldGroup.type) { + // throw new Error('group.type is required'); + oldGroup.type = 'guild'; + } + + if (!oldGroup.leader) { + if (oldGroup.members && oldGroup.members.length > 0) { + oldGroup.leader = oldGroup.members[0]; + } else { + throw new Error('group.leader is required and no member available!'); + } + } + + if (!oldGroup.privacy) { + // throw new Error('group.privacy is required'); + oldGroup.privacy = 'private'; + } + + let updateMembers = {}; + + if (oldGroup.type === 'guild') { + updateMembers.$push = {guilds: oldGroup._id}; + } else if (oldGroup.type === 'party') { + updateMembers.$set = {'party._id': oldGroup._id}; + } + + if (oldGroup.members) { + // Tyler Renelle + oldGroup.members.forEach(function (id, index) { + if (id === '9') { + oldGroup.members[index] = '00000000-0000-4000-9000-000000000000'; + } + }); + + promises.push(newUserCollection.updateMany({ + _id: {$in: oldGroup.members}, + }, updateMembers, {multi: true})); + } + + let newGroup = new NewGroup(oldGroup); + + batchInsertGroups.insert(newGroup.toObject()); + }); + + console.log(`Saving ${oldGroups.length} groups and migrating members to users collection.`); + + promises.push(batchInsertGroups.execute()); + return Bluebird.all(promises); + }) + .then(function () { + processedGroups += oldGroups.length; + + console.log(`Saved ${oldGroups.length} groups and migrated their members to the user collection.`); + + if (lastGroup) { + return processGroups(lastGroup); + } else { + return console.log('Done!'); + } + }); +} + +// Connect to the databases +Bluebird.all([ + MongoClient.connect(MONGODB_OLD), + MongoClient.connect(MONGODB_NEW), +]) + .then(function (result) { + let oldInstance = result[0]; + let newInstance = result[1]; + + mongoDbOldInstance = oldInstance; + oldGroupCollection = mongoDbOldInstance.collection('groups'); + + mongoDbNewInstance = newInstance; + newGroupCollection = mongoDbNewInstance.collection('groups'); + newUserCollection = mongoDbNewInstance.collection('users'); + + console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); + + // First delete the tavern group created by having required the group model + return newGroupCollection.deleteOne({_id: TAVERN_ID}); + }) + .then(function () { + return processGroups(); + }) + .catch(function (err) { + console.error(err.stack || err); + }); diff --git a/migrations/api_v3/indexes.js b/migrations/archive/api_v3/indexes.js similarity index 100% rename from migrations/api_v3/indexes.js rename to migrations/archive/api_v3/indexes.js diff --git a/migrations/archive/api_v3/users.js b/migrations/archive/api_v3/users.js new file mode 100644 index 0000000000..1560c9d3dd --- /dev/null +++ b/migrations/archive/api_v3/users.js @@ -0,0 +1,268 @@ +// Migrate users collection to new schema +// This should run AFTER challenges migration + +// The console-stamp module must be installed (not included in package.json) + +// It requires two environment variables: MONGODB_OLD and MONGODB_NEW + +// Due to some big user profiles it needs more RAM than is allowed by default by v8 (arounf 1.7GB). +// Run the script with --max-old-space-size=4096 to allow up to 4GB of RAM +console.log('Starting migrations/api_v3/users.js.'); + +// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash. +// We've now upgraded to lodash v4 but the code used in this migration has not been +// adapted to work with it. Before this migration is used again any lodash method should +// be checked for compatibility against the v4 changelog and changed if necessary. +// https://github.com/lodash/lodash/wiki/Changelog#v400 + +require('babel-register'); +require('babel-polyfill'); + +let Bluebird = require('bluebird'); +let MongoDB = require('mongodb'); +let nconf = require('nconf'); +let mongoose = require('mongoose'); +let _ = require('lodash'); +let uuid = require('uuid'); +let consoleStamp = require('console-stamp'); +let common = require('../../common'); +let moment = require('moment'); + +// Add timestamps to console messages +consoleStamp(console); + +// Initialize configuration +require('../../website/server/libs/api-v3/setupNconf')(); + +let MONGODB_OLD = nconf.get('MONGODB_OLD'); +let MONGODB_NEW = nconf.get('MONGODB_NEW'); + +let taskDefaults = common.taskDefaults; +let MongoClient = MongoDB.MongoClient; + +mongoose.Promise = Bluebird; // otherwise mongoose models won't work + +// Load new models +let NewUser = require('../../website/server/models/user').model; +let NewTasks = require('../../website/server/models/task'); + +// To be defined later when MongoClient connects +let mongoDbOldInstance; +let oldUserCollection; + +let mongoDbNewInstance; +let newUserCollection; +let newTaskCollection; + +let BATCH_SIZE = 1000; + +let processedUsers = 0; +let totoalProcessedTasks = 0; + +let challengeTaskWithMatchingId = 0; +let challengeTaskNoMatchingId = 0; + +// Load the new tasks ids for challenges tasks +let newTasksIds = require('./newTasksIds.json'); + +// Only process users that fall in a interval ie up to -> 0000-4000-0000-0000 +let AFTER_USER_ID = nconf.get('AFTER_USER_ID'); +let BEFORE_USER_ID = nconf.get('BEFORE_USER_ID'); + +function processUsers (afterId) { + let processedTasks = 0; + let lastUser = null; + let oldUsers; + + let now = new Date(); + + let query = {}; + + if (BEFORE_USER_ID) { + query._id = {$lte: BEFORE_USER_ID}; + } + + if ((afterId || AFTER_USER_ID) && !query._id) { + query._id = {}; + } + + if (afterId) { + query._id.$gt = afterId; + } else if (AFTER_USER_ID) { + query._id.$gt = AFTER_USER_ID; + } + + let batchInsertTasks = newTaskCollection.initializeUnorderedBulkOp(); + let batchInsertUsers = newUserCollection.initializeUnorderedBulkOp(); + + console.log(`Executing users query.\nMatching users after ${afterId ? afterId : AFTER_USER_ID} and before ${BEFORE_USER_ID} (included).`); + + return oldUserCollection + .find(query) + .sort({_id: 1}) + .limit(BATCH_SIZE) + .toArray() + .then(function (oldUsersR) { + oldUsers = oldUsersR; + + console.log(`Processing ${oldUsers.length} users. Already processed ${processedUsers} users and ${totoalProcessedTasks} tasks.`); + + if (oldUsers.length === BATCH_SIZE) { + lastUser = oldUsers[oldUsers.length - 1]._id; + } + + oldUsers.forEach(function (oldUser) { + let oldTasks = oldUser.habits.concat(oldUser.dailys).concat(oldUser.rewards).concat(oldUser.todos); + delete oldUser.habits; + delete oldUser.dailys; + delete oldUser.rewards; + delete oldUser.todos; + + delete oldUser.id; + + // spookDust -> spookySparkles + + if (oldUser.achievements && oldUser.achievements.spookDust) { + oldUser.achievements.spookySparkles = oldUser.achievements.spookDust; + delete oldUser.achievements.spookDust; + } + + if (oldUser.items && oldUser.items.special && oldUser.items.special.spookDust) { + oldUser.items.special.spookySparkles = oldUser.items.special.spookDust; + delete oldUser.items.special.spookDust; + } + + if (oldUser.stats && oldUser.stats.buffs && oldUser.stats.buffs.spookySparkles) { + oldUser.stats.buffs.spookySparkles = oldUser.stats.buffs.spookDust; + delete oldUser.stats.buffs.spookDust; + } + + // end spookDust -> spookySparkles + + oldUser.tags = oldUser.tags.map(function (tag) { + return { + id: tag.id, + name: tag.name || 'tag name', + challenge: tag.challenge, + }; + }); + + if (oldUser._id === '9') { // Tyler Renelle + oldUser._id = '00000000-0000-4000-9000-000000000000'; + } + + let newUser = new NewUser(oldUser); + let isSubscribed = newUser.isSubscribed(); + + oldTasks.forEach(function (oldTask) { + oldTask._id = uuid.v4(); // create a new unique uuid + oldTask.userId = newUser._id; + oldTask._legacyId = oldTask.id; // store the old task id + delete oldTask.id; + + oldTask.challenge = oldTask.challenge || {}; + if (oldTask.challenge.id) { + if (oldTask.challenge.broken) { + oldTask.challenge.taskId = oldTask._legacyId; + } else { + let newId = newTasksIds[`${oldTask._legacyId }-${ oldTask.challenge.id}`]; + + // Challenges' tasks ids changed + if (!newId && !oldTask.challenge.broken) { + challengeTaskNoMatchingId++; + oldTask.challenge.taskId = oldTask._legacyId; + oldTask.challenge.broken = 'CHALLENGE_TASK_NOT_FOUND'; + } else { + challengeTaskWithMatchingId++; + oldTask.challenge.taskId = newId; + } + } + } + + // Delete old completed todos + if (oldTask.type === 'todo' && oldTask.completed && (!oldTask.challenge.id || oldTask.challenge.broken)) { + if (moment(now).subtract(isSubscribed ? 90 : 30, 'days').toDate() > moment(oldTask.dateCompleted).toDate()) { + return; + } + } + + oldTask.createdAt = oldTask.dateCreated; + + if (!oldTask.text) oldTask.text = 'task text'; // required + oldTask.tags = _.map(oldTask.tags, function (tagPresent, tagId) { + return tagPresent && tagId; + }).filter(function (tag) { + return tag !== false; + }); + + if (oldTask.type !== 'todo' || oldTask.type === 'todo' && !oldTask.completed) { + newUser.tasksOrder[`${oldTask.type}s`].push(oldTask._id); + } + + let allTasksFields = ['_id', 'type', 'text', 'notes', 'tags', 'value', 'priority', 'attribute', 'challenge', 'reminders', 'userId', '_legacyId', 'createdAt']; + // using mongoose models is too slow + if (oldTask.type === 'habit') { + oldTask = _.pick(oldTask, allTasksFields.concat(['history', 'up', 'down'])); + } else if (oldTask.type === 'daily') { + oldTask = _.pick(oldTask, allTasksFields.concat(['completed', 'collapseChecklist', 'checklist', 'history', 'frequency', 'everyX', 'startDate', 'repeat', 'streak'])); + } else if (oldTask.type === 'todo') { + oldTask = _.pick(oldTask, allTasksFields.concat(['completed', 'collapseChecklist', 'checklist', 'date', 'dateCompleted'])); + } else if (oldTask.type === 'reward') { + oldTask = _.pick(oldTask, allTasksFields); + } else { + throw new Error('Task with no or invalid type!'); + } + + batchInsertTasks.insert(taskDefaults(oldTask)); + processedTasks++; + }); + + batchInsertUsers.insert(newUser.toObject()); + }); + + console.log(`Saving ${oldUsers.length} users and ${processedTasks} tasks.`); + + return Bluebird.all([ + batchInsertUsers.execute(), + batchInsertTasks.execute(), + ]); + }) + .then(function () { + totoalProcessedTasks += processedTasks; + processedUsers += oldUsers.length; + + console.log(`Saved ${oldUsers.length} users and their tasks.`); + console.log('Challenges\' tasks no matching id: ', challengeTaskNoMatchingId); + console.log('Challenges\' tasks with matching id: ', challengeTaskWithMatchingId); + + if (lastUser) { + return processUsers(lastUser); + } else { + return console.log('Done!'); + } + }); +} + +// Connect to the databases +Bluebird.all([ + MongoClient.connect(MONGODB_OLD), + MongoClient.connect(MONGODB_NEW), +]) + .then(function (result) { + let oldInstance = result[0]; + let newInstance = result[1]; + + mongoDbOldInstance = oldInstance; + oldUserCollection = mongoDbOldInstance.collection('users'); + + mongoDbNewInstance = newInstance; + newUserCollection = mongoDbNewInstance.collection('users'); + newTaskCollection = mongoDbNewInstance.collection('tasks'); + + console.log(`Connected with MongoClient to ${MONGODB_OLD} and ${MONGODB_NEW}.`); + + return processUsers(); + }) + .catch(function (err) { + console.error(err.stack || err); + }); diff --git a/migrations/manual_password_reset.js b/migrations/archive/manual_password_reset.js similarity index 54% rename from migrations/manual_password_reset.js rename to migrations/archive/manual_password_reset.js index 6e84673eaa..94262a17ec 100644 --- a/migrations/manual_password_reset.js +++ b/migrations/archive/manual_password_reset.js @@ -4,11 +4,11 @@ // IMPORTANT: this script isn't updated to use the new password encryption that uses bcrypt // using it will break accounts and should not be used until upgraded -var nconf = require('nconf'), +let nconf = require('nconf'), path = require('path'); nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../config.json'))); -var Users = require('mongoskin').db(nconf.get("PRODUCTION_DB:URL"), nconf.get("PRODUCTION_DB").CREDS).collection('users'), +let Users = require('mongoskin').db(nconf.get('PRODUCTION_DB:URL'), nconf.get('PRODUCTION_DB').CREDS).collection('users'), async = require('async'), utils = require('../website/server/utils'), salt = utils.makeSalt(), @@ -16,23 +16,23 @@ var Users = require('mongoskin').db(nconf.get("PRODUCTION_DB:URL"), nconf.get("P hashed_password = utils.encryptPassword(newPassword, salt); async.waterfall([ - function(cb){ - Users.findItems({'auth.local.email':nconf.get("EMAIL")}, {auth:1}, cb); + function (cb) { + Users.findItems({'auth.local.email': nconf.get('EMAIL')}, {auth: 1}, cb); }, - function(users, cb){ - if (users.length<1) return cb("User not found for that email"); - if (users.length>1) return cb("Multiple users for that email"); - var user = users[0]; - console.dir({username:user.auth.local.username, password: newPassword}); - Users.update({_id:user._id}, { - $set:{ + function (users, cb) { + if (users.length < 1) return cb('User not found for that email'); + if (users.length > 1) return cb('Multiple users for that email'); + let user = users[0]; + console.dir({username: user.auth.local.username, password: newPassword}); + Users.update({_id: user._id}, { + $set: { 'auth.local.salt': salt, 'auth.local.hashed_password': hashed_password, - 'preferences.sleep': true - } - }, cb) - } -], function(err){ + 'preferences.sleep': true, + }, + }, cb); + }, +], function (err) { if (err) console.log(err); - process.exit() + process.exit(); }); \ No newline at end of file diff --git a/migrations/archive/metrics.js b/migrations/archive/metrics.js new file mode 100644 index 0000000000..866c0bfc3a --- /dev/null +++ b/migrations/archive/metrics.js @@ -0,0 +1,85 @@ +// node habitrpg ./migrations/metrics.js + +let EXPORT_EMAILS = true; +let mongo = require('mongoskin'); +let csv = require('csv'); +let _ = require('lodash'); +let moment = require('moment'); +let db = mongo.db('localhost:27017/habitrpg?auto_reconnect'); +let twoWeeksAgo = moment().subtract(14, 'days'); +let angularRewrite = moment('07/09/2013'); + +let query = {auth: {$exists: 1}}; +let fields = {lastCron: 1, 'history.exp': 1, 'auth.timestamps': 1, 'auth.local.email': 1}; +db.collection('users').find(query, fields).toArray(function (err, items) { + if (err) return console.error({err}); + let stats = {total: _.size(items), lostToDerby: 0, isActive: 0}; + let emails = []; + _.each(items, function (item) { + // if (!item.history || !item.history.exp) console.log(item._id) + + // var hasBeenActive = item.history && item.history.exp && item.history.exp.length > 7; + let hasBeenActive = item.auth.timestamps && item.auth.timestamps.created && + Math.abs(moment(item.lastCron).diff(item.auth.timestamps.created, 'd')) > 14; + + if (/* hasBeenActive && */moment(item.lastCron).isBefore(angularRewrite)) { + stats.lostToDerby++; + if (item.auth.local) + emails.push([item.auth.local.email]); + // Facebook emails. Kinda dirty, and there's only ~30 available fb emails anyway. + // } else if (item.auth.facebook && item.auth.facebook.email) { + // emails.push([item.auth.facebook.email]) + // } else if (item.auth.facebook && item.auth.facebook.emails && item.auth.facebook.emails[0] && !!item.auth.facebook.emails[0].value) { + // emails.push([item.auth.facebook.emails[0].value]) + } + if (hasBeenActive && moment(item.lastCron).isAfter(twoWeeksAgo)) { + stats.isActive++; + } + }); + stats.emails = _.size(emails); + console.log(stats); + + if (EXPORT_EMAILS) + csv().from.array(emails).to.path(`${__dirname}/emails.csv`); +}); + +/* +load('./node_modules/moment/moment.js'); +var today = +new Date, + twoWeeksAgo = +moment().subtract(14, 'days'); + + corrupt = { + $or: [ + {lastCron: {$exists:false}}, + {lastCron: 'new'} + ] + } + + un_registered = { + "auth.local": {$exists: false}, + "auth.facebook": {$exists: false} + }, + + registered = { + $or: [ + { 'auth.local': { $exists: true }}, + { 'auth.facebook': { $exists: true }} + ] + }, + + active = { + $or: [ + { 'auth.local': { $exists: true }}, + { 'auth.facebook': { $exists: true }} + ], + $where: function(){ + return this.history && this.history.exp && this.history.exp.length > 7; + }, + 'lastCron': {$gt: twoWeeksAgo} + }; + +print('corrupt: ' + db.users.count(corrupt)); +print('unregistered: ' + db.users.count(un_registered)); +print('registered: ' + db.users.count(registered)); +print('active: ' + db.users.count(active)); +*/ \ No newline at end of file diff --git a/migrations/challenges/sync-all-challenges.js b/migrations/challenges/sync-all-challenges.js index 4cb9d00088..3be7a74bb0 100644 --- a/migrations/challenges/sync-all-challenges.js +++ b/migrations/challenges/sync-all-challenges.js @@ -4,14 +4,14 @@ import { model as Challenges } from '../../website/server/models/challenge'; import { model as User } from '../../website/server/models/user'; async function syncChallengeToMembers (challenges) { - let challengSyncPromises = challenges.map(async function (challenge) { + let challengSyncPromises = challenges.map(async (challenge) => { let users = await User.find({ // _id: '', challenges: challenge._id, }).exec(); let promises = []; - users.forEach(function (user) { + users.forEach((user) => { promises.push(challenge.syncToUser(user)); promises.push(challenge.save()); promises.push(user.save()); @@ -42,6 +42,6 @@ async function syncChallenges (lastChallengeDate) { let lastChallenge = challengesFound[challengesFound.length - 1]; if (lastChallenge) syncChallenges(lastChallenge.createdAt); return syncedChallenges; -}; +} module.exports = syncChallenges; diff --git a/migrations/command-line/.eslintrc b/migrations/command-line/.eslintrc new file mode 100644 index 0000000000..49551e8040 --- /dev/null +++ b/migrations/command-line/.eslintrc @@ -0,0 +1,10 @@ +{ + "root": false, + "globals": { + "db": true, + "moment": true, + "print": true, + "printjson": true, + "_": true, + }, +} diff --git a/migrations/command-line/apology_gems.js b/migrations/command-line/apology_gems.js new file mode 100644 index 0000000000..347a63d141 --- /dev/null +++ b/migrations/command-line/apology_gems.js @@ -0,0 +1 @@ +db.users.update({_id: {$in: ['']}}, {$inc: {balance: 0.5}}, {multi: true}); \ No newline at end of file diff --git a/migrations/cancelSubscription.js b/migrations/command-line/cancelSubscription.js similarity index 77% rename from migrations/cancelSubscription.js rename to migrations/command-line/cancelSubscription.js index 38a5fe318d..f823bed40f 100644 --- a/migrations/cancelSubscription.js +++ b/migrations/command-line/cancelSubscription.js @@ -4,8 +4,8 @@ // the FAQ (http://goo.gl/1uoPGQ) they insist... db.users.update( - {_id:''}, + {_id: ''}, {$set: { - 'purchased.plan.dateTerminated': moment().add('month',1).toDate() + 'purchased.plan.dateTerminated': moment().add('month', 1).toDate(), }} ); \ No newline at end of file diff --git a/migrations/command-line/contribs_plan.js b/migrations/command-line/contribs_plan.js new file mode 100644 index 0000000000..548ff6f18f --- /dev/null +++ b/migrations/command-line/contribs_plan.js @@ -0,0 +1,23 @@ +// Give contrib.level 7+ free subscription for life +db.users.update( + + { + 'contributor.level': {$gte: 7}, + 'purchased.plan.customerId': null, + }, + + { + $set: { + 'purchased.plan': { + planId: 'basic', + customerId: 'habitrpg', + dateCreated: new Date(), + dateUpdated: new Date(), + gemsBought: 0, + }, + }, + }, + + {multi: true} + +); \ No newline at end of file diff --git a/migrations/current_period_end.js b/migrations/command-line/current_period_end.js similarity index 52% rename from migrations/current_period_end.js rename to migrations/command-line/current_period_end.js index 31e33e4a79..56c9e8b45d 100644 --- a/migrations/current_period_end.js +++ b/migrations/command-line/current_period_end.js @@ -1,5 +1,5 @@ // mongo habitrpg ./node_modules/moment/moment.js ./migrations/current_period_end.js db.users.update( - {_id:''}, - {$set:{'purchased.plan.dateTerminated':moment().add({days:7}).toDate()}} -) \ No newline at end of file + {_id: ''}, + {$set: {'purchased.plan.dateTerminated': moment().add({days: 7}).toDate()}} +); \ No newline at end of file diff --git a/migrations/duplicatedTasksFindAndRemove.js b/migrations/command-line/duplicatedTasksFindAndRemove.js similarity index 75% rename from migrations/duplicatedTasksFindAndRemove.js rename to migrations/command-line/duplicatedTasksFindAndRemove.js index a6288efc4a..2dcdb10e5c 100644 --- a/migrations/duplicatedTasksFindAndRemove.js +++ b/migrations/command-line/duplicatedTasksFindAndRemove.js @@ -39,51 +39,49 @@ // needed. Do not miss any of them! -var uuid='30fb2640-7121-4968-ace5-f385e60ea6c5'; +let uuid = '30fb2640-7121-4968-ace5-f385e60ea6c5'; db.users.aggregate([ {$match: { - '_id': uuid + _id: uuid, }}, {$project: { - '_id':0, 'todos':1 + _id: 0, todos: 1, }}, {$unwind: '$todos'}, {$group: { _id: { taskid: '$todos.id' }, - count: { $sum: 1 } + count: { $sum: 1 }, }}, {$match: { - count: { $gt: 1 } + count: { $gt: 1 }, }}, {$project: { - '_id.taskid':1, + '_id.taskid': 1, }}, {$group: { _id: { taskid: '$todos.id' }, - troublesomeIds: { $addToSet: "$_id.taskid" }, + troublesomeIds: { $addToSet: '$_id.taskid' }, }}, {$project: { - '_id':0, - troublesomeIds:1, + _id: 0, + troublesomeIds: 1, }}, -]).forEach( - function(data) { - // print( "\n" ); printjson(data); - data.troublesomeIds.forEach( function(taskid) { - print('non-unique task: ' + taskid); - db.users.update({ - '_id': uuid, - 'todos': { $elemMatch: { id: taskid } } - },{ - $set: { "todos.$.id" : 'de666' } - }); +]).forEach((data) => { + // print( "\n" ); printjson(data); + data.troublesomeIds.forEach((taskid) => { + print(`non-unique task: ${ taskid}`); + db.users.update({ + _id: uuid, + todos: { $elemMatch: { id: taskid } }, + }, { + $set: { 'todos.$.id': 'de666' }, }); - } -); + }); +}); db.users.update( - {'_id': uuid}, + {_id: uuid}, {$pull: { todos: { id: 'de666' } } }, {multi: false } ); diff --git a/migrations/facebook_to_local.js b/migrations/command-line/facebook_to_local.js similarity index 51% rename from migrations/facebook_to_local.js rename to migrations/command-line/facebook_to_local.js index 0aca5573b1..de707c4f05 100644 --- a/migrations/facebook_to_local.js +++ b/migrations/command-line/facebook_to_local.js @@ -1,10 +1,10 @@ -var oldId = "", - newId = "", - newUser = db.users.findOne({_id: newId}) +let oldId = ''; +let newId = ''; +let newUser = db.users.findOne({_id: newId}); -db.users.update({_id: oldId}, {$set:{auth: newUser.auth}}); +db.users.update({_id: oldId}, {$set: {auth: newUser.auth}}); // remove the auth on the new user (which is a template account). The account will be preened automatically later, // this allows us to keep the account around a few days in case there was a mistake -db.users.update({_id: newId}, {$unset:{auth:1}}); +db.users.update({_id: newId}, {$unset: {auth: 1}}); diff --git a/migrations/find_unique_user.js b/migrations/command-line/find_unique_user.js similarity index 74% rename from migrations/find_unique_user.js rename to migrations/command-line/find_unique_user.js index 014933ac1f..378c6c8708 100644 --- a/migrations/find_unique_user.js +++ b/migrations/command-line/find_unique_user.js @@ -5,8 +5,8 @@ * Past in the text of a unique habit here to find the user, then you can restore their UUID */ -db.users.find().forEach(function(user){ +db.users.find().forEach((user) => { user.tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards); - var found = _.some(user.tasks, {text: ""}) - if (found) printjson({id:user._id, auth:user.auth}); -}) \ No newline at end of file + let found = _.some(user.tasks, {text: ''}); + if (found) printjson({id: user._id, auth: user.auth}); +}); \ No newline at end of file diff --git a/migrations/freeMonth.js b/migrations/command-line/freeMonth.js similarity index 65% rename from migrations/freeMonth.js rename to migrations/command-line/freeMonth.js index cd2c501149..2b9b19cccd 100644 --- a/migrations/freeMonth.js +++ b/migrations/command-line/freeMonth.js @@ -1,16 +1,16 @@ // mongo habitrpg ./node_modules/moment/moment.js ./migrations/freeMonth.js db.users.update( - {_id:''}, - {$set:{ - 'purchased.plan.customerId':'temporary', - 'purchased.plan.paymentMethod':'Stripe', - 'purchased.plan.planId':'basic_earned', - 'purchased.plan.dateTerminated': moment().add('month',1).toDate() + {_id: ''}, + {$set: { + 'purchased.plan.customerId': 'temporary', + 'purchased.plan.paymentMethod': 'Stripe', + 'purchased.plan.planId': 'basic_earned', + 'purchased.plan.dateTerminated': moment().add('month', 1).toDate(), }} -) -//var m = 12; -//db.users.update( +); +// var m = 12; +// db.users.update( // {_id:''}, // {$set:{'purchased.plan':{ // planId: 'basic_'+m+'mo', @@ -29,4 +29,4 @@ db.users.update( // trinkets: m/3 // } // }}} -//) \ No newline at end of file +// ) \ No newline at end of file diff --git a/migrations/command-line/habitica_day.js b/migrations/command-line/habitica_day.js new file mode 100644 index 0000000000..9e4fd3af5b --- /dev/null +++ b/migrations/command-line/habitica_day.js @@ -0,0 +1,5 @@ +db.users.update( + {}, + {$inc: {'achievements.habiticaDays': 1}}, + {multi: 1} +); diff --git a/migrations/command-line/missing_gems.js b/migrations/command-line/missing_gems.js new file mode 100644 index 0000000000..080bfbd687 --- /dev/null +++ b/migrations/command-line/missing_gems.js @@ -0,0 +1 @@ +db.users.update({_id: ''}, {$inc: {balance: 5}}); \ No newline at end of file diff --git a/migrations/mystery_items.js b/migrations/command-line/mystery_items.js similarity index 51% rename from migrations/mystery_items.js rename to migrations/command-line/mystery_items.js index 28da1c7ed6..25d8b815af 100644 --- a/migrations/mystery_items.js +++ b/migrations/command-line/mystery_items.js @@ -1,26 +1,26 @@ -var UserNotification = require('../website/server/models/userNotification').model +let UserNotification = require('../../website/server/models/userNotification').model; -var _id = ''; +let _id = ''; -var items = ['back_mystery_201801','headAccessory_mystery_201801'] +let items = ['back_mystery_201801', 'headAccessory_mystery_201801']; -var update = { +let update = { $addToSet: { - 'purchased.plan.mysteryItems':{ + 'purchased.plan.mysteryItems': { $each: items, - } + }, }, $push: { notifications: (new UserNotification({ type: 'NEW_MYSTERY_ITEMS', data: { - items: items, + items, }, })).toJSON(), }, }; -/*var update = { +/* var update = { $set:{ 'purchased.plan':{ customerId: "", @@ -37,15 +37,15 @@ var update = { if (_id) { // singular (missing items) - db.users.update({_id: _id}, update); + db.users.update({_id}, update); } else { // multiple (once @ start of event) db.users.update({ - 'purchased.plan.customerId': { $ne: null }, - $or: [ - { 'purchased.plan.dateTerminated': { $gte: new Date() } }, - { 'purchased.plan.dateTerminated': { $exists: false } }, - { 'purchased.plan.dateTerminated': { $eq: null } } - ] + 'purchased.plan.customerId': { $ne: null }, + $or: [ + { 'purchased.plan.dateTerminated': { $gte: new Date() } }, + { 'purchased.plan.dateTerminated': { $exists: false } }, + { 'purchased.plan.dateTerminated': { $eq: null } }, + ], }, update, { multi: true }); } diff --git a/migrations/contribs_plan.js b/migrations/contribs_plan.js deleted file mode 100644 index a08bd93f76..0000000000 --- a/migrations/contribs_plan.js +++ /dev/null @@ -1,23 +0,0 @@ -// Give contrib.level 7+ free subscription for life -db.users.update( - - { - 'contributor.level':{$gte:7}, - 'purchased.plan.customerId':null - }, - - { - $set: { - 'purchased.plan':{ - planId: 'basic', - customerId: 'habitrpg', - dateCreated: new Date, - dateUpdated: new Date, - gemsBought: 0 - } - } - }, - - {multi:true} - -) \ No newline at end of file diff --git a/migrations/groups/add-unlimited-subscription.js b/migrations/groups/add-unlimited-subscription.js index 4a7eb27a02..43fbe55b5d 100644 --- a/migrations/groups/add-unlimited-subscription.js +++ b/migrations/groups/add-unlimited-subscription.js @@ -1,6 +1,8 @@ -var migrationName = 'AddUnlimitedSubscription'; -var authorName = 'TheHollidayInn'; // in case script author needs to know when their ... -var authorUuid = ''; //... own data is done +/* +let migrationName = 'AddUnlimitedSubscription'; +let authorName = 'TheHollidayInn'; // in case script author needs to know when their ... +let authorUuid = ''; // ... own data is done +*/ /* * This migrations will add a free subscription to a specified group @@ -11,30 +13,30 @@ import { model as Group } from '../../website/server/models/group'; // @TODO: this should probably be a GroupManager library method async function addUnlimitedSubscription (groupId, dateTerminated) { - let group = await Group.findById(groupId); + let group = await Group.findOne({_id: groupId}); - group.purchased.plan.customerId = "group-unlimited"; - group.purchased.plan.dateCreated = new Date(); - group.purchased.plan.dateUpdated = new Date(); - group.purchased.plan.paymentMethod = "Group Unlimited"; - group.purchased.plan.planId = "group_monthly"; - group.purchased.plan.dateTerminated = null; - if (dateTerminated) { - let dateToEnd = moment(dateTerminated).toDate(); - group.purchased.plan.dateTerminated = dateToEnd; - } - // group.purchased.plan.owner = ObjectId(); - group.purchased.plan.subscriptionId = ""; + group.purchased.plan.customerId = 'group-unlimited'; + group.purchased.plan.dateCreated = new Date(); + group.purchased.plan.dateUpdated = new Date(); + group.purchased.plan.paymentMethod = 'Group Unlimited'; + group.purchased.plan.planId = 'group_monthly'; + group.purchased.plan.dateTerminated = null; + if (dateTerminated) { + let dateToEnd = moment(dateTerminated).toDate(); + group.purchased.plan.dateTerminated = dateToEnd; + } + // group.purchased.plan.owner = ObjectId(); + group.purchased.plan.subscriptionId = ''; - return group.save(); -}; + return group.save(); +} module.exports = async function addUnlimitedSubscriptionCreator () { - let groupId = process.argv[2]; + let groupId = process.argv[2]; - if (!groupId) throw Error('Group ID is required'); + if (!groupId) throw Error('Group ID is required'); - let dateTerminated = process.argv[3]; + let dateTerminated = process.argv[3]; - let result = await addUnlimitedSubscription(groupId, dateTerminated); + await addUnlimitedSubscription(groupId, dateTerminated); }; diff --git a/migrations/groups/create-group.js b/migrations/groups/create-group.js index 79a4c03e63..d1cedcc4fc 100644 --- a/migrations/groups/create-group.js +++ b/migrations/groups/create-group.js @@ -5,28 +5,27 @@ import { model as User } from '../../website/server/models/user'; // @TODO: this should probably be a GroupManager library method async function createGroup (name, privacy, type, leaderId) { - let user = await User.findById(leaderId); - - let group = new Group({ - name, - privacy, - type, - }); + let user = await User.findOne({_id: leaderId}); - group.leader = user._id; - user.guilds.push(group._id); + let group = new Group({ + name, + privacy, + type, + }); - return Bluebird.all([group.save(), user.save()]); -}; + group.leader = user._id; + user.guilds.push(group._id); + + return Bluebird.all([group.save(), user.save()]); +} module.exports = async function groupCreator () { - let name = process.argv[2]; - let privacy = process.argv[3]; - let type = process.argv[4]; - let leaderId = process.argv[5]; + let name = process.argv[2]; + let privacy = process.argv[3]; + let type = process.argv[4]; + let leaderId = process.argv[5]; - let result = await createGroup(name, privacy, type, leaderId) + await createGroup(name, privacy, type, leaderId); }; - diff --git a/migrations/groups/habitrpg-jackalopes.js b/migrations/groups/habitrpg-jackalopes.js index de7df3eb49..50c6da4673 100644 --- a/migrations/groups/habitrpg-jackalopes.js +++ b/migrations/groups/habitrpg-jackalopes.js @@ -1,4 +1,4 @@ -var migrationName = 'Jackalopes for Unlimited Subscribers'; +/* let migrationName = 'Jackalopes for Unlimited Subscribers'; */ /* * This migration will find users with unlimited subscriptions who are also eligible for Jackalope mounts, and award them @@ -7,16 +7,15 @@ import Bluebird from 'bluebird'; import { model as Group } from '../../website/server/models/group'; import { model as User } from '../../website/server/models/user'; -import * as payments from '../../website/server/libs/payments'; async function handOutJackalopes () { let promises = []; let cursor = User.find({ - 'purchased.plan.customerId':'habitrpg', + 'purchased.plan.customerId': 'habitrpg', }).cursor(); - cursor.on('data', async function(user) { - console.log('User: ' + user._id); + cursor.on('data', async (user) => { + console.log(`User: ${ user._id}`); let groupList = []; if (user.party._id) groupList.push(user.party._id); @@ -24,23 +23,23 @@ async function handOutJackalopes () { let subscribedGroup = await Group.findOne({ - '_id': {$in: groupList}, + _id: {$in: groupList}, 'purchased.plan.planId': 'group_monthly', 'purchased.plan.dateTerminated': null, }, - {'_id':1} - ); + {_id: 1} + ); if (subscribedGroup) { - User.update({'_id':user._id},{$set:{'items.mounts.Jackalope-RoyalPurple':true}}).exec(); + User.update({_id: user._id}, {$set: {'items.mounts.Jackalope-RoyalPurple': true}}).exec(); promises.push(user.save()); } }); - cursor.on('close', async function() { + cursor.on('close', async () => { console.log('done'); return await Bluebird.all(promises); }); -}; +} module.exports = handOutJackalopes; diff --git a/migrations/groups/update-groups-with-group-plans.js b/migrations/groups/update-groups-with-group-plans.js index f217d54031..921c9bbb99 100644 --- a/migrations/groups/update-groups-with-group-plans.js +++ b/migrations/groups/update-groups-with-group-plans.js @@ -1,6 +1,8 @@ -var migrationName = 'ResyncGroupPlanMembers'; -var authorName = 'TheHollidayInn'; // in case script author needs to know when their ... -var authorUuid = ''; //... own data is done +/* +let migrationName = 'ResyncGroupPlanMembers'; +let authorName = 'TheHollidayInn'; // in case script author needs to know when their ... +let authorUuid = ''; // ... own data is done +*/ /* * This migrations will iterate through all groups with a group plan a subscription and resync the free @@ -20,14 +22,14 @@ async function updateGroupsWithGroupPlans () { let promises = []; - cursor.on('data', function(group) { + cursor.on('data', (group) => { promises.push(payments.addSubscriptionToGroupUsers(group)); - promises.push(group.save()) + promises.push(group.save()); }); - cursor.on('close', async function() { + cursor.on('close', async () => { return await Bluebird.all(promises); }); -}; +} module.exports = updateGroupsWithGroupPlans; diff --git a/migrations/habitica_day.js b/migrations/habitica_day.js deleted file mode 100644 index 6e352f6f06..0000000000 --- a/migrations/habitica_day.js +++ /dev/null @@ -1,5 +0,0 @@ -db.users.update( - {}, - {$inc:{'achievements.habiticaDays':1}}, - {multi:1} -); diff --git a/migrations/metrics.js b/migrations/metrics.js deleted file mode 100644 index 523aab9113..0000000000 --- a/migrations/metrics.js +++ /dev/null @@ -1,86 +0,0 @@ -// node habitrpg ./migrations/metrics.js - -var EXPORT_EMAILS = true; -var mongo = require('mongoskin'); -var csv = require('csv'); -var _ = require('lodash'); -var moment = require('moment'); -var db = mongo.db('localhost:27017/habitrpg?auto_reconnect'); -var twoWeeksAgo = moment().subtract(14, 'days'); -var angularRewrite = moment('07/09/2013'); - -var query = {auth: {'$exists':1}}; -var fields = {lastCron:1, 'history.exp':1, 'auth.timestamps':1, 'auth.local.email':1}; -db.collection('users').find(query, fields).toArray(function(err, items) { - if (err) return console.error({err:err}); - var stats = {total: _.size(items), lostToDerby: 0, isActive: 0}; - var emails = []; - _.each(items, function(item) { - //if (!item.history || !item.history.exp) console.log(item._id) - - //var hasBeenActive = item.history && item.history.exp && item.history.exp.length > 7; - var hasBeenActive = item.auth.timestamps && item.auth.timestamps.created && - (Math.abs(moment(item.lastCron).diff(item.auth.timestamps.created, 'd')) > 14); - - if (/*hasBeenActive && */moment(item.lastCron).isBefore(angularRewrite)) { - stats.lostToDerby++; - if (item.auth.local) - emails.push([item.auth.local.email]); - // Facebook emails. Kinda dirty, and there's only ~30 available fb emails anyway. -// } else if (item.auth.facebook && item.auth.facebook.email) { -// emails.push([item.auth.facebook.email]) -// } else if (item.auth.facebook && item.auth.facebook.emails && item.auth.facebook.emails[0] && !!item.auth.facebook.emails[0].value) { -// emails.push([item.auth.facebook.emails[0].value]) - } - if (hasBeenActive && moment(item.lastCron).isAfter(twoWeeksAgo)) { - stats.isActive++; - } - - }) - stats.emails = _.size(emails); - console.log(stats); - - if (EXPORT_EMAILS) - csv().from.array(emails).to.path(__dirname+'/emails.csv') -}); - -/* -load('./node_modules/moment/moment.js'); -var today = +new Date, - twoWeeksAgo = +moment().subtract(14, 'days'); - - corrupt = { - $or: [ - {lastCron: {$exists:false}}, - {lastCron: 'new'} - ] - } - - un_registered = { - "auth.local": {$exists: false}, - "auth.facebook": {$exists: false} - }, - - registered = { - $or: [ - { 'auth.local': { $exists: true }}, - { 'auth.facebook': { $exists: true }} - ] - }, - - active = { - $or: [ - { 'auth.local': { $exists: true }}, - { 'auth.facebook': { $exists: true }} - ], - $where: function(){ - return this.history && this.history.exp && this.history.exp.length > 7; - }, - 'lastCron': {$gt: twoWeeksAgo} - }; - -print('corrupt: ' + db.users.count(corrupt)); -print('unregistered: ' + db.users.count(un_registered)); -print('registered: ' + db.users.count(registered)); -print('active: ' + db.users.count(active)); -*/ \ No newline at end of file diff --git a/migrations/migration-runner.js b/migrations/migration-runner.js index 2b030b88e6..59a2a32a27 100644 --- a/migrations/migration-runner.js +++ b/migrations/migration-runner.js @@ -1,13 +1,13 @@ -require("babel-register"); -require("babel-polyfill"); +require('babel-register'); +require('babel-polyfill'); // This file must use ES5, everything required can be in ES6 function setUpServer () { - var nconf = require('nconf'); - var mongoose = require('mongoose'); - var Bluebird = require('bluebird'); - var setupNconf = require('../website/server/libs/setupNconf'); + const nconf = require('nconf'); // eslint-disable-line global-require, no-unused-vars + const mongoose = require('mongoose'); // eslint-disable-line global-require, no-unused-vars + const Bluebird = require('bluebird'); // eslint-disable-line global-require, no-unused-vars + const setupNconf = require('../website/server/libs/setupNconf'); // eslint-disable-line global-require setupNconf(); // We require src/server and npt src/index because // 1. nconf is already setup diff --git a/migrations/missing_gems.js b/migrations/missing_gems.js deleted file mode 100644 index 78ff37ed1d..0000000000 --- a/migrations/missing_gems.js +++ /dev/null @@ -1 +0,0 @@ -db.users.update({_id:''},{$inc:{balance:5}}); \ No newline at end of file diff --git a/migrations/new_stuff.js b/migrations/new_stuff.js index 9abcbc32a1..3ee124ab6b 100644 --- a/migrations/new_stuff.js +++ b/migrations/new_stuff.js @@ -1,41 +1,41 @@ -var migrationName = 'new_stuff.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +/* let migrationName = 'new_stuff.js'; */ +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * set the newStuff flag in all user accounts so they see a Bailey message */ -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'flags.newStuff': {$ne:true}, + let query = { + 'flags.newStuff': {$ne: true}, }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { sort: {_id: 1}, limit: 250, - fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch((err) => { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -44,37 +44,42 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(() => { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = {'flags.newStuff': true}; + let set = {'flags.newStuff': true}; - dbUsers.update({_id: user._id}, {$set:set}); + dbUsers.update({_id: user._id}, {$set: set}); - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/restock_armoire.js b/migrations/restock_armoire.js index a26e45b693..5046998a3b 100644 --- a/migrations/restock_armoire.js +++ b/migrations/restock_armoire.js @@ -1,41 +1,41 @@ -var migrationName = 'restock_armoire.js'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +let migrationName = 'restock_armoire.js'; +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Remove flag stating that the Enchanted Armoire is empty, for when new equipment is added */ -var monk = require('monk'); -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { + let query = { 'flags.armoireEmpty': true, }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { sort: {_id: 1}, limit: 250, - fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch((err) => { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -44,37 +44,42 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(() => { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = {'migration': migrationName, 'flags.armoireEmpty': false}; + let set = {migration: migrationName, 'flags.armoireEmpty': false}; - dbUsers.update({_id: user._id}, {$set:set}); + dbUsers.update({_id: user._id}, {$set: set}); - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/restock_armoire_for_users_that_need_it.js b/migrations/restock_armoire_for_users_that_need_it.js index 1c335ffe78..5bf0422d04 100644 --- a/migrations/restock_armoire_for_users_that_need_it.js +++ b/migrations/restock_armoire_for_users_that_need_it.js @@ -1,65 +1,65 @@ -var migrationName = 'restock_armoire_for_users_that_need_it.js'; -var authorName = 'Alys (ALittleYellowSpider)'; // in case script author needs to know when their ... -var authorUuid = '3e595299-3d8a-4a10-bfe0-88f555e4aa0c'; //... own data is done +let migrationName = 'restock_armoire_for_users_that_need_it.js'; +let authorName = 'Alys (ALittleYellowSpider)'; // in case script author needs to know when their ... +let authorUuid = '3e595299-3d8a-4a10-bfe0-88f555e4aa0c'; // ... own data is done /* * Remove flag stating that the Enchanted Armoire is empty, - * for when new equipment has been added + * for when new equipment has been added * AND the normal restock_armoire.js script has failed. * This script finds all users that logged in recently, checks if they * do NOT own all Armoire items, and only then does it mark the Armoire * as not empty. - * + * ********************************************************************* * IMPORTANT: * You must update the list of Armoire items that this list checks for. * Scroll down. You'll see it. ********************************************************************* - * + * */ -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var monk = require('monk'); -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'auth.timestamps.loggedin':{$gt:new Date('2016-01-04')} + let query = { + 'auth.timestamps.loggedin': {$gt: new Date('2016-01-04')}, // '_id': authorUuid // FOR TESTING }; // specify a query to limit the affected users (empty for all users): - var fields = { - 'flags.armoireEmpty':1, - 'items.gear.owned':1 - }; + /* let fields = { + 'flags.armoireEmpty': 1, + 'items.gear.owned': 1, + };*/ if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { sort: {_id: 1}, limit: 250, fields: { - 'flags.armoireEmpty':1, - 'items.gear.owned':1 - } // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + 'flags.armoireEmpty': 1, + 'items.gear.owned': 1, + }, // specify fields we are interested in to limit retrieved data (empty if we're not reading data): }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch((err) => { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -68,19 +68,19 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(() => { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = {'migration':migrationName, 'flags.armoireEmpty':false}; + let set = {migration: migrationName, 'flags.armoireEmpty': false}; if (user.flags.armoireEmpty) { @@ -98,21 +98,26 @@ function updateUser (user) { // console.log("DON'T CHANGE: " + user._id); // FOR TESTING } - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/restore-profile-data.js b/migrations/restore-profile-data.js index 78884738e1..750a991efb 100644 --- a/migrations/restore-profile-data.js +++ b/migrations/restore-profile-data.js @@ -1,23 +1,22 @@ -var migrationName = 'restore_profile_data.js'; -var authorName = 'ThehollidayInn'; // in case script author needs to know when their ... -var authorUuid = ''; //... own data is done +/* let migrationName = 'restore_profile_data.js'; */ +let authorName = 'ThehollidayInn'; // in case script author needs to know when their ... +let authorUuid = ''; // ... own data is done /* * Check if users have empty profile data in new database and update it with old database info */ -var monk = require('monk'); -var connectionString = ''; // FOR TEST DATABASE -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = ''; // FOR TEST DATABASE +let dbUsers = monk(connectionString).get('users', { castIds: false }); -var monk2 = require('monk'); -var oldDbConnectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var olDbUsers = monk2(oldDbConnectionString).get('users', { castIds: false }); +let monk2 = require('monk'); +let oldDbConnectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let olDbUsers = monk2(oldDbConnectionString).get('users', { castIds: false }); -function processUsers(lastId) -{ +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { + let query = { // 'profile.name': 'profile name not found', 'profile.blurb': null, // 'auth.timestamps.loggedin': {$gt: new Date('11/30/2016')}, @@ -25,24 +24,24 @@ function processUsers(lastId) if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { sort: {_id: 1}, limit: 250, - fields: ['_id', 'profile', 'auth.timestamps.loggedin'] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + fields: ['_id', 'profile', 'auth.timestamps.loggedin'], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch((err) => { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -51,13 +50,13 @@ function updateUsers (users) { return; } - var userPaymentPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPaymentPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPaymentPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(() => { + return processUsers(lastUser._id); + }); } function updateUser (user) { @@ -68,11 +67,11 @@ function updateUser (user) { .then((oldUserData) => { if (!oldUserData) return; // specify user data to change: - var set = {}; + let set = {}; if (oldUserData.profile.name === 'profile name not found') return; - var userNeedsProfileName = !user.profile.name || user.profile.name === 'profile name not found'; + let userNeedsProfileName = !user.profile.name || user.profile.name === 'profile name not found'; if (userNeedsProfileName && oldUserData.profile.name) { set['profile.name'] = oldUserData.profile.name; } @@ -86,30 +85,35 @@ function updateUser (user) { } if (Object.keys(set).length !== 0 && set.constructor === Object) { - console.log(set) - return dbUsers.update({_id: user._id}, {$set:set}); + console.log(set); + return dbUsers.update({_id: user._id}, {$set: set}); } }); } - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } -processUsers() +processUsers(); diff --git a/migrations/s3-upload.js b/migrations/s3-upload.js index dfb07f1eca..7538e83f6d 100644 --- a/migrations/s3-upload.js +++ b/migrations/s3-upload.js @@ -4,7 +4,7 @@ let last = require('lodash/last'); let AWS = require('aws-sdk'); let config = require('../config'); -const S3_DIRECTORY = 'mobileApp/images'; //config.S3.SPRITES_DIRECTORY; +const S3_DIRECTORY = 'mobileApp/images'; // config.S3.SPRITES_DIRECTORY; AWS.config.update({ accessKeyId: config.S3.accessKeyId, @@ -53,26 +53,26 @@ function getFileFromUrl (url) { let commit = '78f94e365c72cc58f66857d5941105638db7d35c'; commit = 'df0dbaba636c9ce424cc7040f7bd7fc1aa311015'; -let gihuburl = `https://api.github.com/repos/HabitRPG/habitica/commits/${commit}` +let gihuburl = `https://api.github.com/repos/HabitRPG/habitica/commits/${commit}`; let currentIndex = 0; -function uploadToS3(start, end, filesUrls) { +function uploadToS3 (start, end, filesUrls) { let urls = filesUrls.slice(start, end); if (urls.length === 0) { - console.log("done"); + console.log('done'); return; } let promises = urls.map(fullUrl => { return getFileFromUrl(fullUrl) - .then((buffer) => { - return uploadFile(buffer, getFileName(fullUrl)); - }); + .then((buffer) => { + return uploadFile(buffer, getFileName(fullUrl)); + }); }); - console.log(promises.length) + console.log(promises.length); return Bluebird.all(promises) .then(() => { @@ -92,7 +92,7 @@ request.get(gihuburl) let filesUrls = ['']; filesUrls = files.map(file => { return file.raw_url; - }) + }); uploadToS3(currentIndex, currentIndex + 50, filesUrls); }); diff --git a/migrations/takeThis.js b/migrations/takeThis.js index 17336e394d..13e4283b9b 100644 --- a/migrations/takeThis.js +++ b/migrations/takeThis.js @@ -1,26 +1,26 @@ -var migrationName = '20180102_takeThis.js'; // Update per month -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +let migrationName = '20180102_takeThis.js'; // Update per month +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Award Take This ladder items to participants in this month's challenge */ -var monk = require('monk'); -var connectionString = 'mongodb://sabrecat:z8e8jyRA8CTofMQ@ds013393-a0.mlab.com:13393/habitica?auto_reconnect=true'; -var dbUsers = monk(connectionString).get('users', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://sabrecat:z8e8jyRA8CTofMQ@ds013393-a0.mlab.com:13393/habitica?auto_reconnect=true'; +let dbUsers = monk(connectionString).get('users', { castIds: false }); -function processUsers(lastId) { +function processUsers (lastId) { // specify a query to limit the affected users (empty for all users): - var query = { - 'migration':{$ne:migrationName}, - 'challenges':{$in:['5f70ce5b-2d82-4114-8e44-ca65615aae62']} // Update per month + let query = { + migration: {$ne: migrationName}, + challenges: {$in: ['5f70ce5b-2d82-4114-8e44-ca65615aae62']}, // Update per month }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbUsers.find(query, { @@ -28,17 +28,17 @@ function processUsers(lastId) { limit: 250, fields: [ 'items.gear.owned', - ] // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + ], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): }) - .then(updateUsers) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateUsers) + .catch((err) => { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateUsers (users) { if (!users || users.length === 0) { @@ -47,40 +47,41 @@ function updateUsers (users) { return; } - var userPromises = users.map(updateUser); - var lastUser = users[users.length - 1]; + let userPromises = users.map(updateUser); + let lastUser = users[users.length - 1]; return Promise.all(userPromises) - .then(function () { - processUsers(lastUser._id); - }); + .then(() => { + processUsers(lastUser._id); + }); } function updateUser (user) { count++; - var set = {}; + let set = {}; + let push; if (typeof user.items.gear.owned.back_special_takeThis !== 'undefined') { - set = {'migration':migrationName}; + set = {migration: migrationName}; } else if (typeof user.items.gear.owned.body_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.back_special_takeThis':false}; - var push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.back_special_takeThis', '_id': monk.id()}}; + set = {migration: migrationName, 'items.gear.owned.back_special_takeThis': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.back_special_takeThis', _id: monk.id()}}; } else if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.body_special_takeThis':false}; - var push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.body_special_takeThis', '_id': monk.id()}}; + set = {migration: migrationName, 'items.gear.owned.body_special_takeThis': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.body_special_takeThis', _id: monk.id()}}; } else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.head_special_takeThis':false}; - var push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_takeThis', '_id': monk.id()}}; + set = {migration: migrationName, 'items.gear.owned.head_special_takeThis': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_takeThis', _id: monk.id()}}; } else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.armor_special_takeThis':false}; - var push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_takeThis', '_id': monk.id()}}; + set = {migration: migrationName, 'items.gear.owned.armor_special_takeThis': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_takeThis', _id: monk.id()}}; } else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') { - set = {'migration':migrationName, 'items.gear.owned.weapon_special_takeThis':false}; - var push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.weapon_special_takeThis', '_id': monk.id()}}; + set = {migration: migrationName, 'items.gear.owned.weapon_special_takeThis': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.weapon_special_takeThis', _id: monk.id()}}; } else { - set = {'migration':migrationName, 'items.gear.owned.shield_special_takeThis':false}; - var push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.shield_special_takeThis', '_id': monk.id()}}; + set = {migration: migrationName, 'items.gear.owned.shield_special_takeThis': false}; + push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.shield_special_takeThis', _id: monk.id()}}; } if (push) { @@ -89,21 +90,26 @@ function updateUser (user) { dbUsers.update({_id: user._id}, {$set: set}); } - if (count % progressCount == 0) console.warn(count + ' ' + user._id); - if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); + if (user._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' users processed\n'); +function displayData () { + console.warn(`\n${ count } users processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/tasks/tasks-set-everyX.js b/migrations/tasks/tasks-set-everyX.js index c0a4acc7fb..f3bd5408d6 100644 --- a/migrations/tasks/tasks-set-everyX.js +++ b/migrations/tasks/tasks-set-everyX.js @@ -1,32 +1,32 @@ -var migrationName = 'tasks-set-everyX'; -var authorName = 'Sabe'; // in case script author needs to know when their ... -var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done +/* let migrationName = 'tasks-set-everyX'; */ +let authorName = 'Sabe'; // in case script author needs to know when their ... +let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done /* * Iterates over all tasks and sets invalid everyX values (less than 0 or more than 9999 or not an int) field to 0 */ -var monk = require('monk'); -var connectionString = 'mongodb://sabrecat:z8e8jyRA8CTofMQ@ds013393-a0.mlab.com:13393/habitica?auto_reconnect=true'; -var dbTasks = monk(connectionString).get('tasks', { castIds: false }); +let monk = require('monk'); +let connectionString = 'mongodb://sabrecat:z8e8jyRA8CTofMQ@ds013393-a0.mlab.com:13393/habitica?auto_reconnect=true'; +let dbTasks = monk(connectionString).get('tasks', { castIds: false }); -function processTasks(lastId) { +function processTasks (lastId) { // specify a query to limit the affected tasks (empty for all tasks): - var query = { - type: "daily", + let query = { + type: 'daily', everyX: { $not: { $gte: 0, $lte: 9999, - $type: "int", - } + $type: 'int', + }, }, }; if (lastId) { query._id = { - $gt: lastId - } + $gt: lastId, + }; } dbTasks.find(query, { @@ -34,15 +34,15 @@ function processTasks(lastId) { limit: 250, fields: [], }) - .then(updateTasks) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); + .then(updateTasks) + .catch((err) => { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); } -var progressCount = 1000; -var count = 0; +let progressCount = 1000; +let count = 0; function updateTasks (tasks) { if (!tasks || tasks.length === 0) { @@ -51,36 +51,41 @@ function updateTasks (tasks) { return; } - var taskPromises = tasks.map(updatetask); - var lasttask = tasks[tasks.length - 1]; + let taskPromises = tasks.map(updatetask); + let lasttask = tasks[tasks.length - 1]; return Promise.all(taskPromises) - .then(function () { - processTasks(lasttask._id); - }); + .then(() => { + return processTasks(lasttask._id); + }); } function updatetask (task) { count++; - var set = {'everyX': 0}; + let set = {everyX: 0}; - dbTasks.update({_id: task._id}, {$set:set}); + dbTasks.update({_id: task._id}, {$set: set}); - if (count % progressCount == 0) console.warn(count + ' ' + task._id); - if (task._id == authorUuid) console.warn(authorName + ' processed'); + if (count % progressCount === 0) console.warn(`${count } ${ task._id}`); + if (task._id === authorUuid) console.warn(`${authorName } processed`); } -function displayData() { - console.warn('\n' + count + ' tasks processed\n'); +function displayData () { + console.warn(`\n${ count } tasks processed\n`); return exiting(0); } -function exiting(code, msg) { +function exiting (code, msg) { code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } + if (code && !msg) { + msg = 'ERROR!'; + } if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } + if (code) { + console.error(msg); + } else { + console.log(msg); + } } process.exit(code); } diff --git a/migrations/tasks/tasks-set-yesterdailies.js b/migrations/tasks/tasks-set-yesterdailies.js index 8ce87b1046..253d871612 100644 --- a/migrations/tasks/tasks-set-yesterdailies.js +++ b/migrations/tasks/tasks-set-yesterdailies.js @@ -1,83 +1,88 @@ -var migrationName = 'tasks-set-yesterdaily'; -var authorName = 'TheHollidayInn'; // in case script author needs to know when their ... -var authorUuid = ''; //... own data is done - -/* - * Iterates over all tasks and sets the yseterDaily field to True - */ - -import monk from 'monk'; - -var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE -var dbTasks = monk(connectionString).get('tasks', { castIds: false }); - -function processTasks(lastId) { - // specify a query to limit the affected tasks (empty for all tasks): - var query = { - yesterDaily: false, - }; - - if (lastId) { - query._id = { - $gt: lastId - } - } - - dbTasks.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - ], - }) - .then(updateTasks) - .catch(function (err) { - console.log(err); - return exiting(1, 'ERROR! ' + err); - }); -} - -var progressCount = 1000; -var count = 0; - -function updateTasks (tasks) { - if (!tasks || tasks.length === 0) { - console.warn('All appropriate tasks found and modified.'); - displayData(); - return; - } - - var taskPromises = tasks.map(updatetask); - var lasttask = tasks[tasks.length - 1]; - - return Promise.all(taskPromises) - .then(function () { - processtasks(lasttask._id); - }); -} - -function updatetask (task) { - count++; - var set = {'yesterDaily': true}; - - dbTasks.update({_id: task._id}, {$set:set}); - - if (count % progressCount == 0) console.warn(count + ' ' + task._id); - if (task._id == authorUuid) console.warn(authorName + ' processed'); -} - -function displayData() { - console.warn('\n' + count + ' tasks processed\n'); - return exiting(0); -} - -function exiting(code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { msg = 'ERROR!'; } - if (msg) { - if (code) { console.error(msg); } - else { console.log( msg); } - } - process.exit(code); -} - -module.exports = processtasks; +/* let migrationName = 'tasks-set-yesterdaily'; */ +let authorName = 'TheHollidayInn'; // in case script author needs to know when their ... +let authorUuid = ''; // ... own data is done + +/* + * Iterates over all tasks and sets the yseterDaily field to True + */ + +import monk from 'monk'; + +let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE +let dbTasks = monk(connectionString).get('tasks', { castIds: false }); + +let progressCount = 1000; +let count = 0; + +function exiting (code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { + msg = 'ERROR!'; + } + if (msg) { + if (code) { + console.error(msg); + } else { + console.log(msg); + } + } + process.exit(code); +} + +function displayData () { + console.warn(`\n${ count } tasks processed\n`); + return exiting(0); +} + +function updatetask (task) { + count++; + let set = {yesterDaily: true}; + + dbTasks.update({_id: task._id}, {$set: set}); + + if (count % progressCount === 0) console.warn(`${count } ${ task._id}`); + if (task._id === authorUuid) console.warn(`${authorName } processed`); +} + +function updateTasks (tasks) { + if (!tasks || tasks.length === 0) { + console.warn('All appropriate tasks found and modified.'); + displayData(); + return; + } + + let taskPromises = tasks.map(updatetask); + let lasttask = tasks[tasks.length - 1]; + + return Promise.all(taskPromises) + .then(() => { + return processTasks(lasttask._id); // eslint-disable-line no-use-before-define + }); +} + +function processTasks (lastId) { + // specify a query to limit the affected tasks (empty for all tasks): + let query = { + yesterDaily: false, + }; + + if (lastId) { + query._id = { + $gt: lastId, + }; + } + + dbTasks.find(query, { + sort: {_id: 1}, + limit: 250, + fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data): + ], + }) + .then(updateTasks) + .catch((err) => { + console.log(err); + return exiting(1, `ERROR! ${ err}`); + }); +} + +module.exports = processTasks; diff --git a/migrations/users/account-transfer.js b/migrations/users/account-transfer.js index 7d57dac08b..42a9602aa1 100644 --- a/migrations/users/account-transfer.js +++ b/migrations/users/account-transfer.js @@ -1,6 +1,8 @@ -var migrationName = 'AccountTransfer'; -var authorName = 'TheHollidayInn'; // in case script author needs to know when their ... -var authorUuid = ''; //... own data is done +/* +let migrationName = 'AccountTransfer'; +let authorName = 'TheHollidayInn'; // in case script author needs to know when their ... +let authorUuid = ''; // ... own data is done +*/ /* * This migraition will copy user data from prod to test @@ -10,10 +12,6 @@ const monk = require('monk'); const connectionString = ''; const Users = monk(connectionString).get('users', { castIds: false }); -import uniq from 'lodash/uniq'; -import Bluebird from 'bluebird'; - - module.exports = async function accountTransfer () { const fromAccountId = ''; const toAccountId = ''; @@ -32,7 +30,7 @@ module.exports = async function accountTransfer () { 'purchased.background': newBackgrounds, }, }) - .then((result) => { - console.log(result); - }); + .then((result) => { + console.log(result); + }); }; diff --git a/migrations/users/achievement-restore.js b/migrations/users/achievement-restore.js index bd7e91a327..e87300bc18 100644 --- a/migrations/users/achievement-restore.js +++ b/migrations/users/achievement-restore.js @@ -1,17 +1,17 @@ +/* const migrationName = 'AchievementRestore'; const authorName = 'TheHollidayInn'; // in case script author needs to know when their ... -const authorUuid = ''; //... own data is done +const authorUuid = ''; // ... own data is done +*/ /* * This migraition will copy user data from prod to test */ -import Bluebird from 'bluebird'; const monk = require('monk'); const connectionString = 'mongodb://localhost/new-habit'; const Users = monk(connectionString).get('users', { castIds: false }); -const monkOld = require('monk'); const oldConnectionSting = 'mongodb://localhost/old-habit'; const UsersOld = monk(oldConnectionSting).get('users', { castIds: false }); @@ -52,21 +52,19 @@ function getAchievementUpdate (newUser, oldUser) { achievementsUpdate.rebirthLevel = oldAchievements.rebirthLevel; } - //All others + // All others const indexsToIgnore = ['ultimateGearSets', 'challenges', 'quests', 'rebirthLevel']; for (let index in oldAchievements) { - if (indexsToIgnore.indexOf(index) !== -1) continue; + if (indexsToIgnore.indexOf(index) !== -1) continue; // eslint-disable-line no-continue if (!achievementsUpdate[index]) { achievementsUpdate[index] = oldAchievements[index]; - continue; + continue; // eslint-disable-line no-continue } if (Number.isInteger(oldAchievements[index])) { achievementsUpdate[index] += oldAchievements[index]; - } else { - if (oldAchievements[index] === true) achievementsUpdate[index] = true; - } + } else if (oldAchievements[index] === true) achievementsUpdate[index] = true; } return achievementsUpdate; @@ -77,6 +75,7 @@ module.exports = async function achievementRestore () { ]; for (let index in userIds) { + /* eslint-disable no-await-in-loop */ const userId = userIds[index]; const oldUser = await UsersOld.findOne({_id: userId}, 'achievements'); const newUser = await Users.findOne({_id: userId}, 'achievements'); @@ -85,9 +84,10 @@ module.exports = async function achievementRestore () { {_id: userId}, { $set: { - 'achievements': achievementUpdate, + achievements: achievementUpdate, }, }); console.log(`Updated ${userId}`); + /* eslint-enable no-await-in-loop */ } }; diff --git a/migrations/users/users-to-test.js b/migrations/users/users-to-test.js index 64b6c38e07..cf9f4cc92f 100644 --- a/migrations/users/users-to-test.js +++ b/migrations/users/users-to-test.js @@ -1,32 +1,35 @@ -var migrationName = 'UserFromProdToTest'; -var authorName = 'TheHollidayInn'; // in case script author needs to know when their ... -var authorUuid = ''; //... own data is done +/* +let migrationName = 'UserFromProdToTest'; +let authorName = 'TheHollidayInn'; // in case script author needs to know when their ... +let authorUuid = ''; // ... own data is done +*/ /* * This migraition will copy user data from prod to test */ -var monk = require('monk'); -var testConnectionSting = ''; // FOR TEST DATABASE -var usersTest = monk(testConnectionSting).get('users', { castIds: false }); -var groupsTest = monk(testConnectionSting).get('groups', { castIds: false }); -var challengesTest = monk(testConnectionSting).get('challenges', { castIds: false }); -var tasksTest = monk(testConnectionSting).get('tasks', { castIds: false }); +let monk = require('monk'); +let testConnectionSting = ''; // FOR TEST DATABASE +let usersTest = monk(testConnectionSting).get('users', { castIds: false }); +let groupsTest = monk(testConnectionSting).get('groups', { castIds: false }); +let challengesTest = monk(testConnectionSting).get('challenges', { castIds: false }); +let tasksTest = monk(testConnectionSting).get('tasks', { castIds: false }); -var monk2 = require('monk'); -var liveConnectString = ''; // FOR TEST DATABASE -var userLive = monk2(liveConnectString).get('users', { castIds: false }); -var groupsLive = monk2(liveConnectString).get('groups', { castIds: false }); -var challengesLive = monk2(liveConnectString).get('challenges', { castIds: false }); -var tasksLive = monk2(liveConnectString).get('tasks', { castIds: false }); +let monk2 = require('monk'); +let liveConnectString = ''; // FOR TEST DATABASE +let userLive = monk2(liveConnectString).get('users', { castIds: false }); +let groupsLive = monk2(liveConnectString).get('groups', { castIds: false }); +let challengesLive = monk2(liveConnectString).get('challenges', { castIds: false }); +let tasksLive = monk2(liveConnectString).get('tasks', { castIds: false }); import uniq from 'lodash/uniq'; -import Bluebird from 'bluebird'; // Variabls for updating +/* let userIds = [ '206039c6-24e4-4b9f-8a31-61cbb9aa3f66', ]; +*/ let groupIds = []; let challengeIds = []; @@ -34,10 +37,10 @@ let tasksIds = []; async function processUsers () { let userPromises = []; - //{_id: {$in: userIds}} + // {_id: {$in: userIds}} return userLive.find({guilds: 'b0764d64-8276-45a1-afa5-5ca9a5c64ca0'}) - .each((user, {close, pause, resume}) => { + .each((user) => { if (user.guilds.length > 0) groupIds = groupIds.concat(user.guilds); if (user.party._id) groupIds.push(user.party._id); if (user.challenges.length > 0) challengeIds = challengeIds.concat(user.challenges); @@ -46,13 +49,13 @@ async function processUsers () { if (user.tasksOrder.dailys.length > 0) tasksIds = tasksIds.concat(user.tasksOrder.dailys); if (user.tasksOrder.habits.length > 0) tasksIds = tasksIds.concat(user.tasksOrder.habits); - let userPromise = usersTest.update({'_id': user._id}, user, {upsert:true}); + let userPromise = usersTest.update({_id: user._id}, user, {upsert: true}); userPromises.push(userPromise); }).then(() => { - return Bluebird.all(userPromises); + return Promise.all(userPromises); }) .then(() => { - console.log("Done User"); + console.log('Done User'); }); } @@ -60,14 +63,14 @@ function processGroups () { let promises = []; let groupsToQuery = uniq(groupIds); return groupsLive.find({_id: {$in: groupsToQuery}}) - .each((group, {close, pause, resume}) => { - let promise = groupsTest.update({_id: group._id}, group, {upsert:true}); + .each((group) => { + let promise = groupsTest.update({_id: group._id}, group, {upsert: true}); promises.push(promise); }).then(() => { - return Bluebird.all(promises); + return Promise.all(promises); }) .then(() => { - console.log("Done Group"); + console.log('Done Group'); }); } @@ -75,14 +78,14 @@ function processChallenges () { let promises = []; let challengesToQuery = uniq(challengeIds); return challengesLive.find({_id: {$in: challengesToQuery}}) - .each((challenge, {close, pause, resume}) => { - let promise = challengesTest.update({_id: challenge._id}, challenge, {upsert:true}); + .each((challenge) => { + let promise = challengesTest.update({_id: challenge._id}, challenge, {upsert: true}); promises.push(promise); }).then(() => { - return Bluebird.all(promises); + return Promise.all(promises); }) .then(() => { - console.log("Done Challenge"); + console.log('Done Challenge'); }); } @@ -90,14 +93,14 @@ function processTasks () { let promises = []; let tasksToQuery = uniq(tasksIds); return tasksLive.find({_id: {$in: tasksToQuery}}) - .each((task, {close, pause, resume}) => { - let promise = tasksTest.update({_id: task._id}, task, {upsert:true}); + .each((task) => { + let promise = tasksTest.update({_id: task._id}, task, {upsert: true}); promises.push(promise); }).then(() => { - return Bluebird.all(promises); + return Promise.all(promises); }) .then(() => { - console.log("Done Tasks"); + console.log('Done Tasks'); }); } diff --git a/migrations/utils/connect.js b/migrations/utils/connect.js index 492b473708..1b20d523ca 100644 --- a/migrations/utils/connect.js +++ b/migrations/utils/connect.js @@ -3,7 +3,7 @@ const MongoClient = require('mongodb').MongoClient; const logger = require('./logger'); -let db; +let dbConnection; function connectToDb (dbUri) { return new Promise((resolve, reject) => { @@ -13,7 +13,7 @@ function connectToDb (dbUri) { return reject(err); } - db = database; + dbConnection = database; logger.success(`Connected to ${dbUri}`); @@ -23,7 +23,7 @@ function connectToDb (dbUri) { } function closeDb () { - if (db) db.close(); + if (dbConnection) dbConnection.close(); logger.success('Closed connection to the database'); return Promise.resolve(); @@ -32,4 +32,4 @@ function closeDb () { module.exports = { connectToDb, closeDb, -} +}; diff --git a/migrations/utils/logger.js b/migrations/utils/logger.js index a2ddc96fe2..cf6d643e76 100644 --- a/migrations/utils/logger.js +++ b/migrations/utils/logger.js @@ -2,6 +2,13 @@ const chalk = require('chalk'); +function loggerGenerator (type, color) { + return function logger () { + let args = Array.from(arguments).map(arg => chalk[color](arg)); + console[type].apply(null, args); + }; +} + const logger = { info: loggerGenerator('info', 'cyan'), success: loggerGenerator('info', 'green'), @@ -10,11 +17,4 @@ const logger = { warn: loggerGenerator('warn', 'yellow'), }; -function loggerGenerator (type, color) { - return function () { - let args = Array.from(arguments).map(arg => chalk[color](arg)); - console[type].apply(null, args); - } -} - module.exports = logger; diff --git a/migrations/utils/timer.js b/migrations/utils/timer.js index 37a75830b1..cacdfc1b8b 100644 --- a/migrations/utils/timer.js +++ b/migrations/utils/timer.js @@ -13,7 +13,7 @@ class Timer { if (!options.disableAutoStart) this.start(); } start () { - this._internalTimer = setInterval(() =>{ + this._internalTimer = setInterval(() => { this.count++; let shouldWarn = this._minutesWarningThreshold < this.count; diff --git a/package-lock.json b/package-lock.json index f953f8092e..7ef630a64f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,104 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.36.tgz", + "integrity": "sha512-sW77BFwJ48YvQp3Gzz5xtAUiXuYOL2aMJKDwiaY3OcvdqBFurtYfOpSa4QrNyDxmOGRFSYzUpabU2m9QrlWE7w==", + "requires": { + "chalk": "2.3.0", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.36.tgz", + "integrity": "sha512-/SGPOyifPf20iTrMN+WdlY2MbKa7/o4j7B/4IAsdOusASp2icT+Wcdjf4tjJHaXNX8Pe9bpgVxLNxhRvcf8E5w==", + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.36", + "@babel/template": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.36.tgz", + "integrity": "sha512-vPPcx2vsSoDbcyWr9S3nd0FM3B4hEXnt0p1oKpwa08GwK0fSRxa98MyaRGf8suk8frdQlG1P3mDrz5p/Rr3pbA==", + "requires": { + "@babel/types": "7.0.0-beta.36" + } + }, + "@babel/template": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.36.tgz", + "integrity": "sha512-mUBi90WRyZ9iVvlWLEdeo8gn/tROyJdjKNC4W5xJTSZL+9MS89rTJSqiaJKXIkxk/YRDL/g/8snrG/O0xl33uA==", + "requires": { + "@babel/code-frame": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36", + "babylon": "7.0.0-beta.36", + "lodash": "4.17.5" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz", + "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ==" + } + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.36.tgz", + "integrity": "sha512-OTUb6iSKVR/98dGThRJ1BiyfwbuX10BVnkz89IpaerjTPRhDfMBfLsqmzxz5MiywUOW4M0Clta0o7rSxkfcuzw==", + "requires": { + "@babel/code-frame": "7.0.0-beta.36", + "@babel/helper-function-name": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36", + "babylon": "7.0.0-beta.36", + "debug": "3.1.0", + "globals": "11.3.0", + "invariant": "2.2.2", + "lodash": "4.17.5" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz", + "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ==" + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==" + } + } + }, + "@babel/types": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.36.tgz", + "integrity": "sha512-PyAORDO9um9tfnrddXgmWN9e6Sq9qxraQIt5ynqBOSXKA5qvK1kUr+Q3nSzKFdzorsiK+oqcUnAFvEoKxv9D+Q==", + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, "@slack/client": { "version": "3.16.0", "resolved": "https://registry.npmjs.org/@slack/client/-/client-3.16.0.tgz", @@ -917,14 +1015,23 @@ } }, "babel-eslint": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz", - "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.1.tgz", + "integrity": "sha512-RzdVOyWKQRUnLXhwLk+eKb4oyW+BykZSkpYwFhM4tnfzAG5OWfvG0w/uyzMp5XKEU0jN82+JefHr39bG2+KhRQ==", "requires": { - "babel-code-frame": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0" + "@babel/code-frame": "7.0.0-beta.36", + "@babel/traverse": "7.0.0-beta.36", + "@babel/types": "7.0.0-beta.36", + "babylon": "7.0.0-beta.36", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.36", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.36.tgz", + "integrity": "sha512-rw4YdadGwajAMMRl6a5swhQ0JCOOFyaYCfJ0AsmNBD8uBD/r4J8mux7wBaqavvFKqUKQYWOzA1Speams4YDzsQ==" + } } }, "babel-generator": { @@ -2414,21 +2521,38 @@ } }, "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", "dev": true, "requires": { "assertion-error": "1.1.0", - "deep-eql": "0.1.3", - "type-detect": "1.0.0" + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + }, + "dependencies": { + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + } } }, "chai-as-promised": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-5.3.0.tgz", - "integrity": "sha1-CdekApCKpw39vq1T5YU/x50+8hw=", - "dev": true + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "requires": { + "check-error": "1.0.2" + } }, "chai-dom": { "version": "1.7.0", @@ -2470,7 +2594,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, "requires": { "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", @@ -2481,7 +2604,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, "requires": { "color-convert": "1.9.1" } @@ -2489,14 +2611,12 @@ "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, "requires": { "has-flag": "2.0.0" } @@ -2516,6 +2636,12 @@ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "check-types": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.3.0.tgz", @@ -2862,6 +2988,12 @@ "q": "1.5.1" } }, + "coalescy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/coalescy/-/coalescy-1.0.0.tgz", + "integrity": "sha1-SwZYRrg2NhrabEtKSr9LwcrDG/E=", + "dev": true + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -5116,38 +5248,11 @@ "es6-symbol": "3.1.1" } }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, "es6-promise": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", @@ -5210,185 +5315,126 @@ } } }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } - } - }, "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz", + "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==", "dev": true, "requires": { + "ajv": "5.5.2", "babel-code-frame": "6.26.0", - "chalk": "1.1.3", + "chalk": "2.3.0", "concat-stream": "1.6.0", - "debug": "2.6.9", + "cross-spawn": "5.1.0", + "debug": "3.1.0", "doctrine": "2.1.0", - "escope": "3.6.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", "espree": "3.5.3", "esquery": "1.0.0", - "estraverse": "4.2.0", "esutils": "2.0.2", "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", "glob": "7.1.2", - "globals": "9.18.0", + "globals": "11.3.0", "ignore": "3.3.7", "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.17.1", + "inquirer": "3.0.6", "is-resolvable": "1.1.0", - "js-yaml": "3.7.0", - "json-stable-stringify": "1.0.1", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.5", + "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", + "pluralize": "7.0.0", + "progress": "2.0.0", "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", + "semver": "5.5.0", + "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "table": "4.0.2", + "text-table": "0.2.0" }, "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "1.0.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.2.0", - "figures": "1.7.0", - "lodash": "4.17.5", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, - "requires": { - "glob": "7.1.2", - "interpret": "1.1.0", - "rechoir": "0.6.2" - } - }, - "strip-bom": { + "ansi-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "globals": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" } } } }, "eslint-config-habitrpg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-habitrpg/-/eslint-config-habitrpg-3.0.0.tgz", - "integrity": "sha1-fPq7yR9b084PAMCpo1Ccorl3O+0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-habitrpg/-/eslint-config-habitrpg-4.0.0.tgz", + "integrity": "sha512-vZc/KjnNVL2BkDBQaQBF9JV16cnZyKa6djCCqH6iKhp8Uuye8Bym3eeLNEcnGkOtZfzJE61hDqiPZXQk7BiXJQ==", "dev": true, "requires": { "eslint-plugin-lodash": "2.6.1", @@ -5396,12 +5442,13 @@ } }, "eslint-friendly-formatter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/eslint-friendly-formatter/-/eslint-friendly-formatter-2.0.7.tgz", - "integrity": "sha1-ZX+VoZr0mJY2r+uxzJ3mzrvQiO4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-friendly-formatter/-/eslint-friendly-formatter-3.0.0.tgz", + "integrity": "sha1-J4h0Q1psRuwdlPoLH/SU4w7wQpA=", "dev": true, "requires": { "chalk": "1.1.3", + "coalescy": "1.0.0", "extend": "3.0.1", "minimist": "1.2.0", "text-table": "0.2.0" @@ -5455,9 +5502,9 @@ } }, "eslint-plugin-html": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-2.0.3.tgz", - "integrity": "sha1-fImIOrDIX6XSi2ZqFKTpBqqQuJc=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.2.tgz", + "integrity": "sha512-CrQd0F8GWdNWnu4PFrYZl+LjUCXNVy2h0uhDMtnf/7VKc9HRcnkXSrlg0BSGfptZPSzmwnnwCaREAa9+fnQhYw==", "dev": true, "requires": { "htmlparser2": "3.9.2" @@ -5507,6 +5554,27 @@ "ramda": "0.24.1" } }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + } + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, "espree": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", @@ -5543,7 +5611,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, "requires": { "estraverse": "4.2.0", "object-assign": "4.1.1" @@ -5552,8 +5619,7 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" } } }, @@ -5572,16 +5638,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.38" - } - }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", @@ -5687,12 +5743,6 @@ "meow": "3.7.0" } }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", @@ -7385,6 +7435,12 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -7426,6 +7482,12 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, "get-pixels": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.0.tgz", @@ -7555,12 +7617,6 @@ "logalot": "2.1.0" } }, - "gitbook-plugin-github": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gitbook-plugin-github/-/gitbook-plugin-github-2.0.0.tgz", - "integrity": "sha1-UWbnY8/MQC1DKIC3pshcHFS1ao0=", - "dev": true - }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -7839,12 +7895,10 @@ } }, "gulp-babel": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.3.tgz", - "integrity": "sha512-tm15R3rt4gO59WXCuqrwf4QXJM9VIJC+0J2NPYSC6xZn+cZRD5y5RPGAiHaDxCJq7Rz5BDljlrk3cEjWADF+wQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-7.0.1.tgz", + "integrity": "sha512-UqHS3AdxZyJCRxqnAX603Dj3k/Wx6hzcgmav3QcxvsIFq3Y8ZkU7iXd0O+JwD5ivqCc6o0r1S7tCB/xxLnuSNw==", "requires": { - "babel-core": "6.26.0", - "object-assign": "4.1.1", "plugin-error": "1.0.1", "replace-ext": "0.0.1", "through2": "2.0.3", @@ -10236,6 +10290,12 @@ "jsonify": "0.0.0" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -10520,6 +10580,31 @@ "sinon-chai": "2.14.0" }, "dependencies": { + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + }, + "dependencies": { + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + } + } + }, + "chai-as-promised": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-5.3.0.tgz", + "integrity": "sha1-CdekApCKpw39vq1T5YU/x50+8hw=", + "dev": true + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -12618,16 +12703,58 @@ } }, "monk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/monk/-/monk-4.1.0.tgz", - "integrity": "sha1-x+VA6GquaQ1xLD4KtwYa2LpaOio=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/monk/-/monk-6.0.5.tgz", + "integrity": "sha512-NEygZ2fhRkPE9zxyOT/GhEYKIGClMCQ+StsTruZSlAWf1aRsgvdu8suVvOj3KWfdiOtsIMs9gg8eyyVHPNWRwg==", "dev": true, "requires": { "debug": "2.6.9", - "gitbook-plugin-github": "2.0.0", - "mongodb": "2.2.34" + "mongodb": "2.2.34", + "monk-middleware-cast-ids": "0.2.1", + "monk-middleware-fields": "0.2.0", + "monk-middleware-handle-callback": "0.2.2", + "monk-middleware-options": "0.2.1", + "monk-middleware-query": "0.2.0", + "monk-middleware-wait-for-connection": "0.2.0", + "object-assign": "4.1.1" } }, + "monk-middleware-cast-ids": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/monk-middleware-cast-ids/-/monk-middleware-cast-ids-0.2.1.tgz", + "integrity": "sha1-QMQOWmyzPM7cKJIglDJ17ohhxSk=", + "dev": true + }, + "monk-middleware-fields": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/monk-middleware-fields/-/monk-middleware-fields-0.2.0.tgz", + "integrity": "sha1-/2N6819ZSIecyyvhWpE2CRG+psE=", + "dev": true + }, + "monk-middleware-handle-callback": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/monk-middleware-handle-callback/-/monk-middleware-handle-callback-0.2.2.tgz", + "integrity": "sha512-5hBynb7asZ2uw9XVze7C3XH0zXT51yFDvYydk/5HnWWzh2NLglDSiKDcX0yLKPHzFgiq+5Z4Laq5fFVnFsmm8w==", + "dev": true + }, + "monk-middleware-options": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/monk-middleware-options/-/monk-middleware-options-0.2.1.tgz", + "integrity": "sha1-WNrhxRjUZjbr3/UG+t/Hc7tEKIY=", + "dev": true + }, + "monk-middleware-query": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/monk-middleware-query/-/monk-middleware-query-0.2.0.tgz", + "integrity": "sha1-qSbGd9SlYgxiFRsKVtDAwVFnWHQ=", + "dev": true + }, + "monk-middleware-wait-for-connection": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/monk-middleware-wait-for-connection/-/monk-middleware-wait-for-connection-0.2.0.tgz", + "integrity": "sha1-MSlY0w5Yi1fQl1TdfJe0hDMWg1o=", + "dev": true + }, "morgan": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", @@ -14475,6 +14602,12 @@ "pinkie-promise": "2.0.1" } }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", @@ -14699,9 +14832,9 @@ } }, "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "pngjs": { @@ -16041,25 +16174,6 @@ "set-immediate-shim": "1.0.1" } }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "mute-stream": "0.0.5" - }, - "dependencies": { - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - } - } - }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -16648,12 +16762,6 @@ "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -17130,10 +17238,21 @@ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } }, "sliced": { "version": "1.0.1", @@ -18207,28 +18326,24 @@ } }, "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", "lodash": "4.17.5", - "slice-ansi": "0.0.4", + "slice-ansi": "1.0.0", "string-width": "2.1.1" }, "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true }, "ansi-regex": { "version": "3.0.0", @@ -18236,36 +18351,6 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - } - } - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -18923,9 +19008,9 @@ } }, "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "type-is": { diff --git a/package.json b/package.json index 1666a4f8d4..85bebd4807 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "axios": "^0.16.0", "axios-progress-bar": "^0.1.7", "babel-core": "^6.0.0", - "babel-eslint": "^7.2.3", + "babel-eslint": "^8.2.1", "babel-loader": "^6.0.0", "babel-plugin-syntax-async-functions": "^6.13.0", "babel-plugin-syntax-dynamic-import": "^6.18.0", @@ -36,8 +36,8 @@ "coupon-code": "^0.4.5", "cross-env": "^5.1.3", "css-loader": "^0.28.0", - "cwait": "^1.1.1", "csv-stringify": "^2.0.1", + "cwait": "^1.1.1", "domain-middleware": "~0.1.0", "express": "^4.16.2", "express-basic-auth": "^1.0.1", @@ -46,7 +46,7 @@ "glob": "^7.1.2", "got": "^6.1.1", "gulp": "^4.0.0", - "gulp-babel": "^6.1.2", + "gulp-babel": "^7.0.1", "gulp-imagemin": "^4.1.0", "gulp-nodemon": "^2.2.1", "gulp.spritesmith": "^6.9.0", @@ -85,8 +85,8 @@ "request": "^2.83.0", "rimraf": "^2.4.3", "sass-loader": "^6.0.2", - "stripe": "^5.4.0", "shelljs": "^0.8.1", + "stripe": "^5.4.0", "superagent": "^3.4.3", "svg-inline-loader": "^0.7.1", "svg-url-loader": "^2.0.2", @@ -142,18 +142,18 @@ }, "devDependencies": { "babel-plugin-istanbul": "^4.0.0", - "chai": "^3.4.0", - "chai-as-promised": "^5.1.0", + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", "chalk": "^2.3.0", "chromedriver": "^2.27.2", "connect-history-api-fallback": "^1.1.0", "coveralls": "^3.0.0", "cross-spawn": "^6.0.4", - "eslint": "^3.0.0", - "eslint-config-habitrpg": "^3.0.0", - "eslint-friendly-formatter": "^2.0.5", + "eslint": "^4.17.0", + "eslint-config-habitrpg": "^4.0.0", + "eslint-friendly-formatter": "^3.0.0", "eslint-loader": "^1.3.0", - "eslint-plugin-html": "^2.0.0", + "eslint-plugin-html": "^4.0.2", "eslint-plugin-mocha": "^4.7.0", "eventsource-polyfill": "^0.9.6", "expect.js": "^0.3.1", @@ -173,7 +173,7 @@ "karma-webpack": "^2.0.2", "lcov-result-merger": "^2.0.0", "mocha": "^5.0.0", - "monk": "^4.0.0", + "monk": "^6.0.5", "nightwatch": "^0.9.12", "phantomjs-prebuilt": "^2.1.12", "require-again": "^2.0.0", diff --git a/scripts/paypalBillingSetup.js b/scripts/paypalBillingSetup.js index 78fcedce2e..b941254420 100644 --- a/scripts/paypalBillingSetup.js +++ b/scripts/paypalBillingSetup.js @@ -1,111 +1,120 @@ -require("babel-register"); -require("babel-polyfill"); +require('babel-register'); +require('babel-polyfill'); + // This file is used for creating paypal billing plans. PayPal doesn't have a web interface for setting up recurring // payment plan definitions, instead you have to create it via their REST SDK and keep it updated the same way. So this // file will be used once for initing your billing plan (then you get the resultant plan.id to store in config.json), // and once for any time you need to edit the plan thereafter -var path = require('path'); -var nconf = require('nconf'); -var _ = require('lodash'); -var paypal = require('paypal-rest-sdk'); -var blocks = require('../website/common').content.subscriptionBlocks; -var live = nconf.get('PAYPAL:mode')=='live'; +/* eslint-disable no-console, camelcase, no-case-declarations */ + +const path = require('path'); +const nconf = require('nconf'); +const _ = require('lodash'); +const paypal = require('paypal-rest-sdk'); +const blocks = require('../website/common').content.subscriptionBlocks; +const live = nconf.get('PAYPAL:mode') === 'live'; nconf.argv().env().file('user', path.join(path.resolve(__dirname, '../config.json'))); -var OP = 'create'; // list create update remove +let OP = 'create'; // list create update remove paypal.configure({ - 'mode': nconf.get("PAYPAL:mode"), //sandbox or live - 'client_id': nconf.get("PAYPAL:client_id"), - 'client_secret': nconf.get("PAYPAL:client_secret") + mode: nconf.get('PAYPAL:mode'), // sandbox or live + client_id: nconf.get('PAYPAL:client_id'), + client_secret: nconf.get('PAYPAL:client_secret'), }); // https://developer.paypal.com/docs/api/#billing-plans-and-agreements -var billingPlanTitle ="Habitica Subscription"; -var billingPlanAttributes = { - "name": billingPlanTitle, - "description": billingPlanTitle, - "type": "INFINITE", - "merchant_preferences": { - "auto_bill_amount": "yes", - "cancel_url": live ? 'https://habitica.com' : 'http://localhost:3000', - "return_url": (live ? 'https://habitica.com' : 'http://localhost:3000') + '/paypal/subscribe/success' +let billingPlanTitle = 'Habitica Subscription'; +let billingPlanAttributes = { + name: billingPlanTitle, + description: billingPlanTitle, + type: 'INFINITE', + merchant_preferences: { + auto_bill_amount: 'yes', + cancel_url: live ? 'https://habitica.com' : 'http://localhost:3000', + return_url: `${live ? 'https://habitica.com' : 'http://localhost:3000' }/paypal/subscribe/success`, }, payment_definitions: [{ - "type": "REGULAR", - "frequency": "MONTH", - "cycles": "0" - }] + type: 'REGULAR', + frequency: 'MONTH', + cycles: '0', + }], }; -_.each(blocks, function(block){ + +_.each(blocks, (block) => { block.definition = _.cloneDeep(billingPlanAttributes); _.merge(block.definition.payment_definitions[0], { - "name": billingPlanTitle + ' ($'+block.price+' every '+block.months+' months, recurring)', - "frequency_interval": ""+block.months, - "amount": { - "currency": "USD", - "value": ""+block.price - } + name: `${billingPlanTitle } ($${block.price} every ${block.months} months, recurring)`, + frequency_interval: `${block.months}`, + amount: { + currency: 'USD', + value: `${block.price}`, + }, }); -}) +}); // @TODO: Add cli library for this -switch(OP) { - case "list": - paypal.billingPlan.list({status: 'ACTIVE'}, function(err, plans){ - console.log({err:err, plans:plans}); +switch (OP) { + case 'list': + paypal.billingPlan.list({status: 'ACTIVE'}, (err, plans) => { + console.log({err, plans}); }); break; - case "get": - paypal.billingPlan.get(nconf.get("PAYPAL:billing_plans:12"), function (err, plan) { - console.log({err:err, plan:plan}); - }) + case 'get': + paypal.billingPlan.get(nconf.get('PAYPAL:billing_plans:12'), (err, plan) => { + console.log({err, plan}); + }); break; - case "update": - var update = { - "op": "replace", - "path": "/merchant_preferences", - "value": { - "cancel_url": "https://habitica.com" - } + case 'update': + let updatePayload = { + op: 'replace', + path: '/merchant_preferences', + value: { + cancel_url: 'https://habitica.com', + }, }; - paypal.billingPlan.update(nconf.get("PAYPAL:billing_plans:12"), update, function (err, res) { - console.log({err:err, plan:res}); + paypal.billingPlan.update(nconf.get('PAYPAL:billing_plans:12'), updatePayload, (err, res) => { + console.log({err, plan: res}); }); break; - case "create": - paypal.billingPlan.create(blocks["google_6mo"].definition, function(err,plan){ + case 'create': + paypal.billingPlan.create(blocks.google_6mo.definition, (err, plan) => { if (err) return console.log(err); - if (plan.state == "ACTIVE") - return console.log({err:err, plan:plan}); - var billingPlanUpdateAttributes = [{ - "op": "replace", - "path": "/", - "value": { - "state": "ACTIVE" - } + + if (plan.state === 'ACTIVE') { + return console.log({err, plan}); + } + + let billingPlanUpdateAttributes = [{ + op: 'replace', + path: '/', + value: { + state: 'ACTIVE', + }, }]; + // Activate the plan by changing status to Active - paypal.billingPlan.update(plan.id, billingPlanUpdateAttributes, function(err, response){ - console.log({err:err, response:response, id:plan.id}); + paypal.billingPlan.update(plan.id, billingPlanUpdateAttributes, (err2, response) => { + console.log({err: err2, response, id: plan.id}); }); }); break; - case "remove": break; + + case 'remove': break; case 'create-webprofile': let webexpinfo = { - "name": "HabiticaProfile", - "input_fields": { - "no_shipping": 1, + name: 'HabiticaProfile', + input_fields: { + no_shipping: 1, }, }; paypal.webProfile.create(webexpinfo, (error, result) => { - console.log(error, result) - }) + console.log(error, result); + }); break; -} +} \ No newline at end of file diff --git a/test/api/v3/integration/challenges/POST-challenges_challengeId_winner_winnerId.test.js b/test/api/v3/integration/challenges/POST-challenges_challengeId_winner_winnerId.test.js index e0dc561c66..19e8deaf12 100644 --- a/test/api/v3/integration/challenges/POST-challenges_challengeId_winner_winnerId.test.js +++ b/test/api/v3/integration/challenges/POST-challenges_challengeId_winner_winnerId.test.js @@ -99,7 +99,7 @@ describe('POST /challenges/:challengeId/winner/:winnerId', () => { await sleep(0.5); - await expect(winningUser.sync()).to.eventually.have.deep.property('achievements.challenges').to.include(challenge.name); + await expect(winningUser.sync()).to.eventually.have.nested.property('achievements.challenges').to.include(challenge.name); expect(winningUser.notifications.length).to.equal(2); // 2 because winningUser just joined the challenge, which now awards an achievement expect(winningUser.notifications[1].type).to.equal('WON_CHALLENGE'); }); diff --git a/test/api/v3/integration/chat/POST-chat.test.js b/test/api/v3/integration/chat/POST-chat.test.js index 395c6b88e1..c9b2d97384 100644 --- a/test/api/v3/integration/chat/POST-chat.test.js +++ b/test/api/v3/integration/chat/POST-chat.test.js @@ -119,21 +119,21 @@ describe('POST /chat', () => { it('errors when word is part of a phrase', async () => { let wordInPhrase = `phrase ${testBannedWordMessage} end`; await expect(user.post('/groups/habitrpg/chat', { message: wordInPhrase})) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: bannedWordErrorMessage, - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: bannedWordErrorMessage, + }); }); it('errors when word is surrounded by non alphabet characters', async () => { let wordInPhrase = `_!${testBannedWordMessage}@_`; await expect(user.post('/groups/habitrpg/chat', { message: wordInPhrase})) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: bannedWordErrorMessage, - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: bannedWordErrorMessage, + }); }); it('checks error message has the banned words used', async () => { diff --git a/test/api/v3/integration/content/GET-content.test.js b/test/api/v3/integration/content/GET-content.test.js index fad68edae2..1489738577 100644 --- a/test/api/v3/integration/content/GET-content.test.js +++ b/test/api/v3/integration/content/GET-content.test.js @@ -7,19 +7,19 @@ import i18n from '../../../../../website/common/script/i18n'; describe('GET /content', () => { it('returns content (and does not require authentication)', async () => { let res = await requester().get('/content'); - expect(res).to.have.deep.property('backgrounds.backgrounds062014.beach'); + expect(res).to.have.nested.property('backgrounds.backgrounds062014.beach'); expect(res.backgrounds.backgrounds062014.beach.text).to.equal(t('backgroundBeachText')); }); it('returns content not in English', async () => { let res = await requester().get('/content?language=de'); - expect(res).to.have.deep.property('backgrounds.backgrounds062014.beach'); + expect(res).to.have.nested.property('backgrounds.backgrounds062014.beach'); expect(res.backgrounds.backgrounds062014.beach.text).to.equal(i18n.t('backgroundBeachText', 'de')); }); it('falls back to English if the desired language is not found', async () => { let res = await requester().get('/content?language=wrong'); - expect(res).to.have.deep.property('backgrounds.backgrounds062014.beach'); + expect(res).to.have.nested.property('backgrounds.backgrounds062014.beach'); expect(res.backgrounds.backgrounds062014.beach.text).to.equal(t('backgroundBeachText')); }); }); diff --git a/test/api/v3/integration/debug/POST-debug_addTenGems.test.js b/test/api/v3/integration/debug/POST-debug_addTenGems.test.js index fd01aea5d3..d1a3b39eb2 100644 --- a/test/api/v3/integration/debug/POST-debug_addTenGems.test.js +++ b/test/api/v3/integration/debug/POST-debug_addTenGems.test.js @@ -26,10 +26,10 @@ describe('POST /debug/add-ten-gems', () => { nconf.set('IS_PROD', true); await expect(userToGainTenGems.post('/debug/add-ten-gems')) - .eventually.be.rejected.and.to.deep.equal({ - code: 404, - error: 'NotFound', - message: 'Not found.', - }); + .eventually.be.rejected.and.to.deep.equal({ + code: 404, + error: 'NotFound', + message: 'Not found.', + }); }); }); diff --git a/test/api/v3/integration/debug/POST-debug_make-admin.test.js b/test/api/v3/integration/debug/POST-debug_make-admin.test.js index 98818fb07e..0696b6469f 100644 --- a/test/api/v3/integration/debug/POST-debug_make-admin.test.js +++ b/test/api/v3/integration/debug/POST-debug_make-admin.test.js @@ -26,10 +26,10 @@ describe('POST /debug/make-admin (pended for v3 prod testing)', () => { nconf.set('IS_PROD', true); await expect(user.post('/debug/make-admin')) - .eventually.be.rejected.and.to.deep.equal({ - code: 404, - error: 'NotFound', - message: 'Not found.', - }); + .eventually.be.rejected.and.to.deep.equal({ + code: 404, + error: 'NotFound', + message: 'Not found.', + }); }); }); diff --git a/test/api/v3/integration/debug/POST-debug_modify-inventory.test.js b/test/api/v3/integration/debug/POST-debug_modify-inventory.test.js index 93f9081492..7047150477 100644 --- a/test/api/v3/integration/debug/POST-debug_modify-inventory.test.js +++ b/test/api/v3/integration/debug/POST-debug_modify-inventory.test.js @@ -151,10 +151,10 @@ describe('POST /debug/modify-inventory', () => { nconf.set('IS_PROD', true); await expect(user.post('/debug/modify-inventory')) - .eventually.be.rejected.and.to.deep.equal({ - code: 404, - error: 'NotFound', - message: 'Not found.', - }); + .eventually.be.rejected.and.to.deep.equal({ + code: 404, + error: 'NotFound', + message: 'Not found.', + }); }); }); diff --git a/test/api/v3/integration/debug/POST-debug_quest-progress.test.js b/test/api/v3/integration/debug/POST-debug_quest-progress.test.js index 6f10b78ba4..90c14c4470 100644 --- a/test/api/v3/integration/debug/POST-debug_quest-progress.test.js +++ b/test/api/v3/integration/debug/POST-debug_quest-progress.test.js @@ -16,11 +16,11 @@ describe('POST /debug/quest-progress', () => { it('errors if user is not on a quest', async () => { await expect(user.post('/debug/quest-progress')) - .to.eventually.be.rejected.and.to.deep.equal({ - code: 400, - error: 'BadRequest', - message: 'User is not on a valid quest.', - }); + .to.eventually.be.rejected.and.to.deep.equal({ + code: 400, + error: 'BadRequest', + message: 'User is not on a valid quest.', + }); }); it('increases boss quest progress by 1000', async () => { @@ -51,10 +51,10 @@ describe('POST /debug/quest-progress', () => { nconf.set('IS_PROD', true); await expect(user.post('/debug/quest-progress')) - .eventually.be.rejected.and.to.deep.equal({ - code: 404, - error: 'NotFound', - message: 'Not found.', - }); + .eventually.be.rejected.and.to.deep.equal({ + code: 404, + error: 'NotFound', + message: 'Not found.', + }); }); }); diff --git a/test/api/v3/integration/debug/POST-debug_set-cron.test.js b/test/api/v3/integration/debug/POST-debug_set-cron.test.js index c737831d95..10fe75fa14 100644 --- a/test/api/v3/integration/debug/POST-debug_set-cron.test.js +++ b/test/api/v3/integration/debug/POST-debug_set-cron.test.js @@ -30,10 +30,10 @@ describe('POST /debug/set-cron', () => { nconf.set('IS_PROD', true); await expect(user.post('/debug/set-cron')) - .eventually.be.rejected.and.to.deep.equal({ - code: 404, - error: 'NotFound', - message: 'Not found.', - }); + .eventually.be.rejected.and.to.deep.equal({ + code: 404, + error: 'NotFound', + message: 'Not found.', + }); }); }); diff --git a/test/api/v3/integration/groups/GET-groups.test.js b/test/api/v3/integration/groups/GET-groups.test.js index b7c8fbd942..10821a7dcb 100644 --- a/test/api/v3/integration/groups/GET-groups.test.js +++ b/test/api/v3/integration/groups/GET-groups.test.js @@ -93,14 +93,14 @@ describe('GET /groups', () => { it('returns only the tavern when tavern passed in as query', async () => { await expect(user.get('/groups?type=tavern')) .to.eventually.have.a.lengthOf(1) - .and.to.have.deep.property('[0]') + .and.to.have.nested.property('[0]') .and.to.have.property('_id', TAVERN_ID); }); it('returns only the user\'s party when party passed in as query', async () => { await expect(user.get('/groups?type=party')) .to.eventually.have.a.lengthOf(1) - .and.to.have.deep.property('[0]'); + .and.to.have.nested.property('[0]'); }); it('returns all public guilds when publicGuilds passed in as query', async () => { diff --git a/test/api/v3/integration/groups/POST-groups_groupId_join.test.js b/test/api/v3/integration/groups/POST-groups_groupId_join.test.js index 33b1b7f5a4..a06f40bc4e 100644 --- a/test/api/v3/integration/groups/POST-groups_groupId_join.test.js +++ b/test/api/v3/integration/groups/POST-groups_groupId_join.test.js @@ -58,7 +58,7 @@ describe('POST /group/:groupId/join', () => { await joiningUser.post(`/groups/${publicGuild._id}/join`); - await expect(joiningUser.get(`/groups/${publicGuild._id}`)).to.eventually.have.deep.property('leader._id', joiningUser._id); + await expect(joiningUser.get(`/groups/${publicGuild._id}`)).to.eventually.have.nested.property('leader._id', joiningUser._id); }); it('increments memberCount when joining guilds', async () => { @@ -72,7 +72,7 @@ describe('POST /group/:groupId/join', () => { it('awards Joined Guild achievement', async () => { await joiningUser.post(`/groups/${publicGuild._id}/join`); - await expect(joiningUser.get('/user')).to.eventually.have.deep.property('achievements.joinedGuild', true); + await expect(joiningUser.get('/user')).to.eventually.have.nested.property('achievements.joinedGuild', true); }); }); @@ -115,7 +115,7 @@ describe('POST /group/:groupId/join', () => { await invitedUser.post(`/groups/${guild._id}/join`); await expect(invitedUser.get('/user')) - .to.eventually.have.deep.property('invitations.guilds') + .to.eventually.have.nested.property('invitations.guilds') .to.not.include({id: guild._id}); }); @@ -130,7 +130,7 @@ describe('POST /group/:groupId/join', () => { it('does not give basilist quest to inviter when joining a guild', async () => { await invitedUser.post(`/groups/${guild._id}/join`); - await expect(user.get('/user')).to.eventually.not.have.deep.property('items.quests.basilist'); + await expect(user.get('/user')).to.eventually.not.have.nested.property('items.quests.basilist'); }); it('does not increment basilist quest count to inviter with basilist when joining a guild', async () => { @@ -138,7 +138,7 @@ describe('POST /group/:groupId/join', () => { await invitedUser.post(`/groups/${guild._id}/join`); - await expect(user.get('/user')).to.eventually.have.deep.property('items.quests.basilist', 1); + await expect(user.get('/user')).to.eventually.have.nested.property('items.quests.basilist', 1); }); it('notifies inviting user that their invitation was accepted', async () => { @@ -160,7 +160,7 @@ describe('POST /group/:groupId/join', () => { it('awards Joined Guild achievement', async () => { await invitedUser.post(`/groups/${guild._id}/join`); - await expect(invitedUser.get('/user')).to.eventually.have.deep.property('achievements.joinedGuild', true); + await expect(invitedUser.get('/user')).to.eventually.have.nested.property('achievements.joinedGuild', true); }); }); }); @@ -197,7 +197,7 @@ describe('POST /group/:groupId/join', () => { it('allows invited user to join party', async () => { await invitedUser.post(`/groups/${party._id}/join`); - await expect(invitedUser.get('/user')).to.eventually.have.deep.property('party._id', party._id); + await expect(invitedUser.get('/user')).to.eventually.have.nested.property('party._id', party._id); }); it('notifies inviting user that their invitation was accepted', async () => { @@ -220,7 +220,7 @@ describe('POST /group/:groupId/join', () => { it('clears invitation from user when joining party', async () => { await invitedUser.post(`/groups/${party._id}/join`); - await expect(invitedUser.get('/user')).to.eventually.not.have.deep.property('invitations.parties[0].id'); + await expect(invitedUser.get('/user')).to.eventually.not.have.nested.property('invitations.parties[0].id'); }); it('increments memberCount when joining party', async () => { @@ -234,7 +234,7 @@ describe('POST /group/:groupId/join', () => { it('gives basilist quest item to the inviter when joining a party', async () => { await invitedUser.post(`/groups/${party._id}/join`); - await expect(user.get('/user')).to.eventually.have.deep.property('items.quests.basilist', 1); + await expect(user.get('/user')).to.eventually.have.nested.property('items.quests.basilist', 1); }); it('increments basilist quest item count to inviter when joining a party', async () => { @@ -242,7 +242,7 @@ describe('POST /group/:groupId/join', () => { await invitedUser.post(`/groups/${party._id}/join`); - await expect(user.get('/user')).to.eventually.have.deep.property('items.quests.basilist', 2); + await expect(user.get('/user')).to.eventually.have.nested.property('items.quests.basilist', 2); }); it('deletes previous party where the user was the only member', async () => { @@ -258,7 +258,7 @@ describe('POST /group/:groupId/join', () => { }); await userToInvite.post(`/groups/${party._id}/join`); - await expect(user.get('/user')).to.eventually.have.deep.property('party._id', party._id); + await expect(user.get('/user')).to.eventually.have.nested.property('party._id', party._id); await expect(checkExistence('groups', oldParty._id)).to.eventually.equal(false); }); @@ -273,8 +273,8 @@ describe('POST /group/:groupId/join', () => { await invitedUser.sync(); await party.sync(); - expect(invitedUser).to.have.deep.property('party.quest.RSVPNeeded', true); - expect(invitedUser).to.have.deep.property('party.quest.key', party.quest.key); + expect(invitedUser).to.have.nested.property('party.quest.RSVPNeeded', true); + expect(invitedUser).to.have.nested.property('party.quest.key', party.quest.key); expect(party.quest.members[invitedUser._id]).to.be.null; }); }); @@ -300,16 +300,16 @@ describe('POST /group/:groupId/join', () => { await member.sync(); await leader.sync(); - expect(member).to.have.deep.property('achievements.partyUp', true); - expect(leader).to.have.deep.property('achievements.partyUp', true); + expect(member).to.have.nested.property('achievements.partyUp', true); + expect(leader).to.have.nested.property('achievements.partyUp', true); }); it('does not award Party On achievement to party of size 2', async () => { await member.sync(); await leader.sync(); - expect(member).to.not.have.deep.property('achievements.partyOn'); - expect(leader).to.not.have.deep.property('achievements.partyOn'); + expect(member).to.not.have.nested.property('achievements.partyOn'); + expect(leader).to.not.have.nested.property('achievements.partyOn'); }); it('awards Party On achievement to party of size 4', async () => { @@ -324,8 +324,8 @@ describe('POST /group/:groupId/join', () => { await member.sync(); await leader.sync(); - expect(member).to.have.deep.property('achievements.partyOn', true); - expect(leader).to.have.deep.property('achievements.partyOn', true); + expect(member).to.have.nested.property('achievements.partyOn', true); + expect(leader).to.have.nested.property('achievements.partyOn', true); }); }); }); diff --git a/test/api/v3/integration/groups/POST-groups_groupId_leave.js b/test/api/v3/integration/groups/POST-groups_groupId_leave.js index c9dd64e7a9..615b5e01e2 100644 --- a/test/api/v3/integration/groups/POST-groups_groupId_leave.js +++ b/test/api/v3/integration/groups/POST-groups_groupId_leave.js @@ -85,7 +85,7 @@ describe('POST /groups/:groupId/leave', () => { expect(leader.notifications.find(n => { return n.type === 'NEW_CHAT_MESSAGE' && n.data.group.id === groupToLeave._id; })).to.not.exist; - expect(leader.newMessages[groupToLeave._id]).to.be.empty; + expect(leader.newMessages[groupToLeave._id]).to.be.undefined; }); context('with challenges', () => { @@ -257,7 +257,7 @@ describe('POST /groups/:groupId/leave', () => { let userWithoutInvitation = await invitedUser.get('/user'); - expect(userWithoutInvitation.invitations.parties[0]).to.be.empty; + expect(userWithoutInvitation.invitations.parties[0]).to.be.undefined; }); }); diff --git a/test/api/v3/integration/groups/POST-groups_groupId_reject.test.js b/test/api/v3/integration/groups/POST-groups_groupId_reject.test.js index 626c6ff896..7f1e31df85 100644 --- a/test/api/v3/integration/groups/POST-groups_groupId_reject.test.js +++ b/test/api/v3/integration/groups/POST-groups_groupId_reject.test.js @@ -36,7 +36,7 @@ describe('POST /group/:groupId/reject-invite', () => { await invitedUser.post(`/groups/${publicGuild._id}/reject-invite`); await expect(invitedUser.get('/user')) - .to.eventually.have.deep.property('invitations.guilds') + .to.eventually.have.nested.property('invitations.guilds') .to.not.include({id: publicGuild._id}); }); }); @@ -72,7 +72,7 @@ describe('POST /group/:groupId/reject-invite', () => { await invitedUser.post(`/groups/${guild._id}/reject-invite`); await expect(invitedUser.get('/user')) - .to.eventually.have.deep.property('invitations.guilds') + .to.eventually.have.nested.property('invitations.guilds') .to.not.include({id: guild._id}); }); }); @@ -107,7 +107,7 @@ describe('POST /group/:groupId/reject-invite', () => { it('clears invitation from user', async () => { await invitedUser.post(`/groups/${party._id}/reject-invite`); - await expect(invitedUser.get('/user')).to.eventually.not.have.deep.property('invitations.parties[0].id'); + await expect(invitedUser.get('/user')).to.eventually.not.have.nested.property('invitations.parties[0].id'); }); }); }); diff --git a/test/api/v3/integration/groups/POST-groups_id_removeMember.test.js b/test/api/v3/integration/groups/POST-groups_id_removeMember.test.js index 6fb2af0704..97819e7a41 100644 --- a/test/api/v3/integration/groups/POST-groups_id_removeMember.test.js +++ b/test/api/v3/integration/groups/POST-groups_id_removeMember.test.js @@ -184,7 +184,7 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => { let invitedUserWithoutInvite = await partyInvitedUser.get('/user'); - expect(invitedUserWithoutInvite.invitations.parties[0]).to.be.empty; + expect(invitedUserWithoutInvite.invitations.parties[0]).to.be.undefined; }); it('removes new messages from a member who is removed', async () => { @@ -203,7 +203,7 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => { expect(removedMember.notifications.find(n => { return n.type === 'NEW_CHAT_MESSAGE' && n.data.group.id === party._id; })).to.not.exist; - expect(removedMember.newMessages[party._id]).to.be.empty; + expect(removedMember.newMessages[party._id]).to.be.undefined; }); it('removes user from quest when removing user from party after quest starts', async () => { diff --git a/test/api/v3/integration/groups/POST-groups_invite.test.js b/test/api/v3/integration/groups/POST-groups_invite.test.js index 3de01d0d40..385fa431a6 100644 --- a/test/api/v3/integration/groups/POST-groups_invite.test.js +++ b/test/api/v3/integration/groups/POST-groups_invite.test.js @@ -30,22 +30,22 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids: [fakeID], })) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('userWithIDNotFound', {userId: fakeID}), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('userWithIDNotFound', {userId: fakeID}), + }); }); it('returns an error when inviting yourself to a group', async () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids: [inviter._id], })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('cannotInviteSelfToGroup'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('cannotInviteSelfToGroup'), + }); }); it('returns an error when uuids is not an array', async () => { @@ -54,11 +54,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids: {fakeID}, })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('uuidsMustBeAnArray'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('uuidsMustBeAnArray'), + }); }); it('returns an error when uuids and emails are empty', async () => { @@ -66,22 +66,22 @@ describe('Post /groups/:groupId/invite', () => { emails: [], uuids: [], })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('inviteMustNotBeEmpty'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('inviteMustNotBeEmpty'), + }); }); it('returns an error when uuids is empty and emails is not passed', async () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids: [], })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('inviteMissingUuid'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('inviteMissingUuid'), + }); }); it('returns an error when there are more than INVITES_LIMIT uuids', async () => { @@ -94,11 +94,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids, })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}), + }); }); it('invites a user to a group by uuid', async () => { @@ -114,7 +114,7 @@ describe('Post /groups/:groupId/invite', () => { }]); await expect(userToInvite.get('/user')) - .to.eventually.have.deep.property('invitations.guilds[0].id', group._id); + .to.eventually.have.nested.property('invitations.guilds[0].id', group._id); }); it('invites multiple users to a group by uuid', async () => { @@ -138,8 +138,8 @@ describe('Post /groups/:groupId/invite', () => { }, ]); - await expect(userToInvite.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id); - await expect(userToInvite2.get('/user')).to.eventually.have.deep.property('invitations.guilds[0].id', group._id); + await expect(userToInvite.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id); + await expect(userToInvite2.get('/user')).to.eventually.have.nested.property('invitations.guilds[0].id', group._id); }); it('returns an error when inviting multiple users and a user is not found', async () => { @@ -149,11 +149,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids: [userToInvite._id, fakeID], })) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('userWithIDNotFound', {userId: fakeID}), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('userWithIDNotFound', {userId: fakeID}), + }); }); }); @@ -164,33 +164,33 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { emails: [{name: 'test'}], })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('inviteMissingEmail'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('inviteMissingEmail'), + }); }); it('returns an error when emails is not an array', async () => { await expect(inviter.post(`/groups/${group._id}/invite`, { emails: {testInvite}, })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('emailsMustBeAnArray'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('emailsMustBeAnArray'), + }); }); it('returns an error when emails is empty and uuids is not passed', async () => { await expect(inviter.post(`/groups/${group._id}/invite`, { emails: [], })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('inviteMissingEmail'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('inviteMissingEmail'), + }); }); it('returns an error when there are more than INVITES_LIMIT emails', async () => { @@ -203,11 +203,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { emails, })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}), + }); }); it('returns an error when a user has sent the max number of email invites', async () => { @@ -224,11 +224,11 @@ describe('Post /groups/:groupId/invite', () => { emails: [testInvite], inviter: 'inviter name', })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('inviteLimitReached', {techAssistanceEmail: nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL')}), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('inviteLimitReached', {techAssistanceEmail: nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL')}), + }); }); it('invites a user to a group by email', async () => { @@ -258,11 +258,11 @@ describe('Post /groups/:groupId/invite', () => { describe('user and email invites', () => { it('returns an error when emails and uuids are not provided', async () => { await expect(inviter.post(`/groups/${group._id}/invite`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('canOnlyInviteEmailUuid'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('canOnlyInviteEmailUuid'), + }); }); it('returns an error when there are more than INVITES_LIMIT uuids and emails', async () => { @@ -281,11 +281,11 @@ describe('Post /groups/:groupId/invite', () => { emails, uuids, })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('canOnlyInviteMaxInvites', {maxInvites: INVITES_LIMIT}), + }); }); it('invites users to a group by uuid and email', async () => { @@ -330,11 +330,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids: [userToInivite._id], })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('userAlreadyInvitedToGroup'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('userAlreadyInvitedToGroup'), + }); }); it('returns an error when invited user is already in the group', async () => { @@ -347,11 +347,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${group._id}/invite`, { uuids: [userToInvite._id], })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('userAlreadyInGroup'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('userAlreadyInGroup'), + }); }); it('allows 30+ members in a guild', async () => { @@ -380,11 +380,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(nonGroupLeader.post(`/groups/${group._id}/invite`, { uuids: [userToInvite._id], })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('onlyGroupLeaderCanInviteToGroupPlan'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('onlyGroupLeaderCanInviteToGroupPlan'), + }); }); }); @@ -407,11 +407,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${party._id}/invite`, { uuids: [userToInvite._id], })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('userAlreadyPendingInvitation'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('userAlreadyPendingInvitation'), + }); }); it('returns an error when invited user is already in a party of more than 1 member', async () => { @@ -426,11 +426,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${party._id}/invite`, { uuids: [userToInvite._id], })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('userAlreadyInAParty'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('userAlreadyInAParty'), + }); }); it('allow inviting a user to a party if they are partying solo', async () => { @@ -512,11 +512,11 @@ describe('Post /groups/:groupId/invite', () => { await expect(inviter.post(`/groups/${party._id}/invite`, { uuids: generatedInvites.map(invite => invite._id), })) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('partyExceedsMembersLimit', {maxMembersParty: PARTY_LIMIT_MEMBERS}), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('partyExceedsMembersLimit', {maxMembersParty: PARTY_LIMIT_MEMBERS}), + }); }); }); }); diff --git a/test/api/v3/integration/news/POST-news_tell_me_later.test.js b/test/api/v3/integration/news/POST-news_tell_me_later.test.js index 47444574c4..491a33f210 100644 --- a/test/api/v3/integration/news/POST-news_tell_me_later.test.js +++ b/test/api/v3/integration/news/POST-news_tell_me_later.test.js @@ -24,7 +24,7 @@ describe('POST /news/tell-me-later', () => { const notification = user.notifications[user.notifications.length - 1]; expect(notification.type).to.equal('NEW_STUFF'); - // should be marked as seen by default so it's not counted in the number of notifications + // should be marked as seen by default so it's not counted in the number of notifications expect(notification.seen).to.equal(true); expect(notification.data.title).to.be.a.string; }); diff --git a/test/api/v3/integration/payments/apple/POST-payments_apple_verifyiap.js b/test/api/v3/integration/payments/apple/POST-payments_apple_verifyiap.js index a5d4c1e769..72ebf915f7 100644 --- a/test/api/v3/integration/payments/apple/POST-payments_apple_verifyiap.js +++ b/test/api/v3/integration/payments/apple/POST-payments_apple_verifyiap.js @@ -26,9 +26,9 @@ describe('payments : apple #verify', () => { }); await user.post(endpoint, { - transaction: { - receipt: 'receipt', - }}); + transaction: { + receipt: 'receipt', + }}); expect(verifyStub).to.be.calledOnce; expect(verifyStub.args[0][0]._id).to.eql(user._id); diff --git a/test/api/v3/integration/quests/POST-groups_groupId_quests_accept.test.js b/test/api/v3/integration/quests/POST-groups_groupId_quests_accept.test.js index ecff25cfd3..9faa405054 100644 --- a/test/api/v3/integration/quests/POST-groups_groupId_quests_accept.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupId_quests_accept.test.js @@ -33,20 +33,20 @@ describe('POST /groups/:groupId/quests/accept', () => { context('failure conditions', () => { it('does not accept quest without an invite', async () => { await expect(leader.post(`/groups/${questingGroup._id}/quests/accept`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('questInviteNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('questInviteNotFound'), + }); }); it('does not accept quest for a group in which user is not a member', async () => { await expect(user.post(`/groups/${questingGroup._id}/quests/accept`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('groupNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('groupNotFound'), + }); }); it('does not accept quest for a guild', async () => { @@ -55,11 +55,11 @@ describe('POST /groups/:groupId/quests/accept', () => { }); await expect(guildLeader.post(`/groups/${guild._id}/quests/accept`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('guildQuestsNotSupported'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('guildQuestsNotSupported'), + }); }); it('does not accept invite twice', async () => { @@ -67,11 +67,11 @@ describe('POST /groups/:groupId/quests/accept', () => { await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('questAlreadyAccepted'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('questAlreadyAccepted'), + }); }); it('clears the invalid invite from the user when the request fails', async () => { @@ -79,11 +79,11 @@ describe('POST /groups/:groupId/quests/accept', () => { await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('questAlreadyAccepted'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('questAlreadyAccepted'), + }); await partyMembers[0].sync(); expect(partyMembers[0].party.quest.RSVPNeeded).to.be.false; @@ -96,11 +96,11 @@ describe('POST /groups/:groupId/quests/accept', () => { await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('questAlreadyUnderway'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('questAlreadyUnderway'), + }); }); }); diff --git a/test/api/v3/integration/quests/POST-groups_groupId_quests_force-start.test.js b/test/api/v3/integration/quests/POST-groups_groupId_quests_force-start.test.js index 76497f50e9..bcbf6a6cf1 100644 --- a/test/api/v3/integration/quests/POST-groups_groupId_quests_force-start.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupId_quests_force-start.test.js @@ -32,11 +32,11 @@ describe('POST /groups/:groupId/quests/force-start', () => { let nonMember = await generateUser(); await expect(nonMember.post(`/groups/${questingGroup._id}/quests/force-start`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('groupNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('groupNotFound'), + }); }); it('does not force start quest for a guild', async () => { @@ -45,20 +45,20 @@ describe('POST /groups/:groupId/quests/force-start', () => { }); await expect(guildLeader.post(`/groups/${guild._id}/quests/force-start`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('guildQuestsNotSupported'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('guildQuestsNotSupported'), + }); }); it('does not force start for a party without a pending quest', async () => { await expect(leader.post(`/groups/${questingGroup._id}/quests/force-start`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('questNotPending'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('questNotPending'), + }); }); it('does not force start for a quest already underway', async () => { @@ -69,22 +69,22 @@ describe('POST /groups/:groupId/quests/force-start', () => { await partyMembers[2].post(`/groups/${questingGroup._id}/quests/accept`); await expect(leader.post(`/groups/${questingGroup._id}/quests/force-start`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('questAlreadyUnderway'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('questAlreadyUnderway'), + }); }); it('does not allow non-quest leader or non-group leader to force start a quest', async () => { await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/force-start`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('questOrGroupLeaderOnlyStartQuest'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('questOrGroupLeaderOnlyStartQuest'), + }); }); }); diff --git a/test/api/v3/integration/quests/POST-groups_groupid_quests_abort.test.js b/test/api/v3/integration/quests/POST-groups_groupid_quests_abort.test.js index 9b5503736b..aa90c5940d 100644 --- a/test/api/v3/integration/quests/POST-groups_groupid_quests_abort.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupid_quests_abort.test.js @@ -42,11 +42,11 @@ describe('POST /groups/:groupId/quests/abort', () => { it('returns an error for a group in which user is not a member', async () => { await expect(user.post(`/groups/${questingGroup._id}/quests/abort`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('groupNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('groupNotFound'), + }); }); it('returns an error when group is a guild', async () => { @@ -55,11 +55,11 @@ describe('POST /groups/:groupId/quests/abort', () => { }); await expect(guildLeader.post(`/groups/${guild._id}/quests/abort`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('guildQuestsNotSupported'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('guildQuestsNotSupported'), + }); }); it('returns an error when quest is not active', async () => { diff --git a/test/api/v3/integration/quests/POST-groups_groupid_quests_cancel.test.js b/test/api/v3/integration/quests/POST-groups_groupid_quests_cancel.test.js index 96d78c9bb4..3a5afe4254 100644 --- a/test/api/v3/integration/quests/POST-groups_groupid_quests_cancel.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupid_quests_cancel.test.js @@ -41,11 +41,11 @@ describe('POST /groups/:groupId/quests/cancel', () => { it('does not reject quest for a group in which user is not a member', async () => { await expect(user.post(`/groups/${questingGroup._id}/quests/cancel`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('groupNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('groupNotFound'), + }); }); it('returns an error when group is a guild', async () => { @@ -54,11 +54,11 @@ describe('POST /groups/:groupId/quests/cancel', () => { }); await expect(guildLeader.post(`/groups/${guild._id}/quests/cancel`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('guildQuestsNotSupported'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('guildQuestsNotSupported'), + }); }); it('returns an error when group is not on a quest', async () => { @@ -74,11 +74,11 @@ describe('POST /groups/:groupId/quests/cancel', () => { await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/cancel`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('onlyLeaderCancelQuest'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('onlyLeaderCancelQuest'), + }); }); it('does not cancel a quest already underway', async () => { @@ -88,11 +88,11 @@ describe('POST /groups/:groupId/quests/cancel', () => { await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`); await expect(leader.post(`/groups/${questingGroup._id}/quests/cancel`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('cantCancelActiveQuest'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('cantCancelActiveQuest'), + }); }); }); diff --git a/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js b/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js index 89c65d0c73..8a2870681d 100644 --- a/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js @@ -41,11 +41,11 @@ describe('POST /groups/:groupId/quests/leave', () => { it('returns an error for a group in which user is not a member', async () => { await expect(user.post(`/groups/${questingGroup._id}/quests/leave`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('groupNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('groupNotFound'), + }); }); it('returns an error when group is a guild', async () => { @@ -54,11 +54,11 @@ describe('POST /groups/:groupId/quests/leave', () => { }); await expect(guildLeader.post(`/groups/${guild._id}/quests/leave`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('guildQuestsNotSupported'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('guildQuestsNotSupported'), + }); }); it('returns an error when quest is not active', async () => { @@ -89,11 +89,11 @@ describe('POST /groups/:groupId/quests/leave', () => { await partyMembers[1].post(`/groups/${questingGroup._id}/quests/reject`); await expect(partyMembers[1].post(`/groups/${questingGroup._id}/quests/leave`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('notPartOfQuest'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('notPartOfQuest'), + }); }); }); diff --git a/test/api/v3/integration/quests/POST-groups_groupid_quests_reject.test.js b/test/api/v3/integration/quests/POST-groups_groupid_quests_reject.test.js index 46dfb5a88d..aacec2598b 100644 --- a/test/api/v3/integration/quests/POST-groups_groupid_quests_reject.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupid_quests_reject.test.js @@ -42,11 +42,11 @@ describe('POST /groups/:groupId/quests/reject', () => { it('does not accept quest for a group in which user is not a member', async () => { await expect(user.post(`/groups/${questingGroup._id}/quests/accept`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('groupNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('groupNotFound'), + }); }); it('returns an error when group is a guild', async () => { @@ -55,11 +55,11 @@ describe('POST /groups/:groupId/quests/reject', () => { }); await expect(guildLeader.post(`/groups/${guild._id}/quests/reject`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('guildQuestsNotSupported'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('guildQuestsNotSupported'), + }); }); it('returns an error when group is not on a quest', async () => { @@ -76,11 +76,11 @@ describe('POST /groups/:groupId/quests/reject', () => { await partyMembers[0].post(`/groups/${questingGroup._id}/quests/reject`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/reject`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('questAlreadyRejected'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('questAlreadyRejected'), + }); }); it('clears the user rsvp needed if the request fails because the request is invalid', async () => { @@ -88,11 +88,11 @@ describe('POST /groups/:groupId/quests/reject', () => { await partyMembers[0].post(`/groups/${questingGroup._id}/quests/reject`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/reject`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('questAlreadyRejected'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('questAlreadyRejected'), + }); await partyMembers[0].sync(); expect(partyMembers[0].party.quest.RSVPNeeded).to.be.false; @@ -103,11 +103,11 @@ describe('POST /groups/:groupId/quests/reject', () => { await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/reject`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('questAlreadyAccepted'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('questAlreadyAccepted'), + }); }); it('does not reject invite for a quest already underway', async () => { @@ -117,11 +117,11 @@ describe('POST /groups/:groupId/quests/reject', () => { await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`); await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/reject`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('questAlreadyUnderway'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('questAlreadyUnderway'), + }); }); }); diff --git a/test/api/v3/integration/tasks/POST-tasks_id_score_direction.test.js b/test/api/v3/integration/tasks/POST-tasks_id_score_direction.test.js index fa435c5e31..458fed6f10 100644 --- a/test/api/v3/integration/tasks/POST-tasks_id_score_direction.test.js +++ b/test/api/v3/integration/tasks/POST-tasks_id_score_direction.test.js @@ -141,11 +141,11 @@ describe('POST /tasks/:id/score/:direction', () => { it('doesn\'t let a todo be completed twice', async () => { await user.post(`/tasks/${todo._id}/score/up`); await expect(user.post(`/tasks/${todo._id}/score/up`)) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('sessionOutdated'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('sessionOutdated'), + }); }); it('doesn\'t let a todo be uncompleted twice', async () => { @@ -380,11 +380,11 @@ describe('POST /tasks/:id/score/:direction', () => { await expect(user.post(`/tasks/${habit._id}/score/up`, { scoreNotes: scoreNotesString, })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('taskScoreNotesTooLong'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('taskScoreNotesTooLong'), + }); }); }); diff --git a/test/api/v3/integration/tasks/POST-tasks_unlink-all_challengeId.test.js b/test/api/v3/integration/tasks/POST-tasks_unlink-all_challengeId.test.js index ee60541017..cd8bec5acc 100644 --- a/test/api/v3/integration/tasks/POST-tasks_unlink-all_challengeId.test.js +++ b/test/api/v3/integration/tasks/POST-tasks_unlink-all_challengeId.test.js @@ -41,30 +41,30 @@ describe('POST /tasks/unlink-all/:challengeId', () => { it('fails if no keep query', async () => { await expect(user.post(`/tasks/unlink-all/${challenge._id}`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('invalidReqParams'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); }); it('fails if invalid challenge id', async () => { await expect(user.post('/tasks/unlink-all/123?keep=remove-all')) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('invalidReqParams'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); }); it('fails on an unbroken challenge', async () => { await user.post(`/tasks/challenge/${challenge._id}`, tasksToTest.daily); await expect(user.post(`/tasks/unlink-all/${challenge._id}?keep=remove-all`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('cantOnlyUnlinkChalTask'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('cantOnlyUnlinkChalTask'), + }); }); it('unlinks all tasks from a challenge and deletes them on keep=remove-all', async () => { @@ -87,7 +87,7 @@ describe('POST /tasks/unlink-all/:challengeId', () => { const daily = await user.post(`/tasks/challenge/${challenge._id}`, tasksToTest.daily); const anotherUser = await generateUser(); await user.post(`/groups/${guild._id}/invite`, { - uuids: [anotherUser._id], + uuids: [anotherUser._id], }); // Have the second user join the group and challenge await anotherUser.post(`/groups/${guild._id}/join`); diff --git a/test/api/v3/integration/tasks/POST-tasks_unlink-one_taskId.test.js b/test/api/v3/integration/tasks/POST-tasks_unlink-one_taskId.test.js index 570f46c92e..fb67ec1451 100644 --- a/test/api/v3/integration/tasks/POST-tasks_unlink-one_taskId.test.js +++ b/test/api/v3/integration/tasks/POST-tasks_unlink-one_taskId.test.js @@ -43,50 +43,50 @@ describe('POST /tasks/unlink-one/:taskId', () => { it('fails if no keep query', async () => { const daily = await user.post(`/tasks/challenge/${challenge._id}`, tasksToTest.daily); await expect(user.post(`/tasks/unlink-one/${daily._id}`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('invalidReqParams'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); }); it('fails if invalid task id', async () => { await expect(user.post('/tasks/unlink-one/123?keep=remove')) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('invalidReqParams'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); }); it('fails on task not found', async () => { await expect(user.post(`/tasks/unlink-one/${generateUUID()}?keep=keep`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('taskNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('taskNotFound'), + }); }); it('fails on task unlinked to challenge', async () => { let daily = await user.post('/tasks/user', tasksToTest.daily); await expect(user.post(`/tasks/unlink-one/${daily._id}?keep=keep`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('cantOnlyUnlinkChalTask'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('cantOnlyUnlinkChalTask'), + }); }); it('fails on unbroken challenge', async () => { await user.post(`/tasks/challenge/${challenge._id}`, tasksToTest.daily); let [daily] = await user.get('/tasks/user'); await expect(user.post(`/tasks/unlink-one/${daily._id}?keep=keep`)) - .to.eventually.be.rejected.and.eql({ - code: 400, - error: 'BadRequest', - message: t('cantOnlyUnlinkChalTask'), - }); + .to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('cantOnlyUnlinkChalTask'), + }); }); it('unlinks a task from a challenge and saves it on keep=keep', async () => { diff --git a/test/api/v3/integration/tasks/PUT-tasks_id.test.js b/test/api/v3/integration/tasks/PUT-tasks_id.test.js index b2b802f837..aba6c254cf 100644 --- a/test/api/v3/integration/tasks/PUT-tasks_id.test.js +++ b/test/api/v3/integration/tasks/PUT-tasks_id.test.js @@ -46,7 +46,7 @@ describe('PUT /tasks/:id', () => { expect(savedTask.userId).to.equal(task.userId); expect(savedTask.history).to.eql(task.history); expect(savedTask.createdAt).to.equal(task.createdAt); - expect(savedTask.updatedAt).to.be.greaterThan(task.updatedAt); + expect(new Date(savedTask.updatedAt)).to.be.greaterThan(new Date(task.updatedAt)); expect(savedTask.challenge).to.eql(task.challenge); expect(savedTask.completed).to.eql(task.completed); expect(savedTask.streak).to.equal(savedTask.streak); // it's an habit, dailies can change it @@ -54,7 +54,7 @@ describe('PUT /tasks/:id', () => { }); it('ignores invalid fields', async () => { - let savedTask = await user.put(`/tasks/${task._id}`, { + let savedTask = await user.put(`/tasks/${task._id}`, { notValid: true, }); @@ -133,7 +133,7 @@ describe('PUT /tasks/:id', () => { expect(savedChallengeUserTask.text).to.equal(challengeUserTask.text); expect(savedChallengeUserTask.history).to.eql(challengeUserTask.history); expect(savedChallengeUserTask.createdAt).to.equal(challengeUserTask.createdAt); - expect(savedChallengeUserTask.updatedAt).to.be.greaterThan(challengeUserTask.updatedAt); + expect(new Date(savedChallengeUserTask.updatedAt)).to.be.greaterThan(new Date(challengeUserTask.updatedAt)); expect(savedChallengeUserTask.challenge).to.eql(challengeUserTask.challenge); expect(savedChallengeUserTask.completed).to.equal(challengeUserTask.completed); expect(savedChallengeUserTask.dateCompleted).to.equal(challengeUserTask.dateCompleted); diff --git a/test/api/v3/integration/tasks/challenges/POST-tasks_challenge_challengeId_taskId_checklist.test.js b/test/api/v3/integration/tasks/challenges/POST-tasks_challenge_challengeId_taskId_checklist.test.js index 06bc7b68b2..ec4d09f7b3 100644 --- a/test/api/v3/integration/tasks/challenges/POST-tasks_challenge_challengeId_taskId_checklist.test.js +++ b/test/api/v3/integration/tasks/challenges/POST-tasks_challenge_challengeId_taskId_checklist.test.js @@ -40,11 +40,11 @@ describe('POST /tasks/:taskId/checklist/', () => { ignored: false, _id: 123, })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('onlyChalLeaderEditTasks'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('onlyChalLeaderEditTasks'), + }); }); it('adds a checklist item to a daily', async () => { diff --git a/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId.test.js b/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId.test.js index bd3be00508..94d96367b8 100644 --- a/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId.test.js +++ b/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId.test.js @@ -98,7 +98,7 @@ describe('PUT /tasks/:id', () => { expect(savedTask.userId).to.equal(task.userId); expect(savedTask.history).to.eql(task.history); expect(savedTask.createdAt).to.equal(task.createdAt); - expect(savedTask.updatedAt).to.be.greaterThan(task.updatedAt); + expect(new Date(savedTask.updatedAt)).to.be.greaterThan(new Date(task.updatedAt)); expect(savedTask.challenge._id).to.equal(task.challenge._id); expect(savedTask.completed).to.equal(task.completed); expect(savedTask.streak).to.equal(task.streak); diff --git a/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId_tasksId_checklist_itemId.test.js b/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId_tasksId_checklist_itemId.test.js index 4dc2ceaa3e..cce7ce79f3 100644 --- a/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId_tasksId_checklist_itemId.test.js +++ b/test/api/v3/integration/tasks/challenges/PUT-tasks_challenge_challengeId_tasksId_checklist_itemId.test.js @@ -28,11 +28,11 @@ describe('PUT /tasks/:taskId/checklist/:itemId', () => { completed: true, _id: 123, // ignored })) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('checklistItemNotFound'), - }); + .to.eventually.be.rejected.and.eql({ + code: 404, + error: 'NotFound', + message: t('checklistItemNotFound'), + }); }); it('returns error when user is not a member of the challenge', async () => { @@ -53,11 +53,11 @@ describe('PUT /tasks/:taskId/checklist/:itemId', () => { completed: true, _id: 123, // ignored })) - .to.eventually.be.rejected.and.eql({ - code: 401, - error: 'NotAuthorized', - message: t('onlyChalLeaderEditTasks'), - }); + .to.eventually.be.rejected.and.eql({ + code: 401, + error: 'NotAuthorized', + message: t('onlyChalLeaderEditTasks'), + }); }); it('updates a checklist item on dailies', async () => { diff --git a/test/api/v3/integration/tasks/groups/tags/POST-tasks_taskId_tags.test.js b/test/api/v3/integration/tasks/groups/tags/POST-tasks_taskId_tags.test.js index bfa5f31840..ead583d122 100644 --- a/test/api/v3/integration/tasks/groups/tags/POST-tasks_taskId_tags.test.js +++ b/test/api/v3/integration/tasks/groups/tags/POST-tasks_taskId_tags.test.js @@ -3,6 +3,7 @@ import { translate as t, } from '../../../../../../helpers/api-integration/v3'; import { v4 as generateUUID } from 'uuid'; + // Currently we do not support adding tags to group original tasks, but if we do in the future, these tests will check xdescribe('POST group /tasks/:taskId/tags/:tagId', () => { let user, guild, task; diff --git a/test/api/v3/integration/user/POST-user_release_both.test.js b/test/api/v3/integration/user/POST-user_release_both.test.js index 047ea5a2c9..ce8e5246dd 100644 --- a/test/api/v3/integration/user/POST-user_release_both.test.js +++ b/test/api/v3/integration/user/POST-user_release_both.test.js @@ -54,9 +54,9 @@ describe('POST /user/release-both', () => { expect(response.message).to.equal(t('mountsAndPetsReleased')); expect(user.balance).to.equal(0); - expect(user.items.currentMount).to.be.empty; - expect(user.items.currentPet).to.be.empty; - expect(user.items.pets[animal]).to.be.empty; + expect(user.items.currentMount).to.equal(''); + expect(user.items.currentPet).to.equal(''); + expect(user.items.pets[animal]).to.equal(0); expect(user.items.mounts[animal]).to.equal(null); expect(user.achievements.beastMasterCount).to.equal(1); expect(user.achievements.mountMasterCount).to.equal(1); diff --git a/test/api/v3/integration/user/auth/DELETE-user_auth_social_network.test.js b/test/api/v3/integration/user/auth/DELETE-user_auth_social_network.test.js index ae4fde82a9..55c5522322 100644 --- a/test/api/v3/integration/user/auth/DELETE-user_auth_social_network.test.js +++ b/test/api/v3/integration/user/auth/DELETE-user_auth_social_network.test.js @@ -41,7 +41,7 @@ describe('DELETE social registration', () => { let response = await user.del('/user/auth/social/facebook'); expect(response).to.eql({}); await user.sync(); - expect(user.auth.facebook).to.be.empty; + expect(user.auth.facebook).to.be.undefined; }); it('succeeds if user has a google registration', async () => { @@ -54,7 +54,7 @@ describe('DELETE social registration', () => { let response = await user.del('/user/auth/social/facebook'); expect(response).to.eql({}); await user.sync(); - expect(user.auth.facebook).to.be.empty; + expect(user.auth.facebook).to.be.undefined; }); }); @@ -79,7 +79,7 @@ describe('DELETE social registration', () => { let response = await user.del('/user/auth/social/google'); expect(response).to.eql({}); await user.sync(); - expect(user.auth.google).to.be.empty; + expect(user.auth.google).to.be.undefined; }); it('succeeds if user has a facebook registration', async () => { @@ -92,7 +92,7 @@ describe('DELETE social registration', () => { let response = await user.del('/user/auth/social/google'); expect(response).to.eql({}); await user.sync(); - expect(user.auth.google).to.be.empty; + expect(user.auth.goodl).to.be.undefined; }); }); }); diff --git a/test/api/v3/integration/user/auth/POST-register_local.test.js b/test/api/v3/integration/user/auth/POST-register_local.test.js index 259d848c05..1ad091a79e 100644 --- a/test/api/v3/integration/user/auth/POST-register_local.test.js +++ b/test/api/v3/integration/user/auth/POST-register_local.test.js @@ -579,7 +579,7 @@ describe('POST /user/auth/local/register', () => { it('adds a user to a guild on an invite of type other than party', async () => { let { group, groupLeader } = await createAndPopulateGroup({ - groupDetails: { type: 'guild', privacy: 'private' }, + groupDetails: { type: 'guild', privacy: 'private' }, }); let invite = encrypt(JSON.stringify({ diff --git a/test/api/v3/integration/world-state/GET-world-state.test.js b/test/api/v3/integration/world-state/GET-world-state.test.js index fac08ad639..5c91062769 100644 --- a/test/api/v3/integration/world-state/GET-world-state.test.js +++ b/test/api/v3/integration/world-state/GET-world-state.test.js @@ -19,7 +19,7 @@ describe('GET /world-state', () => { await updateDocument('groups', {_id: TAVERN_ID}, {quest: {active: true, key: 'dysheartener', progress: {hp: 50000, rage: 9999}}}); const res = await requester().get('/world-state'); - expect(res).to.have.deep.property('worldBoss'); + expect(res).to.have.nested.property('worldBoss'); expect(res.worldBoss).to.eql({ active: true, diff --git a/test/api/v3/unit/libs/apiMessages.js b/test/api/v3/unit/libs/apiMessages.js index 09ff86f5ba..3d2ac2fad1 100644 --- a/test/api/v3/unit/libs/apiMessages.js +++ b/test/api/v3/unit/libs/apiMessages.js @@ -14,7 +14,7 @@ describe('API Messages', () => { let vars = {a: 1}; sandbox.stub(_, 'clone').returns({}); apiMessages('guildsOnlyPaginate', vars); - expect(_.clone).to.have.been.called.once; + expect(_.clone).to.have.been.calledOnce; expect(_.clone).to.have.been.calledWith(vars); }); @@ -23,9 +23,9 @@ describe('API Messages', () => { let stub = sinon.stub().returns('string'); sandbox.stub(_, 'template').returns(stub); apiMessages('guildsOnlyPaginate', vars); - expect(_.template).to.have.been.called.once; + expect(_.template).to.have.been.calledOnce; expect(_.template).to.have.been.calledWith(message); - expect(stub).to.have.been.called.once; + expect(stub).to.have.been.calledOnce; expect(stub).to.have.been.calledWith(vars); }); }); diff --git a/test/api/v3/unit/libs/collectionManipulators.test.js b/test/api/v3/unit/libs/collectionManipulators.test.js index a2bc6e71c4..2736b37502 100644 --- a/test/api/v3/unit/libs/collectionManipulators.test.js +++ b/test/api/v3/unit/libs/collectionManipulators.test.js @@ -1,6 +1,6 @@ import mongoose from 'mongoose'; import { - removeFromArray, + removeFromArray, } from '../../../../../website/server/libs/collectionManipulators'; describe('Collection Manipulators', () => { diff --git a/test/api/v3/unit/libs/cron.test.js b/test/api/v3/unit/libs/cron.test.js index 2fefcbf483..76990aa20a 100644 --- a/test/api/v3/unit/libs/cron.test.js +++ b/test/api/v3/unit/libs/cron.test.js @@ -181,9 +181,9 @@ describe('cron', () => { cron({user, tasksByType, daysMissed, analytics}); expect(user.purchased.plan.customerId).to.not.exist; - expect(user.purchased.plan.consecutive.gemCapExtra).to.be.empty; - expect(user.purchased.plan.consecutive.count).to.be.empty; - expect(user.purchased.plan.consecutive.offset).to.be.empty; + expect(user.purchased.plan.consecutive.gemCapExtra).to.equal(0); + expect(user.purchased.plan.consecutive.count).to.equal(0); + expect(user.purchased.plan.consecutive.offset).to.equal(0); }); }); @@ -1027,7 +1027,7 @@ describe('cron', () => { cron({user, tasksByType, daysMissed, analytics}); expect(user.party.quest.progress.up).to.equal(0); expect(user.party.quest.progress.down).to.equal(0); - expect(user.party.quest.progress.collectedItems).to.be.empty; + expect(user.party.quest.progress.collectedItems).to.equal(0); }); it('applies the user progress', () => { diff --git a/test/api/v3/unit/libs/payments/amazon/checkout.test.js b/test/api/v3/unit/libs/payments/amazon/checkout.test.js index 9e74cdb145..0581c76772 100644 --- a/test/api/v3/unit/libs/payments/amazon/checkout.test.js +++ b/test/api/v3/unit/libs/payments/amazon/checkout.test.js @@ -132,11 +132,11 @@ describe('Amazon Payments - Checkout', () => { }; await expect(amzLib.checkout({gift, user, orderReferenceId, headers})) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - message: 'Amount must be at least 1.', - name: 'BadRequest', - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + message: 'Amount must be at least 1.', + name: 'BadRequest', + }); }); it('should error if user cannot get gems gems', async () => { diff --git a/test/api/v3/unit/libs/payments/amazon/subscribe.test.js b/test/api/v3/unit/libs/payments/amazon/subscribe.test.js index 8095f90c63..930c64d06a 100644 --- a/test/api/v3/unit/libs/payments/amazon/subscribe.test.js +++ b/test/api/v3/unit/libs/payments/amazon/subscribe.test.js @@ -123,11 +123,11 @@ describe('Amazon Payments - Subscribe', () => { groupId, headers, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - name: 'BadRequest', - message: i18n.t('missingSubscriptionCode'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + name: 'BadRequest', + message: i18n.t('missingSubscriptionCode'), + }); }); it('should throw an error if we are missing a billingAgreementId', async () => { @@ -138,11 +138,11 @@ describe('Amazon Payments - Subscribe', () => { groupId, headers, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - name: 'BadRequest', - message: 'Missing req.body.billingAgreementId', - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + name: 'BadRequest', + message: 'Missing req.body.billingAgreementId', + }); }); it('should throw an error when coupon code is missing', async () => { @@ -156,11 +156,11 @@ describe('Amazon Payments - Subscribe', () => { groupId, headers, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - name: 'BadRequest', - message: i18n.t('couponCodeRequired'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + name: 'BadRequest', + message: i18n.t('couponCodeRequired'), + }); }); it('should throw an error when coupon code is invalid', async () => { @@ -182,11 +182,11 @@ describe('Amazon Payments - Subscribe', () => { groupId, headers, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 401, - name: 'NotAuthorized', - message: i18n.t('invalidCoupon'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 401, + name: 'NotAuthorized', + message: i18n.t('invalidCoupon'), + }); cc.validate.restore(); }); diff --git a/test/api/v3/unit/libs/payments/group-plans/group-payments-create.test.js b/test/api/v3/unit/libs/payments/group-plans/group-payments-create.test.js index 96bcde4134..72489aa4df 100644 --- a/test/api/v3/unit/libs/payments/group-plans/group-payments-create.test.js +++ b/test/api/v3/unit/libs/payments/group-plans/group-payments-create.test.js @@ -305,7 +305,7 @@ describe('Purchasing a group plan for group', () => { await api.createSubscription(data); - expect(sender.sendTxn).to.be.calledFourTimes; + expect(sender.sendTxn).to.have.callCount(4); expect(sender.sendTxn.args[0][0]._id).to.equal(TECH_ASSISTANCE_EMAIL); expect(sender.sendTxn.args[0][1]).to.equal('admin-user-subscription-details'); expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id); @@ -338,7 +338,7 @@ describe('Purchasing a group plan for group', () => { await api.createSubscription(data); - expect(sender.sendTxn).to.be.calledFourTimes; + expect(sender.sendTxn).to.have.callCount(4); expect(sender.sendTxn.args[0][0]._id).to.equal(TECH_ASSISTANCE_EMAIL); expect(sender.sendTxn.args[0][1]).to.equal('admin-user-subscription-details'); expect(sender.sendTxn.args[1][0]._id).to.equal(recipient._id); diff --git a/test/api/v3/unit/libs/payments/paypal/checkout.test.js b/test/api/v3/unit/libs/payments/paypal/checkout.test.js index 9ed40c1ad8..aaa83535ee 100644 --- a/test/api/v3/unit/libs/payments/paypal/checkout.test.js +++ b/test/api/v3/unit/libs/payments/paypal/checkout.test.js @@ -71,11 +71,11 @@ describe('checkout', () => { }; await expect(paypalPayments.checkout({gift})) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - message: 'Amount must be at least 1.', - name: 'BadRequest', - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + message: 'Amount must be at least 1.', + name: 'BadRequest', + }); }); it('should error if the user cannot get gems', async () => { diff --git a/test/api/v3/unit/libs/payments/stripe/cancel-subscription.test.js b/test/api/v3/unit/libs/payments/stripe/cancel-subscription.test.js index 2e09014a39..d062ad0b89 100644 --- a/test/api/v3/unit/libs/payments/stripe/cancel-subscription.test.js +++ b/test/api/v3/unit/libs/payments/stripe/cancel-subscription.test.js @@ -42,11 +42,11 @@ describe('cancel subscription', () => { user, groupId: undefined, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 401, - name: 'NotAuthorized', - message: i18n.t('missingSubscription'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 401, + name: 'NotAuthorized', + message: i18n.t('missingSubscription'), + }); }); it('throws an error if the group is not found', async () => { @@ -54,11 +54,11 @@ describe('cancel subscription', () => { user, groupId: 'fake-group', })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 404, - name: 'NotFound', - message: i18n.t('groupNotFound'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 404, + name: 'NotFound', + message: i18n.t('groupNotFound'), + }); }); it('throws an error if user is not the group leader', async () => { @@ -70,11 +70,11 @@ describe('cancel subscription', () => { user: nonLeader, groupId, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 401, - name: 'NotAuthorized', - message: i18n.t('onlyGroupLeaderCanManageSubscription'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 401, + name: 'NotAuthorized', + message: i18n.t('onlyGroupLeaderCanManageSubscription'), + }); }); describe('success', () => { diff --git a/test/api/v3/unit/libs/payments/stripe/checkout-subscription.test.js b/test/api/v3/unit/libs/payments/stripe/checkout-subscription.test.js index d1d908c7fa..7271b1dbd3 100644 --- a/test/api/v3/unit/libs/payments/stripe/checkout-subscription.test.js +++ b/test/api/v3/unit/libs/payments/stripe/checkout-subscription.test.js @@ -88,11 +88,11 @@ describe('checkout with subscription', () => { headers, coupon, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - name: 'BadRequest', - message: 'Missing req.body.id', - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + name: 'BadRequest', + message: 'Missing req.body.id', + }); }); it('should throw an error when coupon code is missing', async () => { @@ -108,11 +108,11 @@ describe('checkout with subscription', () => { headers, coupon, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - name: 'BadRequest', - message: i18n.t('couponCodeRequired'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + name: 'BadRequest', + message: i18n.t('couponCodeRequired'), + }); }); it('should throw an error when coupon code is invalid', async () => { @@ -136,11 +136,11 @@ describe('checkout with subscription', () => { headers, coupon, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - name: 'BadRequest', - message: i18n.t('invalidCoupon'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + name: 'BadRequest', + message: i18n.t('invalidCoupon'), + }); cc.validate.restore(); }); diff --git a/test/api/v3/unit/libs/payments/stripe/checkout.test.js b/test/api/v3/unit/libs/payments/stripe/checkout.test.js index f784bca300..b8f398ef6e 100644 --- a/test/api/v3/unit/libs/payments/stripe/checkout.test.js +++ b/test/api/v3/unit/libs/payments/stripe/checkout.test.js @@ -57,11 +57,11 @@ describe('checkout', () => { headers, coupon, }, stripe)) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - message: 'Amount must be at least 1.', - name: 'BadRequest', - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + message: 'Amount must be at least 1.', + name: 'BadRequest', + }); }); diff --git a/test/api/v3/unit/libs/payments/stripe/edit-subscription.test.js b/test/api/v3/unit/libs/payments/stripe/edit-subscription.test.js index 9c58c4bae5..40153f8496 100644 --- a/test/api/v3/unit/libs/payments/stripe/edit-subscription.test.js +++ b/test/api/v3/unit/libs/payments/stripe/edit-subscription.test.js @@ -43,11 +43,11 @@ describe('edit subscription', () => { user, groupId: undefined, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 401, - name: 'NotAuthorized', - message: i18n.t('missingSubscription'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 401, + name: 'NotAuthorized', + message: i18n.t('missingSubscription'), + }); }); it('throws an error if a token is not provided', async () => { @@ -55,11 +55,11 @@ describe('edit subscription', () => { user, groupId: undefined, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 400, - name: 'BadRequest', - message: 'Missing req.body.id', - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 400, + name: 'BadRequest', + message: 'Missing req.body.id', + }); }); it('throws an error if the group is not found', async () => { @@ -68,11 +68,11 @@ describe('edit subscription', () => { user, groupId: 'fake-group', })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 404, - name: 'NotFound', - message: i18n.t('groupNotFound'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 404, + name: 'NotFound', + message: i18n.t('groupNotFound'), + }); }); it('throws an error if user is not the group leader', async () => { @@ -85,11 +85,11 @@ describe('edit subscription', () => { user: nonLeader, groupId, })) - .to.eventually.be.rejected.and.to.eql({ - httpCode: 401, - name: 'NotAuthorized', - message: i18n.t('onlyGroupLeaderCanManageSubscription'), - }); + .to.eventually.be.rejected.and.to.eql({ + httpCode: 401, + name: 'NotAuthorized', + message: i18n.t('onlyGroupLeaderCanManageSubscription'), + }); }); describe('success', () => { diff --git a/test/api/v3/unit/libs/payments/stripe/handle-webhook.test.js b/test/api/v3/unit/libs/payments/stripe/handle-webhook.test.js index 762e840c8a..f8786b2718 100644 --- a/test/api/v3/unit/libs/payments/stripe/handle-webhook.test.js +++ b/test/api/v3/unit/libs/payments/stripe/handle-webhook.test.js @@ -34,7 +34,7 @@ describe('Stripe - Webhooks', () => { it('logs an error if an unsupported webhook event is passed', async () => { const error = new Error(`Missing handler for Stripe webhook ${eventType}`); await stripePayments.handleWebhooks({requestBody: event}, stripe); - expect(logger.error).to.have.been.called.once; + expect(logger.error).to.have.been.calledOnce; const calledWith = logger.error.getCall(0).args; expect(calledWith[0].message).to.equal(error.message); @@ -43,7 +43,7 @@ describe('Stripe - Webhooks', () => { it('retrieves and validates the event from Stripe', async () => { await stripePayments.handleWebhooks({requestBody: event}, stripe); - expect(stripe.events.retrieve).to.have.been.called.once; + expect(stripe.events.retrieve).to.have.been.calledOnce; expect(stripe.events.retrieve).to.have.been.calledWith(event.id); }); }); @@ -70,7 +70,7 @@ describe('Stripe - Webhooks', () => { await stripePayments.handleWebhooks({requestBody: {}}, stripe); - expect(stripe.events.retrieve).to.have.been.called.once; + expect(stripe.events.retrieve).to.have.been.calledOnce; expect(stripe.customers.del).to.not.have.been.called; expect(payments.cancelSubscription).to.not.have.been.called; stripe.events.retrieve.restore(); diff --git a/test/api/v3/unit/libs/taskManager.js b/test/api/v3/unit/libs/taskManager.js index 546fcbe19f..14dc8feb49 100644 --- a/test/api/v3/unit/libs/taskManager.js +++ b/test/api/v3/unit/libs/taskManager.js @@ -54,7 +54,7 @@ describe('taskManager', () => { expect(newTask.type).to.equal(testHabit.type); expect(newTask.up).to.equal(testHabit.up); expect(newTask.down).to.equal(testHabit.down); - expect(newTask.createdAt).isNotEmtpy; + expect(newTask.createdAt).to.exist; }); it('gets user tasks', async () => { @@ -75,7 +75,7 @@ describe('taskManager', () => { expect(task.type).to.equal(testHabit.type); expect(task.up).to.equal(testHabit.up); expect(task.down).to.equal(testHabit.down); - expect(task.createdAt).isNotEmtpy; + expect(task.createdAt).to.exist; }); it('creates group tasks', async () => { @@ -89,7 +89,7 @@ describe('taskManager', () => { expect(newTask.type).to.equal(testHabit.type); expect(newTask.up).to.equal(testHabit.up); expect(newTask.down).to.equal(testHabit.down); - expect(newTask.createdAt).isNotEmtpy; + expect(newTask.createdAt).to.exist; expect(newTask.group.id).to.equal(group._id); }); @@ -111,7 +111,7 @@ describe('taskManager', () => { expect(task.type).to.equal(testHabit.type); expect(task.up).to.equal(testHabit.up); expect(task.down).to.equal(testHabit.down); - expect(task.createdAt).isNotEmtpy; + expect(task.createdAt).to.exist; expect(task.group.id).to.equal(group._id); }); @@ -126,7 +126,7 @@ describe('taskManager', () => { expect(newTask.type).to.equal(testHabit.type); expect(newTask.up).to.equal(testHabit.up); expect(newTask.down).to.equal(testHabit.down); - expect(newTask.createdAt).isNotEmtpy; + expect(newTask.createdAt).to.exist; expect(newTask.challenge.id).to.equal(challenge._id); }); @@ -148,7 +148,7 @@ describe('taskManager', () => { expect(task.type).to.equal(testHabit.type); expect(task.up).to.equal(testHabit.up); expect(task.down).to.equal(testHabit.down); - expect(task.createdAt).isNotEmtpy; + expect(task.createdAt).to.exist; expect(task.challenge.id).to.equal(challenge._id); }); @@ -171,7 +171,7 @@ describe('taskManager', () => { expect(syncableTask.updatedAt).to.not.exist; }); - it('moves tasks to a specified position', async() => { + it('moves tasks to a specified position', async () => { let order = ['task-id-1', 'task-id-2']; moveTask(order, 'task-id-2', 0); diff --git a/test/api/v3/unit/middlewares/cors.test.js b/test/api/v3/unit/middlewares/cors.test.js index 8ece1e9ca2..8cf6dbc3ff 100644 --- a/test/api/v3/unit/middlewares/cors.test.js +++ b/test/api/v3/unit/middlewares/cors.test.js @@ -23,7 +23,7 @@ describe('cors middleware', () => { 'Access-Control-Allow-Headers': 'Content-Type,Accept,Content-Encoding,X-Requested-With,x-api-user,x-api-key,x-client', }); expect(res.sendStatus).to.not.have.been.called; - expect(next).to.have.been.called.once; + expect(next).to.have.been.calledOnce; }); it('responds immediately if method is OPTIONS', () => { diff --git a/test/api/v3/unit/middlewares/cronMiddleware.js b/test/api/v3/unit/middlewares/cronMiddleware.js index fd38079691..12209b1a87 100644 --- a/test/api/v3/unit/middlewares/cronMiddleware.js +++ b/test/api/v3/unit/middlewares/cronMiddleware.js @@ -36,12 +36,12 @@ describe('cron middleware', () => { }); user.save() - .then(savedUser => { - res.locals.user = savedUser; - res.analytics = analyticsService; - done(); - }) - .catch(done); + .then(savedUser => { + res.locals.user = savedUser; + res.analytics = analyticsService; + done(); + }) + .catch(done); }); afterEach(() => { diff --git a/test/api/v3/unit/middlewares/maintenanceMode.test.js b/test/api/v3/unit/middlewares/maintenanceMode.test.js index 857fb2c941..566d572206 100644 --- a/test/api/v3/unit/middlewares/maintenanceMode.test.js +++ b/test/api/v3/unit/middlewares/maintenanceMode.test.js @@ -22,7 +22,7 @@ describe('maintenance mode middleware', () => { attachMaintenanceMode(req, res, next); - expect(next).to.have.been.called.once; + expect(next).to.have.been.calledOnce; expect(res.status).to.not.have.been.called; }); diff --git a/test/api/v3/unit/middlewares/redirects.js b/test/api/v3/unit/middlewares/redirects.js index ed210c169a..184d60b706 100644 --- a/test/api/v3/unit/middlewares/redirects.js +++ b/test/api/v3/unit/middlewares/redirects.js @@ -43,7 +43,7 @@ describe('redirects middleware', () => { attachRedirects.forceSSL(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); it('does not redirect outside of production environments', () => { @@ -57,7 +57,7 @@ describe('redirects middleware', () => { attachRedirects.forceSSL(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); it('does not redirect if base URL is not https', () => { @@ -71,7 +71,7 @@ describe('redirects middleware', () => { attachRedirects.forceSSL(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); }); @@ -108,7 +108,7 @@ describe('redirects middleware', () => { attachRedirects.forceHabitica(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); it('does not redirect if env is set to ignore redirection', () => { @@ -125,7 +125,7 @@ describe('redirects middleware', () => { attachRedirects.forceHabitica(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); it('does not redirect if request hostname matches base URL host', () => { @@ -142,7 +142,7 @@ describe('redirects middleware', () => { attachRedirects.forceHabitica(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); it('does not redirect if request is an API URL', () => { @@ -159,7 +159,7 @@ describe('redirects middleware', () => { attachRedirects.forceHabitica(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); it('does not redirect if request method is not GET', () => { @@ -176,7 +176,7 @@ describe('redirects middleware', () => { attachRedirects.forceHabitica(req, res, next); - expect(res.redirect).to.be.notCalled; + expect(res.redirect).to.have.not.been.called; }); }); }); diff --git a/test/api/v3/unit/models/challenge.test.js b/test/api/v3/unit/models/challenge.test.js index 18e7de7bcf..a27d8b65a7 100644 --- a/test/api/v3/unit/models/challenge.test.js +++ b/test/api/v3/unit/models/challenge.test.js @@ -65,7 +65,7 @@ describe('Challenge Model', () => { each(tasksToTest, (taskValue, taskType) => { context(`${taskType}`, () => { - beforeEach(async() => { + beforeEach(async () => { task = new Tasks[`${taskType}`](Tasks.Task.sanitize(taskValue)); task.challenge.id = challenge._id; await task.save(); @@ -194,7 +194,7 @@ describe('Challenge Model', () => { }); expect(syncedTask).to.exist; - expect(syncedTask.challenge._id).to.be.empty; + expect(syncedTask.challenge._id).to.be.undefined; }); }); }); diff --git a/test/api/v3/unit/models/group_tasks.test.js b/test/api/v3/unit/models/group_tasks.test.js index 331b91ac1b..76e7666c96 100644 --- a/test/api/v3/unit/models/group_tasks.test.js +++ b/test/api/v3/unit/models/group_tasks.test.js @@ -64,7 +64,7 @@ describe('Group Task Methods', () => { each(tasksToTest, (taskValue, taskType) => { context(`${taskType}`, () => { - beforeEach(async() => { + beforeEach(async () => { task = new Tasks[`${taskType}`](Tasks.Task.sanitize(taskValue)); task.group.id = guild._id; await task.save(); @@ -127,7 +127,7 @@ describe('Group Task Methods', () => { expect(syncedTask.checklist[0].text).to.equal(task.checklist[0].text); }); - describe('syncs updated info', async() => { + describe('syncs updated info', async () => { let newMember; beforeEach(async () => { @@ -274,7 +274,7 @@ describe('Group Task Methods', () => { expect(task.group.assignedUsers).to.not.contain(leader._id); expect(updatedSyncedTask).to.exist; - expect(updatedSyncedTask.group._id).to.be.empty; + expect(updatedSyncedTask.group._id).to.be.undefined; }); }); }); diff --git a/test/api/v3/unit/models/task.test.js b/test/api/v3/unit/models/task.test.js index ddab40b26f..fc3ab9a513 100644 --- a/test/api/v3/unit/models/task.test.js +++ b/test/api/v3/unit/models/task.test.js @@ -54,7 +54,7 @@ describe('Task Model', () => { each(tasksToTest, (taskValue, taskType) => { context(`${taskType}`, () => { - beforeEach(async() => { + beforeEach(async () => { task = new Tasks[`${taskType}`](Tasks.Task.sanitize(taskValue)); task.challenge.id = challenge._id; task.history = generateHistory(396); diff --git a/test/api/v3/unit/models/user.test.js b/test/api/v3/unit/models/user.test.js index 7305401d5a..63d99193b6 100644 --- a/test/api/v3/unit/models/user.test.js +++ b/test/api/v3/unit/models/user.test.js @@ -120,7 +120,7 @@ describe('User Model', () => { expect(User.pushNotification({_id: user._id}, 'CRON', null, 'INVALID_SEEN')).to.eventually.be.rejected; }); - it('adds notifications without data for all given users via static method', async() => { + it('adds notifications without data for all given users via static method', async () => { let user = new User(); let otherUser = new User(); await Bluebird.all([user.save(), otherUser.save()]); diff --git a/test/client/e2e/specs/test.js b/test/client/e2e/specs/test.js index e3e19d4d96..da58561b29 100644 --- a/test/client/e2e/specs/test.js +++ b/test/client/e2e/specs/test.js @@ -9,7 +9,7 @@ module.exports = { const devServer = browser.globals.devServerURL; browser - .url(devServer) + .url(devServer) .waitForElementVisible('#app', 5000) .assert.elementPresent('.logo') .assert.containsText('h1', 'Hello Vue!') diff --git a/test/common/libs/taskClasses.test.js b/test/common/libs/taskClasses.test.js deleted file mode 100644 index dbfa6881a6..0000000000 --- a/test/common/libs/taskClasses.test.js +++ /dev/null @@ -1,82 +0,0 @@ -import taskClasses from '../../../website/common/script/libs/taskClasses'; - -describe('taskClasses', () => { - let task = {}; - let filters = {}; - let result; - - describe('a todo task', () => { - beforeEach(() => { - task = { type: 'todo', _editing: false, tags: [] }; - }); - - it('is hidden', () => { - filters = { a: true }; - result = taskClasses(task, filters, 0, Number(new Date()), false, true); - expect(result).to.eql('hidden'); - }); - it('is beingEdited', () => { - task._editing = true; - result = taskClasses(task, filters); - expect(result.split(' ').indexOf('beingEdited')).to.not.eql(-1); - }); - it('is completed', () => { - task.completed = true; - result = taskClasses(task, filters); - expect(result.split(' ').indexOf('completed')).to.not.eql(-1); - task.completed = false; - result = taskClasses(task, filters); - expect(result.split(' ').indexOf('completed')).to.eql(-1); - expect(result.split(' ').indexOf('uncompleted')).to.not.eql(-1); - }); - }); - - describe('a daily task', () => { - it('is completed', () => { - task = { type: 'daily' }; - result = taskClasses(task); - expect(result.split(' ').indexOf('completed')).to.not.eql(-1); - }); - - it('is uncompleted'); // this requires stubbing the internal dependency shouldDo in taskClasses - }); - - describe('a habit', () => { - it('that is wide', () => { - task = { type: 'habit', up: true, down: true }; - result = taskClasses(task); - expect(result.split(' ').indexOf('habit-wide')).to.not.eql(-1); - }); - it('that is narrow', () => { - task = { type: 'habit' }; - result = taskClasses(task); - expect(result.split(' ').indexOf('habit-narrow')).to.not.eql(-1); - }); - }); - - describe('varies based on priority', () => { - it('trivial', () => { - task.priority = 0.1; - result = taskClasses(task); - expect(result.split(' ').indexOf('difficulty-trivial')).to.not.eql(-1); - }); - it('hard', () => { - task.priority = 2; - result = taskClasses(task); - expect(result.split(' ').indexOf('difficulty-hard')).to.not.eql(-1); - }); - }); - - describe('varies based on value', () => { - it('color-worst', () => { - task.value = -30; - result = taskClasses(task); - expect(result.split(' ').indexOf('color-worst')).to.not.eql(-1); - }); - it('color-neutral', () => { - task.value = 0; - result = taskClasses(task); - expect(result.split(' ').indexOf('color-neutral')).to.not.eql(-1); - }); - }); -}); diff --git a/test/common/ops/releaseBoth.js b/test/common/ops/releaseBoth.js index 880f62a316..72411e419b 100644 --- a/test/common/ops/releaseBoth.js +++ b/test/common/ops/releaseBoth.js @@ -72,7 +72,7 @@ describe('shared.ops.releaseBoth', () => { let message = releaseBoth(user)[1]; expect(message).to.equal(i18n.t('mountsAndPetsReleased')); - expect(user.items.pets[animal]).to.be.empty; + expect(user.items.pets[animal]).to.equal(0); expect(user.items.mounts[animal]).to.equal(null); }); diff --git a/test/mocha.opts b/test/mocha.opts index f7bf61a268..63c3988a56 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -2,7 +2,6 @@ --reporter spec --timeout 8000 --check-leaks ---growl --globals io -r babel-polyfill --require babel-register diff --git a/website/client/components/groups/membersModal.vue b/website/client/components/groups/membersModal.vue index eb0199fc03..8b63c6b21a 100644 --- a/website/client/components/groups/membersModal.vue +++ b/website/client/components/groups/membersModal.vue @@ -432,10 +432,10 @@ export default { if (!lastMember) return; let newMembers = await this.$store.state.memberModalOptions.fetchMoreMembers({ - challengeId: this.challengeId, - groupId: this.groupId, - lastMemberId: lastMember._id, - includeAllPublicFields: true, + challengeId: this.challengeId, + groupId: this.groupId, + lastMemberId: lastMember._id, + includeAllPublicFields: true, }); this.members = this.members.concat(newMembers); diff --git a/website/client/components/inventory/items/index.vue b/website/client/components/inventory/items/index.vue index efd01112b9..f0839b2d4d 100644 --- a/website/client/components/inventory/items/index.vue +++ b/website/client/components/inventory/items/index.vue @@ -478,7 +478,7 @@ export default { this.$refs.clickPotionInfo.style.left = `${$event.x - 60}px`; this.$refs.clickPotionInfo.style.top = `${$event.y + 10}px`; } else if (this.eggClickMode) { - // dragging eggInfo is 180px wide (90 would be centered) + // dragging eggInfo is 180px wide (90 would be centered) this.$refs.clickEggInfo.style.left = `${$event.x - 60}px`; this.$refs.clickEggInfo.style.top = `${$event.y + 10}px`; } else { diff --git a/website/client/components/static/faq.vue b/website/client/components/static/faq.vue index cec8430cd6..a26e1260cd 100644 --- a/website/client/components/static/faq.vue +++ b/website/client/components/static/faq.vue @@ -62,8 +62,8 @@ wikiTechAssistanceEmail: `mailto:${TECH_ASSISTANCE_EMAIL}`, }, // @TODO webFaqStillNeedHelp: { - // linkStart: '[', - // linkEnd: '](/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a)', + // linkStart: '[', + // linkEnd: '](/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a)', // }, // "webFaqStillNeedHelp": "If you have a question that isn't on this list or on the [Wiki FAQ](http://habitica.wikia.com/wiki/FAQ), come ask in the <%= linkStart %>Habitica Help guild<%= linkEnd %>! We're happy to help." }; diff --git a/website/client/store/actions/common.js b/website/client/store/actions/common.js index ae242fea7b..e3e2ac8428 100644 --- a/website/client/store/actions/common.js +++ b/website/client/store/actions/common.js @@ -8,9 +8,9 @@ export function equip (store, params) { equipOp(user, {params}); axios .post(`/api/v3/user/equip/${params.type}/${params.key}`); - // TODO - // .then((res) => console.log('equip', res)) - // .catch((err) => console.error('equip', err)); + // TODO + // .then((res) => console.log('equip', res)) + // .catch((err) => console.error('equip', err)); } export function hatch (store, params) { @@ -18,9 +18,9 @@ export function hatch (store, params) { hatchOp(user, {params}); axios .post(`/api/v3/user/hatch/${params.egg}/${params.hatchingPotion}`); - // TODO - // .then((res) => console.log('equip', res)) - // .catch((err) => console.error('equip', err)); + // TODO + // .then((res) => console.log('equip', res)) + // .catch((err) => console.error('equip', err)); } export async function feed (store, params) { diff --git a/website/client/store/actions/shops.js b/website/client/store/actions/shops.js index 554694f499..46480de461 100644 --- a/website/client/store/actions/shops.js +++ b/website/client/store/actions/shops.js @@ -69,16 +69,16 @@ async function buyArmoire (store, params) { // @TODO: We might need to abstract notifications to library rather than mixin const notificationOptions = isExperience ? - { - text: `+ ${item.value}`, - type: 'xp', - flavorMessage: message, - } : - { - text: message, - type: 'drop', - icon: getDropClass({type: item.type, key: item.dropKey}), - }; + { + text: `+ ${item.value}`, + type: 'xp', + flavorMessage: message, + } : + { + text: message, + type: 'drop', + icon: getDropClass({type: item.type, key: item.dropKey}), + }; store.dispatch('snackbars:add', { title: '', diff --git a/website/common/script/content/appearance/skin.js b/website/common/script/content/appearance/skin.js index 1de36e767a..ea23edd4ea 100644 --- a/website/common/script/content/appearance/skin.js +++ b/website/common/script/content/appearance/skin.js @@ -73,5 +73,5 @@ module.exports = prefill({ 'snowy': {price: 2, set: sets.winterySkins}, 'winterstar': {price: 2, set: sets.winterySkins}, - /* eslint-enable quote-props */ + /* eslint-enable quote-props */ }); diff --git a/website/common/script/content/shop-featuredItems.js b/website/common/script/content/shop-featuredItems.js index 31010cb4e4..b1881440c4 100644 --- a/website/common/script/content/shop-featuredItems.js +++ b/website/common/script/content/shop-featuredItems.js @@ -37,7 +37,7 @@ const featuredItems = { ], seasonal: 'summerMage', timeTravelers: [ - // TODO + // TODO ], }; diff --git a/website/common/script/index.js b/website/common/script/index.js index d5de49a42b..57eaa890ca 100644 --- a/website/common/script/index.js +++ b/website/common/script/index.js @@ -86,9 +86,6 @@ api.gold = gold; import silver from './libs/silver'; api.silver = silver; -import taskClasses from './libs/taskClasses'; -api.taskClasses = taskClasses; - import noTags from './libs/noTags'; api.noTags = noTags; diff --git a/website/common/script/libs/taskClasses.js b/website/common/script/libs/taskClasses.js deleted file mode 100644 index a61a82dd75..0000000000 --- a/website/common/script/libs/taskClasses.js +++ /dev/null @@ -1,83 +0,0 @@ -import { - shouldDo, -} from '../cron'; -import moment from 'moment'; - -/* -Task classes given everything about the class -*/ - -// TODO move to the client - -module.exports = function taskClasses (task, filters = [], dayStart = 0, lastCron = Number(new Date()), showCompleted = false, main = false, processingYesterdailies = false) { - if (!task) { - return ''; - } - let type = task.type; - let completed = task.completed; - let value = task.value; - let priority = task.priority; - - if (main && !task._editing) { - for (let filter in filters) { - let enabled = filters[filter]; - if (!task.tags) task.tags = []; - if (enabled && task.tags.indexOf(filter) === -1) { - return 'hidden'; - } - } - } - - let classes = task.type; - if (task._editing) { - classes += ' beingEdited'; - } - - if (type === 'todo' || type === 'daily') { - let dayShouldDo = moment(); - if (processingYesterdailies) dayShouldDo.subtract(1, 'days'); - let notDue = !shouldDo(Number(dayShouldDo), task, { dayStart }); - let isNotDueDaily = type === 'daily' && notDue; - - if (completed || isNotDueDaily) { - classes += ' completed'; - } else { - classes += ' uncompleted'; - } - } else if (type === 'habit') { - if (task.down && task.up) { - classes += ' habit-wide'; - } - if (!task.down && !task.up) { - classes += ' habit-narrow'; - } - } - - if (priority === 0.1) { - classes += ' difficulty-trivial'; - } else if (priority === 1) { - classes += ' difficulty-easy'; - } else if (priority === 1.5) { - classes += ' difficulty-medium'; - } else if (priority === 2) { - classes += ' difficulty-hard'; - } - - if (value < -20) { - classes += ' color-worst'; - } else if (value < -10) { - classes += ' color-worse'; - } else if (value < -1) { - classes += ' color-bad'; - } else if (value < 1) { - classes += ' color-neutral'; - } else if (value < 5) { - classes += ' color-good'; - } else if (value < 10) { - classes += ' color-better'; - } else { - classes += ' color-best'; - } - - return classes; -}; diff --git a/website/server/controllers/api-v3/auth.js b/website/server/controllers/api-v3/auth.js index 910568ed4a..ddb4ccbfcc 100644 --- a/website/server/controllers/api-v3/auth.js +++ b/website/server/controllers/api-v3/auth.js @@ -347,11 +347,11 @@ api.loginSocial = { // Clean previous email preferences if (savedUser.auth[network].emails && savedUser.auth[network].emails[0] && savedUser.auth[network].emails[0].value) { EmailUnsubscription - .remove({email: savedUser.auth[network].emails[0].value.toLowerCase()}) - .exec() - .then(() => { - if (!existingUser) sendTxnEmail(savedUser, 'welcome'); - }); // eslint-disable-line max-nested-callbacks + .remove({email: savedUser.auth[network].emails[0].value.toLowerCase()}) + .exec() + .then(() => { + if (!existingUser) sendTxnEmail(savedUser, 'welcome'); + }); // eslint-disable-line max-nested-callbacks } if (!existingUser) { diff --git a/website/server/controllers/api-v3/challenges.js b/website/server/controllers/api-v3/challenges.js index 7dbd7b0448..6bfb5e116b 100644 --- a/website/server/controllers/api-v3/challenges.js +++ b/website/server/controllers/api-v3/challenges.js @@ -434,11 +434,11 @@ api.getUserChallenges = { let challenges = await Challenge.find({ $or: orOptions, }) - .sort('-official -createdAt') - // see below why we're not using populate - // .populate('group', basicGroupFields) - // .populate('leader', nameFields) - .exec(); + .sort('-official -createdAt') + // see below why we're not using populate + // .populate('group', basicGroupFields) + // .populate('leader', nameFields) + .exec(); let resChals = challenges.map(challenge => challenge.toJSON()); // Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833 diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js index ae7c8c1234..bcc321d427 100644 --- a/website/server/controllers/api-v3/groups.js +++ b/website/server/controllers/api-v3/groups.js @@ -1018,9 +1018,9 @@ async function _inviteByEmail (invite, group, inviter, req, res) { if (!invite.email) throw new BadRequest(res.t('inviteMissingEmail')); let userToContact = await User.findOne({$or: [ - {'auth.local.email': invite.email}, - {'auth.facebook.emails.value': invite.email}, - {'auth.google.emails.value': invite.email}, + {'auth.local.email': invite.email}, + {'auth.facebook.emails.value': invite.email}, + {'auth.google.emails.value': invite.email}, ]}) .select({_id: true, 'preferences.emailNotifications': true}) .exec(); diff --git a/website/server/controllers/api-v3/hall.js b/website/server/controllers/api-v3/hall.js index af2b8bd104..5d836407b3 100644 --- a/website/server/controllers/api-v3/hall.js +++ b/website/server/controllers/api-v3/hall.js @@ -71,15 +71,15 @@ api.getPatrons = { const perPage = 50; let patrons = await User - .find({ - 'backer.tier': {$gt: 0}, - }) - .select('contributor backer profile.name') - .sort('-backer.tier') - .skip(page * perPage) - .limit(perPage) - .lean() - .exec(); + .find({ + 'backer.tier': {$gt: 0}, + }) + .select('contributor backer profile.name') + .sort('-backer.tier') + .skip(page * perPage) + .limit(perPage) + .lean() + .exec(); res.respond(200, patrons); }, @@ -123,13 +123,13 @@ api.getHeroes = { middlewares: [authWithHeaders()], async handler (req, res) { let heroes = await User - .find({ - 'contributor.level': {$gt: 0}, - }) - .select('contributor backer profile.name') - .sort('-contributor.level') - .lean() - .exec(); + .find({ + 'contributor.level': {$gt: 0}, + }) + .select('contributor backer profile.name') + .sort('-contributor.level') + .lean() + .exec(); res.respond(200, heroes); }, diff --git a/website/server/controllers/api-v3/i18n.js b/website/server/controllers/api-v3/i18n.js index ed1b744133..505df9b0fa 100644 --- a/website/server/controllers/api-v3/i18n.js +++ b/website/server/controllers/api-v3/i18n.js @@ -13,11 +13,11 @@ function geti18nBrowserScript (language) { return `(function () { if (!window) return; window['habitica-i18n'] = ${JSON.stringify({ - availableLanguages, - language, - strings: translations[langCode], - momentLang: momentLangs[language.momentLangCode], - })}; + availableLanguages, + language, + strings: translations[langCode], + momentLang: momentLangs[language.momentLangCode], + })}; })()`; } diff --git a/website/server/controllers/api-v3/members.js b/website/server/controllers/api-v3/members.js index b9e390891e..279f759ee7 100644 --- a/website/server/controllers/api-v3/members.js +++ b/website/server/controllers/api-v3/members.js @@ -408,8 +408,8 @@ api.getChallengeMemberProgress = { userId: memberId, 'challenge.id': challengeId, }) - .select('-tags') // We don't want to return the tags publicly TODO same for other data? - .exec(); + .select('-tags') // We don't want to return the tags publicly TODO same for other data? + .exec(); // manually call toJSON with minimize: true so empty paths aren't returned let response = member.toJSON({minimize: true}); diff --git a/website/server/controllers/api-v3/quests.js b/website/server/controllers/api-v3/quests.js index 8d4bd71992..792c37e124 100644 --- a/website/server/controllers/api-v3/quests.js +++ b/website/server/controllers/api-v3/quests.js @@ -79,8 +79,8 @@ api.inviteToQuest = { 'party._id': group._id, _id: {$ne: user._id}, }) - .select('auth.facebook auth.local preferences.emailNotifications profile.name pushDevices') - .exec(); + .select('auth.facebook auth.local preferences.emailNotifications profile.name pushDevices') + .exec(); group.markModified('quest'); group.quest.key = questKey; diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js index 2f1a1675d8..62ebb403ee 100644 --- a/website/server/controllers/api-v3/tasks/groups.js +++ b/website/server/controllers/api-v3/tasks/groups.js @@ -489,8 +489,8 @@ api.getGroupApprovals = { 'group.approval.approved': false, 'group.approval.requested': true, }, 'userId group text') - .populate('userId', 'profile') - .exec(); + .populate('userId', 'profile') + .exec(); res.respond(200, approvals); }, diff --git a/website/server/controllers/top-level/dataexport.js b/website/server/controllers/top-level/dataexport.js index 817d252d29..d8d63f01a3 100644 --- a/website/server/controllers/top-level/dataexport.js +++ b/website/server/controllers/top-level/dataexport.js @@ -159,7 +159,7 @@ api.exportUserDataXml = { * * @apiUse UserNotFound */ - // @TODO fix +// @TODO fix api.exportUserAvatarHtml = { method: 'GET', url: '/export/avatar-:memberId.html', @@ -223,11 +223,11 @@ api.exportUserAvatarPng = { } let [stream] = await new Pageres() - .src(`${BASE_URL}/export/avatar-${memberId}.html`, ['140x147'], { - crop: true, - filename: filename.replace('.png', ''), - }) - .run(); + .src(`${BASE_URL}/export/avatar-${memberId}.html`, ['140x147'], { + crop: true, + filename: filename.replace('.png', ''), + }) + .run(); let s3upload = S3.upload({ Bucket: S3_BUCKET, diff --git a/website/server/libs/logger.js b/website/server/libs/logger.js index 9d1cd13aab..67bc4df2a7 100644 --- a/website/server/libs/logger.js +++ b/website/server/libs/logger.js @@ -22,10 +22,10 @@ if (IS_PROD) { prettyPrint: false, }); logger.add(winston.transports.Loggly, { - inputToken: nconf.get('LOGGLY:TOKEN'), - subdomain: nconf.get('LOGGLY:SUBDOMAIN'), - tags: ['Winston-NodeJS'], - json: true, + inputToken: nconf.get('LOGGLY:TOKEN'), + subdomain: nconf.get('LOGGLY:SUBDOMAIN'), + tags: ['Winston-NodeJS'], + json: true, }); } } else if (!IS_TEST || IS_TEST && ENABLE_LOGS_IN_TEST) { // Do not log anything when testing unless specified diff --git a/website/server/libs/password.js b/website/server/libs/password.js index c81c836e04..12d162f6ef 100644 --- a/website/server/libs/password.js +++ b/website/server/libs/password.js @@ -21,17 +21,17 @@ export function bcryptCompare (passwordToCheck, hashedPassword) { // Used for legacy passwords that have not yet been migrated to bcrypt export function sha1Encrypt (password, salt) { return crypto - .createHmac('sha1', salt) - .update(password) - .digest('hex'); + .createHmac('sha1', salt) + .update(password) + .digest('hex'); } // Create a salt, default length is 10 export function sha1MakeSalt (len = 10) { return crypto - .randomBytes(Math.ceil(len / 2)) - .toString('hex') - .substring(0, len); + .randomBytes(Math.ceil(len / 2)) + .toString('hex') + .substring(0, len); } // Compare the password for an user diff --git a/website/server/libs/payments.js b/website/server/libs/payments.js index 33ea4c2b39..c041e3c479 100644 --- a/website/server/libs/payments.js +++ b/website/server/libs/payments.js @@ -42,7 +42,7 @@ function revealMysteryItems (user) { moment().isBefore(shared.content.mystery[item.mystery].end) && !user.items.gear.owned[item.key] && user.purchased.plan.mysteryItems.indexOf(item.key) === -1 - ) { + ) { user.purchased.plan.mysteryItems.push(item.key); pushedItems.push(item.key); } @@ -511,9 +511,9 @@ api.cancelSubscription = async function cancelSubscription (data) { plan.dateTerminated = moment(nowStr, nowStrFormat) - .add({days: remaining}) - .add({days: extraDays}) - .toDate(); + .add({days: remaining}) + .add({days: extraDays}) + .toDate(); plan.extraMonths = 0; // clear extra time. If they subscribe again, it'll be recalculated from p.dateTerminated diff --git a/website/server/libs/pushNotifications.js b/website/server/libs/pushNotifications.js index ddd7f12667..e7071c03bc 100644 --- a/website/server/libs/pushNotifications.js +++ b/website/server/libs/pushNotifications.js @@ -31,33 +31,33 @@ if (APN_ENABLED) { Key: 'apple_apn/key.pem', }).promise(), ]) - .then(([certObj, keyObj]) => { - let cert = certObj.Body.toString(); - let key = keyObj.Body.toString(); + .then(([certObj, keyObj]) => { + let cert = certObj.Body.toString(); + let key = keyObj.Body.toString(); - apn = pushNotify.apn({ - key, - cert, - }); + apn = pushNotify.apn({ + key, + cert, + }); - apn.on('error', err => logger.error('APN error', err)); - apn.on('transmissionError', (errorCode, notification, device) => { - logger.error('APN transmissionError', errorCode, notification, device); - }); + apn.on('error', err => logger.error('APN error', err)); + apn.on('transmissionError', (errorCode, notification, device) => { + logger.error('APN transmissionError', errorCode, notification, device); + }); - let feedback = new apnLib.Feedback({ - key, - cert, - batchFeedback: true, - interval: 3600, // Check for feedback once an hour - }); + let feedback = new apnLib.Feedback({ + key, + cert, + batchFeedback: true, + interval: 3600, // Check for feedback once an hour + }); - feedback.on('feedback', (devices) => { - if (devices && devices.length > 0) { - logger.info('Delivery of push notifications failed for some Apple devices.', devices); - } + feedback.on('feedback', (devices) => { + if (devices && devices.length > 0) { + logger.info('Delivery of push notifications failed for some Apple devices.', devices); + } + }); }); - }); } function sendNotification (user, details = {}) { if (!user) throw new Error('User is required.'); diff --git a/website/server/middlewares/analytics.js b/website/server/middlewares/analytics.js index f86becb773..2ab8b1fd7d 100644 --- a/website/server/middlewares/analytics.js +++ b/website/server/middlewares/analytics.js @@ -1,8 +1,8 @@ import nconf from 'nconf'; import { - track, - trackPurchase, - mockAnalyticsService, + track, + trackPurchase, + mockAnalyticsService, } from '../libs/analyticsService'; let service; diff --git a/website/server/middlewares/auth.js b/website/server/middlewares/auth.js index 012d52584a..b86f525d35 100644 --- a/website/server/middlewares/auth.js +++ b/website/server/middlewares/auth.js @@ -44,17 +44,17 @@ export function authWithHeaders (optional = false, userFieldProjection = '') { const findPromise = fields ? User.findOne(userQuery, fields) : User.findOne(userQuery); return findPromise - .exec() - .then((user) => { - if (!user) throw new NotAuthorized(res.t('invalidCredentials')); - if (user.auth.blocked) throw new NotAuthorized(res.t('accountSuspended', {communityManagerEmail: COMMUNITY_MANAGER_EMAIL, userId: user._id})); + .exec() + .then((user) => { + if (!user) throw new NotAuthorized(res.t('invalidCredentials')); + if (user.auth.blocked) throw new NotAuthorized(res.t('accountSuspended', {communityManagerEmail: COMMUNITY_MANAGER_EMAIL, userId: user._id})); - res.locals.user = user; + res.locals.user = user; - req.session.userId = user._id; - return next(); - }) - .catch(next); + req.session.userId = user._id; + return next(); + }) + .catch(next); }; } @@ -74,14 +74,14 @@ export function authWithSession (req, res, next) { return User.findOne({ _id: userId, }) - .exec() - .then((user) => { - if (!user) throw new NotAuthorized(res.t('invalidCredentials')); + .exec() + .then((user) => { + if (!user) throw new NotAuthorized(res.t('invalidCredentials')); - res.locals.user = user; - return next(); - }) - .catch(next); + res.locals.user = user; + return next(); + }) + .catch(next); } export function authWithUrl (req, res, next) { @@ -98,11 +98,11 @@ export function authWithUrl (req, res, next) { } return User.findOne({ _id: userId, apiToken }).exec() - .then((user) => { - if (!user) throw new NotAuthorized(res.t('invalidCredentials')); + .then((user) => { + if (!user) throw new NotAuthorized(res.t('invalidCredentials')); - res.locals.user = user; - return next(); - }) - .catch(next); + res.locals.user = user; + return next(); + }) + .catch(next); } diff --git a/website/server/middlewares/language.js b/website/server/middlewares/language.js index 50ef8a2b16..d5d6f2d96f 100644 --- a/website/server/middlewares/language.js +++ b/website/server/middlewares/language.js @@ -77,13 +77,13 @@ export function getUserLanguage (req, res, next) { return User.findOne({ _id: req.session.userId, }, 'preferences.language') - .lean() - .exec() - .then((user) => { - req.language = _getFromUser(user, req); - return next(); - }) - .catch(next); + .lean() + .exec() + .then((user) => { + req.language = _getFromUser(user, req); + return next(); + }) + .catch(next); } else { // Otherwise get from browser req.language = _getFromUser(null, req); return next(); diff --git a/website/server/models/group.js b/website/server/models/group.js index 49006ac0e3..45c7c99235 100644 --- a/website/server/models/group.js +++ b/website/server/models/group.js @@ -1012,16 +1012,16 @@ let tavernQ = {_id: TAVERN_ID, 'quest.key': {$ne: null}}; // we use process.nextTick because at this point the model is not yet available process.nextTick(() => { model // eslint-disable-line no-use-before-define - .findOne(tavernQ).exec() - .then(tavern => { - if (!tavern) return; // No tavern quest + .findOne(tavernQ).exec() + .then(tavern => { + if (!tavern) return; // No tavern quest - // Using _assign so we don't lose the reference to the exported tavernQuest - _.assign(tavernQuest, tavern.quest.toObject()); - }) - .catch(err => { - throw err; - }); + // Using _assign so we don't lose the reference to the exported tavernQuest + _.assign(tavernQuest, tavern.quest.toObject()); + }) + .catch(err => { + throw err; + }); }); // returns a promise