Ported sendGift route and renamed it to transferGems. Refactored user.sendMessage logic.

This commit is contained in:
Keith Holliday 2016-03-24 21:35:54 -05:00
parent 95ea73d440
commit 19a63e8128
5 changed files with 234 additions and 112 deletions

View file

@ -124,5 +124,7 @@
"notAuthorizedToSendMessageToThisUser": "Can't send message to this user.",
"privateMessageGiftIntro": "Hello <%= receiverName %>, <%= senderName %> has sent you ",
"privateMessageGiftGemsMessage": "<%= gemAmount %> gems! ",
"privateMessageGiftSubscriptionMessage": "<%= numberOfMonths %> months of subscription! "
"privateMessageGiftSubscriptionMessage": "<%= numberOfMonths %> months of subscription! ",
"cannotSendGemsToYourself": "Cannot send gems to yourself. Try a subscription instead.",
"notEnoughGemsToSend": "Amount must be within 0 and your current number of gems."
}

View file

@ -6,7 +6,7 @@ import { v4 as generateUUID } from 'uuid';
describe('POST /members/send-private-message', () => {
let userToSendMessage;
let messageToSend = { message: 'Test Private Message' };
let messageToSend = 'Test Private Message';
beforeEach(async () => {
userToSendMessage = await generateUser();
@ -94,92 +94,14 @@ describe('POST /members/send-private-message', () => {
let updatedSender = await userToSendMessage.get('/user');
let sendersMessageInReceiversInbox = _.find(updatedReceiver.inbox.messages, (message) => {
return message.uuid === userToSendMessage._id && message.text === messageToSend.message;
return message.uuid === userToSendMessage._id && message.text === messageToSend;
});
let sendersMessageInSendersInbox = _.find(updatedSender.inbox.messages, (message) => {
return message.uuid === receiver._id && message.text === messageToSend.message;
return message.uuid === receiver._id && message.text === messageToSend;
});
expect(sendersMessageInReceiversInbox).to.exist;
expect(sendersMessageInSendersInbox).to.exist;
});
it('sends a private message about gems to a user', async () => {
let receiver = await generateUser();
let messageAboutGemsToSend = {
type: 'gems',
gems: {
amount: 2,
},
message: 'Test Message About Gems',
};
await userToSendMessage.post('/members/send-private-message', {
message: messageAboutGemsToSend,
toUserId: receiver._id,
});
let updatedReceiver = await receiver.get('/user');
let updatedSender = await userToSendMessage.get('/user');
let sendersMessageInReceiversInbox = _.find(updatedReceiver.inbox.messages, (message) => {
return message.uuid === userToSendMessage._id;
});
let sendersMessageInSendersInbox = _.find(updatedSender.inbox.messages, (message) => {
return message.uuid === receiver._id;
});
let messageSentContent = t('privateMessageGiftIntro', {
receiverName: receiver.profile.name,
senderName: userToSendMessage.profile.name,
});
messageSentContent += t('privateMessageGiftGemsMessage', {gemAmount: messageAboutGemsToSend.gems.amount});
messageSentContent += messageAboutGemsToSend.message;
expect(sendersMessageInReceiversInbox).to.exist;
expect(sendersMessageInReceiversInbox.text).to.equal(messageSentContent);
expect(sendersMessageInSendersInbox).to.exist;
expect(sendersMessageInSendersInbox.text).to.equal(messageSentContent);
});
it('sends a private message about subscriptions to a user', async () => {
let receiver = await generateUser();
let messageAboutSubscriptionToSend = {
type: 'subscription',
subscription: {
key: 'basic_12mo',
},
message: 'Test Message About Subscription',
};
await userToSendMessage.post('/members/send-private-message', {
message: messageAboutSubscriptionToSend,
toUserId: receiver._id,
});
let updatedReceiver = await receiver.get('/user');
let updatedSender = await userToSendMessage.get('/user');
let sendersMessageInReceiversInbox = _.find(updatedReceiver.inbox.messages, (message) => {
return message.uuid === userToSendMessage._id;
});
let sendersMessageInSendersInbox = _.find(updatedSender.inbox.messages, (message) => {
return message.uuid === receiver._id;
});
let messageSentContent = t('privateMessageGiftIntro', {
receiverName: receiver.profile.name,
senderName: userToSendMessage.profile.name,
});
messageSentContent += t('privateMessageGiftSubscriptionMessage', {numberOfMonths: 12});
messageSentContent += messageAboutSubscriptionToSend.message;
expect(sendersMessageInReceiversInbox).to.exist;
expect(sendersMessageInReceiversInbox.text).to.equal(messageSentContent);
expect(sendersMessageInSendersInbox).to.exist;
expect(sendersMessageInSendersInbox.text).to.equal(messageSentContent);
});
});

View file

@ -0,0 +1,146 @@
import {
generateUser,
translate as t,
} from '../../../../helpers/api-v3-integration.helper';
import { v4 as generateUUID } from 'uuid';
describe('POST /members/transfer-gems', () => {
let userToSendMessage;
let receiver;
let message = 'Test Private Message';
let gemAmount = 20;
let giftType = 'gems';
beforeEach(async () => {
userToSendMessage = await generateUser({balance: 5});
receiver = await generateUser();
});
it('returns error when giftType is not provided', async () => {
await expect(userToSendMessage.post('/members/transfer-gems'))
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: 'Invalid request parameters.',
});
});
it('returns error when message is not provided', async () => {
await expect(userToSendMessage.post('/members/transfer-gems'), {
giftType,
message,
}).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: 'Invalid request parameters.',
});
});
it('returns error when toUserId is not provided', async () => {
await expect(userToSendMessage.post('/members/transfer-gems', {
giftType,
message,
})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: 'Invalid request parameters.',
});
});
it('returns error when to user is not found', async () => {
await expect(userToSendMessage.post('/members/transfer-gems', {
giftType,
message,
toUserId: generateUUID(),
})).to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
message: t('userNotFound'),
});
});
it('returns error when to user attempts to send gems to themselves', async () => {
await expect(userToSendMessage.post('/members/transfer-gems', {
giftType,
message,
toUserId: userToSendMessage._id,
})).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('cannotSendGemsToYourself'),
});
});
it('returns error when there is no amount', async () => {
await expect(userToSendMessage.post('/members/transfer-gems', {
giftType,
message,
toUserId: receiver._id,
})).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('notEnoughGemsToSend'),
});
});
it('returns error when gemAmount is negative', async () => {
await expect(userToSendMessage.post('/members/transfer-gems', {
giftType,
message,
gemAmount: -5,
toUserId: receiver._id,
})).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('notEnoughGemsToSend'),
});
});
it('returns error when gemAmount is more than the sender\'s balance', async () => {
await expect(userToSendMessage.post('/members/transfer-gems', {
giftType,
message,
gemAmount: gemAmount + 4,
toUserId: receiver._id,
})).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('notEnoughGemsToSend'),
});
});
it('sends a private message about gems to a user', async () => {
await userToSendMessage.post('/members/transfer-gems', {
giftType,
message,
gemAmount,
toUserId: receiver._id,
});
let updatedReceiver = await receiver.get('/user');
let updatedSender = await userToSendMessage.get('/user');
let sendersMessageInReceiversInbox = _.find(updatedReceiver.inbox.messages, (inboxMessage) => {
return inboxMessage.uuid === userToSendMessage._id;
});
let sendersMessageInSendersInbox = _.find(updatedSender.inbox.messages, (inboxMessage) => {
return inboxMessage.uuid === receiver._id;
});
let messageSentContent = t('privateMessageGiftIntro', {
receiverName: receiver.profile.name,
senderName: userToSendMessage.profile.name,
});
messageSentContent += t('privateMessageGiftGemsMessage', {gemAmount});
messageSentContent += message;
expect(sendersMessageInReceiversInbox).to.exist;
expect(sendersMessageInReceiversInbox.text).to.equal(messageSentContent);
expect(updatedReceiver.balance).to.equal(gemAmount / 4);
expect(sendersMessageInSendersInbox).to.exist;
expect(sendersMessageInSendersInbox.text).to.equal(messageSentContent);
expect(updatedSender.balance).to.equal(0);
});
});

