Browse Source

Merge pull request #38 from stakwork/replay

Replay
feature/dockerfile-arm v0.9.5
Evan Feenstra 5 years ago
committed by GitHub
parent
commit
c3cf4854f1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 210
      api/controllers/chatTribes.ts
  2. 281
      api/controllers/chats.ts
  3. 155
      api/controllers/index.ts
  4. 3
      api/controllers/messages.ts
  5. 5
      api/helpers.ts
  6. 4
      api/network/index.ts
  7. 23
      api/network/receive.ts
  8. 2
      api/network/send.ts
  9. 201
      dist/api/controllers/chatTribes.js
  10. 1
      dist/api/controllers/chatTribes.js.map
  11. 265
      dist/api/controllers/chats.js
  12. 2
      dist/api/controllers/chats.js.map
  13. 142
      dist/api/controllers/index.js
  14. 2
      dist/api/controllers/index.js.map
  15. 4
      dist/api/controllers/messages.js
  16. 2
      dist/api/controllers/messages.js.map
  17. 3
      dist/api/helpers.js
  18. 2
      dist/api/helpers.js.map
  19. 1
      dist/api/network/index.js
  20. 2
      dist/api/network/index.js.map
  21. 25
      dist/api/network/receive.js
  22. 2
      dist/api/network/receive.js.map
  23. 1
      dist/api/network/send.js
  24. 2
      dist/api/network/send.js.map

210
api/controllers/chatTribes.ts

@ -0,0 +1,210 @@
import { models } from '../models'
import * as jsonUtils from '../utils/json'
import { success, failure } from '../utils/res'
import * as network from '../network'
import * as rsa from '../crypto/rsa'
import * as tribes from '../utils/tribes'
import * as path from 'path'
import {personalizeMessage, decryptMessage} from '../utils/msg'
const constants = require(path.join(__dirname,'../../config/constants.json'))
async function joinTribe(req, res){
console.log('=> joinTribe')
const { uuid, group_key, name, host, amount, img, owner_pubkey, owner_alias } = req.body
const existing = await models.Chat.findOne({where:{uuid}})
if(existing) {
console.log('[tribes] u are already in this tribe')
return
}
if(!owner_pubkey || !group_key || !uuid) {
console.log('[tribes] missing required params')
return
}
const ownerPubKey = owner_pubkey
// verify signature here?
const tribeOwner = await models.Contact.findOne({ where: { publicKey: ownerPubKey } })
let theTribeOwner
const owner = await models.Contact.findOne({ where: { isOwner: true } })
const contactIds = [owner.id]
if (tribeOwner) {
theTribeOwner = tribeOwner // might already include??
if(!contactIds.includes(tribeOwner.id)) contactIds.push(tribeOwner.id)
} else {
const createdContact = await models.Contact.create({
publicKey: ownerPubKey,
contactKey: '',
alias: owner_alias||'Unknown',
status: 1,
fromGroup: true,
})
theTribeOwner = createdContact
contactIds.push(createdContact.id)
}
let date = new Date()
date.setMilliseconds(0)
const chatParams = {
uuid: uuid,
contactIds: JSON.stringify(contactIds),
photoUrl: img||'',
createdAt: date,
updatedAt: date,
name: name,
type: constants.chat_types.tribe,
host: host || tribes.getHost(),
groupKey: group_key,
ownerPubkey: owner_pubkey,
}
network.sendMessage({ // send my data to tribe owner
chat: {
...chatParams, members: {
[owner.publicKey]: {
key: owner.contactKey,
alias: owner.alias||''
}
}
},
amount:amount||0,
sender: owner,
message: {},
type: constants.message_types.group_join,
failure: function (e) {
failure(res, e)
},
success: async function () {
const chat = await models.Chat.create(chatParams)
models.ChatMember.create({
contactId: theTribeOwner.id,
chatId: chat.id,
role: constants.chat_roles.owner,
lastActive: date,
})
success(res, jsonUtils.chatToJson(chat))
}
})
}
async function editTribe(req, res) {
const {
name,
is_listed,
price_per_message,
price_to_join,
img,
description,
tags,
} = req.body
const { id } = req.params
if(!id) return failure(res, 'group id is required')
const chat = await models.Chat.findOne({where:{id}})
if(!chat) {
return failure(res, 'cant find chat')
}
const owner = await models.Contact.findOne({ where: { isOwner: true } })
let okToUpdate = true
if(is_listed) {
try{
await tribes.edit({
uuid: chat.uuid,
name: name,
host: chat.host,
price_per_message: price_per_message||0,
price_to_join: price_to_join||0,
description,
tags,
img,
owner_alias: owner.alias,
})
} catch(e) {
okToUpdate = false
}
}
if(okToUpdate) {
await chat.update({
photoUrl: img||'',
name: name,
pricePerMessage: price_per_message||0,
priceToJoin: price_to_join||0
})
success(res, jsonUtils.chatToJson(chat))
} else {
failure(res, 'failed to update tribe')
}
}
async function replayChatHistory(chat, contact) {
const msgs = await models.Message.findAll({ order: [['id', 'asc']], limit:40 })
const owner = await models.Contact.findOne({ where: { isOwner: true } })
asyncForEach(msgs, async m=>{
const sender = {
...owner.dataValues,
...m.senderAlias && {alias: m.senderAlias},
}
let msg = network.newmsg(m.type, chat, sender, {
content: m.remoteContent, // replace with the received content (u are owner)
mediaKey: m.mediaKey,
mediaType: m.mediaType,
mediaToken: m.mediaToken
})
msg = await decryptMessage(msg, chat)
const data = await personalizeMessage(msg, contact, true)
const mqttTopic = `${contact.publicKey}/${chat.uuid}`
await network.signAndSend({data}, owner.publicKey, mqttTopic)
})
}
async function createTribeChatParams(owner, contactIds, name, img, price_per_message, price_to_join): Promise<{[k:string]:any}> {
let date = new Date()
date.setMilliseconds(0)
if (!(owner && contactIds && Array.isArray(contactIds))) {
return {}
}
// make ts sig here w LNd pubkey - that is UUID
const keys:{[k:string]:string} = await rsa.genKeys()
const groupUUID = await tribes.genSignedTimestamp()
const theContactIds = contactIds.includes(owner.id) ? contactIds : [owner.id].concat(contactIds)
return {
uuid: groupUUID,
ownerPubkey: owner.publicKey,
contactIds: JSON.stringify(theContactIds),
createdAt: date,
updatedAt: date,
photoUrl: img||'',
name: name,
type: constants.chat_types.tribe,
groupKey: keys.public,
groupPrivateKey: keys.private,
host: tribes.getHost(),
pricePerMessage: price_per_message||0,
priceToJoin: price_to_join||0,
}
}
export {
joinTribe, editTribe,
replayChatHistory,
createTribeChatParams
}
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}

281
api/controllers/chats.ts

@ -7,8 +7,8 @@ import * as socket from '../utils/socket'
import { sendNotification } from '../hub'
import * as md5 from 'md5'
import * as path from 'path'
import * as rsa from '../crypto/rsa'
import * as tribes from '../utils/tribes'
import {createTribeChatParams} from './chatTribes'
const constants = require(path.join(__dirname,'../../config/constants.json'))
@ -37,60 +37,6 @@ async function mute(req, res) {
success(res, jsonUtils.chatToJson(chat))
}
async function editTribe(req, res) {
const {
name,
is_listed,
price_per_message,
price_to_join,
img,
description,
tags,
} = req.body
const { id } = req.params
if(!id) return failure(res, 'group id is required')
const chat = await models.Chat.findOne({where:{id}})
if(!chat) {
return failure(res, 'cant find chat')
}
const owner = await models.Contact.findOne({ where: { isOwner: true } })
let okToUpdate = true
if(is_listed) {
try{
await tribes.edit({
uuid: chat.uuid,
name: name,
host: chat.host,
price_per_message: price_per_message||0,
price_to_join: price_to_join||0,
description,
tags,
img,
owner_alias: owner.alias,
})
} catch(e) {
okToUpdate = false
}
}
if(okToUpdate) {
await chat.update({
photoUrl: img||'',
name: name,
pricePerMessage: price_per_message||0,
priceToJoin: price_to_join||0
})
success(res, jsonUtils.chatToJson(chat))
} else {
failure(res, 'failed to update tribe')
}
}
// just add self here if tribes
// or can u add contacts as members?
async function createGroupChat(req, res) {
@ -250,143 +196,7 @@ const deleteChat = async (req, res) => {
success(res, { chat_id: id })
}
async function joinTribe(req, res){
console.log('=> joinTribe')
const { uuid, group_key, name, host, amount, img, owner_pubkey, owner_alias } = req.body
const existing = await models.Chat.findOne({where:{uuid}})
if(existing) {
console.log('[tribes] u are already in this tribe')
return
}
if(!owner_pubkey || !group_key || !uuid) {
console.log('[tribes] missing required params')
return
}
const ownerPubKey = owner_pubkey
// verify signature here?
const tribeOwner = await models.Contact.findOne({ where: { publicKey: ownerPubKey } })
let theTribeOwner
const owner = await models.Contact.findOne({ where: { isOwner: true } })
const contactIds = [owner.id]
if (tribeOwner) {
theTribeOwner = tribeOwner // might already include??
if(!contactIds.includes(tribeOwner.id)) contactIds.push(tribeOwner.id)
} else {
const createdContact = await models.Contact.create({
publicKey: ownerPubKey,
contactKey: '',
alias: owner_alias||'Unknown',
status: 1,
fromGroup: true,
})
theTribeOwner = createdContact
contactIds.push(createdContact.id)
}
let date = new Date()
date.setMilliseconds(0)
const chatParams = {
uuid: uuid,
contactIds: JSON.stringify(contactIds),
photoUrl: img||'',
createdAt: date,
updatedAt: date,
name: name,
type: constants.chat_types.tribe,
host: host || tribes.getHost(),
groupKey: group_key,
ownerPubkey: owner_pubkey,
}
network.sendMessage({ // send my data to tribe owner
chat: {
...chatParams, members: {
[owner.publicKey]: {
key: owner.contactKey,
alias: owner.alias||''
}
}
},
amount:amount||0,
sender: owner,
message: {},
type: constants.message_types.group_join,
failure: function (e) {
failure(res, e)
},
success: async function () {
const chat = await models.Chat.create(chatParams)
models.ChatMember.create({
contactId: theTribeOwner.id,
chatId: chat.id,
role: constants.chat_roles.owner,
lastActive: date,
})
success(res, jsonUtils.chatToJson(chat))
}
})
}
async function receiveGroupLeave(payload) {
console.log('=> receiveGroupLeave')
const { sender_pub_key, chat_uuid, chat_type, sender_alias, isTribeOwner } = await helpers.parseReceiveParams(payload)
const chat = await models.Chat.findOne({ where: { uuid: chat_uuid } })
if (!chat) return
const isTribe = chat_type===constants.chat_types.tribe
let sender
if(!isTribe || isTribeOwner) {
sender = await models.Contact.findOne({ where: { publicKey: sender_pub_key } })
if (!sender) return
const oldContactIds = JSON.parse(chat.contactIds || '[]')
const contactIds = oldContactIds.filter(cid => cid !== sender.id)
await chat.update({ contactIds: JSON.stringify(contactIds) })
if(isTribeOwner) {
if(chat_type===constants.chat_types.tribe){
try {
await models.ChatMember.destroy({where:{chatId: chat.id, contactId: sender.id}})
} catch(e) {}
}
}
}
var date = new Date();
date.setMilliseconds(0)
const msg:{[k:string]:any} = {
chatId: chat.id,
type: constants.message_types.group_leave,
sender: (sender && sender.id) || 0,
date: date,
messageContent: `${sender_alias} has left the group`,
remoteMessageContent: '',
status: constants.statuses.confirmed,
createdAt: date,
updatedAt: date
}
if(isTribe) {
msg.senderAlias = sender_alias
}
const message = await models.Message.create(msg)
socket.sendJson({
type: 'group_leave',
response: {
contact: jsonUtils.contactToJson(sender),
chat: jsonUtils.chatToJson(chat),
message: jsonUtils.messageToJson(message, null)
}
})
}
async function receiveGroupJoin(payload) {
console.log('=> receiveGroupJoin')
@ -429,7 +239,7 @@ async function receiveGroupJoin(payload) {
contactIds.push(createdContact.id)
}
}
if(!theSender) return // fail (no contact key?)
if(!theSender) return console.log('no sender') // fail (no contact key?)
await chat.update({ contactIds: JSON.stringify(contactIds) })
@ -440,6 +250,7 @@ async function receiveGroupJoin(payload) {
role: constants.chat_roles.reader,
lastActive: date,
})
// replayChatHistory(chat, theSender)
}
}
@ -469,6 +280,61 @@ async function receiveGroupJoin(payload) {
})
}
async function receiveGroupLeave(payload) {
console.log('=> receiveGroupLeave')
const { sender_pub_key, chat_uuid, chat_type, sender_alias, isTribeOwner } = await helpers.parseReceiveParams(payload)
const chat = await models.Chat.findOne({ where: { uuid: chat_uuid } })
if (!chat) return
const isTribe = chat_type===constants.chat_types.tribe
let sender
if(!isTribe || isTribeOwner) {
sender = await models.Contact.findOne({ where: { publicKey: sender_pub_key } })
if (!sender) return
const oldContactIds = JSON.parse(chat.contactIds || '[]')
const contactIds = oldContactIds.filter(cid => cid !== sender.id)
await chat.update({ contactIds: JSON.stringify(contactIds) })
if(isTribeOwner) {
if(chat_type===constants.chat_types.tribe){
try {
await models.ChatMember.destroy({where:{chatId: chat.id, contactId: sender.id}})
} catch(e) {}
}
}
}
var date = new Date();
date.setMilliseconds(0)
const msg:{[k:string]:any} = {
chatId: chat.id,
type: constants.message_types.group_leave,
sender: (sender && sender.id) || 0,
date: date,
messageContent: `${sender_alias} has left the group`,
remoteMessageContent: '',
status: constants.statuses.confirmed,
createdAt: date,
updatedAt: date
}
if(isTribe) {
msg.senderAlias = sender_alias
}
const message = await models.Message.create(msg)
socket.sendJson({
type: 'group_leave',
response: {
contact: jsonUtils.contactToJson(sender),
chat: jsonUtils.chatToJson(chat),
message: jsonUtils.messageToJson(message, null)
}
})
}
async function validateTribeOwner(chat_uuid: string, pubkey: string){
const verifiedOwnerPubkey = await tribes.verifySignedTimestamp(chat_uuid)
if(verifiedOwnerPubkey===pubkey){
@ -593,44 +459,15 @@ function createGroupChatParams(owner, contactIds, members, name) {
}
}
async function createTribeChatParams(owner, contactIds, name, img, price_per_message, price_to_join): Promise<{[k:string]:any}> {
let date = new Date()
date.setMilliseconds(0)
if (!(owner && contactIds && Array.isArray(contactIds))) {
return {}
}
// make ts sig here w LNd pubkey - that is UUID
const keys:{[k:string]:string} = await rsa.genKeys()
const groupUUID = await tribes.genSignedTimestamp()
const theContactIds = contactIds.includes(owner.id) ? contactIds : [owner.id].concat(contactIds)
return {
uuid: groupUUID,
ownerPubkey: owner.publicKey,
contactIds: JSON.stringify(theContactIds),
createdAt: date,
updatedAt: date,
photoUrl: img||'',
name: name,
type: constants.chat_types.tribe,
groupKey: keys.public,
groupPrivateKey: keys.private,
host: tribes.getHost(),
pricePerMessage: price_per_message||0,
priceToJoin: price_to_join||0,
}
}
export {
getChats, mute, addGroupMembers,
receiveGroupCreateOrInvite, createGroupChat,
deleteChat, receiveGroupLeave, receiveGroupJoin,
joinTribe, editTribe,
}
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}

