mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 06:37:23 +01:00
Inbox: Add API to list conversations (#11110)
* Add API to list inbox conversations * fix test + add api doc * use `.lean()` * orderBy after the the grouped conversations are loaded * fix ordering
This commit is contained in:
@@ -60,4 +60,10 @@ describe('GET /inbox/messages', () => {
|
||||
|
||||
expect(messages.length).to.equal(4);
|
||||
});
|
||||
|
||||
it('returns only the messages of one conversation', async () => {
|
||||
const messages = await user.get(`/inbox/messages?conversation=${otherUser.id}`);
|
||||
|
||||
expect(messages.length).to.equal(3);
|
||||
});
|
||||
});
|
||||
|
||||
44
test/api/v4/inbox/GET-inbox-conversations.test.js
Normal file
44
test/api/v4/inbox/GET-inbox-conversations.test.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
generateUser,
|
||||
} from '../../../helpers/api-integration/v4';
|
||||
|
||||
describe('GET /inbox/conversations', () => {
|
||||
let user;
|
||||
let otherUser;
|
||||
let thirdUser;
|
||||
|
||||
before(async () => {
|
||||
[user, otherUser, thirdUser] = await Promise.all([generateUser(), generateUser(), generateUser()]);
|
||||
|
||||
await otherUser.post('/members/send-private-message', {
|
||||
toUserId: user.id,
|
||||
message: 'first',
|
||||
});
|
||||
await user.post('/members/send-private-message', {
|
||||
toUserId: otherUser.id,
|
||||
message: 'second',
|
||||
});
|
||||
await user.post('/members/send-private-message', {
|
||||
toUserId: thirdUser.id,
|
||||
message: 'third',
|
||||
});
|
||||
await otherUser.post('/members/send-private-message', {
|
||||
toUserId: user.id,
|
||||
message: 'fourth',
|
||||
});
|
||||
|
||||
// message to yourself
|
||||
await user.post('/members/send-private-message', {
|
||||
toUserId: user.id,
|
||||
message: 'fifth',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the conversations', async () => {
|
||||
const result = await user.get('/inbox/conversations');
|
||||
|
||||
expect(result.length).to.be.equal(3);
|
||||
expect(result[0].user).to.be.equal(user.profile.name);
|
||||
expect(result[0].username).to.be.equal(user.auth.local.username);
|
||||
});
|
||||
});
|
||||
@@ -12,6 +12,7 @@ let api = {};
|
||||
* @apiDescription Get inbox messages for a user
|
||||
*
|
||||
* @apiParam (Query) {Number} page Load the messages of the selected Page - 10 Messages per Page
|
||||
* @apiParam (Query) {GUID} conversation Loads only the messages of a conversation
|
||||
*
|
||||
* @apiSuccess {Array} data An array of inbox messages
|
||||
*/
|
||||
@@ -22,9 +23,10 @@ api.getInboxMessages = {
|
||||
async handler (req, res) {
|
||||
const user = res.locals.user;
|
||||
const page = req.query.page;
|
||||
const conversation = req.query.conversation;
|
||||
|
||||
const userInbox = await inboxLib.getUserInbox(user, {
|
||||
page,
|
||||
page, conversation,
|
||||
});
|
||||
|
||||
res.respond(200, userInbox);
|
||||
|
||||
@@ -72,4 +72,25 @@ api.clearMessages = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @api {get} /inbox/conversations Get the conversations for a user
|
||||
* @apiName conversations
|
||||
* @apiGroup Inbox
|
||||
* @apiDescription Get the conversations for a user
|
||||
*
|
||||
* @apiSuccess {Array} data An array of inbox conversations
|
||||
*/
|
||||
api.conversations = {
|
||||
method: 'GET',
|
||||
middlewares: [authWithHeaders()],
|
||||
url: '/inbox/conversations',
|
||||
async handler (req, res) {
|
||||
const user = res.locals.user;
|
||||
|
||||
const result = await inboxLib.listConversations(user);
|
||||
|
||||
res.respond(200, result);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = api;
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
import { inboxModel as Inbox } from '../../models/message';
|
||||
import {inboxModel as Inbox} from '../../models/message';
|
||||
import {
|
||||
model as User,
|
||||
} from '../../models/user';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import keyBy from 'lodash/keyBy';
|
||||
|
||||
const PM_PER_PAGE = 10;
|
||||
|
||||
export async function getUserInbox (user, options = {asArray: true, page: 0}) {
|
||||
export async function getUserInbox (user, options = {asArray: true, page: 0, conversation: null}) {
|
||||
if (typeof options.asArray === 'undefined') {
|
||||
options.asArray = true;
|
||||
}
|
||||
|
||||
const findObj = {ownerId: user._id};
|
||||
|
||||
if (options.conversation) {
|
||||
findObj.uuid = options.conversation;
|
||||
}
|
||||
|
||||
let query = Inbox
|
||||
.find({ownerId: user._id})
|
||||
.find(findObj)
|
||||
.sort({timestamp: -1});
|
||||
|
||||
if (typeof options.page !== 'undefined') {
|
||||
@@ -29,12 +40,45 @@ export async function getUserInbox (user, options = {asArray: true, page: 0}) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function listConversations (user) {
|
||||
let query = Inbox
|
||||
.aggregate([
|
||||
{
|
||||
$match: {
|
||||
ownerId: user._id,
|
||||
},
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: '$uuid',
|
||||
timestamp: {$max: '$timestamp'}, // sort before group doesn't work - use the max value to sort it again after
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const conversationsList = orderBy(await query.exec(), ['timestamp'], ['desc']).map(c => c._id);
|
||||
|
||||
const users = await User.find({_id: {$in: conversationsList}})
|
||||
.select('_id profile.name auth.local.username')
|
||||
.lean()
|
||||
.exec();
|
||||
|
||||
const usersMap = keyBy(users, '_id');
|
||||
const conversations = conversationsList.map(userId => ({
|
||||
uuid: usersMap[userId]._id,
|
||||
user: usersMap[userId].profile.name,
|
||||
username: usersMap[userId].auth.local.username,
|
||||
}));
|
||||
|
||||
return conversations;
|
||||
}
|
||||
|
||||
export async function getUserInboxMessage (user, messageId) {
|
||||
return Inbox.findOne({ownerId: user._id, _id: messageId}).exec();
|
||||
}
|
||||
|
||||
export async function deleteMessage (user, messageId) {
|
||||
const message = await Inbox.findOne({_id: messageId, ownerId: user._id }).exec();
|
||||
const message = await Inbox.findOne({_id: messageId, ownerId: user._id}).exec();
|
||||
if (!message) return false;
|
||||
await Inbox.remove({_id: message._id, ownerId: user._id}).exec();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user