View file

@ -16,6 +16,7 @@ import {
getUserInfo,
sendTxn as sendTxnEmail,
} from '../../libs/api-v3/email';
import Q from 'q';
let api = {};
@ -237,7 +238,7 @@ api.getChallengeMemberProgress = {
};
/**
* @api {posts} /members/send-private-message Get a challenge member progress
* @api {posts} /members/send-private-message Send a private message to a member
* @apiVersion 3.0.0
* @apiName SendPrivateMessage
* @apiGroup Members
@ -261,21 +262,21 @@ api.sendPrivateMessage = {
let sender = res.locals.user;
let message = req.body.message;
let userToReceiveMessage = await User.findById(req.body.toUserId).exec();
if (!userToReceiveMessage) throw new NotFound(res.t('userNotFound'));
let receiver = await User.findById(req.body.toUserId).exec();
if (!receiver) throw new NotFound(res.t('userNotFound'));
let userBlockedSender = userToReceiveMessage.inbox.blocks.indexOf(sender._id) !== -1;
let userIsBlockBySender = sender.inbox.blocks.indexOf(userToReceiveMessage._id) !== -1;
let userOptedOutOfMessaging = userToReceiveMessage.inbox.optOut;
let userBlockedSender = receiver.inbox.blocks.indexOf(sender._id) !== -1;
let userIsBlockBySender = sender.inbox.blocks.indexOf(receiver._id) !== -1;
let userOptedOutOfMessaging = receiver.inbox.optOut;
if (userBlockedSender || userIsBlockBySender || userOptedOutOfMessaging) {
throw new NotAuthorized(res.t('notAuthorizedToSendMessageToThisUser'));
}
await sender.sendMessage(userToReceiveMessage, message);
await sender.sendMessage(receiver, message);
if (userToReceiveMessage.preferences.emailNotifications.newPM !== false) {
sendTxnEmail(userToReceiveMessage, 'new-pm', [
if (receiver.preferences.emailNotifications.newPM !== false) {
sendTxnEmail(receiver, 'new-pm', [
{name: 'SENDER', content: getUserInfo(sender, ['name']).name},
{name: 'PMS_INBOX_URL', content: '/#/options/groups/inbox'},
]);
@ -285,4 +286,73 @@ api.sendPrivateMessage = {
},
};
/**
* @api {posts} /members/transfer-gems Send a gift to a member
* @apiVersion 3.0.0
* @apiName TransferGems
* @apiGroup Members
*
* @apiParam {String} message The message
* @apiParam {UUID} toUserId The toUser _id
*
* @apiSuccess {} Object Returns an empty object
*/
api.transferGems = {
method: 'POST',
url: '/members/transfer-gems',
middlewares: [authWithHeaders(), cron],
async handler (req, res) {
req.checkBody('message', res.t('messageRequired')).notEmpty();
req.checkBody('toUserId', res.t('toUserIDRequired')).notEmpty().isUUID();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
let sender = res.locals.user;
let receiver = await User.findById(req.body.toUserId).exec();
if (!receiver) throw new NotFound(res.t('userNotFound'));
if (receiver._id === sender._id) {
throw new NotAuthorized(res.t('cannotSendGemsToYourself'));
}
let gemAmount = req.body.gemAmount;
let amount = gemAmount / 4;
if (!amount || amount <= 0 || sender.balance < amount) {
throw new NotAuthorized(res.t('notEnoughGemsToSend'));
}
receiver.balance += amount;
sender.balance -= amount;
let promises = [receiver.save(), sender.save()];
await Q.all(promises);
let message = res.t('privateMessageGiftIntro', {
receiverName: receiver.profile.name,
senderName: sender.profile.name,
});
message += res.t('privateMessageGiftGemsMessage', {gemAmount});
message += req.body.message;
await sender.sendMessage(receiver, message);
let byUsername = getUserInfo(sender, ['name']).name;
if (receiver.preferences.emailNotifications.giftedGems !== false) {
sendTxnEmail(receiver, 'gifted-gems', [
{name: 'GIFTER', content: byUsername},
{name: 'X_GEMS_GIFTED', content: gemAmount},
]);
}
// @TODO: Add push notifications
// pushNotify.sendNotify(sender, res.t('giftedGems'), res.t('giftedGemsInfo', { amount: gemAmount, name: byUsername }));
res.respond(200, {});
},
};
module.exports = api;

