@prototypevip/baileys 0.1.1 → 0.1.2

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.
@@ -0,0 +1,475 @@
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 {
5
+ getBinaryNodeChild,
6
+ getBinaryNodeChildren,
7
+ getBinaryNodeChildString,
8
+ isLidUser,
9
+ isPnUser,
10
+ jidEncode,
11
+ jidNormalizedUser,
12
+ } from "../WABinary/index.js";
13
+ import { makeChatsSocket } from "./chats.js";
14
+ import { groupMetadataCache as defaultCache } from "../Store/cache-factory.js";
15
+
16
+ export const makeGroupsSocket = (config) => {
17
+ const cache = config.groupMetadataCache || defaultCache;
18
+
19
+ const sock = makeChatsSocket(config);
20
+ const { authState, ev, query, upsertMessage } = sock;
21
+ const groupQuery = async (jid, type, content) =>
22
+ query({
23
+ tag: "iq",
24
+ attrs: { type: type, xmlns: "w:g2", to: jid },
25
+ content: content,
26
+ });
27
+ const groupMetadata = async (jid, useCache = true) => {
28
+ if (useCache) {
29
+ const cached = cache.get(jid) || config.store?.groups[jid];
30
+ if (cached && Array.isArray(cached.participants)) {
31
+ return cached;
32
+ }
33
+ }
34
+ const result = await groupQuery(jid, "get", [
35
+ { tag: "query", attrs: { request: "interactive" } },
36
+ ]);
37
+ const metadata = extractGroupMetadata(result);
38
+ cache.set(jid, metadata);
39
+ if (config.store && config.store.groups) {
40
+ config.store.groups[jid] = metadata;
41
+ }
42
+ return metadata;
43
+ };
44
+ const groupFetchAllParticipating = async () => {
45
+ const result = await query({
46
+ tag: "iq",
47
+ attrs: { to: "@g.us", xmlns: "w:g2", type: "get" },
48
+ content: [
49
+ {
50
+ tag: "participating",
51
+ attrs: {},
52
+ content: [
53
+ { tag: "participants", attrs: {} },
54
+ { tag: "description", attrs: {} },
55
+ ],
56
+ },
57
+ ],
58
+ });
59
+ const data = Object.create(null);
60
+ const groupsChild = getBinaryNodeChild(result, "groups");
61
+ if (groupsChild) {
62
+ const groups = getBinaryNodeChildren(groupsChild, "group");
63
+ for (const groupNode of groups) {
64
+ const meta = extractGroupMetadata({
65
+ tag: "result",
66
+ attrs: {},
67
+ content: [groupNode],
68
+ });
69
+ data[meta.id] = meta;
70
+ cache.set(meta.id, meta);
71
+ if (config.store && config.store.groups) {
72
+ config.store.groups[meta.id] = meta;
73
+ }
74
+ const lidMappings = meta.participants
75
+ .filter((p) => p.lid && p.pn)
76
+ .map((p) => ({ lid: p.lid, pn: p.pn }));
77
+ if (lidMappings.length > 0) {
78
+ await sock.signalRepository.lidMapping.storeLIDPNMappings(
79
+ lidMappings,
80
+ );
81
+ }
82
+ }
83
+ }
84
+ sock.ev.emit("groups.update", Object.values(data));
85
+ return data;
86
+ };
87
+ sock.ws.on("CB:ib,,dirty", async (node) => {
88
+ const { attrs } = getBinaryNodeChild(node, "dirty");
89
+ if (attrs.type !== "groups") {
90
+ return;
91
+ }
92
+ await groupFetchAllParticipating();
93
+ await sock.cleanDirtyBits("groups");
94
+ });
95
+ return {
96
+ ...sock,
97
+ extractGroupMetadata: extractGroupMetadata,
98
+ groupMetadata: groupMetadata,
99
+ groupCreate: async (subject, participants) => {
100
+ const key = generateMessageIDV2();
101
+ const result = await groupQuery("@g.us", "set", [
102
+ {
103
+ tag: "create",
104
+ attrs: { subject: subject, key: key },
105
+ content: participants.map((jid) => ({
106
+ tag: "participant",
107
+ attrs: { jid: jid },
108
+ })),
109
+ },
110
+ ]);
111
+ return extractGroupMetadata(result);
112
+ },
113
+ groupLeave: async (id) => {
114
+ await groupQuery("@g.us", "set", [
115
+ {
116
+ tag: "leave",
117
+ attrs: {},
118
+ content: [{ tag: "group", attrs: { id: id } }],
119
+ },
120
+ ]);
121
+ },
122
+ groupUpdateSubject: async (jid, subject) => {
123
+ await groupQuery(jid, "set", [
124
+ {
125
+ tag: "subject",
126
+ attrs: {},
127
+ content: Buffer.from(subject, "utf-8"),
128
+ },
129
+ ]);
130
+ cache.del(jid);
131
+ if (config.store && config.store.groups) {
132
+ delete config.store.groups[jid];
133
+ }
134
+ },
135
+ groupRequestParticipantsList: async (jid) => {
136
+ const result = await groupQuery(jid, "get", [
137
+ { tag: "membership_approval_requests", attrs: {} },
138
+ ]);
139
+ const node = getBinaryNodeChild(result, "membership_approval_requests");
140
+ const participants = getBinaryNodeChildren(
141
+ node,
142
+ "membership_approval_request",
143
+ );
144
+ return participants.map((v) => v.attrs);
145
+ },
146
+ groupRequestParticipantsUpdate: async (jid, participants, action) => {
147
+ const result = await groupQuery(jid, "set", [
148
+ {
149
+ tag: "membership_requests_action",
150
+ attrs: {},
151
+ content: [
152
+ {
153
+ tag: action,
154
+ attrs: {},
155
+ content: participants.map((jid) => ({
156
+ tag: "participant",
157
+ attrs: { jid: jid },
158
+ })),
159
+ },
160
+ ],
161
+ },
162
+ ]);
163
+ const node = getBinaryNodeChild(result, "membership_requests_action");
164
+ const nodeAction = getBinaryNodeChild(node, action);
165
+ const participantsAffected = getBinaryNodeChildren(
166
+ nodeAction,
167
+ "participant",
168
+ );
169
+ return participantsAffected.map((p) => {
170
+ return { status: p.attrs.error || "200", jid: p.attrs.jid };
171
+ });
172
+ },
173
+ groupParticipantsUpdate: async (jid, participants, action) => {
174
+ // PN-First API: Translate PN to LID only if the group's addressingMode requires it
175
+ const metadata = await groupMetadata(jid);
176
+ if (
177
+ metadata &&
178
+ metadata.addressingMode === "lid" &&
179
+ sock.signalRepository &&
180
+ sock.signalRepository.lidMapping
181
+ ) {
182
+ const resolvedParticipants = [];
183
+ for (const p of participants) {
184
+ if (p.includes("@s.whatsapp.net")) {
185
+ try {
186
+ let lid = await sock.signalRepository.lidMapping.getLIDForPN(p);
187
+ if (!lid && sock.onWhatsApp) {
188
+ await sock.onWhatsApp(p);
189
+ lid = await sock.signalRepository.lidMapping.getLIDForPN(p);
190
+ }
191
+ resolvedParticipants.push(lid || p);
192
+ } catch (e) {
193
+ resolvedParticipants.push(p);
194
+ }
195
+ } else {
196
+ resolvedParticipants.push(p);
197
+ }
198
+ }
199
+ participants = resolvedParticipants;
200
+ }
201
+
202
+ const result = await groupQuery(jid, "set", [
203
+ {
204
+ tag: action,
205
+ attrs: {},
206
+ content: participants.map((jid) => ({
207
+ tag: "participant",
208
+ attrs: { jid: jid },
209
+ })),
210
+ },
211
+ ]);
212
+ const node = getBinaryNodeChild(result, action);
213
+ const participantsAffected = getBinaryNodeChildren(node, "participant");
214
+ return participantsAffected.map((p) => {
215
+ return {
216
+ status: p.attrs.error || "200",
217
+ jid: p.attrs.jid,
218
+ content: p,
219
+ };
220
+ });
221
+ },
222
+ groupUpdateDescription: async (jid, description) => {
223
+ const metadata = await groupMetadata(jid);
224
+ const prev = metadata.descId ?? null;
225
+ await groupQuery(jid, "set", [
226
+ {
227
+ tag: "description",
228
+ attrs: {
229
+ ...(description
230
+ ? { id: generateMessageIDV2() }
231
+ : { delete: "true" }),
232
+ ...(prev ? { prev: prev } : {}),
233
+ },
234
+ content: description
235
+ ? [
236
+ {
237
+ tag: "body",
238
+ attrs: {},
239
+ content: Buffer.from(description, "utf-8"),
240
+ },
241
+ ]
242
+ : undefined,
243
+ },
244
+ ]);
245
+ cache.del(jid);
246
+ if (config.store && config.store.groups) {
247
+ delete config.store.groups[jid];
248
+ }
249
+ },
250
+ groupInviteCode: async (jid) => {
251
+ const result = await groupQuery(jid, "get", [
252
+ { tag: "invite", attrs: {} },
253
+ ]);
254
+ const inviteNode = getBinaryNodeChild(result, "invite");
255
+ return inviteNode?.attrs.code;
256
+ },
257
+ groupRevokeInvite: async (jid) => {
258
+ const result = await groupQuery(jid, "set", [
259
+ { tag: "invite", attrs: {} },
260
+ ]);
261
+ const inviteNode = getBinaryNodeChild(result, "invite");
262
+ return inviteNode?.attrs.code;
263
+ },
264
+ groupAcceptInvite: async (code) => {
265
+ const results = await groupQuery("@g.us", "set", [
266
+ { tag: "invite", attrs: { code: code } },
267
+ ]);
268
+ const result = getBinaryNodeChild(results, "group");
269
+ return result?.attrs.jid;
270
+ },
271
+ /**
272
+ * revoke a v4 invite for someone
273
+ * @param groupJid group jid
274
+ * @param invitedJid jid of person you invited
275
+ * @returns true if successful
276
+ */
277
+ groupRevokeInviteV4: async (groupJid, invitedJid) => {
278
+ const result = await groupQuery(groupJid, "set", [
279
+ {
280
+ tag: "revoke",
281
+ attrs: {},
282
+ content: [{ tag: "participant", attrs: { jid: invitedJid } }],
283
+ },
284
+ ]);
285
+ return !!result;
286
+ },
287
+ /**
288
+ * accept a GroupInviteMessage
289
+ * @param key the key of the invite message, or optionally only provide the jid of the person who sent the invite
290
+ * @param inviteMessage the message to accept
291
+ */
292
+ groupAcceptInviteV4: ev.createBufferedFunction(
293
+ async (key, inviteMessage) => {
294
+ key = typeof key === "string" ? { remoteJid: key } : key;
295
+ const results = await groupQuery(inviteMessage.groupJid, "set", [
296
+ {
297
+ tag: "accept",
298
+ attrs: {
299
+ code: inviteMessage.inviteCode,
300
+ expiration: inviteMessage.inviteExpiration.toString(),
301
+ admin: key.remoteJid,
302
+ },
303
+ },
304
+ ]);
305
+ // if we have the full message key
306
+ // update the invite message to be expired
307
+ if (key.id) {
308
+ // create new invite message that is expired
309
+ inviteMessage =
310
+ proto.Message.GroupInviteMessage.fromObject(inviteMessage);
311
+ inviteMessage.inviteExpiration = 0;
312
+ inviteMessage.inviteCode = "";
313
+ ev.emit("messages.update", [
314
+ {
315
+ key: key,
316
+ update: {
317
+ message: { groupInviteMessage: inviteMessage },
318
+ },
319
+ },
320
+ ]);
321
+ }
322
+ // generate the group add message
323
+ await upsertMessage(
324
+ {
325
+ key: {
326
+ remoteJid: inviteMessage.groupJid,
327
+ id: generateMessageIDV2(sock.user?.id),
328
+ fromMe: false,
329
+ participant: key.remoteJid,
330
+ },
331
+ messageStubType: WAMessageStubType.GROUP_PARTICIPANT_ADD,
332
+ messageStubParameters: [JSON.stringify(authState.creds.me)],
333
+ participant: key.remoteJid,
334
+ messageTimestamp: unixTimestampSeconds(),
335
+ },
336
+ "notify",
337
+ );
338
+ return results.attrs.from;
339
+ },
340
+ ),
341
+ groupGetInviteInfo: async (code) => {
342
+ const results = await groupQuery("@g.us", "get", [
343
+ { tag: "invite", attrs: { code: code } },
344
+ ]);
345
+ return extractGroupMetadata(results);
346
+ },
347
+ groupToggleEphemeral: async (jid, ephemeralExpiration) => {
348
+ const content = ephemeralExpiration
349
+ ? {
350
+ tag: "ephemeral",
351
+ attrs: { expiration: ephemeralExpiration.toString() },
352
+ }
353
+ : { tag: "not_ephemeral", attrs: {} };
354
+ await groupQuery(jid, "set", [content]);
355
+ },
356
+ groupSettingUpdate: async (jid, setting) => {
357
+ await groupQuery(jid, "set", [{ tag: setting, attrs: {} }]);
358
+ },
359
+ groupMemberAddMode: async (jid, mode) => {
360
+ await groupQuery(jid, "set", [
361
+ { tag: "member_add_mode", attrs: {}, content: mode },
362
+ ]);
363
+ },
364
+ groupJoinApprovalMode: async (jid, mode) => {
365
+ await groupQuery(jid, "set", [
366
+ {
367
+ tag: "membership_approval_mode",
368
+ attrs: {},
369
+ content: [{ tag: "group_join", attrs: { state: mode } }],
370
+ },
371
+ ]);
372
+ cache.del(jid);
373
+ if (config.store && config.store.groups) {
374
+ delete config.store.groups[jid];
375
+ }
376
+ },
377
+ groupFetchAllParticipating: groupFetchAllParticipating,
378
+ groupQuery: groupQuery,
379
+ };
380
+ };
381
+ export const extractGroupMetadata = (result) => {
382
+ const group = getBinaryNodeChild(result, "group");
383
+ const descChild = getBinaryNodeChild(group, "description");
384
+ let desc;
385
+ let descId;
386
+ let descOwner;
387
+ let descOwnerPn;
388
+ let descTime;
389
+ if (descChild) {
390
+ desc = getBinaryNodeChildString(descChild, "body");
391
+ descOwner = descChild.attrs.participant
392
+ ? jidNormalizedUser(descChild.attrs.participant)
393
+ : undefined;
394
+ descOwnerPn = descChild.attrs.participant_pn
395
+ ? jidNormalizedUser(descChild.attrs.participant_pn)
396
+ : undefined;
397
+ descTime = +descChild.attrs.t;
398
+ descId = descChild.attrs.id;
399
+ }
400
+ const groupId = group.attrs.id.includes("@")
401
+ ? group.attrs.id
402
+ : jidEncode(group.attrs.id, "g.us");
403
+ const eph = getBinaryNodeChild(group, "ephemeral")?.attrs.expiration;
404
+ const memberAddMode =
405
+ getBinaryNodeChildString(group, "member_add_mode") === "all_member_add";
406
+ const metadata = {
407
+ id: groupId,
408
+ notify: group.attrs.notify,
409
+ addressingMode:
410
+ group.attrs.addressing_mode === "lid"
411
+ ? WAMessageAddressingMode.LID
412
+ : WAMessageAddressingMode.PN,
413
+ subject: group.attrs.subject,
414
+ subjectOwner: group.attrs.s_o,
415
+ subjectOwnerPn: group.attrs.s_o_pn,
416
+ subjectTime: +group.attrs.s_t,
417
+ size: group.attrs.size
418
+ ? +group.attrs.size
419
+ : getBinaryNodeChildren(group, "participant").length,
420
+ creation: +group.attrs.creation,
421
+ owner: group.attrs.creator
422
+ ? jidNormalizedUser(group.attrs.creator)
423
+ : undefined,
424
+ ownerPn: group.attrs.creator_pn
425
+ ? jidNormalizedUser(group.attrs.creator_pn)
426
+ : undefined,
427
+ owner_country_code: group.attrs.creator_country_code,
428
+ desc: desc,
429
+ descId: descId,
430
+ descOwner: descOwner,
431
+ descOwnerPn: descOwnerPn,
432
+ descTime: descTime,
433
+ linkedParent:
434
+ getBinaryNodeChild(group, "linked_parent")?.attrs.jid || undefined,
435
+ restrict: !!getBinaryNodeChild(group, "locked"),
436
+ announce: !!getBinaryNodeChild(group, "announcement"),
437
+ isCommunity: !!getBinaryNodeChild(group, "parent"),
438
+ isCommunityAnnounce: !!getBinaryNodeChild(group, "default_sub_group"),
439
+ joinApprovalMode: !!getBinaryNodeChild(group, "membership_approval_mode"),
440
+ memberAddMode: memberAddMode,
441
+ participants: getBinaryNodeChildren(group, "participant").map(
442
+ ({ attrs }) => {
443
+ // مهم: الـ id هنا لازم يفضل زي ما السيرفر بعته (attrs.jid) بالظبط,
444
+ // من غير ما نلمسه أو نبدله بـ lid/phone بديل. السبب: القيمة دي هي
445
+ // اللي بتتبعت زي ما هي في participantsList لـ getUSyncDevices وفي
446
+ // الـ addressing_mode بتاع الرسالة الصادرة (messages-send.js) —
447
+ // فلو الجروب addressingMode="pn" لازم كل الـ ids تكون بصيغة PN,
448
+ // ولو "lid" لازم تكون كلها LID. أي تبديل هنا بيسبب mismatch بين
449
+ // هوية المشارك والـ addressing_mode المعلن، وده اللي كان بيطلع
450
+ // "بيشفر"/Waiting for this message لمشاركين الـ username بالذات —
451
+ // مش مشكلة سيشن عشان كده افتكاك السيشن وإعادة الدخول ما كانتش بتحل حاجة.
452
+ // عرض الرقم/اليوزرنيم للمستخدم (لو الرقم مخفي) اتحل بالفعل في مكان
453
+ // تاني (resolveDisplayIdentity) وده المكان الصح ليه، مش هنا.
454
+ const id = attrs.jid;
455
+ return {
456
+ id,
457
+ // jid هنا نفس قيمة id بالظبط (مش قيمة تانية زي الكود القديم) —
458
+ // مُبقّاها بس عشان بعض أوامر البوت (كتم.js, مجتمع.js, muteSystem.js,
459
+ // context/group.js) بتقرا p.jid كـ fallback؛ ما بتأثرش على
460
+ // participantsList/addressing_mode لأنها زي id بالظبط دلوقتي
461
+ jid: id,
462
+ phoneNumber:
463
+ isLidUser(id) && isPnUser(attrs.phone_number)
464
+ ? attrs.phone_number
465
+ : undefined,
466
+ lid: isPnUser(id) && isLidUser(attrs.lid) ? attrs.lid : undefined,
467
+ username: attrs.participant_username || attrs.username || undefined,
468
+ admin: attrs.type || null,
469
+ };
470
+ },
471
+ ),
472
+ ephemeralDuration: eph ? +eph : undefined,
473
+ };
474
+ return metadata;
475
+ };
@@ -1,11 +1,27 @@
1
1
  import { DEFAULT_CONNECTION_CONFIG } from "../Defaults/index.js";
