UNPKG

@dongdev/fca-unofficial

Version:

Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically

1,373 lines (1,359 loc) 1.03 MB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/func/logger.ts function writeStdout(message) { process.stdout.write(`${message} `); } function writeStderr(message) { process.stderr.write(`${message} `); } function padLabel(label, width = 8) { return label.length >= width ? label : `${label}${" ".repeat(width - label.length)}`; } function getTimestamp() { const now = /* @__PURE__ */ new Date(); const hh = String(now.getHours()).padStart(2, "0"); const mm = String(now.getMinutes()).padStart(2, "0"); const ss = String(now.getSeconds()).padStart(2, "0"); return `${hh}:${mm}:${ss}`; } function getTheme() { const fromEnv = String(process.env.FCA_LOG_THEME || "").toLowerCase(); if (fromEnv === "minimal") return "minimal"; return "cyberpunk"; } function makeStyles(theme) { if (theme === "minimal") { return { time: (v) => import_picocolors.default.dim(v), text: (v) => import_picocolors.default.white(v), info: (v) => import_picocolors.default.cyan(v), warn: (v) => import_picocolors.default.yellow(v), error: (v) => import_picocolors.default.red(v), sys: (v) => import_picocolors.default.blue(v) }; } return { time: (v) => import_picocolors.default.dim(v), text: (v) => import_picocolors.default.white(v), info: (v) => import_picocolors.default.cyan(v), warn: (v) => import_picocolors.default.yellow(v), error: (v) => import_picocolors.default.red(v), sys: (v) => import_picocolors.default.blue(v) }; } function parseLabel(message, fallback) { const m = message.match(/^([A-Z][A-Z0-9 _-]{1,14})\s*:\s*(.+)$/); if (!m) return { label: fallback, body: message }; return { label: m[1].trim(), body: m[2] }; } function loadGradientFns() { if (gradientFns !== void 0) return gradientFns; try { const g3 = typeof import_gradient_string.default === "function" ? import_gradient_string.default : import_gradient_string.default.default; if (typeof g3 !== "function") { gradientFns = null; return gradientFns; } gradientFns = { cyberpunk: g3("magenta", "cyan"), blueToRed: g3("#3b82f6", "#ef4444"), coolStatus: g3("#86efac", "#22d3ee") }; } catch { gradientFns = null; } return gradientFns; } function formatSuccessBody(body, grad, fallbackPaint) { const m = body.match(/^Loaded (\d+) API methods(.*)$/i); if (m && grad) { return `${import_picocolors.default.dim("Loaded ")}${grad.blueToRed(m[1])}${import_picocolors.default.dim(` API methods${m[2]}`)}`; } return fallbackPaint(body); } async function ensureUiLibs() { if (!oraFactory) { try { const oraMod = await import("ora"); oraFactory = oraMod.default ?? oraMod; } catch { } } if (!progressCtor || !progressPreset) { try { const progressMod = await import("cli-progress"); progressCtor = progressMod.SingleBar ?? progressMod.default?.SingleBar; progressPreset = progressMod.Presets?.shades_classic ?? progressMod.default?.Presets?.shades_classic ?? null; } catch { } } } function logLine(text, type) { const level = String(type || "info").toLowerCase(); const message = String(text ?? ""); const styles = makeStyles(getTheme()); const ts = styles.time(`[${getTimestamp()}]`); const theme = getTheme(); const grad = theme === "cyberpunk" ? loadGradientFns() : null; if (level === "success") { const parts2 = parseLabel(message, "READY"); const bodyOut2 = parts2.label === "READY" ? formatSuccessBody(parts2.body, grad, styles.text) : grad ? grad.coolStatus(parts2.body) : styles.text(parts2.body); const labelOut2 = grad ? grad.coolStatus(padLabel(parts2.label)) : styles.text(padLabel(parts2.label)); writeStdout(`${ts} ${import_picocolors.default.bgGreen(import_picocolors.default.black(import_picocolors.default.bold(" SUCCESS ")))} ${labelOut2} : ${bodyOut2}`); return; } if (level === "warn") { const parts2 = parseLabel(message, "WARN"); writeStderr(`${ts} ${styles.text(padLabel(parts2.label))} : ${styles.warn(parts2.body)}`); return; } if (level === "error") { const parts2 = parseLabel(message, "ERROR"); writeStderr(`${ts} ${styles.text(padLabel(parts2.label))} : ${styles.error(parts2.body)}`); return; } if (level === "sys" || level === "system" || level === "core") { const parts2 = parseLabel(message, "SYSTEM"); const labelOut2 = grad ? grad.blueToRed(padLabel(parts2.label)) : styles.text(padLabel(parts2.label)); const bodyOut2 = grad ? import_picocolors.default.dim(import_picocolors.default.blue(parts2.body)) : styles.sys(parts2.body); writeStdout(`${ts} ${labelOut2} : ${bodyOut2}`); return; } const parts = parseLabel(message, "SESSION"); const labelOut = grad ? grad.coolStatus(padLabel(parts.label)) : styles.text(padLabel(parts.label)); const bodyOut = grad ? grad.coolStatus(parts.body) : styles.info(parts.body); writeStdout(`${ts} ${labelOut} : ${bodyOut}`); } var import_picocolors, import_gradient_string, oraFactory, progressCtor, progressPreset, gradientFns, baseLogger, logger_default; var init_logger = __esm({ "src/func/logger.ts"() { "use strict"; import_picocolors = __toESM(require("picocolors")); import_gradient_string = __toESM(require("gradient-string")); oraFactory = null; progressCtor = null; progressPreset = null; baseLogger = logLine; baseLogger.fca = (text) => baseLogger(`SESSION: ${text}`, "info"); baseLogger.sys = (text) => baseLogger(`SYSTEM: ${text}`, "sys"); baseLogger.success = (text) => baseLogger(text, "success"); baseLogger.warn = (text) => baseLogger(text, "warn"); baseLogger.error = (text) => baseLogger(text, "error"); baseLogger.showBanner = async () => { }; baseLogger.startSpinner = async (text) => { await ensureUiLibs(); if (!oraFactory || !process.stdout.isTTY) return null; const grad = getTheme() === "cyberpunk" ? loadGradientFns() : null; const line = grad ? grad.cyberpunk(text) : import_picocolors.default.cyan(text); const spinner = oraFactory({ text: line, color: "cyan" }); return typeof spinner.start === "function" ? spinner.start() : spinner; }; baseLogger.runMethodLoadProgress = async (loaded) => { await ensureUiLibs(); if (!progressCtor || !process.stdout.isTTY || loaded <= 0) return; const grad = getTheme() === "cyberpunk" ? loadGradientFns() : null; const prefix = grad ? grad.cyberpunk("fca \xB7 methods") : import_picocolors.default.cyan("fca \xB7 methods"); const bar = new progressCtor( { format: `${prefix} |{bar}| {percentage}% | {value}/{total}`, barCompleteChar: "\u2588", barIncompleteChar: "\u2591", hideCursor: true }, progressPreset ?? void 0 ); bar.start(loaded, 0); for (let i = 1; i <= loaded; i += 1) { bar.update(i); } bar.stop(); }; baseLogger.persistCheckpointOk = (spinner) => { if (spinner && typeof spinner.stop === "function") { spinner.stop(); } baseLogger("SESSION: No checkpoint detected", "info"); }; baseLogger.persistLoginSuccess = (spinner) => { if (spinner && typeof spinner.stop === "function") { spinner.stop(); } }; baseLogger.persistLoginFail = (spinner) => { if (spinner && typeof spinner.stop === "function") { spinner.stop(); } }; logger_default = baseLogger; } }); // src/utils/format/attachment.ts var require_attachment = __commonJS({ "src/utils/format/attachment.ts"(exports2, module2) { "use strict"; var import_node_querystring = __toESM(require("querystring")); var import_node_url2 = __toESM(require("url")); function _formatAttachment2(attachment1, attachment2) { attachment2 = attachment2 || { id: "", image_data: {} }; attachment1 = attachment1.mercury ? attachment1.mercury : attachment1; var blob = attachment1.blob_attachment; var type = blob && blob.__typename ? blob.__typename : attachment1.attach_type; if (!type && attachment1.sticker_attachment) { type = "StickerAttachment"; blob = attachment1.sticker_attachment; } else if (!type && attachment1.extensible_attachment) { if (attachment1.extensible_attachment.story_attachment && attachment1.extensible_attachment.story_attachment.target && attachment1.extensible_attachment.story_attachment.target.__typename && attachment1.extensible_attachment.story_attachment.target.__typename === "MessageLocation") type = "MessageLocation"; else type = "ExtensibleAttachment"; blob = attachment1.extensible_attachment; } if (blob && blob.real_metadata) { const realMetadata = blob.real_metadata; if (realMetadata.Src) { attachment2.src = realMetadata.Src; } if (realMetadata.ThumbnailSrc) { attachment2.thumbnailSrc = realMetadata.ThumbnailSrc; } } switch (type) { case "sticker": return { type: "sticker", ID: attachment1.metadata.stickerID.toString(), url: attachment1.url, packID: attachment1.metadata.packID.toString(), spriteUrl: attachment1.metadata.spriteURI, spriteUrl2x: attachment1.metadata.spriteURI2x, width: attachment1.metadata.width, height: attachment1.metadata.height, caption: attachment2.caption, description: attachment2.description, frameCount: attachment1.metadata.frameCount, frameRate: attachment1.metadata.frameRate, framesPerRow: attachment1.metadata.framesPerRow, framesPerCol: attachment1.metadata.framesPerCol, stickerID: attachment1.metadata.stickerID.toString(), spriteURI: attachment1.metadata.spriteURI, spriteURI2x: attachment1.metadata.spriteURI2x }; case "file": return { type: "file", filename: attachment1.name, ID: attachment2.id.toString(), url: attachment1.url, isMalicious: attachment2.is_malicious, contentType: attachment2.mime_type, name: attachment1.name, mimeType: attachment2.mime_type, fileSize: attachment2.file_size }; case "photo": return { type: "photo", ID: attachment1.metadata.fbid.toString(), filename: attachment1.fileName, thumbnailUrl: attachment1.thumbnail_url, previewUrl: attachment1.preview_url, previewWidth: attachment1.preview_width, previewHeight: attachment1.preview_height, largePreviewUrl: attachment1.large_preview_url, largePreviewWidth: attachment1.large_preview_width, largePreviewHeight: attachment1.large_preview_height, url: attachment1.metadata.url, width: attachment1.metadata.dimensions.split(",")[0], height: attachment1.metadata.dimensions.split(",")[1], name: attachment1.fileName }; case "animated_image": return { type: "animated_image", ID: attachment2.id.toString(), filename: attachment2.filename, previewUrl: attachment1.preview_url, previewWidth: attachment1.preview_width, previewHeight: attachment1.preview_height, url: attachment2.image_data.url, width: attachment2.image_data.width, height: attachment2.image_data.height, name: attachment1.name, facebookUrl: attachment1.url, thumbnailUrl: attachment1.thumbnail_url, mimeType: attachment2.mime_type, rawGifImage: attachment2.image_data.raw_gif_image, rawWebpImage: attachment2.image_data.raw_webp_image, animatedGifUrl: attachment2.image_data.animated_gif_url, animatedGifPreviewUrl: attachment2.image_data.animated_gif_preview_url, animatedWebpUrl: attachment2.image_data.animated_webp_url, animatedWebpPreviewUrl: attachment2.image_data.animated_webp_preview_url }; case "share": return { type: "share", ID: attachment1.share.share_id.toString(), url: attachment2.href, title: attachment1.share.title, description: attachment1.share.description, source: attachment1.share.source, image: attachment1.share.media.image, width: attachment1.share.media.image_size.width, height: attachment1.share.media.image_size.height, playable: attachment1.share.media.playable, duration: attachment1.share.media.duration, subattachments: attachment1.share.subattachments, properties: {}, animatedImageSize: attachment1.share.media.animated_image_size, facebookUrl: attachment1.share.uri, target: attachment1.share.target, styleList: attachment1.share.style_list }; case "video": return { type: "video", ID: attachment1.metadata.fbid.toString(), filename: attachment1.name, previewUrl: attachment1.preview_url, previewWidth: attachment1.preview_width, previewHeight: attachment1.preview_height, url: attachment1.url, width: attachment1.metadata.dimensions.width, height: attachment1.metadata.dimensions.height, duration: attachment1.metadata.duration, videoType: "unknown", thumbnailUrl: attachment1.thumbnail_url }; case "error": return { type: "error", attachment1, attachment2 }; case "MessageImage": return { type: "photo", ID: blob.legacy_attachment_id, filename: blob.filename, thumbnailUrl: blob.thumbnail.uri, previewUrl: blob.preview.uri, previewWidth: blob.preview.width, previewHeight: blob.preview.height, largePreviewUrl: blob.large_preview.uri, largePreviewWidth: blob.large_preview.width, largePreviewHeight: blob.large_preview.height, url: blob.large_preview.uri, width: blob.original_dimensions.x, height: blob.original_dimensions.y, name: blob.filename }; case "MessageAnimatedImage": return { type: "animated_image", ID: blob.legacy_attachment_id, filename: blob.filename, previewUrl: blob.preview_image.uri, previewWidth: blob.preview_image.width, previewHeight: blob.preview_image.height, url: blob.animated_image.uri, width: blob.animated_image.width, height: blob.animated_image.height, thumbnailUrl: blob.preview_image.uri, name: blob.filename, facebookUrl: blob.animated_image.uri, rawGifImage: blob.animated_image.uri, animatedGifUrl: blob.animated_image.uri, animatedGifPreviewUrl: blob.preview_image.uri, animatedWebpUrl: blob.animated_image.uri, animatedWebpPreviewUrl: blob.preview_image.uri }; case "MessageVideo": return { type: "video", filename: blob.filename, ID: blob.legacy_attachment_id, previewUrl: blob.large_image.uri, previewWidth: blob.large_image.width, previewHeight: blob.large_image.height, url: blob.playable_url, width: blob.original_dimensions.x, height: blob.original_dimensions.y, duration: blob.playable_duration_in_ms, videoType: blob.video_type.toLowerCase(), thumbnailUrl: blob.large_image.uri }; case "MessageAudio": return { type: "audio", filename: blob.filename, ID: blob.url_shimhash, audioType: blob.audio_type, duration: blob.playable_duration_in_ms, url: blob.playable_url, isVoiceMail: blob.is_voicemail }; case "StickerAttachment": return { type: "sticker", ID: blob.id, url: blob.url, packID: blob.pack ? blob.pack.id : null, spriteUrl: blob.sprite_image, spriteUrl2x: blob.sprite_image_2x, width: blob.width, height: blob.height, caption: blob.label, description: blob.label, frameCount: blob.frame_count, frameRate: blob.frame_rate, framesPerRow: blob.frames_per_row, framesPerCol: blob.frames_per_column, stickerID: blob.id, spriteURI: blob.sprite_image, spriteURI2x: blob.sprite_image_2x }; case "MessageLocation": { var urlAttach = blob.story_attachment.url; var mediaAttach = blob.story_attachment.media; const q0 = import_node_url2.default.parse(String(urlAttach)).query; const uRaw = import_node_querystring.default.parse(typeof q0 === "string" ? q0 : "").u; const uPart = Array.isArray(uRaw) ? uRaw[0] : uRaw; const u = uPart != null ? String(uPart) : ""; const q1 = import_node_url2.default.parse(u).query; const where1Raw = import_node_querystring.default.parse(typeof q1 === "string" ? q1 : "").where1; const where1 = Array.isArray(where1Raw) ? where1Raw[0] : where1Raw; const whereStr = typeof where1 === "string" ? where1 : ""; var address = whereStr.split(", "); var latitude; var longitude; try { latitude = Number.parseFloat(address[0]); longitude = Number.parseFloat(address[1]); } catch (err) { } var imageUrl; var width; var height; if (mediaAttach && mediaAttach.image) { imageUrl = mediaAttach.image.uri; width = mediaAttach.image.width; height = mediaAttach.image.height; } return { type: "location", ID: blob.legacy_attachment_id, latitude, longitude, image: imageUrl, width, height, url: u || urlAttach, address: whereStr, facebookUrl: blob.story_attachment.url, target: blob.story_attachment.target, styleList: blob.story_attachment.style_list }; } case "ExtensibleAttachment": return { type: "share", ID: blob.legacy_attachment_id, url: blob.story_attachment.url, title: blob.story_attachment.title_with_entities.text, description: blob.story_attachment.description && blob.story_attachment.description.text, source: blob.story_attachment.source ? blob.story_attachment.source.text : null, image: blob.story_attachment.media && blob.story_attachment.media.image && blob.story_attachment.media.image.uri, width: blob.story_attachment.media && blob.story_attachment.media.image && blob.story_attachment.media.image.width, height: blob.story_attachment.media && blob.story_attachment.media.image && blob.story_attachment.media.image.height, playable: blob.story_attachment.media && blob.story_attachment.media.is_playable, duration: blob.story_attachment.media && blob.story_attachment.media.playable_duration_in_ms, playableUrl: blob.story_attachment.media == null ? null : blob.story_attachment.media.playable_url, subattachments: blob.story_attachment.subattachments, properties: blob.story_attachment.properties.reduce( function(obj, cur) { const row = cur; if (row.key) obj[row.key] = row.value?.text; return obj; }, {} ), facebookUrl: blob.story_attachment.url, target: blob.story_attachment.target, styleList: blob.story_attachment.style_list }; case "MessageFile": return { type: "file", filename: blob.filename, ID: blob.message_file_fbid, url: blob.url, isMalicious: blob.is_malicious, contentType: blob.content_type, name: blob.filename, mimeType: "", fileSize: -1 }; default: throw new Error( "unrecognized attach_file of type " + type + "`" + JSON.stringify(attachment1, null, 4) + " attachment2: " + JSON.stringify(attachment2, null, 4) + "`" ); } } function formatAttachment(attachments, attachmentIds, attachmentMap, shareMap) { const map = shareMap || attachmentMap; return attachments ? attachments.map(function(att, idx) { if (!map || !attachmentIds || !map[attachmentIds[idx]]) { return _formatAttachment2(att, void 0); } return _formatAttachment2(att, map[attachmentIds[idx]]); }) : []; } module2.exports = { _formatAttachment: _formatAttachment2, formatAttachment }; } }); // src/utils/format/cookie.ts var require_cookie = __commonJS({ "src/utils/format/cookie.ts"(exports2, module2) { "use strict"; function formatCookie2(arr, urlBase) { return `${arr[0]}=${arr[1]}; Path=${arr[3]}; Domain=${urlBase}.com`; } module2.exports = { formatCookie: formatCookie2 }; } }); // src/utils/format/date.ts var require_date = __commonJS({ "src/utils/format/date.ts"(exports2, module2) { "use strict"; var NUM_TO_MONTH = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; var NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; function formatDate(date) { let d = date.getUTCDate(); d = d >= 10 ? d : "0" + d; let h = date.getUTCHours(); h = h >= 10 ? h : "0" + h; let m = date.getUTCMinutes(); m = m >= 10 ? m : "0" + m; let s = date.getUTCSeconds(); s = s >= 10 ? s : "0" + s; return `${NUM_TO_DAY[date.getUTCDay()]}, ${d} ${NUM_TO_MONTH[date.getUTCMonth()]} ${date.getUTCFullYear()} ${h}:${m}:${s} GMT`; } module2.exports = { NUM_TO_MONTH, NUM_TO_DAY, formatDate }; } }); // src/utils/format/decode.ts var require_decode = __commonJS({ "src/utils/format/decode.ts"(exports2, module2) { "use strict"; function decodeClientPayload(payload) { function utf8ArrayToStr(array) { let out = ""; const len = array.length; let i = 0; while (i < len) { const c = array[i++]; let char2; let char3; switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: out += String.fromCharCode(c); break; case 12: case 13: char2 = array[i++]; out += String.fromCharCode((c & 31) << 6 | char2 & 63); break; case 14: char2 = array[i++]; char3 = array[i++]; out += String.fromCharCode((c & 15) << 12 | (char2 & 63) << 6 | char3 & 63); break; } } return out; } return JSON.parse(utf8ArrayToStr(payload)); } module2.exports = { decodeClientPayload }; } }); // src/utils/format/utils.ts function getType(obj) { return Object.prototype.toString.call(obj).slice(8, -1); } function formatID(id) { if (id !== void 0 && id !== null) return id.replace(/(fb)?id[:.]/, ""); return id; } function padZeros(val, len = 2) { let out = String(val); while (out.length < len) out = "0" + out; return out; } function arrayToObject(arr, getKey, getValue) { return arr.reduce((acc, val) => { acc[getKey(val)] = getValue(val); return acc; }, {}); } function arrToForm(form) { return arrayToObject( form, (v) => v.name, (v) => v.val ); } function getData_Path(Obj, Arr, Stt) { if (Arr.length === 0 && Obj !== void 0) { return Obj; } if (Obj === void 0) { return Stt; } const head = Arr[0]; if (head === void 0) { return Stt; } const tail = Arr.slice(1); return getData_Path(Obj[head], tail, Stt++); } function setData_Path(obj, path5, value) { if (!path5.length) { return obj; } const currentKey = path5[0]; let currentObj = obj[currentKey]; if (!currentObj) { obj[currentKey] = value; currentObj = obj[currentKey]; } path5.shift(); if (!path5.length) { currentObj = value; } else { currentObj = setData_Path(currentObj, path5, value); } return obj; } function getPaths(obj, parentPath = []) { let paths = []; for (const prop in obj) { if (typeof obj[prop] === "object" && obj[prop] !== null) { paths = paths.concat(getPaths(obj[prop], [...parentPath, prop])); } else { paths.push([...parentPath, prop]); } } return paths; } function cleanHTML(text) { let out = text; out = out.replace( /(<br>)|(<\/?i>)|(<\/?em>)|(<\/?b>)|(!?~)|(&amp;)|(&#039;)|(&lt;)|(&gt;)|(&quot;)/g, (match) => { switch (match) { case "<br>": return "\n"; case "<i>": case "<em>": case "</i>": case "</em>": return "*"; case "<b>": case "</b>": return "**"; case "~!": case "!~": return "||"; case "&amp;": return "&"; case "&#039;": return "'"; case "&lt;": return "<"; case "&gt;": return ">"; case "&quot;": return '"'; default: return match; } } ); return out; } function getCurrentTimestamp() { return Date.now(); } function getSignatureID() { return Math.floor(Math.random() * 2147483648).toString(16); } var init_utils = __esm({ "src/utils/format/utils.ts"() { "use strict"; } }); // src/utils/format/delta.ts var require_delta = __commonJS({ "src/utils/format/delta.ts"(exports2, module2) { "use strict"; var import_attachment = __toESM(require_attachment()); init_utils(); var { _formatAttachment: _formatAttachment2 } = import_attachment.default; function getAdminTextMessageType2(m) { const type = m && (m.type || m); switch (type) { case "joinable_group_link_mode_change": return "log:link-status"; case "magic_words": return "log:magic-words"; case "change_thread_theme": return "log:thread-color"; case "change_thread_icon": case "change_thread_quick_reaction": return "log:thread-icon"; case "change_thread_nickname": return "log:user-nickname"; case "change_thread_admins": return "log:thread-admins"; case "group_poll": return "log:thread-poll"; case "change_thread_approval_mode": return "log:thread-approval-mode"; case "messenger_call_log": case "participant_joined_group_call": return "log:thread-call"; case "pin_messages_v2": return "log:thread-pinned"; case "unpin_messages_v2": return "log:unpin-message"; default: return m && m.type != null ? m.type : type; } } function formatDeltaEvent(m) { var logMessageType; var logMessageData; switch (m.class) { case "AdminTextMessage": logMessageType = getAdminTextMessageType2(m); logMessageData = m.untypedData; break; case "ThreadName": logMessageType = "log:thread-name"; logMessageData = { name: m.name }; break; case "ParticipantsAddedToGroupThread": logMessageType = "log:subscribe"; logMessageData = { addedParticipants: m.addedParticipants }; break; case "ParticipantLeftGroupThread": logMessageType = "log:unsubscribe"; logMessageData = { leftParticipantFbId: m.leftParticipantFbId }; break; case "UserLocation": { logMessageType = "log:user-location"; logMessageData = { Image: m.attachments[0].mercury.extensible_attachment.story_attachment.media.image, Location: m.attachments[0].mercury.extensible_attachment.story_attachment.target.location_title, coordinates: m.attachments[0].mercury.extensible_attachment.story_attachment.target.coordinate, url: m.attachments[0].mercury.extensible_attachment.story_attachment.url }; } case "ApprovalQueue": logMessageType = "log:approval-queue"; logMessageData = { approvalQueue: { action: m.action, recipientFbId: m.recipientFbId, requestSource: m.requestSource, ...m.messageMetadata } }; } return { type: "event", threadID: formatID( (m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString() ), logMessageType, logMessageData, logMessageBody: m.messageMetadata.adminText, author: m.messageMetadata.actorFbId, participantIDs: (m?.participants || []).map((e) => String(e)) }; } function getMentionsFromDeltaMessage(m) { var body = m.body || ""; var mentions = {}; var mdata = []; if (m.data && m.data.prng) { try { mdata = JSON.parse(m.data.prng); } catch (e) { mdata = []; } } if (mdata.length > 0) { for (var i = 0; i < mdata.length; i++) { const row = mdata[i]; var mentionId = row.i; var o = parseInt(String(row.o ?? ""), 10) || 0; var l = parseInt(String(row.l ?? ""), 10) || 0; mentions[String(mentionId)] = body.substring(o, o + l); } return mentions; } var md = m.messageMetadata; if (md && md.data && md.data.data && md.data.data.Gb && md.data.data.Gb.asMap && md.data.data.Gb.asMap.data) { var gbData = md.data.data.Gb.asMap.data; for (var key in gbData) { if (!Object.prototype.hasOwnProperty.call(gbData, key)) continue; var entry = gbData[key]; if (entry && entry.asMap && entry.asMap.data) { var d = entry.asMap.data; var midId = d.id && d.id.asLong ? String(d.id.asLong) : null; var offset = parseInt( String(d.offset && d.offset.asLong ? d.offset.asLong : 0), 10 ); var len = parseInt( String(d.length && d.length.asLong ? d.length.asLong : 0), 10 ); if (midId != null) { mentions[midId] = body.substring(offset, offset + len); } } } } return mentions; } function formatDeltaMessage(m) { var md = m.messageMetadata; var body = m.body || ""; var mentions = getMentionsFromDeltaMessage(m); var args = body === "" ? [] : body.trim().split(/\s+/); return { type: "message", senderID: formatID(md.actorFbId.toString()), threadID: formatID( (md.threadKey.threadFbId || md.threadKey.otherUserFbId).toString() ), messageID: md.messageId, args, body, attachments: (m.attachments || []).map((v) => _formatAttachment2(v, void 0)), mentions, timestamp: md.timestamp, isGroup: !!md.threadKey.threadFbId, participantIDs: (m.participants || []).map((p) => formatID(p.toString())), isUnread: md.isUnread !== void 0 ? md.isUnread : false }; } function formatDeltaReadReceipt(delta) { return { reader: (delta.threadKey.otherUserFbId || delta.actorFbId).toString(), time: delta.actionTimestampMs, threadID: formatID( (delta.threadKey.otherUserFbId || delta.threadKey.threadFbId).toString() ), type: "read_receipt" }; } module2.exports = { getAdminTextMessageType: getAdminTextMessageType2, formatDeltaEvent, formatDeltaMessage, getMentionsFromDeltaMessage, formatDeltaReadReceipt }; } }); // src/utils/format/ids.ts var require_ids = __commonJS({ "src/utils/format/ids.ts"(exports2, module2) { "use strict"; init_utils(); function binaryToDecimal(data) { let ret = ""; while (data !== "0") { let end = 0; let fullName = ""; for (let i = 0; i < data.length; i++) { end = 2 * end + parseInt(data[i], 10); if (end >= 10) { fullName += "1"; end -= 10; } else { fullName += "0"; } } ret = end.toString() + ret; data = fullName.slice(fullName.indexOf("1")); } return ret; } function generateOfflineThreadingID2() { const ret = Date.now(); const value = Math.floor(Math.random() * 4294967295); const str = ("0000000000000000000000" + value.toString(2)).slice(-22); const msgs = ret.toString(2) + str; return binaryToDecimal(msgs); } function generateThreadingID2(clientID) { const k = Date.now(); const l = Math.floor(Math.random() * 4294967295); return `<${k}:${l}-${clientID}@mail.projektitan.com>`; } function getGUID() { let sectionLength = Date.now(); const id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = Math.floor((sectionLength + Math.random() * 16) % 16); sectionLength = Math.floor(sectionLength / 16); const guid = (c === "x" ? r : r & 7 | 8).toString(16); return guid; }); return id; } function generateTimestampRelative2() { const d = /* @__PURE__ */ new Date(); return `${d.getHours()}:${padZeros(d.getMinutes())}`; } module2.exports = { binaryToDecimal, generateOfflineThreadingID: generateOfflineThreadingID2, generateThreadingID: generateThreadingID2, getGUID, generateTimestampRelative: generateTimestampRelative2 }; } }); // src/utils/format/message.ts var require_message = __commonJS({ "src/utils/format/message.ts"(exports2, module2) { "use strict"; var import_attachment = __toESM(require_attachment()); var import_delta = __toESM(require_delta()); init_utils(); var { formatAttachment } = import_attachment.default; var { getAdminTextMessageType: getAdminTextMessageType2 } = import_delta.default; function formatMessage2(m) { var originalMessage = m.message ? m.message : m; var body = originalMessage.body || ""; var args = body == "" ? [] : body.trim().split(/\s+/); const obj = { type: "message", senderName: originalMessage.sender_name, senderID: formatID(originalMessage.sender_fbid.toString()), participantNames: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_names : [originalMessage.sender_name.split(" ")[0]], participantIDs: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_ids.map(function(v) { return formatID(v.toString()); }) : [formatID(originalMessage.sender_fbid)], body, args, threadID: formatID( (originalMessage.thread_fbid || originalMessage.other_user_fbid).toString() ), threadName: originalMessage.group_thread_info ? originalMessage.group_thread_info.name : originalMessage.sender_name, location: originalMessage.coordinates ? originalMessage.coordinates : null, messageID: originalMessage.mid ? originalMessage.mid.toString() : originalMessage.message_id, attachments: formatAttachment( originalMessage.attachments, originalMessage.attachmentIds, originalMessage.attachment_map, originalMessage.share_map ), timestamp: originalMessage.timestamp, timestampAbsolute: originalMessage.timestamp_absolute, timestampRelative: originalMessage.timestamp_relative, timestampDatetime: originalMessage.timestamp_datetime, tags: originalMessage.tags, reactions: originalMessage.reactions ? originalMessage.reactions : [], isUnread: originalMessage.is_unread }; if (m.type === "pages_messaging") obj.pageID = m.realtime_viewer_fbid.toString(); obj.isGroup = obj.participantIDs.length > 2; return obj; } function formatEvent(m) { var originalMessage = m.message ? m.message : m; var logMessageType = originalMessage.log_message_type; var logMessageData; if (logMessageType === "log:generic-admin-text") { logMessageData = originalMessage.log_message_data.untypedData; logMessageType = getAdminTextMessageType2( originalMessage.log_message_data.message_type ); } else logMessageData = originalMessage.log_message_data; return Object.assign(formatMessage2(originalMessage), { type: "event", logMessageType, logMessageData, logMessageBody: originalMessage.log_message_body }); } function formatHistoryMessage(m) { switch (m.action_type) { case "ma-type:log-message": return formatEvent(m); default: return formatMessage2(m); } } module2.exports = { formatMessage: formatMessage2, formatEvent, formatHistoryMessage }; } }); // src/utils/format/presence.ts var require_presence = __commonJS({ "src/utils/format/presence.ts"(exports2, module2) { "use strict"; var PRESENCE_MAP = { _: "%", A: "%2", B: "000", C: "%7d", D: "%7b%22", E: "%2c%22", F: "%22%3a", G: "%2c%22ut%22%3a1", H: "%2c%22bls%22%3a", I: "%2c%22n%22%3a%22%", J: "%22%3a%7b%22i%22%3a0%7d", K: "%2c%22pt%22%3a0%2c%22vis%22%3a", L: "%2c%22ch%22%3a%7b%22h%22%3a%22", M: "%7b%22v%22%3a2%2c%22time%22%3a1", N: ".channel%22%2c%22sub%22%3a%5b", O: "%2c%22sb%22%3a1%2c%22t%22%3a%5b", P: "%2c%22ud%22%3a100%2c%22lc%22%3a0", Q: "%5d%2c%22f%22%3anull%2c%22uct%22%3a", R: ".channel%22%2c%22sub%22%3a%5b1%5d", S: "%22%2c%22m%22%3a0%7d%2c%7b%22i%22%3a", T: "%2c%22blc%22%3a1%2c%22snd%22%3a1%2c%22ct%22%3a", U: "%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a", V: "%2c%22blc%22%3a0%2c%22snd%22%3a0%2c%22ct%22%3a", W: "%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a", X: "%2c%22ri%22%3a0%7d%2c%22state%22%3a%7b%22p%22%3a0%2c%22ut%22%3a1", Y: "%2c%22pt%22%3a0%2c%22vis%22%3a1%2c%22bls%22%3a0%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a", Z: "%2c%22sb%22%3a1%2c%22t%22%3a%5b%5d%2c%22f%22%3anull%2c%22uct%22%3a0%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a" }; var PRESENCE_REVERSE = {}; var PRESENCE_REGEX; (function() { const l = []; for (const m of Object.keys(PRESENCE_MAP)) { const v = PRESENCE_MAP[m]; if (v !== void 0) { PRESENCE_REVERSE[v] = m; l.push(v); } } l.reverse(); PRESENCE_REGEX = new RegExp(l.join("|"), "g"); })(); function presenceEncode(str) { return encodeURIComponent(str).replace(/([_A-Z])|%../g, function(m, n) { return n ? "%" + n.charCodeAt(0).toString(16) : m; }).toLowerCase().replace(PRESENCE_REGEX, function(m) { return PRESENCE_REVERSE[m] ?? m; }); } function presenceDecode(str) { return decodeURIComponent( str.replace(/[_A-Z]/g, function(m) { return PRESENCE_MAP[m] ?? m; }) ); } function generatePresence(userID) { const time = Date.now(); return "E" + presenceEncode( JSON.stringify({ v: 3, time: Math.floor(time / 1e3), user: userID, state: { ut: 0, t2: [], lm2: null, uct2: time, tr: null, tw: Math.floor(Math.random() * 4294967295) + 1, at: time }, ch: { ["p_" + userID]: 0 } }) ); } function generateAccessiblityCookie() { const time = Date.now(); return encodeURIComponent( JSON.stringify({ sr: 0, "sr-ts": time, jk: 0, "jk-ts": time, kb: 0, "kb-ts": time, hcm: 0, "hcm-ts": time }) ); } function formatProxyPresence(presence, userID) { const p = presence; if (p.lat === void 0 || p.p === void 0) return null; return { type: "presence", timestamp: p.lat * 1e3, userID: userID || "", statuses: p.p }; } function formatPresence(presence, userID) { const pr = presence; return { type: "presence", timestamp: (pr.la ?? 0) * 1e3, userID: userID || "", statuses: pr.a }; } module2.exports = { presenceEncode, presenceDecode, generatePresence, generateAccessiblityCookie, formatProxyPresence, formatPresence }; } }); // src/utils/format/readTyp.ts var require_readTyp = __commonJS({ "src/utils/format/readTyp.ts"(exports2, module2) { "use strict"; init_utils(); function formatReadReceipt(event) { return { reader: event.reader.toString(), time: event.time, threadID: formatID((event.thread_fbid || event.reader).toString()), type: "read_receipt" }; } function formatRead(event) { return { threadID: formatID((event.chat_ids && event.chat_ids[0] || event.thread_fbids && event.thread_fbids[0]).toString()), time: event.timestamp, type: "read" }; } function formatTyp(event) { return { isTyping: Boolean(event.st), from: event.from.toString(), threadID: formatID((event.to || event.thread_fbid || event.from).toString()), fromMobile: Object.prototype.hasOwnProperty.call(event, "from_mobile") ? event.from_mobile : true, userID: (event.realtime_viewer_fbid || event.from).toString(), type: "typ" }; } module2.exports = { formatReadReceipt, formatRead, formatTyp }; } }); // src/utils/format/thread.ts var require_thread = __commonJS({ "src/utils/format/thread.ts"(exports2, module2) { "use strict"; init_utils(); function formatThread2(data) { return { threadID: formatID(data.thread_fbid.toString()), participants: data.participants.map(formatID), participantIDs: data.participants.map(formatID), name: data.name, nicknames: data.custom_nickname, snippet: data.snippet, snippetAttachments: data.snippet_attachments, snippetSender: formatID((data.snippet_sender || "").toString()), unreadCount: data.unread_count, messageCount: data.message_count, imageSrc: data.image_src, timestamp: data.timestamp, muteUntil: data.mute_until, isCanonicalUser: data.is_canonical_user, isCanonical: data.is_canonical, isSubscribed: data.is_subscribed, folder: data.folder, isArchived: data.is_archived, recipientsLoadable: data.recipients_loadable, hasEmailParticipant: data.has_email_participant, readOnly: data.read_only, canReply: data.can_reply, cannotReplyReason: data.cannot_reply_reason, lastMessageTimestamp: data.last_message_timestamp, lastReadTimestamp: data.last_read_timestamp, lastMessageType: data.last_message_type, emoji: data.custom_like_icon, color: data.custom_color, adminIDs: data.admin_ids, threadType: data.thread_type }; } module2.exports = { formatThread: formatThread2 }; } }); // src/utils/format/index.ts var require_format = __commonJS({ "src/utils/format/index.ts"(exports2, module2) { "use strict"; var import_attachment = __toESM(require_attachment()); var import_cookie = __toESM(require_cookie()); var import_date = __toESM(require_date()); var import_decode = __toESM(require_decode()); var import_delta = __toESM(require_delta()); var import_ids = __toESM(require_ids()); var import_message = __toESM(require_message()); var import_presence = __toESM(require_presence()); var import_readTyp = __toESM(require_readTyp()); var import_thread2 = __toESM(require_thread()); init_utils(); module2.exports = { getType, formatID, padZeros, arrayToObject, arrToForm, getData_Path, setData_Path, getPaths, cleanHTML, getCurrentTimestamp, getSignatureID, generateOfflineThreadingID: import_ids.default.generateOfflineThreadingID, generateThreadingID: import_ids.default.generateThreadingID, getGUID: import_ids.default.getGUID, generateTimestampRelative: import_ids.default.generateTimestampRelative, formatDate: import_date.default.formatDate, presenceEncode: import_presence.default.presenceEncode, presenceDecode: import_presence.default.presenceDecode, generatePresence: import_presence.default.generatePresence, generateAccessiblityCookie: import_presence.default.generateAccessiblityCookie, formatProxyPresence: import_presence.default.formatProxyPresence, formatPresence: import_presence.default.formatPresence, _formatAttachment: import_attachment.default._formatAttachment, formatAttachment: import_attachment.default.formatAttachment, getAdminTextMessageType: import_delta.default.getAdminTextMessageType, formatDeltaEvent: import_delta.default.formatDeltaEvent, formatDeltaMessage: import_delta.default.formatDeltaMessage, getMentionsFromDeltaMessage: import_delta.default.getMentionsFromDeltaMessage, formatDeltaReadReceipt: import_delta.default.formatDeltaReadReceipt, formatMessage: import_message.default.formatMessage, formatEvent: import_message.default.formatEvent, formatHistoryMessage: import_message.default.formatHistoryMessage, formatReadReceipt: import_readTyp.default.formatReadReceipt, formatRead: import_readTyp.default.formatRead, formatTyp: import_readTyp.default.formatTyp, formatThread: import_thread2.default.formatThread, decodeClientPayload: import_decode.default.decodeClientPayload, formatCookie: import_cookie.default.formatCookie }; } }); // src/core/state.ts function createStateStore(initialState) { const state = Object.assign({}, initialState); Object.defineProperty(state, "__set", { enumerable: false, configurable: false, writable: false, value: function setStateField(key, value) { state[key] = value; return value; } }); Object.defineProperty(state, "__merge", { enumerable: false, configurable: false, writable: false, value: function mergeState(partial) { if (partial && typeof partial === "object") { Object.assign(state, partial); } return state; } }); Object.defineProperty(state, "__snapshot", { enumerable: false, configurable: false, writable: