forked from kaverti/website
243 lines
5.5 KiB
JavaScript
243 lines
5.5 KiB
JavaScript
let Type = require('../lib/validation/type');
|
|
let validationError = require('../lib/errors/validationError');
|
|
let {
|
|
User,
|
|
Conversation,
|
|
Message,
|
|
UserConversation,
|
|
Sequelize
|
|
} = require('../models');
|
|
let sequelizeInstance = require('../models').sequelize;
|
|
|
|
exports.create = async function (userIds, name) {
|
|
//Remove duplicates
|
|
let userIdsSet = new Set(
|
|
userIds.filter(id => typeof id === 'number')
|
|
);
|
|
let userPromises = [];
|
|
let users;
|
|
|
|
userIdsSet.forEach(id => {
|
|
userPromises.push(User.findById(id));
|
|
});
|
|
users = (await Promise.all(userPromises)).filter(user => user !== null);
|
|
|
|
if(users.length > 1) {
|
|
let notNullUserIds = users.map(u => u.id).sort().join(',');
|
|
let existingConversation = await Conversation.findOne({
|
|
where: {
|
|
groupUsers: notNullUserIds
|
|
}
|
|
});
|
|
|
|
if(existingConversation) {
|
|
throw validationError({
|
|
message: 'Channel conversation already exists, you cannot make a duplicate.',
|
|
value: userIds
|
|
});
|
|
} else {
|
|
let conversation = await Conversation.create({ name, groupUsers: notNullUserIds });
|
|
await conversation.addUsers(users);
|
|
|
|
return conversation.toJSON();
|
|
}
|
|
} else {
|
|
throw validationError({
|
|
message: 'At least two users required for a conversation',
|
|
value: userIds
|
|
});
|
|
}
|
|
};
|
|
|
|
/*
|
|
userId of current user
|
|
page to search on (offset)
|
|
searchString of usernames given by user
|
|
*/
|
|
exports.getFromUser = async function (userId, page, searchString) {
|
|
console.log(userId)
|
|
let usernames = (searchString || '').split(/\s+/);
|
|
let replacementsObj = {
|
|
offset: (page || 0) * 10,
|
|
usernamesLen: usernames.length,
|
|
usernames: usernames.join('|'),
|
|
userId
|
|
};
|
|
|
|
let orClause = '';
|
|
if(usernames[0]) {
|
|
orClause = 'OR users.username RLIKE :usernames'
|
|
replacementsObj.usernamesLen++;
|
|
}
|
|
|
|
let sql = `
|
|
SELECT
|
|
conversations.*,
|
|
messages.content as 'Messages.content',
|
|
messages.createdAt as 'Messages.createdAt',
|
|
users.username as 'User.username',
|
|
users.id as 'User.id',
|
|
userconversations.lastRead as 'lastRead'
|
|
|
|
FROM
|
|
(
|
|
SELECT ConversationId
|
|
FROM userconversations
|
|
INNER JOIN users
|
|
ON userconversations.UserId = users.id
|
|
WHERE users.id = :userId ${orClause}
|
|
GROUP BY userconversations.ConversationId
|
|
HAVING count(*) = :usernamesLen
|
|
) q
|
|
JOIN conversations
|
|
ON conversations.id = q.ConversationId
|
|
JOIN messages
|
|
ON conversations.id = messages.ConversationId AND messages.id in
|
|
(
|
|
SELECT MAX(id)
|
|
FROM messages
|
|
WHERE messages.ConversationId = conversations.id
|
|
)
|
|
JOIN users
|
|
ON users.id = messages.UserId
|
|
JOIN userconversations
|
|
ON userconversations.UserId = users.id AND userconversations.ConversationId = conversations.id
|
|
|
|
ORDER BY messages.id DESC
|
|
|
|
LIMIT 10
|
|
OFFSET :offset
|
|
`;
|
|
|
|
let conversations = await sequelizeInstance.query(sql, {
|
|
replacements: replacementsObj,
|
|
type: sequelizeInstance.QueryTypes.SELECT,
|
|
model: Conversation
|
|
});
|
|
|
|
let mappedPropertiesPromises = conversations.map(async conversation => {
|
|
let json = await conversation.setName(userId);
|
|
|
|
json.Messages = [{
|
|
content: json['Messages.content'],
|
|
createdAt: json['Messages.createdAt'],
|
|
User: {
|
|
id: json['User.id'],
|
|
username: json['User.username']
|
|
}
|
|
}];
|
|
|
|
delete json['Messages.content'];
|
|
delete json['Messages.createdAt'];
|
|
delete json['User.id'];
|
|
delete json['User.username'];
|
|
|
|
return json;
|
|
});
|
|
let mappedProperties = await Promise.all(mappedPropertiesPromises);
|
|
|
|
return {
|
|
Conversations: mappedProperties,
|
|
continuePagination: mappedProperties.length === 10
|
|
};
|
|
};
|
|
|
|
exports.get = async function (userId, conversationId, page) {
|
|
let messageCount = await Message.count({
|
|
where: {
|
|
ConversationId: conversationId
|
|
}
|
|
});
|
|
|
|
let offset = messageCount - (page || 1) * 10;
|
|
let limit = 10;
|
|
if(offset < 0) {
|
|
limit = 10 + offset;
|
|
offset = 0;
|
|
}
|
|
|
|
let conversation = await Conversation.findById(conversationId, {
|
|
include: [
|
|
{
|
|
model: User,
|
|
where: { id: userId },
|
|
attributes: { exclude: ['hash'] }
|
|
},
|
|
{
|
|
model: Message,
|
|
include: [
|
|
{
|
|
model: User,
|
|
attributes: { exclude: ['hash'] }
|
|
}
|
|
],
|
|
limit,
|
|
offset,
|
|
order: [['id', 'ASC']]
|
|
}
|
|
]
|
|
});
|
|
|
|
if(!conversation) {
|
|
throw validationError({
|
|
message: 'Either the conversation doesn\'t exist or you\'re not part of the conversation'
|
|
});
|
|
} else {
|
|
let json = await conversation.setName(userId);
|
|
json.continuePagination = !!offset;
|
|
|
|
return json;
|
|
}
|
|
};
|
|
|
|
exports.getUserIds = async function (conversationId) {
|
|
let conversation = await Conversation.findById(conversationId, {
|
|
include: [{ model: User }]
|
|
});
|
|
|
|
if(!conversation) {
|
|
throw validationError({
|
|
message: 'The conversation doesn\'t exist'
|
|
});
|
|
} else {
|
|
return conversation.Users.map(user => user.id);
|
|
}
|
|
};
|
|
|
|
exports.updateLastRead = async function (conversationId, userId) {
|
|
let res = await UserConversation.update({
|
|
lastRead: new Date()
|
|
}, {
|
|
where: { ConversationId: conversationId, UserId: userId }
|
|
});
|
|
|
|
//Affected rows should always be 1
|
|
if(res[0] !== 1) {
|
|
throw validationError({
|
|
message: 'Either the conversationId or UserId is invalid'
|
|
});
|
|
} else {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
exports.updateName = async function (conversationId, userId, name) {
|
|
let conversation = await Conversation.findById(conversationId, {
|
|
include: [{ model: User }]
|
|
});
|
|
|
|
if(
|
|
!conversation ||
|
|
conversation.Users.find(u => u.id === userId) === undefined
|
|
) {
|
|
throw validationError({
|
|
message: 'Either the conversationId or userId is invalid'
|
|
});
|
|
}
|
|
|
|
let res = await Conversation.update({ name }, {
|
|
where: { id: conversationId }
|
|
});
|
|
|
|
return true;
|
|
}; |