mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Merge branch 'master' into invalid-qr-patch
This commit is contained in:
@@ -276,6 +276,11 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const willSendMessageAgain = (id: string) => {
|
||||||
|
const retryCount = msgRetryMap[id] || 0
|
||||||
|
return retryCount < 5
|
||||||
|
}
|
||||||
|
|
||||||
const sendMessagesAgain = async(key: proto.IMessageKey, ids: string[]) => {
|
const sendMessagesAgain = async(key: proto.IMessageKey, ids: string[]) => {
|
||||||
const msgs = await Promise.all(
|
const msgs = await Promise.all(
|
||||||
ids.map(id => (
|
ids.map(id => (
|
||||||
@@ -294,6 +299,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
|
|
||||||
for(let i = 0; i < msgs.length;i++) {
|
for(let i = 0; i < msgs.length;i++) {
|
||||||
if(msgs[i]) {
|
if(msgs[i]) {
|
||||||
|
msgRetryMap[ids[i]] = (msgRetryMap[ids[i]] || 0) + 1
|
||||||
await relayMessage(key.remoteJid, msgs[i], {
|
await relayMessage(key.remoteJid, msgs[i], {
|
||||||
messageId: ids[i],
|
messageId: ids[i],
|
||||||
participant
|
participant
|
||||||
@@ -363,18 +369,22 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(attrs.type === 'retry') {
|
if(attrs.type === 'retry') {
|
||||||
// correctly set who is asking for the retry
|
if(willSendMessageAgain(ids[0])) {
|
||||||
key.participant = key.participant || attrs.from
|
// correctly set who is asking for the retry
|
||||||
if(key.fromMe) {
|
key.participant = key.participant || attrs.from
|
||||||
try {
|
if(key.fromMe) {
|
||||||
logger.debug({ attrs, key }, 'recv retry request')
|
try {
|
||||||
await sendMessagesAgain(key, ids)
|
logger.debug({ attrs, key }, 'recv retry request')
|
||||||
} catch(error) {
|
await sendMessagesAgain(key, ids)
|
||||||
logger.error({ key, ids, trace: error.stack }, 'error in sending message again')
|
} catch(error) {
|
||||||
shouldAck = false
|
logger.error({ key, ids, trace: error.stack }, 'error in sending message again')
|
||||||
|
shouldAck = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.info({ attrs, key }, 'recv retry for not fromMe message')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info({ attrs, key }, 'recv retry for not fromMe message')
|
logger.info({ attrs, key }, 'will not send message again, as sent too many times')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export type AnyMediaMessageContent = (
|
|||||||
export type AnyRegularMessageContent = (
|
export type AnyRegularMessageContent = (
|
||||||
({
|
({
|
||||||
text: string
|
text: string
|
||||||
|
linkPreview?: WAUrlInfo
|
||||||
}
|
}
|
||||||
& Mentionable & Buttonable & Templatable & Listable) |
|
& Mentionable & Buttonable & Templatable & Listable) |
|
||||||
AnyMediaMessageContent |
|
AnyMediaMessageContent |
|
||||||
@@ -177,3 +178,9 @@ export type WAMessageUpdate = { update: Partial<WAMessage>, key: proto.IMessageK
|
|||||||
export type WAMessageCursor = { before: WAMessageKey | undefined } | { after: WAMessageKey | undefined }
|
export type WAMessageCursor = { before: WAMessageKey | undefined } | { after: WAMessageKey | undefined }
|
||||||
|
|
||||||
export type MessageUserReceiptUpdate = { key: proto.IMessageKey, receipt: MessageUserReceipt }
|
export type MessageUserReceiptUpdate = { key: proto.IMessageKey, receipt: MessageUserReceipt }
|
||||||
|
|
||||||
|
export type MediaDecryptionKeyInfo = {
|
||||||
|
iv: Buffer
|
||||||
|
cipherKey: Buffer
|
||||||
|
macKey?: Buffer
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import type { Logger } from 'pino'
|
|||||||
import { Readable, Transform } from 'stream'
|
import { Readable, Transform } from 'stream'
|
||||||
import { URL } from 'url'
|
import { URL } from 'url'
|
||||||
import { DEFAULT_ORIGIN, MEDIA_PATH_MAP } from '../Defaults'
|
import { DEFAULT_ORIGIN, MEDIA_PATH_MAP } from '../Defaults'
|
||||||
import { CommonSocketConfig, DownloadableMessage, MediaConnInfo, MediaType, MessageType, WAGenericMediaMessage, WAMediaUpload, WAMediaUploadFunction, WAMessageContent, WAProto } from '../Types'
|
import { CommonSocketConfig, DownloadableMessage, MediaConnInfo, MediaDecryptionKeyInfo, MediaType, MessageType, WAGenericMediaMessage, WAMediaUpload, WAMediaUploadFunction, WAMessageContent, WAProto } from '../Types'
|
||||||
import { hkdf } from './crypto'
|
import { hkdf } from './crypto'
|
||||||
import { generateMessageID } from './generics'
|
import { generateMessageID } from './generics'
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ export const hkdfInfoKey = (type: MediaType) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
||||||
export function getMediaKeys(buffer, mediaType: MediaType) {
|
export function getMediaKeys(buffer: Uint8Array | string, mediaType: MediaType): MediaDecryptionKeyInfo {
|
||||||
if(typeof buffer === 'string') {
|
if(typeof buffer === 'string') {
|
||||||
buffer = Buffer.from(buffer.replace('data:;base64,', ''), 'base64')
|
buffer = Buffer.from(buffer.replace('data:;base64,', ''), 'base64')
|
||||||
}
|
}
|
||||||
@@ -186,6 +186,7 @@ export const toBuffer = async(stream: Readable) => {
|
|||||||
buff = Buffer.concat([ buff, chunk ])
|
buff = Buffer.concat([ buff, chunk ])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream.destroy()
|
||||||
return buff
|
return buff
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,12 +344,26 @@ export type MediaDownloadOptions = {
|
|||||||
endByte?: number
|
endByte?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export const downloadContentFromMessage = async(
|
export const downloadContentFromMessage = (
|
||||||
{ mediaKey, directPath, url }: DownloadableMessage,
|
{ mediaKey, directPath, url }: DownloadableMessage,
|
||||||
type: MediaType,
|
type: MediaType,
|
||||||
{ startByte, endByte }: MediaDownloadOptions = { }
|
opts: MediaDownloadOptions = { }
|
||||||
) => {
|
) => {
|
||||||
const downloadUrl = url || `https://${DEF_HOST}${directPath}`
|
const downloadUrl = url || `https://${DEF_HOST}${directPath}`
|
||||||
|
const keys = getMediaKeys(mediaKey, type)
|
||||||
|
|
||||||
|
return downloadEncryptedContent(downloadUrl, keys, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts and downloads an AES256-CBC encrypted file given the keys.
|
||||||
|
* Assumes the SHA256 of the plaintext is appended to the end of the ciphertext
|
||||||
|
* */
|
||||||
|
export const downloadEncryptedContent = async(
|
||||||
|
downloadUrl: string,
|
||||||
|
{ cipherKey, iv }: MediaDecryptionKeyInfo,
|
||||||
|
{ startByte, endByte }: MediaDownloadOptions = { }
|
||||||
|
) => {
|
||||||
let bytesFetched = 0
|
let bytesFetched = 0
|
||||||
let startChunk = 0
|
let startChunk = 0
|
||||||
let firstBlockIsIV = false
|
let firstBlockIsIV = false
|
||||||
@@ -386,7 +401,6 @@ export const downloadContentFromMessage = async(
|
|||||||
)
|
)
|
||||||
|
|
||||||
let remainingBytes = Buffer.from([])
|
let remainingBytes = Buffer.from([])
|
||||||
const { cipherKey, iv } = getMediaKeys(mediaKey, type)
|
|
||||||
|
|
||||||
let aes: Crypto.Decipher
|
let aes: Crypto.Decipher
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
WAMessageContent,
|
WAMessageContent,
|
||||||
WAMessageStatus,
|
WAMessageStatus,
|
||||||
WAProto,
|
WAProto,
|
||||||
WATextMessage
|
WATextMessage,
|
||||||
} from '../Types'
|
} from '../Types'
|
||||||
import { generateMessageID, unixTimestampSeconds } from './generics'
|
import { generateMessageID, unixTimestampSeconds } from './generics'
|
||||||
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, MediaDownloadOptions } from './messages-media'
|
import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, MediaDownloadOptions } from './messages-media'
|
||||||
@@ -245,21 +245,26 @@ export const generateWAMessageContent = async(
|
|||||||
) => {
|
) => {
|
||||||
let m: WAMessageContent = {}
|
let m: WAMessageContent = {}
|
||||||
if('text' in message) {
|
if('text' in message) {
|
||||||
const extContent = { ...message } as WATextMessage
|
const extContent = { text: message.text } as WATextMessage
|
||||||
if(!!options.getUrlInfo && message.text.match(URL_REGEX)) {
|
|
||||||
|
let urlInfo = message.linkPreview
|
||||||
|
if(!urlInfo && !!options.getUrlInfo && message.text.match(URL_REGEX)) {
|
||||||
try {
|
try {
|
||||||
const data = await options.getUrlInfo(message.text)
|
urlInfo = await options.getUrlInfo(message.text)
|
||||||
extContent.canonicalUrl = data['canonical-url']
|
|
||||||
extContent.matchedText = data['matched-text']
|
|
||||||
extContent.jpegThumbnail = data.jpegThumbnail
|
|
||||||
extContent.description = data.description
|
|
||||||
extContent.title = data.title
|
|
||||||
extContent.previewType = 0
|
|
||||||
} catch(error) { // ignore if fails
|
} catch(error) { // ignore if fails
|
||||||
options.logger?.warn({ trace: error.stack }, 'url generation failed')
|
options.logger?.warn({ trace: error.stack }, 'url generation failed')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(urlInfo) {
|
||||||
|
extContent.canonicalUrl = urlInfo['canonical-url']
|
||||||
|
extContent.matchedText = urlInfo['matched-text']
|
||||||
|
extContent.jpegThumbnail = urlInfo.jpegThumbnail
|
||||||
|
extContent.description = urlInfo.description
|
||||||
|
extContent.title = urlInfo.title
|
||||||
|
extContent.previewType = 0
|
||||||
|
}
|
||||||
|
|
||||||
m.extendedTextMessage = extContent
|
m.extendedTextMessage = extContent
|
||||||
} else if('contacts' in message) {
|
} else if('contacts' in message) {
|
||||||
const contactLen = message.contacts.contacts.length
|
const contactLen = message.contacts.contacts.length
|
||||||
|
|||||||
Reference in New Issue
Block a user