@modzneverdie/baileys 17.1.2 → 17.1.3
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/LICENSE +21 -0
- package/WAProto/GenerateStatics.sh +3 -0
- package/WAProto/WAProto.proto +6035 -0
- package/WAProto/fix-imports.js +81 -0
- package/WAProto/index.d.ts +2 -0
- package/WAProto/index.js +59469 -96804
- package/lib/Defaults/index.d.ts +29 -8
- package/lib/Defaults/index.d.ts.map +1 -0
- package/lib/Defaults/index.js +134 -141
- package/lib/Defaults/index.js.map +1 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +1 -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 +4 -3
- 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 +4 -4
- 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 -11
- 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 +2 -1
- 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 +3 -2
- 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 +2 -1
- 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 +2 -1
- 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 +1 -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 +3 -2
- 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 +7 -6
- 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 +1 -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 -3
- package/lib/Signal/libsignal.d.ts.map +1 -0
- package/lib/Signal/libsignal.js +319 -90
- package/lib/Signal/libsignal.js.map +1 -0
- package/lib/Signal/lid-mapping.d.ts +19 -0
- package/lib/Signal/lid-mapping.d.ts.map +1 -0
- package/lib/Signal/lid-mapping.js +271 -0
- package/lib/Signal/lid-mapping.js.map +1 -0
- package/lib/Socket/Client/index.d.ts +3 -3
- package/lib/Socket/Client/index.d.ts.map +1 -0
- package/lib/Socket/Client/index.js +3 -19
- package/lib/Socket/Client/index.js.map +1 -0
- package/lib/Socket/Client/{abstract-socket-client.d.ts → types.d.ts} +4 -5
- package/lib/Socket/Client/types.d.ts.map +1 -0
- package/lib/Socket/Client/types.js +11 -0
- package/lib/Socket/Client/types.js.map +1 -0
- package/lib/Socket/Client/{web-socket-client.d.ts → websocket.d.ts} +3 -2
- package/lib/Socket/Client/websocket.d.ts.map +1 -0
- package/lib/Socket/Client/websocket.js +54 -0
- package/lib/Socket/Client/websocket.js.map +1 -0
- package/lib/Socket/business.d.ts +533 -168
- package/lib/Socket/business.d.ts.map +1 -0
- package/lib/Socket/business.js +405 -243
- package/lib/Socket/business.js.map +1 -0
- package/lib/Socket/chats.d.ts +84 -240
- package/lib/Socket/chats.d.ts.map +1 -0
- package/lib/Socket/chats.js +406 -385
- package/lib/Socket/chats.js.map +1 -0
- package/lib/Socket/communities.d.ts +645 -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/dugong.d.ts +125 -249
- package/lib/Socket/dugong.d.ts.map +1 -0
- package/lib/Socket/dugong.js +749 -465
- package/lib/Socket/dugong.js.map +1 -0
- package/lib/Socket/groups.d.ts +93 -58
- package/lib/Socket/groups.d.ts.map +1 -0
- package/lib/Socket/groups.js +105 -95
- package/lib/Socket/groups.js.map +1 -0
- package/lib/Socket/index.d.ts +632 -169
- package/lib/Socket/index.d.ts.map +1 -0
- package/lib/Socket/index.js +15 -11
- package/lib/Socket/index.js.map +1 -0
- package/lib/Socket/messages-recv.d.ts +162 -85
- package/lib/Socket/messages-recv.d.ts.map +1 -0
- package/lib/Socket/messages-recv.js +806 -608
- package/lib/Socket/messages-recv.js.map +1 -0
- package/lib/Socket/messages-send.d.ts +576 -146
- package/lib/Socket/messages-send.d.ts.map +1 -0
- package/lib/Socket/messages-send.js +1563 -861
- 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 +48 -0
- package/lib/Socket/mex.js.map +1 -0
- package/lib/Socket/newsletter.d.ts +129 -86
- package/lib/Socket/newsletter.d.ts.map +1 -0
- package/lib/Socket/newsletter.js +438 -297
- package/lib/Socket/newsletter.js.map +1 -0
- package/lib/Socket/socket.d.ts +31 -19
- package/lib/Socket/socket.d.ts.map +1 -0
- package/lib/Socket/socket.js +512 -241
- package/lib/Socket/socket.js.map +1 -0
- package/lib/Types/Auth.d.ts +18 -12
- 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 +37 -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 +3 -1
- 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 +34 -13
- 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 +6 -1
- 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 +97 -17
- 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 +18 -5
- 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 +12 -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 +1 -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 +355 -206
- package/lib/Types/Message.d.ts.map +1 -0
- package/lib/Types/Message.js +11 -9
- package/lib/Types/Message.js.map +1 -0
- package/lib/Types/Newsletter.d.ts +130 -98
- package/lib/Types/Newsletter.d.ts.map +1 -0
- package/lib/Types/Newsletter.js +31 -38
- package/lib/Types/Newsletter.js.map +1 -0
- package/lib/Types/Product.d.ts +2 -1
- 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 +20 -1
- 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 +152 -105
- 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 +14 -2
- package/lib/Types/State.d.ts.map +1 -0
- package/lib/Types/State.js +13 -2
- package/lib/Types/State.js.map +1 -0
- package/lib/Types/USync.d.ts +3 -2
- 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 +54 -45
- package/lib/Types/index.d.ts.map +1 -0
- package/lib/Types/index.js +32 -41
- package/lib/Types/index.js.map +1 -0
- package/lib/Utils/auth-utils.d.ts +7 -6
- package/lib/Utils/auth-utils.d.ts.map +1 -0
- package/lib/Utils/auth-utils.js +228 -144
- 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 +3 -2
- 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 +19 -20
- package/lib/Utils/chat-utils.d.ts.map +1 -0
- package/lib/Utils/chat-utils.js +331 -248
- package/lib/Utils/chat-utils.js.map +1 -0
- package/lib/Utils/crypto.d.ts +10 -14
- package/lib/Utils/crypto.d.ts.map +1 -0
- package/lib/Utils/crypto.js +57 -90
- package/lib/Utils/crypto.js.map +1 -0
- package/lib/Utils/decode-wa-message.d.ts +37 -8
- package/lib/Utils/decode-wa-message.d.ts.map +1 -0
- package/lib/Utils/decode-wa-message.js +169 -84
- package/lib/Utils/decode-wa-message.js.map +1 -0
- package/lib/Utils/event-buffer.d.ts +7 -8
- package/lib/Utils/event-buffer.d.ts.map +1 -0
- package/lib/Utils/event-buffer.js +138 -78
- package/lib/Utils/event-buffer.js.map +1 -0
- package/lib/Utils/generics.d.ts +26 -27
- package/lib/Utils/generics.d.ts.map +1 -0
- package/lib/Utils/generics.js +170 -209
- package/lib/Utils/generics.js.map +1 -0
- package/lib/Utils/history.d.ts +16 -9
- package/lib/Utils/history.d.ts.map +1 -0
- package/lib/Utils/history.js +83 -48
- package/lib/Utils/history.js.map +1 -0
- package/lib/Utils/identity-change-handler.d.ts +37 -0
- package/lib/Utils/identity-change-handler.d.ts.map +1 -0
- package/lib/Utils/identity-change-handler.js +49 -0
- package/lib/Utils/identity-change-handler.js.map +1 -0
- package/lib/Utils/index.d.ts +23 -17
- package/lib/Utils/index.d.ts.map +1 -0
- package/lib/Utils/index.js +23 -33
- package/lib/Utils/index.js.map +1 -0
- package/lib/Utils/link-preview.d.ts +5 -5
- package/lib/Utils/link-preview.d.ts.map +1 -0
- package/lib/Utils/link-preview.js +14 -22
- package/lib/Utils/link-preview.js.map +1 -0
- package/lib/Utils/logger.d.ts +12 -3
- 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 -12
- 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 +4 -2
- 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 +110 -0
- package/lib/Utils/message-retry-manager.d.ts.map +1 -0
- package/lib/Utils/message-retry-manager.js +225 -0
- package/lib/Utils/message-retry-manager.js.map +1 -0
- package/lib/Utils/messages-media.d.ts +56 -42
- package/lib/Utils/messages-media.d.ts.map +1 -0
- package/lib/Utils/messages-media.js +411 -448
- package/lib/Utils/messages-media.js.map +1 -0
- package/lib/Utils/messages.d.ts +32 -18
- package/lib/Utils/messages.d.ts.map +1 -0
- package/lib/Utils/messages.js +1132 -710
- package/lib/Utils/messages.js.map +1 -0
- package/lib/Utils/noise-handler.d.ts +12 -13
- package/lib/Utils/noise-handler.d.ts.map +1 -0
- package/lib/Utils/noise-handler.js +145 -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 +31 -12
- package/lib/Utils/process-message.d.ts.map +1 -0
- package/lib/Utils/process-message.js +357 -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/rich-messages.d.ts +277 -0
- package/lib/Utils/rich-messages.d.ts.map +1 -0
- package/lib/Utils/rich-messages.js +1144 -0
- package/lib/Utils/rich-messages.js.map +1 -0
- package/lib/Utils/signal.d.ts +7 -5
- package/lib/Utils/signal.d.ts.map +1 -0
- package/lib/Utils/signal.js +78 -72
- 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/sticker-pack.d.ts +10 -0
- package/lib/Utils/sticker-pack.js +111 -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 +48 -0
- package/lib/Utils/sync-action-utils.js.map +1 -0
- package/lib/Utils/tc-token-utils.d.ts +12 -0
- package/lib/Utils/tc-token-utils.d.ts.map +1 -0
- package/lib/Utils/tc-token-utils.js +18 -0
- package/lib/Utils/tc-token-utils.js.map +1 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +2 -2
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -0
- package/lib/Utils/use-multi-file-auth-state.js +29 -27
- package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
- package/lib/Utils/validate-connection.d.ts +7 -7
- package/lib/Utils/validate-connection.d.ts.map +1 -0
- package/lib/Utils/validate-connection.js +70 -99
- package/lib/Utils/validate-connection.js.map +1 -0
- package/lib/WABinary/constants.d.ts +25 -27
- package/lib/WABinary/constants.d.ts.map +1 -0
- package/lib/WABinary/constants.js +1281 -20
- package/lib/WABinary/constants.js.map +1 -0
- package/lib/WABinary/decode.d.ts +5 -5
- package/lib/WABinary/decode.d.ts.map +1 -0
- package/lib/WABinary/decode.js +52 -42
- package/lib/WABinary/decode.js.map +1 -0
- package/lib/WABinary/encode.d.ts +3 -3
- package/lib/WABinary/encode.d.ts.map +1 -0
- package/lib/WABinary/encode.js +110 -155
- package/lib/WABinary/encode.js.map +1 -0
- package/lib/WABinary/generic-utils.d.ts +8 -8
- package/lib/WABinary/generic-utils.d.ts.map +1 -0
- package/lib/WABinary/generic-utils.js +142 -149
- package/lib/WABinary/generic-utils.js.map +1 -0
- package/lib/WABinary/index.d.ts +6 -5
- 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 +25 -8
- package/lib/WABinary/jid-utils.d.ts.map +1 -0
- package/lib/WABinary/jid-utils.js +74 -40
- package/lib/WABinary/jid-utils.js.map +1 -0
- package/lib/WABinary/types.d.ts +2 -1
- 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 +3 -11
- 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 +5 -3
- 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 +2 -2
- 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 -3
- 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 +4 -3
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +8 -11
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +3 -2
- 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 +3 -2
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +9 -12
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +3 -2
- 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/UsyncBotProfileProtocol.d.ts +4 -3
- 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 +5 -3
- 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 +5 -4
- package/lib/WAUSync/Protocols/index.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/index.js +5 -20
- package/lib/WAUSync/Protocols/index.js.map +1 -0
- package/lib/WAUSync/USyncQuery.d.ts +5 -4
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -0
- package/lib/WAUSync/USyncQuery.js +40 -35
- package/lib/WAUSync/USyncQuery.js.map +1 -0
- package/lib/WAUSync/USyncUser.d.ts +6 -5
- package/lib/WAUSync/USyncUser.d.ts.map +1 -0
- package/lib/WAUSync/USyncUser.js +2 -5
- package/lib/WAUSync/USyncUser.js.map +1 -0
- package/lib/WAUSync/index.d.ts +4 -3
- 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 +10 -9
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +12 -33
- package/lib/index.js.map +1 -0
- package/package.json +64 -105
- package/README.md +0 -364
- package/engine-requirements.js +0 -10
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Signal/Group/queue-job.d.ts +0 -1
- package/lib/Signal/Group/queue-job.js +0 -57
- package/lib/Socket/Client/abstract-socket-client.js +0 -13
- package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.js +0 -62
- package/lib/Socket/registration.d.ts +0 -267
- package/lib/Socket/registration.js +0 -166
- package/lib/Socket/usync.d.ts +0 -36
- package/lib/Socket/usync.js +0 -70
- package/lib/Store/index.d.ts +0 -3
- package/lib/Store/index.js +0 -10
- package/lib/Store/make-cache-manager-store.d.ts +0 -13
- package/lib/Store/make-cache-manager-store.js +0 -83
- package/lib/Store/make-in-memory-store.d.ts +0 -118
- package/lib/Store/make-in-memory-store.js +0 -427
- package/lib/Store/make-ordered-dictionary.d.ts +0 -13
- package/lib/Store/make-ordered-dictionary.js +0 -81
- package/lib/Store/object-repository.d.ts +0 -10
- package/lib/Store/object-repository.js +0 -27
- package/lib/Utils/baileys-event-stream.d.ts +0 -16
- package/lib/Utils/baileys-event-stream.js +0 -63
|
@@ -1,219 +1,326 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const {
|
|
20
|
-
logger,
|
|
21
|
-
retryRequestDelayMs,
|
|
22
|
-
maxMsgRetryCount,
|
|
23
|
-
getMessage,
|
|
24
|
-
shouldIgnoreJid
|
|
25
|
-
} = config;
|
|
26
|
-
const sock = (0, messages_send_1.makeMessagesSocket)(config);
|
|
27
|
-
const {
|
|
28
|
-
ev,
|
|
29
|
-
authState,
|
|
30
|
-
ws,
|
|
31
|
-
processingMutex,
|
|
32
|
-
signalRepository,
|
|
33
|
-
query,
|
|
34
|
-
upsertMessage,
|
|
35
|
-
resyncAppState,
|
|
36
|
-
groupMetadata,
|
|
37
|
-
onUnexpectedError,
|
|
38
|
-
assertSessions,
|
|
39
|
-
sendNode,
|
|
40
|
-
relayMessage,
|
|
41
|
-
sendReceipt,
|
|
42
|
-
uploadPreKeys,
|
|
43
|
-
createParticipantNodes,
|
|
44
|
-
getUSyncDevices,
|
|
45
|
-
sendPeerDataOperationMessage
|
|
46
|
-
} = sock;
|
|
1
|
+
import NodeCache from '@cacheable/node-cache';
|
|
2
|
+
import { Boom } from '@hapi/boom';
|
|
3
|
+
import { randomBytes } from 'crypto';
|
|
4
|
+
import Long from 'long';
|
|
5
|
+
import { proto } from '../../WAProto/index.js';
|
|
6
|
+
import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT, PLACEHOLDER_MAX_AGE_SECONDS, STATUS_EXPIRY_SECONDS } from '../Defaults/index.js';
|
|
7
|
+
import { WAMessageStatus, WAMessageStubType } from '../Types/index.js';
|
|
8
|
+
import { aesDecryptCTR, aesEncryptGCM, cleanMessage, Curve, decodeMediaRetryNode, decodeMessageNode, decryptMessageNode, delay, derivePairingCodeKey, encodeBigEndian, encodeSignedDeviceIdentity, extractAddressingContext, getCallStatusFromNode, getHistoryMsg, getNextPreKeys, getStatusFromReceiptType, handleIdentityChange, hkdf, MISSING_KEYS_ERROR_TEXT, NACK_REASONS, NO_MESSAGE_FOUND_ERROR_TEXT, toNumber, unixTimestampSeconds, xmppPreKey, xmppSignedPreKey } from '../Utils/index.js';
|
|
9
|
+
import { makeMutex } from '../Utils/make-mutex.js';
|
|
10
|
+
import { makeOfflineNodeProcessor } from '../Utils/offline-node-processor.js';
|
|
11
|
+
import { buildAckStanza } from '../Utils/stanza-ack.js';
|
|
12
|
+
import { areJidsSameUser, binaryNodeToString, getAllBinaryNodeChildren, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildren, getBinaryNodeChildString, isJidGroup, isJidNewsletter, isJidStatusBroadcast, isLidUser, isPnUser, jidDecode, jidNormalizedUser, S_WHATSAPP_NET } from '../WABinary/index.js';
|
|
13
|
+
import { extractGroupMetadata } from './groups.js';
|
|
14
|
+
import { makeMessagesSocket } from './messages-send.js';
|
|
15
|
+
export const makeMessagesRecvSocket = (config) => {
|
|
16
|
+
const { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid, enableAutoSessionRecreation } = config;
|
|
17
|
+
const sock = makeMessagesSocket(config);
|
|
18
|
+
const { ev, authState, ws, messageMutex, notificationMutex, receiptMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, sendPeerDataOperationMessage, messageRetryManager } = sock;
|
|
47
19
|
/** this mutex ensures that each retryRequest will wait for the previous one to finish */
|
|
48
|
-
const retryMutex =
|
|
49
|
-
const msgRetryCache = config.msgRetryCounterCache ||
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
20
|
+
const retryMutex = makeMutex();
|
|
21
|
+
const msgRetryCache = config.msgRetryCounterCache ||
|
|
22
|
+
new NodeCache({
|
|
23
|
+
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
24
|
+
useClones: false
|
|
25
|
+
});
|
|
26
|
+
const callOfferCache = config.callOfferCache ||
|
|
27
|
+
new NodeCache({
|
|
28
|
+
stdTTL: DEFAULT_CACHE_TTLS.CALL_OFFER, // 5 mins
|
|
29
|
+
useClones: false
|
|
30
|
+
});
|
|
31
|
+
const placeholderResendCache = config.placeholderResendCache ||
|
|
32
|
+
new NodeCache({
|
|
33
|
+
stdTTL: DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
34
|
+
useClones: false
|
|
35
|
+
});
|
|
36
|
+
// Debounce identity-change session refreshes per JID to avoid bursts
|
|
37
|
+
const identityAssertDebounce = new NodeCache({ stdTTL: 5, useClones: false });
|
|
61
38
|
let sendActiveReceipts = false;
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
attrs: {
|
|
66
|
-
id: attrs.id,
|
|
67
|
-
to: attrs.from,
|
|
68
|
-
class: tag
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (!!errorCode) {
|
|
72
|
-
stanza.attrs.error = errorCode.toString();
|
|
39
|
+
const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
|
|
40
|
+
if (!authState.creds.me?.id) {
|
|
41
|
+
throw new Boom('Not authenticated');
|
|
73
42
|
}
|
|
74
|
-
|
|
75
|
-
|
|
43
|
+
const pdoMessage = {
|
|
44
|
+
historySyncOnDemandRequest: {
|
|
45
|
+
chatJid: oldestMsgKey.remoteJid,
|
|
46
|
+
oldestMsgFromMe: oldestMsgKey.fromMe,
|
|
47
|
+
oldestMsgId: oldestMsgKey.id,
|
|
48
|
+
oldestMsgTimestampMs: oldestMsgTimestamp,
|
|
49
|
+
onDemandMsgCount: count
|
|
50
|
+
},
|
|
51
|
+
peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
|
|
52
|
+
};
|
|
53
|
+
return sendPeerDataOperationMessage(pdoMessage);
|
|
54
|
+
};
|
|
55
|
+
const requestPlaceholderResend = async (messageKey, msgData) => {
|
|
56
|
+
if (!authState.creds.me?.id) {
|
|
57
|
+
throw new Boom('Not authenticated');
|
|
76
58
|
}
|
|
77
|
-
if (
|
|
78
|
-
|
|
59
|
+
if (await placeholderResendCache.get(messageKey?.id)) {
|
|
60
|
+
logger.debug({ messageKey }, 'already requested resend');
|
|
61
|
+
return;
|
|
79
62
|
}
|
|
80
|
-
|
|
81
|
-
|
|
63
|
+
else {
|
|
64
|
+
// Store original message data so PDO response handler can preserve
|
|
65
|
+
// metadata (LID details, timestamps, etc.) that the phone may omit
|
|
66
|
+
await placeholderResendCache.set(messageKey?.id, msgData || true);
|
|
82
67
|
}
|
|
83
|
-
|
|
84
|
-
|
|
68
|
+
await delay(2000);
|
|
69
|
+
if (!(await placeholderResendCache.get(messageKey?.id))) {
|
|
70
|
+
logger.debug({ messageKey }, 'message received while resend requested');
|
|
71
|
+
return 'RESOLVED';
|
|
85
72
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
73
|
+
const pdoMessage = {
|
|
74
|
+
placeholderMessageResendRequest: [
|
|
75
|
+
{
|
|
76
|
+
messageKey
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
peerDataOperationRequestType: proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
|
|
80
|
+
};
|
|
81
|
+
setTimeout(async () => {
|
|
82
|
+
if (await placeholderResendCache.get(messageKey?.id)) {
|
|
83
|
+
logger.debug({ messageKey }, 'PDO message without response after 8 seconds. Phone possibly offline');
|
|
84
|
+
await placeholderResendCache.del(messageKey?.id);
|
|
85
|
+
}
|
|
86
|
+
}, 8000);
|
|
87
|
+
return sendPeerDataOperationMessage(pdoMessage);
|
|
93
88
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
89
|
+
// Handles mex newsletter notifications
|
|
90
|
+
const handleMexNewsletterNotification = async (node) => {
|
|
91
|
+
const mexNode = getBinaryNodeChild(node, 'mex');
|
|
92
|
+
if (!mexNode?.content) {
|
|
93
|
+
logger.warn({ node }, 'Invalid mex newsletter notification');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
let data;
|
|
97
|
+
try {
|
|
98
|
+
data = JSON.parse(mexNode.content.toString());
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
logger.error({ err: error, node }, 'Failed to parse mex newsletter notification');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const operation = data?.operation;
|
|
105
|
+
const updates = data?.updates;
|
|
106
|
+
if (!updates || !operation) {
|
|
107
|
+
logger.warn({ data }, 'Invalid mex newsletter notification content');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
logger.info({ operation, updates }, 'got mex newsletter notification');
|
|
111
|
+
switch (operation) {
|
|
112
|
+
case 'NotificationNewsletterUpdate':
|
|
113
|
+
for (const update of updates) {
|
|
114
|
+
if (update.jid && update.settings && Object.keys(update.settings).length > 0) {
|
|
115
|
+
ev.emit('newsletter-settings.update', {
|
|
116
|
+
id: update.jid,
|
|
117
|
+
update: update.settings
|
|
118
|
+
});
|
|
119
|
+
}
|
|
121
120
|
}
|
|
122
|
-
|
|
121
|
+
break;
|
|
122
|
+
case 'NotificationNewsletterAdminPromote':
|
|
123
|
+
for (const update of updates) {
|
|
124
|
+
if (update.jid && update.user) {
|
|
125
|
+
ev.emit('newsletter-participants.update', {
|
|
126
|
+
id: update.jid,
|
|
127
|
+
author: node.attrs.from,
|
|
128
|
+
user: update.user,
|
|
129
|
+
new_role: 'ADMIN',
|
|
130
|
+
action: 'promote'
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
default:
|
|
136
|
+
logger.info({ operation, data }, 'Unhandled mex newsletter notification');
|
|
137
|
+
break;
|
|
123
138
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
139
|
+
};
|
|
140
|
+
// Handles newsletter notifications
|
|
141
|
+
const handleNewsletterNotification = async (node) => {
|
|
142
|
+
const from = node.attrs.from;
|
|
143
|
+
const child = getAllBinaryNodeChildren(node)[0];
|
|
144
|
+
const author = node.attrs.participant;
|
|
145
|
+
logger.info({ from, child }, 'got newsletter notification');
|
|
146
|
+
switch (child.tag) {
|
|
147
|
+
case 'reaction':
|
|
148
|
+
const reactionUpdate = {
|
|
149
|
+
id: from,
|
|
150
|
+
server_id: child.attrs.message_id,
|
|
151
|
+
reaction: {
|
|
152
|
+
code: getBinaryNodeChildString(child, 'reaction'),
|
|
153
|
+
count: 1
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
ev.emit('newsletter.reaction', reactionUpdate);
|
|
157
|
+
break;
|
|
158
|
+
case 'view':
|
|
159
|
+
const viewUpdate = {
|
|
160
|
+
id: from,
|
|
161
|
+
server_id: child.attrs.message_id,
|
|
162
|
+
count: parseInt(child.content?.toString() || '0', 10)
|
|
163
|
+
};
|
|
164
|
+
ev.emit('newsletter.view', viewUpdate);
|
|
165
|
+
break;
|
|
166
|
+
case 'participant':
|
|
167
|
+
const participantUpdate = {
|
|
168
|
+
id: from,
|
|
169
|
+
author,
|
|
170
|
+
user: child.attrs.jid,
|
|
171
|
+
action: child.attrs.action,
|
|
172
|
+
new_role: child.attrs.role
|
|
173
|
+
};
|
|
174
|
+
ev.emit('newsletter-participants.update', participantUpdate);
|
|
175
|
+
break;
|
|
176
|
+
case 'update':
|
|
177
|
+
const settingsNode = getBinaryNodeChild(child, 'settings');
|
|
178
|
+
if (settingsNode) {
|
|
179
|
+
const update = {};
|
|
180
|
+
const nameNode = getBinaryNodeChild(settingsNode, 'name');
|
|
181
|
+
if (nameNode?.content)
|
|
182
|
+
update.name = nameNode.content.toString();
|
|
183
|
+
const descriptionNode = getBinaryNodeChild(settingsNode, 'description');
|
|
184
|
+
if (descriptionNode?.content)
|
|
185
|
+
update.description = descriptionNode.content.toString();
|
|
186
|
+
ev.emit('newsletter-settings.update', {
|
|
187
|
+
id: from,
|
|
188
|
+
update
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
case 'message':
|
|
193
|
+
const plaintextNode = getBinaryNodeChild(child, 'plaintext');
|
|
194
|
+
if (plaintextNode?.content) {
|
|
195
|
+
try {
|
|
196
|
+
const contentBuf = typeof plaintextNode.content === 'string'
|
|
197
|
+
? Buffer.from(plaintextNode.content, 'binary')
|
|
198
|
+
: Buffer.from(plaintextNode.content);
|
|
199
|
+
const messageProto = proto.Message.decode(contentBuf).toJSON();
|
|
200
|
+
const fullMessage = proto.WebMessageInfo.fromObject({
|
|
201
|
+
key: {
|
|
202
|
+
remoteJid: from,
|
|
203
|
+
id: child.attrs.message_id || child.attrs.server_id,
|
|
204
|
+
fromMe: false // TODO: is this really true though
|
|
205
|
+
},
|
|
206
|
+
message: messageProto,
|
|
207
|
+
messageTimestamp: +child.attrs.t
|
|
208
|
+
}).toJSON();
|
|
209
|
+
await upsertMessage(fullMessage, 'append');
|
|
210
|
+
logger.info('Processed plaintext newsletter message');
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
logger.error({ error }, 'Failed to decode plaintext newsletter message');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
default:
|
|
218
|
+
logger.warn({ node }, 'Unknown newsletter notification');
|
|
219
|
+
break;
|
|
156
220
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
content: [{
|
|
163
|
-
tag: 'offer',
|
|
164
|
-
attrs: {
|
|
165
|
-
'call-id': callId,
|
|
166
|
-
'call-creator': authState.creds.me.id,
|
|
167
|
-
},
|
|
168
|
-
content: offerContent,
|
|
169
|
-
}],
|
|
170
|
-
});
|
|
171
|
-
await query(stanza);
|
|
172
|
-
return {
|
|
173
|
-
callId,
|
|
174
|
-
toJid,
|
|
175
|
-
isVideo,
|
|
176
|
-
};
|
|
221
|
+
};
|
|
222
|
+
const sendMessageAck = async (node, errorCode) => {
|
|
223
|
+
const stanza = buildAckStanza(node, errorCode, authState.creds.me.id);
|
|
224
|
+
logger.debug({ recv: { tag: node.tag, attrs: node.attrs }, sent: stanza.attrs }, 'sent ack');
|
|
225
|
+
await sendNode(stanza);
|
|
177
226
|
};
|
|
178
227
|
const rejectCall = async (callId, callFrom) => {
|
|
179
|
-
const stanza =
|
|
228
|
+
const stanza = {
|
|
180
229
|
tag: 'call',
|
|
181
230
|
attrs: {
|
|
182
231
|
from: authState.creds.me.id,
|
|
183
|
-
to: callFrom
|
|
232
|
+
to: callFrom
|
|
184
233
|
},
|
|
185
|
-
content: [
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
186
236
|
tag: 'reject',
|
|
187
237
|
attrs: {
|
|
188
238
|
'call-id': callId,
|
|
189
239
|
'call-creator': callFrom,
|
|
190
|
-
count: '0'
|
|
240
|
+
count: '0'
|
|
191
241
|
},
|
|
192
|
-
content: undefined
|
|
193
|
-
}
|
|
194
|
-
|
|
242
|
+
content: undefined
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
};
|
|
195
246
|
await query(stanza);
|
|
196
247
|
};
|
|
197
248
|
const sendRetryRequest = async (node, forceIncludeKeys = false) => {
|
|
198
|
-
const { fullMessage } =
|
|
249
|
+
const { fullMessage } = decodeMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '');
|
|
199
250
|
const { key: msgKey } = fullMessage;
|
|
200
251
|
const msgId = msgKey.id;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
252
|
+
if (messageRetryManager) {
|
|
253
|
+
// Check if we've exceeded max retries using the new system
|
|
254
|
+
if (messageRetryManager.hasExceededMaxRetries(msgId)) {
|
|
255
|
+
logger.debug({ msgId }, 'reached retry limit with new retry manager, clearing');
|
|
256
|
+
messageRetryManager.markRetryFailed(msgId);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
// Increment retry count using new system
|
|
260
|
+
const retryCount = messageRetryManager.incrementRetryCount(msgId);
|
|
261
|
+
// Use the new retry count for the rest of the logic
|
|
262
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
263
|
+
await msgRetryCache.set(key, retryCount);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
// Fallback to old system
|
|
267
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
268
|
+
let retryCount = (await msgRetryCache.get(key)) || 0;
|
|
269
|
+
if (retryCount >= maxMsgRetryCount) {
|
|
270
|
+
logger.debug({ retryCount, msgId }, 'reached retry limit, clearing');
|
|
271
|
+
await msgRetryCache.del(key);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
retryCount += 1;
|
|
275
|
+
await msgRetryCache.set(key, retryCount);
|
|
207
276
|
}
|
|
208
|
-
|
|
209
|
-
msgRetryCache.
|
|
277
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
278
|
+
const retryCount = (await msgRetryCache.get(key)) || 1;
|
|
210
279
|
const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
280
|
+
const fromJid = node.attrs.from;
|
|
281
|
+
// Check if we should recreate the session
|
|
282
|
+
let shouldRecreateSession = false;
|
|
283
|
+
let recreateReason = '';
|
|
284
|
+
if (enableAutoSessionRecreation && messageRetryManager && retryCount > 1) {
|
|
285
|
+
try {
|
|
286
|
+
// Check if we have a session with this JID
|
|
287
|
+
const sessionId = signalRepository.jidToSignalProtocolAddress(fromJid);
|
|
288
|
+
const hasSession = await signalRepository.validateSession(fromJid);
|
|
289
|
+
const result = messageRetryManager.shouldRecreateSession(fromJid, hasSession.exists);
|
|
290
|
+
shouldRecreateSession = result.recreate;
|
|
291
|
+
recreateReason = result.reason;
|
|
292
|
+
if (shouldRecreateSession) {
|
|
293
|
+
logger.debug({ fromJid, retryCount, reason: recreateReason }, 'recreating session for retry');
|
|
294
|
+
// Delete existing session to force recreation
|
|
295
|
+
await authState.keys.set({ session: { [sessionId]: null } });
|
|
296
|
+
forceIncludeKeys = true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
logger.warn({ error, fromJid }, 'failed to check session recreation');
|
|
301
|
+
}
|
|
215
302
|
}
|
|
216
|
-
|
|
303
|
+
if (retryCount <= 2) {
|
|
304
|
+
// Use new retry manager for phone requests if available
|
|
305
|
+
if (messageRetryManager) {
|
|
306
|
+
// Schedule phone request with delay (like whatsmeow)
|
|
307
|
+
messageRetryManager.schedulePhoneRequest(msgId, async () => {
|
|
308
|
+
try {
|
|
309
|
+
const requestId = await requestPlaceholderResend(msgKey);
|
|
310
|
+
logger.debug(`sendRetryRequest: requested placeholder resend (${requestId}) for message ${msgId} (scheduled)`);
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
logger.warn({ error, msgId }, 'failed to send scheduled phone request');
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
// Fallback to immediate request
|
|
319
|
+
const msgId = await requestPlaceholderResend(msgKey);
|
|
320
|
+
logger.debug(`sendRetryRequest: requested placeholder resend for message ${msgId}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const deviceIdentity = encodeSignedDeviceIdentity(account, true);
|
|
217
324
|
await authState.keys.transaction(async () => {
|
|
218
325
|
const receipt = {
|
|
219
326
|
tag: 'receipt',
|
|
@@ -229,13 +336,15 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
229
336
|
count: retryCount.toString(),
|
|
230
337
|
id: node.attrs.id,
|
|
231
338
|
t: node.attrs.t,
|
|
232
|
-
v: '1'
|
|
339
|
+
v: '1',
|
|
340
|
+
// ADD ERROR FIELD
|
|
341
|
+
error: '0'
|
|
233
342
|
}
|
|
234
343
|
},
|
|
235
344
|
{
|
|
236
345
|
tag: 'registration',
|
|
237
346
|
attrs: {},
|
|
238
|
-
content:
|
|
347
|
+
content: encodeBigEndian(authState.creds.registrationId)
|
|
239
348
|
}
|
|
240
349
|
]
|
|
241
350
|
};
|
|
@@ -245,8 +354,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
245
354
|
if (node.attrs.participant) {
|
|
246
355
|
receipt.attrs.participant = node.attrs.participant;
|
|
247
356
|
}
|
|
248
|
-
if (retryCount > 1 || forceIncludeKeys) {
|
|
249
|
-
const { update, preKeys } = await
|
|
357
|
+
if (retryCount > 1 || forceIncludeKeys || shouldRecreateSession) {
|
|
358
|
+
const { update, preKeys } = await getNextPreKeys(authState, 1);
|
|
250
359
|
const [keyId] = Object.keys(preKeys);
|
|
251
360
|
const key = preKeys[+keyId];
|
|
252
361
|
const content = receipt.content;
|
|
@@ -254,10 +363,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
254
363
|
tag: 'keys',
|
|
255
364
|
attrs: {},
|
|
256
365
|
content: [
|
|
257
|
-
{ tag: 'type', attrs: {}, content: Buffer.from(
|
|
366
|
+
{ tag: 'type', attrs: {}, content: Buffer.from(KEY_BUNDLE_TYPE) },
|
|
258
367
|
{ tag: 'identity', attrs: {}, content: identityKey.public },
|
|
259
|
-
|
|
260
|
-
|
|
368
|
+
xmppPreKey(key, +keyId),
|
|
369
|
+
xmppSignedPreKey(signedPreKey),
|
|
261
370
|
{ tag: 'device-identity', attrs: {}, content: deviceIdentity }
|
|
262
371
|
]
|
|
263
372
|
});
|
|
@@ -265,63 +374,73 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
265
374
|
}
|
|
266
375
|
await sendNode(receipt);
|
|
267
376
|
logger.info({ msgAttrs: node.attrs, retryCount }, 'sent retry receipt');
|
|
268
|
-
});
|
|
377
|
+
}, authState?.creds?.me?.id || 'sendRetryRequest');
|
|
269
378
|
};
|
|
270
379
|
const handleEncryptNotification = async (node) => {
|
|
271
380
|
const from = node.attrs.from;
|
|
272
|
-
if (from ===
|
|
273
|
-
const countChild =
|
|
381
|
+
if (from === S_WHATSAPP_NET) {
|
|
382
|
+
const countChild = getBinaryNodeChild(node, 'count');
|
|
274
383
|
const count = +countChild.attrs.value;
|
|
275
|
-
const shouldUploadMorePreKeys = count <
|
|
384
|
+
const shouldUploadMorePreKeys = count < MIN_PREKEY_COUNT;
|
|
276
385
|
logger.debug({ count, shouldUploadMorePreKeys }, 'recv pre-key count');
|
|
277
386
|
if (shouldUploadMorePreKeys) {
|
|
278
387
|
await uploadPreKeys();
|
|
279
388
|
}
|
|
280
389
|
}
|
|
281
390
|
else {
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
391
|
+
const result = await handleIdentityChange(node, {
|
|
392
|
+
meId: authState.creds.me?.id,
|
|
393
|
+
meLid: authState.creds.me?.lid,
|
|
394
|
+
validateSession: signalRepository.validateSession,
|
|
395
|
+
assertSessions,
|
|
396
|
+
debounceCache: identityAssertDebounce,
|
|
397
|
+
logger
|
|
398
|
+
});
|
|
399
|
+
if (result.action === 'no_identity_node') {
|
|
289
400
|
logger.info({ node }, 'unknown encrypt notification');
|
|
290
401
|
}
|
|
291
402
|
}
|
|
292
403
|
};
|
|
293
|
-
const handleGroupNotification = (
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
|
|
404
|
+
const handleGroupNotification = (fullNode, child, msg) => {
|
|
405
|
+
// TODO: Support PN/LID (Here is only LID now)
|
|
406
|
+
const actingParticipantLid = fullNode.attrs.participant;
|
|
407
|
+
const actingParticipantPn = fullNode.attrs.participant_pn;
|
|
408
|
+
const affectedParticipantLid = getBinaryNodeChild(child, 'participant')?.attrs?.jid || actingParticipantLid;
|
|
409
|
+
const affectedParticipantPn = getBinaryNodeChild(child, 'participant')?.attrs?.phone_number || actingParticipantPn;
|
|
410
|
+
switch (child?.tag) {
|
|
297
411
|
case 'create':
|
|
298
|
-
const metadata =
|
|
299
|
-
msg.messageStubType =
|
|
412
|
+
const metadata = extractGroupMetadata(child);
|
|
413
|
+
msg.messageStubType = WAMessageStubType.GROUP_CREATE;
|
|
300
414
|
msg.messageStubParameters = [metadata.subject];
|
|
301
|
-
msg.key = { participant: metadata.owner };
|
|
302
|
-
ev.emit('chats.upsert', [
|
|
415
|
+
msg.key = { participant: metadata.owner, participantAlt: metadata.ownerPn };
|
|
416
|
+
ev.emit('chats.upsert', [
|
|
417
|
+
{
|
|
303
418
|
id: metadata.id,
|
|
304
419
|
name: metadata.subject,
|
|
305
|
-
conversationTimestamp: metadata.creation
|
|
306
|
-
}
|
|
307
|
-
|
|
420
|
+
conversationTimestamp: metadata.creation
|
|
421
|
+
}
|
|
422
|
+
]);
|
|
423
|
+
ev.emit('groups.upsert', [
|
|
424
|
+
{
|
|
308
425
|
...metadata,
|
|
309
|
-
author:
|
|
310
|
-
|
|
426
|
+
author: actingParticipantLid,
|
|
427
|
+
authorPn: actingParticipantPn
|
|
428
|
+
}
|
|
429
|
+
]);
|
|
311
430
|
break;
|
|
312
431
|
case 'ephemeral':
|
|
313
432
|
case 'not_ephemeral':
|
|
314
433
|
msg.message = {
|
|
315
434
|
protocolMessage: {
|
|
316
|
-
type:
|
|
435
|
+
type: proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
317
436
|
ephemeralExpiration: +(child.attrs.expiration || 0)
|
|
318
437
|
}
|
|
319
438
|
};
|
|
320
439
|
break;
|
|
321
440
|
case 'modify':
|
|
322
|
-
const oldNumber =
|
|
441
|
+
const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid);
|
|
323
442
|
msg.messageStubParameters = oldNumber || [];
|
|
324
|
-
msg.messageStubType =
|
|
443
|
+
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
|
|
325
444
|
break;
|
|
326
445
|
case 'promote':
|
|
327
446
|
case 'demote':
|
|
@@ -329,179 +448,141 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
329
448
|
case 'add':
|
|
330
449
|
case 'leave':
|
|
331
450
|
const stubType = `GROUP_PARTICIPANT_${child.tag.toUpperCase()}`;
|
|
332
|
-
msg.messageStubType =
|
|
333
|
-
const participants =
|
|
451
|
+
msg.messageStubType = WAMessageStubType[stubType];
|
|
452
|
+
const participants = getBinaryNodeChildren(child, 'participant').map(({ attrs }) => {
|
|
453
|
+
// TODO: Store LID MAPPINGS
|
|
454
|
+
return {
|
|
455
|
+
id: attrs.jid,
|
|
456
|
+
phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
|
|
457
|
+
lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined,
|
|
458
|
+
admin: (attrs.type || null)
|
|
459
|
+
};
|
|
460
|
+
});
|
|
334
461
|
if (participants.length === 1 &&
|
|
335
462
|
// if recv. "remove" message and sender removed themselves
|
|
336
463
|
// mark as left
|
|
337
|
-
(
|
|
464
|
+
(areJidsSameUser(participants[0].id, actingParticipantLid) ||
|
|
465
|
+
areJidsSameUser(participants[0].id, actingParticipantPn)) &&
|
|
338
466
|
child.tag === 'remove') {
|
|
339
|
-
msg.messageStubType =
|
|
467
|
+
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE;
|
|
340
468
|
}
|
|
341
|
-
msg.messageStubParameters = participants;
|
|
469
|
+
msg.messageStubParameters = participants.map(a => JSON.stringify(a));
|
|
342
470
|
break;
|
|
343
471
|
case 'subject':
|
|
344
|
-
msg.messageStubType =
|
|
472
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_SUBJECT;
|
|
345
473
|
msg.messageStubParameters = [child.attrs.subject];
|
|
346
474
|
break;
|
|
347
475
|
case 'description':
|
|
348
|
-
const description =
|
|
349
|
-
msg.messageStubType =
|
|
476
|
+
const description = getBinaryNodeChild(child, 'body')?.content?.toString();
|
|
477
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
|
|
350
478
|
msg.messageStubParameters = description ? [description] : undefined;
|
|
351
479
|
break;
|
|
352
480
|
case 'announcement':
|
|
353
481
|
case 'not_announcement':
|
|
354
|
-
msg.messageStubType =
|
|
355
|
-
msg.messageStubParameters = [
|
|
482
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
|
|
483
|
+
msg.messageStubParameters = [child.tag === 'announcement' ? 'on' : 'off'];
|
|
356
484
|
break;
|
|
357
485
|
case 'locked':
|
|
358
486
|
case 'unlocked':
|
|
359
|
-
msg.messageStubType =
|
|
360
|
-
msg.messageStubParameters = [
|
|
487
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_RESTRICT;
|
|
488
|
+
msg.messageStubParameters = [child.tag === 'locked' ? 'on' : 'off'];
|
|
361
489
|
break;
|
|
362
490
|
case 'invite':
|
|
363
|
-
msg.messageStubType =
|
|
491
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
|
|
364
492
|
msg.messageStubParameters = [child.attrs.code];
|
|
365
493
|
break;
|
|
366
494
|
case 'member_add_mode':
|
|
367
495
|
const addMode = child.content;
|
|
368
496
|
if (addMode) {
|
|
369
|
-
msg.messageStubType =
|
|
497
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBER_ADD_MODE;
|
|
370
498
|
msg.messageStubParameters = [addMode.toString()];
|
|
371
499
|
}
|
|
372
500
|
break;
|
|
373
501
|
case 'membership_approval_mode':
|
|
374
|
-
const approvalMode =
|
|
502
|
+
const approvalMode = getBinaryNodeChild(child, 'group_join');
|
|
375
503
|
if (approvalMode) {
|
|
376
|
-
msg.messageStubType =
|
|
504
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE;
|
|
377
505
|
msg.messageStubParameters = [approvalMode.attrs.state];
|
|
378
506
|
}
|
|
379
507
|
break;
|
|
380
508
|
case 'created_membership_requests':
|
|
381
|
-
msg.messageStubType =
|
|
382
|
-
msg.messageStubParameters = [
|
|
509
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
|
510
|
+
msg.messageStubParameters = [
|
|
511
|
+
JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipantPn }),
|
|
512
|
+
'created',
|
|
513
|
+
child.attrs.request_method
|
|
514
|
+
];
|
|
383
515
|
break;
|
|
384
516
|
case 'revoked_membership_requests':
|
|
385
|
-
const isDenied =
|
|
386
|
-
|
|
387
|
-
msg.
|
|
388
|
-
|
|
517
|
+
const isDenied = areJidsSameUser(affectedParticipantLid, actingParticipantLid);
|
|
518
|
+
// TODO: LIDMAPPING SUPPORT
|
|
519
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_REQUEST_NON_ADMIN_ADD;
|
|
520
|
+
msg.messageStubParameters = [
|
|
521
|
+
JSON.stringify({ lid: affectedParticipantLid, pn: affectedParticipantPn }),
|
|
522
|
+
isDenied ? 'revoked' : 'rejected'
|
|
523
|
+
];
|
|
389
524
|
break;
|
|
390
|
-
default:
|
|
391
|
-
// console.log("BAILEYS-DEBUG:", JSON.stringify({ ...child, content: Buffer.isBuffer(child.content) ? child.content.toString() : child.content, participant }, null, 2))
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
const handleNewsletterNotification = (id, node) => {
|
|
395
|
-
const messages = (0, WABinary_1.getBinaryNodeChild)(node, 'messages');
|
|
396
|
-
const message = (0, WABinary_1.getBinaryNodeChild)(messages, 'message');
|
|
397
|
-
const serverId = message.attrs.server_id;
|
|
398
|
-
const reactionsList = (0, WABinary_1.getBinaryNodeChild)(message, 'reactions');
|
|
399
|
-
const viewsList = (0, WABinary_1.getBinaryNodeChildren)(message, 'views_count');
|
|
400
|
-
if (reactionsList) {
|
|
401
|
-
const reactions = (0, WABinary_1.getBinaryNodeChildren)(reactionsList, 'reaction');
|
|
402
|
-
if (reactions.length === 0) {
|
|
403
|
-
ev.emit('newsletter.reaction', { id, 'server_id': serverId, reaction: { removed: true } });
|
|
404
|
-
}
|
|
405
|
-
reactions.forEach(item => {
|
|
406
|
-
var _a, _b;
|
|
407
|
-
ev.emit('newsletter.reaction', { id, 'server_id': serverId, reaction: { code: (_a = item.attrs) === null || _a === void 0 ? void 0 : _a.code, count: +((_b = item.attrs) === null || _b === void 0 ? void 0 : _b.count) } });
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
if (viewsList.length) {
|
|
411
|
-
viewsList.forEach(item => {
|
|
412
|
-
ev.emit('newsletter.view', { id, 'server_id': serverId, count: +item.attrs.count });
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
};
|
|
416
|
-
const handleMexNewsletterNotification = (id, node) => {
|
|
417
|
-
var _a;
|
|
418
|
-
const operation = node === null || node === void 0 ? void 0 : node.attrs.op_name;
|
|
419
|
-
const content = JSON.parse((_a = node === null || node === void 0 ? void 0 : node.content) === null || _a === void 0 ? void 0 : _a.toString());
|
|
420
|
-
let contentPath;
|
|
421
|
-
if (operation === Types_1.MexOperations.PROMOTE || operation === Types_1.MexOperations.DEMOTE) {
|
|
422
|
-
let action;
|
|
423
|
-
if (operation === Types_1.MexOperations.PROMOTE) {
|
|
424
|
-
action = 'promote';
|
|
425
|
-
contentPath = content.data[Types_1.XWAPaths.PROMOTE];
|
|
426
|
-
}
|
|
427
|
-
if (operation === Types_1.MexOperations.DEMOTE) {
|
|
428
|
-
action = 'demote';
|
|
429
|
-
contentPath = content.data[Types_1.XWAPaths.DEMOTE];
|
|
430
|
-
}
|
|
431
|
-
ev.emit('newsletter-participants.update', { id, author: contentPath.actor.pn, user: contentPath.user.pn, new_role: contentPath.user_new_role, action });
|
|
432
|
-
}
|
|
433
|
-
if (operation === Types_1.MexOperations.UPDATE) {
|
|
434
|
-
contentPath = content.data[Types_1.XWAPaths.METADATA_UPDATE];
|
|
435
|
-
ev.emit('newsletter-settings.update', { id, update: contentPath.thread_metadata.settings });
|
|
436
525
|
}
|
|
437
526
|
};
|
|
438
527
|
const processNotification = async (node) => {
|
|
439
|
-
var _a, _b;
|
|
440
528
|
const result = {};
|
|
441
|
-
const [child] =
|
|
529
|
+
const [child] = getAllBinaryNodeChildren(node);
|
|
442
530
|
const nodeType = node.attrs.type;
|
|
443
|
-
const from =
|
|
531
|
+
const from = jidNormalizedUser(node.attrs.from);
|
|
444
532
|
switch (nodeType) {
|
|
445
|
-
case 'privacy_token':
|
|
446
|
-
const tokenList = (0, WABinary_1.getBinaryNodeChildren)(child, 'token');
|
|
447
|
-
for (const { attrs, content } of tokenList) {
|
|
448
|
-
const jid = attrs.jid;
|
|
449
|
-
ev.emit('chats.update', [
|
|
450
|
-
{
|
|
451
|
-
id: jid,
|
|
452
|
-
tcToken: content
|
|
453
|
-
}
|
|
454
|
-
]);
|
|
455
|
-
logger.debug({ jid }, 'got privacy token update');
|
|
456
|
-
}
|
|
457
|
-
break;
|
|
458
533
|
case 'newsletter':
|
|
459
|
-
handleNewsletterNotification(node
|
|
534
|
+
await handleNewsletterNotification(node);
|
|
460
535
|
break;
|
|
461
536
|
case 'mex':
|
|
462
|
-
handleMexNewsletterNotification(node
|
|
537
|
+
await handleMexNewsletterNotification(node);
|
|
463
538
|
break;
|
|
464
539
|
case 'w:gp2':
|
|
465
|
-
|
|
540
|
+
// TODO: HANDLE PARTICIPANT_PN
|
|
541
|
+
handleGroupNotification(node, child, result);
|
|
466
542
|
break;
|
|
467
543
|
case 'mediaretry':
|
|
468
|
-
const event =
|
|
544
|
+
const event = decodeMediaRetryNode(node);
|
|
469
545
|
ev.emit('messages.media-update', [event]);
|
|
470
546
|
break;
|
|
471
547
|
case 'encrypt':
|
|
472
548
|
await handleEncryptNotification(node);
|
|
473
549
|
break;
|
|
474
550
|
case 'devices':
|
|
475
|
-
const devices =
|
|
476
|
-
if (
|
|
477
|
-
|
|
478
|
-
|
|
551
|
+
const devices = getBinaryNodeChildren(child, 'device');
|
|
552
|
+
if (areJidsSameUser(child.attrs.jid, authState.creds.me.id) ||
|
|
553
|
+
areJidsSameUser(child.attrs.lid, authState.creds.me.lid)) {
|
|
554
|
+
const deviceData = devices.map(d => ({ id: d.attrs.jid, lid: d.attrs.lid }));
|
|
555
|
+
logger.info({ deviceData }, 'my own devices changed');
|
|
479
556
|
}
|
|
557
|
+
//TODO: drop a new event, add hashes
|
|
480
558
|
break;
|
|
481
559
|
case 'server_sync':
|
|
482
|
-
const update =
|
|
560
|
+
const update = getBinaryNodeChild(node, 'collection');
|
|
483
561
|
if (update) {
|
|
484
562
|
const name = update.attrs.name;
|
|
485
563
|
await resyncAppState([name], false);
|
|
486
564
|
}
|
|
487
565
|
break;
|
|
488
566
|
case 'picture':
|
|
489
|
-
const setPicture =
|
|
490
|
-
const delPicture =
|
|
491
|
-
|
|
492
|
-
|
|
567
|
+
const setPicture = getBinaryNodeChild(node, 'set');
|
|
568
|
+
const delPicture = getBinaryNodeChild(node, 'delete');
|
|
569
|
+
// TODO: WAJIDHASH stuff proper support inhouse
|
|
570
|
+
ev.emit('contacts.update', [
|
|
571
|
+
{
|
|
572
|
+
id: jidNormalizedUser(node?.attrs?.from) || (setPicture || delPicture)?.attrs?.hash || '',
|
|
493
573
|
imgUrl: setPicture ? 'changed' : 'removed'
|
|
494
|
-
}
|
|
495
|
-
|
|
574
|
+
}
|
|
575
|
+
]);
|
|
576
|
+
if (isJidGroup(from)) {
|
|
496
577
|
const node = setPicture || delPicture;
|
|
497
|
-
result.messageStubType =
|
|
578
|
+
result.messageStubType = WAMessageStubType.GROUP_CHANGE_ICON;
|
|
498
579
|
if (setPicture) {
|
|
499
580
|
result.messageStubParameters = [setPicture.attrs.id];
|
|
500
581
|
}
|
|
501
|
-
result.participant = node
|
|
582
|
+
result.participant = node?.attrs.author;
|
|
502
583
|
result.key = {
|
|
503
|
-
...result.key || {},
|
|
504
|
-
participant: setPicture
|
|
584
|
+
...(result.key || {}),
|
|
585
|
+
participant: setPicture?.attrs.author
|
|
505
586
|
};
|
|
506
587
|
}
|
|
507
588
|
break;
|
|
@@ -515,44 +596,48 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
515
596
|
...authState.creds.accountSettings,
|
|
516
597
|
defaultDisappearingMode: {
|
|
517
598
|
ephemeralExpiration: newDuration,
|
|
518
|
-
ephemeralSettingTimestamp: timestamp
|
|
519
|
-
}
|
|
599
|
+
ephemeralSettingTimestamp: timestamp
|
|
600
|
+
}
|
|
520
601
|
}
|
|
521
602
|
});
|
|
522
603
|
}
|
|
523
604
|
else if (child.tag === 'blocklist') {
|
|
524
|
-
const blocklists =
|
|
605
|
+
const blocklists = getBinaryNodeChildren(child, 'item');
|
|
525
606
|
for (const { attrs } of blocklists) {
|
|
526
607
|
const blocklist = [attrs.jid];
|
|
527
|
-
const type =
|
|
608
|
+
const type = attrs.action === 'block' ? 'add' : 'remove';
|
|
528
609
|
ev.emit('blocklist.update', { blocklist, type });
|
|
529
610
|
}
|
|
530
611
|
}
|
|
531
612
|
break;
|
|
532
613
|
case 'link_code_companion_reg':
|
|
533
|
-
const linkCodeCompanionReg =
|
|
534
|
-
const ref = toRequiredBuffer(
|
|
535
|
-
const primaryIdentityPublicKey = toRequiredBuffer(
|
|
536
|
-
const primaryEphemeralPublicKeyWrapped = toRequiredBuffer(
|
|
614
|
+
const linkCodeCompanionReg = getBinaryNodeChild(node, 'link_code_companion_reg');
|
|
615
|
+
const ref = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_ref'));
|
|
616
|
+
const primaryIdentityPublicKey = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'primary_identity_pub'));
|
|
617
|
+
const primaryEphemeralPublicKeyWrapped = toRequiredBuffer(getBinaryNodeChildBuffer(linkCodeCompanionReg, 'link_code_pairing_wrapped_primary_ephemeral_pub'));
|
|
537
618
|
const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
|
|
538
|
-
const companionSharedKey =
|
|
539
|
-
const random =
|
|
540
|
-
const linkCodeSalt =
|
|
541
|
-
const linkCodePairingExpanded =
|
|
619
|
+
const companionSharedKey = Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey);
|
|
620
|
+
const random = randomBytes(32);
|
|
621
|
+
const linkCodeSalt = randomBytes(32);
|
|
622
|
+
const linkCodePairingExpanded = hkdf(companionSharedKey, 32, {
|
|
542
623
|
salt: linkCodeSalt,
|
|
543
624
|
info: 'link_code_pairing_key_bundle_encryption_key'
|
|
544
625
|
});
|
|
545
|
-
const encryptPayload = Buffer.concat([
|
|
546
|
-
|
|
547
|
-
|
|
626
|
+
const encryptPayload = Buffer.concat([
|
|
627
|
+
Buffer.from(authState.creds.signedIdentityKey.public),
|
|
628
|
+
primaryIdentityPublicKey,
|
|
629
|
+
random
|
|
630
|
+
]);
|
|
631
|
+
const encryptIv = randomBytes(12);
|
|
632
|
+
const encrypted = aesEncryptGCM(encryptPayload, linkCodePairingExpanded, encryptIv, Buffer.alloc(0));
|
|
548
633
|
const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]);
|
|
549
|
-
const identitySharedKey =
|
|
634
|
+
const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
|
|
550
635
|
const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random]);
|
|
551
|
-
authState.creds.advSecretKey = (
|
|
636
|
+
authState.creds.advSecretKey = Buffer.from(hkdf(identityPayload, 32, { info: 'adv_secret' })).toString('base64');
|
|
552
637
|
await query({
|
|
553
638
|
tag: 'iq',
|
|
554
639
|
attrs: {
|
|
555
|
-
to:
|
|
640
|
+
to: S_WHATSAPP_NET,
|
|
556
641
|
type: 'set',
|
|
557
642
|
id: sock.generateMessageTag(),
|
|
558
643
|
xmlns: 'md'
|
|
@@ -562,7 +647,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
562
647
|
tag: 'link_code_companion_reg',
|
|
563
648
|
attrs: {
|
|
564
649
|
jid: authState.creds.me.id,
|
|
565
|
-
stage: 'companion_finish'
|
|
650
|
+
stage: 'companion_finish'
|
|
566
651
|
},
|
|
567
652
|
content: [
|
|
568
653
|
{
|
|
@@ -586,53 +671,125 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
586
671
|
});
|
|
587
672
|
authState.creds.registered = true;
|
|
588
673
|
ev.emit('creds.update', authState.creds);
|
|
674
|
+
break;
|
|
675
|
+
case 'privacy_token':
|
|
676
|
+
await handlePrivacyTokenNotification(node);
|
|
677
|
+
break;
|
|
589
678
|
}
|
|
590
679
|
if (Object.keys(result).length) {
|
|
591
680
|
return result;
|
|
592
681
|
}
|
|
593
682
|
};
|
|
683
|
+
const handlePrivacyTokenNotification = async (node) => {
|
|
684
|
+
const tokensNode = getBinaryNodeChild(node, 'tokens');
|
|
685
|
+
const from = jidNormalizedUser(node.attrs.from);
|
|
686
|
+
if (!tokensNode)
|
|
687
|
+
return;
|
|
688
|
+
const tokenNodes = getBinaryNodeChildren(tokensNode, 'token');
|
|
689
|
+
for (const tokenNode of tokenNodes) {
|
|
690
|
+
const { attrs, content } = tokenNode;
|
|
691
|
+
const type = attrs.type;
|
|
692
|
+
const timestamp = attrs.t;
|
|
693
|
+
if (type === 'trusted_contact' && content instanceof Buffer) {
|
|
694
|
+
logger.debug({
|
|
695
|
+
from,
|
|
696
|
+
timestamp,
|
|
697
|
+
tcToken: content
|
|
698
|
+
}, 'received trusted contact token');
|
|
699
|
+
await authState.keys.set({
|
|
700
|
+
tctoken: { [from]: { token: content, timestamp } }
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
};
|
|
594
705
|
async function decipherLinkPublicKey(data) {
|
|
595
706
|
const buffer = toRequiredBuffer(data);
|
|
596
707
|
const salt = buffer.slice(0, 32);
|
|
597
|
-
const secretKey = await
|
|
708
|
+
const secretKey = await derivePairingCodeKey(authState.creds.pairingCode, salt);
|
|
598
709
|
const iv = buffer.slice(32, 48);
|
|
599
710
|
const payload = buffer.slice(48, 80);
|
|
600
|
-
return
|
|
711
|
+
return aesDecryptCTR(payload, secretKey, iv);
|
|
601
712
|
}
|
|
602
713
|
function toRequiredBuffer(data) {
|
|
603
714
|
if (data === undefined) {
|
|
604
|
-
throw new
|
|
715
|
+
throw new Boom('Invalid buffer', { statusCode: 400 });
|
|
605
716
|
}
|
|
606
717
|
return data instanceof Buffer ? data : Buffer.from(data);
|
|
607
718
|
}
|
|
608
|
-
const willSendMessageAgain = (id, participant) => {
|
|
719
|
+
const willSendMessageAgain = async (id, participant) => {
|
|
609
720
|
const key = `${id}:${participant}`;
|
|
610
|
-
const retryCount = msgRetryCache.get(key) || 0;
|
|
721
|
+
const retryCount = (await msgRetryCache.get(key)) || 0;
|
|
611
722
|
return retryCount < maxMsgRetryCount;
|
|
612
723
|
};
|
|
613
|
-
const updateSendMessageAgainCount = (id, participant) => {
|
|
724
|
+
const updateSendMessageAgainCount = async (id, participant) => {
|
|
614
725
|
const key = `${id}:${participant}`;
|
|
615
|
-
const newValue = (msgRetryCache.get(key) || 0) + 1;
|
|
616
|
-
msgRetryCache.set(key, newValue);
|
|
726
|
+
const newValue = ((await msgRetryCache.get(key)) || 0) + 1;
|
|
727
|
+
await msgRetryCache.set(key, newValue);
|
|
617
728
|
};
|
|
618
729
|
const sendMessagesAgain = async (key, ids, retryNode) => {
|
|
619
|
-
var _a;
|
|
620
|
-
// todo: implement a cache to store the last 256 sent messages (copy whatsmeow)
|
|
621
|
-
const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id })));
|
|
622
730
|
const remoteJid = key.remoteJid;
|
|
623
731
|
const participant = key.participant || remoteJid;
|
|
732
|
+
const retryCount = +retryNode.attrs.count || 1;
|
|
733
|
+
// Try to get messages from cache first, then fallback to getMessage
|
|
734
|
+
const msgs = [];
|
|
735
|
+
for (const id of ids) {
|
|
736
|
+
let msg;
|
|
737
|
+
// Try to get from retry cache first if enabled
|
|
738
|
+
if (messageRetryManager) {
|
|
739
|
+
const cachedMsg = messageRetryManager.getRecentMessage(remoteJid, id);
|
|
740
|
+
if (cachedMsg) {
|
|
741
|
+
msg = cachedMsg.message;
|
|
742
|
+
logger.debug({ jid: remoteJid, id }, 'found message in retry cache');
|
|
743
|
+
// Mark retry as successful since we found the message
|
|
744
|
+
messageRetryManager.markRetrySuccess(id);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
// Fallback to getMessage if not found in cache
|
|
748
|
+
if (!msg) {
|
|
749
|
+
msg = await getMessage({ ...key, id });
|
|
750
|
+
if (msg) {
|
|
751
|
+
logger.debug({ jid: remoteJid, id }, 'found message via getMessage');
|
|
752
|
+
// Also mark as successful if found via getMessage
|
|
753
|
+
if (messageRetryManager) {
|
|
754
|
+
messageRetryManager.markRetrySuccess(id);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
msgs.push(msg);
|
|
759
|
+
}
|
|
624
760
|
// if it's the primary jid sending the request
|
|
625
761
|
// just re-send the message to everyone
|
|
626
762
|
// prevents the first message decryption failure
|
|
627
|
-
const sendToAll = !
|
|
763
|
+
const sendToAll = !jidDecode(participant)?.device;
|
|
764
|
+
// Check if we should recreate session for this retry
|
|
765
|
+
let shouldRecreateSession = false;
|
|
766
|
+
let recreateReason = '';
|
|
767
|
+
if (enableAutoSessionRecreation && messageRetryManager && retryCount > 1) {
|
|
768
|
+
try {
|
|
769
|
+
const sessionId = signalRepository.jidToSignalProtocolAddress(participant);
|
|
770
|
+
const hasSession = await signalRepository.validateSession(participant);
|
|
771
|
+
const result = messageRetryManager.shouldRecreateSession(participant, hasSession.exists);
|
|
772
|
+
shouldRecreateSession = result.recreate;
|
|
773
|
+
recreateReason = result.reason;
|
|
774
|
+
if (shouldRecreateSession) {
|
|
775
|
+
logger.debug({ participant, retryCount, reason: recreateReason }, 'recreating session for outgoing retry');
|
|
776
|
+
await authState.keys.set({ session: { [sessionId]: null } });
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
catch (error) {
|
|
780
|
+
logger.warn({ error, participant }, 'failed to check session recreation for outgoing retry');
|
|
781
|
+
}
|
|
782
|
+
}
|
|
628
783
|
await assertSessions([participant], true);
|
|
629
|
-
if (
|
|
784
|
+
if (isJidGroup(remoteJid)) {
|
|
630
785
|
await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
|
|
631
786
|
}
|
|
632
|
-
logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
|
|
787
|
+
logger.debug({ participant, sendToAll, shouldRecreateSession, recreateReason }, 'forced new session for retry recp');
|
|
633
788
|
for (const [i, msg] of msgs.entries()) {
|
|
634
|
-
if (
|
|
635
|
-
|
|
789
|
+
if (!ids[i])
|
|
790
|
+
continue;
|
|
791
|
+
if (msg && (await willSendMessageAgain(ids[i], participant))) {
|
|
792
|
+
await updateSendMessageAgainCount(ids[i], participant);
|
|
636
793
|
const msgRelayOpts = { messageId: ids[i] };
|
|
637
794
|
if (sendToAll) {
|
|
638
795
|
msgRelayOpts.useUserDevicesCache = false;
|
|
@@ -651,11 +808,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
651
808
|
}
|
|
652
809
|
};
|
|
653
810
|
const handleReceipt = async (node) => {
|
|
654
|
-
var _a, _b;
|
|
655
811
|
const { attrs, content } = node;
|
|
656
812
|
const isLid = attrs.from.includes('lid');
|
|
657
|
-
const isNodeFromMe =
|
|
658
|
-
const remoteJid = !isNodeFromMe ||
|
|
813
|
+
const isNodeFromMe = areJidsSameUser(attrs.participant || attrs.from, isLid ? authState.creds.me?.lid : authState.creds.me?.id);
|
|
814
|
+
const remoteJid = !isNodeFromMe || isJidGroup(attrs.from) ? attrs.from : attrs.recipient;
|
|
659
815
|
const fromMe = !attrs.recipient || ((attrs.type === 'retry' || attrs.type === 'sender') && isNodeFromMe);
|
|
660
816
|
const key = {
|
|
661
817
|
remoteJid,
|
|
@@ -663,33 +819,31 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
663
819
|
fromMe,
|
|
664
820
|
participant: attrs.participant
|
|
665
821
|
};
|
|
666
|
-
if (shouldIgnoreJid(remoteJid) && remoteJid !==
|
|
822
|
+
if (shouldIgnoreJid(remoteJid) && remoteJid !== S_WHATSAPP_NET) {
|
|
667
823
|
logger.debug({ remoteJid }, 'ignoring receipt from jid');
|
|
668
824
|
await sendMessageAck(node);
|
|
669
825
|
return;
|
|
670
826
|
}
|
|
671
827
|
const ids = [attrs.id];
|
|
672
828
|
if (Array.isArray(content)) {
|
|
673
|
-
const items =
|
|
829
|
+
const items = getBinaryNodeChildren(content[0], 'item');
|
|
674
830
|
ids.push(...items.map(i => i.attrs.id));
|
|
675
831
|
}
|
|
676
832
|
try {
|
|
677
833
|
await Promise.all([
|
|
678
|
-
|
|
679
|
-
const status =
|
|
834
|
+
receiptMutex.mutex(async () => {
|
|
835
|
+
const status = getStatusFromReceiptType(attrs.type);
|
|
680
836
|
if (typeof status !== 'undefined' &&
|
|
681
|
-
(
|
|
682
837
|
// basically, we only want to know when a message from us has been delivered to/read by the other person
|
|
683
838
|
// or another device of ours has read some messages
|
|
684
|
-
status >=
|
|
685
|
-
|
|
686
|
-
if ((0, WABinary_1.isJidGroup)(remoteJid) || (0, WABinary_1.isJidStatusBroadcast)(remoteJid)) {
|
|
839
|
+
(status >= proto.WebMessageInfo.Status.SERVER_ACK || !isNodeFromMe)) {
|
|
840
|
+
if (isJidGroup(remoteJid) || isJidStatusBroadcast(remoteJid)) {
|
|
687
841
|
if (attrs.participant) {
|
|
688
|
-
const updateKey = status ===
|
|
842
|
+
const updateKey = status === proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
|
|
689
843
|
ev.emit('message-receipt.update', ids.map(id => ({
|
|
690
844
|
key: { ...key, id },
|
|
691
845
|
receipt: {
|
|
692
|
-
userJid:
|
|
846
|
+
userJid: jidNormalizedUser(attrs.participant),
|
|
693
847
|
[updateKey]: +attrs.t
|
|
694
848
|
}
|
|
695
849
|
})));
|
|
@@ -698,22 +852,23 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
698
852
|
else {
|
|
699
853
|
ev.emit('messages.update', ids.map(id => ({
|
|
700
854
|
key: { ...key, id },
|
|
701
|
-
update: { status }
|
|
855
|
+
update: { status, messageTimestamp: toNumber(+(attrs.t ?? 0)) }
|
|
702
856
|
})));
|
|
703
857
|
}
|
|
704
858
|
}
|
|
705
859
|
if (attrs.type === 'retry') {
|
|
706
860
|
// correctly set who is asking for the retry
|
|
707
861
|
key.participant = key.participant || attrs.from;
|
|
708
|
-
const retryNode =
|
|
709
|
-
if (willSendMessageAgain(ids[0], key.participant)) {
|
|
862
|
+
const retryNode = getBinaryNodeChild(node, 'retry');
|
|
863
|
+
if (ids[0] && key.participant && (await willSendMessageAgain(ids[0], key.participant))) {
|
|
710
864
|
if (key.fromMe) {
|
|
711
865
|
try {
|
|
866
|
+
await updateSendMessageAgainCount(ids[0], key.participant);
|
|
712
867
|
logger.debug({ attrs, key }, 'recv retry request');
|
|
713
868
|
await sendMessagesAgain(key, ids, retryNode);
|
|
714
869
|
}
|
|
715
870
|
catch (error) {
|
|
716
|
-
logger.error({ key, ids, trace: error.stack }, 'error in sending message again');
|
|
871
|
+
logger.error({ key, ids, trace: error instanceof Error ? error.stack : 'Unknown error' }, 'error in sending message again');
|
|
717
872
|
}
|
|
718
873
|
}
|
|
719
874
|
else {
|
|
@@ -728,257 +883,308 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
728
883
|
]);
|
|
729
884
|
}
|
|
730
885
|
finally {
|
|
731
|
-
await sendMessageAck(node);
|
|
886
|
+
await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack receipt'));
|
|
732
887
|
}
|
|
733
888
|
};
|
|
734
889
|
const handleNotification = async (node) => {
|
|
735
890
|
const remoteJid = node.attrs.from;
|
|
736
|
-
if (shouldIgnoreJid(remoteJid) && remoteJid !==
|
|
891
|
+
if (shouldIgnoreJid(remoteJid) && remoteJid !== S_WHATSAPP_NET) {
|
|
737
892
|
logger.debug({ remoteJid, id: node.attrs.id }, 'ignored notification');
|
|
738
893
|
await sendMessageAck(node);
|
|
739
894
|
return;
|
|
740
895
|
}
|
|
741
896
|
try {
|
|
742
897
|
await Promise.all([
|
|
743
|
-
|
|
744
|
-
var _a;
|
|
898
|
+
notificationMutex.mutex(async () => {
|
|
745
899
|
const msg = await processNotification(node);
|
|
746
900
|
if (msg) {
|
|
747
|
-
const fromMe =
|
|
901
|
+
const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me.id);
|
|
902
|
+
const { senderAlt: participantAlt, addressingMode } = extractAddressingContext(node);
|
|
748
903
|
msg.key = {
|
|
749
904
|
remoteJid,
|
|
750
905
|
fromMe,
|
|
751
906
|
participant: node.attrs.participant,
|
|
907
|
+
participantAlt,
|
|
908
|
+
addressingMode,
|
|
752
909
|
id: node.attrs.id,
|
|
753
910
|
...(msg.key || {})
|
|
754
911
|
};
|
|
755
|
-
|
|
912
|
+
msg.participant ?? (msg.participant = node.attrs.participant);
|
|
756
913
|
msg.messageTimestamp = +node.attrs.t;
|
|
757
|
-
const fullMsg =
|
|
914
|
+
const fullMsg = proto.WebMessageInfo.fromObject(msg);
|
|
758
915
|
await upsertMessage(fullMsg, 'append');
|
|
759
916
|
}
|
|
760
917
|
})
|
|
761
918
|
]);
|
|
762
919
|
}
|
|
763
920
|
finally {
|
|
764
|
-
await sendMessageAck(node);
|
|
921
|
+
await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack notification'));
|
|
765
922
|
}
|
|
766
923
|
};
|
|
767
924
|
const handleMessage = async (node) => {
|
|
768
|
-
|
|
769
|
-
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
|
|
925
|
+
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== S_WHATSAPP_NET) {
|
|
770
926
|
logger.debug({ key: node.attrs.key }, 'ignored message');
|
|
771
|
-
await sendMessageAck(node);
|
|
927
|
+
await sendMessageAck(node, NACK_REASONS.UnhandledError);
|
|
772
928
|
return;
|
|
773
929
|
}
|
|
774
|
-
const encNode =
|
|
930
|
+
const encNode = getBinaryNodeChild(node, 'enc');
|
|
775
931
|
// TODO: temporary fix for crashes and issues resulting of failed msmsg decryption
|
|
776
|
-
if (encNode
|
|
932
|
+
if (encNode?.attrs.type === 'msmsg') {
|
|
777
933
|
logger.debug({ key: node.attrs.key }, 'ignored msmsg');
|
|
778
|
-
await sendMessageAck(node);
|
|
934
|
+
await sendMessageAck(node, NACK_REASONS.MissingMessageSecret);
|
|
779
935
|
return;
|
|
780
936
|
}
|
|
781
|
-
let
|
|
782
|
-
if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable') && !encNode) {
|
|
783
|
-
await sendMessageAck(node);
|
|
784
|
-
const { key } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '').fullMessage;
|
|
785
|
-
response = await requestPlaceholderResend(key);
|
|
786
|
-
if (response === 'RESOLVED') {
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
logger.debug('received unavailable message, acked and requested resend from phone');
|
|
790
|
-
}
|
|
791
|
-
else {
|
|
792
|
-
if (placeholderResendCache.get(node.attrs.id)) {
|
|
793
|
-
placeholderResendCache.del(node.attrs.id);
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
const { fullMessage: msg, category, author, decrypt } = (0, Utils_1.decryptMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
|
|
797
|
-
if (response && ((_a = msg === null || msg === void 0 ? void 0 : msg.messageStubParameters) === null || _a === void 0 ? void 0 : _a[0]) === Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT) {
|
|
798
|
-
msg.messageStubParameters = [Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT, response];
|
|
799
|
-
}
|
|
800
|
-
if (((_c = (_b = msg.message) === null || _b === void 0 ? void 0 : _b.protocolMessage) === null || _c === void 0 ? void 0 : _c.type) === WAProto_1.proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER && node.attrs.sender_pn) {
|
|
801
|
-
ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
|
|
802
|
-
}
|
|
937
|
+
let acked = false;
|
|
803
938
|
try {
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
939
|
+
const { fullMessage: msg, category, author, decrypt } = decryptMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
|
|
940
|
+
const alt = msg.key.participantAlt || msg.key.remoteJidAlt;
|
|
941
|
+
// store new mappings we didn't have before
|
|
942
|
+
if (!!alt) {
|
|
943
|
+
const altServer = jidDecode(alt)?.server;
|
|
944
|
+
const primaryJid = msg.key.participant || msg.key.remoteJid;
|
|
945
|
+
if (altServer === 'lid') {
|
|
946
|
+
if (!(await signalRepository.lidMapping.getPNForLID(alt))) {
|
|
947
|
+
await signalRepository.lidMapping.storeLIDPNMappings([{ lid: alt, pn: primaryJid }]);
|
|
948
|
+
await signalRepository.migrateSession(primaryJid, alt);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
await signalRepository.lidMapping.storeLIDPNMappings([{ lid: primaryJid, pn: alt }]);
|
|
953
|
+
await signalRepository.migrateSession(alt, primaryJid);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
await messageMutex.mutex(async () => {
|
|
957
|
+
await decrypt();
|
|
958
|
+
if (msg.key?.remoteJid && msg.key?.id && msg.message && messageRetryManager) {
|
|
959
|
+
messageRetryManager.addRecentMessage(msg.key.remoteJid, msg.key.id, msg.message);
|
|
960
|
+
}
|
|
961
|
+
// message failed to decrypt
|
|
962
|
+
if (msg.messageStubType === proto.WebMessageInfo.StubType.CIPHERTEXT && msg.category !== 'peer') {
|
|
963
|
+
if (msg?.messageStubParameters?.[0] === MISSING_KEYS_ERROR_TEXT) {
|
|
964
|
+
acked = true;
|
|
965
|
+
return sendMessageAck(node, NACK_REASONS.ParsingError);
|
|
966
|
+
}
|
|
967
|
+
if (msg.messageStubParameters?.[0] === NO_MESSAGE_FOUND_ERROR_TEXT) {
|
|
968
|
+
// Message arrived without encryption (e.g. CTWA ads messages).
|
|
969
|
+
// Check if this is eligible for placeholder resend (matching WA Web filters).
|
|
970
|
+
const unavailableNode = getBinaryNodeChild(node, 'unavailable');
|
|
971
|
+
const unavailableType = unavailableNode?.attrs?.type;
|
|
972
|
+
if (unavailableType === 'bot_unavailable_fanout' ||
|
|
973
|
+
unavailableType === 'hosted_unavailable_fanout' ||
|
|
974
|
+
unavailableType === 'view_once_unavailable_fanout') {
|
|
975
|
+
logger.debug({ msgId: msg.key.id, unavailableType }, 'skipping placeholder resend for excluded unavailable type');
|
|
976
|
+
acked = true;
|
|
977
|
+
return sendMessageAck(node);
|
|
812
978
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
979
|
+
const messageAge = unixTimestampSeconds() - toNumber(msg.messageTimestamp);
|
|
980
|
+
if (messageAge > PLACEHOLDER_MAX_AGE_SECONDS) {
|
|
981
|
+
logger.debug({ msgId: msg.key.id, messageAge }, 'skipping placeholder resend for old message');
|
|
982
|
+
acked = true;
|
|
983
|
+
return sendMessageAck(node);
|
|
984
|
+
}
|
|
985
|
+
// Request the real content from the phone via placeholder resend PDO.
|
|
986
|
+
// Upsert the CIPHERTEXT stub as a placeholder (like WA Web's processPlaceholderMsg),
|
|
987
|
+
// and store the requestId in stubParameters[1] so users can correlate
|
|
988
|
+
// with the incoming PDO response event.
|
|
989
|
+
const cleanKey = {
|
|
990
|
+
remoteJid: msg.key.remoteJid,
|
|
991
|
+
fromMe: msg.key.fromMe,
|
|
992
|
+
id: msg.key.id,
|
|
993
|
+
participant: msg.key.participant
|
|
994
|
+
};
|
|
995
|
+
// Cache the original message metadata so the PDO response handler
|
|
996
|
+
// can preserve key fields (LID details etc.) that the phone may omit
|
|
997
|
+
const msgData = {
|
|
998
|
+
key: msg.key,
|
|
999
|
+
messageTimestamp: msg.messageTimestamp,
|
|
1000
|
+
pushName: msg.pushName,
|
|
1001
|
+
participant: msg.participant,
|
|
1002
|
+
verifiedBizName: msg.verifiedBizName
|
|
1003
|
+
};
|
|
1004
|
+
requestPlaceholderResend(cleanKey, msgData)
|
|
1005
|
+
.then(requestId => {
|
|
1006
|
+
if (requestId && requestId !== 'RESOLVED') {
|
|
1007
|
+
logger.debug({ msgId: msg.key.id, requestId }, 'requested placeholder resend for unavailable message');
|
|
1008
|
+
ev.emit('messages.update', [
|
|
1009
|
+
{
|
|
1010
|
+
key: msg.key,
|
|
1011
|
+
update: { messageStubParameters: [NO_MESSAGE_FOUND_ERROR_TEXT, requestId] }
|
|
1012
|
+
}
|
|
1013
|
+
]);
|
|
1014
|
+
}
|
|
1015
|
+
})
|
|
1016
|
+
.catch(err => {
|
|
1017
|
+
logger.warn({ err, msgId: msg.key.id }, 'failed to request placeholder resend for unavailable message');
|
|
1018
|
+
});
|
|
1019
|
+
acked = true;
|
|
1020
|
+
await sendMessageAck(node);
|
|
1021
|
+
// Don't return — fall through to upsertMessage so the stub is emitted
|
|
1022
|
+
}
|
|
1023
|
+
else {
|
|
1024
|
+
// Skip retry for expired status messages (>24h old)
|
|
1025
|
+
if (isJidStatusBroadcast(msg.key.remoteJid)) {
|
|
1026
|
+
const messageAge = unixTimestampSeconds() - toNumber(msg.messageTimestamp);
|
|
1027
|
+
if (messageAge > STATUS_EXPIRY_SECONDS) {
|
|
1028
|
+
logger.debug({ msgId: msg.key.id, messageAge, remoteJid: msg.key.remoteJid }, 'skipping retry for expired status message');
|
|
1029
|
+
acked = true;
|
|
1030
|
+
return sendMessageAck(node);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
const errorMessage = msg?.messageStubParameters?.[0] || '';
|
|
1034
|
+
const isPreKeyError = errorMessage.includes('PreKey');
|
|
1035
|
+
logger.debug(`[handleMessage] Attempting retry request for failed decryption`);
|
|
1036
|
+
// Handle both pre-key and normal retries in single mutex
|
|
1037
|
+
await retryMutex.mutex(async () => {
|
|
1038
|
+
try {
|
|
1039
|
+
if (!ws.isOpen) {
|
|
1040
|
+
logger.debug({ node }, 'Connection closed, skipping retry');
|
|
816
1041
|
return;
|
|
817
1042
|
}
|
|
818
|
-
|
|
1043
|
+
// Handle pre-key errors with upload and delay
|
|
1044
|
+
if (isPreKeyError) {
|
|
1045
|
+
logger.info({ error: errorMessage }, 'PreKey error detected, uploading and retrying');
|
|
1046
|
+
try {
|
|
1047
|
+
logger.debug('Uploading pre-keys for error recovery');
|
|
1048
|
+
await uploadPreKeys(5);
|
|
1049
|
+
logger.debug('Waiting for server to process new pre-keys');
|
|
1050
|
+
await delay(1000);
|
|
1051
|
+
}
|
|
1052
|
+
catch (uploadErr) {
|
|
1053
|
+
logger.error({ uploadErr }, 'Pre-key upload failed, proceeding with retry anyway');
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
const encNode = getBinaryNodeChild(node, 'enc');
|
|
819
1057
|
await sendRetryRequest(node, !encNode);
|
|
820
1058
|
if (retryRequestDelayMs) {
|
|
821
|
-
await
|
|
1059
|
+
await delay(retryRequestDelayMs);
|
|
822
1060
|
}
|
|
823
1061
|
}
|
|
824
|
-
|
|
825
|
-
logger.
|
|
1062
|
+
catch (err) {
|
|
1063
|
+
logger.error({ err, isPreKeyError }, 'Failed to handle retry, attempting basic retry');
|
|
1064
|
+
// Still attempt retry even if pre-key upload failed
|
|
1065
|
+
try {
|
|
1066
|
+
const encNode = getBinaryNodeChild(node, 'enc');
|
|
1067
|
+
await sendRetryRequest(node, !encNode);
|
|
1068
|
+
}
|
|
1069
|
+
catch (retryErr) {
|
|
1070
|
+
logger.error({ retryErr }, 'Failed to send retry after error handling');
|
|
1071
|
+
}
|
|
826
1072
|
}
|
|
1073
|
+
acked = true;
|
|
1074
|
+
await sendMessageAck(node, NACK_REASONS.UnhandledError);
|
|
827
1075
|
});
|
|
828
1076
|
}
|
|
829
|
-
|
|
1077
|
+
}
|
|
1078
|
+
else {
|
|
1079
|
+
if (messageRetryManager && msg.key.id) {
|
|
1080
|
+
messageRetryManager.cancelPendingPhoneRequest(msg.key.id);
|
|
1081
|
+
}
|
|
1082
|
+
const isNewsletter = isJidNewsletter(msg.key.remoteJid);
|
|
1083
|
+
if (!isNewsletter) {
|
|
830
1084
|
// no type in the receipt => message delivered
|
|
831
1085
|
let type = undefined;
|
|
832
|
-
if ((_b = msg.key.participant) === null || _b === void 0 ? void 0 : _b.endsWith('@lid')) {
|
|
833
|
-
msg.key.participant = node.attrs.participant_pn || authState.creds.me.id;
|
|
834
|
-
}
|
|
835
|
-
if ((0, WABinary_1.isJidGroup)(msg.key.remoteJid) && ((_f = (_e = (_d = (_c = msg.message) === null || _c === void 0 ? void 0 : _c.extendedTextMessage) === null || _d === void 0 ? void 0 : _d.contextInfo) === null || _e === void 0 ? void 0 : _e.participant) === null || _f === void 0 ? void 0 : _f.endsWith('@lid'))) {
|
|
836
|
-
if (msg.message.extendedTextMessage.contextInfo) {
|
|
837
|
-
const metadata = await groupMetadata(msg.key.remoteJid);
|
|
838
|
-
const sender = msg.message.extendedTextMessage.contextInfo.participant;
|
|
839
|
-
const found = metadata.participants.find(p => p.id === sender);
|
|
840
|
-
msg.message.extendedTextMessage.contextInfo.participant = (found === null || found === void 0 ? void 0 : found.jid) || sender;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
if (!(0, WABinary_1.isJidGroup)(msg.key.remoteJid) && (0, WABinary_1.isLidUser)(msg.key.remoteJid)) {
|
|
844
|
-
msg.key.remoteJid = node.attrs.sender_pn || node.attrs.peer_recipient_pn;
|
|
845
|
-
}
|
|
846
1086
|
let participant = msg.key.participant;
|
|
847
|
-
if (category === 'peer') {
|
|
1087
|
+
if (category === 'peer') {
|
|
1088
|
+
// special peer message
|
|
848
1089
|
type = 'peer_msg';
|
|
849
1090
|
}
|
|
850
|
-
else if (msg.key.fromMe) {
|
|
1091
|
+
else if (msg.key.fromMe) {
|
|
1092
|
+
// message was sent by us from a different device
|
|
851
1093
|
type = 'sender';
|
|
852
1094
|
// need to specially handle this case
|
|
853
|
-
if ((
|
|
854
|
-
participant = author;
|
|
1095
|
+
if (isLidUser(msg.key.remoteJid) || isLidUser(msg.key.remoteJidAlt)) {
|
|
1096
|
+
participant = author; // TODO: investigate sending receipts to LIDs and not PNs
|
|
855
1097
|
}
|
|
856
1098
|
}
|
|
857
1099
|
else if (!sendActiveReceipts) {
|
|
858
1100
|
type = 'inactive';
|
|
859
1101
|
}
|
|
1102
|
+
acked = true;
|
|
860
1103
|
await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
|
|
861
1104
|
// send ack for history message
|
|
862
|
-
const isAnyHistoryMsg =
|
|
1105
|
+
const isAnyHistoryMsg = getHistoryMsg(msg.message);
|
|
863
1106
|
if (isAnyHistoryMsg) {
|
|
864
|
-
const jid =
|
|
865
|
-
await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync');
|
|
1107
|
+
const jid = jidNormalizedUser(msg.key.remoteJid);
|
|
1108
|
+
await sendReceipt(jid, undefined, [msg.key.id], 'hist_sync'); // TODO: investigate
|
|
866
1109
|
}
|
|
867
1110
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1111
|
+
else {
|
|
1112
|
+
acked = true;
|
|
1113
|
+
await sendMessageAck(node);
|
|
1114
|
+
logger.debug({ key: msg.key }, 'processed newsletter message without receipts');
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
cleanMessage(msg, authState.creds.me.id, authState.creds.me.lid);
|
|
1118
|
+
await upsertMessage(msg, node.attrs.offline ? 'append' : 'notify');
|
|
1119
|
+
});
|
|
873
1120
|
}
|
|
874
1121
|
catch (error) {
|
|
875
|
-
logger.error({ error, node }, 'error in handling message');
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
|
|
879
|
-
var _a;
|
|
880
|
-
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
881
|
-
throw new boom_1.Boom('Not authenticated');
|
|
882
|
-
}
|
|
883
|
-
const pdoMessage = {
|
|
884
|
-
historySyncOnDemandRequest: {
|
|
885
|
-
chatJid: oldestMsgKey.remoteJid,
|
|
886
|
-
oldestMsgFromMe: oldestMsgKey.fromMe,
|
|
887
|
-
oldestMsgId: oldestMsgKey.id,
|
|
888
|
-
oldestMsgTimestampMs: oldestMsgTimestamp,
|
|
889
|
-
onDemandMsgCount: count
|
|
890
|
-
},
|
|
891
|
-
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
|
|
892
|
-
};
|
|
893
|
-
return sendPeerDataOperationMessage(pdoMessage);
|
|
894
|
-
};
|
|
895
|
-
const requestPlaceholderResend = async (messageKey) => {
|
|
896
|
-
var _a;
|
|
897
|
-
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
898
|
-
throw new boom_1.Boom('Not authenticated');
|
|
899
|
-
}
|
|
900
|
-
if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
|
901
|
-
logger.debug({ messageKey }, 'already requested resend');
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
else {
|
|
905
|
-
placeholderResendCache.set(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id, true);
|
|
906
|
-
}
|
|
907
|
-
await (0, Utils_1.delay)(5000);
|
|
908
|
-
if (!placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
|
909
|
-
logger.debug({ messageKey }, 'message received while resend requested');
|
|
910
|
-
return 'RESOLVED';
|
|
911
|
-
}
|
|
912
|
-
const pdoMessage = {
|
|
913
|
-
placeholderMessageResendRequest: [{
|
|
914
|
-
messageKey
|
|
915
|
-
}],
|
|
916
|
-
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
|
|
917
|
-
};
|
|
918
|
-
setTimeout(() => {
|
|
919
|
-
if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
|
920
|
-
logger.debug({ messageKey }, 'PDO message without response after 15 seconds. Phone possibly offline');
|
|
921
|
-
placeholderResendCache.del(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id);
|
|
1122
|
+
logger.error({ error, node: binaryNodeToString(node) }, 'error in handling message');
|
|
1123
|
+
if (!acked) {
|
|
1124
|
+
await sendMessageAck(node, NACK_REASONS.UnhandledError).catch(ackErr => logger.error({ ackErr }, 'failed to ack message after error'));
|
|
922
1125
|
}
|
|
923
|
-
}
|
|
924
|
-
return sendPeerDataOperationMessage(pdoMessage);
|
|
1126
|
+
}
|
|
925
1127
|
};
|
|
926
1128
|
const handleCall = async (node) => {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1129
|
+
try {
|
|
1130
|
+
const { attrs } = node;
|
|
1131
|
+
const [infoChild] = getAllBinaryNodeChildren(node);
|
|
1132
|
+
if (!infoChild) {
|
|
1133
|
+
throw new Boom('Missing call info in call node');
|
|
1134
|
+
}
|
|
1135
|
+
const status = getCallStatusFromNode(infoChild);
|
|
1136
|
+
const callId = infoChild.attrs['call-id'];
|
|
1137
|
+
const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
|
|
1138
|
+
const call = {
|
|
1139
|
+
chatId: attrs.from,
|
|
1140
|
+
from,
|
|
1141
|
+
callerPn: infoChild.attrs['caller_pn'],
|
|
1142
|
+
id: callId,
|
|
1143
|
+
date: new Date(+attrs.t * 1000),
|
|
1144
|
+
offline: !!attrs.offline,
|
|
1145
|
+
status
|
|
1146
|
+
};
|
|
1147
|
+
if (status === 'offer') {
|
|
1148
|
+
call.isVideo = !!getBinaryNodeChild(infoChild, 'video');
|
|
1149
|
+
call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
|
|
1150
|
+
call.groupJid = infoChild.attrs['group-jid'];
|
|
1151
|
+
await callOfferCache.set(call.id, call);
|
|
1152
|
+
}
|
|
1153
|
+
const existingCall = await callOfferCache.get(call.id);
|
|
1154
|
+
// use existing call info to populate this event
|
|
1155
|
+
if (existingCall) {
|
|
1156
|
+
call.isVideo = existingCall.isVideo;
|
|
1157
|
+
call.isGroup = existingCall.isGroup;
|
|
1158
|
+
call.callerPn = call.callerPn || existingCall.callerPn;
|
|
1159
|
+
}
|
|
1160
|
+
// delete data once call has ended
|
|
1161
|
+
if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
|
|
1162
|
+
await callOfferCache.del(call.id);
|
|
1163
|
+
}
|
|
1164
|
+
ev.emit('call', [call]);
|
|
945
1165
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
if (existingCall) {
|
|
949
|
-
call.isVideo = existingCall.isVideo;
|
|
950
|
-
call.isGroup = existingCall.isGroup;
|
|
1166
|
+
catch (error) {
|
|
1167
|
+
logger.error({ error, node: binaryNodeToString(node) }, 'error in handling call');
|
|
951
1168
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
callOfferCache.del(call.id);
|
|
1169
|
+
finally {
|
|
1170
|
+
await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack call'));
|
|
955
1171
|
}
|
|
956
|
-
ev.emit('call', [call]);
|
|
957
|
-
await sendMessageAck(node);
|
|
958
1172
|
};
|
|
959
1173
|
const handleBadAck = async ({ attrs }) => {
|
|
960
|
-
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id
|
|
961
|
-
//
|
|
962
|
-
//
|
|
963
|
-
//
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
if (msg) {
|
|
975
|
-
await relayMessage(key.remoteJid, msg, { messageId: key.id, useUserDevicesCache: false });
|
|
976
|
-
msgRetryCache.set(cacheKey, retryCount + 1);
|
|
977
|
-
}
|
|
978
|
-
else {
|
|
979
|
-
logger.warn({ attrs }, 'could not send message again, as it was not found');
|
|
980
|
-
}
|
|
981
|
-
}
|
|
1174
|
+
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
|
|
1175
|
+
// WARNING: REFRAIN FROM ENABLING THIS FOR NOW. IT WILL CAUSE A LOOP
|
|
1176
|
+
// // current hypothesis is that if pash is sent in the ack
|
|
1177
|
+
// // it means -- the message hasn't reached all devices yet
|
|
1178
|
+
// // we'll retry sending the message here
|
|
1179
|
+
// if(attrs.phash) {
|
|
1180
|
+
// logger.info({ attrs }, 'received phash in ack, resending message...')
|
|
1181
|
+
// const msg = await getMessage(key)
|
|
1182
|
+
// if(msg) {
|
|
1183
|
+
// await relayMessage(key.remoteJid!, msg, { messageId: key.id!, useUserDevicesCache: false })
|
|
1184
|
+
// } else {
|
|
1185
|
+
// logger.warn({ attrs }, 'could not send message again, as it was not found')
|
|
1186
|
+
// }
|
|
1187
|
+
// }
|
|
982
1188
|
// error in acknowledgement,
|
|
983
1189
|
// device could not display the message
|
|
984
1190
|
if (attrs.error) {
|
|
@@ -987,13 +1193,24 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
987
1193
|
{
|
|
988
1194
|
key,
|
|
989
1195
|
update: {
|
|
990
|
-
status:
|
|
991
|
-
messageStubParameters: [
|
|
992
|
-
attrs.error
|
|
993
|
-
]
|
|
1196
|
+
status: WAMessageStatus.ERROR,
|
|
1197
|
+
messageStubParameters: [attrs.error]
|
|
994
1198
|
}
|
|
995
1199
|
}
|
|
996
1200
|
]);
|
|
1201
|
+
// resend the message with device_fanout=false, use at your own risk
|
|
1202
|
+
// if (attrs.error === '475') {
|
|
1203
|
+
// const msg = await getMessage(key)
|
|
1204
|
+
// if (msg) {
|
|
1205
|
+
// await relayMessage(key.remoteJid!, msg, {
|
|
1206
|
+
// messageId: key.id!,
|
|
1207
|
+
// useUserDevicesCache: false,
|
|
1208
|
+
// additionalAttributes: {
|
|
1209
|
+
// device_fanout: 'false'
|
|
1210
|
+
// }
|
|
1211
|
+
// })
|
|
1212
|
+
// }
|
|
1213
|
+
// }
|
|
997
1214
|
}
|
|
998
1215
|
};
|
|
999
1216
|
/// processes a node with the given function
|
|
@@ -1003,69 +1220,48 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1003
1220
|
await execTask();
|
|
1004
1221
|
ev.flush();
|
|
1005
1222
|
function execTask() {
|
|
1006
|
-
return exec(node, false)
|
|
1007
|
-
.catch(err => onUnexpectedError(err, identifier));
|
|
1223
|
+
return exec(node, false).catch(err => onUnexpectedError(err, identifier));
|
|
1008
1224
|
}
|
|
1009
1225
|
};
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
if (isProcessing) {
|
|
1022
|
-
return;
|
|
1023
|
-
}
|
|
1024
|
-
isProcessing = true;
|
|
1025
|
-
const promise = async () => {
|
|
1026
|
-
while (nodes.length && ws.isOpen) {
|
|
1027
|
-
const { type, node } = nodes.shift();
|
|
1028
|
-
const nodeProcessor = nodeProcessorMap.get(type);
|
|
1029
|
-
if (!nodeProcessor) {
|
|
1030
|
-
onUnexpectedError(new Error(`unknown offline node type: ${type}`), 'processing offline node');
|
|
1031
|
-
continue;
|
|
1032
|
-
}
|
|
1033
|
-
await nodeProcessor(node);
|
|
1034
|
-
}
|
|
1035
|
-
isProcessing = false;
|
|
1036
|
-
};
|
|
1037
|
-
promise().catch(error => onUnexpectedError(error, 'processing offline nodes'));
|
|
1038
|
-
};
|
|
1039
|
-
return { enqueue };
|
|
1040
|
-
};
|
|
1041
|
-
const offlineNodeProcessor = makeOfflineNodeProcessor();
|
|
1042
|
-
const processNode = (type, node, identifier, exec) => {
|
|
1226
|
+
const offlineNodeProcessor = makeOfflineNodeProcessor(new Map([
|
|
1227
|
+
['message', handleMessage],
|
|
1228
|
+
['call', handleCall],
|
|
1229
|
+
['receipt', handleReceipt],
|
|
1230
|
+
['notification', handleNotification]
|
|
1231
|
+
]), {
|
|
1232
|
+
isWsOpen: () => ws.isOpen,
|
|
1233
|
+
onUnexpectedError,
|
|
1234
|
+
yieldToEventLoop: () => new Promise(resolve => setImmediate(resolve))
|
|
1235
|
+
});
|
|
1236
|
+
const processNode = async (type, node, identifier, exec) => {
|
|
1043
1237
|
const isOffline = !!node.attrs.offline;
|
|
1044
1238
|
if (isOffline) {
|
|
1045
1239
|
offlineNodeProcessor.enqueue(type, node);
|
|
1046
1240
|
}
|
|
1047
1241
|
else {
|
|
1048
|
-
processNodeWithBuffer(node, identifier, exec);
|
|
1242
|
+
await processNodeWithBuffer(node, identifier, exec);
|
|
1049
1243
|
}
|
|
1050
1244
|
};
|
|
1051
1245
|
// recv a message
|
|
1052
|
-
ws.on('CB:message', (node) => {
|
|
1053
|
-
processNode('message', node, 'processing message', handleMessage);
|
|
1246
|
+
ws.on('CB:message', async (node) => {
|
|
1247
|
+
await processNode('message', node, 'processing message', handleMessage);
|
|
1054
1248
|
});
|
|
1055
1249
|
ws.on('CB:call', async (node) => {
|
|
1056
|
-
processNode('call', node, 'handling call', handleCall);
|
|
1250
|
+
await processNode('call', node, 'handling call', handleCall);
|
|
1057
1251
|
});
|
|
1058
|
-
ws.on('CB:receipt', node => {
|
|
1059
|
-
processNode('receipt', node, 'handling receipt', handleReceipt);
|
|
1252
|
+
ws.on('CB:receipt', async (node) => {
|
|
1253
|
+
await processNode('receipt', node, 'handling receipt', handleReceipt);
|
|
1060
1254
|
});
|
|
1061
1255
|
ws.on('CB:notification', async (node) => {
|
|
1062
|
-
processNode('notification', node, 'handling notification', handleNotification);
|
|
1256
|
+
await processNode('notification', node, 'handling notification', handleNotification);
|
|
1063
1257
|
});
|
|
1064
1258
|
ws.on('CB:ack,class:message', (node) => {
|
|
1065
|
-
handleBadAck(node)
|
|
1066
|
-
.catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1259
|
+
handleBadAck(node).catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1067
1260
|
});
|
|
1068
|
-
ev.on('call', ([call]) => {
|
|
1261
|
+
ev.on('call', async ([call]) => {
|
|
1262
|
+
if (!call) {
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1069
1265
|
// missed call + group call notification message generation
|
|
1070
1266
|
if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
|
|
1071
1267
|
const msg = {
|
|
@@ -1074,21 +1270,23 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1074
1270
|
id: call.id,
|
|
1075
1271
|
fromMe: false
|
|
1076
1272
|
},
|
|
1077
|
-
messageTimestamp:
|
|
1273
|
+
messageTimestamp: unixTimestampSeconds(call.date)
|
|
1078
1274
|
};
|
|
1079
1275
|
if (call.status === 'timeout') {
|
|
1080
1276
|
if (call.isGroup) {
|
|
1081
|
-
msg.messageStubType = call.isVideo
|
|
1277
|
+
msg.messageStubType = call.isVideo
|
|
1278
|
+
? WAMessageStubType.CALL_MISSED_GROUP_VIDEO
|
|
1279
|
+
: WAMessageStubType.CALL_MISSED_GROUP_VOICE;
|
|
1082
1280
|
}
|
|
1083
1281
|
else {
|
|
1084
|
-
msg.messageStubType = call.isVideo ?
|
|
1282
|
+
msg.messageStubType = call.isVideo ? WAMessageStubType.CALL_MISSED_VIDEO : WAMessageStubType.CALL_MISSED_VOICE;
|
|
1085
1283
|
}
|
|
1086
1284
|
}
|
|
1087
1285
|
else {
|
|
1088
1286
|
msg.message = { call: { callKey: Buffer.from(call.id) } };
|
|
1089
1287
|
}
|
|
1090
|
-
const protoMsg =
|
|
1091
|
-
upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
|
|
1288
|
+
const protoMsg = proto.WebMessageInfo.fromObject(msg);
|
|
1289
|
+
await upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
|
|
1092
1290
|
}
|
|
1093
1291
|
});
|
|
1094
1292
|
ev.on('connection.update', ({ isOnline }) => {
|
|
@@ -1102,9 +1300,9 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
1102
1300
|
sendMessageAck,
|
|
1103
1301
|
sendRetryRequest,
|
|
1104
1302
|
rejectCall,
|
|
1105
|
-
offerCall,
|
|
1106
1303
|
fetchMessageHistory,
|
|
1107
1304
|
requestPlaceholderResend,
|
|
1305
|
+
messageRetryManager
|
|
1108
1306
|
};
|
|
1109
1307
|
};
|
|
1110
|
-
|
|
1308
|
+
//# sourceMappingURL=messages-recv.js.map
|