Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9181d01339 | |||
| 60798b77ff | |||
| d2db4cec97 | |||
| be44c5fdb0 | |||
| f63f0a766f | |||
| fbefa6a0ad | |||
| 9c4cdc3e02 |
@@ -1,7 +1,7 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package proto;
|
package proto;
|
||||||
|
|
||||||
/// WhatsApp Version: 2.3000.1035484955
|
/// WhatsApp Version: 2.3000.1035577069
|
||||||
|
|
||||||
message ADVDeviceIdentity {
|
message ADVDeviceIdentity {
|
||||||
optional uint32 rawId = 1;
|
optional uint32 rawId = 1;
|
||||||
@@ -2149,7 +2149,6 @@ message LimitSharing {
|
|||||||
CHAT_SETTING = 1;
|
CHAT_SETTING = 1;
|
||||||
BIZ_SUPPORTS_FB_HOSTING = 2;
|
BIZ_SUPPORTS_FB_HOSTING = 2;
|
||||||
UNKNOWN_GROUP = 3;
|
UNKNOWN_GROUP = 3;
|
||||||
DEPRECATION = 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4893,6 +4892,7 @@ message SyncActionValue {
|
|||||||
repeated SyncActionValue.BroadcastListParticipant participants = 2;
|
repeated SyncActionValue.BroadcastListParticipant participants = 2;
|
||||||
optional string listName = 3;
|
optional string listName = 3;
|
||||||
repeated string labelIds = 4;
|
repeated string labelIds = 4;
|
||||||
|
optional string audienceExpression = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CallLogAction {
|
message CallLogAction {
|
||||||
|
|||||||
Vendored
+3
-2
@@ -5356,8 +5356,7 @@ export namespace proto {
|
|||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
CHAT_SETTING = 1,
|
CHAT_SETTING = 1,
|
||||||
BIZ_SUPPORTS_FB_HOSTING = 2,
|
BIZ_SUPPORTS_FB_HOSTING = 2,
|
||||||
UNKNOWN_GROUP = 3,
|
UNKNOWN_GROUP = 3
|
||||||
DEPRECATION = 4
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12483,6 +12482,7 @@ export namespace proto {
|
|||||||
participants?: (proto.SyncActionValue.IBroadcastListParticipant[]|null);
|
participants?: (proto.SyncActionValue.IBroadcastListParticipant[]|null);
|
||||||
listName?: (string|null);
|
listName?: (string|null);
|
||||||
labelIds?: (string[]|null);
|
labelIds?: (string[]|null);
|
||||||
|
audienceExpression?: (string|null);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BusinessBroadcastListAction implements IBusinessBroadcastListAction {
|
class BusinessBroadcastListAction implements IBusinessBroadcastListAction {
|
||||||
@@ -12491,6 +12491,7 @@ export namespace proto {
|
|||||||
public participants: proto.SyncActionValue.IBroadcastListParticipant[];
|
public participants: proto.SyncActionValue.IBroadcastListParticipant[];
|
||||||
public listName?: (string|null);
|
public listName?: (string|null);
|
||||||
public labelIds: string[];
|
public labelIds: string[];
|
||||||
|
public audienceExpression?: (string|null);
|
||||||
public static create(properties?: proto.SyncActionValue.IBusinessBroadcastListAction): proto.SyncActionValue.BusinessBroadcastListAction;
|
public static create(properties?: proto.SyncActionValue.IBusinessBroadcastListAction): proto.SyncActionValue.BusinessBroadcastListAction;
|
||||||
public static encode(m: proto.SyncActionValue.IBusinessBroadcastListAction, w?: $protobuf.Writer): $protobuf.Writer;
|
public static encode(m: proto.SyncActionValue.IBusinessBroadcastListAction, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): proto.SyncActionValue.BusinessBroadcastListAction;
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): proto.SyncActionValue.BusinessBroadcastListAction;
|
||||||
|
|||||||
+21
-9
@@ -26692,10 +26692,6 @@ export const proto = $root.proto = (() => {
|
|||||||
case 3:
|
case 3:
|
||||||
m.limitSharingTrigger = 3;
|
m.limitSharingTrigger = 3;
|
||||||
break;
|
break;
|
||||||
case "DEPRECATION":
|
|
||||||
case 4:
|
|
||||||
m.limitSharingTrigger = 4;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (d.limitSharingInitiatedByMe != null) {
|
if (d.limitSharingInitiatedByMe != null) {
|
||||||
m.limitSharingInitiatedByMe = Boolean(d.limitSharingInitiatedByMe);
|
m.limitSharingInitiatedByMe = Boolean(d.limitSharingInitiatedByMe);
|
||||||
@@ -36778,10 +36774,6 @@ export const proto = $root.proto = (() => {
|
|||||||
case 3:
|
case 3:
|
||||||
m.trigger = 3;
|
m.trigger = 3;
|
||||||
break;
|
break;
|
||||||
case "DEPRECATION":
|
|
||||||
case 4:
|
|
||||||
m.trigger = 4;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (d.limitSharingSettingTimestamp != null) {
|
if (d.limitSharingSettingTimestamp != null) {
|
||||||
if ($util.Long)
|
if ($util.Long)
|
||||||
@@ -36846,7 +36838,6 @@ export const proto = $root.proto = (() => {
|
|||||||
values[valuesById[1] = "CHAT_SETTING"] = 1;
|
values[valuesById[1] = "CHAT_SETTING"] = 1;
|
||||||
values[valuesById[2] = "BIZ_SUPPORTS_FB_HOSTING"] = 2;
|
values[valuesById[2] = "BIZ_SUPPORTS_FB_HOSTING"] = 2;
|
||||||
values[valuesById[3] = "UNKNOWN_GROUP"] = 3;
|
values[valuesById[3] = "UNKNOWN_GROUP"] = 3;
|
||||||
values[valuesById[4] = "DEPRECATION"] = 4;
|
|
||||||
return values;
|
return values;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@@ -87581,6 +87572,7 @@ export const proto = $root.proto = (() => {
|
|||||||
BusinessBroadcastListAction.prototype.participants = $util.emptyArray;
|
BusinessBroadcastListAction.prototype.participants = $util.emptyArray;
|
||||||
BusinessBroadcastListAction.prototype.listName = null;
|
BusinessBroadcastListAction.prototype.listName = null;
|
||||||
BusinessBroadcastListAction.prototype.labelIds = $util.emptyArray;
|
BusinessBroadcastListAction.prototype.labelIds = $util.emptyArray;
|
||||||
|
BusinessBroadcastListAction.prototype.audienceExpression = null;
|
||||||
|
|
||||||
let $oneOfFields;
|
let $oneOfFields;
|
||||||
|
|
||||||
@@ -87596,6 +87588,12 @@ export const proto = $root.proto = (() => {
|
|||||||
set: $util.oneOfSetter($oneOfFields)
|
set: $util.oneOfSetter($oneOfFields)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Virtual OneOf for proto3 optional field
|
||||||
|
Object.defineProperty(BusinessBroadcastListAction.prototype, "_audienceExpression", {
|
||||||
|
get: $util.oneOfGetter($oneOfFields = ["audienceExpression"]),
|
||||||
|
set: $util.oneOfSetter($oneOfFields)
|
||||||
|
});
|
||||||
|
|
||||||
BusinessBroadcastListAction.create = function create(properties) {
|
BusinessBroadcastListAction.create = function create(properties) {
|
||||||
return new BusinessBroadcastListAction(properties);
|
return new BusinessBroadcastListAction(properties);
|
||||||
};
|
};
|
||||||
@@ -87615,6 +87613,8 @@ export const proto = $root.proto = (() => {
|
|||||||
for (var i = 0; i < m.labelIds.length; ++i)
|
for (var i = 0; i < m.labelIds.length; ++i)
|
||||||
w.uint32(34).string(m.labelIds[i]);
|
w.uint32(34).string(m.labelIds[i]);
|
||||||
}
|
}
|
||||||
|
if (m.audienceExpression != null && Object.hasOwnProperty.call(m, "audienceExpression"))
|
||||||
|
w.uint32(42).string(m.audienceExpression);
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -87647,6 +87647,10 @@ export const proto = $root.proto = (() => {
|
|||||||
m.labelIds.push(r.string());
|
m.labelIds.push(r.string());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 5: {
|
||||||
|
m.audienceExpression = r.string();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
r.skipType(t & 7);
|
r.skipType(t & 7);
|
||||||
break;
|
break;
|
||||||
@@ -87683,6 +87687,9 @@ export const proto = $root.proto = (() => {
|
|||||||
m.labelIds[i] = String(d.labelIds[i]);
|
m.labelIds[i] = String(d.labelIds[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (d.audienceExpression != null) {
|
||||||
|
m.audienceExpression = String(d.audienceExpression);
|
||||||
|
}
|
||||||
return m;
|
return m;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -87716,6 +87723,11 @@ export const proto = $root.proto = (() => {
|
|||||||
d.labelIds[j] = m.labelIds[j];
|
d.labelIds[j] = m.labelIds[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m.audienceExpression != null && m.hasOwnProperty("audienceExpression")) {
|
||||||
|
d.audienceExpression = m.audienceExpression;
|
||||||
|
if (o.oneofs)
|
||||||
|
d._audienceExpression = "audienceExpression";
|
||||||
|
}
|
||||||
return d;
|
return d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":[2,3000,1035504971]}
|
{"version":[2,3000,1035595667]}
|
||||||
|
|||||||
@@ -157,6 +157,15 @@ export const MEDIA_PATH_MAP: { [T in MediaType]?: string } = {
|
|||||||
'thumbnail-sticker-pack': '/mms/thumbnail-sticker-pack'
|
'thumbnail-sticker-pack': '/mms/thumbnail-sticker-pack'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const NEWSLETTER_MEDIA_PATH_MAP: { [T in MediaType]?: string } = {
|
||||||
|
image: '/newsletter/newsletter-image',
|
||||||
|
video: '/newsletter/newsletter-video',
|
||||||
|
document: '/newsletter/newsletter-document',
|
||||||
|
audio: '/newsletter/newsletter-audio',
|
||||||
|
sticker: '/newsletter/newsletter-image',
|
||||||
|
'thumbnail-link': '/newsletter/newsletter-image'
|
||||||
|
}
|
||||||
|
|
||||||
export const MEDIA_HKDF_KEY_MAPPING = {
|
export const MEDIA_HKDF_KEY_MAPPING = {
|
||||||
audio: 'Audio',
|
audio: 'Audio',
|
||||||
document: 'Document',
|
document: 'Document',
|
||||||
|
|||||||
+26
-11
@@ -49,9 +49,12 @@ import {
|
|||||||
getStatusFromReceiptType,
|
getStatusFromReceiptType,
|
||||||
handleIdentityChange,
|
handleIdentityChange,
|
||||||
hkdf,
|
hkdf,
|
||||||
|
BAD_MAC_ERROR_TEXT,
|
||||||
|
DECRYPTION_RETRY_CONFIG,
|
||||||
MISSING_KEYS_ERROR_TEXT,
|
MISSING_KEYS_ERROR_TEXT,
|
||||||
NACK_REASONS,
|
NACK_REASONS,
|
||||||
NO_MESSAGE_FOUND_ERROR_TEXT,
|
NO_MESSAGE_FOUND_ERROR_TEXT,
|
||||||
|
RetryReason,
|
||||||
normalizeKeyLidToPn,
|
normalizeKeyLidToPn,
|
||||||
normalizeMessageJids,
|
normalizeMessageJids,
|
||||||
resolveLidToPn,
|
resolveLidToPn,
|
||||||
@@ -1312,25 +1315,37 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
const fromJid = node.attrs.from!
|
const fromJid = node.attrs.from!
|
||||||
|
|
||||||
// Derive the Signal error code from the actual decryption failure message.
|
// Derive the Signal error code from the actual decryption failure message.
|
||||||
// This is sent in the retry receipt so the peer (even another InfiniteAPI instance)
|
// Sent in the retry receipt so the peer (even another InfiniteAPI instance)
|
||||||
// knows the exact reason and can recreate the session immediately instead of waiting
|
// knows the exact failure type and can recreate the session immediately
|
||||||
// for the 1-hour timeout fallback.
|
// instead of falling back to the 1-hour timeout.
|
||||||
//
|
//
|
||||||
// Codes mirror RetryReason enum in message-retry-manager.ts:
|
// Codes mirror RetryReason enum in message-retry-manager.ts:
|
||||||
// 0 = UnknownError | 1 = NoSession | 2 = InvalidKey
|
// 0 = UnknownError | 1 = NoSession | 2 = InvalidKey
|
||||||
// 3 = InvalidKeyId | 7 = BadMac (= SignalErrorInvalidMessage/InvalidCipherKey)
|
// 3 = InvalidKeyId | 4 = InvalidMessage | 7 = BadMac
|
||||||
|
//
|
||||||
|
// Uses DECRYPTION_RETRY_CONFIG error lists (single source of truth in
|
||||||
|
// decode-wa-message.ts) so additions to those lists are picked up here
|
||||||
|
// automatically.
|
||||||
//
|
//
|
||||||
// NOTE: We do NOT delete the session here (receiver side). The Signal Protocol
|
// NOTE: We do NOT delete the session here (receiver side). The Signal Protocol
|
||||||
// recovers automatically when the sender's pkmsg arrives — it overwrites the
|
// recovers automatically when the sender's pkmsg arrives — it overwrites the
|
||||||
// corrupted session. Deleting prematurely creates a race window where no session
|
// corrupted session. Deleting prematurely creates a race window where no session
|
||||||
// exists, which can cause "No Session" errors on concurrent messages.
|
// exists, which can cause "No Session" errors on concurrent messages.
|
||||||
const retryErrorCode = (() => {
|
const retryErrorCode = (() => {
|
||||||
if (!decryptionError) return 0
|
if (!decryptionError) return RetryReason.UnknownError
|
||||||
if (/bad\s*mac/i.test(decryptionError)) return 7 // SignalErrorBadMac
|
// Bad MAC must be checked first — it is also in corruptedSessionErrors
|
||||||
if (/no\s*session/i.test(decryptionError)) return 1 // SignalErrorNoSession
|
// but warrants the more specific code 7 over the generic code 4.
|
||||||
if (/pre\s*key/i.test(decryptionError)) return 3 // SignalErrorInvalidKeyId
|
if (decryptionError.includes(BAD_MAC_ERROR_TEXT)) return RetryReason.SignalErrorBadMac
|
||||||
if (/invalid\s*key/i.test(decryptionError)) return 2 // SignalErrorInvalidKey
|
// MessageCounterError and other corrupted-session variants
|
||||||
return 0
|
if (DECRYPTION_RETRY_CONFIG.corruptedSessionErrors.some(e => decryptionError.includes(e))) return RetryReason.SignalErrorInvalidMessage
|
||||||
|
// Missing / invalid session record
|
||||||
|
if (DECRYPTION_RETRY_CONFIG.sessionRecordErrors.some(e => decryptionError.includes(e)) ||
|
||||||
|
/no\s+(open\s+)?sessions?/i.test(decryptionError)) return RetryReason.SignalErrorNoSession
|
||||||
|
// PreKey / key-id errors
|
||||||
|
if (/pre\s*key/i.test(decryptionError)) return RetryReason.SignalErrorInvalidKeyId
|
||||||
|
// Identity / key errors
|
||||||
|
if (/invalid\s*key|untrusted\s*identity/i.test(decryptionError)) return RetryReason.SignalErrorInvalidKey
|
||||||
|
return RetryReason.UnknownError
|
||||||
})()
|
})()
|
||||||
|
|
||||||
if (retryCount <= 2) {
|
if (retryCount <= 2) {
|
||||||
|
|||||||
@@ -1051,7 +1051,7 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
const bytes = encodeNewsletterMessage(patched as proto.IMessage)
|
const bytes = encodeNewsletterMessage(patched as proto.IMessage)
|
||||||
binaryNodeContent.push({
|
binaryNodeContent.push({
|
||||||
tag: 'plaintext',
|
tag: 'plaintext',
|
||||||
attrs: {},
|
attrs: mediaType ? { mediatype: mediaType } : {},
|
||||||
content: bytes
|
content: bytes
|
||||||
})
|
})
|
||||||
const stanza: BinaryNode = {
|
const stanza: BinaryNode = {
|
||||||
|
|||||||
+10
-2
@@ -990,8 +990,16 @@ export type MessageGenerationOptionsFromContent = MiscMessageGenerationOptions &
|
|||||||
|
|
||||||
export type WAMediaUploadFunction = (
|
export type WAMediaUploadFunction = (
|
||||||
encFilePath: string,
|
encFilePath: string,
|
||||||
opts: { fileEncSha256B64: string; mediaType: MediaType; timeoutMs?: number }
|
opts: { fileEncSha256B64: string; mediaType: MediaType; timeoutMs?: number; newsletter?: boolean }
|
||||||
) => Promise<{ mediaUrl: string; directPath: string; meta_hmac?: string; ts?: number; fbid?: number }>
|
) => Promise<{
|
||||||
|
mediaUrl: string | undefined
|
||||||
|
directPath: string
|
||||||
|
meta_hmac?: string
|
||||||
|
ts?: number
|
||||||
|
fbid?: number
|
||||||
|
thumbnailDirectPath?: string
|
||||||
|
thumbnailSha256?: string
|
||||||
|
}>
|
||||||
|
|
||||||
export type MediaGenerationOptions = {
|
export type MediaGenerationOptions = {
|
||||||
logger?: ILogger
|
logger?: ILogger
|
||||||
|
|||||||
@@ -10,7 +10,13 @@ import { join } from 'path'
|
|||||||
import { Readable, Transform } from 'stream'
|
import { Readable, Transform } from 'stream'
|
||||||
import { URL } from 'url'
|
import { URL } from 'url'
|
||||||
import { proto } from '../../WAProto/index.js'
|
import { proto } from '../../WAProto/index.js'
|
||||||
import { DEFAULT_ORIGIN, MEDIA_HKDF_KEY_MAPPING, MEDIA_PATH_MAP, type MediaType } from '../Defaults'
|
import {
|
||||||
|
DEFAULT_ORIGIN,
|
||||||
|
MEDIA_HKDF_KEY_MAPPING,
|
||||||
|
MEDIA_PATH_MAP,
|
||||||
|
type MediaType,
|
||||||
|
NEWSLETTER_MEDIA_PATH_MAP
|
||||||
|
} from '../Defaults'
|
||||||
import type {
|
import type {
|
||||||
BaileysEventMap,
|
BaileysEventMap,
|
||||||
DownloadableMessage,
|
DownloadableMessage,
|
||||||
@@ -681,6 +687,10 @@ type MediaUploadResult = {
|
|||||||
meta_hmac?: string
|
meta_hmac?: string
|
||||||
ts?: number
|
ts?: number
|
||||||
fbid?: number
|
fbid?: number
|
||||||
|
thumbnail_info?: {
|
||||||
|
thumbnail_sha256?: string
|
||||||
|
thumbnail_direct_path?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UploadParams = {
|
export type UploadParams = {
|
||||||
@@ -825,11 +835,21 @@ export const getWAUploadToServer = (
|
|||||||
{ customUploadHosts, fetchAgent, logger, options }: SocketConfig,
|
{ customUploadHosts, fetchAgent, logger, options }: SocketConfig,
|
||||||
refreshMediaConn: (force: boolean) => Promise<MediaConnInfo>
|
refreshMediaConn: (force: boolean) => Promise<MediaConnInfo>
|
||||||
): WAMediaUploadFunction => {
|
): WAMediaUploadFunction => {
|
||||||
return async (filePath, { mediaType, fileEncSha256B64, timeoutMs }) => {
|
return async (filePath, { mediaType, fileEncSha256B64, timeoutMs, newsletter }) => {
|
||||||
// send a query JSON to obtain the url & auth token to upload our media
|
// send a query JSON to obtain the url & auth token to upload our media
|
||||||
let uploadInfo = await refreshMediaConn(false)
|
let uploadInfo = await refreshMediaConn(false)
|
||||||
|
|
||||||
let urls: { mediaUrl: string; directPath: string; meta_hmac?: string; ts?: number; fbid?: number } | undefined
|
let urls:
|
||||||
|
| {
|
||||||
|
mediaUrl: string
|
||||||
|
directPath: string
|
||||||
|
meta_hmac?: string
|
||||||
|
ts?: number
|
||||||
|
fbid?: number
|
||||||
|
thumbnailDirectPath?: string
|
||||||
|
thumbnailSha256?: string
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
const hosts = [...customUploadHosts, ...uploadInfo.hosts]
|
const hosts = [...customUploadHosts, ...uploadInfo.hosts]
|
||||||
|
|
||||||
fileEncSha256B64 = encodeBase64EncodedStringForUpload(fileEncSha256B64)
|
fileEncSha256B64 = encodeBase64EncodedStringForUpload(fileEncSha256B64)
|
||||||
@@ -851,7 +871,11 @@ export const getWAUploadToServer = (
|
|||||||
logger.debug(`uploading to "${hostname}"`)
|
logger.debug(`uploading to "${hostname}"`)
|
||||||
|
|
||||||
const auth = encodeURIComponent(uploadInfo.auth)
|
const auth = encodeURIComponent(uploadInfo.auth)
|
||||||
const url = `https://${hostname}${MEDIA_PATH_MAP[mediaType]}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`
|
const mediaPath = (newsletter ? NEWSLETTER_MEDIA_PATH_MAP[mediaType] : undefined) || MEDIA_PATH_MAP[mediaType]
|
||||||
|
let url = `https://${hostname}${mediaPath}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`
|
||||||
|
if (newsletter) {
|
||||||
|
url += '&server_thumb_gen=1'
|
||||||
|
}
|
||||||
|
|
||||||
let result: MediaUploadResult | undefined
|
let result: MediaUploadResult | undefined
|
||||||
try {
|
try {
|
||||||
@@ -868,11 +892,13 @@ export const getWAUploadToServer = (
|
|||||||
|
|
||||||
if (result?.url || result?.direct_path) {
|
if (result?.url || result?.direct_path) {
|
||||||
urls = {
|
urls = {
|
||||||
mediaUrl: result.url!,
|
mediaUrl: result.url || result.direct_path!,
|
||||||
directPath: result.direct_path!,
|
directPath: result.direct_path!,
|
||||||
meta_hmac: result.meta_hmac,
|
meta_hmac: result.meta_hmac,
|
||||||
fbid: result.fbid,
|
fbid: result.fbid,
|
||||||
ts: result.ts
|
ts: result.ts,
|
||||||
|
thumbnailDirectPath: result.thumbnail_info?.thumbnail_direct_path,
|
||||||
|
thumbnailSha256: result.thumbnail_info?.thumbnail_sha256
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -196,10 +196,11 @@ export const prepareWAMessageMedia = async (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const fileSha256B64 = fileSha256.toString('base64')
|
const fileSha256B64 = fileSha256.toString('base64')
|
||||||
const { mediaUrl, directPath } = await options.upload(filePath, {
|
const { directPath, thumbnailDirectPath, thumbnailSha256 } = await options.upload(filePath, {
|
||||||
fileEncSha256B64: fileSha256B64,
|
fileEncSha256B64: fileSha256B64,
|
||||||
mediaType: mediaType,
|
mediaType: mediaType,
|
||||||
timeoutMs: options.mediaUploadTimeoutMs
|
timeoutMs: options.mediaUploadTimeoutMs,
|
||||||
|
newsletter: true
|
||||||
})
|
})
|
||||||
|
|
||||||
await fs.unlink(filePath)
|
await fs.unlink(filePath)
|
||||||
@@ -207,10 +208,12 @@ export const prepareWAMessageMedia = async (
|
|||||||
const obj = WAProto.Message.fromObject({
|
const obj = WAProto.Message.fromObject({
|
||||||
// todo: add more support here
|
// todo: add more support here
|
||||||
[`${mediaType}Message`]: (MessageTypeProto as any)[mediaType].fromObject({
|
[`${mediaType}Message`]: (MessageTypeProto as any)[mediaType].fromObject({
|
||||||
url: mediaUrl,
|
// url intentionally omitted — newsletters use directPath only
|
||||||
directPath,
|
directPath,
|
||||||
fileSha256,
|
fileSha256,
|
||||||
fileLength,
|
fileLength,
|
||||||
|
thumbnailDirectPath,
|
||||||
|
thumbnailSha256: thumbnailSha256 ? Buffer.from(thumbnailSha256, 'base64') : undefined,
|
||||||
...uploadData,
|
...uploadData,
|
||||||
media: undefined
|
media: undefined
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user