@arcaelas/whatsapp 6.1.2 → 6.2.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.
|
@@ -17,6 +17,8 @@ export declare class Chat {
|
|
|
17
17
|
pinned?: number | null;
|
|
18
18
|
mute_end_time?: number | null;
|
|
19
19
|
unread_count?: number | null;
|
|
20
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
21
|
+
activity?: number | null;
|
|
20
22
|
};
|
|
21
23
|
/**
|
|
22
24
|
* @internal Documento crudo del chat. `id` es el identificador del engine (JID, LID o
|
|
@@ -31,6 +33,8 @@ export declare class Chat {
|
|
|
31
33
|
pinned?: number | null;
|
|
32
34
|
mute_end_time?: number | null;
|
|
33
35
|
unread_count?: number | null;
|
|
36
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
37
|
+
activity?: number | null;
|
|
34
38
|
});
|
|
35
39
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
36
40
|
get id(): string;
|
|
@@ -61,6 +65,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
61
65
|
pinned?: number | null;
|
|
62
66
|
mute_end_time?: number | null;
|
|
63
67
|
unread_count?: number | null;
|
|
68
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
69
|
+
activity?: number | null;
|
|
64
70
|
}): {
|
|
65
71
|
/**
|
|
66
72
|
* Participantes del chat: los integrantes en grupos, el contacto y yo en 1:1.
|
|
@@ -161,6 +167,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
161
167
|
pinned?: number | null;
|
|
162
168
|
mute_end_time?: number | null;
|
|
163
169
|
unread_count?: number | null;
|
|
170
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
171
|
+
activity?: number | null;
|
|
164
172
|
};
|
|
165
173
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
166
174
|
get id(): string;
|
|
@@ -286,6 +294,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
286
294
|
pinned?: number | null;
|
|
287
295
|
mute_end_time?: number | null;
|
|
288
296
|
unread_count?: number | null;
|
|
297
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
298
|
+
activity?: number | null;
|
|
289
299
|
};
|
|
290
300
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
291
301
|
get id(): string;
|
|
@@ -410,6 +420,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
410
420
|
pinned?: number | null;
|
|
411
421
|
mute_end_time?: number | null;
|
|
412
422
|
unread_count?: number | null;
|
|
423
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
424
|
+
activity?: number | null;
|
|
413
425
|
};
|
|
414
426
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
415
427
|
get id(): string;
|
|
@@ -68,6 +68,16 @@ function chat(wa) {
|
|
|
68
68
|
* Último mensaje del chat en el formato que exige `chatModify`.
|
|
69
69
|
* The chat's last message in the shape `chatModify` requires.
|
|
70
70
|
*/
|
|
71
|
+
/**
|
|
72
|
+
* Actividad del chat según su último mensaje: mantiene la posición en la lista cuando se
|
|
73
|
+
* reescribe el documento por fijar, archivar, silenciar o marcar leído.
|
|
74
|
+
* Chat activity from its last message: keeps its position in the list when the document is
|
|
75
|
+
* rewritten by pinning, archiving, muting or marking as read.
|
|
76
|
+
*/
|
|
77
|
+
async function activity_of(cid) {
|
|
78
|
+
const [raw] = await wa.engine.list(`/chat/${cid}/message`, 0, 1);
|
|
79
|
+
return (0, store_1.deserialize)(raw ?? null)?.created_at ?? 0;
|
|
80
|
+
}
|
|
71
81
|
async function last_messages(cid) {
|
|
72
82
|
const [raw] = await wa.engine.list(`/chat/${cid}/message`, 0, 1);
|
|
73
83
|
const parsed = (0, store_1.deserialize)(raw ?? null);
|
|
@@ -201,7 +211,7 @@ function chat(wa) {
|
|
|
201
211
|
if (socket) {
|
|
202
212
|
await socket.chatModify({ archive: value, lastMessages: await last_messages(this._raw.id) }, this._raw.id);
|
|
203
213
|
this._raw.archived = value;
|
|
204
|
-
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw));
|
|
214
|
+
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
205
215
|
ok = true;
|
|
206
216
|
}
|
|
207
217
|
return ok;
|
|
@@ -223,7 +233,7 @@ function chat(wa) {
|
|
|
223
233
|
if (allowed) {
|
|
224
234
|
await socket.chatModify({ pin: value }, this._raw.id);
|
|
225
235
|
this._raw.pinned = value ? Date.now() : null;
|
|
226
|
-
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw));
|
|
236
|
+
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
227
237
|
ok = true;
|
|
228
238
|
}
|
|
229
239
|
}
|
|
@@ -244,7 +254,7 @@ function chat(wa) {
|
|
|
244
254
|
const muted = end > Date.now();
|
|
245
255
|
await socket.chatModify({ mute: muted ? end : null }, this._raw.id);
|
|
246
256
|
this._raw.mute_end_time = muted ? end : null;
|
|
247
|
-
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw));
|
|
257
|
+
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
248
258
|
ok = true;
|
|
249
259
|
}
|
|
250
260
|
return ok;
|
|
@@ -261,7 +271,7 @@ function chat(wa) {
|
|
|
261
271
|
if (socket) {
|
|
262
272
|
await socket.chatModify({ markRead: true, lastMessages: await last_messages(this._raw.id) }, this._raw.id);
|
|
263
273
|
this._raw.unread_count = 0;
|
|
264
|
-
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw));
|
|
274
|
+
await wa.engine.set(`/chat/${this._raw.id}`, (0, store_1.serialize)(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
265
275
|
ok = true;
|
|
266
276
|
}
|
|
267
277
|
return ok;
|
|
@@ -595,10 +595,16 @@ class WhatsApp {
|
|
|
595
595
|
if (doc.lid) {
|
|
596
596
|
await this.engine.set(`/lid/${doc.lid}`, (0, store_1.serialize)(doc.id));
|
|
597
597
|
}
|
|
598
|
-
|
|
598
|
+
// Una ficha que existía vacía y ahora tiene nombre es un cambio que el consumidor
|
|
599
|
+
// necesita: sin avisar, quien memorice el contacto sigue mostrando el número.
|
|
600
|
+
// A card that existed empty and now has a name is a change the consumer needs: without
|
|
601
|
+
// notifying, whoever memoized the contact keeps showing the bare number.
|
|
602
|
+
const changed = current && ['lid', 'name', 'notify', 'verified_name', 'img_url', 'status'].some((key) => current[key] !== doc[key]);
|
|
603
|
+
if (!current || changed) {
|
|
599
604
|
const person = new this.Contact(doc);
|
|
600
605
|
const cached_chat = (0, store_1.deserialize)(await this.engine.get(`/chat/${doc.id}`));
|
|
601
|
-
|
|
606
|
+
const chat = new this.Chat(cached_chat ?? { id: doc.id, name: person.name });
|
|
607
|
+
this.emit(current ? 'contact:updated' : 'contact:created', person, chat, this);
|
|
602
608
|
}
|
|
603
609
|
}
|
|
604
610
|
/** @internal */
|
|
@@ -650,6 +656,20 @@ class WhatsApp {
|
|
|
650
656
|
await this.engine.set(`/lid/${lid}`, (0, store_1.serialize)(pn));
|
|
651
657
|
await this.engine.set(`/lid/${pn}`, (0, store_1.serialize)(lid));
|
|
652
658
|
}
|
|
659
|
+
/**
|
|
660
|
+
* Actividad del chat según su último mensaje persistido. Es el respaldo para los
|
|
661
|
+
* documentos que se guardaron antes de que el chat llevara su propia marca.
|
|
662
|
+
* Chat activity from its last persisted message. It is the fallback for documents stored
|
|
663
|
+
* before the chat carried its own stamp.
|
|
664
|
+
*
|
|
665
|
+
* @param cid - Identificador del chat / Chat identifier
|
|
666
|
+
* @returns Epoch ms del último mensaje, o 0 si el chat no tiene ninguno / Last message epoch ms, or 0 when the chat has none
|
|
667
|
+
* @internal
|
|
668
|
+
*/
|
|
669
|
+
async #activity(cid) {
|
|
670
|
+
const [raw] = await this.engine.list(`/chat/${cid}/message`, 0, 1);
|
|
671
|
+
return (0, store_1.deserialize)(raw ?? null)?.created_at ?? 0;
|
|
672
|
+
}
|
|
653
673
|
/** @internal */
|
|
654
674
|
async #handle_chats_upsert(chats) {
|
|
655
675
|
for (const ch of chats) {
|
|
@@ -666,7 +686,13 @@ class WhatsApp {
|
|
|
666
686
|
if (ch.name) {
|
|
667
687
|
raw.name = ch.name;
|
|
668
688
|
}
|
|
669
|
-
|
|
689
|
+
// El sync trae la última actividad del chat; sin ella la lista quedaría ordenada
|
|
690
|
+
// por el momento en que se escribió cada documento.
|
|
691
|
+
// The sync carries the chat's last activity; without it the list would be ordered
|
|
692
|
+
// by the moment each document happened to be written.
|
|
693
|
+
const stamp = ch.conversationTimestamp != null ? Number(ch.conversationTimestamp) * 1_000 : null;
|
|
694
|
+
raw.activity = Math.max(stamp ?? 0, raw.activity ?? 0, await this.#activity(ch.id)) || null;
|
|
695
|
+
await this.engine.set(`/chat/${ch.id}`, (0, store_1.serialize)(raw), raw.activity ?? 0);
|
|
670
696
|
if (current === null) {
|
|
671
697
|
this.emit('chat:created', new this.Chat(raw), this);
|
|
672
698
|
}
|
|
@@ -702,7 +728,9 @@ class WhatsApp {
|
|
|
702
728
|
}
|
|
703
729
|
if (Object.keys(patch).length > 0) {
|
|
704
730
|
const merged = { ...current, ...patch };
|
|
705
|
-
|
|
731
|
+
// Fijar, archivar o silenciar no es actividad: el chat conserva su posición.
|
|
732
|
+
// Pinning, archiving or muting is not activity: the chat keeps its position.
|
|
733
|
+
await this.engine.set(`/chat/${ch.id}`, (0, store_1.serialize)(merged), merged.activity ?? undefined);
|
|
706
734
|
if (pinned_changed) {
|
|
707
735
|
this.emit(ch.pinned != null ? 'chat:pinned' : 'chat:unpinned', new this.Chat(merged), this);
|
|
708
736
|
}
|
|
@@ -1007,12 +1035,22 @@ class WhatsApp {
|
|
|
1007
1035
|
const chat_raw = {
|
|
1008
1036
|
id: cid,
|
|
1009
1037
|
name: is_group ? null : push_name,
|
|
1038
|
+
activity: doc.created_at,
|
|
1010
1039
|
};
|
|
1011
|
-
await this.engine.set(`/chat/${cid}`, (0, store_1.serialize)(chat_raw));
|
|
1040
|
+
await this.engine.set(`/chat/${cid}`, (0, store_1.serialize)(chat_raw), doc.created_at);
|
|
1012
1041
|
this.emit('chat:created', new this.Chat(chat_raw), this);
|
|
1013
1042
|
}
|
|
1014
1043
|
}
|
|
1015
1044
|
await this.engine.set(`/chat/${cid}/message/${mid}`, (0, store_1.serialize)(doc), doc.created_at);
|
|
1045
|
+
// El mensaje más nuevo define la posición del chat en la lista; un mensaje viejo
|
|
1046
|
+
// que llega en un re-sync no la altera.
|
|
1047
|
+
// The newest message defines the chat's position in the list; an old message
|
|
1048
|
+
// arriving in a re-sync does not move it.
|
|
1049
|
+
const chat_doc = (0, store_1.deserialize)(await this.engine.get(`/chat/${cid}`));
|
|
1050
|
+
if (chat_doc && doc.created_at > (chat_doc.activity ?? 0)) {
|
|
1051
|
+
chat_doc.activity = doc.created_at;
|
|
1052
|
+
await this.engine.set(`/chat/${cid}`, (0, store_1.serialize)(chat_doc), doc.created_at);
|
|
1053
|
+
}
|
|
1016
1054
|
// El binario solo se materializa en la primera entrega; en re-syncs ya vive en el engine.
|
|
1017
1055
|
// The binary is only materialized on first delivery; on re-syncs it already lives in the engine.
|
|
1018
1056
|
let content_buf = Buffer.alloc(0);
|
|
@@ -17,6 +17,8 @@ export declare class Chat {
|
|
|
17
17
|
pinned?: number | null;
|
|
18
18
|
mute_end_time?: number | null;
|
|
19
19
|
unread_count?: number | null;
|
|
20
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
21
|
+
activity?: number | null;
|
|
20
22
|
};
|
|
21
23
|
/**
|
|
22
24
|
* @internal Documento crudo del chat. `id` es el identificador del engine (JID, LID o
|
|
@@ -31,6 +33,8 @@ export declare class Chat {
|
|
|
31
33
|
pinned?: number | null;
|
|
32
34
|
mute_end_time?: number | null;
|
|
33
35
|
unread_count?: number | null;
|
|
36
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
37
|
+
activity?: number | null;
|
|
34
38
|
});
|
|
35
39
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
36
40
|
get id(): string;
|
|
@@ -61,6 +65,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
61
65
|
pinned?: number | null;
|
|
62
66
|
mute_end_time?: number | null;
|
|
63
67
|
unread_count?: number | null;
|
|
68
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
69
|
+
activity?: number | null;
|
|
64
70
|
}): {
|
|
65
71
|
/**
|
|
66
72
|
* Participantes del chat: los integrantes en grupos, el contacto y yo en 1:1.
|
|
@@ -161,6 +167,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
161
167
|
pinned?: number | null;
|
|
162
168
|
mute_end_time?: number | null;
|
|
163
169
|
unread_count?: number | null;
|
|
170
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
171
|
+
activity?: number | null;
|
|
164
172
|
};
|
|
165
173
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
166
174
|
get id(): string;
|
|
@@ -286,6 +294,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
286
294
|
pinned?: number | null;
|
|
287
295
|
mute_end_time?: number | null;
|
|
288
296
|
unread_count?: number | null;
|
|
297
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
298
|
+
activity?: number | null;
|
|
289
299
|
};
|
|
290
300
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
291
301
|
get id(): string;
|
|
@@ -410,6 +420,8 @@ export declare function chat(wa: WhatsApp): {
|
|
|
410
420
|
pinned?: number | null;
|
|
411
421
|
mute_end_time?: number | null;
|
|
412
422
|
unread_count?: number | null;
|
|
423
|
+
/** Epoch ms del último mensaje: ordena la lista y sobrevive a las escrituras de flags. / Last message epoch ms: orders the list and survives flag writes. */
|
|
424
|
+
activity?: number | null;
|
|
413
425
|
};
|
|
414
426
|
/** Teléfono del contacto, o el identificador crudo en grupos y LIDs. / Contact phone, or the raw identifier for groups and LIDs. */
|
|
415
427
|
get id(): string;
|
|
@@ -63,6 +63,16 @@ export function chat(wa) {
|
|
|
63
63
|
* Último mensaje del chat en el formato que exige `chatModify`.
|
|
64
64
|
* The chat's last message in the shape `chatModify` requires.
|
|
65
65
|
*/
|
|
66
|
+
/**
|
|
67
|
+
* Actividad del chat según su último mensaje: mantiene la posición en la lista cuando se
|
|
68
|
+
* reescribe el documento por fijar, archivar, silenciar o marcar leído.
|
|
69
|
+
* Chat activity from its last message: keeps its position in the list when the document is
|
|
70
|
+
* rewritten by pinning, archiving, muting or marking as read.
|
|
71
|
+
*/
|
|
72
|
+
async function activity_of(cid) {
|
|
73
|
+
const [raw] = await wa.engine.list(`/chat/${cid}/message`, 0, 1);
|
|
74
|
+
return deserialize(raw ?? null)?.created_at ?? 0;
|
|
75
|
+
}
|
|
66
76
|
async function last_messages(cid) {
|
|
67
77
|
const [raw] = await wa.engine.list(`/chat/${cid}/message`, 0, 1);
|
|
68
78
|
const parsed = deserialize(raw ?? null);
|
|
@@ -196,7 +206,7 @@ export function chat(wa) {
|
|
|
196
206
|
if (socket) {
|
|
197
207
|
await socket.chatModify({ archive: value, lastMessages: await last_messages(this._raw.id) }, this._raw.id);
|
|
198
208
|
this._raw.archived = value;
|
|
199
|
-
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw));
|
|
209
|
+
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
200
210
|
ok = true;
|
|
201
211
|
}
|
|
202
212
|
return ok;
|
|
@@ -218,7 +228,7 @@ export function chat(wa) {
|
|
|
218
228
|
if (allowed) {
|
|
219
229
|
await socket.chatModify({ pin: value }, this._raw.id);
|
|
220
230
|
this._raw.pinned = value ? Date.now() : null;
|
|
221
|
-
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw));
|
|
231
|
+
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
222
232
|
ok = true;
|
|
223
233
|
}
|
|
224
234
|
}
|
|
@@ -239,7 +249,7 @@ export function chat(wa) {
|
|
|
239
249
|
const muted = end > Date.now();
|
|
240
250
|
await socket.chatModify({ mute: muted ? end : null }, this._raw.id);
|
|
241
251
|
this._raw.mute_end_time = muted ? end : null;
|
|
242
|
-
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw));
|
|
252
|
+
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
243
253
|
ok = true;
|
|
244
254
|
}
|
|
245
255
|
return ok;
|
|
@@ -256,7 +266,7 @@ export function chat(wa) {
|
|
|
256
266
|
if (socket) {
|
|
257
267
|
await socket.chatModify({ markRead: true, lastMessages: await last_messages(this._raw.id) }, this._raw.id);
|
|
258
268
|
this._raw.unread_count = 0;
|
|
259
|
-
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw));
|
|
269
|
+
await wa.engine.set(`/chat/${this._raw.id}`, serialize(this._raw), this._raw.activity ?? (await activity_of(this._raw.id)));
|
|
260
270
|
ok = true;
|
|
261
271
|
}
|
|
262
272
|
return ok;
|
|
@@ -556,10 +556,16 @@ export class WhatsApp {
|
|
|
556
556
|
if (doc.lid) {
|
|
557
557
|
await this.engine.set(`/lid/${doc.lid}`, serialize(doc.id));
|
|
558
558
|
}
|
|
559
|
-
|
|
559
|
+
// Una ficha que existía vacía y ahora tiene nombre es un cambio que el consumidor
|
|
560
|
+
// necesita: sin avisar, quien memorice el contacto sigue mostrando el número.
|
|
561
|
+
// A card that existed empty and now has a name is a change the consumer needs: without
|
|
562
|
+
// notifying, whoever memoized the contact keeps showing the bare number.
|
|
563
|
+
const changed = current && ['lid', 'name', 'notify', 'verified_name', 'img_url', 'status'].some((key) => current[key] !== doc[key]);
|
|
564
|
+
if (!current || changed) {
|
|
560
565
|
const person = new this.Contact(doc);
|
|
561
566
|
const cached_chat = deserialize(await this.engine.get(`/chat/${doc.id}`));
|
|
562
|
-
|
|
567
|
+
const chat = new this.Chat(cached_chat ?? { id: doc.id, name: person.name });
|
|
568
|
+
this.emit(current ? 'contact:updated' : 'contact:created', person, chat, this);
|
|
563
569
|
}
|
|
564
570
|
}
|
|
565
571
|
/** @internal */
|
|
@@ -611,6 +617,20 @@ export class WhatsApp {
|
|
|
611
617
|
await this.engine.set(`/lid/${lid}`, serialize(pn));
|
|
612
618
|
await this.engine.set(`/lid/${pn}`, serialize(lid));
|
|
613
619
|
}
|
|
620
|
+
/**
|
|
621
|
+
* Actividad del chat según su último mensaje persistido. Es el respaldo para los
|
|
622
|
+
* documentos que se guardaron antes de que el chat llevara su propia marca.
|
|
623
|
+
* Chat activity from its last persisted message. It is the fallback for documents stored
|
|
624
|
+
* before the chat carried its own stamp.
|
|
625
|
+
*
|
|
626
|
+
* @param cid - Identificador del chat / Chat identifier
|
|
627
|
+
* @returns Epoch ms del último mensaje, o 0 si el chat no tiene ninguno / Last message epoch ms, or 0 when the chat has none
|
|
628
|
+
* @internal
|
|
629
|
+
*/
|
|
630
|
+
async #activity(cid) {
|
|
631
|
+
const [raw] = await this.engine.list(`/chat/${cid}/message`, 0, 1);
|
|
632
|
+
return deserialize(raw ?? null)?.created_at ?? 0;
|
|
633
|
+
}
|
|
614
634
|
/** @internal */
|
|
615
635
|
async #handle_chats_upsert(chats) {
|
|
616
636
|
for (const ch of chats) {
|
|
@@ -627,7 +647,13 @@ export class WhatsApp {
|
|
|
627
647
|
if (ch.name) {
|
|
628
648
|
raw.name = ch.name;
|
|
629
649
|
}
|
|
630
|
-
|
|
650
|
+
// El sync trae la última actividad del chat; sin ella la lista quedaría ordenada
|
|
651
|
+
// por el momento en que se escribió cada documento.
|
|
652
|
+
// The sync carries the chat's last activity; without it the list would be ordered
|
|
653
|
+
// by the moment each document happened to be written.
|
|
654
|
+
const stamp = ch.conversationTimestamp != null ? Number(ch.conversationTimestamp) * 1_000 : null;
|
|
655
|
+
raw.activity = Math.max(stamp ?? 0, raw.activity ?? 0, await this.#activity(ch.id)) || null;
|
|
656
|
+
await this.engine.set(`/chat/${ch.id}`, serialize(raw), raw.activity ?? 0);
|
|
631
657
|
if (current === null) {
|
|
632
658
|
this.emit('chat:created', new this.Chat(raw), this);
|
|
633
659
|
}
|
|
@@ -663,7 +689,9 @@ export class WhatsApp {
|
|
|
663
689
|
}
|
|
664
690
|
if (Object.keys(patch).length > 0) {
|
|
665
691
|
const merged = { ...current, ...patch };
|
|
666
|
-
|
|
692
|
+
// Fijar, archivar o silenciar no es actividad: el chat conserva su posición.
|
|
693
|
+
// Pinning, archiving or muting is not activity: the chat keeps its position.
|
|
694
|
+
await this.engine.set(`/chat/${ch.id}`, serialize(merged), merged.activity ?? undefined);
|
|
667
695
|
if (pinned_changed) {
|
|
668
696
|
this.emit(ch.pinned != null ? 'chat:pinned' : 'chat:unpinned', new this.Chat(merged), this);
|
|
669
697
|
}
|
|
@@ -968,12 +996,22 @@ export class WhatsApp {
|
|
|
968
996
|
const chat_raw = {
|
|
969
997
|
id: cid,
|
|
970
998
|
name: is_group ? null : push_name,
|
|
999
|
+
activity: doc.created_at,
|
|
971
1000
|
};
|
|
972
|
-
await this.engine.set(`/chat/${cid}`, serialize(chat_raw));
|
|
1001
|
+
await this.engine.set(`/chat/${cid}`, serialize(chat_raw), doc.created_at);
|
|
973
1002
|
this.emit('chat:created', new this.Chat(chat_raw), this);
|
|
974
1003
|
}
|
|
975
1004
|
}
|
|
976
1005
|
await this.engine.set(`/chat/${cid}/message/${mid}`, serialize(doc), doc.created_at);
|
|
1006
|
+
// El mensaje más nuevo define la posición del chat en la lista; un mensaje viejo
|
|
1007
|
+
// que llega en un re-sync no la altera.
|
|
1008
|
+
// The newest message defines the chat's position in the list; an old message
|
|
1009
|
+
// arriving in a re-sync does not move it.
|
|
1010
|
+
const chat_doc = deserialize(await this.engine.get(`/chat/${cid}`));
|
|
1011
|
+
if (chat_doc && doc.created_at > (chat_doc.activity ?? 0)) {
|
|
1012
|
+
chat_doc.activity = doc.created_at;
|
|
1013
|
+
await this.engine.set(`/chat/${cid}`, serialize(chat_doc), doc.created_at);
|
|
1014
|
+
}
|
|
977
1015
|
// El binario solo se materializa en la primera entrega; en re-syncs ya vive en el engine.
|
|
978
1016
|
// The binary is only materialized on first delivery; on re-syncs it already lives in the engine.
|
|
979
1017
|
let content_buf = Buffer.alloc(0);
|