UNPKG

cyber-fca

Version:

A Facebook chat api for messenger bots.

323 lines (287 loc) 9.06 kB
var utils = require("../utils"); // @NethWs3Dev var bluebird = require("bluebird"); module.exports = function (defaultFuncs, api, ctx) { function uploadAttachment(attachments, callback) { callback = callback || function () {}; var uploads = []; // create an array of promises for (var i = 0; i < attachments.length; i++) { if (!utils.isReadableStream(attachments[i])) { throw { error: "Attachment should be a readable stream and not " + utils.getType(attachments[i]) + ".", }; } var form = { upload_1024: attachments[i], voice_clip: "true", }; uploads.push( defaultFuncs .postFormData( "https://upload.facebook.com/ajax/mercury/upload.php", ctx.jar, form, {}, ) .then(utils.parseAndCheckLogin(ctx, defaultFuncs)) .then(function (resData) { if (resData.error) { throw resData; } // We have to return the data unformatted unless we want to change it // back in sendMessage. return resData.payload.metadata[0]; }), ); } // resolve all promises bluebird .all(uploads) .then(function (resData) { callback(null, resData); }) .catch(function (err) { console.error("uploadAttachment", err); return callback(err); }); } let variance = 0; const epoch_id = () => Math.floor(Date.now() * (4194304 + (variance = (variance + 0.1) % 5))); const emojiSizes = { small: 1, medium: 2, large: 3, }; function handleEmoji(msg, form, callback, cb) { if (msg.emojiSize != null && msg.emoji == null) { return callback({ error: "emoji property is empty" }); } if (msg.emoji) { if (!msg.emojiSize) { msg.emojiSize = "small"; } if ( msg.emojiSize !== "small" && msg.emojiSize !== "medium" && msg.emojiSize !== "large" && (isNaN(msg.emojiSize) || msg.emojiSize < 1 || msg.emojiSize > 3) ) { return callback({ error: "emojiSize property is invalid" }); } form.payload.tasks[0].payload.send_type = 1; form.payload.tasks[0].payload.text = msg.emoji; form.payload.tasks[0].payload.hot_emoji_size = !isNaN(msg.emojiSize) ? msg.emojiSize : emojiSizes[msg.emojiSize]; } cb(); } function handleSticker(msg, form, callback, cb) { if (msg.sticker) { form.payload.tasks[0].payload.send_type = 2; form.payload.tasks[0].payload.sticker_id = msg.sticker; } cb(); } function handleAttachment(msg, form, callback, cb) { if (msg.attachment) { form.payload.tasks[0].payload.send_type = 3; form.payload.tasks[0].payload.attachment_fbids = []; if (form.payload.tasks[0].payload.text == "") form.payload.tasks[0].payload.text = null; if (utils.getType(msg.attachment) !== "Array") { msg.attachment = [msg.attachment]; } uploadAttachment(msg.attachment, function (err, files) { if (err) { return callback(err); } files.forEach(function (file) { var key = Object.keys(file); var type = key[0]; // image_id, file_id, etc form.payload.tasks[0].payload.attachment_fbids.push(file[type]); // push the id }); cb(); }); } else { cb(); } } function handleMention(msg, form, callback, cb) { if (msg.mentions) { form.payload.tasks[0].payload.send_type = 1; const arrayIds = []; const arrayOffsets = []; const arrayLengths = []; const mention_types = []; for (let i = 0; i < msg.mentions.length; i++) { const mention = msg.mentions[i]; const tag = mention.tag; if (typeof tag !== "string") { return callback({ error: "Mention tags must be strings." }); } const offset = msg.body.indexOf(tag, mention.fromIndex || 0); if (offset < 0) { console.warn( "handleMention", 'Mention for "' + tag + '" not found in message string.', ); } if (mention.id == null) { console.warn("handleMention", "Mention id should be non-null."); } const id = mention.id || 0; arrayIds.push(id); arrayOffsets.push(offset); arrayLengths.push(tag.length); mention_types.push("p"); } form.payload.tasks[0].payload.mention_data = { mention_ids: arrayIds.join(","), mention_offsets: arrayOffsets.join(","), mention_lengths: arrayLengths.join(","), mention_types: mention_types.join(","), }; } cb(); } function handleLocation(msg, form, callback, cb) { // this is not working yet if (msg.location) { if (msg.location.latitude == null || msg.location.longitude == null) { return callback({ error: "location property needs both latitude and longitude", }); } form.payload.tasks[0].payload.send_type = 1; form.payload.tasks[0].payload.location_data = { coordinates: { latitude: msg.location.latitude, longitude: msg.location.longitude, }, is_current_location: !!msg.location.current, is_live_location: !!msg.location.live, }; } cb(); } function send(form, threadID, callback, replyToMessage) { if (replyToMessage) { form.payload.tasks[0].payload.reply_metadata = { reply_source_id: replyToMessage, reply_source_type: 1, reply_type: 0, }; } const mqttClient = ctx.mqttClient; form.payload.tasks.forEach((task) => { task.payload = JSON.stringify(task.payload); }); form.payload = JSON.stringify(form.payload); console.log(global.jsonStringifyColor(form, null, 2)); return mqttClient.publish( "/ls_req", JSON.stringify(form), function (err, data) { if (err) { console.error("Error publishing message: ", err); callback(err); } else { console.log("Message published successfully with data: ", data); callback(null, data); } }, ); } return function sendMessageMqtt(msg, threadID, callback, replyToMessage) { if ( !callback && (utils.getType(threadID) === "Function" || utils.getType(threadID) === "AsyncFunction") ) { return threadID({ error: "Pass a threadID as a second argument." }); } if (!replyToMessage && utils.getType(callback) === "String") { replyToMessage = callback; callback = function () {}; } if (!callback) { callback = function (err, friendList) {}; } var msgType = utils.getType(msg); var threadIDType = utils.getType(threadID); var messageIDType = utils.getType(replyToMessage); if (msgType !== "String" && msgType !== "Object") { return callback({ error: "Message should be of type string or object and not " + msgType + ".", }); } if (msgType === "String") { msg = { body: msg }; } const timestamp = Date.now(); // get full date time const epoch = timestamp << 22; //const otid = epoch + 0; // TODO replace with randomInt(0, 2**22) const otid = epoch + Math.floor(Math.random() * 4194304); const form = { app_id: "2220391788200892", payload: { tasks: [ { label: "46", payload: { thread_id: threadID.toString(), otid: otid.toString(), source: 0, send_type: 1, sync_group: 1, text: msg.body != null && msg.body != undefined ? msg.body.toString() : "", initiating_source: 1, skip_url_preview_gen: 0, }, queue_name: threadID.toString(), task_id: 0, failure_count: null, }, { label: "21", payload: { thread_id: threadID.toString(), last_read_watermark_ts: Date.now(), sync_group: 1, }, queue_name: threadID.toString(), task_id: 1, failure_count: null, }, ], epoch_id: epoch_id(), version_id: "6120284488008082", data_trace_id: null, }, request_id: 1, type: 3, }; handleEmoji(msg, form, callback, function () { handleLocation(msg, form, callback, function () { handleMention(msg, form, callback, function () { handleSticker(msg, form, callback, function () { handleAttachment(msg, form, callback, function () { send(form, threadID, callback, replyToMessage); }); }); }); }); }); }; };