aunubaileys 1.0.39 → 1.0.41
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/README.md +8 -0
- package/lib/Socket/messages-send.js +13 -4
- package/lib/Types/Message.d.ts +12 -0
- package/lib/Utils/messages.d.ts +1 -0
- package/lib/Utils/messages.js +31 -0
- package/lib/WABinary/generic-utils.d.ts +1 -0
- package/lib/WABinary/generic-utils.js +106 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,14 @@ Everything else is pure upstream. When upstream moves, we rebase the patch layer
|
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
|
|
67
|
+
### 🆕 What's new in 1.0.41 / Baru di 1.0.41
|
|
68
|
+
|
|
69
|
+
- 🏷️ **The biz binary node machinery, plus the `secureMetaServiceLabel` option** — the 6.7.24 base never had the `biz` companion node that official clients attach to business/interactive message stanzas. This release ports it in full from @itsliaaa/baileys: `getBizBinaryNode()` (`actual_actors`/`host_storage`/`privacy_mode_ts` attributes + a `quality_control` child, with `native_flow` variants for known flow buttons and a `list` variant for list messages) and the `shouldIncludeBizBinaryNode()` decider. `relayMessage` now attaches the node **automatically** for buttons/list/template/native-flow messages, and the content option `secureMetaServiceLabel: true` forces it onto any message (the secure Meta service label). Both functions are exported for consumers who need to inspect or build the node themselves.
|
|
70
|
+
|
|
71
|
+
### 🆕 What's new in 1.0.40 / Baru di 1.0.40
|
|
72
|
+
|
|
73
|
+
- 🎁 **Four future-proof message wrapper options** — **`viewOnceV2: true`** wraps content into `viewOnceMessageV2`, **`viewOnceV2Extension: true`** into `viewOnceMessageV2Extension`, **`ephemeral: true`** into `ephemeralMessage`, and **`interactiveAsTemplate: true`** wraps an interactive message into a `templateMessage` (optional `templateId`; the `messageContextInfo` device-list metadata is preserved alongside, and using it on a non-interactive message throws a clear 400). The 6.7.24 proto already carries all four wrapper types — only the boolean options were missing. Adapted from @itsliaaa/baileys; classic `viewOnce` behaviour is unchanged.
|
|
74
|
+
|
|
67
75
|
### 🆕 What's new in 1.0.39 / Baru di 1.0.39
|
|
68
76
|
|
|
69
77
|
- 📰 **New `sock.newsletterSubscribed()`** — fetch **every newsletter this account follows** in one call, the newsletter analogue of `groupFetchAllParticipating()` that was missing until now (only `newsletterSubscribers(jid)`, the follower count of one newsletter, existed). Implemented over the same MEX path as the other newsletter methods: query id `6388546374527196`, path `xwa2_newsletter_subscribed` (WhatsApp's own MEX schema constants), added to the `QueryIds`/`XWAPaths` enums. Adapted from @itsliaaa/baileys.
|
|
@@ -2,10 +2,10 @@ import NodeCache from '@cacheable/node-cache';
|
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import { proto } from '../../WAProto/index.js';
|
|
4
4
|
import { BIZ_BOT_SUPPORT_PAYLOAD, DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
5
|
-
import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, delay, extractDeviceJids, generateMessageIDV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
|
|
5
|
+
import { aggregateMessageKeysNotFromMe, assertMediaContent, bindWaitForEvent, decryptMediaRetryData, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, delay, extractDeviceJids, generateMessageIDV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds, shouldIncludeBizBinaryNode } from '../Utils/index.js';
|
|
6
6
|
import { sentMessageCacheFor } from '../Utils/sent-message-cache.js';
|
|
7
7
|
import { getUrlInfo } from '../Utils/link-preview.js';
|
|
8
|
-
import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, isJidNewsletter, isJidUser, isLidUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
8
|
+
import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, getBizBinaryNode, isJidGroup, isJidNewsletter, isJidUser, isLidUser, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
9
9
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
10
10
|
import { makeGroupsSocket } from './groups.js';
|
|
11
11
|
import { makeNewsletterSocket } from './newsletter.js';
|
|
@@ -268,7 +268,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
268
268
|
}));
|
|
269
269
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
270
270
|
};
|
|
271
|
-
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
|
|
271
|
+
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, addBizAttributes, statusJidList }) => {
|
|
272
272
|
if (!ws.isOpen) {
|
|
273
273
|
// AunuBaileys: a send attempted during a reconnect window used to die
|
|
274
274
|
// instantly with Boom 428 from the first internal query — the message
|
|
@@ -515,6 +515,13 @@ export const makeMessagesSocket = (config) => {
|
|
|
515
515
|
;
|
|
516
516
|
stanza.content.push(...additionalNodes);
|
|
517
517
|
}
|
|
518
|
+
// AunuBaileys: biz binary node (dari @itsliaaa/baileys) — otomatis untuk pesan
|
|
519
|
+
// buttons/list/template/native-flow, atau dipaksa opsi secureMetaServiceLabel
|
|
520
|
+
const alreadyHasBizNode = !addBizAttributes &&
|
|
521
|
+
!!additionalNodes?.some(node => node.tag === 'biz');
|
|
522
|
+
if ((!alreadyHasBizNode && shouldIncludeBizBinaryNode(message)) || addBizAttributes) {
|
|
523
|
+
stanza.content.push(getBizBinaryNode(message));
|
|
524
|
+
}
|
|
518
525
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
519
526
|
await sendNode(stanza);
|
|
520
527
|
});
|
|
@@ -703,6 +710,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
703
710
|
const isPinMsg = 'pin' in content && !!content.pin;
|
|
704
711
|
const isPollMessage = 'poll' in content && !!content.poll;
|
|
705
712
|
const isAiMsg = 'ai' in content && !!content.ai;
|
|
713
|
+
const isNeedBizAttrs = 'secureMetaServiceLabel' in content && !!content.secureMetaServiceLabel;
|
|
706
714
|
const additionalAttributes = {};
|
|
707
715
|
const additionalNodes = [];
|
|
708
716
|
// required for delete
|
|
@@ -752,7 +760,8 @@ export const makeMessagesSocket = (config) => {
|
|
|
752
760
|
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
753
761
|
additionalAttributes,
|
|
754
762
|
statusJidList: options.statusJidList,
|
|
755
|
-
additionalNodes
|
|
763
|
+
additionalNodes,
|
|
764
|
+
addBizAttributes: isNeedBizAttrs
|
|
756
765
|
});
|
|
757
766
|
// AunuBaileys: kirim isi album sebagai pesan terasosiasi (dari @itsliaaa/baileys)
|
|
758
767
|
if ('album' in content) {
|
package/lib/Types/Message.d.ts
CHANGED
|
@@ -91,6 +91,16 @@ type Contextable = {
|
|
|
91
91
|
};
|
|
92
92
|
type ViewOnce = {
|
|
93
93
|
viewOnce?: boolean;
|
|
94
|
+
/** wrap the message into viewOnceMessageV2 */
|
|
95
|
+
viewOnceV2?: boolean;
|
|
96
|
+
/** wrap the message into viewOnceMessageV2Extension */
|
|
97
|
+
viewOnceV2Extension?: boolean;
|
|
98
|
+
/** wrap the message into ephemeralMessage */
|
|
99
|
+
ephemeral?: boolean;
|
|
100
|
+
/** wrap an interactive message into a templateMessage (requires `interactive` content) */
|
|
101
|
+
interactiveAsTemplate?: boolean;
|
|
102
|
+
/** optional template id used when interactiveAsTemplate is set */
|
|
103
|
+
templateId?: string;
|
|
94
104
|
};
|
|
95
105
|
type Editable = {
|
|
96
106
|
edit?: WAMessageKey;
|
|
@@ -230,6 +240,8 @@ export type AnyMessageContent = (AnyRegularMessageContent | {
|
|
|
230
240
|
}) & {
|
|
231
241
|
/** AunuBaileys: mark the message with the AI label (private chats only) */
|
|
232
242
|
ai?: boolean;
|
|
243
|
+
/** AunuBaileys: force the biz binary node (secure Meta service label) onto this message's stanza */
|
|
244
|
+
secureMetaServiceLabel?: boolean;
|
|
233
245
|
};
|
|
234
246
|
export type GroupMetadataParticipants = Pick<GroupMetadata, 'participants'>;
|
|
235
247
|
type MinimalRelayOptions = {
|
package/lib/Utils/messages.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare const prepareDisappearingMessageSettingContent: (ephemeralExpirat
|
|
|
18
18
|
* @param options.forceForward will show the message as forwarded even if it is from you
|
|
19
19
|
*/
|
|
20
20
|
export declare const generateForwardMessageContent: (message: WAMessage, forceForward?: boolean) => proto.IMessage;
|
|
21
|
+
export declare const shouldIncludeBizBinaryNode: (message: any) => boolean;
|
|
21
22
|
export declare const generateWAMessageContent: (message: AnyMessageContent, options: MessageContentGenerationOptions) => Promise<proto.Message>;
|
|
22
23
|
export declare const generateWAMessageFromContent: (jid: string, message: WAMessageContent, options: MessageGenerationOptionsFromContent) => proto.WebMessageInfo;
|
|
23
24
|
export declare const generateWAMessage: (jid: string, content: AnyMessageContent, options: MessageGenerationOptions) => Promise<proto.WebMessageInfo>;
|
package/lib/Utils/messages.js
CHANGED
|
@@ -821,6 +821,13 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
821
821
|
if ('viewOnce' in message && !!message.viewOnce) {
|
|
822
822
|
m = { viewOnceMessage: { message: m } };
|
|
823
823
|
}
|
|
824
|
+
// AunuBaileys: viewOnceV2 / viewOnceV2Extension (dari @itsliaaa/baileys)
|
|
825
|
+
else if ('viewOnceV2' in message && !!message.viewOnceV2) {
|
|
826
|
+
m = { viewOnceMessageV2: { message: m } };
|
|
827
|
+
}
|
|
828
|
+
else if ('viewOnceV2Extension' in message && !!message.viewOnceV2Extension) {
|
|
829
|
+
m = { viewOnceMessageV2Extension: { message: m } };
|
|
830
|
+
}
|
|
824
831
|
if (('mentions' in message && message.mentions?.length) ||
|
|
825
832
|
('mentionAll' in message && !!message.mentionAll)) {
|
|
826
833
|
const messageType = Object.keys(m)[0];
|
|
@@ -840,6 +847,24 @@ export const generateWAMessageContent = async (message, options) => {
|
|
|
840
847
|
};
|
|
841
848
|
}
|
|
842
849
|
}
|
|
850
|
+
// AunuBaileys: ephemeral (dari @itsliaaa/baileys)
|
|
851
|
+
if ('ephemeral' in message && !!message.ephemeral) {
|
|
852
|
+
m = { ephemeralMessage: { message: m } };
|
|
853
|
+
}
|
|
854
|
+
// AunuBaileys: interactiveAsTemplate (dari @itsliaaa/baileys) — bungkus interactiveMessage
|
|
855
|
+
// ke templateMessage; messageContextInfo (deviceListMetadata) dipertahankan di sisinya
|
|
856
|
+
if ('interactiveAsTemplate' in message && !!message.interactiveAsTemplate) {
|
|
857
|
+
if (!m.interactiveMessage) {
|
|
858
|
+
throw new Boom('interactiveAsTemplate requires an interactive message', { statusCode: 400 });
|
|
859
|
+
}
|
|
860
|
+
m = {
|
|
861
|
+
templateMessage: {
|
|
862
|
+
interactiveMessageTemplate: m.interactiveMessage,
|
|
863
|
+
templateId: message.templateId || 'template-' + Date.now()
|
|
864
|
+
},
|
|
865
|
+
...(m.messageContextInfo ? { messageContextInfo: m.messageContextInfo } : {})
|
|
866
|
+
};
|
|
867
|
+
}
|
|
843
868
|
if ('edit' in message) {
|
|
844
869
|
m = {
|
|
845
870
|
protocolMessage: {
|
|
@@ -1191,4 +1216,10 @@ export const assertMediaContent = (content) => {
|
|
|
1191
1216
|
}
|
|
1192
1217
|
return mediaContent;
|
|
1193
1218
|
};
|
|
1219
|
+
// AunuBaileys: penentu biz binary node (dari @itsliaaa/baileys)
|
|
1220
|
+
export const shouldIncludeBizBinaryNode = (message) => !!(message.buttonsMessage ||
|
|
1221
|
+
message.listMessage ||
|
|
1222
|
+
message.templateMessage ||
|
|
1223
|
+
(message.interactiveMessage &&
|
|
1224
|
+
message.interactiveMessage.nativeFlowMessage));
|
|
1194
1225
|
//# sourceMappingURL=messages.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { proto } from '../../WAProto/index.js';
|
|
2
2
|
import { type BinaryNode } from './types.js';
|
|
3
3
|
export declare const getBinaryNodeChildren: (node: BinaryNode | undefined, childTag: string) => BinaryNode[];
|
|
4
|
+
export declare const getBizBinaryNode: (message: any) => BinaryNode;
|
|
4
5
|
export declare const getAllBinaryNodeChildren: ({ content }: BinaryNode) => BinaryNode[];
|
|
5
6
|
export declare const getBinaryNodeChild: (node: BinaryNode | undefined, childTag: string) => BinaryNode | undefined;
|
|
6
7
|
export declare const getBinaryNodeChildBuffer: (node: BinaryNode | undefined, childTag: string) => Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike> | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { randomBytes } from 'crypto';
|
|
2
3
|
import { proto } from '../../WAProto/index.js';
|
|
3
4
|
import {} from './types.js';
|
|
4
5
|
// some extra useful utilities
|
|
@@ -99,4 +100,109 @@ export function binaryNodeToString(node, i = 0) {
|
|
|
99
100
|
const content = children ? `>\n${children}\n${tabs(i)}</${node.tag}>` : '/>';
|
|
100
101
|
return tag + content;
|
|
101
102
|
}
|
|
103
|
+
// AunuBaileys: biz binary node (dari @itsliaaa/baileys) — node pendamping stanza
|
|
104
|
+
// untuk pesan bisnis/interaktif; juga dipakai opsi secureMetaServiceLabel
|
|
105
|
+
const FLOWS_MAP = {
|
|
106
|
+
mpm: true,
|
|
107
|
+
cta_catalog: true,
|
|
108
|
+
send_location: true,
|
|
109
|
+
call_permission_request: true,
|
|
110
|
+
wa_payment_transaction_details: true,
|
|
111
|
+
automated_greeting_message_view_catalog: true,
|
|
112
|
+
form_message: true,
|
|
113
|
+
payment_key_info: true
|
|
114
|
+
};
|
|
115
|
+
const DECISION_SOURCE_CONTENT = [
|
|
116
|
+
{
|
|
117
|
+
tag: 'decision_source',
|
|
118
|
+
attrs: { value: 'df' }
|
|
119
|
+
}
|
|
120
|
+
];
|
|
121
|
+
const LIST_TYPE_CONTENT = {
|
|
122
|
+
tag: 'list',
|
|
123
|
+
attrs: { v: '2', type: 'product_list' }
|
|
124
|
+
};
|
|
125
|
+
const NATIVE_FLOW_ATTRIBUTE = { type: 'native_flow', v: '1' };
|
|
126
|
+
const MIXED_NATIVE_FLOW = {
|
|
127
|
+
tag: 'interactive',
|
|
128
|
+
attrs: NATIVE_FLOW_ATTRIBUTE,
|
|
129
|
+
content: [
|
|
130
|
+
{
|
|
131
|
+
tag: 'native_flow',
|
|
132
|
+
attrs: { v: '9', name: 'mixed' }
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
};
|
|
136
|
+
export const getBizBinaryNode = (message) => {
|
|
137
|
+
const flowMsg = message.interactiveMessage?.nativeFlowMessage;
|
|
138
|
+
const firstButtonName = flowMsg?.buttons?.[0]?.name;
|
|
139
|
+
const qualityContent = {
|
|
140
|
+
tag: 'quality_control',
|
|
141
|
+
attrs: {
|
|
142
|
+
decision_id: randomBytes(20).toString('hex'),
|
|
143
|
+
source_type: 'third_party'
|
|
144
|
+
},
|
|
145
|
+
content: DECISION_SOURCE_CONTENT
|
|
146
|
+
};
|
|
147
|
+
const bizAttributes = {
|
|
148
|
+
actual_actors: '2',
|
|
149
|
+
host_storage: '2',
|
|
150
|
+
privacy_mode_ts: `${Date.now() / 1000 | 0}`
|
|
151
|
+
};
|
|
152
|
+
if (firstButtonName === 'review_and_pay' ||
|
|
153
|
+
firstButtonName === 'payment_info') {
|
|
154
|
+
bizAttributes.native_flow_name = firstButtonName === 'review_and_pay'
|
|
155
|
+
? 'order_details'
|
|
156
|
+
: firstButtonName;
|
|
157
|
+
return {
|
|
158
|
+
tag: 'biz',
|
|
159
|
+
attrs: bizAttributes,
|
|
160
|
+
content: [qualityContent]
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (firstButtonName && FLOWS_MAP[firstButtonName]) {
|
|
164
|
+
return {
|
|
165
|
+
tag: 'biz',
|
|
166
|
+
attrs: bizAttributes,
|
|
167
|
+
content: [
|
|
168
|
+
{
|
|
169
|
+
tag: 'interactive',
|
|
170
|
+
attrs: NATIVE_FLOW_ATTRIBUTE,
|
|
171
|
+
content: [
|
|
172
|
+
{
|
|
173
|
+
tag: 'native_flow',
|
|
174
|
+
attrs: firstButtonName === 'form_message' || firstButtonName === 'payment_key_info' ? { name: firstButtonName } : { v: '2', name: firstButtonName }
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
qualityContent
|
|
179
|
+
]
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (flowMsg || message.buttonsMessage || message.templateMessage) {
|
|
183
|
+
return {
|
|
184
|
+
tag: 'biz',
|
|
185
|
+
attrs: bizAttributes,
|
|
186
|
+
content: [
|
|
187
|
+
MIXED_NATIVE_FLOW,
|
|
188
|
+
qualityContent
|
|
189
|
+
]
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (message.listMessage) {
|
|
193
|
+
return {
|
|
194
|
+
tag: 'biz',
|
|
195
|
+
attrs: bizAttributes,
|
|
196
|
+
content: [
|
|
197
|
+
LIST_TYPE_CONTENT,
|
|
198
|
+
qualityContent
|
|
199
|
+
]
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
tag: 'biz',
|
|
204
|
+
attrs: bizAttributes,
|
|
205
|
+
content: [qualityContent]
|
|
206
|
+
};
|
|
207
|
+
};
|
|
102
208
|
//# sourceMappingURL=generic-utils.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aunubaileys",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.41",
|
|
5
5
|
"description": "AunuBaileys \u2014 a WhatsApp Web API for bots that never sleep. Full upstream power with the beloved in-memory store restored and pairing that just works. Forged by AunuCore.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"whatsapp",
|