@fer2809fl/baileys 7.0.2 → 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.
- package/README.md +409 -32
- package/lib/Defaults/index.js +2 -1
- package/lib/Modded/message_builder.js +2356 -0
- package/lib/Signal/libsignal.js +19 -0
- package/lib/Socket/business.d.ts +213 -532
- package/lib/Socket/business.js +359 -401
- package/lib/Socket/chats.d.ts +30 -2
- package/lib/Socket/chats.js +295 -40
- package/lib/Socket/groups.d.ts +16 -0
- package/lib/Socket/groups.js +101 -18
- package/lib/Socket/index.d.ts +17 -0
- package/lib/Socket/messages-recv.js +18 -1
- package/lib/Socket/messages-send.d.ts +18 -0
- package/lib/Socket/messages-send.js +50 -2
- package/lib/Socket/newsletter.js +3 -3
- package/lib/Socket/socket.js +50 -6
- package/lib/Types/Newsletter.d.ts +13 -4
- package/lib/Types/Newsletter.js +12 -2
- package/lib/Utils/anti-ban.d.ts +41 -0
- package/lib/Utils/anti-ban.js +182 -0
- package/lib/Utils/banner.d.ts +8 -0
- package/lib/Utils/banner.js +76 -0
- package/lib/Utils/bot-utils.d.ts +57 -0
- package/lib/Utils/bot-utils.js +241 -0
- package/lib/Utils/chat-utils.d.ts +34 -4
- package/lib/Utils/chat-utils.js +80 -20
- package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
- package/lib/Utils/companion-reg-client-utils.js +35 -0
- package/lib/Utils/enhanced-cache.d.ts +40 -0
- package/lib/Utils/enhanced-cache.js +242 -0
- package/lib/Utils/enhanced-logger.d.ts +41 -0
- package/lib/Utils/enhanced-logger.js +185 -0
- package/lib/Utils/event-buffer.js +49 -1
- package/lib/Utils/index.d.ts +14 -0
- package/lib/Utils/index.js +14 -0
- package/lib/Utils/lid-utils.d.ts +139 -0
- package/lib/Utils/lid-utils.js +503 -0
- package/lib/Utils/message-queue.d.ts +47 -0
- package/lib/Utils/message-queue.js +226 -0
- package/lib/Utils/message-retry-manager.js +40 -0
- package/lib/Utils/rich-message-utils.d.ts +21 -0
- package/lib/Utils/rich-message-utils.js +229 -0
- package/lib/Utils/rich-messages.d.ts +52 -0
- package/lib/Utils/rich-messages.js +185 -0
- package/lib/Utils/scheduled-messages.d.ts +122 -0
- package/lib/Utils/scheduled-messages.js +289 -0
- package/lib/Utils/smart-reconnect.d.ts +48 -0
- package/lib/Utils/smart-reconnect.js +207 -0
- package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
- package/lib/Utils/use-sqlite-auth-state.js +95 -0
- package/lib/VoIP/audio-feeder.d.ts +15 -0
- package/lib/VoIP/audio-feeder.js +132 -0
- package/lib/VoIP/index.js +277 -0
- package/lib/VoIP/relay-transport.d.ts +43 -0
- package/lib/VoIP/relay-transport.js +559 -0
- package/lib/VoIP/signaling.js +594 -0
- package/lib/VoIP/types.d.ts +69 -0
- package/lib/VoIP/types.js +17 -0
- package/lib/VoIP/wasm-engine.d.ts +103 -0
- package/lib/VoIP/wasm-engine.js +1214 -0
- package/lib/VoIP/worker-bootstrap.js +1042 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/lib/WAUSync/Protocols/index.js +1 -0
- package/lib/WAUSync/USyncQuery.js +5 -1
- package/lib/assets/wasm/loader.js +5 -0
- package/lib/assets/wasm/whatsapp.wasm +0 -0
- package/lib/assets/wasm/worker-modules.js +273 -0
- package/lib/index.d.ts +41 -0
- package/lib/index.js +3 -0
- package/package.json +15 -7
- package/lib/Defaults/index.d.ts.map +0 -1
- package/lib/Defaults/index.js.map +0 -1
- package/lib/Signal/Group/ciphertext-message.d.ts.map +0 -1
- package/lib/Signal/Group/ciphertext-message.js.map +0 -1
- package/lib/Signal/Group/group-session-builder.d.ts.map +0 -1
- package/lib/Signal/Group/group-session-builder.js.map +0 -1
- package/lib/Signal/Group/group_cipher.d.ts.map +0 -1
- package/lib/Signal/Group/group_cipher.js.map +0 -1
- package/lib/Signal/Group/index.d.ts.map +0 -1
- package/lib/Signal/Group/index.js.map +0 -1
- package/lib/Signal/Group/keyhelper.d.ts.map +0 -1
- package/lib/Signal/Group/keyhelper.js.map +0 -1
- package/lib/Signal/Group/sender-chain-key.d.ts.map +0 -1
- package/lib/Signal/Group/sender-chain-key.js.map +0 -1
- package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-distribution-message.js.map +0 -1
- package/lib/Signal/Group/sender-key-message.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-message.js.map +0 -1
- package/lib/Signal/Group/sender-key-name.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-name.js.map +0 -1
- package/lib/Signal/Group/sender-key-record.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-record.js.map +0 -1
- package/lib/Signal/Group/sender-key-state.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-state.js.map +0 -1
- package/lib/Signal/Group/sender-message-key.d.ts.map +0 -1
- package/lib/Signal/Group/sender-message-key.js.map +0 -1
- package/lib/Signal/libsignal.d.ts.map +0 -1
- package/lib/Signal/libsignal.js.map +0 -1
- package/lib/Signal/lid-mapping.d.ts.map +0 -1
- package/lib/Signal/lid-mapping.js.map +0 -1
- package/lib/Socket/Client/index.d.ts.map +0 -1
- package/lib/Socket/Client/index.js.map +0 -1
- package/lib/Socket/Client/types.d.ts.map +0 -1
- package/lib/Socket/Client/types.js.map +0 -1
- package/lib/Socket/Client/websocket.d.ts.map +0 -1
- package/lib/Socket/Client/websocket.js.map +0 -1
- package/lib/Socket/business.d.ts.map +0 -1
- package/lib/Socket/business.js.map +0 -1
- package/lib/Socket/chats.d.ts.map +0 -1
- package/lib/Socket/chats.js.map +0 -1
- package/lib/Socket/communities.d.ts.map +0 -1
- package/lib/Socket/communities.js.map +0 -1
- package/lib/Socket/dugong.d.ts.map +0 -1
- package/lib/Socket/dugong.js.map +0 -1
- package/lib/Socket/groups.d.ts.map +0 -1
- package/lib/Socket/groups.js.map +0 -1
- package/lib/Socket/index.d.ts.map +0 -1
- package/lib/Socket/index.js.map +0 -1
- package/lib/Socket/messages-recv.d.ts.map +0 -1
- package/lib/Socket/messages-recv.js.map +0 -1
- package/lib/Socket/messages-send.d.ts.map +0 -1
- package/lib/Socket/messages-send.js.map +0 -1
- package/lib/Socket/mex.d.ts.map +0 -1
- package/lib/Socket/mex.js.map +0 -1
- package/lib/Socket/newsletter.d.ts.map +0 -1
- package/lib/Socket/newsletter.js.map +0 -1
- package/lib/Socket/socket.d.ts.map +0 -1
- package/lib/Socket/socket.js.map +0 -1
- package/lib/Types/Auth.d.ts.map +0 -1
- package/lib/Types/Auth.js.map +0 -1
- package/lib/Types/Bussines.d.ts.map +0 -1
- package/lib/Types/Bussines.js.map +0 -1
- package/lib/Types/Call.d.ts.map +0 -1
- package/lib/Types/Call.js.map +0 -1
- package/lib/Types/Chat.d.ts.map +0 -1
- package/lib/Types/Chat.js.map +0 -1
- package/lib/Types/Contact.d.ts.map +0 -1
- package/lib/Types/Contact.js.map +0 -1
- package/lib/Types/Events.d.ts.map +0 -1
- package/lib/Types/Events.js.map +0 -1
- package/lib/Types/GroupMetadata.d.ts.map +0 -1
- package/lib/Types/GroupMetadata.js.map +0 -1
- package/lib/Types/Label.d.ts.map +0 -1
- package/lib/Types/Label.js.map +0 -1
- package/lib/Types/LabelAssociation.d.ts.map +0 -1
- package/lib/Types/LabelAssociation.js.map +0 -1
- package/lib/Types/Message.d.ts.map +0 -1
- package/lib/Types/Message.js.map +0 -1
- package/lib/Types/Newsletter.d.ts.map +0 -1
- package/lib/Types/Newsletter.js.map +0 -1
- package/lib/Types/Product.d.ts.map +0 -1
- package/lib/Types/Product.js.map +0 -1
- package/lib/Types/Signal.d.ts.map +0 -1
- package/lib/Types/Signal.js.map +0 -1
- package/lib/Types/Socket.d.ts.map +0 -1
- package/lib/Types/Socket.js.map +0 -1
- package/lib/Types/State.d.ts.map +0 -1
- package/lib/Types/State.js.map +0 -1
- package/lib/Types/USync.d.ts.map +0 -1
- package/lib/Types/USync.js.map +0 -1
- package/lib/Types/index.d.ts.map +0 -1
- package/lib/Types/index.js.map +0 -1
- package/lib/Utils/auth-utils.d.ts.map +0 -1
- package/lib/Utils/auth-utils.js.map +0 -1
- package/lib/Utils/browser-utils.d.ts.map +0 -1
- package/lib/Utils/browser-utils.js.map +0 -1
- package/lib/Utils/business.d.ts.map +0 -1
- package/lib/Utils/business.js.map +0 -1
- package/lib/Utils/chat-utils.d.ts.map +0 -1
- package/lib/Utils/chat-utils.js.map +0 -1
- package/lib/Utils/crypto.d.ts.map +0 -1
- package/lib/Utils/crypto.js.map +0 -1
- package/lib/Utils/decode-wa-message.d.ts.map +0 -1
- package/lib/Utils/decode-wa-message.js.map +0 -1
- package/lib/Utils/event-buffer.d.ts.map +0 -1
- package/lib/Utils/event-buffer.js.map +0 -1
- package/lib/Utils/generics.d.ts.map +0 -1
- package/lib/Utils/generics.js.map +0 -1
- package/lib/Utils/history.d.ts.map +0 -1
- package/lib/Utils/history.js.map +0 -1
- package/lib/Utils/identity-change-handler.d.ts.map +0 -1
- package/lib/Utils/identity-change-handler.js.map +0 -1
- package/lib/Utils/index.d.ts.map +0 -1
- package/lib/Utils/index.js.map +0 -1
- package/lib/Utils/link-preview.d.ts.map +0 -1
- package/lib/Utils/link-preview.js.map +0 -1
- package/lib/Utils/logger.d.ts.map +0 -1
- package/lib/Utils/logger.js.map +0 -1
- package/lib/Utils/lt-hash.d.ts.map +0 -1
- package/lib/Utils/lt-hash.js.map +0 -1
- package/lib/Utils/make-mutex.d.ts.map +0 -1
- package/lib/Utils/make-mutex.js.map +0 -1
- package/lib/Utils/message-retry-manager.d.ts.map +0 -1
- package/lib/Utils/message-retry-manager.js.map +0 -1
- package/lib/Utils/messages-media.d.ts.map +0 -1
- package/lib/Utils/messages-media.js.map +0 -1
- package/lib/Utils/messages.d.ts.map +0 -1
- package/lib/Utils/messages.js.map +0 -1
- package/lib/Utils/noise-handler.d.ts.map +0 -1
- package/lib/Utils/noise-handler.js.map +0 -1
- package/lib/Utils/offline-node-processor.d.ts.map +0 -1
- package/lib/Utils/offline-node-processor.js.map +0 -1
- package/lib/Utils/pre-key-manager.d.ts.map +0 -1
- package/lib/Utils/pre-key-manager.js.map +0 -1
- package/lib/Utils/process-message.d.ts.map +0 -1
- package/lib/Utils/process-message.js.map +0 -1
- package/lib/Utils/reporting-utils.d.ts.map +0 -1
- package/lib/Utils/reporting-utils.js.map +0 -1
- package/lib/Utils/rich-messages.d.ts.map +0 -1
- package/lib/Utils/rich-messages.js.map +0 -1
- package/lib/Utils/signal.d.ts.map +0 -1
- package/lib/Utils/signal.js.map +0 -1
- package/lib/Utils/stanza-ack.d.ts.map +0 -1
- package/lib/Utils/stanza-ack.js.map +0 -1
- package/lib/Utils/sync-action-utils.d.ts.map +0 -1
- package/lib/Utils/sync-action-utils.js.map +0 -1
- package/lib/Utils/tc-token-utils.d.ts.map +0 -1
- package/lib/Utils/tc-token-utils.js.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.js.map +0 -1
- package/lib/Utils/validate-connection.d.ts.map +0 -1
- package/lib/Utils/validate-connection.js.map +0 -1
- package/lib/WABinary/constants.d.ts.map +0 -1
- package/lib/WABinary/constants.js.map +0 -1
- package/lib/WABinary/decode.d.ts.map +0 -1
- package/lib/WABinary/decode.js.map +0 -1
- package/lib/WABinary/encode.d.ts.map +0 -1
- package/lib/WABinary/encode.js.map +0 -1
- package/lib/WABinary/generic-utils.d.ts.map +0 -1
- package/lib/WABinary/generic-utils.js.map +0 -1
- package/lib/WABinary/index.d.ts.map +0 -1
- package/lib/WABinary/index.js.map +0 -1
- package/lib/WABinary/jid-utils.d.ts.map +0 -1
- package/lib/WABinary/jid-utils.js.map +0 -1
- package/lib/WABinary/types.d.ts.map +0 -1
- package/lib/WABinary/types.js.map +0 -1
- package/lib/WAM/BinaryInfo.d.ts.map +0 -1
- package/lib/WAM/BinaryInfo.js.map +0 -1
- package/lib/WAM/constants.d.ts.map +0 -1
- package/lib/WAM/constants.js.map +0 -1
- package/lib/WAM/encode.d.ts.map +0 -1
- package/lib/WAM/encode.js.map +0 -1
- package/lib/WAM/index.d.ts.map +0 -1
- package/lib/WAM/index.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/index.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/index.js.map +0 -1
- package/lib/WAUSync/USyncQuery.d.ts.map +0 -1
- package/lib/WAUSync/USyncQuery.js.map +0 -1
- package/lib/WAUSync/USyncUser.d.ts.map +0 -1
- package/lib/WAUSync/USyncUser.js.map +0 -1
- package/lib/WAUSync/index.d.ts.map +0 -1
- package/lib/WAUSync/index.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
package/lib/Socket/chats.d.ts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { Boom } from '@hapi/boom';
|
|
2
2
|
import { proto } from '../../WAProto/index.js';
|
|
3
|
-
import type { BotListInfo, ChatModification, MessageUpsertType, SocketConfig, WABusinessProfile, WAMediaUpload, WAMessage, WAPatchCreate, WAPresence, WAPrivacyCallValue, WAPrivacyGroupAddValue, WAPrivacyMessagesValue, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '../Types/index.js';
|
|
3
|
+
import type { BotListInfo, CacheStore, ChatModification, MessageUpsertType, SocketConfig, WABusinessProfile, WAMediaUpload, WAMessage, WAPatchCreate, WAPresence, WAPrivacyCallValue, WAPrivacyGroupAddValue, WAPrivacyMessagesValue, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '../Types/index.js';
|
|
4
4
|
import type { QuickReplyAction } from '../Types/Bussines.js';
|
|
5
5
|
import type { LabelActionBody } from '../Types/Label.js';
|
|
6
6
|
import { type BinaryNode } from '../WABinary/index.js';
|
|
7
7
|
import { USyncQuery } from '../WAUSync/index.js';
|
|
8
|
+
export declare const buildProfilePictureQueryContent: (type: "preview" | "image", tcTokenContent?: BinaryNode[]) => BinaryNode[];
|
|
8
9
|
export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
10
|
+
serverProps: {
|
|
11
|
+
/** AB prop 10518: gate tctoken on 1:1 messages. Default true (safe: avoids 463). */
|
|
12
|
+
privacyTokenOn1to1: boolean;
|
|
13
|
+
/** AB prop 9666: gate tctoken on profile picture IQs. WA Web default: true. */
|
|
14
|
+
profilePicPrivacyToken: boolean;
|
|
15
|
+
/** AB prop 14303: issue tctokens to LID instead of PN. WA Web default: false. */
|
|
16
|
+
lidTrustedTokenIssueToLid: boolean;
|
|
17
|
+
};
|
|
9
18
|
createCallLink: (type: "audio" | "video", event?: {
|
|
10
19
|
startTime: number;
|
|
11
20
|
}, timeoutMs?: number) => Promise<string | undefined>;
|
|
@@ -57,6 +66,7 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
57
66
|
cleanDirtyBits: (type: "account_sync" | "groups", fromTimestamp?: number | string) => Promise<void>;
|
|
58
67
|
addOrEditContact: (jid: string, contact: proto.SyncActionValue.IContactAction) => Promise<void>;
|
|
59
68
|
removeContact: (jid: string) => Promise<void>;
|
|
69
|
+
placeholderResendCache: CacheStore;
|
|
60
70
|
addLabel: (jid: string, labels: LabelActionBody) => Promise<void>;
|
|
61
71
|
addChatLabel: (jid: string, labelId: string) => Promise<void>;
|
|
62
72
|
removeChatLabel: (jid: string, labelId: string) => Promise<void>;
|
|
@@ -66,6 +76,20 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
66
76
|
id: string;
|
|
67
77
|
fromMe?: boolean;
|
|
68
78
|
}[], star: boolean) => Promise<void>;
|
|
79
|
+
/** Fija o desfija un chat en la parte superior de la lista de chats. */
|
|
80
|
+
pinChat: (jid: string, pin?: boolean) => Promise<void>;
|
|
81
|
+
/** Archiva o desarchiva un chat. */
|
|
82
|
+
archiveChat: (jid: string, archive?: boolean, lastMessages?: import("../Types/index.js").LastMessageList) => Promise<void>;
|
|
83
|
+
/** Silencia un chat hasta `muteEndTimestamp` (ms). Pasa `undefined` para quitar el silencio. */
|
|
84
|
+
muteChat: (jid: string, muteEndTimestamp?: number) => Promise<void>;
|
|
85
|
+
/** Marca un chat como leído (o no leído con `read: false`). */
|
|
86
|
+
markChatRead: (jid: string, read?: boolean, lastMessages?: import("../Types/index.js").LastMessageList) => Promise<void>;
|
|
87
|
+
/** Atajo para marcar un chat como no leído. */
|
|
88
|
+
markChatUnread: (jid: string, lastMessages?: import("../Types/index.js").LastMessageList) => Promise<void>;
|
|
89
|
+
/** Vacía el historial de un chat sin eliminar el chat. */
|
|
90
|
+
clearChat: (jid: string, lastMessages?: import("../Types/index.js").LastMessageList) => Promise<void>;
|
|
91
|
+
/** Elimina un chat completo de la lista de chats. */
|
|
92
|
+
deleteChat: (jid: string, lastMessages?: import("../Types/index.js").LastMessageList) => Promise<void>;
|
|
69
93
|
addOrEditQuickReply: (quickReply: QuickReplyAction) => Promise<void>;
|
|
70
94
|
removeQuickReply: (timestamp: string) => Promise<void>;
|
|
71
95
|
type: "md";
|
|
@@ -76,6 +100,7 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
76
100
|
createBufferedFunction<A extends any[], T>(work: (...args: A) => Promise<T>): (...args: A) => Promise<T>;
|
|
77
101
|
flush(): boolean;
|
|
78
102
|
isBuffering(): boolean;
|
|
103
|
+
destroy(): void;
|
|
79
104
|
};
|
|
80
105
|
authState: {
|
|
81
106
|
creds: import("../Types/index.js").AuthenticationCreds;
|
|
@@ -91,8 +116,9 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
91
116
|
sendNode: (frame: BinaryNode) => Promise<void>;
|
|
92
117
|
logout: (msg?: string) => Promise<void>;
|
|
93
118
|
end: (error: Error | undefined) => Promise<void>;
|
|
119
|
+
registerSocketEndHandler: (handler: (error: Error | undefined) => void | Promise<void>) => void;
|
|
94
120
|
onUnexpectedError: (err: Error | Boom, msg: string) => void;
|
|
95
|
-
uploadPreKeys: (count?: number
|
|
121
|
+
uploadPreKeys: (count?: number) => Promise<void>;
|
|
96
122
|
uploadPreKeysToServerIfRequired: () => Promise<void>;
|
|
97
123
|
digestKeyBundle: () => Promise<void>;
|
|
98
124
|
rotateSignedPreKey: () => Promise<void>;
|
|
@@ -107,5 +133,7 @@ export declare const makeChatsSocket: (config: SocketConfig) => {
|
|
|
107
133
|
jid: string;
|
|
108
134
|
exists: boolean;
|
|
109
135
|
}[] | undefined>;
|
|
136
|
+
fetchAccountReachoutTimelock: () => Promise<import("../Types/index.js").ReachoutTimelockState>;
|
|
137
|
+
fetchNewChatMessageCap: () => Promise<import("../Types/index.js").NewChatMessageCapInfo>;
|
|
110
138
|
};
|
|
111
139
|
//# sourceMappingURL=chats.d.ts.map
|
package/lib/Socket/chats.js
CHANGED
|
@@ -1,22 +1,38 @@
|
|
|
1
1
|
import NodeCache from '@cacheable/node-cache';
|
|
2
2
|
import { Boom } from '@hapi/boom';
|
|
3
3
|
import { proto } from '../../WAProto/index.js';
|
|
4
|
-
import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
4
|
+
import { DEFAULT_CACHE_TTLS, HISTORY_SYNC_PAUSED_TIMEOUT_MS, PROCESSABLE_HISTORY_TYPES } from '../Defaults/index.js';
|
|
5
5
|
import { ALL_WA_PATCH_NAMES } from '../Types/index.js';
|
|
6
6
|
import { SyncState } from '../Types/State.js';
|
|
7
|
-
import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, extractSyncdPatches, generateProfilePicture, getHistoryMsg, newLTHashState, processSyncAction } from '../Utils/index.js';
|
|
7
|
+
import { chatModificationToAppPatch, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, ensureLTHashStateVersion, extractSyncdPatches, generateProfilePicture, getHistoryMsg, isAppStateSyncIrrecoverable, isMissingKeyError, MAX_SYNC_ATTEMPTS, newLTHashState, processSyncAction } from '../Utils/index.js';
|
|
8
8
|
import { makeMutex } from '../Utils/make-mutex.js';
|
|
9
9
|
import processMessage from '../Utils/process-message.js';
|
|
10
10
|
import { buildTcTokenFromJid } from '../Utils/tc-token-utils.js';
|
|
11
|
-
import { getBinaryNodeChild, getBinaryNodeChildren, jidDecode, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
11
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isLidUser, isPnUser, jidDecode, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
12
12
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
13
13
|
import { makeSocket } from './socket.js';
|
|
14
|
-
const
|
|
14
|
+
export const buildProfilePictureQueryContent = (type, tcTokenContent) => {
|
|
15
|
+
const picture = { tag: 'picture', attrs: { type, query: 'url' } };
|
|
16
|
+
if (tcTokenContent?.length) {
|
|
17
|
+
picture.content = tcTokenContent;
|
|
18
|
+
}
|
|
19
|
+
return [picture];
|
|
20
|
+
};
|
|
15
21
|
export const makeChatsSocket = (config) => {
|
|
16
22
|
const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
|
|
17
23
|
const sock = makeSocket(config);
|
|
18
|
-
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession } = sock;
|
|
24
|
+
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError, sendUnifiedSession, registerSocketEndHandler } = sock;
|
|
25
|
+
const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
|
|
19
26
|
let privacySettings;
|
|
27
|
+
/** Server-assigned AB props for protocol behavior. */
|
|
28
|
+
const serverProps = {
|
|
29
|
+
/** AB prop 10518: gate tctoken on 1:1 messages. Default true (safe: avoids 463). */
|
|
30
|
+
privacyTokenOn1to1: true,
|
|
31
|
+
/** AB prop 9666: gate tctoken on profile picture IQs. WA Web default: true. */
|
|
32
|
+
profilePicPrivacyToken: true,
|
|
33
|
+
/** AB prop 14303: issue tctokens to LID instead of PN. WA Web default: false. */
|
|
34
|
+
lidTrustedTokenIssueToLid: false
|
|
35
|
+
};
|
|
20
36
|
let syncState = SyncState.Connecting;
|
|
21
37
|
/** this mutex ensures that messages are processed in order */
|
|
22
38
|
const messageMutex = makeMutex();
|
|
@@ -28,14 +44,20 @@ export const makeChatsSocket = (config) => {
|
|
|
28
44
|
const notificationMutex = makeMutex();
|
|
29
45
|
// Timeout for AwaitingInitialSync state
|
|
30
46
|
let awaitingSyncTimeout;
|
|
47
|
+
// In-memory history sync completion tracking (resets on reconnection)
|
|
48
|
+
const historySyncStatus = {
|
|
49
|
+
initialBootstrapComplete: false,
|
|
50
|
+
recentSyncComplete: false
|
|
51
|
+
};
|
|
52
|
+
let historySyncPausedTimeout;
|
|
53
|
+
// Collections blocked on missing app state sync keys (mirrors WA Web's "Blocked" state).
|
|
54
|
+
// When a key arrives via APP_STATE_SYNC_KEY_SHARE, these are re-synced.
|
|
55
|
+
const blockedCollections = new Set();
|
|
31
56
|
const placeholderResendCache = config.placeholderResendCache ||
|
|
32
57
|
new NodeCache({
|
|
33
58
|
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
34
59
|
useClones: false
|
|
35
60
|
});
|
|
36
|
-
if (!config.placeholderResendCache) {
|
|
37
|
-
config.placeholderResendCache = placeholderResendCache;
|
|
38
|
-
}
|
|
39
61
|
/** helper function to fetch the given app state sync key */
|
|
40
62
|
const getAppStateSyncKey = async (keyId) => {
|
|
41
63
|
const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId]);
|
|
@@ -258,6 +280,42 @@ export const makeChatsSocket = (config) => {
|
|
|
258
280
|
return getBinaryNodeChildren(listNode, 'item').map(n => n.attrs.jid);
|
|
259
281
|
};
|
|
260
282
|
const updateBlockStatus = async (jid, action) => {
|
|
283
|
+
const normalizedJid = jidNormalizedUser(jid);
|
|
284
|
+
let lid;
|
|
285
|
+
let pn_jid;
|
|
286
|
+
if (isLidUser(normalizedJid) || isHostedLidUser(normalizedJid)) {
|
|
287
|
+
lid = normalizedJid;
|
|
288
|
+
if (action === 'block') {
|
|
289
|
+
const pn = await signalRepository.lidMapping.getPNForLID(normalizedJid);
|
|
290
|
+
if (!pn) {
|
|
291
|
+
throw new Boom(`Unable to resolve PN JID for LID: ${jid}`, { statusCode: 400 });
|
|
292
|
+
}
|
|
293
|
+
pn_jid = jidNormalizedUser(pn);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else if (isPnUser(normalizedJid) || isHostedPnUser(normalizedJid)) {
|
|
297
|
+
const mapped = await signalRepository.lidMapping.getLIDForPN(normalizedJid);
|
|
298
|
+
if (!mapped) {
|
|
299
|
+
throw new Boom(`Unable to resolve LID for PN JID: ${jid}`, { statusCode: 400 });
|
|
300
|
+
}
|
|
301
|
+
lid = mapped;
|
|
302
|
+
if (action === 'block') {
|
|
303
|
+
pn_jid = jidNormalizedUser(normalizedJid);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
throw new Boom(`Invalid jid: ${jid}`, { statusCode: 400 });
|
|
308
|
+
}
|
|
309
|
+
const itemAttrs = {
|
|
310
|
+
action,
|
|
311
|
+
jid: lid
|
|
312
|
+
};
|
|
313
|
+
if (action === 'block') {
|
|
314
|
+
if (!pn_jid) {
|
|
315
|
+
throw new Boom(`pn_jid required for block: ${jid}`, { statusCode: 400 });
|
|
316
|
+
}
|
|
317
|
+
itemAttrs.pn_jid = pn_jid;
|
|
318
|
+
}
|
|
261
319
|
await query({
|
|
262
320
|
tag: 'iq',
|
|
263
321
|
attrs: {
|
|
@@ -268,10 +326,7 @@ export const makeChatsSocket = (config) => {
|
|
|
268
326
|
content: [
|
|
269
327
|
{
|
|
270
328
|
tag: 'item',
|
|
271
|
-
attrs:
|
|
272
|
-
action,
|
|
273
|
-
jid
|
|
274
|
-
}
|
|
329
|
+
attrs: itemAttrs
|
|
275
330
|
}
|
|
276
331
|
]
|
|
277
332
|
});
|
|
@@ -370,6 +425,9 @@ export const makeChatsSocket = (config) => {
|
|
|
370
425
|
const collectionsToHandle = new Set(collections);
|
|
371
426
|
// in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
|
|
372
427
|
const attemptsMap = {};
|
|
428
|
+
// collections that failed and need a full snapshot on retry
|
|
429
|
+
// mirrors WA Web's ErrorFatal -> force snapshot behavior
|
|
430
|
+
const forceSnapshotCollections = new Set();
|
|
373
431
|
// keep executing till all collections are done
|
|
374
432
|
// sometimes a single patch request will not return all the patches (God knows why)
|
|
375
433
|
// so we fetch till they're all done (this is determined by the "has_more_patches" flag)
|
|
@@ -380,6 +438,7 @@ export const makeChatsSocket = (config) => {
|
|
|
380
438
|
const result = await authState.keys.get('app-state-sync-version', [name]);
|
|
381
439
|
let state = result[name];
|
|
382
440
|
if (state) {
|
|
441
|
+
state = ensureLTHashStateVersion(state);
|
|
383
442
|
if (typeof initialVersionMap[name] === 'undefined') {
|
|
384
443
|
initialVersionMap[name] = state.version;
|
|
385
444
|
}
|
|
@@ -388,14 +447,18 @@ export const makeChatsSocket = (config) => {
|
|
|
388
447
|
state = newLTHashState();
|
|
389
448
|
}
|
|
390
449
|
states[name] = state;
|
|
391
|
-
|
|
450
|
+
const shouldForceSnapshot = forceSnapshotCollections.has(name);
|
|
451
|
+
if (shouldForceSnapshot) {
|
|
452
|
+
forceSnapshotCollections.delete(name);
|
|
453
|
+
}
|
|
454
|
+
logger.info(`resyncing ${name} from v${state.version}${shouldForceSnapshot ? ' (forcing snapshot)' : ''}`);
|
|
392
455
|
nodes.push({
|
|
393
456
|
tag: 'collection',
|
|
394
457
|
attrs: {
|
|
395
458
|
name,
|
|
396
459
|
version: state.version.toString(),
|
|
397
|
-
// return snapshot if
|
|
398
|
-
return_snapshot: (!state.version).toString()
|
|
460
|
+
// return snapshot if syncing from scratch or forcing after a failed attempt
|
|
461
|
+
return_snapshot: (shouldForceSnapshot || !state.version).toString()
|
|
399
462
|
}
|
|
400
463
|
});
|
|
401
464
|
}
|
|
@@ -421,7 +484,7 @@ export const makeChatsSocket = (config) => {
|
|
|
421
484
|
const { patches, hasMorePatches, snapshot } = decoded[name];
|
|
422
485
|
try {
|
|
423
486
|
if (snapshot) {
|
|
424
|
-
const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot);
|
|
487
|
+
const { state: newState, mutationMap } = await decodeSyncdSnapshot(name, snapshot, getCachedAppStateSyncKey, initialVersionMap[name], appStateMacVerification.snapshot, logger);
|
|
425
488
|
states[name] = newState;
|
|
426
489
|
Object.assign(globalMutationMap, mutationMap);
|
|
427
490
|
logger.info(`restored state of ${name} from snapshot to v${newState.version} with mutations`);
|
|
@@ -444,19 +507,37 @@ export const makeChatsSocket = (config) => {
|
|
|
444
507
|
}
|
|
445
508
|
}
|
|
446
509
|
catch (error) {
|
|
447
|
-
// if retry attempts overshoot
|
|
448
|
-
// or key not found
|
|
449
|
-
const isIrrecoverableError = attemptsMap[name] >= MAX_SYNC_ATTEMPTS ||
|
|
450
|
-
error.output?.statusCode === 404 ||
|
|
451
|
-
error.name === 'TypeError';
|
|
452
|
-
logger.info({ name, error: error.stack }, `failed to sync state from version${isIrrecoverableError ? '' : ', removing and trying from scratch'}`);
|
|
453
|
-
await authState.keys.set({ 'app-state-sync-version': { [name]: null } });
|
|
454
|
-
// increment number of retries
|
|
455
510
|
attemptsMap[name] = (attemptsMap[name] || 0) + 1;
|
|
456
|
-
|
|
457
|
-
|
|
511
|
+
const logData = {
|
|
512
|
+
name,
|
|
513
|
+
attempt: attemptsMap[name],
|
|
514
|
+
version: states[name].version,
|
|
515
|
+
statusCode: error.output?.statusCode,
|
|
516
|
+
errorType: error.name,
|
|
517
|
+
error: error.stack
|
|
518
|
+
};
|
|
519
|
+
if (isMissingKeyError(error) && attemptsMap[name] >= MAX_SYNC_ATTEMPTS) {
|
|
520
|
+
// WA Web treats missing keys as "Blocked" — park the collection
|
|
521
|
+
// until the key arrives via APP_STATE_SYNC_KEY_SHARE.
|
|
522
|
+
logger.warn(logData, `${name} blocked on missing key from v${states[name].version}, parking after ${attemptsMap[name]} attempts`);
|
|
523
|
+
blockedCollections.add(name);
|
|
458
524
|
collectionsToHandle.delete(name);
|
|
459
525
|
}
|
|
526
|
+
else if (isMissingKeyError(error)) {
|
|
527
|
+
// Retry with a snapshot which may use a different key.
|
|
528
|
+
logger.info(logData, `${name} blocked on missing key from v${states[name].version}, retrying with snapshot`);
|
|
529
|
+
forceSnapshotCollections.add(name);
|
|
530
|
+
}
|
|
531
|
+
else if (isAppStateSyncIrrecoverable(error, attemptsMap[name])) {
|
|
532
|
+
logger.warn(logData, `failed to sync ${name} from v${states[name].version}, giving up`);
|
|
533
|
+
collectionsToHandle.delete(name);
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
logger.info(logData, `failed to sync ${name} from v${states[name].version}, forcing snapshot retry`);
|
|
537
|
+
// force a full snapshot on retry to recover from
|
|
538
|
+
// corrupted local state (e.g. LTHash MAC mismatch)
|
|
539
|
+
forceSnapshotCollections.add(name);
|
|
540
|
+
}
|
|
460
541
|
}
|
|
461
542
|
}
|
|
462
543
|
}
|
|
@@ -466,14 +547,68 @@ export const makeChatsSocket = (config) => {
|
|
|
466
547
|
onMutation(globalMutationMap[key]);
|
|
467
548
|
}
|
|
468
549
|
});
|
|
550
|
+
/**
|
|
551
|
+
* Fija o desfija un chat en la parte superior de la lista de chats.
|
|
552
|
+
*/
|
|
553
|
+
const pinChat = (jid, pin = true) => {
|
|
554
|
+
return chatModify({ pin }, jid);
|
|
555
|
+
};
|
|
556
|
+
/**
|
|
557
|
+
* Archiva o desarchiva un chat. Si se pasan `lastMessages`, se usan para
|
|
558
|
+
* calcular el rango de mensajes que WhatsApp debe archivar/desarchivar.
|
|
559
|
+
*/
|
|
560
|
+
const archiveChat = (jid, archive = true, lastMessages) => {
|
|
561
|
+
return chatModify({ archive, lastMessages }, jid);
|
|
562
|
+
};
|
|
563
|
+
/**
|
|
564
|
+
* Silencia un chat. `muteEndTimestamp` es el timestamp (ms) hasta el que
|
|
565
|
+
* estará silenciado; pasa `undefined`/`null` (o llama con `false`) para
|
|
566
|
+
* quitar el silencio.
|
|
567
|
+
*/
|
|
568
|
+
const muteChat = (jid, muteEndTimestamp) => {
|
|
569
|
+
return chatModify({ mute: muteEndTimestamp || undefined }, jid);
|
|
570
|
+
};
|
|
571
|
+
/**
|
|
572
|
+
* Marca un chat como leído o no leído.
|
|
573
|
+
*/
|
|
574
|
+
const markChatRead = (jid, read = true, lastMessages) => {
|
|
575
|
+
return chatModify({ markRead: read, lastMessages }, jid);
|
|
576
|
+
};
|
|
577
|
+
/** Atajo para marcar un chat como no leído. */
|
|
578
|
+
const markChatUnread = (jid, lastMessages) => markChatRead(jid, false, lastMessages);
|
|
579
|
+
/**
|
|
580
|
+
* Vacía el historial de un chat (sin eliminar el chat en sí).
|
|
581
|
+
*/
|
|
582
|
+
const clearChat = (jid, lastMessages) => {
|
|
583
|
+
return chatModify({ clear: true, lastMessages }, jid);
|
|
584
|
+
};
|
|
585
|
+
/**
|
|
586
|
+
* Elimina un chat completo de la lista de chats.
|
|
587
|
+
*/
|
|
588
|
+
const deleteChat = (jid, lastMessages) => {
|
|
589
|
+
return chatModify({ delete: true, lastMessages }, jid);
|
|
590
|
+
};
|
|
469
591
|
/**
|
|
470
592
|
* fetch the profile picture of a user/group
|
|
471
593
|
* type = "preview" for a low res picture
|
|
472
594
|
* type = "image for the high res picture"
|
|
473
595
|
*/
|
|
474
596
|
const profilePictureUrl = async (jid, type = 'preview', timeoutMs) => {
|
|
475
|
-
|
|
476
|
-
|
|
597
|
+
// WA Web only includes tctoken for user JIDs (not groups/newsletters)
|
|
598
|
+
// and never for own profile pic (Chat model for self has no tcToken).
|
|
599
|
+
// Including tctoken for own JID causes the server to never respond.
|
|
600
|
+
const normalizedJid = jidNormalizedUser(jid);
|
|
601
|
+
const isUserJid = isPnUser(normalizedJid) || isLidUser(normalizedJid);
|
|
602
|
+
const me = authState.creds.me;
|
|
603
|
+
const isSelf = me && (normalizedJid === jidNormalizedUser(me.id) || (me.lid && normalizedJid === jidNormalizedUser(me.lid)));
|
|
604
|
+
let tcTokenContent;
|
|
605
|
+
if (serverProps.profilePicPrivacyToken && isUserJid && !isSelf) {
|
|
606
|
+
tcTokenContent = await buildTcTokenFromJid({
|
|
607
|
+
authState,
|
|
608
|
+
jid: normalizedJid,
|
|
609
|
+
getLIDForPN
|
|
610
|
+
});
|
|
611
|
+
}
|
|
477
612
|
jid = jidNormalizedUser(jid);
|
|
478
613
|
const result = await query({
|
|
479
614
|
tag: 'iq',
|
|
@@ -483,7 +618,7 @@ export const makeChatsSocket = (config) => {
|
|
|
483
618
|
type: 'get',
|
|
484
619
|
xmlns: 'w:profile:picture'
|
|
485
620
|
},
|
|
486
|
-
content: tcTokenContent
|
|
621
|
+
content: buildProfilePictureQueryContent(type, tcTokenContent)
|
|
487
622
|
}, timeoutMs);
|
|
488
623
|
const child = getBinaryNodeChild(result, 'picture');
|
|
489
624
|
return child?.attrs?.url;
|
|
@@ -549,7 +684,12 @@ export const makeChatsSocket = (config) => {
|
|
|
549
684
|
* @param tcToken token for subscription, use if present
|
|
550
685
|
*/
|
|
551
686
|
const presenceSubscribe = async (toJid) => {
|
|
552
|
-
|
|
687
|
+
// Only include tctoken for user JIDs — groups/newsletters don't use tctokens
|
|
688
|
+
const normalizedToJid = jidNormalizedUser(toJid);
|
|
689
|
+
const isUserJid = isPnUser(normalizedToJid) || isLidUser(normalizedToJid);
|
|
690
|
+
const tcTokenContent = isUserJid
|
|
691
|
+
? await buildTcTokenFromJid({ authState, jid: normalizedToJid, getLIDForPN })
|
|
692
|
+
: undefined;
|
|
553
693
|
return sendNode({
|
|
554
694
|
tag: 'presence',
|
|
555
695
|
attrs: {
|
|
@@ -570,7 +710,8 @@ export const makeChatsSocket = (config) => {
|
|
|
570
710
|
if (tag === 'presence') {
|
|
571
711
|
presence = {
|
|
572
712
|
lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
|
|
573
|
-
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
|
|
713
|
+
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined,
|
|
714
|
+
groupOnlineCount: attrs.count ? +attrs.count : undefined
|
|
574
715
|
};
|
|
575
716
|
}
|
|
576
717
|
else if (Array.isArray(content)) {
|
|
@@ -604,7 +745,7 @@ export const makeChatsSocket = (config) => {
|
|
|
604
745
|
logger.debug({ patch: patchCreate }, 'applying app patch');
|
|
605
746
|
await resyncAppState([name], false);
|
|
606
747
|
const { [name]: currentSyncVersion } = await authState.keys.get('app-state-sync-version', [name]);
|
|
607
|
-
initial = currentSyncVersion
|
|
748
|
+
initial = currentSyncVersion ? ensureLTHashStateVersion(currentSyncVersion) : newLTHashState();
|
|
608
749
|
encodeResult = await encodeSyncdPatch(patchCreate, myAppStateKeyId, initial, getAppStateSyncKey);
|
|
609
750
|
const { patch, state } = encodeResult;
|
|
610
751
|
const node = {
|
|
@@ -650,22 +791,21 @@ export const makeChatsSocket = (config) => {
|
|
|
650
791
|
}
|
|
651
792
|
}
|
|
652
793
|
};
|
|
653
|
-
/**
|
|
794
|
+
/** fetch AB props */
|
|
654
795
|
const fetchProps = async () => {
|
|
655
|
-
//TODO: implement both protocol 1 and protocol 2 prop fetching, specially for abKey for WM
|
|
656
796
|
const resultNode = await query({
|
|
657
797
|
tag: 'iq',
|
|
658
798
|
attrs: {
|
|
659
799
|
to: S_WHATSAPP_NET,
|
|
660
|
-
xmlns: '
|
|
800
|
+
xmlns: 'abt',
|
|
661
801
|
type: 'get'
|
|
662
802
|
},
|
|
663
803
|
content: [
|
|
664
804
|
{
|
|
665
805
|
tag: 'props',
|
|
666
806
|
attrs: {
|
|
667
|
-
protocol: '
|
|
668
|
-
hash: authState
|
|
807
|
+
protocol: '1',
|
|
808
|
+
...(authState?.creds?.lastPropHash ? { hash: authState.creds.lastPropHash } : {})
|
|
669
809
|
}
|
|
670
810
|
}
|
|
671
811
|
]
|
|
@@ -680,7 +820,20 @@ export const makeChatsSocket = (config) => {
|
|
|
680
820
|
}
|
|
681
821
|
props = reduceBinaryNodeToDictionary(propsNode, 'prop');
|
|
682
822
|
}
|
|
683
|
-
|
|
823
|
+
// Extract protocol-relevant AB props (only the ones we need)
|
|
824
|
+
const privacyTokenProp = props['10518'] ?? props['privacy_token_sending_on_all_1_on_1_messages'];
|
|
825
|
+
if (privacyTokenProp !== undefined) {
|
|
826
|
+
serverProps.privacyTokenOn1to1 = privacyTokenProp === 'true' || privacyTokenProp === '1';
|
|
827
|
+
}
|
|
828
|
+
const profilePicProp = props['9666'] ?? props['profile_scraping_privacy_token_in_photo_iq'];
|
|
829
|
+
if (profilePicProp !== undefined) {
|
|
830
|
+
serverProps.profilePicPrivacyToken = profilePicProp === 'true' || profilePicProp === '1';
|
|
831
|
+
}
|
|
832
|
+
const lidIssueProp = props['14303'] ?? props['lid_trusted_token_issue_to_lid'];
|
|
833
|
+
if (lidIssueProp !== undefined) {
|
|
834
|
+
serverProps.lidTrustedTokenIssueToLid = lidIssueProp === 'true' || lidIssueProp === '1';
|
|
835
|
+
}
|
|
836
|
+
logger.debug({ serverProps }, 'fetched props');
|
|
684
837
|
return props;
|
|
685
838
|
};
|
|
686
839
|
/**
|
|
@@ -820,6 +973,47 @@ export const makeChatsSocket = (config) => {
|
|
|
820
973
|
? shouldSyncHistoryMessage(historyMsg) &&
|
|
821
974
|
PROCESSABLE_HISTORY_TYPES.includes(historyMsg.syncType)
|
|
822
975
|
: false;
|
|
976
|
+
if (historyMsg && shouldProcessHistoryMsg) {
|
|
977
|
+
const syncType = historyMsg.syncType;
|
|
978
|
+
// INITIAL_BOOTSTRAP — fire immediately, no progress check (same as WA Web K function)
|
|
979
|
+
if (syncType === proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP &&
|
|
980
|
+
!historySyncStatus.initialBootstrapComplete) {
|
|
981
|
+
historySyncStatus.initialBootstrapComplete = true;
|
|
982
|
+
ev.emit('messaging-history.status', {
|
|
983
|
+
syncType,
|
|
984
|
+
status: 'complete',
|
|
985
|
+
explicit: true
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
// RECENT with progress === 100 — explicit completion
|
|
989
|
+
if (syncType === proto.HistorySync.HistorySyncType.RECENT &&
|
|
990
|
+
historyMsg.progress === 100 &&
|
|
991
|
+
!historySyncStatus.recentSyncComplete) {
|
|
992
|
+
historySyncStatus.recentSyncComplete = true;
|
|
993
|
+
clearTimeout(historySyncPausedTimeout);
|
|
994
|
+
historySyncPausedTimeout = undefined;
|
|
995
|
+
ev.emit('messaging-history.status', {
|
|
996
|
+
syncType,
|
|
997
|
+
status: 'complete',
|
|
998
|
+
explicit: true
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
// Reset 120s paused timeout on any RECENT chunk (like WA Web's handleChunkProgress)
|
|
1002
|
+
if (syncType === proto.HistorySync.HistorySyncType.RECENT && !historySyncStatus.recentSyncComplete) {
|
|
1003
|
+
clearTimeout(historySyncPausedTimeout);
|
|
1004
|
+
historySyncPausedTimeout = setTimeout(() => {
|
|
1005
|
+
if (!historySyncStatus.recentSyncComplete) {
|
|
1006
|
+
historySyncStatus.recentSyncComplete = true;
|
|
1007
|
+
ev.emit('messaging-history.status', {
|
|
1008
|
+
syncType: proto.HistorySync.HistorySyncType.RECENT,
|
|
1009
|
+
status: 'paused',
|
|
1010
|
+
explicit: false
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
historySyncPausedTimeout = undefined;
|
|
1014
|
+
}, HISTORY_SYNC_PAUSED_TIMEOUT_MS);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
823
1017
|
// State machine: decide on sync and flush
|
|
824
1018
|
if (historyMsg && syncState === SyncState.AwaitingInitialSync) {
|
|
825
1019
|
if (awaitingSyncTimeout) {
|
|
@@ -839,6 +1033,8 @@ export const makeChatsSocket = (config) => {
|
|
|
839
1033
|
}
|
|
840
1034
|
const doAppStateSync = async () => {
|
|
841
1035
|
if (syncState === SyncState.Syncing) {
|
|
1036
|
+
// All collections will be synced, so clear any blocked ones
|
|
1037
|
+
blockedCollections.clear();
|
|
842
1038
|
logger.info('Doing app state sync');
|
|
843
1039
|
await resyncAppState(ALL_WA_PATCH_NAMES, true);
|
|
844
1040
|
// Sync is complete, go online and flush everything
|
|
@@ -898,6 +1094,11 @@ export const makeChatsSocket = (config) => {
|
|
|
898
1094
|
}
|
|
899
1095
|
});
|
|
900
1096
|
ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
|
|
1097
|
+
if (connection === 'close') {
|
|
1098
|
+
blockedCollections.clear();
|
|
1099
|
+
clearTimeout(historySyncPausedTimeout);
|
|
1100
|
+
historySyncPausedTimeout = undefined;
|
|
1101
|
+
}
|
|
901
1102
|
if (connection === 'open') {
|
|
902
1103
|
if (fireInitQueries) {
|
|
903
1104
|
executeInitQueries().catch(error => onUnexpectedError(error, 'init queries'));
|
|
@@ -907,6 +1108,10 @@ export const makeChatsSocket = (config) => {
|
|
|
907
1108
|
if (!receivedPendingNotifications || syncState !== SyncState.Connecting) {
|
|
908
1109
|
return;
|
|
909
1110
|
}
|
|
1111
|
+
historySyncStatus.initialBootstrapComplete = false;
|
|
1112
|
+
historySyncStatus.recentSyncComplete = false;
|
|
1113
|
+
clearTimeout(historySyncPausedTimeout);
|
|
1114
|
+
historySyncPausedTimeout = undefined;
|
|
910
1115
|
syncState = SyncState.AwaitingInitialSync;
|
|
911
1116
|
logger.info('Connection is now AwaitingInitialSync, buffering events');
|
|
912
1117
|
ev.buffer();
|
|
@@ -919,19 +1124,49 @@ export const makeChatsSocket = (config) => {
|
|
|
919
1124
|
setTimeout(() => ev.flush(), 0);
|
|
920
1125
|
return;
|
|
921
1126
|
}
|
|
922
|
-
|
|
1127
|
+
// On reconnection (accountSyncCounter > 0), the server does not push
|
|
1128
|
+
// history sync notifications — the device already has its data.
|
|
1129
|
+
// Skip the 20s wait and go online immediately.
|
|
1130
|
+
if (authState.creds.accountSyncCounter > 0) {
|
|
1131
|
+
logger.info('Reconnection with existing sync data, skipping history sync wait. Transitioning to Online.');
|
|
1132
|
+
syncState = SyncState.Online;
|
|
1133
|
+
setTimeout(() => ev.flush(), 0);
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
logger.info('First connection, awaiting history sync notification with a 20s timeout.');
|
|
923
1137
|
if (awaitingSyncTimeout) {
|
|
924
1138
|
clearTimeout(awaitingSyncTimeout);
|
|
925
1139
|
}
|
|
926
1140
|
awaitingSyncTimeout = setTimeout(() => {
|
|
927
1141
|
if (syncState === SyncState.AwaitingInitialSync) {
|
|
928
|
-
// TODO: investigate
|
|
929
1142
|
logger.warn('Timeout in AwaitingInitialSync, forcing state to Online and flushing buffer');
|
|
930
1143
|
syncState = SyncState.Online;
|
|
931
1144
|
ev.flush();
|
|
1145
|
+
// Increment so subsequent reconnections skip the 20s wait.
|
|
1146
|
+
// Late-arriving history is still processed via processMessage
|
|
1147
|
+
// regardless of the state machine phase.
|
|
1148
|
+
const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1;
|
|
1149
|
+
ev.emit('creds.update', { accountSyncCounter });
|
|
932
1150
|
}
|
|
933
1151
|
}, 20000);
|
|
934
1152
|
});
|
|
1153
|
+
// When an app state sync key arrives (myAppStateKeyId is set) and there are
|
|
1154
|
+
// collections blocked on a missing key, trigger a re-sync for just those collections.
|
|
1155
|
+
// This mirrors WA Web's Blocked → retry-on-key-arrival behavior.
|
|
1156
|
+
ev.on('creds.update', ({ myAppStateKeyId }) => {
|
|
1157
|
+
if (!myAppStateKeyId || blockedCollections.size === 0) {
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
1160
|
+
// If we're in the middle of a full sync, doAppStateSync handles all collections
|
|
1161
|
+
if (syncState === SyncState.Syncing) {
|
|
1162
|
+
blockedCollections.clear();
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const collections = [...blockedCollections];
|
|
1166
|
+
blockedCollections.clear();
|
|
1167
|
+
logger.info({ collections }, 'app state sync key arrived, re-syncing blocked collections');
|
|
1168
|
+
resyncAppState(collections, false).catch(error => onUnexpectedError(error, 'blocked collections resync'));
|
|
1169
|
+
});
|
|
935
1170
|
ev.on('lid-mapping.update', async ({ lid, pn }) => {
|
|
936
1171
|
try {
|
|
937
1172
|
await signalRepository.lidMapping.storeLIDPNMappings([{ lid, pn }]);
|
|
@@ -940,8 +1175,20 @@ export const makeChatsSocket = (config) => {
|
|
|
940
1175
|
logger.warn({ lid, pn, error }, 'Failed to store LID-PN mapping');
|
|
941
1176
|
}
|
|
942
1177
|
});
|
|
1178
|
+
registerSocketEndHandler(() => {
|
|
1179
|
+
if (awaitingSyncTimeout) {
|
|
1180
|
+
clearTimeout(awaitingSyncTimeout);
|
|
1181
|
+
awaitingSyncTimeout = undefined;
|
|
1182
|
+
}
|
|
1183
|
+
if (!config.placeholderResendCache && placeholderResendCache.close) {
|
|
1184
|
+
placeholderResendCache.close();
|
|
1185
|
+
}
|
|
1186
|
+
syncState = SyncState.Connecting;
|
|
1187
|
+
privacySettings = undefined;
|
|
1188
|
+
});
|
|
943
1189
|
return {
|
|
944
1190
|
...sock,
|
|
1191
|
+
serverProps,
|
|
945
1192
|
createCallLink,
|
|
946
1193
|
getBotListV2,
|
|
947
1194
|
messageMutex,
|
|
@@ -978,12 +1225,20 @@ export const makeChatsSocket = (config) => {
|
|
|
978
1225
|
cleanDirtyBits,
|
|
979
1226
|
addOrEditContact,
|
|
980
1227
|
removeContact,
|
|
1228
|
+
placeholderResendCache,
|
|
981
1229
|
addLabel,
|
|
982
1230
|
addChatLabel,
|
|
983
1231
|
removeChatLabel,
|
|
984
1232
|
addMessageLabel,
|
|
985
1233
|
removeMessageLabel,
|
|
986
1234
|
star,
|
|
1235
|
+
pinChat,
|
|
1236
|
+
archiveChat,
|
|
1237
|
+
muteChat,
|
|
1238
|
+
markChatRead,
|
|
1239
|
+
markChatUnread,
|
|
1240
|
+
clearChat,
|
|
1241
|
+
deleteChat,
|
|
987
1242
|
addOrEditQuickReply,
|
|
988
1243
|
removeQuickReply
|
|
989
1244
|
};
|
package/lib/Socket/groups.d.ts
CHANGED
|
@@ -3,6 +3,22 @@ import type { GroupMetadata, ParticipantAction, SocketConfig, WAMessageKey } fro
|
|
|
3
3
|
import { type BinaryNode } from '../WABinary/index.js';
|
|
4
4
|
export declare const makeGroupsSocket: (config: SocketConfig) => {
|
|
5
5
|
groupMetadata: (jid: string) => Promise<GroupMetadata>;
|
|
6
|
+
/** groupMetadata con cache de 30s, invalidado automáticamente ante cambios reales de participantes. */
|
|
7
|
+
groupMetadataCached: (jid: string) => Promise<GroupMetadata>;
|
|
8
|
+
/**
|
|
9
|
+
* Resuelve un jid/@lid a su jid de número de teléfono real usando primero los participantes
|
|
10
|
+
* del grupo y, si no hay coincidencia, el mapeo LID↔PN nativo de Baileys (signalRepository).
|
|
11
|
+
* @param jidOrChatId el chatId del grupo, o directamente el array de participantes ya obtenido
|
|
12
|
+
* @param targetJid el jid/lid a resolver
|
|
13
|
+
*/
|
|
14
|
+
resolveParticipantJid: (jidOrChatId: string | GroupMetadata["participants"], targetJid: string) => Promise<string>;
|
|
15
|
+
/** true si el participante (jid o @lid) es admin/superadmin del grupo. */
|
|
16
|
+
isGroupAdmin: (jid: string, participantJid: string) => Promise<boolean>;
|
|
17
|
+
/** Lista de admins del grupo ya resueltos a jid de número de teléfono. */
|
|
18
|
+
getGroupAdmins: (jid: string) => Promise<{
|
|
19
|
+
jid: string;
|
|
20
|
+
admin: "admin" | "superadmin" | null;
|
|
21
|
+
}[]>;
|
|
6
22
|
groupCreate: (subject: string, participants: string[]) => Promise<GroupMetadata>;
|
|
7
23
|
groupLeave: (id: string) => Promise<void>;
|
|
8
24
|
groupUpdateSubject: (jid: string, subject: string) => Promise<void>;
|