Path: blob/master/node_modules/@adiwajshing/baileys/lib/Utils/generics.js
1129 views
"use strict";1var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {2if (k2 === undefined) k2 = k;3var desc = Object.getOwnPropertyDescriptor(m, k);4if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {5desc = { enumerable: true, get: function() { return m[k]; } };6}7Object.defineProperty(o, k2, desc);8}) : (function(o, m, k, k2) {9if (k2 === undefined) k2 = k;10o[k2] = m[k];11}));12var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {13Object.defineProperty(o, "default", { enumerable: true, value: v });14}) : function(o, v) {15o["default"] = v;16});17var __importStar = (this && this.__importStar) || function (mod) {18if (mod && mod.__esModule) return mod;19var result = {};20if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);21__setModuleDefault(result, mod);22return result;23};24var __importDefault = (this && this.__importDefault) || function (mod) {25return (mod && mod.__esModule) ? mod : { "default": mod };26};27Object.defineProperty(exports, "__esModule", { value: true });28exports.isWABusinessPlatform = exports.getCodeFromWSError = exports.getCallStatusFromNode = exports.getErrorCodeFromStreamError = exports.getStatusFromReceiptType = exports.generateMdTagPrefix = exports.fetchLatestWaWebVersion = exports.fetchLatestBaileysVersion = exports.printQRIfNecessaryListener = exports.bindWaitForConnectionUpdate = exports.bindWaitForEvent = exports.generateMessageID = exports.promiseTimeout = exports.delayCancellable = exports.delay = exports.debouncedTimeout = exports.unixTimestampSeconds = exports.toNumber = exports.encodeBigEndian = exports.generateRegistrationId = exports.encodeWAMessage = exports.unpadRandomMax16 = exports.writeRandomPadMax16 = exports.BufferJSON = exports.Browsers = void 0;29const boom_1 = require("@hapi/boom");30const axios_1 = __importDefault(require("axios"));31const crypto_1 = require("crypto");32const os_1 = require("os");33const WAProto_1 = require("../../WAProto");34const baileys_version_json_1 = require("../Defaults/baileys-version.json");35const Types_1 = require("../Types");36const WABinary_1 = require("../WABinary");37const PLATFORM_MAP = {38'aix': 'AIX',39'darwin': 'Mac OS',40'win32': 'Windows',41'android': 'Android'42};43exports.Browsers = {44ubuntu: browser => ['Ubuntu', browser, '20.0.04'],45macOS: browser => ['Mac OS', browser, '10.15.7'],46baileys: browser => ['Baileys', browser, '4.0.0'],47/** The appropriate browser based on your OS & release */48appropriate: browser => [PLATFORM_MAP[(0, os_1.platform)()] || 'Ubuntu', browser, (0, os_1.release)()]49};50exports.BufferJSON = {51replacer: (k, value) => {52if (Buffer.isBuffer(value) || value instanceof Uint8Array || (value === null || value === void 0 ? void 0 : value.type) === 'Buffer') {53return { type: 'Buffer', data: Buffer.from((value === null || value === void 0 ? void 0 : value.data) || value).toString('base64') };54}55return value;56},57reviver: (_, value) => {58if (typeof value === 'object' && !!value && (value.buffer === true || value.type === 'Buffer')) {59const val = value.data || value.value;60return typeof val === 'string' ? Buffer.from(val, 'base64') : Buffer.from(val || []);61}62return value;63}64};65const writeRandomPadMax16 = (msg) => {66const pad = (0, crypto_1.randomBytes)(1);67pad[0] &= 0xf;68if (!pad[0]) {69pad[0] = 0xf;70}71return Buffer.concat([msg, Buffer.alloc(pad[0], pad[0])]);72};73exports.writeRandomPadMax16 = writeRandomPadMax16;74const unpadRandomMax16 = (e) => {75const t = new Uint8Array(e);76if (0 === t.length) {77throw new Error('unpadPkcs7 given empty bytes');78}79var r = t[t.length - 1];80if (r > t.length) {81throw new Error(`unpad given ${t.length} bytes, but pad is ${r}`);82}83return new Uint8Array(t.buffer, t.byteOffset, t.length - r);84};85exports.unpadRandomMax16 = unpadRandomMax16;86const encodeWAMessage = (message) => ((0, exports.writeRandomPadMax16)(WAProto_1.proto.Message.encode(message).finish()));87exports.encodeWAMessage = encodeWAMessage;88const generateRegistrationId = () => {89return Uint16Array.from((0, crypto_1.randomBytes)(2))[0] & 16383;90};91exports.generateRegistrationId = generateRegistrationId;92const encodeBigEndian = (e, t = 4) => {93let r = e;94const a = new Uint8Array(t);95for (let i = t - 1; i >= 0; i--) {96a[i] = 255 & r;97r >>>= 8;98}99return a;100};101exports.encodeBigEndian = encodeBigEndian;102const toNumber = (t) => ((typeof t === 'object' && t) ? ('toNumber' in t ? t.toNumber() : t.low) : t);103exports.toNumber = toNumber;104/** unix timestamp of a date in seconds */105const unixTimestampSeconds = (date = new Date()) => Math.floor(date.getTime() / 1000);106exports.unixTimestampSeconds = unixTimestampSeconds;107const debouncedTimeout = (intervalMs = 1000, task) => {108let timeout;109return {110start: (newIntervalMs, newTask) => {111task = newTask || task;112intervalMs = newIntervalMs || intervalMs;113timeout && clearTimeout(timeout);114timeout = setTimeout(() => task === null || task === void 0 ? void 0 : task(), intervalMs);115},116cancel: () => {117timeout && clearTimeout(timeout);118timeout = undefined;119},120setTask: (newTask) => task = newTask,121setInterval: (newInterval) => intervalMs = newInterval122};123};124exports.debouncedTimeout = debouncedTimeout;125const delay = (ms) => (0, exports.delayCancellable)(ms).delay;126exports.delay = delay;127const delayCancellable = (ms) => {128const stack = new Error().stack;129let timeout;130let reject;131const delay = new Promise((resolve, _reject) => {132timeout = setTimeout(resolve, ms);133reject = _reject;134});135const cancel = () => {136clearTimeout(timeout);137reject(new boom_1.Boom('Cancelled', {138statusCode: 500,139data: {140stack141}142}));143};144return { delay, cancel };145};146exports.delayCancellable = delayCancellable;147async function promiseTimeout(ms, promise) {148if (!ms) {149return new Promise(promise);150}151const stack = new Error().stack;152// Create a promise that rejects in <ms> milliseconds153const { delay, cancel } = (0, exports.delayCancellable)(ms);154const p = new Promise((resolve, reject) => {155delay156.then(() => reject(new boom_1.Boom('Timed Out', {157statusCode: Types_1.DisconnectReason.timedOut,158data: {159stack160}161})))162.catch(err => reject(err));163promise(resolve, reject);164})165.finally(cancel);166return p;167}168exports.promiseTimeout = promiseTimeout;169// generate a random ID to attach to a message170const generateMessageID = () => 'BAE5' + (0, crypto_1.randomBytes)(6).toString('hex').toUpperCase();171exports.generateMessageID = generateMessageID;172function bindWaitForEvent(ev, event) {173return async (check, timeoutMs) => {174let listener;175let closeListener;176await (promiseTimeout(timeoutMs, (resolve, reject) => {177closeListener = ({ connection, lastDisconnect }) => {178if (connection === 'close') {179reject((lastDisconnect === null || lastDisconnect === void 0 ? void 0 : lastDisconnect.error)180|| new boom_1.Boom('Connection Closed', { statusCode: Types_1.DisconnectReason.connectionClosed }));181}182};183ev.on('connection.update', closeListener);184listener = (update) => {185if (check(update)) {186resolve();187}188};189ev.on(event, listener);190})191.finally(() => {192ev.off(event, listener);193ev.off('connection.update', closeListener);194}));195};196}197exports.bindWaitForEvent = bindWaitForEvent;198const bindWaitForConnectionUpdate = (ev) => bindWaitForEvent(ev, 'connection.update');199exports.bindWaitForConnectionUpdate = bindWaitForConnectionUpdate;200const printQRIfNecessaryListener = (ev, logger) => {201ev.on('connection.update', async ({ qr }) => {202if (qr) {203const QR = await Promise.resolve().then(() => __importStar(require('qrcode-terminal'))).catch(() => {204logger.error('QR code terminal not added as dependency');205});206QR === null || QR === void 0 ? void 0 : QR.generate(qr, { small: true });207}208});209};210exports.printQRIfNecessaryListener = printQRIfNecessaryListener;211/**212* utility that fetches latest baileys version from the master branch.213* Use to ensure your WA connection is always on the latest version214*/215const fetchLatestBaileysVersion = async () => {216const URL = 'https://raw.githubusercontent.com/adiwajshing/Baileys/master/src/Defaults/baileys-version.json';217try {218const result = await axios_1.default.get(URL, { responseType: 'json' });219return {220version: result.data.version,221isLatest: true222};223}224catch (error) {225return {226version: baileys_version_json_1.version,227isLatest: false,228error229};230}231};232exports.fetchLatestBaileysVersion = fetchLatestBaileysVersion;233/**234* A utility that fetches the latest web version of whatsapp.235* Use to ensure your WA connection is always on the latest version236*/237const fetchLatestWaWebVersion = async () => {238try {239const result = await axios_1.default.get('https://web.whatsapp.com/check-update?version=1&platform=web', { responseType: 'json' });240const version = result.data.currentVersion.split('.');241return {242version: [+version[0], +version[1], +version[2]],243isLatest: true244};245}246catch (error) {247return {248version: baileys_version_json_1.version,249isLatest: false,250error251};252}253};254exports.fetchLatestWaWebVersion = fetchLatestWaWebVersion;255/** unique message tag prefix for MD clients */256const generateMdTagPrefix = () => {257const bytes = (0, crypto_1.randomBytes)(4);258return `${bytes.readUInt16BE()}.${bytes.readUInt16BE(2)}-`;259};260exports.generateMdTagPrefix = generateMdTagPrefix;261const STATUS_MAP = {262'played': WAProto_1.proto.WebMessageInfo.Status.PLAYED,263'read': WAProto_1.proto.WebMessageInfo.Status.READ,264'read-self': WAProto_1.proto.WebMessageInfo.Status.READ265};266/**267* Given a type of receipt, returns what the new status of the message should be268* @param type type from receipt269*/270const getStatusFromReceiptType = (type) => {271const status = STATUS_MAP[type];272if (typeof type === 'undefined') {273return WAProto_1.proto.WebMessageInfo.Status.DELIVERY_ACK;274}275return status;276};277exports.getStatusFromReceiptType = getStatusFromReceiptType;278const CODE_MAP = {279conflict: Types_1.DisconnectReason.connectionReplaced280};281/**282* Stream errors generally provide a reason, map that to a baileys DisconnectReason283* @param reason the string reason given, eg. "conflict"284*/285const getErrorCodeFromStreamError = (node) => {286const [reasonNode] = (0, WABinary_1.getAllBinaryNodeChildren)(node);287let reason = (reasonNode === null || reasonNode === void 0 ? void 0 : reasonNode.tag) || 'unknown';288const statusCode = +(node.attrs.code || CODE_MAP[reason] || Types_1.DisconnectReason.badSession);289if (statusCode === Types_1.DisconnectReason.restartRequired) {290reason = 'restart required';291}292return {293reason,294statusCode295};296};297exports.getErrorCodeFromStreamError = getErrorCodeFromStreamError;298const getCallStatusFromNode = ({ tag, attrs }) => {299let status;300switch (tag) {301case 'offer':302case 'offer_notice':303status = 'offer';304break;305case 'terminate':306if (attrs.reason === 'timeout') {307status = 'timeout';308}309else {310status = 'reject';311}312break;313case 'reject':314status = 'reject';315break;316case 'accept':317status = 'accept';318break;319default:320status = 'ringing';321break;322}323return status;324};325exports.getCallStatusFromNode = getCallStatusFromNode;326const UNEXPECTED_SERVER_CODE_TEXT = 'Unexpected server response: ';327const getCodeFromWSError = (error) => {328var _a;329let statusCode = 500;330if (error.message.includes(UNEXPECTED_SERVER_CODE_TEXT)) {331const code = +error.message.slice(UNEXPECTED_SERVER_CODE_TEXT.length);332if (!Number.isNaN(code) && code >= 400) {333statusCode = code;334}335}336else if ((_a = error.code) === null || _a === void 0 ? void 0 : _a.startsWith('E')) { // handle ETIMEOUT, ENOTFOUND etc337statusCode = 408;338}339return statusCode;340};341exports.getCodeFromWSError = getCodeFromWSError;342/**343* Is the given platform WA business344* @param platform AuthenticationCreds.platform345*/346const isWABusinessPlatform = (platform) => {347return platform === 'smbi' || platform === 'smba';348};349exports.isWABusinessPlatform = isWABusinessPlatform;350351352