sauruspro-bail 5.0.2-alpha.spr.test โ 5.0.3
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/README.md +233 -48
- package/docs/CHANGELOG.md +44 -30
- package/docs/SPR.md +1 -1
- package/lib/Socket/index.js +37 -6
- package/lib/Socket/socket.js +80 -50
- package/lib/Utils/crypto.js +25 -1
- package/lib/Utils/greeting-card.d.ts +15 -0
- package/lib/Utils/greeting-card.js +70 -0
- package/lib/Utils/group-history.d.ts +4 -0
- package/lib/Utils/group-history.js +58 -0
- package/lib/Utils/index.js +6 -0
- package/lib/Utils/meta-ai-bot.d.ts +10 -0
- package/lib/Utils/meta-ai-bot.js +94 -0
- package/lib/Utils/native-backend.d.ts +3 -0
- package/lib/Utils/native-backend.js +56 -0
- package/lib/Utils/plugins.d.ts +20 -0
- package/lib/Utils/plugins.js +78 -0
- package/lib/Utils/presence-profile.d.ts +18 -0
- package/lib/Utils/presence-profile.js +50 -0
- package/lib/index.js +14 -4
- package/package.json +7 -3
- package/docs/NEWSLETTER-STATUS.md +0 -120
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# ๐ฆ SAURUSPRO BAILEYS
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**WhatsApp Web API untuk Node.js, lengkap dengan Rich Message, SPR, dan Newsletter Status**
|
|
6
6
|
|
|
7
7
|
<img src="https://cdn.saurus.qzz.io/image/EGYoX.png" width="140" alt="Sauruspro">
|
|
8
8
|
|
|
@@ -11,35 +11,41 @@
|
|
|
11
11
|

|
|
12
12
|

