From ac4b4c7384d6d28978f7c67989697e97bdaa8793 Mon Sep 17 00:00:00 2001 From: Adhiraj Singh Date: Mon, 4 Jan 2021 12:35:48 +0530 Subject: [PATCH] Removed deprecations + merge message-status-update into chat-update 1. Update package version to 4.0.0 2. Retry query if the connection unexpectedly closes + make query iterative instead of recursive 3. Remove message-new & message-update deprecations 4. Deprecate loadProfilePicturesForChatsAutomatically --- Example/example.ts | 23 +++--- package.json | 2 +- src/Tests/Tests.Connect.ts | 17 +++++ src/Tests/Tests.Messages.ts | 39 ++++++----- src/Tests/Tests.Misc.ts | 26 ++++--- src/WAConnection/0.Base.ts | 69 ++++++++++-------- src/WAConnection/3.Connect.ts | 56 ++------------- src/WAConnection/4.Events.ts | 127 +++++++++++----------------------- src/WAConnection/Constants.ts | 19 +---- 9 files changed, 157 insertions(+), 221 deletions(-) diff --git a/Example/example.ts b/Example/example.ts index a1e76de..adcbab9 100644 --- a/Example/example.ts +++ b/Example/example.ts @@ -9,13 +9,14 @@ import { ReconnectMode, ProxyAgent, waChatKey, + delay, } from '../src/WAConnection/WAConnection' import * as fs from 'fs' async function example() { const conn = new WAConnection() // instantiate conn.autoReconnect = ReconnectMode.onConnectionLost // only automatically reconnect when the connection breaks - conn.logger.level = 'debug' // set to 'debug' to see what kind of stuff you can implement + conn.logger.level = 'trace' // set to 'debug' to see what kind of stuff you can implement // attempt to reconnect at most 10 times in a row conn.connectOptions.maxRetries = 10 conn.chatOrderingKey = waChatKey(true) // order chats such that pinned chats are on top @@ -34,28 +35,34 @@ async function example() { }) // 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, + and get full access to one's WhatsApp. Despite the convenience, be careful with this file */ fs.existsSync('./auth_info.json') && conn.loadAuthInfo ('./auth_info.json') // uncomment the following line to proxy the connection; some random proxy I got off of: https://proxyscrape.com/free-proxy-list //conn.connectOptions.agent = ProxyAgent ('http://1.0.180.120:8080') await conn.connect() console.log('oh hello ' + conn.user.name + ' (' + conn.user.jid + ')') + // uncomment to load all unread messages //const unread = await conn.loadAllUnreadMessages () //console.log ('you have ' + unread.length + ' unread messages') - /* Note: one can take this auth_info.json file and login again from any computer without having to scan the QR code, - and get full access to one's WhatsApp. Despite the convenience, be careful with this file */ - conn.on ('message-status-update', json => { - const participant = json.participant ? ' (' + json.participant + ')' : '' // participant exists when the message is from a group - console.log(`${json.to}${participant} acknlowledged message(s) ${json.ids} as ${json.type}`) - }) + /** + * The universal event for anything that happens + * New messages, updated messages, read & delivered messages + */ conn.on('chat-update', async chat => { if (chat.presences) { // receive presence updates -- composing, available, etc. Object.values(chat.presences).forEach(presence => console.log( `${presence.name}'s presence is ${presence.lastKnownPresence} in ${chat.jid}`)) } // only do something when a new message is received - if (!chat.hasNewMessage) return + if (!chat.hasNewMessage) { + if(chat.messages) { + console.log('updated message: ', chat.messages.first) + } + return + } const m = chat.messages.all()[0] // pull the new message from the update const messageStubType = WA_MESSAGE_STUB_TYPES[m.messageStubType] || 'MESSAGE' diff --git a/package.json b/package.json index a84e9a6..60627a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@adiwajshing/baileys", - "version": "3.4.1", + "version": "4.0.0", "description": "WhatsApp Web API", "homepage": "https://github.com/adiwajshing/Baileys", "main": "lib/index.js", diff --git a/src/Tests/Tests.Connect.ts b/src/Tests/Tests.Connect.ts index e9a19ef..c49976c 100644 --- a/src/Tests/Tests.Connect.ts +++ b/src/Tests/Tests.Connect.ts @@ -372,4 +372,21 @@ describe ('Pending Requests', () => { conn.close () }) + it('should re-execute query on connection closed error', async () => { + const conn = makeConnection () + //conn.pendingRequestTimeoutMs = 10_000 + await conn.loadAuthInfo('./auth_info.json').connect () + const task: Promise = conn.query({json: ['query', 'Status', conn.user.jid], waitForOpen: true}) + + await delay(20) + conn['onMessageRecieved']('1234,["Pong",false]') // fake cancel the connection + + await delay(2000) + + const json = await task + + assert.ok (json.status) + + conn.close () + }) }) \ No newline at end of file diff --git a/src/Tests/Tests.Messages.ts b/src/Tests/Tests.Messages.ts index d4ab8ce..ba2ec15 100644 --- a/src/Tests/Tests.Messages.ts +++ b/src/Tests/Tests.Messages.ts @@ -1,4 +1,4 @@ -import { MessageType, Mimetype, delay, promiseTimeout, WA_MESSAGE_STATUS_TYPE, WAMessageStatusUpdate } from '../WAConnection/WAConnection' +import { MessageType, Mimetype, delay, promiseTimeout, WA_MESSAGE_STATUS_TYPE, WAMessageStatusUpdate, generateMessageID, WAMessage } from '../WAConnection/WAConnection' import {promises as fs} from 'fs' import * as assert from 'assert' import { WAConnectionTest, testJid, sendAndRetreiveMessage, assertChatDBIntegrity } from './Common' @@ -168,17 +168,23 @@ WAConnectionTest('Messages', conn => { const content2 = await fs.readFile('./Media/cat.jpeg') await sendAndRetreiveMessage(conn, content2, MessageType.image) }) - it('should fail to send a text message', done => { + it('should fail to send a text message', async () => { const JID = '1234-1234@g.us' - conn.sendMessage(JID, 'hello', MessageType.text) + const messageId = generateMessageID() + conn.sendMessage(JID, 'hello', MessageType.text, { messageId }) - conn.on ('message-status-update', async update => { - if (update.to === JID) { - assert.strictEqual (update.type, WA_MESSAGE_STATUS_TYPE.ERROR) - await conn.deleteChat (JID) - done () - } - }) + await new Promise(resolve => ( + conn.on ('chat-update', async update => { + console.log(messageId, update.messages?.first) + if ( + update.jid === JID && + update.messages?.first.key.id === messageId && + update.messages.first.status === WA_MESSAGE_STATUS_TYPE.ERROR) { + resolve(undefined) + } + }) + )) + conn.removeAllListeners('chat-update') }) it('should maintain message integrity', async () => { // loading twice does not alter the results @@ -236,16 +242,17 @@ WAConnectionTest('Messages', conn => { } }) it('should deliver a message', async () => { + const response = await conn.sendMessage(testJid, 'My Name Jeff', MessageType.text) const waitForUpdate = promiseTimeout(15000, resolve => { - conn.on('message-status-update', update => { - if (update.ids.includes(response.key.id)) { - resolve(update) + conn.on('chat-update', update => { + if (update.messages?.first.key.id === response.key.id) { + resolve(update.messages.first) } }) - }) as Promise - const response = await conn.sendMessage(testJid, 'My Name Jeff', MessageType.text) + }) as Promise + const m = await waitForUpdate - assert.ok (m.type >= WA_MESSAGE_STATUS_TYPE.DELIVERY_ACK) + assert.ok (m.status >= WA_MESSAGE_STATUS_TYPE.DELIVERY_ACK) }) }) diff --git a/src/Tests/Tests.Misc.ts b/src/Tests/Tests.Misc.ts index 68fcb5e..635267e 100644 --- a/src/Tests/Tests.Misc.ts +++ b/src/Tests/Tests.Misc.ts @@ -171,7 +171,7 @@ WAConnectionTest('Misc', conn => { await delay (2000) await conn.modifyChat (testJid, ChatModification.unmute) }) - it('should star/unchar messages', async () => { + it('should star/unstar messages', async () => { for (let i = 1; i <= 5; i++) { await conn.sendMessage(testJid, `Message ${i}`, MessageType.text) await delay(1000) @@ -276,7 +276,7 @@ WAConnectionTest('Misc', conn => { it('should detect overlaps and clear messages accordingly', async () => { // wait for chats await new Promise(resolve => ( - conn.once('chats-received', ({ hasReceivedLastMessage }) => hasReceivedLastMessage && resolve(undefined)) + conn.once('initial-data-received', resolve) )) conn.maxCachedMessages = 100 @@ -293,18 +293,16 @@ WAConnectionTest('Misc', conn => { chat.messages = newMessagesDB( chat.messages.all().slice(0, 20) ) const task = new Promise(resolve => ( - conn.on('chats-received', ({ hasReceivedLastMessage, chatsWithMissingMessages }) => { - if (hasReceivedLastMessage) { - assert.strictEqual(Object.keys(chatsWithMissingMessages).length, 1) - const missing = chatsWithMissingMessages.find(({ jid }) => jid === testJid) - assert.ok(missing, 'missing message not detected') - assert.strictEqual( - conn.chats.get(testJid).messages.length, - missing.count - ) - assert.strictEqual(missing.count, oldCount) - resolve(undefined) - } + conn.on('initial-data-received', ({ chatsWithMissingMessages }) => { + assert.strictEqual(Object.keys(chatsWithMissingMessages).length, 1) + const missing = chatsWithMissingMessages.find(({ jid }) => jid === testJid) + assert.ok(missing, 'missing message not detected') + assert.strictEqual( + conn.chats.get(testJid).messages.length, + missing.count + ) + assert.strictEqual(missing.count, oldCount) + resolve(undefined) }) )) diff --git a/src/WAConnection/0.Base.ts b/src/WAConnection/0.Base.ts index 36abbb7..79b43ed 100644 --- a/src/WAConnection/0.Base.ts +++ b/src/WAConnection/0.Base.ts @@ -61,7 +61,8 @@ export class WAConnection extends EventEmitter { messageLog: { tag: string, json: string, fromMe: boolean, binaryTags?: any[] }[] = [] maxCachedMessages = 50 - loadProfilePicturesForChatsAutomatically = true + /** @deprecated won't be supported soon */ + loadProfilePicturesForChatsAutomatically = false lastChatsReceived: Date chats = new KeyedDB (Utils.waChatKey(false), value => value.jid) @@ -207,39 +208,52 @@ export class WAConnection extends EventEmitter { * @param tag the tag to attach to the message */ async query(q: WAQuery): Promise { - let {json, binaryTags, tag, timeoutMs, expect200, waitForOpen, longTag, requiresPhoneConnection, startDebouncedTimeout} = q + let {json, binaryTags, tag, timeoutMs, expect200, waitForOpen, longTag, requiresPhoneConnection, startDebouncedTimeout, maxRetries} = q requiresPhoneConnection = requiresPhoneConnection !== false waitForOpen = waitForOpen !== false - if (waitForOpen) await this.waitForConnection() - + let triesLeft = maxRetries || 2 tag = tag || this.generateMessageTag (longTag) - const promise = this.waitForMessage(tag, requiresPhoneConnection, timeoutMs) - if (this.logger.level === 'trace') { - this.logger.trace ({ fromMe: true },`${tag},${JSON.stringify(json)}`) - } + while (triesLeft >= 0) { + if (waitForOpen) await this.waitForConnection() + + const promise = this.waitForMessage(tag, requiresPhoneConnection, timeoutMs) - if (binaryTags) tag = await this.sendBinary(json as WANode, binaryTags, tag) - else tag = await this.sendJSON(json, tag) - - const response = await promise - - if (expect200 && response.status && Math.floor(+response.status / 100) !== 2) { - // read here: http://getstatuscode.com/599 - if (response.status === 599) { - this.unexpectedDisconnect (DisconnectReason.badSession) - const response = await this.query (q) - return response + if (this.logger.level === 'trace') { + this.logger.trace ({ fromMe: true },`${tag},${JSON.stringify(json)}`) } - const message = STATUS_CODES[response.status] || 'unknown' - throw new BaileysError ( - `Unexpected status in '${json[0] || 'generic query'}': ${STATUS_CODES[response.status]}(${response.status})`, - {query: json, message, status: response.status} - ) + if (binaryTags) tag = await this.sendBinary(json as WANode, binaryTags, tag) + else tag = await this.sendJSON(json, tag) + + try { + const response = await promise + if (expect200 && response.status && Math.floor(+response.status / 100) !== 2) { + const message = STATUS_CODES[response.status] || 'unknown' + throw new BaileysError ( + `Unexpected status in '${json[0] || 'query'}': ${STATUS_CODES[response.status]}(${response.status})`, + {query: json, message, status: response.status} + ) + } + if (startDebouncedTimeout) { + this.startDebouncedTimeout() + } + return response + } catch (error) { + if (triesLeft === 0) { + throw error + } + // read here: http://getstatuscode.com/599 + if (error.status === 599) { + this.unexpectedDisconnect (DisconnectReason.badSession) + } else if ((error.message === 'close' || error.message === 'lost') && waitForOpen && this.state !== 'close') { + // nothing here + } else throw error + + triesLeft -= 1 + this.logger.debug(`query failed due to ${error}, retrying...`) + } } - if (startDebouncedTimeout) this.startDebouncedTimeout () - return response } /** interval is started when a query takes too long to respond */ protected startPhoneCheckInterval () { @@ -330,7 +344,7 @@ export class WAConnection extends EventEmitter { let onOpen: () => void let onClose: ({ reason }) => void - if (this.pendingRequestTimeoutMs <= 0) { + if (this.pendingRequestTimeoutMs !== null && this.pendingRequestTimeoutMs <= 0) { throw new BaileysError(DisconnectReason.close, { status: 428 }) } await ( @@ -396,7 +410,6 @@ export class WAConnection extends EventEmitter { this.phoneCheckListeners = 0 this.clearPhoneCheckInterval () - this.emit ('ws-close', { reason: DisconnectReason.close }) try { diff --git a/src/WAConnection/3.Connect.ts b/src/WAConnection/3.Connect.ts index e71034f..3998b5d 100644 --- a/src/WAConnection/3.Connect.ts +++ b/src/WAConnection/3.Connect.ts @@ -93,33 +93,21 @@ export class WAConnection extends Base { this.startKeepAliveRequest() this.logger.info(`connected to WhatsApp Web server, authenticating via ${reconnectID ? 'reconnect' : 'takeover'}`) - let waitForChats: Promise<{ hasNewChats: boolean }> - // add wait for chats promise if required - if (options?.waitForChats) { - const {wait, cancellations} = this.receiveChatsAndContacts(this.connectOptions.waitOnlyForLastMessage) - waitForChats = wait - rejections.push (...cancellations) - } try { - const [authResult, chatsResult] = await Promise.all ( - [ - this.authenticate(reconnectID), - waitForChats || undefined - ] - ) + const authResult = await this.authenticate(reconnectID) this.conn .removeAllListeners('error') .removeAllListeners('close') - this.stopDebouncedTimeout () - resolve ({ ...authResult, ...chatsResult }) + this.stopDebouncedTimeout() + resolve(authResult) } catch (error) { - reject (error) + reject(error) } }) this.conn.on('error', rejectAll) this.conn.on('close', () => rejectAll(new Error(DisconnectReason.close))) - }) as Promise<{ hasNewChats?: boolean, isNewUser: boolean }> + }) as Promise<{ isNewUser: boolean }> ) this.on ('ws-close', rejectAllOnWSClose) @@ -132,45 +120,15 @@ export class WAConnection extends Base { const result = await connect () return result } catch (error) { - this.endConnection () + this.endConnection() throw error } finally { this.off ('ws-close', rejectAllOnWSClose) } } - /** - * Sets up callbacks to receive chats, contacts & messages. - * Must be called immediately after connect - */ - protected receiveChatsAndContacts(waitOnlyForLast: boolean) { - const rejectableWaitForEvent = (event: string) => { - let rejectTask = (_: Error) => {} - const task = new Promise((resolve, reject) => { - this.once (event, data => { - this.startDebouncedTimeout() // start timeout again - resolve(data) - }) - rejectTask = reject - }) - return { reject: rejectTask, task } - } - const events = [ 'chats-received', 'contacts-received', 'CB:action,add:last' ] - if (!waitOnlyForLast) events.push('CB:action,add:before', 'CB:action,add:unread') - - const cancellations = [] - const wait = Promise.all ( - events.map (ev => { - const {reject, task} = rejectableWaitForEvent(ev) - cancellations.push(reject) - return task - }) - ).then(([update]) => update as { hasNewChats: boolean }) - - return { wait, cancellations } - } private onMessageRecieved(message: string | Buffer) { if (message[0] === '!') { - // when the first character in the message is an '!', the server is updating the last seen + // when the first character in the message is an '!', the server is sending a pong frame const timestamp = message.slice(1, message.length).toString ('utf-8') this.lastSeen = new Date(parseInt(timestamp)) this.emit ('received-pong') diff --git a/src/WAConnection/4.Events.ts b/src/WAConnection/4.Events.ts index eaed3d2..df67d96 100644 --- a/src/WAConnection/4.Events.ts +++ b/src/WAConnection/4.Events.ts @@ -128,7 +128,7 @@ export class WAConnection extends Base { } } }).filter(Boolean) - this.emit('chats-received', { hasReceivedLastMessage: true, chatsWithMissingMessages }) + this.emit('initial-data-received', { chatsWithMissingMessages }) } } this.on('CB:action,add:last', json => messagesUpdate(json, 'last')) @@ -173,7 +173,6 @@ export class WAConnection extends Base { this.emit('contacts-received', { updatedContacts }) }) - // new messages this.on('CB:action,add:relay,message', json => { const message = json[2][0][2] as WAMessage @@ -227,6 +226,29 @@ export class WAConnection extends Base { this.logger.debug ({ unhandled: true }, 'received message update for non-present message from ' + jid) } }) + this.on('CB:action,add:relay,received', json => { + json = json[2][0][1] + const chat = this.chats.get( whatsappID(json.jid) ) + const msg = chat?.messages.get(GET_MESSAGE_ID({ id: json.index, fromMe: json.owner === 'true' })) + if (msg) { + const MAP = { + read: WA_MESSAGE_STATUS_TYPE.READ, + message: WA_MESSAGE_STATUS_TYPE.DELIVERY_ACK, + error: WA_MESSAGE_STATUS_TYPE.ERROR + } + const status = MAP[json.type] + if (typeof status !== 'undefined') { + if (status > msg.status || status === WA_MESSAGE_STATUS_TYPE.ERROR) { + msg.status = status + this.emit('chat-update', { jid: chat.jid, messages: newMessagesDB([ msg ]) }) + } + } else { + this.logger.warn({ update: json }, 'received unknown message status update') + } + } else { + this.logger.debug ({ unhandled: true, update: json }, 'received message status update for non-present message') + } + }) // If a user's contact has changed this.on ('CB:action,,user', json => { const node = json[2][0] @@ -266,7 +288,7 @@ export class WAConnection extends Base { return 'clear' }, 'archive': () => { - this.chats.updateKey(chat, chat => chat.archive = 'true') + this.chats.update(chat.jid, chat => chat.archive = 'true') return 'archive' }, 'unarchive': () => { @@ -294,7 +316,6 @@ export class WAConnection extends Base { contact.imgUrl = imgUrl this.emit('contact-update', { jid, imgUrl }) } - const chat = this.chats.get(jid) if (chat) { chat.imgUrl = imgUrl @@ -305,8 +326,6 @@ export class WAConnection extends Base { this.on('CB:Status,status', async json => { const jid = whatsappID(json[1].id) this.emit ('contact-update', { jid, status: json[1].status }) - // emit deprecated - this.emit ('user-status-update', { jid, status: json[1].status }) }) // User Profile Name Updates this.on ('CB:Conn,pushname', json => { @@ -326,41 +345,7 @@ export class WAConnection extends Base { else chat.count = 0 this.emit ('chat-update', { jid: chat.jid, count: chat.count }) - }) - this.on ('CB:action,add:relay,received', json => { - json = json[2][0][1] - if (json.type === 'error') { - const update: WAMessageStatusUpdate = { - from: this.user.jid, - to: whatsappID(json.jid), - participant: this.user.jid, - timestamp: new Date(), - ids: [ json.index ], - type: WA_MESSAGE_STATUS_TYPE.ERROR, - } - this.forwardStatusUpdate (update) - } - }) - - const func = json => { - json = json[1] - let ids = json.id - - if (json.cmd === 'ack') ids = [json.id] - - const update: WAMessageStatusUpdate = { - from: whatsappID(json.from), - to: whatsappID(json.to), - participant: whatsappID(json.participant), - timestamp: new Date(json.t * 1000), - ids: ids, - type: (+json.ack)+1, - } - this.forwardStatusUpdate (update) - } - this.on('CB:Msg', func) - this.on('CB:MsgInfo', func) - + }) this.on ('qr', qr => QR.generate(qr, { small: true })) // blocklist updates @@ -380,14 +365,16 @@ export class WAConnection extends Base { /** Get the URL to download the profile picture of a person/group */ @Mutex (jid => jid) async getProfilePicture(jid: string | null) { - const response = await this.query({ json: ['query', 'ProfilePicThumb', jid || this.user.jid], expect200: true, requiresPhoneConnection: false }) + const response = await this.query({ + json: ['query', 'ProfilePicThumb', jid || this.user.jid], + expect200: true, + requiresPhoneConnection: false + }) return response.eurl as string } protected applyingPresenceUpdate(update: PresenceUpdate) { const chatId = whatsappID(update.id) const jid = whatsappID(update.participant || update.id) - // emit deprecated - this.emit('user-presence-update', update) const chat = this.chats.get(chatId) if (chat && jid.endsWith('@s.whatsapp.net')) { // if its a single chat @@ -409,13 +396,6 @@ export class WAConnection extends Base { return { jid: chatId, presences: { [jid]: presence } } as Partial } } - protected forwardStatusUpdate (update: WAMessageStatusUpdate) { - const chat = this.chats.get( whatsappID(update.to) ) - if (!chat) return - - this.emit ('message-status-update', update) - this.chatUpdatedMessage (update.ids, update.type, chat) - } /** inserts an empty chat into the DB */ protected async chatAdd (jid: string, name?: string) { const chat: WAChat = { @@ -499,8 +479,6 @@ export class WAConnection extends Base { found.messageStubType = WA_MESSAGE_STUB_TYPE.REVOKE delete found.message chatUpdate.messages = newMessagesDB([ found ]) - // emit deprecated - this.emit('message-update', found) } break default: @@ -529,8 +507,6 @@ export class WAConnection extends Base { } chatUpdate.hasNewMessage = true chatUpdate.messages = newMessagesDB([ message ]) - // emit deprecated - this.emit('message-new', message) // check if the message is an action if (message.messageStubType) { const jid = chat.jid @@ -611,17 +587,7 @@ export class WAConnection extends Base { if (chat.metadata) Object.assign(chat.metadata, update) this.emit ('group-update', { jid, ...update }) } - protected chatUpdatedMessage (messageIDs: string[], status: WA_MESSAGE_STATUS_TYPE, chat: WAChat) { - for (let id of messageIDs) { - let msg = chat.messages.get (GET_MESSAGE_ID({ id, fromMe: true })) || chat.messages.get (GET_MESSAGE_ID({ id, fromMe: false })) - if (msg && msg.status < status) { - if (status <= WA_MESSAGE_STATUS_TYPE.PENDING) msg.status = status - else if (isGroupID(chat.jid)) msg.status = status-1 - else msg.status = status - } - } - } - protected chatUpdateTime = (chat, stamp: number) => this.chats.updateKey (chat, c => c.t = stamp) + protected chatUpdateTime = (chat, stamp: number) => this.chats.update (chat.jid, c => c.t = stamp) /** sets the profile picture of a chat */ protected async setProfilePicture (chat: WAChat) { chat.imgUrl = await this.getProfilePicture (chat.jid).catch (err => '') @@ -645,39 +611,24 @@ export class WAConnection extends Base { on (event: 'qr', listener: (qr: string) => void): this /** when the connection to the phone changes */ on (event: 'connection-phone-change', listener: (state: {connected: boolean}) => void): this - /** - * when a user's presence is updated - * @deprecated use `chat-update` - * */ - on (event: 'user-presence-update', listener: (update: PresenceUpdate) => void): this - /** - * when a user's status is updated - * @deprecated use `contact-update` - */ - on (event: 'user-status-update', listener: (update: {jid: string, status?: string}) => void): this - /** when a user's status is updated */ + /** when a contact is updated */ on (event: 'contact-update', listener: (update: WAContactUpdate) => void): this /** when a new chat is added */ on (event: 'chat-new', listener: (chat: WAChat) => void): this /** when contacts are sent by WA */ on (event: 'contacts-received', listener: (u: { updatedContacts: Partial[] }) => void): this /** when chats are sent by WA, and when all messages are received */ - on (event: 'chats-received', listener: (update: {hasNewChats?: boolean, hasReceivedLastMessage?: boolean, chatsWithMissingMessages: { jid: string, count: number }[] }) => void): this + on (event: 'chats-received', listener: (update: {hasNewChats?: boolean}) => void): this + /** when all initial messages are received from WA */ + on (event: 'initial-data-received', listener: (update: {chatsWithMissingMessages: { jid: string, count: number }[] }) => void): this /** when multiple chats are updated (new message, updated message, deleted, pinned, etc) */ on (event: 'chats-update', listener: (chats: WAChatUpdate[]) => void): this - /** when a chat is updated (new message, updated message, deleted, pinned, presence updated etc) */ + /** when a chat is updated (new message, updated message, read message, deleted, pinned, presence updated etc) */ on (event: 'chat-update', listener: (chat: WAChatUpdate) => void): this /** - * when a new message is relayed - * @deprecated use `chat-update` + * when a message's status is updated (deleted, delivered, read, sent etc.) + * @deprecated will not be called anymore. Use `chat-update` * */ - on (event: 'message-new', listener: (message: WAMessage) => void): this - /** - * when a message object itself is updated (receives its media info or is deleted) - * @deprecated use `chat-update` - * */ - on (event: 'message-update', listener: (message: WAMessage) => void): this - /** when a message's status is updated (deleted, delivered, read, sent etc.) */ on (event: 'message-status-update', listener: (message: WAMessageStatusUpdate) => void): this /** when participants are added to a group */ on (event: 'group-participants-update', listener: (update: {jid: string, participants: string[], actor?: string, action: WAParticipantAction}) => void): this diff --git a/src/WAConnection/Constants.ts b/src/WAConnection/Constants.ts index 1b98a68..dedf465 100644 --- a/src/WAConnection/Constants.ts +++ b/src/WAConnection/Constants.ts @@ -65,6 +65,7 @@ export interface WAQuery { longTag?: boolean requiresPhoneConnection?: boolean startDebouncedTimeout?: boolean + maxRetries?: number } export enum ReconnectMode { /** does not reconnect */ @@ -80,25 +81,10 @@ export type WALoadChatOptions = { loadProfilePicture?: boolean } export type WAConnectOptions = { - /** - * New QR generation interval, set to null if you don't want to regenerate - * @deprecated no need to set this as we use WA ttl - * */ - regenerateQRIntervalMs?: number /** fails the connection if no data is received for X seconds */ maxIdleTimeMs?: number /** maximum attempts to connect */ maxRetries?: number - /** - * @deprecated -- use the `chats-received` & `contacts-received` events - * should the chats be waited for - * */ - waitForChats?: boolean - /** - * @deprecated -- use the `chats-received` & `contacts-received` events - * if set to true, the connect only waits for the last message of the chat - * */ - waitOnlyForLastMessage?: boolean /** max time for the phone to respond to a connectivity test */ phoneResponseTime?: number connectCooldownMs?: number @@ -465,16 +451,15 @@ export type BaileysEvent = 'close' | 'ws-close' | 'qr' | + 'connection-validated' | 'connection-phone-change' | 'contacts-received' | 'chats-received' | 'chat-new' | 'chat-update' | - 'message-status-update' | 'group-participants-update' | 'group-update' | 'received-pong' | 'credentials-updated' | - 'connection-validated' | 'blocklist-update' | 'contact-update' \ No newline at end of file