@vanzxy/baileys 1.6.2 → 1.6.4

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.
Files changed (51) hide show
  1. package/NOTICE.md +50 -0
  2. package/lib/Utils/A2UI.js +217 -0
  3. package/lib/Utils/MessageBuilder.js +332 -46
  4. package/lib/Utils/MessageBuilder_d.ts +45 -0
  5. package/lib/Utils/PersistentStore.js +592 -0
  6. package/lib/Utils/PersistentStore_d.ts +60 -0
  7. package/lib/Utils/anti-delete.d.ts +68 -0
  8. package/lib/Utils/anti-delete.js +185 -0
  9. package/lib/Utils/auto-reply.d.ts +47 -0
  10. package/lib/Utils/auto-reply.js +155 -0
  11. package/lib/Utils/button-helper-utils.js +314 -0
  12. package/lib/Utils/button-sender.js +817 -0
  13. package/lib/Utils/chat-history-helpers.d.ts +21 -0
  14. package/lib/Utils/chat-history-helpers.js +71 -0
  15. package/lib/Utils/index.d.ts +11 -0
  16. package/lib/Utils/index.js +16 -0
  17. package/lib/Utils/media-messages.d.ts +18 -0
  18. package/lib/Utils/media-messages.js +71 -0
  19. package/lib/Utils/media-set.d.ts +13 -0
  20. package/lib/Utils/media-set.js +165 -0
  21. package/lib/Utils/message-kind.js +139 -0
  22. package/lib/Utils/message-search.d.ts +44 -0
  23. package/lib/Utils/message-search.js +174 -0
  24. package/lib/Utils/scheduling.d.ts +42 -0
  25. package/lib/Utils/scheduling.js +140 -0
  26. package/lib/Utils/status.d.ts +50 -0
  27. package/lib/Utils/status.js +108 -0
  28. package/lib/Utils/stickerpack.d.ts +51 -0
  29. package/lib/Utils/stickerpack.js +276 -0
  30. package/lib/Utils/templates.d.ts +76 -0
  31. package/lib/Utils/templates.js +151 -0
  32. package/lib/Utils/use-sqlite-auth-state.js +28 -1
  33. package/lib/Utils/vcard.d.ts +58 -0
  34. package/lib/Utils/vcard.js +94 -0
  35. package/lib/VoIP/audio-feeder.d.ts +15 -0
  36. package/lib/VoIP/audio-feeder.js +132 -0
  37. package/lib/VoIP/index.js +277 -0
  38. package/lib/VoIP/relay-transport.d.ts +43 -0
  39. package/lib/VoIP/relay-transport.js +559 -0
  40. package/lib/VoIP/signaling.js +624 -0
  41. package/lib/VoIP/types.d.ts +69 -0
  42. package/lib/VoIP/types.js +17 -0
  43. package/lib/VoIP/wasm-engine.d.ts +103 -0
  44. package/lib/VoIP/wasm-engine.js +1214 -0
  45. package/lib/VoIP/worker-bootstrap.js +1042 -0
  46. package/lib/WABinary/generic-utils.js +8 -0
  47. package/lib/assets/wasm/loader.js +5 -0
  48. package/lib/assets/wasm/whatsapp.wasm +0 -0
  49. package/lib/assets/wasm/worker-modules.js +273 -0
  50. package/lib/index.js +4 -0
  51. package/package.json +22 -1
