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.
- package/LICENSE +21 -0
- package/README.MD +2969 -0
- package/WAProto/GenerateStatics.sh +4 -0
- package/WAProto/WAProto.proto +5479 -0
- package/WAProto/index.js +97692 -0
- package/WAProto/p.html +1 -0
- package/engine-requirements.js +10 -0
- package/lib/Defaults/index.js +120 -0
- package/lib/Defaults/rixleys-version.json +3 -0
- package/lib/Signal/Group/ciphertext-message.js +15 -0
- package/lib/Signal/Group/group-session-builder.js +64 -0
- package/lib/Signal/Group/group_cipher.js +96 -0
- package/lib/Signal/Group/index.js +57 -0
- package/lib/Signal/Group/keyhelper.js +55 -0
- package/lib/Signal/Group/queue-job.js +57 -0
- package/lib/Signal/Group/sender-chain-key.js +34 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +66 -0
- package/lib/Signal/Group/sender-key-message.js +69 -0
- package/lib/Signal/Group/sender-key-name.js +51 -0
- package/lib/Signal/Group/sender-key-record.js +53 -0
- package/lib/Signal/Group/sender-key-state.js +99 -0
- package/lib/Signal/Group/sender-message-key.js +29 -0
- package/lib/Signal/core/.eslintrc.json +31 -0
- package/lib/Signal/core/CODE_OF_CONDUCT.md +102 -0
- package/lib/Signal/core/LICENSE +621 -0
- package/lib/Signal/core/README.md +64 -0
- package/lib/Signal/core/SECURITY.md +78 -0
- package/lib/Signal/core/generate-proto.sh +1 -0
- package/lib/Signal/core/index.d.ts +55 -0
- package/lib/Signal/core/index.js +10 -0
- package/lib/Signal/core/protos/WhisperTextProtocol.proto +28 -0
- package/lib/Signal/core/src/.eslintrc.json +31 -0
- package/lib/Signal/core/src/WhisperTextProtocol.js +933 -0
- package/lib/Signal/core/src/base_key_type.js +7 -0
- package/lib/Signal/core/src/chain_type.js +6 -0
- package/lib/Signal/core/src/crypto.d.ts +19 -0
- package/lib/Signal/core/src/crypto.js +98 -0
- package/lib/Signal/core/src/curve.d.ts +22 -0
- package/lib/Signal/core/src/curve.js +142 -0
- package/lib/Signal/core/src/errors.js +33 -0
- package/lib/Signal/core/src/keyhelper.js +45 -0
- package/lib/Signal/core/src/numeric_fingerprint.js +72 -0
- package/lib/Signal/core/src/protobufs.js +10 -0
- package/lib/Signal/core/src/protocol_address.js +40 -0
- package/lib/Signal/core/src/queue_job.js +69 -0
- package/lib/Signal/core/src/session_builder.js +164 -0
- package/lib/Signal/core/src/session_cipher.js +336 -0
- package/lib/Signal/core/src/session_record.js +316 -0
- package/lib/Signal/libsignal.js +184 -0
- package/lib/Socket/Client/index.js +18 -0
- package/lib/Socket/Client/types.js +13 -0
- package/lib/Socket/Client/websocket.js +72 -0
- package/lib/Socket/business.js +260 -0
- package/lib/Socket/chats.js +997 -0
- package/lib/Socket/groups.js +418 -0
- package/lib/Socket/index.js +238 -0
- package/lib/Socket/messages-recv.js +1106 -0
- package/lib/Socket/messages-send.js +882 -0
- package/lib/Socket/newsletter.js +250 -0
- package/lib/Socket/socket.js +646 -0
- package/lib/Socket/usync.js +70 -0
- package/lib/Store/index.js +8 -0
- package/lib/Store/make-in-memory-store.js +439 -0
- package/lib/Store/make-ordered-dictionary.js +81 -0
- package/lib/Store/object-repository.js +27 -0
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.js +4 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.js +27 -0
- package/lib/Types/LabelAssociation.js +9 -0
- package/lib/Types/Message.js +7 -0
- package/lib/Types/Newsletter.js +18 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.js +2 -0
- package/lib/Types/State.js +2 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.js +42 -0
- package/lib/Utils/auth-utils.js +199 -0
- package/lib/Utils/browser-utils.js +35 -0
- package/lib/Utils/business.js +234 -0
- package/lib/Utils/chat-utils.js +730 -0
- package/lib/Utils/crypto.js +193 -0
- package/lib/Utils/decode-wa-message.js +217 -0
- package/lib/Utils/event-buffer.js +518 -0
- package/lib/Utils/generics.js +467 -0
- package/lib/Utils/history.js +94 -0
- package/lib/Utils/index.js +36 -0
- package/lib/Utils/link-preview.js +151 -0
- package/lib/Utils/logger.js +7 -0
- package/lib/Utils/lt-hash.js +51 -0
- package/lib/Utils/make-mutex.js +43 -0
- package/lib/Utils/message-retry-manager.js +185 -0
- package/lib/Utils/messages-media.js +879 -0
- package/lib/Utils/messages.js +1049 -0
- package/lib/Utils/noise-handler.js +150 -0
- package/lib/Utils/process-message.js +404 -0
- package/lib/Utils/rixleys-event-stream.js +63 -0
- package/lib/Utils/serializer.js +238 -0
- package/lib/Utils/signal.js +153 -0
- package/lib/Utils/use-multi-file-auth-state.js +124 -0
- package/lib/Utils/validate-connection.js +229 -0
- package/lib/WABinary/constants.js +1303 -0
- package/lib/WABinary/decode.js +265 -0
- package/lib/WABinary/encode.js +250 -0
- package/lib/WABinary/generic-utils.js +110 -0
- package/lib/WABinary/index.js +21 -0
- package/lib/WABinary/jid-utils.js +85 -0
- package/lib/WABinary/types.js +2 -0
- package/lib/WAM/BinaryInfo.js +13 -0
- package/lib/WAM/constants.js +15350 -0
- package/lib/WAM/encode.js +155 -0
- package/lib/WAM/index.js +19 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
- package/lib/WAUSync/Protocols/index.js +20 -0
- package/lib/WAUSync/USyncQuery.js +89 -0
- package/lib/WAUSync/USyncUser.js +26 -0
- package/lib/WAUSync/index.js +19 -0
- package/lib/index.js +54 -0
- 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;
|