Browse Source

mqtt connect, auth with sig, gen group keys, tribes host

feature/dockerfile-arm
Evan Feenstra 5 years ago
parent
commit
3c8af97b4a
  1. 35
      api/controllers/chats.ts
  2. 4
      api/controllers/index.ts
  3. 27
      api/crypto/rsa.ts
  4. 2
      api/helpers.ts
  5. 4
      api/utils/lightning.ts
  6. 10
      api/utils/setup.ts
  7. 46
      api/utils/tribes.ts
  8. 6
      config/app.json
  9. 3
      config/constants.json
  10. 37
      dist/api/controllers/chats.js
  11. 2
      dist/api/controllers/chats.js.map
  12. 2
      dist/api/controllers/index.js
  13. 2
      dist/api/controllers/index.js.map
  14. 27
      dist/api/crypto/rsa.js
  15. 2
      dist/api/crypto/rsa.js.map
  16. 2
      dist/api/helpers.js
  17. 2
      dist/api/helpers.js.map
  18. 4
      dist/api/utils/lightning.js
  19. 2
      dist/api/utils/lightning.js.map
  20. 11
      dist/api/utils/setup.js
  21. 2
      dist/api/utils/setup.js.map
  22. 57
      dist/api/utils/tribes.js
  23. 1
      dist/api/utils/tribes.js.map
  24. 3
      dist/config/constants.json
  25. 11
      dist/public/index.html
  26. 32444
      dist/public/js/app.js
  27. BIN
      dist/public/relay.jpg
  28. 372
      dist/public/semantic.min.css
  29. 291
      package-lock.json
  30. 1
      package.json

35
api/controllers/chats.ts