155
api/controllers/index.ts

@ -1,90 +1,89 @@
import {models} from '../models'
import * as chats from './chats'
import * as chatTribes from './chatTribes'
import * as details from './details'
import * as contacts from './contacts'
import * as invites from './invites'
import * as invoices from './invoices'
import * as media from './media'
import * as messages from './messages'
import * as payments from './payment'
import * as subcriptions from './subscriptions'
import * as uploads from './uploads'
import * as confirmations from './confirmations'
import {checkTag} from '../utils/gitinfo'
import * as path from 'path'
const env = process.env.NODE_ENV || 'development';
console.log("=> env:",env)
let controllers = {
messages: require('./messages'),
invoices: require('./invoices'),
uploads: require('./uploads'),
contacts: require('./contacts'),
invites: require('./invites'),
payments: require('./payment'),
details: require('./details'),
chats: require('./chats'),
subcriptions: require('./subscriptions'),
media: require('./media'),
confirmations: require('./confirmations')
}
const constants = require(path.join(__dirname,'../../config/constants.json'))
async function set(app) {
if(models && models.Subscription){
controllers.subcriptions.initializeCronJobs()
subcriptions.initializeCronJobs()
}
try{
await controllers.media.cycleMediaToken()
await media.cycleMediaToken()
} catch(e) {
console.log('=> could not auth with media server', e.message)
}
app.get('/chats', controllers.chats.getChats)
app.post('/group', controllers.chats.createGroupChat)
app.post('/chats/:chat_id/:mute_unmute', controllers.chats.mute)
app.delete('/chat/:id', controllers.chats.deleteChat)
app.put('/chat/:id', controllers.chats.addGroupMembers)
app.post('/tribe', controllers.chats.joinTribe)
app.put('/group/:id', controllers.chats.editTribe)
app.post('/contacts/tokens', controllers.contacts.generateToken)
app.post('/upload', controllers.uploads.avatarUpload.single('file'), controllers.uploads.uploadFile)
app.post('/invites', controllers.invites.createInvite)
app.post('/invites/:invite_string/pay', controllers.invites.payInvite)
app.post('/invites/finish', controllers.invites.finishInvite)
app.get('/contacts', controllers.contacts.getContacts)
app.put('/contacts/:id', controllers.contacts.updateContact)
app.post('/contacts/:id/keys', controllers.contacts.exchangeKeys)
app.post('/contacts', controllers.contacts.createContact)
app.delete('/contacts/:id', controllers.contacts.deleteContact)
app.get('/allmessages', controllers.messages.getAllMessages)
app.get('/messages', controllers.messages.getMessages)
app.delete('/message/:id', controllers.messages.deleteMessage)
app.post('/messages', controllers.messages.sendMessage)
app.post('/messages/:chat_id/read', controllers.messages.readMessages)
app.post('/messages/clear', controllers.messages.clearMessages)
app.get('/subscriptions', controllers.subcriptions.getAllSubscriptions)
app.get('/subscription/:id', controllers.subcriptions.getSubscription)
app.delete('/subscription/:id', controllers.subcriptions.deleteSubscription)
app.post('/subscriptions', controllers.subcriptions.createSubscription)
app.put('/subscription/:id', controllers.subcriptions.editSubscription)
app.get('/subscriptions/contact/:contactId', controllers.subcriptions.getSubscriptionsForContact)
app.put('/subscription/:id/pause', controllers.subcriptions.pauseSubscription)
app.put('/subscription/:id/restart', controllers.subcriptions.restartSubscription)
app.get('/chats', chats.getChats)
app.post('/group', chats.createGroupChat)
app.post('/chats/:chat_id/:mute_unmute', chats.mute)
app.delete('/chat/:id', chats.deleteChat)
app.put('/chat/:id', chats.addGroupMembers)
app.post('/tribe', chatTribes.joinTribe)
app.put('/group/:id', chatTribes.editTribe)
app.post('/upload', uploads.avatarUpload.single('file'), uploads.uploadFile)
app.post('/invites', invites.createInvite)
app.post('/invites/:invite_string/pay', invites.payInvite)
app.post('/invites/finish', invites.finishInvite)
app.post('/contacts/tokens', contacts.generateToken)
app.get('/contacts', contacts.getContacts)
app.put('/contacts/:id', contacts.updateContact)
app.post('/contacts/:id/keys', contacts.exchangeKeys)
app.post('/contacts', contacts.createContact)
app.delete('/contacts/:id', contacts.deleteContact)
app.get('/allmessages', messages.getAllMessages)
app.get('/messages', messages.getMessages)
app.delete('/message/:id', messages.deleteMessage)
app.post('/messages', messages.sendMessage)
app.post('/messages/:chat_id/read', messages.readMessages)
app.post('/messages/clear', messages.clearMessages)
app.get('/subscriptions', subcriptions.getAllSubscriptions)
app.get('/subscription/:id', subcriptions.getSubscription)
app.delete('/subscription/:id', subcriptions.deleteSubscription)
app.post('/subscriptions', subcriptions.createSubscription)
app.put('/subscription/:id', subcriptions.editSubscription)
app.get('/subscriptions/contact/:contactId', subcriptions.getSubscriptionsForContact)
app.put('/subscription/:id/pause', subcriptions.pauseSubscription)
app.put('/subscription/:id/restart', subcriptions.restartSubscription)
app.post('/attachment', controllers.media.sendAttachmentMessage)
app.post('/purchase', controllers.media.purchase)
app.get('/signer/:challenge', controllers.media.signer)
app.post('/attachment', media.sendAttachmentMessage)
app.post('/purchase', media.purchase)
app.get('/signer/:challenge', media.signer)
app.post('/invoices', controllers.invoices.createInvoice)
app.get('/invoices', controllers.invoices.listInvoices)
app.put('/invoices', controllers.invoices.payInvoice)
app.post('/invoices/cancel', controllers.invoices.cancelInvoice)
app.post('/invoices', invoices.createInvoice)
app.get('/invoices', invoices.listInvoices)
app.put('/invoices', invoices.payInvoice)
app.post('/invoices/cancel', invoices.cancelInvoice)
app.post('/payment', controllers.payments.sendPayment)
app.get('/payments', controllers.payments.listPayments)
app.post('/payment', payments.sendPayment)
app.get('/payments', payments.listPayments)
app.get('/channels', controllers.details.getChannels)
app.get('/balance', controllers.details.getBalance)
app.get('/balance/all', controllers.details.getLocalRemoteBalance)
app.get('/getinfo', controllers.details.getInfo)
app.get('/logs', controllers.details.getLogsSince)
app.get('/info', controllers.details.getNodeInfo)
app.get('/channels', details.getChannels)
app.get('/balance', details.getBalance)
app.get('/balance/all', details.getLocalRemoteBalance)
app.get('/getinfo', details.getInfo)
app.get('/logs', details.getLogsSince)
app.get('/info', details.getNodeInfo)
app.get('/version', async function(req,res) {
const version = await checkTag()
@ -112,4 +111,22 @@ const login = (req, res) => {
}
}
export {set, controllers}
const msgtypes = constants.message_types
const ACTIONS = {
[msgtypes.contact_key]: contacts.receiveContactKey,
[msgtypes.contact_key_confirmation]: contacts.receiveConfirmContactKey,
[msgtypes.message]: messages.receiveMessage,
[msgtypes.invoice]: invoices.receiveInvoice,
[msgtypes.direct_payment]: payments.receivePayment,
[msgtypes.confirmation]: confirmations.receiveConfirmation,
[msgtypes.attachment]: media.receiveAttachment,
[msgtypes.purchase]: media.receivePurchase,
[msgtypes.purchase_accept]: media.receivePurchaseAccept,
[msgtypes.purchase_deny]: media.receivePurchaseDeny,
[msgtypes.group_create]: chats.receiveGroupCreateOrInvite,
[msgtypes.group_invite]: chats.receiveGroupCreateOrInvite,
[msgtypes.group_join]: chats.receiveGroupJoin,
[msgtypes.group_leave]: chats.receiveGroupLeave,
}
export {set, ACTIONS}

3
api/controllers/messages.ts

@ -156,7 +156,7 @@ const receiveMessage = async (payload) => {
date.setMilliseconds(0)
const total_spent = 1
const {owner, sender, chat, content, msg_id, chat_type, sender_alias} = await helpers.parseReceiveParams(payload)
const {owner, sender, chat, content, remote_content, msg_id, chat_type, sender_alias} = await helpers.parseReceiveParams(payload)
if(!owner || !sender || !chat) {
return console.log('=> no group chat!')
}
@ -175,6 +175,7 @@ const receiveMessage = async (payload) => {
}
if(chat_type===constants.chat_types.tribe) {
msg.senderAlias = sender_alias
if(remote_content) msg.remoteMessageContent=remote_content
}
const message = await models.Message.create(msg)

5
api/helpers.ts

@ -143,6 +143,7 @@ async function parseReceiveParams(payload) {
const chat_host = dat.chat.host
const amount = dat.message.amount
const content = dat.message.content
const remote_content = dat.message.remoteContent
const mediaToken = dat.message.mediaToken
const msg_id = dat.message.id||0
const mediaKey = dat.message.mediaKey
@ -169,7 +170,7 @@ async function parseReceiveParams(payload) {
}
chat = await models.Chat.findOne({ where: { uuid: chat_uuid } })
}
return { owner, sender, chat, sender_pub_key, sender_alias, isTribeOwner, chat_uuid, amount, content, mediaToken, mediaKey, mediaType, chat_type, msg_id, chat_members, chat_name, chat_host, chat_key }
return { owner, sender, chat, sender_pub_key, sender_alias, isTribeOwner, chat_uuid, amount, content, mediaToken, mediaKey, mediaType, chat_type, msg_id, chat_members, chat_name, chat_host, chat_key, remote_content }
}
export {
@ -198,4 +199,4 @@ function newkeyexchangemsg(type, sender){
// ...sender.photoUrl && {photoUrl: sender.photoUrl}
}
}
}
}

