User Agent string in fetch requests

This commit is contained in:
Adhiraj
2020-07-27 22:48:40 +05:30
parent efb66d66f6
commit 18cffdaa17
7 changed files with 24 additions and 9 deletions

View File

@@ -36,6 +36,7 @@
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"protobufjs": "^6.9.0", "protobufjs": "^6.9.0",
"qrcode-terminal": "^0.12.0", "qrcode-terminal": "^0.12.0",
"user-agents": "^1.0.559",
"ws": "^7.3.0" "ws": "^7.3.0"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -12,6 +12,7 @@ import { generateProfilePicture } from '../WAClient/Utils'
export default class WhatsAppWebBase extends WAConnection { export default class WhatsAppWebBase extends WAConnection {
/** Set the callback for message status updates (when a message is delivered, read etc.) */ /** Set the callback for message status updates (when a message is delivered, read etc.) */
setOnMessageStatusChange(callback: (update: MessageStatusUpdate) => void) { setOnMessageStatusChange(callback: (update: MessageStatusUpdate) => void) {
const func = (json) => { const func = (json) => {

View File

@@ -271,7 +271,10 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
const urlFetch = await fetch(hostname, { const urlFetch = await fetch(hostname, {
method: 'POST', method: 'POST',
body: body, body: body,
headers: { Origin: 'https://web.whatsapp.com' }, headers: {
Origin: 'https://web.whatsapp.com',
'User-Agent': this.userAgentString
},
}) })
const responseJSON = await urlFetch.json() const responseJSON = await urlFetch.json()
if (!responseJSON.url) { if (!responseJSON.url) {
@@ -341,14 +344,15 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
* Renews the download url automatically, if necessary. * Renews the download url automatically, if necessary.
*/ */
async downloadMediaMessage (message: WAMessage) { async downloadMediaMessage (message: WAMessage) {
const fetchHeaders = { 'User-Agent': this.userAgentString }
try { try {
const buff = await decodeMediaMessageBuffer (message.message) const buff = await decodeMediaMessageBuffer (message.message, fetchHeaders)
return buff return buff
} catch (error) { } catch (error) {
if (error instanceof BaileysError && error.status === 404) { // media needs to be updated if (error instanceof BaileysError && error.status === 404) { // media needs to be updated
this.log (`updating media of message: ${message.key.id}`, MessageLogLevel.info) this.log (`updating media of message: ${message.key.id}`, MessageLogLevel.info)
await this.updateMediaMessage (message) await this.updateMediaMessage (message)
const buff = await decodeMediaMessageBuffer (message.message) const buff = await decodeMediaMessageBuffer (message.message, fetchHeaders)
return buff return buff
} }
throw error throw error

View File

@@ -5,7 +5,7 @@ import * as assert from 'assert'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { decodeMediaMessage, validateJIDForSending } from './Utils' import { decodeMediaMessage, validateJIDForSending } from './Utils'
import { promiseTimeout, createTimeout } from '../WAConnection/Utils' import { promiseTimeout, createTimeout, Browsers } from '../WAConnection/Utils'
require ('dotenv').config () // dotenv to load test jid 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 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

View File

@@ -18,7 +18,6 @@ export function validateJIDForSending (jid: string) {
) )
} }
} }
/** /**
* Type of notification * Type of notification
* @deprecated use WA_MESSAGE_STUB_TYPE instead * @deprecated use WA_MESSAGE_STUB_TYPE instead
@@ -102,7 +101,7 @@ export async function generateThumbnail(buffer: Buffer, mediaType: MessageType,
* Decode a media message (video, image, document, audio) & return decrypted buffer * Decode a media message (video, image, document, audio) & return decrypted buffer
* @param message the media message you want to decode * @param message the media message you want to decode
*/ */
export async function decodeMediaMessageBuffer(message: WAMessageContent) { export async function decodeMediaMessageBuffer(message: WAMessageContent, fetchHeaders: {[k: string]: string} = {}) {
/* /*
One can infer media type from the key in the message One can infer media type from the key in the message
it is usually written as [mediaType]Message. Eg. imageMessage, audioMessage etc. it is usually written as [mediaType]Message. Eg. imageMessage, audioMessage etc.
@@ -127,7 +126,11 @@ export async function decodeMediaMessageBuffer(message: WAMessageContent) {
} }
// download the message // download the message
const fetched = await fetch(messageContent.url, { headers: { Origin: 'https://web.whatsapp.com' } }) const headers = {
Origin: 'https://web.whatsapp.com',
...fetchHeaders
}
const fetched = await fetch(messageContent.url, { headers })
const buffer = await fetched.buffer() const buffer = await fetched.buffer()
if (buffer.length <= 10) { if (buffer.length <= 10) {
@@ -184,7 +187,7 @@ export function extensionForMediaMessage(message: WAMessageContent) {
* @deprecated use `client.downloadAndSaveMediaMessage` * @deprecated use `client.downloadAndSaveMediaMessage`
*/ */
export async function decodeMediaMessage(message: WAMessageContent, filename: string, attachExtension: boolean=true) { export async function decodeMediaMessage(message: WAMessageContent, filename: string, attachExtension: boolean=true) {
const buffer = await decodeMediaMessageBuffer (message) const buffer = await decodeMediaMessageBuffer (message, {})
const extension = extensionForMediaMessage (message) const extension = extensionForMediaMessage (message)
const trueFileName = attachExtension ? (filename + '.' + extension) : filename const trueFileName = attachExtension ? (filename + '.' + extension) : filename
fs.writeFileSync(trueFileName, buffer) fs.writeFileSync(trueFileName, buffer)

View File

@@ -59,8 +59,9 @@ export default class WAConnectionBase {
protected pendingRequests: (() => void)[] = [] protected pendingRequests: (() => void)[] = []
protected reconnectLoop: () => Promise<void> protected reconnectLoop: () => Promise<void>
protected referenceDate = new Date () // used for generating tags protected referenceDate = new Date () // used for generating tags
protected userAgentString: string
constructor () { constructor () {
this.userAgentString = Utils.userAgentString (this.browserDescription[1])
this.registerCallback (['Cmd', 'type:disconnect'], json => this.unexpectedDisconnect(json[1].kind)) this.registerCallback (['Cmd', 'type:disconnect'], json => this.unexpectedDisconnect(json[1].kind))
} }
async unexpectedDisconnect (error: string) { async unexpectedDisconnect (error: string) {

View File

@@ -3,6 +3,7 @@ import HKDF from 'futoin-hkdf'
import Decoder from '../Binary/Decoder' import Decoder from '../Binary/Decoder'
import {platform, release} from 'os' import {platform, release} from 'os'
import { BaileysError } from './Constants' import { BaileysError } from './Constants'
import UserAgent from 'user-agents'
const platformMap = { const platformMap = {
'aix': 'AIX', 'aix': 'AIX',
@@ -17,6 +18,10 @@ export const Browsers = {
/** The appropriate browser based on your OS & release */ /** The appropriate browser based on your OS & release */
appropriate: browser => [ platformMap [platform()] || 'Ubuntu', browser, release() ] as [string, string, string] appropriate: browser => [ platformMap [platform()] || 'Ubuntu', browser, release() ] as [string, string, string]
} }
export function userAgentString (browser) {
const agent = new UserAgent (new RegExp(browser))
return agent.toString ()
}
/** decrypt AES 256 CBC; where the IV is prefixed to the buffer */ /** decrypt AES 256 CBC; where the IV is prefixed to the buffer */
export function aesDecrypt(buffer: Buffer, key: Buffer) { export function aesDecrypt(buffer: Buffer, key: Buffer) {
return aesDecryptWithIV(buffer.slice(16, buffer.length), key, buffer.slice(0, 16)) return aesDecryptWithIV(buffer.slice(16, buffer.length), key, buffer.slice(0, 16))