@queenanya/baileys 8.6.0-beta → 9.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/GenerateStatics.sh +3 -0
- package/WAProto/WAProto.proto +4633 -0
- package/WAProto/fix-imports.js +29 -0
- package/WAProto/index.d.ts +2165 -45253
- package/WAProto/index.js +45236 -130529
- package/lib/Defaults/index.d.ts +14 -3
- package/lib/Defaults/index.d.ts.map +1 -0
- package/lib/Defaults/index.js +64 -55
- package/lib/Defaults/index.js.map +1 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +1 -0
- package/lib/Signal/Group/ciphertext-message.d.ts.map +1 -0
- package/lib/Signal/Group/ciphertext-message.js +2 -5
- package/lib/Signal/Group/ciphertext-message.js.map +1 -0
- package/lib/Signal/Group/group-session-builder.d.ts +4 -3
- package/lib/Signal/Group/group-session-builder.d.ts.map +1 -0
- package/lib/Signal/Group/group-session-builder.js +7 -41
- package/lib/Signal/Group/group-session-builder.js.map +1 -0
- package/lib/Signal/Group/group_cipher.d.ts +4 -4
- package/lib/Signal/Group/group_cipher.d.ts.map +1 -0
- package/lib/Signal/Group/group_cipher.js +37 -51
- package/lib/Signal/Group/group_cipher.js.map +1 -0
- package/lib/Signal/Group/index.d.ts +12 -11
- package/lib/Signal/Group/index.d.ts.map +1 -0
- package/lib/Signal/Group/index.js +12 -57
- package/lib/Signal/Group/index.js.map +1 -0
- package/lib/Signal/Group/keyhelper.d.ts +2 -1
- package/lib/Signal/Group/keyhelper.d.ts.map +1 -0
- package/lib/Signal/Group/keyhelper.js +7 -44
- package/lib/Signal/Group/keyhelper.js.map +1 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +3 -2
- package/lib/Signal/Group/sender-chain-key.d.ts.map +1 -0
- package/lib/Signal/Group/sender-chain-key.js +7 -15
- package/lib/Signal/Group/sender-chain-key.js.map +1 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +2 -1
- package/lib/Signal/Group/sender-key-distribution-message.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +8 -11
- package/lib/Signal/Group/sender-key-distribution-message.js.map +1 -0
- package/lib/Signal/Group/sender-key-message.d.ts +2 -1
- package/lib/Signal/Group/sender-key-message.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-message.js +9 -12
- package/lib/Signal/Group/sender-key-message.js.map +1 -0
- package/lib/Signal/Group/sender-key-name.d.ts +1 -0
- package/lib/Signal/Group/sender-key-name.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-name.js +2 -5
- package/lib/Signal/Group/sender-key-name.js.map +1 -0
- package/lib/Signal/Group/sender-key-record.d.ts +3 -2
- package/lib/Signal/Group/sender-key-record.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-record.js +9 -21
- package/lib/Signal/Group/sender-key-record.js.map +1 -0
- package/lib/Signal/Group/sender-key-state.d.ts +7 -6
- package/lib/Signal/Group/sender-key-state.d.ts.map +1 -0
- package/lib/Signal/Group/sender-key-state.js +27 -42
- package/lib/Signal/Group/sender-key-state.js.map +1 -0
- package/lib/Signal/Group/sender-message-key.d.ts +1 -0
- package/lib/Signal/Group/sender-message-key.d.ts.map +1 -0
- package/lib/Signal/Group/sender-message-key.js +4 -7
- package/lib/Signal/Group/sender-message-key.js.map +1 -0
- package/lib/Signal/libsignal.d.ts +5 -3
- package/lib/Signal/libsignal.d.ts.map +1 -0
- package/lib/Signal/libsignal.js +258 -90
- package/lib/Signal/libsignal.js.map +1 -0
- package/lib/Signal/lid-mapping.d.ts +23 -0
- package/lib/Signal/lid-mapping.d.ts.map +1 -0
- package/lib/Signal/lid-mapping.js +171 -0
- package/lib/Signal/lid-mapping.js.map +1 -0
- package/lib/Socket/Client/index.d.ts +3 -2
- package/lib/Socket/Client/index.d.ts.map +1 -0
- package/lib/Socket/Client/index.js +3 -18
- package/lib/Socket/Client/index.js.map +1 -0
- package/lib/Socket/Client/types.d.ts +2 -2
- package/lib/Socket/Client/types.d.ts.map +1 -0
- package/lib/Socket/Client/types.js +4 -6
- package/lib/Socket/Client/types.js.map +1 -0
- package/lib/Socket/Client/websocket.d.ts +2 -2
- package/lib/Socket/Client/websocket.d.ts.map +1 -0
- package/lib/Socket/Client/websocket.js +15 -37
- package/lib/Socket/Client/websocket.js.map +1 -0
- package/lib/Socket/business.d.ts +106 -94
- package/lib/Socket/business.d.ts.map +1 -0
- package/lib/Socket/business.js +159 -43
- package/lib/Socket/business.js.map +1 -0
- package/lib/Socket/chats.d.ts +39 -27
- package/lib/Socket/chats.d.ts.map +1 -0
- package/lib/Socket/chats.js +271 -261
- package/lib/Socket/chats.js.map +1 -0
- package/lib/Socket/communities.d.ts +111 -86
- package/lib/Socket/communities.d.ts.map +1 -0
- package/lib/Socket/communities.js +138 -70
- package/lib/Socket/communities.js.map +1 -0
- package/lib/Socket/groups.d.ts +53 -43
- package/lib/Socket/groups.d.ts.map +1 -0
- package/lib/Socket/groups.js +94 -99
- package/lib/Socket/groups.js.map +1 -0
- package/lib/Socket/index.d.ts +133 -108
- package/lib/Socket/index.d.ts.map +1 -0
- package/lib/Socket/index.js +17 -9
- package/lib/Socket/index.js.map +1 -0
- package/lib/Socket/messages-recv.d.ts +90 -82
- package/lib/Socket/messages-recv.d.ts.map +1 -0
- package/lib/Socket/messages-recv.js +635 -480
- package/lib/Socket/messages-recv.js.map +1 -0
- package/lib/Socket/messages-send.d.ts +90 -76
- package/lib/Socket/messages-send.d.ts.map +1 -0
- package/lib/Socket/messages-send.js +476 -402
- 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 +83 -73
- package/lib/Socket/newsletter.d.ts.map +1 -0
- package/lib/Socket/newsletter.js +181 -202
- package/lib/Socket/newsletter.js.map +1 -0
- package/lib/Socket/socket.d.ts +24 -16
- package/lib/Socket/socket.d.ts.map +1 -0
- package/lib/Socket/socket.js +402 -196
- package/lib/Socket/socket.js.map +1 -0
- package/lib/Types/Auth.d.ts +13 -5
- 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 +1 -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 +18 -9
- 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 +5 -4
- 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 +36 -33
- 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 +12 -11
- package/lib/Types/GroupMetadata.d.ts.map +1 -0
- package/lib/Types/GroupMetadata.js +2 -2
- package/lib/Types/GroupMetadata.js.map +1 -0
- package/lib/Types/Label.d.ts +12 -0
- package/lib/Types/Label.d.ts.map +1 -0
- package/lib/Types/Label.js +3 -5
- package/lib/Types/Label.js.map +1 -0
- package/lib/Types/LabelAssociation.d.ts +1 -0
- package/lib/Types/LabelAssociation.d.ts.map +1 -0
- package/lib/Types/LabelAssociation.js +3 -5
- package/lib/Types/LabelAssociation.js.map +1 -0
- package/lib/Types/Message.d.ts +51 -148
- package/lib/Types/Message.d.ts.map +1 -0
- package/lib/Types/Message.js +11 -7
- package/lib/Types/Message.js.map +1 -0
- package/lib/Types/Newsletter.d.ts +173 -71
- package/lib/Types/Newsletter.d.ts.map +1 -0
- package/lib/Types/Newsletter.js +54 -11
- 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 +34 -20
- 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 -14
- 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 +5 -4
- package/lib/Utils/auth-utils.d.ts.map +1 -0
- package/lib/Utils/auth-utils.js +199 -141
- package/lib/Utils/auth-utils.js.map +1 -0
- package/lib/Utils/baileys-event-stream.d.ts +2 -1
- package/lib/Utils/baileys-event-stream.d.ts.map +1 -0
- package/lib/Utils/baileys-event-stream.js +15 -22
- package/lib/Utils/baileys-event-stream.js.map +1 -0
- package/lib/Utils/browser-utils.d.ts +4 -0
- package/lib/Utils/browser-utils.d.ts.map +1 -0
- package/lib/Utils/browser-utils.js +28 -0
- package/lib/Utils/browser-utils.js.map +1 -0
- package/lib/Utils/business.d.ts +3 -2
- package/lib/Utils/business.d.ts.map +1 -0
- package/lib/Utils/business.js +66 -69
- package/lib/Utils/business.js.map +1 -0
- package/lib/Utils/chat-utils.d.ts +11 -11
- package/lib/Utils/chat-utils.d.ts.map +1 -0
- package/lib/Utils/chat-utils.js +203 -194
- package/lib/Utils/chat-utils.js.map +1 -0
- package/lib/Utils/crypto.d.ts +8 -7
- package/lib/Utils/crypto.d.ts.map +1 -0
- package/lib/Utils/crypto.js +50 -101
- package/lib/Utils/crypto.js.map +1 -0
- package/lib/Utils/decode-wa-message.d.ts +18 -5
- package/lib/Utils/decode-wa-message.d.ts.map +1 -0
- package/lib/Utils/decode-wa-message.js +134 -62
- package/lib/Utils/decode-wa-message.js.map +1 -0
- package/lib/Utils/event-buffer.d.ts +6 -7
- package/lib/Utils/event-buffer.d.ts.map +1 -0
- package/lib/Utils/event-buffer.js +99 -69
- package/lib/Utils/event-buffer.js.map +1 -0
- package/lib/Utils/generics.d.ts +57 -68
- package/lib/Utils/generics.d.ts.map +1 -0
- package/lib/Utils/generics.js +179 -356
- package/lib/Utils/generics.js.map +1 -0
- package/lib/Utils/history.d.ts +10 -10
- package/lib/Utils/history.d.ts.map +1 -0
- package/lib/Utils/history.js +37 -50
- package/lib/Utils/history.js.map +1 -0
- package/lib/Utils/index.d.ts +21 -17
- package/lib/Utils/index.d.ts.map +1 -0
- package/lib/Utils/index.js +21 -33
- package/lib/Utils/index.js.map +1 -0
- package/lib/Utils/link-preview.d.ts +4 -4
- package/lib/Utils/link-preview.d.ts.map +1 -0
- package/lib/Utils/link-preview.js +15 -56
- package/lib/Utils/link-preview.js.map +1 -0
- package/lib/Utils/logger.d.ts +8 -6
- 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 +9 -8
- package/lib/Utils/lt-hash.d.ts.map +1 -0
- package/lib/Utils/lt-hash.js +23 -26
- package/lib/Utils/lt-hash.js.map +1 -0
- package/lib/Utils/make-mutex.d.ts +1 -0
- package/lib/Utils/make-mutex.d.ts.map +1 -0
- package/lib/Utils/make-mutex.js +7 -10
- package/lib/Utils/make-mutex.js.map +1 -0
- package/lib/Utils/message-retry-manager.d.ts +82 -0
- package/lib/Utils/message-retry-manager.d.ts.map +1 -0
- package/lib/Utils/message-retry-manager.js +149 -0
- package/lib/Utils/message-retry-manager.js.map +1 -0
- package/lib/Utils/messages-media.d.ts +32 -38
- package/lib/Utils/messages-media.d.ts.map +1 -0
- package/lib/Utils/messages-media.js +283 -496
- package/lib/Utils/messages-media.js.map +1 -0
- package/lib/Utils/messages.d.ts +11 -10
- package/lib/Utils/messages.d.ts.map +1 -0
- package/lib/Utils/messages.js +309 -519
- package/lib/Utils/messages.js.map +1 -0
- package/lib/Utils/noise-handler.d.ts +5 -4
- package/lib/Utils/noise-handler.d.ts.map +1 -0
- package/lib/Utils/noise-handler.js +23 -26
- package/lib/Utils/noise-handler.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 +12 -12
- package/lib/Utils/process-message.d.ts.map +1 -0
- package/lib/Utils/process-message.js +196 -155
- package/lib/Utils/process-message.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 +70 -64
- package/lib/Utils/signal.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 +23 -27
- package/lib/Utils/use-multi-file-auth-state.js.map +1 -0
- package/lib/Utils/use-single-file-auth-state.d.ts +3 -2
- package/lib/Utils/use-single-file-auth-state.d.ts.map +1 -0
- package/lib/Utils/use-single-file-auth-state.js +63 -41
- package/lib/Utils/use-single-file-auth-state.js.map +1 -0
- package/lib/Utils/validate-connection.d.ts +4 -3
- package/lib/Utils/validate-connection.d.ts.map +1 -0
- package/lib/Utils/validate-connection.js +99 -77
- package/lib/Utils/validate-connection.js.map +1 -0
- package/lib/WABinary/constants.d.ts +1 -0
- package/lib/WABinary/constants.d.ts.map +1 -0
- package/lib/WABinary/constants.js +9 -11
- package/lib/WABinary/constants.js.map +1 -0
- package/lib/WABinary/decode.d.ts +2 -1
- package/lib/WABinary/decode.d.ts.map +1 -0
- package/lib/WABinary/decode.js +25 -52
- 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 +14 -48
- package/lib/WABinary/encode.js.map +1 -0
- package/lib/WABinary/generic-utils.d.ts +4 -3
- package/lib/WABinary/generic-utils.d.ts.map +1 -0
- package/lib/WABinary/generic-utils.js +31 -39
- 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 +21 -11
- package/lib/WABinary/jid-utils.d.ts.map +1 -0
- package/lib/WABinary/jid-utils.js +71 -60
- 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 +2 -1
- package/lib/WAM/encode.d.ts.map +1 -0
- package/lib/WAM/encode.js +17 -22
- package/lib/WAM/encode.js.map +1 -0
- package/lib/WAM/index.d.ts +4 -3
- package/lib/WAM/index.d.ts.map +1 -0
- package/lib/WAM/index.js +4 -19
- package/lib/WAM/index.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +4 -3
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +8 -11
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +3 -2
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +11 -14
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +3 -2
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +8 -11
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +3 -2
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +9 -13
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +4 -3
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +20 -22
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +5 -3
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +13 -8
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/index.d.ts +5 -4
- package/lib/WAUSync/Protocols/index.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/index.js +5 -20
- package/lib/WAUSync/Protocols/index.js.map +1 -0
- package/lib/WAUSync/USyncQuery.d.ts +5 -4
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -0
- package/lib/WAUSync/USyncQuery.js +40 -35
- package/lib/WAUSync/USyncQuery.js.map +1 -0
- package/lib/WAUSync/USyncUser.d.ts +6 -5
- package/lib/WAUSync/USyncUser.d.ts.map +1 -0
- package/lib/WAUSync/USyncUser.js +2 -5
- package/lib/WAUSync/USyncUser.js.map +1 -0
- package/lib/WAUSync/index.d.ts +4 -3
- package/lib/WAUSync/index.d.ts.map +1 -0
- package/lib/WAUSync/index.js +4 -19
- package/lib/WAUSync/index.js.map +1 -0
- package/lib/index.d.ts +10 -12
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +11 -34
- package/lib/index.js.map +1 -0
- package/package.json +55 -65
- package/CHANGELOG.md +0 -4
- package/README-anya.md +0 -459
- package/README-shizo.md +0 -445
- package/README-whiskey.md +0 -44
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Signal/Group/queue-job.d.ts +0 -1
- package/lib/Signal/Group/queue-job.js +0 -57
- package/lib/Socket/usync.d.ts +0 -36
- package/lib/Socket/usync.js +0 -70
- package/lib/Store/index.d.ts +0 -2
- package/lib/Store/index.js +0 -8
- package/lib/Store/make-in-memory-store.d.ts +0 -118
- package/lib/Store/make-in-memory-store.js +0 -429
- 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/WAMedia/index.d.ts +0 -2
- package/lib/WAMedia/index.js +0 -18
- package/lib/WAMedia/media-messages.d.ts +0 -18
- package/lib/WAMedia/media-messages.js +0 -102
- package/lib/WAMedia/media-set.d.ts +0 -9
- package/lib/WAMedia/media-set.js +0 -312
|
@@ -1,332 +1,180 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
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.extractVideoThumb = exports.hkdfInfoKey = void 0;
|
|
40
|
-
exports.getMediaKeys = getMediaKeys;
|
|
41
|
-
exports.uploadFile = uploadFile;
|
|
42
|
-
exports.vid2jpg = vid2jpg;
|
|
43
|
-
exports.getAudioDuration = getAudioDuration;
|
|
44
|
-
exports.getAudioWaveform = getAudioWaveform;
|
|
45
|
-
exports.generateThumbnail = generateThumbnail;
|
|
46
|
-
exports.extensionForMediaMessage = extensionForMediaMessage;
|
|
47
|
-
const boom_1 = require("@hapi/boom");
|
|
48
|
-
const axios_1 = __importDefault(require("axios"));
|
|
49
|
-
const form_data_1 = __importDefault(require("form-data"));
|
|
50
|
-
const cheerio = __importStar(require("cheerio"));
|
|
51
|
-
const Crypto = __importStar(require("crypto"));
|
|
52
|
-
const events_1 = require("events");
|
|
53
|
-
const fs_1 = require("fs");
|
|
54
|
-
const os_1 = require("os");
|
|
55
|
-
const path_1 = require("path");
|
|
56
|
-
const jimp_1 = __importDefault(require("jimp"));
|
|
57
|
-
const stream_1 = require("stream");
|
|
58
|
-
const WAProto_1 = require("../../WAProto");
|
|
59
|
-
const Defaults_1 = require("../Defaults");
|
|
60
|
-
const WABinary_1 = require("../WABinary");
|
|
61
|
-
const crypto_1 = require("./crypto");
|
|
62
|
-
const generics_1 = require("./generics");
|
|
63
|
-
const getTmpFilesDirectory = () => (0, os_1.tmpdir)();
|
|
1
|
+
import { Boom } from '@hapi/boom';
|
|
2
|
+
import { exec } from 'child_process';
|
|
3
|
+
import * as Crypto from 'crypto';
|
|
4
|
+
import { once } from 'events';
|
|
5
|
+
import { createReadStream, createWriteStream, promises as fs, WriteStream } from 'fs';
|
|
6
|
+
import { tmpdir } from 'os';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { Readable, Transform } from 'stream';
|
|
9
|
+
import { URL } from 'url';
|
|
10
|
+
import { proto } from '../../WAProto/index.js';
|
|
11
|
+
import { DEFAULT_ORIGIN, MEDIA_HKDF_KEY_MAPPING, MEDIA_PATH_MAP } from '../Defaults/index.js';
|
|
12
|
+
import { getBinaryNodeChild, getBinaryNodeChildBuffer, jidNormalizedUser } from '../WABinary/index.js';
|
|
13
|
+
import { aesDecryptGCM, aesEncryptGCM, hkdf } from './crypto.js';
|
|
14
|
+
import { generateMessageIDV2 } from './generics.js';
|
|
15
|
+
const getTmpFilesDirectory = () => tmpdir();
|
|
64
16
|
const getImageProcessingLibrary = async () => {
|
|
65
|
-
|
|
17
|
+
//@ts-ignore
|
|
18
|
+
const [jimp, sharp] = await Promise.all([import('jimp').catch(() => { }), import('sharp').catch(() => { })]);
|
|
66
19
|
if (sharp) {
|
|
67
20
|
return { sharp };
|
|
68
21
|
}
|
|
69
|
-
const jimp = (_jimp === null || _jimp === void 0 ? void 0 : _jimp.default) || _jimp;
|
|
70
22
|
if (jimp) {
|
|
71
23
|
return { jimp };
|
|
72
24
|
}
|
|
73
|
-
throw new
|
|
25
|
+
throw new Boom('No image processing library available');
|
|
74
26
|
};
|
|
75
|
-
const hkdfInfoKey = (type) => {
|
|
76
|
-
const hkdfInfo =
|
|
27
|
+
export const hkdfInfoKey = (type) => {
|
|
28
|
+
const hkdfInfo = MEDIA_HKDF_KEY_MAPPING[type];
|
|
77
29
|
return `WhatsApp ${hkdfInfo} Keys`;
|
|
78
30
|
};
|
|
79
|
-
|
|
31
|
+
export const getRawMediaUploadData = async (media, mediaType, logger) => {
|
|
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
|
+
};
|
|
80
69
|
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
|
81
|
-
async function getMediaKeys(buffer, mediaType) {
|
|
70
|
+
export async function getMediaKeys(buffer, mediaType) {
|
|
82
71
|
if (!buffer) {
|
|
83
|
-
throw new
|
|
72
|
+
throw new Boom('Cannot derive from empty media key');
|
|
84
73
|
}
|
|
85
74
|
if (typeof buffer === 'string') {
|
|
86
75
|
buffer = Buffer.from(buffer.replace('data:;base64,', ''), 'base64');
|
|
87
76
|
}
|
|
88
77
|
// expand using HKDF to 112 bytes, also pass in the relevant app info
|
|
89
|
-
const expandedMediaKey = await
|
|
78
|
+
const expandedMediaKey = await hkdf(buffer, 112, { info: hkdfInfoKey(mediaType) });
|
|
90
79
|
return {
|
|
91
80
|
iv: expandedMediaKey.slice(0, 16),
|
|
92
81
|
cipherKey: expandedMediaKey.slice(16, 48),
|
|
93
|
-
macKey: expandedMediaKey.slice(48, 80)
|
|
82
|
+
macKey: expandedMediaKey.slice(48, 80)
|
|
94
83
|
};
|
|
95
84
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const services = [
|
|
103
|
-
{
|
|
104
|
-
name: "catbox",
|
|
105
|
-
url: "https://catbox.moe/user/api.php",
|
|
106
|
-
buildForm: () => {
|
|
107
|
-
const form = new form_data_1.default();
|
|
108
|
-
form.append("fileToUpload", buffer, {
|
|
109
|
-
filename: `file.${ext}`,
|
|
110
|
-
contentType: mime || "application/octet-stream"
|
|
111
|
-
});
|
|
112
|
-
form.append("reqtype", "fileupload");
|
|
113
|
-
return form;
|
|
114
|
-
},
|
|
115
|
-
parseResponse: res => res.data
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
name: "pdi.moe",
|
|
119
|
-
url: "https://scdn.pdi.moe/upload",
|
|
120
|
-
buildForm: () => {
|
|
121
|
-
const form = new form_data_1.default();
|
|
122
|
-
form.append("file", buffer, {
|
|
123
|
-
filename: `file.${ext}`,
|
|
124
|
-
contentType: mime
|
|
125
|
-
});
|
|
126
|
-
return form;
|
|
127
|
-
},
|
|
128
|
-
parseResponse: res => res.data.result.url
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
name: "qu.ax",
|
|
132
|
-
url: "https://qu.ax/upload.php",
|
|
133
|
-
buildForm: () => {
|
|
134
|
-
const form = new form_data_1.default();
|
|
135
|
-
form.append("files[]", buffer, {
|
|
136
|
-
filename: `file.${ext}`,
|
|
137
|
-
contentType: mime || "application/octet-stream"
|
|
138
|
-
});
|
|
139
|
-
return form;
|
|
140
|
-
},
|
|
141
|
-
parseResponse: res => {
|
|
142
|
-
var _a, _b, _c;
|
|
143
|
-
if (!((_c = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.url))
|
|
144
|
-
throw new Error("Failed to get URL from qu.ax");
|
|
145
|
-
return res.data.files[0].url;
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
name: "uguu.se",
|
|
150
|
-
url: "https://uguu.se/upload.php",
|
|
151
|
-
buildForm: () => {
|
|
152
|
-
const form = new form_data_1.default();
|
|
153
|
-
form.append("files[]", buffer, {
|
|
154
|
-
filename: `file.${ext}`,
|
|
155
|
-
contentType: mime || "application/octet-stream"
|
|
156
|
-
});
|
|
157
|
-
return form;
|
|
158
|
-
},
|
|
159
|
-
parseResponse: res => {
|
|
160
|
-
var _a, _b, _c;
|
|
161
|
-
if (!((_c = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.url))
|
|
162
|
-
throw new Error("Failed to get URL from uguu.se");
|
|
163
|
-
return res.data.files[0].url;
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
name: "tmpfiles",
|
|
168
|
-
url: "https://tmpfiles.org/api/v1/upload",
|
|
169
|
-
buildForm: () => {
|
|
170
|
-
const form = new form_data_1.default();
|
|
171
|
-
form.append("file", buffer, {
|
|
172
|
-
filename: `file.${ext}`,
|
|
173
|
-
contentType: mime
|
|
174
|
-
});
|
|
175
|
-
return form;
|
|
176
|
-
},
|
|
177
|
-
parseResponse: res => {
|
|
178
|
-
const match = res.data.data.url.match(/https:\/\/tmpfiles\.org\/(.*)/);
|
|
179
|
-
if (!match)
|
|
180
|
-
throw new Error("Failed to parse tmpfiles URL.");
|
|
181
|
-
return `https://tmpfiles.org/dl/${match[1]}`;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
];
|
|
185
|
-
for (const service of services) {
|
|
186
|
-
try {
|
|
187
|
-
const form = service.buildForm();
|
|
188
|
-
const res = await axios_1.default.post(service.url, form, {
|
|
189
|
-
headers: form.getHeaders()
|
|
190
|
-
});
|
|
191
|
-
const url = service.parseResponse(res);
|
|
192
|
-
return url;
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
logger === null || logger === void 0 ? void 0 : logger.debug(`[${service.name}] eror:`, (error === null || error === void 0 ? void 0 : error.message) || error);
|
|
85
|
+
/** Extracts video thumb using FFMPEG */
|
|
86
|
+
const extractVideoThumb = async (path, destPath, time, size) => new Promise((resolve, reject) => {
|
|
87
|
+
const cmd = `ffmpeg -ss ${time} -i ${path} -y -vf scale=${size.width}:-1 -vframes 1 -f image2 ${destPath}`;
|
|
88
|
+
exec(cmd, err => {
|
|
89
|
+
if (err) {
|
|
90
|
+
reject(err);
|
|
196
91
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
async function vid2jpg(videoUrl) {
|
|
201
|
-
try {
|
|
202
|
-
const { data } = await axios_1.default.get(`https://ezgif.com/video-to-jpg?url=${encodeURIComponent(videoUrl)}`);
|
|
203
|
-
const $ = cheerio.load(data);
|
|
204
|
-
const fileToken = $('input[name="file"]').attr("value");
|
|
205
|
-
if (!fileToken) {
|
|
206
|
-
throw new Error("Failed to retrieve file token. The video URL may be invalid or inaccessible.");
|
|
207
|
-
}
|
|
208
|
-
const formData = new URLSearchParams();
|
|
209
|
-
formData.append("file", fileToken);
|
|
210
|
-
formData.append("end", "1");
|
|
211
|
-
formData.append("video-to-jpg", "Convert to JPG!");
|
|
212
|
-
const convert = await axios_1.default.post(`https://ezgif.com/video-to-jpg/${fileToken}`, formData);
|
|
213
|
-
const $2 = cheerio.load(convert.data);
|
|
214
|
-
let imageUrl = $2("#output img").first().attr("src");
|
|
215
|
-
if (!imageUrl) {
|
|
216
|
-
throw new Error("Could not locate the converted image output.");
|
|
217
|
-
}
|
|
218
|
-
if (imageUrl.startsWith("//")) {
|
|
219
|
-
imageUrl = "https:" + imageUrl;
|
|
220
|
-
}
|
|
221
|
-
else if (imageUrl.startsWith("/")) {
|
|
222
|
-
const cdnMatch = imageUrl.match(/\/(s\d+\..+?)\/.*/);
|
|
223
|
-
if (cdnMatch) {
|
|
224
|
-
imageUrl = "https://" + imageUrl.slice(2);
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
imageUrl = "https://ezgif.com" + imageUrl;
|
|
228
|
-
}
|
|
92
|
+
else {
|
|
93
|
+
resolve();
|
|
229
94
|
}
|
|
230
|
-
return imageUrl;
|
|
231
|
-
}
|
|
232
|
-
catch (error) {
|
|
233
|
-
throw new Error("Failed to convert video to JPG: " + error.message);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Originally written by Techwiz (https://github.com/techwiz37)
|
|
238
|
-
* Modified for customization and improvements
|
|
239
|
-
*/
|
|
240
|
-
const extractVideoThumb = async (videoPath) => {
|
|
241
|
-
const videoBuffer = await fs_1.promises.readFile(videoPath);
|
|
242
|
-
const dataUrl = await uploadFile(videoBuffer);
|
|
243
|
-
if (!dataUrl || typeof dataUrl !== 'string') {
|
|
244
|
-
throw new Error('Failed to upload video: Invalid or missing URL');
|
|
245
|
-
}
|
|
246
|
-
const jpgUrl = await vid2jpg(dataUrl);
|
|
247
|
-
const { data: imageBuffer } = await axios_1.default.get(jpgUrl, {
|
|
248
|
-
responseType: 'arraybuffer',
|
|
249
95
|
});
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
bufferOrFilePath = await (0, exports.toBuffer)(bufferOrFilePath);
|
|
96
|
+
});
|
|
97
|
+
export const extractImageThumb = async (bufferOrFilePath, width = 32) => {
|
|
98
|
+
// TODO: Move entirely to sharp, removing jimp as it supports readable streams
|
|
99
|
+
// This will have positive speed and performance impacts as well as minimizing RAM usage.
|
|
100
|
+
if (bufferOrFilePath instanceof Readable) {
|
|
101
|
+
bufferOrFilePath = await toBuffer(bufferOrFilePath);
|
|
257
102
|
}
|
|
258
103
|
const lib = await getImageProcessingLibrary();
|
|
259
|
-
if ('sharp' in lib && typeof
|
|
104
|
+
if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
|
|
260
105
|
const img = lib.sharp.default(bufferOrFilePath);
|
|
261
106
|
const dimensions = await img.metadata();
|
|
262
|
-
const buffer = await img
|
|
263
|
-
.resize(width)
|
|
264
|
-
.jpeg({ quality: 50 })
|
|
265
|
-
.toBuffer();
|
|
107
|
+
const buffer = await img.resize(width).jpeg({ quality: 50 }).toBuffer();
|
|
266
108
|
return {
|
|
267
109
|
buffer,
|
|
268
110
|
original: {
|
|
269
111
|
width: dimensions.width,
|
|
270
|
-
height: dimensions.height
|
|
271
|
-
}
|
|
112
|
+
height: dimensions.height
|
|
113
|
+
}
|
|
272
114
|
};
|
|
273
115
|
}
|
|
274
|
-
else if ('jimp' in lib && typeof
|
|
275
|
-
const
|
|
276
|
-
const jimp = await read(bufferOrFilePath);
|
|
116
|
+
else if ('jimp' in lib && typeof lib.jimp?.Jimp === 'object') {
|
|
117
|
+
const jimp = await lib.jimp.Jimp.read(bufferOrFilePath);
|
|
277
118
|
const dimensions = {
|
|
278
|
-
width: jimp.
|
|
279
|
-
height: jimp.
|
|
119
|
+
width: jimp.width,
|
|
120
|
+
height: jimp.height
|
|
280
121
|
};
|
|
281
122
|
const buffer = await jimp
|
|
282
|
-
.
|
|
283
|
-
.
|
|
284
|
-
.getBufferAsync(MIME_JPEG);
|
|
123
|
+
.resize({ w: width, mode: lib.jimp.ResizeStrategy.BILINEAR })
|
|
124
|
+
.getBuffer('image/jpeg', { quality: 50 });
|
|
285
125
|
return {
|
|
286
126
|
buffer,
|
|
287
127
|
original: dimensions
|
|
288
128
|
};
|
|
289
129
|
}
|
|
290
130
|
else {
|
|
291
|
-
throw new
|
|
131
|
+
throw new Boom('No image processing library available');
|
|
292
132
|
}
|
|
293
133
|
};
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
.replace(/\=+$/, '')));
|
|
299
|
-
exports.encodeBase64EncodedStringForUpload = encodeBase64EncodedStringForUpload;
|
|
300
|
-
const generateProfilePicture = async (mediaUpload) => {
|
|
301
|
-
let bufferOrFilePath;
|
|
302
|
-
let img;
|
|
134
|
+
export const encodeBase64EncodedStringForUpload = (b64) => encodeURIComponent(b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, ''));
|
|
135
|
+
export const generateProfilePicture = async (mediaUpload, dimensions) => {
|
|
136
|
+
let buffer;
|
|
137
|
+
const { width: w = 640, height: h = 640 } = dimensions || {};
|
|
303
138
|
if (Buffer.isBuffer(mediaUpload)) {
|
|
304
|
-
|
|
139
|
+
buffer = mediaUpload;
|
|
305
140
|
}
|
|
306
|
-
else
|
|
307
|
-
|
|
141
|
+
else {
|
|
142
|
+
// Use getStream to handle all WAMediaUpload types (Buffer, Stream, URL)
|
|
143
|
+
const { stream } = await getStream(mediaUpload);
|
|
144
|
+
// Convert the resulting stream to a buffer
|
|
145
|
+
buffer = await toBuffer(stream);
|
|
146
|
+
}
|
|
147
|
+
const lib = await getImageProcessingLibrary();
|
|
148
|
+
let img;
|
|
149
|
+
if ('sharp' in lib && typeof lib.sharp?.default === 'function') {
|
|
150
|
+
img = lib.sharp
|
|
151
|
+
.default(buffer)
|
|
152
|
+
.resize(w, h)
|
|
153
|
+
.jpeg({
|
|
154
|
+
quality: 50
|
|
155
|
+
})
|
|
156
|
+
.toBuffer();
|
|
157
|
+
}
|
|
158
|
+
else if ('jimp' in lib && typeof lib.jimp?.Jimp === 'object') {
|
|
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 });
|
|
308
163
|
}
|
|
309
164
|
else {
|
|
310
|
-
|
|
165
|
+
throw new Boom('No image processing library available');
|
|
311
166
|
}
|
|
312
|
-
const jimp = await jimp_1.default.read(bufferOrFilePath);
|
|
313
|
-
const cropped = jimp.getWidth() > jimp.getHeight() ? jimp.resize(550, -1) : jimp.resize(-1, 650);
|
|
314
|
-
img = cropped
|
|
315
|
-
.quality(100)
|
|
316
|
-
.getBufferAsync(jimp_1.default.MIME_JPEG);
|
|
317
167
|
return {
|
|
318
|
-
img: await img
|
|
168
|
+
img: await img
|
|
319
169
|
};
|
|
320
170
|
};
|
|
321
|
-
exports.generateProfilePicture = generateProfilePicture;
|
|
322
171
|
/** gets the SHA256 of the given media message */
|
|
323
|
-
const mediaMessageSHA256B64 = (message) => {
|
|
172
|
+
export const mediaMessageSHA256B64 = (message) => {
|
|
324
173
|
const media = Object.values(message)[0];
|
|
325
|
-
return
|
|
174
|
+
return media?.fileSha256 && Buffer.from(media.fileSha256).toString('base64');
|
|
326
175
|
};
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
const musicMetadata = await Promise.resolve().then(() => __importStar(require('music-metadata')));
|
|
176
|
+
export async function getAudioDuration(buffer) {
|
|
177
|
+
const musicMetadata = await import('music-metadata');
|
|
330
178
|
let metadata;
|
|
331
179
|
const options = {
|
|
332
180
|
duration: true
|
|
@@ -345,19 +193,20 @@ async function getAudioDuration(buffer) {
|
|
|
345
193
|
/**
|
|
346
194
|
referenced from and modifying https://github.com/wppconnect-team/wa-js/blob/main/src/chat/functions/prepareAudioWaveform.ts
|
|
347
195
|
*/
|
|
348
|
-
async function getAudioWaveform(buffer, logger) {
|
|
196
|
+
export async function getAudioWaveform(buffer, logger) {
|
|
349
197
|
try {
|
|
350
|
-
|
|
198
|
+
// @ts-ignore
|
|
199
|
+
const { default: decoder } = await import('audio-decode');
|
|
351
200
|
let audioData;
|
|
352
201
|
if (Buffer.isBuffer(buffer)) {
|
|
353
202
|
audioData = buffer;
|
|
354
203
|
}
|
|
355
204
|
else if (typeof buffer === 'string') {
|
|
356
|
-
const rStream =
|
|
357
|
-
audioData = await
|
|
205
|
+
const rStream = createReadStream(buffer);
|
|
206
|
+
audioData = await toBuffer(rStream);
|
|
358
207
|
}
|
|
359
208
|
else {
|
|
360
|
-
audioData = await
|
|
209
|
+
audioData = await toBuffer(buffer);
|
|
361
210
|
}
|
|
362
211
|
const audioBuffer = await decoder(audioData);
|
|
363
212
|
const rawData = audioBuffer.getChannelData(0); // We only need to work with one channel of data
|
|
@@ -374,23 +223,22 @@ async function getAudioWaveform(buffer, logger) {
|
|
|
374
223
|
}
|
|
375
224
|
// This guarantees that the largest data point will be set to 1, and the rest of the data will scale proportionally.
|
|
376
225
|
const multiplier = Math.pow(Math.max(...filteredData), -1);
|
|
377
|
-
const normalizedData = filteredData.map(
|
|
226
|
+
const normalizedData = filteredData.map(n => n * multiplier);
|
|
378
227
|
// Generate waveform like WhatsApp
|
|
379
|
-
const waveform = new Uint8Array(normalizedData.map(
|
|
228
|
+
const waveform = new Uint8Array(normalizedData.map(n => Math.floor(100 * n)));
|
|
380
229
|
return waveform;
|
|
381
230
|
}
|
|
382
231
|
catch (e) {
|
|
383
|
-
logger
|
|
232
|
+
logger?.debug('Failed to generate waveform: ' + e);
|
|
384
233
|
}
|
|
385
234
|
}
|
|
386
|
-
const toReadable = (buffer) => {
|
|
387
|
-
const readable = new
|
|
235
|
+
export const toReadable = (buffer) => {
|
|
236
|
+
const readable = new Readable({ read: () => { } });
|
|
388
237
|
readable.push(buffer);
|
|
389
238
|
readable.push(null);
|
|
390
239
|
return readable;
|
|
391
240
|
};
|
|
392
|
-
|
|
393
|
-
const toBuffer = async (stream) => {
|
|
241
|
+
export const toBuffer = async (stream) => {
|
|
394
242
|
const chunks = [];
|
|
395
243
|
for await (const chunk of stream) {
|
|
396
244
|
chunks.push(chunk);
|
|
@@ -398,10 +246,9 @@ const toBuffer = async (stream) => {
|
|
|
398
246
|
stream.destroy();
|
|
399
247
|
return Buffer.concat(chunks);
|
|
400
248
|
};
|
|
401
|
-
|
|
402
|
-
const getStream = async (item, opts) => {
|
|
249
|
+
export const getStream = async (item, opts) => {
|
|
403
250
|
if (Buffer.isBuffer(item)) {
|
|
404
|
-
return { stream:
|
|
251
|
+
return { stream: toReadable(item), type: 'buffer' };
|
|
405
252
|
}
|
|
406
253
|
if ('stream' in item) {
|
|
407
254
|
return { stream: item.stream, type: 'readable' };
|
|
@@ -409,46 +256,37 @@ const getStream = async (item, opts) => {
|
|
|
409
256
|
const urlStr = item.url.toString();
|
|
410
257
|
if (urlStr.startsWith('data:')) {
|
|
411
258
|
const buffer = Buffer.from(urlStr.split(',')[1], 'base64');
|
|
412
|
-
return { stream:
|
|
259
|
+
return { stream: toReadable(buffer), type: 'buffer' };
|
|
413
260
|
}
|
|
414
261
|
if (urlStr.startsWith('http://') || urlStr.startsWith('https://')) {
|
|
415
|
-
return { stream: await
|
|
262
|
+
return { stream: await getHttpStream(item.url, opts), type: 'remote' };
|
|
416
263
|
}
|
|
417
|
-
return { stream:
|
|
264
|
+
return { stream: createReadStream(item.url), type: 'file' };
|
|
418
265
|
};
|
|
419
|
-
exports.getStream = getStream;
|
|
420
266
|
/** generates a thumbnail for a given media, if required */
|
|
421
|
-
async function generateThumbnail(file, mediaType, options) {
|
|
422
|
-
var _a;
|
|
267
|
+
export async function generateThumbnail(file, mediaType, options) {
|
|
423
268
|
let thumbnail;
|
|
424
269
|
let originalImageDimensions;
|
|
425
270
|
if (mediaType === 'image') {
|
|
426
|
-
const { buffer, original } = await
|
|
271
|
+
const { buffer, original } = await extractImageThumb(file);
|
|
427
272
|
thumbnail = buffer.toString('base64');
|
|
428
273
|
if (original.width && original.height) {
|
|
429
274
|
originalImageDimensions = {
|
|
430
275
|
width: original.width,
|
|
431
|
-
height: original.height
|
|
276
|
+
height: original.height
|
|
432
277
|
};
|
|
433
278
|
}
|
|
434
279
|
}
|
|
435
280
|
else if (mediaType === 'video') {
|
|
281
|
+
const imgFilename = join(getTmpFilesDirectory(), generateMessageIDV2() + '.jpg');
|
|
436
282
|
try {
|
|
437
|
-
|
|
438
|
-
const
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
thumbnail = processedThumbnailBuffer.toString('base64');
|
|
442
|
-
if (original.width && original.height) {
|
|
443
|
-
originalImageDimensions = {
|
|
444
|
-
width: original.width,
|
|
445
|
-
height: original.height,
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
await fs_1.promises.unlink(imgFilename);
|
|
283
|
+
await extractVideoThumb(file, imgFilename, '00:00:00', { width: 32, height: 32 });
|
|
284
|
+
const buff = await fs.readFile(imgFilename);
|
|
285
|
+
thumbnail = buff.toString('base64');
|
|
286
|
+
await fs.unlink(imgFilename);
|
|
449
287
|
}
|
|
450
288
|
catch (err) {
|
|
451
|
-
|
|
289
|
+
options.logger?.debug('could not generate video thumb: ' + err);
|
|
452
290
|
}
|
|
453
291
|
}
|
|
454
292
|
return {
|
|
@@ -456,164 +294,120 @@ async function generateThumbnail(file, mediaType, options) {
|
|
|
456
294
|
originalImageDimensions
|
|
457
295
|
};
|
|
458
296
|
}
|
|
459
|
-
const getHttpStream = async (url, options = {}) => {
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
let bodyPath;
|
|
468
|
-
let didSaveToTmpPath = false;
|
|
469
|
-
try {
|
|
470
|
-
const buffer = await (0, exports.toBuffer)(stream);
|
|
471
|
-
if (type === 'file') {
|
|
472
|
-
bodyPath = media.url;
|
|
473
|
-
}
|
|
474
|
-
else if (saveOriginalFileIfRequired) {
|
|
475
|
-
bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageIDV2)());
|
|
476
|
-
(0, fs_1.writeFileSync)(bodyPath, buffer);
|
|
477
|
-
didSaveToTmpPath = true;
|
|
478
|
-
}
|
|
479
|
-
const fileLength = buffer.length;
|
|
480
|
-
const fileSha256 = Crypto.createHash('sha256').update(buffer).digest();
|
|
481
|
-
stream === null || stream === void 0 ? void 0 : stream.destroy();
|
|
482
|
-
logger === null || logger === void 0 ? void 0 : logger.debug('prepare stream data successfully');
|
|
483
|
-
return {
|
|
484
|
-
mediaKey: undefined,
|
|
485
|
-
encWriteStream: buffer,
|
|
486
|
-
fileLength,
|
|
487
|
-
fileSha256,
|
|
488
|
-
fileEncSha256: undefined,
|
|
489
|
-
bodyPath,
|
|
490
|
-
didSaveToTmpPath
|
|
491
|
-
};
|
|
492
|
-
}
|
|
493
|
-
catch (error) {
|
|
494
|
-
// destroy all streams with error
|
|
495
|
-
stream.destroy();
|
|
496
|
-
if (didSaveToTmpPath) {
|
|
497
|
-
try {
|
|
498
|
-
await fs_1.promises.unlink(bodyPath);
|
|
499
|
-
}
|
|
500
|
-
catch (err) {
|
|
501
|
-
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
throw error;
|
|
297
|
+
export const getHttpStream = async (url, options = {}) => {
|
|
298
|
+
const response = await fetch(url.toString(), {
|
|
299
|
+
dispatcher: options.dispatcher,
|
|
300
|
+
method: 'GET',
|
|
301
|
+
headers: options.headers
|
|
302
|
+
});
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
throw new Boom(`Failed to fetch stream from ${url}`, { statusCode: response.status, data: { url } });
|
|
505
305
|
}
|
|
306
|
+
// @ts-ignore Node18+ Readable.fromWeb exists
|
|
307
|
+
return Readable.fromWeb(response.body);
|
|
506
308
|
};
|
|
507
|
-
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
309
|
+
export const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
310
|
+
const { stream, type } = await getStream(media, opts);
|
|
311
|
+
logger?.debug('fetched media stream');
|
|
511
312
|
const mediaKey = Crypto.randomBytes(32);
|
|
512
313
|
const { cipherKey, iv, macKey } = await getMediaKeys(mediaKey, mediaType);
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
let
|
|
516
|
-
let
|
|
517
|
-
if (
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
else if (saveOriginalFileIfRequired) {
|
|
521
|
-
bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageIDV2)());
|
|
522
|
-
writeStream = (0, fs_1.createWriteStream)(bodyPath);
|
|
523
|
-
didSaveToTmpPath = true;
|
|
314
|
+
const encFilePath = join(getTmpFilesDirectory(), mediaType + generateMessageIDV2() + '-enc');
|
|
315
|
+
const encFileWriteStream = createWriteStream(encFilePath);
|
|
316
|
+
let originalFileStream;
|
|
317
|
+
let originalFilePath;
|
|
318
|
+
if (saveOriginalFileIfRequired) {
|
|
319
|
+
originalFilePath = join(getTmpFilesDirectory(), mediaType + generateMessageIDV2() + '-original');
|
|
320
|
+
originalFileStream = createWriteStream(originalFilePath);
|
|
524
321
|
}
|
|
525
322
|
let fileLength = 0;
|
|
526
323
|
const aes = Crypto.createCipheriv('aes-256-cbc', cipherKey, iv);
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
324
|
+
const hmac = Crypto.createHmac('sha256', macKey).update(iv);
|
|
325
|
+
const sha256Plain = Crypto.createHash('sha256');
|
|
326
|
+
const sha256Enc = Crypto.createHash('sha256');
|
|
327
|
+
const onChunk = (buff) => {
|
|
328
|
+
sha256Enc.update(buff);
|
|
329
|
+
hmac.update(buff);
|
|
330
|
+
encFileWriteStream.write(buff);
|
|
331
|
+
};
|
|
530
332
|
try {
|
|
531
333
|
for await (const data of stream) {
|
|
532
334
|
fileLength += data.length;
|
|
533
|
-
if (type === 'remote'
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
throw new
|
|
335
|
+
if (type === 'remote' &&
|
|
336
|
+
opts?.maxContentLength &&
|
|
337
|
+
fileLength + data.length > opts.maxContentLength) {
|
|
338
|
+
throw new Boom(`content length exceeded when encrypting "${type}"`, {
|
|
537
339
|
data: { media, type }
|
|
538
340
|
});
|
|
539
341
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
await (0, events_1.once)(writeStream, 'drain');
|
|
342
|
+
if (originalFileStream) {
|
|
343
|
+
if (!originalFileStream.write(data)) {
|
|
344
|
+
await once(originalFileStream, 'drain');
|
|
544
345
|
}
|
|
545
346
|
}
|
|
347
|
+
sha256Plain.update(data);
|
|
546
348
|
onChunk(aes.update(data));
|
|
547
349
|
}
|
|
548
350
|
onChunk(aes.final());
|
|
549
351
|
const mac = hmac.digest().slice(0, 10);
|
|
550
|
-
sha256Enc
|
|
352
|
+
sha256Enc.update(mac);
|
|
551
353
|
const fileSha256 = sha256Plain.digest();
|
|
552
354
|
const fileEncSha256 = sha256Enc.digest();
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
355
|
+
encFileWriteStream.write(mac);
|
|
356
|
+
encFileWriteStream.end();
|
|
357
|
+
originalFileStream?.end?.();
|
|
556
358
|
stream.destroy();
|
|
557
|
-
logger
|
|
359
|
+
logger?.debug('encrypted data successfully');
|
|
558
360
|
return {
|
|
559
361
|
mediaKey,
|
|
560
|
-
|
|
561
|
-
|
|
362
|
+
originalFilePath,
|
|
363
|
+
encFilePath,
|
|
562
364
|
mac,
|
|
563
365
|
fileEncSha256,
|
|
564
366
|
fileSha256,
|
|
565
|
-
fileLength
|
|
566
|
-
didSaveToTmpPath
|
|
367
|
+
fileLength
|
|
567
368
|
};
|
|
568
369
|
}
|
|
569
370
|
catch (error) {
|
|
570
371
|
// destroy all streams with error
|
|
571
|
-
|
|
572
|
-
|
|
372
|
+
encFileWriteStream.destroy();
|
|
373
|
+
originalFileStream?.destroy?.();
|
|
573
374
|
aes.destroy();
|
|
574
375
|
hmac.destroy();
|
|
575
376
|
sha256Plain.destroy();
|
|
576
377
|
sha256Enc.destroy();
|
|
577
378
|
stream.destroy();
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
catch (err) {
|
|
583
|
-
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
379
|
+
try {
|
|
380
|
+
await fs.unlink(encFilePath);
|
|
381
|
+
if (originalFilePath) {
|
|
382
|
+
await fs.unlink(originalFilePath);
|
|
584
383
|
}
|
|
585
384
|
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
logger?.error({ err }, 'failed deleting tmp files');
|
|
387
|
+
}
|
|
586
388
|
throw error;
|
|
587
389
|
}
|
|
588
|
-
function onChunk(buff) {
|
|
589
|
-
sha256Enc = sha256Enc.update(buff);
|
|
590
|
-
hmac = hmac.update(buff);
|
|
591
|
-
encWriteStream.push(buff);
|
|
592
|
-
}
|
|
593
390
|
};
|
|
594
|
-
exports.encryptedStream = encryptedStream;
|
|
595
391
|
const DEF_HOST = 'mmg.whatsapp.net';
|
|
596
392
|
const AES_CHUNK_SIZE = 16;
|
|
597
393
|
const toSmallestChunkSize = (num) => {
|
|
598
394
|
return Math.floor(num / AES_CHUNK_SIZE) * AES_CHUNK_SIZE;
|
|
599
395
|
};
|
|
600
|
-
const getUrlFromDirectPath = (directPath) => `https://${DEF_HOST}${directPath}`;
|
|
601
|
-
|
|
602
|
-
const
|
|
603
|
-
const
|
|
604
|
-
const downloadUrl = isValidMediaUrl ? url : (0, exports.getUrlFromDirectPath)(directPath);
|
|
396
|
+
export const getUrlFromDirectPath = (directPath) => `https://${DEF_HOST}${directPath}`;
|
|
397
|
+
export const downloadContentFromMessage = async ({ mediaKey, directPath, url }, type, opts = {}) => {
|
|
398
|
+
const isValidMediaUrl = url?.startsWith('https://mmg.whatsapp.net/');
|
|
399
|
+
const downloadUrl = isValidMediaUrl ? url : getUrlFromDirectPath(directPath);
|
|
605
400
|
if (!downloadUrl) {
|
|
606
|
-
throw new
|
|
401
|
+
throw new Boom('No valid media URL or directPath present in message', { statusCode: 400 });
|
|
607
402
|
}
|
|
608
403
|
const keys = await getMediaKeys(mediaKey, type);
|
|
609
|
-
return
|
|
404
|
+
return downloadEncryptedContent(downloadUrl, keys, opts);
|
|
610
405
|
};
|
|
611
|
-
exports.downloadContentFromMessage = downloadContentFromMessage;
|
|
612
406
|
/**
|
|
613
407
|
* Decrypts and downloads an AES256-CBC encrypted file given the keys.
|
|
614
408
|
* Assumes the SHA256 of the plaintext is appended to the end of the ciphertext
|
|
615
409
|
* */
|
|
616
|
-
const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startByte, endByte, options } = {}) => {
|
|
410
|
+
export const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startByte, endByte, options } = {}) => {
|
|
617
411
|
let bytesFetched = 0;
|
|
618
412
|
let startChunk = 0;
|
|
619
413
|
let firstBlockIsIV = false;
|
|
@@ -627,9 +421,14 @@ const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startB
|
|
|
627
421
|
}
|
|
628
422
|
}
|
|
629
423
|
const endChunk = endByte ? toSmallestChunkSize(endByte || 0) + AES_CHUNK_SIZE : undefined;
|
|
424
|
+
const headersInit = options?.headers ? options.headers : undefined;
|
|
630
425
|
const headers = {
|
|
631
|
-
...(
|
|
632
|
-
|
|
426
|
+
...(headersInit
|
|
427
|
+
? Array.isArray(headersInit)
|
|
428
|
+
? Object.fromEntries(headersInit)
|
|
429
|
+
: headersInit
|
|
430
|
+
: {}),
|
|
431
|
+
Origin: DEFAULT_ORIGIN
|
|
633
432
|
};
|
|
634
433
|
if (startChunk || endChunk) {
|
|
635
434
|
headers.Range = `bytes=${startChunk}-`;
|
|
@@ -638,11 +437,9 @@ const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startB
|
|
|
638
437
|
}
|
|
639
438
|
}
|
|
640
439
|
// download the message
|
|
641
|
-
const fetched = await
|
|
642
|
-
...options || {},
|
|
643
|
-
headers
|
|
644
|
-
maxBodyLength: Infinity,
|
|
645
|
-
maxContentLength: Infinity,
|
|
440
|
+
const fetched = await getHttpStream(downloadUrl, {
|
|
441
|
+
...(options || {}),
|
|
442
|
+
headers
|
|
646
443
|
});
|
|
647
444
|
let remainingBytes = Buffer.from([]);
|
|
648
445
|
let aes;
|
|
@@ -657,7 +454,7 @@ const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startB
|
|
|
657
454
|
push(bytes);
|
|
658
455
|
}
|
|
659
456
|
};
|
|
660
|
-
const output = new
|
|
457
|
+
const output = new Transform({
|
|
661
458
|
transform(chunk, _, callback) {
|
|
662
459
|
let data = Buffer.concat([remainingBytes, chunk]);
|
|
663
460
|
const decryptLength = toSmallestChunkSize(data.length);
|
|
@@ -692,18 +489,15 @@ const downloadEncryptedContent = async (downloadUrl, { cipherKey, iv }, { startB
|
|
|
692
489
|
catch (error) {
|
|
693
490
|
callback(error);
|
|
694
491
|
}
|
|
695
|
-
}
|
|
492
|
+
}
|
|
696
493
|
});
|
|
697
494
|
return fetched.pipe(output, { end: true });
|
|
698
495
|
};
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
const getExtension = (mimetype) => mimetype.split(';')[0].split('/')[1];
|
|
496
|
+
export function extensionForMediaMessage(message) {
|
|
497
|
+
const getExtension = (mimetype) => mimetype.split(';')[0]?.split('/')[1];
|
|
702
498
|
const type = Object.keys(message)[0];
|
|
703
499
|
let extension;
|
|
704
|
-
if (type === 'locationMessage' ||
|
|
705
|
-
type === 'liveLocationMessage' ||
|
|
706
|
-
type === 'productMessage') {
|
|
500
|
+
if (type === 'locationMessage' || type === 'liveLocationMessage' || type === 'productMessage') {
|
|
707
501
|
extension = '.jpeg';
|
|
708
502
|
}
|
|
709
503
|
else {
|
|
@@ -712,53 +506,54 @@ function extensionForMediaMessage(message) {
|
|
|
712
506
|
}
|
|
713
507
|
return extension;
|
|
714
508
|
}
|
|
715
|
-
const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
|
|
716
|
-
return async (
|
|
717
|
-
var _a, _b;
|
|
509
|
+
export const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
|
|
510
|
+
return async (filePath, { mediaType, fileEncSha256B64, timeoutMs }) => {
|
|
718
511
|
// send a query JSON to obtain the url & auth token to upload our media
|
|
719
512
|
let uploadInfo = await refreshMediaConn(false);
|
|
720
513
|
let urls;
|
|
721
514
|
const hosts = [...customUploadHosts, ...uploadInfo.hosts];
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
for await (const chunk of stream) {
|
|
725
|
-
chunks.push(chunk);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
const reqBody = Buffer.isBuffer(stream) ? stream : Buffer.concat(chunks);
|
|
729
|
-
fileEncSha256B64 = (0, exports.encodeBase64EncodedStringForUpload)(fileEncSha256B64);
|
|
730
|
-
let media = Defaults_1.MEDIA_PATH_MAP[mediaType];
|
|
731
|
-
if (newsletter) {
|
|
732
|
-
media = media === null || media === void 0 ? void 0 : media.replace('/mms/', '/newsletter/newsletter-');
|
|
733
|
-
}
|
|
734
|
-
for (const { hostname, maxContentLengthBytes } of hosts) {
|
|
515
|
+
fileEncSha256B64 = encodeBase64EncodedStringForUpload(fileEncSha256B64);
|
|
516
|
+
for (const { hostname } of hosts) {
|
|
735
517
|
logger.debug(`uploading to "${hostname}"`);
|
|
736
518
|
const auth = encodeURIComponent(uploadInfo.auth); // the auth token
|
|
737
|
-
const url = `https://${hostname}${
|
|
519
|
+
const url = `https://${hostname}${MEDIA_PATH_MAP[mediaType]}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
|
|
520
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
738
521
|
let result;
|
|
739
522
|
try {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
523
|
+
const stream = createReadStream(filePath);
|
|
524
|
+
const response = await fetch(url, {
|
|
525
|
+
dispatcher: fetchAgent,
|
|
526
|
+
method: 'POST',
|
|
527
|
+
body: stream,
|
|
745
528
|
headers: {
|
|
746
|
-
...
|
|
529
|
+
...(() => {
|
|
530
|
+
const hdrs = options?.headers;
|
|
531
|
+
if (!hdrs)
|
|
532
|
+
return {};
|
|
533
|
+
return Array.isArray(hdrs) ? Object.fromEntries(hdrs) : hdrs;
|
|
534
|
+
})(),
|
|
747
535
|
'Content-Type': 'application/octet-stream',
|
|
748
|
-
|
|
536
|
+
Origin: DEFAULT_ORIGIN
|
|
749
537
|
},
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
maxBodyLength: Infinity,
|
|
754
|
-
maxContentLength: Infinity,
|
|
538
|
+
duplex: 'half',
|
|
539
|
+
// Note: custom agents/proxy require undici Agent; omitted here.
|
|
540
|
+
signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined
|
|
755
541
|
});
|
|
756
|
-
|
|
757
|
-
|
|
542
|
+
let parsed = undefined;
|
|
543
|
+
try {
|
|
544
|
+
parsed = await response.json();
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
parsed = undefined;
|
|
548
|
+
}
|
|
549
|
+
result = parsed;
|
|
550
|
+
if (result?.url || result?.directPath) {
|
|
758
551
|
urls = {
|
|
759
552
|
mediaUrl: result.url,
|
|
760
553
|
directPath: result.direct_path,
|
|
761
|
-
|
|
554
|
+
meta_hmac: result.meta_hmac,
|
|
555
|
+
fbid: result.fbid,
|
|
556
|
+
ts: result.ts
|
|
762
557
|
};
|
|
763
558
|
break;
|
|
764
559
|
}
|
|
@@ -768,37 +563,33 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
|
|
|
768
563
|
}
|
|
769
564
|
}
|
|
770
565
|
catch (error) {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
const isLast = hostname === ((_b = hosts[uploadInfo.hosts.length - 1]) === null || _b === void 0 ? void 0 : _b.hostname);
|
|
775
|
-
logger.warn({ trace: error.stack, uploadResult: result }, `Error in uploading to ${hostname} ${isLast ? '' : ', retrying...'}`);
|
|
566
|
+
const isLast = hostname === hosts[uploadInfo.hosts.length - 1]?.hostname;
|
|
567
|
+
logger.warn({ trace: error?.stack, uploadResult: result }, `Error in uploading to ${hostname} ${isLast ? '' : ', retrying...'}`);
|
|
776
568
|
}
|
|
777
569
|
}
|
|
778
570
|
if (!urls) {
|
|
779
|
-
throw new
|
|
571
|
+
throw new Boom('Media upload failed on all hosts', { statusCode: 500 });
|
|
780
572
|
}
|
|
781
573
|
return urls;
|
|
782
574
|
};
|
|
783
575
|
};
|
|
784
|
-
exports.getWAUploadToServer = getWAUploadToServer;
|
|
785
576
|
const getMediaRetryKey = (mediaKey) => {
|
|
786
|
-
return
|
|
577
|
+
return hkdf(mediaKey, 32, { info: 'WhatsApp Media Retry Notification' });
|
|
787
578
|
};
|
|
788
579
|
/**
|
|
789
580
|
* Generate a binary node that will request the phone to re-upload the media & return the newly uploaded URL
|
|
790
581
|
*/
|
|
791
|
-
const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
|
|
582
|
+
export const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
|
|
792
583
|
const recp = { stanzaId: key.id };
|
|
793
|
-
const recpBuffer =
|
|
584
|
+
const recpBuffer = proto.ServerErrorReceipt.encode(recp).finish();
|
|
794
585
|
const iv = Crypto.randomBytes(12);
|
|
795
586
|
const retryKey = await getMediaRetryKey(mediaKey);
|
|
796
|
-
const ciphertext =
|
|
587
|
+
const ciphertext = aesEncryptGCM(recpBuffer, retryKey, iv, Buffer.from(key.id));
|
|
797
588
|
const req = {
|
|
798
589
|
tag: 'receipt',
|
|
799
590
|
attrs: {
|
|
800
591
|
id: key.id,
|
|
801
|
-
to:
|
|
592
|
+
to: jidNormalizedUser(meId),
|
|
802
593
|
type: 'server-error'
|
|
803
594
|
},
|
|
804
595
|
content: [
|
|
@@ -817,7 +608,7 @@ const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
|
|
|
817
608
|
tag: 'rmr',
|
|
818
609
|
attrs: {
|
|
819
610
|
jid: key.remoteJid,
|
|
820
|
-
|
|
611
|
+
from_me: (!!key.fromMe).toString(),
|
|
821
612
|
// @ts-ignore
|
|
822
613
|
participant: key.participant || undefined
|
|
823
614
|
}
|
|
@@ -826,9 +617,8 @@ const encryptMediaRetryRequest = async (key, mediaKey, meId) => {
|
|
|
826
617
|
};
|
|
827
618
|
return req;
|
|
828
619
|
};
|
|
829
|
-
|
|
830
|
-
const
|
|
831
|
-
const rmrNode = (0, WABinary_1.getBinaryNodeChild)(node, 'rmr');
|
|
620
|
+
export const decodeMediaRetryNode = (node) => {
|
|
621
|
+
const rmrNode = getBinaryNodeChild(node, 'rmr');
|
|
832
622
|
const event = {
|
|
833
623
|
key: {
|
|
834
624
|
id: node.attrs.id,
|
|
@@ -837,40 +627,37 @@ const decodeMediaRetryNode = (node) => {
|
|
|
837
627
|
participant: rmrNode.attrs.participant
|
|
838
628
|
}
|
|
839
629
|
};
|
|
840
|
-
const errorNode =
|
|
630
|
+
const errorNode = getBinaryNodeChild(node, 'error');
|
|
841
631
|
if (errorNode) {
|
|
842
632
|
const errorCode = +errorNode.attrs.code;
|
|
843
|
-
event.error = new
|
|
633
|
+
event.error = new Boom(`Failed to re-upload media (${errorCode})`, {
|
|
634
|
+
data: errorNode.attrs,
|
|
635
|
+
statusCode: getStatusCodeForMediaRetry(errorCode)
|
|
636
|
+
});
|
|
844
637
|
}
|
|
845
638
|
else {
|
|
846
|
-
const encryptedInfoNode =
|
|
847
|
-
const ciphertext =
|
|
848
|
-
const iv =
|
|
639
|
+
const encryptedInfoNode = getBinaryNodeChild(node, 'encrypt');
|
|
640
|
+
const ciphertext = getBinaryNodeChildBuffer(encryptedInfoNode, 'enc_p');
|
|
641
|
+
const iv = getBinaryNodeChildBuffer(encryptedInfoNode, 'enc_iv');
|
|
849
642
|
if (ciphertext && iv) {
|
|
850
643
|
event.media = { ciphertext, iv };
|
|
851
644
|
}
|
|
852
645
|
else {
|
|
853
|
-
event.error = new
|
|
646
|
+
event.error = new Boom('Failed to re-upload media (missing ciphertext)', { statusCode: 404 });
|
|
854
647
|
}
|
|
855
648
|
}
|
|
856
649
|
return event;
|
|
857
650
|
};
|
|
858
|
-
|
|
859
|
-
const decryptMediaRetryData = async ({ ciphertext, iv }, mediaKey, msgId) => {
|
|
651
|
+
export const decryptMediaRetryData = async ({ ciphertext, iv }, mediaKey, msgId) => {
|
|
860
652
|
const retryKey = await getMediaRetryKey(mediaKey);
|
|
861
|
-
const plaintext =
|
|
862
|
-
return
|
|
653
|
+
const plaintext = aesDecryptGCM(ciphertext, retryKey, iv, Buffer.from(msgId));
|
|
654
|
+
return proto.MediaRetryNotification.decode(plaintext);
|
|
863
655
|
};
|
|
864
|
-
|
|
865
|
-
const getStatusCodeForMediaRetry = (code) => MEDIA_RETRY_STATUS_MAP[code];
|
|
866
|
-
exports.getStatusCodeForMediaRetry = getStatusCodeForMediaRetry;
|
|
656
|
+
export const getStatusCodeForMediaRetry = (code) => MEDIA_RETRY_STATUS_MAP[code];
|
|
867
657
|
const MEDIA_RETRY_STATUS_MAP = {
|
|
868
|
-
[
|
|
869
|
-
[
|
|
870
|
-
[
|
|
871
|
-
[
|
|
658
|
+
[proto.MediaRetryNotification.ResultType.SUCCESS]: 200,
|
|
659
|
+
[proto.MediaRetryNotification.ResultType.DECRYPTION_ERROR]: 412,
|
|
660
|
+
[proto.MediaRetryNotification.ResultType.NOT_FOUND]: 404,
|
|
661
|
+
[proto.MediaRetryNotification.ResultType.GENERAL_ERROR]: 418
|
|
872
662
|
};
|
|
873
|
-
|
|
874
|
-
function __importStar(arg0) {
|
|
875
|
-
throw new Error('Function not implemented.');
|
|
876
|
-
}
|
|
663
|
+
//# sourceMappingURL=messages-media.js.map
|