lint: 0 warnings left

This commit is contained in:
Rajeh Taher
2024-10-14 05:15:10 +03:00
parent 61a0ff3178
commit 18ac07df8e
32 changed files with 652 additions and 1006 deletions

View File

@@ -6,5 +6,5 @@ coverage
src/WABinary/index.ts src/WABinary/index.ts
WAProto WAProto
WASignalGroup WASignalGroup
Example/test.ts Example/Example.ts
docs docs

View File

@@ -1,5 +1,5 @@
{ {
"extends": "@adiwajshing", "extends": "@whiskeysockets",
"parserOptions": { "parserOptions": {
"sourceType": "module", "sourceType": "module",
"project": "./tsconfig.json" "project": "./tsconfig.json"
@@ -21,13 +21,7 @@
"@typescript-eslint/no-unnecessary-type-assertion": [ "@typescript-eslint/no-unnecessary-type-assertion": [
"warn" "warn"
], ],
"no-restricted-syntax": [ "no-restricted-syntax": "off",
"warn",
{
"selector": "TSEnumDeclaration",
"message": "Don't declare enums, use literals instead"
}
],
"keyword-spacing": [ "keyword-spacing": [
"warn" "warn"
] ]

View File

@@ -34,8 +34,8 @@
"changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", "changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"example": "node --inspect -r ts-node/register Example/example.ts", "example": "node --inspect -r ts-node/register Example/example.ts",
"gen:protobuf": "sh WAProto/GenerateStatics.sh", "gen:protobuf": "sh WAProto/GenerateStatics.sh",
"lint": "eslint src --ext .js,.ts,.jsx,.tsx", "lint": "eslint src --ext .js,.ts",
"lint:fix": "eslint src --fix --ext .js,.ts,.jsx,.tsx", "lint:fix": "yarn lint --fix",
"prepack": "tsc", "prepack": "tsc",
"prepare": "tsc", "prepare": "tsc",
"release": "release-it", "release": "release-it",
@@ -44,6 +44,7 @@
"dependencies": { "dependencies": {
"@adiwajshing/keyed-db": "^0.2.4", "@adiwajshing/keyed-db": "^0.2.4",
"@hapi/boom": "^9.1.3", "@hapi/boom": "^9.1.3",
"@whiskeysockets/eslint-config": "github:whiskeysockets/eslint-config",
"async-lock": "^1.4.1", "async-lock": "^1.4.1",
"audio-decode": "^2.1.3", "audio-decode": "^2.1.3",
"axios": "^1.6.0", "axios": "^1.6.0",
@@ -60,7 +61,6 @@
"ws": "^8.13.0" "ws": "^8.13.0"
}, },
"devDependencies": { "devDependencies": {
"@adiwajshing/eslint-config": "github:adiwajshing/eslint-config",
"@types/got": "^9.6.11", "@types/got": "^9.6.11",
"@types/jest": "^27.5.1", "@types/jest": "^27.5.1",
"@types/node": "^16.0.0", "@types/node": "^16.0.0",

View File

@@ -20,8 +20,6 @@ export const KEY_BUNDLE_TYPE = Buffer.from([5])
export const NOISE_WA_HEADER = Buffer.from( export const NOISE_WA_HEADER = Buffer.from(
[ 87, 65, 6, DICT_VERSION ] [ 87, 65, 6, DICT_VERSION ]
) // last is "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 */ /** 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_REGEX = /(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/

View File

@@ -999,15 +999,13 @@ export const makeChatsSocket = (config: SocketConfig) => {
) )
} }
if(receivedPendingNotifications) { if(receivedPendingNotifications && // if we don't have the app state key
// if we don't have the app state key
// we keep buffering events until we finally have // we keep buffering events until we finally have
// the key and can sync the messages // the key and can sync the messages
// todo scrutinize // todo scrutinize
if(!authState.creds?.myAppStateKeyId) { !authState.creds?.myAppStateKeyId) {
ev.buffer() ev.buffer()
needToFlushWithAppStateSync = true needToFlushWithAppStateSync = true
}
} }
}) })

View File

@@ -342,7 +342,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
break break
case 'membership_approval_mode': case 'membership_approval_mode':
const approvalMode: any = getBinaryNodeChild(child, 'group_join') const approvalMode = getBinaryNodeChild(child, 'group_join')
if(approvalMode) { if(approvalMode) {
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE
msg.messageStubParameters = [ approvalMode.attrs.state ] msg.messageStubParameters = [ approvalMode.attrs.state ]
@@ -574,8 +574,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
logger.debug({ participant, sendToAll }, 'forced new session for retry recp') logger.debug({ participant, sendToAll }, 'forced new session for retry recp')
for(let i = 0; i < msgs.length;i++) { for(const [i, msg] of msgs.entries()) {
const msg = msgs[i]
if(msg) { if(msg) {
updateSendMessageAgainCount(ids[i], participant) updateSendMessageAgainCount(ids[i], participant)
const msgRelayOpts: MessageRelayOptions = { messageId: ids[i] } const msgRelayOpts: MessageRelayOptions = { messageId: ids[i] }
@@ -761,10 +760,8 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
msg.messageStubParameters = [NO_MESSAGE_FOUND_ERROR_TEXT, response] msg.messageStubParameters = [NO_MESSAGE_FOUND_ERROR_TEXT, response]
} }
if(msg.message?.protocolMessage?.type === proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER) { if(msg.message?.protocolMessage?.type === proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER && node.attrs.sender_pn) {
if(node.attrs.sender_pn) { ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn })
ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn })
}
} }
try { try {
@@ -851,7 +848,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
return sendPeerDataOperationMessage(pdoMessage) return sendPeerDataOperationMessage(pdoMessage)
} }
const requestPlaceholderResend = async(messageKey: WAMessageKey): Promise<'RESOLVED'| string | undefined> => { const requestPlaceholderResend = async(messageKey: WAMessageKey): Promise<string | undefined> => {
if(!authState.creds.me?.id) { if(!authState.creds.me?.id) {
throw new Boom('Not authenticated') throw new Boom('Not authenticated')
} }

View File

@@ -280,7 +280,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
} }
} }
const meJid = jidNormalizedUser(authState.creds.me.id)! const meJid = jidNormalizedUser(authState.creds.me.id)
const msgId = await relayMessage(meJid, protocolMessage, { const msgId = await relayMessage(meJid, protocolMessage, {
additionalAttributes: { additionalAttributes: {

View File

@@ -76,7 +76,7 @@ export const makeSocket = (config: SocketConfig) => {
url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url')) url.searchParams.append('ED', authState.creds.routingInfo.toString('base64url'))
} }
const ws = config.socket ? config.socket : new WebSocketClient(url, config) const ws = new WebSocketClient(url, config)
ws.connect() ws.connect()
@@ -327,11 +327,12 @@ export const makeSocket = (config: SocketConfig) => {
const l1 = frame.attrs || {} const l1 = frame.attrs || {}
const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : '' const l2 = Array.isArray(frame.content) ? frame.content[0]?.tag : ''
Object.keys(l1).forEach(key => { for(const key of Object.keys(l1)) {
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, frame) || anyTriggered
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]}`, frame) || anyTriggered
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}`, frame) || anyTriggered
}) }
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},,${l2}`, frame) || anyTriggered
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0}`, frame) || anyTriggered

