phantom-baileys 0.0.8 → 0.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/README.md +592 -0
- package/WAProto/GenerateStatics.sh +3 -0
- package/WAProto/WAProto.proto +5479 -0
- package/WAProto/fix-imports.js +81 -0
- package/WAProto/index.d.ts +5147 -41513
- package/WAProto/index.js +84008 -142014
- package/lib/Defaults/index.d.ts +29 -8
- package/lib/Defaults/index.d.ts.map +1 -0
- package/lib/Defaults/index.js +80 -60
- package/lib/Defaults/index.js.map +1 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +10 -0
- package/lib/Signal/Group/ciphertext-message.d.ts.map +1 -0
- package/lib/Signal/Group/ciphertext-message.js +12 -0
- package/lib/Signal/Group/ciphertext-message.js.map +1 -0
- package/lib/Signal/Group/group-session-builder.d.ts +15 -0
- package/lib/Signal/Group/group-session-builder.d.ts.map +1 -0
- package/lib/Signal/Group/group-session-builder.js +30 -0
- package/lib/Signal/Group/group-session-builder.js.map +1 -0
- package/lib/Signal/Group/group_cipher.d.ts +17 -0
- package/lib/Signal/Group/group_cipher.d.ts.map +1 -0
- package/lib/Signal/Group/group_cipher.js +82 -0
- package/lib/Signal/Group/group_cipher.js.map +1 -0
- package/lib/Signal/Group/index.d.ts +12 -0
- package/lib/Signal/Group/index.d.ts.map +1 -0
- package/lib/Signal/Group/index.js +12 -0
- package/lib/Signal/Group/index.js.map +1 -0
- package/lib/Signal/Group/keyhelper.d.ts +11 -0
- package/lib/Signal/Group/keyhelper.d.ts.map +1 -0
- package/lib/Signal/Group/keyhelper.js +18 -0
- package/lib/Signal/Group/keyhelper.js.map +1 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +14 -0
- package/lib/Signal/Group/sender-chain-key.d.ts.map +1 -0
- package/lib/Signal/Group/sender-chain-key.js +26 -0
- package/lib/Signal/Group/sender-chain-key.js.map +1 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +17 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +63 -0
- package/lib/Signal/Group/sender-key-distribution-message.js.map +1 -0
- package/lib/Signal/Group/sender-key-message.d.ts +19 -0
- package/lib/Signal/Group/sender-key-message.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-message.js +66 -0
- package/lib/Signal/Group/sender-key-message.js.map +1 -0
- package/lib/Signal/Group/sender-key-name.d.ts +18 -0
- package/lib/Signal/Group/sender-key-name.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-name.js +48 -0
- package/lib/Signal/Group/sender-key-name.js.map +1 -0
- package/lib/Signal/Group/sender-key-record.d.ts +31 -0
- package/lib/Signal/Group/sender-key-record.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-record.js +41 -0
- package/lib/Signal/Group/sender-key-record.js.map +1 -0
- package/lib/Signal/Group/sender-key-state.d.ts +39 -0
- package/lib/Signal/Group/sender-key-state.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-state.js +84 -0
- package/lib/Signal/Group/sender-key-state.js.map +1 -0
- package/lib/Signal/Group/sender-message-key.d.ts +12 -0
- package/lib/Signal/Group/sender-message-key.d.ts.map +1 -0
- package/{WASignalGroup/sender_message_key.js → lib/Signal/Group/sender-message-key.js} +3 -16
- 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 +331 -80
- 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 +184 -101
- package/lib/Socket/business.d.ts.map +1 -0
- package/lib/Socket/business.js +162 -43
- package/lib/Socket/business.js.map +1 -0
- package/lib/Socket/chats.d.ts +72 -42
- package/lib/Socket/chats.d.ts.map +1 -0
- package/lib/Socket/chats.js +340 -299
- package/lib/Socket/chats.js.map +1 -0
- package/lib/Socket/communities.d.ts +309 -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 +79 -0
- package/lib/Socket/dugong.d.ts.map +1 -0
- package/lib/Socket/dugong.js +527 -0
- 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 +96 -84
- package/lib/Socket/groups.js.map +1 -0
- package/lib/Socket/index.d.ts +232 -107
- package/lib/Socket/index.d.ts.map +1 -0
- package/lib/Socket/index.js +13 -10
- package/lib/Socket/index.js.map +1 -0
- package/lib/Socket/messages-recv.d.ts +170 -90
- package/lib/Socket/messages-recv.d.ts.map +1 -0
- package/lib/Socket/messages-recv.js +798 -462
- package/lib/Socket/messages-recv.js.map +1 -0
- package/lib/Socket/messages-send.d.ts +180 -99
- package/lib/Socket/messages-send.d.ts.map +1 -0
- package/lib/Socket/messages-send.js +833 -709
- package/lib/Socket/messages-send.js.map +1 -0
- package/lib/Socket/mex.d.ts +3 -0
- package/lib/Socket/mex.d.ts.map +1 -0
- package/lib/Socket/mex.js +42 -0
- package/lib/Socket/mex.js.map +1 -0
- package/lib/Socket/newsletter.d.ts +120 -75
- package/lib/Socket/newsletter.d.ts.map +1 -0
- package/lib/Socket/newsletter.js +227 -198
- package/lib/Socket/newsletter.js.map +1 -0
- package/lib/Socket/socket.d.ts +31 -20
- package/lib/Socket/socket.d.ts.map +1 -0
- package/lib/Socket/socket.js +508 -215
- package/lib/Socket/socket.js.map +1 -0
- package/lib/Types/Auth.d.ts +18 -11
- package/lib/Types/Auth.d.ts.map +1 -0
- package/lib/Types/Auth.js +2 -2
- package/lib/Types/Auth.js.map +1 -0
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Bussines.d.ts.map +1 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Bussines.js.map +1 -0
- package/lib/Types/Call.d.ts +2 -0
- package/lib/Types/Call.d.ts.map +1 -0
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Call.js.map +1 -0
- package/lib/Types/Chat.d.ts +24 -8
- 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 +82 -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 +15 -3
- 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 +1 -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 +77 -202
- 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 +128 -85
- package/lib/Types/Newsletter.d.ts.map +1 -0
- package/lib/Types/Newsletter.js +25 -26
- 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 +41 -24
- 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 +15 -16
- package/lib/Types/index.d.ts.map +1 -0
- package/lib/Types/index.js +15 -31
- package/lib/Types/index.js.map +1 -0
- package/lib/Utils/auth-utils.d.ts +7 -6
- package/lib/Utils/auth-utils.d.ts.map +1 -0
- package/lib/Utils/auth-utils.js +228 -165
- 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 +4 -3
- 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 +16 -16
- package/lib/Utils/chat-utils.d.ts.map +1 -0
- package/lib/Utils/chat-utils.js +299 -232
- package/lib/Utils/chat-utils.js.map +1 -0
- package/lib/Utils/crypto.d.ts +18 -21
- package/lib/Utils/crypto.d.ts.map +1 -0
- package/lib/Utils/crypto.js +44 -125
- package/lib/Utils/crypto.js.map +1 -0
- package/lib/Utils/decode-wa-message.d.ts +20 -8
- package/lib/Utils/decode-wa-message.d.ts.map +1 -0
- package/lib/Utils/decode-wa-message.js +139 -90
- 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 +129 -72
- package/lib/Utils/event-buffer.js.map +1 -0
- package/lib/Utils/generics.d.ts +25 -22
- package/lib/Utils/generics.d.ts.map +1 -0
- package/lib/Utils/generics.js +157 -175
- package/lib/Utils/generics.js.map +1 -0
- package/lib/Utils/history.d.ts +14 -11
- package/lib/Utils/history.d.ts.map +1 -0
- package/lib/Utils/history.js +83 -46
- 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 +22 -17
- package/lib/Utils/index.d.ts.map +1 -0
- package/lib/Utils/index.js +22 -33
- package/lib/Utils/index.js.map +1 -0
- package/lib/Utils/link-preview.d.ts +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 -1
- 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 +2 -0
- package/lib/Utils/make-mutex.d.ts.map +1 -0
- package/lib/Utils/make-mutex.js +24 -34
- package/lib/Utils/make-mutex.js.map +1 -0
- package/lib/Utils/message-retry-manager.d.ts +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 +59 -42
- package/lib/Utils/messages-media.d.ts.map +1 -0
- package/lib/Utils/messages-media.js +411 -356
- 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 +412 -723
- package/lib/Utils/messages.js.map +1 -0
- package/lib/Utils/noise-handler.d.ts +13 -13
- package/lib/Utils/noise-handler.d.ts.map +1 -0
- package/lib/Utils/noise-handler.js +149 -108
- 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 +30 -11
- package/lib/Utils/process-message.d.ts.map +1 -0
- package/lib/Utils/process-message.js +321 -166
- 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 +129 -0
- package/lib/Utils/rich-messages.d.ts.map +1 -0
- package/lib/Utils/rich-messages.js +455 -0
- package/lib/Utils/rich-messages.js.map +1 -0
- package/lib/Utils/signal.d.ts +7 -6
- package/lib/Utils/signal.d.ts.map +1 -0
- package/lib/Utils/signal.js +65 -65
- package/lib/Utils/signal.js.map +1 -0
- package/lib/Utils/stanza-ack.d.ts +11 -0
- package/lib/Utils/stanza-ack.d.ts.map +1 -0
- package/lib/Utils/stanza-ack.js +38 -0
- package/lib/Utils/stanza-ack.js.map +1 -0
- package/lib/Utils/sync-action-utils.d.ts +19 -0
- package/lib/Utils/sync-action-utils.d.ts.map +1 -0
- package/lib/Utils/sync-action-utils.js +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 -1
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -0
- package/lib/Utils/use-multi-file-auth-state.js +79 -253
- package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
- package/lib/Utils/validate-connection.d.ts +6 -6
- package/lib/Utils/validate-connection.d.ts.map +1 -0
- package/lib/Utils/validate-connection.js +111 -116
- package/lib/Utils/validate-connection.js.map +1 -0
- package/lib/WABinary/constants.d.ts +5 -4
- 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 +4 -3
- package/lib/WABinary/decode.d.ts.map +1 -0
- package/lib/WABinary/decode.js +51 -53
- package/lib/WABinary/decode.js.map +1 -0
- package/lib/WABinary/encode.d.ts +2 -1
- package/lib/WABinary/encode.d.ts.map +1 -0
- package/lib/WABinary/encode.js +12 -44
- package/lib/WABinary/encode.js.map +1 -0
- package/lib/WABinary/generic-utils.d.ts +9 -6
- package/lib/WABinary/generic-utils.d.ts.map +1 -0
- package/lib/WABinary/generic-utils.js +124 -43
- 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 +24 -7
- 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 +2 -1
- 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 +3 -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/WAProto/fix-imports.d.ts +1 -0
- package/lib/WAProto/fix-imports.js +71 -0
- package/lib/WAProto/index.js +89345 -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 +7 -4
- 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 +13 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +16 -31
- package/lib/index.js.map +1 -0
- package/package.json +34 -74
- package/Readme.md +0 -1
- package/WASignalGroup/GroupProtocol.js +0 -1697
- package/WASignalGroup/ciphertext_message.js +0 -16
- package/WASignalGroup/group_cipher.js +0 -120
- package/WASignalGroup/group_session_builder.js +0 -46
- package/WASignalGroup/index.js +0 -5
- package/WASignalGroup/keyhelper.js +0 -21
- package/WASignalGroup/protobufs.js +0 -3
- package/WASignalGroup/queue_job.js +0 -69
- package/WASignalGroup/sender_chain_key.js +0 -50
- package/WASignalGroup/sender_key_distribution_message.js +0 -78
- package/WASignalGroup/sender_key_message.js +0 -92
- package/WASignalGroup/sender_key_name.js +0 -70
- package/WASignalGroup/sender_key_record.js +0 -56
- package/WASignalGroup/sender_key_state.js +0 -129
- package/lib/Defaults/baileys-version.json +0 -3
- 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 -264
- package/lib/Socket/registration.js +0 -166
- package/lib/Socket/usync.d.ts +0 -37
- 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 -14
- 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 -431
- 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
- package/lib/Utils/use-single-file-auth-state.d.ts +0 -12
- package/lib/Utils/use-single-file-auth-state.js +0 -75
|
@@ -1,157 +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 { logger, retryRequestDelayMs, maxMsgRetryCount, getMessage, shouldIgnoreJid } = config;
|
|
20
|
-
const sock = (0, messages_send_1.makeMessagesSocket)(config);
|
|
21
|
-
const { ev, authState, ws, processingMutex, signalRepository, query, upsertMessage, resyncAppState, onUnexpectedError, assertSessions, sendNode, relayMessage, sendReceipt, uploadPreKeys, getUSyncDevices, sendPeerDataOperationMessage, createParticipantNodes } = 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;
|
|
22
19
|
/** this mutex ensures that each retryRequest will wait for the previous one to finish */
|
|
23
|
-
const retryMutex =
|
|
24
|
-
const msgRetryCache = config.msgRetryCounterCache ||
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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 });
|
|
36
38
|
let sendActiveReceipts = false;
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
attrs: {
|
|
41
|
-
id: attrs.id,
|
|
42
|
-
to: attrs.from,
|
|
43
|
-
class: tag
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
if (!!errorCode) {
|
|
47
|
-
stanza.attrs.error = errorCode.toString();
|
|
39
|
+
const fetchMessageHistory = async (count, oldestMsgKey, oldestMsgTimestamp) => {
|
|
40
|
+
if (!authState.creds.me?.id) {
|
|
41
|
+
throw new Boom('Not authenticated');
|
|
48
42
|
}
|
|
49
|
-
|
|
50
|
-
|
|
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');
|
|
51
58
|
}
|
|
52
|
-
if (
|
|
53
|
-
|
|
59
|
+
if (await placeholderResendCache.get(messageKey?.id)) {
|
|
60
|
+
logger.debug({ messageKey }, 'already requested resend');
|
|
61
|
+
return;
|
|
54
62
|
}
|
|
55
|
-
|
|
56
|
-
|
|
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);
|
|
57
67
|
}
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
await delay(2000);
|
|
69
|
+
if (!(await placeholderResendCache.get(messageKey?.id))) {
|
|
70
|
+
logger.debug({ messageKey }, 'message received while resend requested');
|
|
71
|
+
return 'RESOLVED';
|
|
60
72
|
}
|
|
61
|
-
|
|
62
|
-
|
|
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);
|
|
63
88
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
offerContent.push({
|
|
71
|
-
tag: 'video',
|
|
72
|
-
attrs: { enc: 'vp8', dec: 'vp8', orientation: '0', 'screen_width': '1920', 'screen_height': '1080', 'device_orientation': '0' },
|
|
73
|
-
content: undefined
|
|
74
|
-
});
|
|
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;
|
|
75
95
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const encKey = (0, crypto_1.randomBytes)(32);
|
|
80
|
-
const devices = (await getUSyncDevices([toJid], true, false)).map(({ user, device }) => (0, WABinary_1.jidEncode)(user, 's.whatsapp.net', device));
|
|
81
|
-
await assertSessions(devices, true);
|
|
82
|
-
const { nodes: destinations, shouldIncludeDeviceIdentity } = await createParticipantNodes(devices, {
|
|
83
|
-
call: {
|
|
84
|
-
callKey: new Uint8Array(encKey)
|
|
85
|
-
}
|
|
86
|
-
}, { count: '0' });
|
|
87
|
-
offerContent.push({ tag: 'destination', attrs: {}, content: destinations });
|
|
88
|
-
if (shouldIncludeDeviceIdentity) {
|
|
89
|
-
offerContent.push({
|
|
90
|
-
tag: 'device-identity',
|
|
91
|
-
attrs: {},
|
|
92
|
-
content: (0, Utils_1.encodeSignedDeviceIdentity)(authState.creds.account, true)
|
|
93
|
-
});
|
|
96
|
+
let data;
|
|
97
|
+
try {
|
|
98
|
+
data = JSON.parse(mexNode.content.toString());
|
|
94
99
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
+
}
|
|
120
|
+
}
|
|
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;
|
|
138
|
+
}
|
|
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;
|
|
220
|
+
}
|
|
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);
|
|
115
226
|
};
|
|
116
227
|
const rejectCall = async (callId, callFrom) => {
|
|
117
|
-
const stanza =
|
|
228
|
+
const stanza = {
|
|
118
229
|
tag: 'call',
|
|
119
230
|
attrs: {
|
|
120
231
|
from: authState.creds.me.id,
|
|
121
|
-
to: callFrom
|
|
232
|
+
to: callFrom
|
|
122
233
|
},
|
|
123
|
-
content: [
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
124
236
|
tag: 'reject',
|
|
125
237
|
attrs: {
|
|
126
238
|
'call-id': callId,
|
|
127
239
|
'call-creator': callFrom,
|
|
128
|
-
count: '0'
|
|
240
|
+
count: '0'
|
|
129
241
|
},
|
|
130
|
-
content: undefined
|
|
131
|
-
}
|
|
132
|
-
|
|
242
|
+
content: undefined
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
};
|
|
133
246
|
await query(stanza);
|
|
134
247
|
};
|
|
135
248
|
const sendRetryRequest = async (node, forceIncludeKeys = false) => {
|
|
136
|
-
const { fullMessage } =
|
|
249
|
+
const { fullMessage } = decodeMessageNode(node, authState.creds.me.id, authState.creds.me.lid || '');
|
|
137
250
|
const { key: msgKey } = fullMessage;
|
|
138
251
|
const msgId = msgKey.id;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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);
|
|
145
276
|
}
|
|
146
|
-
|
|
147
|
-
msgRetryCache.
|
|
277
|
+
const key = `${msgId}:${msgKey?.participant}`;
|
|
278
|
+
const retryCount = (await msgRetryCache.get(key)) || 1;
|
|
148
279
|
const { account, signedPreKey, signedIdentityKey: identityKey } = authState.creds;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
+
}
|
|
302
|
+
}
|
|
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
|
+
}
|
|
153
322
|
}
|
|
154
|
-
const deviceIdentity =
|
|
323
|
+
const deviceIdentity = encodeSignedDeviceIdentity(account, true);
|
|
155
324
|
await authState.keys.transaction(async () => {
|
|
156
325
|
const receipt = {
|
|
157
326
|
tag: 'receipt',
|
|
@@ -167,13 +336,15 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
167
336
|
count: retryCount.toString(),
|
|
168
337
|
id: node.attrs.id,
|
|
169
338
|
t: node.attrs.t,
|
|
170
|
-
v: '1'
|
|
339
|
+
v: '1',
|
|
340
|
+
// ADD ERROR FIELD
|
|
341
|
+
error: '0'
|
|
171
342
|
}
|
|
172
343
|
},
|
|
173
344
|
{
|
|
174
345
|
tag: 'registration',
|
|
175
346
|
attrs: {},
|
|
176
|
-
content:
|
|
347
|
+
content: encodeBigEndian(authState.creds.registrationId)
|
|
177
348
|
}
|
|
178
349
|
]
|
|
179
350
|
};
|
|
@@ -183,8 +354,8 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
183
354
|
if (node.attrs.participant) {
|
|
184
355
|
receipt.attrs.participant = node.attrs.participant;
|
|
185
356
|
}
|
|
186
|
-
if (retryCount > 1 || forceIncludeKeys) {
|
|
187
|
-
const { update, preKeys } = await
|
|
357
|
+
if (retryCount > 1 || forceIncludeKeys || shouldRecreateSession) {
|
|
358
|
+
const { update, preKeys } = await getNextPreKeys(authState, 1);
|
|
188
359
|
const [keyId] = Object.keys(preKeys);
|
|
189
360
|
const key = preKeys[+keyId];
|
|
190
361
|
const content = receipt.content;
|
|
@@ -192,10 +363,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
192
363
|
tag: 'keys',
|
|
193
364
|
attrs: {},
|
|
194
365
|
content: [
|
|
195
|
-
{ tag: 'type', attrs: {}, content: Buffer.from(
|
|
366
|
+
{ tag: 'type', attrs: {}, content: Buffer.from(KEY_BUNDLE_TYPE) },
|
|
196
367
|
{ tag: 'identity', attrs: {}, content: identityKey.public },
|
|
197
|
-
|
|
198
|
-
|
|
368
|
+
xmppPreKey(key, +keyId),
|
|
369
|
+
xmppSignedPreKey(signedPreKey),
|
|
199
370
|
{ tag: 'device-identity', attrs: {}, content: deviceIdentity }
|
|
200
371
|
]
|
|
201
372
|
});
|
|
@@ -203,63 +374,73 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
203
374
|
}
|
|
204
375
|
await sendNode(receipt);
|
|
205
376
|
logger.info({ msgAttrs: node.attrs, retryCount }, 'sent retry receipt');
|
|
206
|
-
});
|
|
377
|
+
}, authState?.creds?.me?.id || 'sendRetryRequest');
|
|
207
378
|
};
|
|
208
379
|
const handleEncryptNotification = async (node) => {
|
|
209
380
|
const from = node.attrs.from;
|
|
210
|
-
if (from ===
|
|
211
|
-
const countChild =
|
|
381
|
+
if (from === S_WHATSAPP_NET) {
|
|
382
|
+
const countChild = getBinaryNodeChild(node, 'count');
|
|
212
383
|
const count = +countChild.attrs.value;
|
|
213
|
-
const shouldUploadMorePreKeys = count <
|
|
384
|
+
const shouldUploadMorePreKeys = count < MIN_PREKEY_COUNT;
|
|
214
385
|
logger.debug({ count, shouldUploadMorePreKeys }, 'recv pre-key count');
|
|
215
386
|
if (shouldUploadMorePreKeys) {
|
|
216
387
|
await uploadPreKeys();
|
|
217
388
|
}
|
|
218
389
|
}
|
|
219
390
|
else {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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') {
|
|
227
400
|
logger.info({ node }, 'unknown encrypt notification');
|
|
228
401
|
}
|
|
229
402
|
}
|
|
230
403
|
};
|
|
231
|
-
const handleGroupNotification = (
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
|
|
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) {
|
|
235
411
|
case 'create':
|
|
236
|
-
const metadata =
|
|
237
|
-
msg.messageStubType =
|
|
412
|
+
const metadata = extractGroupMetadata(child);
|
|
413
|
+
msg.messageStubType = WAMessageStubType.GROUP_CREATE;
|
|
238
414
|
msg.messageStubParameters = [metadata.subject];
|
|
239
|
-
msg.key = { participant: metadata.owner };
|
|
240
|
-
ev.emit('chats.upsert', [
|
|
415
|
+
msg.key = { participant: metadata.owner, participantAlt: metadata.ownerPn };
|
|
416
|
+
ev.emit('chats.upsert', [
|
|
417
|
+
{
|
|
241
418
|
id: metadata.id,
|
|
242
419
|
name: metadata.subject,
|
|
243
|
-
conversationTimestamp: metadata.creation
|
|
244
|
-
}
|
|
245
|
-
|
|
420
|
+
conversationTimestamp: metadata.creation
|
|
421
|
+
}
|
|
422
|
+
]);
|
|
423
|
+
ev.emit('groups.upsert', [
|
|
424
|
+
{
|
|
246
425
|
...metadata,
|
|
247
|
-
author:
|
|
248
|
-
|
|
426
|
+
author: actingParticipantLid,
|
|
427
|
+
authorPn: actingParticipantPn
|
|
428
|
+
}
|
|
429
|
+
]);
|
|
249
430
|
break;
|
|
250
431
|
case 'ephemeral':
|
|
251
432
|
case 'not_ephemeral':
|
|
252
433
|
msg.message = {
|
|
253
434
|
protocolMessage: {
|
|
254
|
-
type:
|
|
435
|
+
type: proto.Message.ProtocolMessage.Type.EPHEMERAL_SETTING,
|
|
255
436
|
ephemeralExpiration: +(child.attrs.expiration || 0)
|
|
256
437
|
}
|
|
257
438
|
};
|
|
258
439
|
break;
|
|
259
440
|
case 'modify':
|
|
260
|
-
const oldNumber =
|
|
441
|
+
const oldNumber = getBinaryNodeChildren(child, 'participant').map(p => p.attrs.jid);
|
|
261
442
|
msg.messageStubParameters = oldNumber || [];
|
|
262
|
-
msg.messageStubType =
|
|
443
|
+
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_CHANGE_NUMBER;
|
|
263
444
|
break;
|
|
264
445
|
case 'promote':
|
|
265
446
|
case 'demote':
|
|
@@ -267,126 +448,141 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
267
448
|
case 'add':
|
|
268
449
|
case 'leave':
|
|
269
450
|
const stubType = `GROUP_PARTICIPANT_${child.tag.toUpperCase()}`;
|
|
270
|
-
msg.messageStubType =
|
|
271
|
-
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
|
+
});
|
|
272
461
|
if (participants.length === 1 &&
|
|
273
462
|
// if recv. "remove" message and sender removed themselves
|
|
274
463
|
// mark as left
|
|
275
|
-
(
|
|
464
|
+
(areJidsSameUser(participants[0].id, actingParticipantLid) ||
|
|
465
|
+
areJidsSameUser(participants[0].id, actingParticipantPn)) &&
|
|
276
466
|
child.tag === 'remove') {
|
|
277
|
-
msg.messageStubType =
|
|
467
|
+
msg.messageStubType = WAMessageStubType.GROUP_PARTICIPANT_LEAVE;
|
|
278
468
|
}
|
|
279
|
-
msg.messageStubParameters = participants;
|
|
469
|
+
msg.messageStubParameters = participants.map(a => JSON.stringify(a));
|
|
280
470
|
break;
|
|
281
471
|
case 'subject':
|
|
282
|
-
msg.messageStubType =
|
|
472
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_SUBJECT;
|
|
283
473
|
msg.messageStubParameters = [child.attrs.subject];
|
|
284
474
|
break;
|
|
285
475
|
case 'description':
|
|
286
|
-
const description =
|
|
287
|
-
msg.messageStubType =
|
|
476
|
+
const description = getBinaryNodeChild(child, 'body')?.content?.toString();
|
|
477
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_DESCRIPTION;
|
|
288
478
|
msg.messageStubParameters = description ? [description] : undefined;
|
|
289
479
|
break;
|
|
290
480
|
case 'announcement':
|
|
291
481
|
case 'not_announcement':
|
|
292
|
-
msg.messageStubType =
|
|
293
|
-
msg.messageStubParameters = [
|
|
482
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_ANNOUNCE;
|
|
483
|
+
msg.messageStubParameters = [child.tag === 'announcement' ? 'on' : 'off'];
|
|
294
484
|
break;
|
|
295
485
|
case 'locked':
|
|
296
486
|
case 'unlocked':
|
|
297
|
-
msg.messageStubType =
|
|
298
|
-
msg.messageStubParameters = [
|
|
487
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_RESTRICT;
|
|
488
|
+
msg.messageStubParameters = [child.tag === 'locked' ? 'on' : 'off'];
|
|
299
489
|
break;
|
|
300
490
|
case 'invite':
|
|
301
|
-
msg.messageStubType =
|
|
491
|
+
msg.messageStubType = WAMessageStubType.GROUP_CHANGE_INVITE_LINK;
|
|
302
492
|
msg.messageStubParameters = [child.attrs.code];
|
|
303
493
|
break;
|
|
304
494
|
case 'member_add_mode':
|
|
305
495
|
const addMode = child.content;
|
|
306
496
|
if (addMode) {
|
|
307
|
-
msg.messageStubType =
|
|
497
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBER_ADD_MODE;
|
|
308
498
|
msg.messageStubParameters = [addMode.toString()];
|
|
309
499
|
}
|
|
310
500
|
break;
|
|
311
501
|
case 'membership_approval_mode':
|
|
312
|
-
const approvalMode =
|
|
502
|
+
const approvalMode = getBinaryNodeChild(child, 'group_join');
|
|
313
503
|
if (approvalMode) {
|
|
314
|
-
msg.messageStubType =
|
|
504
|
+
msg.messageStubType = WAMessageStubType.GROUP_MEMBERSHIP_JOIN_APPROVAL_MODE;
|
|
315
505
|
msg.messageStubParameters = [approvalMode.attrs.state];
|
|
316
506
|
}
|
|
317
507
|
break;
|
|
318
508
|
case 'created_membership_requests':
|
|
319
|
-
msg.messageStubType =
|
|
320
|
-
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
|
+
];
|
|
321
515
|
break;
|
|
322
516
|
case 'revoked_membership_requests':
|
|
323
|
-
const isDenied =
|
|
324
|
-
|
|
325
|
-
msg.
|
|
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
|
+
];
|
|
326
524
|
break;
|
|
327
525
|
}
|
|
328
526
|
};
|
|
329
527
|
const processNotification = async (node) => {
|
|
330
|
-
var _a, _b, _c;
|
|
331
528
|
const result = {};
|
|
332
|
-
const [child] =
|
|
529
|
+
const [child] = getAllBinaryNodeChildren(node);
|
|
333
530
|
const nodeType = node.attrs.type;
|
|
334
|
-
const from =
|
|
531
|
+
const from = jidNormalizedUser(node.attrs.from);
|
|
335
532
|
switch (nodeType) {
|
|
336
|
-
case '
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
{
|
|
342
|
-
id: jid,
|
|
343
|
-
tcToken: content
|
|
344
|
-
}
|
|
345
|
-
]);
|
|
346
|
-
logger.debug({ jid }, 'got privacy token update');
|
|
347
|
-
}
|
|
533
|
+
case 'newsletter':
|
|
534
|
+
await handleNewsletterNotification(node);
|
|
535
|
+
break;
|
|
536
|
+
case 'mex':
|
|
537
|
+
await handleMexNewsletterNotification(node);
|
|
348
538
|
break;
|
|
349
539
|
case 'w:gp2':
|
|
350
|
-
|
|
540
|
+
// TODO: HANDLE PARTICIPANT_PN
|
|
541
|
+
handleGroupNotification(node, child, result);
|
|
351
542
|
break;
|
|
352
543
|
case 'mediaretry':
|
|
353
|
-
const event =
|
|
544
|
+
const event = decodeMediaRetryNode(node);
|
|
354
545
|
ev.emit('messages.media-update', [event]);
|
|
355
546
|
break;
|
|
356
547
|
case 'encrypt':
|
|
357
548
|
await handleEncryptNotification(node);
|
|
358
549
|
break;
|
|
359
550
|
case 'devices':
|
|
360
|
-
const devices =
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
|
|
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');
|
|
364
556
|
}
|
|
557
|
+
//TODO: drop a new event, add hashes
|
|
365
558
|
break;
|
|
366
559
|
case 'server_sync':
|
|
367
|
-
const update =
|
|
560
|
+
const update = getBinaryNodeChild(node, 'collection');
|
|
368
561
|
if (update) {
|
|
369
562
|
const name = update.attrs.name;
|
|
370
563
|
await resyncAppState([name], false);
|
|
371
564
|
}
|
|
372
565
|
break;
|
|
373
566
|
case 'picture':
|
|
374
|
-
const setPicture =
|
|
375
|
-
const delPicture =
|
|
376
|
-
|
|
377
|
-
|
|
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 || '',
|
|
378
573
|
imgUrl: setPicture ? 'changed' : 'removed'
|
|
379
|
-
}
|
|
380
|
-
|
|
574
|
+
}
|
|
575
|
+
]);
|
|
576
|
+
if (isJidGroup(from)) {
|
|
381
577
|
const node = setPicture || delPicture;
|
|
382
|
-
result.messageStubType =
|
|
578
|
+
result.messageStubType = WAMessageStubType.GROUP_CHANGE_ICON;
|
|
383
579
|
if (setPicture) {
|
|
384
580
|
result.messageStubParameters = [setPicture.attrs.id];
|
|
385
581
|
}
|
|
386
|
-
result.participant = node
|
|
582
|
+
result.participant = node?.attrs.author;
|
|
387
583
|
result.key = {
|
|
388
|
-
...result.key || {},
|
|
389
|
-
participant: setPicture
|
|
584
|
+
...(result.key || {}),
|
|
585
|
+
participant: setPicture?.attrs.author
|
|
390
586
|
};
|
|
391
587
|
}
|
|
392
588
|
break;
|
|
@@ -400,44 +596,48 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
400
596
|
...authState.creds.accountSettings,
|
|
401
597
|
defaultDisappearingMode: {
|
|
402
598
|
ephemeralExpiration: newDuration,
|
|
403
|
-
ephemeralSettingTimestamp: timestamp
|
|
404
|
-
}
|
|
599
|
+
ephemeralSettingTimestamp: timestamp
|
|
600
|
+
}
|
|
405
601
|
}
|
|
406
602
|
});
|
|
407
603
|
}
|
|
408
604
|
else if (child.tag === 'blocklist') {
|
|
409
|
-
const blocklists =
|
|
605
|
+
const blocklists = getBinaryNodeChildren(child, 'item');
|
|
410
606
|
for (const { attrs } of blocklists) {
|
|
411
607
|
const blocklist = [attrs.jid];
|
|
412
|
-
const type =
|
|
608
|
+
const type = attrs.action === 'block' ? 'add' : 'remove';
|
|
413
609
|
ev.emit('blocklist.update', { blocklist, type });
|
|
414
610
|
}
|
|
415
611
|
}
|
|
416
612
|
break;
|
|
417
613
|
case 'link_code_companion_reg':
|
|
418
|
-
const linkCodeCompanionReg =
|
|
419
|
-
const ref = toRequiredBuffer(
|
|
420
|
-
const primaryIdentityPublicKey = toRequiredBuffer(
|
|
421
|
-
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'));
|
|
422
618
|
const codePairingPublicKey = await decipherLinkPublicKey(primaryEphemeralPublicKeyWrapped);
|
|
423
|
-
const companionSharedKey =
|
|
424
|
-
const random =
|
|
425
|
-
const linkCodeSalt =
|
|
426
|
-
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, {
|
|
427
623
|
salt: linkCodeSalt,
|
|
428
624
|
info: 'link_code_pairing_key_bundle_encryption_key'
|
|
429
625
|
});
|
|
430
|
-
const encryptPayload = Buffer.concat([
|
|
431
|
-
|
|
432
|
-
|
|
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));
|
|
433
633
|
const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted]);
|
|
434
|
-
const identitySharedKey =
|
|
634
|
+
const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey);
|
|
435
635
|
const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random]);
|
|
436
|
-
authState.creds.advSecretKey = (
|
|
636
|
+
authState.creds.advSecretKey = Buffer.from(hkdf(identityPayload, 32, { info: 'adv_secret' })).toString('base64');
|
|
437
637
|
await query({
|
|
438
638
|
tag: 'iq',
|
|
439
639
|
attrs: {
|
|
440
|
-
to:
|
|
640
|
+
to: S_WHATSAPP_NET,
|
|
441
641
|
type: 'set',
|
|
442
642
|
id: sock.generateMessageTag(),
|
|
443
643
|
xmlns: 'md'
|
|
@@ -447,7 +647,7 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
447
647
|
tag: 'link_code_companion_reg',
|
|
448
648
|
attrs: {
|
|
449
649
|
jid: authState.creds.me.id,
|
|
450
|
-
stage: 'companion_finish'
|
|
650
|
+
stage: 'companion_finish'
|
|
451
651
|
},
|
|
452
652
|
content: [
|
|
453
653
|
{
|
|
@@ -471,52 +671,125 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
471
671
|
});
|
|
472
672
|
authState.creds.registered = true;
|
|
473
673
|
ev.emit('creds.update', authState.creds);
|
|
674
|
+
break;
|
|
675
|
+
case 'privacy_token':
|
|
676
|
+
await handlePrivacyTokenNotification(node);
|
|
677
|
+
break;
|
|
474
678
|
}
|
|
475
679
|
if (Object.keys(result).length) {
|
|
476
680
|
return result;
|
|
477
681
|
}
|
|
478
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
|
+
};
|
|
479
705
|
async function decipherLinkPublicKey(data) {
|
|
480
706
|
const buffer = toRequiredBuffer(data);
|
|
481
707
|
const salt = buffer.slice(0, 32);
|
|
482
|
-
const secretKey = await
|
|
708
|
+
const secretKey = await derivePairingCodeKey(authState.creds.pairingCode, salt);
|
|
483
709
|
const iv = buffer.slice(32, 48);
|
|
484
710
|
const payload = buffer.slice(48, 80);
|
|
485
|
-
return
|
|
711
|
+
return aesDecryptCTR(payload, secretKey, iv);
|
|
486
712
|
}
|
|
487
713
|
function toRequiredBuffer(data) {
|
|
488
714
|
if (data === undefined) {
|
|
489
|
-
throw new
|
|
715
|
+
throw new Boom('Invalid buffer', { statusCode: 400 });
|
|
490
716
|
}
|
|
491
717
|
return data instanceof Buffer ? data : Buffer.from(data);
|
|
492
718
|
}
|
|
493
|
-
const willSendMessageAgain = (id, participant) => {
|
|
719
|
+
const willSendMessageAgain = async (id, participant) => {
|
|
494
720
|
const key = `${id}:${participant}`;
|
|
495
|
-
const retryCount = msgRetryCache.get(key) || 0;
|
|
721
|
+
const retryCount = (await msgRetryCache.get(key)) || 0;
|
|
496
722
|
return retryCount < maxMsgRetryCount;
|
|
497
723
|
};
|
|
498
|
-
const updateSendMessageAgainCount = (id, participant) => {
|
|
724
|
+
const updateSendMessageAgainCount = async (id, participant) => {
|
|
499
725
|
const key = `${id}:${participant}`;
|
|
500
|
-
const newValue = (msgRetryCache.get(key) || 0) + 1;
|
|
501
|
-
msgRetryCache.set(key, newValue);
|
|
726
|
+
const newValue = ((await msgRetryCache.get(key)) || 0) + 1;
|
|
727
|
+
await msgRetryCache.set(key, newValue);
|
|
502
728
|
};
|
|
503
729
|
const sendMessagesAgain = async (key, ids, retryNode) => {
|
|
504
|
-
var _a;
|
|
505
|
-
const msgs = await Promise.all(ids.map(id => getMessage({ ...key, id })));
|
|
506
730
|
const remoteJid = key.remoteJid;
|
|
507
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
|
+
}
|
|
508
760
|
// if it's the primary jid sending the request
|
|
509
761
|
// just re-send the message to everyone
|
|
510
762
|
// prevents the first message decryption failure
|
|
511
|
-
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
|
+
}
|
|
512
783
|
await assertSessions([participant], true);
|
|
513
|
-
if (
|
|
784
|
+
if (isJidGroup(remoteJid)) {
|
|
514
785
|
await authState.keys.set({ 'sender-key-memory': { [remoteJid]: null } });
|
|
515
786
|
}
|
|
516
|
-
logger.debug({ participant, sendToAll }, 'forced new session for retry recp');
|
|
787
|
+
logger.debug({ participant, sendToAll, shouldRecreateSession, recreateReason }, 'forced new session for retry recp');
|
|
517
788
|
for (const [i, msg] of msgs.entries()) {
|
|
518
|
-
if (
|
|
519
|
-
|
|
789
|
+
if (!ids[i])
|
|
790
|
+
continue;
|
|
791
|
+
if (msg && (await willSendMessageAgain(ids[i], participant))) {
|
|
792
|
+
await updateSendMessageAgainCount(ids[i], participant);
|
|
520
793
|
const msgRelayOpts = { messageId: ids[i] };
|
|
521
794
|
if (sendToAll) {
|
|
522
795
|
msgRelayOpts.useUserDevicesCache = false;
|
|
@@ -535,45 +808,42 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
535
808
|
}
|
|
536
809
|
};
|
|
537
810
|
const handleReceipt = async (node) => {
|
|
538
|
-
var _a, _b;
|
|
539
811
|
const { attrs, content } = node;
|
|
540
812
|
const isLid = attrs.from.includes('lid');
|
|
541
|
-
const isNodeFromMe =
|
|
542
|
-
const remoteJid = !isNodeFromMe ||
|
|
543
|
-
const fromMe = !attrs.recipient || (attrs.type === 'retry' && 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;
|
|
815
|
+
const fromMe = !attrs.recipient || ((attrs.type === 'retry' || attrs.type === 'sender') && isNodeFromMe);
|
|
544
816
|
const key = {
|
|
545
817
|
remoteJid,
|
|
546
818
|
id: '',
|
|
547
819
|
fromMe,
|
|
548
820
|
participant: attrs.participant
|
|
549
821
|
};
|
|
550
|
-
if (shouldIgnoreJid(remoteJid) && remoteJid !==
|
|
822
|
+
if (shouldIgnoreJid(remoteJid) && remoteJid !== S_WHATSAPP_NET) {
|
|
551
823
|
logger.debug({ remoteJid }, 'ignoring receipt from jid');
|
|
552
824
|
await sendMessageAck(node);
|
|
553
825
|
return;
|
|
554
826
|
}
|
|
555
827
|
const ids = [attrs.id];
|
|
556
828
|
if (Array.isArray(content)) {
|
|
557
|
-
const items =
|
|
829
|
+
const items = getBinaryNodeChildren(content[0], 'item');
|
|
558
830
|
ids.push(...items.map(i => i.attrs.id));
|
|
559
831
|
}
|
|
560
832
|
try {
|
|
561
833
|
await Promise.all([
|
|
562
|
-
|
|
563
|
-
const status =
|
|
834
|
+
receiptMutex.mutex(async () => {
|
|
835
|
+
const status = getStatusFromReceiptType(attrs.type);
|
|
564
836
|
if (typeof status !== 'undefined' &&
|
|
565
|
-
(
|
|
566
837
|
// basically, we only want to know when a message from us has been delivered to/read by the other person
|
|
567
838
|
// or another device of ours has read some messages
|
|
568
|
-
status >=
|
|
569
|
-
|
|
570
|
-
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)) {
|
|
571
841
|
if (attrs.participant) {
|
|
572
|
-
const updateKey = status ===
|
|
842
|
+
const updateKey = status === proto.WebMessageInfo.Status.DELIVERY_ACK ? 'receiptTimestamp' : 'readTimestamp';
|
|
573
843
|
ev.emit('message-receipt.update', ids.map(id => ({
|
|
574
844
|
key: { ...key, id },
|
|
575
845
|
receipt: {
|
|
576
|
-
userJid:
|
|
846
|
+
userJid: jidNormalizedUser(attrs.participant),
|
|
577
847
|
[updateKey]: +attrs.t
|
|
578
848
|
}
|
|
579
849
|
})));
|
|
@@ -582,22 +852,23 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
582
852
|
else {
|
|
583
853
|
ev.emit('messages.update', ids.map(id => ({
|
|
584
854
|
key: { ...key, id },
|
|
585
|
-
update: { status }
|
|
855
|
+
update: { status, messageTimestamp: toNumber(+(attrs.t ?? 0)) }
|
|
586
856
|
})));
|
|
587
857
|
}
|
|
588
858
|
}
|
|
589
859
|
if (attrs.type === 'retry') {
|
|
590
860
|
// correctly set who is asking for the retry
|
|
591
861
|
key.participant = key.participant || attrs.from;
|
|
592
|
-
const retryNode =
|
|
593
|
-
if (willSendMessageAgain(ids[0], key.participant)) {
|
|
862
|
+
const retryNode = getBinaryNodeChild(node, 'retry');
|
|
863
|
+
if (ids[0] && key.participant && (await willSendMessageAgain(ids[0], key.participant))) {
|
|
594
864
|
if (key.fromMe) {
|
|
595
865
|
try {
|
|
866
|
+
await updateSendMessageAgainCount(ids[0], key.participant);
|
|
596
867
|
logger.debug({ attrs, key }, 'recv retry request');
|
|
597
868
|
await sendMessagesAgain(key, ids, retryNode);
|
|
598
869
|
}
|
|
599
870
|
catch (error) {
|
|
600
|
-
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');
|
|
601
872
|
}
|
|
602
873
|
}
|
|
603
874
|
else {
|
|
@@ -612,219 +883,292 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
612
883
|
]);
|
|
613
884
|
}
|
|
614
885
|
finally {
|
|
615
|
-
await sendMessageAck(node);
|
|
886
|
+
await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack receipt'));
|
|
616
887
|
}
|
|
617
888
|
};
|
|
618
889
|
const handleNotification = async (node) => {
|
|
619
890
|
const remoteJid = node.attrs.from;
|
|
620
|
-
if (shouldIgnoreJid(remoteJid) && remoteJid !==
|
|
891
|
+
if (shouldIgnoreJid(remoteJid) && remoteJid !== S_WHATSAPP_NET) {
|
|
621
892
|
logger.debug({ remoteJid, id: node.attrs.id }, 'ignored notification');
|
|
622
893
|
await sendMessageAck(node);
|
|
623
894
|
return;
|
|
624
895
|
}
|
|
625
896
|
try {
|
|
626
897
|
await Promise.all([
|
|
627
|
-
|
|
628
|
-
var _a;
|
|
898
|
+
notificationMutex.mutex(async () => {
|
|
629
899
|
const msg = await processNotification(node);
|
|
630
900
|
if (msg) {
|
|
631
|
-
const fromMe =
|
|
901
|
+
const fromMe = areJidsSameUser(node.attrs.participant || remoteJid, authState.creds.me.id);
|
|
902
|
+
const { senderAlt: participantAlt, addressingMode } = extractAddressingContext(node);
|
|
632
903
|
msg.key = {
|
|
633
904
|
remoteJid,
|
|
634
905
|
fromMe,
|
|
635
906
|
participant: node.attrs.participant,
|
|
907
|
+
participantAlt,
|
|
908
|
+
addressingMode,
|
|
636
909
|
id: node.attrs.id,
|
|
637
910
|
...(msg.key || {})
|
|
638
911
|
};
|
|
639
|
-
|
|
912
|
+
msg.participant ?? (msg.participant = node.attrs.participant);
|
|
640
913
|
msg.messageTimestamp = +node.attrs.t;
|
|
641
|
-
const fullMsg =
|
|
914
|
+
const fullMsg = proto.WebMessageInfo.fromObject(msg);
|
|
642
915
|
await upsertMessage(fullMsg, 'append');
|
|
643
916
|
}
|
|
644
917
|
})
|
|
645
918
|
]);
|
|
646
919
|
}
|
|
647
920
|
finally {
|
|
648
|
-
await sendMessageAck(node);
|
|
921
|
+
await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack notification'));
|
|
649
922
|
}
|
|
650
923
|
};
|
|
651
924
|
const handleMessage = async (node) => {
|
|
652
|
-
|
|
653
|
-
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== '@s.whatsapp.net') {
|
|
925
|
+
if (shouldIgnoreJid(node.attrs.from) && node.attrs.from !== S_WHATSAPP_NET) {
|
|
654
926
|
logger.debug({ key: node.attrs.key }, 'ignored message');
|
|
655
|
-
await sendMessageAck(node);
|
|
927
|
+
await sendMessageAck(node, NACK_REASONS.UnhandledError);
|
|
656
928
|
return;
|
|
657
929
|
}
|
|
658
|
-
const encNode =
|
|
930
|
+
const encNode = getBinaryNodeChild(node, 'enc');
|
|
659
931
|
// TODO: temporary fix for crashes and issues resulting of failed msmsg decryption
|
|
660
|
-
if (encNode
|
|
932
|
+
if (encNode?.attrs.type === 'msmsg') {
|
|
661
933
|
logger.debug({ key: node.attrs.key }, 'ignored msmsg');
|
|
662
|
-
await sendMessageAck(node);
|
|
934
|
+
await sendMessageAck(node, NACK_REASONS.MissingMessageSecret);
|
|
663
935
|
return;
|
|
664
936
|
}
|
|
665
|
-
let
|
|
666
|
-
if ((0, WABinary_1.getBinaryNodeChild)(node, 'unavailable') && !encNode) {
|
|
667
|
-
await sendMessageAck(node);
|
|
668
|
-
const { key } = (0, Utils_1.decodeMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '').fullMessage;
|
|
669
|
-
response = await requestPlaceholderResend(key);
|
|
670
|
-
if (response === 'RESOLVED') {
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
logger.debug('received unavailable message, acked and requested resend from phone');
|
|
674
|
-
}
|
|
675
|
-
else {
|
|
676
|
-
if (placeholderResendCache.get(node.attrs.id)) {
|
|
677
|
-
placeholderResendCache.del(node.attrs.id);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
const { fullMessage: msg, category, author, decrypt } = (0, Utils_1.decryptMessageNode)(node, authState.creds.me.id, authState.creds.me.lid || '', signalRepository, logger);
|
|
681
|
-
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) {
|
|
682
|
-
msg.messageStubParameters = [Utils_1.NO_MESSAGE_FOUND_ERROR_TEXT, response];
|
|
683
|
-
}
|
|
684
|
-
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) {
|
|
685
|
-
ev.emit('chats.phoneNumberShare', { lid: node.attrs.from, jid: node.attrs.sender_pn });
|
|
686
|
-
}
|
|
937
|
+
let acked = false;
|
|
687
938
|
try {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
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);
|
|
978
|
+
}
|
|
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);
|
|
696
984
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
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');
|
|
700
1041
|
return;
|
|
701
1042
|
}
|
|
702
|
-
|
|
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');
|
|
703
1057
|
await sendRetryRequest(node, !encNode);
|
|
704
1058
|
if (retryRequestDelayMs) {
|
|
705
|
-
await
|
|
1059
|
+
await delay(retryRequestDelayMs);
|
|
706
1060
|
}
|
|
707
1061
|
}
|
|
708
|
-
|
|
709
|
-
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
|
+
}
|
|
710
1072
|
}
|
|
1073
|
+
acked = true;
|
|
1074
|
+
await sendMessageAck(node, NACK_REASONS.UnhandledError);
|
|
711
1075
|
});
|
|
712
1076
|
}
|
|
713
|
-
|
|
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) {
|
|
714
1084
|
// no type in the receipt => message delivered
|
|
715
1085
|
let type = undefined;
|
|
716
1086
|
let participant = msg.key.participant;
|
|
717
|
-
if (category === 'peer') {
|
|
1087
|
+
if (category === 'peer') {
|
|
1088
|
+
// special peer message
|
|
718
1089
|
type = 'peer_msg';
|
|
719
1090
|
}
|
|
720
|
-
else if (msg.key.fromMe) {
|
|
1091
|
+
else if (msg.key.fromMe) {
|
|
1092
|
+
// message was sent by us from a different device
|
|
721
1093
|
type = 'sender';
|
|
722
1094
|
// need to specially handle this case
|
|
723
|
-
if ((
|
|
724
|
-
participant = author;
|
|
1095
|
+
if (isLidUser(msg.key.remoteJid) || isLidUser(msg.key.remoteJidAlt)) {
|
|
1096
|
+
participant = author; // TODO: investigate sending receipts to LIDs and not PNs
|
|
725
1097
|
}
|
|
726
1098
|
}
|
|
727
1099
|
else if (!sendActiveReceipts) {
|
|
728
1100
|
type = 'inactive';
|
|
729
1101
|
}
|
|
1102
|
+
acked = true;
|
|
730
1103
|
await sendReceipt(msg.key.remoteJid, participant, [msg.key.id], type);
|
|
731
1104
|
// send ack for history message
|
|
732
|
-
const isAnyHistoryMsg =
|
|
1105
|
+
const isAnyHistoryMsg = getHistoryMsg(msg.message);
|
|
733
1106
|
if (isAnyHistoryMsg) {
|
|
734
|
-
const jid =
|
|
735
|
-
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
|
|
736
1109
|
}
|
|
737
1110
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
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
|
+
});
|
|
743
1120
|
}
|
|
744
1121
|
catch (error) {
|
|
745
|
-
logger.error({ error, node }, 'error in handling message');
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
var _a;
|
|
750
|
-
if (!((_a = authState.creds.me) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
751
|
-
throw new boom_1.Boom('Not authenticated');
|
|
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'));
|
|
1125
|
+
}
|
|
752
1126
|
}
|
|
753
|
-
const pdoMessage = {
|
|
754
|
-
historySyncOnDemandRequest: {
|
|
755
|
-
chatJid: oldestMsgKey.remoteJid,
|
|
756
|
-
oldestMsgFromMe: oldestMsgKey.fromMe,
|
|
757
|
-
oldestMsgId: oldestMsgKey.id,
|
|
758
|
-
oldestMsgTimestampMs: oldestMsgTimestamp,
|
|
759
|
-
onDemandMsgCount: count
|
|
760
|
-
},
|
|
761
|
-
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.HISTORY_SYNC_ON_DEMAND
|
|
762
|
-
};
|
|
763
|
-
return sendPeerDataOperationMessage(pdoMessage);
|
|
764
1127
|
};
|
|
765
|
-
const
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
1128
|
+
const handleCall = async (node) => {
|
|
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]);
|
|
773
1165
|
}
|
|
774
|
-
|
|
775
|
-
|
|
1166
|
+
catch (error) {
|
|
1167
|
+
logger.error({ error, node: binaryNodeToString(node) }, 'error in handling call');
|
|
776
1168
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
logger.debug({ messageKey }, 'message received while resend requested');
|
|
780
|
-
return 'RESOLVED';
|
|
1169
|
+
finally {
|
|
1170
|
+
await sendMessageAck(node).catch(ackErr => logger.error({ ackErr }, 'failed to ack call'));
|
|
781
1171
|
}
|
|
782
|
-
const pdoMessage = {
|
|
783
|
-
placeholderMessageResendRequest: [{
|
|
784
|
-
messageKey
|
|
785
|
-
}],
|
|
786
|
-
peerDataOperationRequestType: WAProto_1.proto.Message.PeerDataOperationRequestType.PLACEHOLDER_MESSAGE_RESEND
|
|
787
|
-
};
|
|
788
|
-
setTimeout(() => {
|
|
789
|
-
if (placeholderResendCache.get(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id)) {
|
|
790
|
-
logger.debug({ messageKey }, 'PDO message without response after 15 seconds. Phone possibly offline');
|
|
791
|
-
placeholderResendCache.del(messageKey === null || messageKey === void 0 ? void 0 : messageKey.id);
|
|
792
|
-
}
|
|
793
|
-
}, 15000);
|
|
794
|
-
return sendPeerDataOperationMessage(pdoMessage);
|
|
795
|
-
};
|
|
796
|
-
const handleCall = async (node) => {
|
|
797
|
-
const { attrs } = node;
|
|
798
|
-
const [infoChild] = (0, WABinary_1.getAllBinaryNodeChildren)(node);
|
|
799
|
-
const callId = infoChild.attrs['call-id'];
|
|
800
|
-
const from = infoChild.attrs.from || infoChild.attrs['call-creator'];
|
|
801
|
-
const status = (0, Utils_1.getCallStatusFromNode)(infoChild);
|
|
802
|
-
const call = {
|
|
803
|
-
chatId: attrs.from,
|
|
804
|
-
from,
|
|
805
|
-
id: callId,
|
|
806
|
-
date: new Date(+attrs.t * 1000),
|
|
807
|
-
offline: !!attrs.offline,
|
|
808
|
-
status,
|
|
809
|
-
};
|
|
810
|
-
if (status === 'offer') {
|
|
811
|
-
call.isVideo = !!(0, WABinary_1.getBinaryNodeChild)(infoChild, 'video');
|
|
812
|
-
call.isGroup = infoChild.attrs.type === 'group' || !!infoChild.attrs['group-jid'];
|
|
813
|
-
call.groupJid = infoChild.attrs['group-jid'];
|
|
814
|
-
callOfferCache.set(call.id, call);
|
|
815
|
-
}
|
|
816
|
-
const existingCall = callOfferCache.get(call.id);
|
|
817
|
-
// use existing call info to populate this event
|
|
818
|
-
if (existingCall) {
|
|
819
|
-
call.isVideo = existingCall.isVideo;
|
|
820
|
-
call.isGroup = existingCall.isGroup;
|
|
821
|
-
}
|
|
822
|
-
// delete data once call has ended
|
|
823
|
-
if (status === 'reject' || status === 'accept' || status === 'timeout' || status === 'terminate') {
|
|
824
|
-
callOfferCache.del(call.id);
|
|
825
|
-
}
|
|
826
|
-
ev.emit('call', [call]);
|
|
827
|
-
await sendMessageAck(node);
|
|
828
1172
|
};
|
|
829
1173
|
const handleBadAck = async ({ attrs }) => {
|
|
830
1174
|
const key = { remoteJid: attrs.from, fromMe: true, id: attrs.id };
|
|
@@ -849,13 +1193,24 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
849
1193
|
{
|
|
850
1194
|
key,
|
|
851
1195
|
update: {
|
|
852
|
-
status:
|
|
853
|
-
messageStubParameters: [
|
|
854
|
-
attrs.error
|
|
855
|
-
]
|
|
1196
|
+
status: WAMessageStatus.ERROR,
|
|
1197
|
+
messageStubParameters: [attrs.error]
|
|
856
1198
|
}
|
|
857
1199
|
}
|
|
858
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
|
+
// }
|
|
859
1214
|
}
|
|
860
1215
|
};
|
|
861
1216
|
/// processes a node with the given function
|
|
@@ -865,69 +1220,48 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
865
1220
|
await execTask();
|
|
866
1221
|
ev.flush();
|
|
867
1222
|
function execTask() {
|
|
868
|
-
return exec(node, false)
|
|
869
|
-
.catch(err => onUnexpectedError(err, identifier));
|
|
1223
|
+
return exec(node, false).catch(err => onUnexpectedError(err, identifier));
|
|
870
1224
|
}
|
|
871
1225
|
};
|
|
872
|
-
const
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
if (isProcessing) {
|
|
884
|
-
return;
|
|
885
|
-
}
|
|
886
|
-
isProcessing = true;
|
|
887
|
-
const promise = async () => {
|
|
888
|
-
while (nodes.length && ws.isOpen) {
|
|
889
|
-
const { type, node } = nodes.shift();
|
|
890
|
-
const nodeProcessor = nodeProcessorMap.get(type);
|
|
891
|
-
if (!nodeProcessor) {
|
|
892
|
-
onUnexpectedError(new Error(`unknown offline node type: ${type}`), 'processing offline node');
|
|
893
|
-
continue;
|
|
894
|
-
}
|
|
895
|
-
await nodeProcessor(node);
|
|
896
|
-
}
|
|
897
|
-
isProcessing = false;
|
|
898
|
-
};
|
|
899
|
-
promise().catch(error => onUnexpectedError(error, 'processing offline nodes'));
|
|
900
|
-
};
|
|
901
|
-
return { enqueue };
|
|
902
|
-
};
|
|
903
|
-
const offlineNodeProcessor = makeOfflineNodeProcessor();
|
|
904
|
-
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) => {
|
|
905
1237
|
const isOffline = !!node.attrs.offline;
|
|
906
1238
|
if (isOffline) {
|
|
907
1239
|
offlineNodeProcessor.enqueue(type, node);
|
|
908
1240
|
}
|
|
909
1241
|
else {
|
|
910
|
-
processNodeWithBuffer(node, identifier, exec);
|
|
1242
|
+
await processNodeWithBuffer(node, identifier, exec);
|
|
911
1243
|
}
|
|
912
1244
|
};
|
|
913
1245
|
// recv a message
|
|
914
|
-
ws.on('CB:message', (node) => {
|
|
915
|
-
processNode('message', node, 'processing message', handleMessage);
|
|
1246
|
+
ws.on('CB:message', async (node) => {
|
|
1247
|
+
await processNode('message', node, 'processing message', handleMessage);
|
|
916
1248
|
});
|
|
917
1249
|
ws.on('CB:call', async (node) => {
|
|
918
|
-
processNode('call', node, 'handling call', handleCall);
|
|
1250
|
+
await processNode('call', node, 'handling call', handleCall);
|
|
919
1251
|
});
|
|
920
|
-
ws.on('CB:receipt', node => {
|
|
921
|
-
processNode('receipt', node, 'handling receipt', handleReceipt);
|
|
1252
|
+
ws.on('CB:receipt', async (node) => {
|
|
1253
|
+
await processNode('receipt', node, 'handling receipt', handleReceipt);
|
|
922
1254
|
});
|
|
923
1255
|
ws.on('CB:notification', async (node) => {
|
|
924
|
-
processNode('notification', node, 'handling notification', handleNotification);
|
|
1256
|
+
await processNode('notification', node, 'handling notification', handleNotification);
|
|
925
1257
|
});
|
|
926
1258
|
ws.on('CB:ack,class:message', (node) => {
|
|
927
|
-
handleBadAck(node)
|
|
928
|
-
.catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
1259
|
+
handleBadAck(node).catch(error => onUnexpectedError(error, 'handling bad ack'));
|
|
929
1260
|
});
|
|
930
|
-
ev.on('call', ([call]) => {
|
|
1261
|
+
ev.on('call', async ([call]) => {
|
|
1262
|
+
if (!call) {
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
931
1265
|
// missed call + group call notification message generation
|
|
932
1266
|
if (call.status === 'timeout' || (call.status === 'offer' && call.isGroup)) {
|
|
933
1267
|
const msg = {
|
|
@@ -936,21 +1270,23 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
936
1270
|
id: call.id,
|
|
937
1271
|
fromMe: false
|
|
938
1272
|
},
|
|
939
|
-
messageTimestamp:
|
|
1273
|
+
messageTimestamp: unixTimestampSeconds(call.date)
|
|
940
1274
|
};
|
|
941
1275
|
if (call.status === 'timeout') {
|
|
942
1276
|
if (call.isGroup) {
|
|
943
|
-
msg.messageStubType = call.isVideo
|
|
1277
|
+
msg.messageStubType = call.isVideo
|
|
1278
|
+
? WAMessageStubType.CALL_MISSED_GROUP_VIDEO
|
|
1279
|
+
: WAMessageStubType.CALL_MISSED_GROUP_VOICE;
|
|
944
1280
|
}
|
|
945
1281
|
else {
|
|
946
|
-
msg.messageStubType = call.isVideo ?
|
|
1282
|
+
msg.messageStubType = call.isVideo ? WAMessageStubType.CALL_MISSED_VIDEO : WAMessageStubType.CALL_MISSED_VOICE;
|
|
947
1283
|
}
|
|
948
1284
|
}
|
|
949
1285
|
else {
|
|
950
1286
|
msg.message = { call: { callKey: Buffer.from(call.id) } };
|
|
951
1287
|
}
|
|
952
|
-
const protoMsg =
|
|
953
|
-
upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
|
|
1288
|
+
const protoMsg = proto.WebMessageInfo.fromObject(msg);
|
|
1289
|
+
await upsertMessage(protoMsg, call.offline ? 'append' : 'notify');
|
|
954
1290
|
}
|
|
955
1291
|
});
|
|
956
1292
|
ev.on('connection.update', ({ isOnline }) => {
|
|
@@ -963,10 +1299,10 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
963
1299
|
...sock,
|
|
964
1300
|
sendMessageAck,
|
|
965
1301
|
sendRetryRequest,
|
|
966
|
-
offerCall,
|
|
967
1302
|
rejectCall,
|
|
968
1303
|
fetchMessageHistory,
|
|
969
1304
|
requestPlaceholderResend,
|
|
1305
|
+
messageRetryManager
|
|
970
1306
|
};
|
|
971
1307
|
};
|
|
972
|
-
|
|
1308
|
+
//# sourceMappingURL=messages-recv.js.map
|