@@ -0,0 +1,68 @@
1
+ import type { WAMessage, WAMessageKey } from '../Types/index.js';
2
+ export interface MessageStoreOptions {
3
+ maxMessagesPerChat?: number;
4
+ ttl?: number;
5
+ cleanupInterval?: number;
6
+ }
7
+ export interface StoredMessage {
8
+ message: WAMessage;
9
+ storedAt: number;
10
+ isDeleted: boolean;
11
+ deletedAt?: number;
12
+ deletedBy?: string;
13
+ }
14
+ export interface DeletedMessageInfo {
15
+ originalMessage: WAMessage;
16
+ key: WAMessageKey;
17
+ deletedAt: number;
18
+ deletedBy?: string;
19
+ isRevokedBySender: boolean;
20
+ }
21
+ export declare class MessageStore {
22
+ private store;
23
+ private deletedMessages;
24
+ private cleanupTimer;
25
+ private options;
26
+ constructor(options?: MessageStoreOptions);
27
+ stopCleanup(): void;
28
+ storeMessage(message: WAMessage): void;
29
+ storeMessages(messages: WAMessage[]): void;
30
+ getMessage(key: WAMessageKey): StoredMessage | undefined;
31
+ getOriginalMessage(key: WAMessageKey): WAMessage | undefined;
32
+ markAsDeleted(key: WAMessageKey, deletedBy?: string): DeletedMessageInfo | null;
33
+ getDeletedMessage(key: WAMessageKey): DeletedMessageInfo | undefined;
34
+ getAllDeletedMessages(): DeletedMessageInfo[];
35
+ getDeletedMessagesByChat(chatId: string): DeletedMessageInfo[];
36
+ getChatMessages(chatId: string): WAMessage[];
37
+ getChatIds(): string[];
38
+ getStats(): {
39
+ totalChats: number;
40
+ totalMessages: number;
41
+ totalDeleted: number;
42
+ };
43
+ clear(): void;
44
+ clearChat(chatId: string): void;
45
+ getAllMessages(): Record<string, WAMessage[]>;
46
+ }
47
+ export declare const isDeleteMessage: (message: WAMessage) => boolean;
48
+ export declare const getDeletedMessageKey: (message: WAMessage) => WAMessageKey | null;
49
+ export declare const createAntiDeleteHandler: (store: MessageStore, onDelete?: (info: DeletedMessageInfo) => void) => (updates: Array<{
50
+ key: WAMessageKey;
51
+ update: Partial<WAMessage>;
52
+ }>) => DeletedMessageInfo[];
53
+ export declare const createMessageStoreHandler: (store: MessageStore) => ({ messages }: {
54
+ messages: WAMessage[];
55
+ }) => void;
56
+ declare const _default: {
57
+ MessageStore: typeof MessageStore;
58
+ isDeleteMessage: (message: WAMessage) => boolean;
59
+ getDeletedMessageKey: (message: WAMessage) => WAMessageKey | null;
60
+ createAntiDeleteHandler: (store: MessageStore, onDelete?: (info: DeletedMessageInfo) => void) => (updates: Array<{
61
+ key: WAMessageKey;
62
+ update: Partial<WAMessage>;
63
+ }>) => DeletedMessageInfo[];
64
+ createMessageStoreHandler: (store: MessageStore) => ({ messages }: {
65
+ messages: WAMessage[];
66
+ }) => void;
67
+ };
68
+ export default _default;
@@ -0,0 +1,185 @@
1
+ // Vanz@Add --- ported from Bail-master addons/anti-delete.ts (adapted to lib/ CJS-free ESM
2
+ // runtime style used throughout this fork; type-only annotations dropped, behavior unchanged).
3
+ import { proto } from '../../WAProto/index.js';
4
+ // ── MessageStore ───────────────────────────────────────────────────────────
5
+ /**
6
+ * In-memory, TTL-bounded store of recently seen messages, used to recover the
7
+ * original content of a message after WhatsApp delivers a REVOKE (delete-for-everyone)
8
+ * protocol message, which itself carries no content — only a reference key.
9
+ */
10
+ export class MessageStore {
11
+ store = new Map();
12
+ deletedMessages = new Map();
13
+ cleanupTimer = null;
14
+ options;
15
+ constructor(options = {}) {
16
+ this.options = {
17
+ maxMessagesPerChat: options.maxMessagesPerChat ?? 1000,
18
+ ttl: options.ttl ?? 24 * 60 * 60 * 1000,
19
+ cleanupInterval: options.cleanupInterval ?? 60 * 60 * 1000
20
+ };
21
+ this.startCleanup();
22
+ }
23
+ startCleanup() {
24
+ this.cleanupTimer = setInterval(() => this.cleanup(), this.options.cleanupInterval);
25
+ this.cleanupTimer?.unref?.();
26
+ }
27
+ stopCleanup() {
28
+ if (this.cleanupTimer)
29
+ clearInterval(this.cleanupTimer);
30
+ }
31
+ cleanup() {
32
+ const cutoff = Date.now() - this.options.ttl;
33
+ for (const [chatId, messages] of this.store) {
34
+ for (const [msgId, stored] of messages) {
35
+ if (stored.storedAt < cutoff)
36
+ messages.delete(msgId);
37
+ }
38
+ if (messages.size === 0)
39
+ this.store.delete(chatId);
40
+ }
41
+ for (const [key, info] of this.deletedMessages) {
42
+ if (info.deletedAt < cutoff)
43
+ this.deletedMessages.delete(key);
44
+ }
45
+ }
46
+ getKey(key) {
47
+ return `${key.remoteJid}:${key.id}`;
48
+ }
49
+ storeMessage(message) {
50
+ const chatId = message.key.remoteJid;
51
+ if (!chatId || !message.key.id)
52
+ return;
53
+ let chatMessages = this.store.get(chatId);
54
+ if (!chatMessages) {
55
+ chatMessages = new Map();
56
+ this.store.set(chatId, chatMessages);
57
+ }
58
+ if (chatMessages.size >= this.options.maxMessagesPerChat) {
59
+ const oldestKey = chatMessages.keys().next().value;
60
+ if (oldestKey)
61
+ chatMessages.delete(oldestKey);
62
+ }
63
+ chatMessages.set(message.key.id, { message, storedAt: Date.now(), isDeleted: false });
64
+ }
65
+ storeMessages(messages) {
66
+ for (const msg of messages)
67
+ this.storeMessage(msg);
68
+ }
69
+ getMessage(key) {
70
+ return this.store.get(key.remoteJid)?.get(key.id);
71
+ }
72
+ getOriginalMessage(key) {
73
+ return this.getMessage(key)?.message;
74
+ }
75
+ markAsDeleted(key, deletedBy) {
76
+ const stored = this.getMessage(key);
77
+ if (!stored)
78
+ return null;
79
+ const now = Date.now();
80
+ stored.isDeleted = true;
81
+ stored.deletedAt = now;
82
+ stored.deletedBy = deletedBy;
83
+ const info = {
84
+ originalMessage: stored.message,
85
+ key,
86
+ deletedAt: now,
87
+ deletedBy,
88
+ isRevokedBySender: !deletedBy || deletedBy === stored.message.key.participant
89
+ };
90
+ this.deletedMessages.set(this.getKey(key), info);
91
+ return info;
92
+ }
93
+ getDeletedMessage(key) {
94
+ return this.deletedMessages.get(this.getKey(key));
95
+ }
96
+ getAllDeletedMessages() {
97
+ return Array.from(this.deletedMessages.values());
98
+ }
99
+ getDeletedMessagesByChat(chatId) {
100
+ return Array.from(this.deletedMessages.values()).filter((i) => i.key.remoteJid === chatId);
101
+ }
102
+ getChatMessages(chatId) {
103
+ return Array.from(this.store.get(chatId)?.values() ?? []).map((s) => s.message);
104
+ }
105
+ getChatIds() {
106
+ return Array.from(this.store.keys());
107
+ }
108
+ getStats() {
109
+ let totalMessages = 0;
110
+ for (const messages of this.store.values())
111
+ totalMessages += messages.size;
112
+ return { totalChats: this.store.size, totalMessages, totalDeleted: this.deletedMessages.size };
113
+ }
114
+ clear() {
115
+ this.store.clear();
116
+ this.deletedMessages.clear();
117
+ }
118
+ clearChat(chatId) {
119
+ this.store.delete(chatId);
120
+ }
121
+ getAllMessages() {
122
+ const all = {};
123
+ for (const [chatId, messages] of this.store) {
124
+ all[chatId] = Array.from(messages.values()).map((s) => s.message);
125
+ }
126
+ return all;
127
+ }
128
+ }
129
+ // ── Helpers ────────────────────────────────────────────────────────────────
130
+ export const isDeleteMessage = (message) => {
131
+ return message.message?.protocolMessage?.type === proto.Message.ProtocolMessage.Type.REVOKE;
132
+ };
133
+ export const getDeletedMessageKey = (message) => {
134
+ const protoMsg = message.message?.protocolMessage;
135
+ if (protoMsg?.type !== proto.Message.ProtocolMessage.Type.REVOKE)
136
+ return null;
137
+ return protoMsg.key ?? null;
138
+ };
139
+ /**
140
+ * Wire this into `sock.ev.on('messages.update', ...)`. Fires `onDelete` for
141
+ * every update in the batch whose stub type is REVOKE, using `store` to look
142
+ * up the original content that WhatsApp's own update payload omits.
143
+ */
144
+ export const createAntiDeleteHandler = (store, onDelete) => {
145
+ return (updates) => {
146
+ const deletedMessages = [];
147
+ for (const { key, update } of updates) {
148
+ if (update.messageStubType === proto.WebMessageInfo.StubType.REVOKE) {
149
+ const info = store.markAsDeleted(key, update.messageStubParameters?.[0]);
150
+ if (info) {
151
+ deletedMessages.push(info);
152
+ onDelete?.(info);
153
+ }
154
+ }
155
+ }
156
+ return deletedMessages;
157
+ };
158
+ };
159
+ /**
160
+ * Wire this into `sock.ev.on('messages.upsert', ...)` to keep `store` populated.
161
+ * Skips protocol/sender-key-distribution messages, which carry no user content.
162
+ */
163
+ export const createMessageStoreHandler = (store) => {
164
+ return ({ messages }) => {
165
+ const regular = messages.filter((msg) => {
166
+ const c = msg.message;
167
+ if (!c)
168
+ return false;
169
+ if (c.protocolMessage)
170
+ return false;
171
+ if (c.senderKeyDistributionMessage)
172
+ return false;
173
+ return true;
174
+ });
175
+ store.storeMessages(regular);
176
+ };
177
+ };
178
+ export default {
179
+ MessageStore,
180
+ isDeleteMessage,
181
+ getDeletedMessageKey,
182
+ createAntiDeleteHandler,
183
+ createMessageStoreHandler
184
+ };
185
+ //# sourceMappingURL=anti-delete.js.map
@@ -0,0 +1,47 @@
1
+ import type { WAMessage, AnyMessageContent } from '../Types/index.js';
2
+ export interface AutoReplyRule {
3
+ id?: string;
4
+ keywords?: string[];
5
+ pattern?: RegExp;
6
+ exactMatch?: string;
7
+ response: AnyMessageContent | ((message: WAMessage, match: RegExpMatchArray | string[]) => Promise<AnyMessageContent> | AnyMessageContent);
8
+ cooldown?: number;
9
+ priority?: number;
10
+ active?: boolean;
11
+ groupsOnly?: boolean;
12
+ privateOnly?: boolean;
13
+ allowedJids?: string[];
14
+ blockedJids?: string[];
15
+ quoted?: boolean;
16
+ }
17
+ export interface AutoReplyOptions {
18
+ globalCooldown?: number;
19
+ simulateTyping?: boolean;
20
+ typingDuration?: number;
21
+ multiMatch?: boolean;
22
+ onReply?: (rule: AutoReplyRule, message: WAMessage, response: AnyMessageContent) => void;
23
+ onError?: (error: Error, rule: AutoReplyRule, message: WAMessage) => void;
24
+ }
25
+ export declare class AutoReplyHandler {
26
+ private rules;
27
+ private cooldowns;
28
+ private globalCooldown;
29
+ private sendMessage;
30
+ private sendPresence?;
31
+ private options;
32
+ constructor(sendMessage: (jid: string, content: AnyMessageContent, options?: any) => Promise<any>, sendPresence?: (jid: string, presence: string) => Promise<void>, options?: AutoReplyOptions);
33
+ addRule(rule: AutoReplyRule): AutoReplyRule & {
34
+ id: string;
35
+ };
36
+ removeRule(id: string): boolean;
37
+ getRules(): (AutoReplyRule & {
38
+ id: string;
39
+ })[];
40
+ getRule(id: string): (AutoReplyRule & {
41
+ id: string;
42
+ }) | undefined;
43
+ setRuleActive(id: string, active: boolean): boolean;
44
+ clearRules(): void;
45
+ processMessage(message: WAMessage): Promise<boolean>;
46
+ }
47
+ export declare const createAutoReply: (sendMessage: (jid: string, content: AnyMessageContent, options?: any) => Promise<any>, sendPresence?: (jid: string, presence: string) => Promise<void>, options?: AutoReplyOptions) => AutoReplyHandler;
@@ -0,0 +1,155 @@
1
+ // Vanz@Add --- ported from Bail-master addons/auto-reply.ts (type-only
2
+ // annotations dropped; behavior unchanged).
3
+ export class AutoReplyHandler {
4
+ rules = new Map();
5
+ cooldowns = new Map();
6
+ globalCooldown = new Map();
7
+ sendMessage;
8
+ sendPresence;
9
+ options;
10
+ constructor(sendMessage, sendPresence, options = {}) {
11
+ this.sendMessage = sendMessage;
12
+ this.sendPresence = sendPresence;
13
+ this.options = {
14
+ globalCooldown: options.globalCooldown ?? 1000,
15
+ simulateTyping: options.simulateTyping ?? false,
16
+ typingDuration: options.typingDuration ?? 1000,
17
+ multiMatch: options.multiMatch ?? false,
18
+ onReply: options.onReply ?? (() => { }),
19
+ onError: options.onError ?? (() => { })
20
+ };
21
+ }
22
+ generateId() {
23
+ return `ar_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
24
+ }
25
+ /** Add a rule keyed by keywords, a regex pattern, or an exact-match string. */
26
+ addRule(rule) {
27
+ const fullRule = {
28
+ ...rule,
29
+ id: rule.id ?? this.generateId(),
30
+ active: rule.active ?? true,
31
+ priority: rule.priority ?? 0
32
+ };
33
+ if (!fullRule.keywords && !fullRule.pattern && !fullRule.exactMatch)
34
+ throw new Error('Rule must have keywords, pattern, or exactMatch');
35
+ this.rules.set(fullRule.id, fullRule);
36
+ return fullRule;
37
+ }
38
+ removeRule(id) {
39
+ return this.rules.delete(id);
40
+ }
41
+ getRules() {
42
+ return Array.from(this.rules.values());
43
+ }
44
+ getRule(id) {
45
+ return this.rules.get(id);
46
+ }
47
+ setRuleActive(id, active) {
48
+ const r = this.rules.get(id);
49
+ if (r) {
50
+ r.active = active;
51
+ return true;
52
+ }
53
+ return false;
54
+ }
55
+ clearRules() {
56
+ this.rules.clear();
57
+ }
58
+ checkCooldown(ruleId, jid) {
59
+ return Date.now() - (this.cooldowns.get(`${ruleId}:${jid}`) ?? 0) > 0;
60
+ }
61
+ checkGlobalCooldown(jid) {
62
+ return Date.now() - (this.globalCooldown.get(jid) ?? 0) > this.options.globalCooldown;
63
+ }
64
+ setCooldown(ruleId, jid, cooldown) {
65
+ this.cooldowns.set(`${ruleId}:${jid}`, Date.now() + cooldown);
66
+ this.globalCooldown.set(jid, Date.now());
67
+ }
68
+ matchRule(text, rule) {
69
+ if (!rule.active)
70
+ return null;
71
+ if (text.toLowerCase() === rule.exactMatch?.toLowerCase())
72
+ return [text];
73
+ if (rule.keywords?.length) {
74
+ const lower = text.toLowerCase();
75
+ for (const kw of rule.keywords)
76
+ if (lower.includes(kw.toLowerCase()))
77
+ return [kw];
78
+ }
79
+ if (rule.pattern)
80
+ return text.match(rule.pattern);
81
+ return null;
82
+ }
83
+ isJidAllowed(jid, rule) {
84
+ const isGroup = jid.endsWith('@g.us');
85
+ if (jid.endsWith('@newsletter'))
86
+ return false;
87
+ if (rule.groupsOnly && !isGroup)
88
+ return false;
89
+ if (rule.privateOnly && isGroup)
90
+ return false;
91
+ if (rule.allowedJids?.length && !rule.allowedJids.includes(jid))
92
+ return false;
93
+ if (rule.blockedJids?.includes(jid))
94
+ return false;
95
+ return true;
96
+ }
97
+ /**
98
+ * Feed each incoming message through here (e.g. from `messages.upsert`).
99
+ * Returns true if a rule matched and a reply was sent.
100
+ */
101
+ async processMessage(message) {
102
+ const content = message.message;
103
+ if (!content)
104
+ return false;
105
+ const text = content.conversation ||
106
+ content.extendedTextMessage?.text ||
107
+ content.imageMessage?.caption ||
108
+ content.videoMessage?.caption ||
109
+ content.documentMessage?.caption ||
110
+ '';
111
+ if (!text)
112
+ return false;
113
+ const jid = message.key.remoteJid;
114
+ if (!jid || !this.checkGlobalCooldown(jid))
115
+ return false;
116
+ const sortedRules = Array.from(this.rules.values())
117
+ .filter((r) => r.active)
118
+ .sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
119
+ let matched = false;
120
+ for (const rule of sortedRules) {
121
+ if (!this.isJidAllowed(jid, rule))
122
+ continue;
123
+ if (rule.cooldown && !this.checkCooldown(rule.id, jid))
124
+ continue;
125
+ const match = this.matchRule(text, rule);
126
+ if (!match)
127
+ continue;
128
+ try {
129
+ let response;
130
+ if (typeof rule.response === 'function')
131
+ response = await rule.response(message, match);
132
+ else
133
+ response = rule.response;
134
+ if (this.options.simulateTyping && this.sendPresence) {
135
+ await this.sendPresence(jid, 'composing');
136
+ await new Promise((r) => setTimeout(r, this.options.typingDuration));
137
+ await this.sendPresence(jid, 'paused');
138
+ }
139
+ await this.sendMessage(jid, response, rule.quoted ? { quoted: message } : undefined);
140
+ if (rule.cooldown)
141
+ this.setCooldown(rule.id, jid, rule.cooldown);
142
+ this.options.onReply(rule, message, response);
143
+ matched = true;
144
+ if (!this.options.multiMatch)
145
+ break;
146
+ }
147
+ catch (error) {
148
+ this.options.onError(error, rule, message);
149
+ }
150
+ }
151
+ return matched;
152
+ }
153
+ }
154
+ export const createAutoReply = (sendMessage, sendPresence, options) => new AutoReplyHandler(sendMessage, sendPresence, options);
155
+ //# sourceMappingURL=auto-reply.js.map