You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

153 lines
4.4 KiB

import { models } from '../models'
import * as LND from '../utils/lightning'
import {personalizeMessage, decryptMessage} from '../utils/msg'
import * as path from 'path'
import * as tribes from '../utils/tribes'
const constants = require(path.join(__dirname,'../../config/constants.json'))
type NetworkType = undefined | 'mqtt' | 'lightning'
export async function sendMessage(params) {
const { type, chat, message, sender, amount, success, failure, skipPubKey } = params
const m = newmsg(type, chat, sender, message)
let msg = m
// console.log(type,message)
if(!(sender&&sender.publicKey)) {
console.log("NO SENDER?????")
return
}
let contactIds = (typeof chat.contactIds==='string' ? JSON.parse(chat.contactIds) : chat.contactIds) || []
if(contactIds.length===1) {
if (contactIds[0]===1) {
if(success) success(true)
return // if no contacts thats fine (like create public tribe)
}
}
let networkType:NetworkType = undefined
const isTribe = chat.type===constants.chat_types.tribe
let isTribeOwner = false
const chatUUID = chat.uuid
if(isTribe) {
if(type===constants.message_types.confirmation) {
return // dont send confs for tribe
}
console.log("is tribe!")
const tribeOwnerPubKey = chat.ownerPubkey
if(sender.publicKey===tribeOwnerPubKey){
console.log('im owner! mqtt!')
isTribeOwner = true
networkType = 'mqtt' // broadcast to all
// decrypt message.content and message.mediaKey w groupKey
msg = await decryptMessage(msg, chat)
} else {
// if tribe, send to owner only
const tribeOwner = await models.Contact.findOne({where: {publicKey:tribeOwnerPubKey}})
contactIds = tribeOwner ? [tribeOwner.id] : []
}
}
let yes:any = null
let no:any = null
console.log('all contactIds',contactIds)
await asyncForEach(contactIds, async contactId => {
if (contactId == 1) { // dont send to self
return
}
const contact = await models.Contact.findOne({ where: { id: contactId } })
const destkey = contact.publicKey
if(destkey===skipPubKey) {
return // skip (for tribe owner broadcasting, not back to the sender)
}
console.log('-> sending to ', contact.id, destkey)
const m = await personalizeMessage(msg, contact, isTribeOwner)
const opts = {
dest: destkey,
data: m,
amt: Math.max((amount||0), 3)
}
try {
const mqttTopic = networkType==='mqtt' ? `${destkey}/${chatUUID}` : ''
const r = await signAndSend(opts, sender.publicKey, mqttTopic)
yes = r
} catch (e) {
console.log("KEYSEND ERROR", e)
no = e
}
await sleep(2)
})
if(yes){
if(success) success(yes)
} else {
if(failure) failure(no)
}
}
export function signAndSend(opts, pubkey, mqttTopic?:string){
// console.log('sign and send!!!!',opts.data)
return new Promise(async function(resolve, reject) {
if(!opts.data || typeof opts.data!=='object') {
return reject('object plz')
}
let data = JSON.stringify(opts.data)
const sig = await LND.signAscii(data)
data = data + sig
// console.log("ACTUALLY SEND", mqttTopic)
try {
if(mqttTopic) {
await tribes.publish(mqttTopic, data)
} else {
await LND.keysendMessage({...opts,data})
}
resolve(true)
} catch(e) {
reject(e)
}
})
}
export function newmsg(type, chat, sender, message){
const includeGroupKey = type===constants.message_types.group_create || type===constants.message_types.group_invite
const includeAlias = sender && sender.alias && chat.type===constants.chat_types.tribe
return {
type: type,
chat: {
uuid: chat.uuid,
...chat.name && { name: chat.name },
...(chat.type||chat.type===0) && { type: chat.type },
...chat.members && { members: chat.members },
...(includeGroupKey&&chat.groupKey) && { groupKey: chat.groupKey },
...(includeGroupKey&&chat.host) && { host: chat.host }
},
message: message,
sender: {
...includeAlias && {alias: sender.alias},
pub_key: sender.publicKey,
// ...sender.contactKey && {contact_key: sender.contactKey}
}
}
}
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
// function urlBase64FromHex(ascii){
// return Buffer.from(ascii,'hex').toString('base64').replace(/\//g, '_').replace(/\+/g, '-')
// }
// function urlBase64FromBytes(buf){
// return Buffer.from(buf).toString('base64').replace(/\//g, '_').replace(/\+/g, '-')
// }