@kyyinfinite/lumina 1.0.0
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/LICENSE +21 -0
- package/README.md +629 -0
- package/examples/ai-rich.js +84 -0
- package/examples/button.js +57 -0
- package/examples/carousel.js +51 -0
- package/examples/interactive.js +102 -0
- package/examples/media.js +66 -0
- package/examples/simple-bot.js +56 -0
- package/package.json +86 -0
- package/src/builders/ai-rich.js +644 -0
- package/src/builders/base.js +109 -0
- package/src/builders/button-v2.js +159 -0
- package/src/builders/button.js +398 -0
- package/src/builders/card.js +168 -0
- package/src/builders/carousel.js +122 -0
- package/src/builders/index.d.ts +1 -0
- package/src/builders/index.js +13 -0
- package/src/client/bot.js +192 -0
- package/src/client/connection.js +180 -0
- package/src/errors.js +88 -0
- package/src/index.d.ts +458 -0
- package/src/index.js +152 -0
- package/src/media/fetch.js +67 -0
- package/src/media/image.js +86 -0
- package/src/media/index.d.ts +1 -0
- package/src/media/index.js +12 -0
- package/src/media/resolver.js +115 -0
- package/src/media/uploader.js +65 -0
- package/src/media/video.js +195 -0
- package/src/parsers/code-tokenizer-keywords.js +128 -0
- package/src/parsers/code-tokenizer.js +191 -0
- package/src/parsers/index.d.ts +1 -0
- package/src/parsers/index.js +11 -0
- package/src/parsers/inline-entity.js +231 -0
- package/src/parsers/table-metadata.js +69 -0
- package/src/proto/enums.js +170 -0
- package/src/proto/index.d.ts +1 -0
- package/src/proto/index.js +13 -0
- package/src/proto/layouts.js +89 -0
- package/src/proto/primitives.js +181 -0
- package/src/proto/relay-nodes.js +55 -0
- package/src/proto/rich-response.js +144 -0
- package/src/proto/updater.js +318 -0
- package/src/services/index.d.ts +1 -0
- package/src/services/index.js +10 -0
- package/src/services/media-service.js +184 -0
- package/src/services/message-service.js +288 -0
- package/src/services/proto-service.js +90 -0
- package/src/utils/id.js +42 -0
- package/src/utils/logger.js +65 -0
- package/src/utils/mime.js +104 -0
- package/src/utils/promise.js +52 -0
- package/src/utils/validator.js +129 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ai-rich.js — AI Rich Response showcase.
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates every primitive AIRichBuilder supports:
|
|
5
|
+
* text (with inline entities) → code → image → table →
|
|
6
|
+
* tip → suggest → source → product → post
|
|
7
|
+
*
|
|
8
|
+
* Each method is awaited (eager async) and chainable.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import makeWASocket from '@whiskeysockets/baileys'
|
|
12
|
+
import { useMultiFileAuthState } from '@whiskeysockets/baileys'
|
|
13
|
+
import { Bot } from '../src/index.js'
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
const { state, saveCreds } = await useMultiFileAuthState('./.auth')
|
|
17
|
+
const socket = makeWASocket.default({ auth: state, printQRInTerminal: true })
|
|
18
|
+
const bot = new Bot(socket)
|
|
19
|
+
socket.ev.on('creds.update', saveCreds)
|
|
20
|
+
|
|
21
|
+
await new Promise((resolve) => {
|
|
22
|
+
socket.ev.on('connection.update', (u) => u.connection === 'open' && resolve())
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const jid = '62812xxxxxxx@s.whatsapp.net'
|
|
26
|
+
|
|
27
|
+
// ─── Full demo ─────────────────────────────────────────────────────
|
|
28
|
+
await bot.ai()
|
|
29
|
+
.title('Lumina AI Assistant')
|
|
30
|
+
.footer('Generated by Lumina v1.0.0')
|
|
31
|
+
.text(
|
|
32
|
+
[
|
|
33
|
+
'Halo! Saya adalah AI assistant yang dibangun di atas **Lumina**.',
|
|
34
|
+
'Coba kunjungi [dokumentasi](https://github.com/kyyinfinite/lumina) untuk info lebih lanjut.',
|
|
35
|
+
'Atau lihat referensi [API](https://github.com/kyyinfinite/lumina#api-reference).',
|
|
36
|
+
].join('\n'),
|
|
37
|
+
)
|
|
38
|
+
.code('javascript', [
|
|
39
|
+
'import { Bot } from "@kyyinfinite/lumina"',
|
|
40
|
+
'const bot = new Bot(socket)',
|
|
41
|
+
'await bot.text(jid, "Hello!")',
|
|
42
|
+
].join('\n'))
|
|
43
|
+
.image('https://picsum.photos/600/300')
|
|
44
|
+
.table([
|
|
45
|
+
['Fitur', 'Status', 'Catatan'],
|
|
46
|
+
['Text', '✓', 'Basic'],
|
|
47
|
+
['Image', '✓', 'Auto upload'],
|
|
48
|
+
['Video', '✓', 'Auto thumbnail'],
|
|
49
|
+
['AI Rich', '✓', '11 primitives'],
|
|
50
|
+
])
|
|
51
|
+
.tip('Tip: gunakan fluent API untuk chaining yang bersih.')
|
|
52
|
+
.suggest(['Lanjutkan', 'Ulangi', 'Info produk'])
|
|
53
|
+
.source([
|
|
54
|
+
['https://favicon.io/favicon.png', 'https://github.com', 'GitHub'],
|
|
55
|
+
['https://favicon.io/favicon.png', 'https://nodejs.org', 'Node.js'],
|
|
56
|
+
])
|
|
57
|
+
.send(jid)
|
|
58
|
+
|
|
59
|
+
// ─── Product carousel ──────────────────────────────────────────────
|
|
60
|
+
await bot.ai()
|
|
61
|
+
.title('Rekomendasi Produk')
|
|
62
|
+
.product([
|
|
63
|
+
{
|
|
64
|
+
title: 'Sepatu Lumina',
|
|
65
|
+
brand: 'Lumina',
|
|
66
|
+
price: 'Rp 250.000',
|
|
67
|
+
sale_price: 'Rp 199.000',
|
|
68
|
+
url: 'https://example.com/1',
|
|
69
|
+
image_url: 'https://picsum.photos/id/21/400/400',
|
|
70
|
+
icon_url: 'https://picsum.photos/id/21/64/64',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
title: 'Tas Lumina',
|
|
74
|
+
brand: 'Lumina',
|
|
75
|
+
price: 'Rp 350.000',
|
|
76
|
+
url: 'https://example.com/2',
|
|
77
|
+
image_url: 'https://picsum.photos/id/22/400/400',
|
|
78
|
+
icon_url: 'https://picsum.photos/id/22/64/64',
|
|
79
|
+
},
|
|
80
|
+
])
|
|
81
|
+
.send(jid)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
main()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* button.js — native-flow button builder.
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates:
|
|
5
|
+
* - ButtonBuilder fluent API (title/body/footer)
|
|
6
|
+
* - reply buttons (quick_reply)
|
|
7
|
+
* - URL button (cta_url)
|
|
8
|
+
* - Copy-to-clipboard button (cta_copy)
|
|
9
|
+
* - Callback-based selection (single_select with sections + rows)
|
|
10
|
+
* - Image header
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import makeWASocket from '@whiskeysockets/baileys'
|
|
14
|
+
import { useMultiFileAuthState } from '@whiskeysockets/baileys'
|
|
15
|
+
import { Bot } from '../src/index.js'
|
|
16
|
+
|
|
17
|
+
async function main() {
|
|
18
|
+
const { state, saveCreds } = await useMultiFileAuthState('./.auth')
|
|
19
|
+
const socket = makeWASocket.default({ auth: state, printQRInTerminal: true })
|
|
20
|
+
const bot = new Bot(socket)
|
|
21
|
+
socket.ev.on('creds.update', saveCreds)
|
|
22
|
+
|
|
23
|
+
// Wait for connection.
|
|
24
|
+
await new Promise((resolve) => {
|
|
25
|
+
socket.ev.on('connection.update', (u) => u.connection === 'open' && resolve())
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const jid = '62812xxxxxxx@s.whatsapp.net'
|
|
29
|
+
|
|
30
|
+
// ─── Simple reply + URL + copy ─────────────────────────────────────
|
|
31
|
+
await bot.button()
|
|
32
|
+
.title('Lumina Demo')
|
|
33
|
+
.body('Pilih salah satu menu di bawah ini.')
|
|
34
|
+
.footer('Powered by Lumina')
|
|
35
|
+
.image('https://picsum.photos/600/300')
|
|
36
|
+
.reply('Menu Utama', 'cmd_menu')
|
|
37
|
+
.reply('Owner', 'cmd_owner')
|
|
38
|
+
.url('Website', 'https://github.com/kyyinfinite/lumina')
|
|
39
|
+
.copy('Salin Token', 'LUMINA-TOKEN-1234')
|
|
40
|
+
.send(jid)
|
|
41
|
+
|
|
42
|
+
// ─── Callback-based selection ──────────────────────────────────────
|
|
43
|
+
await bot.button()
|
|
44
|
+
.title('Daftar Produk')
|
|
45
|
+
.body('Pilih kategori dan produk.')
|
|
46
|
+
.selection('Kategori', (sel) =>
|
|
47
|
+
sel
|
|
48
|
+
.section('Makanan', (s) => s
|
|
49
|
+
.row('Nasi Goreng', 'Nasi Goreng Special', 'Rp 25.000', 'food_nasgor')
|
|
50
|
+
.row('Mie Ayam', 'Mie Ayam Bakso', 'Rp 20.000', 'food_mieayam'))
|
|
51
|
+
.section('Minuman', (s) => s
|
|
52
|
+
.row('Es Teh', 'Es Teh Manis', 'Rp 5.000', 'drink_esteh')
|
|
53
|
+
.row('Kopi', 'Kopi Hitam', 'Rp 8.000', 'drink_kopi')))
|
|
54
|
+
.send(jid)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
main()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* carousel.js — multi-card carousel builder.
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates:
|
|
5
|
+
* - CarouselBuilder + CardBuilder composition
|
|
6
|
+
* - Media headers (image)
|
|
7
|
+
* - Reply buttons per card
|
|
8
|
+
* - Sending to a JID
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import makeWASocket from '@whiskeysockets/baileys'
|
|
12
|
+
import { useMultiFileAuthState } from '@whiskeysockets/baileys'
|
|
13
|
+
import { Bot } from '../src/index.js'
|
|
14
|
+
|
|
15
|
+
async function main() {
|
|
16
|
+
const { state, saveCreds } = await useMultiFileAuthState('./.auth')
|
|
17
|
+
const socket = makeWASocket.default({ auth: state, printQRInTerminal: true })
|
|
18
|
+
const bot = new Bot(socket)
|
|
19
|
+
socket.ev.on('creds.update', saveCreds)
|
|
20
|
+
|
|
21
|
+
await new Promise((resolve) => {
|
|
22
|
+
socket.ev.on('connection.update', (u) => u.connection === 'open' && resolve())
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const jid = '62812xxxxxxx@s.whatsapp.net'
|
|
26
|
+
|
|
27
|
+
const carousel = bot.carousel().body('Pilih produk favoritmu:')
|
|
28
|
+
|
|
29
|
+
// Build each card separately.
|
|
30
|
+
const products = [
|
|
31
|
+
{ name: 'Sepatu A', price: 'Rp 250.000', image: 'https://picsum.photos/id/21/600/400', cmd: 'buy_sepatu_a' },
|
|
32
|
+
{ name: 'Sepatu B', price: 'Rp 350.000', image: 'https://picsum.photos/id/22/600/400', cmd: 'buy_sepatu_b' },
|
|
33
|
+
{ name: 'Sepatu C', price: 'Rp 450.000', image: 'https://picsum.photos/id/23/600/400', cmd: 'buy_sepatu_c' },
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
for (const p of products) {
|
|
37
|
+
const card = await carousel
|
|
38
|
+
.newCard()
|
|
39
|
+
.title(p.name)
|
|
40
|
+
.body(p.price)
|
|
41
|
+
.footer('Klik beli untuk memesan')
|
|
42
|
+
.image(p.image)
|
|
43
|
+
.reply('Beli', p.cmd)
|
|
44
|
+
.build()
|
|
45
|
+
carousel.card(card)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await carousel.send(jid)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
main()
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* interactive.js — combined showcase of every interactive primitive.
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates:
|
|
5
|
+
* - ButtonBuilder with image header + selection
|
|
6
|
+
* - ButtonV2Builder (legacy) with thumbnail fallback
|
|
7
|
+
* - CarouselBuilder with multiple cards
|
|
8
|
+
* - AIRichBuilder with text + code + table + image + suggest
|
|
9
|
+
* - Reply / react / edit / delete on incoming messages
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import makeWASocket from '@whiskeysockets/baileys'
|
|
13
|
+
import { useMultiFileAuthState } from '@whiskeysockets/baileys'
|
|
14
|
+
import { Bot } from '../src/index.js'
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
const { state, saveCreds } = await useMultiFileAuthState('./.auth')
|
|
18
|
+
const socket = makeWASocket.default({ auth: state, printQRInTerminal: true })
|
|
19
|
+
const bot = new Bot(socket)
|
|
20
|
+
socket.ev.on('creds.update', saveCreds)
|
|
21
|
+
|
|
22
|
+
await new Promise((resolve) => {
|
|
23
|
+
socket.ev.on('connection.update', (u) => u.connection === 'open' && resolve())
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const jid = '62812xxxxxxx@s.whatsapp.net'
|
|
27
|
+
|
|
28
|
+
// ─── 1. Native-flow button with selection ──────────────────────────
|
|
29
|
+
await bot.button()
|
|
30
|
+
.title('Interactive Demo')
|
|
31
|
+
.body('Coba berbagai jenis button di bawah ini.')
|
|
32
|
+
.footer('Lumina v1.0.0')
|
|
33
|
+
.reply('Quick Reply', 'qr_1')
|
|
34
|
+
.url('Buka Browser', 'https://github.com/kyyinfinite/lumina')
|
|
35
|
+
.copy('Salin Kode', 'LUMINA-2025')
|
|
36
|
+
.call('Telepon CS', '62812xxxxxxx')
|
|
37
|
+
.selection('Pilih Menu', (sel) =>
|
|
38
|
+
sel
|
|
39
|
+
.section('Utama', (s) => s
|
|
40
|
+
.row('A', 'Menu A', 'Deskripsi A', 'menu_a')
|
|
41
|
+
.row('B', 'Menu B', 'Deskripsi B', 'menu_b'))
|
|
42
|
+
.section('Tambahan', (s) => s
|
|
43
|
+
.row('C', 'Menu C', 'Deskripsi C', 'menu_c')))
|
|
44
|
+
.send(jid)
|
|
45
|
+
|
|
46
|
+
// ─── 2. Legacy ButtonsMessage (ButtonV2) ───────────────────────────
|
|
47
|
+
await bot.buttonV2()
|
|
48
|
+
.title('Legacy Button')
|
|
49
|
+
.body('ButtonV2 untuk WhatsApp client lama.')
|
|
50
|
+
.footer('Powered by Lumina')
|
|
51
|
+
.thumbnail('https://picsum.photos/300')
|
|
52
|
+
.button('OK', 'btn_ok')
|
|
53
|
+
.button('Cancel', 'btn_cancel')
|
|
54
|
+
.send(jid)
|
|
55
|
+
|
|
56
|
+
// ─── 3. Carousel of products ──────────────────────────────────────
|
|
57
|
+
const car = bot.carousel().body('Pilih produk:')
|
|
58
|
+
for (const id of [10, 20, 30]) {
|
|
59
|
+
const card = await car
|
|
60
|
+
.newCard()
|
|
61
|
+
.title(`Produk ${id}`)
|
|
62
|
+
.body(`Harga Rp ${id}.000`)
|
|
63
|
+
.image(`https://picsum.photos/id/${id}/400/300`)
|
|
64
|
+
.reply('Beli', `buy_${id}`)
|
|
65
|
+
.build()
|
|
66
|
+
car.card(card)
|
|
67
|
+
}
|
|
68
|
+
await car.send(jid)
|
|
69
|
+
|
|
70
|
+
// ─── 4. AI Rich Response ──────────────────────────────────────────
|
|
71
|
+
await bot.ai()
|
|
72
|
+
.title('AI Demo')
|
|
73
|
+
.text('Ini **AI Rich Response** dengan [link](https://lumina.dev) inline.')
|
|
74
|
+
.code('javascript', 'console.log("Hello from Lumina!")')
|
|
75
|
+
.table([['A', 'B'], ['1', '2'], ['3', '4']])
|
|
76
|
+
.image('https://picsum.photos/600/300')
|
|
77
|
+
.suggest(['Lanjut', 'Stop'])
|
|
78
|
+
.send(jid)
|
|
79
|
+
|
|
80
|
+
// ─── 5. React + edit + delete on incoming ──────────────────────────
|
|
81
|
+
bot.on('messages.upsert', async ({ messages }) => {
|
|
82
|
+
const m = messages[0]
|
|
83
|
+
if (!m?.message || m.key.fromMe) return
|
|
84
|
+
|
|
85
|
+
// React with thumbs-up.
|
|
86
|
+
await bot.react(m.key.remoteJid, m.key, '👍')
|
|
87
|
+
|
|
88
|
+
// Reply with text.
|
|
89
|
+
const sent = await bot.text(m.key.remoteJid, 'Got your message!')
|
|
90
|
+
|
|
91
|
+
// After 2s, edit it.
|
|
92
|
+
setTimeout(async () => {
|
|
93
|
+
try {
|
|
94
|
+
await bot.edit(m.key.remoteJid, sent.key, '(edited) message received ✅')
|
|
95
|
+
} catch (e) {
|
|
96
|
+
console.error('edit failed:', e.message)
|
|
97
|
+
}
|
|
98
|
+
}, 2000)
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
main()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* media.js — MediaService showcase.
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates:
|
|
5
|
+
* - bot.media.fetch(url)
|
|
6
|
+
* - bot.media.resize(buf, opts)
|
|
7
|
+
* - bot.media.thumbnail(buf)
|
|
8
|
+
* - bot.media.duration(buf)
|
|
9
|
+
* - bot.media.videoThumbnail(buf)
|
|
10
|
+
* - bot.media.upload(buf, type)
|
|
11
|
+
* - bot.media.sniff(buf)
|
|
12
|
+
* - bot.media.resolve(source, opts)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import makeWASocket from '@whiskeysockets/baileys'
|
|
16
|
+
import { useMultiFileAuthState } from '@whiskeysockets/baileys'
|
|
17
|
+
import { Bot } from '../src/index.js'
|
|
18
|
+
import { writeFileSync } from 'node:fs'
|
|
19
|
+
|
|
20
|
+
async function main() {
|
|
21
|
+
const { state, saveCreds } = await useMultiFileAuthState('./.auth')
|
|
22
|
+
const socket = makeWASocket.default({ auth: state, printQRInTerminal: true })
|
|
23
|
+
const bot = new Bot(socket)
|
|
24
|
+
socket.ev.on('creds.update', saveCreds)
|
|
25
|
+
|
|
26
|
+
await new Promise((resolve) => {
|
|
27
|
+
socket.ev.on('connection.update', (u) => u.connection === 'open' && resolve())
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// ─── Fetch + resize ────────────────────────────────────────────────
|
|
31
|
+
const imageUrl = 'https://picsum.photos/1200/800'
|
|
32
|
+
const imageBuf = await bot.media.fetch(imageUrl)
|
|
33
|
+
console.log('fetched image bytes:', imageBuf.length)
|
|
34
|
+
|
|
35
|
+
const thumb = await bot.media.resize(imageBuf, {
|
|
36
|
+
width: 200,
|
|
37
|
+
height: 200,
|
|
38
|
+
fit: 'cover',
|
|
39
|
+
format: 'jpeg',
|
|
40
|
+
})
|
|
41
|
+
writeFileSync('./download/thumb.jpg', thumb)
|
|
42
|
+
console.log('thumbnail saved to ./download/thumb.jpg')
|
|
43
|
+
|
|
44
|
+
// ─── Sniff MIME ────────────────────────────────────────────────────
|
|
45
|
+
const mime = bot.media.sniff(imageBuf, 'photo.jpg')
|
|
46
|
+
console.log('sniffed MIME:', mime, '→ category:', bot.media.category(mime))
|
|
47
|
+
|
|
48
|
+
// ─── Upload to WhatsApp ────────────────────────────────────────────
|
|
49
|
+
const cdnUrl = await bot.media.upload(imageBuf, 'image')
|
|
50
|
+
console.log('uploaded to WA CDN:', cdnUrl)
|
|
51
|
+
|
|
52
|
+
// ─── Resolve (URL → URL passthrough, since wa.me) ──────────────────
|
|
53
|
+
// For non-wa.me URLs, resolve() will fetch + upload automatically.
|
|
54
|
+
const resolved = await bot.media.resolve('https://picsum.photos/100', {
|
|
55
|
+
mediaType: 'image',
|
|
56
|
+
strategy: 'auto',
|
|
57
|
+
})
|
|
58
|
+
console.log('resolved:', resolved)
|
|
59
|
+
|
|
60
|
+
// ─── Video duration + thumbnail ────────────────────────────────────
|
|
61
|
+
// const videoBuf = await bot.media.fetch('https://example.com/clip.mp4')
|
|
62
|
+
// const dur = bot.media.duration(videoBuf)
|
|
63
|
+
// const frame = await bot.media.videoThumbnail(videoBuf, { time: 0, result: 'base64' })
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
main()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* simple-bot.js — minimal Lumina bot.
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates: text(), reply(), and the events bus.
|
|
5
|
+
*
|
|
6
|
+
* Run: node examples/simple-bot.js
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import makeWASocket from '@whiskeysockets/baileys'
|
|
10
|
+
import { useMultiFileAuthState, DisconnectReason } from '@whiskeysockets/baileys'
|
|
11
|
+
import { Bot } from '../src/index.js'
|
|
12
|
+
|
|
13
|
+
async function start() {
|
|
14
|
+
const { state, saveCreds } = await useMultiFileAuthState('./.auth')
|
|
15
|
+
|
|
16
|
+
const socket = makeWASocket.default({
|
|
17
|
+
auth: state,
|
|
18
|
+
printQRInTerminal: true,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const bot = new Bot(socket, {
|
|
22
|
+
uploadJid: '62831@s.whatsapp.net',
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
socket.ev.on('creds.update', saveCreds)
|
|
26
|
+
|
|
27
|
+
socket.ev.on('connection.update', (update) => {
|
|
28
|
+
const { connection, lastDisconnect } = update
|
|
29
|
+
if (connection === 'close') {
|
|
30
|
+
const shouldReconnect =
|
|
31
|
+
lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut
|
|
32
|
+
if (shouldReconnect) start()
|
|
33
|
+
} else if (connection === 'open') {
|
|
34
|
+
console.log('[lumina] connection opened')
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
bot.on('messages.upsert', async ({ messages }) => {
|
|
39
|
+
const m = messages[0]
|
|
40
|
+
if (!m?.message || m.key.fromMe) return
|
|
41
|
+
|
|
42
|
+
const jid = m.key.remoteJid
|
|
43
|
+
const text =
|
|
44
|
+
m.message.conversation ??
|
|
45
|
+
m.message.extendedTextMessage?.text ??
|
|
46
|
+
''
|
|
47
|
+
|
|
48
|
+
if (text.toLowerCase() === 'ping') {
|
|
49
|
+
await bot.text(jid, 'pong 🏓')
|
|
50
|
+
} else if (text.toLowerCase() === 'hello') {
|
|
51
|
+
await bot.reply(jid, 'Hi there!', m)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
start()
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kyyinfinite/lumina",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Lumina — Modern WhatsApp framework built on top of Baileys. Hide the protocol complexity, expose a fluent API.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"import": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./parsers": {
|
|
14
|
+
"types": "./src/parsers/index.d.ts",
|
|
15
|
+
"import": "./src/parsers/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./media": {
|
|
18
|
+
"types": "./src/media/index.d.ts",
|
|
19
|
+
"import": "./src/media/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./proto": {
|
|
22
|
+
"types": "./src/proto/index.d.ts",
|
|
23
|
+
"import": "./src/proto/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./services": {
|
|
26
|
+
"types": "./src/services/index.d.ts",
|
|
27
|
+
"import": "./src/services/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./builders": {
|
|
30
|
+
"types": "./src/builders/index.d.ts",
|
|
31
|
+
"import": "./src/builders/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"src",
|
|
36
|
+
"examples",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"test": "echo 'no tests yet' && exit 0"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"whatsapp",
|
|
45
|
+
"baileys",
|
|
46
|
+
"framework",
|
|
47
|
+
"bot",
|
|
48
|
+
"whatsapp-bot",
|
|
49
|
+
"lumina",
|
|
50
|
+
"native-flow",
|
|
51
|
+
"interactive-message",
|
|
52
|
+
"ai-rich",
|
|
53
|
+
"carousel"
|
|
54
|
+
],
|
|
55
|
+
"author": "KyyInfinite <kyyinfinite@github.com>",
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "git+https://github.com/kyyinfinite/lumina.git"
|
|
60
|
+
},
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/kyyinfinite/lumina/issues"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://github.com/kyyinfinite/lumina#readme",
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=20"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"@whiskeysockets/baileys": "^6.7.0"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"@whiskeysockets/baileys": {
|
|
73
|
+
"optional": false
|
|
74
|
+
},
|
|
75
|
+
"sharp": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"fluent-ffmpeg": {
|
|
79
|
+
"optional": true
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"optionalDependencies": {
|
|
83
|
+
"sharp": "^0.33.0",
|
|
84
|
+
"fluent-ffmpeg": "^2.1.0"
|
|
85
|
+
}
|
|
86
|
+
}
|