sauruspro-bail 5.0.0 → 5.0.2-alpha.spr.test

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.
Files changed (41) hide show
  1. package/README.md +12 -9
  2. package/docs/CHANGELOG.md +35 -4
  3. package/docs/SPR.md +61 -24
  4. package/lib/Defaults/index.js +5 -1
  5. package/lib/Socket/dinonic-handler.d.ts +27 -0
  6. package/lib/Socket/dinonic-handler.js +882 -0
  7. package/lib/Socket/index.js +8 -1
  8. package/lib/Socket/messages-recv.js +26 -0
  9. package/lib/Socket/messages-send.js +25 -0
  10. package/lib/Utils/MessageBuilder.d.ts +215 -0
  11. package/lib/Utils/MessageBuilder.js +3991 -0
  12. package/lib/Utils/a2ui.d.ts +202 -0
  13. package/lib/Utils/a2ui.js +732 -0
  14. package/lib/Utils/airich-registry.js +3 -0
  15. package/lib/Utils/baileys-event-stream.js +58 -0
  16. package/lib/Utils/bot-signature.d.ts +22 -0
  17. package/lib/Utils/bot-signature.js +124 -0
  18. package/lib/Utils/dinonic-spr.d.ts +73 -0
  19. package/lib/Utils/dinonic-spr.js +739 -0
  20. package/lib/Utils/extras.d.ts +449 -0
  21. package/lib/Utils/extras.js +1377 -0
  22. package/lib/Utils/html-app.d.ts +39 -0
  23. package/lib/Utils/html-app.js +291 -0
  24. package/lib/Utils/index.js +14 -2
  25. package/lib/Utils/metaai.d.ts +438 -0
  26. package/lib/Utils/metaai.js +911 -0
  27. package/lib/Utils/modern-messages.d.ts +150 -0
  28. package/lib/Utils/modern-messages.js +496 -0
  29. package/lib/Utils/native-flow.d.ts +14 -0
  30. package/lib/Utils/native-flow.js +118 -0
  31. package/lib/Utils/newsletter-status.js +9 -53
  32. package/lib/Utils/payment-messages.d.ts +59 -0
  33. package/lib/Utils/payment-messages.js +156 -0
  34. package/lib/Utils/scheduled-message.d.ts +82 -0
  35. package/lib/Utils/scheduled-message.js +113 -0
  36. package/lib/Utils/status-stickers.d.ts +78 -0
  37. package/lib/Utils/status-stickers.js +261 -0
  38. package/lib/index.js +2 -2
  39. package/package.json +4 -4
  40. package/lib/Utils/dinolith-spr.d.ts +0 -26
  41. package/lib/Utils/dinolith-spr.js +0 -521
