@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,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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prototypevip/baileys",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Baileys fork (@prototypevip/baileys) — clean, without anti-ban, group encryption disabled (like 0.0.8)",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",