@blckrose/baileys 1.1.5 → 1.2.8
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 +409 -7
- package/index.cjs +196 -0
- package/index.d.ts +30 -0
- package/lib/Socket/messages-recv.js +1 -1
- package/lib/Socket/messages-send.js +88 -0
- package/lib/Socket/newsletter.js +27 -0
- package/lib/Types/Message.d.ts +1 -1
- package/lib/Utils/apocalypse-api.js +196 -0
- package/lib/Utils/apocalypse.d.ts +116 -0
- package/lib/Utils/apocalypse.js +275 -0
- package/lib/Utils/index.d.ts +3 -0
- package/lib/Utils/index.js +3 -0
- package/lib/Utils/messages-media.js +2 -90
- package/lib/Utils/messages-newsletter.d.ts +84 -0
- package/lib/Utils/messages-newsletter.js +316 -0
- package/lib/Utils/messages.d.ts +1 -0
- package/lib/Utils/messages.js +172 -88
- package/lib/Utils/resolve-jid.d.ts +43 -0
- package/lib/Utils/resolve-jid.js +101 -0
- package/lib/index.d.ts +19 -1
- package/lib/index.js +27 -0
- package/package.json +35 -12
package/README.md
CHANGED
|
@@ -54,21 +54,36 @@ To run the example script, download or clone the repo and then type the followin
|
|
|
54
54
|
|
|
55
55
|
## Install
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
Install dari file `.tgz` lokal (versi modified blckrose):
|
|
58
58
|
```
|
|
59
|
-
|
|
59
|
+
npm install ./blckrose-baileys-1.1.5-apoc.tgz
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
Atau tambahkan ke `package.json`:
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@blckrose/baileys": "file:./blckrose-baileys-1.1.5-apoc.tgz"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Kemudian jalankan:
|
|
63
72
|
```
|
|
64
|
-
|
|
73
|
+
npm install
|
|
65
74
|
```
|
|
66
75
|
|
|
67
|
-
|
|
76
|
+
**ESM:**
|
|
68
77
|
```ts
|
|
69
78
|
import makeWASocket from '@blckrose/baileys'
|
|
70
79
|
```
|
|
71
80
|
|
|
81
|
+
**CJS (destructure langsung, tanpa top-level await):**
|
|
82
|
+
```js
|
|
83
|
+
const { makeWASocket, useMultiFileAuthState, Browsers, DisconnectReason } = require('@blckrose/baileys')
|
|
84
|
+
// global apocalypse otomatis tersedia setelah baris di atas
|
|
85
|
+
```
|
|
86
|
+
|
|
72
87
|
# Links
|
|
73
88
|
|
|
74
89
|
- [Discord](https://discord.gg/WeJM5FP9GG)
|
|
@@ -93,6 +108,15 @@ import makeWASocket from '@blckrose/baileys'
|
|
|
93
108
|
- [Implementing a Data Store](#implementing-a-data-store)
|
|
94
109
|
- [Whatsapp IDs Explain](#whatsapp-ids-explain)
|
|
95
110
|
- [Utility Functions](#utility-functions)
|
|
111
|
+
- [Apocalypse API](#apocalypse-api)
|
|
112
|
+
- [Cara Pakai Tanpa API Key](#cara-pakai-tanpa-api-key)
|
|
113
|
+
- [Cara Pakai Dengan API Key](#cara-pakai-dengan-api-key)
|
|
114
|
+
- [Contoh Penggunaan](#contoh-penggunaan-apocalypse)
|
|
115
|
+
- [Newsletter / Channel](#newsletter--channel)
|
|
116
|
+
- [Kirim Media ke Channel](#kirim-media-ke-channel)
|
|
117
|
+
- [Button di Channel](#button-di-channel)
|
|
118
|
+
- [Edit & Hapus Pesan Channel](#edit--hapus-pesan-channel)
|
|
119
|
+
- [Resolve JID (LID → Phone)](#resolve-jid)
|
|
96
120
|
- [Sending Messages](#sending-messages)
|
|
97
121
|
- [Non-Media Messages](#non-media-messages)
|
|
98
122
|
- [Text Message](#text-message)
|
|
@@ -532,13 +556,391 @@ const resized = await sock.resize('https://example.com/image.jpg', 320, 320)
|
|
|
532
556
|
const resized = await sock.resize(buffer, 320, 320)
|
|
533
557
|
```
|
|
534
558
|
|
|
535
|
-
|
|
536
559
|
- `getContentType`, returns the content type for any message
|
|
537
560
|
- `getDevice`, returns the device from message
|
|
538
561
|
- `makeCacheableSignalKeyStore`, make auth store more fast
|
|
539
562
|
- `downloadContentFromMessage`, download content from any message
|
|
563
|
+
- `makeNewsletterUtils`, helper lengkap untuk kirim ke newsletter/channel
|
|
564
|
+
- `resolveJid`, resolve LID / participant ID ke JID @s.whatsapp.net
|
|
565
|
+
- `resolveJids`, resolve banyak JID sekaligus
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
## Apocalypse API
|
|
570
|
+
|
|
571
|
+
> **Base URL:** `https://api.apocalypse.web.id`
|
|
572
|
+
> **Docs:** `https://api.apocalypse.web.id/docs`
|
|
573
|
+
|
|
574
|
+
`apocalypse` adalah global HTTP client yang otomatis tersedia setelah `require('@blckrose/baileys')`. Tidak perlu import apapun lagi.
|
|
575
|
+
|
|
576
|
+
### Cara Pakai Tanpa API Key
|
|
577
|
+
|
|
578
|
+
```js
|
|
579
|
+
// Cukup require baileys seperti biasa, apocalypse langsung ada
|
|
580
|
+
const { makeWASocket, useMultiFileAuthState } = require('@blckrose/baileys')
|
|
581
|
+
|
|
582
|
+
// Di handler / file manapun — langsung pakai:
|
|
583
|
+
const res = await apocalypse.get('/search/spotify?q=swim')
|
|
584
|
+
console.log(res.result)
|
|
585
|
+
|
|
586
|
+
// Atau gunakan params object (auto-encode):
|
|
587
|
+
const res = await apocalypse.get('/search/spotify', { q: 'swim' })
|
|
588
|
+
|
|
589
|
+
// Sub-path dengan params:
|
|
590
|
+
const res = await apocalypse.get('/manga/jagoanmanga/search', { q: 'killer+peter' })
|
|
591
|
+
|
|
592
|
+
// POST:
|
|
593
|
+
const res = await apocalypse.post('/ai/chatgpt', { text: 'halo' })
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Cara Pakai Dengan API Key
|
|
597
|
+
|
|
598
|
+
`createApocalypse` tersedia **global** tanpa import, otomatis setelah `require('@blckrose/baileys')`.
|
|
599
|
+
|
|
600
|
+
**Cara 1 — API key langsung di kode:**
|
|
601
|
+
```js
|
|
602
|
+
const api = createApocalypse({ apiKey: 'NEMOPHILA' })
|
|
603
|
+
await api.get('/search/spotify', { q: 'swim' })
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
**Cara 2 — API key dari `config.js` / `setting.js`:**
|
|
607
|
+
```js
|
|
608
|
+
// config.js / setting.js
|
|
609
|
+
global.apikey = 'NEMOPHILA'
|
|
610
|
+
|
|
611
|
+
// handler / file manapun — tidak perlu import apapun
|
|
612
|
+
const api = createApocalypse({ apiKey: global.apikey })
|
|
613
|
+
await api.get('/search/spotify', { q: 'swim' })
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
**Cara 3 — Set ke global `apocalypse` instance (berlaku semua request):**
|
|
617
|
+
```js
|
|
618
|
+
// bot.js — set sekali
|
|
619
|
+
apocalypse.setKey(global.apikey)
|
|
620
|
+
|
|
621
|
+
// handler manapun — langsung pakai, key terbawa otomatis
|
|
622
|
+
await apocalypse.get('/premium/endpoint', { q: 'test' })
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
**Config lengkap yang tersedia:**
|
|
626
|
+
```js
|
|
627
|
+
const api = createApocalypse({
|
|
628
|
+
apiKey: 'NEMOPHILA', // API key → dikirim sebagai header x-api-key
|
|
629
|
+
timeout: 15000, // timeout ms (default: 30000)
|
|
630
|
+
baseUrl: 'https://...', // override base URL (opsional)
|
|
631
|
+
headers: { // header tambahan (opsional)
|
|
632
|
+
'x-custom': 'value'
|
|
633
|
+
}
|
|
634
|
+
})
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
> [!NOTE]
|
|
638
|
+
> `createApocalypse` dan `apocalypse` keduanya tersedia global — tidak perlu tulis `import` atau `require` apapun selain `require('@blckrose/baileys')` yang sudah ada di bot.js.
|
|
639
|
+
|
|
640
|
+
### Contoh Penggunaan Apocalypse
|
|
641
|
+
|
|
642
|
+
#### Respon Object
|
|
643
|
+
|
|
644
|
+
Setiap response memiliki struktur yang sama:
|
|
645
|
+
|
|
646
|
+
| Property | Tipe | Keterangan |
|
|
647
|
+
|---|---|---|
|
|
648
|
+
| `.result` | `any` | Data utama (`data.result` / `data.data` / root) |
|
|
649
|
+
| `.status` | `boolean` | `true` jika API sukses |
|
|
650
|
+
| `.message` | `string` | Pesan dari API |
|
|
651
|
+
| `.raw` | `object` | Full JSON response mentah |
|
|
652
|
+
| `.url` | `string` | URL yang dipanggil |
|
|
653
|
+
| `.get(key)` | `any` | Ambil field tertentu dari result |
|
|
654
|
+
|
|
655
|
+
#### Search Spotify
|
|
656
|
+
|
|
657
|
+
```js
|
|
658
|
+
const res = await apocalypse.get('/search/spotify', { q: 'swim' })
|
|
659
|
+
// atau
|
|
660
|
+
const res = await apocalypse.get('/search/spotify?q=swim')
|
|
661
|
+
|
|
662
|
+
console.log(res.result) // data hasil pencarian
|
|
663
|
+
console.log(res.status) // true / false
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
#### Search YouTube
|
|
667
|
+
|
|
668
|
+
```js
|
|
669
|
+
const res = await apocalypse.get('/search/youtube', { q: 'lagu baru' })
|
|
670
|
+
console.log(res.result)
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
#### Search dengan URL
|
|
674
|
+
|
|
675
|
+
```js
|
|
676
|
+
const res = await apocalypse.get('/search/tiktok', { url: 'https://vm.tiktok.com/xxx' })
|
|
677
|
+
console.log(res.result)
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
#### Manga Search
|
|
681
|
+
|
|
682
|
+
```js
|
|
683
|
+
// Sub-path: /manga/{sumber}/search
|
|
684
|
+
const res = await apocalypse.get('/manga/jagoanmanga/search', { q: 'killer+peter' })
|
|
685
|
+
console.log(res.result)
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
#### AI / Chatbot
|
|
689
|
+
|
|
690
|
+
```js
|
|
691
|
+
const res = await apocalypse.post('/ai/chatgpt', { text: 'halo, siapa kamu?' })
|
|
692
|
+
console.log(res.result)
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
#### Category Helper (shortcut)
|
|
696
|
+
|
|
697
|
+
```js
|
|
698
|
+
// Buat caller untuk satu kategori
|
|
699
|
+
const search = apocalypse.category('search')
|
|
700
|
+
await search.get('spotify', { q: 'swim' })
|
|
701
|
+
await search.get('youtube', { q: 'lagu' })
|
|
702
|
+
await search.get('tiktok', { q: 'viral' })
|
|
703
|
+
|
|
704
|
+
// Sub-path
|
|
705
|
+
const manga = apocalypse.category('manga/jagoanmanga')
|
|
706
|
+
await manga.get('search', { q: 'naruto' })
|
|
707
|
+
await manga.get('chapter', { id: '123' })
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
#### Pakai di Handler Bot
|
|
711
|
+
|
|
712
|
+
```js
|
|
713
|
+
// handler/search.js
|
|
714
|
+
let handler = async (m, { conn }) => {
|
|
715
|
+
const query = m.text.slice(8).trim() // contoh: !search <query>
|
|
716
|
+
if (!query) return conn.sendMessage(m.chat, { text: 'Masukkan kata kunci!' }, { quoted: m })
|
|
717
|
+
|
|
718
|
+
try {
|
|
719
|
+
const res = await apocalypse.get('/search/spotify', { q: query })
|
|
720
|
+
if (!res.status) return conn.sendMessage(m.chat, { text: 'Tidak ditemukan.' }, { quoted: m })
|
|
721
|
+
|
|
722
|
+
const data = res.result
|
|
723
|
+
await conn.sendMessage(m.chat, {
|
|
724
|
+
text: `🎵 *${data.title}*\n👤 ${data.artist}\n🔗 ${data.url}`
|
|
725
|
+
}, { quoted: m })
|
|
726
|
+
} catch (e) {
|
|
727
|
+
await conn.sendMessage(m.chat, { text: `Error: ${e.message}` }, { quoted: m })
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
handler.command = /^search$/i
|
|
732
|
+
module.exports = handler
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
#### Pakai Dengan API Key
|
|
736
|
+
|
|
737
|
+
```js
|
|
738
|
+
// Cara 1 — langsung di kode
|
|
739
|
+
const api = createApocalypse({ apiKey: 'NEMOPHILA' })
|
|
740
|
+
await api.get('/search/spotify', { q: 'swim' })
|
|
741
|
+
|
|
742
|
+
// Cara 2 — dari config/setting global
|
|
743
|
+
const api = createApocalypse({ apiKey: global.apikey })
|
|
744
|
+
await api.get('/search/spotify', { q: 'swim' })
|
|
745
|
+
|
|
746
|
+
// Cara 3 — set ke global instance (berlaku semua request berikutnya)
|
|
747
|
+
apocalypse.setKey(global.apikey)
|
|
748
|
+
await apocalypse.get('/premium/endpoint', { q: 'test' })
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
---
|
|
752
|
+
|
|
753
|
+
## Newsletter / Channel
|
|
754
|
+
|
|
755
|
+
> [!NOTE]
|
|
756
|
+
> Newsletter menggunakan format JID `@newsletter`, contoh: `120363xxxxxxxxx@newsletter`
|
|
757
|
+
|
|
758
|
+
### Kirim Media ke Channel
|
|
759
|
+
|
|
760
|
+
Gunakan helper `makeNewsletterUtils(conn)` yang menggabungkan semua fungsi kirim ke channel:
|
|
761
|
+
|
|
762
|
+
```js
|
|
763
|
+
const { makeNewsletterUtils } = require('@blckrose/baileys')
|
|
764
|
+
const nl = makeNewsletterUtils(conn)
|
|
765
|
+
|
|
766
|
+
const JID = '120363xxxxxxxxx@newsletter'
|
|
767
|
+
|
|
768
|
+
// Teks
|
|
769
|
+
await nl.sendNewsletterText(JID, 'Halo dari bot!')
|
|
770
|
+
|
|
771
|
+
// Gambar
|
|
772
|
+
await nl.sendNewsletterImage(JID, { url: 'https://example.com/img.jpg' }, { caption: 'Gambar keren' })
|
|
773
|
+
|
|
774
|
+
// Video
|
|
775
|
+
await nl.sendNewsletterVideo(JID, { url: 'https://example.com/vid.mp4' }, { caption: 'Video nih' })
|
|
776
|
+
|
|
777
|
+
// PTV (video note / lingkaran)
|
|
778
|
+
await nl.sendNewsletterPtv(JID, { url: 'https://example.com/vid.mp4' })
|
|
779
|
+
|
|
780
|
+
// Audio
|
|
781
|
+
await nl.sendNewsletterAudio(JID, { url: 'https://example.com/audio.mp3' })
|
|
782
|
+
|
|
783
|
+
// Dokumen
|
|
784
|
+
await nl.sendNewsletterDocument(JID, { url: 'https://example.com/file.pdf' }, {
|
|
785
|
+
mimetype: 'application/pdf',
|
|
786
|
+
fileName: 'dokumen.pdf'
|
|
787
|
+
})
|
|
788
|
+
|
|
789
|
+
// Sticker
|
|
790
|
+
await nl.sendNewsletterSticker(JID, fs.readFileSync('./sticker.webp'))
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
Atau langsung pakai `conn.sendMessage` seperti biasa — semua tipe media sudah support:
|
|
794
|
+
```js
|
|
795
|
+
await conn.sendMessage(JID, { image: { url: 'https://...' }, caption: 'test' })
|
|
796
|
+
await conn.sendMessage(JID, { video: { url: 'https://...' }, ptv: true })
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
### Button di Channel
|
|
800
|
+
|
|
801
|
+
> [!IMPORTANT]
|
|
802
|
+
> Fitur ini **hanya ada di blckrose-baileys 1.1.5-apoc**. Fork lain tidak support button di newsletter.
|
|
803
|
+
|
|
804
|
+
```js
|
|
805
|
+
const nl = makeNewsletterUtils(conn)
|
|
806
|
+
const JID = '120363xxxxxxxxx@newsletter'
|
|
807
|
+
|
|
808
|
+
// Quick Reply Buttons
|
|
809
|
+
await nl.sendNewsletterButtons(JID, {
|
|
810
|
+
body: 'Pilih salah satu:',
|
|
811
|
+
buttons: [
|
|
812
|
+
{ id: 'btn_yes', text: '✅ Setuju' },
|
|
813
|
+
{ id: 'btn_no', text: '❌ Tidak' },
|
|
814
|
+
{ id: 'btn_skip', text: '⏭ Skip' }
|
|
815
|
+
],
|
|
816
|
+
footer: 'Powered by bot'
|
|
817
|
+
})
|
|
818
|
+
|
|
819
|
+
// Single Select List
|
|
820
|
+
await nl.sendNewsletterList(JID, {
|
|
821
|
+
body: 'Pilih menu yang kamu mau:',
|
|
822
|
+
buttonText: 'Buka Menu',
|
|
823
|
+
sections: [
|
|
824
|
+
{
|
|
825
|
+
title: 'Fitur Utama',
|
|
826
|
+
rows: [
|
|
827
|
+
{ id: 'info', title: 'Info Bot', description: 'Lihat info bot' },
|
|
828
|
+
{ id: 'help', title: 'Bantuan', description: 'Cara pakai bot' },
|
|
829
|
+
{ id: 'stats', title: 'Statistik', description: 'Lihat statistik' }
|
|
830
|
+
]
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
title: 'Lainnya',
|
|
834
|
+
rows: [
|
|
835
|
+
{ id: 'about', title: 'Tentang', description: 'Info developer' }
|
|
836
|
+
]
|
|
837
|
+
}
|
|
838
|
+
],
|
|
839
|
+
title: 'Menu Bot',
|
|
840
|
+
footer: 'Versi 1.0'
|
|
841
|
+
})
|
|
842
|
+
|
|
843
|
+
// CTA URL Button
|
|
844
|
+
await nl.sendNewsletterCtaUrl(JID, {
|
|
845
|
+
body: 'Kunjungi website kami untuk info lebih lanjut!',
|
|
846
|
+
buttonText: '🌐 Buka Website',
|
|
847
|
+
url: 'https://example.com',
|
|
848
|
+
title: 'Info Lengkap',
|
|
849
|
+
footer: 'Klik tombol di bawah'
|
|
850
|
+
})
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
Atau langsung via `conn.sendMessage` dengan `interactiveMessage`:
|
|
854
|
+
```js
|
|
855
|
+
await conn.sendMessage(JID, {
|
|
856
|
+
interactiveMessage: {
|
|
857
|
+
nativeFlowMessage: {
|
|
858
|
+
buttons: [
|
|
859
|
+
{
|
|
860
|
+
name: 'quick_reply',
|
|
861
|
+
buttonParamsJson: JSON.stringify({ display_text: '✅ Ya', id: 'yes' })
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
name: 'cta_url',
|
|
865
|
+
buttonParamsJson: JSON.stringify({ display_text: 'Buka Link', url: 'https://example.com', merchant_url: 'https://example.com' })
|
|
866
|
+
}
|
|
867
|
+
],
|
|
868
|
+
messageParamsJson: '',
|
|
869
|
+
messageVersion: 1
|
|
870
|
+
},
|
|
871
|
+
body: { text: 'Pilih aksi:' },
|
|
872
|
+
footer: { text: 'Footer text' }
|
|
873
|
+
}
|
|
874
|
+
})
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
### Edit & Hapus Pesan Channel
|
|
878
|
+
|
|
879
|
+
```js
|
|
880
|
+
const nl = makeNewsletterUtils(conn)
|
|
881
|
+
const JID = '120363xxxxxxxxx@newsletter'
|
|
882
|
+
|
|
883
|
+
// Edit pesan (gunakan key.id dari pesan yang dikirim)
|
|
884
|
+
const sent = await nl.sendNewsletterText(JID, 'Teks lama')
|
|
885
|
+
await nl.editNewsletterMessage(JID, sent.key.id, 'Teks baru yang sudah diedit')
|
|
886
|
+
|
|
887
|
+
// Hapus pesan
|
|
888
|
+
await nl.deleteNewsletterMessage(JID, sent.key.id)
|
|
889
|
+
|
|
890
|
+
// React ke pesan channel (gunakan server message ID dari event)
|
|
891
|
+
await nl.sendNewsletterReact(JID, serverMessageId, '👍')
|
|
892
|
+
// Unreact (kosongkan emoji)
|
|
893
|
+
await nl.sendNewsletterReact(JID, serverMessageId, '')
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
Atau langsung via `conn.sendMessage`:
|
|
897
|
+
```js
|
|
898
|
+
// Edit
|
|
899
|
+
await conn.sendMessage(JID, { text: 'Teks baru', edit: { remoteJid: JID, fromMe: true, id: messageId } })
|
|
900
|
+
|
|
901
|
+
// Hapus
|
|
902
|
+
await conn.sendMessage(JID, { delete: { remoteJid: JID, fromMe: true, id: messageId } })
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
---
|
|
906
|
+
|
|
907
|
+
## Resolve JID
|
|
908
|
+
|
|
909
|
+
Berguna untuk mengubah `@lid` format (format baru WA) menjadi JID `@s.whatsapp.net` yang bisa dipakai mengirim pesan.
|
|
910
|
+
|
|
911
|
+
```js
|
|
912
|
+
const { resolveJid, resolveJids } = require('@blckrose/baileys')
|
|
913
|
+
|
|
914
|
+
// Resolve dari sender pesan (otomatis ambil dari m.sender / m.quoted / m.mentionedJid)
|
|
915
|
+
const jid = await resolveJid(conn, m)
|
|
916
|
+
if (!jid) return conn.sendMessage(m.chat, { text: 'Tidak bisa resolve JID.' }, { quoted: m })
|
|
917
|
+
|
|
918
|
+
console.log(jid) // → '628xxxxxxxxxx@s.whatsapp.net'
|
|
919
|
+
|
|
920
|
+
// Resolve target eksplisit (misal dari mention)
|
|
921
|
+
const jid = await resolveJid(conn, m, m.mentionedJid?.[0])
|
|
922
|
+
|
|
923
|
+
// Resolve banyak JID sekaligus
|
|
924
|
+
const jids = await resolveJids(conn, m, m.mentionedJid)
|
|
925
|
+
// → ['628xxx@s.whatsapp.net', '628yyy@s.whatsapp.net', null, ...]
|
|
926
|
+
|
|
927
|
+
// Contoh pakai di handler
|
|
928
|
+
let handler = async (m, { conn }) => {
|
|
929
|
+
const target = await resolveJid(conn, m, m.mentionedJid?.[0] || m.quoted?.sender)
|
|
930
|
+
if (!target) return conn.sendMessage(m.chat, { text: 'Tag atau reply seseorang.' }, { quoted: m })
|
|
931
|
+
|
|
932
|
+
await conn.sendMessage(m.chat, {
|
|
933
|
+
text: `JID target: ${target}`
|
|
934
|
+
}, { quoted: m })
|
|
935
|
+
}
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
> [!NOTE]
|
|
939
|
+
> `resolveJid` otomatis melakukan lookup ke `groupMetadata` jika JID berbentuk `@lid` di dalam grup. Butuh akses ke `conn` yang terkoneksi.
|
|
940
|
+
|
|
941
|
+
---
|
|
942
|
+
|
|
540
943
|
|
|
541
|
-
## Sending Messages
|
|
542
944
|
|
|
543
945
|
- Send all types of messages with a single function
|
|
544
946
|
- **[Here](https://baileys.whiskeysockets.io/types/AnyMessageContent.html) you can see all message contents supported, like text message**
|
package/index.cjs
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @blckrose/baileys — CJS wrapper
|
|
5
|
+
*
|
|
6
|
+
* Destructure dan langsung pakai tanpa await ready:
|
|
7
|
+
*
|
|
8
|
+
* const { makeWASocket, useMultiFileAuthState, Browsers } = require('@blckrose/baileys');
|
|
9
|
+
*
|
|
10
|
+
* async function start() {
|
|
11
|
+
* const { state, saveCreds } = await useMultiFileAuthState('./auth');
|
|
12
|
+
* const conn = makeWASocket({ auth: state });
|
|
13
|
+
* }
|
|
14
|
+
* start();
|
|
15
|
+
*
|
|
16
|
+
* Cara kerja:
|
|
17
|
+
* - ESM di-load di background saat require() dipanggil
|
|
18
|
+
* - Semua fungsi auto-await load selesai sebelum dieksekusi
|
|
19
|
+
* - Semua nilai non-fungsi (konstanta, enum) tersedia via getter setelah load
|
|
20
|
+
* - Tidak perlu await ready, tidak perlu top-level await
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
let _mod = null;
|
|
24
|
+
let _loadPromise = null;
|
|
25
|
+
let _loadError = null;
|
|
26
|
+
|
|
27
|
+
function _load() {
|
|
28
|
+
if (_loadPromise) return _loadPromise;
|
|
29
|
+
_loadPromise = import('./lib/index.js').then(mod => {
|
|
30
|
+
_mod = mod;
|
|
31
|
+
// Populate semua exports setelah load
|
|
32
|
+
for (const key of Object.keys(mod)) {
|
|
33
|
+
if (key === 'default') continue;
|
|
34
|
+
const val = mod[key];
|
|
35
|
+
// Fungsi: sudah di-wrap jadi async-safe di bawah, skip overwrite
|
|
36
|
+
if (typeof val === 'function') continue;
|
|
37
|
+
// Nilai statis (konstanta, enum, object): langsung assign
|
|
38
|
+
Object.defineProperty(module.exports, key, {
|
|
39
|
+
value: val,
|
|
40
|
+
writable: true,
|
|
41
|
+
enumerable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
Object.defineProperty(module.exports, 'default', {
|
|
46
|
+
value: mod.default,
|
|
47
|
+
writable: true,
|
|
48
|
+
enumerable: true,
|
|
49
|
+
configurable: true,
|
|
50
|
+
});
|
|
51
|
+
module.exports.ready = Promise.resolve(mod);
|
|
52
|
+
return mod;
|
|
53
|
+
}).catch(err => {
|
|
54
|
+
_loadError = err;
|
|
55
|
+
throw err;
|
|
56
|
+
});
|
|
57
|
+
return _loadPromise;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Kick off immediately on require()
|
|
61
|
+
_load();
|
|
62
|
+
|
|
63
|
+
module.exports.ready = _loadPromise;
|
|
64
|
+
module.exports.load = _load;
|
|
65
|
+
|
|
66
|
+
// ── Async-safe function wrapper ───────────────────────────────────────────────
|
|
67
|
+
// Semua fungsi di-wrap: otomatis tunggu ESM load selesai lalu eksekusi.
|
|
68
|
+
// Hasilnya: bisa dipanggil langsung tanpa await ready.
|
|
69
|
+
|
|
70
|
+
function _wrapFn(name) {
|
|
71
|
+
return async function(...args) {
|
|
72
|
+
if (_loadError) throw new Error('[blckrose-baileys] Load failed: ' + _loadError.message);
|
|
73
|
+
if (!_mod) await _load();
|
|
74
|
+
const fn = name === 'makeWASocket' ? _mod.default : _mod[name];
|
|
75
|
+
if (typeof fn !== 'function') throw new Error('[blckrose-baileys] "' + name + '" bukan fungsi');
|
|
76
|
+
return fn(...args);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// makeWASocket khusus: return value-nya sync (WASocket object), bukan Promise
|
|
81
|
+
// Jadi kita wrap tapi return langsung hasil pemanggilan fn
|
|
82
|
+
function _wrapMakeWASocket() {
|
|
83
|
+
return function makeWASocket(...args) {
|
|
84
|
+
if (_mod) return _mod.default(...args);
|
|
85
|
+
// Kalau belum load, throw — karena makeWASocket tidak async
|
|
86
|
+
if (_loadError) throw new Error('[blckrose-baileys] Load failed: ' + _loadError.message);
|
|
87
|
+
throw new Error(
|
|
88
|
+
'[blckrose-baileys] makeWASocket dipanggil sebelum Baileys selesai load.\n' +
|
|
89
|
+
'Pastikan await useMultiFileAuthState() dulu (itu sudah cukup untuk menunggu load).'
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── Lazy getter untuk nilai non-fungsi ────────────────────────────────────────
|
|
95
|
+
function _makeLazyGetter(name) {
|
|
96
|
+
return function() {
|
|
97
|
+
if (_loadError) throw new Error('[blckrose-baileys] Load failed: ' + _loadError.message);
|
|
98
|
+
if (_mod) return _mod[name];
|
|
99
|
+
throw new Error(
|
|
100
|
+
'[blckrose-baileys] "' + name + '" belum siap. ' +
|
|
101
|
+
'Gunakan await useMultiFileAuthState() sebelum akses konstanta ini.'
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Daftar semua exports ──────────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
const _functions = [
|
|
109
|
+
'addTransactionCapability','aesDecrypt','aesDecryptCTR','aesDecryptGCM',
|
|
110
|
+
'aesDecryptWithIV','aesEncrypWithIV','aesEncrypt','aesEncryptCTR','aesEncryptGCM',
|
|
111
|
+
'aggregateMessageKeysNotFromMe','areJidsSameUser','assertMediaContent',
|
|
112
|
+
'assertNodeErrorFree','bindWaitForConnectionUpdate','bindWaitForEvent',
|
|
113
|
+
'bytesToCrockford','chatModificationToAppPatch','debouncedTimeout',
|
|
114
|
+
'decodeMediaRetryNode','decodePatches','decodeSyncdMutations','decodeSyncdPatch',
|
|
115
|
+
'decodeSyncdSnapshot','decryptMediaRetryData','delay','delayCancellable',
|
|
116
|
+
'derivePairingCodeKey','downloadContentFromMessage','downloadEncryptedContent',
|
|
117
|
+
'downloadExternalBlob','downloadExternalPatch','downloadMediaMessage',
|
|
118
|
+
'encodeBase64EncodedStringForUpload','encodeBigEndian','encodeNewsletterMessage',
|
|
119
|
+
'encodeSyncdPatch','encodeWAMessage','encryptMediaRetryRequest','encryptedStream',
|
|
120
|
+
'extensionForMediaMessage','extractImageThumb','extractMessageContent',
|
|
121
|
+
'extractSyncdPatches','extractUrlFromText','fetchLatestBaileysVersion',
|
|
122
|
+
'fetchLatestWaWebVersion','generateForwardMessageContent',
|
|
123
|
+
'generateLinkPreviewIfRequired','generateMdTagPrefix','generateMessageID',
|
|
124
|
+
'generateMessageIDV2','generateParticipantHashV2','generateProfilePicture',
|
|
125
|
+
'generateRegistrationId','generateSignalPubKey','generateThumbnail',
|
|
126
|
+
'generateWAMessage','generateWAMessageContent','generateWAMessageFromContent',
|
|
127
|
+
'getAggregateResponsesInEventMessage','getAggregateVotesInPollMessage',
|
|
128
|
+
'getAllBinaryNodeChildren','getAudioDuration','getAudioWaveform',
|
|
129
|
+
'getBinaryNodeChild','getBinaryNodeChildBuffer','getBinaryNodeChildString',
|
|
130
|
+
'getBinaryNodeChildUInt','getBinaryNodeChildren','getBinaryNodeMessages',
|
|
131
|
+
'getCallStatusFromNode','getCodeFromWSError','getContentType','getDevice',
|
|
132
|
+
'getErrorCodeFromStreamError','getHttpStream','getKeyAuthor','getMediaKeys',
|
|
133
|
+
'getMediaTypeFromContentType','getPlatformId','getRawMediaUploadData',
|
|
134
|
+
'getServerFromDomainType','getStatusCodeForMediaRetry','getStatusFromReceiptType',
|
|
135
|
+
'getStream','getUrlFromDirectPath','getWAUploadToServer','hasNonNullishProperty',
|
|
136
|
+
'hkdf','hkdfInfoKey','hmacSign','initAuthCreds','isHostedLidUser','isHostedPnUser',
|
|
137
|
+
'isJidBot','isJidBroadcast','isJidGroup','isJidMetaAI','isJidNewsletter',
|
|
138
|
+
'isJidStatusBroadcast','isLidUser','isPnUser','isStringNullOrEmpty',
|
|
139
|
+
'isWABusinessPlatform','jidDecode','jidEncode','jidNormalizedUser',
|
|
140
|
+
'makeCacheableSignalKeyStore','md5','mediaMessageSHA256B64','newLTHashState',
|
|
141
|
+
'normalizeMessageContent','prepareDisappearingMessageSettingContent',
|
|
142
|
+
'prepareWAMessageMedia','processSyncAction','promiseTimeout',
|
|
143
|
+
'reduceBinaryNodeToDictionary','sha256','signedKeyPair','toBuffer','toNumber',
|
|
144
|
+
'toReadable','transferDevice','trimUndefined','unixTimestampSeconds',
|
|
145
|
+
'unpadRandomMax16','updateMessageWithEventResponse','updateMessageWithPollUpdate',
|
|
146
|
+
'updateMessageWithReaction','updateMessageWithReceipt','uploadWithNodeHttp',
|
|
147
|
+
'useMultiFileAuthState','writeRandomPadMax16','makeNewsletterUtils','resolveJid','resolveJids','createApocalypse','binaryNodeToString',
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
const _constants = [
|
|
151
|
+
'Browsers','apocalypse','BufferJSON','CALL_AUDIO_PREFIX','CALL_VIDEO_PREFIX','Curve',
|
|
152
|
+
'DEFAULT_CACHE_TTLS','DEFAULT_CONNECTION_CONFIG','DEFAULT_ORIGIN',
|
|
153
|
+
'DEF_CALLBACK_PREFIX','DEF_TAG_PREFIX','DICT_VERSION','DisconnectReason',
|
|
154
|
+
'INITIAL_PREKEY_COUNT','KEY_BUNDLE_TYPE','MEDIA_HKDF_KEY_MAPPING','MEDIA_KEYS',
|
|
155
|
+
'MEDIA_PATH_MAP','META_AI_JID','MIN_PREKEY_COUNT','MIN_UPLOAD_INTERVAL',
|
|
156
|
+
'NOISE_MODE','NOISE_WA_HEADER','OFFICIAL_BIZ_JID','PHONE_CONNECTION_CB',
|
|
157
|
+
'PLACEHOLDER_MAX_AGE_SECONDS','PROCESSABLE_HISTORY_TYPES','PSA_WID','proto',
|
|
158
|
+
'SERVER_JID','STATUS_EXPIRY_SECONDS','STORIES_JID','S_WHATSAPP_NET','TimeMs',
|
|
159
|
+
'UNAUTHORIZED_CODES','UPLOAD_TIMEOUT','URL_REGEX','WA_ADV_ACCOUNT_SIG_PREFIX',
|
|
160
|
+
'WA_ADV_DEVICE_SIG_PREFIX','WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX',
|
|
161
|
+
'WA_ADV_HOSTED_DEVICE_SIG_PREFIX','WA_CERT_DETAILS','WA_DEFAULT_EPHEMERAL',
|
|
162
|
+
'WAJIDDomains',
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
// Register fungsi sebagai async-safe wrapper
|
|
166
|
+
for (const name of _functions) {
|
|
167
|
+
Object.defineProperty(module.exports, name, {
|
|
168
|
+
value: _wrapFn(name),
|
|
169
|
+
writable: true,
|
|
170
|
+
enumerable: true,
|
|
171
|
+
configurable: true,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// makeWASocket khusus — sync wrapper
|
|
176
|
+
Object.defineProperty(module.exports, 'makeWASocket', {
|
|
177
|
+
value: _wrapMakeWASocket(),
|
|
178
|
+
writable: true,
|
|
179
|
+
enumerable: true,
|
|
180
|
+
configurable: true,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Register konstanta sebagai lazy getter
|
|
184
|
+
for (const name of _constants) {
|
|
185
|
+
if (name in module.exports) continue;
|
|
186
|
+
Object.defineProperty(module.exports, name, {
|
|
187
|
+
get: _makeLazyGetter(name),
|
|
188
|
+
set(v) {
|
|
189
|
+
Object.defineProperty(module.exports, name, {
|
|
190
|
+
value: v, writable: true, enumerable: true, configurable: true,
|
|
191
|
+
});
|
|
192
|
+
},
|
|
193
|
+
enumerable: true,
|
|
194
|
+
configurable: true,
|
|
195
|
+
});
|
|
196
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @blckrose/baileys — CJS wrapper type declarations
|
|
3
|
+
*
|
|
4
|
+
* Destructure dan langsung pakai, tanpa await ready:
|
|
5
|
+
*
|
|
6
|
+
* const { makeWASocket, useMultiFileAuthState, Browsers } = require('@blckrose/baileys');
|
|
7
|
+
*
|
|
8
|
+
* async function start() {
|
|
9
|
+
* const { state, saveCreds } = await useMultiFileAuthState('./auth');
|
|
10
|
+
* const conn = makeWASocket({ auth: state });
|
|
11
|
+
* }
|
|
12
|
+
* start();
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export * from './lib/index.js';
|
|
16
|
+
export { default, default as makeWASocket } from './lib/index.js';
|
|
17
|
+
|
|
18
|
+
import type { UserFacingSocketConfig } from './lib/Types/index.js';
|
|
19
|
+
type BaileysModule = typeof import('./lib/index.js');
|
|
20
|
+
|
|
21
|
+
/** Promise yang resolve saat Baileys selesai load. Opsional — fungsi sudah auto-await. */
|
|
22
|
+
export declare const ready: Promise<BaileysModule>;
|
|
23
|
+
|
|
24
|
+
/** Load Baileys secara eksplisit. */
|
|
25
|
+
export declare function load(): Promise<BaileysModule>;
|
|
26
|
+
|
|
27
|
+
/** Convenience: load + makeWASocket sekaligus. */
|
|
28
|
+
export declare function createSocket(
|
|
29
|
+
config: UserFacingSocketConfig
|
|
30
|
+
): Promise<ReturnType<BaileysModule['default']>>;
|
|
@@ -205,7 +205,7 @@ export const makeMessagesRecvSocket = (config) => {
|
|
|
205
205
|
message: messageProto,
|
|
206
206
|
messageTimestamp: +child.attrs.t
|
|
207
207
|
}).toJSON();
|
|
208
|
-
await upsertMessage(fullMessage, '
|
|
208
|
+
await upsertMessage(fullMessage, 'notify');
|
|
209
209
|
logger.info('Processed plaintext newsletter message');
|
|
210
210
|
}
|
|
211
211
|
catch (error) {
|