View file

@ -708,33 +708,15 @@ schema.methods.getGroups = function getUserGroups () {
return userGroups;
};
schema.methods.sendMessage = async function sendMessage (userToReceiveMessage, messageData) {
let msg;
schema.methods.sendMessage = async function sendMessage (userToReceiveMessage, message) {
let sender = this;
if (!messageData.type) {
msg = messageData.message;
} else {
msg = shared.i18n.t('privateMessageGiftIntro', {
receiverName: userToReceiveMessage.profile.name,
senderName: sender.profile.name,
});
if (messageData.type === 'gems') {
msg += shared.i18n.t('privateMessageGiftGemsMessage', {gemAmount: messageData.gems.amount});
} else {
msg += shared.i18n.t('privateMessageGiftSubscriptionMessage', {numberOfMonths: shared.content.subscriptionBlocks[messageData.subscription.key].months});
}
msg += messageData.message;
}
shared.refPush(userToReceiveMessage.inbox.messages, chatDefaults(msg, sender));
shared.refPush(userToReceiveMessage.inbox.messages, chatDefaults(message, sender));
userToReceiveMessage.inbox.newMessages++;
userToReceiveMessage._v++;
userToReceiveMessage.markModified('inbox.messages');
shared.refPush(sender.inbox.messages, defaults({sent: true}, chatDefaults(msg, userToReceiveMessage)));
shared.refPush(sender.inbox.messages, defaults({sent: true}, chatDefaults(message, userToReceiveMessage)));
sender.markModified('inbox.messages');
let promises = [userToReceiveMessage.save(), sender.save()];