rixleys 1.0.0

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 (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.MD +2969 -0
  3. package/WAProto/GenerateStatics.sh +4 -0
  4. package/WAProto/WAProto.proto +5479 -0
  5. package/WAProto/index.js +97692 -0
  6. package/WAProto/p.html +1 -0
  7. package/engine-requirements.js +10 -0
  8. package/lib/Defaults/index.js +120 -0
  9. package/lib/Defaults/rixleys-version.json +3 -0
  10. package/lib/Signal/Group/ciphertext-message.js +15 -0
  11. package/lib/Signal/Group/group-session-builder.js +64 -0
  12. package/lib/Signal/Group/group_cipher.js +96 -0
  13. package/lib/Signal/Group/index.js +57 -0
  14. package/lib/Signal/Group/keyhelper.js +55 -0
  15. package/lib/Signal/Group/queue-job.js +57 -0
  16. package/lib/Signal/Group/sender-chain-key.js +34 -0
  17. package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
  18. package/lib/Signal/Group/sender-key-message.js +69 -0
  19. package/lib/Signal/Group/sender-key-name.js +51 -0
  20. package/lib/Signal/Group/sender-key-record.js +53 -0
  21. package/lib/Signal/Group/sender-key-state.js +99 -0
  22. package/lib/Signal/Group/sender-message-key.js +29 -0
  23. package/lib/Signal/core/.eslintrc.json +31 -0
  24. package/lib/Signal/core/CODE_OF_CONDUCT.md +102 -0
  25. package/lib/Signal/core/LICENSE +621 -0
  26. package/lib/Signal/core/README.md +64 -0
  27. package/lib/Signal/core/SECURITY.md +78 -0
  28. package/lib/Signal/core/generate-proto.sh +1 -0
  29. package/lib/Signal/core/index.d.ts +55 -0
  30. package/lib/Signal/core/index.js +10 -0
  31. package/lib/Signal/core/protos/WhisperTextProtocol.proto +28 -0
  32. package/lib/Signal/core/src/.eslintrc.json +31 -0
  33. package/lib/Signal/core/src/WhisperTextProtocol.js +933 -0
  34. package/lib/Signal/core/src/base_key_type.js +7 -0
  35. package/lib/Signal/core/src/chain_type.js +6 -0
  36. package/lib/Signal/core/src/crypto.d.ts +19 -0
  37. package/lib/Signal/core/src/crypto.js +98 -0
  38. package/lib/Signal/core/src/curve.d.ts +22 -0
  39. package/lib/Signal/core/src/curve.js +142 -0
  40. package/lib/Signal/core/src/errors.js +33 -0
  41. package/lib/Signal/core/src/keyhelper.js +45 -0
  42. package/lib/Signal/core/src/numeric_fingerprint.js +72 -0
  43. package/lib/Signal/core/src/protobufs.js +10 -0
  44. package/lib/Signal/core/src/protocol_address.js +40 -0
  45. package/lib/Signal/core/src/queue_job.js +69 -0
  46. package/lib/Signal/core/src/session_builder.js +164 -0
  47. package/lib/Signal/core/src/session_cipher.js +336 -0
  48. package/lib/Signal/core/src/session_record.js +316 -0
  49. package/lib/Signal/libsignal.js +184 -0
  50. package/lib/Socket/Client/index.js +18 -0
  51. package/lib/Socket/Client/types.js +13 -0
  52. package/lib/Socket/Client/websocket.js +72 -0
  53. package/lib/Socket/business.js +260 -0
  54. package/lib/Socket/chats.js +997 -0
  55. package/lib/Socket/groups.js +418 -0
  56. package/lib/Socket/index.js +238 -0
  57. package/lib/Socket/messages-recv.js +1106 -0
  58. package/lib/Socket/messages-send.js +882 -0
  59. package/lib/Socket/newsletter.js +250 -0
  60. package/lib/Socket/socket.js +646 -0
  61. package/lib/Socket/usync.js +70 -0
  62. package/lib/Store/index.js +8 -0
  63. package/lib/Store/make-in-memory-store.js +439 -0
  64. package/lib/Store/make-ordered-dictionary.js +81 -0
  65. package/lib/Store/object-repository.js +27 -0
  66. package/lib/Types/Auth.js +2 -0
  67. package/lib/Types/Call.js +2 -0
  68. package/lib/Types/Chat.js +4 -0
  69. package/lib/Types/Contact.js +2 -0
  70. package/lib/Types/Events.js +2 -0
  71. package/lib/Types/GroupMetadata.js +2 -0
  72. package/lib/Types/Label.js +27 -0
  73. package/lib/Types/LabelAssociation.js +9 -0
  74. package/lib/Types/Message.js +7 -0
  75. package/lib/Types/Newsletter.js +18 -0
  76. package/lib/Types/Product.js +2 -0
  77. package/lib/Types/Signal.js +2 -0
  78. package/lib/Types/Socket.js +2 -0
  79. package/lib/Types/State.js +2 -0
  80. package/lib/Types/USync.js +2 -0
  81. package/lib/Types/index.js +42 -0
  82. package/lib/Utils/auth-utils.js +199 -0
  83. package/lib/Utils/browser-utils.js +35 -0
  84. package/lib/Utils/business.js +234 -0
  85. package/lib/Utils/chat-utils.js +730 -0
  86. package/lib/Utils/crypto.js +193 -0
  87. package/lib/Utils/decode-wa-message.js +217 -0
  88. package/lib/Utils/event-buffer.js +518 -0
  89. package/lib/Utils/generics.js +467 -0
  90. package/lib/Utils/history.js +94 -0
  91. package/lib/Utils/index.js +36 -0
  92. package/lib/Utils/link-preview.js +151 -0
  93. package/lib/Utils/logger.js +7 -0
  94. package/lib/Utils/lt-hash.js +51 -0
  95. package/lib/Utils/make-mutex.js +43 -0
  96. package/lib/Utils/message-retry-manager.js +185 -0
  97. package/lib/Utils/messages-media.js +879 -0
  98. package/lib/Utils/messages.js +1049 -0
  99. package/lib/Utils/noise-handler.js +150 -0
  100. package/lib/Utils/process-message.js +404 -0
  101. package/lib/Utils/rixleys-event-stream.js +63 -0
  102. package/lib/Utils/serializer.js +238 -0
  103. package/lib/Utils/signal.js +153 -0
  104. package/lib/Utils/use-multi-file-auth-state.js +124 -0
  105. package/lib/Utils/validate-connection.js +229 -0
  106. package/lib/WABinary/constants.js +1303 -0
  107. package/lib/WABinary/decode.js +265 -0
  108. package/lib/WABinary/encode.js +250 -0
  109. package/lib/WABinary/generic-utils.js +110 -0
  110. package/lib/WABinary/index.js +21 -0
  111. package/lib/WABinary/jid-utils.js +85 -0
  112. package/lib/WABinary/types.js +2 -0
  113. package/lib/WAM/BinaryInfo.js +13 -0
  114. package/lib/WAM/constants.js +15350 -0
  115. package/lib/WAM/encode.js +155 -0
  116. package/lib/WAM/index.js +19 -0
  117. package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
  118. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
  119. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
  120. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
  121. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
  122. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  123. package/lib/WAUSync/Protocols/index.js +20 -0
  124. package/lib/WAUSync/USyncQuery.js +89 -0
  125. package/lib/WAUSync/USyncUser.js +26 -0
  126. package/lib/WAUSync/index.js +19 -0
  127. package/lib/index.js +54 -0
  128. package/package.json +113 -0
@@ -0,0 +1,418 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractGroupMetadata = exports.makeGroupsSocket = void 0;
4
+ const WAProto_1 = require("../../WAProto");
5
+ const Types_1 = require("../Types");
6
+ const Utils_1 = require("../Utils");
7
+ const WABinary_1 = require("../WABinary");
8
+ const chats_1 = require("./chats");
9
+ const makeGroupsSocket = (config) => {
10
+ const sock = (0, chats_1.makeChatsSocket)(config);
11
+ const { authState, ev, query, upsertMessage } = sock;
12
+ const groupQuery = async (jid, type, content) => (query({
13
+ tag: 'iq',
14
+ attrs: {
15
+ type,
16
+ xmlns: 'w:g2',
17
+ to: jid,
18
+ },
19
+ content
20
+ }));
21
+ const groupMetadata = async (jid) => {
22
+ const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }]);
23
+ return (0, exports.extractGroupMetadata)(result);
24
+ };
25
+ const groupFetchAllParticipating = async () => {
26
+ const result = await query({
27
+ tag: 'iq',
28
+ attrs: {
29
+ to: '@g.us',
30
+ xmlns: 'w:g2',
31
+ type: 'get',
32
+ },
33
+ content: [
34
+ {
35
+ tag: 'participating',
36
+ attrs: {},
37
+ content: [
38
+ { tag: 'participants', attrs: {} },
39
+ { tag: 'description', attrs: {} }
40
+ ]
41
+ }
42
+ ]
43
+ });
44
+ const data = {};
45
+ const groupsChild = (0, WABinary_1.getBinaryNodeChild)(result, 'groups');
46
+ if (groupsChild) {
47
+ const groups = (0, WABinary_1.getBinaryNodeChildren)(groupsChild, 'group');
48
+ for (const groupNode of groups) {
49
+ const meta = (0, exports.extractGroupMetadata)({
50
+ tag: 'result',
51
+ attrs: {},
52
+ content: [groupNode]
53
+ });
54
+ data[meta.id] = meta;
55
+ }
56
+ }
57
+ sock.ev.emit('groups.update', Object.values(data));
58
+ return data;
59
+ };
60
+ sock.ws.on('CB:ib,,dirty', async (node) => {
61
+ const { attrs } = (0, WABinary_1.getBinaryNodeChild)(node, 'dirty');
62
+ if (attrs.type !== 'groups') {
63
+ return;
64
+ }
65
+ await groupFetchAllParticipating();
66
+ await sock.cleanDirtyBits('groups');
67
+ });
68
+ return {
69
+ ...sock,
70
+ groupQuery,
71
+ groupMetadata,
72
+ groupCreate: async (subject, participants) => {
73
+ const key = (0, Utils_1.generateMessageIDV2)();
74
+ const result = await groupQuery('@g.us', 'set', [
75
+ {
76
+ tag: 'create',
77
+ attrs: {
78
+ subject,
79
+ key
80
+ },
81
+ content: participants.map(jid => ({
82
+ tag: 'participant',
83
+ attrs: { jid }
84
+ }))
85
+ }
86
+ ]);
87
+ return (0, exports.extractGroupMetadata)(result);
88
+ },
89
+ groupLeave: async (id) => {
90
+ await groupQuery('@g.us', 'set', [
91
+ {
92
+ tag: 'leave',
93
+ attrs: {},
94
+ content: [
95
+ { tag: 'group', attrs: { id } }
96
+ ]
97
+ }
98
+ ]);
99
+ },
100
+ groupUpdateSubject: async (jid, subject) => {
101
+ await groupQuery(jid, 'set', [
102
+ {
103
+ tag: 'subject',
104
+ attrs: {},
105
+ content: Buffer.from(subject, 'utf-8')
106
+ }
107
+ ]);
108
+ },
109
+ groupRequestParticipantsList: async (jid) => {
110
+ const result = await groupQuery(jid, 'get', [
111
+ {
112
+ tag: 'membership_approval_requests',
113
+ attrs: {}
114
+ }
115
+ ]);
116
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'membership_approval_requests');
117
+ const participants = (0, WABinary_1.getBinaryNodeChildren)(node, 'membership_approval_request');
118
+ return participants.map(v => v.attrs);
119
+ },
120
+ groupRequestParticipantsUpdate: async (jid, participants, action) => {
121
+ const result = await groupQuery(jid, 'set', [{
122
+ tag: 'membership_requests_action',
123
+ attrs: {},
124
+ content: [
125
+ {
126
+ tag: action,
127
+ attrs: {},
128
+ content: participants.map(jid => ({
129
+ tag: 'participant',
130
+ attrs: { jid }
131
+ }))
132
+ }
133
+ ]
134
+ }]);
135
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'membership_requests_action');
136
+ const nodeAction = (0, WABinary_1.getBinaryNodeChild)(node, action);
137
+ const participantsAffected = (0, WABinary_1.getBinaryNodeChildren)(nodeAction, 'participant');
138
+ return participantsAffected.map(p => {
139
+ return { status: p.attrs.error || '200', jid: p.attrs.jid };
140
+ });
141
+ },
142
+ groupParticipantsUpdate: async (jid, participants, action) => {
143
+ const result = await groupQuery(jid, 'set', [
144
+ {
145
+ tag: action,
146
+ attrs: {},
147
+ content: participants.map(jid => ({
148
+ tag: 'participant',
149
+ attrs: { jid }
150
+ }))
151
+ }
152
+ ]);
153
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, action);
154
+ const participantsAffected = (0, WABinary_1.getBinaryNodeChildren)(node, 'participant');
155
+ return participantsAffected.map(p => {
156
+ return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p };
157
+ });
158
+ },
159
+ groupUpdateDescription: async (jid, description) => {
160
+ var _a;
161
+ const metadata = await groupMetadata(jid);
162
+ const prev = (_a = metadata.descId) !== null && _a !== void 0 ? _a : null;
163
+ await groupQuery(jid, 'set', [
164
+ {
165
+ tag: 'description',
166
+ attrs: {
167
+ ...(description ? { id: (0, Utils_1.generateMessageIDV2)() } : { delete: 'true' }),
168
+ ...(prev ? { prev } : {})
169
+ },
170
+ content: description ? [
171
+ { tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') }
172
+ ] : undefined
173
+ }
174
+ ]);
175
+ },
176
+ groupInviteCode: async (jid) => {
177
+ const result = await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }]);
178
+ const inviteNode = (0, WABinary_1.getBinaryNodeChild)(result, 'invite');
179
+ return inviteNode === null || inviteNode === void 0 ? void 0 : inviteNode.attrs.code;
180
+ },
181
+ groupRevokeInvite: async (jid) => {
182
+ const result = await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }]);
183
+ const inviteNode = (0, WABinary_1.getBinaryNodeChild)(result, 'invite');
184
+ return inviteNode === null || inviteNode === void 0 ? void 0 : inviteNode.attrs.code;
185
+ },
186
+ groupAcceptInvite: async (code) => {
187
+ const results = await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }]);
188
+ const result = (0, WABinary_1.getBinaryNodeChild)(results, 'group');
189
+ return result === null || result === void 0 ? void 0 : result.attrs.jid;
190
+ },
191
+ /**
192
+ * revoke a v4 invite for someone
193
+ * @param groupJid group jid
194
+ * @param invitedJid jid of person you invited
195
+ * @returns true if successful
196
+ */
197
+ groupRevokeInviteV4: async (groupJid, invitedJid) => {
198
+ const result = await groupQuery(groupJid, 'set', [{ tag: 'revoke', attrs: {}, content: [{ tag: 'participant', attrs: { jid: invitedJid } }] }]);
199
+ return !!result;
200
+ },
201
+ /**
202
+ * accept a GroupInviteMessage
203
+ * @param key the key of the invite message, or optionally only provide the jid of the person who sent the invite
204
+ * @param inviteMessage the message to accept
205
+ */
206
+ groupAcceptInviteV4: ev.createBufferedFunction(async (key, inviteMessage) => {
207
+ var _a;
208
+ key = typeof key === 'string' ? { remoteJid: key } : key;
209
+ const results = await groupQuery(inviteMessage.groupJid, 'set', [{
210
+ tag: 'accept',
211
+ attrs: {
212
+ code: inviteMessage.inviteCode,
213
+ expiration: inviteMessage.inviteExpiration.toString(),
214
+ admin: key.remoteJid
215
+ }
216
+ }]);
217
+ // if we have the full message key
218
+ // update the invite message to be expired
219
+ if (key.id) {
220
+ // create new invite message that is expired
221
+ inviteMessage = WAProto_1.proto.Message.GroupInviteMessage.fromObject(inviteMessage);
222
+ inviteMessage.inviteExpiration = 0;
223
+ inviteMessage.inviteCode = '';
224
+ ev.emit('messages.update', [
225
+ {
226
+ key,
227
+ update: {
228
+ message: {
229
+ groupInviteMessage: inviteMessage
230
+ }
231
+ }
232
+ }
233
+ ]);
234
+ }
235
+ // generate the group add message
236
+ await upsertMessage({
237
+ key: {
238
+ remoteJid: inviteMessage.groupJid,
239
+ id: (0, Utils_1.generateMessageIDV2)((_a = sock.user) === null || _a === void 0 ? void 0 : _a.id),
240
+ fromMe: false,
241
+ participant: key.remoteJid,
242
+ },
243
+ messageStubType: Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD,
244
+ messageStubParameters: [
245
+ authState.creds.me.id
246
+ ],
247
+ participant: key.remoteJid,
248
+ messageTimestamp: (0, Utils_1.unixTimestampSeconds)()
249
+ }, 'notify');
250
+ return results.attrs.from;
251
+ }),
252
+ groupGetInviteInfo: async (code) => {
253
+ const results = await groupQuery('@g.us', 'get', [{ tag: 'invite', attrs: { code } }]);
254
+ return (0, exports.extractGroupMetadata)(results);
255
+ },
256
+ groupToggleEphemeral: async (jid, ephemeralExpiration) => {
257
+ const content = ephemeralExpiration ?
258
+ { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } } :
259
+ { tag: 'not_ephemeral', attrs: {} };
260
+ await groupQuery(jid, 'set', [content]);
261
+ },
262
+ groupSettingUpdate: async (jid, setting) => {
263
+ await groupQuery(jid, 'set', [{ tag: setting, attrs: {} }]);
264
+ },
265
+ groupMemberAddMode: async (jid, mode) => {
266
+ await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }]);
267
+ },
268
+ groupJoinApprovalMode: async (jid, mode) => {
269
+ await groupQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state: mode } }] }]);
270
+ },
271
+ groupFetchAllParticipating,
272
+
273
+ // ==========================================
274
+ // EASY GROUP MEMBER & SETTING HELPERS (PROMPT)
275
+ // ==========================================
276
+ kickMember: async (chatId, targetJid) => {
277
+ const list = Array.isArray(targetJid) ? targetJid : [targetJid];
278
+ return sock.groupParticipantsUpdate(chatId, list, 'remove');
279
+ },
280
+ addMember: async (chatId, targetJid) => {
281
+ const list = Array.isArray(targetJid) ? targetJid : [targetJid];
282
+ return sock.groupParticipantsUpdate(chatId, list, 'add');
283
+ },
284
+ promoteMember: async (chatId, targetJid) => {
285
+ const list = Array.isArray(targetJid) ? targetJid : [targetJid];
286
+ return sock.groupParticipantsUpdate(chatId, list, 'promote');
287
+ },
288
+ demoteMember: async (chatId, targetJid) => {
289
+ const list = Array.isArray(targetJid) ? targetJid : [targetJid];
290
+ return sock.groupParticipantsUpdate(chatId, list, 'demote');
291
+ },
292
+ openGroup: async (chatId) => {
293
+ return sock.groupSettingUpdate(chatId, 'not_announcement');
294
+ },
295
+ closeGroup: async (chatId) => {
296
+ return sock.groupSettingUpdate(chatId, 'announcement');
297
+ },
298
+ lockGroup: async (chatId) => {
299
+ return sock.groupSettingUpdate(chatId, 'locked');
300
+ },
301
+ unlockGroup: async (chatId) => {
302
+ return sock.groupSettingUpdate(chatId, 'unlocked');
303
+ },
304
+ updateGroupSubject: async (chatId, subject) => {
305
+ return sock.groupUpdateSubject(chatId, subject);
306
+ },
307
+ updateGroupDescription: async (chatId, description) => {
308
+ return sock.groupUpdateDescription(chatId, description);
309
+ },
310
+
311
+ // ==========================================
312
+ // SEND GROUP STATUS / STORY HELPER (SWGC)
313
+ // ==========================================
314
+ sendStatusGc: async (chatId, content, options = {}) => {
315
+ const crypto = require('crypto');
316
+ const messages = require('../Utils/messages');
317
+
318
+ let contentToSend = { ...content };
319
+ let extraOptions = {
320
+ upload: sock.waUploadToServer,
321
+ ...options
322
+ };
323
+
324
+ // If text status without background color, generate random color if not specified
325
+ if (contentToSend.text && !contentToSend.image && !contentToSend.video && !contentToSend.audio) {
326
+ if (!extraOptions.backgroundColor) {
327
+ extraOptions.backgroundColor = '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
328
+ }
329
+ }
330
+
331
+ const inside = await messages.generateWAMessageContent(contentToSend, extraOptions);
332
+ const messageSecret = crypto.randomBytes(32);
333
+
334
+ const msgToSend = messages.generateWAMessageFromContent(
335
+ chatId,
336
+ {
337
+ groupStatusMessageV2: {
338
+ message: {
339
+ ...inside,
340
+ messageContextInfo: {
341
+ messageSecret
342
+ }
343
+ }
344
+ }
345
+ },
346
+ options
347
+ );
348
+
349
+ await sock.relayMessage(chatId, msgToSend.message, {
350
+ messageId: msgToSend.key.id
351
+ });
352
+
353
+ return msgToSend;
354
+ },
355
+ sendGroupStatus: async (chatId, content, options = {}) => {
356
+ return sock.sendStatusGc(chatId, content, options);
357
+ }
358
+ };
359
+ };
360
+ exports.makeGroupsSocket = makeGroupsSocket;
361
+ const extractGroupMetadata = (result) => {
362
+ var _a, _b;
363
+ const group = (0, WABinary_1.getBinaryNodeChild)(result, 'group');
364
+ const descChild = (0, WABinary_1.getBinaryNodeChild)(group, 'description');
365
+ let desc;
366
+ let descId;
367
+ let descOwner;
368
+ let descOwnerLid;
369
+ let descTime;
370
+ if (descChild) {
371
+ desc = (0, WABinary_1.getBinaryNodeChildString)(descChild, 'body');
372
+ descOwner = (0, WABinary_1.jidNormalizedUser)(descChild.attrs.participant_pn || descChild.attrs.participant);
373
+ if (group.attrs.addressing_mode === 'lid') {
374
+ descOwnerLid = (0, WABinary_1.jidNormalizedUser)(descChild.attrs.participant);
375
+ }
376
+ descId = descChild.attrs.id;
377
+ descTime = descChild.attrs.t ? +descChild.attrs.t : undefined;
378
+ }
379
+ const groupSize = group.attrs.size ? Number(group.attrs.size) : undefined;
380
+ const groupId = group.attrs.id.includes('@') ? group.attrs.id : (0, WABinary_1.jidEncode)(group.attrs.id, 'g.us');
381
+ const eph = (_a = (0, WABinary_1.getBinaryNodeChild)(group, 'ephemeral')) === null || _a === void 0 ? void 0 : _a.attrs.expiration;
382
+ const memberAddMode = (0, WABinary_1.getBinaryNodeChildString)(group, 'member_add_mode') === 'all_member_add';
383
+ const metadata = {
384
+ id: groupId,
385
+ addressingMode: group.attrs.addressing_mode,
386
+ subject: group.attrs.subject,
387
+ subjectOwner: (0, WABinary_1.jidNormalizedUser)(group.attrs.s_o_pn || group.attrs.s_o),
388
+ ...(group.attrs.addressing_mode === 'lid' ? { subjectOwnerLid: (0, WABinary_1.jidNormalizedUser)(group.attrs.s_o) } : {}),
389
+ subjectTime: group.attrs.s_t ? +group.attrs.s_t : undefined,
390
+ size: groupSize || (0, WABinary_1.getBinaryNodeChildren)(group, 'participant').length,
391
+ creation: group.attrs.creation ? +group.attrs.creation : undefined,
392
+ owner: (0, WABinary_1.jidNormalizedUser)(group.attrs.creator_pn || group.attrs.creator),
393
+ ...(group.attrs.addressing_mode === 'lid' ? { ownerLid: (0, WABinary_1.jidNormalizedUser)(group.attrs.creator) } : {}),
394
+ desc,
395
+ descId,
396
+ descOwner,
397
+ descOwnerLid,
398
+ descTime,
399
+ linkedParent: ((_b = (0, WABinary_1.getBinaryNodeChild)(group, 'linked_parent')) === null || _b === void 0 ? void 0 : _b.attrs.jid) || undefined,
400
+ restrict: !!(0, WABinary_1.getBinaryNodeChild)(group, 'locked'),
401
+ announce: !!(0, WABinary_1.getBinaryNodeChild)(group, 'announcement'),
402
+ isCommunity: !!(0, WABinary_1.getBinaryNodeChild)(group, 'parent'),
403
+ isCommunityAnnounce: !!(0, WABinary_1.getBinaryNodeChild)(group, 'default_sub_group'),
404
+ joinApprovalMode: !!(0, WABinary_1.getBinaryNodeChild)(group, 'membership_approval_mode'),
405
+ memberAddMode,
406
+ participants: (0, WABinary_1.getBinaryNodeChildren)(group, 'participant').map(({ attrs }) => {
407
+ return {
408
+ id: attrs.jid,
409
+ jid: attrs.phone_number || attrs.jid,
410
+ lid: attrs.lid || attrs.jid,
411
+ admin: (attrs.type || null),
412
+ };
413
+ }),
414
+ ephemeralDuration: eph ? +eph : undefined
415
+ };
416
+ return metadata;
417
+ };
418
+ exports.extractGroupMetadata = extractGroupMetadata;
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.makeWASocket = exports.Client = exports.makeWASocketAdvanced = void 0;
5
+
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const events = require("events");
9
+ const pino = require("pino");
10
+ const boom_1 = require("@hapi/boom");
11
+ const qrcode_terminal = require("qrcode-terminal");
12
+ const chalk = require("chalk");
13
+
14
+ const business_1 = require("./business");
15
+ const Defaults_1 = require("../Defaults");
16
+ const Types_1 = require("../Types");
17
+ const use_multi_file_auth_state_1 = require("../Utils/use-multi-file-auth-state");
18
+ const serializer_1 = require("../Utils/serializer");
19
+
20
+ /**
21
+ * Low-level standard socket creator
22
+ */
23
+ const rawMakeWASocket = (config) =>
24
+ (0, business_1.makeBusinessSocket)({
25
+ ...Defaults_1.DEFAULT_CONNECTION_CONFIG,
26
+ ...config
27
+ });
28
+
29
+ /**
30
+ * Advanced Client Wrapper Class
31
+ */
32
+ class Client extends events.EventEmitter {
33
+ constructor(options = {}) {
34
+ super();
35
+ this.options = {
36
+ sessionName: "auth-session",
37
+ usePairingCode: false,
38
+ phoneNumber: "",
39
+ customPair: null,
40
+ autoReconnect: true,
41
+ maxReconnectAttempts: 10,
42
+ autoCleanSessionOnLogout: true,
43
+ printQRInTerminal: true,
44
+ logger: pino({ level: "silent" }),
45
+ browser: Defaults_1.DEFAULT_CONNECTION_CONFIG.browser,
46
+ ...options
47
+ };
48
+
49
+ this.sock = null;
50
+ this.reconnectAttempts = 0;
51
+ this.isClosed = false;
52
+ this.ev = new events.EventEmitter();
53
+
54
+ // Forward public events from this.ev to instance
55
+ const originalEmit = this.ev.emit.bind(this.ev);
56
+ this.ev.emit = (event, ...args) => {
57
+ originalEmit(event, ...args);
58
+ this.emit(event, ...args);
59
+ };
60
+
61
+ // Proxy socket methods directly to Client instance
62
+ return new Proxy(this, {
63
+ get: (target, prop) => {
64
+ if (prop in target) return target[prop];
65
+ if (target.sock && typeof target.sock[prop] === "function") {
66
+ return target.sock[prop].bind(target.sock);
67
+ }
68
+ return target.sock?.[prop];
69
+ }
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Start connecting to WhatsApp
75
+ */
76
+ async connect() {
77
+ const sessionPath = path.resolve(this.options.sessionName);
78
+ const { state, saveCreds } = await (0, use_multi_file_auth_state_1.useMultiFileAuthState)(sessionPath);
79
+
80
+ this.sock = rawMakeWASocket({
81
+ ...this.options,
82
+ auth: state,
83
+ printQRInTerminal: false // Handled internally
84
+ });
85
+
86
+ // Event: creds.update
87
+ this.sock.ev.on("creds.update", saveCreds);
88
+
89
+ // Auto Pairing Code Handler
90
+ if (this.options.usePairingCode && !this.sock.authState.creds.registered) {
91
+ setTimeout(async () => {
92
+ try {
93
+ const phone = String(this.options.phoneNumber || "").replace(/[^0-9]/g, "");
94
+ if (!phone) {
95
+ console.log(chalk.red("❌ [Rixleys] Error: phoneNumber wajib diisi jika usePairingCode = true!"));
96
+ return;
97
+ }
98
+
99
+ if (this.options.customPair && this.options.customPair.length === 8) {
100
+ const code = await this.sock.requestPairingCode(phone, this.options.customPair);
101
+ console.log(chalk.cyan(`🔑 [Rixleys] Kode Pairing Kustom: ${chalk.bold.yellow(code)}`));
102
+ } else {
103
+ const code = await this.sock.requestPairingCode(phone);
104
+ console.log(chalk.cyan(`🔑 [Rixleys] Kode Pairing: ${chalk.bold.yellow(code)}`));
105
+ }
106
+ } catch (err) {
107
+ console.error("❌ [Rixleys] Gagal request pairing code:", err);
108
+ }
109
+ }, 2000);
110
+ }
111
+
112
+ // Connection update handler
113
+ this.sock.ev.on("connection.update", async (update) => {
114
+ const { connection, lastDisconnect, qr } = update;
115
+
116
+ // QR Code display
117
+ if (qr && !this.options.usePairingCode && this.options.printQRInTerminal) {
118
+ console.log(chalk.cyan("📱 [Rixleys] Pindai QR Code ini untuk login:"));
119
+ qrcode_terminal.generate(qr, { small: true });
120
+ }
121
+
122
+ if (connection === "open") {
123
+ this.reconnectAttempts = 0;
124
+ console.log(chalk.green("✅ [Rixleys] Berhasil terhubung ke WhatsApp!"));
125
+ }
126
+
127
+ if (connection === "close") {
128
+ const statusCode = (0, boom_1.isBoom)(lastDisconnect?.error)
129
+ ? lastDisconnect?.error?.output?.statusCode
130
+ : lastDisconnect?.error?.statusCode;
131
+
132
+ const isLoggedOut =
133
+ statusCode === Types_1.DisconnectReason.loggedOut ||
134
+ statusCode === Types_1.DisconnectReason.badSession;
135
+
136
+ if (isLoggedOut) {
137
+ console.log(chalk.red(`🚪 [Rixleys] Sesi terputus / Logout (status: ${statusCode})`));
138
+ if (this.options.autoCleanSessionOnLogout) {
139
+ try {
140
+ if (fs.existsSync(sessionPath)) {
141
+ fs.rmSync(sessionPath, { recursive: true, force: true });
142
+ console.log(chalk.yellow(`🗑️ [Rixleys] Folder sesi '${this.options.sessionName}' berhasil dibersihkan.`));
143
+ }
144
+ } catch (e) {
145
+ console.error("❌ [Rixleys] Gagal menghapus folder sesi:", e);
146
+ }
147
+ }
148
+ return;
149
+ }
150
+
151
+ if (this.options.autoReconnect && !this.isClosed) {
152
+ if (this.reconnectAttempts < this.options.maxReconnectAttempts) {
153
+ this.reconnectAttempts++;
154
+ const delayMs = Math.min(this.reconnectAttempts * 2000, 10000);
155
+ console.log(chalk.yellow(`🔌 [Rixleys] Koneksi putus (${statusCode}). Mencoba reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts}) dalam ${delayMs / 1000}s...`));
156
+ setTimeout(() => this.connect(), delayMs);
157
+ } else {
158
+ console.log(chalk.red(`❌ [Rixleys] Mencapai batas maksimal reconnect (${this.options.maxReconnectAttempts}). Berhenti.`));
159
+ }
160
+ }
161
+ }
162
+
163
+ // Forward event
164
+ this.ev.emit("connection.update", update);
165
+ });
166
+
167
+ // Forward messages.upsert with auto-serialization
168
+ this.sock.ev.on("messages.upsert", (upsert) => {
169
+ if (Array.isArray(upsert?.messages)) {
170
+ for (let i = 0; i < upsert.messages.length; i++) {
171
+ (0, serializer_1.serialize)(this.sock, upsert.messages[i]);
172
+ }
173
+ }
174
+ this.ev.emit("messages.upsert", upsert);
175
+ });
176
+
177
+ // Forward other events from sock.ev to this.ev
178
+ const eventsList = [
179
+ "contacts.upsert",
180
+ "contacts.update",
181
+ "chats.upsert",
182
+ "chats.update",
183
+ "chats.delete",
184
+ "presence.update",
185
+ "message-receipt.update",
186
+ "messages.reaction",
187
+ "messages.update",
188
+ "messages.delete",
189
+ "group-participants.update",
190
+ "groups.update",
191
+ "blocklist.set",
192
+ "blocklist.update",
193
+ "call",
194
+ "labels.edit",
195
+ "labels.association"
196
+ ];
197
+
198
+ for (const evt of eventsList) {
199
+ this.sock.ev.on(evt, (...args) => this.ev.emit(evt, ...args));
200
+ }
201
+
202
+ return this;
203
+ }
204
+
205
+ /**
206
+ * Terminate connection
207
+ */
208
+ end(error) {
209
+ this.isClosed = true;
210
+ return this.sock?.end(error);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Universal makeWASocket:
216
+ * - If called with 'new makeWASocket(opts)' or opts contain 'sessionName', returns managed Client
217
+ * - If called as standard function makeWASocket(config), returns normal WASocket
218
+ */
219
+ function makeWASocketUniversal(config = {}) {
220
+ // If called with new or user passed high-level wrapper options
221
+ if (
222
+ new.target ||
223
+ config.sessionName ||
224
+ typeof config.usePairingCode !== "undefined" ||
225
+ config.autoReconnect
226
+ ) {
227
+ const client = new Client(config);
228
+ client.connect();
229
+ return client;
230
+ }
231
+
232
+ return rawMakeWASocket(config);
233
+ }
234
+
235
+ exports.Client = Client;
236
+ exports.makeWASocketAdvanced = makeWASocketUniversal;
237
+ exports.makeWASocket = makeWASocketUniversal;
238
+ exports.default = makeWASocketUniversal;