import {models} from '../models' import { Op } from 'sequelize' import { indexBy } from 'underscore' import { sendNotification } from '../hub' import * as socket from '../utils/socket' import * as jsonUtils from '../utils/json' import * as helpers from '../helpers' import { success } from '../utils/res' import * as timers from '../utils/timers' import {sendConfirmation} from './confirmations' import * as path from 'path' import * as network from '../network' import * as short from 'short-uuid' const constants = require(path.join(__dirname,'../../config/constants.json')) export const getMessages = async (req, res) => { const dateToReturn = req.query.date; if (!dateToReturn) { return getAllMessages(req, res) } console.log(dateToReturn) const owner = await models.Contact.findOne({ where: { isOwner: true } }) // const chatId = req.query.chat_id let newMessagesWhere = { date: { [Op.gte]: dateToReturn }, [Op.or]: [ {receiver: owner.id}, {receiver: null} ] } let confirmedMessagesWhere = { updated_at: { [Op.gte]: dateToReturn }, status: {[Op.or]: [ constants.statuses.received, ]}, sender: owner.id } let deletedMessagesWhere = { updated_at: { [Op.gte]: dateToReturn }, status: {[Op.or]: [ constants.statuses.deleted ]}, } // if (chatId) { // newMessagesWhere.chat_id = chatId // confirmedMessagesWhere.chat_id = chatId // } const newMessages = await models.Message.findAll({ where: newMessagesWhere }) const confirmedMessages = await models.Message.findAll({ where: confirmedMessagesWhere }) const deletedMessages = await models.Message.findAll({ where: deletedMessagesWhere }) const chatIds: number[] = [] newMessages.forEach(m => { if(!chatIds.includes(m.chatId)) chatIds.push(m.chatId) }) confirmedMessages.forEach(m => { if(!chatIds.includes(m.chatId)) chatIds.push(m.chatId) }) deletedMessages.forEach(m => { if(!chatIds.includes(m.chatId)) chatIds.push(m.chatId) }) let chats = chatIds.length > 0 ? await models.Chat.findAll({ where: {deleted:false, id: chatIds} }) : [] const chatsById = indexBy(chats, 'id') res.json({ success: true, response: { new_messages: newMessages.map(message => jsonUtils.messageToJson(message, chatsById[parseInt(message.chatId)]) ), confirmed_messages: confirmedMessages.map(message => jsonUtils.messageToJson(message, chatsById[parseInt(message.chatId)]) ), deleted_messages: deletedMessages.map(message => jsonUtils.messageToJson(message, chatsById[parseInt(message.chatId)]) ) } }); res.status(200) res.end() } export const getAllMessages = async (req, res) => { const limit = (req.query.limit && parseInt(req.query.limit)) || 1000 const offset = (req.query.offset && parseInt(req.query.offset)) || 0 const messages = await models.Message.findAll({ order: [['id', 'asc']], limit, offset }) const chatIds = messages.map(m => m.chatId) console.log(`=> getAllMessages, limit: ${limit}, offset: ${offset}`) let chats = chatIds.length > 0 ? await models.Chat.findAll({ where: {deleted:false, id: chatIds} }) : [] const chatsById = indexBy(chats, 'id') success(res, { new_messages: messages.map( message => jsonUtils.messageToJson(message, chatsById[parseInt(message.chatId)]) ), confirmed_messages: [] }) }; export async function deleteMessage(req, res){ const id = parseInt(req.params.id) const message = await models.Message.findOne({where:{id}}) const uuid = message.uuid await message.update({status: constants.statuses.deleted}) const chat_id = message.chatId let chat if(chat_id) { chat = await models.Chat.findOne({where:{id:chat_id}}) } success(res, jsonUtils.messageToJson(message, chat)) if(!chat) return const isTribe = chat.type===constants.chat_types.tribe const owner = await models.Contact.findOne({ where: { isOwner: true }}) const isTribeOwner = isTribe && owner.publicKey===chat.ownerPubkey if(isTribeOwner) { timers.removeTimerByMsgId(id) } network.sendMessage({ chat: chat, sender: owner, type: constants.message_types.delete, message: {id,uuid}, }) } export const sendMessage = async (req, res) => { // try { // schemas.message.validateSync(req.body) // } catch(e) { // return failure(res, e.message) // } const { contact_id, text, remote_text, chat_id, remote_text_map, amount, reply_uuid, } = req.body var date = new Date(); date.setMilliseconds(0) const owner = await models.Contact.findOne({ where: { isOwner: true }}) const chat = await helpers.findOrCreateChat({ chat_id, owner_id: owner.id, recipient_id: contact_id, }) const remoteMessageContent = remote_text_map?JSON.stringify(remote_text_map) : remote_text const msg:{[k:string]:any}={ chatId: chat.id, uuid: short.generate(), type: constants.message_types.message, sender: owner.id, amount: amount||0, date: date, messageContent: text, remoteMessageContent, status: constants.statuses.pending, createdAt: date, updatedAt: date, } if(reply_uuid) msg.replyUuid=reply_uuid // console.log(msg) const message = await models.Message.create(msg) success(res, jsonUtils.messageToJson(message, chat)) const msgToSend:{[k:string]:any} = { id: message.id, uuid: message.uuid, content: remote_text_map || remote_text || text } if(reply_uuid) msgToSend.replyUuid=reply_uuid network.sendMessage({ chat: chat, sender: owner, amount: amount||0, type: constants.message_types.message, message: msgToSend, }) } export const receiveMessage = async (payload) => { // console.log('received message', { payload }) var date = new Date(); date.setMilliseconds(0) const total_spent = 1 const {owner, sender, chat, content, remote_content, msg_id, chat_type, sender_alias, msg_uuid, date_string, reply_uuid} = await helpers.parseReceiveParams(payload) if(!owner || !sender || !chat) { return console.log('=> no group chat!') } const text = content if(date_string) date=new Date(date_string) const msg:{[k:string]:any} = { chatId: chat.id, uuid: msg_uuid, type: constants.message_types.message, asciiEncodedTotal: total_spent, sender: sender.id, date: date, messageContent: text, createdAt: date, updatedAt: date, status: constants.statuses.received } const isTribe = chat_type===constants.chat_types.tribe if(isTribe) { msg.senderAlias = sender_alias if(remote_content) msg.remoteMessageContent=remote_content } if(reply_uuid) msg.replyUuid = reply_uuid const message = await models.Message.create(msg) // console.log('saved message', message.dataValues) socket.sendJson({ type: 'message', response: jsonUtils.messageToJson(message, chat, sender) }) sendNotification(chat, msg.senderAlias||sender.alias, 'message') const theChat = {...chat.dataValues, contactIds:[sender.id]} sendConfirmation({ chat:theChat, sender: owner, msg_id }) } export const receiveDeleteMessage = async (payload) => { console.log('=> received delete message') const {owner, sender, chat, chat_type, msg_uuid} = await helpers.parseReceiveParams(payload) if(!owner || !sender || !chat) { return console.log('=> no group chat!') } const isTribe = chat_type===constants.chat_types.tribe // in tribe this is already validated on admin's node let where:{[k:string]:any} = {uuid: msg_uuid} if(!isTribe) { where.sender = sender.id // validate sender } const message = await models.Message.findOne({where}) if(!message) return await message.update({status: constants.statuses.deleted}) socket.sendJson({ type: 'delete', response: jsonUtils.messageToJson(message, chat, sender) }) } export const readMessages = async (req, res) => { const chat_id = req.params.chat_id; const owner = await models.Contact.findOne({ where: { isOwner: true }}) models.Message.update({ seen: true }, { where: { sender: { [Op.ne]: owner.id }, chatId: chat_id } }); success(res, {}) } export const clearMessages = (req, res) => { models.Message.destroy({ where: {}, truncate: true }) success(res, {}) }