2
2
  import { makeCommunitiesSocket } from "./communities.js";
3
+ import { stampSocket } from "../Utils/socket-guard.js";
4
+ import { verifyBrandIntegrity } from "../Utils/integrity-guard.js";
3
5
 
4
6
  /**
5
7
  * Create a WhatsApp socket.
6
8
  * Clean version — without AntiBan.
7
9
  */
8
10
  const makeWASocket = (config = {}) => {
11
+ // بصمة "prototype" بتتفحص هنا تلقائي — قبل حتى ما أي سوكت يتبني، مش
12
+ // محتاجه استدعاء يدوي من البوت (نفس فلسفة stampSocket تحت). لو حد فَكّ
13
+ // اسم الباكدج أو غيّر بايتات البصمة يدوي، المكتبه بترفض تشتغل خالص.
14
+ if (!verifyBrandIntegrity()) {
15
+ try {
16
+ console.error("[INTEGRITY-GUARD] brand fingerprint mismatch — refusing to start.");
17
+ } catch {}
18
+ setTimeout(() => {
19
+ try {
20
+ process.exit(1);
21
+ } catch {}
22
+ }, 500);
23
+ }
24
+
9
25
  const restConfig = { ...(config || {}) };
10
26
 
11
27
  // strip any leftover antiBan keys if present
@@ -16,6 +32,16 @@ const makeWASocket = (config = {}) => {
16
32
 
17
33
  const newConfig = { ...DEFAULT_CONNECTION_CONFIG, ...restConfig };
18
34
 
35
+ // ملحوظه مهمه: `Utils/generics.js` (ودوال تانيه زيها) بتستورد
36
+ // DEFAULT_CONNECTION_CONFIG مباشره كـ `config` وبتقرا منها وقت التشغيل
37
+ // (مش الـ newConfig المدموج فوق)، فأي override زي generateMessageID/
38
+ // generateMessageIDV2 بيتحط هنا كان بيتضاع تماما - الكود الداخلي في
39
+ // المكتبه (زي توليد id الأزرار) كان بيفضل يستخدم القيم الافتراضيه
40
+ // الأصليه (GIN4B0T/G1N4B0T) حتى لو المستخدم غيّرها في makeWASocket().
41
+ // بنعمل mutate للـ object المشترك نفسه عشان أي import ثابت ليه في باقي
42
+ // المكتبه ياخد نفس القيم المدموجه.
43
+ Object.assign(DEFAULT_CONNECTION_CONFIG, newConfig);
44
+
19
45
  let sock;
20
46
  const originalGetMessage = newConfig.getMessage;
21
47
  if (typeof originalGetMessage === "function") {
@@ -25,6 +51,12 @@ const makeWASocket = (config = {}) => {
25
51
  }
26
52
 
27
53
  sock = makeCommunitiesSocket(newConfig);
54
+
55
+ // ختم السوكت تلقائي هنا — قبل كده كان لازم البوت ينادي stampSocket()
56
+ // يدوي بعد ما السوكت يترجع (وده كان سهل يتنسى في ملف 2300+ سطر زي
57
+ // patch.js)، دلوقتي أي سوكت طالع من makeWASocket() بيتختم لوحده.
58
+ stampSocket(sock);
59
+
28
60
  return sock;
29
61
  };
30
62
 
@@ -35,4 +67,4 @@ const wrapSocketWithFingerprint = (makeSock, opts) =>
35
67
  const PRESETS = {};
36
68
 
37
69
  export default makeWASocket;
38
- export { makeWASocket, wrapSocket, wrapSocketWithFingerprint, PRESETS };
70
+ export { makeWASocket, wrapSocket, wrapSocketWithFingerprint, PRESETS };
@@ -0,0 +1,38 @@
1
+ import { DEFAULT_CONNECTION_CONFIG } from "../Defaults/index.js";
2
+ import { makeCommunitiesSocket } from "./communities.js";
3
+
4
+ /**
5
+ * Create a WhatsApp socket.
6
+ * Clean version — without AntiBan.
7
+ */
8
+ const makeWASocket = (config = {}) => {
9
+ const restConfig = { ...(config || {}) };
10
+
11
+ // strip any leftover antiBan keys if present
12
+ delete restConfig.antiBan;
13
+ delete restConfig.antiBanWarmUpState;
14
+ delete restConfig.antiBanWrapOptions;
15
+ delete restConfig.userDevicesCache;
16
+
17
+ const newConfig = { ...DEFAULT_CONNECTION_CONFIG, ...restConfig };
18
+
19
+ let sock;
20
+ const originalGetMessage = newConfig.getMessage;
21
+ if (typeof originalGetMessage === "function") {
22
+ newConfig.getMessage = async function (key) {
23
+ return originalGetMessage.call(sock || this, key);
24
+ };
25
+ }
26
+
27
+ sock = makeCommunitiesSocket(newConfig);
28
+ return sock;
29
+ };
30
+
31
+ /** Stubs kept for API compatibility (no-op without AntiBan) */
32
+ const wrapSocket = (sock) => sock;
33
+ const wrapSocketWithFingerprint = (makeSock, opts) =>
34
+ typeof makeSock === "function" ? makeSock(opts || {}) : makeSock;
35
+ const PRESETS = {};
36
+
37
+ export default makeWASocket;
38
+ export { makeWASocket, wrapSocket, wrapSocketWithFingerprint, PRESETS };