@arcaelas/whatsapp 5.1.0 → 6.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.
- package/README.md +284 -239
- package/build/cjs/decorators.js +0 -1
- package/build/cjs/index.js +0 -1
- package/build/cjs/lib/bot/decorator.js +0 -1
- package/build/cjs/lib/bot/decorators.d.ts +2 -2
- package/build/cjs/lib/bot/decorators.js +4 -4
- package/build/cjs/lib/bot/index.js +0 -1
- package/build/cjs/lib/chat/index.d.ts +41 -0
- package/build/cjs/lib/chat/index.js +27 -8
- package/build/cjs/lib/contact/index.js +0 -1
- package/build/cjs/lib/internal.js +0 -1
- package/build/cjs/lib/message/index.d.ts +10 -0
- package/build/cjs/lib/message/index.js +79 -14
- package/build/cjs/lib/status/index.js +0 -1
- package/build/cjs/lib/store/engine/index.d.ts +14 -0
- package/build/cjs/lib/store/engine/index.js +0 -1
- package/build/cjs/lib/store/engine/lib/file_system/index.d.ts +10 -0
- package/build/cjs/lib/store/engine/lib/file_system/index.js +27 -1
- package/build/cjs/lib/store/engine/lib/index.js +0 -1
- package/build/cjs/lib/store/engine/lib/redis/index.d.ts +18 -4
- package/build/cjs/lib/store/engine/lib/redis/index.js +21 -3
- package/build/cjs/lib/store/engine/lib/s3/index.js +0 -1
- package/build/cjs/lib/store/engine/lib/sqlite/index.d.ts +16 -4
- package/build/cjs/lib/store/engine/lib/sqlite/index.js +24 -6
- package/build/cjs/lib/store/index.js +0 -1
- package/build/cjs/lib/whatsapp/index.d.ts +1 -1
- package/build/cjs/lib/whatsapp/index.js +76 -20
- package/build/esm/decorators.js +0 -1
- package/build/esm/index.js +0 -1
- package/build/esm/lib/bot/decorator.js +0 -1
- package/build/esm/lib/bot/decorators.d.ts +2 -2
- package/build/esm/lib/bot/decorators.js +4 -4
- package/build/esm/lib/bot/index.js +0 -1
- package/build/esm/lib/chat/index.d.ts +41 -0
- package/build/esm/lib/chat/index.js +27 -8
- package/build/esm/lib/contact/index.js +0 -1
- package/build/esm/lib/internal.js +0 -1
- package/build/esm/lib/message/index.d.ts +10 -0
- package/build/esm/lib/message/index.js +79 -14
- package/build/esm/lib/status/index.js +0 -1
- package/build/esm/lib/store/engine/index.d.ts +14 -0
- package/build/esm/lib/store/engine/index.js +0 -1
- package/build/esm/lib/store/engine/lib/file_system/index.d.ts +10 -0
- package/build/esm/lib/store/engine/lib/file_system/index.js +27 -1
- package/build/esm/lib/store/engine/lib/index.js +0 -1
- package/build/esm/lib/store/engine/lib/redis/index.d.ts +18 -4
- package/build/esm/lib/store/engine/lib/redis/index.js +21 -3
- package/build/esm/lib/store/engine/lib/s3/index.js +0 -1
- package/build/esm/lib/store/engine/lib/sqlite/index.d.ts +16 -4
- package/build/esm/lib/store/engine/lib/sqlite/index.js +24 -6
- package/build/esm/lib/store/index.js +0 -1
- package/build/esm/lib/whatsapp/index.d.ts +1 -1
- package/build/esm/lib/whatsapp/index.js +76 -20
- package/package.json +24 -5
- package/build/cjs/decorators.js.map +0 -1
- package/build/cjs/index.js.map +0 -1
- package/build/cjs/lib/bot/decorator.js.map +0 -1
- package/build/cjs/lib/bot/decorators.js.map +0 -1
- package/build/cjs/lib/bot/index.js.map +0 -1
- package/build/cjs/lib/chat/index.js.map +0 -1
- package/build/cjs/lib/contact/index.js.map +0 -1
- package/build/cjs/lib/internal.js.map +0 -1
- package/build/cjs/lib/message/index.js.map +0 -1
- package/build/cjs/lib/status/index.js.map +0 -1
- package/build/cjs/lib/store/engine/index.js.map +0 -1
- package/build/cjs/lib/store/engine/lib/file_system/index.js.map +0 -1
- package/build/cjs/lib/store/engine/lib/index.js.map +0 -1
- package/build/cjs/lib/store/engine/lib/redis/index.js.map +0 -1
- package/build/cjs/lib/store/engine/lib/s3/index.js.map +0 -1
- package/build/cjs/lib/store/engine/lib/sqlite/index.js.map +0 -1
- package/build/cjs/lib/store/index.js.map +0 -1
- package/build/cjs/lib/whatsapp/index.js.map +0 -1
- package/build/cjs/test.d.ts +0 -1
- package/build/cjs/test.js +0 -72
- package/build/cjs/test.js.map +0 -1
- package/build/esm/decorators.js.map +0 -1
- package/build/esm/index.js.map +0 -1
- package/build/esm/lib/bot/decorator.js.map +0 -1
- package/build/esm/lib/bot/decorators.js.map +0 -1
- package/build/esm/lib/bot/index.js.map +0 -1
- package/build/esm/lib/chat/index.js.map +0 -1
- package/build/esm/lib/contact/index.js.map +0 -1
- package/build/esm/lib/internal.js.map +0 -1
- package/build/esm/lib/message/index.js.map +0 -1
- package/build/esm/lib/status/index.js.map +0 -1
- package/build/esm/lib/store/engine/index.js.map +0 -1
- package/build/esm/lib/store/engine/lib/file_system/index.js.map +0 -1
- package/build/esm/lib/store/engine/lib/index.js.map +0 -1
- package/build/esm/lib/store/engine/lib/redis/index.js.map +0 -1
- package/build/esm/lib/store/engine/lib/s3/index.js.map +0 -1
- package/build/esm/lib/store/engine/lib/sqlite/index.js.map +0 -1
- package/build/esm/lib/store/index.js.map +0 -1
- package/build/esm/lib/whatsapp/index.js.map +0 -1
- package/build/esm/test.d.ts +0 -1
- package/build/esm/test.js +0 -67
- package/build/esm/test.js.map +0 -1
|
@@ -82,9 +82,9 @@ export declare function delay(ms: number): (_value: unknown, context: ClassMetho
|
|
|
82
82
|
export declare const pair: () => (_value: unknown, context: ClassMethodDecoratorContext) => void;
|
|
83
83
|
/**
|
|
84
84
|
* Filtra por autor del mensaje. Acepta JID, LID o teléfono numérico; el string
|
|
85
|
-
* se normaliza
|
|
85
|
+
* se normaliza con la resolución interna del cliente y cache lazy. Un array produce match OR.
|
|
86
86
|
* Filters by message author. Accepts JID, LID or numeric phone; the string is
|
|
87
|
-
* normalized
|
|
87
|
+
* normalized through the client's internal resolution with lazy cache. An array yields OR matching.
|
|
88
88
|
*
|
|
89
89
|
* @param source - Identificador(es) permitidos o predicate sobre `msg.from` / Allowed identifier(s) or predicate on `msg.from`
|
|
90
90
|
*/
|
|
@@ -15,6 +15,7 @@ exports.from = from;
|
|
|
15
15
|
exports.Bot = Bot;
|
|
16
16
|
exports.pipe = pipe;
|
|
17
17
|
exports.command = command;
|
|
18
|
+
const internal_1 = require("../../lib/internal");
|
|
18
19
|
const decorator_1 = require("./decorator");
|
|
19
20
|
/**
|
|
20
21
|
* Registra el método como listener del evento indicado. Apilable: varios `@on`
|
|
@@ -126,9 +127,9 @@ exports.pair = (0, decorator_1.decorator)((_meta, h) => {
|
|
|
126
127
|
});
|
|
127
128
|
/**
|
|
128
129
|
* Filtra por autor del mensaje. Acepta JID, LID o teléfono numérico; el string
|
|
129
|
-
* se normaliza
|
|
130
|
+
* se normaliza con la resolución interna del cliente y cache lazy. Un array produce match OR.
|
|
130
131
|
* Filters by message author. Accepts JID, LID or numeric phone; the string is
|
|
131
|
-
* normalized
|
|
132
|
+
* normalized through the client's internal resolution with lazy cache. An array yields OR matching.
|
|
132
133
|
*
|
|
133
134
|
* @param source - Identificador(es) permitidos o predicate sobre `msg.from` / Allowed identifier(s) or predicate on `msg.from`
|
|
134
135
|
*/
|
|
@@ -146,7 +147,7 @@ function from(source) {
|
|
|
146
147
|
if (resolved === null) {
|
|
147
148
|
resolved = new Set();
|
|
148
149
|
for (const raw of list) {
|
|
149
|
-
const r = await wa.
|
|
150
|
+
const r = await (0, internal_1.internals)(wa).resolve_jid(raw);
|
|
150
151
|
if (r) {
|
|
151
152
|
resolved.add(r);
|
|
152
153
|
}
|
|
@@ -259,4 +260,3 @@ function command(pattern) {
|
|
|
259
260
|
});
|
|
260
261
|
};
|
|
261
262
|
}
|
|
262
|
-
//# sourceMappingURL=decorators.js.map
|
|
@@ -18,4 +18,3 @@ Object.defineProperty(exports, "delay", { enumerable: true, get: function () { r
|
|
|
18
18
|
Object.defineProperty(exports, "pipe", { enumerable: true, get: function () { return decorators_1.pipe; } });
|
|
19
19
|
Object.defineProperty(exports, "pair", { enumerable: true, get: function () { return decorators_1.pair; } });
|
|
20
20
|
Object.defineProperty(exports, "Bot", { enumerable: true, get: function () { return decorators_1.Bot; } });
|
|
21
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -16,6 +16,7 @@ export declare class Chat {
|
|
|
16
16
|
archived?: boolean | null;
|
|
17
17
|
pinned?: number | null;
|
|
18
18
|
mute_end_time?: number | null;
|
|
19
|
+
unread_count?: number | null;
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* @internal Documento crudo del chat. `id` es el identificador del engine (JID, LID o
|
|
@@ -29,6 +30,7 @@ export declare class Chat {
|
|
|
29
30
|
archived?: boolean | null;
|
|
30
31
|
pinned?: number | null;
|
|
31
32
|
mute_end_time?: number | null;
|
|
33
|
+
unread_count?: number | null;
|
|
32
34
|
});
|
|
33
35
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
34
36
|
get id(): string;
|
|
@@ -40,6 +42,8 @@ export declare class Chat {
|
|
|
40
42
|
get archived(): boolean;
|
|
41
43
|
/** true si el chat está fijado. / true when the chat is pinned. */
|
|
42
44
|
get pinned(): boolean;
|
|
45
|
+
/** Mensajes sin leer del chat. / Chat's unread messages. */
|
|
46
|
+
get count(): number;
|
|
43
47
|
/** Fecha ISO UTC hasta la que el chat está silenciado, o null. / ISO UTC date until the chat stays muted, or null. */
|
|
44
48
|
get muted(): string | null;
|
|
45
49
|
}
|
|
@@ -56,6 +60,7 @@ export declare function chat(wa: WhatsApp): {
|
|
|
56
60
|
archived?: boolean | null;
|
|
57
61
|
pinned?: number | null;
|
|
58
62
|
mute_end_time?: number | null;
|
|
63
|
+
unread_count?: number | null;
|
|
59
64
|
}): {
|
|
60
65
|
/**
|
|
61
66
|
* Participantes del chat: los integrantes en grupos, el contacto y yo en 1:1.
|
|
@@ -66,6 +71,15 @@ export declare function chat(wa: WhatsApp): {
|
|
|
66
71
|
* @returns Página de contactos / Contact page
|
|
67
72
|
*/
|
|
68
73
|
members(offset?: number, limit?: number): Promise<InstanceType<typeof wa.Contact>[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Descripción del chat: el asunto del grupo o, en un 1:1, la bio del contacto.
|
|
76
|
+
* Es asíncrono porque ninguno de los dos vive en el documento del chat.
|
|
77
|
+
* Chat description: the group's subject or, on a 1:1, the contact's bio. It is async
|
|
78
|
+
* because neither of them lives in the chat document.
|
|
79
|
+
*
|
|
80
|
+
* @returns Descripción, o cadena vacía si no hay / Description, or an empty string when absent
|
|
81
|
+
*/
|
|
82
|
+
content(): Promise<string>;
|
|
69
83
|
/**
|
|
70
84
|
* Mensajes del chat paginados desde el más reciente.
|
|
71
85
|
* Chat messages paginated from the most recent one.
|
|
@@ -146,6 +160,7 @@ export declare function chat(wa: WhatsApp): {
|
|
|
146
160
|
archived?: boolean | null;
|
|
147
161
|
pinned?: number | null;
|
|
148
162
|
mute_end_time?: number | null;
|
|
163
|
+
unread_count?: number | null;
|
|
149
164
|
};
|
|
150
165
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
151
166
|
get id(): string;
|
|
@@ -157,6 +172,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
157
172
|
get archived(): boolean;
|
|
158
173
|
/** true si el chat está fijado. / true when the chat is pinned. */
|
|
159
174
|
get pinned(): boolean;
|
|
175
|
+
/** Mensajes sin leer del chat. / Chat's unread messages. */
|
|
176
|
+
get count(): number;
|
|
160
177
|
/** Fecha ISO UTC hasta la que el chat está silenciado, o null. / ISO UTC date until the chat stays muted, or null. */
|
|
161
178
|
get muted(): string | null;
|
|
162
179
|
};
|
|
@@ -179,6 +196,15 @@ export declare function chat(wa: WhatsApp): {
|
|
|
179
196
|
* @returns Página de contactos / Contact page
|
|
180
197
|
*/
|
|
181
198
|
members(offset?: number, limit?: number): Promise<InstanceType<typeof wa.Contact>[]>;
|
|
199
|
+
/**
|
|
200
|
+
* Descripción del chat: el asunto del grupo o, en un 1:1, la bio del contacto.
|
|
201
|
+
* Es asíncrono porque ninguno de los dos vive en el documento del chat.
|
|
202
|
+
* Chat description: the group's subject or, on a 1:1, the contact's bio. It is async
|
|
203
|
+
* because neither of them lives in the chat document.
|
|
204
|
+
*
|
|
205
|
+
* @returns Descripción, o cadena vacía si no hay / Description, or an empty string when absent
|
|
206
|
+
*/
|
|
207
|
+
content(): Promise<string>;
|
|
182
208
|
/**
|
|
183
209
|
* Mensajes del chat paginados desde el más reciente.
|
|
184
210
|
* Chat messages paginated from the most recent one.
|
|
@@ -259,6 +285,7 @@ export declare function chat(wa: WhatsApp): {
|
|
|
259
285
|
archived?: boolean | null;
|
|
260
286
|
pinned?: number | null;
|
|
261
287
|
mute_end_time?: number | null;
|
|
288
|
+
unread_count?: number | null;
|
|
262
289
|
};
|
|
263
290
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
264
291
|
get id(): string;
|
|
@@ -270,6 +297,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
270
297
|
get archived(): boolean;
|
|
271
298
|
/** true si el chat está fijado. / true when the chat is pinned. */
|
|
272
299
|
get pinned(): boolean;
|
|
300
|
+
/** Mensajes sin leer del chat. / Chat's unread messages. */
|
|
301
|
+
get count(): number;
|
|
273
302
|
/** Fecha ISO UTC hasta la que el chat está silenciado, o null. / ISO UTC date until the chat stays muted, or null. */
|
|
274
303
|
get muted(): string | null;
|
|
275
304
|
} | null>;
|
|
@@ -291,6 +320,15 @@ export declare function chat(wa: WhatsApp): {
|
|
|
291
320
|
* @returns Página de contactos / Contact page
|
|
292
321
|
*/
|
|
293
322
|
members(offset?: number, limit?: number): Promise<InstanceType<typeof wa.Contact>[]>;
|
|
323
|
+
/**
|
|
324
|
+
* Descripción del chat: el asunto del grupo o, en un 1:1, la bio del contacto.
|
|
325
|
+
* Es asíncrono porque ninguno de los dos vive en el documento del chat.
|
|
326
|
+
* Chat description: the group's subject or, on a 1:1, the contact's bio. It is async
|
|
327
|
+
* because neither of them lives in the chat document.
|
|
328
|
+
*
|
|
329
|
+
* @returns Descripción, o cadena vacía si no hay / Description, or an empty string when absent
|
|
330
|
+
*/
|
|
331
|
+
content(): Promise<string>;
|
|
294
332
|
/**
|
|
295
333
|
* Mensajes del chat paginados desde el más reciente.
|
|
296
334
|
* Chat messages paginated from the most recent one.
|
|
@@ -371,6 +409,7 @@ export declare function chat(wa: WhatsApp): {
|
|
|
371
409
|
archived?: boolean | null;
|
|
372
410
|
pinned?: number | null;
|
|
373
411
|
mute_end_time?: number | null;
|
|
412
|
+
unread_count?: number | null;
|
|
374
413
|
};
|
|
375
414
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
376
415
|
get id(): string;
|
|
@@ -382,6 +421,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
382
421
|
get archived(): boolean;
|
|
383
422
|
/** true si el chat está fijado. / true when the chat is pinned. */
|
|
384
423
|
get pinned(): boolean;
|
|
424
|
+
/** Mensajes sin leer del chat. / Chat's unread messages. */
|
|
425
|
+
get count(): number;
|
|
385
426
|
/** Fecha ISO UTC hasta la que el chat está silenciado, o null. / ISO UTC date until the chat stays muted, or null. */
|
|
386
427
|
get muted(): string | null;
|
|
387
428
|
}[]>;
|
|
@@ -44,6 +44,10 @@ class Chat {
|
|
|
44
44
|
get pinned() {
|
|
45
45
|
return this._raw.pinned != null;
|
|
46
46
|
}
|
|
47
|
+
/** Mensajes sin leer del chat. / Chat's unread messages. */
|
|
48
|
+
get count() {
|
|
49
|
+
return this._raw.unread_count ?? 0;
|
|
50
|
+
}
|
|
47
51
|
/** Fecha ISO UTC hasta la que el chat está silenciado, o null. / ISO UTC date until the chat stays muted, or null. */
|
|
48
52
|
get muted() {
|
|
49
53
|
const end = this._raw.mute_end_time;
|
|
@@ -95,14 +99,14 @@ function chat(wa) {
|
|
|
95
99
|
* Participantes del grupo memoizados 15s, para no repetir `groupMetadata` en cada página.
|
|
96
100
|
* Group participants memoized for 15s, avoiding a `groupMetadata` round-trip per page.
|
|
97
101
|
*/
|
|
98
|
-
const
|
|
99
|
-
function
|
|
100
|
-
if (!
|
|
102
|
+
const groups_cache = new Map();
|
|
103
|
+
function group_meta(jid) {
|
|
104
|
+
if (!groups_cache.has(jid)) {
|
|
101
105
|
const socket = (0, internal_1.internals)(wa).socket;
|
|
102
|
-
|
|
103
|
-
setTimeout(() =>
|
|
106
|
+
groups_cache.set(jid, socket ? socket.groupMetadata(jid).catch(() => ({ participants: [] })) : Promise.resolve({ participants: [] }));
|
|
107
|
+
setTimeout(() => groups_cache.delete(jid), 15_000);
|
|
104
108
|
}
|
|
105
|
-
return
|
|
109
|
+
return groups_cache.get(jid);
|
|
106
110
|
}
|
|
107
111
|
/**
|
|
108
112
|
* Contacto desde el engine, o ficha mínima local cuando no está persistido (sin red).
|
|
@@ -123,10 +127,24 @@ function chat(wa) {
|
|
|
123
127
|
*/
|
|
124
128
|
async members(offset = 0, limit = 50) {
|
|
125
129
|
const ids = this.type === 'group'
|
|
126
|
-
? (await
|
|
130
|
+
? (await group_meta(this._raw.id)).participants.map((participant) => participant.id)
|
|
127
131
|
: [this._raw.id, (0, internal_1.internals)(wa).socket?.user?.id].filter((id) => Boolean(id));
|
|
128
132
|
return Promise.all(ids.slice(offset, offset + limit).map(load_contact));
|
|
129
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Descripción del chat: el asunto del grupo o, en un 1:1, la bio del contacto.
|
|
136
|
+
* Es asíncrono porque ninguno de los dos vive en el documento del chat.
|
|
137
|
+
* Chat description: the group's subject or, on a 1:1, the contact's bio. It is async
|
|
138
|
+
* because neither of them lives in the chat document.
|
|
139
|
+
*
|
|
140
|
+
* @returns Descripción, o cadena vacía si no hay / Description, or an empty string when absent
|
|
141
|
+
*/
|
|
142
|
+
async content() {
|
|
143
|
+
if (this.type === 'group') {
|
|
144
|
+
return (await group_meta(this._raw.id)).desc ?? '';
|
|
145
|
+
}
|
|
146
|
+
return (0, store_1.deserialize)(await wa.engine.get(`/contact/${this._raw.id}`))?.status ?? '';
|
|
147
|
+
}
|
|
130
148
|
/**
|
|
131
149
|
* Mensajes del chat paginados desde el más reciente.
|
|
132
150
|
* Chat messages paginated from the most recent one.
|
|
@@ -242,6 +260,8 @@ function chat(wa) {
|
|
|
242
260
|
const socket = (0, internal_1.internals)(wa).socket;
|
|
243
261
|
if (socket) {
|
|
244
262
|
await socket.chatModify({ markRead: true, lastMessages: await last_messages(this._raw.id) }, this._raw.id);
|
|
263
|
+
this._raw.unread_count = 0;
|
|
264
|
+
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw));
|
|
245
265
|
ok = true;
|
|
246
266
|
}
|
|
247
267
|
return ok;
|
|
@@ -323,4 +343,3 @@ function chat(wa) {
|
|
|
323
343
|
}
|
|
324
344
|
};
|
|
325
345
|
}
|
|
326
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -103,6 +103,10 @@ export declare class Message {
|
|
|
103
103
|
get status(): (typeof STATUS)[number];
|
|
104
104
|
/** true si el mensaje fue visto. / true when the message was seen. */
|
|
105
105
|
get read(): boolean;
|
|
106
|
+
/** Motivo del rechazo cuando `status` es `error` (`restricted`, `invalid-session`, o el código crudo); null en cualquier otro caso. / Rejection reason when `status` is `error` (`restricted`, `invalid-session`, or the raw code); null otherwise. */
|
|
107
|
+
get reason(): string | null;
|
|
108
|
+
/** Nombre del negocio verificado que firma el mensaje, o null. / Verified business name signing the message, or null. */
|
|
109
|
+
get business(): string | null;
|
|
106
110
|
/** true si está destacado. / true when starred. */
|
|
107
111
|
get starred(): boolean;
|
|
108
112
|
/** true si fue reenviado. / true when forwarded. */
|
|
@@ -451,6 +455,12 @@ export declare class Sticker extends Message {
|
|
|
451
455
|
* Document message; the actual MIME lives in the base `mime`.
|
|
452
456
|
*/
|
|
453
457
|
export declare class Document extends Message {
|
|
458
|
+
/** @internal */
|
|
459
|
+
private get _media();
|
|
460
|
+
/** Nombre del archivo. / File name. */
|
|
461
|
+
get name(): string;
|
|
462
|
+
/** Número de páginas (PDF); 0 cuando no aplica. / Page count (PDF); 0 when not applicable. */
|
|
463
|
+
get pages(): number;
|
|
454
464
|
/** Peso en bytes. / Size in bytes. */
|
|
455
465
|
get size(): number;
|
|
456
466
|
content(): Promise<Buffer>;
|
|
@@ -18,6 +18,16 @@ const chat_1 = require("../../lib/chat");
|
|
|
18
18
|
const store_1 = require("../../lib/store");
|
|
19
19
|
/** Estados legibles indexados por el status numérico de baileys. / Readable states indexed by the baileys numeric status. */
|
|
20
20
|
const STATUS = ['error', 'pending', 'sent', 'delivered', 'read', 'played'];
|
|
21
|
+
/**
|
|
22
|
+
* Motivos legibles de los códigos con los que el servidor rechaza un mensaje. `restricted`
|
|
23
|
+
* es la cuenta limitada por WhatsApp: puede seguir chats existentes pero no abrir nuevos.
|
|
24
|
+
* Readable reasons for the codes the server rejects a message with. `restricted` is an
|
|
25
|
+
* account limited by WhatsApp: it can continue existing chats but not open new ones.
|
|
26
|
+
*/
|
|
27
|
+
const REASON = {
|
|
28
|
+
463: 'restricted',
|
|
29
|
+
479: 'invalid-session',
|
|
30
|
+
};
|
|
21
31
|
const MESSAGE_TYPE_MAP = {
|
|
22
32
|
conversation: 'text',
|
|
23
33
|
extendedTextMessage: 'text',
|
|
@@ -79,11 +89,11 @@ async function send(wa, cid, content, binary, extra = {}, doc_overrides) {
|
|
|
79
89
|
const quoted = extra.mid
|
|
80
90
|
? ((0, store_1.deserialize)(await wa.engine.get(`/chat/${jid}/message/${extra.mid}`))?.raw ?? undefined)
|
|
81
91
|
: undefined;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
});
|
|
92
|
+
// La cita viaja en las opciones del socket, no en el contenido: dentro del contenido
|
|
93
|
+
// baileys la ignora y el mensaje sale sin `contextInfo`.
|
|
94
|
+
// The quote travels in the socket options, not in the content: inside the content
|
|
95
|
+
// baileys ignores it and the message goes out without `contextInfo`.
|
|
96
|
+
const raw = await socket.sendMessage(jid, { ...content, ...(extra.once && { viewOnce: true }) }, { ...(quoted && { quoted }) });
|
|
87
97
|
const sent_id = raw?.key?.id;
|
|
88
98
|
if (raw && sent_id) {
|
|
89
99
|
const instance = message(wa, raw);
|
|
@@ -92,21 +102,56 @@ async function send(wa, cid, content, binary, extra = {}, doc_overrides) {
|
|
|
92
102
|
}
|
|
93
103
|
await wa.engine.set(`/chat/${jid}/message/${sent_id}`, (0, store_1.serialize)(instance._raw), instance._raw.created_at);
|
|
94
104
|
if (binary) {
|
|
95
|
-
await wa
|
|
105
|
+
await write_content(wa, `/chat/${jid}/message/${sent_id}/content`, binary);
|
|
96
106
|
}
|
|
97
107
|
result = instance;
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
return result;
|
|
101
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Binario persistido de un documento: primero el crudo del engine y, si el driver no soporta
|
|
114
|
+
* binarios o el dato viene de una sesión anterior, el documento JSON con base64.
|
|
115
|
+
* A document's persisted binary: the engine's raw one first and, when the driver lacks binary
|
|
116
|
+
* support or the data comes from an older session, the base64 JSON document.
|
|
117
|
+
*
|
|
118
|
+
* @param wa - Cliente dueño / Owner client
|
|
119
|
+
* @param path - Ruta del contenido / Content path
|
|
120
|
+
* @returns Binario o null / Binary or null
|
|
121
|
+
*/
|
|
122
|
+
async function read_content(wa, path) {
|
|
123
|
+
const raw = await wa.engine.get_buffer?.(path);
|
|
124
|
+
if (raw?.length) {
|
|
125
|
+
return raw;
|
|
126
|
+
}
|
|
127
|
+
const legacy = (0, store_1.deserialize)(await wa.engine.get(path));
|
|
128
|
+
return legacy?.data ? Buffer.from(legacy.data, 'base64') : null;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Persiste el binario de un documento: crudo cuando el driver lo soporta, JSON con base64
|
|
132
|
+
* en caso contrario.
|
|
133
|
+
* Persists a document's binary: raw when the driver supports it, base64 JSON otherwise.
|
|
134
|
+
*
|
|
135
|
+
* @param wa - Cliente dueño / Owner client
|
|
136
|
+
* @param path - Ruta del contenido / Content path
|
|
137
|
+
* @param data - Binario a guardar / Binary to store
|
|
138
|
+
*/
|
|
139
|
+
async function write_content(wa, path, data) {
|
|
140
|
+
if (wa.engine.set_buffer) {
|
|
141
|
+
await wa.engine.set_buffer(path, data);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
await wa.engine.set(path, (0, store_1.serialize)({ data: data.toString('base64') }));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
102
147
|
/**
|
|
103
148
|
* Stream del binario del mensaje: cache del engine o descarga de baileys.
|
|
104
149
|
* Message binary stream: engine cache or baileys download.
|
|
105
150
|
*/
|
|
106
151
|
async function media_stream(wa, doc) {
|
|
107
|
-
const cached = (
|
|
108
|
-
if (cached
|
|
109
|
-
return node_stream_1.Readable.from(
|
|
152
|
+
const cached = await read_content(wa, `/chat/${doc.cid}/message/${doc.id}/content`);
|
|
153
|
+
if (cached) {
|
|
154
|
+
return node_stream_1.Readable.from(cached);
|
|
110
155
|
}
|
|
111
156
|
const socket = (0, internal_1.internals)(wa).socket;
|
|
112
157
|
if (socket) {
|
|
@@ -196,6 +241,17 @@ class Message {
|
|
|
196
241
|
get read() {
|
|
197
242
|
return this._raw.status >= 4;
|
|
198
243
|
}
|
|
244
|
+
/** Motivo del rechazo cuando `status` es `error` (`restricted`, `invalid-session`, o el código crudo); null en cualquier otro caso. / Rejection reason when `status` is `error` (`restricted`, `invalid-session`, or the raw code); null otherwise. */
|
|
245
|
+
get reason() {
|
|
246
|
+
const code = this._raw.raw.messageStubParameters?.[0];
|
|
247
|
+
if (this._raw.status === 0 && code)
|
|
248
|
+
return REASON[code] ?? code;
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
/** Nombre del negocio verificado que firma el mensaje, o null. / Verified business name signing the message, or null. */
|
|
252
|
+
get business() {
|
|
253
|
+
return this._raw.raw.verifiedBizName ?? null;
|
|
254
|
+
}
|
|
199
255
|
/** true si está destacado. / true when starred. */
|
|
200
256
|
get starred() {
|
|
201
257
|
return this._raw.starred;
|
|
@@ -259,8 +315,7 @@ class Message {
|
|
|
259
315
|
* @returns Buffer del contenido / Content buffer
|
|
260
316
|
*/
|
|
261
317
|
async content() {
|
|
262
|
-
|
|
263
|
-
return cached?.data ? Buffer.from(cached.data, 'base64') : Buffer.alloc(0);
|
|
318
|
+
return (await read_content(this._wa, `/chat/${this._raw.cid}/message/${this._raw.id}/content`)) ?? Buffer.alloc(0);
|
|
264
319
|
}
|
|
265
320
|
/**
|
|
266
321
|
* Stream del contenido; para media descarga de baileys si el cache falta.
|
|
@@ -789,10 +844,21 @@ exports.Sticker = Sticker;
|
|
|
789
844
|
* Document message; the actual MIME lives in the base `mime`.
|
|
790
845
|
*/
|
|
791
846
|
class Document extends Message {
|
|
847
|
+
/** @internal */
|
|
848
|
+
get _media() {
|
|
849
|
+
return unwrap(this._raw.raw.message ?? {}).documentMessage;
|
|
850
|
+
}
|
|
851
|
+
/** Nombre del archivo. / File name. */
|
|
852
|
+
get name() {
|
|
853
|
+
return this._media?.fileName ?? '';
|
|
854
|
+
}
|
|
855
|
+
/** Número de páginas (PDF); 0 cuando no aplica. / Page count (PDF); 0 when not applicable. */
|
|
856
|
+
get pages() {
|
|
857
|
+
return this._media?.pageCount ?? 0;
|
|
858
|
+
}
|
|
792
859
|
/** Peso en bytes. / Size in bytes. */
|
|
793
860
|
get size() {
|
|
794
|
-
|
|
795
|
-
return to_number(media?.fileLength);
|
|
861
|
+
return to_number(this._media?.fileLength);
|
|
796
862
|
}
|
|
797
863
|
async content() {
|
|
798
864
|
return drain(await this.stream());
|
|
@@ -1079,4 +1145,3 @@ function message(wa, raw) {
|
|
|
1079
1145
|
};
|
|
1080
1146
|
return new (types[doc.type] ?? Message)(wa, doc);
|
|
1081
1147
|
}
|
|
1082
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -42,6 +42,20 @@ export interface Engine {
|
|
|
42
42
|
count(path: string): Promise<number>;
|
|
43
43
|
/** Vacía completamente el almacén. / Clears the entire store. */
|
|
44
44
|
clear(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Lee un binario por path. Opcional: un driver que no lo implemente sigue siendo válido y
|
|
47
|
+
* la librería cae al documento serializado.
|
|
48
|
+
* Reads a binary by path. Optional: a driver that does not implement it stays valid and the
|
|
49
|
+
* library falls back to the serialized document.
|
|
50
|
+
*/
|
|
51
|
+
get_buffer?(path: string): Promise<Buffer | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Escribe un binario sin pasar por JSON ni base64 (un 33% menos de peso y sin parseo para
|
|
54
|
+
* leerlo). Opcional, igual que `get_buffer`.
|
|
55
|
+
* Writes a binary without JSON nor base64 (33% less weight and no parsing to read it back).
|
|
56
|
+
* Optional, just like `get_buffer`.
|
|
57
|
+
*/
|
|
58
|
+
set_buffer?(path: string, data: Buffer, score?: number): Promise<void>;
|
|
45
59
|
}
|
|
46
60
|
export { FileSystemEngine } from '../../../lib/store/engine/lib/file_system';
|
|
47
61
|
export { RedisEngine, type RedisClient } from '../../../lib/store/engine/lib/redis';
|
|
@@ -15,4 +15,3 @@ var s3_1 = require("../../../lib/store/engine/lib/s3");
|
|
|
15
15
|
Object.defineProperty(exports, "S3Engine", { enumerable: true, get: function () { return s3_1.S3Engine; } });
|
|
16
16
|
var sqlite_1 = require("../../../lib/store/engine/lib/sqlite");
|
|
17
17
|
Object.defineProperty(exports, "SQLiteEngine", { enumerable: true, get: function () { return sqlite_1.SQLiteEngine; } });
|
|
18
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -78,6 +78,16 @@ export declare class FileSystemEngine implements Engine {
|
|
|
78
78
|
* Counts direct children with a valid document.
|
|
79
79
|
*/
|
|
80
80
|
count(path: string): Promise<number>;
|
|
81
|
+
/**
|
|
82
|
+
* Lee el binario del documento, o null si no existe.
|
|
83
|
+
* Reads the document binary, or null when missing.
|
|
84
|
+
*/
|
|
85
|
+
get_buffer(path: string): Promise<Buffer | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Escribe el binario del documento como archivo crudo, sin JSON ni base64.
|
|
88
|
+
* Writes the document binary as a raw file, with no JSON nor base64.
|
|
89
|
+
*/
|
|
90
|
+
set_buffer(path: string, data: Buffer, score?: number): Promise<void>;
|
|
81
91
|
/**
|
|
82
92
|
* Vacía completamente el almacén.
|
|
83
93
|
* Clears the entire store.
|
|
@@ -13,6 +13,8 @@ const lib_1 = require("../../../../../lib/store/engine/lib");
|
|
|
13
13
|
const INDEX_FILE = 'index.json';
|
|
14
14
|
/** Índice de orden persistido junto a los hijos del directorio. / Ordering index persisted next to the directory children. */
|
|
15
15
|
const ORDER_FILE = '.order';
|
|
16
|
+
/** Binario del documento, guardado crudo junto a su JSON. / Document binary, stored raw next to its JSON. */
|
|
17
|
+
const BINARY_FILE = 'content.bin';
|
|
16
18
|
/**
|
|
17
19
|
* Driver de persistencia en sistema de archivos.
|
|
18
20
|
* Cada documento se almacena como `<base>/<path>/index.json` de modo que un recurso pueda
|
|
@@ -161,6 +163,31 @@ class FileSystemEngine {
|
|
|
161
163
|
async count(path) {
|
|
162
164
|
return (await this._index(path)).size;
|
|
163
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Lee el binario del documento, o null si no existe.
|
|
168
|
+
* Reads the document binary, or null when missing.
|
|
169
|
+
*/
|
|
170
|
+
async get_buffer(path) {
|
|
171
|
+
return (0, promises_1.readFile)((0, node_path_1.join)(this._dir(path), BINARY_FILE)).catch(() => null);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Escribe el binario del documento como archivo crudo, sin JSON ni base64.
|
|
175
|
+
* Writes the document binary as a raw file, with no JSON nor base64.
|
|
176
|
+
*/
|
|
177
|
+
async set_buffer(path, data, score) {
|
|
178
|
+
const dir = this._dir(path);
|
|
179
|
+
await (0, promises_1.mkdir)(dir, { recursive: true });
|
|
180
|
+
const file = (0, node_path_1.join)(dir, BINARY_FILE);
|
|
181
|
+
const tmp = `${file}.${(0, node_crypto_1.randomBytes)(6).toString('hex')}.tmp`;
|
|
182
|
+
await (0, promises_1.writeFile)(tmp, data);
|
|
183
|
+
await (0, promises_1.rename)(tmp, file);
|
|
184
|
+
const when = score ?? Date.now();
|
|
185
|
+
if (score !== undefined) {
|
|
186
|
+
await (0, promises_1.utimes)(file, new Date(score), new Date(score)).catch(() => { });
|
|
187
|
+
}
|
|
188
|
+
const { parent, name } = (0, lib_1.split_path)(path);
|
|
189
|
+
this._indexes.get(parent)?.set(name, when);
|
|
190
|
+
}
|
|
164
191
|
/**
|
|
165
192
|
* Vacía completamente el almacén.
|
|
166
193
|
* Clears the entire store.
|
|
@@ -176,4 +203,3 @@ class FileSystemEngine {
|
|
|
176
203
|
}
|
|
177
204
|
}
|
|
178
205
|
exports.FileSystemEngine = FileSystemEngine;
|
|
179
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -13,18 +13,20 @@ import type { Engine } from '../../../../../lib/store/engine';
|
|
|
13
13
|
export interface RedisClient {
|
|
14
14
|
get(key: string): Promise<string | null>;
|
|
15
15
|
set(key: string, value: string): Promise<unknown>;
|
|
16
|
-
del(keys:
|
|
16
|
+
del(...keys: unknown[]): Promise<unknown>;
|
|
17
17
|
mget(keys: string[]): Promise<(string | null)[]>;
|
|
18
18
|
scan(cursor: number | string, ...args: unknown[]): Promise<[string, string[]]>;
|
|
19
19
|
zadd(key: string, score: number, member: string): Promise<unknown>;
|
|
20
|
-
zrem(
|
|
20
|
+
zrem(...args: unknown[]): Promise<unknown>;
|
|
21
21
|
zrevrange(key: string, start: number, stop: number): Promise<string[]>;
|
|
22
22
|
zcard(key: string): Promise<number>;
|
|
23
|
+
getBuffer?(...args: unknown[]): Promise<Buffer | null>;
|
|
24
|
+
setBuffer?(...args: unknown[]): Promise<unknown>;
|
|
23
25
|
pipeline?(): {
|
|
24
26
|
set(key: string, value: string): unknown;
|
|
25
|
-
del(keys:
|
|
27
|
+
del(...keys: unknown[]): unknown;
|
|
26
28
|
zadd(key: string, score: number, member: string): unknown;
|
|
27
|
-
zrem(
|
|
29
|
+
zrem(...args: unknown[]): unknown;
|
|
28
30
|
exec(): Promise<unknown>;
|
|
29
31
|
};
|
|
30
32
|
}
|
|
@@ -82,6 +84,18 @@ export declare class RedisEngine implements Engine {
|
|
|
82
84
|
* Counts direct children in O(1) via ZCARD.
|
|
83
85
|
*/
|
|
84
86
|
count(path: string): Promise<number>;
|
|
87
|
+
/**
|
|
88
|
+
* Lee el binario del documento. Requiere un cliente con soporte de buffers (ioredis lo
|
|
89
|
+
* trae con `getBuffer`); sin él la librería cae al documento serializado.
|
|
90
|
+
* Reads the document binary. Requires a buffer-capable client (ioredis ships `getBuffer`);
|
|
91
|
+
* without it the library falls back to the serialized document.
|
|
92
|
+
*/
|
|
93
|
+
get_buffer(path: string): Promise<Buffer | null>;
|
|
94
|
+
/**
|
|
95
|
+
* Escribe el binario del documento en su propia key, sin JSON ni base64.
|
|
96
|
+
* Writes the document binary in its own key, with no JSON nor base64.
|
|
97
|
+
*/
|
|
98
|
+
set_buffer(path: string, data: Buffer, score?: number): Promise<void>;
|
|
85
99
|
/**
|
|
86
100
|
* Vacía todo el prefix del cliente.
|
|
87
101
|
* Clears the entire client prefix.
|
|
@@ -78,12 +78,12 @@ class RedisEngine {
|
|
|
78
78
|
const full = (0, lib_1.normalize_path)(path);
|
|
79
79
|
const pipeline = this._client.pipeline?.();
|
|
80
80
|
if (pipeline) {
|
|
81
|
-
pipeline.del(this._doc_key(full));
|
|
81
|
+
pipeline.del([this._doc_key(full), `${this._doc_key(full)}:bin`]);
|
|
82
82
|
pipeline.zrem(this._idx_key(parent), full);
|
|
83
83
|
await pipeline.exec();
|
|
84
84
|
}
|
|
85
85
|
else {
|
|
86
|
-
await this._client.del(this._doc_key(full));
|
|
86
|
+
await this._client.del([this._doc_key(full), `${this._doc_key(full)}:bin`]);
|
|
87
87
|
await this._client.zrem(this._idx_key(parent), full);
|
|
88
88
|
}
|
|
89
89
|
await Promise.all([
|
|
@@ -112,6 +112,25 @@ class RedisEngine {
|
|
|
112
112
|
async count(path) {
|
|
113
113
|
return this._client.zcard(this._idx_key(path));
|
|
114
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Lee el binario del documento. Requiere un cliente con soporte de buffers (ioredis lo
|
|
117
|
+
* trae con `getBuffer`); sin él la librería cae al documento serializado.
|
|
118
|
+
* Reads the document binary. Requires a buffer-capable client (ioredis ships `getBuffer`);
|
|
119
|
+
* without it the library falls back to the serialized document.
|
|
120
|
+
*/
|
|
121
|
+
async get_buffer(path) {
|
|
122
|
+
return (await this._client.getBuffer?.(`${this._doc_key(path)}:bin`)) ?? null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Escribe el binario del documento en su propia key, sin JSON ni base64.
|
|
126
|
+
* Writes the document binary in its own key, with no JSON nor base64.
|
|
127
|
+
*/
|
|
128
|
+
async set_buffer(path, data, score) {
|
|
129
|
+
const { parent } = (0, lib_1.split_path)(path);
|
|
130
|
+
const full = (0, lib_1.normalize_path)(path);
|
|
131
|
+
await this._client.setBuffer?.(`${this._doc_key(full)}:bin`, data);
|
|
132
|
+
await this._client.zadd(this._idx_key(parent), score ?? Date.now(), full);
|
|
133
|
+
}
|
|
115
134
|
/**
|
|
116
135
|
* Vacía todo el prefix del cliente.
|
|
117
136
|
* Clears the entire client prefix.
|
|
@@ -137,4 +156,3 @@ class RedisEngine {
|
|
|
137
156
|
}
|
|
138
157
|
}
|
|
139
158
|
exports.RedisEngine = RedisEngine;
|
|
140
|
-
//# sourceMappingURL=index.js.map
|