mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
filename to messageoptions + group query + media query
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ yarn.lock
|
||||
browser-messages.json
|
||||
package-lock.json
|
||||
package-lock.json
|
||||
decoded-ws.json
|
||||
|
||||
@@ -212,6 +212,7 @@ To note:
|
||||
mimetype: Mimetype.pdf, /* (for media messages) specify the type of media (optional for all media types except documents),
|
||||
import {Mimetype} from '@adiwajshing/baileys'
|
||||
*/
|
||||
filename: 'somefile.pdf' // (for media messages) file name for the media
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ export default class WhatsAppWebBase extends WAConnection {
|
||||
},
|
||||
null,
|
||||
]
|
||||
const response = await this.query(json, [WAMetric.group, WAFlag.ignore])
|
||||
const response = await this.query(json, [WAMetric.queryMessages, WAFlag.ignore])
|
||||
|
||||
if (response.status) throw new Error(`error in query, got status: ${response.status}`)
|
||||
|
||||
@@ -158,7 +158,6 @@ export default class WhatsAppWebBase extends WAConnection {
|
||||
*/
|
||||
loadEntireConversation(jid: string, onMessage: (m: WAMessage) => void, chunkSize = 25, mostRecentFirst = true) {
|
||||
let offsetID = null
|
||||
|
||||
const loadMessage = async () => {
|
||||
const json = await this.loadConversation(jid, chunkSize, offsetID, mostRecentFirst)
|
||||
// callback with most recent message first (descending order of date)
|
||||
@@ -208,6 +207,20 @@ export default class WhatsAppWebBase extends WAConnection {
|
||||
}
|
||||
/** Get the metadata of the group */
|
||||
groupMetadata = (jid: string) => this.queryExpecting200(['query', 'GroupMetadata', jid]) as Promise<WAGroupMetadata>
|
||||
/** Get the metadata (works after you've left the group also) */
|
||||
groupCreatorAndParticipants = async (jid: string) => {
|
||||
const response = await this.queryExpecting200(['query', {type: 'group', jid: jid, epoch: '5'}, null], [WAMetric.group, WAFlag.ignore])
|
||||
if (!response[2] || !response[2][1]) throw new Error ('Data missing in ' + JSON.stringify(response))
|
||||
const json = response[2]
|
||||
return {
|
||||
id: jid,
|
||||
owner: json[1].creator,
|
||||
creator: json[1].creator,
|
||||
creation: parseInt(json[1].create),
|
||||
subject: null,
|
||||
participants: json[2] ? json[2].map (item => ({ id: item[1].jid, isAdmin: item[1].type==='admin' })) : []
|
||||
} as WAGroupMetadata
|
||||
}
|
||||
/**
|
||||
* Create a group
|
||||
* @param title like, the title of the group
|
||||
|
||||
@@ -70,7 +70,8 @@ export interface MessageOptions {
|
||||
caption?: string
|
||||
thumbnail?: string
|
||||
mimetype?: Mimetype
|
||||
validateID?: boolean
|
||||
validateID?: boolean,
|
||||
filename?: string
|
||||
}
|
||||
export interface MessageStatusUpdate {
|
||||
from: string
|
||||
|
||||
@@ -106,6 +106,21 @@ export default class WhatsAppWebMessages extends WhatsAppWebBase {
|
||||
]
|
||||
return this.setQuery ([attrs])
|
||||
}
|
||||
/**
|
||||
* Fetches the latest url & media key for the given message.
|
||||
* You may need to call this when the message is old & the content is deleted off of the WA servers
|
||||
* @param message
|
||||
*/
|
||||
async updateMediaMessage (message: WAMessage) {
|
||||
const content = message.message?.audioMessage || message.message?.videoMessage || message.message?.imageMessage || message.message?.stickerMessage || message.message?.documentMessage
|
||||
if (!content) throw new Error (`given message ${message.key.id} is not a media message`)
|
||||
|
||||
const query = ['query',{type: 'media', index: message.key.id, owner: message.key.fromMe ? 'true' : 'false', jid: message.key.remoteJid, epoch: this.msgCount.toString()},null]
|
||||
const response = await this.query (query, [WAMetric.queryMedia, WAFlag.ignore])
|
||||
if (response[1].code !== 200) throw new Error ('unexpected status ' + response[1].code)
|
||||
|
||||
Object.keys (response[1]).forEach (key => content[key] = response[1][key]) // update message
|
||||
}
|
||||
/**
|
||||
* Delete a message in a chat for everyone
|
||||
* @param id the person or group where you're trying to delete the message
|
||||
@@ -207,9 +222,10 @@ export default class WhatsAppWebMessages extends WhatsAppWebBase {
|
||||
fileEncSha256: fileEncSha256B64,
|
||||
fileSha256: fileSha256.toString('base64'),
|
||||
fileLength: buffer.length,
|
||||
fileName: options.filename || 'file',
|
||||
gifPlayback: isGIF || null,
|
||||
}
|
||||
return message
|
||||
return message as WAMessageContent
|
||||
}
|
||||
/** Generic send message function */
|
||||
async sendGenericMessage(id: string, message: WAMessageContent, options: MessageOptions) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as assert from 'assert'
|
||||
|
||||
import { decodeMediaMessage, validateJIDForSending } from './Utils'
|
||||
import { promiseTimeout, createTimeout } from '../WAConnection/Utils'
|
||||
import { WAMessageContent, WAMessage } from '../WAConnection/Constants'
|
||||
|
||||
require ('dotenv').config () // dotenv to load test jid
|
||||
const testJid = process.env.TEST_JID || '1234@s.whatsapp.net' // set TEST_JID=xyz@s.whatsapp.net in a .env file in the root directory
|
||||
@@ -171,6 +172,7 @@ WAClientTest('Groups', (client) => {
|
||||
})
|
||||
it('should leave the group', async () => {
|
||||
await client.groupLeave(gid)
|
||||
await client.groupCreatorAndParticipants (gid)
|
||||
})
|
||||
it('should archive the group', async () => {
|
||||
await client.archiveChat(gid)
|
||||
|
||||
@@ -109,7 +109,6 @@ export async function decodeMediaMessage(message: WAMessageContent, filename: st
|
||||
fs.writeFileSync(filename + '.jpeg', message[type].jpegThumbnail)
|
||||
return { filename: filename + '.jpeg' }
|
||||
}
|
||||
|
||||
const messageContent = message[type] as
|
||||
| proto.VideoMessage
|
||||
| proto.ImageMessage
|
||||
@@ -117,9 +116,13 @@ export async function decodeMediaMessage(message: WAMessageContent, filename: st
|
||||
| proto.DocumentMessage
|
||||
|
||||
// download the message
|
||||
const fetched = await fetch(messageContent.url, {})
|
||||
const fetched = await fetch(messageContent.url, { headers: { Origin: 'https://web.whatsapp.com' } })
|
||||
const buffer = await fetched.buffer()
|
||||
|
||||
if (buffer.length === 0) {
|
||||
throw new Error ('Empty buffer returned. File has possibly been deleted from WA servers. Run `client.updateMediaMessage()` to refresh the url')
|
||||
}
|
||||
|
||||
const decryptedMedia = (type: MessageType) => {
|
||||
// get the keys to decrypt the message
|
||||
const mediaKeys = getMediaKeys(messageContent.mediaKey, type) //getMediaKeys(Buffer.from(messageContent.mediaKey, 'base64'), type)
|
||||
@@ -134,7 +137,7 @@ export async function decodeMediaMessage(message: WAMessageContent, filename: st
|
||||
if (sign.equals(mac)) {
|
||||
return aesDecryptWithIV(file, mediaKeys.cipherKey, mediaKeys.iv) // decrypt media
|
||||
} else {
|
||||
throw new Error('')
|
||||
throw new Error()
|
||||
}
|
||||
}
|
||||
const allTypes = [type, ...Object.keys(HKDFInfoKeys)]
|
||||
@@ -151,5 +154,5 @@ export async function decodeMediaMessage(message: WAMessageContent, filename: st
|
||||
if (i === 0) { console.log (`decryption of ${type} media with original HKDF key failed`) }
|
||||
}
|
||||
}
|
||||
throw new Error('HMAC sign does not match for: ' + buffer.toString('utf-8'))
|
||||
throw new Error('HMAC sign does not match for ' + buffer.length)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ import Decoder from '../Binary/Decoder'
|
||||
interface BrowserMessagesInfo {
|
||||
encKey: string,
|
||||
macKey: string,
|
||||
messages: string[]
|
||||
harFilePath: string
|
||||
}
|
||||
interface WSMessage {
|
||||
type: 'send' | 'receive',
|
||||
data: string
|
||||
}
|
||||
const file = fs.readFileSync ('./browser-messages.json', {encoding: 'utf-8'})
|
||||
const json: BrowserMessagesInfo = JSON.parse (file)
|
||||
@@ -13,6 +17,14 @@ const json: BrowserMessagesInfo = JSON.parse (file)
|
||||
const encKey = Buffer.from (json.encKey, 'base64')
|
||||
const macKey = Buffer.from (json.macKey, 'base64')
|
||||
|
||||
const harFile = JSON.parse ( fs.readFileSync( json.harFilePath , {encoding: 'utf-8'}))
|
||||
const entries = harFile['log']['entries']
|
||||
let wsMessages: WSMessage[] = []
|
||||
entries.forEach ((e, i) => {
|
||||
if ('_webSocketMessages' in e) {
|
||||
wsMessages.push (...e['_webSocketMessages'])
|
||||
}
|
||||
})
|
||||
const decrypt = buffer => {
|
||||
try {
|
||||
return decryptWA (buffer, macKey, encKey, new Decoder())
|
||||
@@ -21,19 +33,16 @@ const decrypt = buffer => {
|
||||
}
|
||||
}
|
||||
|
||||
json.messages.forEach ((str, i) => {
|
||||
const buffer = Buffer.from (str, 'base64')
|
||||
console.log ('parsing ' + wsMessages.length + ' messages')
|
||||
const list = wsMessages.map ((item, i) => {
|
||||
const buffer = Buffer.from (item.data, 'base64')
|
||||
try {
|
||||
const [tag, json, binaryTags] = decrypt (buffer)
|
||||
console.log (
|
||||
`
|
||||
${i}.
|
||||
messageTag: ${tag}
|
||||
output: ${JSON.stringify(json)}
|
||||
binaryTags: ${binaryTags}
|
||||
`
|
||||
)
|
||||
return {tag, json: JSON.stringify(json), binaryTags}
|
||||
} catch (error) {
|
||||
console.error (`received error in decoding ${i}: ${error}`)
|
||||
return null
|
||||
}
|
||||
})
|
||||
})
|
||||
const str = JSON.stringify (list, null, '\t')
|
||||
fs.writeFileSync ('decoded-ws.json', str)
|
||||
@@ -78,6 +78,8 @@ export interface WAChat {
|
||||
}
|
||||
export enum WAMetric {
|
||||
liveLocation = 3,
|
||||
queryMedia = 4,
|
||||
queryMessages = 7,
|
||||
group = 10,
|
||||
message = 16,
|
||||
queryLiveLocation = 33,
|
||||
|
||||
Reference in New Issue
Block a user