mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
Challenge small refactor (#9964)
* Removed challenge group duplication * Removed duplication of joined challenge * Moved helpers to challenge library * Passed group to function * Fixed group response
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import { authWithHeaders, authWithSession } from '../../middlewares/auth';
|
||||
import _ from 'lodash';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import omit from 'lodash/omit';
|
||||
import uuid from 'uuid';
|
||||
import { model as Challenge } from '../../models/challenge';
|
||||
import {
|
||||
model as Group,
|
||||
@@ -24,77 +22,15 @@ import {
|
||||
createTasks,
|
||||
} from '../../libs/taskManager';
|
||||
|
||||
const TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'dateCompleted', 'history', 'id', 'streak', 'createdAt', 'challenge'];
|
||||
import {
|
||||
addUserJoinChallengeNotification,
|
||||
getChallengeGroupResponse,
|
||||
createChallenge,
|
||||
cleanUpTask,
|
||||
} from '../../libs/challenges';
|
||||
|
||||
let api = {};
|
||||
|
||||
async function createChallenge (user, req, res) {
|
||||
let groupId = req.body.group;
|
||||
let prize = req.body.prize;
|
||||
|
||||
let group = await Group.getGroup({user, groupId, fields: '-chat', mustBeMember: true});
|
||||
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||
if (!group.isMember(user)) throw new NotAuthorized(res.t('mustBeGroupMember'));
|
||||
|
||||
if (group.leaderOnly && group.leaderOnly.challenges && group.leader !== user._id) {
|
||||
throw new NotAuthorized(res.t('onlyGroupLeaderChal'));
|
||||
}
|
||||
|
||||
if (group._id === TAVERN_ID && prize < 1) {
|
||||
throw new NotAuthorized(res.t('tavChalsMinPrize'));
|
||||
}
|
||||
|
||||
if (prize > 0) {
|
||||
let groupBalance = group.balance && group.leader === user._id ? group.balance : 0;
|
||||
let prizeCost = prize / 4;
|
||||
|
||||
if (prizeCost > user.balance + groupBalance) {
|
||||
throw new NotAuthorized(res.t('cantAfford'));
|
||||
}
|
||||
|
||||
if (groupBalance >= prizeCost) {
|
||||
// Group pays for all of prize
|
||||
group.balance -= prizeCost;
|
||||
} else if (groupBalance > 0) {
|
||||
// User pays remainder of prize cost after group
|
||||
let remainder = prizeCost - group.balance;
|
||||
group.balance = 0;
|
||||
user.balance -= remainder;
|
||||
} else {
|
||||
// User pays for all of prize
|
||||
user.balance -= prizeCost;
|
||||
}
|
||||
}
|
||||
|
||||
group.challengeCount += 1;
|
||||
|
||||
if (!req.body.summary) {
|
||||
req.body.summary = req.body.name;
|
||||
}
|
||||
req.body.leader = user._id;
|
||||
req.body.official = user.contributor.admin && req.body.official ? true : false;
|
||||
let challenge = new Challenge(Challenge.sanitize(req.body));
|
||||
|
||||
// First validate challenge so we don't save group if it's invalid (only runs sync validators)
|
||||
let challengeValidationErrors = challenge.validateSync();
|
||||
if (challengeValidationErrors) throw challengeValidationErrors;
|
||||
|
||||
// Add achievement if user's first challenge
|
||||
if (!user.achievements.joinedChallenge) {
|
||||
user.achievements.joinedChallenge = true;
|
||||
user.addNotification('CHALLENGE_JOINED_ACHIEVEMENT');
|
||||
}
|
||||
|
||||
let results = await Bluebird.all([challenge.save({
|
||||
validateBeforeSave: false, // already validate
|
||||
}), group.save()]);
|
||||
let savedChal = results[0];
|
||||
|
||||
await savedChal.syncToUser(user); // (it also saves the user)
|
||||
|
||||
return {savedChal, group};
|
||||
}
|
||||
|
||||
/**
|
||||
* @apiDefine ChallengeLeader Challenge Leader
|
||||
* The leader of the challenge can use this route.
|
||||
@@ -264,12 +200,7 @@ api.createChallenge = {
|
||||
_id: user._id,
|
||||
profile: {name: user.profile.name},
|
||||
};
|
||||
response.group = { // we already have the group data
|
||||
_id: group._id,
|
||||
name: group.name,
|
||||
type: group.type,
|
||||
privacy: group.privacy,
|
||||
};
|
||||
response.group = getChallengeGroupResponse(group);
|
||||
|
||||
res.analytics.track('challenge create', {
|
||||
uuid: user._id,
|
||||
@@ -320,22 +251,13 @@ api.joinChallenge = {
|
||||
|
||||
challenge.memberCount += 1;
|
||||
|
||||
// Add achievement if user's first challenge
|
||||
if (!user.achievements.joinedChallenge) {
|
||||
user.achievements.joinedChallenge = true;
|
||||
user.addNotification('CHALLENGE_JOINED_ACHIEVEMENT');
|
||||
}
|
||||
addUserJoinChallengeNotification(user);
|
||||
|
||||
// Add all challenge's tasks to user's tasks and save the challenge
|
||||
let results = await Bluebird.all([challenge.syncToUser(user), challenge.save()]);
|
||||
|
||||
let response = results[1].toJSON();
|
||||
response.group = { // we already have the group data
|
||||
_id: group._id,
|
||||
name: group.name,
|
||||
type: group.type,
|
||||
privacy: group.privacy,
|
||||
};
|
||||
response.group = getChallengeGroupResponse(group);
|
||||
let chalLeader = await User.findById(response.leader).select(nameFields).exec();
|
||||
response.leader = chalLeader ? chalLeader.toJSON({minimize: true}) : null;
|
||||
|
||||
@@ -692,12 +614,7 @@ api.updateChallenge = {
|
||||
|
||||
let savedChal = await challenge.save();
|
||||
let response = savedChal.toJSON();
|
||||
response.group = { // we already have the group data
|
||||
_id: group._id,
|
||||
name: group.name,
|
||||
type: group.type,
|
||||
privacy: group.privacy,
|
||||
};
|
||||
response.group = getChallengeGroupResponse(group);
|
||||
let chalLeader = await User.findById(response.leader).select(nameFields).exec();
|
||||
response.leader = chalLeader ? chalLeader.toJSON({minimize: true}) : null;
|
||||
res.respond(200, response);
|
||||
@@ -798,23 +715,6 @@ api.selectChallengeWinner = {
|
||||
},
|
||||
};
|
||||
|
||||
function cleanUpTask (task) {
|
||||
let cleansedTask = omit(task, TASK_KEYS_TO_REMOVE);
|
||||
|
||||
// Copy checklists but reset to uncomplete and assign new id
|
||||
if (!cleansedTask.checklist) cleansedTask.checklist = [];
|
||||
cleansedTask.checklist.forEach((item) => {
|
||||
item.completed = false;
|
||||
item.id = uuid();
|
||||
});
|
||||
|
||||
if (cleansedTask.type !== 'reward') {
|
||||
delete cleansedTask.value;
|
||||
}
|
||||
|
||||
return cleansedTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /api/v3/challenges/:challengeId/clone Clone a challenge
|
||||
* @apiName CloneChallenge
|
||||
|
||||
Reference in New Issue
Block a user