View File

@@ -225,16 +225,14 @@ export default (config: BaileysInMemoryStoreConfig) => {
const list = assertMessageList(jid) const list = assertMessageList(jid)
list.upsert(msg, 'append') list.upsert(msg, 'append')
if(type === 'notify') { if(type === 'notify' && !chats.get(jid)) {
if(!chats.get(jid)) { ev.emit('chats.upsert', [
ev.emit('chats.upsert', [ {
{ id: jid,
id: jid, conversationTimestamp: toNumber(msg.messageTimestamp),
conversationTimestamp: toNumber(msg.messageTimestamp), unreadCount: 1
unreadCount: 1 }
} ])
])
}
} }
} }

View File

@@ -61,9 +61,9 @@ function makeOrderedDictionary<T>(idGetter: (item: T) => string) {
}, },
clear: () => { clear: () => {
array.splice(0, array.length) array.splice(0, array.length)
Object.keys(dict).forEach(key => { for(const key of Object.keys(dict)) {
delete dict[key] delete dict[key]
}) }
}, },
filter: (contain: (item: T) => boolean) => { filter: (contain: (item: T) => boolean) => {
let i = 0 let i = 0

View File

@@ -15,6 +15,6 @@ export interface Contact {
* null => if the profile picture has not been set (default profile picture) * null => if the profile picture has not been set (default profile picture)
* any other string => url of the profile picture * any other string => url of the profile picture
*/ */
imgUrl?: string | null | 'changed' imgUrl?: string | null
status?: string status?: string
} }

View File

@@ -23,7 +23,9 @@ export type WAGenericMediaMessage = proto.Message.IVideoMessage | proto.Message.
export import WAMessageStubType = proto.WebMessageInfo.StubType export import WAMessageStubType = proto.WebMessageInfo.StubType
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
export import WAMessageStatus = proto.WebMessageInfo.Status export import WAMessageStatus = proto.WebMessageInfo.Status
export type WAMediaUpload = Buffer | { url: URL | string } | { stream: Readable } export type WAMediaPayloadURL = { url: URL | string }
export type WAMediaPayloadStream = { stream: Readable }
export type WAMediaUpload = Buffer | WAMediaPayloadStream | WAMediaPayloadURL
/** Set of message types that are supported by the library */ /** Set of message types that are supported by the library */
export type MessageType = keyof proto.Message export type MessageType = keyof proto.Message

View File

@@ -125,7 +125,4 @@ export type SocketConfig = {
cachedGroupMetadata: (jid: string) => Promise<GroupMetadata | undefined> cachedGroupMetadata: (jid: string) => Promise<GroupMetadata | undefined>
makeSignalRepository: (auth: SignalAuthState) => SignalRepository makeSignalRepository: (auth: SignalAuthState) => SignalRepository
/** Socket passthrough */
socket?: any
} }

View File

