mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Changes
- Separated message-status-update & message-update - Removed contact storage & waiting for contacts. General connect speed should improve by 10%-20% - Added `contacts-received` event
This commit is contained in:
@@ -17,23 +17,29 @@ async function example() {
|
|||||||
conn.logLevel = MessageLogLevel.info // set to unhandled to see what kind of stuff you can implement
|
conn.logLevel = MessageLogLevel.info // set to unhandled to see what kind of stuff you can implement
|
||||||
|
|
||||||
// loads the auth file credentials if present
|
// loads the auth file credentials if present
|
||||||
if (fs.existsSync('./auth_info.json')) conn.loadAuthInfo ('./auth_info.json')
|
fs.existsSync('./auth_info.json') && conn.loadAuthInfo ('./auth_info.json')
|
||||||
conn.on ('qr', qr => console.log (qr))
|
|
||||||
// connect or timeout in 30 seconds
|
/* Called when contacts are received,
|
||||||
await conn.connect({ timeoutMs: 30 * 1000 })
|
* do note, that this method may be called before the connection is done completely because WA is funny sometimes
|
||||||
|
* */
|
||||||
|
conn.on ('contacts-received', contacts => console.log(`received ${Object.keys(contacts).length} contacts`))
|
||||||
|
|
||||||
|
// connect or timeout in 60 seconds
|
||||||
|
await conn.connect({ timeoutMs: 60 * 1000, retryOnNetworkErrors: true })
|
||||||
|
|
||||||
const unread = await conn.loadAllUnreadMessages ()
|
const unread = await conn.loadAllUnreadMessages ()
|
||||||
|
|
||||||
console.log('oh hello ' + conn.user.name + ' (' + conn.user.id + ')')
|
console.log('oh hello ' + conn.user.name + ' (' + conn.user.id + ')')
|
||||||
console.log('you have ' + conn.chats.all().length + ' chats & ' + Object.keys(conn.contacts).length + ' contacts')
|
console.log('you have ' + conn.chats.all().length + ' chats')
|
||||||
console.log ('you have ' + unread.length + ' unread messages')
|
console.log ('you have ' + unread.length + ' unread messages')
|
||||||
|
|
||||||
const authInfo = conn.base64EncodedAuthInfo() // get all the auth info we need to restore this session
|
const authInfo = conn.base64EncodedAuthInfo() // get all the auth info we need to restore this session
|
||||||
fs.writeFileSync('./auth_info.json', JSON.stringify(authInfo, null, '\t')) // save this info to a file
|
fs.writeFileSync('./auth_info.json', JSON.stringify(authInfo, null, '\t')) // save this info to a file
|
||||||
|
|
||||||
/* 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,
|
||||||
and get full access to one's WhatsApp. Despite the convenience, be careful with this file */
|
and get full access to one's WhatsApp. Despite the convenience, be careful with this file */
|
||||||
conn.on ('user-presence-update', json => console.log(json.id + ' presence is ' + json.type))
|
conn.on ('user-presence-update', json => console.log(json.id + ' presence is ' + json.type))
|
||||||
conn.on ('message-update', json => {
|
conn.on ('message-status-update', json => {
|
||||||
const participant = json.participant ? ' (' + json.participant + ')' : '' // participant exists when the message is from a group
|
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}`)
|
console.log(`${json.to}${participant} acknlowledged message(s) ${json.ids} as ${json.type}`)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { MessageType, Mimetype, delay, promiseTimeout, WAMessage, WA_MESSAGE_STATUS_TYPE, MessageStatusUpdate } from '../WAConnection/WAConnection'
|
import { MessageType, Mimetype, delay, promiseTimeout, WAMessage, WA_MESSAGE_STATUS_TYPE, WAMessageStatusUpdate } from '../WAConnection/WAConnection'
|
||||||
import {promises as fs} from 'fs'
|
import {promises as fs} from 'fs'
|
||||||
import * as assert from 'assert'
|
import * as assert from 'assert'
|
||||||
import { WAConnectionTest, testJid, sendAndRetreiveMessage } from './Common'
|
import { WAConnectionTest, testJid, sendAndRetreiveMessage } from './Common'
|
||||||
@@ -79,7 +79,7 @@ WAConnectionTest('Message Events', (conn) => {
|
|||||||
resolve(update)
|
resolve(update)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}) as Promise<MessageStatusUpdate>
|
}) as Promise<WAMessageStatusUpdate>
|
||||||
const response = await conn.sendMessage(testJid, 'My Name Jeff', MessageType.text)
|
const response = await conn.sendMessage(testJid, 'My Name Jeff', MessageType.text)
|
||||||
const m = await waitForUpdate
|
const m = await waitForUpdate
|
||||||
assert.ok (m.type >= WA_MESSAGE_STATUS_TYPE.DELIVERY_ACK)
|
assert.ok (m.type >= WA_MESSAGE_STATUS_TYPE.DELIVERY_ACK)
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ export class WAConnection extends EventEmitter {
|
|||||||
|
|
||||||
maxCachedMessages = 25
|
maxCachedMessages = 25
|
||||||
|
|
||||||
contacts: {[k: string]: WAContact} = {}
|
|
||||||
chats: KeyedDB<WAChat> = new KeyedDB (Utils.waChatUniqueKey, value => value.jid)
|
chats: KeyedDB<WAChat> = new KeyedDB (Utils.waChatUniqueKey, value => value.jid)
|
||||||
|
|
||||||
/** Data structure of tokens & IDs used to establish one's identiy to WhatsApp Web */
|
/** Data structure of tokens & IDs used to establish one's identiy to WhatsApp Web */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as Curve from 'curve25519-js'
|
import * as Curve from 'curve25519-js'
|
||||||
import * as Utils from './Utils'
|
import * as Utils from './Utils'
|
||||||
import {WAConnection as Base} from './0.Base'
|
import {WAConnection as Base} from './0.Base'
|
||||||
import { MessageLogLevel, WAMetric, WAFlag, BaileysError, Presence } from './Constants'
|
import { MessageLogLevel, WAMetric, WAFlag, BaileysError, Presence, WAUser } from './Constants'
|
||||||
|
|
||||||
export class WAConnection extends Base {
|
export class WAConnection extends Base {
|
||||||
|
|
||||||
@@ -53,14 +53,16 @@ export class WAConnection extends Base {
|
|||||||
// otherwise just chain the promise further
|
// otherwise just chain the promise further
|
||||||
return json
|
return json
|
||||||
})
|
})
|
||||||
.then(async json => {
|
.then(json => {
|
||||||
this.validateNewConnection(json[1]) // validate the connection
|
this.user = this.validateNewConnection(json[1]) // validate the connection
|
||||||
this.log('validated connection successfully', MessageLogLevel.info)
|
this.log('validated connection successfully', MessageLogLevel.info)
|
||||||
|
|
||||||
this.sendPostConnectQueries ()
|
this.sendPostConnectQueries ()
|
||||||
|
|
||||||
this.lastSeen = new Date() // set last seen to right now
|
this.lastSeen = new Date() // set last seen to right now
|
||||||
})
|
})
|
||||||
|
// load profile picture
|
||||||
|
.then (() => this.query({ json: ['query', 'ProfilePicThumb', this.user.id], waitForOpen: false, expect200: false }))
|
||||||
|
.then (response => this.user.imgUrl = response?.eurl || '')
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Send the same queries WA Web sends after connect
|
* Send the same queries WA Web sends after connect
|
||||||
@@ -88,25 +90,24 @@ export class WAConnection extends Base {
|
|||||||
* @param {object} json
|
* @param {object} json
|
||||||
*/
|
*/
|
||||||
private validateNewConnection(json) {
|
private validateNewConnection(json) {
|
||||||
const onValidationSuccess = () => {
|
// set metadata: one's WhatsApp ID [cc][number]@s.whatsapp.net, name on WhatsApp, info about the phone
|
||||||
// set metadata: one's WhatsApp ID [cc][number]@s.whatsapp.net, name on WhatsApp, info about the phone
|
const onValidationSuccess = () => ({
|
||||||
this.user = {
|
id: Utils.whatsappID(json.wid),
|
||||||
id: Utils.whatsappID(json.wid),
|
name: json.pushname,
|
||||||
name: json.pushname,
|
phone: json.phone,
|
||||||
phone: json.phone,
|
imgUrl: null
|
||||||
imgUrl: null
|
}) as WAUser
|
||||||
}
|
|
||||||
return this.user
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!json.secret) {
|
if (!json.secret) {
|
||||||
// if we didn't get a secret, we don't need it, we're validated
|
// if we didn't get a secret, we don't need it, we're validated
|
||||||
return onValidationSuccess()
|
return onValidationSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
const secret = Buffer.from(json.secret, 'base64')
|
const secret = Buffer.from(json.secret, 'base64')
|
||||||
if (secret.length !== 144) {
|
if (secret.length !== 144) {
|
||||||
throw new Error ('incorrect secret length received: ' + secret.length)
|
throw new Error ('incorrect secret length received: ' + secret.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate shared key from our private key & the secret shared by the server
|
// generate shared key from our private key & the secret shared by the server
|
||||||
const sharedKey = Curve.sharedKey(this.curveKeys.private, secret.slice(0, 32))
|
const sharedKey = Curve.sharedKey(this.curveKeys.private, secret.slice(0, 32))
|
||||||
// expand the key to 80 bytes using HKDF
|
// expand the key to 80 bytes using HKDF
|
||||||
@@ -118,28 +119,28 @@ export class WAConnection extends Base {
|
|||||||
|
|
||||||
const hmac = Utils.hmacSign(hmacValidationMessage, hmacValidationKey)
|
const hmac = Utils.hmacSign(hmacValidationMessage, hmacValidationKey)
|
||||||
|
|
||||||
if (hmac.equals(secret.slice(32, 64))) {
|
if (!hmac.equals(secret.slice(32, 64))) {
|
||||||
// computed HMAC should equal secret[32:64]
|
|
||||||
// expandedKey[64:] + secret[64:] are the keys, encrypted using AES, that are used to encrypt/decrypt the messages recieved from WhatsApp
|
|
||||||
// they are encrypted using key: expandedKey[0:32]
|
|
||||||
const encryptedAESKeys = Buffer.concat([
|
|
||||||
expandedKey.slice(64, expandedKey.length),
|
|
||||||
secret.slice(64, secret.length),
|
|
||||||
])
|
|
||||||
const decryptedKeys = Utils.aesDecrypt(encryptedAESKeys, expandedKey.slice(0, 32))
|
|
||||||
// set the credentials
|
|
||||||
this.authInfo = {
|
|
||||||
encKey: decryptedKeys.slice(0, 32), // first 32 bytes form the key to encrypt/decrypt messages
|
|
||||||
macKey: decryptedKeys.slice(32, 64), // last 32 bytes from the key to sign messages
|
|
||||||
clientToken: json.clientToken,
|
|
||||||
serverToken: json.serverToken,
|
|
||||||
clientID: this.authInfo.clientID,
|
|
||||||
}
|
|
||||||
return onValidationSuccess()
|
|
||||||
} else {
|
|
||||||
// if the checksums didn't match
|
// if the checksums didn't match
|
||||||
throw new BaileysError ('HMAC validation failed', json)
|
throw new BaileysError ('HMAC validation failed', json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// computed HMAC should equal secret[32:64]
|
||||||
|
// expandedKey[64:] + secret[64:] are the keys, encrypted using AES, that are used to encrypt/decrypt the messages recieved from WhatsApp
|
||||||
|
// they are encrypted using key: expandedKey[0:32]
|
||||||
|
const encryptedAESKeys = Buffer.concat([
|
||||||
|
expandedKey.slice(64, expandedKey.length),
|
||||||
|
secret.slice(64, secret.length),
|
||||||
|
])
|
||||||
|
const decryptedKeys = Utils.aesDecrypt(encryptedAESKeys, expandedKey.slice(0, 32))
|
||||||
|
// set the credentials
|
||||||
|
this.authInfo = {
|
||||||
|
encKey: decryptedKeys.slice(0, 32), // first 32 bytes form the key to encrypt/decrypt messages
|
||||||
|
macKey: decryptedKeys.slice(32, 64), // last 32 bytes from the key to sign messages
|
||||||
|
clientToken: json.clientToken,
|
||||||
|
serverToken: json.serverToken,
|
||||||
|
clientID: this.authInfo.clientID,
|
||||||
|
}
|
||||||
|
return onValidationSuccess()
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* When logging back in (restoring a previously closed session), WhatsApp may challenge one to check if one still has the encryption keys
|
* When logging back in (restoring a previously closed session), WhatsApp may challenge one to check if one still has the encryption keys
|
||||||
|
|||||||
@@ -47,10 +47,9 @@ export class WAConnection extends Base {
|
|||||||
this.phoneConnected = true
|
this.phoneConnected = true
|
||||||
this.state = 'open'
|
this.state = 'open'
|
||||||
|
|
||||||
this.user.imgUrl = await this.getProfilePicture (this.user.id).catch (err => '')
|
|
||||||
this.registerPhoneConnectionPoll ()
|
|
||||||
|
|
||||||
this.emit ('open')
|
this.emit ('open')
|
||||||
|
|
||||||
|
this.registerPhoneConnectionPoll ()
|
||||||
this.releasePendingRequests ()
|
this.releasePendingRequests ()
|
||||||
|
|
||||||
this.log ('opened connection to WhatsApp Web', MessageLogLevel.info)
|
this.log ('opened connection to WhatsApp Web', MessageLogLevel.info)
|
||||||
@@ -64,21 +63,14 @@ export class WAConnection extends Base {
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** Get the URL to download the profile picture of a person/group */
|
|
||||||
async getProfilePicture(jid: string | null) {
|
|
||||||
const response = await this.query({ json: ['query', 'ProfilePicThumb', jid || this.user.id] })
|
|
||||||
return response.eurl as string
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Sets up callbacks to receive chats, contacts & messages.
|
* Sets up callbacks to receive chats, contacts & messages.
|
||||||
* Must be called immediately after connect
|
* Must be called immediately after connect
|
||||||
* @returns [chats, contacts]
|
* @returns [chats, contacts]
|
||||||
*/
|
*/
|
||||||
protected async receiveChatsAndContacts(timeoutMs: number = null, stopAfterMostRecentMessage: boolean=false) {
|
protected async receiveChatsAndContacts(timeoutMs: number = null, stopAfterMostRecentMessage: boolean=false) {
|
||||||
this.contacts = {}
|
|
||||||
this.chats.clear ()
|
this.chats.clear ()
|
||||||
|
|
||||||
let receivedContacts = false
|
|
||||||
let receivedMessages = false
|
let receivedMessages = false
|
||||||
|
|
||||||
let resolveTask: () => void
|
let resolveTask: () => void
|
||||||
@@ -90,12 +82,7 @@ export class WAConnection extends Base {
|
|||||||
this.deregisterCallback(['action', 'add:unread'])
|
this.deregisterCallback(['action', 'add:unread'])
|
||||||
}
|
}
|
||||||
this.deregisterCallback(['response', 'type:chat'])
|
this.deregisterCallback(['response', 'type:chat'])
|
||||||
this.deregisterCallback(['response', 'type:contacts'])
|
}
|
||||||
}
|
|
||||||
const checkForResolution = () => {
|
|
||||||
if (receivedContacts && receivedMessages) resolveTask ()
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for messages to load
|
// wait for messages to load
|
||||||
const chatUpdate = json => {
|
const chatUpdate = json => {
|
||||||
receivedMessages = true
|
receivedMessages = true
|
||||||
@@ -110,7 +97,7 @@ export class WAConnection extends Base {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// if received contacts before messages
|
// if received contacts before messages
|
||||||
if (isLast && receivedContacts) checkForResolution ()
|
if (isLast) resolveTask ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for actual messages to load, "last" is the most recent message, "before" contains prior messages
|
// wait for actual messages to load, "last" is the most recent message, "before" contains prior messages
|
||||||
@@ -121,10 +108,9 @@ export class WAConnection extends Base {
|
|||||||
}
|
}
|
||||||
// get chats
|
// get chats
|
||||||
this.registerCallback(['response', 'type:chat'], json => {
|
this.registerCallback(['response', 'type:chat'], json => {
|
||||||
if (json[1].duplicate || !json[2]) return
|
if (json[1].duplicate) return
|
||||||
|
|
||||||
json[2]
|
json[2]?.forEach(([item, chat]: [any, WAChat]) => {
|
||||||
.forEach(([item, chat]: [any, WAChat]) => {
|
|
||||||
if (!chat) {
|
if (!chat) {
|
||||||
this.log (`unexpectedly got null chat: ${item}, ${chat}`, MessageLogLevel.info)
|
this.log (`unexpectedly got null chat: ${item}, ${chat}`, MessageLogLevel.info)
|
||||||
return
|
return
|
||||||
@@ -140,23 +126,14 @@ export class WAConnection extends Base {
|
|||||||
this.chats.insert (chat) // chats data (log json to see what it looks like)
|
this.chats.insert (chat) // chats data (log json to see what it looks like)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.log ('received chats list', MessageLogLevel.info)
|
this.log (`received ${this.chats.all().length} chats`, MessageLogLevel.info)
|
||||||
|
// if there are no chats
|
||||||
|
if (this.chats.all().length === 0) {
|
||||||
|
receivedMessages = true
|
||||||
|
resolveTask ()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
// get contacts
|
|
||||||
this.registerCallback(['response', 'type:contacts'], json => {
|
|
||||||
if (json[1].duplicate) return
|
|
||||||
|
|
||||||
receivedContacts = true
|
|
||||||
|
|
||||||
json[2].forEach(([type, contact]: ['user', WAContact]) => {
|
|
||||||
if (!contact) return this.log (`unexpectedly got null contact: ${type}, ${contact}`, MessageLogLevel.info)
|
|
||||||
|
|
||||||
contact.jid = Utils.whatsappID (contact.jid)
|
|
||||||
this.contacts[contact.jid] = contact
|
|
||||||
})
|
|
||||||
this.log ('received contacts list', MessageLogLevel.info)
|
|
||||||
checkForResolution ()
|
|
||||||
})
|
|
||||||
// wait for the chats & contacts to load
|
// wait for the chats & contacts to load
|
||||||
await Utils.promiseTimeout (timeoutMs, (resolve, reject) => {
|
await Utils.promiseTimeout (timeoutMs, (resolve, reject) => {
|
||||||
resolveTask = resolve
|
resolveTask = resolve
|
||||||
@@ -167,13 +144,6 @@ export class WAConnection extends Base {
|
|||||||
this.on ('close', rejectTask)
|
this.on ('close', rejectTask)
|
||||||
})
|
})
|
||||||
.finally (deregisterCallbacks)
|
.finally (deregisterCallbacks)
|
||||||
|
|
||||||
this.chats
|
|
||||||
.all ()
|
|
||||||
.forEach (chat => {
|
|
||||||
const respectiveContact = this.contacts[chat.jid]
|
|
||||||
chat.name = respectiveContact?.name || respectiveContact?.notify || chat.name
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
private releasePendingRequests () {
|
private releasePendingRequests () {
|
||||||
this.pendingRequests.forEach (({resolve}) => resolve()) // send off all pending request
|
this.pendingRequests.forEach (({resolve}) => resolve()) // send off all pending request
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as QR from 'qrcode-terminal'
|
import * as QR from 'qrcode-terminal'
|
||||||
import { WAConnection as Base } from './3.Connect'
|
import { WAConnection as Base } from './3.Connect'
|
||||||
import { MessageStatusUpdate, WAMessage, WAContact, WAChat, WAMessageProto, WA_MESSAGE_STUB_TYPE, WA_MESSAGE_STATUS_TYPE, MessageLogLevel, PresenceUpdate, BaileysEvent, DisconnectReason, WANode } from './Constants'
|
import { WAMessageStatusUpdate, WAMessage, WAContact, WAChat, WAMessageProto, WA_MESSAGE_STUB_TYPE, WA_MESSAGE_STATUS_TYPE, MessageLogLevel, PresenceUpdate, BaileysEvent, DisconnectReason, WANode } from './Constants'
|
||||||
import { whatsappID, unixTimestampSeconds, isGroupID } from './Utils'
|
import { whatsappID, unixTimestampSeconds, isGroupID } from './Utils'
|
||||||
|
|
||||||
export class WAConnection extends Base {
|
export class WAConnection extends Base {
|
||||||
@@ -30,8 +30,7 @@ export class WAConnection extends Base {
|
|||||||
if (node) {
|
if (node) {
|
||||||
const user = node[1] as WAContact
|
const user = node[1] as WAContact
|
||||||
user.jid = whatsappID(user.jid)
|
user.jid = whatsappID(user.jid)
|
||||||
this.contacts[user.jid] = user
|
|
||||||
|
|
||||||
const chat = this.chats.get (user.jid)
|
const chat = this.chats.get (user.jid)
|
||||||
if (chat) {
|
if (chat) {
|
||||||
chat.name = user.name || user.notify
|
chat.name = user.name || user.notify
|
||||||
@@ -104,6 +103,19 @@ export class WAConnection extends Base {
|
|||||||
|
|
||||||
this.emit ('chat-update', { jid: chat.jid, count: chat.count })
|
this.emit ('chat-update', { jid: chat.jid, count: chat.count })
|
||||||
})
|
})
|
||||||
|
// get contacts
|
||||||
|
this.registerCallback(['response', 'type:contacts'], json => {
|
||||||
|
if (json[1].duplicate || !json[2]) return
|
||||||
|
|
||||||
|
const contacts: {[k: string]: WAContact} = {}
|
||||||
|
json[2].forEach(([type, contact]: ['user', WAContact]) => {
|
||||||
|
if (!contact) return this.log (`unexpectedly got null contact: ${type}, ${contact}`, MessageLogLevel.info)
|
||||||
|
|
||||||
|
contact.jid = whatsappID (contact.jid)
|
||||||
|
contacts[contact.jid] = contact
|
||||||
|
})
|
||||||
|
this.emit ('contacts-received', contacts)
|
||||||
|
})
|
||||||
/*// genetic chat action
|
/*// genetic chat action
|
||||||
this.registerCallback (['Chat', 'cmd:action'], json => {
|
this.registerCallback (['Chat', 'cmd:action'], json => {
|
||||||
const data = json[1].data as WANode
|
const data = json[1].data as WANode
|
||||||
@@ -118,6 +130,11 @@ export class WAConnection extends Base {
|
|||||||
|
|
||||||
this.on ('qr', qr => QR.generate(qr, { small: true }))
|
this.on ('qr', qr => QR.generate(qr, { small: true }))
|
||||||
}
|
}
|
||||||
|
/** Get the URL to download the profile picture of a person/group */
|
||||||
|
async getProfilePicture(jid: string | null) {
|
||||||
|
const response = await this.query({ json: ['query', 'ProfilePicThumb', jid || this.user.id] })
|
||||||
|
return response.eurl as string
|
||||||
|
}
|
||||||
/** Set the callback for message status updates (when a message is delivered, read etc.) */
|
/** Set the callback for message status updates (when a message is delivered, read etc.) */
|
||||||
protected registerOnMessageStatusChange() {
|
protected registerOnMessageStatusChange() {
|
||||||
const func = json => {
|
const func = json => {
|
||||||
@@ -126,7 +143,7 @@ export class WAConnection extends Base {
|
|||||||
|
|
||||||
if (json.cmd === 'ack') ids = [json.id]
|
if (json.cmd === 'ack') ids = [json.id]
|
||||||
|
|
||||||
const update: MessageStatusUpdate = {
|
const update: WAMessageStatusUpdate = {
|
||||||
from: json.from,
|
from: json.from,
|
||||||
to: json.to,
|
to: json.to,
|
||||||
participant: json.participant,
|
participant: json.participant,
|
||||||
@@ -138,7 +155,7 @@ export class WAConnection extends Base {
|
|||||||
const chat = this.chats.get( whatsappID(update.to) )
|
const chat = this.chats.get( whatsappID(update.to) )
|
||||||
if (!chat) return
|
if (!chat) return
|
||||||
|
|
||||||
this.emit ('message-update', update)
|
this.emit ('message-status-update', update)
|
||||||
this.chatUpdatedMessage (update.ids, update.type as number, chat)
|
this.chatUpdatedMessage (update.ids, update.type as number, chat)
|
||||||
}
|
}
|
||||||
this.registerCallback('Msg', func)
|
this.registerCallback('Msg', func)
|
||||||
@@ -199,14 +216,8 @@ export class WAConnection extends Base {
|
|||||||
|
|
||||||
found.messageStubType = WA_MESSAGE_STUB_TYPE.REVOKE
|
found.messageStubType = WA_MESSAGE_STUB_TYPE.REVOKE
|
||||||
found.message = null
|
found.message = null
|
||||||
const update: MessageStatusUpdate = {
|
|
||||||
from: this.user.id,
|
this.emit ('message-update', found)
|
||||||
to: message.key.remoteJid,
|
|
||||||
ids: [message.key.id],
|
|
||||||
timestamp: new Date(),
|
|
||||||
type: 'delete'
|
|
||||||
}
|
|
||||||
this.emit ('message-update', update)
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@@ -294,14 +305,18 @@ export class WAConnection extends Base {
|
|||||||
on (event: 'user-presence-update', listener: (update: PresenceUpdate) => void): this
|
on (event: 'user-presence-update', listener: (update: PresenceUpdate) => void): this
|
||||||
/** when a user's status is updated */
|
/** when a user's status is updated */
|
||||||
on (event: 'user-status-update', listener: (update: {jid: string, status?: string}) => void): this
|
on (event: 'user-status-update', listener: (update: {jid: string, status?: string}) => void): this
|
||||||
|
/** when a user receives contacts */
|
||||||
|
on (event: 'contacts-received', listener: (contacts: {[k: string]: WAContact}) => void): this
|
||||||
/** when a new chat is added */
|
/** when a new chat is added */
|
||||||
on (event: 'chat-new', listener: (chat: WAChat) => void): this
|
on (event: 'chat-new', listener: (chat: WAChat) => void): this
|
||||||
/** when a chat is updated (archived, deleted, pinned) */
|
/** when a chat is updated (archived, deleted, pinned) */
|
||||||
on (event: 'chat-update', listener: (chat: Partial<WAChat> & { jid: string }) => void): this
|
on (event: 'chat-update', listener: (chat: Partial<WAChat> & { jid: string }) => void): this
|
||||||
/** when a new message is relayed */
|
/** when a new message is relayed */
|
||||||
on (event: 'message-new', listener: (message: WAMessage) => void): this
|
on (event: 'message-new', listener: (message: WAMessage) => void): this
|
||||||
/** when a message is updated (deleted, delivered, read, sent etc.) */
|
/** when a message object itself is updated (receives its media info or is deleted) */
|
||||||
on (event: 'message-update', listener: (message: MessageStatusUpdate) => void): this
|
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 */
|
/** when participants are added to a group */
|
||||||
on (event: 'group-participants-add', listener: (update: {jid: string, participants: string[], actor?: string}) => void): this
|
on (event: 'group-participants-add', listener: (update: {jid: string, participants: string[], actor?: string}) => void): this
|
||||||
/** when participants are removed or leave from a group */
|
/** when participants are removed or leave from a group */
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ export interface MessageInfo {
|
|||||||
reads: {jid: string, t: string}[]
|
reads: {jid: string, t: string}[]
|
||||||
deliveries: {jid: string, t: string}[]
|
deliveries: {jid: string, t: string}[]
|
||||||
}
|
}
|
||||||
export interface MessageStatusUpdate {
|
export interface WAMessageStatusUpdate {
|
||||||
from: string
|
from: string
|
||||||
to: string
|
to: string
|
||||||
/** Which participant caused the update (only for groups) */
|
/** Which participant caused the update (only for groups) */
|
||||||
@@ -296,7 +296,7 @@ export interface MessageStatusUpdate {
|
|||||||
/** Message IDs read/delivered */
|
/** Message IDs read/delivered */
|
||||||
ids: string[]
|
ids: string[]
|
||||||
/** Status of the Message IDs */
|
/** Status of the Message IDs */
|
||||||
type: WA_MESSAGE_STATUS_TYPE | 'delete'
|
type: WA_MESSAGE_STATUS_TYPE
|
||||||
}
|
}
|
||||||
export enum GroupSettingChange {
|
export enum GroupSettingChange {
|
||||||
messageSend = 'announcement',
|
messageSend = 'announcement',
|
||||||
@@ -338,10 +338,12 @@ export type BaileysEvent =
|
|||||||
'connection-phone-change' |
|
'connection-phone-change' |
|
||||||
'user-presence-update' |
|
'user-presence-update' |
|
||||||
'user-status-update' |
|
'user-status-update' |
|
||||||
|
'contacts-received' |
|
||||||
'chat-new' |
|
'chat-new' |
|
||||||
'chat-update' |
|
'chat-update' |
|
||||||
'message-new' |
|
'message-new' |
|
||||||
'message-update' |
|
'message-update' |
|
||||||
|
'message-status-update' |
|
||||||
'group-participants-add' |
|
'group-participants-add' |
|
||||||
'group-participants-remove' |
|
'group-participants-remove' |
|
||||||
'group-participants-promote' |
|
'group-participants-promote' |
|
||||||
|
|||||||
Reference in New Issue
Block a user