protobuf uniformity + messages bug fix

This commit is contained in:
Adhiraj
2020-08-31 16:02:09 +05:30
parent 83a45939ef
commit cadd34bc0e
4 changed files with 81 additions and 61 deletions

View File

@@ -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 * as assert from 'assert'
import { WAConnectionTest, testJid, sendAndRetreiveMessage } from './Common'
WAConnectionTest('Messages', (conn) => {
WAConnectionTest('Messages', conn => {
it('should send a text message', async () => {
//const message = await sendAndRetreiveMessage(conn, 'hello fren', MessageType.text)
//assert.strictEqual(message.message.conversation || message.message.extendedTextMessage?.text, 'hello fren')
const message = await sendAndRetreiveMessage(conn, 'hello fren', MessageType.text)
assert.strictEqual(message.message.conversation || message.message.extendedTextMessage?.text, 'hello fren')
})
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)
messages = await conn.loadMessages (testJid, 1)
const message = messages[0]
messages = (await conn.loadMessages (testJid, 1)).messages
const message = messages.slice (-1)[0]
const content = message.message[ Object.keys(message.message)[0] ]
assert.equal (content?.contextInfo?.isForwarded, true)
})
@@ -25,7 +25,7 @@ WAConnectionTest('Messages', (conn) => {
assert.strictEqual(received.text, content.text)
assert.ok (received.canonicalUrl)
assert.ok (received.title)
assert.ok (received.jpegThumbnail)
assert.ok (received.description)
})
it('should quote a message', async () => {
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)
})
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 message = await sendAndRetreiveMessage(conn, content, MessageType.image, { quoted: messages[0] })
@@ -65,12 +65,21 @@ WAConnectionTest('Messages', (conn) => {
await conn.deleteMessage (testJid, message.key)
})
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 conn.clearMessage (messages[0].key)
})
})
WAConnectionTest('Message Events', (conn) => {
it('should fail to send a text message', done => {
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 () => {
const waitForUpdate =
promiseTimeout(15000, resolve => {

View File

@@ -7,11 +7,16 @@ export class WAConnection extends Base {
constructor () {
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)
this.registerCallback (['action', 'add:update', 'message'], json => {
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.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
this.registerCallback (['Chat', 'cmd:action'], json => {
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 */
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
}
/** Set the callback for message status updates (when a message is delivered, read etc.) */
protected registerOnMessageStatusChange() {
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,
}
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))
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 as number, chat)
}
/** inserts an empty chat into the DB */
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) {
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
}
}

View File

@@ -34,7 +34,7 @@ export class WAConnection extends Base {
requestPresenceUpdate = async (jid: string) => this.query({json: ['action', 'presence', 'subscribe', jid]})
/** Query the status of the person (see groupMetadata() for groups) */
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
}
async setStatus (status: string) {
@@ -53,7 +53,7 @@ export class WAConnection extends Base {
/** Get your contacts */
async getContacts() {
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
}
/** Get the stories of your contacts */
@@ -74,7 +74,7 @@ export class WAConnection extends Base {
/** Fetch your chats */
async getChats() {
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 */
async getBroadcastListInfo(jid: string) { return this.query({json: ['query', 'contact', jid], expect200: true}) as Promise<WABroadcastListInfo> }

View File

@@ -10,7 +10,7 @@ import {
WALocationMessage,
WAContactMessage,
WATextMessage,
WAMessageContent, WAMetric, WAFlag, WAMessage, BaileysError, MessageLogLevel, WA_MESSAGE_STATUS_TYPE
WAMessageContent, WAMetric, WAFlag, WAMessage, BaileysError, MessageLogLevel, WA_MESSAGE_STATUS_TYPE, WAMessageProto
} from './Constants'
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)
break
}
return m
return WAMessageProto.Message.create (m)
}
/** Prepare a media message for sending */
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,
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() */
async relayWAMessage(message: WAMessage) {
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
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)
}
/**