@fer2809fl/baileys 7.0.4 → 7.0.5

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/README.md +347 -50
  2. package/lib/Defaults/index.js +1 -1
  3. package/lib/Modded/message_builder.js +2356 -0
  4. package/lib/Socket/chats.d.ts +14 -0
  5. package/lib/Socket/chats.js +48 -0
  6. package/lib/Socket/index.d.ts +17 -0
  7. package/lib/Socket/messages-send.d.ts +18 -0
  8. package/lib/Socket/messages-send.js +50 -2
  9. package/lib/Utils/anti-ban.d.ts +41 -0
  10. package/lib/Utils/anti-ban.js +182 -0
  11. package/lib/Utils/banner.d.ts +8 -0
  12. package/lib/Utils/banner.js +76 -0
  13. package/lib/Utils/bot-utils.d.ts +57 -0
  14. package/lib/Utils/bot-utils.js +241 -0
  15. package/lib/Utils/enhanced-cache.d.ts +40 -0
  16. package/lib/Utils/enhanced-cache.js +242 -0
  17. package/lib/Utils/enhanced-logger.d.ts +41 -0
  18. package/lib/Utils/enhanced-logger.js +185 -0
  19. package/lib/Utils/index.d.ts +14 -0
  20. package/lib/Utils/index.js +13 -0
  21. package/lib/Utils/lid-utils.d.ts +139 -0
  22. package/lib/Utils/lid-utils.js +503 -0
  23. package/lib/Utils/message-queue.d.ts +47 -0
  24. package/lib/Utils/message-queue.js +226 -0
  25. package/lib/Utils/rich-message-utils.d.ts +21 -0
  26. package/lib/Utils/rich-message-utils.js +229 -0
  27. package/lib/Utils/rich-messages.d.ts +52 -0
  28. package/lib/Utils/rich-messages.js +185 -0
  29. package/lib/Utils/scheduled-messages.d.ts +122 -0
  30. package/lib/Utils/scheduled-messages.js +289 -0
  31. package/lib/Utils/smart-reconnect.d.ts +48 -0
  32. package/lib/Utils/smart-reconnect.js +207 -0
  33. package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
  34. package/lib/Utils/use-sqlite-auth-state.js +95 -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 +594 -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/assets/wasm/loader.js +5 -0
  47. package/lib/assets/wasm/whatsapp.wasm +0 -0
  48. package/lib/assets/wasm/worker-modules.js +273 -0
  49. package/lib/index.d.ts +41 -0
  50. package/lib/index.js +3 -0
  51. package/package.json +10 -2
@@ -170,6 +170,55 @@ export const BASH_KEYWORDS = new Set([
170
170
  "declare",
171
171
  "typeset",
172
172
  ]);
