@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.
- package/lib/Defaults/index.js +3 -3
- package/lib/Defaults/index.js.bak-1788476907801 +187 -0
- package/lib/Defaults/index.js.bak-1788479166288 +187 -0
- package/lib/Socket/groups.js.bak-1788476973954 +475 -0
- package/lib/Socket/index.js +33 -1
- package/lib/Socket/index.js.bak-1788479281092 +38 -0
- package/lib/Socket/messages-send.js +61 -7
- package/lib/Store/prototype-store.js +34 -22
- package/lib/Store/prototype-store.js.bak-1788477006895 +983 -0
- package/lib/Utils/index.js +2 -0
- package/lib/Utils/integrity-guard.js +281 -0
- package/lib/Utils/interactive-message-handler.js +28 -8
- package/lib/Utils/interactive-message-handler.js.bak-1788476898661 +478 -0
- package/lib/Utils/socket-guard.js +154 -0
- package/package.json +1 -1
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
import { proto as WAProto } from '../../WAProto/index.js';
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
import * as Utils_1 from '../Utils/index.js';
|
|
4
|
+
|
|
5
|
+
export default class InteractiveMessageHandler {
|
|
6
|
+
constructor(utils, waUploadToServer, relayMessageFn) {
|
|
7
|
+
this.utils = utils;
|
|
8
|
+
this.relayMessage = relayMessageFn;
|
|
9
|
+
this.waUploadToServer = waUploadToServer;
|
|
10
|
+
|
|
11
|
+
this.bail = {
|
|
12
|
+
generateWAMessageContent: this.utils.generateWAMessageContent || Utils_1.generateWAMessageContent,
|
|
13
|
+
generateMessageID: Utils_1.generateMessageID,
|
|
14
|
+
getContentType: (msg) => Object.keys(msg.message || {})[0]
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
detectType(content) {
|
|
19
|
+
if (content.requestPaymentMessage) return 'PAYMENT';
|
|
20
|
+
if (content.productMessage) return 'PRODUCT';
|
|
21
|
+
if (content.interactiveMessage) return 'INTERACTIVE';
|
|
22
|
+
if (content.albumMessage) return 'ALBUM';
|
|
23
|
+
if (content.eventMessage) return 'EVENT';
|
|
24
|
+
if (content.pollResultMessage) return 'POLL_RESULT';
|
|
25
|
+
if (content.groupStatusMessage) return 'GROUP_STORY';
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async handlePayment(content, quoted) {
|
|
30
|
+
const data = content.requestPaymentMessage;
|
|
31
|
+
let notes = {};
|
|
32
|
+
|
|
33
|
+
if (data.sticker?.stickerMessage) {
|
|
34
|
+
notes = {
|
|
35
|
+
stickerMessage: {
|
|
36
|
+
...data.sticker.stickerMessage,
|
|
37
|
+
contextInfo: {
|
|
38
|
+
stanzaId: quoted?.key?.id,
|
|
39
|
+
participant: quoted?.key?.participant || content.sender,
|
|
40
|
+
quotedMessage: quoted?.message
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
} else if (data.note) {
|
|
45
|
+
notes = {
|
|
46
|
+
extendedTextMessage: {
|
|
47
|
+
text: data.note,
|
|
48
|
+
contextInfo: {
|
|
49
|
+
stanzaId: quoted?.key?.id,
|
|
50
|
+
participant: quoted?.key?.participant || content.sender,
|
|
51
|
+
quotedMessage: quoted?.message
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
requestPaymentMessage: WAProto.Message.RequestPaymentMessage.fromObject({
|
|
59
|
+
expiryTimestamp: data.expiry || 0,
|
|
60
|
+
amount1000: data.amount || 0,
|
|
61
|
+
currencyCodeIso4217: data.currency || "IDR",
|
|
62
|
+
requestFrom: data.from || "0@s.whatsapp.net",
|
|
63
|
+
noteMessage: notes,
|
|
64
|
+
background: data.background ?? {
|
|
65
|
+
id: "DEFAULT",
|
|
66
|
+
placeholderArgb: 0xFFF0F0F0
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async handleProduct(content, jid, quoted) {
|
|
73
|
+
const {
|
|
74
|
+
title,
|
|
75
|
+
description,
|
|
76
|
+
thumbnail,
|
|
77
|
+
productId,
|
|
78
|
+
retailerId,
|
|
79
|
+
url,
|
|
80
|
+
body = "",
|
|
81
|
+
footer = "",
|
|
82
|
+
buttons = [],
|
|
83
|
+
priceAmount1000 = null,
|
|
84
|
+
currencyCode = "IDR"
|
|
85
|
+
} = content.productMessage;
|
|
86
|
+
|
|
87
|
+
let productImage;
|
|
88
|
+
|
|
89
|
+
if (Buffer.isBuffer(thumbnail)) {
|
|
90
|
+
const { imageMessage } = await this.utils.generateWAMessageContent(
|
|
91
|
+
{ image: thumbnail },
|
|
92
|
+
{ upload: this.waUploadToServer }
|
|
93
|
+
);
|
|
94
|
+
productImage = imageMessage;
|
|
95
|
+
} else if (typeof thumbnail === 'object' && thumbnail.url) {
|
|
96
|
+
const { imageMessage } = await this.utils.generateWAMessageContent(
|
|
97
|
+
{ image: { url: thumbnail.url }},
|
|
98
|
+
{ upload: this.waUploadToServer }
|
|
99
|
+
);
|
|
100
|
+
productImage = imageMessage;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
viewOnceMessage: {
|
|
105
|
+
message: {
|
|
106
|
+
interactiveMessage: {
|
|
107
|
+
body: { text: body },
|
|
108
|
+
footer: { text: footer },
|
|
109
|
+
header: {
|
|
110
|
+
title,
|
|
111
|
+
hasMediaAttachment: true,
|
|
112
|
+
productMessage: {
|
|
113
|
+
product: {
|
|
114
|
+
productImage,
|
|
115
|
+
productId,
|
|
116
|
+
title,
|
|
117
|
+
description,
|
|
118
|
+
currencyCode,
|
|
119
|
+
priceAmount1000,
|
|
120
|
+
retailerId,
|
|
121
|
+
url,
|
|
122
|
+
productImageCount: 1
|
|
123
|
+
},
|
|
124
|
+
businessOwnerJid: "0@s.whatsapp.net"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
nativeFlowMessage: { buttons }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async handleInteractive(content, jid, quoted) {
|
|
135
|
+
const {
|
|
136
|
+
title,
|
|
137
|
+
footer,
|
|
138
|
+
thumbnail,
|
|
139
|
+
image,
|
|
140
|
+
video,
|
|
141
|
+
document,
|
|
142
|
+
mimetype,
|
|
143
|
+
fileName,
|
|
144
|
+
jpegThumbnail,
|
|
145
|
+
contextInfo,
|
|
146
|
+
externalAdReply,
|
|
147
|
+
buttons = [],
|
|
148
|
+
nativeFlowMessage,
|
|
149
|
+
header
|
|
150
|
+
} = content.interactiveMessage;
|
|
151
|
+
|
|
152
|
+
let media = null;
|
|
153
|
+
let mediaType = null;
|
|
154
|
+
|
|
155
|
+
if (thumbnail) {
|
|
156
|
+
media = await this.utils.prepareWAMessageMedia(
|
|
157
|
+
{ image: { url: thumbnail } },
|
|
158
|
+
{ upload: this.waUploadToServer }
|
|
159
|
+
);
|
|
160
|
+
mediaType = 'image';
|
|
161
|
+
} else if (image) {
|
|
162
|
+
if (typeof image === 'object' && image.url) {
|
|
163
|
+
media = await this.utils.prepareWAMessageMedia(
|
|
164
|
+
{ image: { url: image.url } },
|
|
165
|
+
{ upload: this.waUploadToServer }
|
|
166
|
+
);
|
|
167
|
+
} else {
|
|
168
|
+
media = await this.utils.prepareWAMessageMedia(
|
|
169
|
+
{ image: image },
|
|
170
|
+
{ upload: this.waUploadToServer }
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
mediaType = 'image';
|
|
174
|
+
} else if (video) {
|
|
175
|
+
if (typeof video === 'object' && video.url) {
|
|
176
|
+
media = await this.utils.prepareWAMessageMedia(
|
|
177
|
+
{ video: { url: video.url } },
|
|
178
|
+
{ upload: this.waUploadToServer }
|
|
179
|
+
);
|
|
180
|
+
} else {
|
|
181
|
+
media = await this.utils.prepareWAMessageMedia(
|
|
182
|
+
{ video: video },
|
|
183
|
+
{ upload: this.waUploadToServer }
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
mediaType = 'video';
|
|
187
|
+
} else if (document) {
|
|
188
|
+
let documentPayload = {
|
|
189
|
+
document: document
|
|
190
|
+
};
|
|
191
|
+
if (jpegThumbnail) {
|
|
192
|
+
if (typeof jpegThumbnail === 'object' && jpegThumbnail.url) {
|
|
193
|
+
documentPayload.jpegThumbnail = { url: jpegThumbnail.url };
|
|
194
|
+
} else {
|
|
195
|
+
documentPayload.jpegThumbnail = jpegThumbnail;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
media = await this.utils.prepareWAMessageMedia(
|
|
200
|
+
documentPayload,
|
|
201
|
+
{ upload: this.waUploadToServer }
|
|
202
|
+
);
|
|
203
|
+
if (fileName) {
|
|
204
|
+
media.documentMessage.fileName = fileName;
|
|
205
|
+
}
|
|
206
|
+
if (mimetype) {
|
|
207
|
+
media.documentMessage.mimetype = mimetype;
|
|
208
|
+
}
|
|
209
|
+
mediaType = 'document';
|
|
210
|
+
}
|
|
211
|
+
let interactiveMessage = {
|
|
212
|
+
body: { text: title || "" },
|
|
213
|
+
footer: { text: footer || "" }
|
|
214
|
+
};
|
|
215
|
+
if (buttons && buttons.length > 0) {
|
|
216
|
+
interactiveMessage.nativeFlowMessage = {
|
|
217
|
+
buttons: buttons
|
|
218
|
+
};
|
|
219
|
+
if (nativeFlowMessage) {
|
|
220
|
+
interactiveMessage.nativeFlowMessage = {
|
|
221
|
+
...interactiveMessage.nativeFlowMessage,
|
|
222
|
+
...nativeFlowMessage
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
} else if (nativeFlowMessage) {
|
|
226
|
+
interactiveMessage.nativeFlowMessage = nativeFlowMessage;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (media) {
|
|
230
|
+
interactiveMessage.header = {
|
|
231
|
+
title: header || "",
|
|
232
|
+
hasMediaAttachment: true,
|
|
233
|
+
...media
|
|
234
|
+
};
|
|
235
|
+
} else {
|
|
236
|
+
interactiveMessage.header = {
|
|
237
|
+
title: header || "",
|
|
238
|
+
hasMediaAttachment: false
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
let finalContextInfo = {};
|
|
243
|
+
if (contextInfo) {
|
|
244
|
+
finalContextInfo = {
|
|
245
|
+
mentionedJid: contextInfo.mentionedJid || [],
|
|
246
|
+
forwardingScore: contextInfo.forwardingScore || 0,
|
|
247
|
+
isForwarded: contextInfo.isForwarded || false,
|
|
248
|
+
...contextInfo
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (externalAdReply) {
|
|
253
|
+
finalContextInfo.externalAdReply = {
|
|
254
|
+
title: externalAdReply.title || "",
|
|
255
|
+
body: externalAdReply.body || "",
|
|
256
|
+
mediaType: externalAdReply.mediaType || 1,
|
|
257
|
+
thumbnailUrl: externalAdReply.thumbnailUrl || "",
|
|
258
|
+
mediaUrl: externalAdReply.mediaUrl || "",
|
|
259
|
+
sourceUrl: externalAdReply.sourceUrl || "",
|
|
260
|
+
showAdAttribution: externalAdReply.showAdAttribution || false,
|
|
261
|
+
renderLargerThumbnail: externalAdReply.renderLargerThumbnail || false,
|
|
262
|
+
...externalAdReply
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (Object.keys(finalContextInfo).length > 0) {
|
|
267
|
+
interactiveMessage.contextInfo = finalContextInfo;
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
interactiveMessage: interactiveMessage
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async handleAlbum(content, jid, quoted) {
|
|
275
|
+
const array = content.albumMessage;
|
|
276
|
+
const album = await this.utils.generateWAMessageFromContent(jid, {
|
|
277
|
+
messageContextInfo: {
|
|
278
|
+
messageSecret: crypto.randomBytes(32),
|
|
279
|
+
},
|
|
280
|
+
albumMessage: {
|
|
281
|
+
expectedImageCount: array.filter((a) => a.hasOwnProperty("image")).length,
|
|
282
|
+
expectedVideoCount: array.filter((a) => a.hasOwnProperty("video")).length,
|
|
283
|
+
},
|
|
284
|
+
}, {
|
|
285
|
+
userJid: this.utils.generateMessageID().split('@')[0] + '@s.whatsapp.net',
|
|
286
|
+
quoted,
|
|
287
|
+
upload: this.waUploadToServer
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
await this.relayMessage(jid, album.message, {
|
|
291
|
+
messageId: album.key.id,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
for (let content of array) {
|
|
295
|
+
const img = await this.utils.generateWAMessage(jid, content, {
|
|
296
|
+
upload: this.waUploadToServer,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
img.message.messageContextInfo = {
|
|
300
|
+
messageSecret: crypto.randomBytes(32),
|
|
301
|
+
messageAssociation: {
|
|
302
|
+
associationType: 1,
|
|
303
|
+
parentMessageKey: album.key,
|
|
304
|
+
},
|
|
305
|
+
participant: "0@s.whatsapp.net",
|
|
306
|
+
remoteJid: "status@broadcast",
|
|
307
|
+
forwardingScore: 99999,
|
|
308
|
+
isForwarded: true,
|
|
309
|
+
mentionedJid: [jid],
|
|
310
|
+
starred: true,
|
|
311
|
+
labels: ["Y", "Important"],
|
|
312
|
+
isHighlighted: true,
|
|
313
|
+
businessMessageForwardInfo: {
|
|
314
|
+
businessOwnerJid: jid,
|
|
315
|
+
},
|
|
316
|
+
dataSharingContext: {
|
|
317
|
+
showMmDisclosure: true,
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
img.message.forwardedNewsletterMessageInfo = {
|
|
322
|
+
newsletterJid: "0@newsletter",
|
|
323
|
+
serverMessageId: 1,
|
|
324
|
+
newsletterName: `WhatsApp`,
|
|
325
|
+
contentType: 1,
|
|
326
|
+
timestamp: new Date().toISOString(),
|
|
327
|
+
senderName: "Alip Clutch",
|
|
328
|
+
content: "Text Message",
|
|
329
|
+
priority: "high",
|
|
330
|
+
status: "sent",
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
img.message.disappearingMode = {
|
|
334
|
+
initiator: 3,
|
|
335
|
+
trigger: 4,
|
|
336
|
+
initiatorDeviceJid: jid,
|
|
337
|
+
initiatedByExternalService: true,
|
|
338
|
+
initiatedByUserDevice: true,
|
|
339
|
+
initiatedBySystem: true,
|
|
340
|
+
initiatedByServer: true,
|
|
341
|
+
initiatedByAdmin: true,
|
|
342
|
+
initiatedByUser: true,
|
|
343
|
+
initiatedByApp: true,
|
|
344
|
+
initiatedByBot: true,
|
|
345
|
+
initiatedByMe: true,
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
await this.relayMessage(jid, img.message, {
|
|
349
|
+
messageId: img.key.id,
|
|
350
|
+
quoted: {
|
|
351
|
+
key: {
|
|
352
|
+
remoteJid: album.key.remoteJid,
|
|
353
|
+
id: album.key.id,
|
|
354
|
+
fromMe: true,
|
|
355
|
+
participant: this.utils.generateMessageID().split('@')[0] + '@s.whatsapp.net',
|
|
356
|
+
},
|
|
357
|
+
message: album.message,
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
return album;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
async handleEvent(content, jid, quoted) {
|
|
365
|
+
const eventData = content.eventMessage;
|
|
366
|
+
|
|
367
|
+
const msg = await this.utils.generateWAMessageFromContent(jid, {
|
|
368
|
+
viewOnceMessage: {
|
|
369
|
+
message: {
|
|
370
|
+
messageContextInfo: {
|
|
371
|
+
deviceListMetadata: {},
|
|
372
|
+
deviceListMetadataVersion: 2,
|
|
373
|
+
messageSecret: crypto.randomBytes(32),
|
|
374
|
+
supportPayload: JSON.stringify({
|
|
375
|
+
version: 2,
|
|
376
|
+
is_ai_message: true,
|
|
377
|
+
should_show_system_message: true,
|
|
378
|
+
ticket_id: crypto.randomBytes(16).toString('hex')
|
|
379
|
+
})
|
|
380
|
+
},
|
|
381
|
+
eventMessage: {
|
|
382
|
+
contextInfo: {
|
|
383
|
+
mentionedJid: [jid],
|
|
384
|
+
participant: jid,
|
|
385
|
+
remoteJid: "status@broadcast",
|
|
386
|
+
forwardedNewsletterMessageInfo: {
|
|
387
|
+
newsletterName: "alip clutch.",
|
|
388
|
+
newsletterJid: "120363406965898096@newsletter",
|
|
389
|
+
serverMessageId: 1
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
isCanceled: eventData.isCanceled || false,
|
|
393
|
+
name: eventData.name,
|
|
394
|
+
description: eventData.description,
|
|
395
|
+
location: eventData.location || {
|
|
396
|
+
degreesLatitude: 0,
|
|
397
|
+
degreesLongitude: 0,
|
|
398
|
+
name: "Location"
|
|
399
|
+
},
|
|
400
|
+
joinLink: eventData.joinLink || '',
|
|
401
|
+
startTime: typeof eventData.startTime === 'string' ? parseInt(eventData.startTime) : eventData.startTime || Date.now(),
|
|
402
|
+
endTime: typeof eventData.endTime === 'string' ? parseInt(eventData.endTime) : eventData.endTime || Date.now() + 3600000,
|
|
403
|
+
extraGuestsAllowed: eventData.extraGuestsAllowed !== false
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}, { quoted });
|
|
408
|
+
|
|
409
|
+
await this.relayMessage(jid, msg.message, {
|
|
410
|
+
messageId: msg.key.id
|
|
411
|
+
});
|
|
412
|
+
return msg;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async handlePollResult(content, jid, quoted) {
|
|
416
|
+
const pollData = content.pollResultMessage;
|
|
417
|
+
|
|
418
|
+
const msg = await this.utils.generateWAMessageFromContent(jid, {
|
|
419
|
+
pollResultSnapshotMessage: {
|
|
420
|
+
name: pollData.name,
|
|
421
|
+
pollVotes: pollData.pollVotes.map(vote => ({
|
|
422
|
+
optionName: vote.optionName,
|
|
423
|
+
optionVoteCount: typeof vote.optionVoteCount === 'number'
|
|
424
|
+
? vote.optionVoteCount.toString()
|
|
425
|
+
: vote.optionVoteCount
|
|
426
|
+
}))
|
|
427
|
+
}
|
|
428
|
+
}, {
|
|
429
|
+
userJid: this.utils.generateMessageID().split('@')[0] + '@s.whatsapp.net',
|
|
430
|
+
quoted
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
await this.relayMessage(jid, msg.message, {
|
|
434
|
+
messageId: msg.key.id
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
return msg;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async handleGroupStory(content, jid, quoted) {
|
|
441
|
+
const storyData = content.groupStatusMessage;
|
|
442
|
+
let waMsgContent;
|
|
443
|
+
|
|
444
|
+
if (storyData.message) {
|
|
445
|
+
waMsgContent = storyData;
|
|
446
|
+
} else {
|
|
447
|
+
if (typeof this.bail?.generateWAMessageContent === "function") {
|
|
448
|
+
waMsgContent = await this.bail.generateWAMessageContent(storyData, {
|
|
449
|
+
upload: this.waUploadToServer
|
|
450
|
+
});
|
|
451
|
+
} else if (typeof this.utils?.generateWAMessageContent === "function") {
|
|
452
|
+
waMsgContent = await this.utils.generateWAMessageContent(storyData, {
|
|
453
|
+
upload: this.waUploadToServer
|
|
454
|
+
});
|
|
455
|
+
} else if (typeof this.utils?.prepareMessageContent === "function") {
|
|
456
|
+
waMsgContent = await this.utils.prepareMessageContent(storyData, {
|
|
457
|
+
upload: this.waUploadToServer
|
|
458
|
+
});
|
|
459
|
+
} else {
|
|
460
|
+
waMsgContent = await Utils_1.generateWAMessageContent(storyData, {
|
|
461
|
+
upload: this.waUploadToServer
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
let msg = {
|
|
467
|
+
message: {
|
|
468
|
+
groupStatusMessageV2: {
|
|
469
|
+
message: waMsgContent.message || waMsgContent
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
return await this.relayMessage(jid, msg.message, {
|
|
475
|
+
messageId: this.bail.generateMessageID()
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* socket-guard.js
|
|
5
|
+
* منقول من حماية "protoGuard" اللي كانت جوه بوت Proto.Vip، ونقلناها هنا
|
|
6
|
+
* جوه المكتبه نفسها عشان:
|
|
7
|
+
* 1) الختم بقى تلقائي جوه makeWASocket() نفسها — مفيش استدعاء يدوي
|
|
8
|
+
* ممكن يتنسى (كان قبل كده بينادى يدوي من جوه patch.js).
|
|
9
|
+
* 2) أي بوت تاني يستخدم المكتبه دي يقدر ياخد نفس الحمايه من غير ما
|
|
10
|
+
* يعيد كتابتها.
|
|
11
|
+
*
|
|
12
|
+
* 1) ختم السوكت الرسمي — لو اتشال أو اتغير التوقيع، البوت بيتوقف.
|
|
13
|
+
* 2) محاكاة الكتابة قبل تنفيذ أي أمر (مستقلة عن Anti-Ban).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import fs from "fs";
|
|
17
|
+
import path from "path";
|
|
18
|
+
|
|
19
|
+
const PROTO_MARK = Symbol.for("proto.vip.socket.mark");
|
|
20
|
+
const PROTO_MARK_VALUE = (() => {
|
|
21
|
+
// قيمة مشتقة — مش نص صريح في الكود
|
|
22
|
+
const a = [0x50, 0x52, 0x4f, 0x54, 0x4f]; // PROTO
|
|
23
|
+
const b = [0x56, 0x49, 0x50]; // VIP
|
|
24
|
+
return Buffer.from([...a, 0x2e, ...b]).toString("base64"); // "UFJPVE8uVklQ"
|
|
25
|
+
})();
|
|
26
|
+
|
|
27
|
+
function getKillFile(config) {
|
|
28
|
+
const rel = (config && config.killFilePath) || path.join("database", ".proto_kill");
|
|
29
|
+
return path.isAbsolute(rel) ? rel : path.join(process.cwd(), rel);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function isKilled(config = {}) {
|
|
33
|
+
try {
|
|
34
|
+
return fs.existsSync(getKillFile(config));
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeKill(config = {}, reason = "socket_tamper") {
|
|
41
|
+
try {
|
|
42
|
+
const killFile = getKillFile(config);
|
|
43
|
+
const dir = path.dirname(killFile);
|
|
44
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
45
|
+
fs.writeFileSync(killFile, JSON.stringify({ at: Date.now(), reason }), "utf8");
|
|
46
|
+
} catch {}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* ختم السوكت — بتتنادى تلقائي جوه makeWASocket()، مش محتاجه تتنادى يدوي.
|
|
51
|
+
*/
|
|
52
|
+
function stampSocket(sock) {
|
|
53
|
+
if (!sock || typeof sock !== "object") return sock;
|
|
54
|
+
try {
|
|
55
|
+
if (!(PROTO_MARK in sock)) {
|
|
56
|
+
Object.defineProperty(sock, PROTO_MARK, {
|
|
57
|
+
value: PROTO_MARK_VALUE,
|
|
58
|
+
enumerable: false,
|
|
59
|
+
configurable: false,
|
|
60
|
+
writable: false,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (!("__protoVip" in sock)) {
|
|
64
|
+
Object.defineProperty(sock, "__protoVip", {
|
|
65
|
+
value: true,
|
|
66
|
+
enumerable: false,
|
|
67
|
+
configurable: false,
|
|
68
|
+
writable: false,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
// لو اتعرّف قبل كده
|
|
73
|
+
}
|
|
74
|
+
return sock;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* التحقق إن السوكت هو سوكت رسمي مختوم من نفس المكتبه.
|
|
79
|
+
*/
|
|
80
|
+
function verifySocket(sock, config = {}) {
|
|
81
|
+
if (isKilled(config)) return false;
|
|
82
|
+
if (!sock || typeof sock !== "object") return false;
|
|
83
|
+
try {
|
|
84
|
+
if (sock[PROTO_MARK] !== PROTO_MARK_VALUE) return false;
|
|
85
|
+
if (sock.__protoVip !== true) return false;
|
|
86
|
+
if (typeof sock.sendMessage !== "function") return false;
|
|
87
|
+
return true;
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* لو السوكت مش سليم: يبعت رساله تحذير (قابله للتخصيص عبر config.killMessage)
|
|
95
|
+
* ويقفل البوت للأبد.
|
|
96
|
+
*/
|
|
97
|
+
async function enforceSocketOrDie(sock, chatId, config = {}) {
|
|
98
|
+
if (verifySocket(sock, config)) return true;
|
|
99
|
+
|
|
100
|
+
writeKill(config);
|
|
101
|
+
|
|
102
|
+
const msg = config.killMessage || "لا يمكنك استخدام هذا بوت";
|
|
103
|
+
try {
|
|
104
|
+
if (sock && typeof sock.sendMessage === "function" && chatId) {
|
|
105
|
+
await sock.sendMessage(chatId, { text: msg });
|
|
106
|
+
}
|
|
107
|
+
} catch {}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
console.error("[SOCKET-GUARD] Socket integrity failed — bot disabled permanently.");
|
|
111
|
+
} catch {}
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
try {
|
|
114
|
+
process.exit(1);
|
|
115
|
+
} catch {}
|
|
116
|
+
}, 1500);
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* محاكاة الكتابة قبل تنفيذ الأمر — شغاله حتى لو Anti-Ban مقفول.
|
|
122
|
+
*/
|
|
123
|
+
async function simulateTyping(sock, chatId, minMs = 400, maxMs = 1400) {
|
|
124
|
+
if (!sock || !chatId) return;
|
|
125
|
+
try {
|
|
126
|
+
if (typeof sock.sendPresenceUpdate === "function") {
|
|
127
|
+
await sock.sendPresenceUpdate("composing", chatId);
|
|
128
|
+
} else if (typeof sock.presenceSubscribe === "function") {
|
|
129
|
+
try {
|
|
130
|
+
await sock.presenceSubscribe(chatId);
|
|
131
|
+
} catch {}
|
|
132
|
+
}
|
|
133
|
+
} catch {}
|
|
134
|
+
|
|
135
|
+
const delay = minMs + Math.floor(Math.random() * Math.max(1, maxMs - minMs));
|
|
136
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
if (typeof sock.sendPresenceUpdate === "function") {
|
|
140
|
+
await sock.sendPresenceUpdate("paused", chatId);
|
|
141
|
+
}
|
|
142
|
+
} catch {}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export {
|
|
146
|
+
stampSocket,
|
|
147
|
+
verifySocket,
|
|
148
|
+
enforceSocketOrDie,
|
|
149
|
+
simulateTyping,
|
|
150
|
+
isKilled,
|
|
151
|
+
writeKill,
|
|
152
|
+
PROTO_MARK,
|
|
153
|
+
PROTO_MARK_VALUE,
|
|
154
|
+
};
|
package/package.json
CHANGED