@@ -160,6 +160,7 @@ export const addTransactionCapability = (
let tries = maxCommitRetries let tries = maxCommitRetries
while(tries) { while(tries) {
tries -= 1 tries -= 1
//eslint-disable-next-line max-depth
try { try {
await state.set(mutations) await state.set(mutations)
logger.trace({ dbQueriesInTransaction }, 'committed transaction') logger.trace({ dbQueriesInTransaction }, 'committed transaction')
@@ -207,6 +208,7 @@ export const initAuthCreds = (): AuthenticationCreds => {
accountSettings: { accountSettings: {
unarchiveChats: false unarchiveChats: false
}, },
registered: false,
pairingCode: undefined, pairingCode: undefined,
lastPropHash: undefined, lastPropHash: undefined,
routingInfo: undefined, routingInfo: undefined,

View File

@@ -35,7 +35,7 @@ export const captureEventStream = (ev: BaileysEventEmitter, filename: string) =>
* @param filename filename containing event data * @param filename filename containing event data
* @param delayIntervalMs delay between each event emit * @param delayIntervalMs delay between each event emit
*/ */
export const readAndEmitEventStream = (filename: string, delayIntervalMs: number = 0) => { export const readAndEmitEventStream = (filename: string, delayIntervalMs = 0) => {
const ev = new EventEmitter() as BaileysEventEmitter const ev = new EventEmitter() as BaileysEventEmitter
const fireEvents = async() => { const fireEvents = async() => {

View File

@@ -38,7 +38,7 @@ const generateMac = (operation: proto.SyncdMutation.SyncdOperation, data: Buffer
} }
const buff = Buffer.from([r]) const buff = Buffer.from([r])
return Buffer.concat([buff, Buffer.from(keyId as any, 'base64')]) return Buffer.concat([buff, Buffer.from(keyId as string, 'base64')])
} }
const keyData = getKeyData() const keyData = getKeyData()
@@ -144,7 +144,7 @@ export const encodeSyncdPatch = async(
}) })
const encoded = proto.SyncActionData.encode(dataProto).finish() const encoded = proto.SyncActionData.encode(dataProto).finish()
const keyValue = mutationKeys(key!.keyData!) const keyValue = mutationKeys(key.keyData!)
const encValue = aesEncrypt(encoded, keyValue.valueEncryptionKey) const encValue = aesEncrypt(encoded, keyValue.valueEncryptionKey)
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey) const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey)
@@ -196,7 +196,7 @@ export const decodeSyncdMutations = async(
// indexKey used to HMAC sign record.index.blob // indexKey used to HMAC sign record.index.blob
// valueEncryptionKey used to AES-256-CBC encrypt record.value.blob[0:-32] // valueEncryptionKey used to AES-256-CBC encrypt record.value.blob[0:-32]
// the remaining record.value.blob[0:-32] is the mac, it the HMAC sign of key.keyId + decoded proto data + length of bytes in keyId // the remaining record.value.blob[0:-32] is the mac, it the HMAC sign of key.keyId + decoded proto data + length of bytes in keyId
for(const msgMutation of msgMutations!) { for(const msgMutation of msgMutations) {
// if it's a syncdmutation, get the operation property // if it's a syncdmutation, get the operation property
// otherwise, if it's only a record -- it'll be a SET mutation // otherwise, if it's only a record -- it'll be a SET mutation
const operation = 'operation' in msgMutation ? msgMutation.operation : proto.SyncdMutation.SyncdOperation.SET const operation = 'operation' in msgMutation ? msgMutation.operation : proto.SyncdMutation.SyncdOperation.SET
@@ -236,7 +236,7 @@ export const decodeSyncdMutations = async(
return ltGenerator.finish() return ltGenerator.finish()
async function getKey(keyId: Uint8Array) { async function getKey(keyId: Uint8Array) {
const base64Key = Buffer.from(keyId!).toString('base64') const base64Key = Buffer.from(keyId).toString('base64')
const keyEnc = await getAppStateSyncKey(base64Key) const keyEnc = await getAppStateSyncKey(base64Key)
if(!keyEnc) { if(!keyEnc) {
throw new Boom(`failed to find key "${base64Key}" to decode mutation`, { statusCode: 404, data: { msgMutations } }) throw new Boom(`failed to find key "${base64Key}" to decode mutation`, { statusCode: 404, data: { msgMutations } })
@@ -264,19 +264,19 @@ export const decodeSyncdPatch = async(
const mainKey = mutationKeys(mainKeyObj.keyData!) const mainKey = mutationKeys(mainKeyObj.keyData!)
const mutationmacs = msg.mutations!.map(mutation => mutation.record!.value!.blob!.slice(-32)) const mutationmacs = msg.mutations!.map(mutation => mutation.record!.value!.blob!.slice(-32))
const patchMac = generatePatchMac(msg.snapshotMac!, mutationmacs, toNumber(msg.version!.version!), name, mainKey.patchMacKey) const patchMac = generatePatchMac(msg.snapshotMac!, mutationmacs, toNumber(msg.version!.version), name, mainKey.patchMacKey)
if(Buffer.compare(patchMac, msg.patchMac!) !== 0) { if(Buffer.compare(patchMac, msg.patchMac!) !== 0) {
throw new Boom('Invalid patch mac') throw new Boom('Invalid patch mac')
} }
} }
const result = await decodeSyncdMutations(msg!.mutations!, initialState, getAppStateSyncKey, onMutation, validateMacs) const result = await decodeSyncdMutations(msg.mutations!, initialState, getAppStateSyncKey, onMutation, validateMacs)
return result return result
} }
export const extractSyncdPatches = async( export const extractSyncdPatches = async(
result: BinaryNode, result: BinaryNode,
options: AxiosRequestConfig<any> options: AxiosRequestConfig<{}>
) => { ) => {
const syncNode = getBinaryNodeChild(result, 'sync') const syncNode = getBinaryNodeChild(result, 'sync')
const collectionNodes = getBinaryNodeChildren(syncNode, 'collection') const collectionNodes = getBinaryNodeChildren(syncNode, 'collection')
@@ -302,7 +302,7 @@ export const extractSyncdPatches = async(
} }
const blobRef = proto.ExternalBlobReference.decode( const blobRef = proto.ExternalBlobReference.decode(
snapshotNode.content! as Buffer snapshotNode.content as Buffer
) )
const data = await downloadExternalBlob(blobRef, options) const data = await downloadExternalBlob(blobRef, options)
snapshot = proto.SyncdSnapshot.decode(data) snapshot = proto.SyncdSnapshot.decode(data)
@@ -314,7 +314,7 @@ export const extractSyncdPatches = async(
content = Buffer.from(Object.values(content)) content = Buffer.from(Object.values(content))
} }
const syncd = proto.SyncdPatch.decode(content! as Uint8Array) const syncd = proto.SyncdPatch.decode(content as Uint8Array)
if(!syncd.version) { if(!syncd.version) {
syncd.version = { version: +collectionNode.attrs.version + 1 } syncd.version = { version: +collectionNode.attrs.version + 1 }
} }
@@ -334,7 +334,7 @@ export const extractSyncdPatches = async(
export const downloadExternalBlob = async( export const downloadExternalBlob = async(
blob: proto.IExternalBlobReference, blob: proto.IExternalBlobReference,
options: AxiosRequestConfig<any> options: AxiosRequestConfig<{}>
) => { ) => {
const stream = await downloadContentFromMessage(blob, 'md-app-state', { options }) const stream = await downloadContentFromMessage(blob, 'md-app-state', { options })
const bufferArray: Buffer[] = [] const bufferArray: Buffer[] = []
@@ -347,7 +347,7 @@ export const downloadExternalBlob = async(
export const downloadExternalPatch = async( export const downloadExternalPatch = async(
blob: proto.IExternalBlobReference, blob: proto.IExternalBlobReference,
options: AxiosRequestConfig<any> options: AxiosRequestConfig<{}>
) => { ) => {
const buffer = await downloadExternalBlob(blob, options) const buffer = await downloadExternalBlob(blob, options)
const syncData = proto.SyncdMutations.decode(buffer) const syncData = proto.SyncdMutations.decode(buffer)
@@ -359,10 +359,10 @@ export const decodeSyncdSnapshot = async(
snapshot: proto.ISyncdSnapshot, snapshot: proto.ISyncdSnapshot,
getAppStateSyncKey: FetchAppStateSyncKey, getAppStateSyncKey: FetchAppStateSyncKey,
minimumVersionNumber: number | undefined, minimumVersionNumber: number | undefined,
validateMacs: boolean = true validateMacs = true
) => { ) => {
const newState = newLTHashState() const newState = newLTHashState()
newState.version = toNumber(snapshot.version!.version!) newState.version = toNumber(snapshot.version!.version)
const mutationMap: ChatMutationMap = {} const mutationMap: ChatMutationMap = {}
const areMutationsRequired = typeof minimumVersionNumber === 'undefined' const areMutationsRequired = typeof minimumVersionNumber === 'undefined'
@@ -408,10 +408,10 @@ export const decodePatches = async(
syncds: proto.ISyncdPatch[], syncds: proto.ISyncdPatch[],
initial: LTHashState, initial: LTHashState,
getAppStateSyncKey: FetchAppStateSyncKey, getAppStateSyncKey: FetchAppStateSyncKey,
options: AxiosRequestConfig<any>, options: AxiosRequestConfig<{}>,
minimumVersionNumber?: number, minimumVersionNumber?: number,
logger?: Logger, logger?: Logger,
validateMacs: boolean = true validateMacs = true
) => { ) => {
const newState: LTHashState = { const newState: LTHashState = {
...initial, ...initial,
@@ -420,8 +420,7 @@ export const decodePatches = async(
const mutationMap: ChatMutationMap = {} const mutationMap: ChatMutationMap = {}
for(let i = 0; i < syncds.length; i++) { for(const syncd of syncds) {
const syncd = syncds[i]
const { version, keyId, snapshotMac } = syncd const { version, keyId, snapshotMac } = syncd
if(syncd.externalMutations) { if(syncd.externalMutations) {
logger?.trace({ name, version }, 'downloading external patch') logger?.trace({ name, version }, 'downloading external patch')
@@ -430,7 +429,7 @@ export const decodePatches = async(
syncd.mutations?.push(...ref.mutations) syncd.mutations?.push(...ref.mutations)
} }
const patchVersion = toNumber(version!.version!) const patchVersion = toNumber(version!.version)
newState.version = patchVersion newState.version = patchVersion
const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber const shouldMutate = typeof minimumVersionNumber === 'undefined' || patchVersion > minimumVersionNumber
@@ -736,7 +735,7 @@ export const processSyncAction = (
{ {
id, id,
muteEndTime: action.muteAction?.muted muteEndTime: action.muteAction?.muted
? toNumber(action.muteAction!.muteEndTimestamp!) ? toNumber(action.muteAction.muteEndTimestamp)
: null, : null,
conditional: getChatUpdateConditional(id, undefined) conditional: getChatUpdateConditional(id, undefined)
} }
@@ -794,7 +793,7 @@ export const processSyncAction = (
] ]
}) })
} else if(action?.contactAction) { } else if(action?.contactAction) {
ev.emit('contacts.upsert', [{ id, name: action.contactAction!.fullName! }]) ev.emit('contacts.upsert', [{ id, name: action.contactAction.fullName! }])
} else if(action?.pushNameSetting) { } else if(action?.pushNameSetting) {
const name = action?.pushNameSetting?.name const name = action?.pushNameSetting?.name
if(name && me?.name !== name) { if(name && me?.name !== name) {
@@ -803,7 +802,7 @@ export const processSyncAction = (
} else if(action?.pinAction) { } else if(action?.pinAction) {
ev.emit('chats.update', [{ ev.emit('chats.update', [{
id, id,
pinned: action.pinAction?.pinned ? toNumber(action.timestamp!) : null, pinned: action.pinAction?.pinned ? toNumber(action.timestamp) : null,
conditional: getChatUpdateConditional(id, undefined) conditional: getChatUpdateConditional(id, undefined)
}]) }])
} else if(action?.unarchiveChatsSetting) { } else if(action?.unarchiveChatsSetting) {
@@ -831,7 +830,7 @@ export const processSyncAction = (
ev.emit('chats.delete', [id]) ev.emit('chats.delete', [id])
} }
} else if(action?.labelEditAction) { } else if(action?.labelEditAction) {
const { name, color, deleted, predefinedId } = action.labelEditAction! const { name, color, deleted, predefinedId } = action.labelEditAction
ev.emit('labels.edit', { ev.emit('labels.edit', {
id, id,

View File

@@ -177,6 +177,7 @@ export const decryptMessageNode = (
let msg: proto.IMessage = proto.Message.decode(e2eType !== 'plaintext' ? unpadRandomMax16(msgBuffer) : msgBuffer) let msg: proto.IMessage = proto.Message.decode(e2eType !== 'plaintext' ? unpadRandomMax16(msgBuffer) : msgBuffer)
msg = msg.deviceSentMessage?.message || msg msg = msg.deviceSentMessage?.message || msg
if(msg.senderKeyDistributionMessage) { if(msg.senderKeyDistributionMessage) {
//eslint-disable-next-line max-depth
try { try {
await repository.processSenderKeyDistributionMessage({ await repository.processSenderKeyDistributionMessage({
authorJid: author, authorJid: author,

View File

@@ -42,6 +42,7 @@ type BaileysBufferableEventEmitter = BaileysEventEmitter & {
* */ * */
buffer(): void buffer(): void
/** buffers all events till the promise completes */ /** buffers all events till the promise completes */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createBufferedFunction<A extends any[], T>(work: (...args: A) => Promise<T>): ((...args: A) => Promise<T>) createBufferedFunction<A extends any[], T>(work: (...args: A) => Promise<T>): ((...args: A) => Promise<T>)
/** /**
* flushes all buffered events * flushes all buffered events
@@ -132,7 +133,7 @@ export const makeEventBuffer = (logger: Logger): BaileysBufferableEventEmitter =
}, },
emit<T extends BaileysEvent>(event: BaileysEvent, evData: BaileysEventMap[T]) { emit<T extends BaileysEvent>(event: BaileysEvent, evData: BaileysEventMap[T]) {
if(buffersInProgress && BUFFERABLE_EVENT_SET.has(event)) { if(buffersInProgress && BUFFERABLE_EVENT_SET.has(event)) {
append(data, historyCache, event as any, evData, logger) append(data, historyCache, event as BufferableEvent, evData, logger)
return true return true
} }
@@ -187,6 +188,7 @@ function append<E extends BufferableEvent>(
data: BufferedEventData, data: BufferedEventData,
historyCache: Set<string>, historyCache: Set<string>,
event: E, event: E,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
eventData: any, eventData: any,
logger: Logger logger: Logger
) { ) {
@@ -331,7 +333,7 @@ function append<E extends BufferableEvent>(
} }
if(data.contactUpdates[contact.id]) { if(data.contactUpdates[contact.id]) {
upsert = Object.assign(data.contactUpdates[contact.id], trimUndefined(contact)) upsert = Object.assign(data.contactUpdates[contact.id], trimUndefined(contact)) as Contact
delete data.contactUpdates[contact.id] delete data.contactUpdates[contact.id]
} }
} }
@@ -598,12 +600,10 @@ function consolidateEvents(data: BufferedEventData) {
} }
function concatChats<C extends Partial<Chat>>(a: C, b: Partial<Chat>) { function concatChats<C extends Partial<Chat>>(a: C, b: Partial<Chat>) {
if(b.unreadCount === null) { if(b.unreadCount === null && // neutralize unread counter
// neutralize unread counter a.unreadCount! < 0) {
if(a.unreadCount! < 0) { a.unreadCount = undefined
a.unreadCount = undefined b.unreadCount = undefined
b.unreadCount = undefined
}
} }
if(typeof a.unreadCount === 'number' && typeof b.unreadCount === 'number') { if(typeof a.unreadCount === 'number' && typeof b.unreadCount === 'number') {

View File

@@ -5,7 +5,7 @@ import { platform, release } from 'os'
import { Logger } from 'pino' import { Logger } from 'pino'
import { proto } from '../../WAProto' import { proto } from '../../WAProto'
import { version as baileysVersion } from '../Defaults/baileys-version.json' import { version as baileysVersion } from '../Defaults/baileys-version.json'
import { BaileysEventEmitter, BaileysEventMap, BrowsersMap, DisconnectReason, WACallUpdateType, WAVersion } from '../Types' import { BaileysEventEmitter, BaileysEventMap, BrowsersMap, ConnectionState, DisconnectReason, WACallUpdateType, WAVersion } from '../Types'
import { BinaryNode, getAllBinaryNodeChildren, jidDecode } from '../WABinary' import { BinaryNode, getAllBinaryNodeChildren, jidDecode } from '../WABinary'
const PLATFORM_MAP = { const PLATFORM_MAP = {
@@ -33,6 +33,7 @@ export const getPlatformId = (browser: string) => {
} }
export const BufferJSON = { export const BufferJSON = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
replacer: (k, value: any) => { replacer: (k, value: any) => {
if(Buffer.isBuffer(value) || value instanceof Uint8Array || value?.type === 'Buffer') { if(Buffer.isBuffer(value) || value instanceof Uint8Array || value?.type === 'Buffer') {
return { type: 'Buffer', data: Buffer.from(value?.data || value).toString('base64') } return { type: 'Buffer', data: Buffer.from(value?.data || value).toString('base64') }
@@ -40,6 +41,8 @@ export const BufferJSON = {
return value return value
}, },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
reviver: (_, value: any) => { reviver: (_, value: any) => {
if(typeof value === 'object' && !!value && (value.buffer === true || value.type === 'Buffer')) { if(typeof value === 'object' && !!value && (value.buffer === true || value.type === 'Buffer')) {
const val = value.data || value.value const val = value.data || value.value
@@ -52,7 +55,7 @@ export const BufferJSON = {
export const getKeyAuthor = ( export const getKeyAuthor = (
key: proto.IMessageKey | undefined | null, key: proto.IMessageKey | undefined | null,
meId: string = 'me' meId = 'me'
) => ( ) => (
(key?.fromMe ? meId : key?.participant || key?.remoteJid) || '' (key?.fromMe ? meId : key?.participant || key?.remoteJid) || ''
) )
@@ -102,14 +105,14 @@ export const encodeBigEndian = (e: number, t = 4) => {
return a return a
} }
export const toNumber = (t: Long | number | null | undefined): number => ((typeof t === 'object' && t) ? ('toNumber' in t ? t.toNumber() : (t as any).low) : t) export const toNumber = (t: Long | number | null | undefined): number => ((typeof t === 'object' && t) ? ('toNumber' in t ? t.toNumber() : (t as Long).low) : t || 0)
/** unix timestamp of a date in seconds */ /** unix timestamp of a date in seconds */
export const unixTimestampSeconds = (date: Date = new Date()) => Math.floor(date.getTime() / 1000) export const unixTimestampSeconds = (date: Date = new Date()) => Math.floor(date.getTime() / 1000)
export type DebouncedTimeout = ReturnType<typeof debouncedTimeout> export type DebouncedTimeout = ReturnType<typeof debouncedTimeout>
export const debouncedTimeout = (intervalMs: number = 1000, task?: () => void) => { export const debouncedTimeout = (intervalMs = 1000, task?: () => void) => {
let timeout: NodeJS.Timeout | undefined let timeout: NodeJS.Timeout | undefined
return { return {
start: (newIntervalMs?: number, newTask?: () => void) => { start: (newIntervalMs?: number, newTask?: () => void) => {
@@ -184,9 +187,9 @@ export const generateMessageIDV2 = (userId?: string): string => {
const data = Buffer.alloc(8 + 20 + 16) const data = Buffer.alloc(8 + 20 + 16)
data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000))) data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)))
if (userId) { if(userId) {
const id = jidDecode(userId) const id = jidDecode(userId)
if (id?.user) { if(id?.user) {
data.write(id.user, 8) data.write(id.user, 8)
data.write('@c.us', 8 + id.user.length) data.write('@c.us', 8 + id.user.length)
} }
@@ -205,7 +208,7 @@ export const generateMessageID = () => '3EB0' + randomBytes(18).toString('hex').
export function bindWaitForEvent<T extends keyof BaileysEventMap>(ev: BaileysEventEmitter, event: T) { export function bindWaitForEvent<T extends keyof BaileysEventMap>(ev: BaileysEventEmitter, event: T) {
return async(check: (u: BaileysEventMap[T]) => boolean | undefined, timeoutMs?: number) => { return async(check: (u: BaileysEventMap[T]) => boolean | undefined, timeoutMs?: number) => {
let listener: (item: BaileysEventMap[T]) => void let listener: (item: BaileysEventMap[T]) => void
let closeListener: any let closeListener: (state: Partial<ConnectionState>) => void
await ( await (
promiseTimeout<void>( promiseTimeout<void>(
timeoutMs, timeoutMs,
@@ -256,7 +259,7 @@ export const printQRIfNecessaryListener = (ev: BaileysEventEmitter, logger: Logg
* utility that fetches latest baileys version from the master branch. * utility that fetches latest baileys version from the master branch.
* Use to ensure your WA connection is always on the latest version * Use to ensure your WA connection is always on the latest version
*/ */
export const fetchLatestBaileysVersion = async(options: AxiosRequestConfig<any> = { }) => { export const fetchLatestBaileysVersion = async(options: AxiosRequestConfig<{}> = { }) => {
const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/baileys-version.json' const URL = 'https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/baileys-version.json'
try { try {
const result = await axios.get<{ version: WAVersion }>( const result = await axios.get<{ version: WAVersion }>(
@@ -283,7 +286,7 @@ export const fetchLatestBaileysVersion = async(options: AxiosRequestConfig<any>
* A utility that fetches the latest web version of whatsapp. * A utility that fetches the latest web version of whatsapp.
* Use to ensure your WA connection is always on the latest version * Use to ensure your WA connection is always on the latest version
*/ */
export const fetchLatestWaWebVersion = async(options: AxiosRequestConfig<any>) => { export const fetchLatestWaWebVersion = async(options: AxiosRequestConfig<{}>) => {
try { try {
const result = await axios.get( const result = await axios.get(
'https://web.whatsapp.com/check-update?version=1&platform=web', 'https://web.whatsapp.com/check-update?version=1&platform=web',
@@ -393,6 +396,7 @@ export const getCodeFromWSError = (error: Error) => {
statusCode = code statusCode = code
} }
} else if( } else if(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(error as any)?.code?.startsWith('E') (error as any)?.code?.startsWith('E')
|| error?.message?.includes('timed out') || error?.message?.includes('timed out')
) { // handle ETIMEOUT, ENOTFOUND etc ) { // handle ETIMEOUT, ENOTFOUND etc
@@ -410,7 +414,8 @@ export const isWABusinessPlatform = (platform: string) => {
return platform === 'smbi' || platform === 'smba' return platform === 'smbi' || platform === 'smba'
} }
export function trimUndefined(obj: any) { // eslint-disable-next-line @typescript-eslint/no-explicit-any
export function trimUndefined(obj: {[_: string]: any}) {
for(const key in obj) { for(const key in obj) {
if(typeof obj[key] === 'undefined') { if(typeof obj[key] === 'undefined') {
delete obj[key] delete obj[key]
@@ -427,8 +432,8 @@ export function bytesToCrockford(buffer: Buffer): string {
let bitCount = 0 let bitCount = 0
const crockford: string[] = [] const crockford: string[] = []
for(let i = 0; i < buffer.length; i++) { for(const element of buffer) {
value = (value << 8) | (buffer[i] & 0xff) value = (value << 8) | (element & 0xff)
bitCount += 8 bitCount += 8
while(bitCount >= 5) { while(bitCount >= 5) {

View File

@@ -12,7 +12,7 @@ const inflatePromise = promisify(inflate)
export const downloadHistory = async( export const downloadHistory = async(
msg: proto.Message.IHistorySyncNotification, msg: proto.Message.IHistorySyncNotification,
options: AxiosRequestConfig<any> options: AxiosRequestConfig<{}>
) => { ) => {
const stream = await downloadContentFromMessage(msg, 'md-msg-hist', { options }) const stream = await downloadContentFromMessage(msg, 'md-msg-hist', { options })
const bufferArray: Buffer[] = [] const bufferArray: Buffer[] = []
@@ -101,7 +101,7 @@ export const processHistoryMessage = (item: proto.IHistorySync) => {
export const downloadAndProcessHistorySyncNotification = async( export const downloadAndProcessHistorySyncNotification = async(
msg: proto.Message.IHistorySyncNotification, msg: proto.Message.IHistorySyncNotification,
options: AxiosRequestConfig<any> options: AxiosRequestConfig<{}>
) => { ) => {
const historyMsg = await downloadHistory(msg, options) const historyMsg = await downloadHistory(msg, options)
return processHistoryMessage(historyMsg) return processHistoryMessage(historyMsg)

View File

@@ -1,4 +1,5 @@
export const makeMutex = () => { export const makeMutex = () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let task = Promise.resolve() as Promise<any> let task = Promise.resolve() as Promise<any>
let taskTimeout: NodeJS.Timeout | undefined let taskTimeout: NodeJS.Timeout | undefined

View File

@@ -12,7 +12,7 @@ import { Readable, Transform } from 'stream'
import { URL } from 'url' import { URL } from 'url'
import { proto } from '../../WAProto' import { proto } from '../../WAProto'
import { DEFAULT_ORIGIN, MEDIA_HKDF_KEY_MAPPING, MEDIA_PATH_MAP } from '../Defaults' import { DEFAULT_ORIGIN, MEDIA_HKDF_KEY_MAPPING, MEDIA_PATH_MAP } from '../Defaults'
import { BaileysEventMap, DownloadableMessage, MediaConnInfo, MediaDecryptionKeyInfo, MediaType, MessageType, SocketConfig, WAGenericMediaMessage, WAMediaUpload, WAMediaUploadFunction, WAMessageContent } from '../Types' import { BaileysEventMap, DownloadableMessage, MediaConnInfo, MediaDecryptionKeyInfo, MediaType, MessageType, SocketConfig, WAGenericMediaMessage, WAMediaPayloadURL, WAMediaUpload, WAMediaUploadFunction, WAMessageContent } from '../Types'
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildBuffer, jidNormalizedUser } from '../WABinary' import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildBuffer, jidNormalizedUser } from '../WABinary'
import { aesDecryptGCM, aesEncryptGCM, hkdf } from './crypto' import { aesDecryptGCM, aesEncryptGCM, hkdf } from './crypto'
import { generateMessageID } from './generics' import { generateMessageID } from './generics'
@@ -79,7 +79,7 @@ const extractVideoThumb = async(
destPath: string, destPath: string,
time: string, time: string,
size: { width: number, height: number }, size: { width: number, height: number },
) => new Promise((resolve, reject) => { ) => new Promise<void>((resolve, reject) => {
const cmd = `ffmpeg -ss ${time} -i ${path} -y -vf scale=${size.width}:-1 -vframes 1 -f image2 ${destPath}` const cmd = `ffmpeg -ss ${time} -i ${path} -y -vf scale=${size.width}:-1 -vframes 1 -f image2 ${destPath}`
exec(cmd, (err) => { exec(cmd, (err) => {
if(err) { if(err) {
@@ -88,7 +88,7 @@ const extractVideoThumb = async(
resolve() resolve()
} }
}) })
}) as Promise<void> })
export const extractImageThumb = async(bufferOrFilePath: Readable | Buffer | string, width = 32) => { export const extractImageThumb = async(bufferOrFilePath: Readable | Buffer | string, width = 32) => {
if(bufferOrFilePath instanceof Readable) { if(bufferOrFilePath instanceof Readable) {
@@ -97,7 +97,7 @@ export const extractImageThumb = async(bufferOrFilePath: Readable | Buffer | str
const lib = await getImageProcessingLibrary() const lib = await getImageProcessingLibrary()
if('sharp' in lib && typeof lib.sharp?.default === 'function') { if('sharp' in lib && typeof lib.sharp?.default === 'function') {
const img = lib.sharp!.default(bufferOrFilePath) const img = lib.sharp.default(bufferOrFilePath)
const dimensions = await img.metadata() const dimensions = await img.metadata()
const buffer = await img const buffer = await img
@@ -114,7 +114,7 @@ export const extractImageThumb = async(bufferOrFilePath: Readable | Buffer | str
} else if('jimp' in lib && typeof lib.jimp?.read === 'function') { } else if('jimp' in lib && typeof lib.jimp?.read === 'function') {
const { read, MIME_JPEG, RESIZE_BILINEAR, AUTO } = lib.jimp const { read, MIME_JPEG, RESIZE_BILINEAR, AUTO } = lib.jimp
const jimp = await read(bufferOrFilePath as any) const jimp = await read(bufferOrFilePath as string)
const dimensions = { const dimensions = {
width: jimp.getWidth(), width: jimp.getWidth(),
height: jimp.getHeight() height: jimp.getHeight()
@@ -154,7 +154,7 @@ export const generateProfilePicture = async(mediaUpload: WAMediaUpload) => {
const lib = await getImageProcessingLibrary() const lib = await getImageProcessingLibrary()
let img: Promise<Buffer> let img: Promise<Buffer>
if('sharp' in lib && typeof lib.sharp?.default === 'function') { if('sharp' in lib && typeof lib.sharp?.default === 'function') {
img = lib.sharp!.default(bufferOrFilePath) img = lib.sharp.default(bufferOrFilePath)
.resize(640, 640) .resize(640, 640)
.jpeg({ .jpeg({
quality: 50, quality: 50,
@@ -162,7 +162,7 @@ export const generateProfilePicture = async(mediaUpload: WAMediaUpload) => {
.toBuffer() .toBuffer()
} else if('jimp' in lib && typeof lib.jimp?.read === 'function') { } else if('jimp' in lib && typeof lib.jimp?.read === 'function') {
const { read, MIME_JPEG, RESIZE_BILINEAR } = lib.jimp const { read, MIME_JPEG, RESIZE_BILINEAR } = lib.jimp
const jimp = await read(bufferOrFilePath as any) const jimp = await read(bufferOrFilePath as string)
const min = Math.min(jimp.getWidth(), jimp.getHeight()) const min = Math.min(jimp.getWidth(), jimp.getHeight())
const cropped = jimp.crop(0, 0, min, min) const cropped = jimp.crop(0, 0, min, min)
@@ -351,7 +351,7 @@ export const encryptedStream = async(
let writeStream: WriteStream | undefined let writeStream: WriteStream | undefined
let didSaveToTmpPath = false let didSaveToTmpPath = false
if(type === 'file') { if(type === 'file') {
bodyPath = (media as any).url bodyPath = (media as WAMediaPayloadURL).url.toString()
} else if(saveOriginalFileIfRequired) { } else if(saveOriginalFileIfRequired) {
bodyPath = join(getTmpFilesDirectory(), mediaType + generateMessageID()) bodyPath = join(getTmpFilesDirectory(), mediaType + generateMessageID())
writeStream = createWriteStream(bodyPath) writeStream = createWriteStream(bodyPath)
@@ -382,10 +382,8 @@ export const encryptedStream = async(
} }
sha256Plain = sha256Plain.update(data) sha256Plain = sha256Plain.update(data)
if(writeStream) { if(writeStream && !writeStream.write(data)) {
if(!writeStream.write(data)) { await once(writeStream, 'drain')
await once(writeStream, 'drain')
}
} }
onChunk(aes.update(data)) onChunk(aes.update(data))
@@ -455,7 +453,7 @@ const toSmallestChunkSize = (num: number) => {
export type MediaDownloadOptions = { export type MediaDownloadOptions = {
startByte?: number startByte?: number
endByte?: number endByte?: number
options?: AxiosRequestConfig<any> options?: AxiosRequestConfig<{}>
} }
export const getUrlFromDirectPath = (directPath: string) => `https://${DEF_HOST}${directPath}` export const getUrlFromDirectPath = (directPath: string) => `https://${DEF_HOST}${directPath}`
@@ -501,9 +499,9 @@ export const downloadEncryptedContent = async(
Origin: DEFAULT_ORIGIN, Origin: DEFAULT_ORIGIN,
} }
if(startChunk || endChunk) { if(startChunk || endChunk) {
headers!.Range = `bytes=${startChunk}-` headers.Range = `bytes=${startChunk}-`
if(endChunk) { if(endChunk) {
headers!.Range += endChunk headers.Range += endChunk
} }
} }
@@ -614,6 +612,7 @@ export const getWAUploadToServer = (
const auth = encodeURIComponent(uploadInfo.auth) // the auth token const auth = encodeURIComponent(uploadInfo.auth) // the auth token
const url = `https://${hostname}${MEDIA_PATH_MAP[mediaType]}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}` const url = `https://${hostname}${MEDIA_PATH_MAP[mediaType]}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let result: any let result: any
try { try {
@@ -770,9 +769,4 @@ const MEDIA_RETRY_STATUS_MAP = {
[proto.MediaRetryNotification.ResultType.DECRYPTION_ERROR]: 412, [proto.MediaRetryNotification.ResultType.DECRYPTION_ERROR]: 412,
[proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404, [proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
[proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418, [proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418,
} as const } as const
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function __importStar(arg0: any): any {
throw new Error('Function not implemented.')
}

View File

@@ -488,7 +488,7 @@ export const generateWAMessageContent = async(
options: message.poll.values.map(optionName => ({ optionName })), options: message.poll.values.map(optionName => ({ optionName })),
} }
if (message.poll.toAnnouncementGroup) { if(message.poll.toAnnouncementGroup) {
// poll v2 is for community announcement groups (single select and multiple) // poll v2 is for community announcement groups (single select and multiple)
m.pollCreationMessageV2 = pollCreationMessage m.pollCreationMessageV2 = pollCreationMessage
} else { } else {
@@ -859,17 +859,13 @@ export const downloadMediaMessage = async<Type extends 'buffer' | 'stream'>(
) => { ) => {
const result = await downloadMsg() const result = await downloadMsg()
.catch(async(error) => { .catch(async(error) => {
if(ctx) { if(ctx && axios.isAxiosError(error) && // check if the message requires a reupload
if(axios.isAxiosError(error)) { REUPLOAD_REQUIRED_STATUS.includes(error.response?.status!)) {
// check if the message requires a reupload ctx.logger.info({ key: message.key }, 'sending reupload media request...')
if(REUPLOAD_REQUIRED_STATUS.includes(error.response?.status!)) { // request reupload
ctx.logger.info({ key: message.key }, 'sending reupload media request...') message = await ctx.reuploadRequest(message)
// request reupload const result = await downloadMsg()
message = await ctx.reuploadRequest(message) return result
const result = await downloadMsg()
return result
}
}
} }
throw error throw error

View File

@@ -283,6 +283,7 @@ const processMessage = async(
const { peerDataOperationResult } = response const { peerDataOperationResult } = response
for(const result of peerDataOperationResult!) { for(const result of peerDataOperationResult!) {
const { placeholderMessageResendResponse: retryResponse } = result const { placeholderMessageResendResponse: retryResponse } = result
//eslint-disable-next-line max-depth
if(retryResponse) { if(retryResponse) {
const webMessageInfo = proto.WebMessageInfo.decode(retryResponse.webMessageInfoBytes!) const webMessageInfo = proto.WebMessageInfo.decode(retryResponse.webMessageInfoBytes!)
// wait till another upsert event is available, don't want it to be part of the PDO response message // wait till another upsert event is available, don't want it to be part of the PDO response message

View File

@@ -73,7 +73,7 @@ export const parseAndInjectE2ESessions = async(
const extractKey = (key: BinaryNode) => ( const extractKey = (key: BinaryNode) => (
key ? ({ key ? ({
keyId: getBinaryNodeChildUInt(key, 'id', 3)!, keyId: getBinaryNodeChildUInt(key, 'id', 3)!,
publicKey: generateSignalPubKey(getBinaryNodeChildBuffer(key, 'value')!)!, publicKey: generateSignalPubKey(getBinaryNodeChildBuffer(key, 'value')!),
signature: getBinaryNodeChildBuffer(key, 'signature')!, signature: getBinaryNodeChildBuffer(key, 'signature')!,
}) : undefined }) : undefined
) )
@@ -125,8 +125,10 @@ export const extractDeviceJids = (result: BinaryNode, myJid: string, excludeZero
const devicesNode = getBinaryNodeChild(item, 'devices') const devicesNode = getBinaryNodeChild(item, 'devices')
const deviceListNode = getBinaryNodeChild(devicesNode, 'device-list') const deviceListNode = getBinaryNodeChild(devicesNode, 'device-list')
if(Array.isArray(deviceListNode?.content)) { if(Array.isArray(deviceListNode?.content)) {
//eslint-disable-next-line max-depth
for(const { tag, attrs } of deviceListNode!.content) { for(const { tag, attrs } of deviceListNode!.content) {
const device = +attrs.id const device = +attrs.id
//eslint-disable-next-line max-depth
if( if(
tag === 'device' && // ensure the "device" tag tag === 'device' && // ensure the "device" tag
(!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero (!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero

View File

@@ -21,7 +21,7 @@ const fileLock = new AsyncLock({ maxPending: Infinity })
* Would recommend writing an auth state for use with a proper SQL or No-SQL DB * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
* */ * */
export const useMultiFileAuthState = async(folder: string): Promise<{ state: AuthenticationState, saveCreds: () => Promise<void> }> => { export const useMultiFileAuthState = async(folder: string): Promise<{ state: AuthenticationState, saveCreds: () => Promise<void> }> => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const writeData = (data: any, file: string) => { const writeData = (data: any, file: string) => {
const filePath = join(folder, fixFileName(file)!) const filePath = join(folder, fixFileName(file)!)
return fileLock.acquire( return fileLock.acquire(

View File

@@ -31,12 +31,12 @@ export const SINGLE_BYTE_TOKENS: (string | null)[] = [
export const TOKEN_MAP: { [token: string]: { dict?: number, index: number } } = { } export const TOKEN_MAP: { [token: string]: { dict?: number, index: number } } = { }
for(let i = 0;i < SINGLE_BYTE_TOKENS.length;i++) { for(const [i, SINGLE_BYTE_TOKEN] of SINGLE_BYTE_TOKENS.entries()) {
TOKEN_MAP[SINGLE_BYTE_TOKENS[i]!] = { index: i } TOKEN_MAP[SINGLE_BYTE_TOKEN!] = { index: i }
} }
for(let i = 0;i < DOUBLE_BYTE_TOKENS.length;i++) { for(const [i, DOUBLE_BYTE_TOKEN] of DOUBLE_BYTE_TOKENS.entries()) {
for(let j = 0;j < DOUBLE_BYTE_TOKENS[i].length;j++) { for(const [j, element] of DOUBLE_BYTE_TOKEN.entries()) {
TOKEN_MAP[DOUBLE_BYTE_TOKENS[i][j]] = { dict: i, index: j } TOKEN_MAP[element] = { dict: i, index: j }
} }
} }

View File

@@ -28,9 +28,12 @@ const encodeBinaryNodeInner = (
} }
} }
const pushBytes = (bytes: Uint8Array | Buffer | number[]) => ( const pushBytes = (bytes: Uint8Array | Buffer | number[]) => {
bytes.forEach (b => buffer.push(b)) for(const b of bytes) {
) buffer.push(b)
}
}
const pushInt16 = (value: number) => { const pushInt16 = (value: number) => {
pushBytes([(value >> 8) & 0xff, value & 0xff]) pushBytes([(value >> 8) & 0xff, value & 0xff])
} }
@@ -151,8 +154,7 @@ const encodeBinaryNodeInner = (
return false return false
} }
for(let i = 0;i < str.length;i++) { for(const char of str) {
const char = str[i]
const isInNibbleRange = char >= '0' && char <= '9' const isInNibbleRange = char >= '0' && char <= '9'
if(!isInNibbleRange && char !== '-' && char !== '.') { if(!isInNibbleRange && char !== '-' && char !== '.') {
return false return false
@@ -167,8 +169,7 @@ const encodeBinaryNodeInner = (
return false return false
} }
for(let i = 0;i < str.length;i++) { for(const char of str) {
const char = str[i]
const isInNibbleRange = char >= '0' && char <= '9' const isInNibbleRange = char >= '0' && char <= '9'
if(!isInNibbleRange && !(char >= 'A' && char <= 'F') && !(char >= 'a' && char <= 'f')) { if(!isInNibbleRange && !(char >= 'A' && char <= 'F') && !(char >= 'a' && char <= 'f')) {
return false return false

View File

@@ -4,7 +4,7 @@ export const SERVER_JID = 'server@c.us'
export const PSA_WID = '0@c.us' export const PSA_WID = '0@c.us'
export const STORIES_JID = 'status@broadcast' export const STORIES_JID = 'status@broadcast'
export type JidServer = 'c.us' | 'g.us' | 'broadcast' | 's.whatsapp.net' | 'call' | 'lid' export type JidServer = 'c.us' | 'g.us' | 'broadcast' | 's.whatsapp.net' | 'call' | 'lid' | 'newsletter'
export type JidWithDevice = { export type JidWithDevice = {
user: string user: string
@@ -12,7 +12,7 @@ export type JidWithDevice = {
} }
export type FullJid = JidWithDevice & { export type FullJid = JidWithDevice & {
server: JidServer | string server: JidServer
domainType?: number domainType?: number
} }
@@ -33,7 +33,7 @@ export const jidDecode = (jid: string | undefined): FullJid | undefined => {
const user = userAgent.split('_')[0] const user = userAgent.split('_')[0]
return { return {
server, server: server as JidServer,
user, user,
domainType: server === 'lid' ? 1 : 0, domainType: server === 'lid' ? 1 : 0,
device: device ? +device : undefined device: device ? +device : undefined

View File

@@ -15375,8 +15375,10 @@ export type EventInputType = {
[key in Event['name']]: { [key in Event['name']]: {
props: { props: {
// @ts-ignore // @ts-ignore
[k in keyof EventByName<key>['props']]: any [k in keyof EventByName<key>['props']]: Value
} }
globals: { [x: string]: any } globals: { [x: string]: Value }
} }
} & {} } & {}
export type Value = number | null | string

View File

@@ -1,9 +1,7 @@
import { BinaryInfo } from './BinaryInfo' import { BinaryInfo } from './BinaryInfo'
import { FLAG_BYTE, FLAG_EVENT, FLAG_EXTENDED, FLAG_FIELD, FLAG_GLOBAL, WEB_EVENTS, WEB_GLOBALS } from './constants' import { FLAG_BYTE, FLAG_EVENT, FLAG_EXTENDED, FLAG_FIELD, FLAG_GLOBAL, Value, WEB_EVENTS, WEB_GLOBALS } from './constants'
const getHeaderBitLength = (key: number) => (key < 256 ? 2 : 3) const getHeaderBitLength = (key: number) => (key < 256 ? 2 : 3)
type Value = number | null | string
export const encodeWAM = (binaryInfo: BinaryInfo) => { export const encodeWAM = (binaryInfo: BinaryInfo) => {
binaryInfo.buffer = [] binaryInfo.buffer = []
@@ -17,10 +15,10 @@ export const encodeWAM = (binaryInfo: BinaryInfo) => {
.reduce((a, b) => a + b) .reduce((a, b) => a + b)
const buffer = Buffer.alloc(totalSize) const buffer = Buffer.alloc(totalSize)
let offset = 0 let offset = 0
binaryInfo.buffer.forEach((buffer_) => { for(const buffer_ of binaryInfo.buffer) {
buffer_.copy(buffer, offset) buffer_.copy(buffer, offset)
offset += buffer_.length offset += buffer_.length
}) }
return buffer return buffer
} }
@@ -77,7 +75,7 @@ function encodeEvents(binaryInfo: BinaryInfo) {
} }
const fieldFlag = extended ? FLAG_EVENT : FLAG_FIELD | FLAG_EXTENDED const fieldFlag = extended ? FLAG_EVENT : FLAG_FIELD | FLAG_EXTENDED
binaryInfo.buffer.push(serializeData(id, value as Value, fieldFlag)) binaryInfo.buffer.push(serializeData(id, value, fieldFlag))
} }
} }
} }

1367
yarn.lock

File diff suppressed because it is too large Load Diff