@kyyinfinite/baileys 2.0.0 → 2.1.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.
@@ -0,0 +1,46 @@
1
+ import { downloadMediaMessage } from '../../Utils/messages.js'
2
+
3
+ export class KyyMessage {
4
+ constructor(sock, message) {
5
+ if (!sock) throw new Error('Socket is required')
6
+ if (!message) throw new TypeError('A WhatsApp message is required')
7
+ this.sock = sock
8
+ this.message = message
9
+ this.key = message.key || message
10
+ }
11
+
12
+ get id() { return this.key?.id }
13
+ get jid() { return this.key?.remoteJid }
14
+ get sender() { return this.key?.participant || this.key?.remoteJid }
15
+ get fromMe() { return Boolean(this.key?.fromMe) }
16
+
17
+ reply(content, options = {}) {
18
+ const message = typeof content === 'string' ? { text: content } : { ...(content || {}) }
19
+ const sendOptions = { ...(options || {}), quoted: this.message }
20
+ return this.sock.sendMessage(this.jid, message, sendOptions)
21
+ }
22
+
23
+ react(text = '') {
24
+ return this.sock.sendMessage(this.jid, { react: { text: String(text), key: this.key } })
25
+ }
26
+
27
+ edit(content, options = {}) {
28
+ const message = typeof content === 'string' ? { text: content } : { ...(content || {}) }
29
+ message.edit = this.key
30
+ return this.sock.sendMessage(this.jid, message, options)
31
+ }
32
+
33
+ delete() {
34
+ return this.sock.sendMessage(this.jid, { delete: this.key })
35
+ }
36
+
37
+ forward(jid = this.jid, force = false) {
38
+ return this.sock.sendMessage(jid, { forward: this.message, force })
39
+ }
40
+
41
+ download(type = 'buffer', options = {}, ctx) {
42
+ return downloadMediaMessage(this.message, type, options, ctx)
43
+ }
44
+
45
+ raw() { return this.message }
46
+ }
@@ -1,8 +1,12 @@
1
+ import { applyAutoMentions, resolveMedia } from './messageUtils.js'
2
+
1
3
  export class MediaBuilder {
2
4
  constructor(sock, type, media) {
3
5
  this.sock = sock
4
6
  this.type = type
5
- this.content = { [type]: media }
7
+ this.content = { [type]: resolveMedia(media) }
8
+ this._autoMentions = true
9
+ this._sendOptions = {}
6
10
  }
7
11
 
8
12
  caption(value) { this.content.caption = String(value ?? ''); return this }
@@ -10,6 +14,8 @@ export class MediaBuilder {
10
14
  mimetype(value) { this.content.mimetype = value; return this }
11
15
  context(value) { this.content.contextInfo = value || {}; return this }
12
16
  mentions(value) { this.content.mentions = Array.isArray(value) ? [...value] : []; return this }
17
+ autoMentions(value = true) { this._autoMentions = Boolean(value); return this }
18
+ quoted(message) { this._sendOptions.quoted = message; return this }
13
19
  payload(value) { Object.assign(this.content, value || {}); return this }
14
20
  viewOnce(value = true) { this.content.viewOnce = Boolean(value); return this }
15
21
  ptt(value = true) { this.content.ptt = Boolean(value); return this }
@@ -26,10 +32,10 @@ export class MediaBuilder {
26
32
  thumbnail(value) { this.content.jpegThumbnail = value; return this }
27
33
 
28
34
  build() {
29
- return { ...this.content }
35
+ return applyAutoMentions({ ...this.content }, this._autoMentions)
30
36
  }
31
37
 
32
38
  send(jid, options = {}) {
33
- return this.sock.sendMessage(jid, this.build(), options)
39
+ return this.sock.sendMessage(jid, this.build(), { ...this._sendOptions, ...(options || {}) })
34
40
  }
35
41
  }
@@ -1,8 +1,12 @@
1
+ import { applyAutoMentions, resolveMediaContent } from './messageUtils.js'
2
+
1
3
  export class MessageBuilder {
2
4
  constructor(sock, content = {}) {
3
5
  if (!sock) throw new Error('Socket is required')
4
6
  this.sock = sock
5
7
  this.content = { ...content }
8
+ this._autoMentions = true
9
+ this._sendOptions = {}
6
10
  }
7
11
 
8
12
  payload(value) {
@@ -21,6 +25,16 @@ export class MessageBuilder {
21
25
  return this
22
26
  }
23
27
 
28
+ autoMentions(value = true) {
29
+ this._autoMentions = Boolean(value)
30
+ return this
31
+ }
32
+
33
+ quoted(message) {
34
+ this._sendOptions.quoted = message
35
+ return this
36
+ }
37
+
24
38
  viewOnce(value = true) {
25
39
  this.content.viewOnce = Boolean(value)
26
40
  return this
@@ -32,10 +46,10 @@ export class MessageBuilder {
32
46
  }
33
47
 
34
48
  build() {
35
- return { ...this.content }
49
+ return applyAutoMentions(resolveMediaContent({ ...this.content }), this._autoMentions)
36
50
  }
37
51
 
38
52
  send(jid, options = {}) {
39
- return this.sock.sendMessage(jid, this.build(), options)
53
+ return this.sock.sendMessage(jid, this.build(), { ...this._sendOptions, ...(options || {}) })
40
54
  }
41
55
  }
@@ -6,6 +6,11 @@ import { createCarouselBuilder } from './CarouselBuilder.js'
6
6
  import { createAIBuilder } from './AIBuilder.js'
7
7
  import { createFoadBuilder, createFoad2Builder } from './FoadBuilder.js'
8
8
  import { Toolkit, Button, ButtonV2, Carousel, AIRich, Foad, Foad2 } from '../wrapper.js'
9
+ import { KyyMessage } from './KyyMessage.js'
10
+ import { UniversalMediaBuilder } from './UniversalMediaBuilder.js'
11
+ import { parseMessage } from './parseMessage.js'
12
+ import { applyAutoMentions, extractMentions, resolveMedia, resolveMediaContent, quotedOptions } from './messageUtils.js'
13
+ import { parseJid, normalizeJid, jidUser, jidServer, jidDevice, isGroupJid, isPrivateJid, isBroadcastJid, isStatusJid, isNewsletterJid, isLidJid, makeJid } from './jid.js'
9
14
 
10
15
  export class SimpleClient {
11
16
  constructor(sock) {
@@ -18,6 +23,38 @@ export class SimpleClient {
18
23
  }
19
24
 
20
25
  text(text = '') { return new TextBuilder(this.sock, text) }
26
+ media(media) { return new UniversalMediaBuilder(this.sock, media) }
27
+ wrapMessage(message) { return new KyyMessage(this.sock, message) }
28
+ parseMessage(message, options = {}) { return parseMessage(message, options) }
29
+ send(jid, content, options = {}) {
30
+ const { autoMentions = true, ...sendOptions } = options || {}
31
+ const message = typeof content === 'string' ? { text: content } : resolveMediaContent({ ...(content || {}) })
32
+ return this.sock.sendMessage(jid, applyAutoMentions(message, autoMentions !== false), sendOptions)
33
+ }
34
+ quoted(message, content, options = {}) {
35
+ return this.send(this.wrapMessage(message).jid, content, quotedOptions(message, options))
36
+ }
37
+ mentions(text) { return extractMentions(text) }
38
+ resolveMedia(media) { return resolveMedia(media) }
39
+ resolveMediaContent(content) { return resolveMediaContent(content) }
40
+ jid(value) { return normalizeJid(value) }
41
+ parseJid(value) { return parseJid(value) }
42
+ jidUser(value) { return jidUser(value) }
43
+ jidServer(value) { return jidServer(value) }
44
+ jidDevice(value) { return jidDevice(value) }
45
+ isGroup(value) { return isGroupJid(value) }
46
+ isPrivate(value) { return isPrivateJid(value) }
47
+ isBroadcast(value) { return isBroadcastJid(value) }
48
+ isStatus(value) { return isStatusJid(value) }
49
+ isNewsletter(value) { return isNewsletterJid(value) }
50
+ isLid(value) { return isLidJid(value) }
51
+ makeJid(user, server = 's.whatsapp.net', device = null) { return makeJid(user, server, device) }
52
+ reply(message, content, options = {}) { return this.wrapMessage(message).reply(content, options) }
53
+ reactTo(message, text = '') { return this.wrapMessage(message).react(text) }
54
+ editMessage(message, content, options = {}) { return this.wrapMessage(message).edit(content, options) }
55
+ deleteMessage(message) { return this.wrapMessage(message).delete() }
56
+ forwardMessage(message, jid, force = false) { return this.wrapMessage(message).forward(jid, force) }
57
+ downloadMessage(message, type = 'buffer', options = {}, ctx) { return this.wrapMessage(message).download(type, options, ctx) }
21
58
  image(media) { return new MediaBuilder(this.sock, 'image', media) }
22
59
  video(media) { return new MediaBuilder(this.sock, 'video', media) }
23
60
  audio(media) { return new MediaBuilder(this.sock, 'audio', media) }
@@ -1,22 +1,28 @@
1
+ import { applyAutoMentions } from './messageUtils.js'
2
+
1
3
  export class TextBuilder {
2
4
  constructor(sock, text = '') {
3
5
  this.sock = sock
4
6
  this.content = { text: String(text ?? '') }
7
+ this._autoMentions = true
8
+ this._sendOptions = {}
5
9
  }
6
10
 
7
11
  text(value) { this.content.text = String(value ?? ''); return this }
8
12
  footer(value) { this.content.footer = String(value ?? ''); return this }
9
13
  context(value) { this.content.contextInfo = value || {}; return this }
10
14
  mentions(value) { this.content.mentions = Array.isArray(value) ? [...value] : []; return this }
15
+ autoMentions(value = true) { this._autoMentions = Boolean(value); return this }
16
+ quoted(message) { this._sendOptions.quoted = message; return this }
11
17
  viewOnce(value = true) { this.content.viewOnce = Boolean(value); return this }
12
18
  edit(key) { this.content.edit = key; return this }
13
19
  payload(value) { Object.assign(this.content, value || {}); return this }
14
20
 
15
21
  build() {
16
- return { ...this.content }
22
+ return applyAutoMentions({ ...this.content }, this._autoMentions)
17
23
  }
18
24
 
19
25
  send(jid, options = {}) {
20
- return this.sock.sendMessage(jid, { ...this.content }, options)
26
+ return this.sock.sendMessage(jid, this.build(), { ...this._sendOptions, ...(options || {}) })
21
27
  }
22
28
  }
@@ -0,0 +1,21 @@
1
+ import { MediaBuilder } from './MediaBuilder.js'
2
+
3
+ export class UniversalMediaBuilder extends MediaBuilder {
4
+ constructor(sock, media) {
5
+ super(sock, 'image', media)
6
+ }
7
+
8
+ _setType(type) {
9
+ const current = this.content[this.type]
10
+ delete this.content[this.type]
11
+ this.type = type
12
+ this.content[type] = current
13
+ return this
14
+ }
15
+
16
+ asImage() { return this._setType('image') }
17
+ asVideo() { return this._setType('video') }
18
+ asAudio() { return this._setType('audio') }
19
+ asDocument() { return this._setType('document') }
20
+ asSticker() { return this._setType('sticker') }
21
+ }
@@ -4,6 +4,32 @@ export declare class SimpleClient {
4
4
  readonly wrapper: Record<string, any>
5
5
  constructor(sock: any)
6
6
  text(text?: string): TextBuilder
7
+ media(media: any): UniversalMediaBuilder
8
+ wrapMessage(message: any): KyyMessage
9
+ parseMessage(message: any, options?: { prefix?: string, commandMode?: string }): any
10
+ send(jid: string, content: string | Record<string, any>, options?: Record<string, any> & { autoMentions?: boolean }): Promise<any>
11
+ quoted(message: any, content: string | Record<string, any>, options?: Record<string, any> & { autoMentions?: boolean }): Promise<any>
12
+ mentions(text: string): string[]
13
+ resolveMedia(media: any): any
14
+ resolveMediaContent(content: Record<string, any>): Record<string, any>
15
+ jid(value: string): string
16
+ parseJid(value: string): any
17
+ jidUser(value: string): string | null
18
+ jidServer(value: string): string | null
19
+ jidDevice(value: string): string | null
20
+ isGroup(value: string): boolean
21
+ isPrivate(value: string): boolean
22
+ isBroadcast(value: string): boolean
23
+ isStatus(value: string): boolean
24
+ isNewsletter(value: string): boolean
25
+ isLid(value: string): boolean
26
+ makeJid(user: string | number, server?: string, device?: string | number | null): string
27
+ reply(message: any, content: string | Record<string, any>, options?: Record<string, any>): Promise<any>
28
+ reactTo(message: any, text?: string): Promise<any>
29
+ editMessage(message: any, content: string | Record<string, any>, options?: Record<string, any>): Promise<any>
30
+ deleteMessage(message: any): Promise<any>
31
+ forwardMessage(message: any, jid?: string, force?: boolean): Promise<any>
32
+ downloadMessage(message: any, type?: 'buffer' | 'stream', options?: Record<string, any>, ctx?: any): Promise<any>
7
33
  image(media: any): MediaBuilder
8
34
  video(media: any): MediaBuilder
9
35
  audio(media: any): MediaBuilder
@@ -44,12 +70,11 @@ export declare class TextBuilder {
44
70
  footer(value: string): this
45
71
  context(value: Record<string, any>): this
46
72
  mentions(value: string[]): this
73
+ autoMentions(value?: boolean): this
74
+ quoted(message: any): this
47
75
  viewOnce(value?: boolean): this
48
76
  edit(key: any): this
49
77
  payload(value: Record<string, any>): this
50
- mentions(value: string[]): this
51
- viewOnce(value?: boolean): this
52
- edit(key: any): this
53
78
  build(): Record<string, any>
54
79
  send(jid: string, options?: Record<string, any>): Promise<any>
55
80
  }
@@ -62,6 +87,8 @@ export declare class MediaBuilder {
62
87
  context(value: Record<string, any>): this
63
88
  payload(value: Record<string, any>): this
64
89
  mentions(value: string[]): this
90
+ autoMentions(value?: boolean): this
91
+ quoted(message: any): this
65
92
  viewOnce(value?: boolean): this
66
93
  ptt(value?: boolean): this
67
94
  voice(value?: boolean): this
@@ -125,6 +152,8 @@ export declare class MessageBuilder {
125
152
  payload(value: Record<string, any>): this
126
153
  context(value: Record<string, any>): this
127
154
  mentions(value: string[]): this
155
+ autoMentions(value?: boolean): this
156
+ quoted(message: any): this
128
157
  viewOnce(value?: boolean): this
129
158
  edit(key: any): this
130
159
  build(): Record<string, any>
@@ -139,3 +168,65 @@ export declare function createButtonV2Builder(sock: any, ...args: any[]): any
139
168
  export declare function createCarouselBuilder(sock: any, ...args: any[]): CarouselBuilder
140
169
  export declare function createFoadBuilder(sock: any, ...args: any[]): any
141
170
  export declare function createFoad2Builder(sock: any, ...args: any[]): any
171
+
172
+ export declare class KyyMessage {
173
+ readonly sock: any
174
+ readonly message: any
175
+ readonly key: any
176
+ readonly id: any
177
+ readonly jid: any
178
+ readonly sender: any
179
+ readonly fromMe: boolean
180
+ constructor(sock: any, message: any)
181
+ reply(content: string | Record<string, any>, options?: Record<string, any>): Promise<any>
182
+ react(text?: string): Promise<any>
183
+ edit(content: string | Record<string, any>, options?: Record<string, any>): Promise<any>
184
+ delete(): Promise<any>
185
+ forward(jid?: string, force?: boolean): Promise<any>
186
+ download(type?: 'buffer' | 'stream', options?: Record<string, any>, ctx?: any): Promise<any>
187
+ raw(): any
188
+ }
189
+
190
+ export declare class UniversalMediaBuilder extends MediaBuilder {
191
+ constructor(sock: any, media: any)
192
+ asImage(): this
193
+ asVideo(): this
194
+ asAudio(): this
195
+ asDocument(): this
196
+ asSticker(): this
197
+ }
198
+
199
+ export declare function parseMessage(message: any, options?: { prefix?: string, commandMode?: string }): {
200
+ message: any
201
+ content: any
202
+ messageType: any
203
+ text: string
204
+ command: string
205
+ args: string[]
206
+ jid: any
207
+ sender: any
208
+ isGroup: boolean
209
+ isReply: boolean
210
+ quoted: any
211
+ key: any
212
+ }
213
+
214
+ export declare function parseJid(jid: string): { user: string, device: string | null, server: string, jid: string } | null
215
+ export declare function normalizeJid(jid: string): string
216
+ export declare function jidUser(jid: string): string | null
217
+ export declare function jidServer(jid: string): string | null
218
+ export declare function jidDevice(jid: string): string | null
219
+ export declare function isGroupJid(jid: string): boolean
220
+ export declare function isPrivateJid(jid: string): boolean
221
+ export declare function isBroadcastJid(jid: string): boolean
222
+ export declare function isStatusJid(jid: string): boolean
223
+ export declare function isNewsletterJid(jid: string): boolean
224
+ export declare function isLidJid(jid: string): boolean
225
+ export declare function makeJid(user: string | number, server?: string, device?: string | number | null): string
226
+
227
+ export declare function extractMentions(text: string): string[]
228
+ export declare function getMessageText(content: Record<string, any>): string
229
+ export declare function applyAutoMentions(content: Record<string, any>, enabled?: boolean): Record<string, any>
230
+ export declare function resolveMedia(media: any): any
231
+ export declare function resolveMediaContent(content: Record<string, any>): Record<string, any>
232
+ export declare function quotedOptions(message: any, options?: Record<string, any>): Record<string, any>
@@ -15,7 +15,7 @@ export function createKyyinfinite(sock) {
15
15
 
16
16
  export function attachKyyinfinite(sock) {
17
17
  const api = new SimpleClient(sock)
18
- const names = ['text', 'image', 'video', 'audio', 'voice', 'document', 'sticker', 'ptv', 'gif', 'message', 'poll', 'event', 'album', 'contacts', 'location', 'react', 'groupInvite', 'product', 'requestPhoneNumber', 'sharePhoneNumber', 'pin', 'forward', 'delete', 'disappearing', 'limitSharing', 'button', 'buttonV2', 'carousel', 'ai', 'foad', 'foad2']
18
+ const names = ['text', 'media', 'wrapMessage', 'parseMessage', 'jid', 'parseJid', 'jidUser', 'jidServer', 'jidDevice', 'isGroup', 'isPrivate', 'isBroadcast', 'isStatus', 'isNewsletter', 'isLid', 'makeJid', 'reply', 'reactTo', 'editMessage', 'deleteMessage', 'forwardMessage', 'downloadMessage', 'image', 'video', 'audio', 'voice', 'document', 'sticker', 'ptv', 'gif', 'message', 'poll', 'event', 'album', 'contacts', 'location', 'react', 'groupInvite', 'product', 'requestPhoneNumber', 'sharePhoneNumber', 'pin', 'forward', 'delete', 'disappearing', 'limitSharing', 'button', 'buttonV2', 'carousel', 'ai', 'foad', 'foad2']
19
19
 
20
20
  for (const name of names) {
21
21
  if (name in sock) continue
@@ -29,3 +29,10 @@ export function attachKyyinfinite(sock) {
29
29
 
30
30
  return sock
31
31
  }
32
+
33
+ export { KyyMessage } from './KyyMessage.js'
34
+ export { UniversalMediaBuilder } from './UniversalMediaBuilder.js'
35
+ export { parseMessage } from './parseMessage.js'
36
+ export * from './jid.js'
37
+
38
+ export * from './messageUtils.js'
@@ -0,0 +1,55 @@
1
+ const JID_RE = /^([^:@\s]+)(?::([^@\s]+))?@([^@\s]+)$/
2
+
3
+ export function parseJid(jid) {
4
+ if (typeof jid !== 'string' || !jid) return null
5
+ const match = jid.match(JID_RE)
6
+ if (!match) return null
7
+ return { user: match[1], device: match[2] || null, server: match[3], jid }
8
+ }
9
+
10
+ export function normalizeJid(jid) {
11
+ if (typeof jid !== 'string') return jid
12
+ return jid.trim()
13
+ }
14
+
15
+ export function jidUser(jid) {
16
+ return parseJid(jid)?.user || null
17
+ }
18
+
19
+ export function jidServer(jid) {
20
+ return parseJid(jid)?.server || null
21
+ }
22
+
23
+ export function jidDevice(jid) {
24
+ return parseJid(jid)?.device || null
25
+ }
26
+
27
+ export function isGroupJid(jid) {
28
+ return jidServer(jid) === 'g.us'
29
+ }
30
+
31
+ export function isPrivateJid(jid) {
32
+ const server = jidServer(jid)
33
+ return server === 's.whatsapp.net' || server === 'lid'
34
+ }
35
+
36
+ export function isBroadcastJid(jid) {
37
+ return jidServer(jid) === 'broadcast'
38
+ }
39
+
40
+ export function isStatusJid(jid) {
41
+ return jid === 'status@broadcast'
42
+ }
43
+
44
+ export function isNewsletterJid(jid) {
45
+ return jidServer(jid) === 'newsletter'
46
+ }
47
+
48
+ export function isLidJid(jid) {
49
+ return jidServer(jid) === 'lid'
50
+ }
51
+
52
+ export function makeJid(user, server = 's.whatsapp.net', device = null) {
53
+ if (user == null || user === '') throw new TypeError('JID user is required')
54
+ return `${String(user)}${device != null ? `:${device}` : ''}@${server}`
55
+ }
@@ -0,0 +1,49 @@
1
+ const MENTION_RE = /(^|\s)@(\d{5,16})(?=\s|$|[.,!?])/g
2
+
3
+ export function extractMentions(text) {
4
+ if (typeof text !== 'string' || !text) return []
5
+ const result = []
6
+ const seen = new Set()
7
+ for (const match of text.matchAll(MENTION_RE)) {
8
+ const jid = `${match[2]}@s.whatsapp.net`
9
+ if (!seen.has(jid)) {
10
+ seen.add(jid)
11
+ result.push(jid)
12
+ }
13
+ }
14
+ return result
15
+ }
16
+
17
+ export function getMessageText(content) {
18
+ if (!content || typeof content !== 'object') return ''
19
+ return [content.text, content.caption, content.title, content.description]
20
+ .filter(value => typeof value === 'string')
21
+ .join('\n')
22
+ }
23
+
24
+ export function applyAutoMentions(content, enabled = true) {
25
+ if (!enabled || !content || typeof content !== 'object') return content
26
+ if (Array.isArray(content.mentions)) return content
27
+ const mentions = extractMentions(getMessageText(content))
28
+ if (!mentions.length) return content
29
+ return { ...content, mentions }
30
+ }
31
+
32
+ export function resolveMedia(media) {
33
+ if (typeof media !== 'string') return media
34
+ return { url: media }
35
+ }
36
+
37
+ export function resolveMediaContent(content) {
38
+ if (!content || typeof content !== 'object') return content
39
+ const mediaKeys = ['image', 'video', 'audio', 'document', 'sticker']
40
+ const output = { ...content }
41
+ for (const key of mediaKeys) {
42
+ if (typeof output[key] === 'string') output[key] = resolveMedia(output[key])
43
+ }
44
+ return output
45
+ }
46
+
47
+ export function quotedOptions(message, options = {}) {
48
+ return { ...(options || {}), quoted: message }
49
+ }
@@ -0,0 +1,55 @@
1
+ import { getContentType } from '../../Utils/messages.js'
2
+
3
+ function unwrap(message) {
4
+ let content = message?.message || message || {}
5
+ const wrappers = ['ephemeralMessage', 'viewOnceMessage', 'viewOnceMessageV2', 'viewOnceMessageV2Extension', 'documentWithCaptionMessage']
6
+ for (let i = 0; i < 6; i++) {
7
+ const type = getContentType(content)
8
+ if (!type || !wrappers.includes(type)) break
9
+ content = content[type]?.message || content[type] || content
10
+ }
11
+ return content
12
+ }
13
+
14
+ export function parseMessage(message, options = {}) {
15
+ const content = unwrap(message)
16
+ const type = getContentType(content)
17
+ const node = type ? content[type] : undefined
18
+ let text = ''
19
+
20
+ if (typeof node === 'string') text = node
21
+ else if (node?.text) text = node.text
22
+ else if (node?.caption) text = node.caption
23
+ else if (node?.selectedDisplayText) text = node.selectedDisplayText
24
+ else if (node?.title) text = node.title
25
+ else if (node?.contentText) text = node.contentText
26
+
27
+ const prefix = options.prefix ?? ''
28
+ const commandMode = options.commandMode ?? 'prefix'
29
+ let command = ''
30
+ let args = []
31
+
32
+ const normalized = String(text || '').trim()
33
+ const hasPrefix = !prefix || normalized.startsWith(prefix)
34
+ if (normalized && hasPrefix && (commandMode === 'prefix' || !prefix)) {
35
+ const body = prefix ? normalized.slice(prefix.length).trim() : normalized
36
+ const parts = body ? body.split(/\s+/) : []
37
+ command = parts.shift() || ''
38
+ args = parts
39
+ }
40
+
41
+ return {
42
+ message,
43
+ content,
44
+ messageType: type,
45
+ text: normalized,
46
+ command,
47
+ args,
48
+ jid: message?.key?.remoteJid,
49
+ sender: message?.key?.participant || message?.key?.remoteJid,
50
+ isGroup: Boolean(message?.key?.remoteJid?.endsWith('@g.us')),
51
+ isReply: Boolean(node?.contextInfo?.quotedMessage),
52
+ quoted: node?.contextInfo?.quotedMessage,
53
+ key: message?.key
54
+ }
55
+ }
package/package.json CHANGED
@@ -1,24 +1,30 @@
1
1
  {
2
2
  "name": "@kyyinfinite/baileys",
3
3
  "type": "module",
4
- "version": "2.0.0",
5
- "description": "A WebSockets library for interacting with WhatsApp Web",
4
+ "version": "2.1.0",
5
+ "description": "WhatsApp Web library for Node.js with the Kyyinfinite Simple API",
6
6
  "keywords": [
7
7
  "whatsapp",
8
8
  "automation"
9
9
  ],
10
- "homepage": "https://github.com/WhiskeySockets/Baileys/",
10
+ "homepage": "https://github.com/kyyinfinite/baileys",
11
11
  "repository": {
12
- "url": "git@github.com:WhiskeySockets/Baileys.git"
12
+ "type": "git",
13
+ "url": "git+https://github.com/kyyinfinite/baileys.git"
13
14
  },
14
15
  "license": "MIT",
15
- "author": "Rajeh Taher",
16
+ "author": "kyyinfinite",
16
17
  "main": "lib/index.js",
17
18
  "types": "lib/index.d.ts",
18
19
  "files": [
19
20
  "lib/**/*",
20
21
  "WAProto/**/*",
21
- "engine-requirements.js"
22
+ "engine-requirements.js",
23
+ "LICENSE",
24
+ "THIRD_PARTY_NOTICES.md",
25
+ "CHANGELOG.md",
26
+ "test/**/*",
27
+ "TESTING.md"
22
28
  ],
23
29
  "scripts": {
24
30
  "build:all": "npm run build && npm run build:docs",
@@ -34,9 +40,11 @@
34
40
  "lint:fix": "npm run format && npm run lint -- --fix",
35
41
  "preinstall": "node ./engine-requirements.js",
36
42
  "release": "release-it",
37
- "test": "node --experimental-vm-modules ./node_modules/.bin/jest --testMatch '**/*.test.ts'",
43
+ "test": "node test/simple-api.test.js",
38
44
  "test:e2e": "NODE_TLS_REJECT_UNAUTHORIZED=0 node --experimental-vm-modules ./node_modules/.bin/jest --runInBand --forceExit --testMatch '**/*.test-e2e.ts'",
39
- "update:version": "tsx ./scripts/update-version.ts"
45
+ "update:version": "tsx ./scripts/update-version.ts",
46
+ "test:core": "node test/core.test.js",
47
+ "test:all": "npm run test:core && npm test"
40
48
  },
41
49
  "dependencies": {
42
50
  "@cacheable/node-cache": "^1.4.0",
@@ -135,5 +143,8 @@
135
143
  "packageManager": "yarn@4.9.2",
136
144
  "engines": {
137
145
  "node": ">=20.0.0"
146
+ },
147
+ "bugs": {
148
+ "url": "https://github.com/kyyinfinite/baileys/issues"
138
149
  }
139
150
  }
@@ -0,0 +1,38 @@
1
+ import assert from 'node:assert/strict'
2
+ import { parseJid, normalizeJid, jidUser, jidServer, jidDevice, isGroupJid, isPrivateJid, isBroadcastJid, isStatusJid, isNewsletterJid, isLidJid, makeJid } from '../lib/Kyyinfinite/Simple/jid.js'
3
+ import { extractMentions, getMessageText, applyAutoMentions, resolveMedia, resolveMediaContent, quotedOptions } from '../lib/Kyyinfinite/Simple/messageUtils.js'
4
+
5
+ const tests = [
6
+ ['parseJid', () => assert.deepEqual(parseJid('12345:7@s.whatsapp.net'), { user: '12345', device: '7', server: 's.whatsapp.net', jid: '12345:7@s.whatsapp.net' })],
7
+ ['parseJid invalid', () => assert.equal(parseJid('invalid'), null)],
8
+ ['normalizeJid', () => assert.equal(normalizeJid(' 123@s.whatsapp.net '), '123@s.whatsapp.net')],
9
+ ['jid accessors', () => {
10
+ assert.equal(jidUser('123:4@s.whatsapp.net'), '123')
11
+ assert.equal(jidDevice('123:4@s.whatsapp.net'), '4')
12
+ assert.equal(jidServer('123:4@s.whatsapp.net'), 's.whatsapp.net')
13
+ }],
14
+ ['JID classifiers', () => {
15
+ assert.equal(isGroupJid('123@g.us'), true)
16
+ assert.equal(isPrivateJid('123@s.whatsapp.net'), true)
17
+ assert.equal(isBroadcastJid('123@broadcast'), true)
18
+ assert.equal(isStatusJid('status@broadcast'), true)
19
+ assert.equal(isNewsletterJid('123@newsletter'), true)
20
+ assert.equal(isLidJid('123@lid'), true)
21
+ }],
22
+ ['makeJid', () => assert.equal(makeJid(123, 's.whatsapp.net', 7), '123:7@s.whatsapp.net')],
23
+ ['mention extraction', () => assert.deepEqual(extractMentions('@628123456789 hi @628123456789!'), ['628123456789@s.whatsapp.net'])],
24
+ ['message text extraction', () => assert.equal(getMessageText({ text: 'a', caption: 'b', title: 'c' }), 'a\nb\nc')],
25
+ ['auto mentions enabled', () => assert.deepEqual(applyAutoMentions({ text: 'Hi @628123456789' }).mentions, ['628123456789@s.whatsapp.net'])],
26
+ ['auto mentions disabled', () => assert.equal(applyAutoMentions({ text: 'Hi @628123456789' }, false).mentions, undefined)],
27
+ ['explicit mentions preserved', () => assert.deepEqual(applyAutoMentions({ text: '@628123456789', mentions: ['custom@s.whatsapp.net'] }).mentions, ['custom@s.whatsapp.net'])],
28
+ ['media URL resolver', () => assert.deepEqual(resolveMedia('https://example.com/a.jpg'), { url: 'https://example.com/a.jpg' })],
29
+ ['media content resolver', () => assert.deepEqual(resolveMediaContent({ image: 'a.jpg', video: 'b.mp4', text: 'x' }), { image: { url: 'a.jpg' }, video: { url: 'b.mp4' }, text: 'x' })],
30
+ ['quoted options', () => assert.deepEqual(quotedOptions({ id: 1 }, { ephemeralExpiration: 3600 }), { quoted: { id: 1 }, ephemeralExpiration: 3600 })]
31
+ ]
32
+
33
+ for (const [name, fn] of tests) {
34
+ fn()
35
+ console.log(`PASS ${name}`)
36
+ }
37
+
38
+ console.log(`\nCore 2.1.0 API tests: ${tests.length}/${tests.length} PASS`)