Compare commits

..

1 Commits

Author SHA1 Message Date
Phillip Thelen a018588021 Banning a user now automatically hides all their posts 2022-12-09 13:02:49 +01:00
23 changed files with 92 additions and 274 deletions
@@ -1,108 +0,0 @@
/* eslint-disable no-console */
const MIGRATION_NAME = '20221213_pet_group_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['BearCub-Base']
&& pets['BearCub-CottonCandyBlue']
&& pets['BearCub-CottonCandyPink']
&& pets['BearCub-Desert']
&& pets['BearCub-Golden']
&& pets['BearCub-Red']
&& pets['BearCub-Shade']
&& pets['BearCub-Skeleton']
&& pets['BearCub-White']
&& pets['BearCub-Zombie']
&& pets['Fox-Base']
&& pets['Fox-CottonCandyBlue']
&& pets['Fox-CottonCandyPink']
&& pets['Fox-Desert']
&& pets['Fox-Golden']
&& pets['Fox-Red']
&& pets['Fox-Shade']
&& pets['Fox-Skeleton']
&& pets['Fox-White']
&& pets['Fox-Zombie']
&& pets['Penguin-Base']
&& pets['Penguin-CottonCandyBlue']
&& pets['Penguin-CottonCandyPink']
&& pets['Penguin-Desert']
&& pets['Penguin-Golden']
&& pets['Penguin-Red']
&& pets['Penguin-Shade']
&& pets['Penguin-Skeleton']
&& pets['Penguin-White']
&& pets['Penguin-Zombie']
&& pets['Whale-Base']
&& pets['Whale-CottonCandyBlue']
&& pets['Whale-CottonCandyPink']
&& pets['Whale-Desert']
&& pets['Whale-Golden']
&& pets['Whale-Red']
&& pets['Whale-Shade']
&& pets['Whale-Skeleton']
&& pets['Whale-White']
&& pets['Whale-Zombie']
&& pets['Wolf-Base']
&& pets['Wolf-CottonCandyBlue']
&& pets['Wolf-CottonCandyPink']
&& pets['Wolf-Desert']
&& pets['Wolf-Golden']
&& pets['Wolf-Red']
&& pets['Wolf-Shade']
&& pets['Wolf-Skeleton']
&& pets['Wolf-White']
&& pets['Wolf-Zombie'] {
set['achievements.polarPro'] = true;
}
}
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.update({ _id: user._id }, { $set: set }).exec();
}
export default async function processUsers () {
let query = {
// migration: { $ne: MIGRATION_NAME },
'auth.timestamps.loggedin': { $gt: new Date('2022-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]._id,
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
+7 -6
View File
@@ -1,6 +1,6 @@
{
"name": "habitica",
"version": "4.252.2",
"version": "4.251.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -12097,12 +12097,13 @@
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
},
"passport": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/passport/-/passport-0.5.0.tgz",
"integrity": "sha512-ln+ue5YaNDS+fes6O5PCzXKSseY5u8MYhX9H5Co4s+HfYI5oqvnHKoOORLYDUPh+8tHvrxugF2GFcUA1Q1Gqfg==",
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz",
"integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==",
"requires": {
"passport-strategy": "1.x.x",
"pause": "0.0.1"
"pause": "0.0.1",
"utils-merge": "^1.0.1"
}
},
"passport-facebook": {
@@ -12213,7 +12214,7 @@
"pause": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
"integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
"integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
},
"pause-stream": {
"version": "0.0.11",
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.252.2",
"version": "4.251.0",
"main": "./website/server/index.js",
"dependencies": {
"@babel/core": "^7.19.6",
@@ -54,7 +54,7 @@
"nconf": "^0.12.0",
"node-gcm": "^1.0.5",
"on-headers": "^1.0.2",
"passport": "^0.5.0",
"passport": "^0.6.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth2": "^0.2.0",
"passport-google-oauth20": "2.0.0",
-4
View File
@@ -37,8 +37,6 @@ describe('GET /faq', () => {
expect(res).to.have.property('questions');
expect(res.questions[0]).to.eql({
exclusions: [],
heading: 'overview',
question: translate('faqQuestion0'),
ios: translate('iosFaqAnswer0'),
});
@@ -59,8 +57,6 @@ describe('GET /faq', () => {
expect(res).to.have.property('questions');
expect(res.questions[0]).to.eql({
exclusions: [],
heading: 'overview',
question: translate('faqQuestion0'),
android: translate('androidFaqAnswer0'),
});
@@ -293,11 +293,6 @@
width: 48px;
height: 52px;
}
.achievement-polarPro2x {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/achievement-polarPro2x.png');
width: 68px;
height: 68px;
}
.achievement-primedForPainting2x {
background-image: url('https://habitica-assets.s3.amazonaws.com/mobileApp/images/achievement-primedForPainting2x.png');
width: 48px;
@@ -40,6 +40,11 @@
v-model="hero.auth.blocked"
type="checkbox"
> Ban / Block
<p>
<small>
Banning a user also auto-hides all their guild posts.
</small>
</p>
</label>
</div>
<div class="form-inline">
+56 -41
View File
@@ -5,44 +5,40 @@
>
<div class="row">
<div class="col-12 col-md-6 offset-md-3">
<h1
v-once
id="faq-heading"
>
<h1 id="faq-heading">
{{ $t('frequentlyAskedQuestions') }}
</h1>
<div
v-for="(entry, index) in faq.questions"
v-for="(heading, index) in headings"
:key="index"
class="faq-question"
>
<h2
v-once
v-b-toggle="entry.heading"
role="tab"
variant="info"
@click="handleClick($event)"
<div
v-if="heading !== 'world-boss'"
>
{{ entry.question }}
</h2>
<b-collapse
:id="entry.heading"
:visible="isVisible(entry.heading)"
accordion="faq"
role="tabpanel"
>
<div
v-once
v-markdown="entry.web"
class="card-body"
></div>
</b-collapse>
<h2
v-b-toggle="heading"
role="tab"
variant="info"
@click="handleClick($event)"
>
{{ $t(`faqQuestion${index}`) }}
</h2>
<b-collapse
:id="heading"
:visible="isVisible(heading)"
accordion="faq"
role="tabpanel"
>
<div
v-markdown="$t(`webFaqAnswer${index}`, replacements)"
class="card-body"
></div>
</b-collapse>
</div>
</div>
<hr>
<p
v-once
v-markdown="stillNeedHelp"
></p>
<p v-markdown="$t('webFaqStillNeedHelp')"></p>
</div>
</div>
</div>
@@ -50,7 +46,7 @@
<style lang='scss' scoped>
.card-body {
margin-bottom: 1em;
margin-bottom: 1em;
}
.faq-question h2 {
@@ -78,34 +74,53 @@
</style>
<script>
// @TODO: env.EMAILS.TECH_ASSISTANCE_EMAIL
import markdownDirective from '@/directives/markdown';
const TECH_ASSISTANCE_EMAIL = 'admin@habitica.com';
export default {
directives: {
markdown: markdownDirective,
},
data () {
const headings = [
'overview',
'set-up-tasks',
'sample-tasks',
'task-color',
'health',
'party-with-friends',
'pets-mounts',
'character-classes',
'blue-mana-bar',
'monsters-quests',
'gems',
'bugs-features',
'world-boss',
'group-plans',
];
const hash = window.location.hash.replace('#', '');
return {
faq: {},
headings: [],
stillNeedHelp: '',
headings,
replacements: {
techAssistanceEmail: TECH_ASSISTANCE_EMAIL,
wikiTechAssistanceEmail: `mailto:${TECH_ASSISTANCE_EMAIL}`,
},
visible: hash && headings.includes(hash) ? hash : null,
};
},
async mounted () {
mounted () {
this.$store.dispatch('common:setTitle', {
section: this.$t('help'),
subSection: this.$t('faq'),
});
this.faq = await this.$store.dispatch('faq:getFAQ');
for (const entry of this.faq.questions) {
this.headings.push(entry.heading);
}
this.stillNeedHelp = this.faq.stillNeedHelp.web;
},
methods: {
isVisible (heading) {
const hash = window.location.hash.replace('#', '');
return hash && this.headings.includes(hash) && hash === heading;
return this.visible && this.visible === heading;
},
handleClick (e) {
if (!e) return;
@@ -1028,9 +1028,10 @@ export default {
this.$store.dispatch('hall:updateHero', { heroDetails: this.hero });
},
adminBlockUser () {
this.hero.auth.blocked = true;
this.$store.dispatch('hall:updateHero', { heroDetails: this.hero });
if (window.confirm('Ban user and auto-hide all posts?')) {
this.hero.auth.blocked = true;
this.$store.dispatch('hall:updateHero', { heroDetails: this.hero });
}
},
adminUnblockUser () {
this.hero.auth.blocked = false;
-7
View File
@@ -1,7 +0,0 @@
import axios from 'axios';
export async function getFAQ () {
const url = '/api/v4/faq?platform=web';
const response = await axios.get(url);
return response.data.data;
}
@@ -18,7 +18,6 @@ import * as snackbars from './snackbars';
import * as worldState from './worldState';
import * as news from './news';
import * as analytics from './analytics';
import * as faq from './faq';
// Actions should be named as 'actionName' and can be accessed as 'namespace:actionName'
// Example: fetch in user.js -> 'user:fetch'
@@ -42,7 +41,6 @@ const actions = flattenAndNamespace({
worldState,
news,
analytics,
faq,
});
export default actions;
+1 -4
View File
@@ -141,8 +141,5 @@
"achievementWoodlandWizardModalText": "You collected all the forest pets!",
"achievementBoneToPick": "Bone to Pick",
"achievementBoneToPickText": "Has hatched all the Classic and Quest Skeleton Pets!",
"achievementBoneToPickModalText": "You collected all the Classic and Quest Skeleton Pets!",
"achievementPolarPro": "Polar Pro",
"achievementPolarProText": "Has hatched all Polar pets: Bear, Fox, Penguin, Whale, and Wolf!",
"achievementPolarProModalText": "You collected all the Polar Pets!"
"achievementBoneToPickModalText": "You collected all the Classic and Quest Skeleton Pets!"
}
-2
View File
@@ -67,8 +67,6 @@
"webFaqAnswer12": "World Bosses are special monsters that appear in the Tavern. All active users are automatically battling the Boss, and their tasks and Skills will damage the Boss as usual. You can also be in a normal Quest at the same time. Your tasks and Skills will count towards both the World Boss and the Boss/Collection Quest in your party. A World Boss will never hurt you or your account in any way. Instead, it has a Rage Bar that fills when users skip Dailies. If its Rage bar fills, it will attack one of the Non-Player Characters around the site and their image will change. You can read more about [past World Bosses](https://habitica.fandom.com/wiki/World_Bosses) on the wiki.",
"faqQuestion13": "What is a Group Plan?",
"iosFaqAnswer13": "## How do Group Plans work?\n\nA [Group Plan](/group-plans) gives your Party or Guild access to a shared task board thats similar to your personal task board! Its a shared Habitica experience where tasks can be created and checked off by anyone in the group.\n\nThere are also features available like member roles, status view, and task assigning that give you a more controlled experience. [Visit our wiki](https://habitica.fandom.com/wiki/Group_Plans) to learn more about our Group Plans features!\n\n## Who benefits from a Group Plan?\n\nGroup Plans work best when you have a small team of people who want to collaborate together. We recommend 2-5 members.\n\nGroup Plans are great for families, whether its a parent and child or you and a partner. Shared goals, chores, or responsibilities are easy to keep track of on one board.\n\nGroup Plans can also be useful for teams of colleagues that have shared goals, or managers that want to introduce their employees to gamification.\n\n## Quick tips for using Groups\n\nHere are some quick tips to get you started with your new Group. Well provide more details in the following sections:\n\n* Make a member a manager to give them the ability to create and edit tasks\n* Leave tasks unassigned if anyone can complete it and it only needs done once\n* Assign a task to one person to make sure no one else can complete their task\n* Assign a task to multiple people if they all need to complete it\n* Toggle the ability to display shared tasks on your personal board to not miss anything\n* You get rewarded for the tasks you complete, even multi-assigned\n* Task completion rewards arent shared or split between Team members\n* Use task color on the team board to judge the average completion rate of tasks\n* Regularly review the tasks on your Team Board to make sure they are still relevant\n* Missing a Daily wont damage you or your team, but the task will degrade in color\n\n## How can others in the group create tasks?\n\nOnly the group leader and managers can create tasks. If youd like a group member to be able to create tasks, then you should promote them to be a manager by going to the Group Information tab, viewing the member list, and clicking the dot icon by their name.\n\n## How does assigning a task work?\n\nGroup Plans give you the unique ability to assign tasks to other group members. Assigning a task is great for delegating. If you assign a task to someone, then other members are prevented from completing it.\n\nYou can also assign a task to multiple people if it needs to be completed by more than one member. For example, if everyone has to brush their teeth, create a task and assign it to each group member. They will all be able to check it off and get their individual rewards for doing so. The main task will show as complete once everyone checks it off.\n\n## How do unassigned tasks work?\n\nUnassigned tasks can be completed by anyone in the group, so leave a task unassigned to allow any member to complete it. For example, taking out the trash. Whoever takes out the trash can check off the unassigned task and it will show as completed for everyone.\n\n## How does the synchronized day reset work?\n\nShared tasks will reset at the same time for everyone to keep the shared task board in sync. This time is visible on the shared task board and is determined by the group leaders day start time. Because shared tasks reset automatically, you will not get a chance to complete yesterdays uncompleted shared Dailies when you check in the next morning.\n\nShared Dailies will not do damage if they are missed, however they will degrade in color to help visualize progress. We dont want the shared experience to be a negative one!\n\n## How do I use my Group on the mobile apps?\n\nWhile the mobile apps dont fully support all Group Plans functionality yet, you can still complete shared tasks from the iOS and Android app by copying the tasks onto your personal task board. You can switch this preference on from Settings in the mobile apps or from the group task board on the browser version. Now open and assigned shared tasks will display on your personal task board across all platforms.\n\n## Whats the difference between a Groups shared tasks and Challenges?\n\nGroup Plan shared task boards are more dynamic than Challenges, in that they can constantly be updated and interacted with. Challenges are great if you have one set of tasks to send out to many people.\n\nGroup Plans are also a paid feature, while Challenges are available free to everyone.\n\nYou cannot assign specific tasks in Challenges, and Challenges do not have a shared day reset. In general, Challenges offer less control and direct interaction.",
"androidFaqAnswer13": "## How do Group Plans work?\n\nA [Group Plan](/group-plans) gives your Party or Guild access to a shared task board thats similar to your personal task board! Its a shared Habitica experience where tasks can be created and checked off by anyone in the group.\n\nThere are also features available like member roles, status view, and task assigning that give you a more controlled experience. [Visit our wiki](https://habitica.fandom.com/wiki/Group_Plans) to learn more about our Group Plans features!\n\n## Who benefits from a Group Plan?\n\nGroup Plans work best when you have a small team of people who want to collaborate together. We recommend 2-5 members.\n\nGroup Plans are great for families, whether its a parent and child or you and a partner. Shared goals, chores, or responsibilities are easy to keep track of on one board.\n\nGroup Plans can also be useful for teams of colleagues that have shared goals, or managers that want to introduce their employees to gamification.\n\n## Quick tips for using Groups\n\nHere are some quick tips to get you started with your new Group. Well provide more details in the following sections:\n\n* Make a member a manager to give them the ability to create and edit tasks\n* Leave tasks unassigned if anyone can complete it and it only needs done once\n* Assign a task to one person to make sure no one else can complete their task\n* Assign a task to multiple people if they all need to complete it\n* Toggle the ability to display shared tasks on your personal board to not miss anything\n* You get rewarded for the tasks you complete, even multi-assigned\n* Task completion rewards arent shared or split between Team members\n* Use task color on the team board to judge the average completion rate of tasks\n* Regularly review the tasks on your Team Board to make sure they are still relevant\n* Missing a Daily wont damage you or your team, but the task will degrade in color\n\n## How can others in the group create tasks?\n\nOnly the group leader and managers can create tasks. If youd like a group member to be able to create tasks, then you should promote them to be a manager by going to the Group Information tab, viewing the member list, and clicking the dot icon by their name.\n\n## How does assigning a task work?\n\nGroup Plans give you the unique ability to assign tasks to other group members. Assigning a task is great for delegating. If you assign a task to someone, then other members are prevented from completing it.\n\nYou can also assign a task to multiple people if it needs to be completed by more than one member. For example, if everyone has to brush their teeth, create a task and assign it to each group member. They will all be able to check it off and get their individual rewards for doing so. The main task will show as complete once everyone checks it off.\n\n## How do unassigned tasks work?\n\nUnassigned tasks can be completed by anyone in the group, so leave a task unassigned to allow any member to complete it. For example, taking out the trash. Whoever takes out the trash can check off the unassigned task and it will show as completed for everyone.\n\n## How does the synchronized day reset work?\n\nShared tasks will reset at the same time for everyone to keep the shared task board in sync. This time is visible on the shared task board and is determined by the group leaders day start time. Because shared tasks reset automatically, you will not get a chance to complete yesterdays uncompleted shared Dailies when you check in the next morning.\n\nShared Dailies will not do damage if they are missed, however they will degrade in color to help visualize progress. We dont want the shared experience to be a negative one!\n\n## How do I use my Group on the mobile apps?\n\nWhile the mobile apps dont fully support all Group Plans functionality yet, you can still complete shared tasks from the iOS and Android app by copying the tasks onto your personal task board. You can switch this preference on from Settings in the mobile apps or from the group task board on the browser version. Now open and assigned shared tasks will display on your personal task board across all platforms.\n\n## Whats the difference between a Groups shared tasks and Challenges?\n\nGroup Plan shared task boards are more dynamic than Challenges, in that they can constantly be updated and interacted with. Challenges are great if you have one set of tasks to send out to many people.\n\nGroup Plans are also a paid feature, while Challenges are available free to everyone.\n\nYou cannot assign specific tasks in Challenges, and Challenges do not have a shared day reset. In general, Challenges offer less control and direct interaction.",
"webFaqAnswer13": "## How do Group Plans work?\n\nA [Group Plan](/group-plans) gives your Party or Guild access to a shared task board thats similar to your personal task board! Its a shared Habitica experience where tasks can be created and checked off by anyone in the group.\n\nThere are also features available like member roles, status view, and task assigning that give you a more controlled experience. [Visit our wiki](https://habitica.fandom.com/wiki/Group_Plans) to learn more about our Group Plans features!\n\n## Who benefits from a Group Plan?\n\nGroup Plans work best when you have a small team of people who want to collaborate together. We recommend 2-5 members.\n\nGroup Plans are great for families, whether its a parent and child or you and a partner. Shared goals, chores, or responsibilities are easy to keep track of on one board.\n\nGroup Plans can also be useful for teams of colleagues that have shared goals, or managers that want to introduce their employees to gamification.\n\n## Quick tips for using Groups\n\nHere are some quick tips to get you started with your new Group. Well provide more details in the following sections:\n\n* Make a member a manager to give them the ability to create and edit tasks\n* Leave tasks unassigned if anyone can complete it and it only needs done once\n* Assign a task to one person to make sure no one else can complete their task\n* Assign a task to multiple people if they all need to complete it\n* Toggle the ability to display shared tasks on your personal board to not miss anything\n* You get rewarded for the tasks you complete, even multi-assigned\n* Task completion rewards arent shared or split between Team members\n* Use task color on the team board to judge the average completion rate of tasks\n* Regularly review the tasks on your Team Board to make sure they are still relevant\n* Missing a Daily wont damage you or your team, but the task will degrade in color\n\n## How can others in the group create tasks?\n\nOnly the group leader and managers can create tasks. If youd like a group member to be able to create tasks, then you should promote them to be a manager by going to the Group Information tab, viewing the member list, and clicking the dot icon by their name.\n\n## How does assigning a task work?\n\nGroup Plans give you the unique ability to assign tasks to other group members. Assigning a task is great for delegating. If you assign a task to someone, then other members are prevented from completing it.\n\nYou can also assign a task to multiple people if it needs to be completed by more than one member. For example, if everyone has to brush their teeth, create a task and assign it to each group member. They will all be able to check it off and get their individual rewards for doing so. The main task will show as complete once everyone checks it off.\n\n## How do unassigned tasks work?\n\nUnassigned tasks can be completed by anyone in the group, so leave a task unassigned to allow any member to complete it. For example, taking out the trash. Whoever takes out the trash can check off the unassigned task and it will show as completed for everyone.\n\n## How does the synchronized day reset work?\n\nShared tasks will reset at the same time for everyone to keep the shared task board in sync. This time is visible on the shared task board and is determined by the group leaders day start time. Because shared tasks reset automatically, you will not get a chance to complete yesterdays uncompleted shared Dailies when you check in the next morning.\n\nShared Dailies will not do damage if they are missed, however they will degrade in color to help visualize progress. We dont want the shared experience to be a negative one!\n\n## How do I use my Group on the mobile apps?\n\nWhile the mobile apps dont fully support all Group Plans functionality yet, you can still complete shared tasks from the iOS and Android app by copying the tasks onto your personal task board. You can switch this preference on from Settings in the mobile apps or from the group task board on the browser version. Now open and assigned shared tasks will display on your personal task board across all platforms.\n\n## Whats the difference between a Groups shared tasks and Challenges?\n\nGroup Plan shared task boards are more dynamic than Challenges, in that they can constantly be updated and interacted with. Challenges are great if you have one set of tasks to send out to many people.\n\nGroup Plans are also a paid feature, while Challenges are available free to everyone.\n\nYou cannot assign specific tasks in Challenges, and Challenges do not have a shared day reset. In general, Challenges offer less control and direct interaction.",
"iosFaqStillNeedHelp": "If you have a question that isn't on this list or on the [Wiki FAQ](https://habitica.fandom.com/wiki/FAQ), come ask in the Tavern chat under Menu > Tavern! We're happy to help.",
+1 -1
View File
@@ -229,7 +229,7 @@
"howItWorks": "How it Works",
"g1g1HowItWorks": "Type in the username of the account youd like to gift to. From there, pick the sub length youd like to gift and check out. Your account will automatically be rewarded with the same level of subscription you just gifted.",
"limitations": "Limitations",
"g1g1Limitations": "This is a limited time event that starts on December 15th at 8:00 AM ET (13:00 UTC) and will end January 8th at 11:59 PM ET (January 9th 04:59 UTC). This promotion only applies when you gift to another Habitican. If you or your gift recipient already have a subscription, the gifted subscription will add months of credit that will only be used after the current subscription is canceled or expires.",
"g1g1Limitations": "This is a limited time event that starts on December 16th at 8:00 AM ET (13:00 UTC) and will end January 6th at 8:00 PM ET (1:00 UTC). This promotion only applies when you gift to another Habitican. If you or your gift recipient already have a subscription, the gifted subscription will add months of credit that will only be used after the current subscription is canceled or expires.",
"noLongerAvailable": "This item is no longer available.",
"gemSaleHow": "Between <%= eventStartMonth %> <%= eventStartOrdinal %> and <%= eventEndOrdinal %>, simply purchase any Gem bundle like usual and your account will be credited with the promotional amount of Gems. More Gems to spend, share, or save for any future releases!",
"gemSaleLimitations": "This promotion only applies during the limited time event. This event starts on <%= eventStartMonth %> <%= eventStartOrdinal %> at 8:00 AM EDT (12:00 UTC) and will end <%= eventStartMonth %> <%= eventEndOrdinal %> at 8:00 PM EDT (00:00 UTC). The promo offer is only available when buying Gems for yourself."
@@ -183,11 +183,6 @@ const animalSetAchievs = {
titleKey: 'achievementDomesticated',
textKey: 'achievementDomesticatedText',
},
polarPro: {
icon: 'achievement-polarPro',
titleKey: 'achievementPolarPro',
textKey: 'achievementPolarProText',
},
reptacularRumble: {
icon: 'achievement-reptacularRumble',
titleKey: 'achievementReptacularRumble',
@@ -41,18 +41,6 @@ const ANIMAL_SET_ACHIEVEMENTS = {
achievementKey: 'domesticated',
notificationType: 'ACHIEVEMENT_ANIMAL_SET',
},
polarPro: {
type: 'pet',
species: [
'BearCub',
'Fox',
'Penguin',
'Whale',
'Wolf',
],
achievementKey: 'polarPro',
notificationType: 'ACHIEVEMENT_ANIMAL_SET',
},
reptacularRumble: {
type: 'pet',
species: [
@@ -15,11 +15,6 @@ export const EVENTS = {
season: 'normal',
npcImageSuffix: '',
},
g1g12022: {
start: '2022-12-15T08:00-05:00',
end: '2023-01-08T23:59-05:00',
promo: 'g1g1',
},
harvestFeast2022: {
start: '2022-11-22T08:00-05:00',
end: '2022-11-27T20:00-05:00',
+7 -63
View File
@@ -1,60 +1,6 @@
import t from './translation';
const questionList = [
{
heading: 'overview',
translationIndex: 0,
},
{
heading: 'set-up-tasks',
translationIndex: 1,
},
{
heading: 'sample-tasks',
translationIndex: 2,
},
{
heading: 'task-color',
translationIndex: 3,
},
{
heading: 'health',
translationIndex: 4,
},
{
heading: 'party-with-friends',
translationIndex: 5,
},
{
heading: 'pets-mounts',
translationIndex: 6,
},
{
heading: 'character-classes',
translationIndex: 7,
},
{
heading: 'blue-mana-bar',
translationIndex: 8,
},
{
heading: 'monsters-quests',
translationIndex: 9,
},
{
heading: 'gems',
translationIndex: 10,
},
{
heading: 'bugs-features',
translationIndex: 11,
},
{
heading: 'group-plans',
translationIndex: 13,
excludedPlatforms: ['android', 'ios'],
},
];
const NUMBER_OF_QUESTIONS = 12;
const faq = {
questions: [],
@@ -64,14 +10,12 @@ const faq = {
},
};
questionList.forEach(listEntry => {
for (let i = 0; i <= NUMBER_OF_QUESTIONS; i += 1) {
const question = {
exclusions: listEntry.excludedPlatforms || [],
heading: listEntry.heading,
question: t(`faqQuestion${listEntry.translationIndex}`),
android: t(`androidFaqAnswer${listEntry.translationIndex}`),
ios: t(`iosFaqAnswer${listEntry.translationIndex}`),
web: t(`webFaqAnswer${listEntry.translationIndex}`, {
question: t(`faqQuestion${i}`),
ios: t(`iosFaqAnswer${i}`),
android: t(`androidFaqAnswer${i}`),
web: t(`webFaqAnswer${i}`, {
// TODO: Need to pull these values from nconf
techAssistanceEmail: 'admin@habitica.com',
wikiTechAssistanceEmail: 'mailto:admin@habitica.com',
@@ -79,6 +23,6 @@ questionList.forEach(listEntry => {
};
faq.questions.push(question);
});
}
export default faq;
@@ -220,7 +220,6 @@ function _getBasicAchievements (user, language) {
_addSimple(result, user, { path: 'reptacularRumble', language });
_addSimple(result, user, { path: 'woodlandWizard', language });
_addSimple(result, user, { path: 'boneToPick', language });
_addSimple(result, user, { path: 'polarPro', language });
_addSimpleWithMasterCount(result, user, { path: 'beastMaster', language });
_addSimpleWithMasterCount(result, user, { path: 'mountMaster', language });
@@ -9,6 +9,7 @@ import {
NotFound,
} from '../../libs/errors';
import apiError from '../../libs/apiError';
import { flagAllMessages } from '../../libs/chat/group-chat';
import {
validateItemPath,
castItemVal,
@@ -336,6 +337,7 @@ api.updateHero = {
if (updateData.auth && updateData.auth.blocked === true) {
hero.auth.blocked = updateData.auth.blocked;
hero.preferences.sleep = true; // when blocking, have them rest at an inn to prevent damage
await flagAllMessages(hero);
}
if (updateData.auth && updateData.auth.blocked === false) {
hero.auth.blocked = false;
-1
View File
@@ -22,7 +22,6 @@ function _deleteProperties (obj, keysToDelete, platform) {
function _deleteOtherPlatformsAnswers (faqObject, platform) {
const faqCopy = _.cloneDeep(faqObject);
_.remove(faqCopy.questions, question => question.exclusions.indexOf(platform) !== -1);
const keysToDelete = _.without(['web', 'ios', 'android'], platform);
_deleteProperties(faqCopy.stillNeedHelp, keysToDelete, platform);
+6
View File
@@ -114,3 +114,9 @@ export function translateMessage (lang, info) {
}
return msg;
}
export async function flagAllMessages (user) {
const bulk = Chat.collection.initializeOrderedBulkOp();
bulk.find({ uuid: user._id }).update({ $set: { flagCount: 3 } });
await bulk.execute();
}
-1
View File
@@ -152,7 +152,6 @@ export default new Schema({
reptacularRumble: Boolean,
woodlandWizard: Boolean,
boneToPick: Boolean,
polarPro: Boolean,
// Onboarding Guide
createdTask: Boolean,
completedTask: Boolean,