diff --git a/package-lock.json b/package-lock.json index a4e493203f..ba6e742da1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "habitica", - "version": "4.134.0", + "version": "4.134.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1849,9 +1849,9 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "aws-sdk": { - "version": "2.619.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.619.0.tgz", - "integrity": "sha512-qujQf27p3mrGZGCL+C+vXCEB08AMm6gS1572fgHrVLBXfy6SjhV4dzEYtt+ZptQm+8z0zuHsDqghJuBCcdpxqQ==", + "version": "2.624.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.624.0.tgz", + "integrity": "sha512-6MhbdND7A5lEBiNSZ/HLwhKgrysmwTy6C47H7vfuVnY25hDkIND3C0PLqeRyskUqxv0RqsiAB4kqiMtpE08IGA==", "requires": { "buffer": "4.9.1", "events": "1.1.1", @@ -3962,6 +3962,11 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -9132,6 +9137,7 @@ "version": "3.4.1", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.4.1.tgz", "integrity": "sha512-juqt5/Z42J4DcE7tG7UdVaTKmUC6zinF4yioPfpeOSNBieWSK6qCY+0tfGQcHLKrauWPDdMZVROHJOa8q2pWsA==", + "dev": true, "requires": { "bson": "^1.1.1", "require_optional": "^1.0.1", @@ -9140,13 +9146,13 @@ } }, "mongoose": { - "version": "5.8.11", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.8.11.tgz", - "integrity": "sha512-Yz0leNEJsAtNtMTxTDEadacLWt58gaVeBVL3c1Z3vaBoc159aJqlf+T8jaL9mAdBxKndF5YWhh6Q719xac7cjA==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.2.tgz", + "integrity": "sha512-Sa1qfqBvUfAgsrXpZjbBoIx8PEDUJSKF5Ous8gnBFI7TPiueSgJjg6GRA7A0teU8AB/vd0h8rl1rD5RQNfWhIw==", "requires": { "bson": "~1.1.1", "kareem": "2.3.1", - "mongodb": "3.4.1", + "mongodb": "3.5.3", "mongoose-legacy-pluralize": "1.0.2", "mpath": "0.6.0", "mquery": "3.2.2", @@ -9155,6 +9161,30 @@ "safe-buffer": "5.1.2", "sift": "7.0.1", "sliced": "1.0.1" + }, + "dependencies": { + "bl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", + "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "mongodb": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.3.tgz", + "integrity": "sha512-II7P7A3XUdPiXRgcN96qIoRa1oesM6qLNZkzfPluNZjVkgQk3jnQwOT6/uDk4USRDTTLjNFw2vwfmbRGTA7msg==", + "requires": { + "bl": "^2.2.0", + "bson": "^1.1.1", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + } } }, "mongoose-legacy-pluralize": { @@ -11560,9 +11590,9 @@ } }, "sinon-chai": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.4.0.tgz", - "integrity": "sha512-BpVxsjEkGi6XPbDXrgWUe7Cb1ZzIfxKUbu/MmH5RoUnS7AXpKo3aIYIyQUg0FMvlUL05aPt7VZuAdaeQhEnWxg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.5.0.tgz", + "integrity": "sha512-IifbusYiQBpUxxFJkR3wTU68xzBN0+bxCScEaKMjBvAQERg6FnTTc1F17rseLb1tjmkJ23730AXpFI0c47FgAg==", "dev": true }, "sinon-stub-promise": { @@ -12204,9 +12234,9 @@ "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" }, "superagent": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.2.1.tgz", - "integrity": "sha512-46b4Lkwnlz7Ebdv2FBbfuqb3kVkG1jV/SK3EW6NnwL9a3T4h5hHtegNEQfbXvTFbDoUZXId4W3dMgap2f6ic1g==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.2.2.tgz", + "integrity": "sha512-pMWBUnIllK4ZTw7p/UaobiQPwAO5w/1NRRTDpV0FTVNmECztsxKspj3ZWEordVEaqpZtmOQJJna4yTLyC/q7PQ==", "requires": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.2", @@ -12237,9 +12267,9 @@ "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==" }, "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", diff --git a/package.json b/package.json index c71a8ad898..ae790537f7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "habitica", "description": "A habit tracker app which treats your goals like a Role Playing Game.", - "version": "4.134.0", + "version": "4.134.2", "main": "./website/server/index.js", "dependencies": { "@babel/core": "^7.8.4", @@ -14,7 +14,7 @@ "amplitude": "^3.5.0", "apidoc": "^0.17.5", "apn": "^2.2.0", - "aws-sdk": "^2.619.0", + "aws-sdk": "^2.624.0", "bcrypt": "^3.0.8", "body-parser": "^1.18.3", "compression": "^1.7.4", @@ -46,7 +46,7 @@ "method-override": "^3.0.0", "moment": "^2.24.0", "moment-recur": "^1.0.7", - "mongoose": "^5.8.11", + "mongoose": "^5.9.2", "morgan": "^1.7.0", "nconf": "^0.10.0", "node-gcm": "^1.0.2", @@ -63,7 +63,7 @@ "rimraf": "^3.0.2", "short-uuid": "^3.0.0", "stripe": "^7.15.0", - "superagent": "^5.2.1", + "superagent": "^5.2.2", "universal-analytics": "^0.4.17", "useragent": "^2.1.9", "uuid": "^3.4.0", @@ -113,7 +113,7 @@ "monk": "^7.1.2", "require-again": "^2.0.0", "sinon": "^7.2.4", - "sinon-chai": "^3.4.0", + "sinon-chai": "^3.5.0", "sinon-stub-promise": "^4.0.0" }, "optionalDependencies": {} diff --git a/website/client/package-lock.json b/website/client/package-lock.json index feae651180..f43795c3f7 100644 --- a/website/client/package-lock.json +++ b/website/client/package-lock.json @@ -7814,9 +7814,9 @@ "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==" }, "bootstrap-vue": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.4.2.tgz", - "integrity": "sha512-gtf0QwbtVyNrnXhL3eyrSrcW0/CVilEkOFddYaVAsJCIFMhUjurmzryw+Dh+fOzJmmKRqRxhkLUIGqlkwAcsbg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.5.0.tgz", + "integrity": "sha512-LixZePxJqIkwsha2WAjAu7ZDH+oJ+JLxPGsl1SIbWebcEYZ+QtGx4JM2nR287t/0uWYGO+/oJ0KlaSO662VtLA==", "requires": { "@nuxt/opencollective": "^0.3.0", "bootstrap": ">=4.4.1 <5.0.0", @@ -10556,9 +10556,9 @@ } }, "eslint-plugin-vue": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-6.2.0.tgz", - "integrity": "sha512-6AnZKycVWbwQtL/RyX77Rytm9r16bfYsd5oy65eoSkNFzWQ5qAisdmqUG08v1InTmAh6mbR24X1HMEvoI24wGQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-6.2.1.tgz", + "integrity": "sha512-MiIDOotoWseIfLIfGeDzF6sDvHkVvGd2JgkvjyHtN3q4RoxdAXrAMuI3SXTOKatljgacKwpNAYShmcKZa4yZzw==", "requires": { "natural-compare": "^1.4.0", "semver": "^5.6.0", @@ -11253,9 +11253,9 @@ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, "fp-ts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.4.2.tgz", - "integrity": "sha512-/6dNmbu2CRhwR+/OpjLYT3OAlIlyrnY1qjbGDeyYkisTqQfbIdWL1P4sn28yKhcBLcfIvjo9614sfo0EKscOMA==" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.5.1.tgz", + "integrity": "sha512-IjePHUJwegS9h7+cRCywoL/Nfha3UnMd3VHVg4gycv69nAQPOJ3b/XnjtF5ggTBF4gjLZcNaHjZEYOsRcDeGaA==" }, "fragment-cache": { "version": "0.2.1", @@ -12819,9 +12819,9 @@ } }, "inspectpack": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/inspectpack/-/inspectpack-4.3.1.tgz", - "integrity": "sha512-EF8MsrIxEmjG6uuo3bKIAzAaRDp1vq+gLG9oZ+D50kaQJnQOwwJp2MPvBk6GslUkIO64u524LwbzRv0AYd0qBQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/inspectpack/-/inspectpack-4.4.0.tgz", + "integrity": "sha512-V9vjuP5OqAk3jnCZ0M9TIhZlRNdd9v1fggwAHHOTYvxqFRkAtEbjj1dII6kpj6tN8+yHKBL5u9gf9Lp7GGOLHw==", "requires": { "chalk": "^3.0.0", "fp-ts": "^2.3.1", @@ -13126,9 +13126,9 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" }, "io-ts": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.0.6.tgz", - "integrity": "sha512-WNfGzm4csMVwL4hX6QlpQWu65SV6GmOUtDo259GKlLYH1cC5bpOENgYHqQIRJ9uR3FuU1RQKDke5STwHZAn3KA==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.1.1.tgz", + "integrity": "sha512-6mDCiTc/0uNtC8M1u/kcNiw5JUTlREFCGV7pjcbrQrUDguLkOpuzb4wbJcU78G74QvkhQdvT3F3dAupycXN95g==" }, "io-ts-reporters": { "version": "1.0.0", @@ -19049,36 +19049,13 @@ } }, "svg-inline-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.0.tgz", - "integrity": "sha512-rynplY2eXFrdNomL1FvyTFQlP+dx0WqbzHglmNtA9M4IHRC3no2aPAl3ny9lUpJzFzFMZfWRK5YIclNU+FRePA==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/svg-inline-loader/-/svg-inline-loader-0.8.2.tgz", + "integrity": "sha512-kbrcEh5n5JkypaSC152eGfGcnT4lkR0eSfvefaUJkLqgGjRQJyKDvvEE/CCv5aTSdfXuc+N98w16iAojhShI3g==", "requires": { - "loader-utils": "^0.2.11", + "loader-utils": "^1.1.0", "object-assign": "^4.0.1", "simple-html-tokenizer": "^0.1.1" - }, - "dependencies": { - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - } } }, "svg-tags": { diff --git a/website/client/package.json b/website/client/package.json index 51b414f325..272d968afb 100644 --- a/website/client/package.json +++ b/website/client/package.json @@ -29,16 +29,16 @@ "axios-progress-bar": "^1.2.0", "babel-eslint": "^10.0.1", "bootstrap": "^4.4.1", - "bootstrap-vue": "^2.4.2", + "bootstrap-vue": "^2.5.0", "chai": "^4.1.2", "core-js": "^3.6.4", "eslint": "^6.8.0", "eslint-config-habitrpg": "^6.2.0", "eslint-plugin-mocha": "^5.3.0", - "eslint-plugin-vue": "^6.2.0", + "eslint-plugin-vue": "^6.2.1", "habitica-markdown": "^1.3.2", "hellojs": "^1.18.4", - "inspectpack": "^4.3.1", + "inspectpack": "^4.4.0", "intro.js": "^2.9.3", "jquery": "^3.4.1", "lodash": "^4.17.15", @@ -47,7 +47,7 @@ "sass": "^1.25.0", "sass-loader": "^8.0.2", "smartbanner.js": "^1.15.0", - "svg-inline-loader": "^0.8.0", + "svg-inline-loader": "^0.8.2", "svg-url-loader": "^3.0.3", "svgo": "^1.3.2", "svgo-loader": "^2.2.1", diff --git a/website/client/src/assets/css/sprites/spritesmith-largeSprites-0.css b/website/client/src/assets/css/sprites/spritesmith-largeSprites-0.css index 883b955aa3..dc4bfe8272 100644 --- a/website/client/src/assets/css/sprites/spritesmith-largeSprites-0.css +++ b/website/client/src/assets/css/sprites/spritesmith-largeSprites-0.css @@ -1,42 +1,42 @@ .promo_achievement_CottonCandyPink { background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); - background-position: -328px -148px; + background-position: -668px -444px; width: 204px; height: 102px; } .promo_armoire_backgrounds_202002 { background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); - background-position: -328px 0px; + background-position: 0px -277px; width: 423px; height: 147px; } .promo_mystery_022020 { background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); - background-position: 0px -425px; + background-position: -668px -148px; width: 282px; height: 147px; } .promo_take_this { background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); - background-position: -283px -425px; + background-position: -873px -444px; width: 96px; height: 69px; } .promo_valentines_2020 { background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); - background-position: -421px -277px; + background-position: -668px 0px; width: 309px; height: 147px; } .promo_valentines_potions { background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); - background-position: 0px -277px; + background-position: 0px -425px; width: 420px; height: 147px; } .scene_cake { background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); - background-position: -533px -148px; + background-position: -424px -277px; width: 204px; height: 102px; } @@ -46,3 +46,15 @@ width: 327px; height: 276px; } +.scene_gaining_achievement { + background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); + background-position: -328px 0px; + width: 339px; + height: 210px; +} +.scene_shanaqui { + background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png'); + background-position: -668px -296px; + width: 282px; + height: 147px; +} diff --git a/website/client/src/assets/images/g1g1-notif.png b/website/client/src/assets/images/g1g1-notif.png index 398b4861f3..75633e6db2 100644 Binary files a/website/client/src/assets/images/g1g1-notif.png and b/website/client/src/assets/images/g1g1-notif.png differ diff --git a/website/client/src/assets/images/g1g1-send.png b/website/client/src/assets/images/g1g1-send.png index b92b753402..774be0b37a 100644 Binary files a/website/client/src/assets/images/g1g1-send.png and b/website/client/src/assets/images/g1g1-send.png differ diff --git a/website/client/src/assets/images/sprites/spritesmith-largeSprites-0.png b/website/client/src/assets/images/sprites/spritesmith-largeSprites-0.png index d96a792b6d..d0cff3807a 100644 Binary files a/website/client/src/assets/images/sprites/spritesmith-largeSprites-0.png and b/website/client/src/assets/images/sprites/spritesmith-largeSprites-0.png differ diff --git a/website/client/src/components/header/notifications/g1g1.vue b/website/client/src/components/header/notifications/g1g1.vue index 8149f0aac1..f49feca7fd 100644 --- a/website/client/src/components/header/notifications/g1g1.vue +++ b/website/client/src/components/header/notifications/g1g1.vue @@ -2,19 +2,38 @@
- {{ $t('g1g1Announcement') }} -

{{ $t('g1g1Details') }}

+ + {{ $t('g1g1Announcement') }} + +

+ {{ $t('g1g1Details') }} +

-
{{ $t('sendGift') }}
+
+ {{ $t('sendGift') }} +
-
+
diff --git a/website/client/src/components/payments/selectUserModal.vue b/website/client/src/components/payments/selectUserModal.vue index 77f76a6e8d..70f8407601 100644 --- a/website/client/src/components/payments/selectUserModal.vue +++ b/website/client/src/components/payments/selectUserModal.vue @@ -173,7 +173,6 @@ export default { methods: { close () { this.$root.$emit('habitica::dismiss-modal', 'select-user-modal'); - this.$root.$emit('bv::hide::modal', 'select-user-modal'); }, searchUser: debounce(async function userSearch (searchTerm) { this.foundUser = {}; diff --git a/website/client/src/components/payments/successModal.vue b/website/client/src/components/payments/successModal.vue index 8d33203d8d..965eddecb8 100644 --- a/website/client/src/components/payments/successModal.vue +++ b/website/client/src/components/payments/successModal.vue @@ -245,7 +245,6 @@ export default { close () { this.paymentData = {}; this.$root.$emit('habitica::dismiss-modal', 'payments-success-modal'); - this.$root.$emit('bv::hide::modal', 'payments-success-modal'); }, }, }; diff --git a/website/client/src/components/shops/quests/index.vue b/website/client/src/components/shops/quests/index.vue index 0612d29869..0dc12f46dc 100644 --- a/website/client/src/components/shops/quests/index.vue +++ b/website/client/src/components/shops/quests/index.vue @@ -209,7 +209,6 @@
diff --git a/website/client/src/store/actions/shops.js b/website/client/src/store/actions/shops.js index fea30216b8..52c2aea350 100644 --- a/website/client/src/store/actions/shops.js +++ b/website/client/src/store/actions/shops.js @@ -78,9 +78,8 @@ async function buyArmoire (store, params) { // @TODO: We might need to abstract notifications to library rather than mixin const notificationOptions = isExperience ? { - text: `+ ${item.value}`, - type: 'xp', - flavorMessage: message, + text: message, + type: 'success', } : { text: message, @@ -93,6 +92,10 @@ async function buyArmoire (store, params) { timeout: true, ...notificationOptions, }); + + if (isExperience) { + await store.dispatch('user:fetch', { forceLoad: true }); + } } } diff --git a/website/common/script/content/quests.js b/website/common/script/content/quests.js index 425c1656dd..0e552c87a9 100644 --- a/website/common/script/content/quests.js +++ b/website/common/script/content/quests.js @@ -1067,7 +1067,7 @@ const quests = { notes: t('questBasilistNotes'), group: 'questGroupEarnable', completion: t('questBasilistCompletion'), - value: 4, + goldValue: 100, category: 'unlockable', unlockCondition: { condition: 'party invite', @@ -2238,7 +2238,7 @@ const quests = { notes: t('questDustBunniesNotes'), group: 'questGroupEarnable', completion: t('questDustBunniesCompletion'), - value: 4, + value: 1, category: 'unlockable', unlockCondition: { condition: 'party invite', @@ -2262,7 +2262,7 @@ const quests = { value: 4, category: 'unlockable', unlockCondition: { - condition: 'party invite', + condition: 'login reward', incentiveThreshold: 7, text: t('loginReward', { count: 7 }), }, @@ -2293,7 +2293,7 @@ const quests = { value: 4, category: 'unlockable', unlockCondition: { - condition: 'party invite', + condition: 'login reward', incentiveThreshold: 22, text: t('loginReward', { count: 22 }), }, @@ -2323,7 +2323,7 @@ const quests = { value: 4, category: 'unlockable', unlockCondition: { - condition: 'party invite', + condition: 'login reward', incentiveThreshold: 40, text: t('loginReward', { count: 40 }), }, diff --git a/website/common/script/ops/buy/buyArmoire.js b/website/common/script/ops/buy/buyArmoire.js index fab02460d7..9a7f91e200 100644 --- a/website/common/script/ops/buy/buyArmoire.js +++ b/website/common/script/ops/buy/buyArmoire.js @@ -10,6 +10,7 @@ import { import randomVal, * as randomValFns from '../../libs/randomVal'; import { removeItemByPath } from '../pinnedGearUtils'; import { AbstractGoldItemOperation } from './abstractBuyOperation'; +import updateStats from '../../fns/updateStats'; // TODO this is only used on the server // move out of common? @@ -156,6 +157,7 @@ export class BuyArmoireOperation extends AbstractGoldItemOperation { // eslint-d _experienceResult (user) { const armoireExp = Math.floor(randomValFns.trueRandom() * 40 + 10); user.stats.exp += armoireExp; + updateStats(user, user.stats, this.req); return { message: this.i18n('armoireExp'), diff --git a/website/common/script/ops/buy/buyQuestGold.js b/website/common/script/ops/buy/buyQuestGold.js index a4f16d4bfd..10a0cfadcb 100644 --- a/website/common/script/ops/buy/buyQuestGold.js +++ b/website/common/script/ops/buy/buyQuestGold.js @@ -42,7 +42,7 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation { // es if (!item) throw new NotFound(errorMessage('questNotFound', { key })); - if (!(item.category === 'gold' && item.goldValue)) { + if (!(item.goldValue)) { throw new NotAuthorized(this.i18n('questNotGoldPurchasable', { key })); } diff --git a/website/raw_sprites/spritesmith_large/scene_gaining_achievement.png b/website/raw_sprites/spritesmith_large/scene_gaining_achievement.png new file mode 100644 index 0000000000..0c900350ca Binary files /dev/null and b/website/raw_sprites/spritesmith_large/scene_gaining_achievement.png differ diff --git a/website/raw_sprites/spritesmith_large/scene_shanaqui.png b/website/raw_sprites/spritesmith_large/scene_shanaqui.png new file mode 100644 index 0000000000..fe9d7035dc Binary files /dev/null and b/website/raw_sprites/spritesmith_large/scene_shanaqui.png differ diff --git a/website/server/controllers/api-v3/auth.js b/website/server/controllers/api-v3/auth.js index 745afb0750..9d1befafb8 100644 --- a/website/server/controllers/api-v3/auth.js +++ b/website/server/controllers/api-v3/auth.js @@ -29,7 +29,7 @@ const api = {}; /** * @api {post} /api/v3/user/auth/local/register Register * @apiDescription Register a new user with email, login name, and password or - * attach local auth to a social user + * attach local authentication to a social auth user * @apiName UserRegisterLocal * @apiGroup User * @@ -148,12 +148,14 @@ api.loginSocial = { /** * @api {put} /api/v3/user/auth/update-username Update username - * @apiDescription Update the username of a local user + * @apiDescription Update and verify the user's username * @apiName UpdateUsername * @apiGroup User * * @apiParam (Body) {String} username The new username - + * @apiParam (Body) {String} password The user's password if they use local authentication. + * Omit if they use social auth. + * * @apiSuccess {String} data.username The new username * */ api.updateUsername = { @@ -196,6 +198,8 @@ api.updateUsername = { // save username user.auth.local.lowerCaseUsername = newUsername.toLowerCase(); user.auth.local.username = newUsername; + + // reward user for verifying their username if (!user.flags.verifiedUsername) { user.flags.verifiedUsername = true; if (user.items.pets['Bear-Veteran']) { @@ -277,7 +281,7 @@ api.updatePassword = { }; /** - * @api {post} /api/v3/user/reset-password Reset password + * @api {post} /api/v3/user/reset-password Reset password (email a reset link) * @apiDescription Send the user an email to let them reset their password * @apiName ResetPassword * @apiGroup User @@ -371,7 +375,7 @@ api.updateEmail = { }; /** - * @api {post} /api/v3/user/auth/reset-password-set-new-one Reset Password Set New one + * @api {post} /api/v3/user/auth/reset-password-set-new-one Reset password (set a new one) * @apiDescription Set a new password for a user that reset theirs. Not meant for public usage. * @apiName ResetPasswordSetNewOne * @apiGroup User @@ -424,8 +428,8 @@ api.resetPasswordSetNewOne = { /** * @api {delete} /api/v3/user/auth/social/:network Delete social authentication method - * @apiDescription Remove a social authentication method (only facebook supported) - * from a user profile. The user must have local authentication enabled + * @apiDescription Remove a social authentication method from a user profile. + * The user must have another authentication method enabled. * @apiName UserDeleteSocial * @apiGroup User * diff --git a/website/server/controllers/api-v3/challenges.js b/website/server/controllers/api-v3/challenges.js index 00e283add7..a68e08ffa3 100644 --- a/website/server/controllers/api-v3/challenges.js +++ b/website/server/controllers/api-v3/challenges.js @@ -513,7 +513,7 @@ api.getGroupChallenges = { }; /** - * @api {get} /api/v3/challenges/:challengeId Get a challenge given its id + * @api {get} /api/v3/challenges/:challengeId Get a challenge * @apiName GetChallenge * @apiGroup Challenge * diff --git a/website/server/controllers/api-v3/cron.js b/website/server/controllers/api-v3/cron.js index 0016650bcf..bea3e41201 100644 --- a/website/server/controllers/api-v3/cron.js +++ b/website/server/controllers/api-v3/cron.js @@ -4,8 +4,11 @@ import cron from '../../middlewares/cron'; const api = {}; /** - * @api {post} /api/v3/cron Runs cron + * @api {post} /api/v3/cron Run cron * @apiName Cron + * @apiDescription This causes cron to run. It assumes that the user has already been shown + * the Record Yesterday's Activity ("Check off any Dailies you did yesterday") screen and + * so it will immediately apply damage for incomplete due Dailies. * @apiGroup Cron * * @apiSuccess {Object} data An empty Object diff --git a/website/server/controllers/api-v3/hall.js b/website/server/controllers/api-v3/hall.js index 8e28fbc17a..81b6c97999 100644 --- a/website/server/controllers/api-v3/hall.js +++ b/website/server/controllers/api-v3/hall.js @@ -93,7 +93,7 @@ api.getPatrons = { }; /** - * @api {get} /api/v3/hall/heroes Get all Heroes + * @api {get} /api/v3/hall/heroes Get all Heroes (contributors) * @apiName GetHeroes * @apiGroup Hall * @@ -154,7 +154,7 @@ const heroAdminFields = 'contributor balance profile.name purchased items auth f * @apiGroup Hall * @apiPermission Admin * - * @apiDescription Returns the profile of the given user + * @apiDescription Returns the profile of the given user. User does not need to be a contributor. * * @apiSuccess {Object} data The user object * @@ -208,9 +208,9 @@ const gemsPerTier = { * @apiGroup Hall * @apiPermission Admin * - * @apiDescription Update user's gem balance, contributions & contribution tier - * and admin status. Grant items, block / unblock user's account - * and revoke / unrevoke chat privileges. + * @apiDescription Update user's gem balance, contributions and contribution tier, + * or admin status. Grant items. Block / unblock user's account. + * Revoke / unrevoke chat privileges. * * @apiExample Example Body: * { diff --git a/website/server/controllers/api-v3/members.js b/website/server/controllers/api-v3/members.js index 126546d4f4..e7d3e0dfe9 100644 --- a/website/server/controllers/api-v3/members.js +++ b/website/server/controllers/api-v3/members.js @@ -658,8 +658,8 @@ api.getObjectionsToInteraction = { * @apiName SendPrivateMessage * @apiGroup Member * - * @apiParam (Body) {String} message Body parameter - The message - * @apiParam (Body) {UUID} toUserId Body parameter - The user to contact + * @apiParam (Body) {String} message The message + * @apiParam (Body) {UUID} toUserId The id of the user to contact * * @apiSuccess {Object} data.message The message just sent * @@ -698,7 +698,7 @@ api.sendPrivateMessage = { * @apiGroup Member * * @apiParam (Body) {String} message The message to the user - * @apiParam (Body) {UUID} toUserId The toUser _id + * @apiParam (Body) {UUID} toUserId The user to send the gift to * @apiParam (Body) {Integer} gemAmount The number of gems to send * * @apiSuccess {Object} data An empty Object diff --git a/website/server/controllers/api-v3/news.js b/website/server/controllers/api-v3/news.js index 863a80605b..a3fa4223f2 100644 --- a/website/server/controllers/api-v3/news.js +++ b/website/server/controllers/api-v3/news.js @@ -4,7 +4,7 @@ const api = {}; // @TODO export this const, cannot export it from here because only routes are exported from // controllers -const LAST_ANNOUNCEMENT_TITLE = 'NEW PET COLLECTION BADGES!'; +const LAST_ANNOUNCEMENT_TITLE = 'BLOG POSTS: PARTY PARTICIPATION AND OUR FAVO(U)RITE GUILDS!'; const worldDmg = { // @TODO bailey: false, }; @@ -31,23 +31,43 @@ api.getNews = {

${res.t('newStuff')}

-

2/18/2020 - ${LAST_ANNOUNCEMENT_TITLE}

+

2/20/2020 - ${LAST_ANNOUNCEMENT_TITLE}


-
+
+

Use Case Spotlight: Party Participation

- We're releasing a new achievement so you can celebrate your successes in the world of - Habitican pet collecting! Earn the Tickled Pink and Rosy Outlook achievements by - collecting Cotton Candy Pink pets and mounts and you'll earn a nifty badge for your - profile. + This month's Use Case Spotlight is about Party Participation! It features a number + of great suggestions submitted by Habiticans in the Use Case Spotlights Guild. + We hope it helps any of you who might be looking for ways to keep your quest party + engaged and excited to win battles with good habits.

- If you already have all the Cotton Candy Pink pets and/or mounts in your stable, you'll - receive the badge automatically! Check your profile and celebrate your new achievement - with pride in your pink prowess. + Plus, we're collecting user submissions for the next spotlight! How do you use Habitica + to manage conflicting needs, like productivity versus self-care? We’ll be featuring + player-submitted examples in Use Case Spotlights on the Habitica Blog next month, so post + your suggestions in the Use Case Spotlight Guild now. We look forward to learning more + about how you use Habitica to improve your life and get things done!

-
by Piyowo and SabreCat
+
by shanaqui
+
+

Guild Spotlight: Shanaqui's Favourites

+

+ For this year's Guild Spotlight series, we're highlighting some favourites from + Habitica's staff, moderators, and maybe some high-level contributors! +

+

+ This month we're kicking things off with some picks from shanaqui! If you want to curate your Habitica experience + and join active, positive Guilds, this is a great way to pick up some new ideas for + Guilds to join. +

+
by shanaqui
`, }); @@ -55,8 +75,10 @@ api.getNews = { }; /** - * @api {post} /api/v3/news/tell-me-later Get latest Bailey announcement in a second moment + * @api {post} /api/v3/news/tell-me-later Allow latest Bailey announcement to be read later * @apiName TellMeLaterNews + * @apiDescription Add a notification to allow viewing of the latest "New Stuff by Bailey" message. + * Prevent this specific Bailey message from appearing automatically. * @apiGroup News * * diff --git a/website/server/controllers/api-v3/tags.js b/website/server/controllers/api-v3/tags.js index 6c2ab2e268..0da234f1df 100644 --- a/website/server/controllers/api-v3/tags.js +++ b/website/server/controllers/api-v3/tags.js @@ -78,7 +78,7 @@ api.getTags = { }; /** - * @api {get} /api/v3/tags/:tagId Get a tag given its id + * @api {get} /api/v3/tags/:tagId Get a tag * @apiName GetTag * @apiGroup Tag * @@ -199,7 +199,7 @@ api.reorderTags = { }; /** - * @api {delete} /api/v3/tags/:tagId Delete a user tag given its id + * @api {delete} /api/v3/tags/:tagId Delete a user tag * @apiName DeleteTag * @apiGroup Tag * diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js index 8f2488cbd6..41544680d8 100644 --- a/website/server/controllers/api-v3/tasks.js +++ b/website/server/controllers/api-v3/tasks.js @@ -1479,6 +1479,8 @@ api.unlinkOneTask = { /** * @api {post} /api/v3/tasks/clearCompletedTodos Delete user's completed todos * @apiName ClearCompletedTodos + * @apiDescription Deletes all of a user's completed To-Dos except + * those belonging to active Challenges and Group Plans. * @apiGroup Task * * @apiExample {curl} Example call: @@ -1523,7 +1525,7 @@ api.clearCompletedTodos = { }; /** - * @api {delete} /api/v3/tasks/:taskId Delete a task given its id + * @api {delete} /api/v3/tasks/:taskId Delete a task * @apiName DeleteTask * @apiGroup Task * diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js index 5b17204bee..dfbd9c0438 100644 --- a/website/server/controllers/api-v3/tasks/groups.js +++ b/website/server/controllers/api-v3/tasks/groups.js @@ -178,7 +178,7 @@ api.groupMoveTask = { * @apiParam (Path) {UUID} taskId The id of the task that will be assigned * @apiParam (Path) {UUID} assignedUserId The id of the user that will be assigned to the task * - * @apiSuccess data An object if a single task was created, otherwise an array of tasks + * @apiSuccess data The assigned task */ api.assignTask = { method: 'POST', @@ -246,14 +246,14 @@ api.assignTask = { /** * @api {post} /api/v3/tasks/:taskId/unassign/:assignedUserId Unassign a user from a task - * @apiDescription Unassigns a user to from a group task + * @apiDescription Unassigns a user from a group task * @apiName UnassignTask * @apiGroup Task * - * @apiParam (Path) {UUID} taskId The id of the task that will be assigned + * @apiParam (Path) {UUID} taskId The id of the task that is the original group task * @apiParam (Path) {UUID} assignedUserId The id of the user that will be unassigned from the task * - * @apiSuccess data An object if a single task was created, otherwise an array of tasks + * @apiSuccess data The unassigned task */ api.unassignTask = { method: 'POST', @@ -398,8 +398,8 @@ api.approveTask = { }; /** - * @api {post} /api/v3/tasks/:taskId/needs-work/:userId Group task needs more work - * @apiDescription Mark an assigned group task as needeing more work before it can be approved + * @api {post} /api/v3/tasks/:taskId/needs-work/:userId Require more work for a group task + * @apiDescription Mark an assigned group task as needing more work before it can be approved * @apiVersion 3.0.0 * @apiName TaskNeedsWork * @apiGroup Task diff --git a/website/server/controllers/api-v3/user.js b/website/server/controllers/api-v3/user.js index 18c411b018..ac45666121 100644 --- a/website/server/controllers/api-v3/user.js +++ b/website/server/controllers/api-v3/user.js @@ -41,28 +41,28 @@ const api = {}; * @apiGroup User * * @apiDescription The user profile contains data related to the authenticated - * user including (but not limited to); - * Achievements - * Authentications (including types and timestamps) - * Challenges - * Flags (including armoire, tutorial, tour etc...) - * Guilds - * History (including timestamps and values) - * Inbox - * Invitations (to parties/guilds) - * Items (character's full inventory) - * New Messages (flags for groups/guilds that have new messages) - * Notifications - * Party (includes current quest information) - * Preferences (user selected prefs) - * Profile (name, photo url, blurb) - * Purchased (includes purchase history, gem purchased items, plans) - * PushDevices (identifiers for mobile devices authorized) - * Stats (standard RPG stats, class, buffs, xp, etc..) - * Tags - * TasksOrder (list of all ids for dailys, habits, rewards and todos) + * user including (but not limited to): + * Achievements; + * Authentications (including types and timestamps); + * Challenges memberships (Challenge IDs); + * Flags (including armoire, tutorial, tour etc...); + * Guilds memberships (Guild IDs); + * History (including timestamps and values, only for Experience and summed To-Do values); + * Inbox; + * Invitations (to parties/guilds); + * Items (character's full inventory); + * New Messages (flags for party/guilds that have new messages; also reported in Notifications); + * Notifications; + * Party (includes current quest information); + * Preferences (user selected prefs); + * Profile (name, photo url, blurb); + * Purchased (includes subscription data and some gem-purchased items); + * PushDevices (identifiers for mobile devices authorized); + * Stats (standard RPG stats, class, buffs, xp, etc..); + * Tags; + * TasksOrder (list of all IDs for Dailys, Habits, Rewards and To-Dos). * - * @apiParam (Query) {String} [userFields] A list of comma separated user fields to + * @apiParam (Query) {String} [userFields] A list of comma-separated user fields to * be returned instead of the entire document. * Notifications are always returned. * @@ -92,7 +92,7 @@ api.getUser = { /** * @api {get} /api/v3/user/inventory/buy - * Get the gear items available for purchase for the authenticated user + * Get equipment/gear items available for purchase for the authenticated user * @apiName UserGetBuyList * @apiGroup User * @@ -231,7 +231,8 @@ api.updateUser = { * @apiName UserDelete * @apiGroup User * - * @apiParam (Body) {String} password The user's password if the account uses local authentication + * @apiParam (Body) {String} password The user's password if the account uses local authentication, + * otherwise the localized word "DELETE" * @apiParam (Body) {String} feedback User's optional feedback explaining reasons for deletion * * @apiSuccess {Object} data An empty Object @@ -242,9 +243,14 @@ api.updateUser = { * "data": {} * } * - * @apiError {BadRequest} MissingPassword The password was not included in the request - * @apiError {BadRequest} LengthExceeded The feedback provided is longer than 10K - * @apiError {BadRequest} NotAuthorized There is no account that uses those credentials. + * @apiError {BadRequest} MissingPassword Missing password. + * @apiError {BadRequest} NotAuthorized Wrong password. + * @apiError {BadRequest} NotAuthorized Please type DELETE in all capital letters to + * delete your account. + * @apiError {BadRequest} BadRequest Account deletion feedback is limited to 10,000 characters. + * For lengthy feedback, email ${TECH_ASSISTANCE_EMAIL}. + * @apiError {BadRequest} NotAuthorized You have an active subscription, + * cancel your plan before deleting your account. * * @apiErrorExample {json} Example error: * { @@ -279,7 +285,7 @@ api.deleteUser = { } const { feedback } = req.body; - if (feedback && feedback.length > 10000) throw new BadRequest(`Account deletion feedback is limited to 10,000 characters. For lengthy feedback, email ${TECH_ASSISTANCE_EMAIL}.`); + if (feedback && feedback.length > 10000) throw new BadRequest(`Account deletion feedback is limited to 10,000 characters. For lengthy feedback, email ${TECH_ASSISTANCE_EMAIL}.`); // @TODO localize this string if (plan && plan.customerId && !plan.dateTerminated) { throw new NotAuthorized(res.t('cannotDeleteActiveAccount')); @@ -333,14 +339,14 @@ function _cleanChecklist (task) { * @apiGroup User * * @apiDescription Returns the user's data without: - * Authentication information - * NewMessages/Invitations/Inbox - * Profile - * Purchased information - * Contributor information - * Special items - * Webhooks - * Notifications + * Authentication information, + * NewMessages/Invitations/Inbox, + * Profile, + * Purchased information, + * Contributor information, + * Special items, + * Webhooks, + * Notifications. * * @apiSuccess {Object} data.user * @apiSuccess {Object} data.tasks @@ -537,7 +543,7 @@ api.buyGear = { }; /** - * @api {post} /api/v3/user/buy-armoire Buy an armoire item + * @api {post} /api/v3/user/buy-armoire Buy an Enchanted Armoire item * @apiName UserBuyArmoire * @apiGroup User * @@ -619,8 +625,9 @@ api.buyHealthPotion = { }; /** - * @api {post} /api/v3/user/buy-mystery-set/:key Buy a mystery set + * @api {post} /api/v3/user/buy-mystery-set/:key Buy a Mystery Item set * @apiName UserBuyMysterySet + * @apiDescription This buys a Mystery Item set using an Hourglass. * @apiGroup User * * @apiParam (Path) {String} key The mystery set to buy @@ -703,7 +710,7 @@ api.buyQuest = { }; /** - * @api {post} /api/v3/user/buy-special-spell/:key Buy special "spell" item + * @api {post} /api/v3/user/buy-special-spell/:key Buy special item (card, avatar transformation) * @apiDescription Includes gift cards (e.g., birthday card), and avatar Transformation * Items and their antidotes (e.g., Snowball item and Salt reward). * @apiName UserBuySpecialSpell @@ -1003,6 +1010,8 @@ api.purchase = { /** * @api {post} /api/v3/user/purchase-hourglass/:type/:key Purchase Hourglass-purchasable item * @apiName UserPurchaseHourglass + * @apiDescription Purchases an Hourglass-purchasable item. + * Does not include Mystery Item sets (use /api/v3/user/buy-mystery-set/:key). * @apiGroup User * * @apiParam (Path) {String="pets","mounts"} type The type of item to purchase @@ -1492,7 +1501,7 @@ api.clearMessages = { }; /** - * @api {post} /api/v3/user/mark-pms-read Marks Private Messages as read + * @api {post} /api/v3/user/mark-pms-read Mark Private Messages as read * @apiName markPmsRead * @apiGroup User * @@ -1517,7 +1526,7 @@ api.markPmsRead = { /* NOTE this route has also an API v4 version */ /** - * @api {post} /api/v3/user/reroll Reroll a user using the Fortify Potion + * @api {post} /api/v3/user/reroll Reroll a user (reset tasks) using the Fortify Potion * @apiName UserReroll * @apiGroup User * @@ -1580,14 +1589,12 @@ api.userReset = { }; /** - * @api {post} /api/v3/user/custom-day-start - * Set preferences.dayStart (Custom Day Start time) for user + * @api {post} /api/v3/user/custom-day-start Set Custom Day Start time for user. * @apiName setCustomDayStart * @apiGroup User * - * * @apiParam (Body) {number} [dayStart=0] The hour number 0-23 for day to begin. - * If body is not included, will default to 0. + * If not supplied, will default to 0. * * @apiParamExample {json} Request-Example: * {"dayStart":2} diff --git a/website/server/controllers/api-v3/user/spells.js b/website/server/controllers/api-v3/user/spells.js index 736fdc114f..86a03a3ecd 100644 --- a/website/server/controllers/api-v3/user/spells.js +++ b/website/server/controllers/api-v3/user/spells.js @@ -30,29 +30,30 @@ const api = {}; * the necessary fields will be populated. The user is always returned. * * @apiDescription Skill Key to Name Mapping - * Mage - * fireball: "Burst of Flames" - * mpheal: "Ethereal Surge" - * earth: "Earthquake" - * frost: "Chilling Frost" * - * Warrior - * smash: "Brutal Smash" - * defensiveStance: "Defensive Stance" - * valorousPresence: "Valorous Presence" - * intimidate: "Intimidating Gaze" + * Mage: + * fireball="Burst of Flames", + * mpheal="Ethereal Surge", + * earth="Earthquake", + * frost="Chilling Frost" * - * Rogue - * pickPocket: "Pickpocket" - * backStab: "Backstab" - * toolsOfTrade: "Tools of the Trade" - * stealth: "Stealth" + * Warrior: + * smash="Brutal Smash", + * defensiveStance="Defensive Stance", + * valorousPresence="Valorous Presence", + * intimidate="Intimidating Gaze" * - * Healer - * heal: "Healing Light" - * protectAura: "Protective Aura" - * brightness: "Searing Brightness" - * healAll: "Blessing" + * Rogue: + * pickPocket="Pickpocket", + * backStab="Backstab", + * toolsOfTrade="Tools of the Trade", + * stealth="Stealth" + * + * Healer: + * heal="Healing Light", + * protectAura="Protective Aura", + * brightness="Searing Brightness", + * healAll="Blessing" * * @apiError (400) {NotAuthorized} Not enough mana. * @apiUse TaskNotFound diff --git a/website/server/controllers/api-v3/user/stats.js b/website/server/controllers/api-v3/user/stats.js index 5da2c442f0..3cb24248b0 100644 --- a/website/server/controllers/api-v3/user/stats.js +++ b/website/server/controllers/api-v3/user/stats.js @@ -9,6 +9,7 @@ const api = {}; * Allocate a single Stat Point (previously called Attribute Point) * @apiName UserAllocate * @apiGroup User + * @apiDescription Allocates a single Stat Point. * * @apiParam (Query) {String="str","con","int","per"} stat The Stat to increase. Default is 'str' * diff --git a/website/server/controllers/api-v4/inbox.js b/website/server/controllers/api-v4/inbox.js index 6ced58cc26..be5cca6a4d 100644 --- a/website/server/controllers/api-v4/inbox.js +++ b/website/server/controllers/api-v4/inbox.js @@ -77,7 +77,9 @@ api.clearMessages = { * @api {get} /api/v4/inbox/conversations Get the conversations for a user * @apiName conversations * @apiGroup Inbox - * @apiDescription Get the conversations for a user + * @apiDescription Get the conversations for a user. + * This is for API v4 which must not be used in third-party tools. + * For API v3, use "Get inbox messages for a user". * * @apiSuccess {Array} data An array of inbox conversations * diff --git a/website/server/controllers/api-v4/members.js b/website/server/controllers/api-v4/members.js index bd31d6a0b4..b84a3775fe 100644 --- a/website/server/controllers/api-v4/members.js +++ b/website/server/controllers/api-v4/members.js @@ -5,8 +5,10 @@ const api = {}; /** * @api {post} /api/v4/members/flag-private-message/:messageId Flag a private message - * @apiDescription An email and slack message are sent - * to the moderators about every flagged message. + * @apiDescription Moderators are notified about every flagged message, + * including the sender, recipient, and full content of the message. + * This is for API v4 which must not be used in third-party tools as it can change without notice. + * There is no equivalent route in API v3. * @apiName FlagPrivateMessage * @apiGroup Member * diff --git a/website/server/controllers/top-level/dataexport.js b/website/server/controllers/top-level/dataexport.js index 7d55fb4074..715b8c2268 100644 --- a/website/server/controllers/top-level/dataexport.js +++ b/website/server/controllers/top-level/dataexport.js @@ -161,6 +161,7 @@ api.exportUserDataJson = { /** * @api {get} /export/userdata.xml Export user data in XML format * @apiName ExportUserDataXml + * @apiDescription This XML export feature is not currently working (https://github.com/HabitRPG/habitica/issues/10100). * @apiGroup DataExport * * @apiSuccess {XML} File An xml file of the user object. @@ -224,6 +225,7 @@ api.exportUserAvatarHtml = { /** * @api {get} /export/avatar-:uuid.png Render a user avatar as a PNG file * @apiName ExportUserAvatarPng + * @apiDescription This PNG export feature is not currently working (https://github.com/HabitRPG/habitica/issues/9489). * @apiGroup DataExport * * @apiParam (Path) {String} uuid The User ID of the user @@ -293,6 +295,7 @@ api.exportUserAvatarPng = { /** * @api {get} /export/inbox.html Export user private messages as HTML document * @apiName ExportUserPrivateMessages + * @apiDescription This HTML export feature is not currently working (https://github.com/HabitRPG/habitica/issues/9489). * @apiGroup DataExport * * @apiSuccess {HTML} File An html page of the user's private messages. diff --git a/website/server/controllers/top-level/email.js b/website/server/controllers/top-level/email.js index 1fd0cdcdf4..5062961cd6 100644 --- a/website/server/controllers/top-level/email.js +++ b/website/server/controllers/top-level/email.js @@ -8,14 +8,15 @@ import { const api = {}; /** - * @api {get} /email/unsubscribe Unsubscribe an email or user from email notifications - * @apiDescription Does not require authentication + * @api {get} /email/unsubscribe Unsubscribe an email address or user from email notifications * @apiName UnsubscribeEmail * @apiGroup Unsubscribe * @apiDescription This is a GET method included in official emails from Habitica * that will unsubscribe the user from emails. + * Does not require authentication. * - * @apiParam (Query) {String} code An unsubscription code + * @apiParam (Query) {String} code An unsubscription code that contains an encrypted User ID or + * email address * * @apiSuccess {String} Webpage An html success message * diff --git a/website/server/libs/bannedSlurs.js b/website/server/libs/bannedSlurs.js index 7c5f4fc9ca..48f3a9aae9 100644 --- a/website/server/libs/bannedSlurs.js +++ b/website/server/libs/bannedSlurs.js @@ -95,7 +95,6 @@ const bannedSlurs = [ - 'sluts', 'spics', 'tranny', 'trannies', diff --git a/website/server/libs/bannedWords.js b/website/server/libs/bannedWords.js index 620b955c1f..b1dd2f3653 100644 --- a/website/server/libs/bannedWords.js +++ b/website/server/libs/bannedWords.js @@ -69,6 +69,10 @@ // These words are blocked from use in the Tavern but do not appear in bannedSlurs.js // because we do not want people to be automatically muted when the words are used // appropriately in guilds. +// As of 2020-02-26, 'sluts' is also here rather than in bannedSlurs.js because +// "Expanded Party: Polyamorous Adventurers" guild (17bb8393-2d74-42de-8dcb-315a5f596636) +// wants to discuss https://en.wikipedia.org/wiki/The_Ethical_Slut (a book) and +// we've decided to allow that. // DO NOT EDIT! See the comments at the top of this file. @@ -147,6 +151,7 @@ const bannedWords = [ 'fag', 'slut', + 'sluts', 'retard', 'retards', 'bastard', diff --git a/website/server/libs/guildsAllowingBannedWords.js b/website/server/libs/guildsAllowingBannedWords.js index b2decb3f5a..b7111b36f0 100644 --- a/website/server/libs/guildsAllowingBannedWords.js +++ b/website/server/libs/guildsAllowingBannedWords.js @@ -44,6 +44,7 @@ const guildsAllowingBannedWords = { '612e5766-a171-4e0a-b02b-c55a9fe786e4': true, // Compulsive Overeaters '726058f7-4452-47a3-aa86-e995d1ac031c': true, // Conscientious Consumption 'c59147bf-46c1-4ec8-a63f-9a8ebfcf9987': true, // Culinary Institute of Habitica + '9ffb19bb-1356-4ead-b585-c5031b5393b1': true, // Cynophiles '202ab416-92b7-4cbe-97d7-772776c8f911': true, // Danish Translators '6c6f4df6-8bc2-4a4c-a5a1-d4f1ef447989': true, // Dar al-Arqam 'ad251001-c1c5-4227-b165-6549a5b9e267': true, // Das Planertarium @@ -57,6 +58,7 @@ const guildsAllowingBannedWords = { '955fdbb8-f1b3-40cb-b528-8d292b312a6a': true, // Egyptology Unearthed 'a4cd281d-4683-4604-86f3-d2cc955e1544': true, // En espanol '4c366cdd-9ece-4ee1-9bc5-fa0d0c8df63f': true, // Essential Habits of a Christian + '17bb8393-2d74-42de-8dcb-315a5f596636': true, // Expanded Party: Polyamorous Adventurers '414381ad-08bf-4fe4-b767-c0e874660438': true, // FOCUS - Fellowship of Catholic University Students '1705f33f-9303-4b78-93ac-e21ed2d08df8': true, // Fitbit Guild '2ed36580-011f-4abb-94fc-e52022f38f6f': true, // Foodies @@ -117,6 +119,7 @@ const guildsAllowingBannedWords = { '8dc268f5-5f6d-41a0-82ca-a248dfd240c4': true, // Portugal Fenomenal '77e13b13-e3ba-4e45-badf-9e448bb9be64': true, // Portuguese Translators '46bc163e-f34e-4216-b916-9062d30a141f': true, // Procurando Grupo Brasil (Pedir Convite) + '14ae3965-0536-4b63-bc55-3dbd6660e3af': true, // Purely Positive Dog Trainers '00698a77-cda2-4f49-a59f-f32205078903': true, // Quit Soda Support Group '3584819a-a854-4768-ba49-8880fc0dda14': true, // Reiki Br 'd7838bfa-4577-4a4f-b922-65834e4a824c': true, // Rhyme Commando @@ -137,8 +140,6 @@ const guildsAllowingBannedWords = { '8e389264-ada0-4834-828c-ef65679e929c': true, // Witches, Pagans, and Diviners '0ff469a9-677f-4dcd-a091-2d2d3cebcaa8': true, // Writers of Ideas: Speculative Fiction Authors 'f371368a-b3b0-4a81-a400-3bd59fc0a89d': true, // Youtube francophone - '9ffb19bb-1356-4ead-b585-c5031b5393b1': true, // Cynophiles - '14ae3965-0536-4b63-bc55-3dbd6660e3af': true, // Purely Positive Dog Trainers }; export default guildsAllowingBannedWords;