4
api/network/index.ts

@ -1,4 +1,4 @@
import {sendMessage,signAndSend} from './send'
import {sendMessage,signAndSend,newmsg} from './send'
import {initGrpcSubscriptions,initTribesSubscriptions,parseKeysendInvoice} from './receive'
/*
@ -6,7 +6,7 @@ Abstracts between lightning network and MQTT depending on Chat type and sender
*/
export {
sendMessage,signAndSend,
sendMessage,signAndSend,newmsg,
initGrpcSubscriptions,
initTribesSubscriptions,
parseKeysendInvoice,

23
api/network/receive.ts

@ -1,7 +1,7 @@
import * as path from 'path'
import * as lndService from '../grpc'
import {getInfo} from '../utils/lightning'
import {controllers} from '../controllers'
import {ACTIONS} from '../controllers'
import * as tribes from '../utils/tribes'
import {SPHINX_CUSTOM_RECORD_KEY, verifyAscii} from '../utils/lightning'
import { models } from '../models'
@ -57,11 +57,13 @@ async function onReceive(payload){
async function doTheAction(data){
let payload = data
if(payload.isTribeOwner) {
// decrypt and re-encrypt with self pubkey
const ogContent = data.message && data.message.content
// decrypt and re-encrypt with phone's pubkey for storage
const chat = await models.Chat.findOne({where:{uuid:payload.chat.uuid}})
const pld = await decryptMessage(data, chat)
const me = await models.Contact.findOne({where:{isOwner:true}})
payload = await encryptTribeBroadcast(pld, me, true) // true=isTribeOwner
if(ogContent) payload.message.remoteContent = ogContent
}
if(ACTIONS[payload.type]) {
ACTIONS[payload.type](payload)
@ -99,23 +101,6 @@ async function forwardMessageToTribe(ogpayload){
})
}
const ACTIONS = {
[msgtypes.contact_key]: controllers.contacts.receiveContactKey,
[msgtypes.contact_key_confirmation]: controllers.contacts.receiveConfirmContactKey,
[msgtypes.message]: controllers.messages.receiveMessage,
[msgtypes.invoice]: controllers.invoices.receiveInvoice,
[msgtypes.direct_payment]: controllers.payments.receivePayment,
[msgtypes.confirmation]: controllers.confirmations.receiveConfirmation,
[msgtypes.attachment]: controllers.media.receiveAttachment,
[msgtypes.purchase]: controllers.media.receivePurchase,
[msgtypes.purchase_accept]: controllers.media.receivePurchaseAccept,
[msgtypes.purchase_deny]: controllers.media.receivePurchaseDeny,
[msgtypes.group_create]: controllers.chats.receiveGroupCreateOrInvite,
[msgtypes.group_invite]: controllers.chats.receiveGroupCreateOrInvite,
[msgtypes.group_join]: controllers.chats.receiveGroupJoin,
[msgtypes.group_leave]: controllers.chats.receiveGroupLeave,
}
export async function initGrpcSubscriptions() {
try{
await getInfo()

2
api/network/send.ts

@ -114,7 +114,7 @@ export function signAndSend(opts, pubkey, mqttTopic?:string){
})
}
function newmsg(type, chat, sender, message){
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 {

201
dist/api/controllers/chatTribes.js

@ -0,0 +1,201 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const models_1 = require("../models");
const jsonUtils = require("../utils/json");
const res_1 = require("../utils/res");
const network = require("../network");
const rsa = require("../crypto/rsa");
const tribes = require("../utils/tribes");
const path = require("path");
const msg_1 = require("../utils/msg");
const constants = require(path.join(__dirname, '../../config/constants.json'));
function joinTribe(req, res) {
return __awaiter(this, void 0, void 0, function* () {
console.log('=> joinTribe');
const { uuid, group_key, name, host, amount, img, owner_pubkey, owner_alias } = req.body;
const existing = yield models_1.models.Chat.findOne({ where: { uuid } });
if (existing) {
console.log('[tribes] u are already in this tribe');
return;
}
if (!owner_pubkey || !group_key || !uuid) {
console.log('[tribes] missing required params');
return;
}
const ownerPubKey = owner_pubkey;
// verify signature here?
const tribeOwner = yield models_1.models.Contact.findOne({ where: { publicKey: ownerPubKey } });
let theTribeOwner;
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
const contactIds = [owner.id];
if (tribeOwner) {
theTribeOwner = tribeOwner; // might already include??
if (!contactIds.includes(tribeOwner.id))
contactIds.push(tribeOwner.id);
}
else {
const createdContact = yield models_1.models.Contact.create({
publicKey: ownerPubKey,
contactKey: '',
alias: owner_alias || 'Unknown',
status: 1,
fromGroup: true,
});
theTribeOwner = createdContact;
contactIds.push(createdContact.id);
}
let date = new Date();
date.setMilliseconds(0);
const chatParams = {
uuid: uuid,
contactIds: JSON.stringify(contactIds),
photoUrl: img || '',
createdAt: date,
updatedAt: date,
name: name,
type: constants.chat_types.tribe,
host: host || tribes.getHost(),
groupKey: group_key,
ownerPubkey: owner_pubkey,
};
network.sendMessage({
chat: Object.assign(Object.assign({}, chatParams), { members: {
[owner.publicKey]: {
key: owner.contactKey,
alias: owner.alias || ''
}
} }),
amount: amount || 0,
sender: owner,
message: {},
type: constants.message_types.group_join,
failure: function (e) {
res_1.failure(res, e);
},
success: function () {
return __awaiter(this, void 0, void 0, function* () {
const chat = yield models_1.models.Chat.create(chatParams);
models_1.models.ChatMember.create({
contactId: theTribeOwner.id,
chatId: chat.id,
role: constants.chat_roles.owner,
lastActive: date,
});
res_1.success(res, jsonUtils.chatToJson(chat));
});
}
});
});
}
exports.joinTribe = joinTribe;
function editTribe(req, res) {
return __awaiter(this, void 0, void 0, function* () {
const { name, is_listed, price_per_message, price_to_join, img, description, tags, } = req.body;
const { id } = req.params;
if (!id)
return res_1.failure(res, 'group id is required');
const chat = yield models_1.models.Chat.findOne({ where: { id } });
if (!chat) {
return res_1.failure(res, 'cant find chat');
}
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
let okToUpdate = true;
if (is_listed) {
try {
yield tribes.edit({
uuid: chat.uuid,
name: name,
host: chat.host,
price_per_message: price_per_message || 0,
price_to_join: price_to_join || 0,
description,
tags,
img,
owner_alias: owner.alias,
});
}
catch (e) {
okToUpdate = false;
}
}
if (okToUpdate) {
yield chat.update({
photoUrl: img || '',
name: name,
pricePerMessage: price_per_message || 0,
priceToJoin: price_to_join || 0
});
res_1.success(res, jsonUtils.chatToJson(chat));
}
else {
res_1.failure(res, 'failed to update tribe');
}
});
}
exports.editTribe = editTribe;
function replayChatHistory(chat, contact) {
return __awaiter(this, void 0, void 0, function* () {
const msgs = yield models_1.models.Message.findAll({ order: [['id', 'asc']], limit: 40 });
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
asyncForEach(msgs, (m) => __awaiter(this, void 0, void 0, function* () {
const sender = Object.assign(Object.assign({}, owner.dataValues), m.senderAlias && { alias: m.senderAlias });
let msg = network.newmsg(m.type, chat, sender, {
content: m.remoteContent,
mediaKey: m.mediaKey,
mediaType: m.mediaType,
mediaToken: m.mediaToken
});
msg = yield msg_1.decryptMessage(msg, chat);
const data = yield msg_1.personalizeMessage(msg, contact, true);
const mqttTopic = `${contact.publicKey}/${chat.uuid}`;
yield network.signAndSend({ data }, owner.publicKey, mqttTopic);
}));
});
}
exports.replayChatHistory = replayChatHistory;
function createTribeChatParams(owner, contactIds, name, img, price_per_message, price_to_join) {
return __awaiter(this, void 0, void 0, function* () {
let date = new Date();
date.setMilliseconds(0);
if (!(owner && contactIds && Array.isArray(contactIds))) {
return {};
}
// make ts sig here w LNd pubkey - that is UUID
const keys = yield rsa.genKeys();
const groupUUID = yield tribes.genSignedTimestamp();
const theContactIds = contactIds.includes(owner.id) ? contactIds : [owner.id].concat(contactIds);
return {
uuid: groupUUID,
ownerPubkey: owner.publicKey,
contactIds: JSON.stringify(theContactIds),
createdAt: date,
updatedAt: date,
photoUrl: img || '',
name: name,
type: constants.chat_types.tribe,
groupKey: keys.public,
groupPrivateKey: keys.private,
host: tribes.getHost(),
pricePerMessage: price_per_message || 0,
priceToJoin: price_to_join || 0,
};
});
}
exports.createTribeChatParams = createTribeChatParams;
function asyncForEach(array, callback) {
return __awaiter(this, void 0, void 0, function* () {
for (let index = 0; index < array.length; index++) {
yield callback(array[index], index, array);
}
});
}
//# sourceMappingURL=chatTribes.js.map

1
dist/api/controllers/chatTribes.js.map

File diff suppressed because one or more lines are too long

265
dist/api/controllers/chats.js

@ -18,8 +18,8 @@ const socket = require("../utils/socket");
const hub_1 = require("../hub");
const md5 = require("md5");
const path = require("path");
const rsa = require("../crypto/rsa");
const tribes = require("../utils/tribes");
const chatTribes_1 = require("./chatTribes");
const constants = require(path.join(__dirname, '../../config/constants.json'));
function getChats(req, res) {
return __awaiter(this, void 0, void 0, function* () {
@ -45,51 +45,6 @@ function mute(req, res) {
});
}
exports.mute = mute;
function editTribe(req, res) {
return __awaiter(this, void 0, void 0, function* () {
const { name, is_listed, price_per_message, price_to_join, img, description, tags, } = req.body;
const { id } = req.params;
if (!id)
return res_1.failure(res, 'group id is required');
const chat = yield models_1.models.Chat.findOne({ where: { id } });
if (!chat) {
return res_1.failure(res, 'cant find chat');
}
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
let okToUpdate = true;
if (is_listed) {
try {
yield tribes.edit({
uuid: chat.uuid,
name: name,
host: chat.host,
price_per_message: price_per_message || 0,
price_to_join: price_to_join || 0,
description,
tags,
img,
owner_alias: owner.alias,
});
}
catch (e) {
okToUpdate = false;
}
}
if (okToUpdate) {
yield chat.update({
photoUrl: img || '',
name: name,
pricePerMessage: price_per_message || 0,
priceToJoin: price_to_join || 0
});
res_1.success(res, jsonUtils.chatToJson(chat));
}
else {
res_1.failure(res, 'failed to update tribe');
}
});
}
exports.editTribe = editTribe;
// just add self here if tribes
// or can u add contacts as members?
function createGroupChat(req, res) {
@ -111,7 +66,7 @@ function createGroupChat(req, res) {
let chatParams = null;
let okToCreate = true;
if (is_tribe) {
chatParams = yield createTribeChatParams(owner, contact_ids, name, img, price_per_message, price_to_join);
chatParams = yield chatTribes_1.createTribeChatParams(owner, contact_ids, name, img, price_per_message, price_to_join);
if (is_listed && chatParams.uuid) {
// publish to tribe server
try {
@ -234,138 +189,6 @@ const deleteChat = (req, res) => __awaiter(void 0, void 0, void 0, function* ()
res_1.success(res, { chat_id: id });
});
exports.deleteChat = deleteChat;
function joinTribe(req, res) {
return __awaiter(this, void 0, void 0, function* () {
console.log('=> joinTribe');
const { uuid, group_key, name, host, amount, img, owner_pubkey, owner_alias } = req.body;
const existing = yield models_1.models.Chat.findOne({ where: { uuid } });
if (existing) {
console.log('[tribes] u are already in this tribe');
return;
}
if (!owner_pubkey || !group_key || !uuid) {
console.log('[tribes] missing required params');
return;
}
const ownerPubKey = owner_pubkey;
// verify signature here?
const tribeOwner = yield models_1.models.Contact.findOne({ where: { publicKey: ownerPubKey } });
let theTribeOwner;
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
const contactIds = [owner.id];
if (tribeOwner) {
theTribeOwner = tribeOwner; // might already include??
if (!contactIds.includes(tribeOwner.id))
contactIds.push(tribeOwner.id);
}
else {
const createdContact = yield models_1.models.Contact.create({
publicKey: ownerPubKey,
contactKey: '',
alias: owner_alias || 'Unknown',
status: 1,
fromGroup: true,
});
theTribeOwner = createdContact;
contactIds.push(createdContact.id);
}
let date = new Date();
date.setMilliseconds(0);
const chatParams = {
uuid: uuid,
contactIds: JSON.stringify(contactIds),
photoUrl: img || '',
createdAt: date,
updatedAt: date,
name: name,
type: constants.chat_types.tribe,
host: host || tribes.getHost(),
groupKey: group_key,
ownerPubkey: owner_pubkey,
};
network.sendMessage({
chat: Object.assign(Object.assign({}, chatParams), { members: {
[owner.publicKey]: {
key: owner.contactKey,
alias: owner.alias || ''
}
} }),
amount: amount || 0,
sender: owner,
message: {},
type: constants.message_types.group_join,
failure: function (e) {
res_1.failure(res, e);
},
success: function () {
return __awaiter(this, void 0, void 0, function* () {
const chat = yield models_1.models.Chat.create(chatParams);
models_1.models.ChatMember.create({
contactId: theTribeOwner.id,
chatId: chat.id,
role: constants.chat_roles.owner,
lastActive: date,
});
res_1.success(res, jsonUtils.chatToJson(chat));
});
}
});
});
}
exports.joinTribe = joinTribe;
function receiveGroupLeave(payload) {
return __awaiter(this, void 0, void 0, function* () {
console.log('=> receiveGroupLeave');
const { sender_pub_key, chat_uuid, chat_type, sender_alias, isTribeOwner } = yield helpers.parseReceiveParams(payload);
const chat = yield models_1.models.Chat.findOne({ where: { uuid: chat_uuid } });
if (!chat)
return;
const isTribe = chat_type === constants.chat_types.tribe;
let sender;
if (!isTribe || isTribeOwner) {
sender = yield models_1.models.Contact.findOne({ where: { publicKey: sender_pub_key } });
if (!sender)
return;
const oldContactIds = JSON.parse(chat.contactIds || '[]');
const contactIds = oldContactIds.filter(cid => cid !== sender.id);
yield chat.update({ contactIds: JSON.stringify(contactIds) });
if (isTribeOwner) {
if (chat_type === constants.chat_types.tribe) {
try {
yield models_1.models.ChatMember.destroy({ where: { chatId: chat.id, contactId: sender.id } });
}
catch (e) { }
}
}
}
var date = new Date();
date.setMilliseconds(0);
const msg = {
chatId: chat.id,
type: constants.message_types.group_leave,
sender: (sender && sender.id) || 0,
date: date,
messageContent: `${sender_alias} has left the group`,
remoteMessageContent: '',
status: constants.statuses.confirmed,
createdAt: date,
updatedAt: date
};
if (isTribe) {
msg.senderAlias = sender_alias;
}
const message = yield models_1.models.Message.create(msg);
socket.sendJson({
type: 'group_leave',
response: {
contact: jsonUtils.contactToJson(sender),
chat: jsonUtils.chatToJson(chat),
message: jsonUtils.messageToJson(message, null)
}
});
});
}
exports.receiveGroupLeave = receiveGroupLeave;
function receiveGroupJoin(payload) {
return __awaiter(this, void 0, void 0, function* () {
console.log('=> receiveGroupJoin');
@ -407,7 +230,7 @@ function receiveGroupJoin(payload) {
}
}
if (!theSender)
return; // fail (no contact key?)
return console.log('no sender'); // fail (no contact key?)
yield chat.update({ contactIds: JSON.stringify(contactIds) });
if (isTribeOwner) { // IF TRIBE, ADD TO XREF
models_1.models.ChatMember.create({
@ -416,6 +239,7 @@ function receiveGroupJoin(payload) {
role: constants.chat_roles.reader,
lastActive: date,
});
// replayChatHistory(chat, theSender)
}
}
const msg = {
@ -444,6 +268,59 @@ function receiveGroupJoin(payload) {
});
}
exports.receiveGroupJoin = receiveGroupJoin;
function receiveGroupLeave(payload) {
return __awaiter(this, void 0, void 0, function* () {
console.log('=> receiveGroupLeave');
const { sender_pub_key, chat_uuid, chat_type, sender_alias, isTribeOwner } = yield helpers.parseReceiveParams(payload);
const chat = yield models_1.models.Chat.findOne({ where: { uuid: chat_uuid } });
if (!chat)
return;
const isTribe = chat_type === constants.chat_types.tribe;
let sender;
if (!isTribe || isTribeOwner) {
sender = yield models_1.models.Contact.findOne({ where: { publicKey: sender_pub_key } });
if (!sender)
return;
const oldContactIds = JSON.parse(chat.contactIds || '[]');
const contactIds = oldContactIds.filter(cid => cid !== sender.id);
yield chat.update({ contactIds: JSON.stringify(contactIds) });
if (isTribeOwner) {
if (chat_type === constants.chat_types.tribe) {
try {
yield models_1.models.ChatMember.destroy({ where: { chatId: chat.id, contactId: sender.id } });
}
catch (e) { }
}
}
}
var date = new Date();
date.setMilliseconds(0);
const msg = {
chatId: chat.id,
type: constants.message_types.group_leave,
sender: (sender && sender.id) || 0,
date: date,
messageContent: `${sender_alias} has left the group`,
remoteMessageContent: '',
status: constants.statuses.confirmed,
createdAt: date,
updatedAt: date
};
if (isTribe) {
msg.senderAlias = sender_alias;
}
const message = yield models_1.models.Message.create(msg);
socket.sendJson({
type: 'group_leave',
response: {
contact: jsonUtils.contactToJson(sender),
chat: jsonUtils.chatToJson(chat),
message: jsonUtils.messageToJson(message, null)
}
});
});
}
exports.receiveGroupLeave = receiveGroupLeave;
function validateTribeOwner(chat_uuid, pubkey) {
return __awaiter(this, void 0, void 0, function* () {
const verifiedOwnerPubkey = yield tribes.verifySignedTimestamp(chat_uuid);
@ -557,34 +434,6 @@ function createGroupChatParams(owner, contactIds, members, name) {
type: constants.chat_types.group
};
}
function createTribeChatParams(owner, contactIds, name, img, price_per_message, price_to_join) {
return __awaiter(this, void 0, void 0, function* () {
let date = new Date();
date.setMilliseconds(0);
if (!(owner && contactIds && Array.isArray(contactIds))) {
return {};
}
// make ts sig here w LNd pubkey - that is UUID
const keys = yield rsa.genKeys();
const groupUUID = yield tribes.genSignedTimestamp();
const theContactIds = contactIds.includes(owner.id) ? contactIds : [owner.id].concat(contactIds);
return {
uuid: groupUUID,
ownerPubkey: owner.publicKey,
contactIds: JSON.stringify(theContactIds),
createdAt: date,
updatedAt: date,
photoUrl: img || '',
name: name,
type: constants.chat_types.tribe,
groupKey: keys.public,
groupPrivateKey: keys.private,
host: tribes.getHost(),
pricePerMessage: price_per_message || 0,
priceToJoin: price_to_join || 0,
};
});
}
function asyncForEach(array, callback) {
return __awaiter(this, void 0, void 0, function* () {
for (let index = 0; index < array.length; index++) {

2
dist/api/controllers/chats.js.map

File diff suppressed because one or more lines are too long

142
dist/api/controllers/index.js

@ -10,80 +10,80 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", { value: true });
const models_1 = require("../models");
const chats = require("./chats");
const chatTribes = require("./chatTribes");
const details = require("./details");
const contacts = require("./contacts");
const invites = require("./invites");
const invoices = require("./invoices");
const media = require("./media");
const messages = require("./messages");
const payments = require("./payment");
const subcriptions = require("./subscriptions");
const uploads = require("./uploads");
const confirmations = require("./confirmations");
const gitinfo_1 = require("../utils/gitinfo");
const path = require("path");
const env = process.env.NODE_ENV || 'development';
console.log("=> env:", env);
let controllers = {
messages: require('./messages'),
invoices: require('./invoices'),
uploads: require('./uploads'),
contacts: require('./contacts'),
invites: require('./invites'),
payments: require('./payment'),
details: require('./details'),
chats: require('./chats'),
subcriptions: require('./subscriptions'),
media: require('./media'),
confirmations: require('./confirmations')
};
exports.controllers = controllers;
const constants = require(path.join(__dirname, '../../config/constants.json'));
function set(app) {
return __awaiter(this, void 0, void 0, function* () {
if (models_1.models && models_1.models.Subscription) {
controllers.subcriptions.initializeCronJobs();
subcriptions.initializeCronJobs();
}
try {
yield controllers.media.cycleMediaToken();
yield media.cycleMediaToken();
}
catch (e) {
console.log('=> could not auth with media server', e.message);
}
app.get('/chats', controllers.chats.getChats);
app.post('/group', controllers.chats.createGroupChat);
app.post('/chats/:chat_id/:mute_unmute', controllers.chats.mute);
app.delete('/chat/:id', controllers.chats.deleteChat);
app.put('/chat/:id', controllers.chats.addGroupMembers);
app.post('/tribe', controllers.chats.joinTribe);
app.put('/group/:id', controllers.chats.editTribe);
app.post('/contacts/tokens', controllers.contacts.generateToken);
app.post('/upload', controllers.uploads.avatarUpload.single('file'), controllers.uploads.uploadFile);
app.post('/invites', controllers.invites.createInvite);
app.post('/invites/:invite_string/pay', controllers.invites.payInvite);
app.post('/invites/finish', controllers.invites.finishInvite);
app.get('/contacts', controllers.contacts.getContacts);
app.put('/contacts/:id', controllers.contacts.updateContact);
app.post('/contacts/:id/keys', controllers.contacts.exchangeKeys);
app.post('/contacts', controllers.contacts.createContact);
app.delete('/contacts/:id', controllers.contacts.deleteContact);
app.get('/allmessages', controllers.messages.getAllMessages);
app.get('/messages', controllers.messages.getMessages);
app.delete('/message/:id', controllers.messages.deleteMessage);
app.post('/messages', controllers.messages.sendMessage);
app.post('/messages/:chat_id/read', controllers.messages.readMessages);
app.post('/messages/clear', controllers.messages.clearMessages);
app.get('/subscriptions', controllers.subcriptions.getAllSubscriptions);
app.get('/subscription/:id', controllers.subcriptions.getSubscription);
app.delete('/subscription/:id', controllers.subcriptions.deleteSubscription);
app.post('/subscriptions', controllers.subcriptions.createSubscription);
app.put('/subscription/:id', controllers.subcriptions.editSubscription);
app.get('/subscriptions/contact/:contactId', controllers.subcriptions.getSubscriptionsForContact);
app.put('/subscription/:id/pause', controllers.subcriptions.pauseSubscription);
app.put('/subscription/:id/restart', controllers.subcriptions.restartSubscription);
app.post('/attachment', controllers.media.sendAttachmentMessage);
app.post('/purchase', controllers.media.purchase);
app.get('/signer/:challenge', controllers.media.signer);
app.post('/invoices', controllers.invoices.createInvoice);
app.get('/invoices', controllers.invoices.listInvoices);
app.put('/invoices', controllers.invoices.payInvoice);
app.post('/invoices/cancel', controllers.invoices.cancelInvoice);
app.post('/payment', controllers.payments.sendPayment);
app.get('/payments', controllers.payments.listPayments);
app.get('/channels', controllers.details.getChannels);
app.get('/balance', controllers.details.getBalance);
app.get('/balance/all', controllers.details.getLocalRemoteBalance);
app.get('/getinfo', controllers.details.getInfo);
app.get('/logs', controllers.details.getLogsSince);
app.get('/info', controllers.details.getNodeInfo);
app.get('/chats', chats.getChats);
app.post('/group', chats.createGroupChat);
app.post('/chats/:chat_id/:mute_unmute', chats.mute);
app.delete('/chat/:id', chats.deleteChat);
app.put('/chat/:id', chats.addGroupMembers);
app.post('/tribe', chatTribes.joinTribe);
app.put('/group/:id', chatTribes.editTribe);
app.post('/upload', uploads.avatarUpload.single('file'), uploads.uploadFile);
app.post('/invites', invites.createInvite);
app.post('/invites/:invite_string/pay', invites.payInvite);
app.post('/invites/finish', invites.finishInvite);
app.post('/contacts/tokens', contacts.generateToken);
app.get('/contacts', contacts.getContacts);
app.put('/contacts/:id', contacts.updateContact);
app.post('/contacts/:id/keys', contacts.exchangeKeys);
app.post('/contacts', contacts.createContact);
app.delete('/contacts/:id', contacts.deleteContact);
app.get('/allmessages', messages.getAllMessages);
app.get('/messages', messages.getMessages);
app.delete('/message/:id', messages.deleteMessage);
app.post('/messages', messages.sendMessage);
app.post('/messages/:chat_id/read', messages.readMessages);
app.post('/messages/clear', messages.clearMessages);
app.get('/subscriptions', subcriptions.getAllSubscriptions);
app.get('/subscription/:id', subcriptions.getSubscription);
app.delete('/subscription/:id', subcriptions.deleteSubscription);
app.post('/subscriptions', subcriptions.createSubscription);
app.put('/subscription/:id', subcriptions.editSubscription);
app.get('/subscriptions/contact/:contactId', subcriptions.getSubscriptionsForContact);
app.put('/subscription/:id/pause', subcriptions.pauseSubscription);
app.put('/subscription/:id/restart', subcriptions.restartSubscription);
app.post('/attachment', media.sendAttachmentMessage);
app.post('/purchase', media.purchase);
app.get('/signer/:challenge', media.signer);
app.post('/invoices', invoices.createInvoice);
app.get('/invoices', invoices.listInvoices);
app.put('/invoices', invoices.payInvoice);
app.post('/invoices/cancel', invoices.cancelInvoice);
app.post('/payment', payments.sendPayment);
app.get('/payments', payments.listPayments);
app.get('/channels', details.getChannels);
app.get('/balance', details.getBalance);
app.get('/balance/all', details.getLocalRemoteBalance);
app.get('/getinfo', details.getInfo);
app.get('/logs', details.getLogsSince);
app.get('/info', details.getNodeInfo);
app.get('/version', function (req, res) {
return __awaiter(this, void 0, void 0, function* () {
const version = yield gitinfo_1.checkTag();
@ -111,4 +111,22 @@ const login = (req, res) => {
res.end();
}
};
const msgtypes = constants.message_types;
const ACTIONS = {
[msgtypes.contact_key]: contacts.receiveContactKey,
[msgtypes.contact_key_confirmation]: contacts.receiveConfirmContactKey,
[msgtypes.message]: messages.receiveMessage,
[msgtypes.invoice]: invoices.receiveInvoice,
[msgtypes.direct_payment]: payments.receivePayment,
[msgtypes.confirmation]: confirmations.receiveConfirmation,
[msgtypes.attachment]: media.receiveAttachment,
[msgtypes.purchase]: media.receivePurchase,
[msgtypes.purchase_accept]: media.receivePurchaseAccept,
[msgtypes.purchase_deny]: media.receivePurchaseDeny,
[msgtypes.group_create]: chats.receiveGroupCreateOrInvite,
[msgtypes.group_invite]: chats.receiveGroupCreateOrInvite,
[msgtypes.group_join]: chats.receiveGroupJoin,
[msgtypes.group_leave]: chats.receiveGroupLeave,
};
exports.ACTIONS = ACTIONS;
//# sourceMappingURL=index.js.map

2
dist/api/controllers/index.js.map

File diff suppressed because one or more lines are too long

4
dist/api/controllers/messages.js

@ -139,7 +139,7 @@ const receiveMessage = (payload) => __awaiter(void 0, void 0, void 0, function*
var date = new Date();
date.setMilliseconds(0);
const total_spent = 1;
const { owner, sender, chat, content, msg_id, chat_type, sender_alias } = yield helpers.parseReceiveParams(payload);
const { owner, sender, chat, content, remote_content, msg_id, chat_type, sender_alias } = yield helpers.parseReceiveParams(payload);
if (!owner || !sender || !chat) {
return console.log('=> no group chat!');
}
@ -157,6 +157,8 @@ const receiveMessage = (payload) => __awaiter(void 0, void 0, void 0, function*
};
if (chat_type === constants.chat_types.tribe) {
msg.senderAlias = sender_alias;
if (remote_content)
msg.remoteMessageContent = remote_content;
}
const message = yield models_1.models.Message.create(msg);
console.log('saved message', message.dataValues);

2
dist/api/controllers/messages.js.map

File diff suppressed because one or more lines are too long

3
dist/api/helpers.js

@ -159,6 +159,7 @@ function parseReceiveParams(payload) {
const chat_host = dat.chat.host;
const amount = dat.message.amount;
const content = dat.message.content;
const remote_content = dat.message.remoteContent;
const mediaToken = dat.message.mediaToken;
const msg_id = dat.message.id || 0;
const mediaKey = dat.message.mediaKey;
@ -183,7 +184,7 @@ function parseReceiveParams(payload) {
}
chat = yield models_1.models.Chat.findOne({ where: { uuid: chat_uuid } });
}
return { owner, sender, chat, sender_pub_key, sender_alias, isTribeOwner, chat_uuid, amount, content, mediaToken, mediaKey, mediaType, chat_type, msg_id, chat_members, chat_name, chat_host, chat_key };
return { owner, sender, chat, sender_pub_key, sender_alias, isTribeOwner, chat_uuid, amount, content, mediaToken, mediaKey, mediaType, chat_type, msg_id, chat_members, chat_name, chat_host, chat_key, remote_content };
});
}
exports.parseReceiveParams = parseReceiveParams;

2
dist/api/helpers.js.map

File diff suppressed because one or more lines are too long

1
dist/api/network/index.js

@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const send_1 = require("./send");
exports.sendMessage = send_1.sendMessage;
exports.signAndSend = send_1.signAndSend;
exports.newmsg = send_1.newmsg;
const receive_1 = require("./receive");
exports.initGrpcSubscriptions = receive_1.initGrpcSubscriptions;
exports.initTribesSubscriptions = receive_1.initTribesSubscriptions;

2
dist/api/network/index.js.map

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../api/network/index.ts"],"names":[],"mappings":";;AAAA,iCAA8C;AAQ1C,sBARI,kBAAW,CAQJ;AAAC,sBARI,kBAAW,CAQJ;AAP3B,uCAA2F;AAQvF,gCARI,+BAAqB,CAQJ;AACrB,kCAT0B,iCAAuB,CAS1B;AACvB,8BAVkD,6BAAmB,CAUlD"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../api/network/index.ts"],"names":[],"mappings":";;AAAA,iCAAqD;AAQjD,sBARI,kBAAW,CAQJ;AAAC,sBARI,kBAAW,CAQJ;AAAC,iBARI,aAAM,CAQJ;AAPlC,uCAA2F;AAQvF,gCARI,+BAAqB,CAQJ;AACrB,kCAT0B,iCAAuB,CAS1B;AACvB,8BAVkD,6BAAmB,CAUlD"}

25
dist/api/network/receive.js

@ -74,14 +74,17 @@ function doTheAction(data) {
return __awaiter(this, void 0, void 0, function* () {
let payload = data;
if (payload.isTribeOwner) {
// decrypt and re-encrypt with self pubkey
const ogContent = data.message && data.message.content;
// decrypt and re-encrypt with phone's pubkey for storage
const chat = yield models_1.models.Chat.findOne({ where: { uuid: payload.chat.uuid } });
const pld = yield msg_1.decryptMessage(data, chat);
const me = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
payload = yield msg_1.encryptTribeBroadcast(pld, me, true); // true=isTribeOwner
if (ogContent)
payload.message.remoteContent = ogContent;
}
if (ACTIONS[payload.type]) {
ACTIONS[payload.type](payload);
if (controllers_1.ACTIONS[payload.type]) {
controllers_1.ACTIONS[payload.type](payload);
}
else {
console.log('Incorrect payload type:', payload.type);
@ -114,22 +117,6 @@ function forwardMessageToTribe(ogpayload) {
});
});
}
const ACTIONS = {
[msgtypes.contact_key]: controllers_1.controllers.contacts.receiveContactKey,
[msgtypes.contact_key_confirmation]: controllers_1.controllers.contacts.receiveConfirmContactKey,
[msgtypes.message]: controllers_1.controllers.messages.receiveMessage,
[msgtypes.invoice]: controllers_1.controllers.invoices.receiveInvoice,
[msgtypes.direct_payment]: controllers_1.controllers.payments.receivePayment,
[msgtypes.confirmation]: controllers_1.controllers.confirmations.receiveConfirmation,
[msgtypes.attachment]: controllers_1.controllers.media.receiveAttachment,
[msgtypes.purchase]: controllers_1.controllers.media.receivePurchase,
[msgtypes.purchase_accept]: controllers_1.controllers.media.receivePurchaseAccept,
[msgtypes.purchase_deny]: controllers_1.controllers.media.receivePurchaseDeny,
[msgtypes.group_create]: controllers_1.controllers.chats.receiveGroupCreateOrInvite,
[msgtypes.group_invite]: controllers_1.controllers.chats.receiveGroupCreateOrInvite,
[msgtypes.group_join]: controllers_1.controllers.chats.receiveGroupJoin,
[msgtypes.group_leave]: controllers_1.controllers.chats.receiveGroupLeave,
};
function initGrpcSubscriptions() {
return __awaiter(this, void 0, void 0, function* () {
try {

2
dist/api/network/receive.js.map

File diff suppressed because one or more lines are too long

1
dist/api/network/send.js

@ -134,6 +134,7 @@ function newmsg(type, chat, sender, message) {
sender: Object.assign(Object.assign({}, includeAlias && { alias: sender.alias }), { pub_key: sender.publicKey })
};
}
exports.newmsg = newmsg;
function asyncForEach(array, callback) {
return __awaiter(this, void 0, void 0, function* () {
for (let index = 0; index < array.length; index++) {

2
dist/api/network/send.js.map

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save