|
|
13
13
|
|
|
14
|
-
**Owner: Saurus / Dinonic** ยท **Version: 5.0.2-alpha.spr.test**
|
|
15
|
-
|
|
16
14
|
</div>
|
|
17
15
|
|
|
18
16
|
---
|
|
19
17
|
|
|
20
|
-
##
|
|
18
|
+
## ๐ Apa itu Baileys?
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
**Baileys** adalah library JavaScript/TypeScript yang berbicara langsung dengan server WhatsApp lewat **WebSocket**, sama seperti WhatsApp Web, tetapi **tanpa browser** dan tanpa Selenium/Puppeteer. Dengan Baileys kamu bisa membuat bot atau aplikasi yang:
|
|
21
|
+
|
|
22
|
+
- login sebagai *linked device* (perangkat tertaut) lewat **QR** atau **pairing code**,
|
|
23
|
+
- mengirim dan menerima pesan (teks, gambar, video, stiker, poll, dll),
|
|
24
|
+
- mengelola grup, komunitas, channel (newsletter), dan profil,
|
|
25
|
+
- berjalan ringan karena hanya memakai protokol multi-device, bukan emulasi browser.
|
|
26
|
+
|
|
27
|
+
**Sauruspro Baileys (`sauruspro-bail`)** adalah turunan Baileys dengan fitur tambahan:
|
|
28
|
+
|
|
29
|
+
| Fitur | Isi |
|
|
23
30
|
|---|---|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
31
|
+
| ๐ฌ **Rich Message** | `AIRich`, Carousel, Button, Native Flow, A2UI |
|
|
32
|
+
| ๐ฏ **SPR (Selective Relay)** | Kirim pesan hanya ke device tertentu, pesan khusus per orang |
|
|
33
|
+
| ๐ข **Newsletter Status** | Kirim, react, hapus, dan ambil status Channel |
|
|
34
|
+
| ๐ชช **Greeting Card `/buss`** | Kartu sapaan untuk WhatsApp Business |
|
|
35
|
+
| ๐งฉ **Plugin system** | `sock.use(plugin)` dan fitur bawaan bisa dimatikan |
|
|
36
|
+
| ๐ค **Presence & Profile API** | `sock.presence.*` dan `sock.profile.*` yang lebih rapi |
|
|
37
|
+
| โก **Native crypto (opsional)** | X25519 dan XEdDSA lebih cepat jika `@zapo-js/native` terpasang |
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
> Beberapa fitur diadaptasi dari [zapo-js](https://github.com/vinikjkkj/zapo) (MIT).
|
|
32
40
|
|
|
33
|
-
|
|
41
|
+
## ๐ฆ Info Paket
|
|
42
|
+
|
|
43
|
+
| | |
|
|
34
44
|
|---|---|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
| ๐ LID & PN | Kompatibel LID dan nomor telepon |
|
|
40
|
-
| ๐ค Username | Fetch username |
|
|
41
|
-
| ๐ฅ Groups & Communities | Manajemen grup dan komunitas |
|
|
42
|
-
| ๐๏ธ Auth | Multi-file & SQLite auth state |
|
|
45
|
+
| Nama | `sauruspro-bail` |
|
|
46
|
+
| Modul | ESM (`"type": "module"`), bisa dipakai dari CommonJS (lihat di bawah) |
|
|
47
|
+
| Node.js | >= 20 |
|
|
48
|
+
| Telegram | [@lordsaurus](https://t.me/lordsaurus) |
|
|
43
49
|
|
|
44
50
|
## ๐ Install
|
|
45
51
|
|
|
@@ -47,44 +53,214 @@
|
|
|
47
53
|
npm install sauruspro-bail
|
|
48
54
|
```
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## ๐ Menghubungkan ke WhatsApp (bot)
|
|
59
|
+
|
|
60
|
+
Ada dua cara login: **QR code** atau **pairing code** (kode 8 karakter yang dimasukkan di HP). Sesi disimpan di folder, jadi login hanya perlu sekali.
|
|
61
|
+
|
|
62
|
+
### Contoh lengkap (pairing code + reconnect)
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
import makeWASocket, {
|
|
66
|
+
useMultiFileAuthState,
|
|
67
|
+
DisconnectReason,
|
|
68
|
+
Browsers
|
|
69
|
+
} from 'sauruspro-bail'
|
|
70
|
+
|
|
71
|
+
const NOMOR = '628123456789' // format internasional, tanpa +, spasi, atau strip
|
|
72
|
+
|
|
73
|
+
async function start() {
|
|
74
|
+
const { state, saveCreds } = await useMultiFileAuthState('session')
|
|
75
|
+
|
|
76
|
+
const sock = makeWASocket({
|
|
77
|
+
auth: state,
|
|
78
|
+
browser: Browsers.ubuntu('Chrome') // dianjurkan untuk pairing code
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// simpan kredensial setiap kali berubah
|
|
82
|
+
sock.ev.on('creds.update', saveCreds)
|
|
83
|
+
|
|
84
|
+
// minta pairing code hanya jika belum login
|
|
85
|
+
if (!sock.authState.creds.registered) {
|
|
86
|
+
const code = await sock.requestPairingCode(NOMOR)
|
|
87
|
+
console.log('Pairing code:', code.match(/.{1,4}/g).join('-'))
|
|
88
|
+
// HP: WhatsApp > Perangkat tertaut > Tautkan perangkat > Tautkan dengan nomor telepon
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// status koneksi + reconnect otomatis
|
|
92
|
+
sock.ev.on('connection.update', ({ connection, lastDisconnect }) => {
|
|
93
|
+
if (connection === 'open') console.log('โ
Bot terhubung')
|
|
94
|
+
if (connection === 'close') {
|
|
95
|
+
const status = lastDisconnect?.error?.output?.statusCode
|
|
96
|
+
if (status === DisconnectReason.loggedOut) {
|
|
97
|
+
console.log('Logout. Hapus folder "session" lalu jalankan ulang.')
|
|
98
|
+
} else {
|
|
99
|
+
start() // koneksi putus, sambungkan lagi
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// contoh membalas pesan
|
|
105
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
106
|
+
const msg = messages[0]
|
|
107
|
+
if (!msg?.message || msg.key.fromMe) return
|
|
108
|
+
const teks = msg.message.conversation || msg.message.extendedTextMessage?.text
|
|
109
|
+
if (teks === 'ping') {
|
|
110
|
+
await sock.sendMessage(msg.key.remoteJid, { text: 'pong' }, { quoted: msg })
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
start()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Catatan pairing code
|
|
119
|
+
|
|
120
|
+
- Setiap pemanggilan `requestPairingCode` menghasilkan **kode acak baru**. Kamu juga bisa memakai kode sendiri: `requestPairingCode(NOMOR, 'ABCD1234')` (8 karakter, `A-Z` dan `0-9`).
|
|
121
|
+
- Nomor otomatis dibersihkan, jadi `+62 812-3456-789` tetap diterima.
|
|
122
|
+
- Jika sesi sudah login (`registered`), pairing ditolak. Hapus folder sesi untuk login ulang.
|
|
123
|
+
- Kode berlaku singkat. Kalau kedaluwarsa, panggil `requestPairingCode` lagi.
|
|
124
|
+
|
|
125
|
+
### Login dengan QR
|
|
51
126
|
|
|
52
|
-
|
|
127
|
+
Dengarkan event `connection.update` dan tampilkan `qr` (misalnya dengan paket `qrcode-terminal`):
|
|
53
128
|
|
|
54
129
|
```js
|
|
55
|
-
|
|
130
|
+
sock.ev.on('connection.update', ({ qr }) => {
|
|
131
|
+
if (qr) console.log('Scan QR ini di WhatsApp:', qr)
|
|
132
|
+
})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Menyimpan sesi di SQLite (opsional)
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
import { useSqliteAuthState } from 'sauruspro-bail'
|
|
139
|
+
const { state, saveCreds } = await useSqliteAuthState('session.db')
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
56
143
|
|
|
57
|
-
|
|
58
|
-
const sock = makeWASocket({ auth: state })
|
|
144
|
+
## ๐ Memakai dari CommonJS (`require`)
|
|
59
145
|
|
|
60
|
-
|
|
146
|
+
Paket ini ESM. Dari file `.js`/`.cjs` biasa, ada dua cara:
|
|
61
147
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
148
|
+
**1. `import()` dinamis (semua versi Node 20+, paling aman)**
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
// index.cjs
|
|
152
|
+
async function main() {
|
|
153
|
+
const { default: makeWASocket, useMultiFileAuthState } = await import('sauruspro-bail')
|
|
154
|
+
|
|
155
|
+
const { state, saveCreds } = await useMultiFileAuthState('session')
|
|
156
|
+
const sock = makeWASocket({ auth: state })
|
|
157
|
+
sock.ev.on('creds.update', saveCreds)
|
|
66
158
|
}
|
|
159
|
+
main()
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**2. `require()` langsung (Node 22.12+ atau Node 20.19+)**
|
|
163
|
+
|
|
164
|
+
```js
|
|
165
|
+
const baileys = require('sauruspro-bail')
|
|
166
|
+
const makeWASocket = baileys.default
|
|
167
|
+
const { useMultiFileAuthState } = baileys
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Pada Node versi lama, `require('sauruspro-bail')` akan error `ERR_REQUIRE_ESM`. Pakai cara pertama.
|
|
171
|
+
|
|
172
|
+
Mau ubah proyekmu jadi ESM saja? Tambahkan `"type": "module"` di `package.json` proyekmu lalu pakai `import`.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## ๐ฌ Rich Message (AIRich)
|
|
177
|
+
|
|
178
|
+
Rich Message adalah balasan bergaya Meta AI: teks, kode, tabel, gambar, dan lainnya dalam satu pesan. Dibuat dengan builder `sock.AIRich`.
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
const rich = new sock.AIRich(sock)
|
|
182
|
+
|
|
183
|
+
rich
|
|
184
|
+
.addText('Halo! Ini **Rich Message** dari Sauruspro.')
|
|
185
|
+
.addCode('javascript', "console.log('halo dunia')")
|
|
186
|
+
.addTable([
|
|
187
|
+
['Fitur', 'Status'],
|
|
188
|
+
['SPR', 'Aktif'],
|
|
189
|
+
['Newsletter Status', 'Aktif']
|
|
190
|
+
])
|
|
191
|
+
|
|
192
|
+
await rich.send(jid)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Cara singkat tanpa builder:
|
|
196
|
+
|
|
197
|
+
```js
|
|
198
|
+
import { sendAIRichMessage } from 'sauruspro-bail'
|
|
199
|
+
|
|
200
|
+
await sendAIRichMessage(sock, jid, { text: 'Halo dari Rich Message!' })
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Builder lain yang tersedia: `sock.Carousel`, `sock.Button`, `sock.ButtonV2`, `sock.Toolkit`. Pesan `interactiveMessage`, `buttonsMessage`, `flowMessage`, dan `carouselMessage` juga bisa dikirim lewat `sock.sendMessage`.
|
|
204
|
+
|
|
205
|
+
> Rich Message memakai fitur WhatsApp yang bisa berubah. Tampilannya bergantung pada versi aplikasi penerima.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## ๐ฏ SPR (Selective Relay)
|
|
210
|
+
|
|
211
|
+
SPR mengontrol **siapa membaca apa** dalam satu pesan grup. Tiap device penerima masuk salah satu peran:
|
|
212
|
+
|
|
213
|
+
| Peran | Yang diterima |
|
|
214
|
+
|---|---|
|
|
215
|
+
| `public` | pesan umum |
|
|
216
|
+
| `personal` | pesan khusus miliknya saja |
|
|
217
|
+
| `hidden` | tidak menerima apa-apa |
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
// Sembunyikan pesan dari 1 orang
|
|
221
|
+
await sock.sPR(groupJid, { conversation: 'rahasia' }, {
|
|
222
|
+
mode: 'exclude', // 'include' = hanya target yang menerima
|
|
223
|
+
target: ['6281234567890@s.whatsapp.net']
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
// Pesan umum untuk semua, pesan lain khusus untuk A
|
|
227
|
+
await sock.sPR(groupJid, { conversation: 'info umum' }, {
|
|
228
|
+
personal: { '6281234567890@s.whatsapp.net': { conversation: 'info khusus kamu' } }
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
// Anggota lain lihat publicText, targetJid lihat privateText + foto profilnya
|
|
232
|
+
await sock.sPRPrivate(groupJid, targetJid, {
|
|
233
|
+
publicText: 'Pesan ini memiliki isi khusus untuk beberapa penerima.',
|
|
234
|
+
privateText: 'rahasia buat kamu'
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
// Tiap anggota menerima pesan sendiri, {name} menjadi @mention orang itu
|
|
238
|
+
await sock.sPRBroadcast(groupJid, { template: 'Halo {name}, ada pesan untukmu.', limit: 100 })
|
|
67
239
|
```
|
|
68
240
|
|
|
241
|
+
Opsi lengkap dan penjelasan lebih dalam: **[docs/SPR.md](docs/SPR.md)**
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
69
245
|
## ๐ข Newsletter Status
|
|
70
246
|
|
|
71
|
-
Kirim status ke Channel (newsletter) yang kamu admin-i.
|
|
247
|
+
Kirim status ke **Channel (newsletter)** yang kamu admin-i. JID channel berakhiran `@newsletter`.
|
|
72
248
|
|
|
73
249
|
```js
|
|
74
250
|
const jid = '120363xxxxxxxxxxxxx@newsletter'
|
|
75
251
|
|
|
76
252
|
// Teks
|
|
77
253
|
const sent = await sock.newsletter.sendStatus(jid, { text: 'Halo Channel!' })
|
|
78
|
-
console.log(sent.newsletterStatusServerId)
|
|
254
|
+
console.log(sent.newsletterStatusServerId) // dipakai untuk react / revoke
|
|
79
255
|
|
|
80
|
-
// Gambar
|
|
81
|
-
await sock.
|
|
256
|
+
// Gambar atau video
|
|
257
|
+
await sock.newsletter.sendStatus(jid, {
|
|
82
258
|
image: { url: './foto.jpg' },
|
|
83
259
|
caption: 'Update terbaru'
|
|
84
260
|
})
|
|
85
261
|
|
|
86
|
-
// React ke status
|
|
87
|
-
await sock.newsletter.reactToStatus(jid,
|
|
262
|
+
// React ke status
|
|
263
|
+
await sock.newsletter.reactToStatus(jid, sent.newsletterStatusServerId, '๐ฅ')
|
|
88
264
|
|
|
89
265
|
// Hapus status
|
|
90
266
|
await sock.newsletter.revokeStatus(jid, statusId)
|
|
@@ -93,27 +269,36 @@ await sock.newsletter.revokeStatus(jid, statusId)
|
|
|
93
269
|
const list = await sock.newsletter.fetchStatuses(jid, { count: 20 })
|
|
94
270
|
```
|
|
95
271
|
|
|
96
|
-
|
|
272
|
+
Semua fungsi juga tersedia langsung di socket: `sock.sendNewsletterStatus(...)`, `sock.sendNewsletterStatusReaction(...)`, dan seterusnya.
|
|
97
273
|
|
|
98
|
-
|
|
274
|
+
Dokumentasi jenis konten, opsi, dan error: lihat tipe di `lib/Utils/newsletter-status.d.ts`.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## ๐งฉ Fitur lain
|
|
99
279
|
|
|
100
280
|
```js
|
|
101
|
-
|
|
102
|
-
|
|
281
|
+
// Greeting Card /buss (hanya terlihat di WhatsApp Business)
|
|
282
|
+
await sock.sendGreetingCard(jid, {
|
|
283
|
+
text: 'wow', title: 'Judul Kartu', greeting: 'Hi Business',
|
|
284
|
+
imageUrl: 'https://.../img.jpg', contactUrl: 'https://wa.me/NOMOR'
|
|
285
|
+
})
|
|
103
286
|
|
|
104
|
-
//
|
|
105
|
-
await sock.
|
|
106
|
-
await sock.
|
|
107
|
-
```
|
|
287
|
+
// Presence & profile
|
|
288
|
+
await sock.presence.withTyping(jid, () => sock.sendMessage(jid, { text: 'halo' }))
|
|
289
|
+
await sock.profile.setStatus('Bot aktif')
|
|
108
290
|
|
|
109
|
-
|
|
291
|
+
// Plugin
|
|
292
|
+
import { definePlugin } from 'sauruspro-bail'
|
|
293
|
+
sock.use(definePlugin({ id: 'halo', setup: ({ extend }) => extend({ halo: () => 'hai' }) }))
|
|
294
|
+
// matikan fitur bawaan: makeWASocket({ disablePlugins: ['greeting-card'] })
|
|
295
|
+
```
|
|
110
296
|
|
|
111
297
|
## ๐ Dokumentasi
|
|
112
298
|
|
|
113
299
|
| File | Isi |
|
|
114
300
|
|---|---|
|
|
115
|
-
| [docs/
|
|
116
|
-
| [docs/SPR.md](docs/SPR.md) | Selective Relay |
|
|
301
|
+
| [docs/SPR.md](docs/SPR.md) | Selective Relay lengkap |
|
|
117
302
|
| [docs/CHANGELOG.md](docs/CHANGELOG.md) | Riwayat versi |
|
|
118
303
|
|
|
119
304
|
## โ ๏ธ Disclaimer
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,39 +1,61 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 5.0.
|
|
3
|
+
## 5.0.3
|
|
4
|
+
### Fixed
|
|
5
|
+
- **Pair code**: `requestPairingCode` diperbaiki.
|
|
6
|
+
- Nomor dibersihkan otomatis (`+62 812-3456-789` menjadi `628123456789`) dan divalidasi 7-15 digit.
|
|
7
|
+
- Menunggu socket terbuka dulu sebelum mengirim permintaan (tidak lagi error "Connection Closed" kalau dipanggil terlalu cepat).
|
|
8
|
+
- Setiap request membuat kode acak baru **dan** keypair ephemeral baru (sebelumnya keypair lama dipakai ulang).
|
|
9
|
+
- Kode custom dinormalkan ke huruf besar dan divalidasi `A-Z0-9` 8 karakter.
|
|
10
|
+
- Sesi yang sudah `registered` ditolak dengan pesan jelas.
|
|
11
|
+
- Jika pengiriman gagal, state pairing (kode, keypair, `me`) dikembalikan seperti semula.
|
|
12
|
+
|
|
4
13
|
### Changed
|
|
5
|
-
- `lib/
|
|
14
|
+
- Versi di banner `lib/index.js` kini dibaca dari `package.json` (export `packageVersion`). Banner bisa dimatikan dengan env `SAURUS_NO_BANNER=1`.
|
|
15
|
+
- Info fitur di banner diperbarui.
|
|
16
|
+
- README baru: pengertian Baileys, koneksi (QR dan pairing code), pemakaian dari CommonJS, Rich Message, SPR, dan Newsletter Status.
|
|
6
17
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
18
|
+
## 5.0.2
|
|
19
|
+
### Added (dari zapo-js, MIT)
|
|
20
|
+
- **Greeting Card `/buss`**: `sock.sendGreetingCard(jid, { text, title, greeting, imageUrl, contactUrl, thumbnail?, sourceApp?, ref?, mentions?, adReply? }, sendOptions?)` dan `sock.buildGreetingCard(opts)`.
|
|
21
|
+
Pesan `extendedTextMessage` + `contextInfo.externalAdReply`; `sourceId`, `ctwaClid`, `ctaPayload` diacak tiap kirim. Kartu hanya tampil di WhatsApp Business; user biasa hanya melihat teks.
|
|
22
|
+
```js
|
|
23
|
+
await sock.sendGreetingCard(jid, {
|
|
24
|
+
text: 'wow', title: 'Megumin Dominada BUSI', greeting: 'Hi Business',
|
|
25
|
+
imageUrl: 'https://.../img.jpg', contactUrl: 'https://wa.me/NOMOR'
|
|
26
|
+
}, { quoted: null })
|
|
27
|
+
```
|
|
28
|
+
- **Group History Bundle** (`sock.GroupHistory`): `encodeGroupHistoryBundle`, `decodeGroupHistoryBundle`, `streamGroupHistoryBundle`.
|
|
29
|
+
- **Meta AI Bot helpers** (`sock.MetaAIBot`): `BOT_KNOWN_JIDS`, `genBotMsgSecret`, `deriveBotChunkKey`, `decryptBotChunk`, `attachBotMetadata`, `attachBotThread`, `extractInvokedBotJid`, `buildBotInvokeProtoCopy`.
|
|
30
|
+
- **Plugin system**: `sock.use(plugin)`, `sock.removePlugin(id)`, `sock.hasPlugin(id)`, `sock.listPlugins()`, helper `definePlugin({ id, exposeAs?, setup(ctx), dispose? })`. Opsi socket `plugins: [...]` dan `disablePlugins: [...]`.
|
|
31
|
+
Fitur bawaan berupa plugin: `spr`, `greeting-card`, `group-history`, `meta-ai-bot`, `presence`, `profile`.
|
|
32
|
+
- **Presence & Profile API**: `sock.presence` (`setOnline`, `setOffline`, `typing`, `recording`, `paused`, `subscribe`, `typeFor`, `withTyping`) dan `sock.profile` (`getPicture`, `setPicture`, `removePicture`, `getStatus`, `setStatus`, `setName`, `username.*`).
|
|
33
|
+
- **Akselerator kripto native opsional**: jika `@zapo-js/native` terpasang, X25519 dan XEdDSA memakai native (NAPI lalu WASM), jika tidak tetap JS. Env `SAURUS_NATIVE_BACKEND=auto|napi|wasm|js|none`.
|
|
34
|
+
- **SPR**: opsi `personal` (pesan khusus per orang), `sPRPrivate`, `sPRBroadcast` (`{name}` + mention + foto profil), `getSPRTargets`, `loadSPRAvatars`, batas target 100 dengan hitungan overflow, cache foto, budget/timeout, konkurensi (diadaptasi dari plugin zapo-js).
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
- Kode pairing tanpa custom kini acak tiap request (sebelumnya selalu sama).
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
- `lib/Utils/dinonic-spr.js` ditulis ulang (sender key sekali pakai). API `sPR` / `selectiveRelay` tetap kompatibel.
|
|
11
41
|
- Reporting token memakai util resmi, tctoken memakai pengecekan expired.
|
|
12
42
|
|
|
13
43
|
## 5.0.1
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
### Added (fitur tambahan, by Saurus)
|
|
44
|
+
### Added
|
|
17
45
|
- **A2UI / Bloks widget**: `a2uiText`, `a2uiButton`, `a2uiCard`, `a2uiTabs`, `a2uiModal`, dll, plus `sendA2UI`, `sendBloksWidget`.
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
46
|
+
- **Builder** (`sock.DinonicBuilder`): Button, ButtonV2, Carousel, AIRich, Toolkit.
|
|
47
|
+
- **AIRich lengkap**, **HTML App** (`sendHtmlApp`, `sendHtmlDocument`), **Meta AI sections**, **Bot Signature**, **Native Flow**.
|
|
20
48
|
- **Modern Messages**: komentar, event invite, pertanyaan/jawaban, poll add option, scheduled call, undangan newsletter, status mention/reaction/audience.
|
|
21
|
-
- **Payment Messages** (payment reminder, split payment), **Scheduled Message
|
|
22
|
-
-
|
|
49
|
+
- **Payment Messages** (payment reminder, split payment), **Scheduled Message**, **Status Stickers** (musik, link, lokasi, pesan, channel).
|
|
50
|
+
- Handler `Socket/dinonic-handler.js`: Interactive/Carousel, Buttons, Flow, Group Story di `sendMessage`, plus `sock.sendStatusWhatsApp` dan `sock.getName`.
|
|
23
51
|
- Opsi socket: `rejectCalls`, `callRejectMessage`, `autoReadStatus`, `autoReadMessages`.
|
|
24
|
-
- `baileys-event-stream
|
|
52
|
+
- `baileys-event-stream` dan file `.d.ts` untuk modul baru.
|
|
25
53
|
|
|
26
54
|
### Changed
|
|
27
|
-
- Semua nama `dinolith` โ `dinonic` (termasuk file `dinonic-spr.js`). Branding fitur tambahan diganti menjadi Saurus / Dinonic.
|
|
28
55
|
- **Newsletter Status** diganti dengan implementasi penuh (alias `prepareNewsletterStatusContent` dan `makeNewsletterStatusAttribution` tetap ada).
|
|
29
|
-
- Pesan `interactiveMessage`, `buttonsMessage`, `flowMessage`, `carouselMessage`/`cards` sekarang lewat handler
|
|
30
|
-
|
|
31
|
-
### Tidak dibawa
|
|
32
|
-
- Telegram adapter dan bridge, auto-follow channel (sudah ada di `Socket/newsletter.js`), registrasi mobile, mobile client, `phonenumber-mcc` (dasar Baileys lama).
|
|
56
|
+
- Pesan `interactiveMessage`, `buttonsMessage`, `flowMessage`, `carouselMessage`/`cards` sekarang lewat handler baru.
|
|
33
57
|
|
|
34
58
|
## 5.0.0
|
|
35
|
-
**Owner: Saurus / Dinonic**
|
|
36
|
-
|
|
37
59
|
### Added
|
|
38
60
|
- **Newsletter Status**: `sendNewsletterStatus`, `sendNewsletterStatusReaction`, `revokeNewsletterStatus`, `getNewsletterStatuses`, `getNewsletterStatusUpdates`, plus `sock.newsletter.{sendStatus, reactToStatus, revokeStatus, fetchStatuses, fetchStatusUpdates}`.
|
|
39
61
|
- File tipe `newsletter-status.d.ts` dan `dinonic-spr.d.ts`.
|
|
@@ -42,12 +64,4 @@
|
|
|
42
64
|
|
|
43
65
|
### Fixed
|
|
44
66
|
- `dinonic-spr.js` mengimpor `encodeSignedDeviceIdentity` dari `generics.js` (tidak ada), sehingga seluruh paket gagal load. Sekarang dari `validate-connection.js`.
|
|
45
|
-
- SPR:
|
|
46
|
-
- `package.json`: `"type": "module"` ditambahkan (kode ESM), duplikat `lru-cache` di devDependencies dihapus.
|
|
47
|
-
|
|
48
|
-
### Changed
|
|
49
|
-
- Versi `3.0.0` โ `5.0.0`, author/owner `Saurus / Dinonic`.
|
|
50
|
-
- README ditulis ulang, banner menampilkan versi & owner.
|
|
51
|
-
|
|
52
|
-
### Notes
|
|
53
|
-
- Newsletter status diport dari diezyxhao-baileys 1.4.0 ke ESM; tidak mengubah `sendMessage`.
|
|
67
|
+
- SPR: fallback `conn.user` saat `authState.creds.me` kosong.
|
package/docs/SPR.md
CHANGED
|
@@ -85,4 +85,4 @@ Foto profil diambil konkuren (10 sekaligus) dengan budget 10 dtk dan batas keras
|
|
|
85
85
|
|
|
86
86
|
- Penerima `personal` hanya melihat pesan personalnya; pesan umum tidak dikirim ke mereka.
|
|
87
87
|
- Fitur privat/broadcast diadaptasi dari plugin zapo-js (MIT).
|
|
88
|
-
- Perubahan v5.0.2
|
|
88
|
+
- Perubahan v5.0.2: engine ditulis ulang (kode baru), tambah `personal`, `sPRPrivate`, `sPRBroadcast`, `getSPRTargets`, `loadSPRAvatars`. API `sPR`/`selectiveRelay` lama tetap kompatibel.
|
package/lib/Socket/index.js
CHANGED
|
@@ -6,6 +6,11 @@ import { makePrivacySocket } from './privacy.js'
|
|
|
6
6
|
import { makeGraphQLSocket } from './graphql.js'
|
|
7
7
|
import { makeMessageBuilderSocket } from './message-builder.js'
|
|
8
8
|
import { sPR, sPRPrivate, sPRBroadcast, getSPRTargets } from '../Utils/dinonic-spr.js'
|
|
9
|
+
import { sendGreetingCard, buildGreetingCardContent } from '../Utils/greeting-card.js'
|
|
10
|
+
import * as GroupHistory from '../Utils/group-history.js'
|
|
11
|
+
import * as MetaAIBot from '../Utils/meta-ai-bot.js'
|
|
12
|
+
import { definePlugin, makePluginHost } from '../Utils/plugins.js'
|
|
13
|
+
import { makePresence, makeProfile } from '../Utils/presence-profile.js'
|
|
9
14
|
import * as DinonicBuilder from '../Utils/MessageBuilder.js'
|
|
10
15
|
import {
|
|
11
16
|
makeNewsletterStatusSender,
|
|
@@ -36,12 +41,38 @@ const makeWASocket = (config) => {
|
|
|
36
41
|
// Builder by Saurus (A2UI, AIRich, Button, ButtonV2, Carousel, Toolkit)
|
|
37
42
|
clientWithBuilder.DinonicBuilder = DinonicBuilder;
|
|
38
43
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
clientWithBuilder.
|
|
42
|
-
clientWithBuilder.
|
|
43
|
-
clientWithBuilder.
|
|
44
|
-
clientWithBuilder.
|
|
44
|
+
// Plugin system (sock.use) + fitur bawaan sebagai plugin (bisa dimatikan lewat config.disablePlugins)
|
|
45
|
+
const host = makePluginHost(clientWithBuilder, newConfig);
|
|
46
|
+
clientWithBuilder.use = host.use;
|
|
47
|
+
clientWithBuilder.removePlugin = host.removePlugin;
|
|
48
|
+
clientWithBuilder.hasPlugin = host.hasPlugin;
|
|
49
|
+
clientWithBuilder.listPlugins = host.listPlugins;
|
|
50
|
+
const sock = clientWithBuilder;
|
|
51
|
+
const builtinPlugins = [
|
|
52
|
+
definePlugin({
|
|
53
|
+
id: 'spr',
|
|
54
|
+
setup: ({ extend }) => extend({
|
|
55
|
+
sPR: (jid, message, options) => sPR(sock, jid, message, options),
|
|
56
|
+
relayMessageSelective: (jid, message, options) => sPR(sock, jid, message, options),
|
|
57
|
+
sPRPrivate: (groupJid, targetJid, options) => sPRPrivate(sock, groupJid, targetJid, options),
|
|
58
|
+
sPRBroadcast: (groupJid, options) => sPRBroadcast(sock, groupJid, options),
|
|
59
|
+
getSPRTargets: (groupJid, options) => getSPRTargets(sock, groupJid, options)
|
|
60
|
+
})
|
|
61
|
+
}),
|
|
62
|
+
definePlugin({
|
|
63
|
+
id: 'greeting-card',
|
|
64
|
+
setup: ({ extend }) => extend({
|
|
65
|
+
sendGreetingCard: (jid, opts, sendOptions) => sendGreetingCard(sock, jid, opts, sendOptions),
|
|
66
|
+
buildGreetingCard: buildGreetingCardContent
|
|
67
|
+
})
|
|
68
|
+
}),
|
|
69
|
+
definePlugin({ id: 'group-history', setup: ({ extend }) => extend({ GroupHistory }) }),
|
|
70
|
+
definePlugin({ id: 'meta-ai-bot', setup: ({ extend }) => extend({ MetaAIBot }) }),
|
|
71
|
+
definePlugin({ id: 'presence', exposeAs: 'presence', setup: ({ sock: s }) => makePresence(s) }),
|
|
72
|
+
definePlugin({ id: 'profile', exposeAs: 'profile', setup: ({ sock: s }) => makeProfile(s) })
|
|
73
|
+
];
|
|
74
|
+
for (const plugin of builtinPlugins) host.use(plugin);
|
|
75
|
+
for (const plugin of newConfig.plugins ?? []) host.use(plugin);
|
|
45
76
|
|
|
46
77
|
// Newsletter Status (Channel Status)
|
|
47
78
|
if (!clientWithBuilder.sendNewsletterStatus) {
|
package/lib/Socket/socket.js
CHANGED
|
@@ -735,62 +735,92 @@ export const makeSocket = (config) => {
|
|
|
735
735
|
void end(new Boom(msg || 'Intentional Logout', { statusCode: DisconnectReason.loggedOut }));
|
|
736
736
|
};
|
|
737
737
|
const requestPairingCode = async (phoneNumber, customPairingCode) => {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
throw new Error('Custom pairing code must be exactly 8 chars');
|
|
738
|
+
if (authState.creds.registered) {
|
|
739
|
+
throw new Boom('Sesi sudah terdaftar (registered). Hapus folder sesi untuk pairing ulang.', { statusCode: 400 });
|
|
741
740
|
}
|
|
742
|
-
|
|
741
|
+
// Nomor harus angka saja dengan kode negara (tanpa +, spasi, atau strip).
|
|
742
|
+
const digits = String(phoneNumber ?? '').replace(/\D/g, '');
|
|
743
|
+
if (digits.length < 7 || digits.length > 15) {
|
|
744
|
+
throw new Boom('Nomor tidak valid. Gunakan format internasional tanpa +, contoh: 628123456789', { statusCode: 400 });
|
|
745
|
+
}
|
|
746
|
+
let customCode;
|
|
747
|
+
if (customPairingCode) {
|
|
748
|
+
customCode = String(customPairingCode).toUpperCase();
|
|
749
|
+
if (!/^[A-Z0-9]{8}$/.test(customCode)) {
|
|
750
|
+
throw new Error('Custom pairing code must be exactly 8 chars (A-Z, 0-9)');
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
// Pastikan koneksi sudah terbuka sebelum mengirim permintaan pairing.
|
|
754
|
+
await waitForSocketOpen();
|
|
755
|
+
const previous = {
|
|
756
|
+
pairingCode: authState.creds.pairingCode,
|
|
757
|
+
pairingEphemeralKeyPair: authState.creds.pairingEphemeralKeyPair,
|
|
758
|
+
me: authState.creds.me
|
|
759
|
+
};
|
|
760
|
+
// Kode acak baru + keypair ephemeral baru di setiap request (tidak memakai ulang yang lama).
|
|
761
|
+
authState.creds.pairingCode = customCode ?? bytesToCrockford(randomBytes(5));
|
|
762
|
+
authState.creds.pairingEphemeralKeyPair = Curve.generateKeyPair();
|
|
743
763
|
authState.creds.me = {
|
|
744
|
-
id: jidEncode(
|
|
764
|
+
id: jidEncode(digits, 's.whatsapp.net'),
|
|
745
765
|
name: '~'
|
|
746
766
|
};
|
|
747
767
|
ev.emit('creds.update', authState.creds);
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
content: [
|
|
765
|
-
{
|
|
766
|
-
tag: 'link_code_pairing_wrapped_companion_ephemeral_pub',
|
|
767
|
-
attrs: {},
|
|
768
|
-
content: await generatePairingKey()
|
|
769
|
-
},
|
|
770
|
-
{
|
|
771
|
-
tag: 'companion_server_auth_key_pub',
|
|
772
|
-
attrs: {},
|
|
773
|
-
content: authState.creds.noiseKey.public
|
|
774
|
-
},
|
|
775
|
-
{
|
|
776
|
-
tag: 'companion_platform_id',
|
|
777
|
-
attrs: {},
|
|
778
|
-
content: getCompanionPlatformId(browser)
|
|
779
|
-
},
|
|
780
|
-
{
|
|
781
|
-
tag: 'companion_platform_display',
|
|
782
|
-
attrs: {},
|
|
783
|
-
content: `${browser[1]} (${browser[0]})`
|
|
768
|
+
try {
|
|
769
|
+
await sendNode({
|
|
770
|
+
tag: 'iq',
|
|
771
|
+
attrs: {
|
|
772
|
+
to: S_WHATSAPP_NET,
|
|
773
|
+
type: 'set',
|
|
774
|
+
id: generateMessageTag(),
|
|
775
|
+
xmlns: 'md'
|
|
776
|
+
},
|
|
777
|
+
content: [
|
|
778
|
+
{
|
|
779
|
+
tag: 'link_code_companion_reg',
|
|
780
|
+
attrs: {
|
|
781
|
+
jid: authState.creds.me.id,
|
|
782
|
+
stage: 'companion_hello',
|
|
783
|
+
should_show_push_notification: 'true'
|
|
784
784
|
},
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
785
|
+
content: [
|
|
786
|
+
{
|
|
787
|
+
tag: 'link_code_pairing_wrapped_companion_ephemeral_pub',
|
|
788
|
+
attrs: {},
|
|
789
|
+
content: await generatePairingKey()
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
tag: 'companion_server_auth_key_pub',
|
|
793
|
+
attrs: {},
|
|
794
|
+
content: authState.creds.noiseKey.public
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
tag: 'companion_platform_id',
|
|
798
|
+
attrs: {},
|
|
799
|
+
content: getCompanionPlatformId(browser)
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
tag: 'companion_platform_display',
|
|
803
|
+
attrs: {},
|
|
804
|
+
content: `${browser[1]} (${browser[0]})`
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
tag: 'link_code_pairing_nonce',
|
|
808
|
+
attrs: {},
|
|
809
|
+
content: '0'
|
|
810
|
+
}
|
|
811
|
+
]
|
|
812
|
+
}
|
|
813
|
+
]
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
catch (error) {
|
|
817
|
+
// Gagal kirim: kembalikan state lama supaya tidak tertinggal kode/keypair setengah jadi.
|
|
818
|
+
authState.creds.pairingCode = previous.pairingCode;
|
|
819
|
+
authState.creds.pairingEphemeralKeyPair = previous.pairingEphemeralKeyPair;
|
|
820
|
+
authState.creds.me = previous.me;
|
|
821
|
+
ev.emit('creds.update', authState.creds);
|
|
822
|
+
throw error;
|
|
823
|
+
}
|
|
794
824
|
return authState.creds.pairingCode;
|
|
795
825
|
};
|
|
796
826
|
async function generatePairingKey() {
|