const MessageModel = require('../model/message'); const UserModel = require('../model/user'); const ChatModel = require('../model/chat'); const fs = require('fs').promises; const s3 = require('../helpers/aws'); const AWS_BUCKET_NAME = process.env.AWS_BUCKET_NAME; require('dotenv').config(); const listMessages = async (req, res, next) => { try { const userId = req.user.id; const messages = await MessageModel.getList({ owner: userId }, req.query); return res.json({ status: 'success', code: 200, data: messages, }); } catch (e) { next(e); } }; const listMessagesById = async (req, res, next) => { try { const userId = req.user.id; const companionId = req.params.companionId; const messages = await MessageModel.getList( { owner: userId, companionId }, {} ); return res.json({ status: 'success', code: 200, data: messages, }); } catch (e) { next(e); } }; const updateMessageEmoji = async (req, res, next) => { try { const id = req.params.id; const userId = req.user.id; const { emoji } = req.body; const userMessage = await MessageModel.updateMessage(id, userId, { emoji }); await MessageModel.findByFieldsAndUpdate( userId, userMessage.idTime, userMessage.companionId, { emojiCompanion: emoji, } ); return res.status(200).json({ status: 'success', code: 200, data: {}, }); } catch (e) { next(e); } }; const updateMessagePin = async (req, res, next) => { try { const id = req.params.id; const userId = req.user.id; const { pinned } = req.body; const userMessage = await MessageModel.updateMessage(id, userId, { pinned, }); await MessageModel.findByFieldsAndUpdate( userId, userMessage.idTime, userMessage.companionId, { pinned, } ); return res.status(200).json({ status: 'success', code: 200, data: {}, }); } catch (e) { next(e); } }; const unpinAllMessage = async (req, res, next) => { try { const userId = req.user.id; const pinnedMessages = req.body.pinnedMessages; pinnedMessages.forEach(async (id) => { const userMessage = await MessageModel.updateMessage(id, userId, { pinned: false, }); await MessageModel.findByFieldsAndUpdate( userId, userMessage.idTime, userMessage.companionId, { pinned: false, } ); }); return res.status(200).json({ status: 'success', code: 200, data: {}, }); } catch (e) { next(e); } }; const removeMessage = async (req, res, next) => { try { const id = req.params.id; const userId = req.user.id; const userMessage = await MessageModel.remove(id, userId); await MessageModel.findByFieldsAndUpdateMany( { oldId: userMessage._id, }, { deleted: true, replyMessage: null, replyName: null, replyLastName: null, replyCaption: null, forwardMessage: null, forwardMessage: null, forwardName: null, forwardLastName: null, forwardCaption: null, fullType: null, companionIdForwardToAndFrom: null, oldId: null, } ); const companionMessage = await MessageModel.findByFields( userId, userMessage.idTime, userMessage.companionId ); await MessageModel.findByFieldsAndUpdateMany( { oldId: companionMessage._id, }, { deleted: true, replyMessage: null, replyName: null, replyLastName: null, replyCaption: null, forwardMessage: null, forwardMessage: null, forwardName: null, forwardLastName: null, forwardCaption: null, fullType: null, companionIdForwardToAndFrom: null, oldId: null, } ); await MessageModel.removeByFields( userId, userMessage.idTime, userMessage.companionId ); if (userMessage.type !== 'text') { const params = { Bucket: AWS_BUCKET_NAME, Key: `${userMessage.message}`, }; s3.deleteObject(params, async function (err, _data) { if (err) throw err; }); } const isChat = await ChatModel.getByField(userMessage.companionId, userId); const isCompanionChat = await ChatModel.getByField( userId, userMessage.companionId ); const { total, messages } = await MessageModel.getList( { owner: userId, companionId: userMessage.companionId }, {} ); const { total: Total } = await MessageModel.getList( { owner: userMessage.companionId, companionId: userId }, {} ); const seenCalculate = (seen, total) => { if (seen <= total) { return seen; } else { return total; } }; const isLastMessages = messages.slice(-1)[0] ? messages.slice(-1)[0] : null; await ChatModel.update(isChat._id, userId, { total: total, seen: seenCalculate(isChat.seen, total), seenCompanion: seenCalculate(isChat.seenCompanion, total), lastMessage: isLastMessages ? isLastMessages.type === 'text' ? isLastMessages.message : isLastMessages.fullType : null, lastMessageCreatedAt: isLastMessages ? isLastMessages.createdAt : null, }); await ChatModel.update(isCompanionChat._id, userMessage.companionId, { total: Total, seen: seenCalculate(isCompanionChat.seen, Total), seenCompanion: seenCalculate(isCompanionChat.seenCompanion, Total), lastMessage: isLastMessages ? isLastMessages.type === 'text' ? isLastMessages.message : isLastMessages.fullType : null, lastMessageCreatedAt: isLastMessages ? isLastMessages.createdAt : null, }); return res.json({ status: 'success', code: 200, data: {}, }); } catch (e) { next(e); } }; const removeSelected = async (req, res, next) => { try { const userId = req.user.id; const { selectedArr, companionId } = req.body; const toDeleteMessage = async (id) => { const userMessage = await MessageModel.remove(id, userId); await MessageModel.findByFieldsAndUpdateMany( { oldId: userMessage._id, }, { deleted: true, replyMessage: null, replyName: null, replyLastName: null, replyCaption: null, forwardMessage: null, forwardMessage: null, forwardName: null, forwardLastName: null, forwardCaption: null, fullType: null, companionIdForwardToAndFrom: null, oldId: null, } ); const companionMessage = await MessageModel.findByFields( userId, userMessage.idTime, companionId ); await MessageModel.findByFieldsAndUpdateMany( { oldId: companionMessage._id, }, { deleted: true, replyMessage: null, replyName: null, replyLastName: null, replyCaption: null, forwardMessage: null, forwardMessage: null, forwardName: null, forwardLastName: null, forwardCaption: null, fullType: null, companionIdForwardToAndFrom: null, oldId: null, } ); await MessageModel.removeByFields( userId, userMessage.idTime, companionId ); if (userMessage.type !== 'text') { const params = { Bucket: AWS_BUCKET_NAME, Key: `${userMessage.message}`, }; s3.deleteObject(params, async function (err, _data) { if (err) throw err; }); } }; await selectedArr.forEach(async (id) => await toDeleteMessage(id)); const isChat = await ChatModel.getByField(companionId, userId); const isCompanionChat = await ChatModel.getByField(userId, companionId); const { total, messages } = await MessageModel.getList( { owner: userId, companionId }, {} ); const { total: Total } = await MessageModel.getList( { owner: companionId, companionId: userId }, {} ); const seenCalculate = (seen, total) => { if (seen <= total) { return seen; } else { return total; } }; const isLastMessages = messages.slice(-1)[0] ? messages.slice(-1)[0] : null; await ChatModel.update(isChat._id, userId, { total: total, seen: seenCalculate(isChat.seen, total), seenCompanion: seenCalculate(isChat.seenCompanion, total), lastMessage: isLastMessages ? isLastMessages.type === 'text' ? isLastMessages.message : isLastMessages.fullType : null, lastMessageCreatedAt: isLastMessages ? isLastMessages.createdAt : null, }); await ChatModel.update(isCompanionChat._id, companionId, { total: Total, seen: seenCalculate(isCompanionChat.seen, Total), seenCompanion: seenCalculate(isCompanionChat.seenCompanion, Total), lastMessage: isLastMessages ? isLastMessages.type === 'text' ? isLastMessages.message : isLastMessages.fullType : null, lastMessageCreatedAt: isLastMessages ? isLastMessages.createdAt : null, }); return res.json({ status: 'success', code: 200, data: {}, }); } catch (e) { next(e); } }; const sentMessage = async (req, res, next) => { try { const { id, message, caption } = req.body; const idTime = Math.round(Date.now() / 1000); const user = req.user; const userId = user.id; const companion = await UserModel.findById(id); const isChat = await ChatModel.getByField(id, userId); const isCompanionChat = await ChatModel.getByField(userId, id); const { name, lastName, avatarUrl, color, number } = user; if (companion && isChat && isCompanionChat) { const newMessage = await MessageModel.add({ message, name, lastName, avatarUrl, color, number, type: 'text', caption, idTime, companionIdFlow: userId, companionId: id, owner: userId, }); await MessageModel.add({ message, name: isCompanionChat.name, lastName: isCompanionChat.lastName, avatarUrl, color, number, type: 'text', caption, idTime, companionIdFlow: userId, companionId: userId, owner: id, }); const { total } = await MessageModel.getList( { owner: userId, companionId: id }, {} ); await ChatModel.update(isChat._id, userId, { total, seen: total, watched: false, lastMessage: message, lastMessageCreatedAt: newMessage.createdAt, }); const { total: Total } = await MessageModel.getList( { owner: id, companionId: userId }, {} ); await ChatModel.update(isCompanionChat._id, id, { total: Total, seenCompanion: Total, lastMessage: message, lastMessageCreatedAt: newMessage.createdAt, }); return res.status(201).json({ status: 'success', code: 201, data: newMessage, }); } } catch (e) { next(e); } }; const sentMessageReply = async (req, res, next) => { try { const { id, message, caption } = req.body; const idTime = Math.round(Date.now() / 1000); const user = req.user; const userId = user.id; const userMessage = await MessageModel.getById(id, userId); const companionMessage = await MessageModel.findByFields( userId, userMessage.idTime, userMessage.companionId ); const isChat = await ChatModel.getByField(userMessage.companionId, userId); const isCompanionChat = await ChatModel.getByField( userId, userMessage.companionId ); if (isChat && isCompanionChat && userMessage && companionMessage) { const newMessage = await MessageModel.add({ message, replyMessage: userMessage.message, name: user.name, lastName: user.lastName, replyName: userMessage.name, replyLastName: userMessage.lastName, avatarUrl: user.avatarUrl, color: user.color, number: user.number, type: 'text', fullType: userMessage.fullType, caption, replyCaption: userMessage.caption, idTime, oldId: id, companionIdFlow: userId, companionId: userMessage.companionId, owner: userId, }); await MessageModel.add({ message, replyMessage: companionMessage.message, name: isCompanionChat.name, lastName: isCompanionChat.lastName, replyName: companionMessage.name, replyLastName: companionMessage.lastName, avatarUrl: user.avatarUrl, color: user.color, number: user.number, type: 'text', fullType: companionMessage.fullType, caption, replyCaption: companionMessage.caption, idTime, oldId: companionMessage._id, companionIdFlow: userId, companionId: userId, owner: userMessage.companionId, }); const { total } = await MessageModel.getList( { owner: userId, companionId: userMessage.companionId }, {} ); await ChatModel.update(isChat._id, userId, { total, seen: total, watched: false, lastMessage: message, lastMessageCreatedAt: newMessage.createdAt, }); const { total: Total } = await MessageModel.getList( { owner: userMessage.companionId, companionId: userId }, {} ); await ChatModel.update(isCompanionChat._id, userMessage.companionId, { total: Total, seenCompanion: Total, lastMessage: message, lastMessageCreatedAt: newMessage.createdAt, }); return res.status(201).json({ status: 'success', code: 201, data: newMessage, }); } } catch (e) { next(e); } }; const sentMessageForward = async (req, res, next) => { try { const { id, companionIdForwardToAndFrom, message, caption } = req.body; const idTime = Math.round(Date.now() / 1000); const user = req.user; const userId = user.id; const userMessage = await MessageModel.getById(id, userId); const isChat = await ChatModel.getByField( companionIdForwardToAndFrom, userId ); const companionMessage = await MessageModel.findByFields( userId, userMessage.idTime, userMessage.companionId ); const isCompanionUser = await UserModel.findById(userMessage.companionId); const isForwardChat = await ChatModel.getByField( userId, companionIdForwardToAndFrom ); if ( userMessage && isCompanionUser && isChat && isForwardChat && companionMessage ) { const newMessage = await MessageModel.add({ message, caption, forwardMessage: userMessage.message, forwardCaption: userMessage.caption, name: user.name, lastName: user.lastName, avatarUrl: user.avatarUrl, color: user.color, number: user.number, type: 'text', fullType: userMessage.fullType, forwardName: user.number === userMessage.number ? user.name : isCompanionUser.name, forwardLastName: user.number === userMessage.number ? user.lastName : isCompanionUser.lastName, oldId: userMessage._id, idTime, companionIdFlow: userId, companionIdForwardToAndFrom: userMessage.companionId, companionId: companionIdForwardToAndFrom, owner: userId, }); await MessageModel.add({ message, caption, forwardMessage: userMessage.message, forwardCaption: userMessage.caption, name: isForwardChat.name, lastName: isForwardChat.lastName, avatarUrl: user.avatarUrl, color: user.color, number: user.number, type: 'text', fullType: userMessage.fullType, forwardName: user.number === userMessage.number ? user.name : isCompanionUser.name, forwardLastName: user.number === userMessage.number ? user.lastName : isCompanionUser.lastName, oldId: companionMessage._id, idTime, companionIdFlow: userId, companionId: userId, companionIdForwardToAndFrom: userMessage.companionId, owner: companionIdForwardToAndFrom, }); const { total } = await MessageModel.getList( { owner: userId, companionId: companionIdForwardToAndFrom }, {} ); await ChatModel.update(isChat._id, userId, { total, seen: total, watched: false, lastMessage: message, lastMessageCreatedAt: newMessage.createdAt, }); const { total: Total } = await MessageModel.getList( { owner: companionIdForwardToAndFrom, companionId: userId }, {} ); await ChatModel.update(isForwardChat._id, companionIdForwardToAndFrom, { total: Total, seenCompanion: Total, lastMessage: message, lastMessageCreatedAt: newMessage.createdAt, }); return res.status(201).json({ status: 'success', code: 201, data: newMessage, }); } } catch (e) { next(e); } }; const imageMessage = async (req, res, next) => { try { const userId = req.user.id; const [id, ...rest] = req.params.companionIdAndCaption.split(' '); const caption = rest.join(' ').slice(0, -1); const idTime = Math.round(Date.now() / 1000); const isChat = await ChatModel.getByField(id, userId); const isCompanionChat = await ChatModel.getByField(userId, id); const originalName = req.file.originalname; const pathToFile = req.file.path; const fullType = req.file.mimetype; const imgUrl = `${Math.round(Date.now() / 1000)}${userId}${originalName}`; const fileContent = await fs.readFile(pathToFile); const params = { Bucket: AWS_BUCKET_NAME, Key: `${imgUrl}`, Body: fileContent, }; s3.upload(params, async (err, _data) => { if (err) throw err; fs.unlink(pathToFile); }); if (isChat && isCompanionChat) { const { name, lastName, avatarUrl, color, number } = req.user; const newMessage = await MessageModel.add({ message: imgUrl, name, lastName, avatarUrl, color, number, type: 'image', fullType, caption, idTime, companionIdFlow: userId, companionId: id, owner: userId, }); await MessageModel.add({ message: imgUrl, name: isCompanionChat.name, lastName: isCompanionChat.lastName, avatarUrl, color, number, type: 'image', fullType, caption, idTime, companionIdFlow: userId, companionId: userId, owner: id, }); const { total } = await MessageModel.getList( { owner: userId, companionId: id }, {} ); await ChatModel.update(isChat._id, userId, { total, seen: total, watched: false, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); const { total: Total } = await MessageModel.getList( { owner: id, companionId: userId }, {} ); await ChatModel.update(isCompanionChat._id, id, { total: Total, seenCompanion: Total, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); return res.status(201).json({ status: 'success', code: 201, data: newMessage, }); } } catch (e) { next(e); } }; const audioMessage = async (req, res, next) => { try { const userId = req.user.id; const [id, ...rest] = req.params.companionIdAndCaption.split(' '); let caption = rest.join(' '); if (caption.length === 1) caption.slice(0, -1); const idTime = Math.round(Date.now() / 1000); const isChat = await ChatModel.getByField(id, userId); const isCompanionChat = await ChatModel.getByField(userId, id); const originalName = req.file.originalname; const pathToFile = req.file.path; const fullType = req.file.mimetype; const audioUrl = `${Math.round(Date.now() / 1000)}${originalName}`; const fileContent = await fs.readFile(pathToFile); const params = { Bucket: AWS_BUCKET_NAME, Key: `${audioUrl}`, Body: fileContent, }; s3.upload(params, async (err, _data) => { if (err) throw err; fs.unlink(pathToFile); }); if (isChat && isCompanionChat) { const { name, lastName, avatarUrl, color, number } = req.user; const newMessage = await MessageModel.add({ message: audioUrl, name, lastName, avatarUrl, color, number, type: 'audio', fullType, caption, idTime, companionIdFlow: userId, companionId: id, owner: userId, }); await MessageModel.add({ message: audioUrl, name: isCompanionChat.name, lastName: isCompanionChat.lastName, avatarUrl, color, number, type: 'audio', fullType, caption, idTime, companionIdFlow: userId, companionId: userId, owner: id, }); const { total } = await MessageModel.getList( { owner: userId, companionId: id }, {} ); await ChatModel.update(isChat._id, userId, { total, seen: total, watched: false, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); const { total: Total } = await MessageModel.getList( { owner: id, companionId: userId }, {} ); await ChatModel.update(isCompanionChat._id, id, { total: Total, seenCompanion: Total, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); return res.status(201).json({ status: 'success', code: 201, data: newMessage, }); } } catch (e) { next(e); } }; const videoMessage = async (req, res, next) => { try { const userId = req.user.id; const [id, ...rest] = req.params.companionIdAndCaption.split(' '); let caption = rest.join(' '); if (caption.length === 1) caption.slice(0, -1); const idTime = Math.round(Date.now() / 1000); const isChat = await ChatModel.getByField(id, userId); const isCompanionChat = await ChatModel.getByField(userId, id); const originalName = req.file.originalname; const pathToFile = req.file.path; const videoUrl = `${Math.round(Date.now() / 1000)}${originalName}`; const fullType = req.file.mimetype; const fileContent = await fs.readFile(pathToFile); const params = { Bucket: AWS_BUCKET_NAME, Key: `${videoUrl}`, Body: fileContent, }; s3.upload(params, async (err, _data) => { if (err) throw err; fs.unlink(pathToFile); }); if (isChat && isCompanionChat) { const { name, lastName, avatarUrl, color, number } = req.user; const newMessage = await MessageModel.add({ message: videoUrl, name: isCompanionChat.name, lastName: isCompanionChat.lastName, avatarUrl, color, number, type: 'video', fullType, caption, idTime, companionIdFlow: userId, companionId: id, owner: userId, }); await MessageModel.add({ message: videoUrl, name, lastName, avatarUrl, color, number, type: 'video', fullType, caption, idTime, companionIdFlow: userId, companionId: userId, owner: id, }); const { total } = await MessageModel.getList( { owner: userId, companionId: id }, {} ); await ChatModel.update(isChat._id, userId, { total, seen: total, watched: false, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); const { total: Total } = await MessageModel.getList( { owner: id, companionId: userId }, {} ); await ChatModel.update(isCompanionChat._id, id, { total: Total, seenCompanion: Total, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); return res.status(201).json({ status: 'success', code: 201, data: newMessage, }); } } catch (e) { next(e); } }; const fileMessage = async (req, res, next) => { try { const userId = req.user.id; const [id, ...rest] = req.params.companionIdAndCaption.split(' '); let caption = rest.join(' '); if (caption.length === 1) caption.slice(0, -1); const idTime = Math.round(Date.now() / 1000); const isChat = await ChatModel.getByField(id, userId); const isCompanionChat = await ChatModel.getByField(userId, id); const pathToFile = req.file.path; const fullType = req.file.mimetype; let type; switch (fullType) { case 'application/pdf': type = 'pdf'; break; case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': type = 'docx'; break; case 'application/octet-stream': type = 'docx'; break; default: break; } const fileUrl = `${Math.round(Date.now() / 1000)}file.${type}`; const fileContent = await fs.readFile(pathToFile); const params = { Bucket: AWS_BUCKET_NAME, Key: `${fileUrl}`, Body: fileContent, }; s3.upload(params, async (err, _data) => { if (err) throw err; fs.unlink(pathToFile); }); if (isChat && isCompanionChat) { const { name, lastName, avatarUrl, color, number } = req.user; const newMessage = await MessageModel.add({ message: fileUrl, name, lastName, avatarUrl, color, number, type, fullType, caption, idTime, companionIdFlow: userId, companionId: id, owner: userId, }); await MessageModel.add({ message: fileUrl, name: isCompanionChat.name, lastName: isCompanionChat.lastName, avatarUrl, color, number, type, fullType, caption, idTime, companionIdFlow: userId, companionId: userId, owner: id, }); const { total } = await MessageModel.getList( { owner: userId, companionId: id }, {} ); await ChatModel.update(isChat._id, userId, { total, seen: total, watched: false, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); const { total: Total } = await MessageModel.getList( { owner: id, companionId: userId }, {} ); await ChatModel.update(isCompanionChat._id, id, { total: Total, seenCompanion: Total, lastMessage: fullType, lastMessageCreatedAt: newMessage.createdAt, }); return res.status(201).json({ status: 'success', code: 201, data: newMessage, }); } } catch (e) { next(e); } }; module.exports = { listMessages, removeMessage, removeSelected, updateMessageEmoji, updateMessagePin, unpinAllMessage, listMessagesById, sentMessage, sentMessageReply, sentMessageForward, imageMessage, audioMessage, videoMessage, fileMessage, };