mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Fix initial-data-received called multiple times
The latest android version has messages with the last: true flag set on all messages, causing incorrect events being fired off. This update creates a timeout that fires off the initial-data-received 2500ms after the last messages received. This may not be as accurate in production but will be better than the current version
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ lib
|
|||||||
docs
|
docs
|
||||||
browser-token.json
|
browser-token.json
|
||||||
Proxy
|
Proxy
|
||||||
|
messages*.json
|
||||||
@@ -25,6 +25,9 @@ async function example() {
|
|||||||
conn.on('contacts-received', () => {
|
conn.on('contacts-received', () => {
|
||||||
console.log(`you have ${Object.keys(conn.contacts).length} contacts`)
|
console.log(`you have ${Object.keys(conn.contacts).length} contacts`)
|
||||||
})
|
})
|
||||||
|
conn.on('initial-data-received', () => {
|
||||||
|
console.log('received all initial messages')
|
||||||
|
})
|
||||||
|
|
||||||
// loads the auth file credentials if present
|
// loads the auth file credentials if present
|
||||||
/* Note: one can take this auth_info.json file and login again from any computer without having to scan the QR code,
|
/* Note: one can take this auth_info.json file and login again from any computer without having to scan the QR code,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const logger = pino({ prettyPrint: { levelFirst: true, ignore: 'hostname', trans
|
|||||||
|
|
||||||
export class WAConnection extends EventEmitter {
|
export class WAConnection extends EventEmitter {
|
||||||
/** The version of WhatsApp Web we're telling the servers we are */
|
/** The version of WhatsApp Web we're telling the servers we are */
|
||||||
version: [number, number, number] = [2, 2047, 10]
|
version: [number, number, number] = [2, 2102, 9]
|
||||||
/** The Browser we're telling the WhatsApp Web servers we are */
|
/** The Browser we're telling the WhatsApp Web servers we are */
|
||||||
browserDescription: [string, string, string] = Utils.Browsers.baileys ('Chrome')
|
browserDescription: [string, string, string] = Utils.Browsers.baileys ('Chrome')
|
||||||
/** Metadata like WhatsApp id, name set on WhatsApp etc. */
|
/** Metadata like WhatsApp id, name set on WhatsApp etc. */
|
||||||
@@ -94,8 +94,11 @@ export class WAConnection extends EventEmitter {
|
|||||||
protected lastDisconnectReason: DisconnectReason
|
protected lastDisconnectReason: DisconnectReason
|
||||||
|
|
||||||
protected mediaConn: MediaConnInfo
|
protected mediaConn: MediaConnInfo
|
||||||
protected debounceTimeout: NodeJS.Timeout
|
protected connectionDebounceTimeout = Utils.debouncedTimeout(
|
||||||
|
1000,
|
||||||
|
() => this.endConnection(DisconnectReason.timedOut)
|
||||||
|
)
|
||||||
|
protected messagesDebounceTimeout = Utils.debouncedTimeout(2000)
|
||||||
/**
|
/**
|
||||||
* Connect to WhatsAppWeb
|
* Connect to WhatsAppWeb
|
||||||
* @param options the connect options
|
* @param options the connect options
|
||||||
@@ -247,7 +250,7 @@ export class WAConnection extends EventEmitter {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (startDebouncedTimeout) {
|
if (startDebouncedTimeout) {
|
||||||
this.startDebouncedTimeout()
|
this.connectionDebounceTimeout.start()
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -344,17 +347,6 @@ export class WAConnection extends EventEmitter {
|
|||||||
await this.send(buff) // send it off
|
await this.send(buff) // send it off
|
||||||
return tag
|
return tag
|
||||||
}
|
}
|
||||||
protected startDebouncedTimeout () {
|
|
||||||
this.stopDebouncedTimeout ()
|
|
||||||
this.debounceTimeout = setTimeout (
|
|
||||||
() => this.endConnection(DisconnectReason.timedOut),
|
|
||||||
this.connectOptions.maxIdleTimeMs
|
|
||||||
)
|
|
||||||
}
|
|
||||||
protected stopDebouncedTimeout () {
|
|
||||||
this.debounceTimeout && clearTimeout (this.debounceTimeout)
|
|
||||||
this.debounceTimeout = null
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Send a plain JSON message to the WhatsApp servers
|
* Send a plain JSON message to the WhatsApp servers
|
||||||
* @param json the message to send
|
* @param json the message to send
|
||||||
@@ -438,7 +430,8 @@ export class WAConnection extends EventEmitter {
|
|||||||
this.conn?.removeAllListeners ('message')
|
this.conn?.removeAllListeners ('message')
|
||||||
|
|
||||||
this.initTimeout && clearTimeout (this.initTimeout)
|
this.initTimeout && clearTimeout (this.initTimeout)
|
||||||
this.debounceTimeout && clearTimeout (this.debounceTimeout)
|
this.connectionDebounceTimeout.cancel()
|
||||||
|
this.messagesDebounceTimeout.cancel()
|
||||||
this.keepAliveReq && clearInterval(this.keepAliveReq)
|
this.keepAliveReq && clearInterval(this.keepAliveReq)
|
||||||
this.phoneCheckListeners = 0
|
this.phoneCheckListeners = 0
|
||||||
this.clearPhoneCheckInterval ()
|
this.clearPhoneCheckInterval ()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class WAConnection extends Base {
|
|||||||
const canLogin = this.canLogin()
|
const canLogin = this.canLogin()
|
||||||
this.referenceDate = new Date () // refresh reference date
|
this.referenceDate = new Date () // refresh reference date
|
||||||
|
|
||||||
this.startDebouncedTimeout ()
|
this.connectionDebounceTimeout.start()
|
||||||
|
|
||||||
const initQuery = (async () => {
|
const initQuery = (async () => {
|
||||||
const {ref, ttl} = await this.query({
|
const {ref, ttl} = await this.query({
|
||||||
@@ -28,7 +28,7 @@ export class WAConnection extends Base {
|
|||||||
}) as WAInitResponse
|
}) as WAInitResponse
|
||||||
|
|
||||||
if (!canLogin) {
|
if (!canLogin) {
|
||||||
this.stopDebouncedTimeout () // stop the debounced timeout for QR gen
|
this.connectionDebounceTimeout.cancel() // stop the debounced timeout for QR gen
|
||||||
this.generateKeysForAuth (ref, ttl)
|
this.generateKeysForAuth (ref, ttl)
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
@@ -73,7 +73,7 @@ export class WAConnection extends Base {
|
|||||||
]
|
]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
)
|
)
|
||||||
this.startDebouncedTimeout()
|
this.connectionDebounceTimeout.start()
|
||||||
this.initTimeout && clearTimeout (this.initTimeout)
|
this.initTimeout && clearTimeout (this.initTimeout)
|
||||||
this.initTimeout = null
|
this.initTimeout = null
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export class WAConnection extends Base {
|
|||||||
this.conn
|
this.conn
|
||||||
.removeAllListeners('error')
|
.removeAllListeners('error')
|
||||||
.removeAllListeners('close')
|
.removeAllListeners('close')
|
||||||
this.stopDebouncedTimeout()
|
this.connectionDebounceTimeout.start(this.connectOptions.maxIdleTimeMs)
|
||||||
resolve(authResult as WAOpenResult)
|
resolve(authResult as WAOpenResult)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error)
|
reject(error)
|
||||||
|
|||||||
@@ -77,12 +77,31 @@ export class WAConnection extends Base {
|
|||||||
// if there are no overlaps of messages and we had messages present, we clear the previous messages
|
// if there are no overlaps of messages and we had messages present, we clear the previous messages
|
||||||
// this prevents missing messages in conversations
|
// this prevents missing messages in conversations
|
||||||
let overlaps: { [_: string]: { requiresOverlap: boolean, didOverlap?: boolean } } = {}
|
let overlaps: { [_: string]: { requiresOverlap: boolean, didOverlap?: boolean } } = {}
|
||||||
|
const onLastBatchOfDataReceived = () => {
|
||||||
|
// find which chats had missing messages
|
||||||
|
// list out all the jids, and how many messages we've cached now
|
||||||
|
const chatsWithMissingMessages = Object.keys(overlaps).map(jid => {
|
||||||
|
// if there was no overlap, delete previous messages
|
||||||
|
if (!overlaps[jid].didOverlap && overlaps[jid].requiresOverlap) {
|
||||||
|
this.logger.debug(`received messages for ${jid}, but did not overlap with previous messages, clearing...`)
|
||||||
|
const chat = this.chats.get(jid)
|
||||||
|
if (chat) {
|
||||||
|
const message = chat.messages.get(lastMessages[jid])
|
||||||
|
const remainingMessages = chat.messages.paginatedByValue(message, this.maxCachedMessages, undefined, 'after')
|
||||||
|
chat.messages = newMessagesDB([message, ...remainingMessages])
|
||||||
|
return { jid, count: chat.messages.length } // return number of messages we've left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).filter(Boolean)
|
||||||
|
this.emit('initial-data-received', { chatsWithMissingMessages })
|
||||||
|
}
|
||||||
// messages received
|
// messages received
|
||||||
const messagesUpdate = (json, style: 'previous' | 'last') => {
|
const messagesUpdate = (json, style: 'previous' | 'last') => {
|
||||||
|
//console.log('msg ', json[1])
|
||||||
|
this.messagesDebounceTimeout.start(undefined, onLastBatchOfDataReceived)
|
||||||
if (style === 'last') {
|
if (style === 'last') {
|
||||||
overlaps = {}
|
overlaps = {}
|
||||||
}
|
}
|
||||||
const isLast = json[1].last
|
|
||||||
const messages = json[2] as WANode[]
|
const messages = json[2] as WANode[]
|
||||||
if (messages) {
|
if (messages) {
|
||||||
const updates: { [k: string]: KeyedDB<WAMessage, string> } = {}
|
const updates: { [k: string]: KeyedDB<WAMessage, string> } = {}
|
||||||
@@ -121,24 +140,6 @@ export class WAConnection extends Base {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isLast) {
|
|
||||||
// find which chats had missing messages
|
|
||||||
// list out all the jids, and how many messages we've cached now
|
|
||||||
const chatsWithMissingMessages = Object.keys(overlaps).map(jid => {
|
|
||||||
// if there was no overlap, delete previous messages
|
|
||||||
if (!overlaps[jid].didOverlap && overlaps[jid].requiresOverlap) {
|
|
||||||
this.logger.debug(`received messages for ${jid}, but did not overlap with previous messages, clearing...`)
|
|
||||||
const chat = this.chats.get(jid)
|
|
||||||
if (chat) {
|
|
||||||
const message = chat.messages.get(lastMessages[jid])
|
|
||||||
const remainingMessages = chat.messages.paginatedByValue(message, this.maxCachedMessages, undefined, 'after')
|
|
||||||
chat.messages = newMessagesDB([message, ...remainingMessages])
|
|
||||||
return { jid, count: chat.messages.length } // return number of messages we've left
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).filter(Boolean)
|
|
||||||
this.emit('initial-data-received', { chatsWithMissingMessages })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.on('CB:action,add:last', json => messagesUpdate(json, 'last'))
|
this.on('CB:action,add:last', json => messagesUpdate(json, 'last'))
|
||||||
this.on('CB:action,add:before', json => messagesUpdate(json, 'previous'))
|
this.on('CB:action,add:before', json => messagesUpdate(json, 'previous'))
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import got, { Options, Response } from 'got'
|
|||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { IAudioMetadata } from 'music-metadata'
|
import { IAudioMetadata } from 'music-metadata'
|
||||||
|
|
||||||
|
|
||||||
const platformMap = {
|
const platformMap = {
|
||||||
'aix': 'AIX',
|
'aix': 'AIX',
|
||||||
'darwin': 'Mac OS',
|
'darwin': 'Mac OS',
|
||||||
@@ -105,6 +104,25 @@ export function randomBytes(length) {
|
|||||||
/** 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 const debouncedTimeout = (intervalMs: number = 1000, task: () => void = undefined) => {
|
||||||
|
let timeout: NodeJS.Timeout
|
||||||
|
return {
|
||||||
|
start: (newIntervalMs?: number, newTask?: () => void) => {
|
||||||
|
task = newTask || task
|
||||||
|
intervalMs = newIntervalMs || intervalMs
|
||||||
|
timeout && clearTimeout(timeout)
|
||||||
|
timeout = setTimeout(task, intervalMs)
|
||||||
|
},
|
||||||
|
cancel: () => {
|
||||||
|
timeout && clearTimeout(timeout)
|
||||||
|
timeout = undefined
|
||||||
|
},
|
||||||
|
setTask: (newTask: () => void) => task = newTask,
|
||||||
|
setInterval: (newInterval: number) => intervalMs = newInterval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const delay = (ms: number) => delayCancellable (ms).delay
|
export const delay = (ms: number) => delayCancellable (ms).delay
|
||||||
export const delayCancellable = (ms: number) => {
|
export const delayCancellable = (ms: number) => {
|
||||||
const stack = new Error().stack
|
const stack = new Error().stack
|
||||||
|
|||||||
Reference in New Issue
Block a user