@d0v3riz/baileys 6.7.5 → 6.7.7

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.
@@ -12,11 +12,10 @@ const Utils_1 = require("../Utils");
12
12
  const link_preview_1 = require("../Utils/link-preview");
13
13
  const WABinary_1 = require("../WABinary");
14
14
  const groups_1 = require("./groups");
15
- var ListType = WAProto_1.proto.Message.ListMessage.ListType;
16
15
  const makeMessagesSocket = (config) => {
17
- const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, } = config;
16
+ const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, cachedGroupMetadata, } = config;
18
17
  const sock = (0, groups_1.makeGroupsSocket)(config);
19
- const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, generateMessageTag, sendNode, groupMetadata, groupToggleEphemeral } = sock;
18
+ const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, generateMessageTag, sendNode, groupMetadata, groupToggleEphemeral, } = sock;
20
19
  const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
21
20
  stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
22
21
  useClones: false
@@ -222,6 +221,28 @@ const makeMessagesSocket = (config) => {
222
221
  }
223
222
  return didFetchNewSession;
224
223
  };
224
+ const sendPeerDataOperationMessage = async (pdoMessage) => {
225
+ var _a;
226
+ //TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
227
+ if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
228
+ throw new boom_1.Boom('Not authenticated');
229
+ }
230
+ const protocolMessage = {
231
+ protocolMessage: {
232
+ peerDataOperationRequestMessage: pdoMessage,
233
+ type: WAProto_1.proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
234
+ }
235
+ };
236
+ const meJid = (0, WABinary_1.jidNormalizedUser)(authState.creds.me.id);
237
+ const msgId = await relayMessage(meJid, protocolMessage, {
238
+ additionalAttributes: {
239
+ category: 'peer',
240
+ // eslint-disable-next-line camelcase
241
+ push_priority: 'high_force',
242
+ },
243
+ });
244
+ return msgId;
245
+ };
225
246
  const createParticipantNodes = async (jids, message, extraAttrs) => {
226
247
  const patched = await patchMessageBeforeSending(message, jids);
227
248
  const bytes = (0, Utils_1.encodeWAMessage)(patched);
@@ -249,7 +270,7 @@ const makeMessagesSocket = (config) => {
249
270
  }));
250
271
  return { nodes, shouldIncludeDeviceIdentity };
251
272
  };
252
- const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata, statusJidList }) => {
273
+ const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
253
274
  var _a;
254
275
  const meId = authState.creds.me.id;
255
276
  let shouldIncludeDeviceIdentity = false;
@@ -260,6 +281,7 @@ const makeMessagesSocket = (config) => {
260
281
  const isLid = server === 'lid';
261
282
  msgId = msgId || (0, Utils_1.generateMessageIDV2)((_a = sock.user) === null || _a === void 0 ? void 0 : _a.id);
262
283
  useUserDevicesCache = useUserDevicesCache !== false;
284
+ useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
263
285
  const participants = [];
264
286
  const destinationJid = (!isStatus) ? (0, WABinary_1.jidEncode)(user, isLid ? 'lid' : isGroup ? 'g.us' : 's.whatsapp.net') : statusJid;
265
287
  const binaryNodeContent = [];
@@ -270,6 +292,7 @@ const makeMessagesSocket = (config) => {
270
292
  message
271
293
  }
272
294
  };
295
+ const extraAttrs = {};
273
296
  if (participant) {
274
297
  // when the retry request is not for a group
275
298
  // only send to the specific device that asked for a retry
@@ -281,16 +304,22 @@ const makeMessagesSocket = (config) => {
281
304
  devices.push({ user, device });
282
305
  }
283
306
  await authState.keys.transaction(async () => {
284
- var _a, _b;
307
+ var _a, _b, _c, _d, _e;
285
308
  const mediaType = getMediaType(message);
309
+ if (mediaType) {
310
+ extraAttrs['mediatype'] = mediaType;
311
+ }
312
+ if ((_a = (0, Utils_1.normalizeMessageContent)(message)) === null || _a === void 0 ? void 0 : _a.pinInChatMessage) {
313
+ extraAttrs['decrypt-fail'] = 'hide';
314
+ }
286
315
  if (isGroup || isStatus) {
287
316
  const [groupData, senderKeyMap] = await Promise.all([
288
317
  (async () => {
289
- let groupData = cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined;
290
- if (groupData) {
318
+ let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined;
319
+ if (groupData && Array.isArray(groupData === null || groupData === void 0 ? void 0 : groupData.participants)) {
291
320
  logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
292
321
  }
293
- if (!groupData && !isStatus) {
322
+ else if (!isStatus) {
294
323
  groupData = await groupMetadata(jid);
295
324
  }
296
325
  return groupData;
@@ -339,7 +368,7 @@ const makeMessagesSocket = (config) => {
339
368
  }
340
369
  };
341
370
  await assertSessions(senderKeyJids, false);
342
- const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, mediaType ? { mediatype: mediaType } : undefined);
371
+ const result = await createParticipantNodes(senderKeyJids, senderKeyMsg, extraAttrs);
343
372
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
344
373
  participants.push(...result.nodes);
345
374
  }
@@ -355,18 +384,20 @@ const makeMessagesSocket = (config) => {
355
384
  if (!participant) {
356
385
  devices.push({ user });
357
386
  // do not send message to self if the device is 0 (mobile)
358
- if (meDevice !== undefined && meDevice !== 0) {
359
- devices.push({ user: meUser });
387
+ if (!((additionalAttributes === null || additionalAttributes === void 0 ? void 0 : additionalAttributes['category']) === 'peer' && user === meUser)) {
388
+ if (meDevice !== undefined && meDevice !== 0) {
389
+ devices.push({ user: meUser });
390
+ }
391
+ const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true);
392
+ devices.push(...additionalDevices);
360
393
  }
361
- const additionalDevices = await getUSyncDevices([meId, jid], !!useUserDevicesCache, true);
362
- devices.push(...additionalDevices);
363
394
  }
364
395
  const allJids = [];
365
396
  const meJids = [];
366
397
  const otherJids = [];
367
398
  for (const { user, device } of devices) {
368
399
  const isMe = user === meUser;
369
- const jid = (0, WABinary_1.jidEncode)(isMe && isLid ? ((_b = (_a = authState.creds) === null || _a === void 0 ? void 0 : _a.me) === null || _b === void 0 ? void 0 : _b.lid.split(':')[0]) || user : user, isLid ? 'lid' : 's.whatsapp.net', device);
400
+ const jid = (0, WABinary_1.jidEncode)(isMe && isLid ? ((_c = (_b = authState.creds) === null || _b === void 0 ? void 0 : _b.me) === null || _c === void 0 ? void 0 : _c.lid.split(':')[0]) || user : user, isLid ? 'lid' : 's.whatsapp.net', device);
370
401
  if (isMe) {
371
402
  meJids.push(jid);
372
403
  }
@@ -377,19 +408,27 @@ const makeMessagesSocket = (config) => {
377
408
  }
378
409
  await assertSessions(allJids, false);
379
410
  const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
380
- createParticipantNodes(meJids, meMsg, mediaType ? { mediatype: mediaType } : undefined),
381
- createParticipantNodes(otherJids, message, mediaType ? { mediatype: mediaType } : undefined)
411
+ createParticipantNodes(meJids, meMsg, extraAttrs),
412
+ createParticipantNodes(otherJids, message, extraAttrs)
382
413
  ]);
383
414
  participants.push(...meNodes);
384
415
  participants.push(...otherNodes);
385
416
  shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
386
417
  }
387
418
  if (participants.length) {
388
- binaryNodeContent.push({
389
- tag: 'participants',
390
- attrs: {},
391
- content: participants
392
- });
419
+ if ((additionalAttributes === null || additionalAttributes === void 0 ? void 0 : additionalAttributes['category']) === 'peer') {
420
+ const peerNode = (_e = (_d = participants[0]) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e[0];
421
+ if (peerNode) {
422
+ binaryNodeContent.push(peerNode); // push only enc
423
+ }
424
+ }
425
+ else {
426
+ binaryNodeContent.push({
427
+ tag: 'participants',
428
+ attrs: {},
429
+ content: participants
430
+ });
431
+ }
393
432
  }
394
433
  const stanza = {
395
434
  tag: 'message',
@@ -427,19 +466,8 @@ const makeMessagesSocket = (config) => {
427
466
  });
428
467
  logger.debug({ jid }, 'adding device identity');
429
468
  }
430
- const buttonType = getButtonType(message);
431
- if (buttonType) {
432
- stanza.content.push({
433
- tag: 'biz',
434
- attrs: {},
435
- content: [
436
- {
437
- tag: buttonType,
438
- attrs: getButtonArgs(message),
439
- }
440
- ]
441
- });
442
- logger.debug({ jid }, 'adding business node');
469
+ if (additionalNodes && additionalNodes.length > 0) {
470
+ stanza.content.push(...additionalNodes);
443
471
  }
444
472
  logger.debug({ msgId }, `sending message to ${participants.length} devices`);
445
473
  await sendNode(stanza);
@@ -489,38 +517,8 @@ const makeMessagesSocket = (config) => {
489
517
  else if (message.interactiveResponseMessage) {
490
518
  return 'native_flow_response';
491
519
  }
492
- };
493
- const getButtonType = (message) => {
494
- if (message.buttonsMessage) {
495
- return 'buttons';
496
- }
497
- else if (message.buttonsResponseMessage) {
498
- return 'buttons_response';
499
- }
500
- else if (message.interactiveResponseMessage) {
501
- return 'interactive_response';
502
- }
503
- else if (message.listMessage) {
504
- return 'list';
505
- }
506
- else if (message.listResponseMessage) {
507
- return 'list_response';
508
- }
509
- };
510
- const getButtonArgs = (message) => {
511
- if (message.templateMessage) {
512
- // TODO: Add attributes
513
- return {};
514
- }
515
- else if (message.listMessage) {
516
- const type = message.listMessage.listType;
517
- if (!type) {
518
- throw new boom_1.Boom('Expected list type inside message');
519
- }
520
- return { v: '2', type: ListType[type].toLowerCase() };
521
- }
522
- else {
523
- return {};
520
+ else if (message.groupInviteMessage) {
521
+ return 'url';
524
522
  }
525
523
  };
526
524
  const getPrivacyTokens = async (jids) => {
@@ -558,11 +556,13 @@ const makeMessagesSocket = (config) => {
558
556
  relayMessage,
559
557
  sendReceipt,
560
558
  sendReceipts,
561
- getButtonArgs,
562
559
  readMessages,
563
560
  refreshMediaConn,
564
561
  waUploadToServer,
565
562
  fetchPrivacySettings,
563
+ sendPeerDataOperationMessage,
564
+ createParticipantNodes,
565
+ getUSyncDevices,
566
566
  updateMediaMessage: async (message) => {
567
567
  const content = (0, Utils_1.assertMediaContent)(message.message);
568
568
  const mediaKey = content.mediaKey;
@@ -632,6 +632,8 @@ const makeMessagesSocket = (config) => {
632
632
  ? waUploadToServer
633
633
  : undefined
634
634
  }),
635
+ //TODO: CACHE
636
+ getProfilePicUrl: sock.profilePictureUrl,
635
637
  upload: waUploadToServer,
636
638
  mediaCache: config.mediaCache,
637
639
  options: config.options,
@@ -640,6 +642,7 @@ const makeMessagesSocket = (config) => {
640
642
  });
641
643
  const isDeleteMsg = 'delete' in content && !!content.delete;
642
644
  const isEditMsg = 'edit' in content && !!content.edit;
645
+ const isPinMsg = 'pin' in content && !!content.pin;
643
646
  const additionalAttributes = {};
644
647
  // required for delete
645
648
  if (isDeleteMsg) {
@@ -654,7 +657,13 @@ const makeMessagesSocket = (config) => {
654
657
  else if (isEditMsg) {
655
658
  additionalAttributes.edit = '1';
656
659
  }
657
- await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, cachedGroupMetadata: options.cachedGroupMetadata, additionalAttributes, statusJidList: options.statusJidList });
660
+ else if (isPinMsg) {
661
+ additionalAttributes.edit = '2';
662
+ }
663
+ if ('cachedGroupMetadata' in options) {
664
+ console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.');
665
+ }
666
+ await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, useCachedGroupMetadata: options.useCachedGroupMetadata, additionalAttributes, statusJidList: options.statusJidList });
658
667
  if (config.emitOwnEvents) {
659
668
  process.nextTick(() => {
660
669
  processingMutex.mutex(() => (upsertMessage(fullMsg, 'append')));
@@ -1,3 +1,4 @@
1
+ /// <reference types="long" />
1
2
  /// <reference types="node" />
2
3
  import { AxiosRequestConfig } from 'axios';
3
4
  import { KeyPair, SignedKeyPair, SocketConfig } from '../Types';
@@ -21,20 +22,27 @@ export declare const makeRegistrationSocket: (config: SocketConfig) => {
21
22
  sendMessageAck: ({ tag, attrs, content }: import("../WABinary").BinaryNode) => Promise<void>;
22
23
  sendRetryRequest: (node: import("../WABinary").BinaryNode, forceIncludeKeys?: boolean) => Promise<void>;
23
24
  rejectCall: (callId: string, callFrom: string) => Promise<void>;
25
+ fetchMessageHistory: (count: number, oldestMsgKey: import("../Types").WAProto.IMessageKey, oldestMsgTimestamp: number | import("long").Long) => Promise<string>;
26
+ requestPlaceholderResend: (messageKey: import("../Types").WAProto.IMessageKey) => Promise<string | undefined>;
24
27
  getPrivacyTokens: (jids: string[]) => Promise<import("../WABinary").BinaryNode>;
25
28
  assertSessions: (jids: string[], force: boolean) => Promise<boolean>;
26
- relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, useUserDevicesCache, cachedGroupMetadata, statusJidList }: import("../Types").MessageRelayOptions) => Promise<string>;
29
+ relayMessage: (jid: string, message: import("../Types").WAProto.IMessage, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }: import("../Types").MessageRelayOptions) => Promise<string>;
27
30
  sendReceipt: (jid: string, participant: string | undefined, messageIds: string[], type: import("../Types").MessageReceiptType) => Promise<void>;
28
31
  sendReceipts: (keys: import("../Types").WAProto.IMessageKey[], type: import("../Types").MessageReceiptType) => Promise<void>;
29
- getButtonArgs: (message: import("../Types").WAProto.IMessage) => {
30
- [key: string]: string;
31
- };
32
32
  readMessages: (keys: import("../Types").WAProto.IMessageKey[]) => Promise<void>;
33
33
  refreshMediaConn: (forceGet?: boolean) => Promise<import("../Types").MediaConnInfo>;
34
34
  waUploadToServer: import("../Types").WAMediaUploadFunction;
35
35
  fetchPrivacySettings: (force?: boolean) => Promise<{
36
36
  [_: string]: string;
37
37
  }>;
38
+ sendPeerDataOperationMessage: (pdoMessage: import("../Types").WAProto.Message.IPeerDataOperationRequestMessage) => Promise<string>;
39
+ createParticipantNodes: (jids: string[], message: import("../Types").WAProto.IMessage, extraAttrs?: {
40
+ [key: string]: string;
41
+ } | undefined) => Promise<{
42
+ nodes: import("../WABinary").BinaryNode[];
43
+ shouldIncludeDeviceIdentity: boolean;
44
+ }>;
45
+ getUSyncDevices: (jids: string[], useCache: boolean, ignoreZeroDevices: boolean) => Promise<import("../WABinary").JidWithDevice[]>;
38
46
  updateMediaMessage: (message: import("../Types").WAProto.IWebMessageInfo) => Promise<import("../Types").WAProto.IWebMessageInfo>;
39
47
  sendMessage: (jid: string, content: import("../Types").AnyMessageContent, options?: import("../Types").MiscMessageGenerationOptions) => Promise<import("../Types").WAProto.WebMessageInfo | undefined>;
40
48
  groupMetadata: (jid: string) => Promise<import("../Types").GroupMetadata>;
@@ -57,6 +65,7 @@ export declare const makeRegistrationSocket: (config: SocketConfig) => {
57
65
  groupInviteCode: (jid: string) => Promise<string | undefined>;
58
66
  groupRevokeInvite: (jid: string) => Promise<string | undefined>;
59
67
  groupAcceptInvite: (code: string) => Promise<string | undefined>;
68
+ groupRevokeInviteV4: (groupJid: string, invitedJid: string) => Promise<boolean>;
60
69
  groupAcceptInviteV4: (key: string | import("../Types").WAProto.IMessageKey, inviteMessage: import("../Types").WAProto.Message.IGroupInviteMessage) => Promise<string>;
61
70
  groupGetInviteInfo: (code: string) => Promise<import("../Types").GroupMetadata>;
62
71
  groupToggleEphemeral: (jid: string, ephemeralExpiration: number) => Promise<void>;
@@ -94,7 +103,7 @@ export declare const makeRegistrationSocket: (config: SocketConfig) => {
94
103
  updateProfilePicturePrivacy: (value: import("../Types").WAPrivacyValue) => Promise<void>;
95
104
  updateStatusPrivacy: (value: import("../Types").WAPrivacyValue) => Promise<void>;
96
105
  updateReadReceiptsPrivacy: (value: import("../Types").WAReadReceiptsValue) => Promise<void>;
97
- updateGroupsAddPrivacy: (value: import("../Types").WAPrivacyValue) => Promise<void>;
106
+ updateGroupsAddPrivacy: (value: import("../Types").WAPrivacyGroupAddValue) => Promise<void>;
98
107
  updateDefaultDisappearingMode: (duration: number) => Promise<void>;
99
108
  getBusinessProfile: (jid: string) => Promise<void | import("../Types").WABusinessProfile>;
100
109
  resyncAppState: (collections: readonly ("critical_block" | "critical_unblock_low" | "regular_high" | "regular_low" | "regular")[], isInitialSync: boolean) => Promise<void>;
@@ -66,7 +66,11 @@ exports.default = (config) => {
66
66
  ev.on('connection.update', update => {
67
67
  Object.assign(state, update);
68
68
  });
69
- ev.on('messaging-history.set', ({ chats: newChats, contacts: newContacts, messages: newMessages, isLatest }) => {
69
+ ev.on('messaging-history.set', ({ chats: newChats, contacts: newContacts, messages: newMessages, isLatest, syncType }) => {
70
+ if (syncType === WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND) {
71
+ return; // FOR NOW,
72
+ //TODO: HANDLE
73
+ }
70
74
  if (isLatest) {
71
75
  chats.clear();
72
76
  for (const id in messages) {
@@ -7,6 +7,7 @@ import type { MinimalMessage } from './Message';
7
7
  /** privacy settings in WhatsApp Web */
8
8
  export type WAPrivacyValue = 'all' | 'contacts' | 'contact_blacklist' | 'none';
9
9
  export type WAPrivacyOnlineValue = 'all' | 'match_last_seen';
10
+ export type WAPrivacyGroupAddValue = 'all' | 'contacts' | 'contact_blacklist';
10
11
  export type WAReadReceiptsValue = 'all' | 'none';
11
12
  export type WAPrivacyCallValue = 'all' | 'known';
12
13
  /** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */
@@ -19,7 +19,9 @@ export type BaileysEventMap = {
19
19
  chats: Chat[];
20
20
  contacts: Contact[];
21
21
  messages: WAMessage[];
22
- isLatest: boolean;
22
+ isLatest?: boolean;
23
+ progress?: number | null;
24
+ syncType?: proto.HistorySync.HistorySyncType;
23
25
  };
24
26
  /** upsert chats */
25
27
  'chats.upsert': Chat[];
@@ -58,10 +60,12 @@ export type BaileysEventMap = {
58
60
  /**
59
61
  * add/update the given messages. If they were received while the connection was online,
60
62
  * the update will have type: "notify"
63
+ * if requestId is provided, then the messages was received from the phone due to it being unavailable
61
64
  * */
62
65
  'messages.upsert': {
63
66
  messages: WAMessage[];
64
67
  type: MessageUpsertType;
68
+ requestId?: string;
65
69
  };
66
70
  /** message was reacted to. If reaction was removed -- then "reaction.text" will be falsey */
67
71
  'messages.reaction': {
@@ -7,6 +7,7 @@ import type { Readable } from 'stream';
7
7
  import type { URL } from 'url';
8
8
  import { proto } from '../../WAProto';
9
9
  import { MEDIA_HKDF_KEY_MAPPING } from '../Defaults';
10
+ import { BinaryNode } from '../WABinary';
10
11
  import type { GroupMetadata } from './GroupMetadata';
11
12
  import { CacheStore } from './Socket';
12
13
  export { proto as WAProto };
@@ -63,26 +64,9 @@ type Contextable = {
63
64
  type ViewOnce = {
64
65
  viewOnce?: boolean;
65
66
  };
66
- type Buttonable = {
67
- /** add buttons to the message */
68
- buttons?: proto.Message.ButtonsMessage.IButton[];
69
- };
70
- type Templatable = {
71
- /** add buttons to the message (conflicts with normal buttons)*/
72
- templateButtons?: proto.IHydratedTemplateButton[];
73
- footer?: string;
74
- };
75
67
  type Editable = {
76
68
  edit?: WAMessageKey;
77
69
  };
78
- type Listable = {
79
- /** Sections of the List */
80
- sections?: proto.Message.ListMessage.ISection[];
81
- /** Title of a List Message only */
82
- title?: string;
83
- /** Text of the bnutton on the list (required) */
84
- buttonText?: string;
85
- };
86
70
  type WithDimensions = {
87
71
  width?: number;
88
72
  height?: number;
@@ -93,6 +77,7 @@ export type PollMessageOptions = {
93
77
  values: string[];
94
78
  /** 32 byte message secret to encrypt poll selections */
95
79
  messageSecret?: Uint8Array;
80
+ toAnnouncementGroup?: boolean;
96
81
  };
97
82
  type SharePhoneNumber = {
98
83
  sharePhoneNumber: boolean;
@@ -105,14 +90,14 @@ export type AnyMediaMessageContent = (({
105
90
  image: WAMediaUpload;
106
91
  caption?: string;
107
92
  jpegThumbnail?: string;
108
- } & Mentionable & Contextable & Buttonable & Templatable & WithDimensions) | ({
93
+ } & Mentionable & Contextable & WithDimensions) | ({
109
94
  video: WAMediaUpload;
110
95
  caption?: string;
111
96
  gifPlayback?: boolean;
112
97
  jpegThumbnail?: string;
113
98
  /** if set to true, will send as a `video note` */
114
99
  ptv?: boolean;
115
- } & Mentionable & Contextable & Buttonable & Templatable & WithDimensions) | {
100
+ } & Mentionable & Contextable & WithDimensions) | {
116
101
  audio: WAMediaUpload;
117
102
  /** if set to true, will send as a `voice note` */
118
103
  ptt?: boolean;
@@ -126,7 +111,7 @@ export type AnyMediaMessageContent = (({
126
111
  mimetype: string;
127
112
  fileName?: string;
128
113
  caption?: string;
129
- } & Contextable & Buttonable & Templatable)) & {
114
+ } & Contextable)) & {
130
115
  mimetype?: string;
131
116
  } & Editable;
132
117
  export type ButtonReplyInfo = {
@@ -134,15 +119,22 @@ export type ButtonReplyInfo = {
134
119
  id: string;
135
120
  index: number;
136
121
  };
122
+ export type GroupInviteInfo = {
123
+ inviteCode: string;
124
+ inviteExpiration: number;
125
+ text: string;
126
+ jid: string;
127
+ subject: string;
128
+ };
137
129
  export type WASendableProduct = Omit<proto.Message.ProductMessage.IProductSnapshot, 'productImage'> & {
138
130
  productImage: WAMediaUpload;
139
131
  };
140
132
  export type AnyRegularMessageContent = (({
141
133
  text: string;
142
134
  linkPreview?: WAUrlInfo | null;
143
- } & Mentionable & Contextable & Buttonable & Templatable & Listable & Editable) | AnyMediaMessageContent | ({
135
+ } & Mentionable & Contextable & Editable) | AnyMediaMessageContent | ({
144
136
  poll: PollMessageOptions;
145
- } & Mentionable & Contextable & Buttonable & Templatable & Editable) | {
137
+ } & Mentionable & Contextable & Editable) | {
146
138
  contacts: {
147
139
  displayName?: string;
148
140
  contacts: proto.Message.IContactMessage[];
@@ -154,8 +146,17 @@ export type AnyRegularMessageContent = (({
154
146
  } | {
155
147
  buttonReply: ButtonReplyInfo;
156
148
  type: 'template' | 'plain';
149
+ } | {
150
+ groupInvite: GroupInviteInfo;
157
151
  } | {
158
152
  listReply: Omit<proto.Message.IListResponseMessage, 'contextInfo'>;
153
+ } | {
154
+ pin: WAMessageKey;
155
+ type: proto.PinInChat.Type;
156
+ /**
157
+ * 24 hours, 7 days, 30 days
158
+ */
159
+ time?: 86400 | 604800 | 2592000;
159
160
  } | {
160
161
  product: WASendableProduct;
161
162
  businessOwnerJid?: string;
@@ -175,8 +176,8 @@ export type GroupMetadataParticipants = Pick<GroupMetadata, 'participants'>;
175
176
  type MinimalRelayOptions = {
176
177
  /** override the message ID with a custom provided string */
177
178
  messageId?: string;
178
- /** cached group metadata, use to prevent redundant requests to WA & speed up msg sending */
179
- cachedGroupMetadata?: (jid: string) => Promise<GroupMetadataParticipants | undefined>;
179
+ /** should we use group metadata cache, or fetch afresh from the server; default assumed to be "true" */
180
+ useCachedGroupMetadata?: boolean;
180
181
  };
181
182
  export type MessageRelayOptions = MinimalRelayOptions & {
182
183
  /** only send to a specific participant; used when a message decryption fails for a single user */
@@ -188,6 +189,7 @@ export type MessageRelayOptions = MinimalRelayOptions & {
188
189
  additionalAttributes?: {
189
190
  [_: string]: string;
190
191
  };
192
+ additionalNodes?: BinaryNode[];
191
193
  /** should we use the devices cache, or fetch afresh from the server; default assumed to be "true" */
192
194
  useUserDevicesCache?: boolean;
193
195
  /** jid list of participants for status@broadcast */
@@ -237,6 +239,7 @@ export type MediaGenerationOptions = {
237
239
  };
238
240
  export type MessageContentGenerationOptions = MediaGenerationOptions & {
239
241
  getUrlInfo?: (text: string) => Promise<WAUrlInfo | undefined>;
242
+ getProfilePicUrl?: (jid: string, type: 'image' | 'preview') => Promise<string | undefined>;
240
243
  };
241
244
  export type MessageGenerationOptions = MessageContentGenerationOptions & MessageGenerationOptionsFromContent;
242
245
  /**
@@ -6,6 +6,7 @@ import type { Logger } from 'pino';
6
6
  import type { URL } from 'url';
7
7
  import { proto } from '../../WAProto';
8
8
  import { AuthenticationState, SignalAuthState, TransactionCapabilityOptions } from './Auth';
9
+ import { GroupMetadata } from './GroupMetadata';
9
10
  import { MediaConnInfo } from './Message';
10
11
  import { SignalRepository } from './Signal';
11
12
  export type WAVersion = [number, number, number];
@@ -71,6 +72,8 @@ export type SocketConfig = {
71
72
  userDevicesCache?: CacheStore;
72
73
  /** cache to store call offers */
73
74
  callOfferCache?: CacheStore;
75
+ /** cache to track placeholder resends */
76
+ placeholderResendCache?: CacheStore;
74
77
  /** width for link preview images */
75
78
  linkPreviewImageThumbnailWidth: number;
76
79
  /** Should Baileys ask the phone for full history, will be received async */
@@ -105,6 +108,8 @@ export type SocketConfig = {
105
108
  * (solves the "this message can take a while" issue) can be retried
106
109
  * */
107
110
  getMessage: (key: proto.IMessageKey) => Promise<proto.IMessage | undefined>;
111
+ /** cached group metadata, use to prevent redundant requests to WA & speed up msg sending */
112
+ cachedGroupMetadata: (jid: string) => Promise<GroupMetadata | undefined>;
108
113
  makeSignalRepository: (auth: SignalAuthState) => SignalRepository;
109
114
  /** Socket passthrough */
110
115
  socket?: any;
@@ -2,6 +2,7 @@ import { Logger } from 'pino';
2
2
  import { proto } from '../../WAProto';
3
3
  import { SignalRepository } from '../Types';
4
4
  import { BinaryNode } from '../WABinary';
5
+ export declare const NO_MESSAGE_FOUND_ERROR_TEXT = "Message absent from node";
5
6
  /**
6
7
  * Decode the received node as a message.
7
8
  * @note this will only parse the message, not decrypt it
@@ -1,16 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.decryptMessageNode = exports.decodeMessageNode = void 0;
3
+ exports.decryptMessageNode = exports.decodeMessageNode = exports.NO_MESSAGE_FOUND_ERROR_TEXT = void 0;
4
4
  const boom_1 = require("@hapi/boom");
5
5
  const WAProto_1 = require("../../WAProto");
6
6
  const WABinary_1 = require("../WABinary");
7
7
  const generics_1 = require("./generics");
8
- const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node';
8
+ exports.NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node';
9
9
  /**
10
10
  * Decode the received node as a message.
11
11
  * @note this will only parse the message, not decrypt it
12
12
  */
13
13
  function decodeMessageNode(stanza, meId, meLid) {
14
+ var _a;
14
15
  let msgType;
15
16
  let chatId;
16
17
  let author;
@@ -68,11 +69,16 @@ function decodeMessageNode(stanza, meId, meLid) {
68
69
  chatId = from;
69
70
  author = participant;
70
71
  }
72
+ else if ((0, WABinary_1.isJidNewsletter)(from)) {
73
+ msgType = 'newsletter';
74
+ chatId = from;
75
+ author = from;
76
+ }
71
77
  else {
72
78
  throw new boom_1.Boom('Unknown message type', { data: stanza });
73
79
  }
74
80
  const fromMe = ((0, WABinary_1.isLidUser)(from) ? isMeLid : isMe)(stanza.attrs.participant || stanza.attrs.from);
75
- const pushname = stanza.attrs.notify;
81
+ const pushname = (_a = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _a === void 0 ? void 0 : _a.notify;
76
82
  const key = {
77
83
  remoteJid: chatId,
78
84
  fromMe,
@@ -111,7 +117,7 @@ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
111
117
  const details = WAProto_1.proto.VerifiedNameCertificate.Details.decode(cert.details);
112
118
  fullMessage.verifiedBizName = details.verifiedName;
113
119
  }
114
- if (tag !== 'enc') {
120
+ if (tag !== 'enc' && tag !== 'plaintext') {
115
121
  continue;
116
122
  }
117
123
  if (!(content instanceof Uint8Array)) {
@@ -120,7 +126,7 @@ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
120
126
  decryptables += 1;
121
127
  let msgBuffer;
122
128
  try {
123
- const e2eType = attrs.type;
129
+ const e2eType = tag === 'plaintext' ? 'plaintext' : attrs.type;
124
130
  switch (e2eType) {
125
131
  case 'skmsg':
126
132
  msgBuffer = await repository.decryptGroupMessage({
@@ -138,10 +144,13 @@ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
138
144
  ciphertext: content
139
145
  });
140
146
  break;
147
+ case 'plaintext':
148
+ msgBuffer = content;
149
+ break;
141
150
  default:
142
151
  throw new Error(`Unknown e2e type: ${e2eType}`);
143
152
  }
144
- let msg = WAProto_1.proto.Message.decode((0, generics_1.unpadRandomMax16)(msgBuffer));
153
+ let msg = WAProto_1.proto.Message.decode(e2eType !== 'plaintext' ? (0, generics_1.unpadRandomMax16)(msgBuffer) : msgBuffer);
145
154
  msg = ((_a = msg.deviceSentMessage) === null || _a === void 0 ? void 0 : _a.message) || msg;
146
155
  if (msg.senderKeyDistributionMessage) {
147
156
  try {
@@ -171,7 +180,7 @@ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
171
180
  // if nothing was found to decrypt
172
181
  if (!decryptables) {
173
182
  fullMessage.messageStubType = WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT;
174
- fullMessage.messageStubParameters = [NO_MESSAGE_FOUND_ERROR_TEXT, JSON.stringify(stanza, generics_1.BufferJSON.replacer)];
183
+ fullMessage.messageStubParameters = [exports.NO_MESSAGE_FOUND_ERROR_TEXT];
175
184
  }
176
185
  }
177
186
  };
@@ -6,10 +6,14 @@ export declare const processHistoryMessage: (item: proto.IHistorySync) => {
6
6
  chats: Chat[];
7
7
  contacts: Contact[];
8
8
  messages: proto.IWebMessageInfo[];
9
+ syncType: proto.HistorySync.HistorySyncType;
10
+ progress: number | null | undefined;
9
11
  };
10
12
  export declare const downloadAndProcessHistorySyncNotification: (msg: proto.Message.IHistorySyncNotification, options: AxiosRequestConfig<any>) => Promise<{
11
13
  chats: Chat[];
12
14
  contacts: Contact[];
13
15
  messages: proto.IWebMessageInfo[];
16
+ syncType: proto.HistorySync.HistorySyncType;
17
+ progress: number | null | undefined;
14
18
  }>;
15
19
  export declare const getHistoryMsg: (message: proto.IMessage) => proto.Message.IHistorySyncNotification | null | undefined;
@@ -32,6 +32,7 @@ const processHistoryMessage = (item) => {
32
32
  case WAProto_1.proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP:
33
33
  case WAProto_1.proto.HistorySync.HistorySyncType.RECENT:
34
34
  case WAProto_1.proto.HistorySync.HistorySyncType.FULL:
35
+ case WAProto_1.proto.HistorySync.HistorySyncType.ON_DEMAND:
35
36
  for (const chat of item.conversations) {
36
37
  contacts.push({ id: chat.id, name: chat.name || undefined });
37
38
  const msgs = chat.messages || [];
@@ -74,6 +75,8 @@ const processHistoryMessage = (item) => {
74
75
  chats,
75
76
  contacts,
76
77
  messages,
78
+ syncType: item.syncType,
79
+ progress: item.progress,
77
80
  };
78
81
  };
79
82
  exports.processHistoryMessage = processHistoryMessage;