mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 07:07:35 +01:00
v3 and adapted v2: bugs fixes for groups, challenges and tasks
This commit is contained in:
@@ -3,7 +3,7 @@ import content from '../content/index';
|
|||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import { daysSince } from '../cron';
|
import { daysSince } from '../cron';
|
||||||
import { diminishingReturns } from '../statHelpers';
|
import { diminishingReturns } from '../statHelpers';
|
||||||
import { predictableRandom } from './predictableRandom';
|
import predictableRandom from './predictableRandom';
|
||||||
import randomVal from './randomVal';
|
import randomVal from './randomVal';
|
||||||
|
|
||||||
// Clone a drop object maintaining its functions so that we can change it without affecting the original item
|
// Clone a drop object maintaining its functions so that we can change it without affecting the original item
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ api.list = async function(req, res, next) {
|
|||||||
let obj = challenge.toJSON();
|
let obj = challenge.toJSON();
|
||||||
|
|
||||||
obj._isMember = user.challenges.indexOf(challenge._id) !== -1;
|
obj._isMember = user.challenges.indexOf(challenge._id) !== -1;
|
||||||
|
return obj;
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||||
await Q.all(resChals.map((chal, index) => {
|
await Q.all(resChals.map((chal, index) => {
|
||||||
return Q.all([
|
return Q.all([
|
||||||
@@ -195,7 +197,8 @@ api.create = async function(req, res, next){
|
|||||||
req.body.rewards = req.body.rewards || [];
|
req.body.rewards = req.body.rewards || [];
|
||||||
|
|
||||||
var chalTasks = req.body.habits.concat(req.body.rewards)
|
var chalTasks = req.body.habits.concat(req.body.rewards)
|
||||||
.concat(req.body.dailys).concat(req.body.todos);
|
.concat(req.body.dailys).concat(req.body.todos)
|
||||||
|
.map(v2Task => Tasks.Task.fromJSONV2(v2Task));
|
||||||
|
|
||||||
chalTasks = chalTasks.map(function(task) {
|
chalTasks = chalTasks.map(function(task) {
|
||||||
var newTask = new Tasks[task.type](Tasks.Task.sanitize(task));
|
var newTask = new Tasks[task.type](Tasks.Task.sanitize(task));
|
||||||
@@ -318,7 +321,7 @@ api.selectWinner = async function(req, res, next) {
|
|||||||
if (!challenge) return next('Challenge ' + req.params.cid + ' not found');
|
if (!challenge) return next('Challenge ' + req.params.cid + ' not found');
|
||||||
if (!challenge.canModify(res.locals.user)) return next(shared.i18n.t('noPermissionCloseChallenge'));
|
if (!challenge.canModify(res.locals.user)) return next(shared.i18n.t('noPermissionCloseChallenge'));
|
||||||
|
|
||||||
let winner = await User.findOne({_id: req.params.uid}).exec();
|
let winner = await User.findOne({_id: req.query.uid}).exec();
|
||||||
if (!winner || winner.challenges.indexOf(challenge._id) === -1) return next('Winner ' + req.query.uid + ' not found.');
|
if (!winner || winner.challenges.indexOf(challenge._id) === -1) return next('Winner ' + req.query.uid + ' not found.');
|
||||||
|
|
||||||
// Close channel in background, some ops are run in the background without `await`ing
|
// Close channel in background, some ops are run in the background without `await`ing
|
||||||
|
|||||||
@@ -676,7 +676,14 @@ api.cast = async function(req, res, next) {
|
|||||||
|
|
||||||
if (!partyMembers) throw new NotFound(res.t('userWithIDNotFound', {userId: targetId}));
|
if (!partyMembers) throw new NotFound(res.t('userWithIDNotFound', {userId: targetId}));
|
||||||
spell.cast(user, partyMembers, req);
|
spell.cast(user, partyMembers, req);
|
||||||
await partyMembers.save();
|
if (partyMembers === user) {
|
||||||
|
await partyMembers.save();
|
||||||
|
} else {
|
||||||
|
await Q.all([
|
||||||
|
await partyMembers.save(),
|
||||||
|
await user.save(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (party && !spell.silent) {
|
if (party && !spell.silent) {
|
||||||
|
|||||||
@@ -350,7 +350,15 @@ api.castSpell = {
|
|||||||
if (task.challenge.id) throw new BadRequest(res.t('challengeTasksNoCast'));
|
if (task.challenge.id) throw new BadRequest(res.t('challengeTasksNoCast'));
|
||||||
|
|
||||||
spell.cast(user, task, req);
|
spell.cast(user, task, req);
|
||||||
await task.save();
|
if (user.isModified()) {
|
||||||
|
await Q.all([
|
||||||
|
user.save(),
|
||||||
|
task.save(),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
await task.save();
|
||||||
|
}
|
||||||
|
|
||||||
res.respond(200, task);
|
res.respond(200, task);
|
||||||
} else if (targetType === 'self') {
|
} else if (targetType === 'self') {
|
||||||
spell.cast(user, null, req);
|
spell.cast(user, null, req);
|
||||||
@@ -370,7 +378,8 @@ api.castSpell = {
|
|||||||
|
|
||||||
let toSave = tasks.filter(t => t.isModified());
|
let toSave = tasks.filter(t => t.isModified());
|
||||||
let isUserModified = user.isModified();
|
let isUserModified = user.isModified();
|
||||||
toSave.unshift(user.save());
|
|
||||||
|
if (isUserModified) toSave.unshift(user.save());
|
||||||
let saved = await Q.all(toSave);
|
let saved = await Q.all(toSave);
|
||||||
|
|
||||||
let response = {
|
let response = {
|
||||||
@@ -403,7 +412,14 @@ api.castSpell = {
|
|||||||
|
|
||||||
if (!partyMembers) throw new NotFound(res.t('userWithIDNotFound', {userId: targetId}));
|
if (!partyMembers) throw new NotFound(res.t('userWithIDNotFound', {userId: targetId}));
|
||||||
spell.cast(user, partyMembers, req);
|
spell.cast(user, partyMembers, req);
|
||||||
await partyMembers.save();
|
if (user.isModified()) {
|
||||||
|
await Q.all([
|
||||||
|
user.save(),
|
||||||
|
partyMembers.save(),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
await partyMembers.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res.respond(200, partyMembers);
|
res.respond(200, partyMembers);
|
||||||
|
|
||||||
|
|||||||
@@ -631,32 +631,32 @@ schema.methods.leave = async function leaveGroup (user, keep = 'keep-all') {
|
|||||||
|
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
|
||||||
// If user is the last one in group and group is private, delete it
|
// remove the group from the user's groups
|
||||||
if (group.memberCount <= 1 && group.privacy === 'private') {
|
|
||||||
return await group.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise just remove a member TODO create User.methods.removeFromGroup?
|
|
||||||
if (group.type === 'guild') {
|
if (group.type === 'guild') {
|
||||||
promises.push(User.update({_id: user._id}, {$pull: {guilds: group._id}}).exec());
|
promises.push(User.update({_id: user._id}, {$pull: {guilds: group._id}}).exec());
|
||||||
} else {
|
} else {
|
||||||
promises.push(User.update({_id: user._id}, {$set: {party: {}}}).exec());
|
promises.push(User.update({_id: user._id}, {$set: {party: {}}}).exec());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the leader is leaving (or if the leader previously left, and this wasn't accounted for)
|
// If user is the last one in group and group is private, delete it
|
||||||
let update = {
|
if (group.memberCount <= 1 && group.privacy === 'private') {
|
||||||
$inc: {memberCount: -1},
|
return await group.remove();
|
||||||
};
|
} else { // otherwise If the leader is leaving (or if the leader previously left, and this wasn't accounted for)
|
||||||
|
let update = {
|
||||||
|
$inc: {memberCount: -1},
|
||||||
|
};
|
||||||
|
|
||||||
if (group.leader === user._id) {
|
if (group.leader === user._id) {
|
||||||
let query = group.type === 'party' ? {'party._id': group._id} : {guilds: group._id};
|
let query = group.type === 'party' ? {'party._id': group._id} : {guilds: group._id};
|
||||||
query._id = {$ne: user._id};
|
query._id = {$ne: user._id};
|
||||||
let seniorMember = await User.findOne(query).select('_id').exec();
|
let seniorMember = await User.findOne(query).select('_id').exec();
|
||||||
|
|
||||||
// could be missing in case of public guild (that can have 0 members) with 1 member who is leaving
|
// could be missing in case of public guild (that can have 0 members) with 1 member who is leaving
|
||||||
if (seniorMember) update.$set = {leader: seniorMember._id};
|
if (seniorMember) update.$set = {leader: seniorMember._id};
|
||||||
|
}
|
||||||
|
promises.push(group.update(update).exec());
|
||||||
}
|
}
|
||||||
promises.push(group.update(update).exec());
|
|
||||||
firebase.removeUserFromGroup(group._id, user._id);
|
firebase.removeUserFromGroup(group._id, user._id);
|
||||||
|
|
||||||
return Q.all(promises);
|
return Q.all(promises);
|
||||||
@@ -730,7 +730,7 @@ if (!nconf.get('IS_TEST')) {
|
|||||||
new model({ // eslint-disable-line babel/new-cap
|
new model({ // eslint-disable-line babel/new-cap
|
||||||
_id: TAVERN_ID,
|
_id: TAVERN_ID,
|
||||||
leader: '7bde7864-ebc5-4ee2-a4b7-1070d464cdb0', // Siena Leslie
|
leader: '7bde7864-ebc5-4ee2-a4b7-1070d464cdb0', // Siena Leslie
|
||||||
name: 'HabitRPG',
|
name: 'Tavern',
|
||||||
type: 'guild',
|
type: 'guild',
|
||||||
privacy: 'public',
|
privacy: 'public',
|
||||||
}).save();
|
}).save();
|
||||||
|
|||||||
Reference in New Issue
Block a user