From ef673f62ca29c4bf3f2b8a60ba16a0bd13d86862 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Thu, 20 Apr 2023 13:01:11 +0200 Subject: [PATCH 01/24] feat: native-mobile-api --- Example/example.ts | 79 +++++++++- package.json | 4 + src/Defaults/index.ts | 14 ++ src/Defaults/phonenumber-mcc.json | 223 ++++++++++++++++++++++++++ src/Socket/index.ts | 2 +- src/Socket/mobile-socket.ts | 47 ++++++ src/Socket/registration.ts | 251 ++++++++++++++++++++++++++++++ src/Socket/socket.ts | 86 +++++----- src/Socket/web-socket.ts | 31 ++++ src/Types/Auth.ts | 8 + src/Types/Socket.ts | 2 + src/Utils/auth-utils.ts | 10 +- src/Utils/crypto.ts | 4 + src/Utils/noise-handler.ts | 35 +++-- src/Utils/validate-connection.ts | 60 +++++-- src/WABinary/generic-utils.ts | 31 ++++ yarn.lock | 127 +++++++++++++++ 17 files changed, 940 insertions(+), 74 deletions(-) create mode 100644 src/Defaults/phonenumber-mcc.json create mode 100644 src/Socket/mobile-socket.ts create mode 100644 src/Socket/registration.ts create mode 100644 src/Socket/web-socket.ts diff --git a/Example/example.ts b/Example/example.ts index eb6fd15..12c2340 100644 --- a/Example/example.ts +++ b/Example/example.ts @@ -1,13 +1,20 @@ import { Boom } from '@hapi/boom' +import parsePhoneNumber from 'libphonenumber-js' import NodeCache from 'node-cache' -import makeWASocket, { AnyMessageContent, delay, DisconnectReason, fetchLatestBaileysVersion, getAggregateVotesInPollMessage, makeCacheableSignalKeyStore, makeInMemoryStore, proto, useMultiFileAuthState, WAMessageContent, WAMessageKey } from '../src' -import MAIN_LOGGER from '../src/Utils/logger' +import P from 'pino' +import readline from 'readline' +import makeWASocket, { AnyMessageContent, delay, DisconnectReason, fetchLatestBaileysVersion, getAggregateVotesInPollMessage, makeCacheableSignalKeyStore, makeInMemoryStore, PHONENUMBER_MCC, proto, useMultiFileAuthState, WAMessageContent, WAMessageKey } from '../src' -const logger = MAIN_LOGGER.child({ }) -logger.level = 'trace' +const logger = P({ + transport: { + target: 'pino-pretty' + }, + level: 'trace' +}) const useStore = !process.argv.includes('--no-store') const doReplies = !process.argv.includes('--no-reply') +const useMobile = process.argv.includes('--mobile') // external map to store retry counts of messages when decryption/encryption fails // keep this out of the socket itself, so as to prevent a message decryption/encryption loop across socket restarts @@ -33,6 +40,7 @@ const startSock = async() => { version, logger, printQRInTerminal: true, + mobile: useMobile, auth: { creds: state.creds, /** caching makes the store faster to send/recv messages */ @@ -49,6 +57,69 @@ const startSock = async() => { store?.bind(sock.ev) + // If mobile was chosen, ask for the code + if(useMobile && !sock.authState.creds.registered) { + const question = (text: string) => new Promise((resolve) => rl.question(text, resolve)) + + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) + const { registration } = sock.authState.creds || { registration: {} } + + if(!registration.phoneNumber) { + registration.phoneNumber = await question('Please enter your mobile phone number:\n') + } else { + console.log('Your mobile phone number is not registered.') + } + + const phoneNumber = parsePhoneNumber(registration!.phoneNumber) + if(!phoneNumber?.isValid()) { + throw new Error('Invalid phone number: ' + registration!.phoneNumber) + } + + registration.phoneNumber = phoneNumber.format('E.164') + registration.phoneNumberCountryCode = phoneNumber.countryCallingCode + registration.phoneNumberNationalNumber = phoneNumber.nationalNumber + const mcc = PHONENUMBER_MCC[phoneNumber.countryCallingCode] + if(!mcc) { + throw new Error('Could not find MCC for phone number: ' + registration!.phoneNumber + '\nPlease specify the MCC manually.') + } + + registration.phoneNumberMobileCountryCode = mcc + + async function enterCode() { + try { + const code = await question('Please enter the one time code:\n') + const response = await sock.register(code.replace(/["']/g, '').trim().toLowerCase()) + console.log('Successfully registered your phone number.') + console.log(response) + rl.close() + } catch(error) { + console.error('Failed to register your phone number. Please try again.\n', error) + await askForOTP() + } + } + + async function askForOTP() { + let code = await question('How would you like to receive the one time code for registration? "sms" or "voice"\n') + code = code.replace(/["']/g, '').trim().toLowerCase() + + if(code !== 'sms' && code !== 'voice') { + return await askForOTP() + } + + registration.method = code + + try { + await sock.requestRegistrationCode(registration) + await enterCode() + } catch(error) { + console.error('Failed to request registration code. Please try again.\n', error) + await askForOTP() + } + } + + askForOTP() + } + const sendMessageWTyping = async(msg: AnyMessageContent, jid: string) => { await sock.presenceSubscribe(jid) await delay(500) diff --git a/package.json b/package.json index 88ade39..681da97 100644 --- a/package.json +++ b/package.json @@ -36,11 +36,13 @@ "@hapi/boom": "^9.1.3", "axios": "^1.3.3", "futoin-hkdf": "^1.5.1", + "libphonenumber-js": "^1.10.20", "libsignal": "git+https://github.com/adiwajshing/libsignal-node", "music-metadata": "^7.12.3", "node-cache": "^5.1.2", "pino": "^7.0.0", "protobufjs": "^6.11.3", + "uuid": "^9.0.0", "ws": "^8.0.0" }, "peerDependencies": { @@ -79,11 +81,13 @@ "@types/jest": "^27.5.1", "@types/node": "^16.0.0", "@types/sharp": "^0.29.4", + "@types/uuid": "^9.0.0", "@types/ws": "^8.0.0", "eslint": "^8.0.0", "jest": "^27.0.6", "jimp": "^0.16.1", "link-preview-js": "^3.0.0", + "pino-pretty": "^9.4.0", "qrcode-terminal": "^0.12.0", "sharp": "^0.30.5", "ts-jest": "^27.0.3", diff --git a/src/Defaults/index.ts b/src/Defaults/index.ts index 6491a8c..9a150ed 100644 --- a/src/Defaults/index.ts +++ b/src/Defaults/index.ts @@ -4,22 +4,36 @@ import type { AuthenticationState, MediaType, SocketConfig, WAVersion } from '.. import { Browsers } from '../Utils' import logger from '../Utils/logger' import { version } from './baileys-version.json' +import phoneNumberMCC from './phonenumber-mcc.json' export const UNAUTHORIZED_CODES = [401, 403, 419] +export const PHONENUMBER_MCC = phoneNumberMCC + export const DEFAULT_ORIGIN = 'https://web.whatsapp.com' +export const MOBILE_ENDPOINT = 'g.whatsapp.net' +export const MOBILE_PORT = 443 export const DEF_CALLBACK_PREFIX = 'CB:' export const DEF_TAG_PREFIX = 'TAG:' export const PHONE_CONNECTION_CB = 'CB:Pong' export const WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60 +export const MOBILE_TOKEN = Buffer.from('0a1mLfGUIBVrMKF1RdvLI5lkRBvof6vn0fD2QRSM4174c0243f5277a5d7720ce842cc4ae6') +export const MOBILE_REGISTRATION_ENDPOINT = 'https://v.whatsapp.net/v2' +export const MOBILE_USERAGENT = 'WhatsApp/2.22.24.81 iOS/15.3.1 Device/Apple-iPhone_7' +export const REGISTRATION_PUBLIC_KEY = Buffer.from([ + 5, 142, 140, 15, 116, 195, 235, 197, 215, 166, 134, 92, 108, 60, 132, 56, 86, 176, 97, 33, 204, 232, 234, 119, 77, + 34, 251, 111, 18, 37, 18, 48, 45, +]) export const NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0' export const DICT_VERSION = 2 export const KEY_BUNDLE_TYPE = Buffer.from([5]) export const NOISE_WA_HEADER = Buffer.from( [ 87, 65, 6, DICT_VERSION ] ) // last is "DICT_VERSION" +export const PROTOCOL_VERSION = [5, 2] +export const MOBILE_NOISE_HEADER = Buffer.concat([Buffer.from('WA'), Buffer.from(PROTOCOL_VERSION)]) /** from: https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url */ export const URL_REGEX = /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/ export const URL_EXCLUDE_REGEX = /.*@.*/ diff --git a/src/Defaults/phonenumber-mcc.json b/src/Defaults/phonenumber-mcc.json new file mode 100644 index 0000000..2fd7c9f --- /dev/null +++ b/src/Defaults/phonenumber-mcc.json @@ -0,0 +1,223 @@ +{ + "93": 412, + "355": 276, + "213": 603, + "1-684": 544, + "376": 213, + "244": 631, + "1-264": 365, + "1-268": 344, + "54": 722, + "374": 283, + "297": 363, + "61": 505, + "43": 232, + "994": 400, + "1-242": 364, + "973": 426, + "880": 470, + "1-246": 342, + "375": 257, + "32": 206, + "501": 702, + "229": 616, + "1-441": 350, + "975": 402, + "591": 736, + "387": 218, + "267": 652, + "55": 724, + "1-284": 348, + "673": 528, + "359": 284, + "226": 613, + "257": 642, + "855": 456, + "237": 624, + "238": 625, + "1-345": 346, + "236": 623, + "235": 622, + "56": 730, + "86": 454, + "57": 732, + "269": 654, + "682": 548, + "506": 712, + "385": 219, + "53": 368, + "357": 280, + "420": 230, + "243": 630, + "45": 238, + "253": 638, + "1-767": 366, + "1-809": 370, + "1-849": 370, + "1-829": 370, + "593": 740, + "20": 602, + "503": 706, + "240": 627, + "291": 657, + "372": 248, + "251": 636, + "500": 750, + "298": 288, + "679": 542, + "358": 244, + "33": 208, + "689": 547, + "241": 628, + "220": 607, + "995": 282, + "49": 262, + "233": 620, + "350": 266, + "30": 202, + "299": 290, + "1-473": 352, + "1-671": 535, + "502": 704, + "224": 537, + "592": 738, + "509": 372, + "504": 708, + "852": 454, + "36": 216, + "354": 274, + "91": 404, + "62": 510, + "98": 432, + "964": 418, + "353": 234, + "972": 425, + "39": 222, + "225": 612, + "1-876": 338, + "81": 440, + "962": 416, + "254": 639, + "686": 545, + "383": 221, + "965": 419, + "371": 247, + "961": 415, + "266": 651, + "231": 618, + "218": 606, + "423": 295, + "370": 246, + "352": 270, + "389": 294, + "261": 646, + "265": 650, + "60": 502, + "960": 472, + "223": 610, + "356": 278, + "692": 551, + "222": 609, + "230": 617, + "52": 334, + "691": 550, + "373": 259, + "377": 212, + "976": 428, + "382": 297, + "1-664": 354, + "212": 604, + "258": 643, + "95": 414, + "264": 649, + "674": 536, + "977": 429, + "31": 204, + "687": 546, + "64": 530, + "505": 710, + "227": 614, + "234": 621, + "683": 555, + "1-670": 534, + "47": 242, + "968": 226, + "92": 410, + "680": 552, + "970": 423, + "507": 714, + "675": 537, + "595": 744, + "51": 716, + "63": 515, + "48": 260, + "351": 268, + "1-787, 1-939": 330, + "974": 427, + "242": 630, + "40": 226, + "7": 250, + "250": 635, + "290": 658, + "1-869": 356, + "1-758": 358, + "508": 308, + "1-784": 360, + "685": 544, + "378": 292, + "239": 626, + "966": 420, + "221": 608, + "381": 220, + "248": 633, + "232": 619, + "65": 525, + "386": 293, + "677": 540, + "27": 655, + "211": 659, + "34": 214, + "94": 413, + "249": 634, + "597": 746, + "268": 653, + "46": 240, + "41": 228, + "963": 417, + "886": 466, + "992": 436, + "255": 640, + "66": 520, + "228": 615, + "690": 554, + "676": 539, + "1-868": 374, + "216": 605, + "90": 286, + "993": 438, + "1-649": 376, + "688": 553, + "1-340": 332, + "256": 641, + "380": 255, + "971": 424, + "44": 234, + "1": 310, + "598": 748, + "998": 434, + "678": 541, + "379": 225, + "58": 734, + "681": 543, + "967": 421, + "260": 645, + "263": 648, + "670": 514, + "245": 632, + "856": 457, + "599": 362, + "850": 467, + "262": 647, + "82": 450, + "84": 452 +} diff --git a/src/Socket/index.ts b/src/Socket/index.ts index 7efebf0..7338c9c 100644 --- a/src/Socket/index.ts +++ b/src/Socket/index.ts @@ -1,6 +1,6 @@ import { DEFAULT_CONNECTION_CONFIG } from '../Defaults' import { UserFacingSocketConfig } from '../Types' -import { makeBusinessSocket as _makeSocket } from './business' +import { makeRegistrationSocket as _makeSocket } from './registration' // export the last socket layer const makeWASocket = (config: UserFacingSocketConfig) => ( diff --git a/src/Socket/mobile-socket.ts b/src/Socket/mobile-socket.ts new file mode 100644 index 0000000..edcdd5d --- /dev/null +++ b/src/Socket/mobile-socket.ts @@ -0,0 +1,47 @@ +import { Socket } from 'net' +import { MOBILE_ENDPOINT, MOBILE_PORT } from '../Defaults' +import { SocketConfig } from '../Types' + +export class MobileSocket extends Socket { + constructor(public config: SocketConfig) { + super() + + if(config.auth.creds.registered) { + this.connect() + } + + this.on('data', (d) => { + this.emit('message', d) + }) + } + + override connect() { + return super.connect(MOBILE_PORT, MOBILE_ENDPOINT, () => { + this.emit('open') + }) + } + + get isOpen(): boolean { + return this.readyState === 'open' + } + + get isClosed(): boolean { + return this.readyState === 'closed' + } + + get isClosing(): boolean { + return this.isClosed + } + + get isConnecting(): boolean { + return this.readyState === 'opening' + } + + close(): void { + this.end() + } + + send(data: unknown, cb?: ((err?: Error | undefined) => void) | undefined) { + return super.write(data as Uint8Array | string, cb as ((err?: Error | undefined) => void)) + } +} \ No newline at end of file diff --git a/src/Socket/registration.ts b/src/Socket/registration.ts new file mode 100644 index 0000000..3f3672e --- /dev/null +++ b/src/Socket/registration.ts @@ -0,0 +1,251 @@ +/* eslint-disable camelcase */ +import { MOBILE_REGISTRATION_ENDPOINT, MOBILE_TOKEN, MOBILE_USERAGENT, REGISTRATION_PUBLIC_KEY } from '../Defaults' +import { KeyPair, SignedKeyPair, SocketConfig } from '../Types' +import { aesEncryptGCM, Curve, md5 } from '../Utils/crypto' +import { jidEncode } from '../WABinary' +import { makeBusinessSocket } from './business' +import { MobileSocket } from './mobile-socket' + +function urlencode(str: string) { + return str.replace(/-/g, '%2d').replace(/_/g, '%5f').replace(/~/g, '%7e') +} + +const validRegistrationOptions = (config: RegistrationOptions) => config?.phoneNumberCountryCode && + config.phoneNumberNationalNumber && + config.phoneNumberMobileCountryCode + +export const makeRegistrationSocket = (config: SocketConfig) => { + const sock = makeBusinessSocket(config) + + const register = async(code: string) => { + if(!validRegistrationOptions(config.auth.creds.registration)) { + throw new Error('please specify the registration options') + } + + const result = await mobileRegister({ ...sock.authState.creds, ...sock.authState.creds.registration as RegistrationOptions, code }) + + sock.authState.creds.me = { + id: jidEncode(result.login!, 's.whatsapp.net'), + name: '~' + } + + sock.authState.creds.registered = true + sock.ev.emit('creds.update', sock.authState.creds) + + if(sock.ws instanceof MobileSocket) { + sock.ws.connect() + } + + return result + } + + const requestRegistrationCode = async(registrationOptions?: RegistrationOptions) => { + registrationOptions = registrationOptions || config.auth.creds.registration + if(!validRegistrationOptions(registrationOptions)) { + throw new Error('Invalid registration options') + } + + sock.authState.creds.registration = registrationOptions + + sock.ev.emit('creds.update', sock.authState.creds) + + return mobileRegisterCode({ ...config.auth.creds, ...registrationOptions }) + } + + return { + ...sock, + register, + requestRegistrationCode, + } +} + +// Backup_token: Base64.getEncoder().encodeToString(Arrays.copyOfRange(Base64.getDecoder().decode(UUID.randomUUID().toString().replace('-','')),0,15)) + +export interface RegistrationData { + registrationId: number + signedPreKey: SignedKeyPair + noiseKey: KeyPair + signedIdentityKey: KeyPair + identityId: Buffer + phoneId: string + deviceId: string + backupToken: Buffer +} + +export interface RegistrationOptions { + /** your phone number */ + phoneNumber?: string + /** the country code of your phone number */ + phoneNumberCountryCode: string + /** your phone number without country code */ + phoneNumberNationalNumber: string + /** the country code of your mobile network + * @see {@link https://de.wikipedia.org/wiki/Mobile_Country_Code} + */ + phoneNumberMobileCountryCode: string + /** the network code of your mobile network + * @see {@link https://de.wikipedia.org/wiki/Mobile_Network_Code} + */ + phoneNumberMobileNetworkCode: string + /** + * How to send the one time code + */ + method?: 'sms' | 'voice' +} + +export type RegistrationParams = RegistrationData & RegistrationOptions + +function convertBufferToUrlHex(buffer: Buffer) { + var id = '' + + buffer.forEach((x) => { + // encode random identity_id buffer as percentage url encoding + id += `%${x.toString(16).padStart(2, '0').toLowerCase()}` + }) + + return id +} + +export function registrationParams(params: RegistrationParams) { + const e_regid = Buffer.alloc(4) + e_regid.writeInt32BE(params.registrationId) + + const e_skey_id = Buffer.alloc(3) + e_skey_id.writeInt16BE(params.signedPreKey.keyId) + + params.phoneNumberCountryCode = params.phoneNumberCountryCode.replace('+', '').trim() + params.phoneNumberNationalNumber = params.phoneNumberNationalNumber.replace(/[/-\s)(]/g, '').trim() + + return { + cc: params.phoneNumberCountryCode, + in: params.phoneNumberNationalNumber, + Rc: '0', + lg: 'en', + lc: 'GB', + mistyped: '6', + authkey: Buffer.from(params.noiseKey.public).toString('base64url'), + e_regid: e_regid.toString('base64url'), + e_keytype: 'BQ', + e_ident: Buffer.from(params.signedIdentityKey.public).toString('base64url'), + // e_skey_id: e_skey_id.toString('base64url'), + e_skey_id: 'AAAA', + e_skey_val: Buffer.from(params.signedPreKey.keyPair.public).toString('base64url'), + e_skey_sig: Buffer.from(params.signedPreKey.signature).toString('base64url'), + fdid: params.phoneId, + network_ratio_type: '1', + expid: params.deviceId, + simnum: '1', + hasinrc: '1', + pid: Math.floor(Math.random() * 1000).toString(), + id: convertBufferToUrlHex(params.identityId), + backup_token: convertBufferToUrlHex(params.backupToken), + token: md5(Buffer.concat([MOBILE_TOKEN, Buffer.from(params.phoneNumberNationalNumber)])).toString('hex'), + } +} + +/** + * Requests a registration code for the given phone number. + */ +export function mobileRegisterCode(params: RegistrationParams) { + return mobileRegisterFetch('/code', { + params: { + ...registrationParams(params), + mcc: `${params.phoneNumberMobileCountryCode}`.padStart(3, '0'), + mnc: `${params.phoneNumberMobileNetworkCode || '001'}`.padStart(3, '0'), + sim_mcc: '000', + sim_mnc: '000', + method: params?.method || 'sms', + reason: '', + hasav: '1' + }, + }) +} + +export function mobileRegisterExists(params: RegistrationParams) { + return mobileRegisterFetch('/exist', { + params: registrationParams(params) + }) +} + +/** + * Registers the phone number on whatsapp with the received OTP code. + */ +export async function mobileRegister(params: RegistrationParams & { code: string }) { + //const result = await mobileRegisterFetch(`/reg_onboard_abprop?cc=${params.phoneNumberCountryCode}&in=${params.phoneNumberNationalNumber}&rc=0`) + + return mobileRegisterFetch('/register', { + params: { ...registrationParams(params), code: params.code.replace('-', '') }, + }) +} + +/** + * Encrypts the given string as AEAD aes-256-gcm with the public whatsapp key and a random keypair. + */ +export function mobileRegisterEncrypt(data: string) { + const keypair = Curve.generateKeyPair() + const key = Curve.sharedKey(keypair.private, REGISTRATION_PUBLIC_KEY) + + const buffer = aesEncryptGCM(Buffer.from(data), new Uint8Array(key), Buffer.alloc(12), Buffer.alloc(0)) + + return Buffer.concat([Buffer.from(keypair.public), buffer]).toString('base64url') +} + +export async function mobileRegisterFetch(path: string, opts: { params?: Record, headers?: Record } = {}) { + let url = `${MOBILE_REGISTRATION_ENDPOINT}${path}` + + if(opts.params) { + const parameter = [] as string[] + + for(const param in opts.params) { + parameter.push(param + '=' + urlencode(opts.params[param])) + } + + console.log('parameter', opts.params, parameter) + + // const params = urlencode(mobileRegisterEncrypt(parameter.join('&'))) + // url += `?ENC=${params}` + url += `?${parameter.join('&')}` + } + + if(!opts.headers) { + opts.headers = {} + } + + opts.headers['User-Agent'] = MOBILE_USERAGENT + + const response = await fetch(url, opts) + + const text = await response.text() + + try { + var json = JSON.parse(text) + } catch(error) { + throw text + } + + if(!response.ok || json.reason) { + throw json + } + + if(json.status && !['ok', 'sent'].includes(json.status)) { + throw json + } + + return json as ExistsResponse +} + + +export interface ExistsResponse { + status: 'fail' + voice_length?: number + voice_wait?: number + sms_length?: number + sms_wait?: number + reason?: 'incorrect' | 'missing_param' + login?: string + flash_type?: number + ab_hash?: string + ab_key?: string + exp_cfg?: string + lid?: string +} diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index b91a3a3..eb9d772 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -1,12 +1,14 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { Boom } from '@hapi/boom' import { promisify } from 'util' -import WebSocket from 'ws' import { proto } from '../../WAProto' -import { DEF_CALLBACK_PREFIX, DEF_TAG_PREFIX, DEFAULT_ORIGIN, INITIAL_PREKEY_COUNT, MIN_PREKEY_COUNT } from '../Defaults' +import { DEF_CALLBACK_PREFIX, DEF_TAG_PREFIX, INITIAL_PREKEY_COUNT, MIN_PREKEY_COUNT, MOBILE_NOISE_HEADER, NOISE_WA_HEADER } from '../Defaults' import { DisconnectReason, SocketConfig } from '../Types' -import { addTransactionCapability, bindWaitForConnectionUpdate, configureSuccessfulPairing, Curve, generateLoginNode, generateMdTagPrefix, generateRegistrationNode, getCodeFromWSError, getErrorCodeFromStreamError, getNextPreKeysNode, makeNoiseHandler, printQRIfNecessaryListener, promiseTimeout } from '../Utils' +import { addTransactionCapability, bindWaitForConnectionUpdate, configureSuccessfulPairing, Curve, generateLoginNode, generateMdTagPrefix, generateMobileNode, generateRegistrationNode, getCodeFromWSError, getErrorCodeFromStreamError, getNextPreKeysNode, makeNoiseHandler, printQRIfNecessaryListener, promiseTimeout } from '../Utils' import { makeEventBuffer } from '../Utils/event-buffer' -import { assertNodeErrorFree, BinaryNode, encodeBinaryNode, getBinaryNodeChild, getBinaryNodeChildren, S_WHATSAPP_NET } from '../WABinary' +import { assertNodeErrorFree, BinaryNode, binaryNodeToString, encodeBinaryNode, getBinaryNodeChild, getBinaryNodeChildren, S_WHATSAPP_NET } from '../WABinary' +import { MobileSocket } from './mobile-socket' +import { WebSocket } from './web-socket' /** * Connects to WA servers and performs: @@ -14,37 +16,35 @@ import { assertNodeErrorFree, BinaryNode, encodeBinaryNode, getBinaryNodeChild, * - listen to messages and emit events * - query phone connection */ -export const makeSocket = ({ - waWebSocketUrl, - connectTimeoutMs, - logger, - agent, - keepAliveIntervalMs, - version, - browser, - auth: authState, - printQRInTerminal, - defaultQueryTimeoutMs, - syncFullHistory, - transactionOpts, - qrTimeout, - options, - makeSignalRepository -}: SocketConfig) => { - const ws = new WebSocket(waWebSocketUrl, undefined, { - origin: DEFAULT_ORIGIN, - headers: options.headers as {}, - handshakeTimeout: connectTimeoutMs, - timeout: connectTimeoutMs, - agent - }) + +export const makeSocket = (config: SocketConfig) => { + const { + connectTimeoutMs, + logger, + keepAliveIntervalMs, + browser, + auth: authState, + printQRInTerminal, + defaultQueryTimeoutMs, + transactionOpts, + qrTimeout, + makeSignalRepository, + } = config + + config.mobile = config.mobile || config.auth.creds.registered + const ws = config.mobile ? new MobileSocket(config) : new WebSocket(config) ws.setMaxListeners(0) const ev = makeEventBuffer(logger) /** ephemeral key pair used to encrypt/decrypt communication. Unique for each connection */ const ephemeralKeyPair = Curve.generateKeyPair() /** WA noise protocol wrapper */ - const noise = makeNoiseHandler(ephemeralKeyPair, logger) + const noise = makeNoiseHandler({ + keyPair: ephemeralKeyPair, + NOISE_HEADER: config.mobile ? MOBILE_NOISE_HEADER : NOISE_WA_HEADER, + mobile: config.mobile, + logger + }) const { creds } = authState // add transaction capability @@ -63,7 +63,7 @@ export const makeSocket = ({ const sendPromise = promisify(ws.send) /** send a raw buffer */ const sendRawMessage = async(data: Uint8Array | Buffer) => { - if(ws.readyState !== ws.OPEN) { + if(!ws.isOpen) { throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }) } @@ -84,7 +84,7 @@ export const makeSocket = ({ /** send a binary node */ const sendNode = (frame: BinaryNode) => { if(logger.level === 'trace') { - logger.trace({ msgId: frame.attrs.id, fromMe: true, frame }, 'communication') + logger.trace(binaryNodeToString(frame), 'xml send') } const buff = encodeBinaryNode(frame) @@ -101,7 +101,7 @@ export const makeSocket = ({ /** await the next incoming message */ const awaitNextMessage = async(sendMsg?: Uint8Array) => { - if(ws.readyState !== ws.OPEN) { + if(!ws.isOpen) { throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }) @@ -186,21 +186,21 @@ export const makeSocket = ({ } helloMsg = proto.HandshakeMessage.fromObject(helloMsg) - logger.info({ browser, helloMsg }, 'connected to WA Web') + logger.info({ browser, helloMsg }, 'connected to WA') const init = proto.HandshakeMessage.encode(helloMsg).finish() const result = await awaitNextMessage(init) const handshake = proto.HandshakeMessage.decode(result) - logger.trace({ handshake }, 'handshake recv from WA Web') + logger.trace({ handshake }, 'handshake recv from WA') const keyEnc = noise.processHandshake(handshake, creds.noiseKey) - const config = { version, browser, syncFullHistory } - let node: proto.IClientPayload - if(!creds.me) { + if(config.mobile) { + node = generateMobileNode(config) + } else if(!creds.me) { node = generateRegistrationNode(creds, config) logger.info({ node }, 'not logged in, attempting registration...') } else { @@ -276,7 +276,7 @@ export const makeSocket = ({ const msgId = frame.attrs.id if(logger.level === 'trace') { - logger.trace({ msgId, fromMe: false, frame }, 'communication') + logger.trace(binaryNodeToString(frame), 'recv xml') } /* Check if this is a response to a message we sent */ @@ -321,7 +321,7 @@ export const makeSocket = ({ ws.removeAllListeners('open') ws.removeAllListeners('message') - if(ws.readyState !== ws.CLOSED && ws.readyState !== ws.CLOSING) { + if(!ws.isClosed && !ws.isClosing) { try { ws.close() } catch{ } @@ -338,11 +338,11 @@ export const makeSocket = ({ } const waitForSocketOpen = async() => { - if(ws.readyState === ws.OPEN) { + if(ws.isOpen) { return } - if(ws.readyState === ws.CLOSED || ws.readyState === ws.CLOSING) { + if(ws.isClosed || ws.isClosing) { throw new Boom('Connection Closed', { statusCode: DisconnectReason.connectionClosed }) } @@ -375,7 +375,7 @@ export const makeSocket = ({ */ if(diff > keepAliveIntervalMs + 5000) { end(new Boom('Connection was lost', { statusCode: DisconnectReason.connectionLost })) - } else if(ws.readyState === ws.OPEN) { + } else if(ws.isOpen) { // if its all good, send a keep alive request query( { @@ -472,7 +472,7 @@ export const makeSocket = ({ let qrMs = qrTimeout || 60_000 // time to let a QR live const genPairQR = () => { - if(ws.readyState !== ws.OPEN) { + if(!ws.isOpen) { return } diff --git a/src/Socket/web-socket.ts b/src/Socket/web-socket.ts new file mode 100644 index 0000000..ece9264 --- /dev/null +++ b/src/Socket/web-socket.ts @@ -0,0 +1,31 @@ +import { WebSocket as WS } from 'ws' +import { DEFAULT_ORIGIN } from '../Defaults' +import { SocketConfig } from '../Types' + +export class WebSocket extends WS { + constructor(public config: SocketConfig) { + super(config.waWebSocketUrl, undefined, { + origin: DEFAULT_ORIGIN, + headers: config.options.headers as Record, + handshakeTimeout: config.connectTimeoutMs, + timeout: config.connectTimeoutMs, + agent: config.agent, + }) + } + + get isOpen() { + return this.readyState === WS.OPEN + } + + get isClosed() { + return this.readyState === WS.CLOSED + } + + get isClosing() { + return this.readyState === WS.CLOSING + } + + get isConnecting() { + return this.readyState === WS.CONNECTING + } +} diff --git a/src/Types/Auth.ts b/src/Types/Auth.ts index 72bde7c..717b94a 100644 --- a/src/Types/Auth.ts +++ b/src/Types/Auth.ts @@ -1,4 +1,5 @@ import type { proto } from '../../WAProto' +import { RegistrationOptions } from '../Socket/registration' import type { Contact } from './Contact' import type { MinimalMessage } from './Message' @@ -58,6 +59,13 @@ export type AuthenticationCreds = SignalCreds & { /** number of times history & app state has been synced */ accountSyncCounter: number accountSettings: AccountSettings + // mobile creds + deviceId: string + phoneId: string + identityId: Buffer + registered: boolean + backupToken: Buffer + registration: RegistrationOptions } export type SignalDataTypeMap = { diff --git a/src/Types/Socket.ts b/src/Types/Socket.ts index 42edaa7..51dd6f7 100644 --- a/src/Types/Socket.ts +++ b/src/Types/Socket.ts @@ -31,6 +31,8 @@ export type SocketConfig = { defaultQueryTimeoutMs: number | undefined /** ping-pong interval for WS connection */ keepAliveIntervalMs: number + /** should baileys use the mobile api instead of the multi device api */ + mobile?: boolean /** proxy agent */ agent?: Agent /** pino logger */ diff --git a/src/Utils/auth-utils.ts b/src/Utils/auth-utils.ts index a4f2e73..7cc830c 100644 --- a/src/Utils/auth-utils.ts +++ b/src/Utils/auth-utils.ts @@ -1,6 +1,7 @@ import { randomBytes } from 'crypto' import NodeCache from 'node-cache' import type { Logger } from 'pino' +import { v4 as uuidv4 } from 'uuid' import { DEFAULT_CACHE_TTLS } from '../Defaults' import type { AuthenticationCreds, CacheStore, SignalDataSet, SignalDataTypeMap, SignalKeyStore, SignalKeyStoreWithTransaction, TransactionCapabilityOptions } from '../Types' import { Curve, signedKeyPair } from './crypto' @@ -202,6 +203,13 @@ export const initAuthCreds = (): AuthenticationCreds => { accountSyncCounter: 0, accountSettings: { unarchiveChats: false - } + }, + // mobile creds + deviceId: Buffer.from(uuidv4().replace(/-/g, ''), 'hex').toString('base64url'), + phoneId: uuidv4(), + identityId: randomBytes(20), + registered: false, + backupToken: randomBytes(20), + registration: {} as RegistrationOptions } } \ No newline at end of file diff --git a/src/Utils/crypto.ts b/src/Utils/crypto.ts index 7855eb5..46c020f 100644 --- a/src/Utils/crypto.ts +++ b/src/Utils/crypto.ts @@ -107,6 +107,10 @@ export function sha256(buffer: Buffer) { return createHash('sha256').update(buffer).digest() } +export function md5(buffer: Buffer) { + return createHash('md5').update(buffer).digest() +} + // HKDF key expansion export function hkdf(buffer: Uint8Array | Buffer, expandedLength: number, info: { salt?: Buffer, info?: string }) { return HKDF(!Buffer.isBuffer(buffer) ? Buffer.from(buffer) : buffer, expandedLength, info) diff --git a/src/Utils/noise-handler.ts b/src/Utils/noise-handler.ts index bd61ddf..2de65e6 100644 --- a/src/Utils/noise-handler.ts +++ b/src/Utils/noise-handler.ts @@ -1,7 +1,7 @@ import { Boom } from '@hapi/boom' import { Logger } from 'pino' import { proto } from '../../WAProto' -import { NOISE_MODE, NOISE_WA_HEADER, WA_CERT_DETAILS } from '../Defaults' +import { NOISE_MODE, WA_CERT_DETAILS } from '../Defaults' import { KeyPair } from '../Types' import { BinaryNode, decodeBinaryNode } from '../WABinary' import { aesDecryptGCM, aesEncryptGCM, Curve, hkdf, sha256 } from './crypto' @@ -13,10 +13,17 @@ const generateIV = (counter: number) => { return new Uint8Array(iv) } -export const makeNoiseHandler = ( - { public: publicKey, private: privateKey }: KeyPair, +export const makeNoiseHandler = ({ + keyPair: { private: privateKey, public: publicKey }, + NOISE_HEADER, + mobile, + logger, +}: { + keyPair: KeyPair + NOISE_HEADER: Uint8Array + mobile: boolean logger: Logger -) => { +}) => { logger = logger.child({ class: 'ns' }) const authenticate = (data: Uint8Array) => { @@ -86,7 +93,7 @@ export const makeNoiseHandler = ( let inBytes = Buffer.alloc(0) - authenticate(NOISE_WA_HEADER) + authenticate(NOISE_HEADER) authenticate(publicKey) return { @@ -103,12 +110,18 @@ export const makeNoiseHandler = ( mixIntoKey(Curve.sharedKey(privateKey, decStaticContent)) const certDecoded = decrypt(serverHello!.payload!) - const { intermediate: certIntermediate } = proto.CertChain.decode(certDecoded) - const { issuerSerial } = proto.CertChain.NoiseCertificate.Details.decode(certIntermediate!.details!) + if(mobile) { + const cert = proto.CertChain.NoiseCertificate.decode(certDecoded) + logger.debug(cert) + } else { + const { intermediate: certIntermediate } = proto.CertChain.decode(certDecoded) - if(issuerSerial !== WA_CERT_DETAILS.SERIAL) { - throw new Boom('certification match failed', { statusCode: 400 }) + const { issuerSerial } = proto.CertChain.NoiseCertificate.Details.decode(certIntermediate!.details!) + + if(issuerSerial !== WA_CERT_DETAILS.SERIAL) { + throw new Boom('certification match failed', { statusCode: 400 }) + } } const keyEnc = encrypt(noiseKey.public) @@ -121,11 +134,11 @@ export const makeNoiseHandler = ( data = encrypt(data) } - const introSize = sentIntro ? 0 : NOISE_WA_HEADER.length + const introSize = sentIntro ? 0 : NOISE_HEADER.length const frame = Buffer.alloc(introSize + 3 + data.byteLength) if(!sentIntro) { - frame.set(NOISE_WA_HEADER) + frame.set(NOISE_HEADER) sentIntro = true } diff --git a/src/Utils/validate-connection.ts b/src/Utils/validate-connection.ts index 444634d..29b6cab 100644 --- a/src/Utils/validate-connection.ts +++ b/src/Utils/validate-connection.ts @@ -8,26 +8,31 @@ import { Curve, hmacSign } from './crypto' import { encodeBigEndian } from './generics' import { createSignalIdentity } from './signal' -type ClientPayloadConfig = Pick +const getUserAgent = (config: SocketConfig): proto.ClientPayload.IUserAgent => { + const osVersion = config.mobile ? '15.3.1' : '0.1' + const version = config.mobile ? [2, 22, 24] : config.version + const device = config.mobile ? 'iPhone_7' : 'Desktop' + const manufacturer = config.mobile ? 'Apple' : '' + const platform = config.mobile ? proto.ClientPayload.UserAgent.Platform.IOS : proto.ClientPayload.UserAgent.Platform.WEB + const phoneId = config.mobile ? { phoneId: config.auth.creds.phoneId } : {} -const getUserAgent = ({ version }: ClientPayloadConfig): proto.ClientPayload.IUserAgent => { - const osVersion = '0.1' return { appVersion: { primary: version[0], secondary: version[1], tertiary: version[2], }, - platform: proto.ClientPayload.UserAgent.Platform.WEB, + platform, releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE, - mcc: '000', - mnc: '000', + mcc: config.auth.creds.registration?.phoneNumberMobileCountryCode || '000', + mnc: config.auth.creds.registration?.phoneNumberMobileNetworkCode || '000', osVersion: osVersion, - manufacturer: '', - device: 'Desktop', + manufacturer, + device, osBuildNumber: osVersion, localeLanguageIso6391: 'en', localeCountryIso31661Alpha2: 'US', + ...phoneId } } @@ -36,7 +41,7 @@ const PLATFORM_MAP = { 'Windows': proto.ClientPayload.WebInfo.WebSubPlatform.WIN32 } -const getWebInfo = (config: ClientPayloadConfig): proto.ClientPayload.IWebInfo => { +const getWebInfo = (config: SocketConfig): proto.ClientPayload.IWebInfo => { let webSubPlatform = proto.ClientPayload.WebInfo.WebSubPlatform.WEB_BROWSER if(config.syncFullHistory && PLATFORM_MAP[config.browser[0]]) { webSubPlatform = PLATFORM_MAP[config.browser[0]] @@ -45,16 +50,43 @@ const getWebInfo = (config: ClientPayloadConfig): proto.ClientPayload.IWebInfo = return { webSubPlatform } } -const getClientPayload = (config: ClientPayloadConfig): proto.IClientPayload => { - return { +const getClientPayload = (config: SocketConfig) => { + const payload: proto.IClientPayload = { connectType: proto.ClientPayload.ConnectType.WIFI_UNKNOWN, connectReason: proto.ClientPayload.ConnectReason.USER_ACTIVATED, userAgent: getUserAgent(config), - webInfo: getWebInfo(config), } + + if(!config.mobile) { + payload.webInfo = getWebInfo(config) + } + + return payload } -export const generateLoginNode = (userJid: string, config: ClientPayloadConfig): proto.IClientPayload => { +export const generateMobileNode = (config: SocketConfig): proto.IClientPayload => { + if(!config.auth.creds) { + throw new Boom('No registration data found', { data: config }) + } + + const payload: proto.IClientPayload = { + ...getClientPayload(config), + sessionId: Math.floor(Math.random() * 999999999 + 1), + shortConnect: true, + connectAttemptCount: 0, + device: 0, + dnsSource: { + appCached: false, + dnsMethod: proto.ClientPayload.DNSSource.DNSResolutionMethod.SYSTEM, + }, + passive: false, // XMPP heartbeat setting (false: server actively pings) (true: client actively pings) + pushName: 'test', + username: Number(`${config.auth.creds.registration.phoneNumberCountryCode}${config.auth.creds.registration.phoneNumberNationalNumber}`), + } + return proto.ClientPayload.fromObject(payload) +} + +export const generateLoginNode = (userJid: string, config: SocketConfig): proto.IClientPayload => { const { user, device } = jidDecode(userJid)! const payload: proto.IClientPayload = { ...getClientPayload(config), @@ -67,7 +99,7 @@ export const generateLoginNode = (userJid: string, config: ClientPayloadConfig): export const generateRegistrationNode = ( { registrationId, signedPreKey, signedIdentityKey }: SignalCreds, - config: ClientPayloadConfig + config: SocketConfig ) => { // the app version needs to be md5 hashed // and passed in diff --git a/src/WABinary/generic-utils.ts b/src/WABinary/generic-utils.ts index dd38620..48b323c 100644 --- a/src/WABinary/generic-utils.ts +++ b/src/WABinary/generic-utils.ts @@ -87,4 +87,35 @@ function bufferToUInt(e: Uint8Array | Buffer, t: number) { } return a +} + +const tabs = (n: number) => '\t'.repeat(n) + +export function binaryNodeToString(node: BinaryNode | BinaryNode['content'], i = 0) { + if(!node) { + return node + } + + if(typeof node === 'string') { + return tabs(i) + node + } + + if(node instanceof Uint8Array) { + return tabs(i) + Buffer.from(node).toString('hex') + } + + if(Array.isArray(node)) { + return node.map((x) => tabs(i + 1) + binaryNodeToString(x, i + 1)).join('\n') + } + + const children = binaryNodeToString(node.content, i + 1) + + const tag = `<${node.tag} ${Object.entries(node.attrs || {}) + .filter(([, v]) => v !== undefined) + .map(([k, v]) => `${k}='${v}'`) + .join(' ')}` + + const content: string = children ? `>\n${children}\n${tabs(i)}` : '/>' + + return tag + content } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 43a983d..3bb1ad9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1127,6 +1127,11 @@ resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz" integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== +"@types/uuid@^9.0.0": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.1.tgz#98586dc36aee8dacc98cc396dbca8d0429647aa6" + integrity sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA== + "@types/ws@^8.0.0": version "8.5.3" resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz" @@ -1576,6 +1581,14 @@ buffer@^5.2.0, buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" @@ -1736,6 +1749,11 @@ color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + combined-stream@^1.0.6, combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" @@ -1838,6 +1856,11 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" @@ -2246,6 +2269,11 @@ event-target-shim@^5.0.0: resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@^5.0.0: version "5.1.1" resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" @@ -2286,6 +2314,11 @@ expect@^27.5.1: jest-matcher-utils "^27.5.1" jest-message-util "^27.5.1" +fast-copy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" + integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" @@ -2317,6 +2350,11 @@ fast-redact@^3.0.0: resolved "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz" integrity sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A== +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + fastq@^1.6.0: version "1.15.0" resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" @@ -2547,6 +2585,17 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + global@~4.4.0: version "4.4.0" resolved "https://registry.npmjs.org/global/-/global-4.4.0.tgz" @@ -2635,6 +2684,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +help-me@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.2.0.tgz#50712bfd799ff1854ae1d312c36eafcea85b0563" + integrity sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA== + dependencies: + glob "^8.0.0" + readable-stream "^3.6.0" + html-encoding-sniffer@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz" @@ -3372,6 +3429,11 @@ jimp@^0.16.1: "@jimp/types" "^0.16.1" regenerator-runtime "^0.13.3" +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + jpeg-js@0.4.2: version "0.4.2" resolved "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.2.tgz" @@ -3494,6 +3556,11 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +libphonenumber-js@^1.10.20: + version "1.10.28" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.28.tgz#cae7e929cad96cee5ecc9449027192ecba39ee72" + integrity sha512-1eAgjLrZA0+2Wgw4hs+4Q/kEBycxQo8ZLYnmOvZ3AlM8ImAVAJgDPlZtISLEzD1vunc2q8s2Pn7XwB7I8U3Kzw== + "libsignal@git+https://github.com/adiwajshing/libsignal-node": version "2.0.1" resolved "git+ssh://git@github.com/adiwajshing/libsignal-node.git#11dbd962ea108187c79a7c46fe4d6f790e23da97" @@ -3866,6 +3933,11 @@ on-exit-leak-free@^0.2.0: resolved "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz" integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== +on-exit-leak-free@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" + integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w== + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" @@ -4033,6 +4105,14 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pino-abstract-transport@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" + integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA== + dependencies: + readable-stream "^4.0.0" + split2 "^4.0.0" + pino-abstract-transport@v0.5.0: version "0.5.0" resolved "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz" @@ -4041,6 +4121,26 @@ pino-abstract-transport@v0.5.0: duplexify "^4.1.2" split2 "^4.0.0" +pino-pretty@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-9.4.0.tgz#fc4026e83c87272cbdfb7afed121770e6000940c" + integrity sha512-NIudkNLxnl7MGj1XkvsqVyRgo6meFP82ECXF2PlOI+9ghmbGuBUUqKJ7IZPIxpJw4vhhSva0IuiDSAuGh6TV9g== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^3.0.0" + fast-safe-stringify "^2.1.1" + help-me "^4.0.1" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^1.0.0" + pump "^3.0.0" + readable-stream "^4.0.0" + secure-json-parse "^2.4.0" + sonic-boom "^3.0.0" + strip-json-comments "^3.1.1" + pino-std-serializers@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz" @@ -4285,6 +4385,16 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.3.0.tgz#0914d0c72db03b316c9733bb3461d64a3cc50cba" + integrity sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + readable-web-to-node-stream@^3.0.0: version "3.0.2" resolved "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz" @@ -4412,6 +4522,11 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" +secure-json-parse@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== + semver@7.x, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7: version "7.3.7" resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz" @@ -4516,6 +4631,13 @@ sonic-boom@^2.2.1: dependencies: atomic-sleep "^1.0.0" +sonic-boom@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.3.0.tgz#cffab6dafee3b2bcb88d08d589394198bee1838c" + integrity sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g== + dependencies: + atomic-sleep "^1.0.0" + source-map-support@^0.5.6: version "0.5.21" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" @@ -4971,6 +5093,11 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" From 9dce6450ca70c78b8b0f753450b9644bd86b7602 Mon Sep 17 00:00:00 2001 From: Alessandro Autiero Date: Thu, 20 Apr 2023 19:52:22 +0200 Subject: [PATCH 02/24] Update README.md First draft of the new README: new discord short summary on what happened to the original library --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 49939e2..e64bfe3 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ # Baileys - Typescript/Javascript WhatsApp Web API + +Baileys does not require Selenium or any other browser to be interface with WhatsApp Web, it does so directly using a **WebSocket**. +Not running Selenium or Chromimum saves you like **half a gig** of ram :/ +Baileys supports interacting with the multi-device & web versions of WhatsApp. +Thank you to [@pokearaujo](https://github.com/pokearaujo/multidevice) for writing his observations on the workings of WhatsApp Multi-Device. Also, thank you to [@Sigalor](https://github.com/sigalor/whatsapp-web-reveng) for writing his observations on the workings of WhatsApp Web and thanks to [@Rhymen](https://github.com/Rhymen/go-whatsapp/) for the __go__ implementation. - Baileys does not require Selenium or any other browser to be interface with WhatsApp Web, it does so directly using a **WebSocket**. Not running Selenium or Chromimum saves you like **half a gig** of ram :/ +## Please Read - Baileys supports interacting with the multi-device & web versions of WhatsApp. - - Thank you to [@pokearaujo](https://github.com/pokearaujo/multidevice) for writing his observations on the workings of WhatsApp Multi-Device. Also, thank you to [@Sigalor](https://github.com/sigalor/whatsapp-web-reveng) for writing his observations on the workings of WhatsApp Web and thanks to [@Rhymen](https://github.com/Rhymen/go-whatsapp/) for the __go__ implementation. - - Baileys is type-safe, extensible and simple to use. If you require more functionality than provided, it's super easy to write an extension. More on this [here](#WritingCustomFunctionality). +Baileys was recently taken down from Gitub as a result of a cease and desist from Whatsapp. +This request has no legal value(it's not the same thing as a DMCA strike), yet the project has been removed by its original author, Adhiraj Singh, and moved here. +This is the only official repository and is mantained by the community. + **Join the Discord [here](https://discord.gg/txhGQF7A7x)** - If you're interested in building a WhatsApp bot, you may wanna check out [WhatsAppInfoBot](https://github.com/adiwajshing/WhatsappInfoBot) and an actual bot built with it, [Messcat](https://github.com/ashokatechmin/Messcat). - - **Read the docs [here](https://adiwajshing.github.io/Baileys)** - **Join the Discord [here](https://discord.gg/WeJM5FP9GG)** - ## Example -Do check out & run [example.ts](https://github.com/adiwajshing/Baileys/blob/master/Example/example.ts) to see an example usage of the library. +Do check out & run [example.ts]( +/blob/master/Example/example.ts) to see an example usage of the library. The script covers most common use cases. To run the example script, download or clone the repo and then type the following in a terminal: 1. ``` cd path/to/Baileys ``` From 676ef648d55b82db606cde14662dca519c473069 Mon Sep 17 00:00:00 2001 From: Alessandro Autiero Date: Thu, 20 Apr 2023 19:54:20 +0200 Subject: [PATCH 03/24] Update README.md Fixed invite to last forever --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e64bfe3..c52788b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Thank you to [@pokearaujo](https://github.com/pokearaujo/multidevice) for writin Baileys was recently taken down from Gitub as a result of a cease and desist from Whatsapp. This request has no legal value(it's not the same thing as a DMCA strike), yet the project has been removed by its original author, Adhiraj Singh, and moved here. This is the only official repository and is mantained by the community. - **Join the Discord [here](https://discord.gg/txhGQF7A7x)** + **Join the Discord [here](https://discord.gg/Hv29aeewvF)** ## Example From 4907090d3c94e7b89845a400cf36174cc70ab6b6 Mon Sep 17 00:00:00 2001 From: Alessandro Autiero Date: Thu, 20 Apr 2023 20:29:09 +0200 Subject: [PATCH 04/24] Update README.md Fixed invite and header --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c52788b..b1e459a 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,9 @@ Thank you to [@pokearaujo](https://github.com/pokearaujo/multidevice) for writin ## Please Read -Baileys was recently taken down from Gitub as a result of a cease and desist from Whatsapp. -This request has no legal value(it's not the same thing as a DMCA strike), yet the project has been removed by its original author, Adhiraj Singh, and moved here. -This is the only official repository and is mantained by the community. - **Join the Discord [here](https://discord.gg/Hv29aeewvF)** +The original repository had to be removed by the original author - we now continue development in this repository here +This is the only official repository and is maintained by the community. + **Join the Discord [here](https://discord.gg/WeJM5FP9GG)** ## Example From 0f4fe2e23b854231697fd2a28e1baa1828cdd487 Mon Sep 17 00:00:00 2001 From: Alessandro Autiero Date: Thu, 20 Apr 2023 20:38:35 +0200 Subject: [PATCH 05/24] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1e459a..46ca69f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Thank you to [@pokearaujo](https://github.com/pokearaujo/multidevice) for writin ## Please Read -The original repository had to be removed by the original author - we now continue development in this repository here +The original repository had to be removed by the original author - we now continue development in this repository here. This is the only official repository and is maintained by the community. **Join the Discord [here](https://discord.gg/WeJM5FP9GG)** From 780b09aad67a9a83be5bb2cec14a31960146f1a0 Mon Sep 17 00:00:00 2001 From: Cassio Santos Date: Thu, 20 Apr 2023 19:43:42 -0300 Subject: [PATCH 06/24] chore: update README installation instructions --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 46ca69f..47b5144 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,12 @@ To run the example script, download or clone the repo and then type the followin Use the stable version: ``` -yarn add @adiwajshing/baileys +temporarily unavailable ``` Use the edge version (no guarantee of stability, but latest fixes + features) ``` -yarn add github:adiwajshing/baileys +yarn add github:WhiskeySockets/Baileys ``` Then import your code using: From f016d0749fd60c5aa0f08a4df282bafccf09fdfa Mon Sep 17 00:00:00 2001 From: Edgard Lorraine Messias Date: Fri, 21 Apr 2023 19:52:33 -0300 Subject: [PATCH 07/24] ci: Fixed docs build (#11) --- .github/workflows/update-docs.yml | 14 +- package.json | 4 +- yarn.lock | 578 +++++++++++++++++++----------- 3 files changed, 370 insertions(+), 226 deletions(-) diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index 9d0d11d..d26938c 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -1,5 +1,8 @@ name: Update Docs +permissions: + contents: write + on: push: branches: @@ -31,11 +34,10 @@ jobs: - name: Build run: yarn run build:all - + - name: Publish to Pages - uses: crazy-max/ghaction-github-pages@v2 + uses: peaceiris/actions-gh-pages@v3 with: - target_branch: gh-pages - build_dir: docs - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + publish_branch: gh-pages + publish_dir: ./docs + github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/package.json b/package.json index 681da97..bf51777 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "axios": "^1.3.3", "futoin-hkdf": "^1.5.1", "libphonenumber-js": "^1.10.20", - "libsignal": "git+https://github.com/adiwajshing/libsignal-node", + "libsignal": "https://github.com/adiwajshing/libsignal-node.git", "music-metadata": "^7.12.3", "node-cache": "^5.1.2", "pino": "^7.0.0", @@ -75,7 +75,7 @@ "WASignalGroup/*.js" ], "devDependencies": { - "@adiwajshing/eslint-config": "git+https://github.com/adiwajshing/eslint-config", + "@adiwajshing/eslint-config": "https://github.com/adiwajshing/eslint-config.git", "@adiwajshing/keyed-db": "^0.2.4", "@types/got": "^9.6.11", "@types/jest": "^27.5.1", diff --git a/yarn.lock b/yarn.lock index 3bb1ad9..97b9274 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,9 +2,9 @@ # yarn lockfile v1 -"@adiwajshing/eslint-config@git+https://github.com/adiwajshing/eslint-config": +"@adiwajshing/eslint-config@https://github.com/adiwajshing/eslint-config.git": version "1.0.0" - resolved "git+ssh://git@github.com/adiwajshing/eslint-config.git#5ec841a7281fc27232d570b30fd410dce5de76c8" + resolved "https://github.com/adiwajshing/eslint-config.git#5ec841a7281fc27232d570b30fd410dce5de76c8" dependencies: "@typescript-eslint/eslint-plugin" "^5.33.1" "@typescript-eslint/parser" "^5.33.1" @@ -312,6 +312,18 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.0.tgz#f6f729b02feee2c749f57e334b7a1b5f40a81724" + integrity sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ== + "@eslint/eslintrc@^1.3.0": version "1.3.0" resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz" @@ -878,7 +890,7 @@ "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -886,12 +898,12 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" @@ -1072,7 +1084,7 @@ "@types/json-schema@^7.0.9": version "7.0.11" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/long@^4.0.0", "@types/long@^4.0.1": @@ -1097,7 +1109,7 @@ "@types/node@^10.1.0": version "10.17.60" - resolved "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== "@types/prettier@^2.1.5": @@ -1107,7 +1119,7 @@ "@types/semver@^7.3.12": version "7.3.13" - resolved "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== "@types/sharp@^0.29.4": @@ -1152,87 +1164,87 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^5.33.1": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz" - integrity sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg== + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.0.tgz#c0e10eeb936debe5d1c3433cf36206a95befefd0" + integrity sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw== dependencies: - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/type-utils" "5.52.0" - "@typescript-eslint/utils" "5.52.0" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.0" + "@typescript-eslint/type-utils" "5.59.0" + "@typescript-eslint/utils" "5.59.0" debug "^4.3.4" grapheme-splitter "^1.0.4" ignore "^5.2.0" natural-compare-lite "^1.4.0" - regexpp "^3.2.0" semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/parser@^5.33.1": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz" - integrity sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA== + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.0.tgz#0ad7cd019346cc5d150363f64869eca10ca9977c" + integrity sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w== dependencies: - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/typescript-estree" "5.52.0" + "@typescript-eslint/scope-manager" "5.59.0" + "@typescript-eslint/types" "5.59.0" + "@typescript-eslint/typescript-estree" "5.59.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz" - integrity sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw== +"@typescript-eslint/scope-manager@5.59.0": + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz#86501d7a17885710b6716a23be2e93fc54a4fe8c" + integrity sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ== dependencies: - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/visitor-keys" "5.52.0" + "@typescript-eslint/types" "5.59.0" + "@typescript-eslint/visitor-keys" "5.59.0" -"@typescript-eslint/type-utils@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz" - integrity sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw== +"@typescript-eslint/type-utils@5.59.0": + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.0.tgz#8e8d1420fc2265989fa3a0d897bde37f3851e8c9" + integrity sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA== dependencies: - "@typescript-eslint/typescript-estree" "5.52.0" - "@typescript-eslint/utils" "5.52.0" + "@typescript-eslint/typescript-estree" "5.59.0" + "@typescript-eslint/utils" "5.59.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz" - integrity sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ== +"@typescript-eslint/types@5.59.0": + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.0.tgz#3fcdac7dbf923ec5251545acdd9f1d42d7c4fe32" + integrity sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA== -"@typescript-eslint/typescript-estree@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz" - integrity sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ== +"@typescript-eslint/typescript-estree@5.59.0": + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz#8869156ee1dcfc5a95be3ed0e2809969ea28e965" + integrity sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg== dependencies: - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/visitor-keys" "5.52.0" + "@typescript-eslint/types" "5.59.0" + "@typescript-eslint/visitor-keys" "5.59.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz" - integrity sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA== +"@typescript-eslint/utils@5.59.0": + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.0.tgz#063d066b3bc4850c18872649ed0da9ee72d833d5" + integrity sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/typescript-estree" "5.52.0" + "@typescript-eslint/scope-manager" "5.59.0" + "@typescript-eslint/types" "5.59.0" + "@typescript-eslint/typescript-estree" "5.59.0" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz" - integrity sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA== +"@typescript-eslint/visitor-keys@5.59.0": + version "5.59.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz#a59913f2bf0baeb61b5cfcb6135d3926c3854365" + integrity sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA== dependencies: - "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/types" "5.59.0" eslint-visitor-keys "^3.3.0" abab@^2.0.3, abab@^2.0.5: @@ -1376,32 +1388,51 @@ argparse@^2.0.1: resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -array-includes@^3.1.5: - version "3.1.5" - resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz" - integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.5, array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" - get-intrinsic "^1.1.1" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" is-string "^1.0.7" array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.flatmap@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz" - integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg== +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" +array.prototype.tosorted@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532" + integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.1.3" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" @@ -1412,6 +1443,11 @@ atomic-sleep@^1.0.0: resolved "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + axios@^1.3.3: version "1.3.3" resolved "https://registry.npmjs.org/axios/-/axios-1.3.3.tgz" @@ -1591,7 +1627,7 @@ buffer@^6.0.3: call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" @@ -1844,7 +1880,7 @@ cssstyle@^2.3.0: curve25519-js@^0.0.4: version "0.0.4" - resolved "https://registry.npmjs.org/curve25519-js/-/curve25519-js-0.0.4.tgz" + resolved "https://registry.yarnpkg.com/curve25519-js/-/curve25519-js-0.0.4.tgz#e6ad967e8cd284590d657bbfc90d8b50e49ba060" integrity sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w== data-urls@^2.0.0: @@ -1900,10 +1936,10 @@ deepmerge@^4.2.2: resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -1940,14 +1976,14 @@ diff@^4.0.1: dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" doctrine@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" @@ -2045,45 +2081,65 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5: - version "1.20.1" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" - function-bind "^1.1.1" function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" + get-intrinsic "^1.2.0" get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" has "^1.0.3" has-property-descriptors "^1.0.0" + has-proto "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" is-string "^1.0.7" + is-typed-array "^1.1.10" is-weakref "^1.0.2" - object-inspect "^1.12.0" + object-inspect "^1.12.3" object-keys "^1.1.1" - object.assign "^4.1.2" + object.assign "^4.1.4" regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" es-shim-unscopables@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== dependencies: has "^1.0.3" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" @@ -2123,33 +2179,34 @@ escodegen@^2.0.0: source-map "~0.6.1" eslint-plugin-react@^7.30.0: - version "7.30.1" - resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz" - integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg== + version "7.32.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10" + integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg== dependencies: - array-includes "^3.1.5" - array.prototype.flatmap "^1.3.0" + array-includes "^3.1.6" + array.prototype.flatmap "^1.3.1" + array.prototype.tosorted "^1.1.1" doctrine "^2.1.0" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.5" - object.fromentries "^2.0.5" - object.hasown "^1.1.1" - object.values "^1.1.5" + object.entries "^1.1.6" + object.fromentries "^2.0.6" + object.hasown "^1.1.2" + object.values "^1.1.6" prop-types "^15.8.1" - resolve "^2.0.0-next.3" + resolve "^2.0.0-next.4" semver "^6.3.0" - string.prototype.matchall "^4.0.7" + string.prototype.matchall "^4.0.8" eslint-plugin-simple-import-sort@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-7.0.0.tgz#a1dad262f46d2184a90095a60c66fef74727f0f8" integrity sha512-U3vEDB5zhYPNfxT5TYR7u01dboFZp+HNpnGhkDB2g/2E4wZ/g1Q9Ton8UwCLfRV9yAKyYqDh62oHOamvkFxsvw== eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -2251,7 +2308,7 @@ esrecurse@^4.3.0: estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: @@ -2326,7 +2383,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: fast-glob@^3.2.9: version "3.2.12" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -2357,7 +2414,7 @@ fast-safe-stringify@^2.1.1: fastq@^1.6.0: version "1.15.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" @@ -2423,6 +2480,13 @@ follow-redirects@^1.15.0: resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + form-data@^2.5.0: version "2.5.1" resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz" @@ -2472,7 +2536,7 @@ function-bind@^1.1.1: function.prototype.name@^1.1.5: version "1.1.5" - resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== dependencies: call-bind "^1.0.2" @@ -2485,9 +2549,9 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2: +functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" - resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== futoin-hkdf@^1.5.1: @@ -2519,10 +2583,10 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz" - integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -2540,7 +2604,7 @@ get-stream@^6.0.0: get-symbol-description@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== dependencies: call-bind "^1.0.2" @@ -2561,7 +2625,7 @@ github-from-package@0.0.0: glob-parent@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -2616,9 +2680,16 @@ globals@^13.15.0: dependencies: type-fest "^0.20.2" +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@^11.1.0: version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -2628,6 +2699,13 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz" @@ -2635,12 +2713,12 @@ graceful-fs@^4.2.9: grapheme-splitter@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-flag@^3.0.0: @@ -2655,19 +2733,24 @@ has-flag@^4.0.0: has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: get-intrinsic "^1.1.1" +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== dependencies: has-symbols "^1.0.2" @@ -2799,15 +2882,24 @@ ini@~1.3.0: resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +internal-slot@^1.0.3, internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== dependencies: - get-intrinsic "^1.1.0" + get-intrinsic "^1.2.0" has "^1.0.3" side-channel "^1.0.4" +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" @@ -2820,23 +2912,23 @@ is-arrayish@^0.3.1: is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== dependencies: has-bigints "^1.0.1" is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== dependencies: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== is-core-module@^2.8.1: version "2.9.0" @@ -2846,15 +2938,15 @@ is-core-module@^2.8.1: has "^1.0.3" is-core-module@^2.9.0: - version "2.10.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== + version "2.12.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" + integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== dependencies: has "^1.0.3" is-date-object@^1.0.1: version "1.0.5" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" @@ -2895,12 +2987,12 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: is-negative-zero@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-number-object@^1.0.4: version "1.0.7" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" @@ -2917,7 +3009,7 @@ is-potential-custom-element-name@^1.0.1: is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" @@ -2925,7 +3017,7 @@ is-regex@^1.1.4: is-shared-array-buffer@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== dependencies: call-bind "^1.0.2" @@ -2937,18 +3029,29 @@ is-stream@^2.0.0: is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" @@ -2956,7 +3059,7 @@ is-typedarray@^1.0.0: is-weakref@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== dependencies: call-bind "^1.0.2" @@ -3524,7 +3627,7 @@ jsonc-parser@^3.0.0: "jsx-ast-utils@^2.4.1 || ^3.0.0": version "3.3.3" - resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw== dependencies: array-includes "^3.1.5" @@ -3561,9 +3664,9 @@ libphonenumber-js@^1.10.20: resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.28.tgz#cae7e929cad96cee5ecc9449027192ecba39ee72" integrity sha512-1eAgjLrZA0+2Wgw4hs+4Q/kEBycxQo8ZLYnmOvZ3AlM8ImAVAJgDPlZtISLEzD1vunc2q8s2Pn7XwB7I8U3Kzw== -"libsignal@git+https://github.com/adiwajshing/libsignal-node": +"libsignal@https://github.com/adiwajshing/libsignal-node.git": version "2.0.1" - resolved "git+ssh://git@github.com/adiwajshing/libsignal-node.git#11dbd962ea108187c79a7c46fe4d6f790e23da97" + resolved "https://github.com/adiwajshing/libsignal-node.git#11dbd962ea108187c79a7c46fe4d6f790e23da97" dependencies: curve25519-js "^0.0.4" protobufjs "6.8.8" @@ -3626,7 +3729,7 @@ long@^4.0.0: loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" @@ -3679,7 +3782,7 @@ merge-stream@^2.0.0: merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: @@ -3780,7 +3883,7 @@ napi-build-utils@^1.0.1: natural-compare-lite@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== natural-compare@^1.4.0: @@ -3868,19 +3971,19 @@ object-assign@^4.1.0, object-assign@^4.1.1: resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-inspect@^1.12.0, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.2, object.assign@^4.1.3: +object.assign@^4.1.3, object.assign@^4.1.4: version "4.1.4" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" @@ -3888,40 +3991,40 @@ object.assign@^4.1.2, object.assign@^4.1.3: has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz" - integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== +object.entries@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" + integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.20.4" -object.fromentries@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz" - integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== +object.fromentries@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" + integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.20.4" -object.hasown@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz" - integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A== +object.hasown@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" + integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== dependencies: define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" -object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + es-abstract "^1.20.4" omggif@^1.0.10, omggif@^1.0.9: version "1.0.10" @@ -4082,7 +4185,7 @@ path-parse@^1.0.7: path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== peek-readable@^4.1.0: @@ -4250,7 +4353,7 @@ prompts@^2.0.1: prop-types@^15.8.1: version "15.8.1" - resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" @@ -4259,7 +4362,7 @@ prop-types@^15.8.1: protobufjs@6.8.8: version "6.8.8" - resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c" integrity sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw== dependencies: "@protobufjs/aspromise" "^1.1.2" @@ -4335,7 +4438,7 @@ querystring@0.2.0: queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== quick-format-unescaped@^4.0.3: @@ -4355,7 +4458,7 @@ rc@^1.2.7: react-is@^16.13.1: version "16.13.1" - resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-is@^17.0.1: @@ -4412,14 +4515,14 @@ regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== -regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== +regexp.prototype.flags@^1.4.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" regexpp@^3.2.0: version "3.2.0" @@ -4462,9 +4565,9 @@ resolve@^1.20.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.3: +resolve@^2.0.0-next.4: version "2.0.0-next.4" - resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== dependencies: is-core-module "^2.9.0" @@ -4473,7 +4576,7 @@ resolve@^2.0.0-next.3: reusify@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rimraf@^3.0.0, rimraf@^3.0.2: @@ -4485,7 +4588,7 @@ rimraf@^3.0.0, rimraf@^3.0.2: run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" @@ -4500,6 +4603,15 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + safe-stable-stringify@^2.1.0: version "2.3.1" resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz" @@ -4581,7 +4693,7 @@ shiki@^0.10.1: side-channel@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== dependencies: call-bind "^1.0.0" @@ -4704,37 +4816,46 @@ string-width@^1.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.matchall@^4.0.7: - version "4.0.7" - resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz" - integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg== +string.prototype.matchall@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" + integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" has-symbols "^1.0.3" internal-slot "^1.0.3" - regexp.prototype.flags "^1.4.1" + regexp.prototype.flags "^1.4.3" side-channel "^1.0.4" -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" string_decoder@^1.1.1: version "1.3.0" @@ -4977,7 +5098,7 @@ ts-node@^10.8.1: tslib@^1.8.1: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.4.0: @@ -4987,7 +5108,7 @@ tslib@^2.4.0: tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -5028,6 +5149,15 @@ type-fest@^0.21.3: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" @@ -5053,7 +5183,7 @@ typescript@^4.0.0: unbox-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: call-bind "^1.0.2" @@ -5194,7 +5324,7 @@ whatwg-url@^8.0.0, whatwg-url@^8.5.0: which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== dependencies: is-bigint "^1.0.1" @@ -5203,6 +5333,18 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + which@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" From 89c1d6e1e1aad1679c3a21f35604c22d73b74572 Mon Sep 17 00:00:00 2001 From: Samuel Rodrigues Almeida Costa Date: Fri, 21 Apr 2023 17:06:56 -0300 Subject: [PATCH 08/24] Update fetchLatestBaileysVersion It was pointing to the old repository --- src/Utils/generics.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Utils/generics.ts b/src/Utils/generics.ts index ab392e2..e7aa654 100644 --- a/src/Utils/generics.ts +++ b/src/Utils/generics.ts @@ -226,7 +226,7 @@ export const printQRIfNecessaryListener = (ev: BaileysEventEmitter, logger: Logg * Use to ensure your WA connection is always on the latest version */ export const fetchLatestBaileysVersion = async(options: AxiosRequestConfig = { }) => { - const URL = 'https://raw.githubusercontent.com/adiwajshing/Baileys/master/src/Defaults/baileys-version.json' + const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/baileys-version.json' try { const result = await axios.get<{ version: WAVersion }>( URL, @@ -386,4 +386,4 @@ export function trimUndefineds(obj: any) { } return obj -} \ No newline at end of file +} From b313e2a9026644f4b258d609b96f50d12f6113b5 Mon Sep 17 00:00:00 2001 From: Edgard Date: Fri, 21 Apr 2023 17:12:21 -0300 Subject: [PATCH 09/24] style: fixed and relaxed style lint --- .eslintignore | 3 ++- .eslintrc.json | 17 ++++++++++++++++- src/Socket/messages-send.ts | 13 +++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.eslintignore b/.eslintignore index f1d610b..d41f50d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,4 +6,5 @@ coverage src/WABinary/index.ts WAProto WASignalGroup -Example/test.ts \ No newline at end of file +Example/test.ts +docs diff --git a/.eslintrc.json b/.eslintrc.json index 7d37e83..58fc1dd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,18 @@ { - "extends": "@adiwajshing" + "extends": "@adiwajshing", + "rules": { + "@typescript-eslint/no-explicit-any": [ + "warn", + { + "ignoreRestArgs": true + } + ], + "no-restricted-syntax": [ + "warn", + { + "selector": "TSEnumDeclaration", + "message": "Don't declare enums, use literals instead" + } + ] + } } \ No newline at end of file diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index e6e94ce..4b02775 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -505,7 +505,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { } const buttonType = getButtonType(message) - if(buttonType){ + if(buttonType) { (stanza.content as BinaryNode[]).push({ tag: 'biz', attrs: { }, @@ -576,17 +576,18 @@ export const makeMessagesSocket = (config: SocketConfig) => { } const getButtonArgs = (message: proto.IMessage): BinaryNode['attrs'] => { - if(message.templateMessage){ + if(message.templateMessage) { // TODO: Add attributes return {} } else if(message.listMessage) { const type = message.listMessage.listType - if(!type){ - throw new Boom("Expected list type inside message") + if(!type) { + throw new Boom('Expected list type inside message') } - return {v: '2', type: ListType[type].toLowerCase()}; + + return { v: '2', type: ListType[type].toLowerCase() } } else { - return {}; + return {} } } From fdbd732205974beae99933d3414dc7b1901d547c Mon Sep 17 00:00:00 2001 From: Andres Aya Date: Thu, 20 Apr 2023 08:14:11 -0500 Subject: [PATCH 10/24] refactor: store w transaction --- src/Types/Auth.ts | 4 ++-- src/Utils/auth-utils.ts | 47 ++++++++++++++++++----------------------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/Types/Auth.ts b/src/Types/Auth.ts index 717b94a..f49b648 100644 --- a/src/Types/Auth.ts +++ b/src/Types/Auth.ts @@ -90,7 +90,7 @@ export type SignalKeyStore = { export type SignalKeyStoreWithTransaction = SignalKeyStore & { isInTransaction: () => boolean - transaction(exec: () => Promise): Promise + transaction(exec: () => Promise): Promise } export type TransactionCapabilityOptions = { @@ -100,7 +100,7 @@ export type TransactionCapabilityOptions = { export type SignalAuthState = { creds: SignalCreds - keys: SignalKeyStore + keys: SignalKeyStore | SignalKeyStoreWithTransaction } export type AuthenticationState = { diff --git a/src/Utils/auth-utils.ts b/src/Utils/auth-utils.ts index 7cc830c..5ef31c9 100644 --- a/src/Utils/auth-utils.ts +++ b/src/Utils/auth-utils.ts @@ -94,32 +94,25 @@ export const addTransactionCapability = ( let transactionCache: SignalDataSet = { } let mutations: SignalDataSet = { } - /** - * prefetches some data and stores in memory, - * useful if these data points will be used together often - * */ - const prefetch = async(type: T, ids: string[]) => { - const dict = transactionCache[type] - const idsRequiringFetch = dict - ? ids.filter(item => typeof dict[item] !== 'undefined') - : ids - // only fetch if there are any items to fetch - if(idsRequiringFetch.length) { - dbQueriesInTransaction += 1 - const result = await state.get(type, idsRequiringFetch) - - transactionCache[type] ||= {} - transactionCache[type] = Object.assign( - transactionCache[type]!, - result - ) - } - } - return { get: async(type, ids) => { if(inTransaction) { - await prefetch(type, ids) + const dict = transactionCache[type] + const idsRequiringFetch = dict + ? ids.filter(item => typeof dict[item] !== 'undefined') + : ids + // only fetch if there are any items to fetch + if(idsRequiringFetch.length) { + dbQueriesInTransaction += 1 + const result = await state.get(type, idsRequiringFetch) + + transactionCache[type] ||= {} + Object.assign( + transactionCache[type]!, + result + ) + } + return ids.reduce( (dict, id) => { const value = transactionCache[type]?.[id] @@ -149,16 +142,17 @@ export const addTransactionCapability = ( } }, isInTransaction: () => inTransaction, - transaction: async(work) => { + async transaction(work) { + let result: Awaited> // if we're already in a transaction, // just execute what needs to be executed -- no commit required if(inTransaction) { - await work() + result = await work() } else { logger.trace('entering transaction') inTransaction = true try { - await work() + result = await work() if(Object.keys(mutations).length) { logger.trace('committing transaction') // retry mechanism to ensure we've some recovery @@ -185,6 +179,7 @@ export const addTransactionCapability = ( dbQueriesInTransaction = 0 } } + return result } } } From 4a2db5a033e507a630a1d5b96a4779cc6f0f84e9 Mon Sep 17 00:00:00 2001 From: Andres Aya Date: Thu, 20 Apr 2023 08:17:06 -0500 Subject: [PATCH 11/24] fix: auth store transactions + tests --- src/Tests/test.key-store.ts | 92 +++++++++++++++++++++++++++++++++++++ src/Tests/utils.ts | 32 ++++++++++++- src/Utils/auth-utils.ts | 38 +++++++++------ 3 files changed, 146 insertions(+), 16 deletions(-) create mode 100644 src/Tests/test.key-store.ts diff --git a/src/Tests/test.key-store.ts b/src/Tests/test.key-store.ts new file mode 100644 index 0000000..f6b86b2 --- /dev/null +++ b/src/Tests/test.key-store.ts @@ -0,0 +1,92 @@ +import { addTransactionCapability, delay } from '../Utils' +import logger from '../Utils/logger' +import { makeMockSignalKeyStore } from './utils' + +logger.level = 'trace' + +describe('Key Store w Transaction Tests', () => { + + const rawStore = makeMockSignalKeyStore() + const store = addTransactionCapability( + rawStore, + logger, + { + maxCommitRetries: 1, + delayBetweenTriesMs: 10 + } + ) + + it('should use transaction cache when mutated', async() => { + const key = '123' + const value = new Uint8Array(1) + const ogGet = rawStore.get + await store.transaction( + async() => { + await store.set({ 'session': { [key]: value } }) + + rawStore.get = () => { + throw new Error('should not have been called') + } + + const { [key]: stored } = await store.get('session', [key]) + expect(stored).toEqual(new Uint8Array(1)) + } + ) + + rawStore.get = ogGet + }) + + it('should not commit a failed transaction', async() => { + const key = 'abcd' + await expect( + store.transaction( + async() => { + await store.set({ 'session': { [key]: new Uint8Array(1) } }) + throw new Error('fail') + } + ) + ).rejects.toThrowError( + 'fail' + ) + + const { [key]: stored } = await store.get('session', [key]) + expect(stored).toBeUndefined() + }) + + it('should handle overlapping transactions', async() => { + // promise to let transaction 2 + // know that transaction 1 has started + let promiseResolve: () => void + const promise = new Promise(resolve => { + promiseResolve = resolve + }) + + store.transaction( + async() => { + await store.set({ + 'session': { + '1': new Uint8Array(1) + } + }) + // wait for the other transaction to start + await delay(5) + // reolve the promise to let the other transaction continue + promiseResolve() + } + ) + + await store.transaction( + async() => { + await promise + await delay(5) + + expect(store.isInTransaction()).toBe(true) + } + ) + + expect(store.isInTransaction()).toBe(false) + // ensure that the transaction were committed + const { ['1']: stored } = await store.get('session', ['1']) + expect(stored).toEqual(new Uint8Array(1)) + }) +}) \ No newline at end of file diff --git a/src/Tests/utils.ts b/src/Tests/utils.ts index 9d5ce04..bcd1469 100644 --- a/src/Tests/utils.ts +++ b/src/Tests/utils.ts @@ -1,6 +1,36 @@ +import { SignalDataTypeMap, SignalKeyStore } from '../Types' import { jidEncode } from '../WABinary' - export function randomJid() { return jidEncode(Math.floor(Math.random() * 1000000), Math.random() < 0.5 ? 's.whatsapp.net' : 'g.us') +} + +export function makeMockSignalKeyStore(): SignalKeyStore { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const store: { [_: string]: any } = {} + + return { + get(type, ids) { + const data: { [_: string]: SignalDataTypeMap[typeof type] } = { } + for(const id of ids) { + const item = store[getUniqueId(type, id)] + if(typeof item !== 'undefined') { + data[id] = item + } + } + + return data + }, + set(data) { + for(const type in data) { + for(const id in data[type]) { + store[getUniqueId(type, id)] = data[type][id] + } + } + }, + } + + function getUniqueId(type: string, id: string) { + return `${type}.${id}` + } } \ No newline at end of file diff --git a/src/Utils/auth-utils.ts b/src/Utils/auth-utils.ts index 5ef31c9..aa176b6 100644 --- a/src/Utils/auth-utils.ts +++ b/src/Utils/auth-utils.ts @@ -87,19 +87,20 @@ export const addTransactionCapability = ( logger: Logger, { maxCommitRetries, delayBetweenTriesMs }: TransactionCapabilityOptions ): SignalKeyStoreWithTransaction => { - let inTransaction = false // number of queries made to the DB during the transaction // only there for logging purposes let dbQueriesInTransaction = 0 let transactionCache: SignalDataSet = { } let mutations: SignalDataSet = { } + let transactionsInProgress = 0 + return { get: async(type, ids) => { - if(inTransaction) { + if(isInTransaction()) { const dict = transactionCache[type] const idsRequiringFetch = dict - ? ids.filter(item => typeof dict[item] !== 'undefined') + ? ids.filter(item => typeof dict[item] === 'undefined') : ids // only fetch if there are any items to fetch if(idsRequiringFetch.length) { @@ -128,7 +129,7 @@ export const addTransactionCapability = ( } }, set: data => { - if(inTransaction) { + if(isInTransaction()) { logger.trace({ types: Object.keys(data) }, 'caching in transaction') for(const key in data) { transactionCache[key] = transactionCache[key] || { } @@ -141,18 +142,18 @@ export const addTransactionCapability = ( return state.set(data) } }, - isInTransaction: () => inTransaction, + isInTransaction, async transaction(work) { let result: Awaited> - // if we're already in a transaction, - // just execute what needs to be executed -- no commit required - if(inTransaction) { - result = await work() - } else { + transactionsInProgress += 1 + if(transactionsInProgress === 1) { logger.trace('entering transaction') - inTransaction = true - try { - result = await work() + } + + try { + result = await work() + // commit if this is the outermost transaction + if(transactionsInProgress === 1) { if(Object.keys(mutations).length) { logger.trace('committing transaction') // retry mechanism to ensure we've some recovery @@ -172,16 +173,23 @@ export const addTransactionCapability = ( } else { logger.trace('no mutations in transaction') } - } finally { - inTransaction = false + } + } finally { + transactionsInProgress -= 1 + if(transactionsInProgress === 0) { transactionCache = { } mutations = { } dbQueriesInTransaction = 0 } } + return result } } + + function isInTransaction() { + return transactionsInProgress > 0 + } } export const initAuthCreds = (): AuthenticationCreds => { From 65aa4a7d99027a2aa7bdadfabcb2accc5f40131b Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Sun, 30 Apr 2023 12:30:08 +0200 Subject: [PATCH 12/24] unify web + mobile and use tcp socket --- src/Socket/messages-recv.ts | 2 +- src/Socket/mobile-socket.ts | 4 ---- src/Socket/socket.ts | 11 +++++++++-- src/Socket/web-socket.ts | 31 ------------------------------- src/Utils/auth-utils.ts | 2 +- src/Utils/validate-connection.ts | 20 +------------------- 6 files changed, 12 insertions(+), 58 deletions(-) delete mode 100644 src/Socket/web-socket.ts diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 88d8fa5..fd0bf9c 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -564,7 +564,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { if(msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT) { retryMutex.mutex( async() => { - if(ws.readyState === ws.OPEN) { + if(ws.isOpen) { const encNode = getBinaryNodeChild(node, 'enc') await sendRetryRequest(node, !encNode) if(retryRequestDelayMs) { diff --git a/src/Socket/mobile-socket.ts b/src/Socket/mobile-socket.ts index edcdd5d..6b01a4e 100644 --- a/src/Socket/mobile-socket.ts +++ b/src/Socket/mobile-socket.ts @@ -6,10 +6,6 @@ export class MobileSocket extends Socket { constructor(public config: SocketConfig) { super() - if(config.auth.creds.registered) { - this.connect() - } - this.on('data', (d) => { this.emit('message', d) }) diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index eb9d772..60e6b92 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -8,7 +8,6 @@ import { addTransactionCapability, bindWaitForConnectionUpdate, configureSuccess import { makeEventBuffer } from '../Utils/event-buffer' import { assertNodeErrorFree, BinaryNode, binaryNodeToString, encodeBinaryNode, getBinaryNodeChild, getBinaryNodeChildren, S_WHATSAPP_NET } from '../WABinary' import { MobileSocket } from './mobile-socket' -import { WebSocket } from './web-socket' /** * Connects to WA servers and performs: @@ -32,9 +31,17 @@ export const makeSocket = (config: SocketConfig) => { } = config config.mobile = config.mobile || config.auth.creds.registered - const ws = config.mobile ? new MobileSocket(config) : new WebSocket(config) + const ws = new MobileSocket(config) ws.setMaxListeners(0) + if(!config.mobile) { + // if not mobile -> auto connect + ws.connect() + } else if(config.auth.creds.registered) { + // if mobile and registered -> auto connect + ws.connect() + } + const ev = makeEventBuffer(logger) /** ephemeral key pair used to encrypt/decrypt communication. Unique for each connection */ const ephemeralKeyPair = Curve.generateKeyPair() diff --git a/src/Socket/web-socket.ts b/src/Socket/web-socket.ts deleted file mode 100644 index ece9264..0000000 --- a/src/Socket/web-socket.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { WebSocket as WS } from 'ws' -import { DEFAULT_ORIGIN } from '../Defaults' -import { SocketConfig } from '../Types' - -export class WebSocket extends WS { - constructor(public config: SocketConfig) { - super(config.waWebSocketUrl, undefined, { - origin: DEFAULT_ORIGIN, - headers: config.options.headers as Record, - handshakeTimeout: config.connectTimeoutMs, - timeout: config.connectTimeoutMs, - agent: config.agent, - }) - } - - get isOpen() { - return this.readyState === WS.OPEN - } - - get isClosed() { - return this.readyState === WS.CLOSED - } - - get isClosing() { - return this.readyState === WS.CLOSING - } - - get isConnecting() { - return this.readyState === WS.CONNECTING - } -} diff --git a/src/Utils/auth-utils.ts b/src/Utils/auth-utils.ts index aa176b6..1f79da5 100644 --- a/src/Utils/auth-utils.ts +++ b/src/Utils/auth-utils.ts @@ -213,6 +213,6 @@ export const initAuthCreds = (): AuthenticationCreds => { identityId: randomBytes(20), registered: false, backupToken: randomBytes(20), - registration: {} as RegistrationOptions + registration: {} as never } } \ No newline at end of file diff --git a/src/Utils/validate-connection.ts b/src/Utils/validate-connection.ts index 29b6cab..fae4a18 100644 --- a/src/Utils/validate-connection.ts +++ b/src/Utils/validate-connection.ts @@ -13,7 +13,7 @@ const getUserAgent = (config: SocketConfig): proto.ClientPayload.IUserAgent => { const version = config.mobile ? [2, 22, 24] : config.version const device = config.mobile ? 'iPhone_7' : 'Desktop' const manufacturer = config.mobile ? 'Apple' : '' - const platform = config.mobile ? proto.ClientPayload.UserAgent.Platform.IOS : proto.ClientPayload.UserAgent.Platform.WEB + const platform = config.mobile ? proto.ClientPayload.UserAgent.Platform.IOS : proto.ClientPayload.UserAgent.Platform.MACOS const phoneId = config.mobile ? { phoneId: config.auth.creds.phoneId } : {} return { @@ -36,20 +36,6 @@ const getUserAgent = (config: SocketConfig): proto.ClientPayload.IUserAgent => { } } -const PLATFORM_MAP = { - 'Mac OS': proto.ClientPayload.WebInfo.WebSubPlatform.DARWIN, - 'Windows': proto.ClientPayload.WebInfo.WebSubPlatform.WIN32 -} - -const getWebInfo = (config: SocketConfig): proto.ClientPayload.IWebInfo => { - let webSubPlatform = proto.ClientPayload.WebInfo.WebSubPlatform.WEB_BROWSER - if(config.syncFullHistory && PLATFORM_MAP[config.browser[0]]) { - webSubPlatform = PLATFORM_MAP[config.browser[0]] - } - - return { webSubPlatform } -} - const getClientPayload = (config: SocketConfig) => { const payload: proto.IClientPayload = { connectType: proto.ClientPayload.ConnectType.WIFI_UNKNOWN, @@ -57,10 +43,6 @@ const getClientPayload = (config: SocketConfig) => { userAgent: getUserAgent(config), } - if(!config.mobile) { - payload.webInfo = getWebInfo(config) - } - return payload } From 470e19d3fc40595023d3bc288389e8ae79582e9b Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Sun, 30 Apr 2023 12:33:07 +0200 Subject: [PATCH 13/24] auto connect socket --- src/Socket/socket.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index 60e6b92..ea980af 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -34,11 +34,8 @@ export const makeSocket = (config: SocketConfig) => { const ws = new MobileSocket(config) ws.setMaxListeners(0) - if(!config.mobile) { - // if not mobile -> auto connect - ws.connect() - } else if(config.auth.creds.registered) { - // if mobile and registered -> auto connect + // if not mobile or already registered -> auto connect + if(!config.mobile || config.auth.creds.registered) { ws.connect() } From 6ab9ca5714356dee797e7b5f40c2f2a0afab12ac Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Sun, 30 Apr 2023 12:33:08 +0200 Subject: [PATCH 14/24] add .prettierignore --- .prettierignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +* \ No newline at end of file From 6ecc5a87578f3c15a13cfedc4278daa1b0dfaaa1 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Fri, 12 May 2023 18:02:41 +0200 Subject: [PATCH 15/24] fix: socket options --- src/Socket/mobile-socket.ts | 7 +++++-- src/Socket/socket.ts | 7 +++++-- src/Utils/generics.ts | 6 +++--- src/Utils/validate-connection.ts | 9 +-------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Socket/mobile-socket.ts b/src/Socket/mobile-socket.ts index 6b01a4e..f61c518 100644 --- a/src/Socket/mobile-socket.ts +++ b/src/Socket/mobile-socket.ts @@ -12,7 +12,10 @@ export class MobileSocket extends Socket { } override connect() { - return super.connect(MOBILE_PORT, MOBILE_ENDPOINT, () => { + return super.connect({ + host: MOBILE_ENDPOINT, + port: MOBILE_PORT, + }, () => { this.emit('open') }) } @@ -38,6 +41,6 @@ export class MobileSocket extends Socket { } send(data: unknown, cb?: ((err?: Error | undefined) => void) | undefined) { - return super.write(data as Uint8Array | string, cb as ((err?: Error | undefined) => void)) + return super.write(data as Uint8Array | string, undefined, cb as ((err?: Error | undefined) => void)) } } \ No newline at end of file diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index ea980af..718cb9b 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -32,7 +32,7 @@ export const makeSocket = (config: SocketConfig) => { config.mobile = config.mobile || config.auth.creds.registered const ws = new MobileSocket(config) - ws.setMaxListeners(0) + ws.setMaxListeners?.(0) // if not mobile or already registered -> auto connect if(!config.mobile || config.auth.creds.registered) { @@ -188,6 +188,9 @@ export const makeSocket = (config: SocketConfig) => { let helloMsg: proto.IHandshakeMessage = { clientHello: { ephemeral: ephemeralKeyPair.public } } + console.log(helloMsg) + console.log(Buffer.from(ephemeralKeyPair.public).toString('base64')) + console.log(ephemeralKeyPair.public.length) helloMsg = proto.HandshakeMessage.fromObject(helloMsg) logger.info({ browser, helloMsg }, 'connected to WA') @@ -627,7 +630,7 @@ function mapWebSocketError(handler: (err: Error) => void) { return (error: Error) => { handler( new Boom( - `WebSocket Error (${error.message})`, + `WebSocket Error (${error?.message})`, { statusCode: getCodeFromWSError(error), data: error } ) ) diff --git a/src/Utils/generics.ts b/src/Utils/generics.ts index e7aa654..74383ca 100644 --- a/src/Utils/generics.ts +++ b/src/Utils/generics.ts @@ -355,13 +355,13 @@ const UNEXPECTED_SERVER_CODE_TEXT = 'Unexpected server response: ' export const getCodeFromWSError = (error: Error) => { let statusCode = 500 - if(error.message.includes(UNEXPECTED_SERVER_CODE_TEXT)) { - const code = +error.message.slice(UNEXPECTED_SERVER_CODE_TEXT.length) + if(error?.message?.includes(UNEXPECTED_SERVER_CODE_TEXT)) { + const code = +error?.message.slice(UNEXPECTED_SERVER_CODE_TEXT.length) if(!Number.isNaN(code) && code >= 400) { statusCode = code } } else if( - (error as any).code?.startsWith('E') + (error as any)?.code?.startsWith('E') || error?.message?.includes('timed out') ) { // handle ETIMEOUT, ENOTFOUND etc statusCode = 408 diff --git a/src/Utils/validate-connection.ts b/src/Utils/validate-connection.ts index fae4a18..6b9e92b 100644 --- a/src/Utils/validate-connection.ts +++ b/src/Utils/validate-connection.ts @@ -88,17 +88,10 @@ export const generateRegistrationNode = ( const appVersionBuf = createHash('md5') .update(config.version.join('.')) // join as string .digest() - const browserVersion = config.browser[2].split('.') const companion: proto.IDeviceProps = { os: config.browser[0], - version: { - primary: +(browserVersion[0] || 0), - secondary: +(browserVersion[1] || 1), - tertiary: +(browserVersion[2] || 0), - }, - platformType: proto.DeviceProps.PlatformType[config.browser[1].toUpperCase()] - || proto.DeviceProps.PlatformType.UNKNOWN, + platformType: proto.DeviceProps.PlatformType.DESKTOP, requireFullSync: config.syncFullHistory, } From 07562c220473237e9575b8cd5b0e7ea6b05b5b26 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Sun, 14 May 2023 17:44:56 +0200 Subject: [PATCH 16/24] feat: fetch groups if ib:dirty --- src/Socket/chats.ts | 16 +++++---- src/Socket/groups.ts | 85 ++++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/Socket/chats.ts b/src/Socket/chats.ts index 35cb8e3..ee40c33 100644 --- a/src/Socket/chats.ts +++ b/src/Socket/chats.ts @@ -340,8 +340,8 @@ export const makeChatsSocket = (config: SocketConfig) => { } } - const updateAccountSyncTimestamp = async(fromTimestamp: number | string) => { - logger.info({ fromTimestamp }, 'requesting account sync') + const cleanDirtyBits = async(type: 'account_sync' | 'groups', fromTimestamp?: number | string) => { + logger.info({ fromTimestamp }, 'clean dirty bits ' + type) await sendNode({ tag: 'iq', attrs: { @@ -354,8 +354,8 @@ export const makeChatsSocket = (config: SocketConfig) => { { tag: 'clean', attrs: { - type: 'account_sync', - timestamp: fromTimestamp.toString(), + type, + ...(fromTimestamp ? { timestamp: fromTimestamp.toString() } : null), } } ] @@ -879,13 +879,16 @@ export const makeChatsSocket = (config: SocketConfig) => { if(attrs.timestamp) { let { lastAccountSyncTimestamp } = authState.creds if(lastAccountSyncTimestamp) { - await updateAccountSyncTimestamp(lastAccountSyncTimestamp) + await cleanDirtyBits('account_sync', lastAccountSyncTimestamp) } lastAccountSyncTimestamp = +attrs.timestamp ev.emit('creds.update', { lastAccountSyncTimestamp }) } + break + case 'groups': + // handled in groups.ts break default: logger.info({ node }, 'received unknown sync') @@ -945,6 +948,7 @@ export const makeChatsSocket = (config: SocketConfig) => { updateDefaultDisappearingMode, getBusinessProfile, resyncAppState, - chatModify + chatModify, + cleanDirtyBits } } diff --git a/src/Socket/groups.ts b/src/Socket/groups.ts index 6a0dcca..7eb5aa7 100644 --- a/src/Socket/groups.ts +++ b/src/Socket/groups.ts @@ -29,6 +29,55 @@ export const makeGroupsSocket = (config: SocketConfig) => { return extractGroupMetadata(result) } + + const groupFetchAllParticipating = async() => { + const result = await query({ + tag: 'iq', + attrs: { + to: '@g.us', + xmlns: 'w:g2', + type: 'get', + }, + content: [ + { + tag: 'participating', + attrs: { }, + content: [ + { tag: 'participants', attrs: { } }, + { tag: 'description', attrs: { } } + ] + } + ] + }) + const data: { [_: string]: GroupMetadata } = { } + const groupsChild = getBinaryNodeChild(result, 'groups') + if(groupsChild) { + const groups = getBinaryNodeChildren(groupsChild, 'group') + for(const groupNode of groups) { + const meta = extractGroupMetadata({ + tag: 'result', + attrs: { }, + content: [groupNode] + }) + data[meta.id] = meta + } + } + + sock.ev.emit('groups.update', Object.values(data)) + + return data + } + + sock.ws.on('CB:ib,,dirty', async(node: BinaryNode) => { + const { attrs } = getBinaryNodeChild(node, 'dirty')! + if(attrs.type !== 'groups') { + return + } + + await groupFetchAllParticipating() + await sock.cleanDirtyBits('groups') + }) + return { ...sock, groupMetadata, @@ -211,41 +260,7 @@ export const makeGroupsSocket = (config: SocketConfig) => { groupSettingUpdate: async(jid: string, setting: 'announcement' | 'not_announcement' | 'locked' | 'unlocked') => { await groupQuery(jid, 'set', [ { tag: setting, attrs: { } } ]) }, - groupFetchAllParticipating: async() => { - const result = await query({ - tag: 'iq', - attrs: { - to: '@g.us', - xmlns: 'w:g2', - type: 'get', - }, - content: [ - { - tag: 'participating', - attrs: { }, - content: [ - { tag: 'participants', attrs: { } }, - { tag: 'description', attrs: { } } - ] - } - ] - }) - const data: { [_: string]: GroupMetadata } = { } - const groupsChild = getBinaryNodeChild(result, 'groups') - if(groupsChild) { - const groups = getBinaryNodeChildren(groupsChild, 'group') - for(const groupNode of groups) { - const meta = extractGroupMetadata({ - tag: 'result', - attrs: { }, - content: [groupNode] - }) - data[meta.id] = meta - } - } - - return data - } + groupFetchAllParticipating } } From a6640bb0f651a194cfc1e847b7e8eff47f51777d Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Sun, 14 May 2023 17:45:19 +0200 Subject: [PATCH 17/24] fix: mobile app state key + message events --- src/Socket/chats.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Socket/chats.ts b/src/Socket/chats.ts index ee40c33..ce3e87f 100644 --- a/src/Socket/chats.ts +++ b/src/Socket/chats.ts @@ -915,7 +915,7 @@ export const makeChatsSocket = (config: SocketConfig) => { // if we don't have the app state key // we keep buffering events until we finally have // the key and can sync the messages - if(!authState.creds?.myAppStateKeyId) { + if(!authState.creds?.myAppStateKeyId && !config.mobile) { ev.buffer() needToFlushWithAppStateSync = true } From e98e309b0d7a4f34b01a1f42143c4c79f082c75b Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Thu, 18 May 2023 11:32:39 +0200 Subject: [PATCH 18/24] wip: two factor auth --- src/Socket/chats.ts | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/Socket/chats.ts b/src/Socket/chats.ts index 1f08f25..2f8206e 100644 --- a/src/Socket/chats.ts +++ b/src/Socket/chats.ts @@ -515,6 +515,52 @@ export const makeChatsSocket = (config: SocketConfig) => { } }) + const getTwoFactor = async() => { + const result = await query({ + tag: 'iq', + attrs: { + to: S_WHATSAPP_NET, + type: 'get', + xmlns: 'urn:xmpp:whatsapp:account', + id: generateMessageTag(), + }, + content: [ + { tag: '2fa', attrs: {} } + ] + }) + return getBinaryNodeChild(result, '2fa')?.content + } + + /** + * @param opts.pin - 2fa pin (6 digits) or undefined to disable + * @param opts.email - email for 2fa backup + */ + const setTwoFactor = async() => { + return query({ + tag: 'iq', + attrs: { + to: S_WHATSAPP_NET, + type: 'set', + xmlns: 'urn:xmpp:whatsapp:account', + id: generateMessageTag(), + }, + content: [ + { + tag: '2fa', + attrs: {}, + content: [ + { + tag: 'code', + attrs: {}, + content: Buffer.alloc(0) + }, + // ...(opts.email ? [{ tag: 'email', attrs: {}, content: opts.email }] : []), + ] + } + ] + }) + } + /** * fetch the profile picture of a user/group * type = "preview" for a low res picture From 90fe440f9a82277466919c5597b371b0c852ab84 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Fri, 19 May 2023 10:14:50 +0200 Subject: [PATCH 19/24] chore: remove console.logs --- src/Socket/socket.ts | 3 --- src/Utils/noise-handler.ts | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Socket/socket.ts b/src/Socket/socket.ts index 718cb9b..9853dd0 100644 --- a/src/Socket/socket.ts +++ b/src/Socket/socket.ts @@ -188,9 +188,6 @@ export const makeSocket = (config: SocketConfig) => { let helloMsg: proto.IHandshakeMessage = { clientHello: { ephemeral: ephemeralKeyPair.public } } - console.log(helloMsg) - console.log(Buffer.from(ephemeralKeyPair.public).toString('base64')) - console.log(ephemeralKeyPair.public.length) helloMsg = proto.HandshakeMessage.fromObject(helloMsg) logger.info({ browser, helloMsg }, 'connected to WA') diff --git a/src/Utils/noise-handler.ts b/src/Utils/noise-handler.ts index 2de65e6..a692856 100644 --- a/src/Utils/noise-handler.ts +++ b/src/Utils/noise-handler.ts @@ -112,8 +112,7 @@ export const makeNoiseHandler = ({ const certDecoded = decrypt(serverHello!.payload!) if(mobile) { - const cert = proto.CertChain.NoiseCertificate.decode(certDecoded) - logger.debug(cert) + proto.CertChain.NoiseCertificate.decode(certDecoded) } else { const { intermediate: certIntermediate } = proto.CertChain.decode(certDecoded) From d9a4dae23580444b87384f62d71b4d78fd84df4d Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Fri, 19 May 2023 10:20:55 +0200 Subject: [PATCH 20/24] revert: example logger --- Example/example.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/example.ts b/Example/example.ts index 3aec923..1dd0e8d 100644 --- a/Example/example.ts +++ b/Example/example.ts @@ -1,9 +1,9 @@ import { Boom } from '@hapi/boom' import parsePhoneNumber from 'libphonenumber-js' import NodeCache from 'node-cache' -import P from 'pino' import readline from 'readline' import makeWASocket, { AnyMessageContent, delay, DisconnectReason, fetchLatestBaileysVersion, getAggregateVotesInPollMessage, makeCacheableSignalKeyStore, makeInMemoryStore, PHONENUMBER_MCC, proto, useMultiFileAuthState, WAMessageContent, WAMessageKey } from '../src' +import MAIN_LOGGER from '../src/Utils/logger' const logger = MAIN_LOGGER.child({}) logger.level = 'trace' From d713e2314dd47b3bb69da754321919e801abe604 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Fri, 19 May 2023 10:24:55 +0200 Subject: [PATCH 21/24] remove wip two factor --- src/Socket/chats.ts | 46 --------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/src/Socket/chats.ts b/src/Socket/chats.ts index 2f8206e..1f08f25 100644 --- a/src/Socket/chats.ts +++ b/src/Socket/chats.ts @@ -515,52 +515,6 @@ export const makeChatsSocket = (config: SocketConfig) => { } }) - const getTwoFactor = async() => { - const result = await query({ - tag: 'iq', - attrs: { - to: S_WHATSAPP_NET, - type: 'get', - xmlns: 'urn:xmpp:whatsapp:account', - id: generateMessageTag(), - }, - content: [ - { tag: '2fa', attrs: {} } - ] - }) - return getBinaryNodeChild(result, '2fa')?.content - } - - /** - * @param opts.pin - 2fa pin (6 digits) or undefined to disable - * @param opts.email - email for 2fa backup - */ - const setTwoFactor = async() => { - return query({ - tag: 'iq', - attrs: { - to: S_WHATSAPP_NET, - type: 'set', - xmlns: 'urn:xmpp:whatsapp:account', - id: generateMessageTag(), - }, - content: [ - { - tag: '2fa', - attrs: {}, - content: [ - { - tag: 'code', - attrs: {}, - content: Buffer.alloc(0) - }, - // ...(opts.email ? [{ tag: 'email', attrs: {}, content: opts.email }] : []), - ] - } - ] - }) - } - /** * fetch the profile picture of a user/group * type = "preview" for a low res picture From c2bff56054f58905a1efbbc69ac76fb3e0446d84 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Mon, 22 May 2023 18:04:24 +0200 Subject: [PATCH 22/24] feat: use axios and config.options for registration --- Example/example.ts | 2 -- src/Socket/registration.ts | 31 +++++++++++++++---------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Example/example.ts b/Example/example.ts index 1dd0e8d..10bd833 100644 --- a/Example/example.ts +++ b/Example/example.ts @@ -62,8 +62,6 @@ const startSock = async() => { if(!registration.phoneNumber) { registration.phoneNumber = await question('Please enter your mobile phone number:\n') - } else { - console.log('Your mobile phone number is not registered.') } const phoneNumber = parsePhoneNumber(registration!.phoneNumber) diff --git a/src/Socket/registration.ts b/src/Socket/registration.ts index 3f3672e..66f90aa 100644 --- a/src/Socket/registration.ts +++ b/src/Socket/registration.ts @@ -1,4 +1,5 @@ /* eslint-disable camelcase */ +import axios, { AxiosRequestConfig } from 'axios' import { MOBILE_REGISTRATION_ENDPOINT, MOBILE_TOKEN, MOBILE_USERAGENT, REGISTRATION_PUBLIC_KEY } from '../Defaults' import { KeyPair, SignedKeyPair, SocketConfig } from '../Types' import { aesEncryptGCM, Curve, md5 } from '../Utils/crypto' @@ -22,7 +23,7 @@ export const makeRegistrationSocket = (config: SocketConfig) => { throw new Error('please specify the registration options') } - const result = await mobileRegister({ ...sock.authState.creds, ...sock.authState.creds.registration as RegistrationOptions, code }) + const result = await mobileRegister({ ...sock.authState.creds, ...sock.authState.creds.registration as RegistrationOptions, code }, config.options) sock.authState.creds.me = { id: jidEncode(result.login!, 's.whatsapp.net'), @@ -49,7 +50,7 @@ export const makeRegistrationSocket = (config: SocketConfig) => { sock.ev.emit('creds.update', sock.authState.creds) - return mobileRegisterCode({ ...config.auth.creds, ...registrationOptions }) + return mobileRegisterCode({ ...config.auth.creds, ...registrationOptions }, config.options) } return { @@ -146,7 +147,7 @@ export function registrationParams(params: RegistrationParams) { /** * Requests a registration code for the given phone number. */ -export function mobileRegisterCode(params: RegistrationParams) { +export function mobileRegisterCode(params: RegistrationParams, fetchOptions?: AxiosRequestConfig) { return mobileRegisterFetch('/code', { params: { ...registrationParams(params), @@ -158,23 +159,26 @@ export function mobileRegisterCode(params: RegistrationParams) { reason: '', hasav: '1' }, + ...fetchOptions, }) } -export function mobileRegisterExists(params: RegistrationParams) { +export function mobileRegisterExists(params: RegistrationParams, fetchOptions?: AxiosRequestConfig) { return mobileRegisterFetch('/exist', { - params: registrationParams(params) + params: registrationParams(params), + ...fetchOptions }) } /** * Registers the phone number on whatsapp with the received OTP code. */ -export async function mobileRegister(params: RegistrationParams & { code: string }) { +export async function mobileRegister(params: RegistrationParams & { code: string }, fetchOptions?: AxiosRequestConfig) { //const result = await mobileRegisterFetch(`/reg_onboard_abprop?cc=${params.phoneNumberCountryCode}&in=${params.phoneNumberNationalNumber}&rc=0`) return mobileRegisterFetch('/register', { params: { ...registrationParams(params), code: params.code.replace('-', '') }, + ...fetchOptions, }) } @@ -190,7 +194,7 @@ export function mobileRegisterEncrypt(data: string) { return Buffer.concat([Buffer.from(keypair.public), buffer]).toString('base64url') } -export async function mobileRegisterFetch(path: string, opts: { params?: Record, headers?: Record } = {}) { +export async function mobileRegisterFetch(path: string, opts: AxiosRequestConfig = {}) { let url = `${MOBILE_REGISTRATION_ENDPOINT}${path}` if(opts.params) { @@ -205,6 +209,7 @@ export async function mobileRegisterFetch(path: string, opts: { params?: Record< // const params = urlencode(mobileRegisterEncrypt(parameter.join('&'))) // url += `?ENC=${params}` url += `?${parameter.join('&')}` + delete opts.params } if(!opts.headers) { @@ -213,17 +218,11 @@ export async function mobileRegisterFetch(path: string, opts: { params?: Record< opts.headers['User-Agent'] = MOBILE_USERAGENT - const response = await fetch(url, opts) + const response = await axios(url, opts) - const text = await response.text() + var json = response.data - try { - var json = JSON.parse(text) - } catch(error) { - throw text - } - - if(!response.ok || json.reason) { + if(response.status > 300 || json.reason) { throw json } From 844de431a30f39d4b160c9fac8b6efd6677f9034 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Fri, 26 May 2023 14:13:12 +0200 Subject: [PATCH 23/24] feat: add native mobile api docs --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a5a8821..42eebe1 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,9 @@ import makeWASocket from '@whiskeysockets/baileys' TODO -## Connecting +## Connecting multi device (recommended) + +WhatsApp provides a multi-device API that allows Baileys to be authenticated as a second WhatsApp client by scanning a QR code with WhatsApp on your phone. ``` ts import makeWASocket, { DisconnectReason } from '@whiskeysockets/baileys' @@ -83,6 +85,12 @@ If the connection is successful, you will see a QR code printed on your terminal **Note:** the code to support the legacy version of WA Web (pre multi-device) has been removed in v5. Only the standard multi-device connection is now supported. This is done as WA seems to have completely dropped support for the legacy version. +## Connecting native mobile api + +Baileys also supports the native mobile API, which allows users to authenticate as a standalone WhatsApp client using their phone number. + +Run the [example](Example/example.ts) file with ``--mobile`` cli flag to use the native mobile API. + ## Configuring the Connection You can configure the connection by passing a `SocketConfig` object. From 5c5b23ec85983963d4d797e1437eca4808ad76f7 Mon Sep 17 00:00:00 2001 From: SamuelScheit Date: Fri, 26 May 2023 14:13:34 +0200 Subject: [PATCH 24/24] feat: add md-msg-hist to MEDIA_PATH_MAP --- src/Defaults/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Defaults/index.ts b/src/Defaults/index.ts index 9a150ed..e964a9f 100644 --- a/src/Defaults/index.ts +++ b/src/Defaults/index.ts @@ -88,7 +88,8 @@ export const MEDIA_PATH_MAP: { [T in MediaType]?: string } = { sticker: '/mms/image', 'thumbnail-link': '/mms/image', 'product-catalog-image': '/product/image', - 'md-app-state': '' + 'md-app-state': '', + 'md-msg-hist': '/mms/md-app-state', } export const MEDIA_HKDF_KEY_MAPPING = {