@ubedsockets/baileys 1.6.4 → 1.6.6
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/engine-requirements.js +10 -0
- package/lib/Defaults/index.d.ts +75 -0
- package/lib/Defaults/index.d.ts.map +1 -0
- package/lib/Defaults/index.js +76 -92
- package/lib/Defaults/index.js.map +1 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +10 -0
- package/lib/Signal/Group/ciphertext-message.d.ts.map +1 -0
- package/lib/Signal/Group/ciphertext-message.js +2 -5
- package/lib/Signal/Group/ciphertext-message.js.map +1 -0
- package/lib/Signal/Group/group-session-builder.d.ts +15 -0
- package/lib/Signal/Group/group-session-builder.d.ts.map +1 -0
- package/lib/Signal/Group/group-session-builder.js +7 -41
- package/lib/Signal/Group/group-session-builder.js.map +1 -0
- package/lib/Signal/Group/group_cipher.d.ts +17 -0
- package/lib/Signal/Group/group_cipher.d.ts.map +1 -0
- package/lib/Signal/Group/group_cipher.js +37 -51
- package/lib/Signal/Group/group_cipher.js.map +1 -0
- package/lib/Signal/Group/index.d.ts +12 -0
- package/lib/Signal/Group/index.d.ts.map +1 -0
- package/lib/Signal/Group/index.js +12 -57
- package/lib/Signal/Group/index.js.map +1 -0
- package/lib/Signal/Group/keyhelper.d.ts +11 -0
- package/lib/Signal/Group/keyhelper.d.ts.map +1 -0
- package/lib/Signal/Group/keyhelper.js +7 -44
- package/lib/Signal/Group/keyhelper.js.map +1 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +14 -0
- package/lib/Signal/Group/sender-chain-key.d.ts.map +1 -0
- package/lib/Signal/Group/sender-chain-key.js +7 -15
- package/lib/Signal/Group/sender-chain-key.js.map +1 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +17 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +8 -11
- package/lib/Signal/Group/sender-key-distribution-message.js.map +1 -0
- package/lib/Signal/Group/sender-key-message.d.ts +19 -0
- package/lib/Signal/Group/sender-key-message.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-message.js +9 -12
- package/lib/Signal/Group/sender-key-message.js.map +1 -0
- package/lib/Signal/Group/sender-key-name.d.ts +18 -0
- package/lib/Signal/Group/sender-key-name.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-name.js +2 -5
- package/lib/Signal/Group/sender-key-name.js.map +1 -0
- package/lib/Signal/Group/sender-key-record.d.ts +31 -0
- package/lib/Signal/Group/sender-key-record.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-record.js +9 -21
- package/lib/Signal/Group/sender-key-record.js.map +1 -0
- package/lib/Signal/Group/sender-key-state.d.ts +39 -0
- package/lib/Signal/Group/sender-key-state.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-state.js +27 -42
- package/lib/Signal/Group/sender-key-state.js.map +1 -0
- package/lib/Signal/Group/sender-message-key.d.ts +12 -0
- package/lib/Signal/Group/sender-message-key.d.ts.map +1 -0
- package/lib/Signal/Group/sender-message-key.js +4 -7
- package/lib/Signal/Group/sender-message-key.js.map +1 -0
- package/lib/Signal/libsignal.d.ts +5 -0
- package/lib/Signal/libsignal.d.ts.map +1 -0
- package/lib/Signal/libsignal.js +347 -90
- package/lib/Signal/libsignal.js.map +1 -0
- package/lib/Signal/lid-mapping.d.ts +23 -0
- package/lib/Signal/lid-mapping.d.ts.map +1 -0
- package/lib/Signal/lid-mapping.js +277 -0
- package/lib/Signal/lid-mapping.js.map +1 -0
- package/lib/Socket/Client/index.d.ts +3 -0
- package/lib/Socket/Client/index.d.ts.map +1 -0
- package/lib/Socket/Client/index.js +3 -18
- package/lib/Socket/Client/index.js.map +1 -0
- package/lib/Socket/Client/types.d.ts +16 -0
- package/lib/Socket/Client/types.d.ts.map +1 -0
- package/lib/Socket/Client/types.js +4 -6
- package/lib/Socket/Client/types.js.map +1 -0
- package/lib/Socket/Client/websocket.d.ts +13 -0
- package/lib/Socket/Client/websocket.d.ts.map +1 -0
- package/lib/Socket/Client/websocket.js +21 -78
- package/lib/Socket/Client/websocket.js.map +1 -0
- package/lib/Socket/business.d.ts +217 -0
- package/lib/Socket/business.d.ts.map +1 -0
- package/lib/Socket/business.js +162 -43
- package/lib/Socket/business.js.map +1 -0
- package/lib/Socket/chats.d.ts +124 -0
- package/lib/Socket/chats.d.ts.map +1 -0
- package/lib/Socket/chats.js +571 -249
- package/lib/Socket/chats.js.map +1 -0
- package/lib/Socket/communities.d.ts +273 -0
- package/lib/Socket/communities.d.ts.map +1 -0
- package/lib/Socket/communities.js +431 -0
- package/lib/Socket/communities.js.map +1 -0
- package/lib/Socket/groups.d.ts +161 -0
- package/lib/Socket/groups.d.ts.map +1 -0
- package/lib/Socket/groups.js +114 -99
- package/lib/Socket/groups.js.map +1 -0
- package/lib/Socket/index.d.ts +260 -0
- package/lib/Socket/index.d.ts.map +1 -0
- package/lib/Socket/index.js +11 -9
- package/lib/Socket/index.js.map +1 -0
- package/lib/Socket/messages-recv.d.ts +203 -0
- package/lib/Socket/messages-recv.d.ts.map +1 -0
- package/lib/Socket/messages-recv.js +1277 -559
- package/lib/Socket/messages-recv.js.map +1 -0
- package/lib/Socket/messages-send.d.ts +199 -0
- package/lib/Socket/messages-send.d.ts.map +1 -0
- package/lib/Socket/messages-send.js +674 -669
- package/lib/Socket/messages-send.js.map +1 -0
- package/lib/Socket/mex.d.ts +3 -0
- package/lib/Socket/mex.d.ts.map +1 -0
- package/lib/Socket/mex.js +42 -0
- package/lib/Socket/mex.js.map +1 -0
- package/lib/Socket/newsletter.d.ts +170 -0
- package/lib/Socket/newsletter.d.ts.map +1 -0
- package/lib/Socket/newsletter.js +149 -286
- package/lib/Socket/newsletter.js.map +1 -0
- package/lib/Socket/socket.d.ts +59 -0
- package/lib/Socket/socket.d.ts.map +1 -0
- package/lib/Socket/socket.js +548 -235
- package/lib/Socket/socket.js.map +1 -0
- package/lib/Types/Auth.d.ts +117 -0
- package/lib/Types/Auth.d.ts.map +1 -0
- package/lib/Types/Auth.js +2 -2
- package/lib/Types/Auth.js.map +1 -0
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Bussines.d.ts.map +1 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Bussines.js.map +1 -0
- package/lib/Types/Call.d.ts +15 -0
- package/lib/Types/Call.d.ts.map +1 -0
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Call.js.map +1 -0
- package/lib/Types/Chat.d.ts +124 -0
- package/lib/Types/Chat.d.ts.map +1 -0
- package/lib/Types/Chat.js +8 -4
- package/lib/Types/Chat.js.map +1 -0
- package/lib/Types/Contact.d.ts +26 -0
- package/lib/Types/Contact.d.ts.map +1 -0
- package/lib/Types/Contact.js +2 -2
- package/lib/Types/Contact.js.map +1 -0
- package/lib/Types/Events.d.ts +256 -0
- package/lib/Types/Events.d.ts.map +1 -0
- package/lib/Types/Events.js +2 -2
- package/lib/Types/Events.js.map +1 -0
- package/lib/Types/GroupMetadata.d.ts +71 -0
- package/lib/Types/GroupMetadata.d.ts.map +1 -0
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/GroupMetadata.js.map +1 -0
- package/lib/Types/Label.d.ts +47 -0
- package/lib/Types/Label.d.ts.map +1 -0
- package/lib/Types/Label.js +3 -5
- package/lib/Types/Label.js.map +1 -0
- package/lib/Types/LabelAssociation.d.ts +30 -0
- package/lib/Types/LabelAssociation.d.ts.map +1 -0
- package/lib/Types/LabelAssociation.js +3 -5
- package/lib/Types/LabelAssociation.js.map +1 -0
- package/lib/Types/Message.d.ts +320 -0
- package/lib/Types/Message.d.ts.map +1 -0
- package/lib/Types/Message.js +11 -7
- package/lib/Types/Message.js.map +1 -0
- package/lib/Types/Mex.d.ts +141 -0
- package/lib/Types/Mex.d.ts.map +1 -0
- package/lib/Types/Mex.js +37 -0
- package/lib/Types/Mex.js.map +1 -0
- package/lib/Types/Product.d.ts +79 -0
- package/lib/Types/Product.d.ts.map +1 -0
- package/lib/Types/Product.js +2 -2
- package/lib/Types/Product.js.map +1 -0
- package/lib/Types/Signal.d.ts +87 -0
- package/lib/Types/Signal.d.ts.map +1 -0
- package/lib/Types/Signal.js +2 -2
- package/lib/Types/Signal.js.map +1 -0
- package/lib/Types/Socket.d.ts +136 -0
- package/lib/Types/Socket.d.ts.map +1 -0
- package/lib/Types/Socket.js +3 -2
- package/lib/Types/Socket.js.map +1 -0
- package/lib/Types/State.d.ts +97 -0
- package/lib/Types/State.d.ts.map +1 -0
- package/lib/Types/State.js +56 -2
- package/lib/Types/State.js.map +1 -0
- package/lib/Types/USync.d.ts +26 -0
- package/lib/Types/USync.d.ts.map +1 -0
- package/lib/Types/USync.js +2 -2
- package/lib/Types/USync.js.map +1 -0
- package/lib/Types/index.d.ts +65 -0
- package/lib/Types/index.d.ts.map +1 -0
- package/lib/Types/index.js +15 -31
- package/lib/Types/index.js.map +1 -0
- package/lib/Utils/auth-utils.d.ts +24 -0
- package/lib/Utils/auth-utils.d.ts.map +1 -0
- package/lib/Utils/auth-utils.js +239 -136
- package/lib/Utils/auth-utils.js.map +1 -0
- package/lib/Utils/browser-utils.d.ts +4 -0
- package/lib/Utils/browser-utils.d.ts.map +1 -0
- package/lib/Utils/browser-utils.js +28 -0
- package/lib/Utils/browser-utils.js.map +1 -0
- package/lib/Utils/business.d.ts +23 -0
- package/lib/Utils/business.d.ts.map +1 -0
- package/lib/Utils/business.js +66 -69
- package/lib/Utils/business.js.map +1 -0
- package/lib/Utils/chat-utils.d.ts +100 -0
- package/lib/Utils/chat-utils.d.ts.map +1 -0
- package/lib/Utils/chat-utils.js +380 -238
- package/lib/Utils/chat-utils.js.map +1 -0
- package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
- package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
- package/lib/Utils/companion-reg-client-utils.js +35 -0
- package/lib/Utils/companion-reg-client-utils.js.map +1 -0
- package/lib/Utils/crypto.d.ts +37 -0
- package/lib/Utils/crypto.d.ts.map +1 -0
- package/lib/Utils/crypto.js +56 -127
- package/lib/Utils/crypto.js.map +1 -0
- package/lib/Utils/decode-wa-message.d.ts +66 -0
- package/lib/Utils/decode-wa-message.d.ts.map +1 -0
- package/lib/Utils/decode-wa-message.js +173 -63
- package/lib/Utils/decode-wa-message.js.map +1 -0
- package/lib/Utils/event-buffer.d.ts +36 -0
- package/lib/Utils/event-buffer.d.ts.map +1 -0
- package/lib/Utils/event-buffer.js +174 -70
- package/lib/Utils/event-buffer.js.map +1 -0
- package/lib/Utils/generics.d.ts +91 -0
- package/lib/Utils/generics.d.ts.map +1 -0
- package/lib/Utils/generics.js +159 -207
- package/lib/Utils/generics.js.map +1 -0
- package/lib/Utils/history.d.ts +24 -0
- package/lib/Utils/history.d.ts.map +1 -0
- package/lib/Utils/history.js +93 -53
- package/lib/Utils/history.js.map +1 -0
- package/lib/Utils/identity-change-handler.d.ts +44 -0
- package/lib/Utils/identity-change-handler.d.ts.map +1 -0
- package/lib/Utils/identity-change-handler.js +50 -0
- package/lib/Utils/identity-change-handler.js.map +1 -0
- package/lib/Utils/index.d.ts +22 -0
- package/lib/Utils/index.d.ts.map +1 -0
- package/lib/Utils/index.js +22 -33
- package/lib/Utils/index.js.map +1 -0
- package/lib/Utils/link-preview.d.ts +21 -0
- package/lib/Utils/link-preview.d.ts.map +1 -0
- package/lib/Utils/link-preview.js +17 -58
- package/lib/Utils/link-preview.js.map +1 -0
- package/lib/Utils/logger.d.ts +12 -0
- package/lib/Utils/logger.d.ts.map +1 -0
- package/lib/Utils/logger.js +3 -7
- package/lib/Utils/logger.js.map +1 -0
- package/lib/Utils/lt-hash.d.ts +8 -0
- package/lib/Utils/lt-hash.d.ts.map +1 -0
- package/lib/Utils/lt-hash.js +3 -46
- package/lib/Utils/lt-hash.js.map +1 -0
- package/lib/Utils/make-mutex.d.ts +9 -0
- package/lib/Utils/make-mutex.d.ts.map +1 -0
- package/lib/Utils/make-mutex.js +24 -34
- package/lib/Utils/make-mutex.js.map +1 -0
- package/lib/Utils/message-retry-manager.d.ts +115 -0
- package/lib/Utils/message-retry-manager.d.ts.map +1 -0
- package/lib/Utils/message-retry-manager.js +265 -0
- package/lib/Utils/message-retry-manager.js.map +1 -0
- package/lib/Utils/messages-media.d.ts +133 -0
- package/lib/Utils/messages-media.d.ts.map +1 -0
- package/lib/Utils/messages-media.js +483 -744
- package/lib/Utils/messages-media.js.map +1 -0
- package/lib/Utils/messages.d.ts +91 -0
- package/lib/Utils/messages.d.ts.map +1 -0
- package/lib/Utils/messages.js +411 -621
- package/lib/Utils/messages.js.map +1 -0
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/noise-handler.d.ts.map +1 -0
- package/lib/Utils/noise-handler.js +149 -99
- package/lib/Utils/noise-handler.js.map +1 -0
- package/lib/Utils/offline-node-processor.d.ts +17 -0
- package/lib/Utils/offline-node-processor.d.ts.map +1 -0
- package/lib/Utils/offline-node-processor.js +40 -0
- package/lib/Utils/offline-node-processor.js.map +1 -0
- package/lib/Utils/pre-key-manager.d.ts +28 -0
- package/lib/Utils/pre-key-manager.d.ts.map +1 -0
- package/lib/Utils/pre-key-manager.js +106 -0
- package/lib/Utils/pre-key-manager.js.map +1 -0
- package/lib/Utils/process-message.d.ts +60 -0
- package/lib/Utils/process-message.d.ts.map +1 -0
- package/lib/Utils/process-message.js +459 -150
- package/lib/Utils/process-message.js.map +1 -0
- package/lib/Utils/reporting-utils.d.ts +11 -0
- package/lib/Utils/reporting-utils.d.ts.map +1 -0
- package/lib/Utils/reporting-utils.js +258 -0
- package/lib/Utils/reporting-utils.js.map +1 -0
- package/lib/Utils/signal.d.ts +47 -0
- package/lib/Utils/signal.d.ts.map +1 -0
- package/lib/Utils/signal.js +112 -73
- package/lib/Utils/signal.js.map +1 -0
- package/lib/Utils/stanza-ack.d.ts +11 -0
- package/lib/Utils/stanza-ack.d.ts.map +1 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/stanza-ack.js.map +1 -0
- package/lib/Utils/sync-action-utils.d.ts +19 -0
- package/lib/Utils/sync-action-utils.d.ts.map +1 -0
- package/lib/Utils/sync-action-utils.js +49 -0
- package/lib/Utils/sync-action-utils.js.map +1 -0
- package/lib/Utils/tc-token-utils.d.ts +37 -0
- package/lib/Utils/tc-token-utils.d.ts.map +1 -0
- package/lib/Utils/tc-token-utils.js +163 -0
- package/lib/Utils/tc-token-utils.js.map +1 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +13 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -0
- package/lib/Utils/use-multi-file-auth-state.js +23 -27
- package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
- package/lib/Utils/validate-connection.d.ts +11 -0
- package/lib/Utils/validate-connection.d.ts.map +1 -0
- package/lib/Utils/validate-connection.js +74 -104
- package/lib/Utils/validate-connection.js.map +1 -0
- package/lib/WABinary/constants.d.ts +28 -0
- package/lib/WABinary/constants.d.ts.map +1 -0
- package/lib/WABinary/constants.js +9 -11
- package/lib/WABinary/constants.js.map +1 -0
- package/lib/WABinary/decode.d.ts +7 -0
- package/lib/WABinary/decode.d.ts.map +1 -0
- package/lib/WABinary/decode.js +49 -52
- package/lib/WABinary/decode.js.map +1 -0
- package/lib/WABinary/encode.d.ts +3 -0
- package/lib/WABinary/encode.d.ts.map +1 -0
- package/lib/WABinary/encode.js +19 -49
- package/lib/WABinary/encode.js.map +1 -0
- package/lib/WABinary/generic-utils.d.ts +15 -0
- package/lib/WABinary/generic-utils.d.ts.map +1 -0
- package/lib/WABinary/generic-utils.js +46 -43
- package/lib/WABinary/generic-utils.js.map +1 -0
- package/lib/WABinary/index.d.ts +6 -0
- package/lib/WABinary/index.d.ts.map +1 -0
- package/lib/WABinary/index.js +6 -21
- package/lib/WABinary/index.js.map +1 -0
- package/lib/WABinary/jid-utils.d.ts +48 -0
- package/lib/WABinary/jid-utils.d.ts.map +1 -0
- package/lib/WABinary/jid-utils.js +72 -45
- package/lib/WABinary/jid-utils.js.map +1 -0
- package/lib/WABinary/types.d.ts +19 -0
- package/lib/WABinary/types.d.ts.map +1 -0
- package/lib/WABinary/types.js +2 -2
- package/lib/WABinary/types.js.map +1 -0
- package/lib/WAM/BinaryInfo.d.ts +9 -0
- package/lib/WAM/BinaryInfo.d.ts.map +1 -0
- package/lib/WAM/BinaryInfo.js +2 -5
- package/lib/WAM/BinaryInfo.js.map +1 -0
- package/lib/WAM/constants.d.ts +40 -0
- package/lib/WAM/constants.d.ts.map +1 -0
- package/lib/WAM/constants.js +19071 -11568
- package/lib/WAM/constants.js.map +1 -0
- package/lib/WAM/encode.d.ts +3 -0
- package/lib/WAM/encode.d.ts.map +1 -0
- package/lib/WAM/encode.js +17 -22
- package/lib/WAM/encode.js.map +1 -0
- package/lib/WAM/index.d.ts +4 -0
- package/lib/WAM/index.d.ts.map +1 -0
- package/lib/WAM/index.js +4 -19
- package/lib/WAM/index.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +33 -13
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +23 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -14
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +13 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +8 -11
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +13 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -13
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +26 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -22
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +13 -8
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/index.d.ts +6 -0
- package/lib/WAUSync/Protocols/index.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/index.js +6 -20
- package/lib/WAUSync/Protocols/index.js.map +1 -0
- package/lib/WAUSync/USyncQuery.d.ts +30 -0
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -0
- package/lib/WAUSync/USyncQuery.js +44 -35
- package/lib/WAUSync/USyncQuery.js.map +1 -0
- package/lib/WAUSync/USyncUser.d.ts +17 -0
- package/lib/WAUSync/USyncUser.d.ts.map +1 -0
- package/lib/WAUSync/USyncUser.js +10 -5
- package/lib/WAUSync/USyncUser.js.map +1 -0
- package/lib/WAUSync/index.d.ts +4 -0
- package/lib/WAUSync/index.d.ts.map +1 -0
- package/lib/WAUSync/index.js +4 -19
- package/lib/WAUSync/index.js.map +1 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +11 -70
- package/lib/index.js.map +1 -0
- package/package.json +100 -60
|
@@ -1,74 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
signalRepository,
|
|
36
|
-
upsertMessage,
|
|
37
|
-
query,
|
|
38
|
-
fetchPrivacySettings,
|
|
39
|
-
sendNode,
|
|
40
|
-
groupMetadata,
|
|
41
|
-
groupToggleEphemeral,
|
|
42
|
-
} = sock;
|
|
43
|
-
const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
|
|
44
|
-
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
45
|
-
useClones: false
|
|
46
|
-
});
|
|
1
|
+
import NodeCache from '@cacheable/node-cache';
|
|
2
|
+
import { Boom } from '@hapi/boom';
|
|
3
|
+
import { proto } from '../../WAProto/index.js';
|
|
4
|
+
import { DEFAULT_CACHE_TTLS, WA_DEFAULT_EPHEMERAL } from '../Defaults/index.js';
|
|
5
|
+
import { aggregateMessageKeysNotFromMe, assertMediaContent, assertMeId, bindWaitForEvent, decryptMediaRetryData, DEF_MEDIA_HOST, encodeNewsletterMessage, encodeSignedDeviceIdentity, encodeWAMessage, encryptMediaRetryRequest, extractDeviceJids, generateMessageIDV2, generateParticipantHashV2, generateWAMessage, getStatusCodeForMediaRetry, getUrlFromDirectPath, getWAUploadToServer, MessageRetryManager, normalizeMessageContent, parseAndInjectE2ESessions, unixTimestampSeconds } from '../Utils/index.js';
|
|
6
|
+
import { getUrlInfo } from '../Utils/link-preview.js';
|
|
7
|
+
import { makeKeyedMutex, makeMutex } from '../Utils/make-mutex.js';
|
|
8
|
+
import { getMessageReportingToken, shouldIncludeReportingToken } from '../Utils/reporting-utils.js';
|
|
9
|
+
import { buildMergedTcTokenIndexWrite, isTcTokenExpired, resolveIssuanceJid, resolveTcTokenJid, shouldSendNewTcToken, storeTcTokensFromIqResult } from '../Utils/tc-token-utils.js';
|
|
10
|
+
import { areJidsSameUser, getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidBot, isJidGroup, isJidMetaAI, isLidUser, isPnUser, jidDecode, jidEncode, jidNormalizedUser, PSA_WID, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
11
|
+
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
12
|
+
import { makeNewsletterSocket } from './newsletter.js';
|
|
13
|
+
export const makeMessagesSocket = (config) => {
|
|
14
|
+
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
|
|
15
|
+
const sock = makeNewsletterSocket(config);
|
|
16
|
+
const { ev, authState, messageMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral, registerSocketEndHandler } = sock;
|
|
17
|
+
const getLIDForPN = signalRepository.lidMapping.getLIDForPN.bind(signalRepository.lidMapping);
|
|
18
|
+
/**
|
|
19
|
+
* Set of tctoken storage JIDs with a fire-and-forget `issuePrivacyTokens` IQ in flight.
|
|
20
|
+
* Prevents duplicate IQs from rapid back-to-back sends before `senderTimestamp` persists.
|
|
21
|
+
* Entries are always removed in `.finally()`, so the set is bounded by concurrency.
|
|
22
|
+
*/
|
|
23
|
+
const inFlightTcTokenIssuance = new Set();
|
|
24
|
+
const userDevicesCache = config.userDevicesCache ||
|
|
25
|
+
new NodeCache({
|
|
26
|
+
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
27
|
+
useClones: false
|
|
28
|
+
});
|
|
29
|
+
/** Serializes writes to userDevicesCache across USync refresh and device-notification handling. */
|
|
30
|
+
const devicesMutex = makeMutex();
|
|
31
|
+
// Initialize message retry manager if enabled
|
|
32
|
+
const messageRetryManager = enableRecentMessageCache ? new MessageRetryManager(logger, maxMsgRetryCount) : null;
|
|
33
|
+
// Prevent race conditions in Signal session encryption by user
|
|
34
|
+
const encryptionMutex = makeKeyedMutex();
|
|
47
35
|
let mediaConn;
|
|
36
|
+
/** Per-socket media host; updated whenever media_conn is fetched. Defaults to the public WhatsApp host. */
|
|
37
|
+
let mediaHost = DEF_MEDIA_HOST;
|
|
48
38
|
const refreshMediaConn = async (forceGet = false) => {
|
|
49
39
|
const media = await mediaConn;
|
|
50
|
-
if (!media || forceGet ||
|
|
40
|
+
if (!media || forceGet || new Date().getTime() - media.fetchDate.getTime() > media.ttl * 1000) {
|
|
51
41
|
mediaConn = (async () => {
|
|
52
42
|
const result = await query({
|
|
53
43
|
tag: 'iq',
|
|
54
44
|
attrs: {
|
|
55
45
|
type: 'set',
|
|
56
46
|
xmlns: 'w:m',
|
|
57
|
-
to:
|
|
47
|
+
to: S_WHATSAPP_NET
|
|
58
48
|
},
|
|
59
49
|
content: [{ tag: 'media_conn', attrs: {} }]
|
|
60
50
|
});
|
|
61
|
-
const mediaConnNode =
|
|
51
|
+
const mediaConnNode = getBinaryNodeChild(result, 'media_conn');
|
|
52
|
+
// TODO: explore full length of data that whatsapp provides
|
|
62
53
|
const node = {
|
|
63
|
-
hosts:
|
|
54
|
+
hosts: getBinaryNodeChildren(mediaConnNode, 'host').map(({ attrs }) => ({
|
|
64
55
|
hostname: attrs.hostname,
|
|
65
|
-
maxContentLengthBytes: +attrs.maxContentLengthBytes
|
|
56
|
+
maxContentLengthBytes: +attrs.maxContentLengthBytes
|
|
66
57
|
})),
|
|
67
58
|
auth: mediaConnNode.attrs.auth,
|
|
68
59
|
ttl: +mediaConnNode.attrs.ttl,
|
|
69
60
|
fetchDate: new Date()
|
|
70
61
|
};
|
|
71
62
|
logger.debug('fetched media conn');
|
|
63
|
+
if (node.hosts[0]) {
|
|
64
|
+
mediaHost = node.hosts[0].hostname;
|
|
65
|
+
}
|
|
72
66
|
return node;
|
|
73
67
|
})();
|
|
74
68
|
}
|
|
@@ -77,19 +71,22 @@ const makeMessagesSocket = (config) => {
|
|
|
77
71
|
/**
|
|
78
72
|
* generic send receipt function
|
|
79
73
|
* used for receipts of phone call, read, delivery etc.
|
|
80
|
-
*/
|
|
74
|
+
* */
|
|
81
75
|
const sendReceipt = async (jid, participant, messageIds, type) => {
|
|
76
|
+
if (!messageIds || messageIds.length === 0) {
|
|
77
|
+
throw new Boom('missing ids in receipt');
|
|
78
|
+
}
|
|
82
79
|
const node = {
|
|
83
80
|
tag: 'receipt',
|
|
84
81
|
attrs: {
|
|
85
|
-
id: messageIds[0]
|
|
86
|
-
}
|
|
82
|
+
id: messageIds[0]
|
|
83
|
+
}
|
|
87
84
|
};
|
|
88
85
|
const isReadReceipt = type === 'read' || type === 'read-self';
|
|
89
86
|
if (isReadReceipt) {
|
|
90
|
-
node.attrs.t =
|
|
87
|
+
node.attrs.t = unixTimestampSeconds().toString();
|
|
91
88
|
}
|
|
92
|
-
if (type === 'sender' && (
|
|
89
|
+
if (type === 'sender' && (isPnUser(jid) || isLidUser(jid))) {
|
|
93
90
|
node.attrs.recipient = jid;
|
|
94
91
|
node.attrs.to = participant;
|
|
95
92
|
}
|
|
@@ -100,7 +97,7 @@ const makeMessagesSocket = (config) => {
|
|
|
100
97
|
}
|
|
101
98
|
}
|
|
102
99
|
if (type) {
|
|
103
|
-
node.attrs.type =
|
|
100
|
+
node.attrs.type = type;
|
|
104
101
|
}
|
|
105
102
|
const remainingMessageIds = messageIds.slice(1);
|
|
106
103
|
if (remainingMessageIds.length) {
|
|
@@ -120,7 +117,7 @@ const makeMessagesSocket = (config) => {
|
|
|
120
117
|
};
|
|
121
118
|
/** Correctly bulk send receipts to multiple chats, participants */
|
|
122
119
|
const sendReceipts = async (keys, type) => {
|
|
123
|
-
const recps =
|
|
120
|
+
const recps = aggregateMessageKeysNotFromMe(keys);
|
|
124
121
|
for (const { jid, participant, messageIds } of recps) {
|
|
125
122
|
await sendReceipt(jid, participant, messageIds, type);
|
|
126
123
|
}
|
|
@@ -134,20 +131,44 @@ const makeMessagesSocket = (config) => {
|
|
|
134
131
|
};
|
|
135
132
|
/** Fetch all the devices we've to send a message to */
|
|
136
133
|
const getUSyncDevices = async (jids, useCache, ignoreZeroDevices) => {
|
|
137
|
-
var _a;
|
|
138
134
|
const deviceResults = [];
|
|
139
135
|
if (!useCache) {
|
|
140
136
|
logger.debug('not using cache for devices');
|
|
141
137
|
}
|
|
142
138
|
const toFetch = [];
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
139
|
+
const jidsWithUser = jids
|
|
140
|
+
.map(jid => {
|
|
141
|
+
const decoded = jidDecode(jid);
|
|
142
|
+
const user = decoded?.user;
|
|
143
|
+
const device = decoded?.device;
|
|
144
|
+
const isExplicitDevice = typeof device === 'number' && device >= 0;
|
|
145
|
+
if (isExplicitDevice && user) {
|
|
146
|
+
deviceResults.push({
|
|
147
|
+
user,
|
|
148
|
+
device,
|
|
149
|
+
jid
|
|
150
|
+
});
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
jid = jidNormalizedUser(jid);
|
|
154
|
+
return { jid, user };
|
|
155
|
+
})
|
|
156
|
+
.filter(jid => jid !== null);
|
|
157
|
+
let mgetDevices;
|
|
158
|
+
if (useCache && userDevicesCache.mget) {
|
|
159
|
+
const usersToFetch = jidsWithUser.map(j => j?.user).filter(Boolean);
|
|
160
|
+
mgetDevices = await userDevicesCache.mget(usersToFetch);
|
|
161
|
+
}
|
|
162
|
+
for (const { jid, user } of jidsWithUser) {
|
|
147
163
|
if (useCache) {
|
|
148
|
-
const devices =
|
|
164
|
+
const devices = mgetDevices?.[user] ||
|
|
165
|
+
(userDevicesCache.mget ? undefined : (await userDevicesCache.get(user)));
|
|
149
166
|
if (devices) {
|
|
150
|
-
|
|
167
|
+
const devicesWithJid = devices.map(d => ({
|
|
168
|
+
...d,
|
|
169
|
+
jid: jidEncode(d.user, d.server, d.device)
|
|
170
|
+
}));
|
|
171
|
+
deviceResults.push(...devicesWithJid);
|
|
151
172
|
logger.trace({ user }, 'using cache for devices');
|
|
152
173
|
}
|
|
153
174
|
else {
|
|
@@ -161,157 +182,270 @@ const makeMessagesSocket = (config) => {
|
|
|
161
182
|
if (!toFetch.length) {
|
|
162
183
|
return deviceResults;
|
|
163
184
|
}
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
185
|
+
const requestedLidUsers = new Set();
|
|
186
|
+
for (const jid of toFetch) {
|
|
187
|
+
if (isLidUser(jid) || isHostedLidUser(jid)) {
|
|
188
|
+
const user = jidDecode(jid)?.user;
|
|
189
|
+
if (user)
|
|
190
|
+
requestedLidUsers.add(user);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const query = new USyncQuery().withContext('message').withDeviceProtocol().withLIDProtocol();
|
|
167
194
|
for (const jid of toFetch) {
|
|
168
|
-
query.withUser(new
|
|
195
|
+
query.withUser(new USyncUser().withId(jid)); // todo: investigate - the idea here is that <user> should have an inline lid field with the lid being the pn equivalent
|
|
169
196
|
}
|
|
170
197
|
const result = await sock.executeUSyncQuery(query);
|
|
171
198
|
if (result) {
|
|
172
|
-
|
|
199
|
+
// TODO: LID MAP this stuff (lid protocol will now return lid with devices)
|
|
200
|
+
const lidResults = result.list.filter(a => !!a.lid);
|
|
201
|
+
if (lidResults.length > 0) {
|
|
202
|
+
logger.trace('Storing LID maps from device call');
|
|
203
|
+
await signalRepository.lidMapping.storeLIDPNMappings(lidResults.map(a => ({ lid: a.lid, pn: a.id })));
|
|
204
|
+
// Force-refresh sessions for newly mapped LIDs to align identity addressing
|
|
205
|
+
try {
|
|
206
|
+
const lids = lidResults.map(a => a.lid);
|
|
207
|
+
if (lids.length) {
|
|
208
|
+
await assertSessions(lids, true);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
logger.warn({ e, count: lidResults.length }, 'failed to assert sessions for newly mapped LIDs');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const extracted = extractDeviceJids(result?.list, authState.creds.me.id, authState.creds.me.lid, ignoreZeroDevices);
|
|
173
216
|
const deviceMap = {};
|
|
174
217
|
for (const item of extracted) {
|
|
175
218
|
deviceMap[item.user] = deviceMap[item.user] || [];
|
|
176
|
-
deviceMap[item.user]
|
|
177
|
-
|
|
219
|
+
deviceMap[item.user]?.push(item);
|
|
220
|
+
}
|
|
221
|
+
// Process each user's devices as a group for bulk LID migration
|
|
222
|
+
for (const [user, userDevices] of Object.entries(deviceMap)) {
|
|
223
|
+
const isLidUser = requestedLidUsers.has(user);
|
|
224
|
+
// Process all devices for this user
|
|
225
|
+
for (const item of userDevices) {
|
|
226
|
+
const finalJid = isLidUser
|
|
227
|
+
? jidEncode(user, item.server, item.device)
|
|
228
|
+
: jidEncode(item.user, item.server, item.device);
|
|
229
|
+
deviceResults.push({
|
|
230
|
+
...item,
|
|
231
|
+
jid: finalJid
|
|
232
|
+
});
|
|
233
|
+
logger.debug({
|
|
234
|
+
user: item.user,
|
|
235
|
+
device: item.device,
|
|
236
|
+
finalJid,
|
|
237
|
+
usedLid: isLidUser
|
|
238
|
+
}, 'Processed device with LID priority');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
await devicesMutex.mutex(async () => {
|
|
242
|
+
if (userDevicesCache.mset) {
|
|
243
|
+
// if the cache supports mset, we can set all devices in one go
|
|
244
|
+
await userDevicesCache.mset(Object.entries(deviceMap).map(([key, value]) => ({ key, value })));
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
for (const key in deviceMap) {
|
|
248
|
+
if (deviceMap[key])
|
|
249
|
+
await userDevicesCache.set(key, deviceMap[key]);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
const userDeviceUpdates = {};
|
|
254
|
+
for (const [userId, devices] of Object.entries(deviceMap)) {
|
|
255
|
+
if (devices && devices.length > 0) {
|
|
256
|
+
userDeviceUpdates[userId] = devices.map(d => d.device?.toString() || '0');
|
|
257
|
+
}
|
|
178
258
|
}
|
|
179
|
-
|
|
180
|
-
|
|
259
|
+
if (Object.keys(userDeviceUpdates).length > 0) {
|
|
260
|
+
try {
|
|
261
|
+
await authState.keys.set({ 'device-list': userDeviceUpdates });
|
|
262
|
+
logger.debug({ userCount: Object.keys(userDeviceUpdates).length }, 'stored user device lists for bulk migration');
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
logger.warn({ error }, 'failed to store user device lists');
|
|
266
|
+
}
|
|
181
267
|
}
|
|
182
268
|
}
|
|
183
269
|
return deviceResults;
|
|
184
270
|
};
|
|
271
|
+
/**
|
|
272
|
+
* Update Member Label
|
|
273
|
+
*/
|
|
274
|
+
const updateMemberLabel = (jid, memberLabel) => {
|
|
275
|
+
return relayMessage(jid, {
|
|
276
|
+
protocolMessage: {
|
|
277
|
+
type: proto.Message.ProtocolMessage.Type.GROUP_MEMBER_LABEL_CHANGE,
|
|
278
|
+
memberLabel: {
|
|
279
|
+
label: memberLabel?.slice(0, 30),
|
|
280
|
+
labelTimestamp: unixTimestampSeconds()
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}, {
|
|
284
|
+
additionalNodes: [
|
|
285
|
+
{
|
|
286
|
+
tag: 'meta',
|
|
287
|
+
attrs: {
|
|
288
|
+
tag_reason: 'user_update',
|
|
289
|
+
appdata: 'member_tag'
|
|
290
|
+
},
|
|
291
|
+
content: undefined
|
|
292
|
+
}
|
|
293
|
+
]
|
|
294
|
+
});
|
|
295
|
+
};
|
|
185
296
|
const assertSessions = async (jids, force) => {
|
|
186
297
|
let didFetchNewSession = false;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
.
|
|
194
|
-
|
|
195
|
-
for (const jid of jids) {
|
|
196
|
-
const signalId = signalRepository
|
|
197
|
-
.jidToSignalProtocolAddress(jid);
|
|
198
|
-
if (!sessions[signalId]) {
|
|
199
|
-
jidsRequiringFetch.push(jid);
|
|
298
|
+
const uniqueJids = [...new Set(jids)];
|
|
299
|
+
const jidsRequiringFetch = [];
|
|
300
|
+
logger.debug({ jids }, 'assertSessions call with jids');
|
|
301
|
+
for (const jid of uniqueJids) {
|
|
302
|
+
if (!force) {
|
|
303
|
+
const sessionValidation = await signalRepository.validateSession(jid);
|
|
304
|
+
if (sessionValidation.exists) {
|
|
305
|
+
continue;
|
|
200
306
|
}
|
|
201
307
|
}
|
|
308
|
+
jidsRequiringFetch.push(jid);
|
|
202
309
|
}
|
|
203
310
|
if (jidsRequiringFetch.length) {
|
|
204
|
-
|
|
311
|
+
// LID if mapped, otherwise original
|
|
312
|
+
const wireJids = [
|
|
313
|
+
...jidsRequiringFetch.filter(jid => !!isLidUser(jid) || !!isHostedLidUser(jid)),
|
|
314
|
+
...((await signalRepository.lidMapping.getLIDsForPNs(jidsRequiringFetch.filter(jid => !!isPnUser(jid) || !!isHostedPnUser(jid)))) || []).map(a => a.lid)
|
|
315
|
+
];
|
|
316
|
+
logger.debug({ jidsRequiringFetch, wireJids }, 'fetching sessions');
|
|
205
317
|
const result = await query({
|
|
206
318
|
tag: 'iq',
|
|
207
319
|
attrs: {
|
|
208
320
|
xmlns: 'encrypt',
|
|
209
321
|
type: 'get',
|
|
210
|
-
to:
|
|
322
|
+
to: S_WHATSAPP_NET
|
|
211
323
|
},
|
|
212
324
|
content: [
|
|
213
325
|
{
|
|
214
326
|
tag: 'key',
|
|
215
327
|
attrs: {},
|
|
216
|
-
content:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
328
|
+
content: wireJids.map(jid => {
|
|
329
|
+
const attrs = { jid };
|
|
330
|
+
if (force)
|
|
331
|
+
attrs.reason = 'identity';
|
|
332
|
+
return { tag: 'user', attrs };
|
|
333
|
+
})
|
|
220
334
|
}
|
|
221
335
|
]
|
|
222
336
|
});
|
|
223
|
-
await
|
|
337
|
+
await parseAndInjectE2ESessions(result, signalRepository);
|
|
224
338
|
didFetchNewSession = true;
|
|
225
339
|
}
|
|
226
340
|
return didFetchNewSession;
|
|
227
341
|
};
|
|
228
342
|
const sendPeerDataOperationMessage = async (pdoMessage) => {
|
|
229
|
-
var _a;
|
|
230
343
|
//TODO: for later, abstract the logic to send a Peer Message instead of just PDO - useful for App State Key Resync with phone
|
|
231
|
-
if (!
|
|
232
|
-
throw new
|
|
344
|
+
if (!authState.creds.me?.id) {
|
|
345
|
+
throw new Boom('Not authenticated');
|
|
233
346
|
}
|
|
234
347
|
const protocolMessage = {
|
|
235
348
|
protocolMessage: {
|
|
236
349
|
peerDataOperationRequestMessage: pdoMessage,
|
|
237
|
-
type:
|
|
350
|
+
type: proto.Message.ProtocolMessage.Type.PEER_DATA_OPERATION_REQUEST_MESSAGE
|
|
238
351
|
}
|
|
239
352
|
};
|
|
240
|
-
const meJid =
|
|
353
|
+
const meJid = jidNormalizedUser(authState.creds.me.id);
|
|
241
354
|
const msgId = await relayMessage(meJid, protocolMessage, {
|
|
242
355
|
additionalAttributes: {
|
|
243
356
|
category: 'peer',
|
|
244
|
-
|
|
245
|
-
push_priority: 'high_force',
|
|
357
|
+
push_priority: 'high_force'
|
|
246
358
|
},
|
|
359
|
+
additionalNodes: [
|
|
360
|
+
{
|
|
361
|
+
tag: 'meta',
|
|
362
|
+
attrs: { appdata: 'default' }
|
|
363
|
+
}
|
|
364
|
+
]
|
|
247
365
|
});
|
|
248
366
|
return msgId;
|
|
249
367
|
};
|
|
250
|
-
const createParticipantNodes = async (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
patched = jids ? jids.map(jid => ({ recipientJid: jid, ...patched })) : [patched];
|
|
368
|
+
const createParticipantNodes = async (recipientJids, message, extraAttrs, dsmMessage) => {
|
|
369
|
+
if (!recipientJids.length) {
|
|
370
|
+
return { nodes: [], shouldIncludeDeviceIdentity: false };
|
|
254
371
|
}
|
|
372
|
+
const patched = await patchMessageBeforeSending(message, recipientJids);
|
|
373
|
+
const patchedMessages = Array.isArray(patched)
|
|
374
|
+
? patched
|
|
375
|
+
: recipientJids.map(jid => ({ recipientJid: jid, message: patched }));
|
|
255
376
|
let shouldIncludeDeviceIdentity = false;
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
377
|
+
const meId = authState.creds.me.id;
|
|
378
|
+
const meLid = authState.creds.me?.lid;
|
|
379
|
+
const meLidUser = meLid ? jidDecode(meLid)?.user : null;
|
|
380
|
+
const encryptionPromises = patchedMessages.map(async ({ recipientJid: jid, message: patchedMessage }) => {
|
|
381
|
+
try {
|
|
382
|
+
if (!jid)
|
|
383
|
+
return null;
|
|
384
|
+
let msgToEncrypt = patchedMessage;
|
|
385
|
+
if (dsmMessage) {
|
|
386
|
+
const { user: targetUser } = jidDecode(jid);
|
|
387
|
+
const { user: ownPnUser } = jidDecode(meId);
|
|
388
|
+
const ownLidUser = meLidUser;
|
|
389
|
+
const isOwnUser = targetUser === ownPnUser || (ownLidUser && targetUser === ownLidUser);
|
|
390
|
+
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
391
|
+
if (isOwnUser && !isExactSenderDevice) {
|
|
392
|
+
msgToEncrypt = dsmMessage;
|
|
393
|
+
logger.debug({ jid, targetUser }, 'Using DSM for own device');
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
const bytes = encodeWAMessage(msgToEncrypt);
|
|
397
|
+
const mutexKey = jid;
|
|
398
|
+
const node = await encryptionMutex.mutex(mutexKey, async () => {
|
|
399
|
+
const { type, ciphertext } = await signalRepository.encryptMessage({ jid, data: bytes });
|
|
400
|
+
if (type === 'pkmsg') {
|
|
401
|
+
shouldIncludeDeviceIdentity = true;
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
tag: 'to',
|
|
405
|
+
attrs: { jid },
|
|
406
|
+
content: [
|
|
407
|
+
{
|
|
408
|
+
tag: 'enc',
|
|
409
|
+
attrs: { v: '2', type, ...(extraAttrs || {}) },
|
|
410
|
+
content: ciphertext
|
|
411
|
+
}
|
|
412
|
+
]
|
|
413
|
+
};
|
|
414
|
+
});
|
|
415
|
+
return node;
|
|
260
416
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (type === 'pkmsg') {
|
|
265
|
-
shouldIncludeDeviceIdentity = true;
|
|
417
|
+
catch (err) {
|
|
418
|
+
logger.error({ jid, err }, 'Failed to encrypt for recipient');
|
|
419
|
+
return null;
|
|
266
420
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
attrs: {
|
|
273
|
-
v: '2',
|
|
274
|
-
type,
|
|
275
|
-
...extraAttrs || {}
|
|
276
|
-
},
|
|
277
|
-
content: ciphertext
|
|
278
|
-
}]
|
|
279
|
-
};
|
|
280
|
-
return node;
|
|
281
|
-
}));
|
|
421
|
+
});
|
|
422
|
+
const nodes = (await Promise.all(encryptionPromises)).filter(node => node !== null);
|
|
423
|
+
if (recipientJids.length > 0 && nodes.length === 0) {
|
|
424
|
+
throw new Boom('All encryptions failed', { statusCode: 500 });
|
|
425
|
+
}
|
|
282
426
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
283
427
|
};
|
|
284
|
-
const relayMessage = async (
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
msgId,
|
|
290
|
-
participant,
|
|
291
|
-
additionalAttributes,
|
|
292
|
-
additionalNodes,
|
|
293
|
-
useUserDevicesCache,
|
|
294
|
-
useCachedGroupMetadata,
|
|
295
|
-
statusJidList, AI = true }) => {
|
|
296
|
-
var _a;
|
|
297
|
-
const meId = authState.creds.me.id;
|
|
298
|
-
let shouldIncludeDeviceIdentity = false;
|
|
299
|
-
const { user, server } = (0, WABinary_1.jidDecode)(jid);
|
|
428
|
+
const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, useCachedGroupMetadata, statusJidList }) => {
|
|
429
|
+
const meId = assertMeId(authState.creds);
|
|
430
|
+
const meLid = authState.creds.me?.lid;
|
|
431
|
+
const isRetryResend = Boolean(participant?.jid);
|
|
432
|
+
let shouldIncludeDeviceIdentity = isRetryResend;
|
|
300
433
|
const statusJid = 'status@broadcast';
|
|
434
|
+
const { user, server } = jidDecode(jid);
|
|
301
435
|
const isGroup = server === 'g.us';
|
|
302
|
-
const isPrivatee = server === 's.whatsapp.net'
|
|
303
|
-
const isNewsletter = server === 'newsletter';
|
|
304
436
|
const isStatus = jid === statusJid;
|
|
305
437
|
const isLid = server === 'lid';
|
|
306
|
-
const
|
|
307
|
-
const
|
|
308
|
-
|
|
438
|
+
const isNewsletter = server === 'newsletter';
|
|
439
|
+
const isGroupOrStatus = isGroup || isStatus;
|
|
440
|
+
const finalJid = jid;
|
|
441
|
+
msgId = msgId || generateMessageIDV2(meId);
|
|
309
442
|
useUserDevicesCache = useUserDevicesCache !== false;
|
|
310
443
|
useCachedGroupMetadata = useCachedGroupMetadata !== false && !isStatus;
|
|
311
444
|
const participants = [];
|
|
312
|
-
const destinationJid =
|
|
445
|
+
const destinationJid = !isStatus ? finalJid : statusJid;
|
|
313
446
|
const binaryNodeContent = [];
|
|
314
447
|
const devices = [];
|
|
448
|
+
let reportingMessage;
|
|
315
449
|
const meMsg = {
|
|
316
450
|
deviceSentMessage: {
|
|
317
451
|
destinationJid,
|
|
@@ -321,161 +455,274 @@ const makeMessagesSocket = (config) => {
|
|
|
321
455
|
};
|
|
322
456
|
const extraAttrs = {};
|
|
323
457
|
if (participant) {
|
|
324
|
-
// when the retry request is not for a group
|
|
325
|
-
// only send to the specific device that asked for a retry
|
|
326
|
-
// otherwise the message is sent out to every device that should be a recipient
|
|
327
458
|
if (!isGroup && !isStatus) {
|
|
328
|
-
additionalAttributes = { ...additionalAttributes,
|
|
459
|
+
additionalAttributes = { ...additionalAttributes, device_fanout: 'false' };
|
|
329
460
|
}
|
|
330
|
-
const { user, device } =
|
|
331
|
-
devices.push({
|
|
461
|
+
const { user, device } = jidDecode(participant.jid);
|
|
462
|
+
devices.push({
|
|
463
|
+
user,
|
|
464
|
+
device,
|
|
465
|
+
jid: participant.jid
|
|
466
|
+
});
|
|
332
467
|
}
|
|
333
468
|
await authState.keys.transaction(async () => {
|
|
334
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
335
469
|
const mediaType = getMediaType(message);
|
|
336
470
|
if (mediaType) {
|
|
337
471
|
extraAttrs['mediatype'] = mediaType;
|
|
338
472
|
}
|
|
339
|
-
if (
|
|
340
|
-
|
|
473
|
+
if (isNewsletter) {
|
|
474
|
+
const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
|
|
475
|
+
const bytes = encodeNewsletterMessage(patched);
|
|
476
|
+
binaryNodeContent.push({
|
|
477
|
+
tag: 'plaintext',
|
|
478
|
+
attrs: {},
|
|
479
|
+
content: bytes
|
|
480
|
+
});
|
|
481
|
+
const stanza = {
|
|
482
|
+
tag: 'message',
|
|
483
|
+
attrs: {
|
|
484
|
+
to: jid,
|
|
485
|
+
id: msgId,
|
|
486
|
+
type: getMessageType(message),
|
|
487
|
+
...(additionalAttributes || {})
|
|
488
|
+
},
|
|
489
|
+
content: binaryNodeContent
|
|
490
|
+
};
|
|
491
|
+
logger.debug({ msgId }, `sending newsletter message to ${jid}`);
|
|
492
|
+
await sendNode(stanza);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
if (normalizeMessageContent(message)?.pinInChatMessage || normalizeMessageContent(message)?.reactionMessage) {
|
|
496
|
+
extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
|
|
341
497
|
}
|
|
342
|
-
if (
|
|
498
|
+
if (isGroupOrStatus && !isRetryResend) {
|
|
343
499
|
const [groupData, senderKeyMap] = await Promise.all([
|
|
344
500
|
(async () => {
|
|
345
|
-
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined;
|
|
346
|
-
if (groupData && Array.isArray(groupData
|
|
501
|
+
let groupData = useCachedGroupMetadata && cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined; // todo: should we rely on the cache specially if the cache is outdated and the metadata has new fields?
|
|
502
|
+
if (groupData && Array.isArray(groupData?.participants)) {
|
|
347
503
|
logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
|
|
348
504
|
}
|
|
349
505
|
else if (!isStatus) {
|
|
350
|
-
groupData = await groupMetadata(jid);
|
|
506
|
+
groupData = await groupMetadata(jid); // TODO: start storing group participant list + addr mode in Signal & stop relying on this
|
|
351
507
|
}
|
|
352
508
|
return groupData;
|
|
353
509
|
})(),
|
|
354
510
|
(async () => {
|
|
355
511
|
if (!participant && !isStatus) {
|
|
356
|
-
|
|
512
|
+
// what if sender memory is less accurate than the cached metadata
|
|
513
|
+
// on participant change in group, we should do sender memory manipulation
|
|
514
|
+
const result = await authState.keys.get('sender-key-memory', [jid]); // TODO: check out what if the sender key memory doesn't include the LID stuff now?
|
|
357
515
|
return result[jid] || {};
|
|
358
516
|
}
|
|
359
517
|
return {};
|
|
360
518
|
})()
|
|
361
519
|
]);
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
520
|
+
const participantsList = groupData ? groupData.participants.map(p => p.id) : [];
|
|
521
|
+
if (groupData?.ephemeralDuration && groupData.ephemeralDuration > 0) {
|
|
522
|
+
additionalAttributes = {
|
|
523
|
+
...additionalAttributes,
|
|
524
|
+
expiration: groupData.ephemeralDuration.toString()
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
if (isStatus && statusJidList) {
|
|
528
|
+
participantsList.push(...statusJidList);
|
|
529
|
+
}
|
|
530
|
+
const additionalDevices = await getUSyncDevices(participantsList, !!useUserDevicesCache, false);
|
|
531
|
+
devices.push(...additionalDevices);
|
|
532
|
+
if (isGroup) {
|
|
533
|
+
additionalAttributes = {
|
|
534
|
+
...additionalAttributes,
|
|
535
|
+
addressing_mode: groupData?.addressingMode || 'lid'
|
|
536
|
+
};
|
|
376
537
|
}
|
|
377
538
|
const patched = await patchMessageBeforeSending(message);
|
|
378
539
|
if (Array.isArray(patched)) {
|
|
379
|
-
throw new
|
|
540
|
+
throw new Boom('Per-jid patching is not supported in groups');
|
|
380
541
|
}
|
|
381
|
-
const bytes =
|
|
542
|
+
const bytes = encodeWAMessage(patched);
|
|
543
|
+
reportingMessage = patched;
|
|
544
|
+
const groupAddressingMode = additionalAttributes?.['addressing_mode'] || groupData?.addressingMode || 'lid';
|
|
545
|
+
const groupSenderIdentity = groupAddressingMode === 'lid' && meLid ? meLid : meId;
|
|
382
546
|
const { ciphertext, senderKeyDistributionMessage } = await signalRepository.encryptGroupMessage({
|
|
383
547
|
group: destinationJid,
|
|
384
548
|
data: bytes,
|
|
385
|
-
meId
|
|
549
|
+
meId: groupSenderIdentity
|
|
386
550
|
});
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const
|
|
391
|
-
if (!
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
551
|
+
const senderKeyRecipients = [];
|
|
552
|
+
for (const device of devices) {
|
|
553
|
+
const deviceJid = device.jid;
|
|
554
|
+
const hasKey = !!senderKeyMap[deviceJid];
|
|
555
|
+
if ((!hasKey || !!participant) &&
|
|
556
|
+
!isHostedLidUser(deviceJid) &&
|
|
557
|
+
!isHostedPnUser(deviceJid) &&
|
|
558
|
+
device.device !== 99) {
|
|
559
|
+
//todo: revamp all this logic
|
|
560
|
+
// the goal is to follow with what I said above for each group, and instead of a true false map of ids, we can set an array full of those the app has already sent pkmsgs
|
|
561
|
+
senderKeyRecipients.push(deviceJid);
|
|
562
|
+
senderKeyMap[deviceJid] = true;
|
|
395
563
|
}
|
|
396
564
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if (senderKeyJids.length) {
|
|
400
|
-
logger.debug({ senderKeyJids }, 'sending new sender key');
|
|
565
|
+
if (senderKeyRecipients.length) {
|
|
566
|
+
logger.debug({ senderKeyJids: senderKeyRecipients }, 'sending new sender key');
|
|
401
567
|
const senderKeyMsg = {
|
|
402
568
|
senderKeyDistributionMessage: {
|
|
403
569
|
axolotlSenderKeyDistributionMessage: senderKeyDistributionMessage,
|
|
404
570
|
groupId: destinationJid
|
|
405
571
|
}
|
|
406
572
|
};
|
|
407
|
-
|
|
408
|
-
|
|
573
|
+
const senderKeySessionTargets = senderKeyRecipients;
|
|
574
|
+
await assertSessions(senderKeySessionTargets);
|
|
575
|
+
const result = await createParticipantNodes(senderKeyRecipients, senderKeyMsg, extraAttrs);
|
|
409
576
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
|
|
410
577
|
participants.push(...result.nodes);
|
|
411
578
|
}
|
|
412
579
|
binaryNodeContent.push({
|
|
413
580
|
tag: 'enc',
|
|
414
|
-
attrs: { v: '2', type: 'skmsg' },
|
|
581
|
+
attrs: { v: '2', type: 'skmsg', ...extraAttrs },
|
|
415
582
|
content: ciphertext
|
|
416
583
|
});
|
|
417
584
|
await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
|
|
418
585
|
}
|
|
419
|
-
else
|
|
420
|
-
//
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (((_d = message.protocolMessage) === null || _d === void 0 ? void 0 : _d.type) === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
|
|
427
|
-
msgId = (_e = message.protocolMessage.key) === null || _e === void 0 ? void 0 : _e.id;
|
|
428
|
-
message = {};
|
|
586
|
+
else {
|
|
587
|
+
// ADDRESSING CONSISTENCY: Match own identity to conversation context
|
|
588
|
+
// TODO: investigate if this is true
|
|
589
|
+
let ownId = meId;
|
|
590
|
+
if (isLid && meLid) {
|
|
591
|
+
ownId = meLid;
|
|
592
|
+
logger.debug({ to: jid, ownId }, 'Using LID identity for @lid conversation');
|
|
429
593
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
throw new boom_1.Boom('Per-jid patching is not supported in channel');
|
|
594
|
+
else {
|
|
595
|
+
logger.debug({ to: jid, ownId }, 'Using PN identity for @s.whatsapp.net conversation');
|
|
433
596
|
}
|
|
434
|
-
const
|
|
435
|
-
binaryNodeContent.push({
|
|
436
|
-
tag: 'plaintext',
|
|
437
|
-
attrs: mediaType ? { mediatype: mediaType } : {},
|
|
438
|
-
content: bytes
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
else {
|
|
442
|
-
const { user: meUser } = (0, WABinary_1.jidDecode)(meId);
|
|
597
|
+
const { user: ownUser } = jidDecode(ownId);
|
|
443
598
|
if (!participant) {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
599
|
+
const patchedForReporting = await patchMessageBeforeSending(message, [jid]);
|
|
600
|
+
reportingMessage = Array.isArray(patchedForReporting)
|
|
601
|
+
? patchedForReporting.find(item => item.recipientJid === jid) || patchedForReporting[0]
|
|
602
|
+
: patchedForReporting;
|
|
603
|
+
}
|
|
604
|
+
if (!isRetryResend) {
|
|
605
|
+
const targetUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
606
|
+
devices.push({
|
|
607
|
+
user,
|
|
608
|
+
device: 0,
|
|
609
|
+
jid: jidEncode(user, targetUserServer, 0) // rajeh, todo: this entire logic is convoluted and weird.
|
|
610
|
+
});
|
|
611
|
+
if (user !== ownUser) {
|
|
612
|
+
const ownUserServer = isLid ? 'lid' : 's.whatsapp.net';
|
|
613
|
+
const ownUserForAddressing = isLid && meLid ? jidDecode(meLid).user : jidDecode(meId).user;
|
|
614
|
+
devices.push({
|
|
615
|
+
user: ownUserForAddressing,
|
|
616
|
+
device: 0,
|
|
617
|
+
jid: jidEncode(ownUserForAddressing, ownUserServer, 0)
|
|
618
|
+
});
|
|
447
619
|
}
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
devices.
|
|
620
|
+
if (additionalAttributes?.['category'] !== 'peer') {
|
|
621
|
+
// Clear placeholders and enumerate actual devices
|
|
622
|
+
devices.length = 0;
|
|
623
|
+
// Use conversation-appropriate sender identity
|
|
624
|
+
const senderIdentity = isLid && meLid
|
|
625
|
+
? jidEncode(jidDecode(meLid)?.user, 'lid', undefined)
|
|
626
|
+
: jidEncode(jidDecode(meId)?.user, 's.whatsapp.net', undefined);
|
|
627
|
+
// Enumerate devices for sender and target with consistent addressing
|
|
628
|
+
const sessionDevices = await getUSyncDevices([senderIdentity, jid], true, false);
|
|
629
|
+
devices.push(...sessionDevices);
|
|
630
|
+
logger.debug({
|
|
631
|
+
deviceCount: devices.length,
|
|
632
|
+
devices: devices.map(d => `${d.user}:${d.device}@${jidDecode(d.jid)?.server}`)
|
|
633
|
+
}, 'Device enumeration complete with unified addressing');
|
|
451
634
|
}
|
|
452
635
|
}
|
|
453
|
-
const
|
|
454
|
-
const
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
636
|
+
const allRecipients = [];
|
|
637
|
+
const meRecipients = [];
|
|
638
|
+
const otherRecipients = [];
|
|
639
|
+
const { user: mePnUser } = jidDecode(meId);
|
|
640
|
+
const { user: meLidUser } = meLid ? jidDecode(meLid) : { user: null };
|
|
641
|
+
for (const { user, jid } of devices) {
|
|
642
|
+
const isExactSenderDevice = jid === meId || (meLid && jid === meLid);
|
|
643
|
+
if (isExactSenderDevice) {
|
|
644
|
+
logger.debug({ jid, meId, meLid }, 'Skipping exact sender device (whatsmeow pattern)');
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
// Check if this is our device (could match either PN or LID user)
|
|
648
|
+
const isMe = user === mePnUser || user === meLidUser;
|
|
459
649
|
if (isMe) {
|
|
460
|
-
|
|
650
|
+
meRecipients.push(jid);
|
|
461
651
|
}
|
|
462
652
|
else {
|
|
463
|
-
|
|
653
|
+
otherRecipients.push(jid);
|
|
464
654
|
}
|
|
465
|
-
|
|
655
|
+
allRecipients.push(jid);
|
|
466
656
|
}
|
|
467
|
-
await assertSessions(
|
|
657
|
+
await assertSessions(allRecipients);
|
|
468
658
|
const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = await Promise.all([
|
|
469
|
-
|
|
470
|
-
createParticipantNodes(
|
|
659
|
+
// For own devices: use DSM if available (1:1 chats only)
|
|
660
|
+
createParticipantNodes(meRecipients, meMsg || message, extraAttrs),
|
|
661
|
+
createParticipantNodes(otherRecipients, message, extraAttrs, meMsg)
|
|
471
662
|
]);
|
|
472
663
|
participants.push(...meNodes);
|
|
473
664
|
participants.push(...otherNodes);
|
|
665
|
+
if (meRecipients.length > 0 || otherRecipients.length > 0) {
|
|
666
|
+
extraAttrs['phash'] = generateParticipantHashV2([...meRecipients, ...otherRecipients]);
|
|
667
|
+
}
|
|
474
668
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || s1 || s2;
|
|
475
669
|
}
|
|
670
|
+
if (isRetryResend) {
|
|
671
|
+
const isParticipantLid = isLidUser(participant.jid);
|
|
672
|
+
const isMe = areJidsSameUser(participant.jid, isParticipantLid ? meLid : meId);
|
|
673
|
+
let messageToSend = message;
|
|
674
|
+
if (isGroupOrStatus) {
|
|
675
|
+
let groupSenderIdentity;
|
|
676
|
+
if (meLid && (await signalRepository.hasSenderKey({ group: destinationJid, meId: meLid }))) {
|
|
677
|
+
groupSenderIdentity = meLid;
|
|
678
|
+
}
|
|
679
|
+
else if (await signalRepository.hasSenderKey({ group: destinationJid, meId })) {
|
|
680
|
+
groupSenderIdentity = meId;
|
|
681
|
+
}
|
|
682
|
+
if (groupSenderIdentity) {
|
|
683
|
+
try {
|
|
684
|
+
const skdm = await signalRepository.getSenderKeyDistributionMessage({
|
|
685
|
+
group: destinationJid,
|
|
686
|
+
meId: groupSenderIdentity
|
|
687
|
+
});
|
|
688
|
+
messageToSend = {
|
|
689
|
+
...message,
|
|
690
|
+
senderKeyDistributionMessage: {
|
|
691
|
+
groupId: destinationJid,
|
|
692
|
+
axolotlSenderKeyDistributionMessage: skdm
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
catch (err) {
|
|
697
|
+
logger.warn({ err, jid: destinationJid }, 'failed to build SKDM for retry, sending without it');
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
const encodedMessageToSend = isMe
|
|
702
|
+
? encodeWAMessage({
|
|
703
|
+
deviceSentMessage: {
|
|
704
|
+
destinationJid,
|
|
705
|
+
message: messageToSend
|
|
706
|
+
}
|
|
707
|
+
})
|
|
708
|
+
: encodeWAMessage(messageToSend);
|
|
709
|
+
const { type, ciphertext: encryptedContent } = await signalRepository.encryptMessage({
|
|
710
|
+
data: encodedMessageToSend,
|
|
711
|
+
jid: participant.jid
|
|
712
|
+
});
|
|
713
|
+
binaryNodeContent.push({
|
|
714
|
+
tag: 'enc',
|
|
715
|
+
attrs: {
|
|
716
|
+
v: '2',
|
|
717
|
+
type,
|
|
718
|
+
count: participant.count.toString()
|
|
719
|
+
},
|
|
720
|
+
content: encryptedContent
|
|
721
|
+
});
|
|
722
|
+
}
|
|
476
723
|
if (participants.length) {
|
|
477
|
-
if (
|
|
478
|
-
const peerNode =
|
|
724
|
+
if (additionalAttributes?.['category'] === 'peer') {
|
|
725
|
+
const peerNode = participants[0]?.content?.[0];
|
|
479
726
|
if (peerNode) {
|
|
480
727
|
binaryNodeContent.push(peerNode); // push only enc
|
|
481
728
|
}
|
|
@@ -492,7 +739,8 @@ const makeMessagesSocket = (config) => {
|
|
|
492
739
|
tag: 'message',
|
|
493
740
|
attrs: {
|
|
494
741
|
id: msgId,
|
|
495
|
-
|
|
742
|
+
to: destinationJid,
|
|
743
|
+
type: getMessageType(message),
|
|
496
744
|
...(additionalAttributes || {})
|
|
497
745
|
},
|
|
498
746
|
content: binaryNodeContent
|
|
@@ -501,11 +749,11 @@ const makeMessagesSocket = (config) => {
|
|
|
501
749
|
// ensure the message is only sent to that person
|
|
502
750
|
// if a retry receipt is sent to everyone -- it'll fail decryption for everyone else who received the msg
|
|
503
751
|
if (participant) {
|
|
504
|
-
if (
|
|
752
|
+
if (isJidGroup(destinationJid)) {
|
|
505
753
|
stanza.attrs.to = destinationJid;
|
|
506
754
|
stanza.attrs.participant = participant.jid;
|
|
507
755
|
}
|
|
508
|
-
else if (
|
|
756
|
+
else if (areJidsSameUser(participant.jid, meId)) {
|
|
509
757
|
stanza.attrs.to = participant.jid;
|
|
510
758
|
stanza.attrs.recipient = destinationJid;
|
|
511
759
|
}
|
|
@@ -517,116 +765,149 @@ const makeMessagesSocket = (config) => {
|
|
|
517
765
|
stanza.attrs.to = destinationJid;
|
|
518
766
|
}
|
|
519
767
|
if (shouldIncludeDeviceIdentity) {
|
|
768
|
+
;
|
|
520
769
|
stanza.content.push({
|
|
521
770
|
tag: 'device-identity',
|
|
522
771
|
attrs: {},
|
|
523
|
-
content:
|
|
772
|
+
content: encodeSignedDeviceIdentity(authState.creds.account, true)
|
|
524
773
|
});
|
|
525
774
|
logger.debug({ jid }, 'adding device identity');
|
|
526
775
|
}
|
|
527
|
-
if (
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
776
|
+
if (!isNewsletter &&
|
|
777
|
+
!isRetryResend &&
|
|
778
|
+
reportingMessage?.messageContextInfo?.messageSecret &&
|
|
779
|
+
shouldIncludeReportingToken(reportingMessage)) {
|
|
780
|
+
try {
|
|
781
|
+
const encoded = encodeWAMessage(reportingMessage);
|
|
782
|
+
const reportingKey = {
|
|
783
|
+
id: msgId,
|
|
784
|
+
fromMe: true,
|
|
785
|
+
remoteJid: destinationJid,
|
|
786
|
+
participant: participant?.jid
|
|
787
|
+
};
|
|
788
|
+
const reportingNode = await getMessageReportingToken(encoded, reportingMessage, reportingKey);
|
|
789
|
+
if (reportingNode) {
|
|
790
|
+
;
|
|
791
|
+
stanza.content.push(reportingNode);
|
|
792
|
+
logger.trace({ jid }, 'added reporting token to message');
|
|
535
793
|
}
|
|
536
794
|
}
|
|
795
|
+
catch (error) {
|
|
796
|
+
logger.warn({ jid, trace: error?.stack }, 'failed to attach reporting token');
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
// WA Web never attaches tctoken to peer (AppStateSync) messages — server rejects with 479
|
|
800
|
+
const isPeerMessage = additionalAttributes?.['category'] === 'peer';
|
|
801
|
+
const is1on1Send = !isGroup && !isRetryResend && !isStatus && !isNewsletter && !isPeerMessage;
|
|
802
|
+
// Resolve destination to LID for tctoken storage — matches Signal session key pattern
|
|
803
|
+
const tcTokenJid = is1on1Send ? await resolveTcTokenJid(destinationJid, getLIDForPN) : destinationJid;
|
|
804
|
+
const contactTcTokenData = is1on1Send ? await authState.keys.get('tctoken', [tcTokenJid]) : {};
|
|
805
|
+
const existingTokenEntry = contactTcTokenData[tcTokenJid];
|
|
806
|
+
let tcTokenBuffer = existingTokenEntry?.token;
|
|
807
|
+
// Treat expired tokens the same as missing — clear from cache
|
|
808
|
+
if (tcTokenBuffer?.length && isTcTokenExpired(existingTokenEntry?.timestamp)) {
|
|
809
|
+
logger.debug({ jid: destinationJid, timestamp: existingTokenEntry?.timestamp }, 'tctoken expired, clearing');
|
|
810
|
+
tcTokenBuffer = undefined;
|
|
811
|
+
// Preserve senderTimestamp so the fire-and-forget issuance dedupe survives cleanup.
|
|
812
|
+
const cleared = existingTokenEntry?.senderTimestamp !== undefined
|
|
813
|
+
? { token: Buffer.alloc(0), senderTimestamp: existingTokenEntry.senderTimestamp }
|
|
814
|
+
: null;
|
|
815
|
+
try {
|
|
816
|
+
await authState.keys.set({ tctoken: { [tcTokenJid]: cleared } });
|
|
817
|
+
}
|
|
818
|
+
catch (err) {
|
|
819
|
+
logger.debug({ jid: destinationJid, err: err?.message }, 'failed to persist tctoken expiry cleanup');
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
if (tcTokenBuffer?.length && sock.serverProps.privacyTokenOn1to1) {
|
|
823
|
+
;
|
|
537
824
|
stanza.content.push({
|
|
538
|
-
tag: '
|
|
539
|
-
attrs:
|
|
825
|
+
tag: 'tctoken',
|
|
826
|
+
attrs: {},
|
|
827
|
+
content: tcTokenBuffer
|
|
540
828
|
});
|
|
541
829
|
}
|
|
542
830
|
if (additionalNodes && additionalNodes.length > 0) {
|
|
831
|
+
;
|
|
543
832
|
stanza.content.push(...additionalNodes);
|
|
544
833
|
}
|
|
545
|
-
if (AI && isPrivatee) {
|
|
546
|
-
const botNode = {
|
|
547
|
-
tag: 'bot',
|
|
548
|
-
attrs: {
|
|
549
|
-
biz_bot: '1'
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
stanza.content.push(botNode);
|
|
553
|
-
}
|
|
554
|
-
const content = (0, Utils_1.normalizeMessageContent)(message);
|
|
555
|
-
const contentType = (0, Utils_1.getContentType)(content);
|
|
556
|
-
if (((0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidUser)(jid)) && (contentType === 'interactiveMessage' ||
|
|
557
|
-
contentType === 'buttonsMessage' ||
|
|
558
|
-
contentType === 'listMessage')) {
|
|
559
|
-
const bizNode = { tag: 'biz', attrs: {} };
|
|
560
|
-
if ((((_l = (_k = message === null || message === void 0 ? void 0 : message.viewOnceMessage) === null || _k === void 0 ? void 0 : _k.message) === null || _l === void 0 ? void 0 : _l.interactiveMessage) || ((_o = (_m = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2) === null || _m === void 0 ? void 0 : _m.message) === null || _o === void 0 ? void 0 : _o.interactiveMessage) || ((_q = (_p = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension) === null || _p === void 0 ? void 0 : _p.message) === null || _q === void 0 ? void 0 : _q.interactiveMessage) || (message === null || message === void 0 ? void 0 : message.interactiveMessage)) || (((_s = (_r = message === null || message === void 0 ? void 0 : message.viewOnceMessage) === null || _r === void 0 ? void 0 : _r.message) === null || _s === void 0 ? void 0 : _s.buttonsMessage) || ((_u = (_t = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2) === null || _t === void 0 ? void 0 : _t.message) === null || _u === void 0 ? void 0 : _u.buttonsMessage) || ((_w = (_v = message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension) === null || _v === void 0 ? void 0 : _v.message) === null || _w === void 0 ? void 0 : _w.buttonsMessage) || (message === null || message === void 0 ? void 0 : message.buttonsMessage))) {
|
|
561
|
-
bizNode.content = [{
|
|
562
|
-
tag: 'interactive',
|
|
563
|
-
attrs: {
|
|
564
|
-
type: 'native_flow',
|
|
565
|
-
v: '1'
|
|
566
|
-
},
|
|
567
|
-
content: [{
|
|
568
|
-
tag: 'native_flow',
|
|
569
|
-
attrs: { v: '9', name: 'mixed' }
|
|
570
|
-
}]
|
|
571
|
-
}];
|
|
572
|
-
}
|
|
573
|
-
else if (message === null || message === void 0 ? void 0 : message.listMessage) {
|
|
574
|
-
// list message only support in private chat
|
|
575
|
-
bizNode.content = [{
|
|
576
|
-
tag: 'list',
|
|
577
|
-
attrs: {
|
|
578
|
-
type: 'product_list',
|
|
579
|
-
v: '2'
|
|
580
|
-
}
|
|
581
|
-
}];
|
|
582
|
-
}
|
|
583
|
-
stanza.content.push(bizNode);
|
|
584
|
-
}
|
|
585
834
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
586
835
|
await sendNode(stanza);
|
|
587
|
-
|
|
836
|
+
// Fire-and-forget: issue our token to the contact AFTER message send.
|
|
837
|
+
// WA Web skips protocol messages and PSA/bot contacts (TcTokenChatAction: isRegularUser)
|
|
838
|
+
const isProtocolMsg = !!normalizeMessageContent(message)?.protocolMessage;
|
|
839
|
+
const isBotOrPSA = destinationJid === PSA_WID || isJidBot(destinationJid) || isJidMetaAI(destinationJid);
|
|
840
|
+
if (is1on1Send &&
|
|
841
|
+
!isProtocolMsg &&
|
|
842
|
+
!isBotOrPSA &&
|
|
843
|
+
shouldSendNewTcToken(existingTokenEntry?.senderTimestamp) &&
|
|
844
|
+
!inFlightTcTokenIssuance.has(tcTokenJid)) {
|
|
845
|
+
inFlightTcTokenIssuance.add(tcTokenJid);
|
|
846
|
+
const issueTimestamp = unixTimestampSeconds();
|
|
847
|
+
const getPNForLID = signalRepository.lidMapping.getPNForLID.bind(signalRepository.lidMapping);
|
|
848
|
+
resolveIssuanceJid(destinationJid, sock.serverProps.lidTrustedTokenIssueToLid, getLIDForPN, getPNForLID)
|
|
849
|
+
.then(issueJid => issuePrivacyTokens([issueJid], issueTimestamp))
|
|
850
|
+
.then(async (result) => {
|
|
851
|
+
await storeTcTokensFromIqResult({
|
|
852
|
+
result,
|
|
853
|
+
fallbackJid: tcTokenJid,
|
|
854
|
+
keys: authState.keys,
|
|
855
|
+
getLIDForPN
|
|
856
|
+
});
|
|
857
|
+
const currentData = await authState.keys.get('tctoken', [tcTokenJid]);
|
|
858
|
+
const currentEntry = currentData[tcTokenJid];
|
|
859
|
+
const indexWrite = await buildMergedTcTokenIndexWrite(authState.keys, [tcTokenJid]);
|
|
860
|
+
await authState.keys.set({
|
|
861
|
+
tctoken: {
|
|
862
|
+
[tcTokenJid]: {
|
|
863
|
+
token: Buffer.alloc(0),
|
|
864
|
+
...currentEntry,
|
|
865
|
+
senderTimestamp: issueTimestamp
|
|
866
|
+
},
|
|
867
|
+
...indexWrite
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
})
|
|
871
|
+
.catch(err => {
|
|
872
|
+
logger.debug({ jid: destinationJid, err: err?.message }, 'fire-and-forget tctoken issuance failed');
|
|
873
|
+
})
|
|
874
|
+
.finally(() => {
|
|
875
|
+
inFlightTcTokenIssuance.delete(tcTokenJid);
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
// Add message to retry cache if enabled
|
|
879
|
+
if (messageRetryManager && !participant) {
|
|
880
|
+
messageRetryManager.addRecentMessage(destinationJid, msgId, message);
|
|
881
|
+
}
|
|
882
|
+
}, meId);
|
|
588
883
|
return msgId;
|
|
589
884
|
};
|
|
590
|
-
const
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
return getTypeMessage(msg.viewOnceMessageV2.message);
|
|
596
|
-
}
|
|
597
|
-
else if (msg.viewOnceMessageV2Extension) {
|
|
598
|
-
return getTypeMessage(msg.viewOnceMessageV2Extension.message);
|
|
599
|
-
}
|
|
600
|
-
else if (msg.ephemeralMessage) {
|
|
601
|
-
return getTypeMessage(msg.ephemeralMessage.message);
|
|
602
|
-
}
|
|
603
|
-
else if (msg.documentWithCaptionMessage) {
|
|
604
|
-
return getTypeMessage(msg.documentWithCaptionMessage.message);
|
|
605
|
-
}
|
|
606
|
-
else if (msg.reactionMessage) {
|
|
885
|
+
const getMessageType = (message) => {
|
|
886
|
+
const normalizedMessage = normalizeMessageContent(message);
|
|
887
|
+
if (!normalizedMessage)
|
|
888
|
+
return 'text';
|
|
889
|
+
if (normalizedMessage.reactionMessage || normalizedMessage.encReactionMessage) {
|
|
607
890
|
return 'reaction';
|
|
608
891
|
}
|
|
609
|
-
|
|
892
|
+
if (normalizedMessage.pollCreationMessage ||
|
|
893
|
+
normalizedMessage.pollCreationMessageV2 ||
|
|
894
|
+
normalizedMessage.pollCreationMessageV3 ||
|
|
895
|
+
normalizedMessage.pollUpdateMessage) {
|
|
610
896
|
return 'poll';
|
|
611
897
|
}
|
|
612
|
-
|
|
613
|
-
return '
|
|
898
|
+
if (normalizedMessage.eventMessage) {
|
|
899
|
+
return 'event';
|
|
614
900
|
}
|
|
615
|
-
|
|
616
|
-
return '
|
|
901
|
+
if (getMediaType(normalizedMessage) !== '') {
|
|
902
|
+
return 'media';
|
|
617
903
|
}
|
|
904
|
+
return 'text';
|
|
618
905
|
};
|
|
619
906
|
const getMediaType = (message) => {
|
|
620
907
|
if (message.imageMessage) {
|
|
621
908
|
return 'image';
|
|
622
909
|
}
|
|
623
|
-
else if (message.ptvMessage) {
|
|
624
|
-
return 'ptv';
|
|
625
|
-
}
|
|
626
910
|
else if (message.videoMessage) {
|
|
627
|
-
if (message.videoMessage.ptv) {
|
|
628
|
-
return 'ptv';
|
|
629
|
-
}
|
|
630
911
|
return message.videoMessage.gifPlayback ? 'gif' : 'video';
|
|
631
912
|
}
|
|
632
913
|
else if (message.audioMessage) {
|
|
@@ -665,19 +946,17 @@ const makeMessagesSocket = (config) => {
|
|
|
665
946
|
else if (message.interactiveResponseMessage) {
|
|
666
947
|
return 'native_flow_response';
|
|
667
948
|
}
|
|
668
|
-
else if (message.richResponseMessage) {
|
|
669
|
-
return 'rich_response';
|
|
670
|
-
}
|
|
671
949
|
else if (message.groupInviteMessage) {
|
|
672
950
|
return 'url';
|
|
673
951
|
}
|
|
952
|
+
return '';
|
|
674
953
|
};
|
|
675
|
-
const
|
|
676
|
-
const t = (
|
|
954
|
+
const issuePrivacyTokens = async (jids, timestamp) => {
|
|
955
|
+
const t = (timestamp ?? unixTimestampSeconds()).toString();
|
|
677
956
|
const result = await query({
|
|
678
957
|
tag: 'iq',
|
|
679
958
|
attrs: {
|
|
680
|
-
to:
|
|
959
|
+
to: S_WHATSAPP_NET,
|
|
681
960
|
type: 'set',
|
|
682
961
|
xmlns: 'privacy'
|
|
683
962
|
},
|
|
@@ -688,7 +967,7 @@ const makeMessagesSocket = (config) => {
|
|
|
688
967
|
content: jids.map(jid => ({
|
|
689
968
|
tag: 'token',
|
|
690
969
|
attrs: {
|
|
691
|
-
jid:
|
|
970
|
+
jid: jidNormalizedUser(jid),
|
|
692
971
|
t,
|
|
693
972
|
type: 'trusted_contact'
|
|
694
973
|
}
|
|
@@ -698,29 +977,42 @@ const makeMessagesSocket = (config) => {
|
|
|
698
977
|
});
|
|
699
978
|
return result;
|
|
700
979
|
};
|
|
701
|
-
const waUploadToServer =
|
|
702
|
-
const
|
|
703
|
-
|
|
980
|
+
const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
|
|
981
|
+
const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
|
|
982
|
+
registerSocketEndHandler(() => {
|
|
983
|
+
if (!config.userDevicesCache && userDevicesCache.close) {
|
|
984
|
+
userDevicesCache.close();
|
|
985
|
+
}
|
|
986
|
+
mediaConn = undefined;
|
|
987
|
+
if (messageRetryManager) {
|
|
988
|
+
messageRetryManager.clear();
|
|
989
|
+
}
|
|
990
|
+
});
|
|
704
991
|
return {
|
|
705
992
|
...sock,
|
|
706
|
-
|
|
993
|
+
userDevicesCache,
|
|
994
|
+
devicesMutex,
|
|
995
|
+
issuePrivacyTokens,
|
|
707
996
|
assertSessions,
|
|
708
997
|
relayMessage,
|
|
709
998
|
sendReceipt,
|
|
710
999
|
sendReceipts,
|
|
711
|
-
avelinel,
|
|
712
1000
|
readMessages,
|
|
713
1001
|
refreshMediaConn,
|
|
1002
|
+
// Function (not getter) so the spread in chats.ts preserves the live closure binding.
|
|
1003
|
+
getMediaHost: () => mediaHost,
|
|
714
1004
|
waUploadToServer,
|
|
715
1005
|
fetchPrivacySettings,
|
|
716
|
-
getUSyncDevices,
|
|
717
|
-
createParticipantNodes,
|
|
718
1006
|
sendPeerDataOperationMessage,
|
|
1007
|
+
createParticipantNodes,
|
|
1008
|
+
getUSyncDevices,
|
|
1009
|
+
messageRetryManager,
|
|
1010
|
+
updateMemberLabel,
|
|
719
1011
|
updateMediaMessage: async (message) => {
|
|
720
|
-
const content =
|
|
1012
|
+
const content = assertMediaContent(message.message);
|
|
721
1013
|
const mediaKey = content.mediaKey;
|
|
722
1014
|
const meId = authState.creds.me.id;
|
|
723
|
-
const node =
|
|
1015
|
+
const node = encryptMediaRetryRequest(message.key, mediaKey, meId);
|
|
724
1016
|
let error = undefined;
|
|
725
1017
|
await Promise.all([
|
|
726
1018
|
sendNode(node),
|
|
@@ -732,13 +1024,16 @@ const makeMessagesSocket = (config) => {
|
|
|
732
1024
|
}
|
|
733
1025
|
else {
|
|
734
1026
|
try {
|
|
735
|
-
const media =
|
|
736
|
-
if (media.result !==
|
|
737
|
-
const resultStr =
|
|
738
|
-
throw new
|
|
1027
|
+
const media = decryptMediaRetryData(result.media, mediaKey, result.key.id);
|
|
1028
|
+
if (media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
|
|
1029
|
+
const resultStr = proto.MediaRetryNotification.ResultType[media.result];
|
|
1030
|
+
throw new Boom(`Media re-upload failed by device (${resultStr})`, {
|
|
1031
|
+
data: media,
|
|
1032
|
+
statusCode: getStatusCodeForMediaRetry(media.result) || 404
|
|
1033
|
+
});
|
|
739
1034
|
}
|
|
740
1035
|
content.directPath = media.directPath;
|
|
741
|
-
content.url =
|
|
1036
|
+
content.url = getUrlFromDirectPath(content.directPath, mediaHost);
|
|
742
1037
|
logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful');
|
|
743
1038
|
}
|
|
744
1039
|
catch (err) {
|
|
@@ -752,384 +1047,94 @@ const makeMessagesSocket = (config) => {
|
|
|
752
1047
|
if (error) {
|
|
753
1048
|
throw error;
|
|
754
1049
|
}
|
|
755
|
-
ev.emit('messages.update', [
|
|
756
|
-
{ key: message.key, update: { message: message.message } }
|
|
757
|
-
]);
|
|
1050
|
+
ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
|
|
758
1051
|
return message;
|
|
759
1052
|
},
|
|
760
|
-
sendStatusMentions: async (content, jids = []) => {
|
|
761
|
-
const userJid = WABinary_1.jidNormalizedUser(authState.creds.me.id)
|
|
762
|
-
let allUsers = new Set()
|
|
763
|
-
allUsers.add(userJid)
|
|
764
|
-
|
|
765
|
-
for (const id of jids) {
|
|
766
|
-
const isGroup = WABinary_1.isJidGroup(id)
|
|
767
|
-
const isPrivate = WABinary_1.isJidUser(id)
|
|
768
|
-
|
|
769
|
-
if (isGroup) {
|
|
770
|
-
try {
|
|
771
|
-
const metadata = await cachedGroupMetadata(id) || await global.groupMetadataCache(id)
|
|
772
|
-
const participants = metadata.participants.map(p => WABinary_1.jidNormalizedUser(p.id))
|
|
773
|
-
participants.forEach(jid => allUsers.add(jid))
|
|
774
|
-
} catch (error) {
|
|
775
|
-
logger.error(`Error getting metadata for group ${id}: ${error}`)
|
|
776
|
-
}
|
|
777
|
-
} else if (isPrivate) {
|
|
778
|
-
allUsers.add(WABinary_1.jidNormalizedUser(id))
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
const uniqueUsers = Array.from(allUsers)
|
|
783
|
-
const getRandomHexColor = () => "#" + Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0")
|
|
784
|
-
|
|
785
|
-
const isMedia = content.image || content.video || content.audio
|
|
786
|
-
const isAudio = !!content.audio
|
|
787
|
-
|
|
788
|
-
const messageContent = {
|
|
789
|
-
...content
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
if (isMedia && !isAudio) {
|
|
793
|
-
if (messageContent.text) {
|
|
794
|
-
messageContent.caption = messageContent.text
|
|
795
|
-
|
|
796
|
-
delete messageContent.text
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
delete messageContent.ptt
|
|
800
|
-
delete messageContent.font
|
|
801
|
-
delete messageContent.backgroundColor
|
|
802
|
-
delete messageContent.textColor
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
if (isAudio) {
|
|
806
|
-
delete messageContent.text
|
|
807
|
-
delete messageContent.caption
|
|
808
|
-
delete messageContent.font
|
|
809
|
-
delete messageContent.textColor
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
const font = !isMedia ? (content.font || Math.floor(Math.random() * 9)) : undefined
|
|
813
|
-
const textColor = !isMedia ? (content.textColor || getRandomHexColor()) : undefined
|
|
814
|
-
const backgroundColor = (!isMedia || isAudio) ? (content.backgroundColor || getRandomHexColor()) : undefined
|
|
815
|
-
const ptt = isAudio ? (typeof content.ptt === 'boolean' ? content.ptt : true) : undefined
|
|
816
|
-
|
|
817
|
-
let msg
|
|
818
|
-
let mediaHandle
|
|
819
|
-
try {
|
|
820
|
-
msg = await Utils_1.generateWAMessage(WABinary_1.STORIES_JID, messageContent, {
|
|
821
|
-
logger,
|
|
822
|
-
userJid,
|
|
823
|
-
getUrlInfo: text => link_preview_1.getUrlInfo(text, {
|
|
824
|
-
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
825
|
-
fetchOpts: {
|
|
826
|
-
timeout: 3000,
|
|
827
|
-
...axiosOptions || {}
|
|
828
|
-
},
|
|
829
|
-
logger,
|
|
830
|
-
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
831
|
-
}),
|
|
832
|
-
upload: async (encFilePath, opts) => {
|
|
833
|
-
const up = await waUploadToServer(encFilePath, {
|
|
834
|
-
...opts
|
|
835
|
-
})
|
|
836
|
-
mediaHandle = up.handle
|
|
837
|
-
return up
|
|
838
|
-
},
|
|
839
|
-
mediaCache: config.mediaCache,
|
|
840
|
-
options: config.options,
|
|
841
|
-
font,
|
|
842
|
-
textColor,
|
|
843
|
-
backgroundColor,
|
|
844
|
-
ptt
|
|
845
|
-
})
|
|
846
|
-
} catch (error) {
|
|
847
|
-
logger.error(`Error generating message: ${error}`)
|
|
848
|
-
throw error
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
await relayMessage(WABinary_1.STORIES_JID, msg.message, {
|
|
852
|
-
messageId: msg.key.id,
|
|
853
|
-
statusJidList: uniqueUsers,
|
|
854
|
-
additionalNodes: [{
|
|
855
|
-
tag: 'meta',
|
|
856
|
-
attrs: {},
|
|
857
|
-
content: [{
|
|
858
|
-
tag: 'mentioned_users',
|
|
859
|
-
attrs: {},
|
|
860
|
-
content: jids.map(jid => ({
|
|
861
|
-
tag: 'to',
|
|
862
|
-
attrs: {
|
|
863
|
-
jid: WABinary_1.jidNormalizedUser(jid)
|
|
864
|
-
}
|
|
865
|
-
}))
|
|
866
|
-
}]
|
|
867
|
-
}]
|
|
868
|
-
})
|
|
869
|
-
|
|
870
|
-
for (const id of jids) {
|
|
871
|
-
try {
|
|
872
|
-
const normalizedId = WABinary_1.jidNormalizedUser(id)
|
|
873
|
-
const isPrivate = WABinary_1.isJidUser(normalizedId)
|
|
874
|
-
const type = isPrivate ? 'statusMentionMessage' : 'groupStatusMentionMessage'
|
|
875
|
-
|
|
876
|
-
const protocolMessage = {
|
|
877
|
-
[type]: {
|
|
878
|
-
message: {
|
|
879
|
-
protocolMessage: {
|
|
880
|
-
key: msg.key,
|
|
881
|
-
type: 25
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
},
|
|
885
|
-
messageContextInfo: {
|
|
886
|
-
messageSecret: crypto_1.randomBytes(32)
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
const statusMsg = await Utils_1.generateWAMessageFromContent(normalizedId,
|
|
891
|
-
protocolMessage, {}
|
|
892
|
-
)
|
|
893
|
-
|
|
894
|
-
await relayMessage(
|
|
895
|
-
normalizedId,
|
|
896
|
-
statusMsg.message, {
|
|
897
|
-
additionalNodes: [{
|
|
898
|
-
tag: 'meta',
|
|
899
|
-
attrs: isPrivate ? {
|
|
900
|
-
is_status_mention: 'true'
|
|
901
|
-
} : {
|
|
902
|
-
is_group_status_mention: 'true'
|
|
903
|
-
}
|
|
904
|
-
}]
|
|
905
|
-
}
|
|
906
|
-
)
|
|
907
|
-
|
|
908
|
-
await Utils_1.delay(2000)
|
|
909
|
-
} catch (error) {
|
|
910
|
-
logger.error(`Error sending to ${id}: ${error}`)
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
return msg
|
|
915
|
-
},
|
|
916
1053
|
sendMessage: async (jid, content, options = {}) => {
|
|
917
|
-
var _a, _b, _c;
|
|
918
1054
|
const userJid = authState.creds.me.id;
|
|
919
|
-
const getParticipantAttr = () => filter ? { participant: { jid } } : {};
|
|
920
|
-
const { filter = false, quoted } = options;
|
|
921
|
-
const messageType = avelinel.detectType(content);
|
|
922
|
-
|
|
923
|
-
if (messageType) {
|
|
924
|
-
switch (messageType) {
|
|
925
|
-
case 'PAYMENT':
|
|
926
|
-
const paymentContent = await avelinel.handlePayment(content, quoted);
|
|
927
|
-
return await relayMessage(jid, paymentContent, {
|
|
928
|
-
messageId: Utils_1.generateMessageID(),
|
|
929
|
-
...getParticipantAttr()
|
|
930
|
-
});
|
|
931
|
-
|
|
932
|
-
case 'PRODUCT':
|
|
933
|
-
const productContent = await avelinel.handleProduct(content, jid, quoted);
|
|
934
|
-
const productMsg = await Utils_1.generateWAMessageFromContent(jid, productContent, { quoted });
|
|
935
|
-
return await relayMessage(jid, productMsg.message, {
|
|
936
|
-
messageId: productMsg.key.id,
|
|
937
|
-
...getParticipantAttr()
|
|
938
|
-
});
|
|
939
|
-
|
|
940
|
-
case 'INTERACTIVE':
|
|
941
|
-
const interactiveContent = await avelinel.handleInteractive(content, jid, quoted);
|
|
942
|
-
const interactiveMsg = await Utils_1.generateWAMessageFromContent(jid, interactiveContent, { quoted });
|
|
943
|
-
return await relayMessage(jid, interactiveMsg.message, {
|
|
944
|
-
messageId: interactiveMsg.key.id,
|
|
945
|
-
...getParticipantAttr()
|
|
946
|
-
});
|
|
947
|
-
|
|
948
|
-
case 'ALBUM':
|
|
949
|
-
const albumContent = await avelinel.handleAlbum(content, jid, quoted);
|
|
950
|
-
return albumContent;
|
|
951
|
-
|
|
952
|
-
case 'EVENT':
|
|
953
|
-
return await avelinel.handleEvent(content, jid, quoted);
|
|
954
|
-
|
|
955
|
-
case 'POLL_RESULT':
|
|
956
|
-
return await avelinel.handlePollResult(content, jid, quoted);
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
if (!options.ephemeralExpiration) {
|
|
961
|
-
if ((0, WABinary_1.isJidGroup)(jid)) {
|
|
962
|
-
const groups = await sock.groupQuery(jid, 'get', [{
|
|
963
|
-
tag: 'query',
|
|
964
|
-
attrs: {
|
|
965
|
-
request: 'interactive'
|
|
966
|
-
}
|
|
967
|
-
}]);
|
|
968
|
-
const metadata = (0, WABinary_1.getBinaryNodeChild)(groups, 'group');
|
|
969
|
-
const expiration = ((_b = (_a = (0, WABinary_1.getBinaryNodeChild)(metadata, 'ephemeral')) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b.expiration) || 0;
|
|
970
|
-
options.ephemeralExpiration = expiration;
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
|
|
974
1055
|
if (typeof content === 'object' &&
|
|
975
1056
|
'disappearingMessagesInChat' in content &&
|
|
976
1057
|
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
977
|
-
|
|
1058
|
+
isJidGroup(jid)) {
|
|
978
1059
|
const { disappearingMessagesInChat } = content;
|
|
979
|
-
const value = typeof disappearingMessagesInChat === 'boolean'
|
|
980
|
-
|
|
981
|
-
|
|
1060
|
+
const value = typeof disappearingMessagesInChat === 'boolean'
|
|
1061
|
+
? disappearingMessagesInChat
|
|
1062
|
+
? WA_DEFAULT_EPHEMERAL
|
|
1063
|
+
: 0
|
|
1064
|
+
: disappearingMessagesInChat;
|
|
982
1065
|
await groupToggleEphemeral(jid, value);
|
|
983
1066
|
}
|
|
984
|
-
if (typeof content === 'object' && 'album' in content && content.album) {
|
|
985
|
-
const { album, caption } = content;
|
|
986
|
-
if (caption && !album[0].caption) {
|
|
987
|
-
album[0].caption = caption;
|
|
988
|
-
}
|
|
989
|
-
let mediaHandle;
|
|
990
|
-
let mediaMsg;
|
|
991
|
-
const albumMsg = (0, Utils_1.generateWAMessageFromContent)(jid, {
|
|
992
|
-
albumMessage: {
|
|
993
|
-
expectedImageCount: album.filter(item => 'image' in item).length,
|
|
994
|
-
expectedVideoCount: album.filter(item => 'video' in item).length
|
|
995
|
-
}
|
|
996
|
-
}, { userJid, ...options });
|
|
997
|
-
await relayMessage(jid, albumMsg.message, {
|
|
998
|
-
messageId: albumMsg.key.id
|
|
999
|
-
});
|
|
1000
|
-
for (const i in album) {
|
|
1001
|
-
const media = album[i];
|
|
1002
|
-
if ('image' in media) {
|
|
1003
|
-
mediaMsg = await (0, Utils_1.generateWAMessage)(jid, {
|
|
1004
|
-
image: media.image,
|
|
1005
|
-
...(media.caption ? { caption: media.caption } : {}),
|
|
1006
|
-
...options
|
|
1007
|
-
}, {
|
|
1008
|
-
userJid,
|
|
1009
|
-
upload: async (readStream, opts) => {
|
|
1010
|
-
const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
|
|
1011
|
-
mediaHandle = up.handle;
|
|
1012
|
-
return up;
|
|
1013
|
-
},
|
|
1014
|
-
...options,
|
|
1015
|
-
});
|
|
1016
|
-
}
|
|
1017
|
-
else if ('video' in media) {
|
|
1018
|
-
mediaMsg = await (0, Utils_1.generateWAMessage)(jid, {
|
|
1019
|
-
video: media.video,
|
|
1020
|
-
...(media.caption ? { caption: media.caption } : {}),
|
|
1021
|
-
...(media.gifPlayback !== undefined ? { gifPlayback: media.gifPlayback } : {}),
|
|
1022
|
-
...options
|
|
1023
|
-
}, {
|
|
1024
|
-
userJid,
|
|
1025
|
-
upload: async (readStream, opts) => {
|
|
1026
|
-
const up = await waUploadToServer(readStream, { ...opts, newsletter: (0, WABinary_1.isJidNewsletter)(jid) });
|
|
1027
|
-
mediaHandle = up.handle;
|
|
1028
|
-
return up;
|
|
1029
|
-
},
|
|
1030
|
-
...options,
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
if (mediaMsg) {
|
|
1034
|
-
mediaMsg.message.messageContextInfo = {
|
|
1035
|
-
messageSecret: (0, crypto_1.randomBytes)(32),
|
|
1036
|
-
messageAssociation: {
|
|
1037
|
-
associationType: 1,
|
|
1038
|
-
parentMessageKey: albumMsg.key
|
|
1039
|
-
}
|
|
1040
|
-
};
|
|
1041
|
-
}
|
|
1042
|
-
await relayMessage(jid, mediaMsg.message, {
|
|
1043
|
-
messageId: mediaMsg.key.id
|
|
1044
|
-
});
|
|
1045
|
-
await new Promise(resolve => setTimeout(resolve, 800));
|
|
1046
|
-
}
|
|
1047
|
-
return albumMsg;
|
|
1048
|
-
}
|
|
1049
1067
|
else {
|
|
1050
|
-
|
|
1051
|
-
const fullMsg = await (0, Utils_1.generateWAMessage)(jid, content, {
|
|
1068
|
+
const fullMsg = await generateWAMessage(jid, content, {
|
|
1052
1069
|
logger,
|
|
1053
1070
|
userJid,
|
|
1054
|
-
getUrlInfo: text =>
|
|
1071
|
+
getUrlInfo: text => getUrlInfo(text, {
|
|
1055
1072
|
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
1056
1073
|
fetchOpts: {
|
|
1057
1074
|
timeout: 3000,
|
|
1058
|
-
...
|
|
1075
|
+
...(httpRequestOptions || {})
|
|
1059
1076
|
},
|
|
1060
1077
|
logger,
|
|
1061
|
-
uploadImage: generateHighQualityLinkPreview
|
|
1062
|
-
? waUploadToServer
|
|
1063
|
-
: undefined
|
|
1078
|
+
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
1064
1079
|
}),
|
|
1080
|
+
//TODO: CACHE
|
|
1065
1081
|
getProfilePicUrl: sock.profilePictureUrl,
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
mediaHandle = up.handle;
|
|
1069
|
-
return up;
|
|
1070
|
-
},
|
|
1082
|
+
getCallLink: sock.createCallLink,
|
|
1083
|
+
upload: waUploadToServer,
|
|
1071
1084
|
mediaCache: config.mediaCache,
|
|
1072
1085
|
options: config.options,
|
|
1073
|
-
messageId:
|
|
1074
|
-
...options
|
|
1086
|
+
messageId: generateMessageIDV2(sock.user?.id),
|
|
1087
|
+
...options
|
|
1075
1088
|
});
|
|
1089
|
+
const isEventMsg = 'event' in content && !!content.event;
|
|
1076
1090
|
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
1077
1091
|
const isEditMsg = 'edit' in content && !!content.edit;
|
|
1078
1092
|
const isPinMsg = 'pin' in content && !!content.pin;
|
|
1079
|
-
const isKeepMsg = 'keep' in content && content.keep;
|
|
1080
1093
|
const isPollMessage = 'poll' in content && !!content.poll;
|
|
1081
|
-
const isAiMsg = 'ai' in content && !!content.ai;
|
|
1082
1094
|
const additionalAttributes = {};
|
|
1083
1095
|
const additionalNodes = [];
|
|
1084
1096
|
// required for delete
|
|
1085
1097
|
if (isDeleteMsg) {
|
|
1086
1098
|
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
1087
|
-
if (
|
|
1099
|
+
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
1088
1100
|
additionalAttributes.edit = '8';
|
|
1089
1101
|
}
|
|
1090
1102
|
else {
|
|
1091
1103
|
additionalAttributes.edit = '7';
|
|
1092
1104
|
}
|
|
1093
|
-
// required for edit message
|
|
1094
1105
|
}
|
|
1095
1106
|
else if (isEditMsg) {
|
|
1096
|
-
additionalAttributes.edit =
|
|
1097
|
-
// required for pin message
|
|
1107
|
+
additionalAttributes.edit = '1';
|
|
1098
1108
|
}
|
|
1099
1109
|
else if (isPinMsg) {
|
|
1100
1110
|
additionalAttributes.edit = '2';
|
|
1101
|
-
// required for keep message
|
|
1102
|
-
}
|
|
1103
|
-
else if (isKeepMsg) {
|
|
1104
|
-
additionalAttributes.edit = '6';
|
|
1105
|
-
// required for polling message
|
|
1106
1111
|
}
|
|
1107
1112
|
else if (isPollMessage) {
|
|
1108
1113
|
additionalNodes.push({
|
|
1109
1114
|
tag: 'meta',
|
|
1110
1115
|
attrs: {
|
|
1111
1116
|
polltype: 'creation'
|
|
1112
|
-
}
|
|
1117
|
+
}
|
|
1113
1118
|
});
|
|
1114
|
-
// required to display AI icon on message
|
|
1115
1119
|
}
|
|
1116
|
-
else if (
|
|
1120
|
+
else if (isEventMsg) {
|
|
1117
1121
|
additionalNodes.push({
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
if (mediaHandle) {
|
|
1124
|
-
additionalAttributes['media_id'] = mediaHandle;
|
|
1125
|
-
}
|
|
1126
|
-
if ('cachedGroupMetadata' in options) {
|
|
1127
|
-
console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.');
|
|
1122
|
+
tag: 'meta',
|
|
1123
|
+
attrs: {
|
|
1124
|
+
event_type: 'creation'
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1128
1127
|
}
|
|
1129
|
-
await relayMessage(jid, fullMsg.message, {
|
|
1128
|
+
await relayMessage(jid, fullMsg.message, {
|
|
1129
|
+
messageId: fullMsg.key.id,
|
|
1130
|
+
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
1131
|
+
additionalAttributes,
|
|
1132
|
+
statusJidList: options.statusJidList,
|
|
1133
|
+
additionalNodes
|
|
1134
|
+
});
|
|
1130
1135
|
if (config.emitOwnEvents) {
|
|
1131
|
-
process.nextTick(() => {
|
|
1132
|
-
|
|
1136
|
+
process.nextTick(async () => {
|
|
1137
|
+
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1133
1138
|
});
|
|
1134
1139
|
}
|
|
1135
1140
|
return fullMsg;
|
|
@@ -1137,4 +1142,4 @@ const makeMessagesSocket = (config) => {
|
|
|
1137
1142
|
}
|
|
1138
1143
|
};
|
|
1139
1144
|
};
|
|
1140
|
-
|
|
1145
|
+
//# sourceMappingURL=messages-send.js.map
|