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

225 lines
10 KiB

"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 path = require("path");
const fetch = require("node-fetch");
const ldat_1 = require("../utils/ldat");
const rsa = require("../crypto/rsa");
const crypto = require("crypto");
const meme = require("../utils/meme");
const FormData = require("form-data");
const models_1 = require("../models");
const RNCryptor = require("jscryptor");
const send_1 = require("./send");
// import { Op } from 'sequelize'
const constants = require(path.join(__dirname, '../../config/constants.json'));
const msgtypes = constants.message_types;
function modifyPayloadAndSaveMediaKey(payload, chat, sender) {
return __awaiter(this, void 0, void 0, function* () {
if (payload.type !== msgtypes.attachment)
return payload;
try {
const ret = yield downloadAndUploadAndSaveReturningTermsAndKey(payload, chat, sender);
return fillmsg(payload, ret); // key is re-encrypted later
}
catch (e) {
console.log("[modify] error", e);
return payload;
}
});
}
exports.modifyPayloadAndSaveMediaKey = modifyPayloadAndSaveMediaKey;
// "purchase" type
function purchaseFromOriginalSender(payload, chat, purchaser) {
return __awaiter(this, void 0, void 0, function* () {
if (payload.type !== msgtypes.purchase)
return;
const mt = payload.message && payload.message.mediaToken;
const amount = payload.message.amount;
const muid = mt && mt.split('.').length && mt.split('.')[1];
if (!muid)
return;
const mediaKey = yield models_1.models.MediaKey.findOne({ where: { originalMuid: muid } });
const terms = ldat_1.parseLDAT(mt);
let price = terms.meta && terms.meta.amt;
if (amount < price)
return; // not enough sats
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
if (mediaKey) { // ALREADY BEEN PURHCASED! simply send
// send back the new mediaToken and key
const mediaTerms = {
muid: mediaKey.muid, ttl: 31536000, host: '',
meta: Object.assign({}, amount && { amt: amount }),
};
// send full new key and token
const msg = {
mediaTerms,
mediaKey: mediaKey.key,
originalMuid: mediaKey.originalMuid,
mediaType: mediaKey.mediaType
};
send_1.sendMessage({
chat: Object.assign(Object.assign({}, chat.dataValues), { contactIds: [purchaser.id] }),
sender: owner,
type: constants.message_types.purchase_accept,
message: msg,
success: () => { },
failure: () => { }
});
// PAY THE OG POSTER HERE!!!
send_1.sendMessage({
chat: Object.assign(Object.assign({}, chat.dataValues), { contactIds: [mediaKey.sender] }),
sender: owner,
type: constants.message_types.purchase,
amount: amount,
message: {
mediaToken: mt,
skipPaymentProcessing: true,
},
success: () => { },
failure: () => { }
});
}
else {
const ogmsg = yield models_1.models.Message.findOne({ where: { chatId: chat.id, mediaToken: mt } });
if (!ogmsg)
return;
// purchase it from creator (send "purchase")
const msg = { mediaToken: mt, purchaser: purchaser.id };
send_1.sendMessage({
chat: Object.assign(Object.assign({}, chat.dataValues), { contactIds: [ogmsg.sender] }),
sender: Object.assign(Object.assign({}, owner.dataValues), purchaser && purchaser.alias && { alias: purchaser.alias }),
type: constants.message_types.purchase,
message: msg,
amount: amount,
success: () => { },
failure: () => { }
});
}
});
}
exports.purchaseFromOriginalSender = purchaseFromOriginalSender;
function sendFinalMemeIfFirstPurchaser(payload, chat, sender) {
return __awaiter(this, void 0, void 0, function* () {
if (payload.type !== msgtypes.purchase_accept)
return;
const mt = payload.message && payload.message.mediaToken;
const typ = payload.message && payload.message.mediaType;
const purchaserID = payload.message && payload.message.purchaser;
if (!mt)
return;
const muid = mt && mt.split('.').length && mt.split('.')[1];
if (!muid)
return;
const existingMediaKey = yield models_1.models.MediaKey.findOne({ where: { muid } });
if (existingMediaKey)
return; // no need, its already been sent
// const host = mt.split('.')[0]
const terms = ldat_1.parseLDAT(mt);
const ogPurchaser = yield models_1.models.Contact.findOne({ where: {
id: purchaserID
} });
if (!ogPurchaser)
return;
const amt = (terms.meta && terms.meta.amt) || 0;
// const ogPurchaseMessage = await models.Message.findOne({where:{
// mediaToken: {[Op.like]: `${host}.${muid}%`},
// type: msgtypes.purchase,
// }})
const termsAndKey = yield downloadAndUploadAndSaveReturningTermsAndKey(payload, chat, sender, amt);
// send it to the purchaser
const owner = yield models_1.models.Contact.findOne({ where: { isOwner: true } });
send_1.sendMessage({
sender: Object.assign(Object.assign({}, owner.dataValues), sender && sender.alias && { alias: sender.alias }),
chat: Object.assign(Object.assign({}, chat.dataValues), { contactIds: [ogPurchaser.id] }),
type: msgtypes.purchase_accept,
message: Object.assign(Object.assign({}, termsAndKey), { mediaType: typ, originalMuid: muid }),
success: () => { },
receive: () => { }
});
});
}
exports.sendFinalMemeIfFirstPurchaser = sendFinalMemeIfFirstPurchaser;
function fillmsg(full, props) {
return Object.assign(Object.assign({}, full), { message: Object.assign(Object.assign({}, full.message), props) });
}
function sleep(ms) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise(resolve => setTimeout(resolve, ms));
});
}
function downloadAndUploadAndSaveReturningTermsAndKey(payload, chat, sender, injectedAmount) {
return __awaiter(this, void 0, void 0, function* () {
const mt = payload.message && payload.message.mediaToken;
const key = payload.message && payload.message.mediaKey;
const typ = payload.message && payload.message.mediaType;
if (!mt || !key)
return payload; // save anyway??????????
const ogmuid = mt && mt.split('.').length && mt.split('.')[1];
const terms = ldat_1.parseLDAT(mt);
if (!terms.host)
return payload;
try {
const r = yield fetch(`https://${terms.host}/file/${mt}`, {
headers: { 'Authorization': `Bearer ${meme.mediaToken}` }
});
const buf = yield r.buffer();
const decMediaKey = rsa.decrypt(chat.groupPrivateKey, key);
const imgBuf = RNCryptor.Decrypt(buf.toString('base64'), decMediaKey);
const newKey = crypto.randomBytes(20).toString('hex');
const encImgBase64 = RNCryptor.Encrypt(imgBuf, newKey);
var encImgBuffer = Buffer.from(encImgBase64, 'base64');
const form = new FormData();
form.append('file', encImgBuffer, {
contentType: typ || 'image/jpg',
filename: 'Image.jpg',
knownLength: encImgBuffer.length,
});
const formHeaders = form.getHeaders();
const resp = yield fetch(`https://${terms.host}/file`, {
method: 'POST',
headers: Object.assign(Object.assign({}, formHeaders), { 'Authorization': `Bearer ${meme.mediaToken}` }),
body: form
});
let json = yield resp.json();
if (!json.muid)
throw new Error('no muid');
// PUT NEW TERMS, to finish in personalizeMessage
const amt = (terms.meta && terms.meta.amt) || injectedAmount;
const ttl = terms.meta && terms.meta.ttl;
const mediaTerms = {
muid: json.muid, ttl: ttl || 31536000, host: '',
meta: Object.assign({}, amt && { amt }),
};
const encKey = rsa.encrypt(chat.groupKey, newKey.slice());
var date = new Date();
date.setMilliseconds(0);
yield sleep(1);
yield models_1.models.MediaKey.create({
muid: json.muid,
chatId: chat.id,
key: encKey,
messageId: (payload.message && payload.message.id) || 0,
receiver: 0,
sender: sender.id,
createdAt: date,
originalMuid: ogmuid,
mediaType: typ,
});
return { mediaTerms, mediaKey: encKey };
}
catch (e) {
throw e;
}
});
}
exports.downloadAndUploadAndSaveReturningTermsAndKey = downloadAndUploadAndSaveReturningTermsAndKey;
//# sourceMappingURL=modify.js.map