Evan Feenstra
5 years ago
committed by
GitHub
24 changed files with 726 additions and 614 deletions
@ -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); |
|||
} |
|||
} |
@ -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
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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"} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue