import { models } from './models' import * as md5 from 'md5' import { keysendMessage } from './utils/lightning' import {personalizeMessage} from './utils/msg' const constants = require('../config/constants.json'); const findOrCreateChat = async (params) => { const { chat_id, owner_id, recipient_id } = params let chat let date = new Date(); date.setMilliseconds(0) if (chat_id) { chat = await models.Chat.findOne({ where: { id: chat_id } }) // console.log('findOrCreateChat: chat_id exists') } else { console.log("chat does not exists, create new") const owner = await models.Contact.findOne({ where: { id: owner_id } }) const recipient = await models.Contact.findOne({ where: { id: recipient_id } }) const uuid = md5([owner.publicKey, recipient.publicKey].sort().join("-")) // find by uuid chat = await models.Chat.findOne({ where:{uuid} }) if(!chat){ // no chat! create new chat = await models.Chat.create({ uuid: uuid, contactIds: JSON.stringify([parseInt(owner_id), parseInt(recipient_id)]), createdAt: date, updatedAt: date, type: constants.chat_types.conversation }) } } return chat } const sendContactKeys = async (args) => { const { type, contactIds, contactPubKey, sender, success, failure } = args const msg = newkeyexchangemsg(type, sender) let yes:any = null let no:any = null let cids = contactIds if(!contactIds) cids = [null] // nully await asyncForEach(cids, async contactId => { let destination_key:string if(!contactId){ // nully destination_key = contactPubKey } else { if (contactId == sender.id) { return } const contact = await models.Contact.findOne({ where: { id: contactId } }) destination_key = contact.publicKey } performKeysendMessage({ destination_key, amount: 3, msg: JSON.stringify(msg), success: (data) => { yes = data }, failure: (error) => { no = error } }) }) if(no && failure){ failure(no) } if(!no && yes && success){ success(yes) } } const sendMessage = async (params) => { const { type, chat, message, sender, amount, success, failure } = params const m = newmsg(type, chat, sender, message) const contactIds = typeof chat.contactIds==='string' ? JSON.parse(chat.contactIds) : chat.contactIds let yes:any = null let no:any = null console.log('all contactIds',contactIds) await asyncForEach(contactIds, async contactId => { if (contactId == sender.id) { return } console.log('-> sending to contact #', contactId) const contact = await models.Contact.findOne({ where: { id: contactId } }) const destkey = contact.publicKey const finalMsg = await personalizeMessage(m, contactId, destkey) const opts = { dest: destkey, data: JSON.stringify(finalMsg), amt: amount || 3, } try { const r = await keysendMessage(opts) yes = r } catch (e) { console.log("KEYSEND ERROR", e) no = e } }) if(yes){ if(success) success(yes) } else { if(failure) failure(no) } } const performKeysendMessage = async ({ destination_key, amount, msg, success, failure }) => { const opts = { dest: destination_key, data: msg || JSON.stringify({}), amt: Math.max(amount, 3) } try { const r = await keysendMessage(opts) console.log("=> external keysend") if (success) success(r) } catch (e) { console.log("MESSAGE ERROR", e) if (failure) failure(e) } } async function findOrCreateContactByPubkey(senderPubKey) { let sender = await models.Contact.findOne({ where: { publicKey: senderPubKey } }) if (!sender) { sender = await models.Contact.create({ publicKey: senderPubKey, alias: "Unknown", status: 1 }) const owner = await models.Contact.findOne({ where: { isOwner: true } }) sendContactKeys({ contactIds: [sender.id], sender: owner, type: constants.message_types.contact_key, }) } return sender } async function findOrCreateChatByUUID(chat_uuid, contactIds) { let chat = await models.Chat.findOne({ where: { uuid: chat_uuid } }) if (!chat) { var date = new Date(); date.setMilliseconds(0) chat = await models.Chat.create({ uuid: chat_uuid, contactIds: JSON.stringify(contactIds || []), createdAt: date, updatedAt: date, type: 0 // conversation }) } return chat } async function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } async function parseReceiveParams(payload) { const dat = payload.content || payload const sender_pub_key = dat.sender.pub_key const chat_uuid = dat.chat.uuid const chat_type = dat.chat.type const chat_members: { [k: string]: any } = dat.chat.members || {} const chat_name = dat.chat.name const amount = dat.message.amount const content = dat.message.content const mediaToken = dat.message.mediaToken const msg_id = dat.message.id||0 const mediaKey = dat.message.mediaKey const mediaType = dat.message.mediaType const isGroup = chat_type && chat_type == constants.chat_types.group let sender let chat const owner = await models.Contact.findOne({ where: { isOwner: true } }) if (isGroup) { sender = await models.Contact.findOne({ where: { publicKey: sender_pub_key } }) chat = await models.Chat.findOne({ where: { uuid: chat_uuid } }) } else { sender = await findOrCreateContactByPubkey(sender_pub_key) chat = await findOrCreateChatByUUID( chat_uuid, [parseInt(owner.id), parseInt(sender.id)] ) } return { owner, sender, chat, sender_pub_key, chat_uuid, amount, content, mediaToken, mediaKey, mediaType, chat_type, msg_id, chat_members, chat_name } } export { findOrCreateChat, sendMessage, sendContactKeys, findOrCreateContactByPubkey, findOrCreateChatByUUID, sleep, parseReceiveParams, performKeysendMessage } async function asyncForEach(array, callback) { for (let index = 0; index < array.length; index++) { await callback(array[index], index, array); } } function newmsg(type, chat, sender, message){ return { type: type, chat: { uuid: chat.uuid, ...chat.name && { name: chat.name }, ...chat.type && { type: chat.type }, ...chat.members && { members: chat.members }, }, message: message, // sender: { // pub_key: sender.publicKey, // // ...sender.contactKey && {contact_key: sender.contactKey} // } } } function newkeyexchangemsg(type, sender){ return { type: type, sender: { // pub_key: sender.publicKey, contact_key: sender.contactKey, ...sender.alias && {alias: sender.alias}, // ...sender.photoUrl && {photoUrl: sender.photoUrl} } } }