@kyyinfinite/lumina 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/builders/ai-rich.js +0 -165
- package/src/builders/base.js +4 -51
- package/src/builders/button-v2.js +13 -78
- package/src/builders/button.js +20 -234
- package/src/builders/card.js +9 -76
- package/src/builders/carousel.js +4 -61
- package/src/builders/index.js +1 -7
- package/src/builders/sticker.js +102 -0
- package/src/client/bot.js +28 -153
- package/src/client/connection.js +4 -111
- package/src/errors.js +0 -37
- package/src/index.d.ts +1 -28
- package/src/index.js +23 -121
- package/src/media/fetch.js +2 -33
- package/src/media/image.js +1 -41
- package/src/media/resolver.js +3 -55
- package/src/media/sticker.js +124 -0
- package/src/media/uploader.js +0 -30
- package/src/media/video.js +1 -39
- package/src/parsers/code-tokenizer-keywords.js +0 -12
- package/src/parsers/code-tokenizer.js +0 -42
- package/src/parsers/index.js +0 -7
- package/src/parsers/inline-entity.js +8 -117
- package/src/parsers/table-metadata.js +1 -35
- package/src/proto/enums.js +9 -65
- package/src/proto/layouts.js +3 -64
- package/src/proto/primitives.js +4 -91
- package/src/proto/relay-nodes.js +1 -32
- package/src/proto/rich-response.js +6 -57
- package/src/proto/updater.js +0 -85
- package/src/services/index.js +0 -7
- package/src/services/media-service.js +1 -102
- package/src/services/message-service.js +16 -158
- package/src/services/proto-service.js +3 -57
- package/src/utils/id.js +0 -25
- package/src/utils/logger.js +2 -39
- package/src/utils/mime.js +17 -73
- package/src/utils/promise.js +0 -26
- package/src/utils/validator.js +6 -71
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { toSticker, addExif } from '../media/sticker.js'
|
|
2
|
+
import { fetchBuffer } from '../media/fetch.js'
|
|
3
|
+
import { sniffMime, mimeToCategory } from '../utils/mime.js'
|
|
4
|
+
import { coerceMediaSource } from '../utils/validator.js'
|
|
5
|
+
import { createInteractiveNodes } from '../proto/relay-nodes.js'
|
|
6
|
+
|
|
7
|
+
export class StickerBuilder {
|
|
8
|
+
constructor(conn) {
|
|
9
|
+
this.#conn = conn
|
|
10
|
+
this._source = null
|
|
11
|
+
this._type = null
|
|
12
|
+
this._packname = 'Lumina'
|
|
13
|
+
this._author = ''
|
|
14
|
+
this._categories = ['']
|
|
15
|
+
this._extra = {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#conn
|
|
19
|
+
|
|
20
|
+
source(input) {
|
|
21
|
+
this._source = input
|
|
22
|
+
return this
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pack(packname, author = '') {
|
|
26
|
+
this._packname = packname
|
|
27
|
+
this._author = author
|
|
28
|
+
return this
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
author(author) {
|
|
32
|
+
this._author = author
|
|
33
|
+
return this
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
emoji(...emojis) {
|
|
37
|
+
this._categories = emojis.flat()
|
|
38
|
+
return this
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type(type) {
|
|
42
|
+
this._type = type
|
|
43
|
+
return this
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
extra(obj) {
|
|
47
|
+
Object.assign(this._extra, obj)
|
|
48
|
+
return this
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#metadata() {
|
|
52
|
+
return {
|
|
53
|
+
packname: this._packname,
|
|
54
|
+
author: this._author,
|
|
55
|
+
categories: this._categories,
|
|
56
|
+
extra: this._extra,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async #resolveBuffer() {
|
|
61
|
+
if (!this._source) throw new Error('sticker source is required — call .source(buffer|url)')
|
|
62
|
+
|
|
63
|
+
let buffer
|
|
64
|
+
|
|
65
|
+
if (Buffer.isBuffer(this._source)) {
|
|
66
|
+
buffer = this._source
|
|
67
|
+
} else if (typeof this._source === 'string') {
|
|
68
|
+
buffer = await fetchBuffer(this._source)
|
|
69
|
+
} else {
|
|
70
|
+
const { raw } = coerceMediaSource(this._source)
|
|
71
|
+
buffer = Buffer.isBuffer(raw) ? raw : await fetchBuffer(raw.url)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return buffer
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#detectType(buffer) {
|
|
78
|
+
if (this._type) return this._type
|
|
79
|
+
const mime = sniffMime(buffer)
|
|
80
|
+
const cat = mimeToCategory(mime)
|
|
81
|
+
if (cat === 'video') return 'video'
|
|
82
|
+
return 'image'
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async build() {
|
|
86
|
+
const buffer = await this.#resolveBuffer()
|
|
87
|
+
const type = this.#detectType(buffer)
|
|
88
|
+
return toSticker(buffer, type, this.#metadata())
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async send(jid, opts = {}) {
|
|
92
|
+
const stickerBuffer = await this.build()
|
|
93
|
+
const msg = await this.#conn.generateMessage(jid, { sticker: stickerBuffer }, opts)
|
|
94
|
+
await this.#conn.relayMessage(msg.key.remoteJid, msg.message, {
|
|
95
|
+
messageId: msg.key.id,
|
|
96
|
+
...opts,
|
|
97
|
+
})
|
|
98
|
+
return msg
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export default StickerBuilder
|
package/src/client/bot.js
CHANGED
|
@@ -1,45 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file client/bot.js
|
|
3
|
-
* @module lumina/client/bot
|
|
4
|
-
*
|
|
5
|
-
* Bot — primary entry point. Wraps a Baileys socket, exposes a fluent,
|
|
6
|
-
* verb-first API, and provides factory methods for every builder.
|
|
7
|
-
*
|
|
8
|
-
* const bot = new Bot(socket)
|
|
9
|
-
* await bot.text(jid, 'Halo')
|
|
10
|
-
* await bot.button().title('T').body('B').reply('OK').send(jid)
|
|
11
|
-
* await bot.ai().text('hi').code('js', 'console.log(1)').send(jid)
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
1
|
import { Connection } from './connection.js'
|
|
15
2
|
import { MediaService } from '../services/media-service.js'
|
|
16
3
|
import { ProtoService } from '../services/proto-service.js'
|
|
17
4
|
import { MessageService } from '../services/message-service.js'
|
|
18
|
-
|
|
19
5
|
import { ButtonBuilder } from '../builders/button.js'
|
|
20
6
|
import { ButtonV2Builder } from '../builders/button-v2.js'
|
|
21
7
|
import { CarouselBuilder } from '../builders/carousel.js'
|
|
22
8
|
import { AIRichBuilder } from '../builders/ai-rich.js'
|
|
23
|
-
|
|
9
|
+
import { StickerBuilder } from '../builders/sticker.js'
|
|
24
10
|
import { extractInlineEntities, tokenizeCode, toTableMetadata } from '../parsers/index.js'
|
|
25
11
|
import { createLogger } from '../utils/logger.js'
|
|
26
12
|
|
|
27
|
-
/** @typedef {import('@whiskeysockets/baileys').WASocket} WASocket */
|
|
28
|
-
/** @typedef {import('../utils/logger.js').Logger} Logger */
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @typedef {object} BotOptions
|
|
32
|
-
* @property {string} [uploadJid] Pre-upload JID for media uploads.
|
|
33
|
-
* @property {Logger} [logger] Custom logger.
|
|
34
|
-
* @property {boolean} [mediaCache=true] Enable MediaService URL cache.
|
|
35
|
-
* @property {string} [uploadJidDefault] Alias for uploadJid.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
13
|
export class Bot {
|
|
39
|
-
/**
|
|
40
|
-
* @param {WASocket} socket
|
|
41
|
-
* @param {BotOptions} [opts]
|
|
42
|
-
*/
|
|
43
14
|
constructor(socket, opts = {}) {
|
|
44
15
|
this.logger = opts.logger ?? createLogger({ level: 'warn' })
|
|
45
16
|
|
|
@@ -57,136 +28,40 @@ export class Bot {
|
|
|
57
28
|
this.proto = new ProtoService(this.connection)
|
|
58
29
|
this.message = new MessageService(this.connection, this.proto, this.media)
|
|
59
30
|
|
|
60
|
-
|
|
61
|
-
this.util = {
|
|
62
|
-
extractInlineEntities,
|
|
63
|
-
tokenizeCode,
|
|
64
|
-
toTableMetadata,
|
|
65
|
-
}
|
|
31
|
+
this.util = { extractInlineEntities, tokenizeCode, toTableMetadata }
|
|
66
32
|
}
|
|
67
33
|
|
|
68
|
-
|
|
34
|
+
text(jid, text, opts) { return this.message.text(jid, text, opts) }
|
|
35
|
+
image(jid, source, caption, opts) { return this.message.image(jid, source, caption, opts) }
|
|
36
|
+
video(jid, source, caption, opts) { return this.message.video(jid, source, caption, opts) }
|
|
37
|
+
audio(jid, source, opts) { return this.message.audio(jid, source, opts) }
|
|
38
|
+
document(jid, source, opts) { return this.message.document(jid, source, opts) }
|
|
39
|
+
sticker(jid, source, opts) { return this.message.sticker(jid, source, opts) }
|
|
40
|
+
contact(jid, contacts, opts) { return this.message.contact(jid, contacts, opts) }
|
|
41
|
+
location(jid, lat, lng, opts) { return this.message.location(jid, lat, lng, opts) }
|
|
42
|
+
poll(jid, name, options, opts) { return this.message.poll(jid, name, options, opts) }
|
|
43
|
+
reply(jid, text, quoted, opts) { return this.message.reply(jid, text, quoted, opts) }
|
|
44
|
+
react(jid, key, emoji, opts) { return this.message.react(jid, key, emoji, opts) }
|
|
45
|
+
delete(jid, key) { return this.message.delete(jid, key) }
|
|
46
|
+
forward(jid, message, opts) { return this.message.forward(jid, message, opts) }
|
|
47
|
+
copy(jid, message, opts) { return this.message.copy(jid, message, opts) }
|
|
48
|
+
edit(jid, key, newText, opts) { return this.message.edit(jid, key, newText, opts) }
|
|
69
49
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
50
|
+
button() { return new ButtonBuilder(this.connection, this.proto, this.media) }
|
|
51
|
+
buttonV2() { return new ButtonV2Builder(this.connection) }
|
|
52
|
+
carousel() { return new CarouselBuilder(this.connection, this.proto, this.media) }
|
|
53
|
+
ai() { return new AIRichBuilder(this.connection, this.proto, this.media) }
|
|
54
|
+
sticker() { return new StickerBuilder(this.connection) }
|
|
74
55
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return this.message.image(jid, source, caption, opts)
|
|
56
|
+
async sendSticker(jid, source, opts = {}) {
|
|
57
|
+
return this.sticker().source(source).pack(opts.packname, opts.author).emoji(...(opts.categories ?? [''])).send(jid, opts)
|
|
78
58
|
}
|
|
79
59
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** @param {string} jid @param {string | Buffer} source @param {object} [opts] */
|
|
86
|
-
audio(jid, source, opts) {
|
|
87
|
-
return this.message.audio(jid, source, opts)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** @param {string} jid @param {string | Buffer} source @param {object} [opts] */
|
|
91
|
-
document(jid, source, opts) {
|
|
92
|
-
return this.message.document(jid, source, opts)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** @param {string} jid @param {string | Buffer} source @param {object} [opts] */
|
|
96
|
-
sticker(jid, source, opts) {
|
|
97
|
-
return this.message.sticker(jid, source, opts)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/** @param {string} jid @param {Array} contacts @param {object} [opts] */
|
|
101
|
-
contact(jid, contacts, opts) {
|
|
102
|
-
return this.message.contact(jid, contacts, opts)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/** @param {string} jid @param {number} lat @param {number} lng @param {object} [opts] */
|
|
106
|
-
location(jid, lat, lng, opts) {
|
|
107
|
-
return this.message.location(jid, lat, lng, opts)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** @param {string} jid @param {string} name @param {string[]} options @param {object} [opts] */
|
|
111
|
-
poll(jid, name, options, opts) {
|
|
112
|
-
return this.message.poll(jid, name, options, opts)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** @param {string} jid @param {string} text @param {object} quoted @param {object} [opts] */
|
|
116
|
-
reply(jid, text, quoted, opts) {
|
|
117
|
-
return this.message.reply(jid, text, quoted, opts)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** @param {string} jid @param {object} key @param {string} emoji @param {object} [opts] */
|
|
121
|
-
react(jid, key, emoji, opts) {
|
|
122
|
-
return this.message.react(jid, key, emoji, opts)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** @param {string} jid @param {object} key */
|
|
126
|
-
delete(jid, key) {
|
|
127
|
-
return this.message.delete(jid, key)
|
|
128
|
-
}
|
|
60
|
+
on(event, handler) { return this.connection.on(event, handler) }
|
|
61
|
+
once(event, handler) { return this.connection.once(event, handler) }
|
|
62
|
+
off(event, handler) { this.connection.off(event, handler) }
|
|
129
63
|
|
|
130
|
-
|
|
131
|
-
forward(jid, message, opts) {
|
|
132
|
-
return this.message.forward(jid, message, opts)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** @param {string} jid @param {object} message @param {object} [opts] */
|
|
136
|
-
copy(jid, message, opts) {
|
|
137
|
-
return this.message.copy(jid, message, opts)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** @param {string} jid @param {object} key @param {string} newText @param {object} [opts] */
|
|
141
|
-
edit(jid, key, newText, opts) {
|
|
142
|
-
return this.message.edit(jid, key, newText, opts)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// ─── Builder factories ─────────────────────────────────────────────
|
|
146
|
-
|
|
147
|
-
/** @returns {ButtonBuilder} */
|
|
148
|
-
button() {
|
|
149
|
-
return new ButtonBuilder(this.connection, this.proto, this.media)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/** @returns {ButtonV2Builder} */
|
|
153
|
-
buttonV2() {
|
|
154
|
-
return new ButtonV2Builder(this.connection)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** @returns {CarouselBuilder} */
|
|
158
|
-
carousel() {
|
|
159
|
-
return new CarouselBuilder(this.connection, this.proto, this.media)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** @returns {AIRichBuilder} */
|
|
163
|
-
ai() {
|
|
164
|
-
return new AIRichBuilder(this.connection, this.proto, this.media)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// ─── Event bus ─────────────────────────────────────────────────────
|
|
168
|
-
|
|
169
|
-
/** @param {string} event @param {(...a: any[]) => void} handler @returns {() => void} */
|
|
170
|
-
on(event, handler) {
|
|
171
|
-
return this.connection.on(event, handler)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/** @param {string} event @param {(...a: any[]) => void} handler @returns {() => void} */
|
|
175
|
-
once(event, handler) {
|
|
176
|
-
return this.connection.once(event, handler)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** @param {string} event @param {(...a: any[]) => void} handler */
|
|
180
|
-
off(event, handler) {
|
|
181
|
-
this.connection.off(event, handler)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// ─── Raw escape ────────────────────────────────────────────────────
|
|
185
|
-
|
|
186
|
-
/** @returns {WASocket} */
|
|
187
|
-
get raw() {
|
|
188
|
-
return this.connection.raw
|
|
189
|
-
}
|
|
64
|
+
get raw() { return this.connection.raw }
|
|
190
65
|
}
|
|
191
66
|
|
|
192
67
|
export default Bot
|
package/src/client/connection.js
CHANGED
|
@@ -1,42 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file connection.js
|
|
3
|
-
* @module lumina/client/connection
|
|
4
|
-
*
|
|
5
|
-
* Connection — Baileys socket adapter. This is the ONLY module in the whole
|
|
6
|
-
* framework that knows about Baileys' raw API surface. Every other module
|
|
7
|
-
* talks to Baileys through one of the four ports Connection exposes:
|
|
8
|
-
*
|
|
9
|
-
* - MediaPort → uploadMedia
|
|
10
|
-
* - GeneratePort → generateMessage
|
|
11
|
-
* - RelayPort → relayMessage
|
|
12
|
-
* - EventBus → on / once / off
|
|
13
|
-
*
|
|
14
|
-
* If Baileys renames `relayMessage` to `sendRaw`, this is the only file
|
|
15
|
-
* that needs updating.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
1
|
import { ConnectionError } from '../errors.js'
|
|
19
2
|
|
|
20
|
-
/** @typedef {import('@whiskeysockets/baileys').WASocket} WASocket */
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @typedef {object} ConnectionOptions
|
|
24
|
-
* @property {string} [uploadJid] Default JID used for pre-uploading media.
|
|
25
|
-
* @property {import('../utils/logger.js').Logger} [logger]
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
3
|
export class Connection {
|
|
29
|
-
/** @param {WASocket} socket */
|
|
30
|
-
/** @param {ConnectionOptions} [opts] */
|
|
31
4
|
constructor(socket, opts = {}) {
|
|
32
|
-
if (!socket) {
|
|
33
|
-
throw new ConnectionError('socket is required', { code: 'LUMINA_CONNECTION_NO_SOCKET' })
|
|
34
|
-
}
|
|
5
|
+
if (!socket) throw new ConnectionError('socket is required', { code: 'LUMINA_CONNECTION_NO_SOCKET' })
|
|
35
6
|
this.#socket = socket
|
|
36
7
|
this.uploadJid = opts.uploadJid
|
|
37
8
|
this.logger = opts.logger
|
|
38
9
|
|
|
39
|
-
// Verify the bare-minimum API surface we depend on.
|
|
40
10
|
const required = ['relayMessage', 'ev']
|
|
41
11
|
for (const m of required) {
|
|
42
12
|
if (typeof socket[m] === 'undefined') {
|
|
@@ -47,18 +17,8 @@ export class Connection {
|
|
|
47
17
|
}
|
|
48
18
|
}
|
|
49
19
|
|
|
50
|
-
/** @type {WASocket | null} */
|
|
51
20
|
#socket = null
|
|
52
21
|
|
|
53
|
-
/**
|
|
54
|
-
* Upload media via Baileys' `prepareWAMessageMedia`. We lazy-import it so
|
|
55
|
-
* that the framework loads even if the user's Baileys version is older
|
|
56
|
-
* than the one we tested against.
|
|
57
|
-
*
|
|
58
|
-
* @param {object} media `{ image: Buffer | { url } }` etc.
|
|
59
|
-
* @param {object} [opts] `{ jid, ... }` forwarded to prepareWAMessageMedia.
|
|
60
|
-
* @returns {Promise<object>}
|
|
61
|
-
*/
|
|
62
22
|
async uploadMedia(media, opts = {}) {
|
|
63
23
|
const { prepareWAMessageMedia } = await import('@whiskeysockets/baileys')
|
|
64
24
|
const jid = opts.jid ?? this.uploadJid
|
|
@@ -67,111 +27,44 @@ export class Connection {
|
|
|
67
27
|
code: 'LUMINA_CONNECTION_NO_UPLOAD_JID',
|
|
68
28
|
})
|
|
69
29
|
}
|
|
70
|
-
return prepareWAMessageMedia(media, {
|
|
71
|
-
upload: this.#socket.waUploadToServer,
|
|
72
|
-
jid,
|
|
73
|
-
...opts,
|
|
74
|
-
})
|
|
30
|
+
return prepareWAMessageMedia(media, { upload: this.#socket.waUploadToServer, jid, ...opts })
|
|
75
31
|
}
|
|
76
32
|
|
|
77
|
-
/**
|
|
78
|
-
* Generate a WA message object from a content descriptor.
|
|
79
|
-
*
|
|
80
|
-
* @param {string} jid
|
|
81
|
-
* @param {object} content
|
|
82
|
-
* @param {object} [opts]
|
|
83
|
-
* @returns {Promise<object>}
|
|
84
|
-
*/
|
|
85
33
|
async generateMessage(jid, content, opts = {}) {
|
|
86
34
|
const { generateWAMessageFromContent } = await import('@whiskeysockets/baileys')
|
|
87
35
|
return generateWAMessageFromContent(jid, content, opts)
|
|
88
36
|
}
|
|
89
37
|
|
|
90
|
-
/**
|
|
91
|
-
* Generate a poll message.
|
|
92
|
-
*
|
|
93
|
-
* @param {string} jid
|
|
94
|
-
* @param {object} opts { name, values, selectableCount, toJid, messageSecret }
|
|
95
|
-
* @returns {Promise<object>}
|
|
96
|
-
*/
|
|
97
38
|
async generatePoll(jid, opts) {
|
|
98
39
|
const { generatePollMessage } = await import('@whiskeysockets/baileys')
|
|
99
40
|
return generatePollMessage(jid, opts)
|
|
100
41
|
}
|
|
101
42
|
|
|
102
|
-
/**
|
|
103
|
-
* Generate a reaction message.
|
|
104
|
-
*
|
|
105
|
-
* @param {string} jid
|
|
106
|
-
* @param {object} opts { key, text }
|
|
107
|
-
* @returns {Promise<object>}
|
|
108
|
-
*/
|
|
109
43
|
async generateReaction(jid, opts) {
|
|
110
44
|
const { generateReactionMessage } = await import('@whiskeysockets/baileys')
|
|
111
45
|
return generateReactionMessage(jid, opts)
|
|
112
46
|
}
|
|
113
47
|
|
|
114
|
-
/**
|
|
115
|
-
* Relay a pre-built message via `relayMessage`. Returns the message ID.
|
|
116
|
-
*
|
|
117
|
-
* @param {string} jid
|
|
118
|
-
* @param {object} message
|
|
119
|
-
* @param {object} [opts]
|
|
120
|
-
* @returns {Promise<string>}
|
|
121
|
-
*/
|
|
122
48
|
async relayMessage(jid, message, opts = {}) {
|
|
123
49
|
const messageId = opts.messageId ?? this.#socket.generateMessageTag()
|
|
124
|
-
await this.#socket.relayMessage(jid, message, {
|
|
125
|
-
messageId,
|
|
126
|
-
...opts,
|
|
127
|
-
})
|
|
50
|
+
await this.#socket.relayMessage(jid, message, { messageId, ...opts })
|
|
128
51
|
return messageId
|
|
129
52
|
}
|
|
130
53
|
|
|
131
|
-
/**
|
|
132
|
-
* Subscribe to a Baileys event. Returns an unsubscriber.
|
|
133
|
-
*
|
|
134
|
-
* @param {string} event
|
|
135
|
-
* @param {(...args: any[]) => void} handler
|
|
136
|
-
* @returns {() => void}
|
|
137
|
-
*/
|
|
138
54
|
on(event, handler) {
|
|
139
55
|
this.#socket.ev.on(event, handler)
|
|
140
56
|
return () => this.#socket.ev.off(event, handler)
|
|
141
57
|
}
|
|
142
58
|
|
|
143
|
-
/**
|
|
144
|
-
* Subscribe once.
|
|
145
|
-
*
|
|
146
|
-
* @param {string} event
|
|
147
|
-
* @param {(...args: any[]) => void} handler
|
|
148
|
-
* @returns {() => void}
|
|
149
|
-
*/
|
|
150
59
|
once(event, handler) {
|
|
151
|
-
const off = this.on(event, (...args) => {
|
|
152
|
-
off()
|
|
153
|
-
handler(...args)
|
|
154
|
-
})
|
|
60
|
+
const off = this.on(event, (...args) => { off(); handler(...args) })
|
|
155
61
|
return off
|
|
156
62
|
}
|
|
157
63
|
|
|
158
|
-
/**
|
|
159
|
-
* Unsubscribe.
|
|
160
|
-
*
|
|
161
|
-
* @param {string} event
|
|
162
|
-
* @param {(...args: any[]) => void} handler
|
|
163
|
-
*/
|
|
164
64
|
off(event, handler) {
|
|
165
65
|
this.#socket.ev.off(event, handler)
|
|
166
66
|
}
|
|
167
67
|
|
|
168
|
-
/**
|
|
169
|
-
* Raw Baileys socket — escape hatch for advanced users. Use sparingly;
|
|
170
|
-
* any code that touches `raw` bypasses Lumina's contract and may break
|
|
171
|
-
* on Baileys upgrades.
|
|
172
|
-
*
|
|
173
|
-
* @returns {WASocket}
|
|
174
|
-
*/
|
|
175
68
|
get raw() {
|
|
176
69
|
return this.#socket
|
|
177
70
|
}
|
package/src/errors.js
CHANGED
|
@@ -1,36 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file errors.js
|
|
3
|
-
* @module lumina/errors
|
|
4
|
-
*
|
|
5
|
-
* Error hierarchy for Lumina. Every Lumina-thrown error subclasses
|
|
6
|
-
* {@link LuminaError} and carries a stable `code`, the originating `module`,
|
|
7
|
-
* and (optionally) a `cause` field that follows the ES2022 Error.cause convention.
|
|
8
|
-
*
|
|
9
|
-
* Hierarchy:
|
|
10
|
-
* LuminaError
|
|
11
|
-
* ├── ValidationError (bad input — subclass of TypeError)
|
|
12
|
-
* ├── MediaError (fetch / resize / upload / ffmpeg failure)
|
|
13
|
-
* ├── ProtoError (assemble / generate / relay failure)
|
|
14
|
-
* ├── ConnectionError (Baileys socket missing or incompatible)
|
|
15
|
-
* └── ProtocolError (WAProto mismatch — emitted by ProtoUpdater)
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Base class for every error thrown by Lumina.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* if (err instanceof LuminaError) {
|
|
23
|
-
* console.error(err.code, err.module, err.message)
|
|
24
|
-
* }
|
|
25
|
-
*/
|
|
26
1
|
export class LuminaError extends Error {
|
|
27
|
-
/**
|
|
28
|
-
* @param {string} message Human-readable message.
|
|
29
|
-
* @param {object} [opts]
|
|
30
|
-
* @param {string} [opts.code='LUMINA_ERROR'] Stable machine code.
|
|
31
|
-
* @param {string} [opts.module='lumina'] Logical module that threw.
|
|
32
|
-
* @param {Error} [opts.cause] Original error (ES2022).
|
|
33
|
-
*/
|
|
34
2
|
constructor(message, opts = {}) {
|
|
35
3
|
super(message, { cause: opts.cause })
|
|
36
4
|
this.name = new.target.name
|
|
@@ -39,7 +7,6 @@ export class LuminaError extends Error {
|
|
|
39
7
|
}
|
|
40
8
|
}
|
|
41
9
|
|
|
42
|
-
/** Thrown when an argument fails validation. Subclass of TypeError for compat. */
|
|
43
10
|
export class ValidationError extends TypeError {
|
|
44
11
|
constructor(message, opts = {}) {
|
|
45
12
|
super(message, { cause: opts.cause })
|
|
@@ -49,7 +16,6 @@ export class ValidationError extends TypeError {
|
|
|
49
16
|
}
|
|
50
17
|
}
|
|
51
18
|
|
|
52
|
-
/** Thrown when a media operation (fetch/resize/upload/ffmpeg) fails. */
|
|
53
19
|
export class MediaError extends LuminaError {
|
|
54
20
|
constructor(message, opts = {}) {
|
|
55
21
|
super(message, opts)
|
|
@@ -58,7 +24,6 @@ export class MediaError extends LuminaError {
|
|
|
58
24
|
}
|
|
59
25
|
}
|
|
60
26
|
|
|
61
|
-
/** Thrown when a proto assembly / message generation / relay fails. */
|
|
62
27
|
export class ProtoError extends LuminaError {
|
|
63
28
|
constructor(message, opts = {}) {
|
|
64
29
|
super(message, opts)
|
|
@@ -67,7 +32,6 @@ export class ProtoError extends LuminaError {
|
|
|
67
32
|
}
|
|
68
33
|
}
|
|
69
34
|
|
|
70
|
-
/** Thrown when the Baileys socket is missing or its API is incompatible. */
|
|
71
35
|
export class ConnectionError extends LuminaError {
|
|
72
36
|
constructor(message, opts = {}) {
|
|
73
37
|
super(message, opts)
|
|
@@ -76,7 +40,6 @@ export class ConnectionError extends LuminaError {
|
|
|
76
40
|
}
|
|
77
41
|
}
|
|
78
42
|
|
|
79
|
-
/** Thrown by {@link ProtoUpdater} when WAProto validation fails. */
|
|
80
43
|
export class ProtocolError extends LuminaError {
|
|
81
44
|
constructor(message, opts = {}) {
|
|
82
45
|
super(message, opts)
|
package/src/index.d.ts
CHANGED
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* @file index.d.ts
|
|
3
|
-
* @module @kyyinfinite/lumina
|
|
4
|
-
*
|
|
5
|
-
* Manual TypeScript declaration for Lumina. Every builder, service, parser,
|
|
6
|
-
* and error is fully typed. Generated `.d.ts` files were rejected to keep
|
|
7
|
-
* the public surface auditable and to expose rich per-method overloads
|
|
8
|
-
* that auto-generation would lose.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
// ─── External dependencies ─────────────────────────────────────────────
|
|
1
|
+
|
|
12
2
|
|
|
13
3
|
declare module '@whiskeysockets/baileys' {
|
|
14
4
|
export interface WASocket {
|
|
@@ -30,8 +20,6 @@ declare module '@whiskeysockets/baileys' {
|
|
|
30
20
|
export function generateReactionMessage(jid: string, opts: any): any
|
|
31
21
|
}
|
|
32
22
|
|
|
33
|
-
// ─── Errors ────────────────────────────────────────────────────────────
|
|
34
|
-
|
|
35
23
|
export class LuminaError extends Error {
|
|
36
24
|
readonly code: string
|
|
37
25
|
readonly module: string
|
|
@@ -47,8 +35,6 @@ export class ProtoError extends LuminaError {}
|
|
|
47
35
|
export class ConnectionError extends LuminaError {}
|
|
48
36
|
export class ProtocolError extends LuminaError {}
|
|
49
37
|
|
|
50
|
-
// ─── Logger ────────────────────────────────────────────────────────────
|
|
51
|
-
|
|
52
38
|
export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug'
|
|
53
39
|
|
|
54
40
|
export interface Logger {
|
|
@@ -66,8 +52,6 @@ export function createLogger(opts?: {
|
|
|
66
52
|
transport?: (level: string, scope: string, args: any[]) => void
|
|
67
53
|
}): Logger
|
|
68
54
|
|
|
69
|
-
// ─── Enums & catalog ───────────────────────────────────────────────────
|
|
70
|
-
|
|
71
55
|
export const MessageType: Readonly<{
|
|
72
56
|
RICH_RESPONSE: 1
|
|
73
57
|
TEXT: 2
|
|
@@ -129,8 +113,6 @@ export const TYPENAME: Readonly<{
|
|
|
129
113
|
layout(kind: string): string
|
|
130
114
|
}>
|
|
131
115
|
|
|
132
|
-
// ─── Parsers ───────────────────────────────────────────────────────────
|
|
133
|
-
|
|
134
116
|
export interface ExtractOptions {
|
|
135
117
|
extract?: boolean
|
|
136
118
|
hyperlink?: boolean
|
|
@@ -165,8 +147,6 @@ export function toTableMetadata(
|
|
|
165
147
|
opts?: { title?: string; hyperlink?: boolean; citation?: boolean; latex?: boolean },
|
|
166
148
|
): TableMetadata
|
|
167
149
|
|
|
168
|
-
// ─── Connection ────────────────────────────────────────────────────────
|
|
169
|
-
|
|
170
150
|
export interface ConnectionOptions {
|
|
171
151
|
uploadJid?: string
|
|
172
152
|
logger?: Logger
|
|
@@ -188,7 +168,6 @@ export class Connection {
|
|
|
188
168
|
get raw(): import('@whiskeysockets/baileys').WASocket
|
|
189
169
|
}
|
|
190
170
|
|
|
191
|
-
// ─── Services ──────────────────────────────────────────────────────────
|
|
192
171
|
|
|
193
172
|
export class MediaService {
|
|
194
173
|
constructor(conn: Connection, opts?: { cache?: boolean; cacheMax?: number; logger?: Logger; uploadJid?: string })
|
|
@@ -230,8 +209,6 @@ export class MessageService {
|
|
|
230
209
|
edit(jid: string, key: any, newText: string, opts?: any): Promise<any>
|
|
231
210
|
}
|
|
232
211
|
|
|
233
|
-
// ─── Builders ──────────────────────────────────────────────────────────
|
|
234
|
-
|
|
235
212
|
export interface ContentFields {
|
|
236
213
|
title(t: string): this
|
|
237
214
|
subtitle(t: string): this
|
|
@@ -371,8 +348,6 @@ export class AIRichBuilder implements ContentFields {
|
|
|
371
348
|
send(jid: string, opts?: object): Promise<string>
|
|
372
349
|
}
|
|
373
350
|
|
|
374
|
-
// ─── ProtoUpdater ──────────────────────────────────────────────────────
|
|
375
|
-
|
|
376
351
|
export class ProtoUpdater {
|
|
377
352
|
constructor(opts?: { protoPath?: string; backupDir?: string; logger?: Logger })
|
|
378
353
|
backup(): Promise<{ id: string; timestamp: number; path: string; hash: string }>
|
|
@@ -395,7 +370,6 @@ export function assembleRichResponse(opts?: any): Promise<object>
|
|
|
395
370
|
export function createInteractiveNodes(opts?: any): any[]
|
|
396
371
|
export function createBareInteractiveNodes(opts?: any): any[]
|
|
397
372
|
|
|
398
|
-
// ─── Bot ───────────────────────────────────────────────────────────────
|
|
399
373
|
|
|
400
374
|
export interface BotOptions {
|
|
401
375
|
uploadJid?: string
|
|
@@ -451,7 +425,6 @@ export class Bot {
|
|
|
451
425
|
get raw(): import('@whiskeysockets/baileys').WASocket
|
|
452
426
|
}
|
|
453
427
|
|
|
454
|
-
// ─── Version ───────────────────────────────────────────────────────────
|
|
455
428
|
|
|
456
429
|
export const VERSION: string
|
|
457
430
|
|