@ -6,6 +6,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'
const constants = require(path.join(__dirname,'../../config/constants.json'))
@ -38,6 +40,7 @@ async function createGroupChat(req, res) {
const {
name,
contact_ids,
is_public,
} = req.body
const members: { [k: string]: {[k:string]:string} } = {} //{pubkey:{key,alias}, ...}
@ -54,7 +57,13 @@ async function createGroupChat(req, res) {
}
})
const chatParams = createGroupChatParams(owner, contact_ids, members, name)
let chatParams:any = null
if(is_public){
chatParams = await createPublicGroupChatParams(owner, contact_ids, name)
// and publish to tribes server? so can be discovered
} else {
chatParams = createGroupChatParams(owner, contact_ids, members, name)
}
helpers.sendMessage({
chat: { ...chatParams, members },
@ -305,6 +314,30 @@ function createGroupChatParams(owner, contactIds, members, name) {
}
}
async function createPublicGroupChatParams(owner, contactIds, name) {
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,
contactIds: JSON.stringify(theContactIds),
createdAt: date,
updatedAt: date,
name: name,
type: constants.chat_types.public_group,
groupKey: keys.public,
groupPrivateKey: keys.private,
host: tribes.getHost()
}
}
export {
getChats, mute, addGroupMembers,
receiveGroupCreateOrInvite, createGroupChat,

4
api/controllers/index.ts

@ -1,7 +1,7 @@
import {models} from '../models'
import * as lndService from '../grpc'
import {checkTag} from '../utils/gitinfo'
import {checkConnection} from '../utils/lightning'
import {getInfo} from '../utils/lightning'
import * as path from 'path'
const constants = require(path.join(__dirname,'../../config/constants.json'))
@ -25,7 +25,7 @@ let controllers = {
async function iniGrpcSubscriptions() {
try{
await checkConnection()
await getInfo()
const types = constants.message_types
await lndService.subscribeInvoices({
[types.contact_key]: controllers.contacts.receiveContactKey,

27
api/crypto/rsa.ts

@ -26,6 +26,27 @@ export function decrypt(privateKey, enc){
}
}
export function genKeys(): Promise<{[k:string]:string}>{
return new Promise((resolve, reject)=>{
crypto.generateKeyPair('rsa', {
modulusLength: 2048
}, (err, publicKey, privKey)=>{
const pubPEM = publicKey.export({
type:'pkcs1',format:'pem'
})
const pubBase64 = cert.unpub(pubPEM)
const privPEM = privKey.export({
type:'pkcs1',format:'pem'
})
const privBase64 = cert.unpriv(privPEM)
resolve({
public: pubBase64,
private: privBase64,
})
})
})
}
export function testRSA(){
crypto.generateKeyPair('rsa', {
modulusLength: 2048
@ -50,6 +71,12 @@ const cert = {
s = s.replace('-----END RSA PUBLIC KEY-----','')
return s.replace(/[\r\n]+/gm, '')
},
unpriv: function(key){
let s = key
s = s.replace('-----BEGIN RSA PRIVATE KEY-----','')
s = s.replace('-----END RSA PRIVATE KEY-----','')
return s.replace(/[\r\n]+/gm, '')
},
pub:function(key){
return '-----BEGIN RSA PUBLIC KEY-----\n' +
key + '\n' +

2
api/helpers.ts

@ -227,6 +227,8 @@ function newmsg(type, chat, sender, message){
...chat.name && { name: chat.name },
...chat.type && { type: chat.type },
...chat.members && { members: chat.members },
...chat.groupKey && { groupKey: chat.groupKey },
...chat.host && { host: chat.host }
},
message: message,
// sender: {

4
api/utils/lightning.ts

@ -355,7 +355,7 @@ function verifyMessage(msg,sig): Promise<{[k:string]:any}> {
})
}
async function checkConnection(){
async function getInfo(): Promise<{[k:string]:any}>{
return new Promise((resolve,reject)=>{
const lightning = loadLightning()
lightning.getInfo({}, function(err, response) {
@ -395,7 +395,7 @@ export {
SPHINX_CUSTOM_RECORD_KEY,
listInvoices,
listAllPayments,
checkConnection,
getInfo,
listAllInvoices,
listAllPaymentsPaginated,
}

10
api/utils/setup.ts

@ -6,7 +6,7 @@ import * as publicIp from 'public-ip'
import password from '../utils/password'
import {checkTag, checkCommitHash} from '../utils/gitinfo'
const USER_VERSION = 1
const USER_VERSION = 2
const setupDatabase = async () => {
console.log('=> [db] starting setup...')
@ -31,8 +31,14 @@ async function setVersion(){
}
async function migrate(){
addTableColumn('sphinx_chats', 'group_key')
addTableColumn('sphinx_chats', 'group_private_key')
addTableColumn('sphinx_chats', 'host')
}
async function addTableColumn(table:string, column:string, type='TEXT') {
try {
await sequelize.query(`alter table sphinx_invites add invoice text`)
await sequelize.query(`alter table ${table} add ${column} ${type}`)
} catch(e) {
//console.log('=> migrate failed',e)
}

46
api/utils/tribes.ts

@ -0,0 +1,46 @@
import * as moment from 'moment'
import * as zbase32 from './zbase32'
import {signBuffer, getInfo} from './lightning'
import * as path from 'path'
import * as mqtt from 'mqtt'
const env = process.env.NODE_ENV || 'development'
const config = require(path.join(__dirname,'../../config/app.json'))[env]
export async function connect() {
const pwd = await genSignedTimestamp()
const info = await getInfo()
const client = mqtt.connect(`tcp://${config.tribes_host}`,{
username:info.identity_pubkey,
password:pwd,
})
client.on('connect', function () {
console.log("MQTT CLIENT CONNECTED!")
// subscribe to all public groups here
// that you are NOT admin of (dont sub to your own!)
})
client.on('close', function () {
console.log("MQTT CLOSED")
})
}
export async function genSignedTimestamp(){
const now = moment().unix()
const tsBytes = Buffer.from(now.toString(16), 'hex')
const sig = await signBuffer(tsBytes)
const sigBytes = zbase32.decode(sig)
const totalLength = tsBytes.length + sigBytes.length
const buf = Buffer.concat([tsBytes, sigBytes], totalLength)
return urlBase64(buf)
}
export function getHost() {
return config.tribes_host || ''
}
function urlBase64(buf){
return buf.toString('base64').replace(/\//g, '_').replace(/\+/g, '-')
}

6
config/app.json

@ -11,7 +11,8 @@
"hub_url": "http://lvh.me/ping",
"hub_invite_url": "http://lvh.me/invites",
"hub_check_invite_url": "http://lvh.me/check_invite",
"media_host": "localhost:5000"
"media_host": "localhost:5000",
"tribes_host": "127.0.0.1:1883"
},
"production": {
"senza_url": "https://staging.senza.us/api/v2/",
@ -27,6 +28,7 @@
"hub_url": "https://hub.sphinx.chat/ping",
"hub_invite_url": "https://hub.sphinx.chat/invites",
"hub_check_invite_url": "https://hub.sphinx.chat/check_invite",
"media_host": "memes.sphinx.chat"
"media_host": "memes.sphinx.chat",
"tribes_host": "tribes.sphinx.chat"
}
}

3
config/constants.json

@ -47,6 +47,7 @@
},
"chat_types": {
"conversation": 0,
"group": 1
"group": 1,
"public_group": 2
}
}

37
dist/api/controllers/chats.js

@ -17,6 +17,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 constants = require(path.join(__dirname, '../../config/constants.json'));
function getChats(req, res) {
return __awaiter(this, void 0, void 0, function* () {
@ -44,7 +46,7 @@ function mute(req, res) {
exports.mute = mute;
function createGroupChat(req, res) {
return __awaiter(this, void 0, void 0, function* () {
const { name, contact_ids, } = req.body;
const { name, contact_ids, is_public, } = req.body;
const members = {}; //{pubkey:{key,alias}, ...}
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
members[owner.publicKey] = {
@ -57,7 +59,14 @@ function createGroupChat(req, res) {
alias: contact.alias || ''
};
}));
const chatParams = createGroupChatParams(owner, contact_ids, members, name);
let chatParams = null;
if (is_public) {
chatParams = yield createPublicGroupChatParams(owner, contact_ids, name);
// and publish to tribes server? so can be discovered
}
else {
chatParams = createGroupChatParams(owner, contact_ids, members, name);
}
helpers.sendMessage({
chat: Object.assign(Object.assign({}, chatParams), { members }),
sender: owner,
@ -299,6 +308,30 @@ function createGroupChatParams(owner, contactIds, members, name) {
type: constants.chat_types.group
};
}
function createPublicGroupChatParams(owner, contactIds, name) {
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,
contactIds: JSON.stringify(theContactIds),
createdAt: date,
updatedAt: date,
name: name,
type: constants.chat_types.public_group,
groupKey: keys.public,
groupPrivateKey: keys.private,
host: tribes.getHost()
};
});
}
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

2
dist/api/controllers/index.js

@ -33,7 +33,7 @@ let controllers = {
function iniGrpcSubscriptions() {
return __awaiter(this, void 0, void 0, function* () {
try {
yield lightning_1.checkConnection();
yield lightning_1.getInfo();
const types = constants.message_types;
yield lndService.subscribeInvoices({
[types.contact_key]: controllers.contacts.receiveContactKey,

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

File diff suppressed because one or more lines are too long

27
dist/api/crypto/rsa.js

@ -29,6 +29,27 @@ function decrypt(privateKey, enc) {
}
}
exports.decrypt = decrypt;
function genKeys() {
return new Promise((resolve, reject) => {
crypto.generateKeyPair('rsa', {
modulusLength: 2048
}, (err, publicKey, privKey) => {
const pubPEM = publicKey.export({
type: 'pkcs1', format: 'pem'
});
const pubBase64 = cert.unpub(pubPEM);
const privPEM = privKey.export({
type: 'pkcs1', format: 'pem'
});
const privBase64 = cert.unpriv(privPEM);
resolve({
public: pubBase64,
private: privBase64,
});
});
});
}
exports.genKeys = genKeys;
function testRSA() {
crypto.generateKeyPair('rsa', {
modulusLength: 2048
@ -51,6 +72,12 @@ const cert = {
s = s.replace('-----END RSA PUBLIC KEY-----', '');
return s.replace(/[\r\n]+/gm, '');
},
unpriv: function (key) {
let s = key;
s = s.replace('-----BEGIN RSA PRIVATE KEY-----', '');
s = s.replace('-----END RSA PRIVATE KEY-----', '');
return s.replace(/[\r\n]+/gm, '');
},
pub: function (key) {
return '-----BEGIN RSA PUBLIC KEY-----\n' +
key + '\n' +

2
dist/api/crypto/rsa.js.map

@ -1 +1 @@
{"version":3,"file":"rsa.js","sourceRoot":"","sources":["../../../api/crypto/rsa.ts"],"names":[],"mappings":";;AAAA,iCAAiC;AAEjC,SAAgB,OAAO,CAAC,GAAG,EAAE,GAAG;IAC9B,IAAG;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC;YAC/B,GAAG,EAAC,IAAI;YACR,OAAO,EAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB;SAC3C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAC,OAAO,CAAC,CAAC,CAAA;QAC5B,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;KAC9B;IAAC,OAAM,CAAC,EAAE;QACT,OAAO,EAAE,CAAA;KACV;AACH,CAAC;AAXD,0BAWC;AAED,SAAgB,OAAO,CAAC,UAAU,EAAE,GAAG;IACrC,IAAG;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACnC,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,CAAC;YAChC,GAAG,EAAC,KAAK;YACT,OAAO,EAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB;SAC3C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAC,QAAQ,CAAC,CAAC,CAAA;QAC7B,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;KAC7B;IAAC,OAAM,CAAC,EAAE;QACT,OAAO,EAAE,CAAA;KACV;AACH,CAAC;AAXD,0BAWC;AAED,SAAgB,OAAO;IACrB,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE;QAC5B,aAAa,EAAE,IAAI;KACpB,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAC,EAAE;QACzB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;YAC9B,IAAI,EAAC,OAAO,EAAC,MAAM,EAAC,KAAK;SAC1B,CAAC,CAAA;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAE9B,MAAM,GAAG,GAAG,IAAI,CAAA;QAChB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAE7B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC9B,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAC,GAAG,CAAC,CAAA;IAC3B,CAAC,CAAC,CAAA;AACJ,CAAC;AAfD,0BAeC;AAED,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,UAAS,GAAG;QACjB,IAAI,CAAC,GAAG,GAAG,CAAA;QACX,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,gCAAgC,EAAC,EAAE,CAAC,CAAA;QAClD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,8BAA8B,EAAC,EAAE,CAAC,CAAA;QAChD,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;IACnC,CAAC;IACD,GAAG,EAAC,UAAS,GAAG;QACd,OAAO,kCAAkC;YACvC,GAAG,GAAG,IAAI;YACV,8BAA8B,CAAA;IAClC,CAAC;IACD,IAAI,EAAC,UAAS,GAAG;QACf,OAAO,mCAAmC;YACxC,GAAG,GAAG,IAAI;YACV,+BAA+B,CAAA;IACnC,CAAC;CACF,CAAA"}
{"version":3,"file":"rsa.js","sourceRoot":"","sources":["../../../api/crypto/rsa.ts"],"names":[],"mappings":"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"}

2
dist/api/helpers.js

@ -225,7 +225,7 @@ function asyncForEach(array, callback) {
function newmsg(type, chat, sender, message) {
return {
type: type,
chat: Object.assign(Object.assign(Object.assign({ uuid: chat.uuid }, chat.name && { name: chat.name }), chat.type && { type: chat.type }), chat.members && { members: chat.members }),
chat: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ uuid: chat.uuid }, chat.name && { name: chat.name }), chat.type && { type: chat.type }), chat.members && { members: chat.members }), chat.groupKey && { groupKey: chat.groupKey }), chat.host && { host: chat.host }),
message: message,
};
}

2
dist/api/helpers.js.map

File diff suppressed because one or more lines are too long

4
dist/api/utils/lightning.js

@ -399,7 +399,7 @@ function verifyMessage(msg, sig) {
}));
}
exports.verifyMessage = verifyMessage;
function checkConnection() {
function getInfo() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const lightning = loadLightning();
@ -414,7 +414,7 @@ function checkConnection() {
});
});
}
exports.checkConnection = checkConnection;
exports.getInfo = getInfo;
function ascii_to_hexa(str) {
var arr1 = [];
for (var n = 0, l = str.length; n < l; n++) {

2
dist/api/utils/lightning.js.map

File diff suppressed because one or more lines are too long

11
dist/api/utils/setup.js

@ -16,7 +16,7 @@ const QRCode = require("qrcode");
const publicIp = require("public-ip");
const password_1 = require("../utils/password");
const gitinfo_1 = require("../utils/gitinfo");
const USER_VERSION = 1;
const USER_VERSION = 2;
const setupDatabase = () => __awaiter(void 0, void 0, void 0, function* () {
console.log('=> [db] starting setup...');
yield setVersion();
@ -43,9 +43,16 @@ function setVersion() {
});
}
function migrate() {
return __awaiter(this, void 0, void 0, function* () {
addTableColumn('sphinx_chats', 'group_key');
addTableColumn('sphinx_chats', 'group_private_key');
addTableColumn('sphinx_chats', 'host');
});
}
function addTableColumn(table, column, type = 'TEXT') {
return __awaiter(this, void 0, void 0, function* () {
try {
yield models_1.sequelize.query(`alter table sphinx_invites add invoice text`);
yield models_1.sequelize.query(`alter table ${table} add ${column} ${type}`);
}
catch (e) {
//console.log('=> migrate failed',e)

2
dist/api/utils/setup.js.map

@ -1 +1 @@
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../api/utils/setup.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../api/utils/setup.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAA2C;AAC3C,sCAA2C;AAC3C,iDAAoC;AACpC,iCAAgC;AAChC,sCAAqC;AACrC,gDAAwC;AACxC,8CAA0D;AAE1D,MAAM,YAAY,GAAG,CAAC,CAAA;AAEtB,MAAM,aAAa,GAAG,GAAS,EAAE;IAC/B,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;IACxC,MAAM,UAAU,EAAE,CAAA;IAClB,IAAI;QACF,MAAM,kBAAS,CAAC,IAAI,EAAE,CAAA;QACtB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;KACpC;IAAC,OAAM,CAAC,EAAE;QACT,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAC,CAAC,CAAC,CAAA;KAChC;IACD,MAAM,OAAO,EAAE,CAAA;IACf,iBAAiB,EAAE,CAAA;IACnB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAA;AACnC,CAAC,CAAA,CAAA;AAsEQ,sCAAa;AApEtB,SAAe,UAAU;;QACvB,IAAI;YACF,MAAM,kBAAS,CAAC,KAAK,CAAC,yBAAyB,YAAY,EAAE,CAAC,CAAA;SAC/D;QAAC,OAAM,CAAC,EAAE;YACT,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAC,CAAC,CAAC,CAAA;SACtC;IACH,CAAC;CAAA;AAED,SAAe,OAAO;;QACpB,cAAc,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA;QAC3C,cAAc,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAA;QACnD,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;IACxC,CAAC;CAAA;AAED,SAAe,cAAc,CAAC,KAAY,EAAE,MAAa,EAAE,IAAI,GAAC,MAAM;;QACpE,IAAI;YACF,MAAM,kBAAS,CAAC,KAAK,CAAC,eAAe,KAAK,QAAQ,MAAM,IAAI,IAAI,EAAE,CAAC,CAAA;SACpE;QAAC,OAAM,CAAC,EAAE;YACT,oCAAoC;SACrC;IACH,CAAC;CAAA;AAED,MAAM,iBAAiB,GAAG,GAAS,EAAE;IACnC,MAAM,KAAK,GAAG,MAAM,eAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAC,CAAC,CAAA;IACvE,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,SAAS,GAAG,MAAM,yBAAa,EAAE,CAAA;QACvC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,CAAO,GAAG,EAAE,IAAI,EAAE,EAAE;YACxC,IAAI,GAAG,EAAE;gBACP,OAAO,CAAC,GAAG,CAAC,mDAAmD,EAAE,GAAG,CAAC,CAAA;aACtE;iBAAM;gBACL,IAAI;oBACF,MAAM,GAAG,GAAG,MAAM,eAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAC,CAAC,CAAA;oBAC7D,IAAG,CAAC,GAAG,EAAC;wBACN,MAAM,OAAO,GAAG,MAAM,eAAM,CAAC,OAAO,CAAC,MAAM,CAAC;4BAC1C,EAAE,EAAE,CAAC;4BACL,SAAS,EAAE,IAAI,CAAC,eAAe;4BAC/B,OAAO,EAAE,IAAI;4BACb,SAAS,EAAE,IAAI;yBAChB,CAAC,CAAA;wBACF,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;qBAChE;iBACF;gBAAC,OAAM,KAAK,EAAE;oBACb,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;iBACxD;aACF;QACH,CAAC,CAAA,CAAC,CAAA;KACH;AACH,CAAC,CAAA,CAAA;AAqBuB,8CAAiB;AAnBzC,MAAM,aAAa,GAAG,GAAS,EAAE;IAC/B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACpC,MAAM,OAAO,GAAQ,oBAAI,CAAC,wCAAwC,EAChE,EAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAC,EAClB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACtB,IAAI,GAAG,EAAE;gBACP,MAAM,CAAC,GAAG,CAAC,CAAC;aACb;iBAAM;gBACL,OAAO,EAAE,CAAC;aACX;QACH,CAAC,CACF,CAAC;QAEF,wCAAwC;QACxC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAA,CAAA;AAE0C,sCAAa;AAExD,SAAe,SAAS;;QACtB,MAAM,YAAY,EAAE,CAAA;QACpB,OAAO,EAAE,CAAA;IACX,CAAC;CAAA;AALyD,8BAAS;AAOnE,SAAe,YAAY;;QACzB,MAAM,UAAU,GAAG,MAAM,yBAAe,EAAE,CAAA;QAC1C,MAAM,GAAG,GAAG,MAAM,kBAAQ,EAAE,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,aAAa,UAAU,EAAE,CAAC,CAAA;IAChE,CAAC;CAAA;AAED,SAAe,OAAO;;QACpB,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAA;QAC9B,IAAI,SAAS,CAAA;QACb,IAAG,CAAC,EAAE,EAAE;YACN,IAAI;gBACF,SAAS,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,CAAA;aAChC;YAAC,OAAM,CAAC,EAAC;gBACR,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;aACf;SACF;aAAM;YACL,SAAS,GAAG,EAAE,CAAA;SACf;QACD,IAAG,CAAC,SAAS,EAAE;YACb,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAA;YACvC,OAAM;SACP;QACD,IAAI,KAAK,GAAG,SAAS,CAAA;QACrB,qDAAqD;QAErD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,kBAAQ,IAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAC3E,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;QAC1C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAChB,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAC,EAAC,IAAI,EAAC,UAAU,EAAC,EAAE,UAAU,GAAG,EAAE,GAAG;YACvD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC;CAAA"}

57
dist/api/utils/tribes.js

@ -0,0 +1,57 @@
"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 moment = require("moment");
const zbase32 = require("./zbase32");
const lightning_1 = require("./lightning");
const path = require("path");
const mqtt = require("mqtt");
const env = process.env.NODE_ENV || 'development';
const config = require(path.join(__dirname, '../../config/app.json'))[env];
function connect() {
return __awaiter(this, void 0, void 0, function* () {
const pwd = yield genSignedTimestamp();
const info = yield lightning_1.getInfo();
const client = mqtt.connect(`tcp://${config.tribes_host}`, {
username: info.identity_pubkey,
password: pwd,
});
client.on('connect', function () {
console.log("MQTT CLIENT CONNECTED!");
// subscribe to all public groups here
// that you are NOT admin of (dont sub to your own!)
});
client.on('close', function () {
console.log("MQTT CLOSED");
});
});
}
exports.connect = connect;
function genSignedTimestamp() {
return __awaiter(this, void 0, void 0, function* () {
const now = moment().unix();
const tsBytes = Buffer.from(now.toString(16), 'hex');
const sig = yield lightning_1.signBuffer(tsBytes);
const sigBytes = zbase32.decode(sig);
const totalLength = tsBytes.length + sigBytes.length;
const buf = Buffer.concat([tsBytes, sigBytes], totalLength);
return urlBase64(buf);
});
}
exports.genSignedTimestamp = genSignedTimestamp;
function getHost() {
return config.tribes_host || '';
}
exports.getHost = getHost;
function urlBase64(buf) {
return buf.toString('base64').replace(/\//g, '_').replace(/\+/g, '-');
}
//# sourceMappingURL=tribes.js.map

1
dist/api/utils/tribes.js.map

@ -0,0 +1 @@
{"version":3,"file":"tribes.js","sourceRoot":"","sources":["../../../api/utils/tribes.ts"],"names":[],"mappings":";;;;;;;;;;;AACA,iCAAgC;AAChC,qCAAoC;AACpC,2CAA+C;AAC/C,6BAA4B;AAC5B,6BAA4B;AAE5B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAA;AACjD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAC,uBAAuB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AAEzE,SAAsB,OAAO;;QACzB,MAAM,GAAG,GAAG,MAAM,kBAAkB,EAAE,CAAA;QACtC,MAAM,IAAI,GAAG,MAAM,mBAAO,EAAE,CAAA;QAE5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,MAAM,CAAC,WAAW,EAAE,EAAC;YACtD,QAAQ,EAAC,IAAI,CAAC,eAAe;YAC7B,QAAQ,EAAC,GAAG;SACf,CAAC,CAAA;QAEF,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE;YACjB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;YACrC,sCAAsC;YACtC,oDAAoD;QACxD,CAAC,CAAC,CAAA;QACF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;YACf,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;QAC9B,CAAC,CAAC,CAAA;IACN,CAAC;CAAA;AAjBD,0BAiBC;AAED,SAAsB,kBAAkB;;QACpC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAA;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;QACpD,MAAM,GAAG,GAAG,MAAM,sBAAU,CAAC,OAAO,CAAC,CAAA;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACpC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;QACpD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,CAAC,CAAA;QAC3D,OAAO,SAAS,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;CAAA;AARD,gDAQC;AAED,SAAgB,OAAO;IACnB,OAAO,MAAM,CAAC,WAAW,IAAI,EAAE,CAAA;AACnC,CAAC;AAFD,0BAEC;AAED,SAAS,SAAS,CAAC,GAAG;IAClB,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;AACzE,CAAC"}

3
dist/config/constants.json

@ -47,6 +47,7 @@
},
"chat_types": {
"conversation": 0,
"group": 1
"group": 1,
"public_group": 2
}
}

11
dist/public/index.html

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>React app</title>
</head>
<body>
<div id="app"></div>
<script src="/static/js/app.js"></script>
<link href="/static/semantic.min.css" rel="stylesheet" />
</body>
</html>

32444
dist/public/js/app.js

File diff suppressed because one or more lines are too long

BIN
dist/public/relay.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

372
dist/public/semantic.min.css

File diff suppressed because one or more lines are too long

291
package-lock.json

@ -1699,6 +1699,15 @@
"file-uri-to-path": "1.0.0"
}
},
"bl": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@ -2125,6 +2134,15 @@
}
}
},
"callback-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/callback-stream/-/callback-stream-1.1.0.tgz",
"integrity": "sha1-RwGlEmbwbgbqpx/BcjOCLYdfSQg=",
"requires": {
"inherits": "^2.0.1",
"readable-stream": "> 1.0.0 < 3.0.0"
}
},
"camel-case": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz",
@ -2475,6 +2493,15 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
"integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg=="
},
"commist": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
"integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
"requires": {
"leven": "^2.1.0",
"minimist": "^1.1.0"
}
},
"commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
@ -3278,7 +3305,6 @@
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
"integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
"dev": true,
"requires": {
"end-of-stream": "^1.0.0",
"inherits": "^2.0.1",
@ -3453,6 +3479,42 @@
"es6-symbol": "^3.1.1"
}
},
"es6-map": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
"integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
"requires": {
"d": "1",
"es5-ext": "~0.10.14",
"es6-iterator": "~2.0.1",
"es6-set": "~0.1.5",
"es6-symbol": "~3.1.1",
"event-emitter": "~0.3.5"
}
},
"es6-set": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
"integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
"requires": {
"d": "1",
"es5-ext": "~0.10.14",
"es6-iterator": "~2.0.1",
"es6-symbol": "3.1.1",
"event-emitter": "~0.3.5"
},
"dependencies": {
"es6-symbol": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
"integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
"requires": {
"d": "1",
"es5-ext": "~0.10.14"
}
}
}
},
"es6-symbol": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz",
@ -4690,7 +4752,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
"dev": true,
"requires": {
"is-glob": "^3.1.0",
"path-dirname": "^1.0.0"
@ -4700,13 +4761,29 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
"integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
"dev": true,
"requires": {
"is-extglob": "^2.1.0"
}
}
}
},
"glob-stream": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz",
"integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=",
"requires": {
"extend": "^3.0.0",
"glob": "^7.1.1",
"glob-parent": "^3.1.0",
"is-negated-glob": "^1.0.0",
"ordered-read-streams": "^1.0.0",
"pumpify": "^1.3.5",
"readable-stream": "^2.1.5",
"remove-trailing-separator": "^1.0.1",
"to-absolute-glob": "^2.0.0",
"unique-stream": "^2.0.2"
}
},
"global-dirs": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
@ -5420,6 +5497,17 @@
"dasherize": "2.0.0"
}
},
"help-me": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/help-me/-/help-me-1.1.0.tgz",
"integrity": "sha1-jy1QjQYAtKRW2i8IZVbn5cBWo8Y=",
"requires": {
"callback-stream": "^1.0.2",
"glob-stream": "^6.1.0",
"through2": "^2.0.1",
"xtend": "^4.0.0"
}
},
"hide-powered-by": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.1.0.tgz",
@ -5728,6 +5816,15 @@
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
"integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
},
"is-absolute": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
"integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
"requires": {
"is-relative": "^1.0.0",
"is-windows": "^1.0.1"
}
},
"is-absolute-url": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
@ -5866,8 +5963,7 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-finite": {
"version": "1.0.2",
@ -5936,6 +6032,11 @@
"define-properties": "^1.1.1"
}
},
"is-negated-glob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
"integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI="
},
"is-npm": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
@ -6033,6 +6134,14 @@
"has": "^1.0.1"
}
},
"is-relative": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
"integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
"requires": {
"is-unc-path": "^1.0.0"
}
},
"is-retry-allowed": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
@ -6058,6 +6167,14 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"is-unc-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
"integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
"requires": {
"unc-path-regex": "^0.1.2"
}
},
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
@ -6067,8 +6184,7 @@
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
},
"is-wsl": {
"version": "1.1.0",
@ -6191,6 +6307,11 @@
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@ -6272,6 +6393,11 @@
"invert-kv": "^2.0.0"
}
},
"leven": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
"integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA="
},
"load-json-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
@ -6872,6 +6998,50 @@
"run-queue": "^1.0.3"
}
},
"mqtt": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.0.0.tgz",
"integrity": "sha512-sRfKhSNK4yetSO9EyeXCNByKJiNW9XMtv214sEaXA2cUgeB+DWq9aKOxAdbW1rRbxjiqXPZYyjwt214TTgh0cA==",
"requires": {
"base64-js": "^1.3.0",
"commist": "^1.0.0",
"concat-stream": "^1.6.2",
"end-of-stream": "^1.4.1",
"es6-map": "^0.1.5",
"help-me": "^1.0.1",
"inherits": "^2.0.3",
"minimist": "^1.2.0",
"mqtt-packet": "^6.0.0",
"pump": "^3.0.0",
"readable-stream": "^2.3.6",
"reinterval": "^1.1.0",
"split2": "^3.1.0",
"websocket-stream": "^5.1.2",
"xtend": "^4.0.1"
}
},
"mqtt-packet": {
"version": "6.3.2",
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.3.2.tgz",
"integrity": "sha512-i56+2kN6F57KInGtjjfUXSl4xG8u/zOvfaXFLKFAbBXzWkXOmwcmjaSCBPayf2IQCkQU0+h+S2DizCo3CF6gQA==",
"requires": {
"bl": "^1.2.2",
"debug": "^4.1.1",
"inherits": "^2.0.3",
"process-nextick-args": "^2.0.0",
"safe-buffer": "^5.1.2"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
}
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@ -7566,6 +7736,14 @@
"resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz",
"integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4="
},
"ordered-read-streams": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
"integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=",
"requires": {
"readable-stream": "^2.0.1"
}
},
"original": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
@ -7780,8 +7958,7 @@
"path-dirname": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
"integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
"dev": true
"integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
},
"path-exists": {
"version": "3.0.0",
@ -8311,7 +8488,6 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
"integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
"dev": true,
"requires": {
"duplexify": "^3.6.0",
"inherits": "^2.0.3",
@ -8322,7 +8498,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
"integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
"dev": true,
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
@ -8717,11 +8892,15 @@
"jsesc": "~0.5.0"
}
},
"reinterval": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
"integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc="
},
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
"dev": true
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
},
"repeat-element": {
"version": "1.1.3",
@ -9803,6 +9982,26 @@
"extend-shallow": "^3.0.0"
}
},
"split2": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/split2/-/split2-3.1.1.tgz",
"integrity": "sha512-emNzr1s7ruq4N+1993yht631/JH+jaj0NYBosuKmLcq+JkGQ9MmTw1RB1fGaTCzUuseRIClrlSLHRNYGwWQ58Q==",
"requires": {
"readable-stream": "^3.0.0"
},
"dependencies": {
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -9924,8 +10123,7 @@
"stream-shift": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
"dev": true
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
},
"streamsearch": {
"version": "0.1.2",
@ -10216,12 +10414,20 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"through2-filter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz",
"integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==",
"requires": {
"through2": "~2.0.0",
"xtend": "~4.0.0"
}
},
"thunky": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz",
@ -10252,6 +10458,15 @@
"next-tick": "1"
}
},
"to-absolute-glob": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
"integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=",
"requires": {
"is-absolute": "^1.0.0",
"is-negated-glob": "^1.0.0"
}
},
"to-arraybuffer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
@ -10452,6 +10667,11 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz",
"integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw=="
},
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
"umzug": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/umzug/-/umzug-2.2.0.tgz",
@ -10461,6 +10681,11 @@
"bluebird": "^3.5.3"
}
},
"unc-path-regex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
"integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo="
},
"undefsafe": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz",
@ -10534,6 +10759,15 @@
"imurmurhash": "^0.1.4"
}
},
"unique-stream": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz",
"integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==",
"requires": {
"json-stable-stringify-without-jsonify": "^1.0.1",
"through2-filter": "^3.0.0"
}
},
"unique-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
@ -11166,6 +11400,31 @@
"integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
"dev": true
},
"websocket-stream": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.5.2.tgz",
"integrity": "sha512-8z49MKIHbGk3C4HtuHWDtYX8mYej1wWabjthC/RupM9ngeukU4IWoM46dgth1UOS/T4/IqgEdCDJuMe2039OQQ==",
"requires": {
"duplexify": "^3.5.1",
"inherits": "^2.0.1",
"readable-stream": "^2.3.3",
"safe-buffer": "^5.1.2",
"ws": "^3.2.0",
"xtend": "^4.0.0"
},
"dependencies": {
"ws": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
"requires": {
"async-limiter": "~1.0.0",
"safe-buffer": "~5.1.0",
"ultron": "~1.1.0"
}
}
}
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",

1
package.json

@ -46,6 +46,7 @@
"js-sha256": "^0.9.0",
"lodash": "^4.17.15",
"md5": "^2.2.1",
"mqtt": "^4.0.0",
"multer": "^1.4.2",
"node-fetch": "^2.6.0",
"pg": "^7.9.0",

Loading…
Cancel
Save