lordceaser-baileys 2.0.0 → 2.0.2
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/WAProto/index.js +136901 -78899
- package/WASignalGroup/GroupProtocol.js +1697 -0
- package/WASignalGroup/ciphertext_message.js +16 -0
- package/WASignalGroup/group_cipher.js +120 -0
- package/WASignalGroup/group_session_builder.js +46 -0
- package/WASignalGroup/index.js +5 -0
- package/WASignalGroup/keyhelper.js +21 -0
- package/WASignalGroup/protobufs.js +3 -0
- package/WASignalGroup/queue_job.js +69 -0
- package/WASignalGroup/sender_chain_key.js +50 -0
- package/WASignalGroup/sender_key_distribution_message.js +78 -0
- package/WASignalGroup/sender_key_message.js +92 -0
- package/WASignalGroup/sender_key_name.js +70 -0
- package/WASignalGroup/sender_key_record.js +56 -0
- package/WASignalGroup/sender_key_state.js +129 -0
- package/{lib/Signal/Group/sender-message-key.js → WASignalGroup/sender_message_key.js} +16 -3
- package/index.js +17 -0
- package/lib/Defaults/baileys-version.json +3 -0
- package/lib/Defaults/index.d.ts +15 -37
- package/lib/Defaults/index.js +60 -81
- package/lib/Signal/libsignal.d.ts +3 -5
- package/lib/Signal/libsignal.js +80 -359
- package/lib/Socket/Client/{types.d.ts → abstract-socket-client.d.ts} +5 -4
- package/lib/Socket/Client/abstract-socket-client.js +13 -0
- package/lib/Socket/Client/index.d.ts +3 -3
- package/lib/Socket/Client/index.js +19 -3
- package/lib/Socket/Client/mobile-socket-client.d.ts +13 -0
- package/lib/Socket/Client/mobile-socket-client.js +65 -0
- package/lib/Socket/Client/{websocket.d.ts → web-socket-client.d.ts} +2 -3
- package/lib/Socket/Client/web-socket-client.js +62 -0
- package/lib/Socket/business.d.ts +100 -147
- package/lib/Socket/business.js +43 -162
- package/lib/Socket/chats.d.ts +41 -85
- package/lib/Socket/chats.js +321 -569
- package/lib/Socket/groups.d.ts +57 -103
- package/lib/Socket/groups.js +84 -116
- package/lib/Socket/index.d.ts +106 -194
- package/lib/Socket/index.js +9 -11
- package/lib/Socket/messages-recv.d.ts +89 -134
- package/lib/Socket/messages-recv.js +475 -1275
- package/lib/Socket/messages-send.d.ts +97 -141
- package/lib/Socket/messages-send.js +633 -691
- package/lib/Socket/newsletter.d.ts +74 -112
- package/lib/Socket/newsletter.js +202 -147
- package/lib/Socket/registration.d.ts +264 -0
- package/lib/Socket/registration.js +166 -0
- package/lib/Socket/socket.d.ts +19 -34
- package/lib/Socket/socket.js +219 -547
- package/lib/Socket/usync.d.ts +37 -0
- package/lib/Socket/usync.js +70 -0
- package/lib/Store/index.d.ts +3 -0
- package/lib/Store/index.js +10 -0
- package/lib/Store/make-cache-manager-store.d.ts +14 -0
- package/lib/Store/make-cache-manager-store.js +83 -0
- package/lib/Store/make-in-memory-store.d.ts +118 -0
- package/lib/Store/make-in-memory-store.js +431 -0
- package/lib/Store/make-ordered-dictionary.d.ts +13 -0
- package/lib/Store/make-ordered-dictionary.js +81 -0
- package/lib/Store/object-repository.d.ts +10 -0
- package/lib/Store/object-repository.js +27 -0
- package/lib/Types/Auth.d.ts +11 -19
- package/lib/Types/Auth.js +2 -2
- package/lib/Types/Call.d.ts +1 -3
- package/lib/Types/Call.js +2 -2
- package/lib/Types/Chat.d.ts +8 -25
- package/lib/Types/Chat.js +4 -8
- package/lib/Types/Contact.d.ts +1 -8
- package/lib/Types/Contact.js +2 -2
- package/lib/Types/Events.d.ts +17 -101
- package/lib/Types/Events.js +2 -2
- package/lib/Types/GroupMetadata.d.ts +3 -18
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/Label.d.ts +0 -1
- package/lib/Types/Label.js +5 -3
- package/lib/Types/LabelAssociation.d.ts +0 -1
- package/lib/Types/LabelAssociation.js +5 -3
- package/lib/Types/Message.d.ts +204 -91
- package/lib/Types/Message.js +9 -11
- package/lib/Types/Newsletter.d.ts +92 -0
- package/lib/Types/Newsletter.js +32 -0
- package/lib/Types/Product.d.ts +1 -2
- package/lib/Types/Product.js +2 -2
- package/lib/Types/Signal.d.ts +2 -32
- package/lib/Types/Signal.js +2 -2
- package/lib/Types/Socket.d.ts +24 -44
- package/lib/Types/Socket.js +2 -3
- package/lib/Types/State.d.ts +2 -72
- package/lib/Types/State.js +2 -56
- package/lib/Types/USync.d.ts +2 -3
- package/lib/Types/USync.js +2 -2
- package/lib/Types/index.d.ts +16 -16
- package/lib/Types/index.js +31 -15
- package/lib/Utils/auth-utils.d.ts +6 -12
- package/lib/Utils/auth-utils.js +143 -239
- package/lib/Utils/baileys-event-stream.d.ts +16 -0
- package/lib/Utils/baileys-event-stream.js +63 -0
- package/lib/Utils/business.d.ts +3 -4
- package/lib/Utils/business.js +69 -66
- package/lib/Utils/c4-compat.js +0 -8
- package/lib/Utils/chat-utils.d.ts +17 -47
- package/lib/Utils/chat-utils.js +237 -364
- package/lib/Utils/crypto.d.ts +21 -18
- package/lib/Utils/crypto.js +125 -44
- package/lib/Utils/decode-wa-message.d.ts +8 -38
- package/lib/Utils/decode-wa-message.js +90 -173
- package/lib/Utils/event-buffer.d.ts +8 -9
- package/lib/Utils/event-buffer.js +71 -176
- package/lib/Utils/generics.d.ts +22 -26
- package/lib/Utils/generics.js +175 -166
- package/lib/Utils/history.d.ts +11 -16
- package/lib/Utils/history.js +53 -93
- package/lib/Utils/index.d.ts +17 -22
- package/lib/Utils/index.js +34 -22
- package/lib/Utils/link-preview.d.ts +5 -5
- package/lib/Utils/link-preview.js +24 -16
- package/lib/Utils/logger.d.ts +1 -11
- package/lib/Utils/logger.js +7 -3
- package/lib/Utils/lt-hash.d.ts +12 -8
- package/lib/Utils/lt-hash.js +46 -3
- package/lib/Utils/make-mutex.d.ts +0 -2
- package/lib/Utils/make-mutex.js +34 -24
- package/lib/Utils/messages-media.d.ts +45 -65
- package/lib/Utils/messages-media.js +358 -425
- package/lib/Utils/messages.d.ts +18 -32
- package/lib/Utils/messages.js +720 -392
- package/lib/Utils/noise-handler.d.ts +13 -13
- package/lib/Utils/noise-handler.js +108 -149
- package/lib/Utils/process-message.d.ts +11 -30
- package/lib/Utils/process-message.js +166 -423
- package/lib/Utils/signal.d.ts +6 -20
- package/lib/Utils/signal.js +65 -107
- package/lib/Utils/use-multi-file-auth-state.d.ts +1 -2
- package/lib/Utils/use-multi-file-auth-state.js +103 -57
- package/lib/Utils/use-single-file-auth-state.d.ts +12 -0
- package/lib/Utils/use-single-file-auth-state.js +76 -0
- package/lib/Utils/validate-connection.d.ts +6 -6
- package/lib/Utils/validate-connection.js +114 -119
- package/lib/WABinary/constants.d.ts +4 -5
- package/lib/WABinary/constants.js +20 -1281
- package/lib/WABinary/decode.d.ts +3 -4
- package/lib/WABinary/decode.js +53 -51
- package/lib/WABinary/encode.d.ts +1 -2
- package/lib/WABinary/encode.js +44 -12
- package/lib/WABinary/generic-utils.d.ts +6 -7
- package/lib/WABinary/generic-utils.js +43 -46
- package/lib/WABinary/index.d.ts +5 -6
- package/lib/WABinary/index.js +21 -6
- package/lib/WABinary/jid-utils.d.ts +7 -24
- package/lib/WABinary/jid-utils.js +40 -74
- package/lib/WABinary/types.d.ts +1 -2
- package/lib/WABinary/types.js +2 -2
- package/lib/WAM/BinaryInfo.d.ts +1 -2
- package/lib/WAM/BinaryInfo.js +5 -2
- package/lib/WAM/constants.d.ts +3 -5
- package/lib/WAM/constants.js +11958 -19461
- package/lib/WAM/encode.d.ts +2 -3
- package/lib/WAM/encode.js +22 -17
- package/lib/WAM/index.d.ts +3 -4
- package/lib/WAM/index.js +19 -4
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +3 -4
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +13 -33
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +2 -3
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +14 -11
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +2 -3
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +12 -9
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +2 -3
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +13 -9
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +3 -4
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +22 -20
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +3 -5
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +8 -13
- package/lib/WAUSync/Protocols/index.d.ts +4 -6
- package/lib/WAUSync/Protocols/index.js +20 -6
- package/lib/WAUSync/USyncQuery.d.ts +4 -6
- package/lib/WAUSync/USyncQuery.js +35 -44
- package/lib/WAUSync/USyncUser.d.ts +4 -11
- package/lib/WAUSync/USyncUser.js +5 -10
- package/lib/WAUSync/index.d.ts +3 -4
- package/lib/WAUSync/index.js +19 -4
- package/lib/index.js +31 -13
- package/package.json +19 -10
- package/WAProto/GenerateStatics.sh +0 -3
- package/WAProto/WAProto.proto +0 -5479
- package/WAProto/fix-imports.js +0 -85
- package/WAProto/index.d.ts +0 -14017
- package/lib/Defaults/index.d.ts.map +0 -1
- package/lib/Defaults/index.js.map +0 -1
- package/lib/Signal/Group/ciphertext-message.d.ts +0 -10
- package/lib/Signal/Group/ciphertext-message.d.ts.map +0 -1
- package/lib/Signal/Group/ciphertext-message.js +0 -12
- package/lib/Signal/Group/ciphertext-message.js.map +0 -1
- package/lib/Signal/Group/group-session-builder.d.ts +0 -15
- package/lib/Signal/Group/group-session-builder.d.ts.map +0 -1
- package/lib/Signal/Group/group-session-builder.js +0 -30
- package/lib/Signal/Group/group-session-builder.js.map +0 -1
- package/lib/Signal/Group/group_cipher.d.ts +0 -17
- package/lib/Signal/Group/group_cipher.d.ts.map +0 -1
- package/lib/Signal/Group/group_cipher.js +0 -82
- package/lib/Signal/Group/group_cipher.js.map +0 -1
- package/lib/Signal/Group/index.d.ts +0 -12
- package/lib/Signal/Group/index.d.ts.map +0 -1
- package/lib/Signal/Group/index.js +0 -12
- package/lib/Signal/Group/index.js.map +0 -1
- package/lib/Signal/Group/keyhelper.d.ts +0 -11
- package/lib/Signal/Group/keyhelper.d.ts.map +0 -1
- package/lib/Signal/Group/keyhelper.js +0 -18
- package/lib/Signal/Group/keyhelper.js.map +0 -1
- package/lib/Signal/Group/sender-chain-key.d.ts +0 -14
- package/lib/Signal/Group/sender-chain-key.d.ts.map +0 -1
- package/lib/Signal/Group/sender-chain-key.js +0 -26
- package/lib/Signal/Group/sender-chain-key.js.map +0 -1
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +0 -17
- package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-distribution-message.js +0 -63
- package/lib/Signal/Group/sender-key-distribution-message.js.map +0 -1
- package/lib/Signal/Group/sender-key-message.d.ts +0 -19
- package/lib/Signal/Group/sender-key-message.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-message.js +0 -66
- package/lib/Signal/Group/sender-key-message.js.map +0 -1
- package/lib/Signal/Group/sender-key-name.d.ts +0 -18
- package/lib/Signal/Group/sender-key-name.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-name.js +0 -48
- package/lib/Signal/Group/sender-key-name.js.map +0 -1
- package/lib/Signal/Group/sender-key-record.d.ts +0 -31
- package/lib/Signal/Group/sender-key-record.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-record.js +0 -41
- package/lib/Signal/Group/sender-key-record.js.map +0 -1
- package/lib/Signal/Group/sender-key-state.d.ts +0 -39
- package/lib/Signal/Group/sender-key-state.d.ts.map +0 -1
- package/lib/Signal/Group/sender-key-state.js +0 -84
- package/lib/Signal/Group/sender-key-state.js.map +0 -1
- package/lib/Signal/Group/sender-message-key.d.ts +0 -12
- package/lib/Signal/Group/sender-message-key.d.ts.map +0 -1
- package/lib/Signal/Group/sender-message-key.js.map +0 -1
- package/lib/Signal/libsignal.d.ts.map +0 -1
- package/lib/Signal/libsignal.js.map +0 -1
- package/lib/Signal/lid-mapping.d.ts +0 -23
- package/lib/Signal/lid-mapping.d.ts.map +0 -1
- package/lib/Signal/lid-mapping.js +0 -277
- package/lib/Signal/lid-mapping.js.map +0 -1
- package/lib/Socket/Client/index.d.ts.map +0 -1
- package/lib/Socket/Client/index.js.map +0 -1
- package/lib/Socket/Client/types.d.ts.map +0 -1
- package/lib/Socket/Client/types.js +0 -11
- package/lib/Socket/Client/types.js.map +0 -1
- package/lib/Socket/Client/websocket.d.ts.map +0 -1
- package/lib/Socket/Client/websocket.js +0 -54
- package/lib/Socket/Client/websocket.js.map +0 -1
- package/lib/Socket/business.d.ts.map +0 -1
- package/lib/Socket/business.js.map +0 -1
- package/lib/Socket/chats.d.ts.map +0 -1
- package/lib/Socket/chats.js.map +0 -1
- package/lib/Socket/communities.d.ts +0 -273
- package/lib/Socket/communities.d.ts.map +0 -1
- package/lib/Socket/communities.js +0 -431
- package/lib/Socket/communities.js.map +0 -1
- package/lib/Socket/groups.d.ts.map +0 -1
- package/lib/Socket/groups.js.map +0 -1
- package/lib/Socket/index.d.ts.map +0 -1
- package/lib/Socket/index.js.map +0 -1
- package/lib/Socket/messages-recv.d.ts.map +0 -1
- package/lib/Socket/messages-recv.js.map +0 -1
- package/lib/Socket/messages-send.d.ts.map +0 -1
- package/lib/Socket/messages-send.js.map +0 -1
- package/lib/Socket/mex.d.ts +0 -3
- package/lib/Socket/mex.d.ts.map +0 -1
- package/lib/Socket/mex.js +0 -42
- package/lib/Socket/mex.js.map +0 -1
- package/lib/Socket/newsletter.d.ts.map +0 -1
- package/lib/Socket/newsletter.js.map +0 -1
- package/lib/Socket/socket.d.ts.map +0 -1
- package/lib/Socket/socket.js.map +0 -1
- package/lib/Types/Auth.d.ts.map +0 -1
- package/lib/Types/Auth.js.map +0 -1
- package/lib/Types/Bussines.d.ts +0 -25
- package/lib/Types/Bussines.d.ts.map +0 -1
- package/lib/Types/Bussines.js +0 -2
- package/lib/Types/Bussines.js.map +0 -1
- package/lib/Types/Call.d.ts.map +0 -1
- package/lib/Types/Call.js.map +0 -1
- package/lib/Types/Chat.d.ts.map +0 -1
- package/lib/Types/Chat.js.map +0 -1
- package/lib/Types/Contact.d.ts.map +0 -1
- package/lib/Types/Contact.js.map +0 -1
- package/lib/Types/Events.d.ts.map +0 -1
- package/lib/Types/Events.js.map +0 -1
- package/lib/Types/GroupMetadata.d.ts.map +0 -1
- package/lib/Types/GroupMetadata.js.map +0 -1
- package/lib/Types/Label.d.ts.map +0 -1
- package/lib/Types/Label.js.map +0 -1
- package/lib/Types/LabelAssociation.d.ts.map +0 -1
- package/lib/Types/LabelAssociation.js.map +0 -1
- package/lib/Types/Message.d.ts.map +0 -1
- package/lib/Types/Message.js.map +0 -1
- package/lib/Types/Mex.d.ts +0 -141
- package/lib/Types/Mex.d.ts.map +0 -1
- package/lib/Types/Mex.js +0 -37
- package/lib/Types/Mex.js.map +0 -1
- package/lib/Types/Product.d.ts.map +0 -1
- package/lib/Types/Product.js.map +0 -1
- package/lib/Types/Signal.d.ts.map +0 -1
- package/lib/Types/Signal.js.map +0 -1
- package/lib/Types/Socket.d.ts.map +0 -1
- package/lib/Types/Socket.js.map +0 -1
- package/lib/Types/State.d.ts.map +0 -1
- package/lib/Types/State.js.map +0 -1
- package/lib/Types/USync.d.ts.map +0 -1
- package/lib/Types/USync.js.map +0 -1
- package/lib/Types/index.d.ts.map +0 -1
- package/lib/Types/index.js.map +0 -1
- package/lib/Utils/auth-utils.d.ts.map +0 -1
- package/lib/Utils/auth-utils.js.map +0 -1
- package/lib/Utils/browser-utils.d.ts +0 -4
- package/lib/Utils/browser-utils.d.ts.map +0 -1
- package/lib/Utils/browser-utils.js +0 -29
- package/lib/Utils/browser-utils.js.map +0 -1
- package/lib/Utils/business.d.ts.map +0 -1
- package/lib/Utils/business.js.map +0 -1
- package/lib/Utils/chat-utils.d.ts.map +0 -1
- package/lib/Utils/chat-utils.js.map +0 -1
- package/lib/Utils/companion-reg-client-utils.d.ts +0 -17
- package/lib/Utils/companion-reg-client-utils.d.ts.map +0 -1
- package/lib/Utils/companion-reg-client-utils.js +0 -35
- package/lib/Utils/companion-reg-client-utils.js.map +0 -1
- package/lib/Utils/crypto.d.ts.map +0 -1
- package/lib/Utils/crypto.js.map +0 -1
- package/lib/Utils/decode-wa-message.d.ts.map +0 -1
- package/lib/Utils/decode-wa-message.js.map +0 -1
- package/lib/Utils/event-buffer.d.ts.map +0 -1
- package/lib/Utils/event-buffer.js.map +0 -1
- package/lib/Utils/generics.d.ts.map +0 -1
- package/lib/Utils/generics.js.map +0 -1
- package/lib/Utils/history.d.ts.map +0 -1
- package/lib/Utils/history.js.map +0 -1
- package/lib/Utils/identity-change-handler.d.ts +0 -44
- package/lib/Utils/identity-change-handler.d.ts.map +0 -1
- package/lib/Utils/identity-change-handler.js +0 -50
- package/lib/Utils/identity-change-handler.js.map +0 -1
- package/lib/Utils/index.d.ts.map +0 -1
- package/lib/Utils/index.js.map +0 -1
- package/lib/Utils/link-preview.d.ts.map +0 -1
- package/lib/Utils/link-preview.js.map +0 -1
- package/lib/Utils/logger.d.ts.map +0 -1
- package/lib/Utils/logger.js.map +0 -1
- package/lib/Utils/lt-hash.d.ts.map +0 -1
- package/lib/Utils/lt-hash.js.map +0 -1
- package/lib/Utils/make-mutex.d.ts.map +0 -1
- package/lib/Utils/make-mutex.js.map +0 -1
- package/lib/Utils/message-retry-manager.d.ts +0 -115
- package/lib/Utils/message-retry-manager.d.ts.map +0 -1
- package/lib/Utils/message-retry-manager.js +0 -265
- package/lib/Utils/message-retry-manager.js.map +0 -1
- package/lib/Utils/messages-media.d.ts.map +0 -1
- package/lib/Utils/messages-media.js.map +0 -1
- package/lib/Utils/messages.d.ts.map +0 -1
- package/lib/Utils/messages.js.map +0 -1
- package/lib/Utils/noise-handler.d.ts.map +0 -1
- package/lib/Utils/noise-handler.js.map +0 -1
- package/lib/Utils/offline-node-processor.d.ts +0 -17
- package/lib/Utils/offline-node-processor.d.ts.map +0 -1
- package/lib/Utils/offline-node-processor.js +0 -40
- package/lib/Utils/offline-node-processor.js.map +0 -1
- package/lib/Utils/pre-key-manager.d.ts +0 -28
- package/lib/Utils/pre-key-manager.d.ts.map +0 -1
- package/lib/Utils/pre-key-manager.js +0 -106
- package/lib/Utils/pre-key-manager.js.map +0 -1
- package/lib/Utils/process-message.d.ts.map +0 -1
- package/lib/Utils/process-message.js.map +0 -1
- package/lib/Utils/reporting-utils.d.ts +0 -11
- package/lib/Utils/reporting-utils.d.ts.map +0 -1
- package/lib/Utils/reporting-utils.js +0 -258
- package/lib/Utils/reporting-utils.js.map +0 -1
- package/lib/Utils/signal.d.ts.map +0 -1
- package/lib/Utils/signal.js.map +0 -1
- package/lib/Utils/stanza-ack.d.ts +0 -11
- package/lib/Utils/stanza-ack.d.ts.map +0 -1
- package/lib/Utils/stanza-ack.js +0 -38
- package/lib/Utils/stanza-ack.js.map +0 -1
- package/lib/Utils/sync-action-utils.d.ts +0 -19
- package/lib/Utils/sync-action-utils.d.ts.map +0 -1
- package/lib/Utils/sync-action-utils.js +0 -49
- package/lib/Utils/sync-action-utils.js.map +0 -1
- package/lib/Utils/tc-token-utils.d.ts +0 -37
- package/lib/Utils/tc-token-utils.d.ts.map +0 -1
- package/lib/Utils/tc-token-utils.js +0 -164
- package/lib/Utils/tc-token-utils.js.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.js.map +0 -1
- package/lib/Utils/validate-connection.d.ts.map +0 -1
- package/lib/Utils/validate-connection.js.map +0 -1
- package/lib/WABinary/constants.d.ts.map +0 -1
- package/lib/WABinary/constants.js.map +0 -1
- package/lib/WABinary/decode.d.ts.map +0 -1
- package/lib/WABinary/decode.js.map +0 -1
- package/lib/WABinary/encode.d.ts.map +0 -1
- package/lib/WABinary/encode.js.map +0 -1
- package/lib/WABinary/generic-utils.d.ts.map +0 -1
- package/lib/WABinary/generic-utils.js.map +0 -1
- package/lib/WABinary/index.d.ts.map +0 -1
- package/lib/WABinary/index.js.map +0 -1
- package/lib/WABinary/jid-utils.d.ts.map +0 -1
- package/lib/WABinary/jid-utils.js.map +0 -1
- package/lib/WABinary/types.d.ts.map +0 -1
- package/lib/WABinary/types.js.map +0 -1
- package/lib/WAM/BinaryInfo.d.ts.map +0 -1
- package/lib/WAM/BinaryInfo.js.map +0 -1
- package/lib/WAM/constants.d.ts.map +0 -1
- package/lib/WAM/constants.js.map +0 -1
- package/lib/WAM/encode.d.ts.map +0 -1
- package/lib/WAM/encode.js.map +0 -1
- package/lib/WAM/index.d.ts.map +0 -1
- package/lib/WAM/index.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +0 -10
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +0 -25
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/index.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/index.js.map +0 -1
- package/lib/WAUSync/USyncQuery.d.ts.map +0 -1
- package/lib/WAUSync/USyncQuery.js.map +0 -1
- package/lib/WAUSync/USyncUser.d.ts.map +0 -1
- package/lib/WAUSync/USyncUser.js.map +0 -1
- package/lib/WAUSync/index.d.ts.map +0 -1
- package/lib/WAUSync/index.js.map +0 -1
- package/lib/index.d.ts +0 -12
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
|
@@ -1,91 +1,105 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.getStream = exports.toBuffer = exports.toReadable = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.hkdfInfoKey = void 0;
|
|
37
|
+
exports.getMediaKeys = getMediaKeys;
|
|
38
|
+
exports.getAudioDuration = getAudioDuration;
|
|
39
|
+
exports.getAudioWaveform = getAudioWaveform;
|
|
40
|
+
exports.generateThumbnail = generateThumbnail;
|
|
41
|
+
exports.extensionForMediaMessage = extensionForMediaMessage;
|
|
42
|
+
const boom_1 = require("@hapi/boom");
|
|
43
|
+
const child_process_1 = require("child_process");
|
|
44
|
+
const Crypto = __importStar(require("crypto"));
|
|
45
|
+
const events_1 = require("events");
|
|
46
|
+
const fs_1 = require("fs");
|
|
47
|
+
const os_1 = require("os");
|
|
48
|
+
const path_1 = require("path");
|
|
49
|
+
const stream_1 = require("stream");
|
|
50
|
+
const WAProto_1 = require("../../WAProto");
|
|
51
|
+
const Defaults_1 = require("../Defaults");
|
|
52
|
+
const WABinary_1 = require("../WABinary");
|
|
53
|
+
const crypto_1 = require("./crypto");
|
|
54
|
+
const generics_1 = require("./generics");
|
|
55
|
+
const getTmpFilesDirectory = () => (0, os_1.tmpdir)();
|
|
16
56
|
const getImageProcessingLibrary = async () => {
|
|
17
|
-
|
|
18
|
-
|
|
57
|
+
const [_jimp, sharp] = await Promise.all([
|
|
58
|
+
(async () => {
|
|
59
|
+
const jimp = await (import('jimp')
|
|
60
|
+
.catch(() => { }));
|
|
61
|
+
return jimp;
|
|
62
|
+
})(),
|
|
63
|
+
(async () => {
|
|
64
|
+
const sharp = await (import('sharp')
|
|
65
|
+
.catch(() => { }));
|
|
66
|
+
return sharp;
|
|
67
|
+
})()
|
|
68
|
+
]);
|
|
19
69
|
if (sharp) {
|
|
20
70
|
return { sharp };
|
|
21
71
|
}
|
|
72
|
+
const jimp = (_jimp === null || _jimp === void 0 ? void 0 : _jimp.default) || _jimp;
|
|
22
73
|
if (jimp) {
|
|
23
74
|
return { jimp };
|
|
24
75
|
}
|
|
25
|
-
throw new Boom('No image processing library available');
|
|
76
|
+
throw new boom_1.Boom('No image processing library available');
|
|
26
77
|
};
|
|
27
|
-
|
|
28
|
-
const hkdfInfo = MEDIA_HKDF_KEY_MAPPING[type];
|
|
78
|
+
const hkdfInfoKey = (type) => {
|
|
79
|
+
const hkdfInfo = Defaults_1.MEDIA_HKDF_KEY_MAPPING[type];
|
|
29
80
|
return `WhatsApp ${hkdfInfo} Keys`;
|
|
30
81
|
};
|
|
31
|
-
|
|
32
|
-
const { stream } = await getStream(media);
|
|
33
|
-
logger?.debug('got stream for raw upload');
|
|
34
|
-
const hasher = Crypto.createHash('sha256');
|
|
35
|
-
const filePath = join(tmpdir(), mediaType + generateMessageIDV2());
|
|
36
|
-
const fileWriteStream = createWriteStream(filePath);
|
|
37
|
-
let fileLength = 0;
|
|
38
|
-
try {
|
|
39
|
-
for await (const data of stream) {
|
|
40
|
-
fileLength += data.length;
|
|
41
|
-
hasher.update(data);
|
|
42
|
-
if (!fileWriteStream.write(data)) {
|
|
43
|
-
await once(fileWriteStream, 'drain');
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
fileWriteStream.end();
|
|
47
|
-
await once(fileWriteStream, 'finish');
|
|
48
|
-
stream.destroy();
|
|
49
|
-
const fileSha256 = hasher.digest();
|
|
50
|
-
logger?.debug('hashed data for raw upload');
|
|
51
|
-
return {
|
|
52
|
-
filePath: filePath,
|
|
53
|
-
fileSha256,
|
|
54
|
-
fileLength
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
fileWriteStream.destroy();
|
|
59
|
-
stream.destroy();
|
|
60
|
-
try {
|
|
61
|
-
await fs.unlink(filePath);
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
//
|
|
65
|
-
}
|
|
66
|
-
throw error;
|
|
67
|
-
}
|
|
68
|
-
};
|
|
82
|
+
exports.hkdfInfoKey = hkdfInfoKey;
|
|
69
83
|
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
|
70
|
-
|
|
84
|
+
async function getMediaKeys(buffer, mediaType) {
|
|
71
85
|
if (!buffer) {
|
|
72
|
-
throw new Boom('Cannot derive from empty media key');
|
|
86
|
+
throw new boom_1.Boom('Cannot derive from empty media key');
|
|
73
87
|
}
|
|
74
88
|
if (typeof buffer === 'string') {
|
|
75
89
|
buffer = Buffer.from(buffer.replace('data:;base64,', ''), 'base64');
|
|
76
90
|
}
|
|
77
91
|
// expand using HKDF to 112 bytes, also pass in the relevant app info
|
|
78
|
-
const expandedMediaKey = hkdf(buffer, 112, { info: hkdfInfoKey(mediaType) });
|
|
92
|
+
const expandedMediaKey = await (0, crypto_1.hkdf)(buffer, 112, { info: (0, exports.hkdfInfoKey)(mediaType) });
|
|
79
93
|
return {
|
|
80
94
|
iv: expandedMediaKey.slice(0, 16),
|
|
81
95
|
cipherKey: expandedMediaKey.slice(16, 48),
|
|
82
|
-
macKey: expandedMediaKey.slice(48, 80)
|
|
96
|
+
macKey: expandedMediaKey.slice(48, 80),
|
|
83
97
|
};
|
|
84
98
|
}
|
|
85
99
|
/** Extracts video thumb using FFMPEG */
|
|
86
100
|
const extractVideoThumb = async (path, destPath, time, size) => new Promise((resolve, reject) => {
|
|
87
101
|
const cmd = `ffmpeg -ss ${time} -i ${path} -y -vf scale=${size.width}:-1 -vframes 1 -f image2 ${destPath}`;
|
|
88
|
-
exec(cmd, err => {
|
|
102
|
+
(0, child_process_1.exec)(cmd, (err) => {
|
|
89
103
|
if (err) {
|
|
90
104
|
reject(err);
|
|
91
105
|
}
|
|
@@ -94,121 +108,118 @@ const extractVideoThumb = async (path, destPath, time, size) => new Promise((res
|
|
|
94
108
|
}
|
|
95
109
|
});
|
|
96
110
|
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
bufferOrFilePath = await toBuffer(bufferOrFilePath);
|
|
111
|
+
const extractImageThumb = async (bufferOrFilePath, width = 32) => {
|
|
112
|
+
var _a, _b;
|
|
113
|
+
if (bufferOrFilePath instanceof stream_1.Readable) {
|
|
114
|
+
bufferOrFilePath = await (0, exports.toBuffer)(bufferOrFilePath);
|
|
102
115
|
}
|
|
103
116
|
const lib = await getImageProcessingLibrary();
|
|
104
|
-
if ('sharp' in lib && typeof lib.sharp
|
|
117
|
+
if ('sharp' in lib && typeof ((_a = lib.sharp) === null || _a === void 0 ? void 0 : _a.default) === 'function') {
|
|
105
118
|
const img = lib.sharp.default(bufferOrFilePath);
|
|
106
119
|
const dimensions = await img.metadata();
|
|
107
|
-
const buffer = await img
|
|
120
|
+
const buffer = await img
|
|
121
|
+
.resize(width)
|
|
122
|
+
.jpeg({ quality: 50 })
|
|
123
|
+
.toBuffer();
|
|
108
124
|
return {
|
|
109
125
|
buffer,
|
|
110
126
|
original: {
|
|
111
127
|
width: dimensions.width,
|
|
112
|
-
height: dimensions.height
|
|
113
|
-
}
|
|
128
|
+
height: dimensions.height,
|
|
129
|
+
},
|
|
114
130
|
};
|
|
115
131
|
}
|
|
116
|
-
else if ('jimp' in lib && typeof lib.jimp
|
|
117
|
-
const
|
|
132
|
+
else if ('jimp' in lib && typeof ((_b = lib.jimp) === null || _b === void 0 ? void 0 : _b.read) === 'function') {
|
|
133
|
+
const { read, MIME_JPEG, RESIZE_BILINEAR, AUTO } = lib.jimp;
|
|
134
|
+
const jimp = await read(bufferOrFilePath);
|
|
118
135
|
const dimensions = {
|
|
119
|
-
width: jimp.
|
|
120
|
-
height: jimp.
|
|
136
|
+
width: jimp.getWidth(),
|
|
137
|
+
height: jimp.getHeight()
|
|
121
138
|
};
|
|
122
139
|
const buffer = await jimp
|
|
123
|
-
.
|
|
124
|
-
.
|
|
140
|
+
.quality(50)
|
|
141
|
+
.resize(width, AUTO, RESIZE_BILINEAR)
|
|
142
|
+
.getBufferAsync(MIME_JPEG);
|
|
125
143
|
return {
|
|
126
144
|
buffer,
|
|
127
145
|
original: dimensions
|
|
128
146
|
};
|
|
129
147
|
}
|
|
130
148
|
else {
|
|
131
|
-
throw new Boom('No image processing library available');
|
|
149
|
+
throw new boom_1.Boom('No image processing library available');
|
|
132
150
|
}
|
|
133
151
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
const lib = await getImageProcessingLibrary();
|
|
152
|
+
exports.extractImageThumb = extractImageThumb;
|
|
153
|
+
const encodeBase64EncodedStringForUpload = (b64) => (encodeURIComponent(b64
|
|
154
|
+
.replace(/\+/g, '-')
|
|
155
|
+
.replace(/\//g, '_')
|
|
156
|
+
.replace(/\=+$/, '')));
|
|
157
|
+
exports.encodeBase64EncodedStringForUpload = encodeBase64EncodedStringForUpload;
|
|
158
|
+
const generateProfilePicture = async (mediaUpload) => {
|
|
159
|
+
const bufferOrFilePath = Buffer.isBuffer(mediaUpload)
|
|
160
|
+
? mediaUpload
|
|
161
|
+
: typeof mediaUpload === 'object' && 'url' in mediaUpload
|
|
162
|
+
? mediaUpload.url.toString()
|
|
163
|
+
: await (0, exports.toBuffer)(mediaUpload.stream);
|
|
148
164
|
let img;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
else if ('jimp' in lib && typeof lib.jimp?.Jimp === 'function') {
|
|
159
|
-
const jimp = await lib.jimp.Jimp.read(buffer);
|
|
160
|
-
const min = Math.min(jimp.width, jimp.height);
|
|
161
|
-
const cropped = jimp.crop({ x: 0, y: 0, w: min, h: min });
|
|
162
|
-
img = cropped.resize({ w, h, mode: lib.jimp.ResizeStrategy.BILINEAR }).getBuffer('image/jpeg', { quality: 50 });
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
throw new Boom('No image processing library available');
|
|
166
|
-
}
|
|
165
|
+
const { read, MIME_JPEG, AUTO } = require('jimp');
|
|
166
|
+
const jimp = await read(bufferOrFilePath);
|
|
167
|
+
const min = jimp.getWidth();
|
|
168
|
+
const max = jimp.getHeight();
|
|
169
|
+
const cropped = jimp.crop(0, 0, min, max);
|
|
170
|
+
img = cropped
|
|
171
|
+
.quality(100)
|
|
172
|
+
.scaleToFit(720, 720, AUTO)
|
|
173
|
+
.getBufferAsync(MIME_JPEG);
|
|
167
174
|
return {
|
|
168
175
|
img: await img
|
|
169
176
|
};
|
|
170
177
|
};
|
|
178
|
+
exports.generateProfilePicture = generateProfilePicture;
|
|
171
179
|
/** gets the SHA256 of the given media message */
|
|
172
|
-
|
|
180
|
+
const mediaMessageSHA256B64 = (message) => {
|
|
173
181
|
const media = Object.values(message)[0];
|
|
174
|
-
return media
|
|
182
|
+
return (media === null || media === void 0 ? void 0 : media.fileSha256) && Buffer.from(media.fileSha256).toString('base64');
|
|
175
183
|
};
|
|
176
|
-
|
|
184
|
+
exports.mediaMessageSHA256B64 = mediaMessageSHA256B64;
|
|
185
|
+
async function getAudioDuration(buffer) {
|
|
177
186
|
const musicMetadata = await import('music-metadata');
|
|
178
187
|
let metadata;
|
|
179
|
-
const options = {
|
|
180
|
-
duration: true
|
|
181
|
-
};
|
|
182
188
|
if (Buffer.isBuffer(buffer)) {
|
|
183
|
-
metadata = await musicMetadata.parseBuffer(buffer, undefined,
|
|
189
|
+
metadata = await musicMetadata.parseBuffer(buffer, undefined, { duration: true });
|
|
184
190
|
}
|
|
185
191
|
else if (typeof buffer === 'string') {
|
|
186
|
-
|
|
192
|
+
const rStream = (0, fs_1.createReadStream)(buffer);
|
|
193
|
+
try {
|
|
194
|
+
metadata = await musicMetadata.parseStream(rStream, undefined, { duration: true });
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
rStream.destroy();
|
|
198
|
+
}
|
|
187
199
|
}
|
|
188
200
|
else {
|
|
189
|
-
metadata = await musicMetadata.parseStream(buffer, undefined,
|
|
201
|
+
metadata = await musicMetadata.parseStream(buffer, undefined, { duration: true });
|
|
190
202
|
}
|
|
191
203
|
return metadata.format.duration;
|
|
192
204
|
}
|
|
193
205
|
/**
|
|
194
206
|
referenced from and modifying https://github.com/wppconnect-team/wa-js/blob/main/src/chat/functions/prepareAudioWaveform.ts
|
|
195
207
|
*/
|
|
196
|
-
|
|
208
|
+
async function getAudioWaveform(buffer, logger) {
|
|
197
209
|
try {
|
|
198
|
-
|
|
199
|
-
const { default: decoder } = await import('audio-decode');
|
|
210
|
+
const audioDecode = (buffer) => import('audio-decode').then(({ default: audioDecode }) => audioDecode(buffer));
|
|
200
211
|
let audioData;
|
|
201
212
|
if (Buffer.isBuffer(buffer)) {
|
|
202
213
|
audioData = buffer;
|
|
203
214
|
}
|
|
204
215
|
else if (typeof buffer === 'string') {
|
|
205
|
-
const rStream = createReadStream(buffer);
|
|
206
|
-
audioData = await toBuffer(rStream);
|
|
216
|
+
const rStream = (0, fs_1.createReadStream)(buffer);
|
|
217
|
+
audioData = await (0, exports.toBuffer)(rStream);
|
|
207
218
|
}
|
|
208
219
|
else {
|
|
209
|
-
audioData = await toBuffer(buffer);
|
|
220
|
+
audioData = await (0, exports.toBuffer)(buffer);
|
|
210
221
|
}
|
|
211
|
-
const audioBuffer = await
|
|
222
|
+
const audioBuffer = await audioDecode(audioData);
|
|
212
223
|
const rawData = audioBuffer.getChannelData(0); // We only need to work with one channel of data
|
|
213
224
|
const samples = 64; // Number of samples we want to have in our final data set
|
|
214
225
|
const blockSize = Math.floor(rawData.length / samples); // the number of samples in each subdivision
|
|
@@ -223,22 +234,23 @@ export async function getAudioWaveform(buffer, logger) {
|
|
|
223
234
|
}
|
|
224
235
|
// This guarantees that the largest data point will be set to 1, and the rest of the data will scale proportionally.
|
|
225
236
|
const multiplier = Math.pow(Math.max(...filteredData), -1);
|
|
226
|
-
const normalizedData = filteredData.map(n => n * multiplier);
|
|
237
|
+
const normalizedData = filteredData.map((n) => n * multiplier);
|
|
227
238
|
// Generate waveform like WhatsApp
|
|
228
|
-
const waveform = new Uint8Array(normalizedData.map(n => Math.floor(100 * n)));
|
|
239
|
+
const waveform = new Uint8Array(normalizedData.map((n) => Math.floor(100 * n)));
|
|
229
240
|
return waveform;
|
|
230
241
|
}
|
|
231
242
|
catch (e) {
|
|
232
|
-
logger
|
|
243
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('Failed to generate waveform: ' + e);
|
|
233
244
|
}
|
|
234
245
|
}
|
|
235
|
-
|
|
236
|
-
const readable = new Readable({ read: () => { } });
|
|
246
|
+
const toReadable = (buffer) => {
|
|
247
|
+
const readable = new stream_1.Readable({ read: () => { } });
|
|
237
248
|
readable.push(buffer);
|
|
238
249
|
readable.push(null);
|
|
239
250
|
return readable;
|
|
240
251
|
};
|
|
241
|
-
|
|
252
|
+
exports.toReadable = toReadable;
|
|
253
|
+
const toBuffer = async (stream) => {
|
|
242
254
|
const chunks = [];
|
|
243
255
|
for await (const chunk of stream) {
|
|
244
256
|
chunks.push(chunk);
|
|
@@ -246,47 +258,45 @@ export const toBuffer = async (stream) => {
|
|
|
246
258
|
stream.destroy();
|
|
247
259
|
return Buffer.concat(chunks);
|
|
248
260
|
};
|
|
249
|
-
|
|
261
|
+
exports.toBuffer = toBuffer;
|
|
262
|
+
const getStream = async (item, opts) => {
|
|
250
263
|
if (Buffer.isBuffer(item)) {
|
|
251
|
-
return { stream: toReadable(item), type: 'buffer' };
|
|
264
|
+
return { stream: (0, exports.toReadable)(item), type: 'buffer' };
|
|
252
265
|
}
|
|
253
266
|
if ('stream' in item) {
|
|
254
267
|
return { stream: item.stream, type: 'readable' };
|
|
255
268
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const buffer = Buffer.from(urlStr.split(',')[1], 'base64');
|
|
259
|
-
return { stream: toReadable(buffer), type: 'buffer' };
|
|
269
|
+
if (item.url.toString().startsWith('http://') || item.url.toString().startsWith('https://')) {
|
|
270
|
+
return { stream: await (0, exports.getHttpStream)(item.url, opts), type: 'remote' };
|
|
260
271
|
}
|
|
261
|
-
|
|
262
|
-
return { stream: await getHttpStream(item.url, opts), type: 'remote' };
|
|
263
|
-
}
|
|
264
|
-
return { stream: createReadStream(item.url), type: 'file' };
|
|
272
|
+
return { stream: (0, fs_1.createReadStream)(item.url), type: 'file' };
|
|
265
273
|
};
|
|
274
|
+
exports.getStream = getStream;
|
|
266
275
|
/** generates a thumbnail for a given media, if required */
|
|
267
|
-
|
|
276
|
+
async function generateThumbnail(file, mediaType, options) {
|
|
277
|
+
var _a;
|
|
268
278
|
let thumbnail;
|
|
269
279
|
let originalImageDimensions;
|
|
270
280
|
if (mediaType === 'image') {
|
|
271
|
-
const { buffer, original } = await extractImageThumb(file);
|
|
281
|
+
const { buffer, original } = await (0, exports.extractImageThumb)(file);
|
|
272
282
|
thumbnail = buffer.toString('base64');
|
|
273
283
|
if (original.width && original.height) {
|
|
274
284
|
originalImageDimensions = {
|
|
275
285
|
width: original.width,
|
|
276
|
-
height: original.height
|
|
286
|
+
height: original.height,
|
|
277
287
|
};
|
|
278
288
|
}
|
|
279
289
|
}
|
|
280
290
|
else if (mediaType === 'video') {
|
|
281
|
-
const imgFilename = join(getTmpFilesDirectory(),
|
|
291
|
+
const imgFilename = (0, path_1.join)(getTmpFilesDirectory(), (0, generics_1.generateMessageID)() + '.jpg');
|
|
282
292
|
try {
|
|
283
293
|
await extractVideoThumb(file, imgFilename, '00:00:00', { width: 32, height: 32 });
|
|
284
|
-
const buff = await
|
|
294
|
+
const buff = await fs_1.promises.readFile(imgFilename);
|
|
285
295
|
thumbnail = buff.toString('base64');
|
|
286
|
-
await
|
|
296
|
+
await fs_1.promises.unlink(imgFilename);
|
|
287
297
|
}
|
|
288
298
|
catch (err) {
|
|
289
|
-
options.logger
|
|
299
|
+
(_a = options.logger) === null || _a === void 0 ? void 0 : _a.debug('could not generate video thumb: ' + err);
|
|
290
300
|
}
|
|
291
301
|
}
|
|
292
302
|
return {
|
|
@@ -294,141 +304,161 @@ export async function generateThumbnail(file, mediaType, options) {
|
|
|
294
304
|
originalImageDimensions
|
|
295
305
|
};
|
|
296
306
|
}
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
307
|
+
const getHttpStream = async (url, options = {}) => {
|
|
308
|
+
const { default: axios } = await import('axios');
|
|
309
|
+
const fetched = await axios.get(url.toString(), { ...options, responseType: 'stream' });
|
|
310
|
+
return fetched.data;
|
|
311
|
+
};
|
|
312
|
+
exports.getHttpStream = getHttpStream;
|
|
313
|
+
const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
314
|
+
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
315
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
316
|
+
let bodyPath;
|
|
317
|
+
let didSaveToTmpPath = false;
|
|
318
|
+
try {
|
|
319
|
+
const buffer = await (0, exports.toBuffer)(stream);
|
|
320
|
+
if (type === 'file') {
|
|
321
|
+
bodyPath = media.url;
|
|
322
|
+
}
|
|
323
|
+
else if (saveOriginalFileIfRequired) {
|
|
324
|
+
bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
|
|
325
|
+
(0, fs_1.writeFileSync)(bodyPath, buffer);
|
|
326
|
+
didSaveToTmpPath = true;
|
|
327
|
+
}
|
|
328
|
+
const fileLength = buffer.length;
|
|
329
|
+
const fileSha256 = Crypto.createHash('sha256').update(buffer).digest();
|
|
330
|
+
stream === null || stream === void 0 ? void 0 : stream.destroy();
|
|
331
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('prepare stream data successfully');
|
|
332
|
+
return {
|
|
333
|
+
mediaKey: undefined,
|
|
334
|
+
encWriteStream: buffer,
|
|
335
|
+
fileLength,
|
|
336
|
+
fileSha256,
|
|
337
|
+
fileEncSha256: undefined,
|
|
338
|
+
bodyPath,
|
|
339
|
+
didSaveToTmpPath
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
// destroy all streams with error
|
|
344
|
+
stream.destroy();
|
|
345
|
+
if (didSaveToTmpPath) {
|
|
346
|
+
try {
|
|
347
|
+
await fs_1.promises.unlink(bodyPath);
|
|
348
|
+
}
|
|
349
|
+
catch (err) {
|
|
350
|
+
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
throw error;
|
|
305
354
|
}
|
|
306
|
-
// @ts-ignore Node18+ Readable.fromWeb exists
|
|
307
|
-
return response.body instanceof Readable ? response.body : Readable.fromWeb(response.body);
|
|
308
355
|
};
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
356
|
+
exports.prepareStream = prepareStream;
|
|
357
|
+
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
358
|
+
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
359
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
312
360
|
const mediaKey = Crypto.randomBytes(32);
|
|
313
361
|
const { cipherKey, iv, macKey } = await getMediaKeys(mediaKey, mediaType);
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
let
|
|
317
|
-
let
|
|
318
|
-
if (
|
|
319
|
-
|
|
320
|
-
|
|
362
|
+
const encWriteStream = new stream_1.Readable({ read: () => { } });
|
|
363
|
+
let bodyPath;
|
|
364
|
+
let writeStream;
|
|
365
|
+
let didSaveToTmpPath = false;
|
|
366
|
+
if (type === 'file') {
|
|
367
|
+
bodyPath = media.url;
|
|
368
|
+
}
|
|
369
|
+
else if (saveOriginalFileIfRequired) {
|
|
370
|
+
bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
|
|
371
|
+
writeStream = (0, fs_1.createWriteStream)(bodyPath);
|
|
372
|
+
didSaveToTmpPath = true;
|
|
321
373
|
}
|
|
322
374
|
let fileLength = 0;
|
|
323
375
|
const aes = Crypto.createCipheriv('aes-256-cbc', cipherKey, iv);
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const onChunk = async (buff) => {
|
|
328
|
-
sha256Enc.update(buff);
|
|
329
|
-
hmac.update(buff);
|
|
330
|
-
// Handle backpressure: if write returns false, wait for drain
|
|
331
|
-
if (!encFileWriteStream.write(buff)) {
|
|
332
|
-
await once(encFileWriteStream, 'drain');
|
|
333
|
-
}
|
|
334
|
-
};
|
|
376
|
+
let hmac = Crypto.createHmac('sha256', macKey).update(iv);
|
|
377
|
+
let sha256Plain = Crypto.createHash('sha256');
|
|
378
|
+
let sha256Enc = Crypto.createHash('sha256');
|
|
335
379
|
try {
|
|
336
380
|
for await (const data of stream) {
|
|
337
381
|
fileLength += data.length;
|
|
338
|
-
if (type === 'remote'
|
|
339
|
-
opts
|
|
340
|
-
fileLength + data.length > opts.maxContentLength) {
|
|
341
|
-
throw new Boom(`content length exceeded when encrypting "${type}"`, {
|
|
382
|
+
if (type === 'remote'
|
|
383
|
+
&& (opts === null || opts === void 0 ? void 0 : opts.maxContentLength)
|
|
384
|
+
&& fileLength + data.length > opts.maxContentLength) {
|
|
385
|
+
throw new boom_1.Boom(`content length exceeded when encrypting "${type}"`, {
|
|
342
386
|
data: { media, type }
|
|
343
387
|
});
|
|
344
388
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
389
|
+
sha256Plain = sha256Plain.update(data);
|
|
390
|
+
if (writeStream) {
|
|
391
|
+
if (!writeStream.write(data)) {
|
|
392
|
+
await (0, events_1.once)(writeStream, 'drain');
|
|
348
393
|
}
|
|
349
394
|
}
|
|
350
|
-
|
|
351
|
-
await onChunk(aes.update(data));
|
|
395
|
+
onChunk(aes.update(data));
|
|
352
396
|
}
|
|
353
|
-
|
|
397
|
+
onChunk(aes.final());
|
|
354
398
|
const mac = hmac.digest().slice(0, 10);
|
|
355
|
-
sha256Enc.update(mac);
|
|
399
|
+
sha256Enc = sha256Enc.update(mac);
|
|
356
400
|
const fileSha256 = sha256Plain.digest();
|
|
357
401
|
const fileEncSha256 = sha256Enc.digest();
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
encFileWriteStream.end();
|
|
362
|
-
originalFileStream?.end?.();
|
|
402
|
+
encWriteStream.push(mac);
|
|
403
|
+
encWriteStream.push(null);
|
|
404
|
+
writeStream === null || writeStream === void 0 ? void 0 : writeStream.end();
|
|
363
405
|
stream.destroy();
|
|
364
|
-
|
|
365
|
-
// This helps reduce memory pressure by allowing OS to release buffers
|
|
366
|
-
await encFinishPromise;
|
|
367
|
-
await originalFinishPromise;
|
|
368
|
-
logger?.debug('encrypted data successfully');
|
|
406
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('encrypted data successfully');
|
|
369
407
|
return {
|
|
370
408
|
mediaKey,
|
|
371
|
-
|
|
372
|
-
|
|
409
|
+
encWriteStream,
|
|
410
|
+
bodyPath,
|
|
373
411
|
mac,
|
|
374
412
|
fileEncSha256,
|
|
375
413
|
fileSha256,
|
|
376
|
-
fileLength
|
|
414
|
+
fileLength,
|
|
415
|
+
didSaveToTmpPath
|
|
377
416
|
};
|
|
378
417
|
}
|
|
379
418
|
catch (error) {
|
|
380
419
|
// destroy all streams with error
|
|
381
|
-
|
|
382
|
-
|
|
420
|
+
encWriteStream.destroy();
|
|
421
|
+
writeStream === null || writeStream === void 0 ? void 0 : writeStream.destroy();
|
|
383
422
|
aes.destroy();
|
|
384
423
|
hmac.destroy();
|
|
385
424
|
sha256Plain.destroy();
|
|
386
425
|
sha256Enc.destroy();
|
|
387
426
|
stream.destroy();
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
427
|
+
if (didSaveToTmpPath) {
|
|
428
|
+
try {
|
|
429
|
+
await fs_1.promises.unlink(bodyPath);
|
|
430
|
+
}
|
|
431
|
+
catch (err) {
|
|
432
|
+
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
392
433
|
}
|
|
393
|
-
}
|
|
394
|
-
catch (err) {
|
|
395
|
-
logger?.error({ err }, 'failed deleting tmp files');
|
|
396
434
|
}
|
|
397
435
|
throw error;
|
|
398
436
|
}
|
|
437
|
+
function onChunk(buff) {
|
|
438
|
+
sha256Enc = sha256Enc.update(buff);
|
|
439
|
+
hmac = hmac.update(buff);
|
|
440
|
+
encWriteStream.push(buff);
|
|
441
|
+
}
|
|
399
442
|
};
|
|
400
|
-
|
|
443
|
+
exports.encryptedStream = encryptedStream;
|
|
444
|
+
const DEF_HOST = 'mmg.whatsapp.net';
|
|
401
445
|
const AES_CHUNK_SIZE = 16;
|
|
402
446
|
const toSmallestChunkSize = (num) => {
|
|
403
447
|
return Math.floor(num / AES_CHUNK_SIZE) * AES_CHUNK_SIZE;
|
|
404
448
|
};
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
try {
|
|
410
|
-
return new URL(url).host;
|
|
411
|
-
}
|
|
412
|
-
catch {
|
|
413
|
-
return undefined;
|
|
414
|
-
}
|
|
415
|
-
};
|
|
416
|
-
export const downloadContentFromMessage = async ({ mediaKey, directPath, url }, type, opts = {}) => {
|
|
417
|
-
// Fallback host: explicit opt > host parsed from `url` > DEF_MEDIA_HOST.
|
|
418
|
-
// Lets us honor a non-default host carried by the proto without forcing callers to thread it through.
|
|
419
|
-
const fallbackHost = opts.host ?? extractHost(url);
|
|
420
|
-
const downloadUrl = directPath ? getUrlFromDirectPath(directPath, fallbackHost) : url;
|
|
421
|
-
if (!downloadUrl) {
|
|
422
|
-
throw new Boom('No valid media URL or directPath present in message', { statusCode: 400 });
|
|
423
|
-
}
|
|
449
|
+
const getUrlFromDirectPath = (directPath) => `https://${DEF_HOST}${directPath}`;
|
|
450
|
+
exports.getUrlFromDirectPath = getUrlFromDirectPath;
|
|
451
|
+
const downloadContentFromMessage = async ({ mediaKey, directPath, url }, type, opts = {}) => {
|
|
452
|
+
const downloadUrl = url || (0, exports.getUrlFromDirectPath)(directPath);
|
|
424
453
|
const keys = await getMediaKeys(mediaKey, type);
|
|
425
|
-
return downloadEncryptedContent(downloadUrl, keys, opts);
|
|
454
|
+
return (0, exports.downloadEncryptedContent)(downloadUrl, keys, opts);
|
|
426
455
|
};
|
|
456
|
+
exports.downloadContentFromMessage = downloadContentFromMessage;
|
|
427
457
|
/**
|
|
428
458
|
* Decrypts and downloads an AES256-CBC encrypted file given the keys.
|
|
429
459
|
* Assumes the SHA256 of the plaintext is appended to the end of the ciphertext
|
|
430
460
|
* */
|
|
431
|
-
|
|
461
|
+
const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startByte, endByte, options } = {}) => {
|
|
432
462
|
let bytesFetched = 0;
|
|
433
463
|
let startChunk = 0;
|
|
434
464
|
let firstBlockIsIV = false;
|
|
@@ -442,14 +472,9 @@ export const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, {
|
|
|
442
472
|
}
|
|
443
473
|
}
|
|
444
474
|
const endChunk = endByte ? toSmallestChunkSize(endByte || 0) + AES_CHUNK_SIZE : undefined;
|
|
445
|
-
const headersInit = options?.headers ? options.headers : undefined;
|
|
446
475
|
const headers = {
|
|
447
|
-
...(
|
|
448
|
-
|
|
449
|
-
? Object.fromEntries(headersInit)
|
|
450
|
-
: headersInit
|
|
451
|
-
: {}),
|
|
452
|
-
Origin: DEFAULT_ORIGIN
|
|
476
|
+
...(options === null || options === void 0 ? void 0 : options.headers) || {},
|
|
477
|
+
Origin: Defaults_1.DEFAULT_ORIGIN,
|
|
453
478
|
};
|
|
454
479
|
if (startChunk || endChunk) {
|
|
455
480
|
headers.Range = `bytes=${startChunk}-`;
|
|
@@ -458,9 +483,11 @@ export const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, {
|
|
|
458
483
|
}
|
|
459
484
|
}
|
|
460
485
|
// download the message
|
|
461
|
-
const fetched = await getHttpStream(downloadUrl, {
|
|
462
|
-
...
|
|
463
|
-
headers
|
|
486
|
+
const fetched = await (0, exports.getHttpStream)(downloadUrl, {
|
|
487
|
+
...options || {},
|
|
488
|
+
headers,
|
|
489
|
+
maxBodyLength: Infinity,
|
|
490
|
+
maxContentLength: Infinity,
|
|
464
491
|
});
|
|
465
492
|
let remainingBytes = Buffer.from([]);
|
|
466
493
|
let aes;
|
|
@@ -475,9 +502,9 @@ export const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, {
|
|
|
475
502
|
push(bytes);
|
|
476
503
|
}
|
|
477
504
|
};
|
|
478
|
-
const output = new Transform({
|
|
505
|
+
const output = new stream_1.Transform({
|
|
479
506
|
transform(chunk, _, callback) {
|
|
480
|
-
let data =
|
|
507
|
+
let data = Buffer.concat([remainingBytes, chunk]);
|
|
481
508
|
const decryptLength = toSmallestChunkSize(data.length);
|
|
482
509
|
remainingBytes = data.slice(decryptLength);
|
|
483
510
|
data = data.slice(0, decryptLength);
|
|
@@ -510,15 +537,18 @@ export const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, {
|
|
|
510
537
|
catch (error) {
|
|
511
538
|
callback(error);
|
|
512
539
|
}
|
|
513
|
-
}
|
|
540
|
+
},
|
|
514
541
|
});
|
|
515
542
|
return fetched.pipe(output, { end: true });
|
|
516
543
|
};
|
|
517
|
-
|
|
518
|
-
|
|
544
|
+
exports.downloadEncryptedContent = downloadEncryptedContent;
|
|
545
|
+
function extensionForMediaMessage(message) {
|
|
546
|
+
const getExtension = (mimetype) => mimetype.split(';')[0].split('/')[1];
|
|
519
547
|
const type = Object.keys(message)[0];
|
|
520
548
|
let extension;
|
|
521
|
-
if (type === 'locationMessage' ||
|
|
549
|
+
if (type === 'locationMessage' ||
|
|
550
|
+
type === 'liveLocationMessage' ||
|
|
551
|
+
type === 'productMessage') {
|
|
522
552
|
extension = '.jpeg';
|
|
523
553
|
}
|
|
524
554
|
else {
|
|
@@ -527,158 +557,54 @@ export function extensionForMediaMessage(message) {
|
|
|
527
557
|
}
|
|
528
558
|
return extension;
|
|
529
559
|
}
|
|
530
|
-
const
|
|
531
|
-
return (
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
typeof globalThis.Deno === 'undefined');
|
|
535
|
-
};
|
|
536
|
-
export const uploadWithNodeHttp = async ({ url, filePath, headers, timeoutMs, agent }, redirectCount = 0) => {
|
|
537
|
-
if (redirectCount > 5) {
|
|
538
|
-
throw new Error('Too many redirects');
|
|
539
|
-
}
|
|
540
|
-
const parsedUrl = new URL(url);
|
|
541
|
-
const httpModule = parsedUrl.protocol === 'https:' ? await import('https') : await import('http');
|
|
542
|
-
// Get file size for Content-Length header (required for Node.js streaming)
|
|
543
|
-
const fileStats = await fs.stat(filePath);
|
|
544
|
-
const fileSize = fileStats.size;
|
|
545
|
-
return new Promise((resolve, reject) => {
|
|
546
|
-
const req = httpModule.request({
|
|
547
|
-
hostname: parsedUrl.hostname,
|
|
548
|
-
port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80),
|
|
549
|
-
path: parsedUrl.pathname + parsedUrl.search,
|
|
550
|
-
method: 'POST',
|
|
551
|
-
headers: {
|
|
552
|
-
...headers,
|
|
553
|
-
'Content-Length': fileSize
|
|
554
|
-
},
|
|
555
|
-
agent,
|
|
556
|
-
timeout: timeoutMs
|
|
557
|
-
}, res => {
|
|
558
|
-
// Handle redirects (3xx)
|
|
559
|
-
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
560
|
-
res.resume(); // Consume response to free resources
|
|
561
|
-
const newUrl = new URL(res.headers.location, url).toString();
|
|
562
|
-
resolve(uploadWithNodeHttp({
|
|
563
|
-
url: newUrl,
|
|
564
|
-
filePath,
|
|
565
|
-
headers,
|
|
566
|
-
timeoutMs,
|
|
567
|
-
agent
|
|
568
|
-
}, redirectCount + 1));
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
let body = '';
|
|
572
|
-
res.on('data', chunk => (body += chunk));
|
|
573
|
-
res.on('end', () => {
|
|
574
|
-
try {
|
|
575
|
-
resolve(JSON.parse(body));
|
|
576
|
-
}
|
|
577
|
-
catch {
|
|
578
|
-
resolve(undefined);
|
|
579
|
-
}
|
|
580
|
-
});
|
|
581
|
-
});
|
|
582
|
-
req.on('error', reject);
|
|
583
|
-
req.on('timeout', () => {
|
|
584
|
-
req.destroy();
|
|
585
|
-
reject(new Error('Upload timeout'));
|
|
586
|
-
});
|
|
587
|
-
const stream = createReadStream(filePath);
|
|
588
|
-
stream.pipe(req);
|
|
589
|
-
stream.on('error', err => {
|
|
590
|
-
req.destroy();
|
|
591
|
-
reject(err);
|
|
592
|
-
});
|
|
593
|
-
});
|
|
594
|
-
};
|
|
595
|
-
const uploadWithFetch = async ({ url, filePath, headers, timeoutMs, agent }) => {
|
|
596
|
-
// Convert Node.js Readable to Web ReadableStream
|
|
597
|
-
const nodeStream = createReadStream(filePath);
|
|
598
|
-
const webStream = Readable.toWeb(nodeStream);
|
|
599
|
-
// Native fetch only accepts Undici-style dispatchers, not generic https Agents.
|
|
600
|
-
const dispatcher = typeof agent?.dispatch === 'function' ? agent : undefined;
|
|
601
|
-
const response = await fetch(url, {
|
|
602
|
-
...(dispatcher ? { dispatcher } : {}),
|
|
603
|
-
method: 'POST',
|
|
604
|
-
body: webStream,
|
|
605
|
-
headers,
|
|
606
|
-
duplex: 'half',
|
|
607
|
-
signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined
|
|
608
|
-
});
|
|
609
|
-
try {
|
|
610
|
-
return (await response.json());
|
|
611
|
-
}
|
|
612
|
-
catch {
|
|
613
|
-
return undefined;
|
|
614
|
-
}
|
|
615
|
-
};
|
|
616
|
-
/**
|
|
617
|
-
* Uploads media to WhatsApp servers.
|
|
618
|
-
*
|
|
619
|
-
* ## Why we have two upload implementations:
|
|
620
|
-
*
|
|
621
|
-
* Node.js's native `fetch` (powered by undici) has a known bug where it buffers
|
|
622
|
-
* the entire request body in memory before sending, even when using streams.
|
|
623
|
-
* This causes memory issues with large files (e.g., 1GB file = 1GB+ memory usage).
|
|
624
|
-
* See: https://github.com/nodejs/undici/issues/4058
|
|
625
|
-
*
|
|
626
|
-
* Other runtimes (Bun, Deno, browsers) correctly stream the request body without
|
|
627
|
-
* buffering, so we can use the web-standard Fetch API there.
|
|
628
|
-
*
|
|
629
|
-
* ## Future considerations:
|
|
630
|
-
* Once the undici bug is fixed, we can simplify this to use only the Fetch API
|
|
631
|
-
* across all runtimes. Monitor the GitHub issue for updates.
|
|
632
|
-
*/
|
|
633
|
-
const uploadMedia = async (params, logger) => {
|
|
634
|
-
if (isNodeRuntime()) {
|
|
635
|
-
logger?.debug('Using Node.js https module for upload (avoids undici buffering bug)');
|
|
636
|
-
return uploadWithNodeHttp(params);
|
|
637
|
-
}
|
|
638
|
-
else {
|
|
639
|
-
logger?.debug('Using web-standard Fetch API for upload');
|
|
640
|
-
return uploadWithFetch(params);
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
export const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
|
|
644
|
-
return async (filePath, { mediaType, fileEncSha256B64, timeoutMs }) => {
|
|
560
|
+
const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
|
|
561
|
+
return async (stream, { mediaType, fileEncSha256B64, newsletter, timeoutMs }) => {
|
|
562
|
+
var _a, _b;
|
|
563
|
+
const { default: axios } = await import('axios');
|
|
645
564
|
// send a query JSON to obtain the url & auth token to upload our media
|
|
646
565
|
let uploadInfo = await refreshMediaConn(false);
|
|
647
566
|
let urls;
|
|
648
567
|
const hosts = [...customUploadHosts, ...uploadInfo.hosts];
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
'
|
|
660
|
-
|
|
661
|
-
}
|
|
662
|
-
for (const { hostname } of hosts) {
|
|
568
|
+
const chunks = [];
|
|
569
|
+
if (!Buffer.isBuffer(stream)) {
|
|
570
|
+
for await (const chunk of stream) {
|
|
571
|
+
chunks.push(chunk);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
const reqBody = Buffer.isBuffer(stream) ? stream : Buffer.concat(chunks);
|
|
575
|
+
fileEncSha256B64 = (0, exports.encodeBase64EncodedStringForUpload)(fileEncSha256B64);
|
|
576
|
+
let media = Defaults_1.MEDIA_PATH_MAP[mediaType];
|
|
577
|
+
if (newsletter) {
|
|
578
|
+
media = media === null || media === void 0 ? void 0 : media.replace('/mms/', '/newsletter/newsletter-');
|
|
579
|
+
}
|
|
580
|
+
for (const { hostname, maxContentLengthBytes } of hosts) {
|
|
663
581
|
logger.debug(`uploading to "${hostname}"`);
|
|
664
|
-
const auth = encodeURIComponent(uploadInfo.auth);
|
|
665
|
-
const url = `https://${hostname}${
|
|
582
|
+
const auth = encodeURIComponent(uploadInfo.auth); // the auth token
|
|
583
|
+
const url = `https://${hostname}${media}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
|
|
666
584
|
let result;
|
|
667
585
|
try {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
586
|
+
if (maxContentLengthBytes && reqBody.length > maxContentLengthBytes) {
|
|
587
|
+
throw new boom_1.Boom(`Body too large for "${hostname}"`, { statusCode: 413 });
|
|
588
|
+
}
|
|
589
|
+
const body = await axios.post(url, reqBody, {
|
|
590
|
+
...options,
|
|
591
|
+
headers: {
|
|
592
|
+
...options.headers || {},
|
|
593
|
+
'Content-Type': 'application/octet-stream',
|
|
594
|
+
'Origin': Defaults_1.DEFAULT_ORIGIN
|
|
595
|
+
},
|
|
596
|
+
httpsAgent: fetchAgent,
|
|
597
|
+
timeout: timeoutMs,
|
|
598
|
+
responseType: 'json',
|
|
599
|
+
maxBodyLength: Infinity,
|
|
600
|
+
maxContentLength: Infinity,
|
|
601
|
+
});
|
|
602
|
+
result = body.data;
|
|
603
|
+
if ((result === null || result === void 0 ? void 0 : result.url) || (result === null || result === void 0 ? void 0 : result.directPath)) {
|
|
676
604
|
urls = {
|
|
677
605
|
mediaUrl: result.url,
|
|
678
606
|
directPath: result.direct_path,
|
|
679
|
-
|
|
680
|
-
fbid: result.fbid,
|
|
681
|
-
ts: result.ts
|
|
607
|
+
handle: result.handle
|
|
682
608
|
};
|
|
683
609
|
break;
|
|
684
610
|
}
|
|
@@ -688,33 +614,37 @@ export const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, opt
|
|
|
688
614
|
}
|
|
689
615
|
}
|
|
690
616
|
catch (error) {
|
|
691
|
-
|
|
692
|
-
|
|
617
|
+
if (axios.isAxiosError(error)) {
|
|
618
|
+
result = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
619
|
+
}
|
|
620
|
+
const isLast = hostname === ((_b = hosts[uploadInfo.hosts.length - 1]) === null || _b === void 0 ? void 0 : _b.hostname);
|
|
621
|
+
logger.warn({ trace: error.stack, uploadResult: result }, `Error in uploading to ${hostname} ${isLast ? '' : ', retrying...'}`);
|
|
693
622
|
}
|
|
694
623
|
}
|
|
695
624
|
if (!urls) {
|
|
696
|
-
throw new Boom('Media upload failed on all hosts', { statusCode: 500 });
|
|
625
|
+
throw new boom_1.Boom('Media upload failed on all hosts', { statusCode: 500 });
|
|
697
626
|
}
|
|
698
627
|
return urls;
|
|
699
628
|
};
|
|
700
629
|
};
|
|
630
|
+
exports.getWAUploadToServer = getWAUploadToServer;
|
|
701
631
|
const getMediaRetryKey = (mediaKey) => {
|
|
702
|
-
return hkdf(mediaKey, 32, { info: 'WhatsApp Media Retry Notification' });
|
|
632
|
+
return (0, crypto_1.hkdf)(mediaKey, 32, { info: 'WhatsApp Media Retry Notification' });
|
|
703
633
|
};
|
|
704
634
|
/**
|
|
705
635
|
* Generate a binary node that will request the phone to re-upload the media & return the newly uploaded URL
|
|
706
636
|
*/
|
|
707
|
-
|
|
637
|
+
const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
|
|
708
638
|
const recp = { stanzaId: key.id };
|
|
709
|
-
const recpBuffer = proto.ServerErrorReceipt.encode(recp).finish();
|
|
639
|
+
const recpBuffer = WAProto_1.proto.ServerErrorReceipt.encode(recp).finish();
|
|
710
640
|
const iv = Crypto.randomBytes(12);
|
|
711
|
-
const retryKey = getMediaRetryKey(mediaKey);
|
|
712
|
-
const ciphertext = aesEncryptGCM(recpBuffer, retryKey, iv, Buffer.from(key.id));
|
|
641
|
+
const retryKey = await getMediaRetryKey(mediaKey);
|
|
642
|
+
const ciphertext = (0, crypto_1.aesEncryptGCM)(recpBuffer, retryKey, iv, Buffer.from(key.id));
|
|
713
643
|
const req = {
|
|
714
644
|
tag: 'receipt',
|
|
715
645
|
attrs: {
|
|
716
646
|
id: key.id,
|
|
717
|
-
to: jidNormalizedUser(meId),
|
|
647
|
+
to: (0, WABinary_1.jidNormalizedUser)(meId),
|
|
718
648
|
type: 'server-error'
|
|
719
649
|
},
|
|
720
650
|
content: [
|
|
@@ -733,7 +663,7 @@ export const encryptMediaRetryRequest = (key, mediaKey, meId) => {
|
|
|
733
663
|
tag: 'rmr',
|
|
734
664
|
attrs: {
|
|
735
665
|
jid: key.remoteJid,
|
|
736
|
-
from_me: (!!key.fromMe).toString(),
|
|
666
|
+
'from_me': (!!key.fromMe).toString(),
|
|
737
667
|
// @ts-ignore
|
|
738
668
|
participant: key.participant || undefined
|
|
739
669
|
}
|
|
@@ -742,8 +672,9 @@ export const encryptMediaRetryRequest = (key, mediaKey, meId) => {
|
|
|
742
672
|
};
|
|
743
673
|
return req;
|
|
744
674
|
};
|
|
745
|
-
|
|
746
|
-
|
|
675
|
+
exports.encryptMediaRetryRequest = encryptMediaRetryRequest;
|
|
676
|
+
const decodeMediaRetryNode = (node) => {
|
|
677
|
+
const rmrNode = (0, WABinary_1.getBinaryNodeChild)(node, 'rmr');
|
|
747
678
|
const event = {
|
|
748
679
|
key: {
|
|
749
680
|
id: node.attrs.id,
|
|
@@ -752,37 +683,39 @@ export const decodeMediaRetryNode = (node) => {
|
|
|
752
683
|
participant: rmrNode.attrs.participant
|
|
753
684
|
}
|
|
754
685
|
};
|
|
755
|
-
const errorNode = getBinaryNodeChild(node, 'error');
|
|
686
|
+
const errorNode = (0, WABinary_1.getBinaryNodeChild)(node, 'error');
|
|
756
687
|
if (errorNode) {
|
|
757
688
|
const errorCode = +errorNode.attrs.code;
|
|
758
|
-
event.error = new Boom(`Failed to re-upload media (${errorCode})`, {
|
|
759
|
-
data: errorNode.attrs,
|
|
760
|
-
statusCode: getStatusCodeForMediaRetry(errorCode)
|
|
761
|
-
});
|
|
689
|
+
event.error = new boom_1.Boom(`Failed to re-upload media (${errorCode})`, { data: errorNode.attrs, statusCode: (0, exports.getStatusCodeForMediaRetry)(errorCode) });
|
|
762
690
|
}
|
|
763
691
|
else {
|
|
764
|
-
const encryptedInfoNode = getBinaryNodeChild(node, 'encrypt');
|
|
765
|
-
const ciphertext = getBinaryNodeChildBuffer(encryptedInfoNode, 'enc_p');
|
|
766
|
-
const iv = getBinaryNodeChildBuffer(encryptedInfoNode, 'enc_iv');
|
|
692
|
+
const encryptedInfoNode = (0, WABinary_1.getBinaryNodeChild)(node, 'encrypt');
|
|
693
|
+
const ciphertext = (0, WABinary_1.getBinaryNodeChildBuffer)(encryptedInfoNode, 'enc_p');
|
|
694
|
+
const iv = (0, WABinary_1.getBinaryNodeChildBuffer)(encryptedInfoNode, 'enc_iv');
|
|
767
695
|
if (ciphertext && iv) {
|
|
768
696
|
event.media = { ciphertext, iv };
|
|
769
697
|
}
|
|
770
698
|
else {
|
|
771
|
-
event.error = new Boom('Failed to re-upload media (missing ciphertext)', { statusCode: 404 });
|
|
699
|
+
event.error = new boom_1.Boom('Failed to re-upload media (missing ciphertext)', { statusCode: 404 });
|
|
772
700
|
}
|
|
773
701
|
}
|
|
774
702
|
return event;
|
|
775
703
|
};
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
const
|
|
779
|
-
|
|
704
|
+
exports.decodeMediaRetryNode = decodeMediaRetryNode;
|
|
705
|
+
const decryptMediaRetryData = async ({ ciphertext, iv }, mediaKey, msgId) => {
|
|
706
|
+
const retryKey = await getMediaRetryKey(mediaKey);
|
|
707
|
+
const plaintext = (0, crypto_1.aesDecryptGCM)(ciphertext, retryKey, iv, Buffer.from(msgId));
|
|
708
|
+
return WAProto_1.proto.MediaRetryNotification.decode(plaintext);
|
|
780
709
|
};
|
|
781
|
-
|
|
710
|
+
exports.decryptMediaRetryData = decryptMediaRetryData;
|
|
711
|
+
const getStatusCodeForMediaRetry = (code) => MEDIA_RETRY_STATUS_MAP[code];
|
|
712
|
+
exports.getStatusCodeForMediaRetry = getStatusCodeForMediaRetry;
|
|
782
713
|
const MEDIA_RETRY_STATUS_MAP = {
|
|
783
|
-
[proto.MediaRetryNotification.ResultType.SUCCESS]: 200,
|
|
784
|
-
[proto.MediaRetryNotification.ResultType.DECRYPTION_ERROR]: 412,
|
|
785
|
-
[proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
|
|
786
|
-
[proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418
|
|
714
|
+
[WAProto_1.proto.MediaRetryNotification.ResultType.SUCCESS]: 200,
|
|
715
|
+
[WAProto_1.proto.MediaRetryNotification.ResultType.DECRYPTION_ERROR]: 412,
|
|
716
|
+
[WAProto_1.proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
|
|
717
|
+
[WAProto_1.proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418,
|
|
787
718
|
};
|
|
788
|
-
|
|
719
|
+
function __importStar(arg0) {
|
|
720
|
+
throw new Error('Function not implemented.');
|
|
721
|
+
}
|