Quote Everything Now + Handling more unread messages

This commit is contained in:
Adhiraj
2020-05-20 16:42:47 +05:30
parent 42a3d12236
commit a4903e77ed
7 changed files with 86 additions and 69 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -62,14 +62,15 @@
```
- Send text messages & quote another message using
``` javascript
client.sendTextMessage(id, "oh hello there", quotedMessage)
const options = {quoted: quotedMessage}
client.sendTextMessage(id, "oh hello there", options)
```
``` quotedMessage ``` is a message object
- Send a media (image, video, sticker, pdf) message using
``` javascript
const buffer = fs.readFileSync("example/ma_gif.mp4") // load some gif
const info = {gif: true, caption: "hello!"} // some metadata & caption
client.sendMediaMessage(id, buffer, WhatsAppWeb.MessageType.video, info)
const options = {gif: true, caption: "hello!"} // some metadata & caption
client.sendMediaMessage(id, buffer, WhatsAppWeb.MessageType.video, options)
```
- The thumbnail can be generated automatically for images & stickers. Though, to automatically generate thumbnails for videos, you need to have ``` ffmpeg ``` installed on your system
- ```mediaBuffer``` is just a Buffer containing the contents of the media you want to send
@@ -82,23 +83,25 @@
WhatsAppWeb.MessageType.sticker // a sticker message
]
```
- ```info``` is a JSON object, providing some information about the media. It can have the following __optional__ values:
``` javascript
info = {
caption: "hello there!", // the caption to send with the media (cannot be sent with stickers though)
thumbnail: null, /* has to be a base 64 encoded JPEG if you want to send a custom thumb,
or set to null if you don't want to send a thumbnail.
Do not enter this field if you want to automatically generate a thumb
*/
mimetype: "application/pdf", /* specify the type of media (optional for all media types except documents),
for pdf files => set to "application/pdf",
for txt files => set to "application/txt"
etc.
*/
gif: true // only applicable to video messages, if the video should be treated as a GIF
}
```
- Tested formats: png, jpeg, webp (sticker), mp4, ogg
```options``` is a JSON object, providing some information about the message. It can have the following __optional__ values:
``` javascript
info = {
caption: "hello there!", // (for media messages) the caption to send with the media (cannot be sent with stickers though)
thumbnail: null, /* (for media messages) has to be a base 64 encoded JPEG if you want to send a custom thumb,
or set to null if you don't want to send a thumbnail.
Do not enter this field if you want to automatically generate a thumb
*/
mimetype: "application/pdf", /* (for media messages) specify the type of media (optional for all media types except documents),
for pdf files => set to "application/pdf",
for txt files => set to "application/txt"
etc.
*/
gif: true, // (for video messages) if the video should be treated as a GIF
quoted: quotedMessage, // the message you want to quote (can used with sending all kinds of messages now)
timestamp: Date() // optional, if you want to manually set the timestamp of the message
}
```
``` id ``` is the WhatsApp id of the person or group you're sending the message to.
It must be in the format ```[country code][phone number]@s.whatsapp.net```, for example ```+19999999999@s.whatsapp.net``` for people. For groups, it must be in the format ``` 123456789-123345@g.us ```.
* __Sending Read Receipts__

View File

