mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-10-29 12:12:36 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f72b503abd |
14
.babelrc
14
.babelrc
@@ -1,12 +1,6 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"node": true
|
||||
}
|
||||
}
|
||||
]
|
||||
"plugins": [
|
||||
"transform-es2015-modules-commonjs",
|
||||
"syntax-object-rest-spread",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
node_modules
|
||||
.git
|
||||
website
|
||||
|
||||
@@ -3,8 +3,6 @@ coverage/
|
||||
database_reports/
|
||||
website/build/
|
||||
website/transpiled-babel/
|
||||
# Has its own linter
|
||||
website/client/
|
||||
website/common/transpiled-babel/
|
||||
dist/
|
||||
dist-client/
|
||||
|
||||
10
.eslintrc
Normal file
10
.eslintrc
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true,
|
||||
},
|
||||
"extends": [
|
||||
"habitrpg",
|
||||
"habitrpg/esnext"
|
||||
],
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'habitrpg/lib/node'
|
||||
],
|
||||
}
|
||||
9
.github/CONTRIBUTING.md
vendored
9
.github/CONTRIBUTING.md
vendored
@@ -4,7 +4,7 @@
|
||||
|
||||
# Pull Request
|
||||
|
||||
[Please see these instructions for adding a pull request](http://habitica.fandom.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API)
|
||||
[Please see these instructions for adding a pull request](http://habitica.wikia.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API)
|
||||
|
||||
# Requesting a feature
|
||||
|
||||
@@ -12,9 +12,4 @@ Habitica uses [Trello](https://trello.com/b/EpoYEYod/habitica) to track feature
|
||||
|
||||
# Contributing Code
|
||||
|
||||
See [Contributing to Habitica](http://habitica.fandom.com/wiki/Contributing_to_Habitica#Coders_.28Web_.26_Mobile.29)
|
||||
|
||||
## Issue Triage [](https://www.codetriage.com/habitrpg/habitica)
|
||||
|
||||
You can triage issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to habitrpg on CodeTriage](https://www.codetriage.com/habitrpg/habitica).
|
||||
|
||||
See [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica#Coders_.28Web_.26_Mobile.29)
|
||||
|
||||
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,7 +1,7 @@
|
||||
[//]: # (Note: See http://habitica.fandom.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API for more info)
|
||||
[//]: # (Note: See http://habitica.wikia.com/wiki/Using_Your_Local_Install_to_Modify_Habitica%27s_Website_and_API for more info)
|
||||
|
||||
[//]: # (Put Issue # here, if applicable. This will automatically close the issue if your PR is merged in)
|
||||
Fixes put_#_and_issue_number_here
|
||||
[//]: # (Put Issue # or URL here, if applicable. This will automatically close the issue if your PR is merged in)
|
||||
Fixes put_issue_url_here
|
||||
|
||||
### Changes
|
||||
[//]: # (Describe the changes that were made in detail here. Include pictures if necessary)
|
||||
|
||||
198
.github/workflows/test.yml
vendored
198
.github/workflows/test.yml
vendored
@@ -1,198 +0,0 @@
|
||||
name: Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run lint-no-fix
|
||||
apidoc:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run apidoc
|
||||
sanity:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run test:sanity
|
||||
|
||||
common:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run test:common
|
||||
content:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run test:content
|
||||
|
||||
api-unit:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: sudo docker run --name mongo -d -p 27017:27017 mongo
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run test:api:unit
|
||||
env:
|
||||
REQUIRES_SERVER=true: true
|
||||
api-v3-integration:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: sudo docker run --name mongo -d -p 27017:27017 mongo
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run test:api-v3:integration
|
||||
env:
|
||||
REQUIRES_SERVER=true: true
|
||||
api-v4-integration:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: sudo docker run --name mongo -d -p 27017:27017 mongo
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run test:api-v4:integration
|
||||
env:
|
||||
REQUIRES_SERVER=true: true
|
||||
|
||||
client-unit:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: cp config.json.example config.json
|
||||
- name: npm install
|
||||
run: |
|
||||
npm ci
|
||||
env:
|
||||
CI: true
|
||||
- run: npm run test:unit
|
||||
working-directory: ./website/client
|
||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,5 +1,10 @@
|
||||
.DS_Store
|
||||
website/client-old/gen
|
||||
website/client-old/common
|
||||
website/client-old/apidoc
|
||||
website/build
|
||||
website/client-old/js/habitrpg-shared.js*
|
||||
website/client-old/css/habitrpg-shared.css
|
||||
website/transpiled-babel/
|
||||
website/common/transpiled-babel/
|
||||
node_modules
|
||||
@@ -10,6 +15,8 @@ apidoc_build
|
||||
config.json
|
||||
npm-debug.log*
|
||||
lib
|
||||
website/client-old/bower_components
|
||||
website/client-old/new-stuff.html
|
||||
newrelic_agent.log
|
||||
.bower-tmp
|
||||
.bower-registry
|
||||
@@ -20,23 +27,20 @@ TODO
|
||||
*.log
|
||||
src/*/*.map
|
||||
src/*/*/*.map
|
||||
test/*.js
|
||||
test/*.map
|
||||
website/client-old/docs
|
||||
*.sublime-workspace
|
||||
coverage
|
||||
coverage.html
|
||||
common/dist/scripts/*
|
||||
dist
|
||||
dist-client
|
||||
website/client/dist
|
||||
test/client/unit/coverage
|
||||
test/client/e2e/reports
|
||||
test/client-old/spec/mocks/translations.js
|
||||
yarn.lock
|
||||
.gitattributes
|
||||
|
||||
# Elastic Beanstalk Files
|
||||
.elasticbeanstalk/*
|
||||
!.elasticbeanstalk/*.cfg.yml
|
||||
!.elasticbeanstalk/*.global.yml
|
||||
|
||||
# webstorm fake webpack for path intellisense
|
||||
webpack.webstorm.config
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
node_modules/**
|
||||
.bower-cache/**
|
||||
.bower-tmp/**
|
||||
.bower-registry/**
|
||||
website/client-old/**
|
||||
website/client/**
|
||||
website/client/store/**
|
||||
website/views/**
|
||||
website/build/**
|
||||
dist/**
|
||||
test/**
|
||||
.git/**
|
||||
Gruntfile.js
|
||||
CHANGELOG.md
|
||||
.idea*
|
||||
*.log
|
||||
newrelic_agent.log
|
||||
*.swp
|
||||
*.swx
|
||||
website/raw_sprites/**
|
||||
|
||||
29
.travis.yml
Normal file
29
.travis.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- '8'
|
||||
services:
|
||||
- mongodb
|
||||
cache:
|
||||
directories:
|
||||
- 'node_modules'
|
||||
addons:
|
||||
chrome: stable
|
||||
before_script:
|
||||
- npm run test:build
|
||||
- cp config.json.example config.json
|
||||
- sleep 5
|
||||
script:
|
||||
- npm run $TEST
|
||||
- if [ $COVERAGE ]; then ./node_modules/.bin/lcov-result-merger 'coverage/**/*.info' | ./node_modules/coveralls/bin/coveralls.js; fi
|
||||
env:
|
||||
global:
|
||||
- DISABLE_REQUEST_LOGGING=true
|
||||
matrix:
|
||||
- TEST="lint"
|
||||
- TEST="test:api-v3:unit" REQUIRES_SERVER=true COVERAGE=true
|
||||
- TEST="test:api-v3:integration" REQUIRES_SERVER=true COVERAGE=true
|
||||
- TEST="test:sanity"
|
||||
- TEST="test:content" COVERAGE=true
|
||||
- TEST="test:common" COVERAGE=true
|
||||
- TEST="client:unit" COVERAGE=true
|
||||
- TEST="apidoc"
|
||||
45
Dockerfile
45
Dockerfile
@@ -1,27 +1,18 @@
|
||||
FROM node:12
|
||||
|
||||
ENV ADMIN_EMAIL admin@habitica.com
|
||||
ENV AMAZON_PAYMENTS_CLIENT_ID amzn1.application-oa2-client.68ed9e6904ef438fbc1bf86bf494056e
|
||||
ENV AMAZON_PAYMENTS_SELLER_ID AMQ3SB4SG5E91
|
||||
ENV AMPLITUDE_KEY e8d4c24b3d6ef3ee73eeba715023dd43
|
||||
ENV BASE_URL https://habitica.com
|
||||
ENV FACEBOOK_KEY 128307497299777
|
||||
ENV GA_ID UA-33510635-1
|
||||
ENV GOOGLE_CLIENT_ID 1035232791481-32vtplgnjnd1aufv3mcu1lthf31795fq.apps.googleusercontent.com
|
||||
ENV LOGGLY_CLIENT_TOKEN ab5663bf-241f-4d14-8783-7d80db77089a
|
||||
ENV NODE_ENV production
|
||||
ENV STRIPE_PUB_KEY pk_85fQ0yMECHNfHTSsZoxZXlPSwSNfA
|
||||
|
||||
# Install global packages
|
||||
RUN npm install -g gulp-cli mocha
|
||||
|
||||
# Clone Habitica repo and install dependencies
|
||||
RUN mkdir -p /usr/src/habitrpg
|
||||
WORKDIR /usr/src/habitrpg
|
||||
RUN git clone --branch release --depth 1 https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
|
||||
RUN npm set unsafe-perm true
|
||||
RUN npm install
|
||||
|
||||
# Start Habitica
|
||||
EXPOSE 80 8080 36612
|
||||
CMD ["node", "./website/transpiled-babel/index.js"]
|
||||
FROM node:8
|
||||
|
||||
# Install global packages
|
||||
RUN npm install -g gulp-cli mocha
|
||||
|
||||
# Clone Habitica repo and install dependencies
|
||||
RUN mkdir -p /usr/src/habitrpg
|
||||
WORKDIR /usr/src/habitrpg
|
||||
RUN git clone https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
|
||||
RUN cp config.json.example config.json
|
||||
RUN npm install
|
||||
|
||||
# Create Build dir
|
||||
RUN mkdir -p ./website/build
|
||||
|
||||
# Start Habitica
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "start"]
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
FROM node:12
|
||||
|
||||
# Install global packages
|
||||
RUN npm install -g gulp-cli mocha
|
||||
|
||||
# Copy package.json and package-lock.json into image, then install
|
||||
# dependencies.
|
||||
WORKDIR /usr/src/habitica
|
||||
COPY ["package.json", "package-lock.json", "./"]
|
||||
RUN npm install
|
||||
|
||||
# Copy the remaining source files in.
|
||||
COPY . /usr/src/habitica
|
||||
RUN npm run postinstall
|
||||
29
Dockerfile-Production
Normal file
29
Dockerfile-Production
Normal file
@@ -0,0 +1,29 @@
|
||||
FROM node:8
|
||||
|
||||
ENV ADMIN_EMAIL admin@habitica.com
|
||||
ENV AMAZON_PAYMENTS_CLIENT_ID amzn1.application-oa2-client.68ed9e6904ef438fbc1bf86bf494056e
|
||||
ENV AMAZON_PAYMENTS_SELLER_ID AMQ3SB4SG5E91
|
||||
ENV AMPLITUDE_KEY e8d4c24b3d6ef3ee73eeba715023dd43
|
||||
ENV BASE_URL https://habitica.com
|
||||
ENV FACEBOOK_KEY 128307497299777
|
||||
ENV GA_ID UA-33510635-1
|
||||
ENV GOOGLE_CLIENT_ID 1035232791481-32vtplgnjnd1aufv3mcu1lthf31795fq.apps.googleusercontent.com
|
||||
ENV NODE_ENV production
|
||||
ENV STRIPE_PUB_KEY pk_85fQ0yMECHNfHTSsZoxZXlPSwSNfA
|
||||
|
||||
# Install global packages
|
||||
RUN npm install -g gulp-cli mocha
|
||||
|
||||
# Clone Habitica repo and install dependencies
|
||||
RUN mkdir -p /usr/src/habitrpg
|
||||
WORKDIR /usr/src/habitrpg
|
||||
RUN git clone --branch v4.41.0 https://github.com/HabitRPG/habitica.git /usr/src/habitrpg
|
||||
RUN npm install
|
||||
RUN gulp build:prod --force
|
||||
|
||||
# Create Build dir
|
||||
RUN mkdir -p ./website/build
|
||||
|
||||
# Start Habitica
|
||||
EXPOSE 3000
|
||||
CMD ["node", "./website/transpiled-babel/index.js"]
|
||||
14
README.md
14
README.md
@@ -1,14 +1,12 @@
|
||||
Habitica  [](https://codeclimate.com/github/HabitRPG/habitrpg) [](https://www.bountysource.com/trackers/68393-habitrpg?utm_source=68393&utm_medium=shield&utm_campaign=TRACKER_BADGE) [](https://www.codetriage.com/habitrpg/habitica)
|
||||
Habitica [](https://travis-ci.org/HabitRPG/habitica) [](https://codeclimate.com/github/HabitRPG/habitrpg) [](https://coveralls.io/github/HabitRPG/habitica?branch=develop) [](https://www.bountysource.com/trackers/68393-habitrpg?utm_source=68393&utm_medium=shield&utm_campaign=TRACKER_BADGE) [](https://www.codetriage.com/habitrpg/habitica)
|
||||
===============
|
||||
|
||||
[](https://greenkeeper.io/)
|
||||
|
||||
[Habitica](https://habitica.com) is an open source habit building program which treats your life like a Role Playing Game. Level up as you succeed, lose HP as you fail, earn money to buy weapons and armor.
|
||||
|
||||
**We need more programmers!** Your assistance will be greatly appreciated. The wiki pages below and the additional pages they link to will tell you how to get started on contributing code and where you can go to seek further help or ask questions:
|
||||
* [Guidance for Blacksmiths](http://habitica.fandom.com/wiki/Guidance_for_Blacksmiths) - an introduction to the technologies used and how the software is organized.
|
||||
* [Setting up Habitica Locally](http://habitica.fandom.com/wiki/Setting_up_Habitica_Locally) - how to set up a local install of Habitica for development and testing on various platforms.
|
||||
We need more programmers! Your assistance will be greatly appreciated.
|
||||
|
||||
Habitica's code is licensed as described at https://github.com/HabitRPG/habitica/blob/develop/LICENSE
|
||||
For an introduction to the technologies used and how the software is organized, refer to [Guidance for Blacksmiths](http://habitica.wikia.com/wiki/Guidance_for_Blacksmiths).
|
||||
|
||||
**Found a bug?** Please report it in the [Report a Bug guild](https://habitica.com/groups/guild/a29da26b-37de-4a71-b0c6-48e72a900dac) rather than creating an issue (an admin will advise you if a new issue is necessary; usually it is not).
|
||||
|
||||
**Have any questions about Habitica or its community?** See the links in the [habitica.com](https://habitica.com) website's Help menu or drop in to [Guilds > Tavern Chat](https://habitica.com/groups/tavern) to ask questions or chat socially!
|
||||
To set up a local install of Habitica for development and testing on various platforms, see [Setting up Habitica Locally](http://habitica.wikia.com/wiki/Setting_up_Habitica_Locally).
|
||||
|
||||
11
VAGRANT.md
Normal file
11
VAGRANT.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Vagrant #
|
||||
|
||||
Vagrant is a system to create reproducible and portable development
|
||||
environments. Because of the variety of systems used for Habitica
|
||||
development and the various issues developers may encounter setting up
|
||||
Habitica on them, vagrant provides a single development enviroment with
|
||||
minimal dependencies on the developer's local platform. It can be used
|
||||
on a variety of systems including Windows, Mac OS X, and Linux.
|
||||
|
||||
Instructions for using the Habitica Vagrant environment are in
|
||||
[Setting up Habitica Locally](http://habitica.wikia.com/wiki/Setting_up_Habitica_Locally).
|
||||
22
Vagrantfile.example
Normal file
22
Vagrantfile.example
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
||||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
config.vm.provider "virtualbox" do |v|
|
||||
v.memory = 4096
|
||||
v.cpus = 1
|
||||
v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/vagrant", "1"]
|
||||
end
|
||||
config.vm.box = "thepeopleseason/habitrpg"
|
||||
config.ssh.forward_agent = true
|
||||
|
||||
config.vm.hostname = "habitrpg"
|
||||
config.vm.network "forwarded_port", guest: 3000, host: 3000, auto_correct: true
|
||||
config.vm.usable_port_range = (3000..3050)
|
||||
config.vm.network "forwarded_port", guest: 8080, host: 8080, auto_correct: true
|
||||
config.vm.usable_port_range = (8080..8130)
|
||||
config.vm.provision :shell, :path => "vagrant_scripts/vagrant.sh"
|
||||
end
|
||||
@@ -1,78 +1,116 @@
|
||||
{
|
||||
"ADMIN_EMAIL": "you@example.com",
|
||||
"AMAZON_PAYMENTS_CLIENT_ID": "CLIENT_ID",
|
||||
"AMAZON_PAYMENTS_MODE": "sandbox",
|
||||
"AMAZON_PAYMENTS_MWS_KEY": "MWS_KEY",
|
||||
"AMAZON_PAYMENTS_MWS_SECRET": "MWS_SECRET",
|
||||
"AMAZON_PAYMENTS_SELLER_ID": "SELLER_ID",
|
||||
"AMPLITUDE_KEY": "AMPLITUDE_KEY",
|
||||
"AMPLITUDE_SECRET": "AMPLITUDE_SECRET",
|
||||
"BASE_URL": "http://localhost:3000",
|
||||
"CRON_SAFE_MODE": "false",
|
||||
"CRON_SEMI_SAFE_MODE": "false",
|
||||
"DISABLE_REQUEST_LOGGING": "true",
|
||||
"EMAILS_COMMUNITY_MANAGER_EMAIL": "admin@habitica.com",
|
||||
"EMAILS_PRESS_ENQUIRY_EMAIL": "admin@habitica.com",
|
||||
"EMAILS_TECH_ASSISTANCE_EMAIL": "admin@habitica.com",
|
||||
"EMAIL_SERVER_AUTH_PASSWORD": "password",
|
||||
"EMAIL_SERVER_AUTH_USER": "user",
|
||||
"EMAIL_SERVER_URL": "http://example.com",
|
||||
"ENABLE_CONSOLE_LOGS_IN_PROD": "false",
|
||||
"ENABLE_CONSOLE_LOGS_IN_TEST": "false",
|
||||
"FACEBOOK_KEY": "123456789012345",
|
||||
"FACEBOOK_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"FLAG_REPORT_EMAIL": "email@example.com, email2@example.com",
|
||||
"GA_ID": "GA_ID",
|
||||
"GOOGLE_CLIENT_ID": "123456789012345",
|
||||
"GOOGLE_CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"IAP_GOOGLE_KEYDIR": "/path/to/google/public/key/dir/",
|
||||
"IGNORE_REDIRECT": "true",
|
||||
"ITUNES_SHARED_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"LOGGLY_CLIENT_TOKEN": "token",
|
||||
"LOGGLY_SUBDOMAIN": "example-subdomain",
|
||||
"LOGGLY_TOKEN": "example-token",
|
||||
"MAINTENANCE_MODE": "false",
|
||||
"NODE_DB_URI": "mongodb://localhost:27017/habitrpg",
|
||||
"MONGODB_POOL_SIZE": "10",
|
||||
"NODE_ENV": "development",
|
||||
"PATH": "bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin",
|
||||
"PAYPAL_BILLING_PLANS_basic_12mo": "basic_12mo",
|
||||
"PAYPAL_BILLING_PLANS_basic_3mo": "basic_3mo",
|
||||
"PAYPAL_BILLING_PLANS_basic_6mo": "basic_6mo",
|
||||
"PAYPAL_BILLING_PLANS_basic_earned": "basic_earned",
|
||||
"PAYPAL_BILLING_PLANS_google_6mo": "google_6mo",
|
||||
"PAYPAL_CLIENT_ID": "client_id",
|
||||
"PAYPAL_CLIENT_SECRET": "client_secret",
|
||||
"PAYPAL_EXPERIENCE_PROFILE_ID": "xp_profile_id",
|
||||
"PAYPAL_MODE": "sandbox",
|
||||
"PLAY_API_ACCESS_TOKEN": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API_CLIENT_ID": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API_CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API_REFRESH_TOKEN": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"PORT": 3000,
|
||||
"PUSH_CONFIGS_APN_ENABLED": "false",
|
||||
"PUSH_CONFIGS_APN_KEY": "xxxxxxxxxx",
|
||||
"PUSH_CONFIGS_APN_KEY_ID": "xxxxxxxxxx",
|
||||
"PUSH_CONFIGS_APN_TEAM_ID": "aaabbbcccd",
|
||||
"PUSH_CONFIGS_FCM_SERVER_API_KEY": "aaabbbcccd",
|
||||
"S3_ACCESS_KEY_ID": "accessKeyId",
|
||||
"S3_BUCKET": "bucket",
|
||||
"S3_SECRET_ACCESS_KEY": "secretAccessKey",
|
||||
"SESSION_SECRET": "YOUR SECRET HERE",
|
||||
"SESSION_SECRET_IV": "12345678912345678912345678912345",
|
||||
"SESSION_SECRET_KEY": "1234567891234567891234567891234567891234567891234567891234567891",
|
||||
"SITE_HTTP_AUTH_ENABLED": "false",
|
||||
"SITE_HTTP_AUTH_PASSWORDS": "password,wordpass,passkey",
|
||||
"SITE_HTTP_AUTH_USERNAMES": "admin,tester,contributor",
|
||||
"SLACK_FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
||||
"SLACK_FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
"SLACK_SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
"SLACK_URL": "https://hooks.slack.com/services/some-url",
|
||||
"STRIPE_API_KEY": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"STRIPE_PUB_KEY": "22223333444455556666777788889999",
|
||||
"TEST_DB_URI": "mongodb://localhost:27017/habitrpg_test",
|
||||
"TRANSIFEX_SLACK_CHANNEL": "transifex",
|
||||
"WEB_CONCURRENCY": 1,
|
||||
"SKIP_SSL_CHECK_KEY": "key",
|
||||
"ENABLE_STACKDRIVER_TRACING": "false"
|
||||
"PORT":3000,
|
||||
"ENABLE_CONSOLE_LOGS_IN_PROD":"false",
|
||||
"IP":"0.0.0.0",
|
||||
"WEB_CONCURRENCY":1,
|
||||
"BASE_URL":"http://localhost:3000",
|
||||
"FACEBOOK_KEY":"123456789012345",
|
||||
"FACEBOOK_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"GOOGLE_CLIENT_ID":"123456789012345",
|
||||
"GOOGLE_CLIENT_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"PLAY_API": {
|
||||
"CLIENT_ID": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"ACCESS_TOKEN":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"REFRESH_TOKEN":"aaaabbbbccccddddeeeeffff00001111"
|
||||
},
|
||||
"NODE_DB_URI":"mongodb://localhost/habitrpg",
|
||||
"TEST_DB_URI":"mongodb://localhost/habitrpg_test",
|
||||
"NODE_ENV":"development",
|
||||
"ENABLE_CONSOLE_LOGS_IN_TEST": false,
|
||||
"CRON_SAFE_MODE":"false",
|
||||
"CRON_SEMI_SAFE_MODE":"false",
|
||||
"MAINTENANCE_MODE": "false",
|
||||
"SESSION_SECRET":"YOUR SECRET HERE",
|
||||
"SESSION_SECRET_KEY": "1234567891234567891234567891234567891234567891234567891234567891",
|
||||
"SESSION_SECRET_IV": "12345678912345678912345678912345",
|
||||
"ADMIN_EMAIL": "you@example.com",
|
||||
"SMTP_USER":"user@example.com",
|
||||
"SMTP_PASS":"password",
|
||||
"SMTP_SERVICE":"Gmail",
|
||||
"SMTP_HOST":"example.com",
|
||||
"SMTP_PORT": 587,
|
||||
"SMTP_TLS": true,
|
||||
"STRIPE_API_KEY":"aaaabbbbccccddddeeeeffff00001111",
|
||||
"STRIPE_PUB_KEY":"22223333444455556666777788889999",
|
||||
"NEW_RELIC_LICENSE_KEY":"NEW_RELIC_LICENSE_KEY",
|
||||
"NEW_RELIC_NO_CONFIG_FILE":"true",
|
||||
"NEW_RELIC_APPLICATION_ID":"NEW_RELIC_APPLICATION_ID",
|
||||
"NEW_RELIC_API_KEY":"NEW_RELIC_API_KEY",
|
||||
"GA_ID": "GA_ID",
|
||||
"AMPLITUDE_KEY": "AMPLITUDE_KEY",
|
||||
"AMAZON_PAYMENTS": {
|
||||
"SELLER_ID": "SELLER_ID",
|
||||
"CLIENT_ID": "CLIENT_ID",
|
||||
"MWS_KEY": "",
|
||||
"MWS_SECRET": ""
|
||||
},
|
||||
"FLAG_REPORT_EMAIL": "email@mod.com,email2@mod.com",
|
||||
"EMAIL_SERVER": {
|
||||
"url": "http://example.com",
|
||||
"authUser": "user",
|
||||
"authPassword": "password"
|
||||
},
|
||||
"S3":{
|
||||
"bucket":"bucket",
|
||||
"accessKeyId":"accessKeyId",
|
||||
"secretAccessKey":"secretAccessKey"
|
||||
},
|
||||
"SLACK_URL": "https://hooks.slack.com/services/some-url",
|
||||
"TRANSIFEX_SLACK_CHANNEL": "transifex",
|
||||
"PAYPAL":{
|
||||
"billing_plans": {
|
||||
"basic_earned":"basic_earned",
|
||||
"basic_3mo":"basic_3mo",
|
||||
"basic_6mo":"basic_6mo",
|
||||
"google_6mo":"google_6mo",
|
||||
"basic_12mo":"basic_12mo"
|
||||
},
|
||||
"mode":"sandbox",
|
||||
"client_id":"client_id",
|
||||
"client_secret":"client_secret",
|
||||
"experience_profile_id": ""
|
||||
},
|
||||
"IAP_GOOGLE_KEYDIR": "/path/to/google/public/key/dir/",
|
||||
"LOGGLY_TOKEN": "token",
|
||||
"LOGGLY_CLIENT_TOKEN": "token",
|
||||
"LOGGLY_ACCOUNT": "account",
|
||||
"PUSH_CONFIGS": {
|
||||
"GCM_SERVER_API_KEY": "",
|
||||
"APN_ENABLED": "false",
|
||||
"FCM_SERVER_API_KEY": ""
|
||||
},
|
||||
"SITE_HTTP_AUTH": {
|
||||
"ENABLED": "false",
|
||||
"USERNAME": "admin",
|
||||
"PASSWORD": "password"
|
||||
},
|
||||
"PUSHER": {
|
||||
"ENABLED": "false",
|
||||
"APP_ID": "appId",
|
||||
"KEY": "key",
|
||||
"SECRET": "secret"
|
||||
},
|
||||
"SLACK": {
|
||||
"FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
||||
"FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
||||
"SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id"
|
||||
},
|
||||
"ITUNES_SHARED_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||
"EMAILS" : {
|
||||
"COMMUNITY_MANAGER_EMAIL" : "admin@habitica.com",
|
||||
"TECH_ASSISTANCE_EMAIL" : "admin@habitica.com",
|
||||
"PRESS_ENQUIRY_EMAIL" : "admin@habitica.com"
|
||||
},
|
||||
"LOGGLY" : {
|
||||
"TOKEN" : "example-token",
|
||||
"SUBDOMAIN" : "exmaple-subdomain"
|
||||
},
|
||||
"KAFKA": {
|
||||
"GROUP_ID": "",
|
||||
"CLOUDKARAFKA_BROKERS": "",
|
||||
"CLOUDKARAFKA_USERNAME": "",
|
||||
"CLOUDKARAFKA_PASSWORD": "",
|
||||
"CLOUDKARAFKA_TOPIC_PREFIX": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
import max from 'lodash/max';
|
||||
import mean from 'lodash/mean';
|
||||
import monk from 'monk';
|
||||
import round from 'lodash/round';
|
||||
import sum from 'lodash/sum';
|
||||
|
||||
/*
|
||||
* Output data on subscribers' task histories, formatted for CSV.
|
||||
* User ID,Count of Dailies,Count of Habits,Total History Size,Max History Size,Mean History Size,Median History Size
|
||||
*/
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
|
||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
let dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||
|
||||
function usersReport () {
|
||||
let allHistoryLengths = [];
|
||||
|
||||
console.info('User ID,Count of Dailies,Count of Habits,Total History Size,Max History Size,Mean History Size,Median History Size');
|
||||
|
||||
dbUsers.find(
|
||||
{
|
||||
$and:
|
||||
[
|
||||
{'purchased.plan.planId': {$ne:null}},
|
||||
{'purchased.plan.planId': {$ne:''}},
|
||||
],
|
||||
$or:
|
||||
[
|
||||
{'purchased.plan.dateTerminated': null},
|
||||
{'purchased.plan.dateTerminated': ''},
|
||||
{'purchased.plan.dateTerminated': {$gt:new Date()}},
|
||||
],
|
||||
},
|
||||
{
|
||||
fields: {_id: 1},
|
||||
}
|
||||
).each((user, {close, pause, resume}) => {
|
||||
let historyLengths = [];
|
||||
let habitCount = 0;
|
||||
let dailyCount = 0;
|
||||
|
||||
pause();
|
||||
return dbTasks.find(
|
||||
{
|
||||
userId: user._id,
|
||||
$or:
|
||||
[
|
||||
{type: 'habit'},
|
||||
{type: 'daily'},
|
||||
],
|
||||
},
|
||||
{
|
||||
fields: {
|
||||
type: 1,
|
||||
history: 1,
|
||||
},
|
||||
}
|
||||
).each((task) => {
|
||||
if (task.type === 'habit') {
|
||||
habitCount++;
|
||||
}
|
||||
if (task.type === 'daily') {
|
||||
dailyCount++;
|
||||
}
|
||||
if (task.history.length > 0) {
|
||||
allHistoryLengths.push(task.history.length);
|
||||
historyLengths.push(task.history.length);
|
||||
}
|
||||
}).then(() => {
|
||||
const totalHistory = sum(historyLengths);
|
||||
const maxHistory = historyLengths.length > 0 ? max(historyLengths) : 0;
|
||||
const meanHistory = historyLengths.length > 0 ? round(mean(historyLengths)) : 0;
|
||||
const medianHistory = historyLengths.length > 0 ? median(historyLengths) : 0;
|
||||
console.info(`${user._id},${dailyCount},${habitCount},${totalHistory},${maxHistory},${meanHistory},${medianHistory}`);
|
||||
resume();
|
||||
});
|
||||
}).then(() => {
|
||||
console.info(`Total Subscriber History Entries: ${sum(allHistoryLengths)}`);
|
||||
console.info(`Largest History Size: ${max(allHistoryLengths)}`);
|
||||
console.info(`Mean History Size: ${round(mean(allHistoryLengths))}`);
|
||||
console.info(`Median History Size: ${median(allHistoryLengths)}`);
|
||||
return process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
function median(values) { // https://gist.github.com/caseyjustus/1166258
|
||||
values.sort( function(a,b) {return a - b;} );
|
||||
|
||||
var half = Math.floor(values.length/2);
|
||||
|
||||
if (values.length % 2) {
|
||||
return values[half];
|
||||
}
|
||||
else {
|
||||
return (values[half-1] + values[half]) / 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = usersReport;
|
||||
@@ -1,48 +0,0 @@
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
|
||||
/*
|
||||
* Output data on users who completed all the To-Do tasks in the 2018 Back-to-School Challenge.
|
||||
* User ID,Profile Name
|
||||
*/
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
const CHALLENGE_ID = '0acb1d56-1660-41a4-af80-9259f080b62b';
|
||||
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
let dbTasks = monk(CONNECTION_STRING).get('tasks', { castIds: false });
|
||||
|
||||
function usersReport() {
|
||||
console.info('User ID,Profile Name');
|
||||
let userCount = 0;
|
||||
|
||||
dbUsers.find(
|
||||
{challenges: CHALLENGE_ID},
|
||||
{fields:
|
||||
{_id: 1, 'profile.name': 1}
|
||||
},
|
||||
).each((user, {close, pause, resume}) => {
|
||||
pause();
|
||||
userCount++;
|
||||
let completedTodos = 0;
|
||||
return dbTasks.find(
|
||||
{
|
||||
userId: user._id,
|
||||
'challenge.id': CHALLENGE_ID,
|
||||
type: 'todo',
|
||||
},
|
||||
{fields: {completed: 1}}
|
||||
).each((task) => {
|
||||
if (task.completed) completedTodos++;
|
||||
}).then(() => {
|
||||
if (completedTodos >= 7) {
|
||||
console.info(`${user._id},${user.profile.name}`);
|
||||
}
|
||||
resume();
|
||||
});
|
||||
}).then(() => {
|
||||
console.info(`${userCount} users reviewed`);
|
||||
return process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = usersReport;
|
||||
@@ -1,46 +1,10 @@
|
||||
version: "3"
|
||||
services:
|
||||
|
||||
client:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile-Dev
|
||||
command: ["npm", "run", "client:dev"]
|
||||
depends_on:
|
||||
- server
|
||||
environment:
|
||||
- BASE_URL=http://server:3000
|
||||
image: habitica
|
||||
networks:
|
||||
- habitica
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- .:/usr/src/habitica
|
||||
- /usr/src/habitica/node_modules
|
||||
- /usr/src/habitica/website/client/node_modules
|
||||
- '.:/usr/src/habitrpg'
|
||||
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile-Dev
|
||||
command: ["npm", "start"]
|
||||
depends_on:
|
||||
- mongo
|
||||
environment:
|
||||
- NODE_DB_URI=mongodb://mongo/habitrpg
|
||||
image: habitica
|
||||
networks:
|
||||
- habitica
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- .:/usr/src/habitica
|
||||
- /usr/src/habitica/node_modules
|
||||
mongo:
|
||||
image: mongo:3.6
|
||||
networks:
|
||||
- habitica
|
||||
ports:
|
||||
- "27017:27017"
|
||||
networks:
|
||||
habitica:
|
||||
driver: bridge
|
||||
- '.:/usr/src/habitrpg'
|
||||
|
||||
@@ -25,7 +25,7 @@ services:
|
||||
- mongo
|
||||
|
||||
mongo:
|
||||
image: mongo:3.6
|
||||
image: mongo:3.4
|
||||
ports:
|
||||
- "27017:27017"
|
||||
networks:
|
||||
|
||||
@@ -4,12 +4,12 @@ import apidoc from 'apidoc';
|
||||
|
||||
const APIDOC_DEST_PATH = './apidoc_build';
|
||||
const APIDOC_SRC_PATH = './website/server';
|
||||
gulp.task('apidoc:clean', done => {
|
||||
gulp.task('apidoc:clean', (done) => {
|
||||
clean(APIDOC_DEST_PATH, done);
|
||||
});
|
||||
|
||||
gulp.task('apidoc', gulp.series('apidoc:clean', done => {
|
||||
const result = apidoc.createDoc({
|
||||
gulp.task('apidoc', gulp.series('apidoc:clean', (done) => {
|
||||
let result = apidoc.createDoc({
|
||||
src: APIDOC_SRC_PATH,
|
||||
dest: APIDOC_DEST_PATH,
|
||||
});
|
||||
@@ -21,4 +21,6 @@ gulp.task('apidoc', gulp.series('apidoc:clean', done => {
|
||||
}
|
||||
}));
|
||||
|
||||
gulp.task('apidoc:watch', gulp.series('apidoc', done => gulp.watch(`${APIDOC_SRC_PATH}/**/*.js`, gulp.series('apidoc', done))));
|
||||
gulp.task('apidoc:watch', gulp.series('apidoc', (done) => {
|
||||
return gulp.watch(`${APIDOC_SRC_PATH}/**/*.js`, gulp.series('apidoc', done));
|
||||
}));
|
||||
|
||||
@@ -1,28 +1,43 @@
|
||||
import gulp from 'gulp';
|
||||
import babel from 'gulp-babel';
|
||||
import webpackProductionBuild from '../webpack/build';
|
||||
|
||||
gulp.task('build:src', () => gulp.src('website/server/**/*.js')
|
||||
.pipe(babel())
|
||||
.pipe(gulp.dest('website/transpiled-babel/')));
|
||||
gulp.task('build:src', () => {
|
||||
return gulp.src('website/server/**/*.js')
|
||||
.pipe(babel())
|
||||
.pipe(gulp.dest('website/transpiled-babel/'));
|
||||
});
|
||||
|
||||
gulp.task('build:common', () => gulp.src('website/common/script/**/*.js')
|
||||
.pipe(babel())
|
||||
.pipe(gulp.dest('website/common/transpiled-babel/')));
|
||||
gulp.task('build:common', () => {
|
||||
return gulp.src('website/common/script/**/*.js')
|
||||
.pipe(babel())
|
||||
.pipe(gulp.dest('website/common/transpiled-babel/'));
|
||||
});
|
||||
|
||||
gulp.task('build:server', gulp.series('build:src', 'build:common', done => done()));
|
||||
|
||||
// Client Production Build
|
||||
gulp.task('build:client', (done) => {
|
||||
webpackProductionBuild((err, output) => {
|
||||
if (err) return done(err);
|
||||
console.log(output); // eslint-disable-line no-console
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('build:prod', gulp.series(
|
||||
'build:server',
|
||||
'build:client',
|
||||
'apidoc',
|
||||
done => done(),
|
||||
done => done()
|
||||
));
|
||||
|
||||
const buildArgs = [];
|
||||
let buildArgs = [];
|
||||
|
||||
if (process.env.NODE_ENV === 'production') { // eslint-disable-line no-process-env
|
||||
buildArgs.push('build:prod');
|
||||
}
|
||||
|
||||
gulp.task('build', gulp.series(buildArgs, done => {
|
||||
gulp.task('build', gulp.series(buildArgs, (done) => {
|
||||
done();
|
||||
}));
|
||||
}));
|
||||
@@ -1,30 +1,26 @@
|
||||
import mongoose from 'mongoose';
|
||||
import nconf from 'nconf';
|
||||
import repl from 'repl';
|
||||
import gulp from 'gulp';
|
||||
import logger from '../website/server/libs/logger';
|
||||
import logger from '../website/server/libs/logger';
|
||||
import nconf from 'nconf';
|
||||
import repl from 'repl';
|
||||
import gulp from 'gulp';
|
||||
|
||||
// Add additional properties to the repl's context
|
||||
const improveRepl = context => {
|
||||
let improveRepl = (context) => {
|
||||
// Let "exit" and "quit" terminate the console
|
||||
['exit', 'quit'].forEach(term => {
|
||||
Object.defineProperty(context, term, {
|
||||
get () { // eslint-disable-line getter-return
|
||||
process.exit();
|
||||
},
|
||||
});
|
||||
['exit', 'quit'].forEach((term) => {
|
||||
Object.defineProperty(context, term, { get () {
|
||||
process.exit();
|
||||
}});
|
||||
});
|
||||
|
||||
// "clear" clears the screen
|
||||
Object.defineProperty(context, 'clear', {
|
||||
get () { // eslint-disable-line getter-return
|
||||
process.stdout.write('\u001B[2J\u001B[0;0f');
|
||||
},
|
||||
});
|
||||
Object.defineProperty(context, 'clear', { get () {
|
||||
process.stdout.write('\u001B[2J\u001B[0;0f');
|
||||
}});
|
||||
|
||||
context.Challenge = require('../website/server/models/challenge').model; // eslint-disable-line global-require
|
||||
context.Group = require('../website/server/models/group').model; // eslint-disable-line global-require
|
||||
context.User = require('../website/server/models/user').model; // eslint-disable-line global-require
|
||||
context.Group = require('../website/server/models/group').model; // eslint-disable-line global-require
|
||||
context.User = require('../website/server/models/user').model; // eslint-disable-line global-require
|
||||
|
||||
const isProd = nconf.get('NODE_ENV') === 'production';
|
||||
const mongooseOptions = !isProd ? {} : {
|
||||
@@ -34,14 +30,14 @@ const improveRepl = context => {
|
||||
mongoose.connect(
|
||||
nconf.get('NODE_DB_URI'),
|
||||
mongooseOptions,
|
||||
err => {
|
||||
(err) => {
|
||||
if (err) throw err;
|
||||
logger.info('Connected with Mongoose');
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
gulp.task('console', done => {
|
||||
gulp.task('console', (done) => {
|
||||
improveRepl(repl.start({
|
||||
prompt: 'Habitica > ',
|
||||
}).context);
|
||||
|
||||
@@ -4,29 +4,29 @@ import spritesmith from 'gulp.spritesmith';
|
||||
import clean from 'rimraf';
|
||||
import sizeOf from 'image-size';
|
||||
import mergeStream from 'merge-stream';
|
||||
import { basename } from 'path';
|
||||
import { sync } from 'glob';
|
||||
import { each } from 'lodash';
|
||||
import {basename} from 'path';
|
||||
import {sync} from 'glob';
|
||||
import {each} from 'lodash';
|
||||
import vinylBuffer from 'vinyl-buffer';
|
||||
|
||||
// https://github.com/Ensighten/grunt-spritesmith/issues/67#issuecomment-34786248
|
||||
const MAX_SPRITESHEET_SIZE = 1024 * 1024 * 3;
|
||||
|
||||
const IMG_DIST_PATH = 'website/client/src/assets/images/sprites/';
|
||||
const CSS_DIST_PATH = 'website/client/src/assets/css/sprites/';
|
||||
const IMG_DIST_PATH = 'website/client/assets/images/sprites/';
|
||||
const CSS_DIST_PATH = 'website/client/assets/css/sprites/';
|
||||
|
||||
function checkForSpecialTreatment (name) {
|
||||
const regex = /^hair|skin|beard|mustach|shirt|flower|^headAccessory_special_\w+Ears|^eyewear_special_\w+TopFrame|^eyewear_special_\w+HalfMoon/;
|
||||
let regex = /^hair|skin|beard|mustach|shirt|flower|^headAccessory_special_\w+Ears|^eyewear_special_\w+TopFrame/;
|
||||
return name.match(regex) || name === 'head_0';
|
||||
}
|
||||
|
||||
function calculateImgDimensions (img, addPadding) {
|
||||
let dims = sizeOf(img);
|
||||
|
||||
const requiresSpecialTreatment = checkForSpecialTreatment(img);
|
||||
let requiresSpecialTreatment = checkForSpecialTreatment(img);
|
||||
if (requiresSpecialTreatment) {
|
||||
const newWidth = dims.width < 90 ? 90 : dims.width;
|
||||
const newHeight = dims.height < 90 ? 90 : dims.height;
|
||||
let newWidth = dims.width < 90 ? 90 : dims.width;
|
||||
let newHeight = dims.height < 90 ? 90 : dims.height;
|
||||
dims = {
|
||||
width: newWidth,
|
||||
height: newHeight,
|
||||
@@ -41,17 +41,17 @@ function calculateImgDimensions (img, addPadding) {
|
||||
|
||||
if (!dims.width || !dims.height) console.error('MISSING DIMENSIONS:', dims); // eslint-disable-line no-console
|
||||
|
||||
const totalPixelSize = dims.width * dims.height + padding;
|
||||
let totalPixelSize = dims.width * dims.height + padding;
|
||||
|
||||
return totalPixelSize;
|
||||
}
|
||||
|
||||
function calculateSpritesheetsSrcIndicies (src) {
|
||||
let totalPixels = 0;
|
||||
const slices = [0];
|
||||
let slices = [0];
|
||||
|
||||
each(src, (img, index) => {
|
||||
const imageSize = calculateImgDimensions(img, true);
|
||||
let imageSize = calculateImgDimensions(img, true);
|
||||
totalPixels += imageSize;
|
||||
|
||||
if (totalPixels > MAX_SPRITESHEET_SIZE) {
|
||||
@@ -64,35 +64,37 @@ function calculateSpritesheetsSrcIndicies (src) {
|
||||
}
|
||||
|
||||
function cssVarMap (sprite) {
|
||||
// For hair, skins, beards, etc. we want to output a '.customize-options.WHATEVER' class,
|
||||
// which works as a 60x60 image pointing at the proper part of the 90x90 sprite.
|
||||
// For hair, skins, beards, etc. we want to output a '.customize-options.WHATEVER' class, which works as a
|
||||
// 60x60 image pointing at the proper part of the 90x90 sprite.
|
||||
// We set up the custom info here, and the template makes use of it.
|
||||
const requiresSpecialTreatment = checkForSpecialTreatment(sprite.name);
|
||||
let requiresSpecialTreatment = checkForSpecialTreatment(sprite.name);
|
||||
if (requiresSpecialTreatment) {
|
||||
sprite.custom = {
|
||||
px: {
|
||||
offsetX: `-${sprite.x + 25}px`,
|
||||
offsetY: `-${sprite.y + 15}px`,
|
||||
offsetX: `-${ sprite.x + 25 }px`,
|
||||
offsetY: `-${ sprite.y + 15 }px`,
|
||||
width: '60px',
|
||||
height: '60px',
|
||||
},
|
||||
};
|
||||
}
|
||||
if (sprite.name.indexOf('shirt') !== -1) sprite.custom.px.offsetY = `-${sprite.y + 35}px`; // even more for shirts
|
||||
if (sprite.name.indexOf('shirt') !== -1)
|
||||
sprite.custom.px.offsetY = `-${ sprite.y + 35 }px`; // even more for shirts
|
||||
if (sprite.name.indexOf('hair_base') !== -1) {
|
||||
const styleArray = sprite.name.split('_').slice(2, 3);
|
||||
if (Number(styleArray[0]) > 14) sprite.custom.px.offsetY = `-${sprite.y}px`; // don't crop updos
|
||||
let styleArray = sprite.name.split('_').slice(2, 3);
|
||||
if (Number(styleArray[0]) > 14)
|
||||
sprite.custom.px.offsetY = `-${ sprite.y }px`; // don't crop updos
|
||||
}
|
||||
}
|
||||
|
||||
function createSpritesStream (name, src) {
|
||||
const spritesheetSliceIndicies = calculateSpritesheetsSrcIndicies(src);
|
||||
const stream = mergeStream();
|
||||
let spritesheetSliceIndicies = calculateSpritesheetsSrcIndicies(src);
|
||||
let stream = mergeStream();
|
||||
|
||||
each(spritesheetSliceIndicies, (start, index) => {
|
||||
const slicedSrc = src.slice(start, spritesheetSliceIndicies[index + 1]);
|
||||
let slicedSrc = src.slice(start, spritesheetSliceIndicies[index + 1]);
|
||||
|
||||
const spriteData = gulp.src(slicedSrc)
|
||||
let spriteData = gulp.src(slicedSrc)
|
||||
.pipe(spritesmith({
|
||||
imgName: `spritesmith-${name}-${index}.png`,
|
||||
cssName: `spritesmith-${name}-${index}.css`,
|
||||
@@ -102,12 +104,12 @@ function createSpritesStream (name, src) {
|
||||
cssVarMap,
|
||||
}));
|
||||
|
||||
const imgStream = spriteData.img
|
||||
let imgStream = spriteData.img
|
||||
.pipe(vinylBuffer())
|
||||
.pipe(imagemin())
|
||||
.pipe(gulp.dest(IMG_DIST_PATH));
|
||||
|
||||
const cssStream = spriteData.css
|
||||
let cssStream = spriteData.css
|
||||
.pipe(gulp.dest(CSS_DIST_PATH));
|
||||
|
||||
stream.add(imgStream);
|
||||
@@ -118,32 +120,32 @@ function createSpritesStream (name, src) {
|
||||
}
|
||||
|
||||
gulp.task('sprites:main', () => {
|
||||
const mainSrc = sync('website/raw_sprites/spritesmith/**/*.png');
|
||||
let mainSrc = sync('website/raw_sprites/spritesmith/**/*.png');
|
||||
return createSpritesStream('main', mainSrc);
|
||||
});
|
||||
|
||||
gulp.task('sprites:largeSprites', () => {
|
||||
const largeSrc = sync('website/raw_sprites/spritesmith_large/**/*.png');
|
||||
let largeSrc = sync('website/raw_sprites/spritesmith_large/**/*.png');
|
||||
return createSpritesStream('largeSprites', largeSrc);
|
||||
});
|
||||
|
||||
gulp.task('sprites:clean', done => {
|
||||
gulp.task('sprites:clean', (done) => {
|
||||
clean(`${IMG_DIST_PATH}spritesmith*,${CSS_DIST_PATH}spritesmith*}`, done);
|
||||
});
|
||||
|
||||
gulp.task('sprites:checkCompiledDimensions', gulp.series('sprites:main', 'sprites:largeSprites', done => {
|
||||
gulp.task('sprites:checkCompiledDimensions', gulp.series('sprites:main', 'sprites:largeSprites', (done) => {
|
||||
console.log('Verifiying that images do not exceed max dimensions'); // eslint-disable-line no-console
|
||||
|
||||
let numberOfSheetsThatAreTooBig = 0;
|
||||
|
||||
const distSpritesheets = sync(`${IMG_DIST_PATH}*.png`);
|
||||
let distSpritesheets = sync(`${IMG_DIST_PATH}*.png`);
|
||||
|
||||
each(distSpritesheets, img => {
|
||||
const spriteSize = calculateImgDimensions(img);
|
||||
each(distSpritesheets, (img) => {
|
||||
let spriteSize = calculateImgDimensions(img);
|
||||
|
||||
if (spriteSize > MAX_SPRITESHEET_SIZE) {
|
||||
numberOfSheetsThatAreTooBig += 1;
|
||||
const name = basename(img, '.png');
|
||||
numberOfSheetsThatAreTooBig++;
|
||||
let name = basename(img, '.png');
|
||||
console.error(`WARNING: ${name} might be too big - ${spriteSize} > ${MAX_SPRITESHEET_SIZE}`); // eslint-disable-line no-console
|
||||
}
|
||||
});
|
||||
@@ -153,8 +155,7 @@ gulp.task('sprites:checkCompiledDimensions', gulp.series('sprites:main', 'sprite
|
||||
console.error( // eslint-disable-line no-console
|
||||
`${numberOfSheetsThatAreTooBig} sheets might too big for mobile Safari to be able to handle
|
||||
them, but there is a margin of error in these calculations so it is probably okay. Mention
|
||||
this to an admin so they can test a staging site on mobile Safari after your PR is merged.`,
|
||||
);
|
||||
this to an admin so they can test a staging site on mobile Safari after your PR is merged.`);
|
||||
} else {
|
||||
console.log('All images are within the correct dimensions'); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import gulp from 'gulp';
|
||||
import nodemon from 'gulp-nodemon';
|
||||
|
||||
import pkg from '../package.json';
|
||||
let pkg = require('../package.json');
|
||||
|
||||
gulp.task('nodemon', done => {
|
||||
gulp.task('nodemon', (done) => {
|
||||
nodemon({
|
||||
script: pkg.main,
|
||||
ignore: [
|
||||
'website/client-old/*',
|
||||
'website/views/*',
|
||||
'common/dist/script/content/*',
|
||||
],
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -1,59 +1,60 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { exec } from 'child_process';
|
||||
import gulp from 'gulp';
|
||||
import os from 'os';
|
||||
import nconf from 'nconf';
|
||||
import {
|
||||
pipe,
|
||||
} from './taskHelper';
|
||||
} from './taskHelper';
|
||||
import mongoose from 'mongoose';
|
||||
import { exec } from 'child_process';
|
||||
import gulp from 'gulp';
|
||||
import os from 'os';
|
||||
import nconf from 'nconf';
|
||||
|
||||
// TODO rewrite
|
||||
|
||||
const TEST_SERVER_PORT = 3003;
|
||||
const TEST_SERVER_PORT = 3003;
|
||||
let server;
|
||||
|
||||
const TEST_DB_URI = nconf.get('TEST_DB_URI');
|
||||
const TEST_DB_URI = nconf.get('TEST_DB_URI');
|
||||
|
||||
const SANITY_TEST_COMMAND = 'npm run test:sanity';
|
||||
const COMMON_TEST_COMMAND = 'npm run test:common';
|
||||
const CONTENT_TEST_COMMAND = 'npm run test:content';
|
||||
const CONTENT_OPTIONS = { maxBuffer: 1024 * 500 };
|
||||
const CONTENT_OPTIONS = {maxBuffer: 1024 * 500};
|
||||
|
||||
/* Helper methods for reporting test summary */
|
||||
const testResults = [];
|
||||
const testCount = (stdout, regexp) => {
|
||||
const match = stdout.match(regexp);
|
||||
return parseInt(match && (match[1] || 0), 10);
|
||||
let testResults = [];
|
||||
let testCount = (stdout, regexp) => {
|
||||
let match = stdout.match(regexp);
|
||||
return parseInt(match && match[1] || 0, 10);
|
||||
};
|
||||
|
||||
const testBin = (string, additionalEnvVariables = '') => {
|
||||
let testBin = (string, additionalEnvVariables = '') => {
|
||||
if (os.platform() === 'win32') {
|
||||
if (additionalEnvVariables !== '') {
|
||||
additionalEnvVariables = additionalEnvVariables.split(' ').join('&&set '); // eslint-disable-line no-param-reassign
|
||||
additionalEnvVariables = `set ${additionalEnvVariables}&&`; // eslint-disable-line no-param-reassign
|
||||
additionalEnvVariables = additionalEnvVariables.split(' ').join('&&set ');
|
||||
additionalEnvVariables = `set ${additionalEnvVariables}&&`;
|
||||
}
|
||||
return `set NODE_ENV=test&&${additionalEnvVariables}${string}`;
|
||||
} else {
|
||||
return `NODE_ENV=test ${additionalEnvVariables} ${string}`;
|
||||
}
|
||||
return `NODE_ENV=test ${additionalEnvVariables} ${string}`;
|
||||
};
|
||||
|
||||
gulp.task('test:nodemon', gulp.series(done => {
|
||||
gulp.task('test:nodemon', gulp.series(function setupNodemon (done) {
|
||||
process.env.PORT = TEST_SERVER_PORT; // eslint-disable-line no-process-env
|
||||
process.env.NODE_DB_URI = TEST_DB_URI; // eslint-disable-line no-process-env
|
||||
done();
|
||||
}, 'nodemon'));
|
||||
|
||||
gulp.task('test:prepare:mongo', cb => {
|
||||
mongoose.connect(TEST_DB_URI, err => {
|
||||
gulp.task('test:prepare:mongo', (cb) => {
|
||||
mongoose.connect(TEST_DB_URI, (err) => {
|
||||
if (err) return cb(`Unable to connect to mongo database. Are you sure it's running? \n\n${err}`);
|
||||
return mongoose.connection.dropDatabase(err2 => {
|
||||
mongoose.connection.dropDatabase((err2) => {
|
||||
if (err2) return cb(err2);
|
||||
return mongoose.connection.close(cb);
|
||||
mongoose.connection.close(cb);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('test:prepare:server', gulp.series('test:prepare:mongo', done => {
|
||||
gulp.task('test:prepare:server', gulp.series('test:prepare:mongo', (done) => {
|
||||
if (!server) {
|
||||
server = exec(testBin('node ./website/server/index.js', `NODE_DB_URI=${TEST_DB_URI} PORT=${TEST_SERVER_PORT}`), (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
@@ -72,43 +73,45 @@ gulp.task('test:prepare:build', gulp.series('build', done => done()));
|
||||
gulp.task('test:prepare', gulp.series(
|
||||
'test:prepare:build',
|
||||
'test:prepare:mongo',
|
||||
done => done(),
|
||||
done => done()
|
||||
));
|
||||
|
||||
gulp.task('test:sanity', cb => {
|
||||
const runner = exec(
|
||||
gulp.task('test:sanity', (cb) => {
|
||||
let runner = exec(
|
||||
testBin(SANITY_TEST_COMMAND),
|
||||
err => {
|
||||
(err) => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
cb();
|
||||
},
|
||||
}
|
||||
);
|
||||
pipe(runner);
|
||||
});
|
||||
|
||||
gulp.task('test:common', gulp.series('test:prepare:build', cb => {
|
||||
const runner = exec(
|
||||
gulp.task('test:common', gulp.series('test:prepare:build', (cb) => {
|
||||
let runner = exec(
|
||||
testBin(COMMON_TEST_COMMAND),
|
||||
err => {
|
||||
(err) => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
cb();
|
||||
},
|
||||
}
|
||||
);
|
||||
pipe(runner);
|
||||
}));
|
||||
|
||||
gulp.task('test:common:clean', cb => {
|
||||
gulp.task('test:common:clean', (cb) => {
|
||||
pipe(exec(testBin(COMMON_TEST_COMMAND), () => cb()));
|
||||
});
|
||||
|
||||
gulp.task('test:common:watch', gulp.series('test:common:clean', () => gulp.watch(['common/script/**/*', 'test/common/**/*'], gulp.series('test:common:clean', done => done()))));
|
||||
gulp.task('test:common:watch', gulp.series('test:common:clean', () => {
|
||||
return gulp.watch(['common/script/**/*', 'test/common/**/*'], gulp.series('test:common:clean', done => done()));
|
||||
}));
|
||||
|
||||
gulp.task('test:common:safe', gulp.series('test:prepare:build', cb => {
|
||||
const runner = exec(
|
||||
gulp.task('test:common:safe', gulp.series('test:prepare:build', (cb) => {
|
||||
let runner = exec(
|
||||
testBin(COMMON_TEST_COMMAND),
|
||||
(err, stdout) => { // eslint-disable-line handle-callback-err
|
||||
testResults.push({
|
||||
@@ -118,36 +121,38 @@ gulp.task('test:common:safe', gulp.series('test:prepare:build', cb => {
|
||||
pend: testCount(stdout, /(\d+) pending/),
|
||||
});
|
||||
cb();
|
||||
},
|
||||
}
|
||||
);
|
||||
pipe(runner);
|
||||
}));
|
||||
|
||||
gulp.task('test:content', gulp.series('test:prepare:build', cb => {
|
||||
const runner = exec(
|
||||
gulp.task('test:content', gulp.series('test:prepare:build', (cb) => {
|
||||
let runner = exec(
|
||||
testBin(CONTENT_TEST_COMMAND),
|
||||
CONTENT_OPTIONS,
|
||||
err => {
|
||||
(err) => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
cb();
|
||||
},
|
||||
}
|
||||
);
|
||||
pipe(runner);
|
||||
}));
|
||||
|
||||
gulp.task('test:content:clean', cb => {
|
||||
gulp.task('test:content:clean', (cb) => {
|
||||
pipe(exec(testBin(CONTENT_TEST_COMMAND), CONTENT_OPTIONS, () => cb()));
|
||||
});
|
||||
|
||||
gulp.task('test:content:watch', gulp.series('test:content:clean', () => gulp.watch(['common/script/content/**', 'test/**'], gulp.series('test:content:clean', done => done()))));
|
||||
gulp.task('test:content:watch', gulp.series('test:content:clean', () => {
|
||||
return gulp.watch(['common/script/content/**', 'test/**'], gulp.series('test:content:clean', done => done()));
|
||||
}));
|
||||
|
||||
gulp.task('test:content:safe', gulp.series('test:prepare:build', cb => {
|
||||
const runner = exec(
|
||||
gulp.task('test:content:safe', gulp.series('test:prepare:build', (cb) => {
|
||||
let runner = exec(
|
||||
testBin(CONTENT_TEST_COMMAND),
|
||||
CONTENT_OPTIONS,
|
||||
(err, stdout) => { // eslint-disable-line handle-callback-err
|
||||
(err, stdout) => { // eslint-disable-line handle-callback-err
|
||||
testResults.push({
|
||||
suite: 'Content Specs\t',
|
||||
pass: testCount(stdout, /(\d+) passing/),
|
||||
@@ -155,77 +160,56 @@ gulp.task('test:content:safe', gulp.series('test:prepare:build', cb => {
|
||||
pend: testCount(stdout, /(\d+) pending/),
|
||||
});
|
||||
cb();
|
||||
},
|
||||
}
|
||||
);
|
||||
pipe(runner);
|
||||
}));
|
||||
|
||||
gulp.task('test:api:unit', done => {
|
||||
const runner = exec(
|
||||
testBin('istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
|
||||
err => {
|
||||
gulp.task('test:api-v3:unit', (done) => {
|
||||
let runner = exec(
|
||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v3-unit --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/unit --recursive --require ./test/helpers/start-server'),
|
||||
(err) => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
done();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
});
|
||||
|
||||
gulp.task('test:api:unit:watch', () => gulp.watch(['website/server/libs/*', 'test/api/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit', done => done())));
|
||||
gulp.task('test:api-v3:unit:watch', () => {
|
||||
return gulp.watch(['website/server/libs/*', 'test/api/v3/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api-v3:unit', done => done()));
|
||||
});
|
||||
|
||||
gulp.task('test:api-v3:integration', done => {
|
||||
const runner = exec(
|
||||
testBin('istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
||||
{ maxBuffer: 500 * 1024 },
|
||||
err => {
|
||||
gulp.task('test:api-v3:integration', (done) => {
|
||||
let runner = exec(
|
||||
testBin('node_modules/.bin/istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
||||
{maxBuffer: 500 * 1024},
|
||||
(err) => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
done();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
});
|
||||
|
||||
gulp.task('test:api-v3:integration:watch', () => gulp.watch([
|
||||
'website/server/controllers/api-v3/**/*', 'common/script/ops/*', 'website/server/libs/*.js',
|
||||
'test/api/v3/integration/**/*',
|
||||
], gulp.series('test:api-v3:integration', done => done())));
|
||||
gulp.task('test:api-v3:integration:watch', () => {
|
||||
return gulp.watch([
|
||||
'website/server/controllers/api-v3/**/*', 'common/script/ops/*', 'website/server/libs/*.js',
|
||||
'test/api/v3/integration/**/*',
|
||||
], gulp.series('test:api-v3:integration', done => done()));
|
||||
});
|
||||
|
||||
gulp.task('test:api-v3:integration:separate-server', done => {
|
||||
const runner = exec(
|
||||
gulp.task('test:api-v3:integration:separate-server', (done) => {
|
||||
let runner = exec(
|
||||
testBin('mocha test/api/v3/integration --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
|
||||
{ maxBuffer: 500 * 1024 },
|
||||
err => done(err),
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
});
|
||||
|
||||
gulp.task('test:api-v4:integration', done => {
|
||||
const runner = exec(
|
||||
testBin('istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
|
||||
{ maxBuffer: 500 * 1024 },
|
||||
err => {
|
||||
if (err) {
|
||||
process.exit(1);
|
||||
}
|
||||
done();
|
||||
},
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
});
|
||||
|
||||
gulp.task('test:api-v4:integration:separate-server', done => {
|
||||
const runner = exec(
|
||||
testBin('mocha test/api/v4 --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
|
||||
{ maxBuffer: 500 * 1024 },
|
||||
err => done(err),
|
||||
{maxBuffer: 500 * 1024},
|
||||
(err) => done(err)
|
||||
);
|
||||
|
||||
pipe(runner);
|
||||
@@ -235,14 +219,13 @@ gulp.task('test', gulp.series(
|
||||
'test:sanity',
|
||||
'test:content',
|
||||
'test:common',
|
||||
'test:api:unit',
|
||||
'test:api-v3:unit',
|
||||
'test:api-v3:integration',
|
||||
'test:api-v4:integration',
|
||||
done => done(),
|
||||
done => done()
|
||||
));
|
||||
|
||||
gulp.task('test:api-v3', gulp.series(
|
||||
'test:api:unit',
|
||||
'test:api-v3:unit',
|
||||
'test:api-v3:integration',
|
||||
done => done(),
|
||||
done => done()
|
||||
));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import _ from 'lodash';
|
||||
import gulp from 'gulp';
|
||||
import fs from 'fs';
|
||||
import _ from 'lodash';
|
||||
import gulp from 'gulp';
|
||||
import { postToSlack, conf } from './taskHelper';
|
||||
|
||||
const SLACK_CONFIG = {
|
||||
@@ -14,7 +14,7 @@ const ENGLISH_LOCALE = `${LOCALES}en/`;
|
||||
|
||||
|
||||
function getArrayOfLanguages () {
|
||||
const languages = fs.readdirSync(LOCALES);
|
||||
let languages = fs.readdirSync(LOCALES);
|
||||
languages.shift(); // Remove README.md from array of languages
|
||||
|
||||
return languages;
|
||||
@@ -23,16 +23,18 @@ function getArrayOfLanguages () {
|
||||
const ALL_LANGUAGES = getArrayOfLanguages();
|
||||
|
||||
function stripOutNonJsonFiles (collection) {
|
||||
const onlyJson = _.filter(collection, file => file.match(/[a-zA-Z]*\.json/));
|
||||
let onlyJson = _.filter(collection, (file) => {
|
||||
return file.match(/[a-zA-Z]*\.json/);
|
||||
});
|
||||
|
||||
return onlyJson;
|
||||
}
|
||||
|
||||
function eachTranslationFile (languages, cb) {
|
||||
const jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
||||
let jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
||||
|
||||
_.each(languages, lang => {
|
||||
_.each(jsonFiles, filename => {
|
||||
_.each(languages, (lang) => {
|
||||
_.each(jsonFiles, (filename) => {
|
||||
let parsedTranslationFile;
|
||||
try {
|
||||
const translationFile = fs.readFileSync(`${LOCALES}${lang}/${filename}`);
|
||||
@@ -41,10 +43,10 @@ function eachTranslationFile (languages, cb) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
const englishFile = fs.readFileSync(ENGLISH_LOCALE + filename);
|
||||
const parsedEnglishFile = JSON.parse(englishFile);
|
||||
let englishFile = fs.readFileSync(ENGLISH_LOCALE + filename);
|
||||
let parsedEnglishFile = JSON.parse(englishFile);
|
||||
|
||||
return cb(null, lang, filename, parsedEnglishFile, parsedTranslationFile);
|
||||
cb(null, lang, filename, parsedEnglishFile, parsedTranslationFile);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -69,9 +71,9 @@ function formatMessageForPosting (msg, items) {
|
||||
}
|
||||
|
||||
function getStringsWith (json, interpolationRegex) {
|
||||
const strings = {};
|
||||
let strings = {};
|
||||
|
||||
_.each(json, fileName => {
|
||||
_.each(json, (fileName) => {
|
||||
const rawFile = fs.readFileSync(ENGLISH_LOCALE + fileName);
|
||||
const parsedJson = JSON.parse(rawFile);
|
||||
|
||||
@@ -91,69 +93,66 @@ const malformedStringExceptions = {
|
||||
feedPet: true,
|
||||
};
|
||||
|
||||
gulp.task('transifex:missingFiles', done => {
|
||||
const missingStrings = [];
|
||||
gulp.task('transifex:missingFiles', (done) => {
|
||||
let missingStrings = [];
|
||||
|
||||
eachTranslationFile(ALL_LANGUAGES, error => {
|
||||
eachTranslationFile(ALL_LANGUAGES, (error) => {
|
||||
if (error) {
|
||||
missingStrings.push(error.path);
|
||||
}
|
||||
});
|
||||
|
||||
if (!_.isEmpty(missingStrings)) {
|
||||
const message = 'the following files were missing from the translations folder';
|
||||
const formattedMessage = formatMessageForPosting(message, missingStrings);
|
||||
let message = 'the following files were missing from the translations folder';
|
||||
let formattedMessage = formatMessageForPosting(message, missingStrings);
|
||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
gulp.task('transifex:missingStrings', done => {
|
||||
const missingStrings = [];
|
||||
gulp.task('transifex:missingStrings', (done) => {
|
||||
let missingStrings = [];
|
||||
|
||||
eachTranslationString(ALL_LANGUAGES, (lang, filename, key, englishString, translationString) => {
|
||||
eachTranslationString(ALL_LANGUAGES, (language, filename, key, englishString, translationString) => {
|
||||
if (!translationString) {
|
||||
const errorString = `${lang} - ${filename} - ${key} - ${englishString}`;
|
||||
let errorString = `${language} - ${filename} - ${key} - ${englishString}`;
|
||||
missingStrings.push(errorString);
|
||||
}
|
||||
});
|
||||
|
||||
if (!_.isEmpty(missingStrings)) {
|
||||
const message = 'The following strings are not translated';
|
||||
const formattedMessage = formatMessageForPosting(message, missingStrings);
|
||||
let message = 'The following strings are not translated';
|
||||
let formattedMessage = formatMessageForPosting(message, missingStrings);
|
||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
gulp.task('transifex:malformedStrings', done => {
|
||||
const jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
||||
const interpolationRegex = /<%= [a-zA-Z]* %>/g;
|
||||
const stringsToLookFor = getStringsWith(jsonFiles, interpolationRegex);
|
||||
gulp.task('transifex:malformedStrings', (done) => {
|
||||
let jsonFiles = stripOutNonJsonFiles(fs.readdirSync(ENGLISH_LOCALE));
|
||||
let interpolationRegex = /<%= [a-zA-Z]* %>/g;
|
||||
let stringsToLookFor = getStringsWith(jsonFiles, interpolationRegex);
|
||||
|
||||
const stringsWithMalformedInterpolations = [];
|
||||
const stringsWithIncorrectNumberOfInterpolations = [];
|
||||
let stringsWithMalformedInterpolations = [];
|
||||
let stringsWithIncorrectNumberOfInterpolations = [];
|
||||
|
||||
_.each(ALL_LANGUAGES, lang => {
|
||||
_.each(ALL_LANGUAGES, (lang) => {
|
||||
_.each(stringsToLookFor, (strings, filename) => {
|
||||
const translationFile = fs.readFileSync(`${LOCALES}${lang}/${filename}`);
|
||||
const parsedTranslationFile = JSON.parse(translationFile);
|
||||
let translationFile = fs.readFileSync(`${LOCALES}${lang}/${filename}`);
|
||||
let parsedTranslationFile = JSON.parse(translationFile);
|
||||
|
||||
_.each(strings, (value, key) => { // eslint-disable-line max-nested-callbacks
|
||||
const translationString = parsedTranslationFile[key];
|
||||
let translationString = parsedTranslationFile[key];
|
||||
if (!translationString) return;
|
||||
|
||||
const englishOccurences = stringsToLookFor[filename][key];
|
||||
const translationOccurences = translationString.match(interpolationRegex);
|
||||
let englishOccurences = stringsToLookFor[filename][key];
|
||||
let translationOccurences = translationString.match(interpolationRegex);
|
||||
|
||||
if (!translationOccurences) {
|
||||
const malformedString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
||||
let malformedString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
||||
stringsWithMalformedInterpolations.push(malformedString);
|
||||
} else if (
|
||||
englishOccurences.length !== translationOccurences.length
|
||||
&& !malformedStringExceptions[key]
|
||||
) {
|
||||
const missingInterpolationString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
||||
} else if (englishOccurences.length !== translationOccurences.length && !malformedStringExceptions[key]) {
|
||||
let missingInterpolationString = `${lang} - ${filename} - ${key} - ${translationString}`;
|
||||
stringsWithIncorrectNumberOfInterpolations.push(missingInterpolationString);
|
||||
}
|
||||
});
|
||||
@@ -161,17 +160,14 @@ gulp.task('transifex:malformedStrings', done => {
|
||||
});
|
||||
|
||||
if (!_.isEmpty(stringsWithMalformedInterpolations)) {
|
||||
const message = 'The following strings have malformed or missing interpolations';
|
||||
const formattedMessage = formatMessageForPosting(message, stringsWithMalformedInterpolations);
|
||||
let message = 'The following strings have malformed or missing interpolations';
|
||||
let formattedMessage = formatMessageForPosting(message, stringsWithMalformedInterpolations);
|
||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||
}
|
||||
|
||||
if (!_.isEmpty(stringsWithIncorrectNumberOfInterpolations)) {
|
||||
const message = 'The following strings have a different number of string interpolations';
|
||||
const formattedMessage = formatMessageForPosting(
|
||||
message,
|
||||
stringsWithIncorrectNumberOfInterpolations,
|
||||
);
|
||||
let message = 'The following strings have a different number of string interpolations';
|
||||
let formattedMessage = formatMessageForPosting(message, stringsWithIncorrectNumberOfInterpolations);
|
||||
postToSlack(formattedMessage, SLACK_CONFIG);
|
||||
}
|
||||
done();
|
||||
@@ -180,5 +176,5 @@ gulp.task('transifex:malformedStrings', done => {
|
||||
gulp.task(
|
||||
'transifex',
|
||||
gulp.series('transifex:missingFiles', 'transifex:missingStrings', 'transifex:malformedStrings'),
|
||||
done => done(),
|
||||
);
|
||||
(done) => done()
|
||||
);
|
||||
@@ -1,11 +1,11 @@
|
||||
import { exec } from 'child_process';
|
||||
import psTree from 'ps-tree';
|
||||
import nconf from 'nconf';
|
||||
import net from 'net';
|
||||
import { post } from 'superagent';
|
||||
import { sync as glob } from 'glob';
|
||||
import Mocha from 'mocha'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
import { resolve } from 'path';
|
||||
import { exec } from 'child_process';
|
||||
import psTree from 'ps-tree';
|
||||
import nconf from 'nconf';
|
||||
import net from 'net';
|
||||
import { post } from 'superagent';
|
||||
import { sync as glob } from 'glob';
|
||||
import Mocha from 'mocha';
|
||||
import { resolve } from 'path';
|
||||
|
||||
/*
|
||||
* Get access to configruable values
|
||||
@@ -19,15 +19,15 @@ export const conf = nconf;
|
||||
* its tasks.
|
||||
*/
|
||||
export function kill (proc) {
|
||||
const killProcess = pid => {
|
||||
let killProcess = (pid) => {
|
||||
psTree(pid, (_, pids) => {
|
||||
if (pids.length) {
|
||||
pids.forEach(kill); return;
|
||||
}
|
||||
try {
|
||||
exec(/^win/.test(process.platform)
|
||||
? `taskkill /PID ${pid} /T /F`
|
||||
: `kill -9 ${pid}`);
|
||||
exec(/^win/.test(process.platform) ?
|
||||
`taskkill /PID ${pid} /T /F` :
|
||||
`kill -9 ${pid}`);
|
||||
} catch (e) {
|
||||
console.log(e); // eslint-disable-line no-console
|
||||
}
|
||||
@@ -46,15 +46,16 @@ export function kill (proc) {
|
||||
export function awaitPort (port, max = 60) {
|
||||
return new Promise((rej, res) => {
|
||||
let socket;
|
||||
let timeout;
|
||||
let interval;
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
timeout = setTimeout(() => {
|
||||
clearInterval(interval);
|
||||
rej(`Timed out after ${max} seconds`);
|
||||
}, max * 1000);
|
||||
|
||||
interval = setInterval(() => {
|
||||
socket = net.connect({ port }, () => {
|
||||
socket = net.connect({port}, () => {
|
||||
clearInterval(interval);
|
||||
clearTimeout(timeout);
|
||||
socket.destroy();
|
||||
@@ -70,10 +71,10 @@ export function awaitPort (port, max = 60) {
|
||||
* Pipe the child's stdin and stderr to the parent process.
|
||||
*/
|
||||
export function pipe (child) {
|
||||
child.stdout.on('data', data => {
|
||||
child.stdout.on('data', (data) => {
|
||||
process.stdout.write(data);
|
||||
});
|
||||
child.stderr.on('data', data => {
|
||||
child.stderr.on('data', (data) => {
|
||||
process.stderr.write(data);
|
||||
});
|
||||
}
|
||||
@@ -82,7 +83,7 @@ export function pipe (child) {
|
||||
* Post request to notify configured slack channel
|
||||
*/
|
||||
export function postToSlack (msg, config = {}) {
|
||||
const slackUrl = nconf.get('SLACK_URL');
|
||||
let slackUrl = nconf.get('SLACK_URL');
|
||||
|
||||
if (!slackUrl) {
|
||||
console.error('No slack post url specified. Your message was:'); // eslint-disable-line no-console
|
||||
@@ -98,7 +99,7 @@ export function postToSlack (msg, config = {}) {
|
||||
text: msg,
|
||||
icon_emoji: `:${config.emoji || 'gulp'}:`, // eslint-disable-line camelcase
|
||||
})
|
||||
.end(err => {
|
||||
.end((err) => {
|
||||
if (err) console.error('Unable to post to slack', err); // eslint-disable-line no-console
|
||||
});
|
||||
}
|
||||
@@ -106,15 +107,15 @@ export function postToSlack (msg, config = {}) {
|
||||
export function runMochaTests (files, server, cb) {
|
||||
require('../test/helpers/globals.helper'); // eslint-disable-line global-require
|
||||
|
||||
const mocha = new Mocha({ reporter: 'spec' });
|
||||
const tests = glob(files);
|
||||
let mocha = new Mocha({reporter: 'spec'});
|
||||
let tests = glob(files);
|
||||
|
||||
tests.forEach(test => {
|
||||
tests.forEach((test) => {
|
||||
delete require.cache[resolve(test)];
|
||||
mocha.addFile(test);
|
||||
});
|
||||
|
||||
mocha.run(numberOfFailures => {
|
||||
mocha.run((numberOfFailures) => {
|
||||
if (!process.env.RUN_INTEGRATION_TEST_FOREVER) { // eslint-disable-line no-process-env
|
||||
if (server) kill(server);
|
||||
process.exit(numberOfFailures);
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
* directory, and it will automatically be included.
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-commonjs */
|
||||
require('@babel/register');
|
||||
require('babel-register');
|
||||
|
||||
const gulp = require('gulp');
|
||||
|
||||
|
||||
7
migrations/.eslintrc
Normal file
7
migrations/.eslintrc
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"root": false,
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"no-use-before-define": ["error", { "functions": false }]
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
module.exports = {
|
||||
root: false,
|
||||
rules: {
|
||||
'no-console': 0,
|
||||
'no-use-before-define': ['error', { functions: false }]
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ const Timer = require('./utils/timer');
|
||||
const connectToDb = require('./utils/connect').connectToDb;
|
||||
const closeDb = require('./utils/connect').closeDb;
|
||||
|
||||
const message = '`This party\'s collection quest has been made easier! For details, refer to http://habitica.fandom.com/wiki/User_blog:LadyAlys/Collection_Quests_are_Now_Easier`';
|
||||
const message = '`This party\'s collection quest has been made easier! For details, refer to http://habitica.wikia.com/wiki/User_blog:LadyAlys/Collection_Quests_are_Now_Easier`';
|
||||
|
||||
const timer = new Timer();
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
let migrationName = '20180724_summer-splash-orcas.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 ladder items to participants in this year's Summer Splash festivities
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
let dbUsers = monk(CONNECTION_STRING).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('2018-07-01')}, // rerun without date restriction after initial run
|
||||
};
|
||||
|
||||
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((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(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = {};
|
||||
|
||||
if (user && user.items && user.items.pets && typeof user.items.pets['Orca-Base'] !== 'undefined') {
|
||||
set = {migration: migrationName};
|
||||
} else if (user && user.items && user.items.mounts && typeof user.items.mounts['Orca-Base'] !== 'undefined') {
|
||||
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;
|
||||
@@ -1,123 +0,0 @@
|
||||
let migrationName = '20180731_naming-day.js'; // Update when running in future years
|
||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Award Naming Day ladder items to participants in this month's Naming Day festivities
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING'); // FOR TEST DATABASE
|
||||
let dbUsers = monk(CONNECTION_STRING).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.gear.owned',
|
||||
'items.mounts',
|
||||
'items.pets',
|
||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch((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(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = {};
|
||||
let push;
|
||||
|
||||
const inc = {
|
||||
'items.food.Cake_Base': 1,
|
||||
'items.food.Cake_CottonCandyBlue': 1,
|
||||
'items.food.Cake_CottonCandyPink': 1,
|
||||
'items.food.Cake_Desert': 1,
|
||||
'items.food.Cake_Golden': 1,
|
||||
'items.food.Cake_Red': 1,
|
||||
'items.food.Cake_Shade': 1,
|
||||
'items.food.Cake_Skeleton': 1,
|
||||
'items.food.Cake_White': 1,
|
||||
'items.food.Cake_Zombie': 1,
|
||||
'achievements.habiticaDays': 1,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.gear && user.items.gear.owned && typeof user.items.gear.owned.head_special_namingDay2017 !== 'undefined') {
|
||||
set = {migration: migrationName, 'items.gear.owned.body_special_namingDay2018': false};
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.body_special_namingDay2018', _id: monk.id()}};
|
||||
} else if (user && user.items && user.items.pets && typeof user.items.pets['Gryphon-RoyalPurple'] !== 'undefined') {
|
||||
set = {migration: migrationName, 'items.gear.owned.head_special_namingDay2017': false};
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.head_special_namingDay2017', _id: monk.id()}};
|
||||
} else if (user && user.items && user.items.mounts && typeof user.items.mounts['Gryphon-RoyalPurple'] !== 'undefined') {
|
||||
set = {migration: migrationName, 'items.pets.Gryphon-RoyalPurple': 5};
|
||||
} else {
|
||||
set = {migration: migrationName, 'items.mounts.Gryphon-RoyalPurple': true};
|
||||
}
|
||||
|
||||
if (push) {
|
||||
dbUsers.update({_id: user._id}, {$set: set, $push: push, $inc: inc});
|
||||
} else {
|
||||
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;
|
||||
@@ -1,147 +0,0 @@
|
||||
const migrationName = '20180811_inboxOutsideUser.js';
|
||||
const authorName = 'paglias'; // in case script author needs to know when their ...
|
||||
const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Move inbox messages from the user model to their own collection
|
||||
*/
|
||||
|
||||
const monk = require('monk');
|
||||
const nconf = require('nconf');
|
||||
const uuid = require('uuid').v4;
|
||||
|
||||
const Inbox = require('../website/server/models/message').inboxModel;
|
||||
const connectionString = nconf.get('MIGRATION_CONNECT_STRING'); // FOR TEST DATABASE
|
||||
const dbInboxes = monk(connectionString).get('inboxes', { castIds: false });
|
||||
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
let query = {
|
||||
migration: {$ne: migrationName},
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: {_id: 1},
|
||||
limit: 1000,
|
||||
fields: ['_id', 'inbox'],
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
let msgCount = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users and their tasks found and modified.');
|
||||
displayData();
|
||||
return;
|
||||
}
|
||||
|
||||
let usersPromises = users.map(updateUser);
|
||||
let lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(usersPromises)
|
||||
.then(() => {
|
||||
return processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count } ${ user._id}`);
|
||||
if (msgCount % progressCount === 0) console.warn(`${msgCount } messages processed`);
|
||||
if (user._id === authorUuid) console.warn(`${authorName } being processed`);
|
||||
|
||||
const oldInboxMessages = user.inbox.messages || {};
|
||||
const oldInboxMessagesIds = Object.keys(oldInboxMessages);
|
||||
|
||||
msgCount += oldInboxMessagesIds.length;
|
||||
|
||||
const newInboxMessages = oldInboxMessagesIds.map(msgId => {
|
||||
const msg = oldInboxMessages[msgId];
|
||||
if (!msg || (!msg.id && !msg._id)) { // eslint-disable-line no-extra-parens
|
||||
console.log('missing message or message _id and id', msg);
|
||||
throw new Error('error!');
|
||||
}
|
||||
|
||||
if (msg.id && !msg._id) msg._id = msg.id;
|
||||
if (msg._id && !msg.id) msg.id = msg._id;
|
||||
|
||||
const newMsg = new Inbox(msg);
|
||||
newMsg.ownerId = user._id;
|
||||
return newMsg.toJSON();
|
||||
});
|
||||
|
||||
const promises = newInboxMessages.map(newMsg => {
|
||||
return (async function fn () {
|
||||
const existing = await dbInboxes.find({_id: newMsg._id});
|
||||
|
||||
if (existing.length > 0) {
|
||||
if (
|
||||
existing[0].ownerId === newMsg.ownerId &&
|
||||
existing[0].text === newMsg.text &&
|
||||
existing[0].uuid === newMsg.uuid &&
|
||||
existing[0].sent === newMsg.sent
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
newMsg.id = newMsg._id = uuid();
|
||||
}
|
||||
|
||||
return newMsg;
|
||||
})();
|
||||
});
|
||||
|
||||
return Promise.all(promises)
|
||||
.then((filteredNewMsg) => {
|
||||
filteredNewMsg = filteredNewMsg.filter(m => Boolean(m && m.id && m._id && m.id == m._id));
|
||||
return dbInboxes.insert(filteredNewMsg);
|
||||
}).then(() => {
|
||||
return dbUsers.update({_id: user._id}, {
|
||||
$set: {
|
||||
migration: migrationName,
|
||||
'inbox.messages': {},
|
||||
},
|
||||
});
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
function displayData () {
|
||||
console.warn(`\n${ count } users processed\n`);
|
||||
console.warn(`\n${ msgCount } messages 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;
|
||||
@@ -1,99 +0,0 @@
|
||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Generate usernames for users who lack them
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
import { generateUsername } from '../../website/server/libs/auth/utils';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING'); // FOR TEST DATABASE
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
'auth.local.username': {$exists: false},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2018-04-01')}, // Initial coverage for users active within last 6 months
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
fields: [
|
||||
'auth',
|
||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch((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(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
if (!user.auth.local.username) {
|
||||
const newName = generateUsername();
|
||||
dbUsers.update(
|
||||
{_id: user._id},
|
||||
{$set:
|
||||
{
|
||||
'auth.local.username': newName,
|
||||
'auth.local.lowerCaseUsername': newName,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
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;
|
||||
@@ -1,107 +0,0 @@
|
||||
const MIGRATION_NAME = '20181003_username_email.js';
|
||||
let authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Send emails to eligible users announcing upcoming username changes
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
import { sendTxn } from '../../website/server/libs/email';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2018-04-01')},
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: {_id: 1},
|
||||
limit: 100,
|
||||
fields: [
|
||||
'_id',
|
||||
'auth',
|
||||
'preferences',
|
||||
'profile',
|
||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch((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(() => delay(7000))
|
||||
.then(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
dbUsers.update({_id: user._id}, {$set: {migration: MIGRATION_NAME}});
|
||||
|
||||
sendTxn(
|
||||
user,
|
||||
'username-change',
|
||||
[{name: 'UNSUB_EMAIL_TYPE_URL', content: '/user/settings/notifications?unsubFrom=importantAnnouncements'},
|
||||
{name: 'LOGIN_NAME', content: user.auth.local.username}]
|
||||
);
|
||||
|
||||
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 delay (t, v) {
|
||||
return new Promise(function batchPause (resolve) {
|
||||
setTimeout(resolve.bind(null, v), t);
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1,66 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20181023_veteran_pet_ladder';
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (user.items.pets['Bear-Veteran']) {
|
||||
set['items.pets.Fox-Veteran'] = 5;
|
||||
} else if (user.items.pets['Lion-Veteran']) {
|
||||
set['items.pets.Bear-Veteran'] = 5;
|
||||
} else if (user.items.pets['Tiger-Veteran']) {
|
||||
set['items.pets.Lion-Veteran'] = 5;
|
||||
} else if (user.items.pets['Wolf-Veteran']) {
|
||||
set['items.pets.Tiger-Veteran'] = 5;
|
||||
} else {
|
||||
set['items.pets.Wolf-Veteran'] = 5;
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'flags.verifiedUsername': true,
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
migration: 1,
|
||||
flags: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Award Habitoween ladder items to participants in this month's Habitoween festivities
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const MIGRATION_NAME = '20181030_habitoween_ladder.js'; // Update when running in future years
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
const AUTHOR_NAME = 'Sabe'; // in case script author needs to know when their ...
|
||||
const AUTHOR_UUID = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2018-10-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((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const PROGRESS_COUNT = 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(() => {
|
||||
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.mounts['JackOLantern-Ghost']) {
|
||||
set['items.pets.JackOLantern-Glow'] = 5;
|
||||
} else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Ghost']) {
|
||||
set['items.mounts.JackOLantern-Ghost'] = true;
|
||||
} else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Base']) {
|
||||
set['items.pets.JackOLantern-Ghost'] = 5;
|
||||
} else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Base']) {
|
||||
set['items.mounts.JackOLantern-Base'] = true;
|
||||
} else {
|
||||
set['items.pets.JackOLantern-Base'] = 5;
|
||||
}
|
||||
|
||||
dbUsers.update({_id: user._id}, {$set: set, $inc: inc});
|
||||
|
||||
if (count % PROGRESS_COUNT === 0) console.warn(`${count} ${user._id}`);
|
||||
if (user._id === AUTHOR_UUID) console.warn(`${AUTHOR_NAME} 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;
|
||||
@@ -1,109 +0,0 @@
|
||||
const MIGRATION_NAME = '20181108_username_email.js';
|
||||
const AUTHOR_NAME = 'Sabe'; // in case script author needs to know when their ...
|
||||
const AUTHOR_UUID = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Send emails to eligible users announcing upcoming username changes
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
import { sendTxn } from '../../../website/server/libs/email';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
const BASE_URL = nconf.get('BASE_URL');
|
||||
let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'flags.verifiedUsername': {$ne: true},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2018-10-25')},
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: {_id: 1},
|
||||
limit: 100,
|
||||
fields: [
|
||||
'_id',
|
||||
'auth',
|
||||
'preferences',
|
||||
'profile',
|
||||
], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch((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(() => delay(7000))
|
||||
.then(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
dbUsers.update({_id: user._id}, {$set: {migration: MIGRATION_NAME}});
|
||||
|
||||
sendTxn(
|
||||
user,
|
||||
'username-change-follow-up',
|
||||
[{name: 'LOGIN_NAME', content: user.auth.local.username},
|
||||
{name: 'BASE_URL', content: BASE_URL}]
|
||||
);
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
if (user._id === AUTHOR_UUID) console.warn(`${AUTHOR_NAME} processed`);
|
||||
}
|
||||
|
||||
function displayData () {
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function delay (t, v) {
|
||||
return new Promise(function batchPause (resolve) {
|
||||
setTimeout(resolve.bind(null, v), t);
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1,109 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20181122_turkey_day';
|
||||
import mongoose from 'mongoose';
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.armor_special_turkeyArmorBase !== 'undefined') {
|
||||
set['items.gear.owned.head_special_turkeyHelmGilded'] = false;
|
||||
set['items.gear.owned.armor_special_turkeyArmorGilded'] = false;
|
||||
set['items.gear.owned.back_special_turkeyTailGilded'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_turkeyHelmGilded',
|
||||
_id: new mongoose.Types.ObjectId(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.armor_special_turkeyArmorGilded',
|
||||
_id: new mongoose.Types.ObjectId(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.back_special_turkeyTailGilded',
|
||||
_id: new mongoose.Types.ObjectId(),
|
||||
},
|
||||
];
|
||||
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Gilded']) {
|
||||
set['items.gear.owned.head_special_turkeyHelmBase'] = false;
|
||||
set['items.gear.owned.armor_special_turkeyArmorBase'] = false;
|
||||
set['items.gear.owned.back_special_turkeyTailBase'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_turkeyHelmBase',
|
||||
_id: new mongoose.Types.ObjectId(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.armor_special_turkeyArmorBase',
|
||||
_id: new mongoose.Types.ObjectId(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.back_special_turkeyTailBase',
|
||||
_id: new mongoose.Types.ObjectId(),
|
||||
},
|
||||
];
|
||||
} else if (user.items && user.items.pets && user.items.pets['Turkey-Gilded']) {
|
||||
set['items.mounts.Turkey-Gilded'] = true;
|
||||
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Base']) {
|
||||
set['items.pets.Turkey-Gilded'] = 5;
|
||||
} else if (user.items && user.items.pets && user.items.pets['Turkey-Base']) {
|
||||
set['items.mounts.Turkey-Base'] = true;
|
||||
} else {
|
||||
set['items.pets.Turkey-Base'] = 5;
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
if (push) {
|
||||
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||
} else {
|
||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,110 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20181231_nye';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
import mongoose from 'mongoose';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {'flags.newStuff': true};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.head_special_nye2017 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2018'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2018',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2016 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2017'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2017',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2016'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2016',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2015'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2015',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2014'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2014',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else {
|
||||
set['items.gear.owned.head_special_nye'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,88 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190131_habit_birthday';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const 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,
|
||||
};
|
||||
const set = {};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.armor_special_birthday2018 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2019'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2019', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday2017 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2018'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2018', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday2016 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2017'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2017', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday2015 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2016'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2016', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2015'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2015', _id: uuid()}};
|
||||
} else {
|
||||
set['items.gear.owned.armor_special_birthday'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday', _id: uuid()}};
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$inc: inc, $set: set, $push: push}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-01-15')},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,62 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190530_halfmoon_glasses';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {
|
||||
'items.gear.owned.eyewear_special_blackHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_blueHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_greenHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_pinkHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_redHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_whiteHalfMoon': true,
|
||||
'items.gear.owned.eyewear_special_yellowHalfMoon': true,
|
||||
};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-05-01')},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190618_summer_splash_orcas';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set;
|
||||
|
||||
if (user && user.items && user.items.pets && typeof user.items.pets['Orca-Base'] !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME };
|
||||
} else if (user && user.items && user.items.mounts && typeof user.items.mounts['Orca-Base'] !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME, 'items.pets.Orca-Base': 5 };
|
||||
} else {
|
||||
set = { migration: MIGRATION_NAME, 'items.mounts.Orca-Base': true };
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-05-18')},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,84 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190716_groups_fix';
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
let backupUsers;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = { migration: MIGRATION_NAME };
|
||||
let addToSet;
|
||||
|
||||
const monkPromise = new Promise((resolve, reject) => {
|
||||
backupUsers.findOne(
|
||||
{ _id: user._id },
|
||||
{ fields: { _id: 1, party: 1, guilds: 1 }},
|
||||
).then(foundUserInBackup => {
|
||||
resolve(foundUserInBackup);
|
||||
}).catch(e => {
|
||||
reject(e);
|
||||
})
|
||||
});
|
||||
let backupUser = await monkPromise;
|
||||
if (!backupUser) return;
|
||||
|
||||
if (!user.party._id) {
|
||||
set.party = backupUser.party;
|
||||
}
|
||||
addToSet = { guilds: { $each: backupUser.guilds }};
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return User.update({ _id: user._id }, { $set: set, $addToSet: addToSet }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
const query = {
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-07-15')},
|
||||
};
|
||||
|
||||
let backupDb = monk(CONNECTION_STRING);
|
||||
const backupDbPromise = new Promise((resolve, reject) => {
|
||||
backupDb.then(() => resolve()).catch((e) => reject(e));
|
||||
});
|
||||
|
||||
await backupDbPromise;
|
||||
console.log('Connected to backup db');
|
||||
backupUsers = backupDb.get('users', { castIds: false });
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
party: 1,
|
||||
guilds: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,88 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190717_groups_fix_2';
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
import { sendTxn as sendTxnEmail } from '../../../website/server/libs/email';
|
||||
import shared from '../../../website/common';
|
||||
|
||||
const questScrolls = shared.content.quests;
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateGroup (group) {
|
||||
count++;
|
||||
|
||||
if (group && group.quest && group.quest.key && group.quest.leader) {
|
||||
const quest = questScrolls[group.quest.key];
|
||||
const leader = await User.findOne({_id: group.quest.leader}).exec();
|
||||
|
||||
if (leader && quest) {
|
||||
await User.update({
|
||||
_id: leader._id,
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
}, {
|
||||
$set: {migration: MIGRATION_NAME},
|
||||
$inc: {
|
||||
balance: 1,
|
||||
[`items.quests.${group.quest.key}`]: 1,
|
||||
},
|
||||
}).exec();
|
||||
|
||||
// unsubscribe from all is already checked by sendTxnEmail
|
||||
if (leader.preferences && leader.preferences.emailNotifications && leader.preferences.emailNotifications.majorUpdates !== false) {
|
||||
sendTxnEmail(leader, 'groups-outage');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${group._id}`);
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
const query = {
|
||||
type: 'party'
|
||||
};
|
||||
|
||||
let backupDb = monk(CONNECTION_STRING);
|
||||
const backupDbPromise = new Promise((resolve, reject) => {
|
||||
backupDb.then(() => resolve()).catch((e) => reject(e));
|
||||
});
|
||||
|
||||
await backupDbPromise;
|
||||
console.log('Connected to backup db');
|
||||
const backupGroups = backupDb.get('groups', { castIds: false });
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const groupsPromise = new Promise((resolve, reject) => {
|
||||
backupGroups
|
||||
.find(query, {
|
||||
limit: 250,
|
||||
sort: {_id: 1}
|
||||
})
|
||||
.then(foundGroupInBackup => {
|
||||
resolve(foundGroupInBackup);
|
||||
}).catch(e => {
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
|
||||
const groups = await groupsPromise;
|
||||
|
||||
if (groups.length === 0) {
|
||||
console.warn('All appropriate groups found and modified.');
|
||||
console.warn(`\n${count} groups processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: groups[groups.length - 1]._id,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(groups.map(updateGroup)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,84 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190731_naming_day';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set;
|
||||
let push;
|
||||
const inc = {
|
||||
'items.food.Cake_Base': 1,
|
||||
'items.food.Cake_CottonCandyBlue': 1,
|
||||
'items.food.Cake_CottonCandyPink': 1,
|
||||
'items.food.Cake_Desert': 1,
|
||||
'items.food.Cake_Golden': 1,
|
||||
'items.food.Cake_Red': 1,
|
||||
'items.food.Cake_Shade': 1,
|
||||
'items.food.Cake_Skeleton': 1,
|
||||
'items.food.Cake_White': 1,
|
||||
'items.food.Cake_Zombie': 1,
|
||||
'achievements.habiticaDays': 1,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.gear && user.items.gear.owned && typeof user.items.gear.owned.body_special_namingDay2018 !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME };
|
||||
} else if (user && user.items && user.items.gear && user.items.gear.owned && typeof user.items.gear.owned.head_special_namingDay2017 !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME, 'items.gear.owned.body_special_namingDay2018': false };
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.body_special_namingDay2018', _id: uuid() }};
|
||||
} else if (user && user.items && user.items.pets && typeof user.items.pets['Gryphon-RoyalPurple'] !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME, 'items.gear.owned.head_special_namingDay2017': false };
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.head_special_namingDay2017', _id: uuid() }};
|
||||
} else if (user && user.items && user.items.mounts && typeof user.items.mounts['Gryphon-RoyalPurple'] !== 'undefined') {
|
||||
set = { migration: MIGRATION_NAME, 'items.pets.Gryphon-RoyalPurple': 5 };
|
||||
} else {
|
||||
set = { migration: MIGRATION_NAME, 'items.mounts.Gryphon-RoyalPurple': true };
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
if (push) {
|
||||
return await User.update({ _id: user._id }, { $set: set, $inc: inc, $push: push }).exec();
|
||||
} else {
|
||||
return await User.update({ _id: user._id }, { $set: set, $inc: inc }).exec();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2019-07-01') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1]._id,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,104 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190917_pet_color_achievements';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = {
|
||||
migration: MIGRATION_NAME,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.pets) {
|
||||
const pets = user.items.pets;
|
||||
if (pets['Wolf-Base'] > 0
|
||||
&& pets['TigerCub-Base'] > 0
|
||||
&& pets['PandaCub-Base'] > 0
|
||||
&& pets['LionCub-Base'] > 0
|
||||
&& pets['Fox-Base'] > 0
|
||||
&& pets['FlyingPig-Base'] > 0
|
||||
&& pets['Dragon-Base'] > 0
|
||||
&& pets['Cactus-Base'] > 0
|
||||
&& pets['BearCub-Base'] > 0) {
|
||||
set['achievements.backToBasics'] = true;
|
||||
}
|
||||
if (pets['Wolf-Desert'] > 0
|
||||
&& pets['TigerCub-Desert'] > 0
|
||||
&& pets['PandaCub-Desert'] > 0
|
||||
&& pets['LionCub-Desert'] > 0
|
||||
&& pets['Fox-Desert'] > 0
|
||||
&& pets['FlyingPig-Desert'] > 0
|
||||
&& pets['Dragon-Desert'] > 0
|
||||
&& pets['Cactus-Desert'] > 0
|
||||
&& pets['BearCub-Desert'] > 0) {
|
||||
set['achievements.dustDevil'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (user && user.items && user.items.mounts) {
|
||||
const mounts = user.items.mounts;
|
||||
if (mounts['Wolf-Base']
|
||||
&& mounts['TigerCub-Base']
|
||||
&& mounts['PandaCub-Base']
|
||||
&& mounts['LionCub-Base']
|
||||
&& mounts['Fox-Base']
|
||||
&& mounts['FlyingPig-Base']
|
||||
&& mounts['Dragon-Base']
|
||||
&& mounts['Cactus-Base']
|
||||
&& mounts['BearCub-Base'] ) {
|
||||
set['achievements.allYourBase'] = true;
|
||||
}
|
||||
if (mounts['Wolf-Desert']
|
||||
&& mounts['TigerCub-Desert']
|
||||
&& mounts['PandaCub-Desert']
|
||||
&& mounts['LionCub-Desert']
|
||||
&& mounts['Fox-Desert']
|
||||
&& mounts['FlyingPig-Desert']
|
||||
&& mounts['Dragon-Desert']
|
||||
&& mounts['Cactus-Desert']
|
||||
&& mounts['BearCub-Desert'] ) {
|
||||
set['achievements.aridAuthority'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2019-09-01') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1]._id,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,67 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20190927_kickstarter';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {};
|
||||
let push = {pinnedItems: {$each: []}};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
set['achievements.ks2019'] = true;
|
||||
|
||||
// set['items.gear.owned.armor_special_ks2019'] = false;
|
||||
// push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.armor_special_ks2019', _id: uuid()});
|
||||
set['items.gear.owned.head_special_ks2019'] = false;
|
||||
push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.head_special_ks2019', _id: uuid()});
|
||||
// set['items.gear.owned.shield_special_ks2019'] = false;
|
||||
// push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.shield_special_ks2019', _id: uuid()});
|
||||
// set['items.gear.owned.weapon_special_ks2019'] = false;
|
||||
// push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.weapon_special_ks2019', _id: uuid()});
|
||||
set['items.gear.owned.eyewear_special_ks2019'] = false;
|
||||
push.pinnedItems.$each.push({type: 'marketGear', path: 'gear.flat.eyewear_special_ks2019', _id: uuid()});
|
||||
// set['items.pets.Gryphon-Gryphatrice'] = 5;
|
||||
// set['items.mounts.Gryphon-Gryphatrice'] = true;
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set, $push: push}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.local.lowerCaseUsername': {$in: []},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20191022_pet_color_achievements';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = {
|
||||
migration: MIGRATION_NAME,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.pets) {
|
||||
const pets = user.items.pets;
|
||||
if (pets['Wolf-Zombie'] > 0
|
||||
&& pets['TigerCub-Zombie'] > 0
|
||||
&& pets['PandaCub-Zombie'] > 0
|
||||
&& pets['LionCub-Zombie'] > 0
|
||||
&& pets['Fox-Zombie'] > 0
|
||||
&& pets['FlyingPig-Zombie'] > 0
|
||||
&& pets['Dragon-Zombie'] > 0
|
||||
&& pets['Cactus-Zombie'] > 0
|
||||
&& pets['BearCub-Zombie'] > 0) {
|
||||
set['achievements.monsterMagus'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (user && user.items && user.items.mounts) {
|
||||
const mounts = user.items.mounts;
|
||||
if (mounts['Wolf-Zombie']
|
||||
&& mounts['TigerCub-Zombie']
|
||||
&& mounts['PandaCub-Zombie']
|
||||
&& mounts['LionCub-Zombie']
|
||||
&& mounts['Fox-Zombie']
|
||||
&& mounts['FlyingPig-Zombie']
|
||||
&& mounts['Dragon-Zombie']
|
||||
&& mounts['Cactus-Zombie']
|
||||
&& mounts['BearCub-Zombie'] ) {
|
||||
set['achievements.undeadUndertaker'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2019-10-01') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1]._id,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Award Habitoween ladder items to participants in this month's Habitoween festivities
|
||||
*/
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const MIGRATION_NAME = '20191031_habitoween_ladder'; // Update when running in future years
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {};
|
||||
const 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,
|
||||
};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Glow']) {
|
||||
set['items.mounts.JackOLantern-Glow'] = true;
|
||||
} else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Ghost']) {
|
||||
set['items.pets.JackOLantern-Glow'] = 5;
|
||||
} else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Ghost']) {
|
||||
set['items.mounts.JackOLantern-Ghost'] = true;
|
||||
} else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Base']) {
|
||||
set['items.pets.JackOLantern-Ghost'] = 5;
|
||||
} else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Base']) {
|
||||
set['items.mounts.JackOLantern-Base'] = true;
|
||||
} else {
|
||||
set['items.pets.JackOLantern-Base'] = 5;
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
return await User.update({_id: user._id}, {$inc: inc, $set: set}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-10-01')},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Award Onboarding Achievements for existing users
|
||||
*/
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const MIGRATION_NAME = '20191218_onboarding_achievements';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count += 1;
|
||||
|
||||
const set = {};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
const hasPet = Object.keys(user.items.pets).find(petKey => {
|
||||
const pet = user.items.pets[petKey];
|
||||
|
||||
if (pet >= 5) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hasPet) {
|
||||
set['achievements.hatchedPet'] = true;
|
||||
}
|
||||
|
||||
const hasFedPet = Object.keys(user.items.pets).find(petKey => {
|
||||
const pet = user.items.pets[petKey];
|
||||
|
||||
if (pet > 5) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hasFedPet) {
|
||||
set['achievements.fedPet'] = true;
|
||||
}
|
||||
|
||||
const hasGear = Object.keys(user.items.gear.owned).find(gearKey => {
|
||||
const gear = user.items.gear.owned[gearKey];
|
||||
|
||||
if (gear === true && gearKey.indexOf('_special_') === -1) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hasGear) {
|
||||
set['achievements.purchasedEquipment'] = true;
|
||||
}
|
||||
|
||||
if (user.tasksOrder) {
|
||||
const hasTask = Object.keys(user.tasksOrder).find(tasksOrderType => {
|
||||
const order = user.tasksOrder[tasksOrderType];
|
||||
|
||||
if (order && order.length > 0) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (hasTask) {
|
||||
set['achievements.createdTask'] = true;
|
||||
}
|
||||
|
||||
const hasExperience = user.stats && user.stats.exp && user.stats.exp > 0;
|
||||
if (hasTask && hasExperience) {
|
||||
set['achievements.completedTask'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
return User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () { // eslint-disable-line import/no-commonjs
|
||||
const query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
stats: 1,
|
||||
items: 1,
|
||||
achievements: 1,
|
||||
tasksOrder: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(100)
|
||||
.sort({ _id: 1 })
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,126 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20191127_harvest_feast';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {};
|
||||
let inc;
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.head_special_turkeyHelmGilded !== 'undefined') {
|
||||
inc = {
|
||||
'items.food.Pie_Base': 1,
|
||||
'items.food.Pie_CottonCandyBlue': 1,
|
||||
'items.food.Pie_CottonCandyPink': 1,
|
||||
'items.food.Pie_Desert': 1,
|
||||
'items.food.Pie_Golden': 1,
|
||||
'items.food.Pie_Red': 1,
|
||||
'items.food.Pie_Shade': 1,
|
||||
'items.food.Pie_Skeleton': 1,
|
||||
'items.food.Pie_Zombie': 1,
|
||||
'items.food.Pie_White': 1,
|
||||
}
|
||||
} else if (typeof user.items.gear.owned.armor_special_turkeyArmorBase !== 'undefined') {
|
||||
set['items.gear.owned.head_special_turkeyHelmGilded'] = false;
|
||||
set['items.gear.owned.armor_special_turkeyArmorGilded'] = false;
|
||||
set['items.gear.owned.back_special_turkeyTailGilded'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_turkeyHelmGilded',
|
||||
_id: uuid(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.armor_special_turkeyArmorGilded',
|
||||
_id: uuid(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.back_special_turkeyTailGilded',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Gilded']) {
|
||||
set['items.gear.owned.head_special_turkeyHelmBase'] = false;
|
||||
set['items.gear.owned.armor_special_turkeyArmorBase'] = false;
|
||||
set['items.gear.owned.back_special_turkeyTailBase'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_turkeyHelmBase',
|
||||
_id: uuid(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.armor_special_turkeyArmorBase',
|
||||
_id: uuid(),
|
||||
},
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.back_special_turkeyTailBase',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (user.items && user.items.pets && user.items.pets['Turkey-Gilded']) {
|
||||
set['items.mounts.Turkey-Gilded'] = true;
|
||||
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Base']) {
|
||||
set['items.pets.Turkey-Gilded'] = 5;
|
||||
} else if (user.items && user.items.pets && user.items.pets['Turkey-Base']) {
|
||||
set['items.mounts.Turkey-Base'] = true;
|
||||
} else {
|
||||
set['items.pets.Turkey-Base'] = 5;
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
if (inc) {
|
||||
return await User.update({_id: user._id}, {$inc: inc, $set: set}).exec();
|
||||
} else if (push) {
|
||||
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||
} else {
|
||||
return await User.update({_id: user._id}, {$set: set}).exec();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-11-01')},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20191210_pet_color_achievements';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
let set = {
|
||||
migration: MIGRATION_NAME,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.pets) {
|
||||
const pets = user.items.pets;
|
||||
if (pets['Wolf-White'] > 0
|
||||
&& pets['TigerCub-White'] > 0
|
||||
&& pets['PandaCub-White'] > 0
|
||||
&& pets['LionCub-White'] > 0
|
||||
&& pets['Fox-White'] > 0
|
||||
&& pets['FlyingPig-White'] > 0
|
||||
&& pets['Dragon-White'] > 0
|
||||
&& pets['Cactus-White'] > 0
|
||||
&& pets['BearCub-White'] > 0) {
|
||||
set['achievements.primedForPainting'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (user && user.items && user.items.mounts) {
|
||||
const mounts = user.items.mounts;
|
||||
if (mounts['Wolf-White']
|
||||
&& mounts['TigerCub-White']
|
||||
&& mounts['PandaCub-White']
|
||||
&& mounts['LionCub-White']
|
||||
&& mounts['Fox-White']
|
||||
&& mounts['FlyingPig-White']
|
||||
&& mounts['Dragon-White']
|
||||
&& mounts['Cactus-White']
|
||||
&& mounts['BearCub-White'] ) {
|
||||
set['achievements.pearlyPro'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2019-12-01') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1]._id,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,118 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20191231_nye';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {'flags.newStuff': true};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.head_special_nye2018 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2019'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2019',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2017 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2018'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2018',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2016 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2017'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2017',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2016'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2016',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2015'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2015',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') {
|
||||
set['items.gear.owned.head_special_nye2014'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye2014',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
} else {
|
||||
set['items.gear.owned.head_special_nye'] = false;
|
||||
push = [
|
||||
{
|
||||
type: 'marketGear',
|
||||
path: 'gear.flat.head_special_nye',
|
||||
_id: uuid(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
|
||||
}
|
||||
|
||||
export default async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,91 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20200131_habit_birthday';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const 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,
|
||||
};
|
||||
const set = {};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.armor_special_birthday2019 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2020'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2020', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday2018 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2019'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2019', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday2017 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2018'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2018', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday2016 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2017'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2017', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday2015 !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2016'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2016', _id: uuid()}};
|
||||
} else if (typeof user.items.gear.owned.armor_special_birthday !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_birthday2015'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday2015', _id: uuid()}};
|
||||
} else {
|
||||
set['items.gear.owned.armor_special_birthday'] = false;
|
||||
push = {pinnedItems: {type: 'marketGear', path: 'gear.flat.armor_special_birthday', _id: uuid()}};
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({_id: user._id}, {$inc: inc, $set: set, $push: push}).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: {$ne: MIGRATION_NAME},
|
||||
'auth.timestamps.loggedin': {$gt: new Date('2019-01-15')},
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const MIGRATION_NAME = '20200218_pet_color_achievements';
|
||||
import { model as User } from '../../../website/server/models/user';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const set = {
|
||||
migration: MIGRATION_NAME,
|
||||
};
|
||||
|
||||
if (user && user.items && user.items.pets) {
|
||||
const pets = user.items.pets;
|
||||
if (pets['Wolf-CottonCandyPink'] > 0
|
||||
&& pets['TigerCub-CottonCandyPink'] > 0
|
||||
&& pets['PandaCub-CottonCandyPink'] > 0
|
||||
&& pets['LionCub-CottonCandyPink'] > 0
|
||||
&& pets['Fox-CottonCandyPink'] > 0
|
||||
&& pets['FlyingPig-CottonCandyPink'] > 0
|
||||
&& pets['Dragon-CottonCandyPink'] > 0
|
||||
&& pets['Cactus-CottonCandyPink'] > 0
|
||||
&& pets['BearCub-CottonCandyPink'] > 0) {
|
||||
set['achievements.tickledPink'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (user && user.items && user.items.mounts) {
|
||||
const mounts = user.items.mounts;
|
||||
if (mounts['Wolf-CottonCandyPink']
|
||||
&& mounts['TigerCub-CottonCandyPink']
|
||||
&& mounts['PandaCub-CottonCandyPink']
|
||||
&& mounts['LionCub-CottonCandyPink']
|
||||
&& mounts['Fox-CottonCandyPink']
|
||||
&& mounts['FlyingPig-CottonCandyPink']
|
||||
&& mounts['Dragon-CottonCandyPink']
|
||||
&& mounts['Cactus-CottonCandyPink']
|
||||
&& mounts['BearCub-CottonCandyPink'] ) {
|
||||
set['achievements.rosyOutlook'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return await User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
module.exports = async function processUsers () {
|
||||
let query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2020-02-01') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({_id: 1})
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1]._id,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
};
|
||||
@@ -2,15 +2,15 @@ import { model as Challenges } from '../../website/server/models/challenge';
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
async function syncChallengeToMembers (challenges) {
|
||||
const challengSyncPromises = challenges.map(async challenge => {
|
||||
const users = await User.find({
|
||||
let challengSyncPromises = challenges.map(async (challenge) => {
|
||||
let users = await User.find({
|
||||
// _id: '',
|
||||
challenges: challenge._id,
|
||||
}).exec();
|
||||
|
||||
const promises = [];
|
||||
users.forEach(user => {
|
||||
promises.push(challenge.syncTasksToUser(user));
|
||||
let promises = [];
|
||||
users.forEach((user) => {
|
||||
promises.push(challenge.syncToUser(user));
|
||||
promises.push(challenge.save());
|
||||
promises.push(user.save());
|
||||
});
|
||||
@@ -18,11 +18,11 @@ async function syncChallengeToMembers (challenges) {
|
||||
return Promise.all(promises);
|
||||
});
|
||||
|
||||
return Promise.all(challengSyncPromises);
|
||||
return await Promise.all(challengSyncPromises);
|
||||
}
|
||||
|
||||
async function syncChallenges (lastChallengeDate) {
|
||||
const query = {
|
||||
let query = {
|
||||
// _id: '',
|
||||
};
|
||||
|
||||
@@ -30,16 +30,16 @@ async function syncChallenges (lastChallengeDate) {
|
||||
query.createdOn = { $lte: lastChallengeDate };
|
||||
}
|
||||
|
||||
const challengesFound = await Challenges.find(query)
|
||||
let challengesFound = await Challenges.find(query)
|
||||
.limit(10)
|
||||
.sort('-createdAt')
|
||||
.exec();
|
||||
|
||||
const syncedChallenges = await syncChallengeToMembers(challengesFound)
|
||||
let syncedChallenges = await syncChallengeToMembers(challengesFound)
|
||||
.catch(reason => console.error(reason));
|
||||
const lastChallenge = challengesFound[challengesFound.length - 1];
|
||||
let lastChallenge = challengesFound[challengesFound.length - 1];
|
||||
if (lastChallenge) syncChallenges(lastChallenge.createdAt);
|
||||
return syncedChallenges;
|
||||
}
|
||||
|
||||
export default syncChallenges;
|
||||
module.exports = syncChallenges;
|
||||
|
||||
@@ -1 +1 @@
|
||||
db.users.update({ _id: { $in: [''] } }, { $inc: { balance: 0.5 } }, { multi: true });
|
||||
db.users.update({_id: {$in: ['']}}, {$inc: {balance: 0.5}}, {multi: true});
|
||||
@@ -1,14 +1,11 @@
|
||||
// mongo habitrpg ./node_modules/moment/moment.js ./migrations/cancelSubscription.js
|
||||
|
||||
// For some reason people often to contact me to cancel their sub,
|
||||
// rather than do it online. Even when I point them to
|
||||
// For some reason people often to contact me to cancel their sub, rather than do it online. Even when I point them to
|
||||
// the FAQ (http://goo.gl/1uoPGQ) they insist...
|
||||
|
||||
db.users.update(
|
||||
{ _id: '' },
|
||||
{
|
||||
$set: {
|
||||
'purchased.plan.dateTerminated': moment().add('month', 1).toDate(),
|
||||
},
|
||||
},
|
||||
);
|
||||
{_id: ''},
|
||||
{$set: {
|
||||
'purchased.plan.dateTerminated': moment().add('month', 1).toDate(),
|
||||
}}
|
||||
);
|
||||
@@ -1,7 +1,8 @@
|
||||
// Give contrib.level 7+ free subscription for life
|
||||
db.users.update(
|
||||
|
||||
{
|
||||
'contributor.level': { $gte: 7 },
|
||||
'contributor.level': {$gte: 7},
|
||||
'purchased.plan.customerId': null,
|
||||
},
|
||||
|
||||
@@ -17,6 +18,6 @@ db.users.update(
|
||||
},
|
||||
},
|
||||
|
||||
{ multi: true },
|
||||
{multi: true}
|
||||
|
||||
);
|
||||
);
|
||||
@@ -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() } },
|
||||
);
|
||||
{_id: ''},
|
||||
{$set: {'purchased.plan.dateTerminated': moment().add({days: 7}).toDate()}}
|
||||
);
|
||||
@@ -39,52 +39,38 @@
|
||||
// needed. Do not miss any of them!
|
||||
|
||||
|
||||
const uuid = '30fb2640-7121-4968-ace5-f385e60ea6c5';
|
||||
let uuid = '30fb2640-7121-4968-ace5-f385e60ea6c5';
|
||||
|
||||
db.users.aggregate([
|
||||
{
|
||||
$match: {
|
||||
_id: uuid,
|
||||
},
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: 0, todos: 1,
|
||||
},
|
||||
},
|
||||
{ $unwind: '$todos' },
|
||||
{
|
||||
$group: {
|
||||
_id: { taskid: '$todos.id' },
|
||||
count: { $sum: 1 },
|
||||
},
|
||||
},
|
||||
{
|
||||
$match: {
|
||||
count: { $gt: 1 },
|
||||
},
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
'_id.taskid': 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: { taskid: '$todos.id' },
|
||||
troublesomeIds: { $addToSet: '$_id.taskid' },
|
||||
},
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: 0,
|
||||
troublesomeIds: 1,
|
||||
},
|
||||
},
|
||||
]).forEach(data => {
|
||||
{$match: {
|
||||
_id: uuid,
|
||||
}},
|
||||
{$project: {
|
||||
_id: 0, todos: 1,
|
||||
}},
|
||||
{$unwind: '$todos'},
|
||||
{$group: {
|
||||
_id: { taskid: '$todos.id' },
|
||||
count: { $sum: 1 },
|
||||
}},
|
||||
{$match: {
|
||||
count: { $gt: 1 },
|
||||
}},
|
||||
{$project: {
|
||||
'_id.taskid': 1,
|
||||
}},
|
||||
{$group: {
|
||||
_id: { taskid: '$todos.id' },
|
||||
troublesomeIds: { $addToSet: '$_id.taskid' },
|
||||
}},
|
||||
{$project: {
|
||||
_id: 0,
|
||||
troublesomeIds: 1,
|
||||
}},
|
||||
]).forEach((data) => {
|
||||
// print( "\n" ); printjson(data);
|
||||
data.troublesomeIds.forEach(taskid => {
|
||||
print(`non-unique task: ${taskid}`); // eslint-disable-line no-restricted-globals
|
||||
data.troublesomeIds.forEach((taskid) => {
|
||||
print(`non-unique task: ${ taskid}`);
|
||||
db.users.update({
|
||||
_id: uuid,
|
||||
todos: { $elemMatch: { id: taskid } },
|
||||
@@ -95,7 +81,8 @@ db.users.aggregate([
|
||||
});
|
||||
|
||||
db.users.update(
|
||||
{ _id: uuid },
|
||||
{ $pull: { todos: { id: 'de666' } } },
|
||||
{ multi: false },
|
||||
{_id: uuid},
|
||||
{$pull: { todos: { id: 'de666' } } },
|
||||
{multi: false }
|
||||
);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const oldId = '';
|
||||
const newId = '';
|
||||
const 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,
|
||||
// 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}});
|
||||
|
||||
|
||||
@@ -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(user => {
|
||||
db.users.find().forEach((user) => {
|
||||
user.tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards);
|
||||
const found = _.some(user.tasks, { text: '' });
|
||||
if (found) printjson({ id: user._id, auth: user.auth });
|
||||
});
|
||||
let found = _.some(user.tasks, {text: ''});
|
||||
if (found) printjson({id: user._id, auth: user.auth});
|
||||
});
|
||||
@@ -1,34 +1,32 @@
|
||||
// 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(
|
||||
// {_id:''},
|
||||
// {$set:{'purchased.plan':{
|
||||
// planId: 'basic_'+m+'mo',
|
||||
// paymentMethod: 'Paypal',
|
||||
// customerId: 'Gift',
|
||||
// dateCreated: new Date(),
|
||||
// dateTerminated: moment().add('month',m).toDate(),
|
||||
// dateUpdated: new Date(),
|
||||
// extraMonths: 0,
|
||||
// gemsBought: 0,
|
||||
// mysteryItems: [],
|
||||
// consecutive: {
|
||||
// count: 0,
|
||||
// offset: m,
|
||||
// gemCapExtra: m/3*5,
|
||||
// trinkets: m/3
|
||||
// }
|
||||
// planId: 'basic_'+m+'mo',
|
||||
// paymentMethod: 'Paypal',
|
||||
// customerId: 'Gift',
|
||||
// dateCreated: new Date(),
|
||||
// dateTerminated: moment().add('month',m).toDate(),
|
||||
// dateUpdated: new Date(),
|
||||
// extraMonths: 0,
|
||||
// gemsBought: 0,
|
||||
// mysteryItems: [],
|
||||
// consecutive: {
|
||||
// count: 0,
|
||||
// offset: m,
|
||||
// gemCapExtra: m/3*5,
|
||||
// trinkets: m/3
|
||||
// }
|
||||
// }}}
|
||||
// )
|
||||
// )
|
||||
@@ -1,5 +1,5 @@
|
||||
db.users.update(
|
||||
{},
|
||||
{ $inc: { 'achievements.habiticaDays': 1 } },
|
||||
{ multi: 1 },
|
||||
{$inc: {'achievements.habiticaDays': 1}},
|
||||
{multi: 1}
|
||||
);
|
||||
|
||||
@@ -1 +1 @@
|
||||
db.users.update({ _id: '' }, { $inc: { balance: 5 } });
|
||||
db.users.update({_id: ''}, {$inc: {balance: 5}});
|
||||
@@ -13,7 +13,7 @@ import { model as Group } from '../../website/server/models/group';
|
||||
|
||||
// @TODO: this should probably be a GroupManager library method
|
||||
async function addUnlimitedSubscription (groupId, dateTerminated) {
|
||||
const group = await Group.findOne({ _id: groupId });
|
||||
let group = await Group.findOne({_id: groupId});
|
||||
|
||||
group.purchased.plan.customerId = 'group-unlimited';
|
||||
group.purchased.plan.dateCreated = new Date();
|
||||
@@ -22,7 +22,7 @@ async function addUnlimitedSubscription (groupId, dateTerminated) {
|
||||
group.purchased.plan.planId = 'group_monthly';
|
||||
group.purchased.plan.dateTerminated = null;
|
||||
if (dateTerminated) {
|
||||
const dateToEnd = moment(dateTerminated).toDate();
|
||||
let dateToEnd = moment(dateTerminated).toDate();
|
||||
group.purchased.plan.dateTerminated = dateToEnd;
|
||||
}
|
||||
// group.purchased.plan.owner = ObjectId();
|
||||
@@ -31,12 +31,12 @@ async function addUnlimitedSubscription (groupId, dateTerminated) {
|
||||
return group.save();
|
||||
}
|
||||
|
||||
export default async function addUnlimitedSubscriptionCreator () {
|
||||
const groupId = process.argv[2];
|
||||
module.exports = async function addUnlimitedSubscriptionCreator () {
|
||||
let groupId = process.argv[2];
|
||||
|
||||
if (!groupId) throw Error('Group ID is required');
|
||||
|
||||
const dateTerminated = process.argv[3];
|
||||
let dateTerminated = process.argv[3];
|
||||
|
||||
await addUnlimitedSubscription(groupId, dateTerminated);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,9 +3,9 @@ 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) {
|
||||
const user = await User.findOne({ _id: leaderId });
|
||||
let user = await User.findOne({_id: leaderId});
|
||||
|
||||
const group = new Group({
|
||||
let group = new Group({
|
||||
name,
|
||||
privacy,
|
||||
type,
|
||||
@@ -17,11 +17,13 @@ async function createGroup (name, privacy, type, leaderId) {
|
||||
return Promise.all([group.save(), user.save()]);
|
||||
}
|
||||
|
||||
export default async function groupCreator () {
|
||||
const name = process.argv[2];
|
||||
const privacy = process.argv[3];
|
||||
const type = process.argv[4];
|
||||
const leaderId = process.argv[5];
|
||||
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];
|
||||
|
||||
await createGroup(name, privacy, type, leaderId);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,43 +1,44 @@
|
||||
/* let migrationName = 'Jackalopes for Unlimited Subscribers'; */
|
||||
|
||||
/*
|
||||
* This migration will find users with unlimited subscriptions who are also eligible
|
||||
* for Jackalope mounts, and award them
|
||||
* This migration will find users with unlimited subscriptions who are also eligible for Jackalope mounts, and award them
|
||||
*/
|
||||
|
||||
import { model as Group } from '../../website/server/models/group';
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
async function handOutJackalopes () {
|
||||
const promises = [];
|
||||
const cursor = User.find({
|
||||
let promises = [];
|
||||
let cursor = User.find({
|
||||
'purchased.plan.customerId': 'habitrpg',
|
||||
}).cursor();
|
||||
|
||||
cursor.on('data', async 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);
|
||||
groupList = groupList.concat(user.guilds);
|
||||
|
||||
const subscribedGroup = await Group.findOne({
|
||||
_id: { $in: groupList },
|
||||
'purchased.plan.planId': 'group_monthly',
|
||||
'purchased.plan.dateTerminated': null,
|
||||
},
|
||||
{ _id: 1 });
|
||||
let subscribedGroup =
|
||||
await Group.findOne({
|
||||
_id: {$in: groupList},
|
||||
'purchased.plan.planId': 'group_monthly',
|
||||
'purchased.plan.dateTerminated': null,
|
||||
},
|
||||
{_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 () => {
|
||||
console.log('done');
|
||||
return Promise.all(promises);
|
||||
return await Promise.all(promises);
|
||||
});
|
||||
}
|
||||
|
||||
export default handOutJackalopes;
|
||||
module.exports = handOutJackalopes;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import { model as Group } from '../../website/server/models/group';
|
||||
import { chatModel as Chat } from '../../website/server/models/message';
|
||||
import { model as Chat } from '../../website/server/models/chat';
|
||||
|
||||
async function moveGroupChatToModel (skip = 0) {
|
||||
const groups = await Group.find({})
|
||||
@@ -40,7 +40,7 @@ async function moveGroupChatToModel (skip = 0) {
|
||||
|
||||
|
||||
const reducedPromises = promises.reduce((acc, curr) => {
|
||||
acc = acc.concat(curr); // eslint-disable-line no-param-reassign
|
||||
acc = acc.concat(curr);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
@@ -49,4 +49,4 @@ async function moveGroupChatToModel (skip = 0) {
|
||||
moveGroupChatToModel(skip + 50);
|
||||
}
|
||||
|
||||
export default moveGroupChatToModel;
|
||||
module.exports = moveGroupChatToModel;
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
import nconf from 'nconf';
|
||||
import stripePayments from '../../website/server/libs/payments/stripe';
|
||||
|
||||
/*
|
||||
* Ensure that group plan billing is accurate by doing the following:
|
||||
* 1. Correct the memberCount in all paid groups whose counts are wrong
|
||||
* 2. Where the above uses Stripe, update their subscription counts in Stripe
|
||||
*
|
||||
* Provides output on what groups were fixed, which can be piped to CSV.
|
||||
*/
|
||||
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING');
|
||||
|
||||
const dbGroups = monk(CONNECTION_STRING).get('groups', { castIds: false });
|
||||
const dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false });
|
||||
|
||||
async function fixGroupPlanMembers () {
|
||||
console.info('Group ID, Customer ID, Plan ID, Quantity, Recorded Member Count, Actual Member Count');
|
||||
let groupPlanCount = 0;
|
||||
let fixedGroupCount = 0;
|
||||
|
||||
dbGroups.find(
|
||||
{
|
||||
$and:
|
||||
[
|
||||
{ 'purchased.plan.planId': { $ne: null } },
|
||||
{ 'purchased.plan.planId': { $ne: '' } },
|
||||
{ 'purchased.plan.customerId': { $ne: 'cus_9f0DV4g7WHRzpM' } }, // Demo groups
|
||||
{ 'purchased.plan.customerId': { $ne: 'cus_9maalqDOFTrvqx' } },
|
||||
],
|
||||
$or:
|
||||
[
|
||||
{ 'purchased.plan.dateTerminated': null },
|
||||
{ 'purchased.plan.dateTerminated': '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
fields: {
|
||||
memberCount: 1,
|
||||
'purchased.plan': 1,
|
||||
},
|
||||
},
|
||||
).each(async (group, { close, pause, resume }) => { // eslint-disable-line no-unused-vars
|
||||
pause();
|
||||
groupPlanCount += 1;
|
||||
|
||||
const canonicalMemberCount = await dbUsers.count(
|
||||
{
|
||||
$or:
|
||||
[
|
||||
{ 'party._id': group._id },
|
||||
{ guilds: group._id },
|
||||
],
|
||||
},
|
||||
);
|
||||
const incorrectMemberCount = group.memberCount !== canonicalMemberCount;
|
||||
|
||||
const isMonthlyPlan = group.purchased.plan.planId === 'group_monthly';
|
||||
const quantityMismatch = group.purchased.plan.quantity !== group.memberCount + 2;
|
||||
const incorrectQuantity = isMonthlyPlan && quantityMismatch;
|
||||
|
||||
if (!incorrectMemberCount && !incorrectQuantity) {
|
||||
resume();
|
||||
return;
|
||||
}
|
||||
|
||||
console.info(`${group._id}, ${group.purchased.plan.customerId}, ${group.purchased.plan.planId}, ${group.purchased.plan.quantity}, ${group.memberCount}, ${canonicalMemberCount}`);
|
||||
|
||||
const groupUpdate = await dbGroups.update(
|
||||
{ _id: group._id },
|
||||
{
|
||||
$set: {
|
||||
memberCount: canonicalMemberCount,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!groupUpdate) return;
|
||||
|
||||
fixedGroupCount += 1;
|
||||
if (group.purchased.plan.paymentMethod === 'Stripe') {
|
||||
await stripePayments.chargeForAdditionalGroupMember(group);
|
||||
await dbGroups.update(
|
||||
{ _id: group._id },
|
||||
{ $set: { 'purchased.plan.quantity': canonicalMemberCount + 2 } },
|
||||
);
|
||||
}
|
||||
|
||||
if (incorrectQuantity) {
|
||||
await dbGroups.update(
|
||||
{ _id: group._id },
|
||||
{ $set: { 'purchased.plan.quantity': canonicalMemberCount + 2 } },
|
||||
);
|
||||
}
|
||||
|
||||
resume();
|
||||
}).then(() => {
|
||||
console.info(`Fixed ${fixedGroupCount} out of ${groupPlanCount} active Group Plans`);
|
||||
return process.exit(0);
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
return process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
export default fixGroupPlanMembers;
|
||||
@@ -5,27 +5,29 @@ let authorUuid = ''; // ... own data is done
|
||||
*/
|
||||
|
||||
/*
|
||||
* This migrations will iterate through all groups with a group plan
|
||||
* a subscription and resync the free subscription to all members
|
||||
* This migrations will iterate through all groups with a group plan a subscription and resync the free
|
||||
* subscription to all members
|
||||
*/
|
||||
|
||||
import { model as Group } from '../../website/server/models/group';
|
||||
import payments from '../../website/server/libs/payments/payments';
|
||||
import * as payments from '../../website/server/libs/payments';
|
||||
|
||||
async function updateGroupsWithGroupPlans () {
|
||||
const cursor = Group.find({
|
||||
let cursor = Group.find({
|
||||
'purchased.plan.planId': 'group_monthly',
|
||||
'purchased.plan.dateTerminated': null,
|
||||
}).cursor();
|
||||
|
||||
const promises = [];
|
||||
let promises = [];
|
||||
|
||||
cursor.on('data', group => {
|
||||
cursor.on('data', (group) => {
|
||||
promises.push(payments.addSubscriptionToGroupUsers(group));
|
||||
promises.push(group.save());
|
||||
});
|
||||
|
||||
cursor.on('close', async () => Promise.all(promises));
|
||||
cursor.on('close', async () => {
|
||||
return await Promise.all(promises);
|
||||
});
|
||||
}
|
||||
|
||||
export default updateGroupsWithGroupPlans;
|
||||
module.exports = updateGroupsWithGroupPlans;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
require('@babel/register'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
require('babel-register');
|
||||
|
||||
// This file must use ES5, everything required can be in ES6
|
||||
|
||||
@@ -18,13 +17,5 @@ function setUpServer () {
|
||||
setUpServer();
|
||||
|
||||
// Replace this with your migration
|
||||
const processUsers = () => {}; // require('').default;
|
||||
|
||||
processUsers()
|
||||
.then(() => {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
process.exit(1);
|
||||
});
|
||||
const processUsers = require('./groups/migrate-chat.js');
|
||||
processUsers();
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
/* let migrationName = 'new_stuff.js'; */
|
||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
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
|
||||
*/
|
||||
|
||||
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
const 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) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
const query = {
|
||||
'flags.newStuff': { $ne: true },
|
||||
let query = {
|
||||
'flags.newStuff': {$ne: true},
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
@@ -25,31 +23,29 @@ function processUsers (lastId) {
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: { _id: 1 },
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
// specify fields we are interested in to limit retrieved data
|
||||
// (empty if we're not reading data):
|
||||
fields: [],
|
||||
fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const userPromises = users.map(updateUser);
|
||||
const lastUser = users[users.length - 1];
|
||||
let userPromises = users.map(updateUser);
|
||||
let lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(() => {
|
||||
@@ -58,31 +54,30 @@ function updateUsers (users) {
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count += 1;
|
||||
count++;
|
||||
|
||||
const 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`);
|
||||
console.warn(`\n${ count } users processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
const migrationName = 'restock_armoire.js';
|
||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
const 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
|
||||
*/
|
||||
|
||||
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
const 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) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
const query = {
|
||||
let query = {
|
||||
'flags.armoireEmpty': true,
|
||||
};
|
||||
|
||||
@@ -25,31 +23,29 @@ function processUsers (lastId) {
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: { _id: 1 },
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
// specify fields we are interested in to limit retrieved data
|
||||
// (empty if we're not reading data):
|
||||
fields: [],
|
||||
fields: [], // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const userPromises = users.map(updateUser);
|
||||
const lastUser = users[users.length - 1];
|
||||
let userPromises = users.map(updateUser);
|
||||
let lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(() => {
|
||||
@@ -58,31 +54,30 @@ function updateUsers (users) {
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count += 1;
|
||||
count++;
|
||||
|
||||
const 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`);
|
||||
console.warn(`\n${ count } users processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
const migrationName = 'restock_armoire_for_users_that_need_it.js';
|
||||
const authorName = 'Alys (ALittleYellowSpider)'; // in case script author needs to know when their ...
|
||||
const 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,
|
||||
@@ -19,17 +18,16 @@ const authorUuid = '3e595299-3d8a-4a10-bfe0-88f555e4aa0c'; // ... own data is do
|
||||
*
|
||||
*/
|
||||
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
|
||||
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
let monk = require('monk');
|
||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
const 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
|
||||
};
|
||||
|
||||
@@ -37,7 +35,7 @@ function processUsers (lastId) {
|
||||
/* let fields = {
|
||||
'flags.armoireEmpty': 1,
|
||||
'items.gear.owned': 1,
|
||||
}; */
|
||||
};*/
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
@@ -46,34 +44,32 @@ function processUsers (lastId) {
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: { _id: 1 },
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
// specify fields we are interested in to limit retrieved data
|
||||
// (empty if we're not reading data):
|
||||
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):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const userPromises = users.map(updateUser);
|
||||
const lastUser = users[users.length - 1];
|
||||
let userPromises = users.map(updateUser);
|
||||
let lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(() => {
|
||||
@@ -82,69 +78,19 @@ function updateUsers (users) {
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count += 1;
|
||||
count++;
|
||||
|
||||
const set = { migration: migrationName, 'flags.armoireEmpty': false };
|
||||
let set = {migration: migrationName, 'flags.armoireEmpty': false};
|
||||
|
||||
|
||||
if (user.flags.armoireEmpty) {
|
||||
// this user believes their armoire has no more items in it
|
||||
if (
|
||||
user.items.gear.owned.weapon_armoire_barristerGavel
|
||||
&& user.items.gear.owned.armor_armoire_barristerRobes
|
||||
&& user.items.gear.owned.head_armoire_jesterCap
|
||||
&& user.items.gear.owned.armor_armoire_jesterCostume
|
||||
&& user.items.gear.owned.head_armoire_barristerWig
|
||||
&& user.items.gear.owned.weapon_armoire_jesterBaton
|
||||
&& user.items.gear.owned.weapon_armoire_lunarSceptre
|
||||
&& user.items.gear.owned.armor_armoire_gladiatorArmor
|
||||
&& user.items.gear.owned.weapon_armoire_basicCrossbow
|
||||
&& user.items.gear.owned.head_armoire_gladiatorHelm
|
||||
&& user.items.gear.owned.armor_armoire_lunarArmor
|
||||
&& user.items.gear.owned.head_armoire_redHairbow
|
||||
&& user.items.gear.owned.head_armoire_violetFloppyHat
|
||||
&& user.items.gear.owned.head_armoire_rancherHat
|
||||
&& user.items.gear.owned.shield_armoire_gladiatorShield
|
||||
&& user.items.gear.owned.head_armoire_blueHairbow
|
||||
&& user.items.gear.owned.weapon_armoire_mythmakerSword
|
||||
&& user.items.gear.owned.head_armoire_royalCrown
|
||||
&& user.items.gear.owned.head_armoire_hornedIronHelm
|
||||
&& user.items.gear.owned.weapon_armoire_rancherLasso
|
||||
&& user.items.gear.owned.armor_armoire_rancherRobes
|
||||
&& user.items.gear.owned.armor_armoire_hornedIronArmor
|
||||
&& user.items.gear.owned.armor_armoire_goldenToga
|
||||
&& user.items.gear.owned.weapon_armoire_ironCrook
|
||||
&& user.items.gear.owned.head_armoire_goldenLaurels
|
||||
&& user.items.gear.owned.head_armoire_redFloppyHat
|
||||
&& user.items.gear.owned.armor_armoire_plagueDoctorOvercoat
|
||||
&& user.items.gear.owned.head_armoire_plagueDoctorHat
|
||||
&& user.items.gear.owned.weapon_armoire_goldWingStaff
|
||||
&& user.items.gear.owned.head_armoire_yellowHairbow
|
||||
&& user.items.gear.owned.eyewear_armoire_plagueDoctorMask
|
||||
&& user.items.gear.owned.head_armoire_blackCat
|
||||
&& user.items.gear.owned.weapon_armoire_batWand
|
||||
&& user.items.gear.owned.head_armoire_orangeCat
|
||||
&& user.items.gear.owned.shield_armoire_midnightShield
|
||||
&& user.items.gear.owned.armor_armoire_royalRobes
|
||||
&& user.items.gear.owned.head_armoire_blueFloppyHat
|
||||
&& user.items.gear.owned.shield_armoire_royalCane
|
||||
&& user.items.gear.owned.weapon_armoire_shepherdsCrook
|
||||
&& user.items.gear.owned.armor_armoire_shepherdRobes
|
||||
&& user.items.gear.owned.head_armoire_shepherdHeaddress
|
||||
&& user.items.gear.owned.weapon_armoire_blueLongbow
|
||||
&& user.items.gear.owned.weapon_armoire_crystalCrescentStaff
|
||||
&& user.items.gear.owned.head_armoire_crystalCrescentHat
|
||||
&& user.items.gear.owned.armor_armoire_dragonTamerArmor
|
||||
&& user.items.gear.owned.head_armoire_dragonTamerHelm
|
||||
&& user.items.gear.owned.armor_armoire_crystalCrescentRobes
|
||||
&& user.items.gear.owned.shield_armoire_dragonTamerShield
|
||||
&& user.items.gear.owned.weapon_armoire_glowingSpear
|
||||
) {
|
||||
if (user.items.gear.owned.weapon_armoire_barristerGavel && user.items.gear.owned.armor_armoire_barristerRobes && user.items.gear.owned.head_armoire_jesterCap && user.items.gear.owned.armor_armoire_jesterCostume && user.items.gear.owned.head_armoire_barristerWig && user.items.gear.owned.weapon_armoire_jesterBaton && user.items.gear.owned.weapon_armoire_lunarSceptre && user.items.gear.owned.armor_armoire_gladiatorArmor && user.items.gear.owned.weapon_armoire_basicCrossbow && user.items.gear.owned.head_armoire_gladiatorHelm && user.items.gear.owned.armor_armoire_lunarArmor && user.items.gear.owned.head_armoire_redHairbow && user.items.gear.owned.head_armoire_violetFloppyHat && user.items.gear.owned.head_armoire_rancherHat && user.items.gear.owned.shield_armoire_gladiatorShield && user.items.gear.owned.head_armoire_blueHairbow && user.items.gear.owned.weapon_armoire_mythmakerSword && user.items.gear.owned.head_armoire_royalCrown && user.items.gear.owned.head_armoire_hornedIronHelm && user.items.gear.owned.weapon_armoire_rancherLasso && user.items.gear.owned.armor_armoire_rancherRobes && user.items.gear.owned.armor_armoire_hornedIronArmor && user.items.gear.owned.armor_armoire_goldenToga && user.items.gear.owned.weapon_armoire_ironCrook && user.items.gear.owned.head_armoire_goldenLaurels && user.items.gear.owned.head_armoire_redFloppyHat && user.items.gear.owned.armor_armoire_plagueDoctorOvercoat && user.items.gear.owned.head_armoire_plagueDoctorHat && user.items.gear.owned.weapon_armoire_goldWingStaff && user.items.gear.owned.head_armoire_yellowHairbow && user.items.gear.owned.eyewear_armoire_plagueDoctorMask && user.items.gear.owned.head_armoire_blackCat && user.items.gear.owned.weapon_armoire_batWand && user.items.gear.owned.head_armoire_orangeCat && user.items.gear.owned.shield_armoire_midnightShield && user.items.gear.owned.armor_armoire_royalRobes && user.items.gear.owned.head_armoire_blueFloppyHat && user.items.gear.owned.shield_armoire_royalCane && user.items.gear.owned.weapon_armoire_shepherdsCrook && user.items.gear.owned.armor_armoire_shepherdRobes && user.items.gear.owned.head_armoire_shepherdHeaddress && user.items.gear.owned.weapon_armoire_blueLongbow && user.items.gear.owned.weapon_armoire_crystalCrescentStaff && user.items.gear.owned.head_armoire_crystalCrescentHat && user.items.gear.owned.armor_armoire_dragonTamerArmor && user.items.gear.owned.head_armoire_dragonTamerHelm && user.items.gear.owned.armor_armoire_crystalCrescentRobes && user.items.gear.owned.shield_armoire_dragonTamerShield && user.items.gear.owned.weapon_armoire_glowingSpear) {
|
||||
// this user does have all the armoire items so we don't change the flag
|
||||
// console.log("don't change: " + user._id); // FOR TESTING
|
||||
} else {
|
||||
// console.log("change: " + user._id); // FOR TESTING
|
||||
dbUsers.update({ _id: user._id }, { $set: set });
|
||||
dbUsers.update({_id: user._id}, {$set: set});
|
||||
}
|
||||
} else {
|
||||
// this user already has armoire marked as containing items to be bought
|
||||
@@ -152,25 +98,24 @@ 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`);
|
||||
console.warn(`\n${ count } users processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
/* let migrationName = 'restore_profile_data.js'; */
|
||||
const authorName = 'ThehollidayInn'; // in case script author needs to know when their ...
|
||||
const authorUuid = ''; // ... own data is done
|
||||
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
|
||||
*/
|
||||
|
||||
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
let monk = require('monk');
|
||||
let connectionString = ''; // FOR TEST DATABASE
|
||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
const connectionString = ''; // FOR TEST DATABASE
|
||||
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
const monk2 = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const oldDbConnectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
const 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) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
const query = {
|
||||
let query = {
|
||||
// 'profile.name': 'profile name not found',
|
||||
'profile.blurb': null,
|
||||
// 'auth.timestamps.loggedin': {$gt: new Date('11/30/2016')},
|
||||
@@ -32,47 +29,49 @@ function processUsers (lastId) {
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: { _id: 1 },
|
||||
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):
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
setTimeout(displayData, 300000);
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const userPaymentPromises = users.map(updateUser);
|
||||
const lastUser = users[users.length - 1];
|
||||
let userPaymentPromises = users.map(updateUser);
|
||||
let lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPaymentPromises)
|
||||
.then(() => processUsers(lastUser._id));
|
||||
.then(() => {
|
||||
return processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count += 1;
|
||||
count++;
|
||||
|
||||
if (!user.profile.name || user.profile.name === 'profile name not found' || !user.profile.imageUrl || !user.profile.blurb) {
|
||||
return olDbUsers.findOne({ _id: user._id }, '_id profile')
|
||||
.then(oldUserData => {
|
||||
if (!oldUserData) return null;
|
||||
return olDbUsers.findOne({_id: user._id}, '_id profile')
|
||||
.then((oldUserData) => {
|
||||
if (!oldUserData) return;
|
||||
// specify user data to change:
|
||||
const set = {};
|
||||
let set = {};
|
||||
|
||||
if (oldUserData.profile.name === 'profile name not found') return null;
|
||||
if (oldUserData.profile.name === 'profile name not found') return;
|
||||
|
||||
const 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;
|
||||
}
|
||||
@@ -87,34 +86,29 @@ function updateUser (user) {
|
||||
|
||||
if (Object.keys(set).length !== 0 && set.constructor === Object) {
|
||||
console.log(set);
|
||||
return dbUsers.update({ _id: user._id }, { $set: set });
|
||||
return dbUsers.update({_id: user._id}, {$set: set});
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
if (user._id === authorUuid) console.warn(`${authorName} processed`);
|
||||
|
||||
return null;
|
||||
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`);
|
||||
console.warn(`\n${ count } users processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
const request = require('superagent');
|
||||
const last = require('lodash/last');
|
||||
const AWS = require('aws-sdk');
|
||||
|
||||
const config = require('../config');
|
||||
let request = require('superagent');
|
||||
let last = require('lodash/last');
|
||||
let AWS = require('aws-sdk');
|
||||
|
||||
let config = require('../config');
|
||||
const S3_DIRECTORY = 'mobileApp/images'; // config.S3.SPRITES_DIRECTORY;
|
||||
|
||||
AWS.config.update({
|
||||
@@ -13,8 +11,8 @@ AWS.config.update({
|
||||
// region: config.get('S3_REGION'),
|
||||
});
|
||||
|
||||
const BUCKET_NAME = config.S3.bucket;
|
||||
const s3 = new AWS.S3();
|
||||
let BUCKET_NAME = config.S3.bucket;
|
||||
let s3 = new AWS.S3();
|
||||
|
||||
// Adapted from http://stackoverflow.com/a/22210077/2601552
|
||||
function uploadFile (buffer, fileName) {
|
||||
@@ -23,11 +21,11 @@ function uploadFile (buffer, fileName) {
|
||||
Body: buffer,
|
||||
Key: fileName,
|
||||
Bucket: BUCKET_NAME,
|
||||
}, error => {
|
||||
}, (error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
// console.info(`${fileName} uploaded to ${BUCKET_NAME} successfully.`);
|
||||
// console.info(`${fileName} uploaded to ${BUCKET_NAME} succesfully.`);
|
||||
resolve(fileName);
|
||||
}
|
||||
});
|
||||
@@ -35,9 +33,9 @@ function uploadFile (buffer, fileName) {
|
||||
}
|
||||
|
||||
function getFileName (file) {
|
||||
const piecesOfPath = file.split('/');
|
||||
const name = last(piecesOfPath);
|
||||
const fullName = S3_DIRECTORY + name;
|
||||
let piecesOfPath = file.split('/');
|
||||
let name = last(piecesOfPath);
|
||||
let fullName = S3_DIRECTORY + name;
|
||||
|
||||
return fullName;
|
||||
}
|
||||
@@ -46,32 +44,36 @@ function getFileFromUrl (url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.get(url).end((err, res) => {
|
||||
if (err) return reject(err);
|
||||
const file = res.body;
|
||||
return resolve(file);
|
||||
let file = res.body;
|
||||
resolve(file);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let commit = '78f94e365c72cc58f66857d5941105638db7d35c';
|
||||
commit = 'df0dbaba636c9ce424cc7040f7bd7fc1aa311015';
|
||||
const 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) {
|
||||
const urls = filesUrls.slice(start, end);
|
||||
let urls = filesUrls.slice(start, end);
|
||||
|
||||
if (urls.length === 0) {
|
||||
console.log('done');
|
||||
return;
|
||||
}
|
||||
|
||||
const promises = urls.map(fullUrl => getFileFromUrl(fullUrl)
|
||||
.then(buffer => uploadFile(buffer, getFileName(fullUrl))));
|
||||
let promises = urls.map(fullUrl => {
|
||||
return getFileFromUrl(fullUrl)
|
||||
.then((buffer) => {
|
||||
return uploadFile(buffer, getFileName(fullUrl));
|
||||
});
|
||||
});
|
||||
console.log(promises.length);
|
||||
|
||||
Promise.all(promises)
|
||||
return Promise.all(promises)
|
||||
.then(() => {
|
||||
currentIndex += 50;
|
||||
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
||||
@@ -84,10 +86,12 @@ function uploadToS3 (start, end, filesUrls) {
|
||||
request.get(gihuburl)
|
||||
.end((err, res) => {
|
||||
console.log(err);
|
||||
const { files } = res.body;
|
||||
let files = res.body.files;
|
||||
|
||||
let filesUrls = [''];
|
||||
filesUrls = files.map(file => file.raw_url);
|
||||
filesUrls = files.map(file => {
|
||||
return file.raw_url;
|
||||
});
|
||||
|
||||
uploadToS3(currentIndex, currentIndex + 50, filesUrls);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
let migrationName = '20180904_takeThis.js'; // Update per month
|
||||
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
|
||||
|
||||
@@ -6,16 +6,15 @@ let authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
* Award Take This ladder items to participants in this month's challenge
|
||||
*/
|
||||
|
||||
import monk from 'monk';
|
||||
import nconf from 'nconf';
|
||||
const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING'); // FOR TEST DATABASE
|
||||
let dbUsers = monk(CONNECTION_STRING).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) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: migrationName},
|
||||
challenges: {$in: ['1044ec0c-4a85-48c5-9f36-d51c0c62c7d3']}, // Update per month
|
||||
challenges: {$in: ['5f70ce5b-2d82-4114-8e44-ca65615aae62']}, // Update per month
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
@@ -1,139 +0,0 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
// const migrationName = 'habits-one-history-entry-per-day';
|
||||
// const authorName = 'paglias'; // in case script author needs to know when their ...
|
||||
// const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Iterates over all habits and condense multiple history entries for the same day into a single one
|
||||
*/
|
||||
|
||||
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const _ = require('lodash');
|
||||
const moment = require('moment');
|
||||
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||
|
||||
function processChallengeHabits (lastId) {
|
||||
const query = {
|
||||
'challenge.id': { $exists: true },
|
||||
userId: { $exists: false },
|
||||
type: 'habit',
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbTasks.find(query, {
|
||||
sort: { _id: 1 },
|
||||
limit: 500,
|
||||
})
|
||||
.then(updateChallengeHabits)
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateChallengeHabits (habits) {
|
||||
if (!habits || habits.length === 0) {
|
||||
console.warn('All appropriate challenge habits found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
}
|
||||
|
||||
const habitsPromises = habits.map(updateChallengeHabit);
|
||||
const lastHabit = habits[habits.length - 1];
|
||||
|
||||
return Promise.all(habitsPromises)
|
||||
.then(() => processChallengeHabits(lastHabit._id));
|
||||
}
|
||||
|
||||
function updateChallengeHabit (habit) {
|
||||
count += 1;
|
||||
|
||||
if (habit && habit.history && habit.history.length > 0) {
|
||||
// First remove missing entries
|
||||
habit.history = habit.history.filter(entry => Boolean(entry));
|
||||
|
||||
habit.history = _.chain(habit.history)
|
||||
// processes all entries to identify an up or down score
|
||||
.forEach((entry, index) => {
|
||||
if (index === 0) { // first entry doesn't have a previous one
|
||||
// first value < 0 identifies a negative score as the first action
|
||||
entry.scoreDirection = entry.value >= 0 ? 'up' : 'down';
|
||||
} else {
|
||||
// could be missing if the previous entry was null and thus excluded
|
||||
const previousEntry = habit.history[index - 1];
|
||||
const previousValue = previousEntry.value;
|
||||
|
||||
entry.scoreDirection = entry.value > previousValue ? 'up' : 'down';
|
||||
}
|
||||
})
|
||||
// group entries by aggregateBy
|
||||
.groupBy(entry => moment(entry.date).format('YYYYMMDD'))
|
||||
.toPairs() // [key, entry]
|
||||
.sortBy(([key]) => key) // sort by date
|
||||
.map(keyEntryPair => {
|
||||
const entries = keyEntryPair[1]; // 1 is entry, 0 is key
|
||||
let scoredUp = 0;
|
||||
let scoredDown = 0;
|
||||
|
||||
entries.forEach(entry => {
|
||||
if (entry.scoreDirection === 'up') {
|
||||
scoredUp += 1;
|
||||
} else {
|
||||
scoredDown += 1;
|
||||
}
|
||||
|
||||
// delete the unnecessary scoreDirection and scoreNotes prop
|
||||
delete entry.scoreDirection;
|
||||
delete entry.scoreNotes;
|
||||
});
|
||||
|
||||
return {
|
||||
date: Number(entries[entries.length - 1].date), // keep last value
|
||||
value: entries[entries.length - 1].value, // keep last value,
|
||||
scoredUp,
|
||||
scoredDown,
|
||||
};
|
||||
})
|
||||
.value();
|
||||
|
||||
return dbTasks.update({ _id: habit._id }, {
|
||||
$set: { history: habit.history },
|
||||
});
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} habits processed`);
|
||||
return null;
|
||||
}
|
||||
|
||||
function displayData () {
|
||||
console.warn(`\n${count} tasks processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
export default processChallengeHabits;
|
||||
@@ -1,162 +0,0 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
const migrationName = 'habits-one-history-entry-per-day';
|
||||
const authorName = 'paglias'; // in case script author needs to know when their ...
|
||||
const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Iterates over all habits and condense multiple history entries for the same day into a single one
|
||||
*/
|
||||
|
||||
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
const _ = require('lodash');
|
||||
const moment = require('moment');
|
||||
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
const query = {
|
||||
migration: { $ne: migrationName },
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: { _id: 1 },
|
||||
limit: 50, // just 50 users per time since we have to process all their habits as well
|
||||
fields: ['_id', 'preferences.timezoneOffset', 'preferences.dayStart'],
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users and their tasks found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
}
|
||||
|
||||
const usersPromises = users.map(updateUser);
|
||||
const lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(usersPromises)
|
||||
.then(() => processUsers(lastUser._id));
|
||||
}
|
||||
|
||||
function updateHabit (habit, timezoneOffset, dayStart) {
|
||||
if (habit && habit.history && habit.history.length > 0) {
|
||||
// First remove missing entries
|
||||
habit.history = habit.history.filter(entry => Boolean(entry));
|
||||
|
||||
habit.history = _.chain(habit.history)
|
||||
// processes all entries to identify an up or down score
|
||||
.forEach((entry, index) => {
|
||||
if (index === 0) { // first entry doesn't have a previous one
|
||||
// first value < 0 identifies a negative score as the first action
|
||||
entry.scoreDirection = entry.value >= 0 ? 'up' : 'down';
|
||||
} else {
|
||||
// could be missing if the previous entry was null and thus excluded
|
||||
const previousEntry = habit.history[index - 1];
|
||||
const previousValue = previousEntry.value;
|
||||
|
||||
entry.scoreDirection = entry.value > previousValue ? 'up' : 'down';
|
||||
}
|
||||
})
|
||||
.groupBy(entry => { // group entries by aggregateBy
|
||||
const entryDate = moment(entry.date).zone(timezoneOffset || 0);
|
||||
if (entryDate.hour() < dayStart) entryDate.subtract(1, 'day');
|
||||
return entryDate.format('YYYYMMDD');
|
||||
})
|
||||
.toPairs() // [key, entry]
|
||||
.sortBy(([key]) => key) // sort by date
|
||||
.map(keyEntryPair => {
|
||||
const entries = keyEntryPair[1]; // 1 is entry, 0 is key
|
||||
let scoredUp = 0;
|
||||
let scoredDown = 0;
|
||||
|
||||
entries.forEach(entry => {
|
||||
if (entry.scoreDirection === 'up') {
|
||||
scoredUp += 1;
|
||||
} else {
|
||||
scoredDown += 1;
|
||||
}
|
||||
|
||||
// delete the unnecessary scoreDirection and scoreNotes prop
|
||||
delete entry.scoreDirection;
|
||||
delete entry.scoreNotes;
|
||||
});
|
||||
|
||||
return {
|
||||
date: Number(entries[entries.length - 1].date), // keep last value
|
||||
value: entries[entries.length - 1].value, // keep last value,
|
||||
scoredUp,
|
||||
scoredDown,
|
||||
};
|
||||
})
|
||||
.value();
|
||||
|
||||
return dbTasks.update({ _id: habit._id }, {
|
||||
$set: { history: habit.history },
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count += 1;
|
||||
|
||||
const { timezoneOffset } = user.preferences;
|
||||
const { dayStart } = user.preferences;
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
if (user._id === authorUuid) console.warn(`${authorName} being processed`);
|
||||
|
||||
return dbTasks.find({
|
||||
type: 'habit',
|
||||
userId: user._id,
|
||||
})
|
||||
.then(habits => Promise.all(habits.map(habit => updateHabit(habit, timezoneOffset, dayStart))))
|
||||
.then(() => dbUsers.update({ _id: user._id }, {
|
||||
$set: { migration: migrationName },
|
||||
}))
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
function displayData () {
|
||||
console.warn(`\n${count} tasks processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
export default processUsers;
|
||||
@@ -1,19 +1,18 @@
|
||||
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
/* let migrationName = 'tasks-set-everyX'; */
|
||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
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
|
||||
* Iterates over all tasks and sets invalid everyX values (less than 0 or more than 9999 or not an int) field to 0
|
||||
*/
|
||||
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true';
|
||||
const 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) {
|
||||
// specify a query to limit the affected tasks (empty for all tasks):
|
||||
const query = {
|
||||
let query = {
|
||||
type: 'daily',
|
||||
everyX: {
|
||||
$not: {
|
||||
@@ -31,63 +30,64 @@ function processTasks (lastId) {
|
||||
}
|
||||
|
||||
dbTasks.find(query, {
|
||||
sort: { _id: 1 },
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
fields: [],
|
||||
})
|
||||
.then(updateTasks)
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateTasks (tasks) {
|
||||
if (!tasks || tasks.length === 0) {
|
||||
console.warn('All appropriate tasks found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const taskPromises = tasks.map(updatetask);
|
||||
const lasttask = tasks[tasks.length - 1];
|
||||
let taskPromises = tasks.map(updatetask);
|
||||
let lasttask = tasks[tasks.length - 1];
|
||||
|
||||
return Promise.all(taskPromises)
|
||||
.then(() => processTasks(lasttask._id));
|
||||
.then(() => {
|
||||
return processTasks(lasttask._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updatetask (task) {
|
||||
count += 1;
|
||||
const set = { everyX: 0 };
|
||||
count++;
|
||||
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`);
|
||||
console.warn(`\n${ count } tasks processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
export default processTasks;
|
||||
module.exports = processTasks;
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
/* let migrationName = 'tasks-set-yesterdaily'; */
|
||||
// ... own data is done
|
||||
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'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
import monk from 'monk';
|
||||
|
||||
const authorName = 'TheHollidayInn'; // in case script author needs to know when their ...
|
||||
const authorUuid = '';
|
||||
let connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
let dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
const dbTasks = monk(connectionString).get('tasks', { castIds: false });
|
||||
|
||||
const progressCount = 1000;
|
||||
let progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function exiting (code, msg) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
code = code || 0; // 0 = success
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
msg = 'ERROR!';
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
@@ -33,37 +30,39 @@ function exiting (code, msg) {
|
||||
}
|
||||
|
||||
function displayData () {
|
||||
console.warn(`\n${count} tasks processed\n`);
|
||||
console.warn(`\n${ count } tasks processed\n`);
|
||||
return exiting(0);
|
||||
}
|
||||
|
||||
function updatetask (task) {
|
||||
count += 1;
|
||||
const set = { yesterDaily: true };
|
||||
count++;
|
||||
let set = {yesterDaily: true};
|
||||
|
||||
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 updateTasks (tasks) {
|
||||
if (!tasks || tasks.length === 0) {
|
||||
console.warn('All appropriate tasks found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
const taskPromises = tasks.map(updatetask);
|
||||
const lasttask = tasks[tasks.length - 1];
|
||||
let taskPromises = tasks.map(updatetask);
|
||||
let lasttask = tasks[tasks.length - 1];
|
||||
|
||||
return Promise.all(taskPromises)
|
||||
.then(() => processTasks(lasttask._id)); // eslint-disable-line no-use-before-define
|
||||
.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):
|
||||
const query = {
|
||||
let query = {
|
||||
yesterDaily: false,
|
||||
};
|
||||
|
||||
@@ -74,18 +73,16 @@ function processTasks (lastId) {
|
||||
}
|
||||
|
||||
dbTasks.find(query, {
|
||||
sort: { _id: 1 },
|
||||
sort: {_id: 1},
|
||||
limit: 250,
|
||||
// specify fields we are interested in to limit retrieved data
|
||||
// (empty if we're not reading data):
|
||||
fields: [
|
||||
fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||
],
|
||||
})
|
||||
.then(updateTasks)
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
return exiting(1, `ERROR! ${ err}`);
|
||||
});
|
||||
}
|
||||
|
||||
export default processTasks;
|
||||
module.exports = processTasks;
|
||||
|
||||
@@ -8,30 +8,29 @@ let authorUuid = ''; // ... own data is done
|
||||
* This migraition will copy user data from prod to test
|
||||
*/
|
||||
|
||||
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const monk = require('monk');
|
||||
const connectionString = '';
|
||||
const Users = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
export default async function accountTransfer () {
|
||||
module.exports = async function accountTransfer () {
|
||||
const fromAccountId = '';
|
||||
const toAccountId = '';
|
||||
|
||||
const fromAccount = await Users.findOne({ _id: fromAccountId });
|
||||
const toAccount = await Users.findOne({ _id: toAccountId });
|
||||
const fromAccount = await Users.findOne({_id: fromAccountId});
|
||||
const toAccount = await Users.findOne({_id: toAccountId});
|
||||
|
||||
const newMounts = { ...fromAccount.items.mounts, ...toAccount.items.mounts };
|
||||
const newPets = { ...fromAccount.items.pets, ...toAccount.items.pets };
|
||||
const newBackgrounds = { ...fromAccount.purchased.background, ...toAccount.purchased.background };
|
||||
const newMounts = Object.assign({}, fromAccount.items.mounts, toAccount.items.mounts);
|
||||
const newPets = Object.assign({}, fromAccount.items.pets, toAccount.items.pets);
|
||||
const newBackgrounds = Object.assign({}, fromAccount.purchased.background, toAccount.purchased.background);
|
||||
|
||||
await Users.update({ _id: toAccountId }, {
|
||||
await Users.update({_id: toAccountId}, {
|
||||
$set: {
|
||||
'items.pets': newPets,
|
||||
'items.mounts': newMounts,
|
||||
'purchased.background': newBackgrounds,
|
||||
},
|
||||
})
|
||||
.then(result => {
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,8 +8,7 @@ const authorUuid = ''; // ... own data is done
|
||||
* This migraition will copy user data from prod to test
|
||||
*/
|
||||
|
||||
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const monk = require('monk');
|
||||
const connectionString = 'mongodb://localhost/new-habit';
|
||||
const Users = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
@@ -20,17 +19,15 @@ function getAchievementUpdate (newUser, oldUser) {
|
||||
const oldAchievements = oldUser.achievements;
|
||||
const newAchievements = newUser.achievements;
|
||||
|
||||
const achievementsUpdate = { ...newAchievements };
|
||||
let achievementsUpdate = Object.assign({}, newAchievements);
|
||||
|
||||
// ultimateGearSets
|
||||
if (!achievementsUpdate.ultimateGearSets && oldAchievements.ultimateGearSets) {
|
||||
achievementsUpdate.ultimateGearSets = oldAchievements.ultimateGearSets;
|
||||
} else if (oldAchievements.ultimateGearSets) {
|
||||
Object.keys(oldAchievements.ultimateGearSets).forEach(index => {
|
||||
if (oldAchievements.ultimateGearSets[index]) {
|
||||
achievementsUpdate.ultimateGearSets[index] = true;
|
||||
}
|
||||
});
|
||||
for (let index in oldAchievements.ultimateGearSets) {
|
||||
if (oldAchievements.ultimateGearSets[index]) achievementsUpdate.ultimateGearSets[index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// challenges
|
||||
@@ -40,57 +37,57 @@ function getAchievementUpdate (newUser, oldUser) {
|
||||
|
||||
// Quests
|
||||
if (!achievementsUpdate.quests) achievementsUpdate.quests = {};
|
||||
Object.keys(oldAchievements.quests).forEach(index => {
|
||||
for (let index in oldAchievements.quests) {
|
||||
if (!achievementsUpdate.quests[index]) {
|
||||
achievementsUpdate.quests[index] = oldAchievements.quests[index];
|
||||
} else {
|
||||
achievementsUpdate.quests[index] += oldAchievements.quests[index];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Rebirth level
|
||||
if (achievementsUpdate.rebirthLevel) {
|
||||
achievementsUpdate.rebirthLevel = Math.max(
|
||||
achievementsUpdate.rebirthLevel, oldAchievements.rebirthLevel,
|
||||
);
|
||||
achievementsUpdate.rebirthLevel = Math.max(achievementsUpdate.rebirthLevel, oldAchievements.rebirthLevel);
|
||||
} else if (oldAchievements.rebirthLevel) {
|
||||
achievementsUpdate.rebirthLevel = oldAchievements.rebirthLevel;
|
||||
}
|
||||
|
||||
// All others
|
||||
const indexsToIgnore = ['ultimateGearSets', 'challenges', 'quests', 'rebirthLevel'];
|
||||
Object.keys(oldAchievements).forEach(index => {
|
||||
if (indexsToIgnore.indexOf(index) !== -1) return;
|
||||
for (let index in oldAchievements) {
|
||||
if (indexsToIgnore.indexOf(index) !== -1) continue; // eslint-disable-line no-continue
|
||||
|
||||
if (!achievementsUpdate[index]) {
|
||||
if (!achievementsUpdate[index]) {
|
||||
achievementsUpdate[index] = oldAchievements[index];
|
||||
return;
|
||||
continue; // eslint-disable-line no-continue
|
||||
}
|
||||
|
||||
if (Number.isInteger(oldAchievements[index])) {
|
||||
achievementsUpdate[index] += oldAchievements[index];
|
||||
} else if (oldAchievements[index] === true) achievementsUpdate[index] = true;
|
||||
});
|
||||
}
|
||||
|
||||
return achievementsUpdate;
|
||||
}
|
||||
|
||||
export default async function achievementRestore () {
|
||||
module.exports = async function achievementRestore () {
|
||||
const userIds = [
|
||||
];
|
||||
|
||||
await Promise.all(userIds.map(userId => (async () => {
|
||||
const oldUser = await UsersOld.findOne({ _id: userId }, 'achievements');
|
||||
const newUser = await Users.findOne({ _id: userId }, 'achievements');
|
||||
/* eslint-disable no-await-in-loop */
|
||||
for (let index in userIds) {
|
||||
const userId = userIds[index];
|
||||
const oldUser = await UsersOld.findOne({_id: userId}, 'achievements');
|
||||
const newUser = await Users.findOne({_id: userId}, 'achievements');
|
||||
const achievementUpdate = getAchievementUpdate(newUser, oldUser);
|
||||
await Users.update(
|
||||
{ _id: userId },
|
||||
{_id: userId},
|
||||
{
|
||||
$set: {
|
||||
achievements: achievementUpdate,
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
console.log(`Updated ${userId}`);
|
||||
})()));
|
||||
}
|
||||
/* eslint-enable no-await-in-loop */
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
import moment from 'moment';
|
||||
import nconf from 'nconf';
|
||||
import { sendTxn } from '../../website/server/libs/email';
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const BASE_URL = nconf.get('BASE_URL');
|
||||
const EMAIL_SLUG = 'mandrill-email-slug'; // Set email template to send
|
||||
const MIGRATION_NAME = 'bulk-email';
|
||||
|
||||
const progressCount = 250;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count += 1;
|
||||
|
||||
if (count % progressCount === 0) {
|
||||
console.warn(`${count} ${user._id}`);
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
}
|
||||
|
||||
await sendTxn(
|
||||
user,
|
||||
EMAIL_SLUG,
|
||||
[{ name: 'BASE_URL', content: BASE_URL }], // Add variables from template
|
||||
);
|
||||
|
||||
return User.update({ _id: user._id }, { $set: { migration: MIGRATION_NAME } }).exec();
|
||||
}
|
||||
|
||||
export default async function processUsers () {
|
||||
const query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: moment().subtract(2, 'weeks').toDate() }, // customize or remove to target different populations
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
auth: 1,
|
||||
preferences: 1,
|
||||
profile: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({ _id: 1 })
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
}
|
||||
@@ -1,85 +1,117 @@
|
||||
/* eslint-disable no-console */
|
||||
import each from 'lodash/each';
|
||||
import keys from 'lodash/keys';
|
||||
import content from '../../website/common/script/content/index';
|
||||
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const MIGRATION_NAME = 'full-stable';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
const migrationName = 'full-stable.js';
|
||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Award users every extant pet and mount
|
||||
*/
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
|
||||
async function updateUser (user) {
|
||||
count += 1;
|
||||
let monk = require('monk');
|
||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
const set = {};
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
each(keys(content.pets), pet => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.premiumPets), pet => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.questPets), pet => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.specialPets), pet => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.mounts), mount => {
|
||||
set[`items.mounts.${mount}`] = true;
|
||||
});
|
||||
each(keys(content.premiumMounts), mount => {
|
||||
set[`items.mounts.${mount}`] = true;
|
||||
});
|
||||
each(keys(content.questMounts), mount => {
|
||||
set[`items.mounts.${mount}`] = true;
|
||||
});
|
||||
each(keys(content.specialMounts), mount => {
|
||||
set[`items.mounts.${mount}`] = true;
|
||||
});
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
return User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
export default async function processUsers () {
|
||||
const query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.local.username': 'olson22',
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
'profile.name': 'SabreCat',
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({ _id: 1 })
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
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((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(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
let set = {
|
||||
migration: migrationName,
|
||||
};
|
||||
|
||||
each(keys(content.pets), (pet) => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.premiumPets), (pet) => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.questPets), (pet) => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.specialPets), (pet) => {
|
||||
set[`items.pets.${pet}`] = 5;
|
||||
});
|
||||
each(keys(content.mounts), (mount) => {
|
||||
set[`items.mounts.${mount}`] = true;
|
||||
});
|
||||
each(keys(content.premiumMounts), (mount) => {
|
||||
set[`items.mounts.${mount}`] = true;
|
||||
});
|
||||
each(keys(content.questMounts), (mount) => {
|
||||
set[`items.mounts.${mount}`] = true;
|
||||
});
|
||||
each(keys(content.specialMounts), (mount) => {
|
||||
set[`items.mounts.${mount}`] = 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;
|
||||
|
||||
108
migrations/users/mystery-items.js
Normal file
108
migrations/users/mystery-items.js
Normal file
@@ -0,0 +1,108 @@
|
||||
const migrationName = 'mystery-items-201802.js'; // Update per month
|
||||
const authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||
const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Award this month's mystery items to subscribers
|
||||
*/
|
||||
const MYSTERY_ITEMS = ['back_mystery_201804', 'headAccessory_mystery_201804'];
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
|
||||
let monk = require('monk');
|
||||
let dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
let UserNotification = require('../../website/server/models/userNotification').model;
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
let query = {
|
||||
migration: {$ne: migrationName},
|
||||
'purchased.plan.customerId': { $ne: null },
|
||||
$or: [
|
||||
{ 'purchased.plan.dateTerminated': { $gte: new Date() } },
|
||||
{ 'purchased.plan.dateTerminated': { $exists: false } },
|
||||
{ 'purchased.plan.dateTerminated': { $eq: null } },
|
||||
],
|
||||
};
|
||||
|
||||
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((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(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count++;
|
||||
|
||||
const addToSet = {
|
||||
'purchased.plan.mysteryItems': {
|
||||
$each: MYSTERY_ITEMS,
|
||||
},
|
||||
};
|
||||
const push = {
|
||||
notifications: (new UserNotification({
|
||||
type: 'NEW_MYSTERY_ITEMS',
|
||||
data: {
|
||||
MYSTERY_ITEMS,
|
||||
},
|
||||
})).toJSON(),
|
||||
};
|
||||
|
||||
dbUsers.update({_id: user._id}, {$addToSet: addToSet, $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;
|
||||
@@ -1,86 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const MIGRATION_NAME = '20200314_pi_day';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count *= 1;
|
||||
|
||||
const inc = {
|
||||
'items.food.Pie_Skeleton': 1,
|
||||
'items.food.Pie_Base': 1,
|
||||
'items.food.Pie_CottonCandyBlue': 1,
|
||||
'items.food.Pie_CottonCandyPink': 1,
|
||||
'items.food.Pie_Shade': 1,
|
||||
'items.food.Pie_White': 1,
|
||||
'items.food.Pie_Golden': 1,
|
||||
'items.food.Pie_Zombie': 1,
|
||||
'items.food.Pie_Desert': 1,
|
||||
'items.food.Pie_Red': 1,
|
||||
};
|
||||
const set = {};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.head_special_piDay !== 'undefined') {
|
||||
push = false;
|
||||
} else {
|
||||
set['items.gear.owned.head_special_piDay'] = false;
|
||||
set['items.gear.owned.shield_special_piDay'] = false;
|
||||
push = [
|
||||
{ type: 'marketGear', path: 'gear.flat.head_special_piDay', _id: uuid() },
|
||||
{ type: 'marketGear', path: 'gear.flat.shield_special_piDay', _id: uuid() },
|
||||
];
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
if (push) {
|
||||
return User
|
||||
.update({ _id: user._id }, { $inc: inc, $set: set, $push: { pinnedItems: { $each: push } } })
|
||||
.exec();
|
||||
}
|
||||
return User
|
||||
.update({ _id: user._id }, { $inc: inc, $set: set })
|
||||
.exec();
|
||||
}
|
||||
|
||||
export default async function processUsers () {
|
||||
const query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
'auth.timestamps.loggedin': { $gt: new Date('2020-02-15') },
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({ _id: 1 })
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
import monk from 'monk'; // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const migrationName = 'remove-social-users-extra-data.js';
|
||||
const authorName = 'paglias'; // in case script author needs to know when their ...
|
||||
const authorUuid = 'ed4c688c-6652-4a92-9d03-a5a79844174a'; // ... own data is done
|
||||
|
||||
/*
|
||||
* Remove not needed data from social profiles
|
||||
*/
|
||||
const connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||
|
||||
|
||||
const dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||
|
||||
function processUsers (lastId) {
|
||||
// specify a query to limit the affected users (empty for all users):
|
||||
const query = {
|
||||
migration: { $ne: migrationName },
|
||||
$or: [
|
||||
{ 'auth.facebook.id': { $exists: true } },
|
||||
{ 'auth.google.id': { $exists: true } },
|
||||
],
|
||||
};
|
||||
|
||||
if (lastId) {
|
||||
query._id = {
|
||||
$gt: lastId,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.find(query, {
|
||||
sort: { _id: 1 },
|
||||
limit: 250,
|
||||
})
|
||||
.then(updateUsers)
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
return exiting(1, `ERROR! ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
function updateUsers (users) {
|
||||
if (!users || users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
displayData();
|
||||
return null;
|
||||
}
|
||||
|
||||
const userPromises = users.map(updateUser);
|
||||
const lastUser = users[users.length - 1];
|
||||
|
||||
return Promise.all(userPromises)
|
||||
.then(() => {
|
||||
processUsers(lastUser._id);
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser (user) {
|
||||
count *= 1;
|
||||
|
||||
const isFacebook = user.auth.facebook && user.auth.facebook.id;
|
||||
const isGoogle = user.auth.google && user.auth.google.id;
|
||||
|
||||
const update = { $set: {} };
|
||||
|
||||
if (isFacebook) {
|
||||
update.$set['auth.facebook'] = {
|
||||
id: user.auth.facebook.id,
|
||||
emails: user.auth.facebook.emails,
|
||||
};
|
||||
}
|
||||
|
||||
if (isGoogle) {
|
||||
update.$set['auth.google'] = {
|
||||
id: user.auth.google.id,
|
||||
emails: user.auth.google.emails,
|
||||
};
|
||||
}
|
||||
|
||||
dbUsers.update({
|
||||
_id: user._id,
|
||||
}, update);
|
||||
|
||||
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) {
|
||||
// 0 = success
|
||||
code = code || 0; // eslint-disable-line no-param-reassign
|
||||
if (code && !msg) {
|
||||
msg = 'ERROR!'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
if (msg) {
|
||||
if (code) {
|
||||
console.error(msg);
|
||||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
export default processUsers;
|
||||
@@ -1,81 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { model as User } from '../../website/server/models/user';
|
||||
|
||||
const MIGRATION_NAME = '20181203_take_this';
|
||||
|
||||
const progressCount = 1000;
|
||||
let count = 0;
|
||||
|
||||
async function updateUser (user) {
|
||||
count += 1;
|
||||
|
||||
const set = {};
|
||||
let push;
|
||||
|
||||
set.migration = MIGRATION_NAME;
|
||||
|
||||
if (typeof user.items.gear.owned.back_special_takeThis !== 'undefined') {
|
||||
push = false;
|
||||
} else if (typeof user.items.gear.owned.body_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.back_special_takeThis'] = false;
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.back_special_takeThis', _id: uuid() } };
|
||||
} else if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.body_special_takeThis'] = false;
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.body_special_takeThis', _id: uuid() } };
|
||||
} else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.head_special_takeThis'] = false;
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.head_special_takeThis', _id: uuid() } };
|
||||
} else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.armor_special_takeThis'] = false;
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.armor_special_takeThis', _id: uuid() } };
|
||||
} else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') {
|
||||
set['items.gear.owned.weapon_special_takeThis'] = false;
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.weapon_special_takeThis', _id: uuid() } };
|
||||
} else {
|
||||
set['items.gear.owned.shield_special_takeThis'] = false;
|
||||
push = { pinnedItems: { type: 'marketGear', path: 'gear.flat.shield_special_takeThis', _id: uuid() } };
|
||||
}
|
||||
|
||||
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
|
||||
|
||||
if (push) {
|
||||
return User.update({ _id: user._id }, { $set: set, $push: push }).exec();
|
||||
}
|
||||
return User.update({ _id: user._id }, { $set: set }).exec();
|
||||
}
|
||||
|
||||
export default async function processUsers () {
|
||||
const query = {
|
||||
migration: { $ne: MIGRATION_NAME },
|
||||
challenges: '00708425-d477-41a5-bf27-6270466e7976',
|
||||
};
|
||||
|
||||
const fields = {
|
||||
_id: 1,
|
||||
items: 1,
|
||||
};
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const users = await User // eslint-disable-line no-await-in-loop
|
||||
.find(query)
|
||||
.limit(250)
|
||||
.sort({ _id: 1 })
|
||||
.select(fields)
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
if (users.length === 0) {
|
||||
console.warn('All appropriate users found and modified.');
|
||||
console.warn(`\n${count} users processed\n`);
|
||||
break;
|
||||
} else {
|
||||
query._id = {
|
||||
$gt: users[users.length - 1],
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
/*
|
||||
let migrationName = 'UserFromProdToTest';
|
||||
let authorName = 'TheHollidayInn'; // in case script author needs to know when their ...
|
||||
@@ -9,24 +8,22 @@ let authorUuid = ''; // ... own data is done
|
||||
* This migraition will copy user data from prod to test
|
||||
*/
|
||||
|
||||
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 });
|
||||
|
||||
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';
|
||||
|
||||
const monk = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const testConnectionSting = ''; // FOR TEST DATABASE
|
||||
const usersTest = monk(testConnectionSting).get('users', { castIds: false });
|
||||
const groupsTest = monk(testConnectionSting).get('groups', { castIds: false });
|
||||
const challengesTest = monk(testConnectionSting).get('challenges', { castIds: false });
|
||||
const tasksTest = monk(testConnectionSting).get('tasks', { castIds: false });
|
||||
|
||||
const monk2 = require('monk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
|
||||
const liveConnectString = ''; // FOR TEST DATABASE
|
||||
const userLive = monk2(liveConnectString).get('users', { castIds: false });
|
||||
const groupsLive = monk2(liveConnectString).get('groups', { castIds: false });
|
||||
const challengesLive = monk2(liveConnectString).get('challenges', { castIds: false });
|
||||
const tasksLive = monk2(liveConnectString).get('tasks', { castIds: false });
|
||||
|
||||
// Variabls for updating
|
||||
/*
|
||||
let userIds = [
|
||||
@@ -39,11 +36,11 @@ let challengeIds = [];
|
||||
let tasksIds = [];
|
||||
|
||||
async function processUsers () {
|
||||
const userPromises = [];
|
||||
let userPromises = [];
|
||||
// {_id: {$in: userIds}}
|
||||
|
||||
return userLive.find({ guilds: 'b0764d64-8276-45a1-afa5-5ca9a5c64ca0' })
|
||||
.each(user => {
|
||||
return userLive.find({guilds: 'b0764d64-8276-45a1-afa5-5ca9a5c64ca0'})
|
||||
.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);
|
||||
@@ -52,56 +49,64 @@ 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);
|
||||
|
||||
const userPromise = usersTest.update({ _id: user._id }, user, { upsert: true });
|
||||
let userPromise = usersTest.update({_id: user._id}, user, {upsert: true});
|
||||
userPromises.push(userPromise);
|
||||
}).then(() => Promise.all(userPromises))
|
||||
}).then(() => {
|
||||
return Promise.all(userPromises);
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Done User');
|
||||
});
|
||||
}
|
||||
|
||||
function processGroups () {
|
||||
const promises = [];
|
||||
const groupsToQuery = uniq(groupIds);
|
||||
return groupsLive.find({ _id: { $in: groupsToQuery } })
|
||||
.each(group => {
|
||||
const promise = groupsTest.update({ _id: group._id }, group, { upsert: true });
|
||||
let promises = [];
|
||||
let groupsToQuery = uniq(groupIds);
|
||||
return groupsLive.find({_id: {$in: groupsToQuery}})
|
||||
.each((group) => {
|
||||
let promise = groupsTest.update({_id: group._id}, group, {upsert: true});
|
||||
promises.push(promise);
|
||||
}).then(() => Promise.all(promises))
|
||||
}).then(() => {
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Done Group');
|
||||
});
|
||||
}
|
||||
|
||||
function processChallenges () {
|
||||
const promises = [];
|
||||
const challengesToQuery = uniq(challengeIds);
|
||||
return challengesLive.find({ _id: { $in: challengesToQuery } })
|
||||
.each(challenge => {
|
||||
const promise = challengesTest.update({ _id: challenge._id }, challenge, { upsert: true });
|
||||
let promises = [];
|
||||
let challengesToQuery = uniq(challengeIds);
|
||||
return challengesLive.find({_id: {$in: challengesToQuery}})
|
||||
.each((challenge) => {
|
||||
let promise = challengesTest.update({_id: challenge._id}, challenge, {upsert: true});
|
||||
promises.push(promise);
|
||||
}).then(() => Promise.all(promises))
|
||||
}).then(() => {
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Done Challenge');
|
||||
});
|
||||
}
|
||||
|
||||
function processTasks () {
|
||||
const promises = [];
|
||||
const tasksToQuery = uniq(tasksIds);
|
||||
return tasksLive.find({ _id: { $in: tasksToQuery } })
|
||||
.each(task => {
|
||||
const promise = tasksTest.update({ _id: task._id }, task, { upsert: true });
|
||||
let promises = [];
|
||||
let tasksToQuery = uniq(tasksIds);
|
||||
return tasksLive.find({_id: {$in: tasksToQuery}})
|
||||
.each((task) => {
|
||||
let promise = tasksTest.update({_id: task._id}, task, {upsert: true});
|
||||
promises.push(promise);
|
||||
}).then(() => Promise.all(promises))
|
||||
}).then(() => {
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Done Tasks');
|
||||
});
|
||||
}
|
||||
|
||||
export default async function prodToTest () {
|
||||
module.exports = async function prodToTest () {
|
||||
await processUsers();
|
||||
await processGroups();
|
||||
await processChallenges();
|
||||
await processTasks();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
const { MongoClient } = require('mongodb'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
'use strict';
|
||||
|
||||
const MongoClient = require('mongodb').MongoClient;
|
||||
const logger = require('./logger');
|
||||
|
||||
let dbConnection;
|
||||
@@ -16,7 +17,7 @@ function connectToDb (dbUri) {
|
||||
|
||||
logger.success(`Connected to ${dbUri}`);
|
||||
|
||||
return resolve(database);
|
||||
resolve(database);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/* eslint-disable import/no-commonjs */
|
||||
const chalk = require('chalk'); // eslint-disable-line import/no-extraneous-dependencies
|
||||
'use strict';
|
||||
|
||||
const chalk = require('chalk');
|
||||
|
||||
function loggerGenerator (type, color) {
|
||||
return function logger () {
|
||||
const args = Array
|
||||
.from(arguments) // eslint-disable-line prefer-rest-params
|
||||
.map(arg => chalk[color](arg));
|
||||
let args = Array.from(arguments).map(arg => chalk[color](arg));
|
||||
console[type].apply(null, args);
|
||||
};
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user