This commit is contained in:
Matteo Pagliazzi
2018-05-04 20:57:18 +02:00
committed by GitHub
parent 63cf5b6be7
commit f226b5da07
3 changed files with 103 additions and 61 deletions

View File

@@ -8,7 +8,7 @@ describe('common.fns.updateStats', () => {
beforeEach(() => {
user = generateUser();
// user.addNotification = sinon.spy();
user.addNotification = sinon.spy();
});
context('No Hp', () => {
@@ -110,14 +110,14 @@ describe('common.fns.updateStats', () => {
expect(user.stats.points).to.eql(10);
});
xit('add user notification when drops are enabled', () => {
it('add user notification when drops are enabled', () => {
user.stats.lvl = 3;
updateStats(user, { });
expect(user.addNotification).to.be.calledOnce;
expect(user.addNotification).to.be.calledWith('DROPS_ENABLED');
});
xit('add user notification when the user levels up', () => {
it('add user notification when the user levels up', () => {
const initialLvl = user.stats.lvl;
updateStats(user, {
exp: 3000,
@@ -129,7 +129,7 @@ describe('common.fns.updateStats', () => {
});
});
xit('add user notification when rebirth is enabled', () => {
it('add user notification when rebirth is enabled', () => {
user.stats.lvl = 51;
updateStats(user, { });
expect(user.addNotification).to.be.calledTwice; // once is for drops enabled

View File

@@ -20,7 +20,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
if (stats.exp >= experienceToNextLevel) {
user.stats.exp = stats.exp;
// const initialLvl = user.stats.lvl;
const initialLvl = user.stats.lvl;
while (stats.exp >= experienceToNextLevel) {
stats.exp -= experienceToNextLevel;
@@ -50,13 +50,12 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
}
}
// @TODO: Tmp disable to see if this is causing concurrency
// const newLvl = user.stats.lvl;
//
// if (user.addNotification) user.addNotification('LEVELED_UP', {
// initialLvl,
// newLvl,
// });
const newLvl = user.stats.lvl;
if (user.addNotification) user.addNotification('LEVELED_UP', {
initialLvl,
newLvl,
});
}
user.stats.exp = stats.exp;

View File

@@ -12,7 +12,10 @@ import * as Tasks from './task';
import validator from 'validator';
import { removeFromArray } from '../libs/collectionManipulators';
import payments from '../libs/payments/payments';
import { groupChatReceivedWebhook } from '../libs/webhook';
import {
groupChatReceivedWebhook,
questActivityWebhook,
} from '../libs/webhook';
import {
InternalServerError,
BadRequest,
@@ -648,20 +651,24 @@ schema.methods.startQuest = async function startQuest (user) {
removeFromArray(nonUserQuestMembers, user._id);
// remove any users from quest.members who aren't in the party
let partyId = this._id;
let questMembers = this.quest.members;
await Promise.all(Object.keys(this.quest.members).map(memberId => {
return User.findOne({_id: memberId, 'party._id': partyId})
.select('_id')
// and get the data necessary to send webhooks
const members = [];
await User.find({
_id: {$in: Object.keys(this.quest.members)},
})
.select('party.quest party._id items.quests auth preferences.emailNotifications preferences.pushNotifications pushDevices profile.name webhooks')
.lean()
.exec()
.then((member) => {
if (!member) {
delete questMembers[memberId];
.then(partyMembers => {
partyMembers.forEach(member => {
if (!member.party || member.party._id !== this._id) {
delete this.quest.members[member._id];
} else {
members.push(member);
}
return;
});
}));
});
if (userIsParticipating) {
user.party.quest.key = this.quest.key;
@@ -670,20 +677,23 @@ schema.methods.startQuest = async function startQuest (user) {
user.markModified('party.quest');
}
const promises = [];
// Remove the quest from the quest leader items (if they are the current user)
if (this.quest.leader === user._id) {
user.items.quests[this.quest.key] -= 1;
user.markModified('items.quests');
promises.push(user.save());
} else { // another user is starting the quest, update the leader separately
await User.update({_id: this.quest.leader}, {
promises.push(User.update({_id: this.quest.leader}, {
$inc: {
[`items.quests.${this.quest.key}`]: -1,
},
}).exec();
}).exec());
}
// update the remaining users
await User.update({
promises.push(User.update({
_id: { $in: nonUserQuestMembers },
}, {
$set: {
@@ -691,7 +701,9 @@ schema.methods.startQuest = async function startQuest (user) {
'party.quest.progress.down': 0,
'party.quest.completed': null,
},
}, { multi: true }).exec();
}, { multi: true }).exec());
await Promise.all(promises);
// update the users who are not participating
// Do not block updates
@@ -703,38 +715,45 @@ schema.methods.startQuest = async function startQuest (user) {
},
}, { multi: true }).exec();
// send notifications in the background without blocking
User.find(
{ _id: { $in: nonUserQuestMembers } },
'party.quest items.quests auth.facebook auth.local preferences.emailNotifications preferences.pushNotifications pushDevices profile.name'
).exec().then((membersToNotify) => {
let membersToEmail = _.filter(membersToNotify, (member) => {
// send push notifications and filter users that disabled emails
return member.preferences.emailNotifications.questStarted !== false &&
member._id !== user._id;
});
sendTxnEmail(membersToEmail, 'quest-started', [
{ name: 'PARTY_URL', content: '/party' },
]);
let membersToPush = _.filter(membersToNotify, (member) => {
// send push notifications and filter users that disabled emails
return member.preferences.pushNotifications.questStarted !== false &&
member._id !== user._id;
});
_.each(membersToPush, (member) => {
sendPushNotification(member,
{
title: quest.text(),
message: `${shared.i18n.t('questStarted')}: ${quest.text()}`,
identifier: 'questStarted',
});
});
});
const newMessage = this.sendChat(`\`Your quest, ${quest.text('en')}, has started.\``, null, {
participatingMembers: this.getParticipatingQuestMembers().join(', '),
});
await newMessage.save();
const membersToEmail = [];
const pushTitle = quest.text();
const pushMessage = `${shared.i18n.t('questStarted')}: ${quest.text()}`;
// send notifications and webhooks in the background without blocking
members.forEach(member => {
if (member._id !== user._id) {
// send push notifications and filter users that disabled emails
if (member.preferences.emailNotifications.questStarted !== false) {
membersToEmail.push(member);
}
// send push notifications and filter users that disabled emails
if (member.preferences.pushNotifications.questStarted !== false) {
sendPushNotification(member, {
title: pushTitle,
message: pushMessage,
identifier: 'questStarted',
});
}
}
// Send webhooks
questActivityWebhook.send(member, {
type: 'questStarted',
group: this,
quest,
});
});
// Send emails in bulk
sendTxnEmail(membersToEmail, 'quest-started', [
{ name: 'PARTY_URL', content: '/party' },
]);
};
schema.methods.sendGroupChatReceivedWebhooks = function sendGroupChatReceivedWebhooks (chat) {
@@ -753,15 +772,14 @@ schema.methods.sendGroupChatReceivedWebhooks = function sendGroupChatReceivedWeb
query.guilds = this._id;
}
/* User.find(query).select({webhooks: 1}).lean().exec().then((users) => {
User.find(query).select({webhooks: 1}).lean().exec().then((users) => {
users.forEach((user) => {
let { webhooks } = user;
groupChatReceivedWebhook.send(webhooks, {
groupChatReceivedWebhook.send(user, {
group: this,
chat,
});
});
}); */
});
};
schema.statics.cleanQuestProgress = _cleanQuestProgress;
@@ -907,6 +925,31 @@ schema.methods.finishQuest = async function finishQuest (quest) {
}));
}
// Send webhooks in background
// @TODO move the find users part to a worker as well, not just the http request
User.find({
_id: {$in: participants},
webhooks: {
$elemMatch: {
type: 'questActivity',
'options.questFinished': true,
},
},
})
.select('_id webhooks')
.lean()
.exec()
.then(participantsWithWebhook => {
participantsWithWebhook.forEach(participantWithWebhook => {
// Send webhooks
questActivityWebhook.send(participantWithWebhook, {
type: 'questFinished',
group: this,
quest,
});
});
});
return await Promise.all(promises);
};