@japofc/baileys 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +111 -0
- package/README.md +1254 -0
- package/WAProto/index.d.ts +9 -0
- package/WAProto/index.js +142276 -0
- package/engine-requirements.js +13 -0
- package/lib/Builders/A2UI.d.ts +242 -0
- package/lib/Builders/A2UI.js +308 -0
- package/lib/Builders/AIRich.d.ts +105 -0
- package/lib/Builders/AIRich.js +2286 -0
- package/lib/Builders/Button.d.ts +103 -0
- package/lib/Builders/Button.js +883 -0
- package/lib/Builders/ButtonV2.d.ts +28 -0
- package/lib/Builders/ButtonV2.js +144 -0
- package/lib/Builders/ButtonV3.d.ts +25 -0
- package/lib/Builders/ButtonV3.js +184 -0
- package/lib/Builders/Carousel.d.ts +22 -0
- package/lib/Builders/Carousel.js +111 -0
- package/lib/Builders/JapBaileys.d.ts +34 -0
- package/lib/Builders/JapBaileys.js +108 -0
- package/lib/Builders/Poll.d.ts +25 -0
- package/lib/Builders/Poll.js +128 -0
- package/lib/Builders/index.d.ts +17 -0
- package/lib/Builders/index.js +11 -0
- package/lib/Builders/shared.d.ts +67 -0
- package/lib/Builders/shared.js +652 -0
- package/lib/Defaults/index.d.ts +154 -0
- package/lib/Defaults/index.js +178 -0
- package/lib/Framework/Bot.d.ts +61 -0
- package/lib/Framework/Bot.js +248 -0
- package/lib/Framework/Context.d.ts +21 -0
- package/lib/Framework/Context.js +89 -0
- package/lib/Framework/MediaManager.d.ts +17 -0
- package/lib/Framework/MediaManager.js +151 -0
- package/lib/Framework/SessionManager.d.ts +13 -0
- package/lib/Framework/SessionManager.js +33 -0
- package/lib/Framework/StatsManager.d.ts +26 -0
- package/lib/Framework/StatsManager.js +119 -0
- package/lib/Framework/Store/SQLiteStore.d.ts +11 -0
- package/lib/Framework/Store/SQLiteStore.js +73 -0
- package/lib/Framework/index.d.ts +9 -0
- package/lib/Framework/index.js +10 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
- package/lib/Signal/Group/ciphertext-message.js +11 -0
- package/lib/Signal/Group/group-session-builder.d.ts +7 -0
- package/lib/Signal/Group/group-session-builder.js +29 -0
- package/lib/Signal/Group/group_cipher.d.ts +10 -0
- package/lib/Signal/Group/group_cipher.js +81 -0
- package/lib/Signal/Group/index.d.ts +11 -0
- package/lib/Signal/Group/index.js +11 -0
- package/lib/Signal/Group/keyhelper.d.ts +6 -0
- package/lib/Signal/Group/keyhelper.js +17 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
- package/lib/Signal/Group/sender-chain-key.js +25 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +62 -0
- package/lib/Signal/Group/sender-key-message.d.ts +18 -0
- package/lib/Signal/Group/sender-key-message.js +65 -0
- package/lib/Signal/Group/sender-key-name.d.ts +11 -0
- package/lib/Signal/Group/sender-key-name.js +47 -0
- package/lib/Signal/Group/sender-key-record.d.ts +12 -0
- package/lib/Signal/Group/sender-key-record.js +40 -0
- package/lib/Signal/Group/sender-key-state.d.ts +16 -0
- package/lib/Signal/Group/sender-key-state.js +83 -0
- package/lib/Signal/Group/sender-message-key.d.ts +11 -0
- package/lib/Signal/Group/sender-message-key.js +25 -0
- package/lib/Signal/libsignal.d.ts +54 -0
- package/lib/Signal/libsignal.js +430 -0
- package/lib/Signal/lid-mapping.d.ts +20 -0
- package/lib/Signal/lid-mapping.js +276 -0
- package/lib/Socket/Client/index.d.ts +2 -0
- package/lib/Socket/Client/index.js +2 -0
- package/lib/Socket/Client/types.d.ts +5 -0
- package/lib/Socket/Client/types.js +10 -0
- package/lib/Socket/Client/websocket.d.ts +12 -0
- package/lib/Socket/Client/websocket.js +53 -0
- package/lib/Socket/business.d.ts +395 -0
- package/lib/Socket/business.js +379 -0
- package/lib/Socket/chats.d.ts +136 -0
- package/lib/Socket/chats.js +1327 -0
- package/lib/Socket/communities.d.ts +562 -0
- package/lib/Socket/communities.js +439 -0
- package/lib/Socket/dugong.d.ts +117 -0
- package/lib/Socket/dugong.js +798 -0
- package/lib/Socket/groups.d.ts +285 -0
- package/lib/Socket/groups.js +354 -0
- package/lib/Socket/index.d.ts +585 -0
- package/lib/Socket/index.js +52 -0
- package/lib/Socket/messages-recv.d.ts +333 -0
- package/lib/Socket/messages-recv.js +1781 -0
- package/lib/Socket/messages-send.d.ts +353 -0
- package/lib/Socket/messages-send.js +1524 -0
- package/lib/Socket/mex.d.ts +1 -0
- package/lib/Socket/mex.js +41 -0
- package/lib/Socket/newsletter.d.ts +286 -0
- package/lib/Socket/newsletter.js +364 -0
- package/lib/Socket/socket.d.ts +60 -0
- package/lib/Socket/socket.js +1012 -0
- package/lib/Socket/username.d.ts +82 -0
- package/lib/Socket/username.js +159 -0
- package/lib/Store/index.d.ts +3 -0
- package/lib/Store/index.js +3 -0
- package/lib/Store/make-in-memory-store.d.ts +62 -0
- package/lib/Store/make-in-memory-store.js +428 -0
- package/lib/Store/make-ordered-dictionary.d.ts +12 -0
- package/lib/Store/make-ordered-dictionary.js +78 -0
- package/lib/Store/object-repository.d.ts +10 -0
- package/lib/Store/object-repository.js +23 -0
- package/lib/Types/Auth.d.ts +117 -0
- package/lib/Types/Auth.js +1 -0
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Call.d.ts +15 -0
- package/lib/Types/Call.js +1 -0
- package/lib/Types/Chat.d.ts +124 -0
- package/lib/Types/Chat.js +7 -0
- package/lib/Types/Contact.d.ts +26 -0
- package/lib/Types/Contact.js +1 -0
- package/lib/Types/Events.d.ts +256 -0
- package/lib/Types/Events.js +1 -0
- package/lib/Types/GroupMetadata.d.ts +71 -0
- package/lib/Types/GroupMetadata.js +1 -0
- package/lib/Types/Label.d.ts +5 -0
- package/lib/Types/Label.js +24 -0
- package/lib/Types/LabelAssociation.d.ts +6 -0
- package/lib/Types/LabelAssociation.js +6 -0
- package/lib/Types/Message.d.ts +62 -0
- package/lib/Types/Message.js +17 -0
- package/lib/Types/Mex.d.ts +2 -0
- package/lib/Types/Mex.js +38 -0
- package/lib/Types/Product.d.ts +79 -0
- package/lib/Types/Product.js +1 -0
- package/lib/Types/RichType.d.ts +2 -0
- package/lib/Types/RichType.js +22 -0
- package/lib/Types/Signal.d.ts +87 -0
- package/lib/Types/Signal.js +1 -0
- package/lib/Types/Socket.d.ts +138 -0
- package/lib/Types/Socket.js +1 -0
- package/lib/Types/State.d.ts +8 -0
- package/lib/Types/State.js +55 -0
- package/lib/Types/USync.d.ts +26 -0
- package/lib/Types/index.d.ts +68 -0
- package/lib/Types/index.js +27 -0
- package/lib/Utils/MessageBuilder.d.ts +2 -0
- package/lib/Utils/MessageBuilder.js +2 -0
- package/lib/Utils/PersistentStore.d.ts +60 -0
- package/lib/Utils/PersistentStore.js +592 -0
- package/lib/Utils/anti-delete.d.ts +74 -0
- package/lib/Utils/anti-delete.js +221 -0
- package/lib/Utils/auth-secure.d.ts +86 -0
- package/lib/Utils/auth-secure.js +764 -0
- package/lib/Utils/auth-utils.d.ts +57 -0
- package/lib/Utils/auth-utils.js +306 -0
- package/lib/Utils/auto-reply.d.ts +47 -0
- package/lib/Utils/auto-reply.js +157 -0
- package/lib/Utils/baileys-event-stream.d.ts +8 -0
- package/lib/Utils/baileys-event-stream.js +62 -0
- package/lib/Utils/browser-utils.d.ts +8 -0
- package/lib/Utils/browser-utils.js +27 -0
- package/lib/Utils/business.d.ts +49 -0
- package/lib/Utils/business.js +239 -0
- package/lib/Utils/button-helper-utils.d.ts +53 -0
- package/lib/Utils/button-helper-utils.js +312 -0
- package/lib/Utils/button-sender.d.ts +54 -0
- package/lib/Utils/button-sender.js +822 -0
- package/lib/Utils/chat-control.d.ts +159 -0
- package/lib/Utils/chat-control.js +230 -0
- package/lib/Utils/chat-history-helpers.d.ts +21 -0
- package/lib/Utils/chat-history-helpers.js +70 -0
- package/lib/Utils/chat-utils.d.ts +407 -0
- package/lib/Utils/chat-utils.js +885 -0
- package/lib/Utils/companion-reg-client-utils.d.ts +4 -0
- package/lib/Utils/companion-reg-client-utils.js +39 -0
- package/lib/Utils/crypto.d.ts +41 -0
- package/lib/Utils/crypto.js +147 -0
- package/lib/Utils/decode-wa-message.d.ts +83 -0
- package/lib/Utils/decode-wa-message.js +316 -0
- package/lib/Utils/event-buffer.d.ts +12 -0
- package/lib/Utils/event-buffer.js +635 -0
- package/lib/Utils/generics.d.ts +69 -0
- package/lib/Utils/generics.js +438 -0
- package/lib/Utils/history-share.d.ts +11 -0
- package/lib/Utils/history-share.js +70 -0
- package/lib/Utils/history.d.ts +90 -0
- package/lib/Utils/history.js +146 -0
- package/lib/Utils/humanizer.d.ts +12 -0
- package/lib/Utils/humanizer.js +73 -0
- package/lib/Utils/identity-change-handler.d.ts +13 -0
- package/lib/Utils/identity-change-handler.js +49 -0
- package/lib/Utils/index.d.ts +57 -0
- package/lib/Utils/index.js +56 -0
- package/lib/Utils/jid-tools.d.ts +6 -0
- package/lib/Utils/jid-tools.js +77 -0
- package/lib/Utils/link-preview.d.ts +12 -0
- package/lib/Utils/link-preview.js +84 -0
- package/lib/Utils/logger.d.ts +4 -0
- package/lib/Utils/logger.js +2 -0
- package/lib/Utils/lt-hash.d.ts +12 -0
- package/lib/Utils/lt-hash.js +26 -0
- package/lib/Utils/make-mutex.d.ts +6 -0
- package/lib/Utils/make-mutex.js +32 -0
- package/lib/Utils/media-messages.d.ts +18 -0
- package/lib/Utils/media-messages.js +70 -0
- package/lib/Utils/media-set.d.ts +13 -0
- package/lib/Utils/media-set.js +171 -0
- package/lib/Utils/message-kind.d.ts +32 -0
- package/lib/Utils/message-kind.js +136 -0
- package/lib/Utils/message-retry-manager.d.ts +79 -0
- package/lib/Utils/message-retry-manager.js +264 -0
- package/lib/Utils/message-search.d.ts +44 -0
- package/lib/Utils/message-search.js +188 -0
- package/lib/Utils/messages-media.d.ts +135 -0
- package/lib/Utils/messages-media.js +868 -0
- package/lib/Utils/messages.d.ts +44 -0
- package/lib/Utils/messages.js +2326 -0
- package/lib/Utils/meta-ai.d.ts +13 -0
- package/lib/Utils/meta-ai.js +74 -0
- package/lib/Utils/mini-app.d.ts +35 -0
- package/lib/Utils/mini-app.js +213 -0
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/noise-handler.js +200 -0
- package/lib/Utils/offline-node-processor.d.ts +9 -0
- package/lib/Utils/offline-node-processor.js +39 -0
- package/lib/Utils/past-participants.d.ts +14 -0
- package/lib/Utils/past-participants.js +40 -0
- package/lib/Utils/pre-key-manager.d.ts +25 -0
- package/lib/Utils/pre-key-manager.js +105 -0
- package/lib/Utils/process-message.d.ts +82 -0
- package/lib/Utils/process-message.js +808 -0
- package/lib/Utils/qr-render.d.ts +59 -0
- package/lib/Utils/qr-render.js +179 -0
- package/lib/Utils/qrcodegen.d.ts +79 -0
- package/lib/Utils/qrcodegen.js +848 -0
- package/lib/Utils/reporting-utils.d.ts +12 -0
- package/lib/Utils/reporting-utils.js +257 -0
- package/lib/Utils/rich-message-utils.d.ts +48 -0
- package/lib/Utils/rich-message-utils.js +444 -0
- package/lib/Utils/router.d.ts +37 -0
- package/lib/Utils/router.js +165 -0
- package/lib/Utils/scheduled-posts.d.ts +30 -0
- package/lib/Utils/scheduled-posts.js +110 -0
- package/lib/Utils/scheduling.d.ts +42 -0
- package/lib/Utils/scheduling.js +139 -0
- package/lib/Utils/signal.d.ts +82 -0
- package/lib/Utils/signal.js +200 -0
- package/lib/Utils/stanza-ack.d.ts +16 -0
- package/lib/Utils/stanza-ack.js +37 -0
- package/lib/Utils/status.d.ts +50 -0
- package/lib/Utils/status.js +107 -0
- package/lib/Utils/stickerpack.d.ts +51 -0
- package/lib/Utils/stickerpack.js +274 -0
- package/lib/Utils/sync-action-utils.d.ts +2 -0
- package/lib/Utils/sync-action-utils.js +48 -0
- package/lib/Utils/tag.d.ts +12 -0
- package/lib/Utils/tag.js +44 -0
- package/lib/Utils/tc-token-utils.d.ts +29 -0
- package/lib/Utils/tc-token-utils.js +162 -0
- package/lib/Utils/templates.d.ts +76 -0
- package/lib/Utils/templates.js +150 -0
- package/lib/Utils/transcribe.d.ts +12 -0
- package/lib/Utils/transcribe.js +107 -0
- package/lib/Utils/use-cache-manager-auth-state.d.ts +13 -0
- package/lib/Utils/use-cache-manager-auth-state.js +81 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-multi-file-auth-state.js +166 -0
- package/lib/Utils/use-single-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-single-file-auth-state.js +113 -0
- package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
- package/lib/Utils/use-sqlite-auth-state.js +169 -0
- package/lib/Utils/validate-connection.d.ts +42 -0
- package/lib/Utils/validate-connection.js +198 -0
- package/lib/Utils/vcard.d.ts +58 -0
- package/lib/Utils/vcard.js +104 -0
- package/lib/Utils/voice-note.d.ts +15 -0
- package/lib/Utils/voice-note.js +63 -0
- package/lib/VoIP/audio-feeder.d.ts +18 -0
- package/lib/VoIP/audio-feeder.js +160 -0
- package/lib/VoIP/call-recorder.d.ts +13 -0
- package/lib/VoIP/call-recorder.js +73 -0
- package/lib/VoIP/index.d.ts +86 -0
- package/lib/VoIP/index.js +611 -0
- package/lib/VoIP/relay-transport.d.ts +43 -0
- package/lib/VoIP/relay-transport.js +563 -0
- package/lib/VoIP/signaling.d.ts +26 -0
- package/lib/VoIP/signaling.js +662 -0
- package/lib/VoIP/types.d.ts +69 -0
- package/lib/VoIP/types.js +17 -0
- package/lib/VoIP/wasm-engine.d.ts +120 -0
- package/lib/VoIP/wasm-engine.js +1358 -0
- package/lib/VoIP/worker-bootstrap.d.ts +4 -0
- package/lib/VoIP/worker-bootstrap.js +1046 -0
- package/lib/WABinary/constants.d.ts +61 -0
- package/lib/WABinary/constants.js +1466 -0
- package/lib/WABinary/decode.d.ts +9 -0
- package/lib/WABinary/decode.js +261 -0
- package/lib/WABinary/encode.d.ts +2 -0
- package/lib/WABinary/encode.js +219 -0
- package/lib/WABinary/generic-utils.d.ts +74 -0
- package/lib/WABinary/generic-utils.js +276 -0
- package/lib/WABinary/index.d.ts +5 -0
- package/lib/WABinary/index.js +5 -0
- package/lib/WABinary/jid-utils.d.ts +28 -0
- package/lib/WABinary/jid-utils.js +95 -0
- package/lib/WABinary/types.d.ts +19 -0
- package/lib/WABinary/types.js +1 -0
- package/lib/WAM/BinaryInfo.d.ts +7 -0
- package/lib/WAM/BinaryInfo.js +9 -0
- package/lib/WAM/constants.d.ts +34926 -0
- package/lib/WAM/constants.js +22852 -0
- package/lib/WAM/encode.d.ts +1 -0
- package/lib/WAM/encode.js +149 -0
- package/lib/WAM/index.d.ts +3 -0
- package/lib/WAM/index.js +3 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +36 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +51 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +29 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +62 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +9 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +24 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +38 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +14 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
- package/lib/WAUSync/Protocols/index.d.ts +7 -0
- package/lib/WAUSync/Protocols/index.js +7 -0
- package/lib/WAUSync/USyncQuery.d.ts +20 -0
- package/lib/WAUSync/USyncQuery.js +121 -0
- package/lib/WAUSync/USyncUser.d.ts +16 -0
- package/lib/WAUSync/USyncUser.js +30 -0
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/WAUSync/index.js +3 -0
- package/lib/assets/wasm/loader.d.ts +5 -0
- package/lib/assets/wasm/loader.js +5 -0
- package/lib/assets/wasm/whatsapp.wasm +0 -0
- package/lib/assets/wasm/worker-modules.d.ts +5 -0
- package/lib/assets/wasm/worker-modules.js +273 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +23 -0
- package/package.json +180 -0
- package/postinstall-banner.js +82 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uploads images not already uploaded to WA's servers
|
|
3
|
+
*/
|
|
4
|
+
export function uploadingNecessaryImagesOfProduct(product: any, waUploadToServer: any, timeoutMs?: number): Promise<any>;
|
|
5
|
+
export function parseCatalogNode(node: any): {
|
|
6
|
+
products: any;
|
|
7
|
+
nextPageCursor: any;
|
|
8
|
+
};
|
|
9
|
+
export function parseCollectionsNode(node: any): {
|
|
10
|
+
collections: any;
|
|
11
|
+
};
|
|
12
|
+
export function parseOrderDetailsNode(node: any): {
|
|
13
|
+
price: {
|
|
14
|
+
total: number;
|
|
15
|
+
currency: any;
|
|
16
|
+
};
|
|
17
|
+
products: any;
|
|
18
|
+
};
|
|
19
|
+
export function toProductNode(productId: any, product: any): {
|
|
20
|
+
tag: string;
|
|
21
|
+
attrs: {
|
|
22
|
+
compliance_category: string;
|
|
23
|
+
is_hidden: any;
|
|
24
|
+
};
|
|
25
|
+
content: {
|
|
26
|
+
tag: string;
|
|
27
|
+
attrs: {};
|
|
28
|
+
content: any;
|
|
29
|
+
}[];
|
|
30
|
+
};
|
|
31
|
+
export function parseProductNode(productNode: any): {
|
|
32
|
+
id: any;
|
|
33
|
+
imageUrls: {
|
|
34
|
+
requested: any;
|
|
35
|
+
original: any;
|
|
36
|
+
};
|
|
37
|
+
reviewStatus: {
|
|
38
|
+
whatsapp: any;
|
|
39
|
+
};
|
|
40
|
+
availability: string;
|
|
41
|
+
name: any;
|
|
42
|
+
retailerId: any;
|
|
43
|
+
url: any;
|
|
44
|
+
description: any;
|
|
45
|
+
price: number;
|
|
46
|
+
currency: any;
|
|
47
|
+
isHidden: boolean;
|
|
48
|
+
};
|
|
49
|
+
export function uploadingNecessaryImages(images: any, waUploadToServer: any, timeoutMs?: number): Promise<any[]>;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import { createWriteStream, promises as fs } from 'fs';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString } from '../WABinary/index.js';
|
|
7
|
+
import { generateMessageIDV2 } from './generics.js';
|
|
8
|
+
import logger from './logger.js';
|
|
9
|
+
import { getStream, getUrlFromDirectPath } from './messages-media.js';
|
|
10
|
+
export const parseCatalogNode = (node) => {
|
|
11
|
+
const catalogNode = getBinaryNodeChild(node, 'product_catalog');
|
|
12
|
+
const products = getBinaryNodeChildren(catalogNode, 'product').map(parseProductNode);
|
|
13
|
+
const paging = getBinaryNodeChild(catalogNode, 'paging');
|
|
14
|
+
return {
|
|
15
|
+
products,
|
|
16
|
+
nextPageCursor: paging ? getBinaryNodeChildString(paging, 'after') : undefined
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export const parseCollectionsNode = (node) => {
|
|
20
|
+
const collectionsNode = getBinaryNodeChild(node, 'collections');
|
|
21
|
+
const collections = getBinaryNodeChildren(collectionsNode, 'collection').map(collectionNode => {
|
|
22
|
+
const id = getBinaryNodeChildString(collectionNode, 'id');
|
|
23
|
+
const name = getBinaryNodeChildString(collectionNode, 'name');
|
|
24
|
+
const products = getBinaryNodeChildren(collectionNode, 'product').map(parseProductNode);
|
|
25
|
+
return {
|
|
26
|
+
id,
|
|
27
|
+
name,
|
|
28
|
+
products,
|
|
29
|
+
status: parseStatusInfo(collectionNode)
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
collections
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export const parseOrderDetailsNode = (node) => {
|
|
37
|
+
const orderNode = getBinaryNodeChild(node, 'order');
|
|
38
|
+
const products = getBinaryNodeChildren(orderNode, 'product').map(productNode => {
|
|
39
|
+
const imageNode = getBinaryNodeChild(productNode, 'image');
|
|
40
|
+
return {
|
|
41
|
+
id: getBinaryNodeChildString(productNode, 'id'),
|
|
42
|
+
name: getBinaryNodeChildString(productNode, 'name'),
|
|
43
|
+
imageUrl: getBinaryNodeChildString(imageNode, 'url'),
|
|
44
|
+
price: +getBinaryNodeChildString(productNode, 'price'),
|
|
45
|
+
currency: getBinaryNodeChildString(productNode, 'currency'),
|
|
46
|
+
quantity: +getBinaryNodeChildString(productNode, 'quantity')
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
const priceNode = getBinaryNodeChild(orderNode, 'price');
|
|
50
|
+
const orderDetails = {
|
|
51
|
+
price: {
|
|
52
|
+
total: +getBinaryNodeChildString(priceNode, 'total'),
|
|
53
|
+
currency: getBinaryNodeChildString(priceNode, 'currency')
|
|
54
|
+
},
|
|
55
|
+
products
|
|
56
|
+
};
|
|
57
|
+
return orderDetails;
|
|
58
|
+
};
|
|
59
|
+
export const toProductNode = (productId, product) => {
|
|
60
|
+
const attrs = {};
|
|
61
|
+
const content = [];
|
|
62
|
+
if (typeof productId !== 'undefined') {
|
|
63
|
+
content.push({
|
|
64
|
+
tag: 'id',
|
|
65
|
+
attrs: {},
|
|
66
|
+
content: Buffer.from(productId)
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (typeof product.name !== 'undefined') {
|
|
70
|
+
content.push({
|
|
71
|
+
tag: 'name',
|
|
72
|
+
attrs: {},
|
|
73
|
+
content: Buffer.from(product.name)
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (typeof product.description !== 'undefined') {
|
|
77
|
+
content.push({
|
|
78
|
+
tag: 'description',
|
|
79
|
+
attrs: {},
|
|
80
|
+
content: Buffer.from(product.description)
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (typeof product.retailerId !== 'undefined') {
|
|
84
|
+
content.push({
|
|
85
|
+
tag: 'retailer_id',
|
|
86
|
+
attrs: {},
|
|
87
|
+
content: Buffer.from(product.retailerId)
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (product.images.length) {
|
|
91
|
+
content.push({
|
|
92
|
+
tag: 'media',
|
|
93
|
+
attrs: {},
|
|
94
|
+
content: product.images.map(img => {
|
|
95
|
+
if (!('url' in img)) {
|
|
96
|
+
throw new Boom('Expected img for product to already be uploaded', { statusCode: 400 });
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
tag: 'image',
|
|
100
|
+
attrs: {},
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
tag: 'url',
|
|
104
|
+
attrs: {},
|
|
105
|
+
content: Buffer.from(img.url.toString())
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
};
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (typeof product.price !== 'undefined') {
|
|
113
|
+
content.push({
|
|
114
|
+
tag: 'price',
|
|
115
|
+
attrs: {},
|
|
116
|
+
content: Buffer.from(product.price.toString())
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (typeof product.currency !== 'undefined') {
|
|
120
|
+
content.push({
|
|
121
|
+
tag: 'currency',
|
|
122
|
+
attrs: {},
|
|
123
|
+
content: Buffer.from(product.currency)
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
if ('originCountryCode' in product) {
|
|
127
|
+
if (typeof product.originCountryCode === 'undefined') {
|
|
128
|
+
attrs['compliance_category'] = 'COUNTRY_ORIGIN_EXEMPT';
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
content.push({
|
|
132
|
+
tag: 'compliance_info',
|
|
133
|
+
attrs: {},
|
|
134
|
+
content: [
|
|
135
|
+
{
|
|
136
|
+
tag: 'country_code_origin',
|
|
137
|
+
attrs: {},
|
|
138
|
+
content: Buffer.from(product.originCountryCode)
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (typeof product.isHidden !== 'undefined') {
|
|
145
|
+
attrs['is_hidden'] = product.isHidden.toString();
|
|
146
|
+
}
|
|
147
|
+
const node = {
|
|
148
|
+
tag: 'product',
|
|
149
|
+
attrs,
|
|
150
|
+
content
|
|
151
|
+
};
|
|
152
|
+
return node;
|
|
153
|
+
};
|
|
154
|
+
export const parseProductNode = (productNode) => {
|
|
155
|
+
const isHidden = productNode.attrs.is_hidden === 'true';
|
|
156
|
+
const id = getBinaryNodeChildString(productNode, 'id');
|
|
157
|
+
const mediaNode = getBinaryNodeChild(productNode, 'media');
|
|
158
|
+
const statusInfoNode = getBinaryNodeChild(productNode, 'status_info');
|
|
159
|
+
const product = {
|
|
160
|
+
id,
|
|
161
|
+
imageUrls: parseImageUrls(mediaNode),
|
|
162
|
+
reviewStatus: {
|
|
163
|
+
whatsapp: getBinaryNodeChildString(statusInfoNode, 'status')
|
|
164
|
+
},
|
|
165
|
+
availability: 'in stock',
|
|
166
|
+
name: getBinaryNodeChildString(productNode, 'name'),
|
|
167
|
+
retailerId: getBinaryNodeChildString(productNode, 'retailer_id'),
|
|
168
|
+
url: getBinaryNodeChildString(productNode, 'url'),
|
|
169
|
+
description: getBinaryNodeChildString(productNode, 'description'),
|
|
170
|
+
price: +getBinaryNodeChildString(productNode, 'price'),
|
|
171
|
+
currency: getBinaryNodeChildString(productNode, 'currency'),
|
|
172
|
+
isHidden
|
|
173
|
+
};
|
|
174
|
+
return product;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Uploads images not already uploaded to WA's servers
|
|
178
|
+
*/
|
|
179
|
+
export async function uploadingNecessaryImagesOfProduct(product, waUploadToServer, timeoutMs = 30000) {
|
|
180
|
+
product = {
|
|
181
|
+
...product,
|
|
182
|
+
images: product.images
|
|
183
|
+
? await uploadingNecessaryImages(product.images, waUploadToServer, timeoutMs)
|
|
184
|
+
: product.images
|
|
185
|
+
};
|
|
186
|
+
return product;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Uploads images not already uploaded to WA's servers
|
|
190
|
+
*/
|
|
191
|
+
export const uploadingNecessaryImages = async (images, waUploadToServer, timeoutMs = 30000) => {
|
|
192
|
+
const results = await Promise.all(images.map(async (img) => {
|
|
193
|
+
if ('url' in img) {
|
|
194
|
+
const url = img.url.toString();
|
|
195
|
+
if (url.includes('.whatsapp.net')) {
|
|
196
|
+
return { url };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const { stream } = await getStream(img);
|
|
200
|
+
const hasher = createHash('sha256');
|
|
201
|
+
const filePath = join(tmpdir(), 'img' + generateMessageIDV2());
|
|
202
|
+
const encFileWriteStream = createWriteStream(filePath);
|
|
203
|
+
// JAP@Fix (bug 61): no 'error' listener meant a write failure (e.g. disk
|
|
204
|
+
// full) would surface as an unhandled 'error' event instead of rejecting
|
|
205
|
+
// this promise; and the stream was never closed before unlink() below.
|
|
206
|
+
const writeStreamError = new Promise((_, reject) => encFileWriteStream.on('error', reject));
|
|
207
|
+
for await (const block of stream) {
|
|
208
|
+
hasher.update(block);
|
|
209
|
+
encFileWriteStream.write(block);
|
|
210
|
+
}
|
|
211
|
+
await Promise.race([
|
|
212
|
+
new Promise((resolve) => encFileWriteStream.end(resolve)),
|
|
213
|
+
writeStreamError
|
|
214
|
+
]);
|
|
215
|
+
const sha = hasher.digest('base64');
|
|
216
|
+
const { directPath } = await waUploadToServer(filePath, {
|
|
217
|
+
mediaType: 'product-catalog-image',
|
|
218
|
+
fileEncSha256B64: sha,
|
|
219
|
+
timeoutMs
|
|
220
|
+
});
|
|
221
|
+
await fs.unlink(filePath).catch(err => logger.warn({ err, filePath }, 'JAP@Fix (bug 57): error deleting temp file')); // was console.log
|
|
222
|
+
return { url: getUrlFromDirectPath(directPath) };
|
|
223
|
+
}));
|
|
224
|
+
return results;
|
|
225
|
+
};
|
|
226
|
+
const parseImageUrls = (mediaNode) => {
|
|
227
|
+
const imgNode = getBinaryNodeChild(mediaNode, 'image');
|
|
228
|
+
return {
|
|
229
|
+
requested: getBinaryNodeChildString(imgNode, 'request_image_url'),
|
|
230
|
+
original: getBinaryNodeChildString(imgNode, 'original_image_url')
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
const parseStatusInfo = (mediaNode) => {
|
|
234
|
+
const node = getBinaryNodeChild(mediaNode, 'status_info');
|
|
235
|
+
return {
|
|
236
|
+
status: getBinaryNodeChildString(node, 'status'),
|
|
237
|
+
canAppeal: getBinaryNodeChildString(node, 'can_appeal') === 'true'
|
|
238
|
+
};
|
|
239
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { BinaryNode } from '../WABinary/index.js';
|
|
2
|
+
|
|
3
|
+
export type DetectedMediaType =
|
|
4
|
+
| 'image' | 'gif' | 'video' | 'ptt' | 'audio' | 'vcard' | 'document'
|
|
5
|
+
| 'contact_array' | 'livelocation' | 'sticker' | 'list' | 'list_response'
|
|
6
|
+
| 'buttons_response' | 'order' | 'product' | 'native_flow_response' | 'url' | '';
|
|
7
|
+
|
|
8
|
+
export type DetectedMessageType = 'reaction' | 'poll' | 'event' | 'media' | 'text';
|
|
9
|
+
export type DetectedButtonType = 'list' | 'buttons' | 'native_flow' | undefined;
|
|
10
|
+
|
|
11
|
+
export declare function getMediaType(message: any): DetectedMediaType;
|
|
12
|
+
export declare function getMessageType(message: any): DetectedMessageType;
|
|
13
|
+
export declare function getButtonType(message: any): DetectedButtonType;
|
|
14
|
+
/** Derive the binary node(s) that must accompany a button/interactive/list message. */
|
|
15
|
+
export declare function getButtonArgs(message: any): BinaryNode;
|
|
16
|
+
/** Build contextInfo for @mention or @all. */
|
|
17
|
+
export declare const buildMentionContextInfo: (message: any) => {
|
|
18
|
+
contextInfo: Record<string, any>;
|
|
19
|
+
};
|
|
20
|
+
/** Extract embedded media from buttons/interactive message (top-level or header-nested). */
|
|
21
|
+
export declare const extractFromButtonsMessage: (msg: any) => {
|
|
22
|
+
imageMessage?: any;
|
|
23
|
+
videoMessage?: any;
|
|
24
|
+
documentMessage?: any;
|
|
25
|
+
} | null;
|
|
26
|
+
/** Normalise media input: string → { url }, Buffer → as-is, others → as-is. */
|
|
27
|
+
export declare const normalizeMediaInput: (media: any) => any;
|
|
28
|
+
/** Wrap buttons/template/list/interactive in viewOnceMessageV2Extension for MD clients. */
|
|
29
|
+
export declare const patchMessageForMdIfRequired: (message: any) => any;
|
|
30
|
+
|
|
31
|
+
export interface AlbumMessageOptions {
|
|
32
|
+
userJid: string;
|
|
33
|
+
/** Socket surface used for relay + upload (`sock`). */
|
|
34
|
+
suki: any;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Build and relay an album (multi-image/video) message. Returns the individual media WAMessages. */
|
|
38
|
+
export declare const prepareAlbumMessageContent: (jid: string, albums: any[], options: AlbumMessageOptions) => Promise<any[]>;
|
|
39
|
+
|
|
40
|
+
export interface MessageExtrasContext {
|
|
41
|
+
query: (...args: any[]) => Promise<any>;
|
|
42
|
+
newsletterWMexQuery?: (...args: any[]) => Promise<any>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface MessageExtrasAddon {
|
|
46
|
+
/** Fetch profile picture URL for any JID, including newsletters. */
|
|
47
|
+
profilePictureUrl: (jid: string) => Promise<string | null>;
|
|
48
|
+
/** Query the ephemeral (disappearing messages) timer for a group. 0 if not set. */
|
|
49
|
+
getEphemeralGroup: (jid: string) => Promise<number | string>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Addon factory for socket-level message extras (profilePictureUrl, getEphemeralGroup). */
|
|
53
|
+
export declare const makeMessageExtrasAddon: (ctx: MessageExtrasContext) => MessageExtrasAddon;
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
// Evernight AI — lib/Utils/button-helper-utils.js / Creator : J.AP
|
|
2
|
+
// Converted TS -> JS ESM to match @japofc/baileys compiled-lib conventions.
|
|
3
|
+
|
|
4
|
+
import { randomBytes } from 'crypto';
|
|
5
|
+
import { generateWAMessage, generateWAMessageFromContent, normalizeMessageContent } from './messages.js';
|
|
6
|
+
import { getUrlFromDirectPath } from './messages-media.js';
|
|
7
|
+
import { unixTimestampSeconds } from './generics.js';
|
|
8
|
+
import { getBinaryNodeChild, isJidGroup, isJidNewsletter, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
9
|
+
import { QueryIds, XWAPaths } from '../Types/Mex.js';
|
|
10
|
+
|
|
11
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
12
|
+
// SECTION 1 — Message Type Detection
|
|
13
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
/** @param {import('../../WAProto/index.js').proto.IMessage} message */
|
|
16
|
+
export function getMediaType(message) {
|
|
17
|
+
if (message.imageMessage) return 'image';
|
|
18
|
+
if (message.videoMessage) return message.videoMessage.gifPlayback ? 'gif' : 'video';
|
|
19
|
+
if (message.audioMessage) return message.audioMessage.ptt ? 'ptt' : 'audio';
|
|
20
|
+
if (message.contactMessage) return 'vcard';
|
|
21
|
+
if (message.documentMessage) return 'document';
|
|
22
|
+
if (message.contactsArrayMessage) return 'contact_array';
|
|
23
|
+
if (message.liveLocationMessage) return 'livelocation';
|
|
24
|
+
if (message.stickerMessage) return 'sticker';
|
|
25
|
+
if (message.listMessage) return 'list';
|
|
26
|
+
if (message.listResponseMessage) return 'list_response';
|
|
27
|
+
if (message.buttonsResponseMessage) return 'buttons_response';
|
|
28
|
+
if (message.orderMessage) return 'order';
|
|
29
|
+
if (message.productMessage) return 'product';
|
|
30
|
+
if (message.interactiveResponseMessage) return 'native_flow_response';
|
|
31
|
+
if (message.groupInviteMessage) return 'url';
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** @param {import('../../WAProto/index.js').proto.IMessage} message */
|
|
36
|
+
export function getMessageType(message) {
|
|
37
|
+
const normalizedMessage = normalizeMessageContent(message);
|
|
38
|
+
if (!normalizedMessage) return 'text';
|
|
39
|
+
if (normalizedMessage.reactionMessage || normalizedMessage.encReactionMessage) return 'reaction';
|
|
40
|
+
if (
|
|
41
|
+
normalizedMessage.pollCreationMessage ||
|
|
42
|
+
normalizedMessage.pollCreationMessageV2 ||
|
|
43
|
+
normalizedMessage.pollCreationMessageV3 ||
|
|
44
|
+
normalizedMessage.pollUpdateMessage
|
|
45
|
+
)
|
|
46
|
+
return 'poll';
|
|
47
|
+
if (normalizedMessage.eventMessage) return 'event';
|
|
48
|
+
if (getMediaType(normalizedMessage) !== '') return 'media';
|
|
49
|
+
return 'text';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
53
|
+
// SECTION 2 — Button / Biz Node Helpers
|
|
54
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
/** @param {import('../../WAProto/index.js').proto.IMessage} message */
|
|
57
|
+
export function getButtonType(message) {
|
|
58
|
+
const inner = message.viewOnceMessageV2Extension?.message || message;
|
|
59
|
+
if (inner.listMessage) return 'list';
|
|
60
|
+
if (inner.buttonsMessage) return 'buttons';
|
|
61
|
+
if (inner.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
62
|
+
if (inner.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
63
|
+
if (message.viewOnceMessage?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
64
|
+
if (message.viewOnceMessageV2?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
65
|
+
if (message.viewOnceMessage?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
66
|
+
if (message.viewOnceMessageV2?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
67
|
+
if (message.viewOnceMessageV2Extension?.message?.interactiveMessage?.nativeFlowMessage) return 'native_flow';
|
|
68
|
+
if (message.viewOnceMessageV2Extension?.message?.interactiveMessage?.carouselMessage) return 'native_flow';
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Derive the binary node(s) that must accompany a button/interactive/list
|
|
74
|
+
* message so it renders correctly across WA Messenger + WA Business,
|
|
75
|
+
* Android + iOS.
|
|
76
|
+
* @param {import('../../WAProto/index.js').proto.IMessage} message
|
|
77
|
+
* @returns {import('../WABinary/index.js').BinaryNode}
|
|
78
|
+
*/
|
|
79
|
+
export function getButtonArgs(message) {
|
|
80
|
+
const inner = message.viewOnceMessageV2Extension?.message || message;
|
|
81
|
+
const nativeFlow =
|
|
82
|
+
inner.interactiveMessage?.nativeFlowMessage ||
|
|
83
|
+
message.viewOnceMessage?.message?.interactiveMessage?.nativeFlowMessage ||
|
|
84
|
+
message.viewOnceMessageV2?.message?.interactiveMessage?.nativeFlowMessage;
|
|
85
|
+
const carouselMessage =
|
|
86
|
+
inner.interactiveMessage?.carouselMessage ||
|
|
87
|
+
message.viewOnceMessage?.message?.interactiveMessage?.carouselMessage ||
|
|
88
|
+
message.viewOnceMessageV2?.message?.interactiveMessage?.carouselMessage;
|
|
89
|
+
|
|
90
|
+
const firstButtonName =
|
|
91
|
+
nativeFlow?.buttons?.[0]?.name ||
|
|
92
|
+
carouselMessage?.cards?.[0]?.nativeFlowMessage?.buttons?.[0]?.name;
|
|
93
|
+
const nativeFlowSpecials = [
|
|
94
|
+
'mpm',
|
|
95
|
+
'cta_catalog',
|
|
96
|
+
'send_location',
|
|
97
|
+
'call_permission_request',
|
|
98
|
+
'wa_payment_transaction_details',
|
|
99
|
+
'automated_greeting_message_view_catalog'
|
|
100
|
+
];
|
|
101
|
+
const ts = unixTimestampSeconds().toString();
|
|
102
|
+
if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info')) {
|
|
103
|
+
return {
|
|
104
|
+
tag: 'biz',
|
|
105
|
+
attrs: { native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' : firstButtonName }
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (nativeFlow && nativeFlowSpecials.includes(firstButtonName ?? '')) {
|
|
110
|
+
return {
|
|
111
|
+
tag: 'biz',
|
|
112
|
+
attrs: { actual_actors: '2', host_storage: '2', privacy_mode_ts: ts },
|
|
113
|
+
content: [
|
|
114
|
+
{
|
|
115
|
+
tag: 'interactive',
|
|
116
|
+
attrs: { type: 'native_flow', v: '1' },
|
|
117
|
+
content: [{ tag: 'native_flow', attrs: { v: '2', name: firstButtonName } }]
|
|
118
|
+
},
|
|
119
|
+
{ tag: 'quality_control', attrs: { source_type: 'third_party' } }
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (nativeFlow || carouselMessage || message.buttonsMessage) {
|
|
125
|
+
return {
|
|
126
|
+
tag: 'biz',
|
|
127
|
+
attrs: {},
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
tag: 'interactive',
|
|
131
|
+
attrs: { type: 'native_flow', v: '1' },
|
|
132
|
+
content: [{ tag: 'native_flow', attrs: { v: '9', name: 'mixed' } }]
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (inner.listMessage) {
|
|
139
|
+
return { tag: 'biz', attrs: {}, content: [{ tag: 'list', attrs: { v: '2', type: 'product_list' } }] };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return { tag: 'biz', attrs: {} };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
146
|
+
// SECTION 3 — WS Extras (mentions, media, MD patch, album, socket extras)
|
|
147
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
/** Build contextInfo for @mention or @all. */
|
|
150
|
+
export const buildMentionContextInfo = (message) => {
|
|
151
|
+
if (message.mentionAll) return { contextInfo: { nonJidMentions: 1 } };
|
|
152
|
+
if (message.mentions?.length) return { contextInfo: { mentionedJid: message.mentions } };
|
|
153
|
+
return { contextInfo: {} };
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/** Extract embedded media from buttons/interactive message (top-level or header-nested). */
|
|
157
|
+
export const extractFromButtonsMessage = (msg) => {
|
|
158
|
+
const header = typeof msg.header === 'object' && msg.header !== null;
|
|
159
|
+
if (header ? msg.header?.imageMessage : msg.imageMessage)
|
|
160
|
+
return { imageMessage: header ? msg.header.imageMessage : msg.imageMessage };
|
|
161
|
+
if (header ? msg.header?.videoMessage : msg.videoMessage)
|
|
162
|
+
return { videoMessage: header ? msg.header.videoMessage : msg.videoMessage };
|
|
163
|
+
if (header ? msg.header?.documentMessage : msg.documentMessage)
|
|
164
|
+
return { documentMessage: header ? msg.header.documentMessage : msg.documentMessage };
|
|
165
|
+
return null;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/** Normalise media input: string → { url }, Buffer → as-is, others → as-is. */
|
|
169
|
+
export const normalizeMediaInput = (media) => {
|
|
170
|
+
if (!media) return media;
|
|
171
|
+
if (Buffer.isBuffer(media)) return media;
|
|
172
|
+
if (typeof media === 'string') return { url: media };
|
|
173
|
+
return media;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/** Wrap buttons/template/list/interactive in viewOnceMessageV2Extension for MD clients. */
|
|
177
|
+
export const patchMessageForMdIfRequired = (message) => {
|
|
178
|
+
if (
|
|
179
|
+
message?.buttonsMessage ||
|
|
180
|
+
message?.templateMessage ||
|
|
181
|
+
message?.listMessage ||
|
|
182
|
+
message?.interactiveMessage?.nativeFlowMessage
|
|
183
|
+
) {
|
|
184
|
+
return {
|
|
185
|
+
viewOnceMessageV2Extension: {
|
|
186
|
+
message: {
|
|
187
|
+
messageContextInfo: { deviceListMetadataVersion: 2, deviceListMetadata: {} },
|
|
188
|
+
...message
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return message;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Build and relay an album (multi-image/video) message.
|
|
199
|
+
* @param {string} jid
|
|
200
|
+
* @param {Array<object>} albums
|
|
201
|
+
* @param {{ userJid: string, suki: { relayMessage: Function, waUploadToServer: Function } }} options
|
|
202
|
+
* @returns {Promise<Array<object>>} Array of individual media WAMessage objects
|
|
203
|
+
* @example
|
|
204
|
+
* const items = await prepareAlbumMessageContent(jid, [
|
|
205
|
+
* { image: { url: 'https://...' }, caption: 'Photo 1' },
|
|
206
|
+
* { video: { url: 'https://...' }, caption: 'Video 1' }
|
|
207
|
+
* ], { userJid: sock.user.id, suki: sock })
|
|
208
|
+
*/
|
|
209
|
+
export const prepareAlbumMessageContent = async (jid, albums, options) => {
|
|
210
|
+
const messages = [];
|
|
211
|
+
|
|
212
|
+
const albumMsg = generateWAMessageFromContent(
|
|
213
|
+
jid,
|
|
214
|
+
{
|
|
215
|
+
albumMessage: {
|
|
216
|
+
expectedImageCount: albums.filter((item) => 'image' in item).length,
|
|
217
|
+
expectedVideoCount: albums.filter((item) => 'video' in item).length
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
{ userJid: options.userJid }
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
await options.suki.relayMessage(jid, albumMsg.message, { messageId: albumMsg.key.id });
|
|
224
|
+
|
|
225
|
+
for (const media of albums) {
|
|
226
|
+
let mediaMsg;
|
|
227
|
+
const uploadFn = async (encFilePath, opts) => {
|
|
228
|
+
const res = await options.suki.waUploadToServer(encFilePath, {
|
|
229
|
+
...opts,
|
|
230
|
+
newsletter: isJidNewsletter(jid)
|
|
231
|
+
});
|
|
232
|
+
return {
|
|
233
|
+
mediaUrl: res.url ?? '',
|
|
234
|
+
directPath: res.directPath ?? '',
|
|
235
|
+
handle: res.handle,
|
|
236
|
+
mediaKey: res.mediaKey,
|
|
237
|
+
fileEncSha256: res.fileEncSha256,
|
|
238
|
+
fileSha256: res.fileSha256,
|
|
239
|
+
fileLength: res.fileLength
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const sharedOpts = { userJid: options.userJid, upload: uploadFn };
|
|
244
|
+
|
|
245
|
+
if ('image' in media && media.image) mediaMsg = await generateWAMessage(jid, media, sharedOpts);
|
|
246
|
+
else if ('video' in media && media.video) mediaMsg = await generateWAMessage(jid, media, sharedOpts);
|
|
247
|
+
|
|
248
|
+
if (mediaMsg) {
|
|
249
|
+
mediaMsg.message.messageContextInfo = {
|
|
250
|
+
messageSecret: randomBytes(32),
|
|
251
|
+
messageAssociation: { associationType: 1, parentMessageKey: albumMsg.key }
|
|
252
|
+
};
|
|
253
|
+
messages.push(mediaMsg);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return messages;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Addon factory for socket-level message extras (profilePictureUrl, getEphemeralGroup).
|
|
262
|
+
* @param {{ query: Function, newsletterWMexQuery?: Function }} ctx
|
|
263
|
+
*/
|
|
264
|
+
export const makeMessageExtrasAddon = (ctx) => {
|
|
265
|
+
const { query, newsletterWMexQuery } = ctx;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Fetch profile picture URL for any JID, including newsletters.
|
|
269
|
+
* @example
|
|
270
|
+
* const url = await sock.profilePictureUrl('1234567890@s.whatsapp.net')
|
|
271
|
+
*/
|
|
272
|
+
const profilePictureUrl = async (jid) => {
|
|
273
|
+
if (isJidNewsletter(jid) && newsletterWMexQuery) {
|
|
274
|
+
const node = await newsletterWMexQuery(undefined, QueryIds.METADATA, {
|
|
275
|
+
input: { key: jid, type: 'JID', view_role: 'GUEST' },
|
|
276
|
+
fetch_viewer_metadata: true,
|
|
277
|
+
fetch_full_image: true,
|
|
278
|
+
fetch_creation_time: true
|
|
279
|
+
});
|
|
280
|
+
const resultStr = getBinaryNodeChild(node, 'result')?.content?.toString();
|
|
281
|
+
if (!resultStr) return null;
|
|
282
|
+
|
|
283
|
+
const metadata = JSON.parse(resultStr).data[XWAPaths.xwa2_newsletter_metadata];
|
|
284
|
+
return getUrlFromDirectPath(metadata?.thread_metadata?.picture?.direct_path || '');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const result = await query({
|
|
288
|
+
tag: 'iq',
|
|
289
|
+
attrs: { target: jidNormalizedUser(jid), to: S_WHATSAPP_NET, type: 'get', xmlns: 'w:profile:picture' },
|
|
290
|
+
content: [{ tag: 'picture', attrs: { type: 'image', query: 'url' }, content: undefined }]
|
|
291
|
+
});
|
|
292
|
+
return getBinaryNodeChild(result, 'picture')?.attrs?.url || null;
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Query the ephemeral (disappearing messages) timer for a group.
|
|
297
|
+
* @returns {Promise<number|string>} timer in seconds, or 0 if not set
|
|
298
|
+
* @example
|
|
299
|
+
* const timer = await sock.getEphemeralGroup('120363xxx@g.us')
|
|
300
|
+
*/
|
|
301
|
+
const getEphemeralGroup = async (jid) => {
|
|
302
|
+
if (!isJidGroup(jid)) throw new TypeError('Jid should originate from a group!');
|
|
303
|
+
const result = await query({
|
|
304
|
+
tag: 'iq',
|
|
305
|
+
attrs: { id: `ephemeral-${Date.now()}`, to: jid, type: 'get', xmlns: 'w:g2' },
|
|
306
|
+
content: [{ tag: 'query', attrs: { request: 'interactive' }, content: undefined }]
|
|
307
|
+
});
|
|
308
|
+
return getBinaryNodeChild(getBinaryNodeChild(result, 'group'), 'ephemeral')?.attrs?.expiration || 0;
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
return { profilePictureUrl, getEphemeralGroup };
|
|
312
|
+
};
|