173
+ // -- Añadido en v7.0.5: mas lenguajes soportados para resaltado de código (portado desde el fork beta) --
174
+ export const RUST_KEYWORDS = new Set([
175
+ "as", "async", "await", "break", "const", "continue", "crate", "dyn", "else",
176
+ "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop",
177
+ "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self",
178
+ "static", "struct", "super", "trait", "true", "type", "unsafe", "use",
179
+ "where", "while",
180
+ ]);
181
+ export const C_KEYWORDS = new Set([
182
+ "auto", "break", "case", "char", "const", "continue", "default", "do",
183
+ "double", "else", "enum", "extern", "float", "for", "goto", "if", "inline",
184
+ "int", "long", "register", "restrict", "return", "short", "signed",
185
+ "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned",
186
+ "void", "volatile", "while",
187
+ ]);
188
+ export const CPP_KEYWORDS = new Set([
189
+ ...C_KEYWORDS, "alignas", "alignof", "and", "asm", "bool", "catch", "class",
190
+ "concept", "consteval", "constexpr", "constinit", "const_cast", "co_await",
191
+ "co_return", "co_yield", "decltype", "delete", "dynamic_cast", "explicit",
192
+ "export", "friend", "mutable", "namespace", "new", "noexcept", "not",
193
+ "nullptr", "operator", "private", "protected", "public", "reinterpret_cast",
194
+ "requires", "static_assert", "static_cast", "template", "this",
195
+ "thread_local", "throw", "true", "try", "typeid", "typename", "using",
196
+ "virtual", "wchar_t",
197
+ ]);
198
+ export const CSHARP_KEYWORDS = new Set([
199
+ "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char",
200
+ "checked", "class", "const", "continue", "decimal", "default", "delegate",
201
+ "do", "double", "else", "enum", "event", "explicit", "extern", "false",
202
+ "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit",
203
+ "in", "int", "interface", "internal", "is", "lock", "long", "namespace",
204
+ "new", "null", "object", "operator", "out", "override", "params", "private",
205
+ "protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
206
+ "short", "sizeof", "stackalloc", "static", "string", "struct", "switch",
207
+ "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked",
208
+ "unsafe", "ushort", "using", "var", "virtual", "void", "volatile", "while",
209
+ ]);
210
+ export const HTML_KEYWORDS = new Set([
211
+ "DOCTYPE", "html", "head", "body", "div", "span", "p", "a", "h1", "h2",
212
+ "h3", "h4", "h5", "h6", "ul", "ol", "li", "table", "tr", "td", "th", "form",
213
+ "input", "button", "select", "option", "textarea", "img", "video", "audio",
214
+ "source", "canvas", "svg", "script", "style", "link", "meta", "title",
215
+ ]);
216
+ export const CSS_KEYWORDS = new Set([
217
+ "color", "background", "margin", "padding", "border", "display",
218
+ "position", "width", "height", "font", "text", "align", "flex", "grid",
219
+ "animation", "transition", "transform", "opacity", "overflow", "cursor",
220
+ "z-index",
221
+ ]);
173
222
  export const LANGUAGE_KEYWORDS = {
174
223
  javascript: JS_KEYWORDS,
175
224
  typescript: JS_KEYWORDS,
@@ -183,6 +232,15 @@ export const LANGUAGE_KEYWORDS = {
183
232
  bash: BASH_KEYWORDS,
184
233
  sh: BASH_KEYWORDS,
185
234
  shell: BASH_KEYWORDS,
235
+ zsh: BASH_KEYWORDS,
236
+ rust: RUST_KEYWORDS,
237
+ c: C_KEYWORDS,
238
+ cpp: CPP_KEYWORDS,
239
+ "c++": CPP_KEYWORDS,
240
+ csharp: CSHARP_KEYWORDS,
241
+ "c#": CSHARP_KEYWORDS,
242
+ html: HTML_KEYWORDS,
243
+ css: CSS_KEYWORDS,
186
244
  };
187
245
  export var CodeHighlightType;
188
246
  (function (CodeHighlightType) {
@@ -1141,4 +1199,131 @@ export const generateLinkContentV2 = (text, links, quoted, options = {}) => {
1141
1199
  messageId: generateMessageIDV2(),
1142
1200
  };
1143
1201
  };
1202
+
1203
+ /**
1204
+ * Construye un mensaje que el cliente de WhatsApp renderiza como un WebView
1205
+ * embebido dentro del bocadillo del mensaje, usando el campo interno
1206
+ * `GenAIaeacdsnwHtmlPrimitive` del protocolo AIRichResponseMessage.
1207
+ *
1208
+ * El HTML vive dentro de `unifiedResponse.data` (bytes opacos para el protocolo
1209
+ * protobuf, pero parseados como JSON por el cliente de WhatsApp). El cliente
1210
+ * levanta un WebView sandboxed y le permite hacer fetch únicamente a los
1211
+ * dominios listados en `trustedSources`.
1212
+ *
1213
+ * Limitaciones estructurales conocidas (ver README sección "HTML embebido"):
1214
+ * - El WebView es efímero: NO confíes en `localStorage` para persistencia
1215
+ * entre sesiones. Mové la persistencia a un backend HTTP listado en
1216
+ * `trustedSources`.
1217
+ * - No existe un puente HTML → bot: el HTML no puede disparar eventos
1218
+ * directos al bot. Usá `fetch()` a tu backend y que el backend llame
1219
+ * `sock.sendMessage(...)` si necesitas reaccionar.
1220
+ * - El HTML no recibe identidad del usuario automáticamente: inyectá
1221
+ * `window.__INITIAL__ = { jid, token, ... }` al renderizar desde el bot.
1222
+ *
1223
+ * @param {string} html - Contenido HTML (con `<style>`, `<body>`, `<script>`).
1224
+ * @param {object} quoted - Mensaje al que responder (opcional).
1225
+ * @param {object} options - Opciones adicionales.
1226
+ * @param {string[]} options.trustedSources - Dominios que el WebView puede
1227
+ * contactar (fetch, imágenes, fuentes, etc.). Sin esquema (ej: "api.tuyo.com").
1228
+ * @param {string} options.headerText - Texto opcional arriba del HTML.
1229
+ * @param {string} options.footer - Texto opcional debajo del HTML.
1230
+ * @param {string} options.fallbackText - Texto mostrado en el submessage de
1231
+ * respaldo si el cliente no soporta HTML (default: "Contenido interactivo").
1232
+ * @returns {{ message: object, messageId: string }}
1233
+ */
1234
+ export const generateHtmlContent = (html, quoted, options = {}) => {
1235
+ const {
1236
+ trustedSources = [],
1237
+ headerText,
1238
+ footer,
1239
+ fallbackText = "Contenido interactivo",
1240
+ } = options;
1241
+
1242
+ const sections = [];
1243
+
1244
+ if (headerText) {
1245
+ sections.push({
1246
+ view_model: {
1247
+ primitive: {
1248
+ text: headerText,
1249
+ __typename: "GenAIMarkdownTextUXPrimitive",
1250
+ },
1251
+ __typename: "GenAISingleLayoutViewModel",
1252
+ },
1253
+ });
1254
+ }
1255
+
1256
+ sections.push({
1257
+ view_model: {
1258
+ primitive: {
1259
+ __typename: "GenAIaeacdsnwHtmlPrimitive",
1260
+ payload: html,
1261
+ trusted_sources: trustedSources,
1262
+ },
1263
+ __typename: "GenAISingleLayoutViewModel",
1264
+ },
1265
+ });
1266
+
1267
+ if (footer) {
1268
+ sections.push({
1269
+ view_model: {
1270
+ primitive: {
1271
+ text: footer,
1272
+ __typename: "GenAIMarkdownTextUXPrimitive",
1273
+ },
1274
+ __typename: "GenAISingleLayoutViewModel",
1275
+ },
1276
+ });
1277
+ }
1278
+
1279
+ const responseId = randomUUID();
1280
+ const unifiedData = {
1281
+ response_id: responseId,
1282
+ sections,
1283
+ version: "1",
1284
+ is_final: true,
1285
+ };
1286
+ const base64Data = Buffer.from(JSON.stringify(unifiedData)).toString(
1287
+ "base64",
1288
+ );
1289
+
1290
+ const submessages = [
1291
+ {
1292
+ messageType: 2, // AI_RICH_RESPONSE_TEXT
1293
+ messageText: fallbackText,
1294
+ },
1295
+ ];
1296
+
1297
+ const ctxInfo = {
1298
+ isForwarded: true,
1299
+ forwardOrigin: 4, // META_AI
1300
+ };
1301
+ if (quoted?.key) {
1302
+ ctxInfo.participant =
1303
+ quoted.key.participant || quoted.sender || quoted.key.remoteJid;
1304
+ ctxInfo.quotedMessage = quoted.message;
1305
+ }
1306
+
1307
+ const content = {
1308
+ messageContextInfo: {
1309
+ threadId: [],
1310
+ messageSecret: randomBytes(32),
1311
+ },
1312
+ botForwardedMessage: {
1313
+ message: {
1314
+ richResponseMessage: {
1315
+ messageType: 1, // AI_RICH_RESPONSE_TYPE_STANDARD
1316
+ submessages,
1317
+ unifiedResponse: { data: base64Data },
1318
+ contextInfo: ctxInfo,
1319
+ },
1320
+ },
1321
+ },
1322
+ };
1323
+
1324
+ return {
1325
+ message: content,
1326
+ messageId: generateMessageIDV2(),
1327
+ };
1328
+ };
1144
1329
  //# sourceMappingURL=rich-messages.js.map
@@ -0,0 +1,122 @@
1
+ import type { WASocket } from '../Socket/index.js';
2
+ import type { AnyMessageContent } from '../Types/Message.js';
3
+
4
+ export interface ScheduledMessage {
5
+ id: string;
6
+ jid: string;
7
+ content: AnyMessageContent;
8
+ type: 'once' | 'recurring';
9
+ timestamp?: number;
10
+ cron?: string;
11
+ sent?: boolean;
12
+ sentAt?: number;
13
+ cancelled?: boolean;
14
+ cancelledAt?: number;
15
+ createdAt: number;
16
+ lastSent?: number;
17
+ executionCount?: number;
18
+ lastError?: string;
19
+ errorCount?: number;
20
+ [key: string]: any;
21
+ }
22
+
23
+ export interface SchedulerStats {
24
+ total: number;
25
+ pending: number;
26
+ sent: number;
27
+ recurring: number;
28
+ cancelled: number;
29
+ errors: number;
30
+ }
31
+
32
+ export interface ScheduledMessageFilter {
33
+ jid?: string;
34
+ type?: 'once' | 'recurring';
35
+ cancelled?: boolean;
36
+ pending?: boolean;
37
+ }
38
+
39
+ /**
40
+ * Iniciar el scheduler de mensajes programados
41
+ * @param sock - Socket de conexión de WhatsApp
42
+ * @param intervalMs - Intervalo de revisión en ms (default: 30000)
43
+ */
44
+ export declare const startScheduler: (sock: WASocket, intervalMs?: number) => void;
45
+
46
+ /**
47
+ * Detener el scheduler
48
+ */
49
+ export declare const stopScheduler: () => void;
50
+
51
+ /**
52
+ * Programar un mensaje para enviar en una fecha/hora específica
53
+ * @param jid - Destinatario
54
+ * @param content - Contenido del mensaje
55
+ * @param timestamp - Fecha/hora de envío (timestamp ms o Date)
56
+ * @param options - Opciones adicionales (id personalizado, etc.)
57
+ * @returns ID del mensaje programado
58
+ */
59
+ export declare const scheduleMessage: (
60
+ jid: string,
61
+ content: AnyMessageContent,
62
+ timestamp: number | Date,
63
+ options?: { id?: string; [key: string]: any }
64
+ ) => string;
65
+
66
+ /**
67
+ * Programar un mensaje recurrente usando cron
68
+ * Formato: "MIN HOUR DOM MON DOW" (ej: "0 9 * * 1-5" = lunes a viernes a las 9am)
69
+ * @param jid - Destinatario
70
+ * @param content - Contenido del mensaje
71
+ * @param cron - Expresión cron
72
+ * @param options - Opciones adicionales
73
+ * @returns ID del mensaje programado
74
+ */
75
+ export declare const recurringMessage: (
76
+ jid: string,
77
+ content: AnyMessageContent,
78
+ cron: string,
79
+ options?: { id?: string; [key: string]: any }
80
+ ) => string;
81
+
82
+ /**
83
+ * Cancelar un mensaje programado
84
+ * @param id - ID del mensaje
85
+ * @returns true si se canceló
86
+ */
87
+ export declare const cancelScheduledMessage: (id: string) => boolean;
88
+
89
+ /**
90
+ * Eliminar un mensaje programado permanentemente
91
+ * @param id - ID del mensaje
92
+ * @returns true si se eliminó
93
+ */
94
+ export declare const deleteScheduledMessage: (id: string) => boolean;
95
+
96
+ /**
97
+ * Obtener todos los mensajes programados
98
+ * @param filter - Filtros opcionales
99
+ * @returns Lista de mensajes
100
+ */
101
+ export declare const listScheduledMessages: (filter?: ScheduledMessageFilter) => ScheduledMessage[];
102
+
103
+ /**
104
+ * Obtener un mensaje programado por ID
105
+ * @param id - ID del mensaje
106
+ * @returns Mensaje o null
107
+ */
108
+ export declare const getScheduledMessage: (id: string) => ScheduledMessage | null;
109
+
110
+ /**
111
+ * Actualizar el contenido de un mensaje programado
112
+ * @param id - ID del mensaje
113
+ * @param updates - Campos a actualizar
114
+ * @returns true si se actualizó
115
+ */
116
+ export declare const updateScheduledMessage: (id: string, updates: Partial<ScheduledMessage>) => boolean;
117
+
118
+ /**
119
+ * Obtener estadísticas del scheduler
120
+ * @returns Estadísticas
121
+ */
122
+ export declare const getSchedulerStats: () => SchedulerStats;
@@ -0,0 +1,289 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
2
+ import { join } from 'path';
3
+
4
+ const SCHEDULED_PATH = join(process.cwd(), 'database', 'scheduled-messages.json');
5
+ const scheduled = new Map();
6
+ let _sock = null;
7
+ let _initialized = false;
8
+
9
+ /**
10
+ * Parse a cron expression (simple format: "MIN HOUR DOM MON DOW")
11
+ * Returns true if the current time matches the cron
12
+ */
13
+ function matchCron(cron, date) {
14
+ if (!cron || typeof cron !== 'string') return false;
15
+ const parts = cron.trim().split(/\s+/);
16
+ if (parts.length !== 5) return false;
17
+
18
+ const [min, hour, dom, mon, dow] = parts;
19
+ const d = date || new Date();
20
+
21
+ const matchField = (field, value) => {
22
+ if (field === '*') return true;
23
+ if (field.includes(',')) return field.split(',').some(v => matchField(v.trim(), value));
24
+ if (field.includes('-')) {
25
+ const [start, end] = field.split('-').map(Number);
26
+ return value >= start && value <= end;
27
+ }
28
+ if (field.includes('/')) {
29
+ const [, step] = field.split('/');
30
+ return value % parseInt(step) === 0;
31
+ }
32
+ return parseInt(field) === value;
33
+ };
34
+
35
+ return (
36
+ matchField(min, d.getMinutes()) &&
37
+ matchField(hour, d.getHours()) &&
38
+ matchField(dom, d.getDate()) &&
39
+ matchField(mon, d.getMonth() + 1) &&
40
+ matchField(dow, d.getDay())
41
+ );
42
+ }
43
+
44
+ function loadScheduled() {
45
+ try {
46
+ if (existsSync(SCHEDULED_PATH)) {
47
+ const data = JSON.parse(readFileSync(SCHEDULED_PATH, 'utf8'));
48
+ if (Array.isArray(data)) {
49
+ for (const msg of data) {
50
+ scheduled.set(msg.id, msg);
51
+ }
52
+ }
53
+ }
54
+ } catch { }
55
+ }
56
+
57
+ function saveScheduled() {
58
+ try {
59
+ const dirPath = join(process.cwd(), 'database');
60
+ if (!existsSync(dirPath)) mkdirSync(dirPath, { recursive: true });
61
+ const arr = Array.from(scheduled.values());
62
+ writeFileSync(SCHEDULED_PATH, JSON.stringify(arr, null, 2));
63
+ } catch { }
64
+ }
65
+
66
+ function generateId() {
67
+ return 'sch_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);
68
+ }
69
+
70
+ async function processScheduled() {
71
+ if (!_sock) return;
72
+ const now = Date.now();
73
+ let changed = false;
74
+
75
+ for (const [id, msg] of scheduled) {
76
+ if (msg.cancelled) continue;
77
+
78
+ const shouldSend =
79
+ (msg.type === 'once' && now >= msg.timestamp && !msg.sent) ||
80
+ (msg.type === 'recurring' && matchCron(msg.cron, new Date()));
81
+
82
+ if (shouldSend) {
83
+ try {
84
+ await _sock.sendMessage(msg.jid, msg.content);
85
+ changed = true;
86
+
87
+ if (msg.type === 'once') {
88
+ msg.sent = true;
89
+ msg.sentAt = now;
90
+ }
91
+
92
+ if (msg.type === 'recurring') {
93
+ msg.lastSent = now;
94
+ msg.executionCount = (msg.executionCount || 0) + 1;
95
+ }
96
+
97
+ _sock.logger?.info?.({ id, jid: msg.jid }, 'scheduled message sent');
98
+ } catch (err) {
99
+ _sock.logger?.warn?.({ err, id }, 'failed to send scheduled message');
100
+ msg.lastError = err.message;
101
+ msg.errorCount = (msg.errorCount || 0) + 1;
102
+ }
103
+ }
104
+
105
+ if (msg.type === 'once' && msg.sent) {
106
+ scheduled.delete(id);
107
+ changed = true;
108
+ }
109
+ }
110
+
111
+ if (changed) saveScheduled();
112
+ }
113
+
114
+ let _interval = null;
115
+
116
+ function startScheduler(sock, intervalMs = 30000) {
117
+ _sock = sock;
118
+ if (!_initialized) {
119
+ loadScheduled();
120
+ _initialized = true;
121
+ }
122
+ if (_interval) clearInterval(_interval);
123
+ _interval = setInterval(processScheduled, intervalMs);
124
+ processScheduled();
125
+ }
126
+
127
+ function stopScheduler() {
128
+ if (_interval) {
129
+ clearInterval(_interval);
130
+ _interval = null;
131
+ }
132
+ _sock = null;
133
+ }
134
+
135
+ /**
136
+ * Programar un mensaje para enviar en una fecha/hora específica
137
+ * @param {string} jid - Destinatario
138
+ * @param {Object} content - Contenido del mensaje (igual que sendMessage)
139
+ * @param {number|Date} timestamp - Fecha/hora de envío (timestamp ms o Date)
140
+ * @param {Object} options - Opciones adicionales
141
+ * @returns {string} ID del mensaje programado
142
+ */
143
+ function scheduleMessage(jid, content, timestamp, options = {}) {
144
+ const id = options.id || generateId();
145
+ const ts = timestamp instanceof Date ? timestamp.getTime() : timestamp;
146
+
147
+ const msg = {
148
+ id,
149
+ jid,
150
+ content,
151
+ timestamp: ts,
152
+ type: 'once',
153
+ sent: false,
154
+ createdAt: Date.now(),
155
+ ...options
156
+ };
157
+
158
+ scheduled.set(id, msg);
159
+ saveScheduled();
160
+ return id;
161
+ }
162
+
163
+ /**
164
+ * Programar un mensaje recurrente usando cron
165
+ * @param {string} jid - Destinatario
166
+ * @param {Object} content - Contenido del mensaje
167
+ * @param {string} cron - Expresión cron (MIN HOUR DOM MON DOW)
168
+ * @param {Object} options - Opciones adicionales
169
+ * @returns {string} ID del mensaje programado
170
+ */
171
+ function recurringMessage(jid, content, cron, options = {}) {
172
+ const id = options.id || generateId();
173
+
174
+ const msg = {
175
+ id,
176
+ jid,
177
+ content,
178
+ cron,
179
+ type: 'recurring',
180
+ executionCount: 0,
181
+ createdAt: Date.now(),
182
+ ...options
183
+ };
184
+
185
+ scheduled.set(id, msg);
186
+ saveScheduled();
187
+ return id;
188
+ }
189
+
190
+ /**
191
+ * Cancelar un mensaje programado
192
+ * @param {string} id - ID del mensaje
193
+ * @returns {boolean} true si se canceló
194
+ */
195
+ function cancelScheduledMessage(id) {
196
+ const msg = scheduled.get(id);
197
+ if (!msg) return false;
198
+ msg.cancelled = true;
199
+ msg.cancelledAt = Date.now();
200
+ saveScheduled();
201
+ return true;
202
+ }
203
+
204
+ /**
205
+ * Eliminar un mensaje programado permanentemente
206
+ * @param {string} id - ID del mensaje
207
+ * @returns {boolean} true si se eliminó
208
+ */
209
+ function deleteScheduledMessage(id) {
210
+ const deleted = scheduled.delete(id);
211
+ if (deleted) saveScheduled();
212
+ return deleted;
213
+ }
214
+
215
+ /**
216
+ * Obtener todos los mensajes programados
217
+ * @param {Object} filter - Filtros opcionales
218
+ * @returns {Object[]} Lista de mensajes
219
+ */
220
+ function listScheduledMessages(filter = {}) {
221
+ let msgs = Array.from(scheduled.values());
222
+
223
+ if (filter.jid) {
224
+ msgs = msgs.filter(m => m.jid === filter.jid);
225
+ }
226
+ if (filter.type) {
227
+ msgs = msgs.filter(m => m.type === filter.type);
228
+ }
229
+ if (filter.cancelled === false) {
230
+ msgs = msgs.filter(m => !m.cancelled);
231
+ }
232
+ if (filter.pending) {
233
+ msgs = msgs.filter(m => m.type === 'once' && !m.sent && !m.cancelled);
234
+ }
235
+
236
+ return msgs.sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));
237
+ }
238
+
239
+ /**
240
+ * Obtener un mensaje programado por ID
241
+ * @param {string} id - ID del mensaje
242
+ * @returns {Object|null}
243
+ */
244
+ function getScheduledMessage(id) {
245
+ return scheduled.get(id) || null;
246
+ }
247
+
248
+ /**
249
+ * Actualizar el contenido de un mensaje programado
250
+ * @param {string} id - ID del mensaje
251
+ * @param {Object} updates - Campos a actualizar
252
+ * @returns {boolean}
253
+ */
254
+ function updateScheduledMessage(id, updates) {
255
+ const msg = scheduled.get(id);
256
+ if (!msg) return false;
257
+ Object.assign(msg, updates);
258
+ saveScheduled();
259
+ return true;
260
+ }
261
+
262
+ /**
263
+ * Obtener estadísticas del scheduler
264
+ * @returns {Object}
265
+ */
266
+ function getSchedulerStats() {
267
+ const msgs = Array.from(scheduled.values());
268
+ return {
269
+ total: msgs.length,
270
+ pending: msgs.filter(m => m.type === 'once' && !m.sent && !m.cancelled).length,
271
+ sent: msgs.filter(m => m.type === 'once' && m.sent).length,
272
+ recurring: msgs.filter(m => m.type === 'recurring' && !m.cancelled).length,
273
+ cancelled: msgs.filter(m => m.cancelled).length,
274
+ errors: msgs.filter(m => m.lastError).length
275
+ };
276
+ }
277
+
278
+ export {
279
+ startScheduler,
280
+ stopScheduler,
281
+ scheduleMessage,
282
+ recurringMessage,
283
+ cancelScheduledMessage,
284
+ deleteScheduledMessage,
285
+ listScheduledMessages,
286
+ getScheduledMessage,
287
+ updateScheduledMessage,
288
+ getSchedulerStats
289
+ };
@@ -0,0 +1,48 @@
1
+ export declare const RECONNECT_CONFIG: {
2
+ MAX_RETRIES: number;
3
+ INITIAL_DELAY: number;
4
+ MAX_DELAY: number;
5
+ BACKOFF_FACTOR: number;
6
+ JITTER_FACTOR: number;
7
+ STABLE_CONNECTION_TIME: number;
8
+ RECOVERABLE_REASONS: number[];
9
+ FATAL_REASONS: number[];
10
+ };
11
+
12
+ export declare class SmartReconnect {
13
+ constructor(logger?: any, config?: Partial<typeof RECONNECT_CONFIG>);
14
+ retryCount: number;
15
+ connectionStable: boolean;
16
+ calculateDelay(): number;
17
+ shouldReconnect(reason: string, statusCode?: number): { shouldReconnect: boolean; reason?: string; delay?: number };
18
+ handleDisconnect(reason: string, statusCode: number | undefined, reconnectCallback: () => Promise<void>): Promise<{ reconnecting: boolean; reason?: string; success?: boolean; error?: any }>;
19
+ onSuccessfulReconnect(): void;
20
+ cancelPendingReconnect(): void;
21
+ reset(): void;
22
+ getStats(): {
23
+ totalReconnects: number;
24
+ successfulReconnects: number;
25
+ failedReconnects: number;
26
+ lastSuccessfulConnect: string | null;
27
+ averageDowntime: number;
28
+ currentRetryCount: number;
29
+ isStable: boolean;
30
+ lastDisconnect: { reason: string; statusCode?: number; time: number } | null;
31
+ };
32
+ startHealthCheck(pingCallback: () => Promise<void>, interval?: number): void;
33
+ stopHealthCheck(): void;
34
+ cleanup(): void;
35
+ }
36
+
37
+ export declare function createConnectionHandler(sock: any, logger?: any, options?: Partial<typeof RECONNECT_CONFIG>): {
38
+ reconnect: SmartReconnect;
39
+ handleConnectionUpdate(update: any, startSock: () => Promise<void>): Promise<any>;
40
+ getStatus(): { stats: ReturnType<SmartReconnect['getStats']>; isHealthy: boolean };
41
+ };
42
+
43
+ export declare function withRetry<T>(fn: () => Promise<T>, options?: {
44
+ maxRetries?: number;
45
+ delay?: number;
46
+ backoff?: number;
47
+ onRetry?: ((error: any, attempt: number, waitTime: number) => void) | null;
48
+ }): Promise<T>;