@prototypevip/baileys 0.1.3 → 0.1.5
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/HELPERS.md +107 -0
- package/lib/Socket/index.js +30 -15
- package/lib/Utils/index.js +4 -0
- package/lib/Utils/messages-media.js +6 -3
- package/lib/Utils/messages.js +1 -0
- package/lib/Utils/modern-messages.js +10 -0
- package/lib/Utils/newsletter-status.js +652 -0
- package/lib/Utils/prototype-helpers.js +610 -0
- package/lib/Utils/status-helpers.js +143 -0
- package/package.json +11 -4
package/HELPERS.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @prototypevip/baileys — Helpers (v0.1.5)
|
|
2
|
+
|
|
3
|
+
طبقة helpers فوق المسارات الأصلية في المكتبة (`sock.sendMessage` → `nativeFlow` / `album` / `code` / `event` / `product`).
|
|
4
|
+
مفيش بروتوكول جديد هنا؛ كل دالة بتفوّض لمسار موجود ومجرَّب.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
```js
|
|
9
|
+
import makeWASocket, { attachPrototypeHelpers } from '@prototypevip/baileys'
|
|
10
|
+
|
|
11
|
+
const sock = makeWASocket({ ... })
|
|
12
|
+
attachPrototypeHelpers(sock)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
الدوال متاحة كمان كـ named exports: `sendButtons(sock, jid, content, options)` … إلخ.
|
|
16
|
+
|
|
17
|
+
## أزرار / قوائم
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
await sock.sendButtons(jid, {
|
|
21
|
+
text: 'اختار', footer: 'Prototype VIP',
|
|
22
|
+
buttons: [
|
|
23
|
+
{ text: 'Menu', id: '#menu' },
|
|
24
|
+
{ text: 'موقع', url: 'https://example.com' },
|
|
25
|
+
{ text: 'نسخ', copy: 'CODE' },
|
|
26
|
+
{ text: 'اتصل', call: '201234567890' }
|
|
27
|
+
]
|
|
28
|
+
}, { quoted: m })
|
|
29
|
+
|
|
30
|
+
// مع ميديا (بتتحوّل لـ header): image | video | document
|
|
31
|
+
await sock.sendButtons(jid, { text: 'كابشن', image: { url: '...' }, buttons: [...] })
|
|
32
|
+
|
|
33
|
+
// أيقونة AI (شات خاص فقط — في الجروب بتتجاهل)
|
|
34
|
+
await sock.sendAIMessage(jid, { text: 'أهلا', buttons: [...] })
|
|
35
|
+
|
|
36
|
+
// قائمة اختيار (single_select داخل Native Flow). legacy: true = listMessage الكلاسيكي
|
|
37
|
+
await sock.sendList(jid, {
|
|
38
|
+
text: 'القائمة', title: 'T', buttonText: 'افتح',
|
|
39
|
+
sections: [{ title: 'قسم', rows: [{ title: 'A', description: 'd', id: '#a' }] }]
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
await sock.sendQuickButtons(jid, 'اختار', ['نعم', 'لا'])
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## ألبوم / Carousel
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
await sock.sendAlbum(jid, [{ image: { url } , caption: '1' }, { video: { url } }], { delayMs: 1500 })
|
|
49
|
+
|
|
50
|
+
// Carousel حقيقي (كل كارت لازم image أو video)
|
|
51
|
+
await sock.sendCarousel(jid, {
|
|
52
|
+
text: 'منتجات', footer: 'Prototype VIP',
|
|
53
|
+
cards: [{ title: 'منتج 1', body: 'وصف', image: 'https://...', buttons: [{ text: 'اشتري', id: '#buy1' }] }]
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Rich (شكل Meta AI)
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
await sock.sendRichCode(jid, { title: 'مثال', code: 'console.log(1)', language: 'javascript' })
|
|
61
|
+
|
|
62
|
+
// ⚠️ HTML: مفيش render حقيقي لـ HTML جوه الفقاعة في المكتبة.
|
|
63
|
+
// sendRichHtml بيبعت الـ HTML كـ code block ملوّن داخل Rich Response.
|
|
64
|
+
await sock.sendRichHtml(jid, { title: 'Card', html: '<div>...</div>' })
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## مكالمات
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
// Scheduled Call Event (مفيش WebRTC outbound حقيقي في Baileys)
|
|
71
|
+
await sock.sendScheduledCall(jid, { name: 'اجتماع', startDate: new Date(Date.now() + 3600_000), callType: 'audio' })
|
|
72
|
+
await sock.sendCallInvite(jid, { name: 'مكالمة سريعة', callType: 'video', minutesFromNow: 2 })
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## متفرقات
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
await sock.sendViewOnce(jid, { image: { url }, caption: 'مرة واحدة' })
|
|
79
|
+
await sock.sendPoll(jid, 'رأيك؟', ['حلو', 'عادي'], { selectableCount: 1 })
|
|
80
|
+
await sock.sendReaction(jid, m.key, '🔥')
|
|
81
|
+
await sock.sendMentionAll(groupJid, 'يا جماعة')
|
|
82
|
+
await sock.sendLocation(jid, 30.04, 31.23, { name: 'القاهرة', address: '...' })
|
|
83
|
+
await sock.sendContact(jid, { fullName: 'أحمد', phone: '201234567890' })
|
|
84
|
+
await sock.sendProduct(jid, { title: 'منتج', price: 100, currencyCode: 'EGP', image: 'https://...' }) // الصورة مطلوبة
|
|
85
|
+
await sock.sendSticker(jid, { url: 'https://.../x.webp' })
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## JID / LID
|
|
89
|
+
|
|
90
|
+
الـ LID **مش** مشتق من رقم التليفون، فالتحويل بيعتمد على mapping حقيقي (`sock.signalRepository.lidMapping`)
|
|
91
|
+
وبيرجّع `null` لو الـ mapping مش معروف.
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
await sock.toLid('2010xxxxxxx@s.whatsapp.net') // → '...@lid' | null (async)
|
|
95
|
+
await sock.toPn('...@lid') // → '...@s.whatsapp.net' | null (async)
|
|
96
|
+
sock.normalizeJid('201...:12@s.whatsapp.net') // يشيل رقم الجهاز بس
|
|
97
|
+
sock.isLid(jid); sock.isPn(jid)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Builders
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
const btn = sock.button() // Button
|
|
104
|
+
const car = sock.carouselBuilder()
|
|
105
|
+
const rich = sock.aiRich()
|
|
106
|
+
// chain methods ثم .send(jid)
|
|
107
|
+
```
|
package/lib/Socket/index.js
CHANGED
|
@@ -2,15 +2,22 @@ import { DEFAULT_CONNECTION_CONFIG } from "../Defaults/index.js";
|
|
|
2
2
|
import { makeCommunitiesSocket } from "./communities.js";
|
|
3
3
|
import { stampSocket } from "../Utils/socket-guard.js";
|
|
4
4
|
import { verifyBrandIntegrity } from "../Utils/integrity-guard.js";
|
|
5
|
+
import {
|
|
6
|
+
makeNewsletterStatusSender,
|
|
7
|
+
makeNewsletterStatusReactionSender,
|
|
8
|
+
makeNewsletterStatusRevokeSender,
|
|
9
|
+
makeNewsletterStatusFetcher,
|
|
10
|
+
makeNewsletterStatusUpdatesFetcher,
|
|
11
|
+
} from "../Utils/newsletter-status.js";
|
|
12
|
+
import { sendPersonalStatus, sendGroupStatus } from "../Utils/status-helpers.js";
|
|
5
13
|
|
|
6
14
|
/**
|
|
7
15
|
* Create a WhatsApp socket.
|
|
8
16
|
* Clean version — without AntiBan.
|
|
17
|
+
* v0.1.4 — Channel Status + Group Status + Personal Status APIs
|
|
9
18
|
*/
|
|
10
19
|
const makeWASocket = (config = {}) => {
|
|
11
|
-
// بصمة "prototype" بتتفحص هنا تلقائي — قبل حتى ما أي سوكت
|
|
12
|
-
// محتاجه استدعاء يدوي من البوت (نفس فلسفة stampSocket تحت). لو حد فَكّ
|
|
13
|
-
// اسم الباكدج أو غيّر بايتات البصمة يدوي، المكتبه بترفض تشتغل خالص.
|
|
20
|
+
// بصمة "prototype" بتتفحص هنا تلقائي — قبل حتى ما أي سوكت يتبني
|
|
14
21
|
if (!verifyBrandIntegrity()) {
|
|
15
22
|
try {
|
|
16
23
|
console.error("[INTEGRITY-GUARD] brand fingerprint mismatch — refusing to start.");
|
|
@@ -32,14 +39,7 @@ const makeWASocket = (config = {}) => {
|
|
|
32
39
|
|
|
33
40
|
const newConfig = { ...DEFAULT_CONNECTION_CONFIG, ...restConfig };
|
|
34
41
|
|
|
35
|
-
//
|
|
36
|
-
// DEFAULT_CONNECTION_CONFIG مباشره كـ `config` وبتقرا منها وقت التشغيل
|
|
37
|
-
// (مش الـ newConfig المدموج فوق)، فأي override زي generateMessageID/
|
|
38
|
-
// generateMessageIDV2 بيتحط هنا كان بيتضاع تماما - الكود الداخلي في
|
|
39
|
-
// المكتبه (زي توليد id الأزرار) كان بيفضل يستخدم القيم الافتراضيه
|
|
40
|
-
// الأصليه (GIN4B0T/G1N4B0T) حتى لو المستخدم غيّرها في makeWASocket().
|
|
41
|
-
// بنعمل mutate للـ object المشترك نفسه عشان أي import ثابت ليه في باقي
|
|
42
|
-
// المكتبه ياخد نفس القيم المدموجه.
|
|
42
|
+
// mutate shared DEFAULT so internal imports see overrides
|
|
43
43
|
Object.assign(DEFAULT_CONNECTION_CONFIG, newConfig);
|
|
44
44
|
|
|
45
45
|
let sock;
|
|
@@ -52,11 +52,26 @@ const makeWASocket = (config = {}) => {
|
|
|
52
52
|
|
|
53
53
|
sock = makeCommunitiesSocket(newConfig);
|
|
54
54
|
|
|
55
|
-
// ختم السوكت تلقائي
|
|
56
|
-
// يدوي بعد ما السوكت يترجع (وده كان سهل يتنسى في ملف 2300+ سطر زي
|
|
57
|
-
// patch.js)، دلوقتي أي سوكت طالع من makeWASocket() بيتختم لوحده.
|
|
55
|
+
// ختم السوكت تلقائي
|
|
58
56
|
stampSocket(sock);
|
|
59
57
|
|
|
58
|
+
// ── Channels & Stories APIs (0.1.4) ──────────────────────────
|
|
59
|
+
// Newsletter / Channel status (Elaina-style transport)
|
|
60
|
+
sock.sendNewsletterStatus = makeNewsletterStatusSender(sock, newConfig);
|
|
61
|
+
sock.sendChannelStatus = sock.sendNewsletterStatus; // alias
|
|
62
|
+
sock.sendNewsletterStatusReaction = makeNewsletterStatusReactionSender(sock);
|
|
63
|
+
sock.revokeNewsletterStatus = makeNewsletterStatusRevokeSender(sock);
|
|
64
|
+
sock.getNewsletterStatuses = makeNewsletterStatusFetcher(sock);
|
|
65
|
+
sock.getNewsletterStatusUpdates = makeNewsletterStatusUpdatesFetcher(sock);
|
|
66
|
+
|
|
67
|
+
// Personal story (status@broadcast)
|
|
68
|
+
sock.sendPersonalStatus = (content, statusJidList, options) =>
|
|
69
|
+
sendPersonalStatus(sock, content, statusJidList, options);
|
|
70
|
+
|
|
71
|
+
// Group story (groupStatusMessageV2 / groupStatus flag)
|
|
72
|
+
sock.sendGroupStatus = (groupJid, content, options) =>
|
|
73
|
+
sendGroupStatus(sock, groupJid, content, options);
|
|
74
|
+
|
|
60
75
|
return sock;
|
|
61
76
|
};
|
|
62
77
|
|
|
@@ -67,4 +82,4 @@ const wrapSocketWithFingerprint = (makeSock, opts) =>
|
|
|
67
82
|
const PRESETS = {};
|
|
68
83
|
|
|
69
84
|
export default makeWASocket;
|
|
70
|
-
export { makeWASocket, wrapSocket, wrapSocketWithFingerprint, PRESETS };
|
|
85
|
+
export { makeWASocket, wrapSocket, wrapSocketWithFingerprint, PRESETS };
|
package/lib/Utils/index.js
CHANGED
|
@@ -31,3 +31,7 @@ export * from "./ai-rich-formatter.js";
|
|
|
31
31
|
export * from "./constants.js";
|
|
32
32
|
export * from "./socket-guard.js";
|
|
33
33
|
export * from "./integrity-guard.js";
|
|
34
|
+
export * from "./newsletter-status.js";
|
|
35
|
+
export * from "./status-helpers.js";
|
|
36
|
+
export * from "./modern-messages.js";
|
|
37
|
+
export * from "./prototype-helpers.js";
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
DEFAULT_ORIGIN,
|
|
18
18
|
MEDIA_HKDF_KEY_MAPPING,
|
|
19
19
|
MEDIA_PATH_MAP,
|
|
20
|
+
NEWSLETTER_MEDIA_PATH_MAP,
|
|
20
21
|
} from "../Defaults/index.js";
|
|
21
22
|
import {
|
|
22
23
|
getBinaryNodeChild,
|
|
@@ -725,7 +726,7 @@ export const getWAUploadToServer = (
|
|
|
725
726
|
{ customUploadHosts, fetchAgent, logger, options },
|
|
726
727
|
refreshMediaConn,
|
|
727
728
|
) => {
|
|
728
|
-
return async (filePath, { mediaType, fileEncSha256B64, timeoutMs }) => {
|
|
729
|
+
return async (filePath, { mediaType, fileEncSha256B64, timeoutMs, newsletter }) => {
|
|
729
730
|
// send a query JSON to obtain the url & auth token to upload our media
|
|
730
731
|
let uploadInfo = await refreshMediaConn(false);
|
|
731
732
|
let urls;
|
|
@@ -745,7 +746,8 @@ export const getWAUploadToServer = (
|
|
|
745
746
|
for (const { hostname } of hosts) {
|
|
746
747
|
logger.debug(`uploading to "${hostname}"`);
|
|
747
748
|
const auth = encodeURIComponent(uploadInfo.auth);
|
|
748
|
-
const
|
|
749
|
+
const mediaPath = (newsletter && NEWSLETTER_MEDIA_PATH_MAP[mediaType]) || MEDIA_PATH_MAP[mediaType];
|
|
750
|
+
const url = `https://${hostname}${mediaPath}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
|
|
749
751
|
let result;
|
|
750
752
|
try {
|
|
751
753
|
result = await uploadMedia(
|
|
@@ -758,8 +760,9 @@ export const getWAUploadToServer = (
|
|
|
758
760
|
},
|
|
759
761
|
logger,
|
|
760
762
|
);
|
|
761
|
-
if (result?.url || result?.direct_path) {
|
|
763
|
+
if (result?.url || result?.direct_path || (newsletter && result?.handle)) {
|
|
762
764
|
urls = {
|
|
765
|
+
handle: result.handle,
|
|
763
766
|
mediaUrl: result.url,
|
|
764
767
|
directPath: result.direct_path,
|
|
765
768
|
meta_hmac: result.meta_hmac,
|
package/lib/Utils/messages.js
CHANGED
|
@@ -402,6 +402,7 @@ export const prepareWAMessageMedia = async (message, options) => {
|
|
|
402
402
|
fileEncSha256B64: fileSha256B64,
|
|
403
403
|
mediaType: mediaType,
|
|
404
404
|
timeoutMs: options.mediaUploadTimeoutMs,
|
|
405
|
+
newsletter: true,
|
|
405
406
|
});
|
|
406
407
|
await fs.unlink(filePath);
|
|
407
408
|
const obj = WAProto.Message.fromObject({
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal modern-messages shim for @prototypevip/baileys
|
|
3
|
+
* Full Elaina modern message builders are optional; status APIs only need identity transform.
|
|
4
|
+
*/
|
|
5
|
+
export const prepareModernMessageContent = (content) => {
|
|
6
|
+
if (!content || typeof content !== "object") return content;
|
|
7
|
+
return content;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default { prepareModernMessageContent };
|