mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
protobuf uniformity + messages bug fix
This commit is contained in:
@@ -1,19 +1,19 @@
|
|||||||
import { MessageType, Mimetype, delay, promiseTimeout, WAMessage, WA_MESSAGE_STATUS_TYPE, WAMessageStatusUpdate } from '../WAConnection/WAConnection'
|
import { MessageType, Mimetype, delay, promiseTimeout, WAMessage, WA_MESSAGE_STATUS_TYPE, WAMessageStatusUpdate, MessageLogLevel } 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'
|
||||||
|
|
||||||
WAConnectionTest('Messages', (conn) => {
|
WAConnectionTest('Messages', conn => {
|
||||||
it('should send a text message', async () => {
|
it('should send a text message', async () => {
|
||||||
//const message = await sendAndRetreiveMessage(conn, 'hello fren', MessageType.text)
|
const message = await sendAndRetreiveMessage(conn, 'hello fren', MessageType.text)
|
||||||
//assert.strictEqual(message.message.conversation || message.message.extendedTextMessage?.text, 'hello fren')
|
assert.strictEqual(message.message.conversation || message.message.extendedTextMessage?.text, 'hello fren')
|
||||||
})
|
})
|
||||||
it('should forward a message', async () => {
|
it('should forward a message', async () => {
|
||||||
let messages = await conn.loadMessages (testJid, 1)
|
let {messages} = await conn.loadMessages (testJid, 1)
|
||||||
await conn.forwardMessage (testJid, messages[0], true)
|
await conn.forwardMessage (testJid, messages[0], true)
|
||||||
|
|
||||||
messages = await conn.loadMessages (testJid, 1)
|
messages = (await conn.loadMessages (testJid, 1)).messages
|
||||||
const message = messages[0]
|
const message = messages.slice (-1)[0]
|
||||||
const content = message.message[ Object.keys(message.message)[0] ]
|
const content = message.message[ Object.keys(message.message)[0] ]
|
||||||
assert.equal (content?.contextInfo?.isForwarded, true)
|
assert.equal (content?.contextInfo?.isForwarded, true)
|
||||||
})
|
})
|
||||||
@@ -25,7 +25,7 @@ WAConnectionTest('Messages', (conn) => {
|
|||||||
assert.strictEqual(received.text, content.text)
|
assert.strictEqual(received.text, content.text)
|
||||||
assert.ok (received.canonicalUrl)
|
assert.ok (received.canonicalUrl)
|
||||||
assert.ok (received.title)
|
assert.ok (received.title)
|
||||||
assert.ok (received.jpegThumbnail)
|
assert.ok (received.description)
|
||||||
})
|
})
|
||||||
it('should quote a message', async () => {
|
it('should quote a message', async () => {
|
||||||
const {messages} = await conn.loadMessages(testJid, 2)
|
const {messages} = await conn.loadMessages(testJid, 2)
|
||||||
@@ -52,7 +52,7 @@ WAConnectionTest('Messages', (conn) => {
|
|||||||
//const message2 = await sendAndRetreiveMessage (conn, 'this is a quote', MessageType.extendedText)
|
//const message2 = await sendAndRetreiveMessage (conn, 'this is a quote', MessageType.extendedText)
|
||||||
})
|
})
|
||||||
it('should send an image & quote', async () => {
|
it('should send an image & quote', async () => {
|
||||||
const messages = await conn.loadMessages(testJid, 1)
|
const {messages} = await conn.loadMessages(testJid, 1)
|
||||||
const content = await fs.readFile('./Media/meme.jpeg')
|
const content = await fs.readFile('./Media/meme.jpeg')
|
||||||
const message = await sendAndRetreiveMessage(conn, content, MessageType.image, { quoted: messages[0] })
|
const message = await sendAndRetreiveMessage(conn, content, MessageType.image, { quoted: messages[0] })
|
||||||
|
|
||||||
@@ -65,12 +65,21 @@ WAConnectionTest('Messages', (conn) => {
|
|||||||
await conn.deleteMessage (testJid, message.key)
|
await conn.deleteMessage (testJid, message.key)
|
||||||
})
|
})
|
||||||
it('should clear the most recent message', async () => {
|
it('should clear the most recent message', async () => {
|
||||||
const messages = await conn.loadMessages (testJid, 1)
|
const {messages} = await conn.loadMessages (testJid, 1)
|
||||||
await delay (2000)
|
await delay (2000)
|
||||||
await conn.clearMessage (messages[0].key)
|
await conn.clearMessage (messages[0].key)
|
||||||
})
|
})
|
||||||
})
|
it('should fail to send a text message', done => {
|
||||||
WAConnectionTest('Message Events', (conn) => {
|
const JID = '1234-1234@g.us'
|
||||||
|
conn.sendMessage(JID, 'hello', MessageType.text)
|
||||||
|
|
||||||
|
conn.on ('message-status-update', update => {
|
||||||
|
if (update.to === JID) {
|
||||||
|
assert.equal (update.type, WA_MESSAGE_STATUS_TYPE.ERROR)
|
||||||
|
done ()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
it('should deliver a message', async () => {
|
it('should deliver a message', async () => {
|
||||||
const waitForUpdate =
|
const waitForUpdate =
|
||||||
promiseTimeout(15000, resolve => {
|
promiseTimeout(15000, resolve => {
|
||||||
|
|||||||
@@ -7,11 +7,16 @@ export class WAConnection extends Base {
|
|||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super ()
|
super ()
|
||||||
|
|
||||||
this.registerOnMessageStatusChange ()
|
|
||||||
this.registerOnUnreadMessage ()
|
|
||||||
this.registerOnPresenceUpdate ()
|
|
||||||
|
|
||||||
|
// new messages
|
||||||
|
this.registerCallback(['action', 'add:relay', 'message'], json => {
|
||||||
|
const message = json[2][0][2] as WAMessage
|
||||||
|
this.chatAddMessageAppropriate (message)
|
||||||
|
})
|
||||||
|
// presence updates
|
||||||
|
this.registerCallback('Presence', json => (
|
||||||
|
this.emit('user-presence-update', json[1] as PresenceUpdate)
|
||||||
|
))
|
||||||
// If a message has been updated (usually called when a video message gets its upload url)
|
// If a message has been updated (usually called when a video message gets its upload url)
|
||||||
this.registerCallback (['action', 'add:update', 'message'], json => {
|
this.registerCallback (['action', 'add:update', 'message'], json => {
|
||||||
const message: WAMessage = json[2][0][2]
|
const message: WAMessage = json[2][0][2]
|
||||||
@@ -105,6 +110,40 @@ 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 })
|
||||||
})
|
})
|
||||||
|
this.registerCallback (['action', 'add:relay', 'received'], json => {
|
||||||
|
json = json[2][0][1]
|
||||||
|
if (json.type === 'error') {
|
||||||
|
const update: WAMessageStatusUpdate = {
|
||||||
|
from: this.user.jid,
|
||||||
|
to: 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: json.from,
|
||||||
|
to: json.to,
|
||||||
|
participant: json.participant,
|
||||||
|
timestamp: new Date(json.t * 1000),
|
||||||
|
ids: ids,
|
||||||
|
type: (+json.ack)+1,
|
||||||
|
}
|
||||||
|
this.forwardStatusUpdate (update)
|
||||||
|
}
|
||||||
|
this.registerCallback('Msg', func)
|
||||||
|
this.registerCallback('MsgInfo', func)
|
||||||
/*// 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
|
||||||
@@ -121,44 +160,15 @@ export class WAConnection extends Base {
|
|||||||
}
|
}
|
||||||
/** Get the URL to download the profile picture of a person/group */
|
/** Get the URL to download the profile picture of a person/group */
|
||||||
async getProfilePicture(jid: string | null) {
|
async getProfilePicture(jid: string | null) {
|
||||||
const response = await this.query({ json: ['query', 'ProfilePicThumb', jid || this.user.jid] })
|
const response = await this.query({ json: ['query', 'ProfilePicThumb', jid || this.user.jid], expect200: true })
|
||||||
return response.eurl as string
|
return response.eurl as string
|
||||||
}
|
}
|
||||||
/** Set the callback for message status updates (when a message is delivered, read etc.) */
|
protected forwardStatusUpdate (update: WAMessageStatusUpdate) {
|
||||||
protected registerOnMessageStatusChange() {
|
const chat = this.chats.get( whatsappID(update.to) )
|
||||||
const func = json => {
|
if (!chat) return
|
||||||
json = json[1]
|
|
||||||
let ids = json.id
|
this.emit ('message-status-update', update)
|
||||||
|
this.chatUpdatedMessage (update.ids, update.type as number, chat)
|
||||||
if (json.cmd === 'ack') ids = [json.id]
|
|
||||||
|
|
||||||
const update: WAMessageStatusUpdate = {
|
|
||||||
from: json.from,
|
|
||||||
to: json.to,
|
|
||||||
participant: json.participant,
|
|
||||||
timestamp: new Date(json.t * 1000),
|
|
||||||
ids: ids,
|
|
||||||
type: (+json.ack)+1,
|
|
||||||
}
|
|
||||||
|
|
||||||
const chat = this.chats.get( whatsappID(update.to) )
|
|
||||||
if (!chat) return
|
|
||||||
|
|
||||||
this.emit ('message-status-update', update)
|
|
||||||
this.chatUpdatedMessage (update.ids, update.type as number, chat)
|
|
||||||
}
|
|
||||||
this.registerCallback('Msg', func)
|
|
||||||
this.registerCallback('MsgInfo', func)
|
|
||||||
}
|
|
||||||
protected registerOnUnreadMessage() {
|
|
||||||
this.registerCallback(['action', 'add:relay', 'message'], json => {
|
|
||||||
const message = json[2][0][2] as WAMessage
|
|
||||||
this.chatAddMessageAppropriate (message)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/** Set the callback for presence updates; if someone goes offline/online, this callback will be fired */
|
|
||||||
protected registerOnPresenceUpdate() {
|
|
||||||
this.registerCallback('Presence', json => this.emit('user-presence-update', json[1] as PresenceUpdate))
|
|
||||||
}
|
}
|
||||||
/** inserts an empty chat into the DB */
|
/** inserts an empty chat into the DB */
|
||||||
protected async chatAdd (jid: string, name?: string) {
|
protected async chatAdd (jid: string, name?: string) {
|
||||||
@@ -265,10 +275,11 @@ export class WAConnection extends Base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected chatUpdatedMessage (messageIDs: string[], status: number, chat: WAChat) {
|
protected chatUpdatedMessage (messageIDs: string[], status: WA_MESSAGE_STATUS_TYPE, chat: WAChat) {
|
||||||
for (let msg of chat.messages) {
|
for (let msg of chat.messages) {
|
||||||
if (messageIDs.includes(msg.key.id)) {
|
if (messageIDs.includes(msg.key.id)) {
|
||||||
if (isGroupID(chat.jid)) msg.status = WA_MESSAGE_STATUS_TYPE.SERVER_ACK
|
if (status <= WA_MESSAGE_STATUS_TYPE.PENDING) msg.status = status
|
||||||
|
else if (isGroupID(chat.jid)) msg.status = status-1
|
||||||
else msg.status = status
|
else msg.status = status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class WAConnection extends Base {
|
|||||||
requestPresenceUpdate = async (jid: string) => this.query({json: ['action', 'presence', 'subscribe', jid]})
|
requestPresenceUpdate = async (jid: string) => this.query({json: ['action', 'presence', 'subscribe', jid]})
|
||||||
/** Query the status of the person (see groupMetadata() for groups) */
|
/** Query the status of the person (see groupMetadata() for groups) */
|
||||||
async getStatus (jid?: string) {
|
async getStatus (jid?: string) {
|
||||||
const status: { status: string } = await this.query({json: ['query', 'Status', jid || this.user.jid]})
|
const status: { status: string } = await this.query({json: ['query', 'Status', jid || this.user.jid], expect200: true})
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
async setStatus (status: string) {
|
async setStatus (status: string) {
|
||||||
@@ -53,7 +53,7 @@ export class WAConnection extends Base {
|
|||||||
/** Get your contacts */
|
/** Get your contacts */
|
||||||
async getContacts() {
|
async getContacts() {
|
||||||
const json = ['query', { epoch: this.msgCount.toString(), type: 'contacts' }, null]
|
const json = ['query', { epoch: this.msgCount.toString(), type: 'contacts' }, null]
|
||||||
const response = await this.query({ json, binaryTags: [6, WAFlag.ignore] }) // this has to be an encrypted query
|
const response = await this.query({ json, binaryTags: [6, WAFlag.ignore], expect200: true }) // this has to be an encrypted query
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
/** Get the stories of your contacts */
|
/** Get the stories of your contacts */
|
||||||
@@ -74,7 +74,7 @@ export class WAConnection extends Base {
|
|||||||
/** Fetch your chats */
|
/** Fetch your chats */
|
||||||
async getChats() {
|
async getChats() {
|
||||||
const json = ['query', { epoch: this.msgCount.toString(), type: 'chat' }, null]
|
const json = ['query', { epoch: this.msgCount.toString(), type: 'chat' }, null]
|
||||||
return this.query({ json, binaryTags: [5, WAFlag.ignore]}) // this has to be an encrypted query
|
return this.query({ json, binaryTags: [5, WAFlag.ignore], expect200: true }) // this has to be an encrypted query
|
||||||
}
|
}
|
||||||
/** Query broadcast list info */
|
/** Query broadcast list info */
|
||||||
async getBroadcastListInfo(jid: string) { return this.query({json: ['query', 'contact', jid], expect200: true}) as Promise<WABroadcastListInfo> }
|
async getBroadcastListInfo(jid: string) { return this.query({json: ['query', 'contact', jid], expect200: true}) as Promise<WABroadcastListInfo> }
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
WALocationMessage,
|
WALocationMessage,
|
||||||
WAContactMessage,
|
WAContactMessage,
|
||||||
WATextMessage,
|
WATextMessage,
|
||||||
WAMessageContent, WAMetric, WAFlag, WAMessage, BaileysError, MessageLogLevel, WA_MESSAGE_STATUS_TYPE
|
WAMessageContent, WAMetric, WAFlag, WAMessage, BaileysError, MessageLogLevel, WA_MESSAGE_STATUS_TYPE, WAMessageProto
|
||||||
} from './Constants'
|
} from './Constants'
|
||||||
import { generateMessageID, sha256, hmacSign, aesEncrypWithIV, randomBytes, generateThumbnail, getMediaKeys, decodeMediaMessageBuffer, extensionForMediaMessage, whatsappID, unixTimestampSeconds } from './Utils'
|
import { generateMessageID, sha256, hmacSign, aesEncrypWithIV, randomBytes, generateThumbnail, getMediaKeys, decodeMediaMessageBuffer, extensionForMediaMessage, whatsappID, unixTimestampSeconds } from './Utils'
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ export class WAConnection extends Base {
|
|||||||
m = await this.prepareMessageMedia(message as Buffer, type, options)
|
m = await this.prepareMessageMedia(message as Buffer, type, options)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return m
|
return WAMessageProto.Message.create (m)
|
||||||
}
|
}
|
||||||
/** Prepare a media message for sending */
|
/** Prepare a media message for sending */
|
||||||
async prepareMessageMedia(buffer: Buffer, mediaType: MessageType, options: MessageOptions = {}) {
|
async prepareMessageMedia(buffer: Buffer, mediaType: MessageType, options: MessageOptions = {}) {
|
||||||
@@ -177,13 +177,13 @@ export class WAConnection extends Base {
|
|||||||
participant: id.includes('@g.us') ? this.user.jid : null,
|
participant: id.includes('@g.us') ? this.user.jid : null,
|
||||||
status: WA_MESSAGE_STATUS_TYPE.PENDING
|
status: WA_MESSAGE_STATUS_TYPE.PENDING
|
||||||
}
|
}
|
||||||
return messageJSON as WAMessage
|
return WAMessageProto.WebMessageInfo.create (messageJSON)
|
||||||
}
|
}
|
||||||
/** Relay (send) a WAMessage; more advanced functionality to send a built WA Message, you may want to stick with sendMessage() */
|
/** Relay (send) a WAMessage; more advanced functionality to send a built WA Message, you may want to stick with sendMessage() */
|
||||||
async relayWAMessage(message: WAMessage) {
|
async relayWAMessage(message: WAMessage) {
|
||||||
const json = ['action', {epoch: this.msgCount.toString(), type: 'relay'}, [['message', null, message]]]
|
const json = ['action', {epoch: this.msgCount.toString(), type: 'relay'}, [['message', null, message]]]
|
||||||
const flag = message.key.remoteJid === this.user.jid ? WAFlag.acknowledge : WAFlag.ignore // acknowledge when sending message to oneself
|
const flag = message.key.remoteJid === this.user.jid ? WAFlag.acknowledge : WAFlag.ignore // acknowledge when sending message to oneself
|
||||||
await this.query({json, binaryTags: [WAMetric.message, flag], tag: message.key.id})
|
await this.query({json, binaryTags: [WAMetric.message, flag], tag: message.key.id, expect200: true})
|
||||||
await this.chatAddMessageAppropriate (message)
|
await this.chatAddMessageAppropriate (message)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user