mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Bug Fixes + ConversationExtract
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@ node_modules
|
|||||||
auth_info.json
|
auth_info.json
|
||||||
test_pvt.js
|
test_pvt.js
|
||||||
media_decode_tests.js
|
media_decode_tests.js
|
||||||
|
output.csv
|
||||||
|
|||||||
96
ConversationExtract.js
Normal file
96
ConversationExtract.js
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
const WhatsAppWeb = require("./WhatsAppWeb")
|
||||||
|
const fs = require("fs")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract all your WhatsApp conversations & save them to a file
|
||||||
|
* produceAnonData => should the Id of the chat be recorded
|
||||||
|
* */
|
||||||
|
function extractChats (authCreds, outputFile, produceAnonData) {
|
||||||
|
let client = new WhatsAppWeb() // instantiate an instance
|
||||||
|
if (authCreds) { // login if creds are present
|
||||||
|
client.login(authCreds)
|
||||||
|
} else { // create a new connection otherwise
|
||||||
|
client.connect()
|
||||||
|
}
|
||||||
|
// internal extract function
|
||||||
|
const extract = function () {
|
||||||
|
fs.writeFileSync(outputFile, "chat,input,output\n") // write header to file
|
||||||
|
|
||||||
|
let rows = 0
|
||||||
|
let chats = Object.keys(client.chats)
|
||||||
|
|
||||||
|
const extractChat = function (index) {
|
||||||
|
const id = chats[index]
|
||||||
|
console.log("extracting for " + id + "...")
|
||||||
|
|
||||||
|
var curInput = ""
|
||||||
|
var curOutput = ""
|
||||||
|
var lastMessage
|
||||||
|
return client.getAllMessages (id, m => {
|
||||||
|
var text
|
||||||
|
if (!m.message) { // if message not present, return
|
||||||
|
return
|
||||||
|
} else if (m.message.conversation) { // if its a plain text message
|
||||||
|
text = m.message.conversation
|
||||||
|
} else if (m.message.extendedTextMessage && m.message.extendedTextMessage.contextInfo) { // if its a reply to a previous message
|
||||||
|
const mText = m.message.extendedTextMessage.text
|
||||||
|
const quotedMessage = m.message.extendedTextMessage.contextInfo.quotedMessage
|
||||||
|
// if it's like a '.' and the quoted message has no text, then just forget it
|
||||||
|
if (mText.length <= 2 && !quotedMessage.conversation) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if somebody sent like a '.', then the text should be the quoted message
|
||||||
|
if (mText.length <= 2) {
|
||||||
|
text = quotedMessage.conversation
|
||||||
|
} else { // otherwise just use this text
|
||||||
|
text = mText
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if the person who sent the message has switched, flush the row
|
||||||
|
if (lastMessage && !m.key.fromMe && lastMessage.key.fromMe) {
|
||||||
|
|
||||||
|
let row = "" + (produceAnonData ? "" : id) + ",\"" + curInput + "\",\"" + curOutput + "\"\n"
|
||||||
|
fs.appendFileSync (outputFile, row)
|
||||||
|
rows += 1
|
||||||
|
curInput = ""
|
||||||
|
curOutput = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.key.fromMe) {
|
||||||
|
curOutput += curOutput === "" ? text : ("\n"+text)
|
||||||
|
} else {
|
||||||
|
curInput += curInput === "" ? text : ("\n"+text)
|
||||||
|
}
|
||||||
|
|
||||||
|
lastMessage = m
|
||||||
|
}, 50, "after") // load from the start, in chunks of 50
|
||||||
|
.then (() => console.log("finished extraction for " + id))
|
||||||
|
.then (() => {
|
||||||
|
if (index+1 < chats.length) {
|
||||||
|
return extractChat(index+1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
extractChat(0)
|
||||||
|
.then (() => {
|
||||||
|
console.log("extracted all; total " + rows + " rows")
|
||||||
|
client.disconnect ()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
client.handlers.onConnected = () => {
|
||||||
|
// start extracting 4 seconds after the connection
|
||||||
|
setTimeout(extract, 4000)
|
||||||
|
}
|
||||||
|
client.handlers.onUnreadMessage = (message) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
client.handlers.onError = (error) => {
|
||||||
|
console.log("got error: " + error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let creds = JSON.parse(fs.readFileSync("auth_info.json"))
|
||||||
|
extractChats(creds, "output.csv", true)
|
||||||
@@ -28,10 +28,10 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
{epoch: this.msgCount.toString(), type: "contacts"},
|
{epoch: this.msgCount.toString(), type: "contacts"},
|
||||||
null
|
null
|
||||||
]
|
]
|
||||||
return this.query(json, true) // this has to be an encrypted query
|
return this.query(json, [10, 64]) // this has to be an encrypted query
|
||||||
}
|
}
|
||||||
// load messages from a group or sender
|
// load messages from a group or sender
|
||||||
WhatsAppWeb.prototype.getMessages = function (jid, count, beforeMessage=null) {
|
WhatsAppWeb.prototype.getMessages = function (jid, count, indexMessage=null, mode="before") {
|
||||||
// construct JSON
|
// construct JSON
|
||||||
let json = [
|
let json = [
|
||||||
"query",
|
"query",
|
||||||
@@ -39,34 +39,44 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
epoch: this.msgCount.toString(),
|
epoch: this.msgCount.toString(),
|
||||||
type: "message",
|
type: "message",
|
||||||
jid: jid,
|
jid: jid,
|
||||||
kind: "before",
|
kind: mode,
|
||||||
owner: "true",
|
owner: "true",
|
||||||
count: count.toString()
|
count: count.toString()
|
||||||
},
|
},
|
||||||
null
|
null
|
||||||
]
|
]
|
||||||
// if we have some index before which we want to query
|
// if we have some index from which we want to query
|
||||||
if (beforeMessage) {
|
if (indexMessage) {
|
||||||
json[1].index = beforeMessage.id
|
json[1].index = indexMessage.id
|
||||||
json[1].owner = beforeMessage.fromMe ? "true" : "false"
|
json[1].owner = indexMessage.fromMe ? "true" : "false"
|
||||||
}
|
}
|
||||||
return this.query(json, true)
|
|
||||||
|
return this.query(json, [10, 128])
|
||||||
}
|
}
|
||||||
// loads all the conversation you've had with given ID
|
// loads all the conversation you've had with given ID
|
||||||
WhatsAppWeb.prototype.getAllMessages = function (jid, onMessage, chunkSize=25) {
|
WhatsAppWeb.prototype.getAllMessages = function (jid, onMessage, chunkSize=25, mode="before") {
|
||||||
var offsetID = null
|
var offsetID = null
|
||||||
|
|
||||||
const loadMessage = () => {
|
const loadMessage = () => {
|
||||||
return this.getMessages(jid, chunkSize, offsetID)
|
return this.getMessages(jid, chunkSize, offsetID, mode)
|
||||||
.then (json => {
|
.then (json => {
|
||||||
if (json[2]) {
|
if (json[2]) {
|
||||||
// callback with most recent message first (descending order of date)
|
// callback with most recent message first (descending order of date)
|
||||||
for (var i = json[2].length-1; i >= 0;i--) {
|
let lastMessage
|
||||||
onMessage(json[2][i][2])
|
if (mode === "before") {
|
||||||
|
for (var i = json[2].length-1; i >= 0;i--) {
|
||||||
|
onMessage(json[2][i][2])
|
||||||
|
lastMessage = json[2][i][2]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < json[2].length;i++) {
|
||||||
|
onMessage(json[2][i][2])
|
||||||
|
lastMessage = json[2][i][2]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// if there are still more messages
|
// if there are still more messages
|
||||||
if (json[2].length >= chunkSize) {
|
if (json[2].length >= chunkSize) {
|
||||||
offsetID = json[2][0][2].key // get the oldest message
|
offsetID = lastMessage.key // get the last message
|
||||||
return new Promise ( (resolve, reject) => {
|
return new Promise ( (resolve, reject) => {
|
||||||
// send query after 200 ms
|
// send query after 200 ms
|
||||||
setTimeout( () => loadMessage().then (resolve).catch(reject), 200)
|
setTimeout( () => loadMessage().then (resolve).catch(reject), 200)
|
||||||
|
|||||||
@@ -27,12 +27,7 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
const messageTag = message.slice(0, commaIndex)
|
const messageTag = message.slice(0, commaIndex)
|
||||||
//console.log(messageTag)
|
//console.log(messageTag)
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
// got an empty message, usually get one after sending a message or something
|
// got an empty message, usually get one after sending a query with the 128 tag
|
||||||
if (this.callbacks[messageTag]) {
|
|
||||||
const q = this.callbacks[messageTag]
|
|
||||||
q.callback()
|
|
||||||
delete this.callbacks[messageTag]
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +79,7 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
case "action":
|
case "action":
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this is when some action was taken on a chat or that we recieve a message.
|
this is when some action was taken on a chat or that we recieve a message.
|
||||||
json[1] tells us more about the message, it can be null
|
json[1] tells us more about the message, it can be null
|
||||||
@@ -122,13 +118,12 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
this.chats[id].messages.push(message[2]) // append this message to the array
|
this.chats[id].messages.push(message[2]) // append this message to the array
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const id = json[0][2].key.remoteJid // get the ID whose chats we just processed
|
const id = json[0][2].key.remoteJid // get the ID whose chats we just processed
|
||||||
this.clearUnreadMessages(id) // forward to the handler any any unread messages
|
this.clearUnreadMessages(id) // forward to the handler any any unread messages
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case "response":
|
case "response":
|
||||||
|
//console.log(json[1])
|
||||||
// if it is the list of all the people the WhatsApp account has chats with
|
// if it is the list of all the people the WhatsApp account has chats with
|
||||||
if (json[1].type === "chat") {
|
if (json[1].type === "chat") {
|
||||||
|
|
||||||
@@ -149,6 +144,8 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
this.handlers.gotContact(json[2])
|
this.handlers.gotContact(json[2])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
} else if (json[1].type === "message") {
|
||||||
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "Presence":
|
case "Presence":
|
||||||
@@ -214,8 +211,8 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
const chat = this.chats[id] // get the chat
|
const chat = this.chats[id] // get the chat
|
||||||
var j = 0
|
var j = 0
|
||||||
let unreadMessages = chat.user.count
|
let unreadMessages = chat.user.count
|
||||||
while (unreadMessages > 0) {
|
while (unreadMessages > 0 && chat.messages[j]) {
|
||||||
if (!chat.messages[j].key.fromMe) { // only forward if the message is from the sender
|
if (!chat.messages[j].key.fromMe && this.handlers.onUnreadMessage) { // only forward if the message is from the sender
|
||||||
this.handlers.onUnreadMessage( chat.messages[j] ) // send off the unread message
|
this.handlers.onUnreadMessage( chat.messages[j] ) // send off the unread message
|
||||||
unreadMessages -= 1 // reduce
|
unreadMessages -= 1 // reduce
|
||||||
}
|
}
|
||||||
@@ -236,7 +233,7 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
this.chats[ message.key.remoteJid ].messages.splice(0, 0, message)
|
this.chats[ message.key.remoteJid ].messages.splice(0, 0, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!message.key.fromMe) { // if this message was sent to us, notify the handler
|
if (!message.key.fromMe && this.handlers.onUnreadMessage) { // if this message was sent to us, notify the handler
|
||||||
this.handlers.onUnreadMessage ( message )
|
this.handlers.onUnreadMessage ( message )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
}
|
}
|
||||||
// send a text message to someone, optionally you can provide a quoted message & the timestamp for the message
|
// send a text message to someone, optionally you can provide a quoted message & the timestamp for the message
|
||||||
WhatsAppWeb.prototype.sendTextMessage = function (id, txt, quoted=null, timestamp=null) {
|
WhatsAppWeb.prototype.sendTextMessage = function (id, txt, quoted=null, timestamp=null) {
|
||||||
|
if (typeof txt !== "string") {
|
||||||
|
return Promise.reject("")
|
||||||
|
}
|
||||||
let message
|
let message
|
||||||
if (quoted) {
|
if (quoted) {
|
||||||
message = {
|
message = {
|
||||||
@@ -149,9 +152,9 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
const json = [
|
const json = [
|
||||||
"action",
|
"action",
|
||||||
{epoch: this.msgCount.toString(), type: "relay" },
|
{epoch: this.msgCount.toString(), type: "relay" },
|
||||||
[ ['message', null, messageJSON] ]
|
[ ["message", null, messageJSON] ]
|
||||||
]
|
]
|
||||||
return this.query(json, [16, 128])
|
return this.query(json, [16, 64])
|
||||||
}
|
}
|
||||||
// send query message to WhatsApp servers; returns a promise
|
// send query message to WhatsApp servers; returns a promise
|
||||||
WhatsAppWeb.prototype.query = function (json, binaryTags=null) {
|
WhatsAppWeb.prototype.query = function (json, binaryTags=null) {
|
||||||
@@ -169,7 +172,7 @@ module.exports = function(WhatsAppWeb) {
|
|||||||
// send a binary message, the tags parameter tell WhatsApp what the message is all about
|
// send a binary message, the tags parameter tell WhatsApp what the message is all about
|
||||||
WhatsAppWeb.prototype.sendBinary = function (json, tags) {
|
WhatsAppWeb.prototype.sendBinary = function (json, tags) {
|
||||||
const binary = this.encoder.write(json) // encode the JSON to the WhatsApp binary format
|
const binary = this.encoder.write(json) // encode the JSON to the WhatsApp binary format
|
||||||
|
|
||||||
var buff = Utils.aesEncrypt(binary, this.authInfo.encKey) // encrypt it using AES and our encKey
|
var buff = Utils.aesEncrypt(binary, this.authInfo.encKey) // encrypt it using AES and our encKey
|
||||||
const sign = Utils.hmacSign(buff, this.authInfo.macKey) // sign the message using HMAC and our macKey
|
const sign = Utils.hmacSign(buff, this.authInfo.macKey) // sign the message using HMAC and our macKey
|
||||||
const tag = Utils.generateMessageTag()
|
const tag = Utils.generateMessageTag()
|
||||||
|
|||||||
Reference in New Issue
Block a user