@@ -36,46 +36,38 @@ module.exports = {
* Send a text message
* @param {string} id the JID of the person/group you're sending the message to
* @param {string} txt the actual text of the message
* @param {object} [quoted] the message you may wanna quote along with this message
* @param {Date} [timestamp] optionally set the timestamp of the message in Unix time MS
* @param {object} [options] some additional options
* @param {object} [options.quoted] the message you may wanna quote along with this message
* @param {Date} [options.timestamp] optionally set the timestamp of the message in Unix time MS
* @return {Promise<[object, object]>}
*/
sendTextMessage: function (id, txt, quoted, timestamp) {
sendTextMessage: function (id, txt, options) {
if (typeof txt !== "string") {
return Promise.reject("expected text to be a string")
}
let message
if (quoted) {
message = {
extendedTextMessage: {
text: txt,
contextInfo: {
participant: quoted.key.remoteJid,
stanzaId: quoted.key.id,
quotedMessage: quoted.message
}
}
}
if (options.quoted) {
message = {extendedTextMessage: { text: txt }}
} else {
message = {conversation: txt}
}
return this.sendMessage(id, message, timestamp)
return this.sendMessage(id, message, options)
},
/**
* Send a media message
* @param {string} id the JID of the person/group you're sending the message to
* @param {Buffer} buffer the buffer of the actual media you're sending
* @param {string} mediaType the type of media, can be one of [imageMessage, documentMessage, stickerMessage, videoMessage]
* @param {Object} [info] object to hold some metadata or caption about the media
* @param {string} [info.caption] caption to go along with the media
* @param {string} [info.thumbnail] base64 encoded thumbnail for the media
* @param {string} [info.mimetype] specify the Mimetype of the media (required for document messages)
* @param {boolean} [info.gif] whether the media is a gif or not, only valid for video messages
* @param {Date} [timestamp] optionally set the timestamp of the message in Unix time MS
* @param {Object} [options] additional information about the message
* @param {string} [options.caption] caption to go along with the media
* @param {string} [options.thumbnail] base64 encoded thumbnail for the media
* @param {string} [options.mimetype] specify the Mimetype of the media (required for document messages)
* @param {boolean} [options.gif] whether the media is a gif or not, only valid for video messages
* @param {object} [options.quoted] the message you may wanna quote along with this message
* @param {Date} [options.timestamp] optionally set the timestamp of the message in Unix time MS
* @return {Promise<[object, object]>}
*/
sendMediaMessage: function (id, buffer, mediaType, info, timestamp) {
sendMediaMessage: function (id, buffer, mediaType, options) {
// path to upload the media
const mediaPathMap = {
imageMessage: "/mms/image",
@@ -92,20 +84,20 @@ module.exports = {
audioMessage: "audio/ogg; codecs=opus",
stickerMessage: "image/webp"
}
if (!info) {
info = {}
if (!options) {
options = {}
}
if (mediaType === "conversation" || mediaType === "extendedTextMessage") {
return Promise.reject("use sendTextMessage() to send text messages")
}
if (mediaType === "documentMessage" && !info.mimetype) {
if (mediaType === "documentMessage" && !options.mimetype) {
return Promise.reject("mimetype required to send a document")
}
if (mediaType === "stickerMessage" && info.caption) {
if (mediaType === "stickerMessage" && options.caption) {
return Promise.reject("cannot send a caption with a sticker")
}
if (!info.mimetype) {
info.mimetype = defaultMimetypeMap[mediaType]
if (!options.mimetype) {
options.mimetype = defaultMimetypeMap[mediaType]
}
// generate a media key
@@ -118,7 +110,7 @@ module.exports = {
// url safe Base64 encode the SHA256 hash of the body
const fileEncSha256B64 = Utils.sha256(body).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '')
return Utils.generateThumbnail(buffer, mediaType, info)
return Utils.generateThumbnail(buffer, mediaType, options)
.then (() => this.query(["query", "mediaConn"])) // send a query JSON to obtain the url & auth token to upload our media
.then (([json,_]) => {
json = json.media_conn
@@ -141,19 +133,19 @@ module.exports = {
.then (url => {
let message = {}
message[mediaType] = {
caption: info.caption,
caption: options.caption,
url: url,
mediaKey: mediaKey.toString('base64'),
mimetype: info.mimetype,
mimetype: options.mimetype,
fileEncSha256: fileEncSha256B64,
fileSha256: fileSha256.toString('base64'),
fileLength: buffer.length,
jpegThumbnail: info.thumbnail
jpegThumbnail: options.thumbnail
}
if (mediaType === "videoMessage" && info.gif) {
message[mediaType].gifPlayback = info.gif
if (mediaType === "videoMessage" && options.gif) {
message[mediaType].gifPlayback = options.gif
}
return this.sendMessage(id, message, timestamp)
return this.sendMessage(id, message, options)
})
},
/**
@@ -161,14 +153,33 @@ module.exports = {
* @private
* @param {string} id who to send the message to
* @param {object} message like, the message
* @param {Date} [timestamp] timestamp for the message
* @param {object} [options] some additional options
* @param {object} [options.quoted] the message you may wanna quote along with this message
* @param {Date} [options.timestamp] timestamp for the message
* @return {Promise<[object, object]>} array of the recieved JSON & the query JSON
*/
sendMessage: function (id, message, timestamp) {
if (!timestamp) { // if no timestamp was provided,
timestamp = new Date() // set timestamp to now
sendMessage: function (id, message, options) {
if (!options.timestamp) { // if no timestamp was provided,
options.timestamp = new Date() // set timestamp to now
}
timestamp = timestamp.getTime()/1000
const timestamp = options.timestamp.getTime()/1000
const quoted = options.quoted
if (quoted) {
const key = Object.keys(message)[0]
const participant = quoted.key.participant || quoted.key.remoteJid
message[key].contextInfo = {
participant: participant,
stanzaId: quoted.key.id,
quotedMessage: quoted.message
}
// if a participant is quoted, then it must be a group
// hence, remoteJid of group must also be entered
if (quoted.key.participant) {
message[key].contextInfo.remoteJid = quoted.key.remoteJid
}
}
console.log(JSON.stringify(quoted))
console.log(JSON.stringify(message))
let messageJSON = {
key: {
@@ -180,13 +191,15 @@ module.exports = {
messageTimestamp: timestamp,
status: "ERROR"
}
if (id.includes ("@g.us")) {
messageJSON.participant = this.userMetaData.id
}
const json = [
"action",
{epoch: this.msgCount.toString(), type: "relay"},
[ ["message", null, messageJSON] ]]
[ ["message", null, messageJSON] ]
]
return this.query(json, [16, 128], null, messageJSON.key.id)
},
/**

View File

@@ -124,12 +124,14 @@ module.exports = {
// de-register the callbacks, so that they don't get called again
this.deregisterCallback (["action", "add:last"])
this.deregisterCallback (["action", "add:before"])
this.deregisterCallback (["action", "add:unread"])
resolve ()
}
}
// wait for actual messages to load, "last" is the most recent message, "before" contains prior messages
this.registerCallback (["action", "add:last"], chatUpdate)
this.registerCallback (["action", "add:before"], chatUpdate)
this.registerCallback (["action", "add:unread"], chatUpdate)
})
const waitForChats = this.registerCallbackOneTime (["response", "type:chat"]).then (json => {
chats = json[2] // chats data (log json to see what it looks like)

BIN
example/.DS_Store vendored

Binary file not shown.

View File

@@ -59,15 +59,14 @@ client.connect (authInfo, 30*1000) // connect or timeout in 30 seconds
.then (() => client.updatePresence(m.key.remoteJid, WhatsAppWeb.Presence.available)) // tell them we're available
.then (() => client.updatePresence(m.key.remoteJid, WhatsAppWeb.Presence.composing)) // tell them we're composing
.then (() => { // send the message
if (Math.random() > 0.5) { // choose at random
return client.sendTextMessage(m.key.remoteJid, "hello!", m) // send a "hello!" & quote the message recieved
let options = {quoted: m}
if (Math.random() > 0.7) { // choose at random
return client.sendTextMessage(m.key.remoteJid, "hello!", options) // send a "hello!" & quote the message recieved
} else {
const buffer = fs.readFileSync("./ma_gif.mp4") // load the gif
const info = {
gif: true, // the video is a gif
caption: "hello!" // the caption
}
return client.sendMediaMessage (m.key.remoteJid, buffer, WhatsAppWeb.MessageType.video, info) // send this gif!
const buffer = fs.readFileSync("example/ma_gif.mp4") // load the gif
options.gif = true // the video is a gif
options.caption = "hello!" // the caption
return client.sendMediaMessage (m.key.remoteJid, buffer, WhatsAppWeb.MessageType.video, options) // send this gif!
}
})
.then (([m, q]) => { // check if it went successfully

BIN
example/meme.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB