@boruto_vk7/baileys 1.0.0 → 1.0.1

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.
@@ -10,7 +10,7 @@ export const CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
10
10
  export const CALL_AUDIO_PREFIX = 'https://call.whatsapp.com/voice/';
11
11
  export const DEF_CALLBACK_PREFIX = 'CB:';
12
12
  export const DEF_TAG_PREFIX = 'TAG:';
13
- export const DONATE_URL = 'https://okarun-api.com.br/status'; // Lia@Note 02-02-26 --- Apologies if this feels cheeky, just a fallback
13
+ export const DONATE_URL = 'https://okarun-api.com.br/status'; // Boruto@Note 02-02-26 --- Apologies if this feels cheeky, just a fallback
14
14
  export const LIBRARY_NAME = 'boruto_vk7/baileys';
15
15
  export const PHONE_CONNECTION_CB = 'CB:Pong';
16
16
  export const WA_ADV_ACCOUNT_SIG_PREFIX = Buffer.from([6, 0]);
@@ -93,7 +93,7 @@ export const MEDIA_PATH_MAP = {
93
93
  'md-msg-hist': '/mms/md-app-state',
94
94
  'biz-cover-photo': '/pps/biz-cover-photo'
95
95
  };
96
- // Lia@Changes 06-02-26 --- Add newsletter media path for "/m1/" instead of "/o1/" (⁠≧⁠▽⁠≦⁠)
96
+ // Boruto@Changes 06-02-26 --- Add newsletter media path for "/m1/" instead of "/o1/" (⁠≧⁠▽⁠≦⁠)
97
97
  export const NEWSLETTER_MEDIA_PATH_MAP = {
98
98
  image: '/newsletter/newsletter-image',
99
99
  video: '/newsletter/newsletter-video',
@@ -0,0 +1,148 @@
1
+ import { proto } from '../../WAProto/index.js';
2
+ import { makeLibSignalRepository } from '../Signal/libsignal.js';
3
+ import { Browsers } from '../Utils/browser-utils.js';
4
+ import logger from '../Utils/logger.js';
5
+ const version = [2, 3000, 1037013887];
6
+ export const UNAUTHORIZED_CODES = [401, 403, 419];
7
+ export const BIZ_BOT_SUPPORT_PAYLOAD = '{"version":1,"is_ai_message":true,"should_upload_client_logs":false,"should_show_system_message":false,"ticket_id":"7004947587700716","citation_items":[],"ticket_locale":"us"}';
8
+ export const DEFAULT_ORIGIN = 'https://web.whatsapp.com';
9
+ export const CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
10
+ export const CALL_AUDIO_PREFIX = 'https://call.whatsapp.com/voice/';
11
+ export const DEF_CALLBACK_PREFIX = 'CB:';
12
+ export const DEF_TAG_PREFIX = 'TAG:';
13
+ export const DONATE_URL = 'https://okarun-api.com.br/status'; // Boruto@Note 02-02-26 --- Apologies if this feels cheeky, just a fallback
14
+ export const LIBRARY_NAME = 'itsBorutoaa/baileys';
15
+ export const PHONE_CONNECTION_CB = 'CB:Pong';
16
+ export const WA_ADV_ACCOUNT_SIG_PREFIX = Buffer.from([6, 0]);
17
+ export const WA_ADV_DEVICE_SIG_PREFIX = Buffer.from([6, 1]);
18
+ export const WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX = Buffer.from([6, 5]);
19
+ export const WA_ADV_HOSTED_DEVICE_SIG_PREFIX = Buffer.from([6, 6]);
20
+ export const WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60;
21
+ /** Status messages older than 24 hours are considered expired */
22
+ export const STATUS_EXPIRY_SECONDS = 24 * 60 * 60;
23
+ /** WA Web enforces a 14-day maximum age for placeholder resend requests */
24
+ export const PLACEHOLDER_MAX_AGE_SECONDS = 14 * 24 * 60 * 60;
25
+ export const NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0';
26
+ export const DICT_VERSION = 3;
27
+ export const KEY_BUNDLE_TYPE = Buffer.from([5]);
28
+ export const NOISE_WA_HEADER = Buffer.from([87, 65, 6, DICT_VERSION]); // last is "DICT_VERSION"
29
+ export const LEXER_REGEX = /(\/\/.*|\/\*[\s\S]*?\*\/|#.*)|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`[\s\S]*?`)|(\b[a-zA-Z_]\w*\b)(?=\s*\()|(\b[a-zA-Z_]\w*\b)|(\b\d+(?:\.\d+)?\b)|(\s+|[^\w\s]+)/g;
30
+ /** from: https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url */
31
+ export const URL_REGEX = /https:\/\/(?![^:@\/\s]+:[^:@\/\s]+@)[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:\d+)?(\/[^\s]*)?/g;
32
+ export const WA_CERT_DETAILS = {
33
+ SERIAL: 0,
34
+ ISSUER: 'WhatsAppLongTerm1',
35
+ PUBLIC_KEY: Buffer.from('142375574d0a587166aae71ebe516437c4a28b73e3695c6ce1f7f9545da8ee6b', 'hex')
36
+ };
37
+ export const PROCESSABLE_HISTORY_TYPES = [
38
+ proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP,
39
+ proto.HistorySync.HistorySyncType.PUSH_NAME,
40
+ proto.HistorySync.HistorySyncType.RECENT,
41
+ proto.HistorySync.HistorySyncType.FULL,
42
+ proto.HistorySync.HistorySyncType.ON_DEMAND,
43
+ proto.HistorySync.HistorySyncType.NON_BLOCKING_DATA,
44
+ proto.HistorySync.HistorySyncType.INITIAL_STATUS_V3
45
+ ];
46
+ export const DEFAULT_CONNECTION_CONFIG = {
47
+ version: version,
48
+ browser: Browsers.macOS('Chrome'),
49
+ waWebSocketUrl: 'wss://web.whatsapp.com/ws/chat',
50
+ connectTimeoutMs: 20000,
51
+ keepAliveIntervalMs: 30000,
52
+ logger: logger.child({ class: 'baileys' }),
53
+ emitOwnEvents: true,
54
+ defaultQueryTimeoutMs: 60000,
55
+ customUploadHosts: [],
56
+ retryRequestDelayMs: 250,
57
+ maxMsgRetryCount: 3,
58
+ fireInitQueries: true,
59
+ auth: undefined,
60
+ markOnlineOnConnect: true,
61
+ syncFullHistory: true,
62
+ patchMessageBeforeSending: msg => msg,
63
+ shouldSyncHistoryMessage: ({ syncType }) => {
64
+ return syncType !== proto.HistorySync.HistorySyncType.FULL;
65
+ },
66
+ shouldIgnoreJid: () => false,
67
+ linkPreviewImageThumbnailWidth: 192,
68
+ transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 },
69
+ generateHighQualityLinkPreview: false,
70
+ enableAutoSessionRecreation: true,
71
+ enableRecentMessageCache: true,
72
+ options: {},
73
+ appStateMacVerification: {
74
+ patch: false,
75
+ snapshot: false
76
+ },
77
+ countryCode: 'US',
78
+ getMessage: async () => undefined,
79
+ cachedGroupMetadata: async () => undefined,
80
+ makeSignalRepository: makeLibSignalRepository
81
+ };
82
+ export const MEDIA_PATH_MAP = {
83
+ image: '/mms/image',
84
+ video: '/mms/video',
85
+ document: '/mms/document',
86
+ audio: '/mms/audio',
87
+ sticker: '/mms/image',
88
+ 'sticker-pack': '/mms/sticker-pack',
89
+ 'thumbnail-sticker-pack': '/mms/thumbnail-sticker-pack',
90
+ 'thumbnail-link': '/mms/thumbnail-link',
91
+ 'product-catalog-image': '/product/image',
92
+ 'md-app-state': '',
93
+ 'md-msg-hist': '/mms/md-app-state',
94
+ 'biz-cover-photo': '/pps/biz-cover-photo'
95
+ };
96
+ // Boruto@Changes 06-02-26 --- Add newsletter media path for "/m1/" instead of "/o1/" (⁠≧⁠▽⁠≦⁠)
97
+ export const NEWSLETTER_MEDIA_PATH_MAP = {
98
+ image: '/newsletter/newsletter-image',
99
+ video: '/newsletter/newsletter-video',
100
+ document: '/newsletter/newsletter-document',
101
+ audio: '/newsletter/newsletter-audio',
102
+ sticker: '/newsletter/newsletter-image',
103
+ 'thumbnail-link': '/newsletter/newsletter-thumbnail-link'
104
+ };
105
+ export const MEDIA_HKDF_KEY_MAPPING = {
106
+ audio: 'Audio',
107
+ document: 'Document',
108
+ gif: 'Video',
109
+ image: 'Image',
110
+ ppic: '',
111
+ product: 'Image',
112
+ ptt: 'Audio',
113
+ 'sticker-pack': 'Sticker Pack',
114
+ 'thumbnail-sticker-pack': 'Sticker Pack Thumbnail',
115
+ sticker: 'Image',
116
+ video: 'Video',
117
+ 'thumbnail-document': 'Document Thumbnail',
118
+ 'thumbnail-image': 'Image Thumbnail',
119
+ 'thumbnail-video': 'Video Thumbnail',
120
+ 'thumbnail-link': 'Link Thumbnail',
121
+ 'md-msg-hist': 'History',
122
+ 'md-app-state': 'App State',
123
+ 'product-catalog-image': '',
124
+ 'payment-bg-image': 'Payment Background',
125
+ ptv: 'Video',
126
+ 'biz-cover-photo': 'Image'
127
+ };
128
+ export const MEDIA_KEYS = Object.keys(MEDIA_PATH_MAP);
129
+ export const MIN_PREKEY_COUNT = 5;
130
+ export const INITIAL_PREKEY_COUNT = 812;
131
+ export const UPLOAD_TIMEOUT = 30000; // 30 seconds
132
+ export const MIN_UPLOAD_INTERVAL = 5000; // 5 seconds minimum between uploads
133
+ export const DEFAULT_CACHE_TTLS = {
134
+ SIGNAL_STORE: 5 * 60, // 5 minutes
135
+ MSG_RETRY: 60 * 60, // 1 hour
136
+ CALL_OFFER: 5 * 60, // 5 minutes
137
+ USER_DEVICES: 5 * 60 // 5 minutes
138
+ };
139
+ export const TimeMs = {
140
+ Minute: 60 * 1000,
141
+ Hour: 60 * 60 * 1000,
142
+ Day: 24 * 60 * 60 * 1000,
143
+ Week: 7 * 24 * 60 * 60 * 1000
144
+ };
145
+ export const BOT_RENDERING_CONFIG_METADATA = {
146
+ bloksVersioningId: '0903aa5f7f47de66789d5f4c86d3bd6e05e4bc3ff85e454a9f907d5ed7fef97c',
147
+ pixelDensity: 2.75
148
+ };
@@ -12,7 +12,7 @@ import { getBinaryNodeChild, getBinaryNodeChildren, isLidUser, isPnUser, jidDeco
12
12
  import { USyncQuery, USyncUser } from '../WAUSync/index.js';
13
13
  import { makeSocket } from './socket.js';
14
14
  const MAX_SYNC_ATTEMPTS = 2;
15
- // Lia@Note 08-02-26 --- I know it's not efficient for RSS ಥ⁠‿⁠ಥ
15
+ // Boruto@Note 08-02-26 --- I know it's not efficient for RSS ಥ⁠‿⁠ಥ
16
16
  const USER_ID_CACHE = new Map();
17
17
  export const makeChatsSocket = (config) => {
18
18
  const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
@@ -174,7 +174,7 @@ export const makeChatsSocket = (config) => {
174
174
  return result.list;
175
175
  }
176
176
  };
177
- // Lia@Note 06-02-26 --- Quick helper only. This function exists solely for faster lookup with caching.
177
+ // Boruto@Note 06-02-26 --- Quick helper only. This function exists solely for faster lookup with caching.
178
178
  const findUserId = async (pnLid) => {
179
179
  const cachedId = USER_ID_CACHE.get(pnLid);
180
180
  if (cachedId) {
@@ -186,7 +186,7 @@ export const makeChatsSocket = (config) => {
186
186
  userId.lid = (await signalRepository.lidMapping.getLIDsForPNs([pnLid]))?.[0]?.lid;
187
187
  if (!userId.lid) {
188
188
  userId.lid = 'id-not-found';
189
- return userId; // Lia@Note 06-02-26 --- Early return to skip caching for non-existent ID
189
+ return userId; // Boruto@Note 06-02-26 --- Early return to skip caching for non-existent ID
190
190
  }
191
191
  }
192
192
  else if (isLidUser(pnLid)) {
@@ -194,7 +194,7 @@ export const makeChatsSocket = (config) => {
194
194
  userId.phoneNumber = (await signalRepository.lidMapping.getPNsForLIDs([pnLid]))?.[0]?.pn;
195
195
  if (!userId.phoneNumber) {
196
196
  userId.phoneNumber = 'id-not-found';
197
- return userId; // Lia@Note 06-02-26 --- Early return to skip caching for non-existent ID
197
+ return userId; // Boruto@Note 06-02-26 --- Early return to skip caching for non-existent ID
198
198
  }
199
199
  }
200
200
  else {
@@ -202,7 +202,7 @@ export const makeChatsSocket = (config) => {
202
202
  }
203
203
  userId.phoneNumber = jidNormalizedUser(userId.phoneNumber);
204
204
  userId.lid = jidNormalizedUser(userId.lid);
205
- // Lia@Note 06-02-26 --- I know... it's dirty (⁠╯⁠︵⁠╰⁠,⁠)
205
+ // Boruto@Note 06-02-26 --- I know... it's dirty (⁠╯⁠︵⁠╰⁠,⁠)
206
206
  USER_ID_CACHE.set(userId.phoneNumber, userId);
207
207
  USER_ID_CACHE.set(userId.lid, userId);
208
208
  return userId;
@@ -507,7 +507,7 @@ export const makeChatsSocket = (config) => {
507
507
  * type = "image for the high res picture"
508
508
  */
509
509
  const profilePictureUrl = async (jid, type = 'image', timeoutMs) => {
510
- // Lia@Changes 06-02-26 --- Refactor profilePictureUrl() to use tctoken and adjust error handling
510
+ // Boruto@Changes 06-02-26 --- Refactor profilePictureUrl() to use tctoken and adjust error handling
511
511
  jid = jidNormalizedUser(jid);
512
512
  const baseContent = {
513
513
  tag: 'picture',
@@ -0,0 +1,329 @@
1
+ import { proto } from '../../WAProto/index.js';
2
+ import { WAMessageAddressingMode, WAMessageStubType } from '../Types/index.js';
3
+ import { generateMessageIDV2, unixTimestampSeconds } from '../Utils/index.js';
4
+ import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString, isLidUser, isPnUser, jidEncode, jidNormalizedUser } from '../WABinary/index.js';
5
+ import { makeChatsSocket } from './chats.js';
6
+ export const makeGroupsSocket = (config) => {
7
+ const sock = makeChatsSocket(config);
8
+ const { authState, ev, query, upsertMessage } = sock;
9
+ const groupQuery = async (jid, type, content) => query({
10
+ tag: 'iq',
11
+ attrs: {
12
+ type,
13
+ xmlns: 'w:g2',
14
+ to: jid
15
+ },
16
+ content
17
+ });
18
+ const groupMetadata = async (jid) => {
19
+ const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }]);
20
+ return extractGroupMetadata(result);
21
+ };
22
+ const groupFetchAllParticipating = async () => {
23
+ const result = await query({
24
+ tag: 'iq',
25
+ attrs: {
26
+ to: '@g.us',
27
+ xmlns: 'w:g2',
28
+ type: 'get'
29
+ },
30
+ content: [
31
+ {
32
+ tag: 'participating',
33
+ attrs: {},
34
+ content: [
35
+ { tag: 'participants', attrs: {} },
36
+ { tag: 'description', attrs: {} }
37
+ ]
38
+ }
39
+ ]
40
+ });
41
+ const data = Object.create(null);
42
+ const groupsChild = getBinaryNodeChild(result, 'groups');
43
+ if (groupsChild) {
44
+ const groups = getBinaryNodeChildren(groupsChild, 'group');
45
+ for (const groupNode of groups) {
46
+ const meta = extractGroupMetadata({
47
+ tag: 'result',
48
+ attrs: {},
49
+ content: [groupNode]
50
+ });
51
+ data[meta.id] = meta;
52
+ }
53
+ }
54
+ // TODO: properly parse LID / PN DATA
55
+ sock.ev.emit('groups.update', Object.values(data));
56
+ return data;
57
+ };
58
+ sock.ws.on('CB:ib,,dirty', async (node) => {
59
+ const { attrs } = getBinaryNodeChild(node, 'dirty');
60
+ if (attrs.type !== 'groups') {
61
+ return;
62
+ }
63
+ await groupFetchAllParticipating();
64
+ await sock.cleanDirtyBits('groups');
65
+ });
66
+ return {
67
+ ...sock,
68
+ extractGroupMetadata,
69
+ groupMetadata,
70
+ groupCreate: async (subject, participants) => {
71
+ const key = generateMessageIDV2();
72
+ const result = await groupQuery('@g.us', 'set', [
73
+ {
74
+ tag: 'create',
75
+ attrs: {
76
+ subject,
77
+ key
78
+ },
79
+ content: participants.map(jid => ({
80
+ tag: 'participant',
81
+ attrs: { jid }
82
+ }))
83
+ }
84
+ ]);
85
+ return extractGroupMetadata(result);
86
+ },
87
+ groupLeave: async (id) => {
88
+ await groupQuery('@g.us', 'set', [
89
+ {
90
+ tag: 'leave',
91
+ attrs: {},
92
+ content: [{ tag: 'group', attrs: { id } }]
93
+ }
94
+ ]);
95
+ },
96
+ groupUpdateSubject: async (jid, subject) => {
97
+ await groupQuery(jid, 'set', [
98
+ {
99
+ tag: 'subject',
100
+ attrs: {},
101
+ content: Buffer.from(subject, 'utf-8')
102
+ }
103
+ ]);
104
+ },
105
+ groupRequestParticipantsList: async (jid) => {
106
+ const result = await groupQuery(jid, 'get', [
107
+ {
108
+ tag: 'membership_approval_requests',
109
+ attrs: {}
110
+ }
111
+ ]);
112
+ const node = getBinaryNodeChild(result, 'membership_approval_requests');
113
+ const participants = getBinaryNodeChildren(node, 'membership_approval_request');
114
+ return participants.map(v => v.attrs);
115
+ },
116
+ groupRequestParticipantsUpdate: async (jid, participants, action) => {
117
+ const result = await groupQuery(jid, 'set', [
118
+ {
119
+ tag: 'membership_requests_action',
120
+ attrs: {},
121
+ content: [
122
+ {
123
+ tag: action,
124
+ attrs: {},
125
+ content: participants.map(jid => ({
126
+ tag: 'participant',
127
+ attrs: { jid }
128
+ }))
129
+ }
130
+ ]
131
+ }
132
+ ]);
133
+ const node = getBinaryNodeChild(result, 'membership_requests_action');
134
+ const nodeAction = getBinaryNodeChild(node, action);
135
+ const participantsAffected = getBinaryNodeChildren(nodeAction, 'participant');
136
+ return participantsAffected.map(p => {
137
+ return { status: p.attrs.error || '200', jid: p.attrs.jid };
138
+ });
139
+ },
140
+ groupParticipantsUpdate: async (jid, participants, action) => {
141
+ const result = await groupQuery(jid, 'set', [
142
+ {
143
+ tag: action,
144
+ attrs: {},
145
+ content: participants.map(jid => ({
146
+ tag: 'participant',
147
+ attrs: { jid }
148
+ }))
149
+ }
150
+ ]);
151
+ const node = getBinaryNodeChild(result, action);
152
+ const participantsAffected = getBinaryNodeChildren(node, 'participant');
153
+ return participantsAffected.map(p => {
154
+ return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p };
155
+ });
156
+ },
157
+ groupUpdateDescription: async (jid, description) => {
158
+ const metadata = await groupMetadata(jid);
159
+ const prev = metadata.descId ?? null;
160
+ await groupQuery(jid, 'set', [
161
+ {
162
+ tag: 'description',
163
+ attrs: {
164
+ ...(description ? { id: generateMessageIDV2() } : { delete: 'true' }),
165
+ ...(prev ? { prev } : {})
166
+ },
167
+ content: description ? [{ tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') }] : undefined
168
+ }
169
+ ]);
170
+ },
171
+ groupInviteCode: async (jid) => {
172
+ const result = await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }]);
173
+ const inviteNode = getBinaryNodeChild(result, 'invite');
174
+ return inviteNode?.attrs.code;
175
+ },
176
+ groupRevokeInvite: async (jid) => {
177
+ const result = await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }]);
178
+ const inviteNode = getBinaryNodeChild(result, 'invite');
179
+ return inviteNode?.attrs.code;
180
+ },
181
+ groupAcceptInvite: async (code) => {
182
+ const results = await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }]);
183
+ const result = getBinaryNodeChild(results, 'group');
184
+ return result?.attrs.jid;
185
+ },
186
+ /**
187
+ * revoke a v4 invite for someone
188
+ * @param groupJid group jid
189
+ * @param invitedJid jid of person you invited
190
+ * @returns true if successful
191
+ */
192
+ groupRevokeInviteV4: async (groupJid, invitedJid) => {
193
+ const result = await groupQuery(groupJid, 'set', [
194
+ { tag: 'revoke', attrs: {}, content: [{ tag: 'participant', attrs: { jid: invitedJid } }] }
195
+ ]);
196
+ return !!result;
197
+ },
198
+ /**
199
+ * accept a GroupInviteMessage
200
+ * @param key the key of the invite message, or optionally only provide the jid of the person who sent the invite
201
+ * @param inviteMessage the message to accept
202
+ */
203
+ groupAcceptInviteV4: ev.createBufferedFunction(async (key, inviteMessage) => {
204
+ key = typeof key === 'string' ? { remoteJid: key } : key;
205
+ const results = await groupQuery(inviteMessage.groupJid, 'set', [
206
+ {
207
+ tag: 'accept',
208
+ attrs: {
209
+ code: inviteMessage.inviteCode,
210
+ expiration: inviteMessage.inviteExpiration.toString(),
211
+ admin: key.remoteJid
212
+ }
213
+ }
214
+ ]);
215
+ // if we have the full message key
216
+ // update the invite message to be expired
217
+ if (key.id) {
218
+ // create new invite message that is expired
219
+ inviteMessage = proto.Message.GroupInviteMessage.fromObject(inviteMessage);
220
+ inviteMessage.inviteExpiration = 0;
221
+ inviteMessage.inviteCode = '';
222
+ ev.emit('messages.update', [
223
+ {
224
+ key,
225
+ update: {
226
+ message: {
227
+ groupInviteMessage: inviteMessage
228
+ }
229
+ }
230
+ }
231
+ ]);
232
+ }
233
+ // generate the group add message
234
+ await upsertMessage({
235
+ key: {
236
+ remoteJid: inviteMessage.groupJid,
237
+ id: generateMessageIDV2(sock.user?.id),
238
+ fromMe: false,
239
+ participant: key.remoteJid
240
+ },
241
+ messageStubType: WAMessageStubType.GROUP_PARTICIPANT_ADD,
242
+ messageStubParameters: [JSON.stringify(authState.creds.me)],
243
+ participant: key.remoteJid,
244
+ messageTimestamp: unixTimestampSeconds()
245
+ }, 'notify');
246
+ return results.attrs.from;
247
+ }),
248
+ groupGetInviteInfo: async (code) => {
249
+ const results = await groupQuery('@g.us', 'get', [{ tag: 'invite', attrs: { code } }]);
250
+ return extractGroupMetadata(results);
251
+ },
252
+ groupToggleEphemeral: async (jid, ephemeralExpiration) => {
253
+ const content = ephemeralExpiration
254
+ ? { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } }
255
+ : { tag: 'not_ephemeral', attrs: {} };
256
+ await groupQuery(jid, 'set', [content]);
257
+ },
258
+ groupSettingUpdate: async (jid, setting) => {
259
+ await groupQuery(jid, 'set', [{ tag: setting, attrs: {} }]);
260
+ },
261
+ groupMemberAddMode: async (jid, mode) => {
262
+ await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }]);
263
+ },
264
+ groupJoinApprovalMode: async (jid, mode) => {
265
+ await groupQuery(jid, 'set', [
266
+ { tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state: mode } }] }
267
+ ]);
268
+ },
269
+ groupFetchAllParticipating,
270
+ groupQuery
271
+ };
272
+ };
273
+ export const extractGroupMetadata = (result) => {
274
+ const group = getBinaryNodeChild(result, 'group');
275
+ const descChild = getBinaryNodeChild(group, 'description');
276
+ let desc;
277
+ let descId;
278
+ let descOwner;
279
+ let descOwnerPn;
280
+ let descTime;
281
+ if (descChild) {
282
+ desc = getBinaryNodeChildString(descChild, 'body');
283
+ descOwner = descChild.attrs.participant ? jidNormalizedUser(descChild.attrs.participant) : undefined;
284
+ descOwnerPn = descChild.attrs.participant_pn ? jidNormalizedUser(descChild.attrs.participant_pn) : undefined;
285
+ descTime = +descChild.attrs.t;
286
+ descId = descChild.attrs.id;
287
+ }
288
+ const groupId = group.attrs.id.includes('@') ? group.attrs.id : jidEncode(group.attrs.id, 'g.us');
289
+ const eph = getBinaryNodeChild(group, 'ephemeral')?.attrs.expiration;
290
+ const memberAddMode = getBinaryNodeChildString(group, 'member_add_mode') === 'all_member_add';
291
+ const metadata = {
292
+ id: groupId,
293
+ develop: "Eduh dev |</>🩵"
294
+ notify: group.attrs.notify,
295
+ addressingMode: group.attrs.addressing_mode === 'lid' ? WAMessageAddressingMode.LID : WAMessageAddressingMode.PN,
296
+ subject: group.attrs.subject,
297
+ subjectOwner: group.attrs.s_o,
298
+ subjectOwnerPn: group.attrs.s_o_pn,
299
+ subjectTime: +group.attrs.s_t,
300
+ size: group.attrs.size ? +group.attrs.size : getBinaryNodeChildren(group, 'participant').length,
301
+ creation: +group.attrs.creation,
302
+ owner: group.attrs.creator ? jidNormalizedUser(group.attrs.creator) : undefined,
303
+ ownerPn: group.attrs.creator_pn ? jidNormalizedUser(group.attrs.creator_pn) : undefined,
304
+ owner_country_code: group.attrs.creator_country_code,
305
+ desc,
306
+ descId,
307
+ descOwner,
308
+ descOwnerPn,
309
+ descTime,
310
+ linkedParent: getBinaryNodeChild(group, 'linked_parent')?.attrs.jid || undefined,
311
+ restrict: !!getBinaryNodeChild(group, 'locked'),
312
+ announce: !!getBinaryNodeChild(group, 'announcement'),
313
+ isCommunity: !!getBinaryNodeChild(group, 'parent'),
314
+ isCommunityAnnounce: !!getBinaryNodeChild(group, 'default_sub_group'),
315
+ joinApprovalMode: !!getBinaryNodeChild(group, 'membership_approval_mode'),
316
+ memberAddMode,
317
+ participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) => {
318
+ // TODO: Store LID MAPPINGS
319
+ return {
320
+ id: attrs.jid,
321
+ jid: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
322
+ lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined,
323
+ admin: (attrs.type || null)
324
+ };
325
+ }),
326
+ ephemeralDuration: eph ? +eph : undefined
327
+ };
328
+ return metadata;
329
+ };
@@ -251,7 +251,7 @@ export const makeMessagesRecvSocket = (config) => {
251
251
  };
252
252
  await query(stanza);
253
253
  };
254
- // Lia@Note 01-03-26 --- Source: https://github.com/koptereli/Baileys/commit/575cd41e6f01a9b3e1d7e2708c2292fa93de91f2
254
+ // Boruto@Note 01-03-26 --- Source: https://github.com/koptereli/Baileys/commit/575cd41e6f01a9b3e1d7e2708c2292fa93de91f2
255
255
  const initiateCall = async (jid, options = {}) => {
256
256
  const meId = authState.creds.me?.id;
257
257
  if (!meId) {
@@ -474,7 +474,7 @@ export const makeMessagesSocket = (config) => {
474
474
  });
475
475
  }
476
476
  await authState.keys.transaction(async () => {
477
- // Lia@Changes 02-02-26 --- Normalize message first to extract the original message and valid media type
477
+ // Boruto@Changes 02-02-26 --- Normalize message first to extract the original message and valid media type
478
478
  const innerMessage = normalizeMessageContent(message);
479
479
  const mediaType = getMediaType(innerMessage);
480
480
  if (mediaType) {
@@ -483,14 +483,14 @@ export const makeMessagesSocket = (config) => {
483
483
  if (isNewsletter) {
484
484
  const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
485
485
  const bytes = encodeNewsletterMessage(patched);
486
- // Lia@Changes 08-02-26 --- Add "additionalNodes" for newsletter too (⁠っ⁠˘̩⁠╭⁠╮⁠˘̩⁠)⁠っ
486
+ // Boruto@Changes 08-02-26 --- Add "additionalNodes" for newsletter too (⁠っ⁠˘̩⁠╭⁠╮⁠˘̩⁠)⁠っ
487
487
  if (additionalNodes && additionalNodes.length > 0) {
488
488
  ;
489
489
  binaryNodeContent.push(...additionalNodes);
490
490
  }
491
491
  binaryNodeContent.push({
492
492
  tag: 'plaintext',
493
- attrs: extraAttrs, // Lia@Changes 02-02-26 --- Add extraAttrs to fix media being rejected when sending to newsletter (⁠◠⁠‿⁠◕⁠)
493
+ attrs: extraAttrs, // Boruto@Changes 02-02-26 --- Add extraAttrs to fix media being rejected when sending to newsletter (⁠◠⁠‿⁠◕⁠)
494
494
  content: bytes
495
495
  });
496
496
  const stanza = {
@@ -507,7 +507,7 @@ export const makeMessagesSocket = (config) => {
507
507
  await sendNode(stanza);
508
508
  return;
509
509
  }
510
- // Lia@Changes 02-02-26 --- Add keepInChat, editedMessage, mediaNotifyMessage and pollUpdateMessage
510
+ // Boruto@Changes 02-02-26 --- Add keepInChat, editedMessage, mediaNotifyMessage and pollUpdateMessage
511
511
  const isNeedMetaAttrs = innerMessage?.pinInChatMessage || innerMessage?.keepInChatMessage || innerMessage?.reactionMessage
512
512
  if (isNeedMetaAttrs) {
513
513
  const metaAttrs = {};
@@ -524,7 +524,7 @@ export const makeMessagesSocket = (config) => {
524
524
  if (isNeedMetaAttrs || innerMessage?.protocolMessage?.editedMessage || innerMessage?.protocolMessage?.mediaNotifyMessage) {
525
525
  extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
526
526
  }
527
- // Lia@Changes 02-02-26 --- Add native_flow_name to extraAttrs when sending interactiveResponseMessage
527
+ // Boruto@Changes 02-02-26 --- Add native_flow_name to extraAttrs when sending interactiveResponseMessage
528
528
  if (innerMessage?.interactiveResponseMessage?.nativeFlowResponseMessage) {
529
529
  extraAttrs['native_flow_name'] = innerMessage.interactiveResponseMessage.nativeFlowResponseMessage.name;
530
530
  }
@@ -818,7 +818,7 @@ export const makeMessagesSocket = (config) => {
818
818
  alreadyHasBizNode = !addBizAttributes &&
819
819
  additionalNodes.some(node => node.tag === 'biz');
820
820
  }
821
- // Lia@Changes 30-01-26 --- Add Biz Binary Node to support button messages
821
+ // Boruto@Changes 30-01-26 --- Add Biz Binary Node to support button messages
822
822
  if ((!alreadyHasBizNode && shouldIncludeBizBinaryNode(innerMessage)) || addBizAttributes) {
823
823
  const bizNode = getBizBinaryNode(innerMessage, addBizAttributes);
824
824
  stanza.content.push(bizNode);
@@ -906,7 +906,7 @@ export const makeMessagesSocket = (config) => {
906
906
  else if (message.extendedTextMessage?.matchedText || message.groupInviteMessage) {
907
907
  return 'url';
908
908
  }
909
- // Lia@Note 02-02-26 --- Add more message type here
909
+ // Boruto@Note 02-02-26 --- Add more message type here
910
910
  else if ((message.extendedTextMessage?.text || message.conversation || '').includes('://wa.me/c/')) {
911
911
  return 'cataloglink';
912
912
  }
@@ -1013,10 +1013,10 @@ export const makeMessagesSocket = (config) => {
1013
1013
  ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
1014
1014
  return message;
1015
1015
  },
1016
- // Lia@Changes 30-01-26 --- Add support for modifying additionalNodes and additionalAttributes using "options" in sendMessage()
1016
+ // Boruto@Changes 30-01-26 --- Add support for modifying additionalNodes and additionalAttributes using "options" in sendMessage()
1017
1017
  sendMessage: async (jid, content, options = {}) => {
1018
1018
  const userJid = authState.creds.me.id;
1019
- // Lia@Changes 13-03-26 --- Add status mentions!
1019
+ // Boruto@Changes 13-03-26 --- Add status mentions!
1020
1020
  if (Array.isArray(jid)) {
1021
1021
  const { delayMs = 1500 } = options;
1022
1022
  const allUsers = new Set();
@@ -1177,7 +1177,7 @@ export const makeMessagesSocket = (config) => {
1177
1177
  additionalNodes.push({
1178
1178
  tag: 'meta',
1179
1179
  attrs: {
1180
- // Lia@Note 08-02-26 --- Still a hypothesis regarding PollResult ༎ຶ⁠‿⁠༎ຶ
1180
+ // Boruto@Note 08-02-26 --- Still a hypothesis regarding PollResult ༎ຶ⁠‿⁠༎ຶ
1181
1181
  polltype: isQuizMsg ? 'quiz_creation' : 'creation',
1182
1182
  contenttype: isPollMsg && isNewsletter ? 'text' : undefined
1183
1183
  },
@@ -1193,7 +1193,7 @@ export const makeMessagesSocket = (config) => {
1193
1193
  content: undefined
1194
1194
  });
1195
1195
  }
1196
- // Lia@Changes 30-01-26 --- Add support for AI label in message when "ai" is true, but works only in private chat
1196
+ // Boruto@Changes 30-01-26 --- Add support for AI label in message when "ai" is true, but works only in private chat
1197
1197
  else if (isAiMsg) {
1198
1198
  if (!(isPnUser(jid) || isLidUser(jid))) {
1199
1199
  throw new Boom('AI icon on message are only allowed in private chat', { statusCode: 400 });
@@ -1223,8 +1223,8 @@ export const makeMessagesSocket = (config) => {
1223
1223
  await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
1224
1224
  });
1225
1225
  }
1226
- // Lia@Changes 31-01-26 --- Add support for album messages
1227
- // Lia@Note 06-02-26 --- Refactored to reduce high RSS usage (⁠╥⁠﹏⁠╥⁠)
1226
+ // Boruto@Changes 31-01-26 --- Add support for album messages
1227
+ // Boruto@Note 06-02-26 --- Refactored to reduce high RSS usage (⁠╥⁠﹏⁠╥⁠)
1228
1228
  if ('album' in content) {
1229
1229
  const { delayMs = 1500 } = options;
1230
1230
  for (const albumMedia of content.album) {