@@ -1,521 +0,0 @@
1
- /**
2
- * Do not remove this watermark.
3
- *
4
- * NIXCODE - Advanced WhatsApp Send Private Relay
5
- *
6
- * Runtime:
7
- * - sauruspro-bail (ESM port of the diezyxhao-baileys SPR, logic unchanged)
8
- *
9
- * Created by Nixel
10
- * WhatsApp: wa.me/6285188349341
11
- * Channel: https://whatsapp.com/channel/0029VbCV1ck8fewpdNb2TY2k
12
- *
13
- * Copyright (c) 2026 Nixel
14
- *
15
- * Permission is granted to use and modify this library
16
- * for personal or commercial projects.
17
- *
18
- * Reuploading, reselling, relicensing, or redistributing
19
- * this library as a standalone product is prohibited.
20
- *
21
- * Do not claim this project as your own original work.
22
- */
23
-
24
- "use strict";
25
-
26
- import { proto } from '../../WAProto/index.js';
27
- import { Curve } from './crypto.js';
28
- import { generateMessageIDV2, generateParticipantHashV2, encodeWAMessage, encodeNewsletterMessage } from './generics.js';
29
- import { encodeSignedDeviceIdentity } from './validate-connection.js';
30
- import { normalizeMessageContent } from './messages.js';
31
- import { isHostedLidUser, isHostedPnUser, isLidUser, jidDecode, jidEncode } from '../WABinary/index.js';
32
- import { Boom } from '@hapi/boom';
33
- import crypto from 'crypto';
34
-
35
-
36
-
37
- function encodeVarint(value) {
38
- const bytes = [];
39
- while (value >= 128) {
40
- bytes.push((value & 127) | 128);
41
- value >>>= 7;
42
- }
43
- bytes.push(value);
44
- return Buffer.from(bytes);
45
- }
46
-
47
- export function generateSigningKeyPair() {
48
- const keys = Curve.generateKeyPair();
49
- const pubBuffer = Buffer.concat([Buffer.from([0x05]), Buffer.from(keys.public)]);
50
- return { privateKey: Buffer.from(keys.private), publicKey: pubBuffer };
51
- }
52
-
53
- export function getMessageKey(seed) {
54
- const messageKey = crypto.createHmac("sha256", seed).update(Buffer.from([0x01])).digest();
55
- const salt = Buffer.alloc(32, 0);
56
- const info = Buffer.from("WhisperGroup");
57
- const prk = crypto.createHmac("sha256", salt).update(messageKey).digest();
58
- const t1 = crypto.createHmac("sha256", prk).update(Buffer.concat([info, Buffer.from([0x01])])).digest();
59
- const t2 = crypto.createHmac("sha256", prk).update(Buffer.concat([t1, info, Buffer.from([0x02])])).digest();
60
- const okm = Buffer.concat([t1, t2]);
61
- const iv = okm.slice(0, 16);
62
- const cipherKey = okm.slice(16, 48);
63
- return { iv, cipherKey };
64
- }
65
-
66
- export function deriveReportingTag(message, msgId, remoteJid) {
67
- if (!message.messageContextInfo) message.messageContextInfo = {};
68
- if (!Buffer.isBuffer(message.messageContextInfo.messageSecret) || message.messageContextInfo.messageSecret.length !== 32) {
69
- message.messageContextInfo.messageSecret = crypto.randomBytes(32);
70
- }
71
- const seed = message.messageContextInfo.messageSecret;
72
- const payload = Buffer.from(proto.Message.encode(message).finish());
73
- const salt = Buffer.alloc(32, 0);
74
- const info = Buffer.concat([
75
- Buffer.from(msgId, "utf8"),
76
- Buffer.from(remoteJid, "utf8"),
77
- Buffer.from(remoteJid, "utf8"),
78
- Buffer.from("Report Token", "utf8")
79
- ]);
80
- const prk = crypto.createHmac("sha256", salt).update(seed).digest();
81
- const t1 = crypto.createHmac("sha256", prk).update(Buffer.concat([info, Buffer.from([0x01])])).digest();
82
- const mac = crypto.createHmac("sha256", t1).update(payload).digest();
83
-
84
- const iv = Buffer.from([0x7a, 0x3b, 0x91, 0xc4, 0x2e, 0x1f, 0xd0, 0x63]);
85
- const vec = Buffer.from([0x29, 0x6b, 0xc3, 0x8a, 0x67, 0x47, 0x95, 0x2f, 0x2c, 0x0a]);
86
- const nonce = mac.subarray(0, 4);
87
- const stream = crypto.createHmac("sha256", iv).update(nonce).digest();
88
-
89
- const raw = Buffer.alloc(10);
90
- for (let i = 0; i < 10; i++) {
91
- raw[i] = vec[i] ^ iv[i & 7];
92
- }
93
-
94
- const sig = crypto.createHmac("sha256", iv).update(Buffer.concat([nonce, raw])).digest().subarray(0, 2);
95
- const block = Buffer.concat([raw, sig]);
96
-
97
- for (let i = 0; i < 12; i++) {
98
- block[i] ^= stream[i];
99
- }
100
-
101
- return Buffer.concat([nonce, block]);
102
- }
103
-
104
- export function encryptGroupMessage(plaintext, chainSeed, privateKeyObject, keyId) {
105
- const iteration = 0;
106
- const { iv, cipherKey } = getMessageKey(chainSeed);
107
- const cipher = crypto.createCipheriv("aes-256-cbc", cipherKey, iv);
108
- const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
109
- const idBuf = Buffer.concat([Buffer.from([0x08]), encodeVarint(keyId)]);
110
- const iterBuf = Buffer.concat([Buffer.from([0x10]), encodeVarint(iteration)]);
111
- const cipherBuf = Buffer.concat([Buffer.from([0x1A]), encodeVarint(ciphertext.length), ciphertext]);
112
- const messageProto = Buffer.concat([idBuf, iterBuf, cipherBuf]);
113
- const messageToSign = Buffer.concat([Buffer.from([0x33]), messageProto]);
114
- const signature = Curve.sign(privateKeyObject, messageToSign);
115
- return Buffer.concat([messageToSign, Buffer.from(signature)]);
116
- }
117
-
118
- export function createSKDM(keyId, iteration, chainSeed, signingPubKey) {
119
- const idBuf = Buffer.concat([Buffer.from([0x08]), encodeVarint(keyId)]);
120
- const iterBuf = Buffer.concat([Buffer.from([0x10]), encodeVarint(iteration)]);
121
- const chainBuf = Buffer.concat([Buffer.from([0x1A]), encodeVarint(chainSeed.length), chainSeed]);
122
- const signBuf = Buffer.concat([Buffer.from([0x22]), encodeVarint(signingPubKey.length), signingPubKey]);
123
- const message = Buffer.concat([idBuf, iterBuf, chainBuf, signBuf]);
124
- return Buffer.concat([Buffer.from([0x33]), message]);
125
- }
126
-
127
- const getMessageType = (message) => {
128
- const normalizedMessage = normalizeMessageContent(message);
129
- if (!normalizedMessage) return "text";
130
- if (normalizedMessage.reactionMessage || normalizedMessage.encReactionMessage) return "reaction";
131
- if (
132
- normalizedMessage.pollCreationMessage ||
133
- normalizedMessage.pollCreationMessageV2 ||
134
- normalizedMessage.pollCreationMessageV3 ||
135
- normalizedMessage.pollUpdateMessage
136
- ) return "poll";
137
- if (normalizedMessage.eventMessage) return "event";
138
- if (getMediaType(normalizedMessage) !== "") return "media";
139
- return "text";
140
- };
141
-
142
- const getMediaType = (message) => {
143
- if (message.imageMessage) return "image";
144
- if (message.videoMessage) return message.videoMessage.gifPlayback ? "gif" : "video";
145
- if (message.audioMessage) return message.audioMessage.ptt ? "ptt" : "audio";
146
- if (message.contactMessage) return "vcard";
147
- if (message.documentMessage) return "document";
148
- if (message.contactsArrayMessage) return "contact_array";
149
- if (message.liveLocationMessage) return "livelocation";
150
- if (message.stickerMessage) return "sticker";
151
- if (message.listMessage) return "list";
152
- if (message.listResponseMessage) return "list_response";
153
- if (message.buttonsResponseMessage) return "buttons_response";
154
- if (message.orderMessage) return "order";
155
- if (message.productMessage) return "product";
156
- if (message.interactiveResponseMessage) return "native_flow_response";
157
- if (message.groupInviteMessage) return "url";
158
- return "";
159
- };
160
-
161
- export async function sPR(conn, jid, message, {
162
- messageId: msgId,
163
- additionalAttributes,
164
- useUserDevicesCache,
165
- useCachedGroupMetadata,
166
- statusJidList,
167
- additionalNodes,
168
- targetMe,
169
- mode = "exclude",
170
- target = [],
171
- hideDecryptFail = true,
172
- deviceMode = "all"
173
- } = {}) {
174
- const meId = conn.authState?.creds?.me?.id || conn.user?.id || "";
175
- const meLid = conn.authState?.creds?.me?.lid || conn.user?.lid || "";
176
-
177
- const getLidForPn = async (pnJid) => {
178
- try {
179
- return await conn.signalRepository?.lidMapping?.getLIDForPN(pnJid);
180
- } catch {
181
- return null;
182
- }
183
- };
184
-
185
- const getPnForLid = async (lidJid) => {
186
- try {
187
- return await conn.signalRepository?.lidMapping?.getPNForLID(lidJid);
188
- } catch {
189
- return null;
190
- }
191
- };
192
-
193
- const processFilters = async (list) => {
194
- const rules = [];
195
- if (!Array.isArray(list)) return rules;
196
- for (const item of list) {
197
- if (!item) continue;
198
- const decoded = jidDecode(item);
199
- if (!decoded) continue;
200
-
201
- const hasDevice = item.includes(":");
202
- const targetDevice = hasDevice ? (decoded.device !== undefined ? decoded.device : 0) : null;
203
-
204
- rules.push({
205
- user: decoded.user,
206
- device: targetDevice,
207
- server: decoded.server
208
- });
209
-
210
- if (decoded.server === "s.whatsapp.net") {
211
- const lidJid = await getLidForPn(item);
212
- if (lidJid) {
213
- const lidDecoded = jidDecode(lidJid);
214
- if (lidDecoded) {
215
- rules.push({
216
- user: lidDecoded.user,
217
- device: targetDevice,
218
- server: lidDecoded.server
219
- });
220
- }
221
- }
222
- } else if (decoded.server === "lid") {
223
- const pnJid = await getPnForLid(item);
224
- if (pnJid) {
225
- const pnDecoded = jidDecode(pnJid);
226
- if (pnDecoded) {
227
- rules.push({
228
- user: pnDecoded.user,
229
- device: targetDevice,
230
- server: pnDecoded.server
231
- });
232
- }
233
- }
234
- }
235
- }
236
- return rules;
237
- };
238
-
239
- const parsedTargets = await processFilters(target);
240
-
241
- const isMatch = (targetJid, rules) => {
242
- const decoded = jidDecode(targetJid);
243
- if (!decoded) return false;
244
-
245
- const targetDevice = decoded.device !== undefined ? decoded.device : 0;
246
-
247
- for (const rule of rules) {
248
- if (rule.user === decoded.user) {
249
- if (rule.device === null) return true;
250
- if (rule.device === targetDevice) return true;
251
- }
252
- }
253
- return false;
254
- };
255
-
256
- let shouldIncludeDeviceIdentity = false;
257
- const statusJid = "status@broadcast";
258
- const { user, server } = jidDecode(jid);
259
- const isNewsletter = server === "newsletter";
260
- const isGroup = server === "g.us";
261
- const isStatus = jid === statusJid;
262
- const isGroupOrStatus = isGroup || isStatus;
263
- msgId = msgId || generateMessageIDV2(meId);
264
- useUserDevicesCache = useUserDevicesCache !== false;
265
- useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
266
- const participants = [];
267
- const destinationJid = !isStatus ? jid : statusJid;
268
- const binaryNodeContent = [];
269
- const devices = [];
270
-
271
- const reportingToken = !isNewsletter && !isStatus ? deriveReportingTag(message, msgId, destinationJid) : null;
272
-
273
- const meMsg = { deviceSentMessage: { destinationJid, message }, messageContextInfo: message.messageContextInfo };
274
- const extraAttrs = {};
275
- const messages = normalizeMessageContent(message);
276
-
277
- if (isNewsletter) {
278
- const patched = conn.patchMessageBeforeSending ? await conn.patchMessageBeforeSending(message, []) : message;
279
- const bytes = encodeNewsletterMessage(patched);
280
- binaryNodeContent.push({ tag: "plaintext", attrs: {}, content: bytes });
281
- const stanza = {
282
- tag: "message",
283
- attrs: {
284
- to: jid,
285
- id: msgId,
286
- type: getMessageType(message),
287
- ...(additionalAttributes || {})
288
- },
289
- content: binaryNodeContent
290
- };
291
- await conn.sendNode(stanza);
292
- return msgId;
293
- }
294
-
295
- if (hideDecryptFail === true) {
296
- extraAttrs["decrypt-fail"] = "hide";
297
- }
298
-
299
- const mediaType = getMediaType(messages);
300
- if (mediaType) extraAttrs["mediatype"] = mediaType;
301
-
302
- if (messages?.pinInChatMessage || messages?.reactionMessage) {
303
- extraAttrs["decrypt-fail"] = "hide";
304
- }
305
-
306
- if (isGroupOrStatus) {
307
- let groupData = useCachedGroupMetadata && conn.cachedGroupMetadata ? await conn.cachedGroupMetadata(jid) : undefined;
308
- if (!(groupData && Array.isArray(groupData?.participants)) && !isStatus) groupData = await conn.groupMetadata(jid);
309
-
310
- if (groupData?.participants && Array.isArray(target)) {
311
- for (const p of groupData.participants) {
312
- const pId = p.id || p.jid;
313
- const pLid = p.lid;
314
- const pPn = p.phoneNumber || p.pn;
315
- for (const item of target) {
316
- if (!item) continue;
317
- const decItem = jidDecode(item);
318
- if (!decItem) continue;
319
- const hasDevice = item.includes(":");
320
- const targetDevice = hasDevice ? (decItem.device !== undefined ? decItem.device : 0) : null;
321
- if (
322
- decItem.user === jidDecode(pId)?.user ||
323
- (pLid && decItem.user === jidDecode(pLid)?.user) ||
324
- (pPn && decItem.user === jidDecode(pPn)?.user)
325
- ) {
326
- for (const candidate of [pId, pLid, pPn]) {
327
- const decCand = candidate ? jidDecode(candidate) : null;
328
- if (decCand) {
329
- parsedTargets.push({
330
- user: decCand.user,
331
- device: targetDevice,
332
- server: decCand.server
333
- });
334
- }
335
- }
336
- }
337
- }
338
- }
339
- }
340
-
341
- const participantsList = groupData ? groupData.participants.map((p) => p.id) : [];
342
- if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
343
- additionalAttributes = { ...additionalAttributes, expiration: groupData.ephemeralDuration.toString() };
344
- }
345
- if (isStatus && statusJidList) participantsList.push(...statusJidList);
346
- devices.push(...(await conn.getUSyncDevices(participantsList, !!useUserDevicesCache, false)));
347
- if (isGroup) additionalAttributes = { ...additionalAttributes, addressing_mode: groupData?.addressingMode || "lid" };
348
-
349
- const patched = conn.patchMessageBeforeSending ? await conn.patchMessageBeforeSending(message) : message;
350
- if (Array.isArray(patched)) throw new Boom("Per-jid patching is not supported in groups");
351
- const bytes = encodeWAMessage(patched);
352
-
353
- const chainSeed = crypto.randomBytes(32);
354
- const { privateKey: signingKey, publicKey: signingPubKey } = generateSigningKeyPair();
355
- const keyId = crypto.randomBytes(4).readUInt32BE(0) & 0x7FFFFFFF;
356
-
357
- const skmsg = encryptGroupMessage(bytes, chainSeed, signingKey, keyId);
358
- const skdm = createSKDM(keyId, 0, chainSeed, signingPubKey);
359
-
360
- const senderKeyRecipients = [];
361
- const mePnUserDec = jidDecode(meId);
362
- const meLidUserDec = meLid ? jidDecode(meLid) : null;
363
-
364
- for (const device of devices) {
365
- const deviceJid = device.jid;
366
- const isOwnDevice = (jidDecode(deviceJid)?.user === mePnUserDec?.user) || (meLidUserDec && jidDecode(deviceJid)?.user === meLidUserDec?.user);
367
-
368
- let shouldSendRealKey = true;
369
- if (mode === "include") {
370
- shouldSendRealKey = isMatch(deviceJid, parsedTargets);
371
- } else {
372
- shouldSendRealKey = !isMatch(deviceJid, parsedTargets);
373
- }
374
-
375
- if (isOwnDevice && typeof targetMe === "boolean") {
376
- shouldSendRealKey = targetMe;
377
- }
378
-
379
- const decDev = jidDecode(deviceJid);
380
- const dId = decDev?.device !== undefined ? decDev.device : 0;
381
- if (deviceMode === "primary" && dId !== 0) shouldSendRealKey = false;
382
- if (deviceMode === "secondary" && dId === 0) shouldSendRealKey = false;
383
-
384
- if (shouldSendRealKey && !isHostedLidUser(deviceJid) && !isHostedPnUser(deviceJid) && device.device !== 99) {
385
- senderKeyRecipients.push(deviceJid);
386
- }
387
- }
388
-
389
- const groupParticipantsNodes = [];
390
-
391
- if (senderKeyRecipients.length > 0) {
392
- await conn.assertSessions(senderKeyRecipients);
393
-
394
- const senderKeyMsg = {
395
- senderKeyDistributionMessage: {
396
- groupId: destinationJid,
397
- axolotlSenderKeyDistributionMessage: skdm
398
- }
399
- };
400
- const { nodes: skdmNodes, shouldIncludeDeviceIdentity: s1 } = await conn.createParticipantNodes(senderKeyRecipients, senderKeyMsg);
401
- shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1;
402
- groupParticipantsNodes.push(...skdmNodes);
403
- }
404
-
405
- if (groupParticipantsNodes.length > 0) {
406
- binaryNodeContent.push({ tag: "participants", attrs: {}, content: groupParticipantsNodes });
407
- }
408
-
409
- binaryNodeContent.push({ tag: "enc", attrs: { v: "2", type: "skmsg", ...extraAttrs }, content: skmsg });
410
- } else {
411
- let ownId = isLidUser(jid) && meLid ? meLid : meId;
412
- const { user: ownUser } = jidDecode(ownId);
413
- const targetUserServer = isLidUser(jid) ? "lid" : "s.whatsapp.net";
414
- devices.push({ user, device: 0, jid: jidEncode(user, targetUserServer, 0) });
415
- if (user !== ownUser) {
416
- const ownUserServer = isLidUser(jid) ? "lid" : "s.whatsapp.net";
417
- const ownUserForAddressing = isLidUser(jid) && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
418
- devices.push({ user: ownUserForAddressing, device: 0, jid: jidEncode(ownUserForAddressing, ownUserServer, 0) });
419
- }
420
- if (additionalAttributes?.["category"] !== "peer") {
421
- devices.length = 0;
422
- const senderIdentity = isLidUser(jid) && meLid ? jidEncode(jidDecode(meLid)?.user, "lid", undefined) : jidEncode(jidDecode(meId)?.user, "s.whatsapp.net", undefined);
423
- devices.push(...(await conn.getUSyncDevices([senderIdentity, jid], true, false)));
424
- }
425
-
426
- const allRecipients = [];
427
- const meRecipients = [];
428
- const otherRecipients = [];
429
- const mePnUserDec = jidDecode(meId);
430
- const meLidUserDec = meLid ? jidDecode(meLid) : null;
431
-
432
- for (const device of devices) {
433
- const deviceJid = device.jid;
434
- const isExactSenderDevice = deviceJid === meId || (meLid && deviceJid === meLid);
435
- if (isExactSenderDevice) continue;
436
-
437
- let shouldSend = true;
438
- if (mode === "include") {
439
- shouldSend = isMatch(deviceJid, parsedTargets);
440
- } else {
441
- shouldSend = !isMatch(deviceJid, parsedTargets);
442
- }
443
-
444
- const isMe = (device.user === mePnUserDec?.user) || (meLidUserDec && device.user === meLidUserDec?.user);
445
-
446
- if (isMe && typeof targetMe === "boolean") {
447
- shouldSend = targetMe;
448
- }
449
-
450
- const decDev = jidDecode(deviceJid);
451
- const dId = decDev?.device !== undefined ? decDev.device : 0;
452
- if (deviceMode === "primary" && dId !== 0) shouldSend = false;
453
- if (deviceMode === "secondary" && dId === 0) shouldSend = false;
454
-
455
- if (!shouldSend) continue;
456
-
457
- if (isMe) {
458
- meRecipients.push(deviceJid);
459
- allRecipients.push(deviceJid);
460
- } else {
461
- otherRecipients.push(deviceJid);
462
- allRecipients.push(deviceJid);
463
- }
464
- }
465
-
466
- await conn.assertSessions(allRecipients);
467
- const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
468
- conn.createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
469
- conn.createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
470
- ]);
471
- participants.push(...meNodes, ...otherNodes);
472
- if (meRecipients.length || otherRecipients.length) extraAttrs["phash"] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
473
- shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
474
- }
475
-
476
- if (participants.length) {
477
- if (additionalAttributes?.["category"] === "peer") {
478
- const peerNode = participants[0]?.content?.[0];
479
- if (peerNode) binaryNodeContent.push(peerNode);
480
- } else {
481
- binaryNodeContent.push({ tag: "participants", attrs: {}, content: participants });
482
- }
483
- }
484
-
485
- const stanza = {
486
- tag: "message",
487
- attrs: { id: msgId, to: destinationJid, type: getMessageType(message), ...(additionalAttributes || {}) },
488
- content: binaryNodeContent
489
- };
490
-
491
- if (shouldIncludeDeviceIdentity) {
492
- stanza.content.push({ tag: "device-identity", attrs: {}, content: encodeSignedDeviceIdentity(conn.authState.creds.account, true) });
493
- }
494
-
495
- if (reportingToken && !(additionalNodes && additionalNodes.some((n) => n.tag === "reporting"))) {
496
- stanza.content.push({
497
- tag: "reporting",
498
- attrs: {},
499
- content: [
500
- {
501
- tag: "reporting_token",
502
- attrs: { v: "2" },
503
- content: reportingToken
504
- }
505
- ]
506
- });
507
- }
508
-
509
- const contactTcTokenData = !isGroup && !isStatus ? await conn.authState.keys.get("tctoken", [destinationJid]) : {};
510
- const tcTokenBuffer = contactTcTokenData[destinationJid]?.token;
511
- if (tcTokenBuffer) stanza.content.push({ tag: "tctoken", attrs: {}, content: tcTokenBuffer });
512
-
513
- if (additionalNodes && additionalNodes.length > 0) stanza.content.push(...additionalNodes);
514
-
515
- await conn.sendNode(stanza);
516
-
517
- return msgId;
518
- }
519
-
520
- export const selectiveRelay = sPR;
521
- export default sPR;