@oxidezap/baileyrs 0.0.26 → 0.0.28
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/README.md +31 -460
- package/lib/Bridge/adapt.d.ts +2 -0
- package/lib/Bridge/adapt.d.ts.map +1 -1
- package/lib/Bridge/adapt.js +2 -1
- package/lib/Bridge/adapt.js.map +1 -1
- package/lib/Bridge/history-sync-wire.d.ts +17 -0
- package/lib/Bridge/history-sync-wire.d.ts.map +1 -0
- package/lib/Bridge/history-sync-wire.js +61 -0
- package/lib/Bridge/history-sync-wire.js.map +1 -0
- package/lib/Bridge/index.d.ts +1 -1
- package/lib/Bridge/index.d.ts.map +1 -1
- package/lib/Bridge/index.js +3 -3
- package/lib/Bridge/index.js.map +1 -1
- package/lib/Bridge/primitives.d.ts +4 -0
- package/lib/Bridge/primitives.d.ts.map +1 -1
- package/lib/Bridge/primitives.js +14 -0
- package/lib/Bridge/primitives.js.map +1 -1
- package/lib/Bridge/schema.d.ts +9 -2
- package/lib/Bridge/schema.d.ts.map +1 -1
- package/lib/Bridge/schema.js +263 -35
- package/lib/Bridge/schema.js.map +1 -1
- package/lib/Bridge/types.d.ts +117 -3
- package/lib/Bridge/types.d.ts.map +1 -1
- package/lib/Compatibility/group-metadata.d.ts +9 -0
- package/lib/Compatibility/group-metadata.d.ts.map +1 -0
- package/lib/Compatibility/group-metadata.js +70 -0
- package/lib/Compatibility/group-metadata.js.map +1 -0
- package/lib/Compatibility/group-notifications.d.ts +22 -0
- package/lib/Compatibility/group-notifications.d.ts.map +1 -0
- package/lib/Compatibility/group-notifications.js +307 -0
- package/lib/Compatibility/group-notifications.js.map +1 -0
- package/lib/Compatibility/group-stub-params.d.ts +32 -0
- package/lib/Compatibility/group-stub-params.d.ts.map +1 -0
- package/lib/Compatibility/group-stub-params.js +57 -0
- package/lib/Compatibility/group-stub-params.js.map +1 -0
- package/lib/Compatibility/internal/async-primitives.d.ts +16 -0
- package/lib/Compatibility/internal/async-primitives.d.ts.map +1 -0
- package/lib/Compatibility/internal/async-primitives.js +42 -0
- package/lib/Compatibility/internal/async-primitives.js.map +1 -0
- package/lib/Compatibility/internal/auth-state.d.ts +15 -0
- package/lib/Compatibility/internal/auth-state.d.ts.map +1 -0
- package/lib/Compatibility/internal/auth-state.js +21 -0
- package/lib/Compatibility/internal/auth-state.js.map +1 -0
- package/lib/Compatibility/internal/cache-store.d.ts +7 -0
- package/lib/Compatibility/internal/cache-store.d.ts.map +1 -0
- package/lib/Compatibility/internal/cache-store.js +19 -0
- package/lib/Compatibility/internal/cache-store.js.map +1 -0
- package/lib/Compatibility/internal/expiring-lru-map.d.ts +21 -0
- package/lib/Compatibility/internal/expiring-lru-map.d.ts.map +1 -0
- package/lib/Compatibility/internal/expiring-lru-map.js +68 -0
- package/lib/Compatibility/internal/expiring-lru-map.js.map +1 -0
- package/lib/Compatibility/internal/make-mutex.d.ts +7 -0
- package/lib/Compatibility/internal/make-mutex.d.ts.map +1 -0
- package/lib/Compatibility/internal/make-mutex.js +31 -0
- package/lib/Compatibility/internal/make-mutex.js.map +1 -0
- package/lib/Compatibility/internal/native-memory-store.d.ts +6 -0
- package/lib/Compatibility/internal/native-memory-store.d.ts.map +1 -0
- package/lib/Compatibility/internal/native-memory-store.js +8 -0
- package/lib/Compatibility/internal/native-memory-store.js.map +1 -0
- package/lib/Compatibility/internal/numeric-enum.d.ts +8 -0
- package/lib/Compatibility/internal/numeric-enum.d.ts.map +1 -0
- package/lib/Compatibility/internal/numeric-enum.js +11 -0
- package/lib/Compatibility/internal/numeric-enum.js.map +1 -0
- package/lib/Compatibility/internal/signal-key-store.d.ts +9 -0
- package/lib/Compatibility/internal/signal-key-store.d.ts.map +1 -0
- package/lib/Compatibility/internal/signal-key-store.js +17 -0
- package/lib/Compatibility/internal/signal-key-store.js.map +1 -0
- package/lib/Compatibility/legacy-store/adapter.d.ts +4 -0
- package/lib/Compatibility/legacy-store/adapter.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/adapter.js +301 -0
- package/lib/Compatibility/legacy-store/adapter.js.map +1 -0
- package/lib/Compatibility/legacy-store/codecs/basic.d.ts +6 -0
- package/lib/Compatibility/legacy-store/codecs/basic.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/codecs/basic.js +184 -0
- package/lib/Compatibility/legacy-store/codecs/basic.js.map +1 -0
- package/lib/Compatibility/legacy-store/codecs/index.d.ts +6 -0
- package/lib/Compatibility/legacy-store/codecs/index.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/codecs/index.js +7 -0
- package/lib/Compatibility/legacy-store/codecs/index.js.map +1 -0
- package/lib/Compatibility/legacy-store/codecs/signal.d.ts +8 -0
- package/lib/Compatibility/legacy-store/codecs/signal.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/codecs/signal.js +219 -0
- package/lib/Compatibility/legacy-store/codecs/signal.js.map +1 -0
- package/lib/Compatibility/legacy-store/common.d.ts +25 -0
- package/lib/Compatibility/legacy-store/common.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/common.js +112 -0
- package/lib/Compatibility/legacy-store/common.js.map +1 -0
- package/lib/Compatibility/legacy-store/constants.d.ts +226 -0
- package/lib/Compatibility/legacy-store/constants.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/constants.js +199 -0
- package/lib/Compatibility/legacy-store/constants.js.map +1 -0
- package/lib/Compatibility/legacy-store/device.d.ts +9 -0
- package/lib/Compatibility/legacy-store/device.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/device.js +192 -0
- package/lib/Compatibility/legacy-store/device.js.map +1 -0
- package/lib/Compatibility/legacy-store/multi-file.d.ts +6 -0
- package/lib/Compatibility/legacy-store/multi-file.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/multi-file.js +84 -0
- package/lib/Compatibility/legacy-store/multi-file.js.map +1 -0
- package/lib/Compatibility/legacy-store/native-projection.d.ts +8 -0
- package/lib/Compatibility/legacy-store/native-projection.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/native-projection.js +109 -0
- package/lib/Compatibility/legacy-store/native-projection.js.map +1 -0
- package/lib/Compatibility/legacy-store/routing.d.ts +18 -0
- package/lib/Compatibility/legacy-store/routing.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/routing.js +162 -0
- package/lib/Compatibility/legacy-store/routing.js.map +1 -0
- package/lib/Compatibility/legacy-store/types.d.ts +41 -0
- package/lib/Compatibility/legacy-store/types.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/types.js +3 -0
- package/lib/Compatibility/legacy-store/types.js.map +1 -0
- package/lib/Compatibility/legacy-store/validation.d.ts +9 -0
- package/lib/Compatibility/legacy-store/validation.d.ts.map +1 -0
- package/lib/Compatibility/legacy-store/validation.js +49 -0
- package/lib/Compatibility/legacy-store/validation.js.map +1 -0
- package/lib/Compatibility/media-type.d.ts +10 -0
- package/lib/Compatibility/media-type.d.ts.map +1 -0
- package/lib/Compatibility/media-type.js +31 -0
- package/lib/Compatibility/media-type.js.map +1 -0
- package/lib/Compatibility/message-keys.d.ts +9 -0
- package/lib/Compatibility/message-keys.d.ts.map +1 -0
- package/lib/Compatibility/message-keys.js +15 -0
- package/lib/Compatibility/message-keys.js.map +1 -0
- package/lib/Compatibility/message-relay.d.ts +26 -0
- package/lib/Compatibility/message-relay.d.ts.map +1 -0
- package/lib/Compatibility/message-relay.js +61 -0
- package/lib/Compatibility/message-relay.js.map +1 -0
- package/lib/Compatibility/message-upsert.d.ts +11 -0
- package/lib/Compatibility/message-upsert.d.ts.map +1 -0
- package/lib/Compatibility/message-upsert.js +8 -0
- package/lib/Compatibility/message-upsert.js.map +1 -0
- package/lib/Compatibility/participating-refresh.d.ts +9 -0
- package/lib/Compatibility/participating-refresh.d.ts.map +1 -0
- package/lib/Compatibility/participating-refresh.js +14 -0
- package/lib/Compatibility/participating-refresh.js.map +1 -0
- package/lib/Compatibility/proto-runtime.d.ts +9 -0
- package/lib/Compatibility/proto-runtime.d.ts.map +1 -0
- package/lib/Compatibility/proto-runtime.js +567 -0
- package/lib/Compatibility/proto-runtime.js.map +1 -0
- package/lib/Compatibility/public-api/auth-utils.d.ts +6 -0
- package/lib/Compatibility/public-api/auth-utils.d.ts.map +1 -0
- package/lib/Compatibility/public-api/auth-utils.js +202 -0
- package/lib/Compatibility/public-api/auth-utils.js.map +1 -0
- package/lib/Compatibility/public-api/enum-types.d.ts +163 -0
- package/lib/Compatibility/public-api/enum-types.d.ts.map +1 -0
- package/lib/Compatibility/public-api/enum-types.js +10 -0
- package/lib/Compatibility/public-api/enum-types.js.map +1 -0
- package/lib/Compatibility/public-api/identity-change-handler.d.ts +42 -0
- package/lib/Compatibility/public-api/identity-change-handler.d.ts.map +1 -0
- package/lib/Compatibility/public-api/identity-change-handler.js +38 -0
- package/lib/Compatibility/public-api/identity-change-handler.js.map +1 -0
- package/lib/Compatibility/public-api/message-retry-manager.d.ts +62 -0
- package/lib/Compatibility/public-api/message-retry-manager.d.ts.map +1 -0
- package/lib/Compatibility/public-api/message-retry-manager.js +180 -0
- package/lib/Compatibility/public-api/message-retry-manager.js.map +1 -0
- package/lib/Compatibility/public-api/pre-key-manager.d.ts +14 -0
- package/lib/Compatibility/public-api/pre-key-manager.d.ts.map +1 -0
- package/lib/Compatibility/public-api/pre-key-manager.js +83 -0
- package/lib/Compatibility/public-api/pre-key-manager.js.map +1 -0
- package/lib/Compatibility/public-api/stanza-ack.d.ts +4 -0
- package/lib/Compatibility/public-api/stanza-ack.d.ts.map +1 -0
- package/lib/Compatibility/public-api/stanza-ack.js +20 -0
- package/lib/Compatibility/public-api/stanza-ack.js.map +1 -0
- package/lib/Compatibility/signal-repository.d.ts +12 -0
- package/lib/Compatibility/signal-repository.d.ts.map +1 -0
- package/lib/Compatibility/signal-repository.js +131 -0
- package/lib/Compatibility/signal-repository.js.map +1 -0
- package/lib/Compatibility/socket-results.d.ts +28 -0
- package/lib/Compatibility/socket-results.d.ts.map +1 -0
- package/lib/Compatibility/socket-results.js +72 -0
- package/lib/Compatibility/socket-results.js.map +1 -0
- package/lib/Compatibility/stanza-responses.d.ts +13 -0
- package/lib/Compatibility/stanza-responses.d.ts.map +1 -0
- package/lib/Compatibility/stanza-responses.js +16 -0
- package/lib/Compatibility/stanza-responses.js.map +1 -0
- package/lib/Compatibility/tagged-message-waiter.d.ts +5 -0
- package/lib/Compatibility/tagged-message-waiter.d.ts.map +1 -0
- package/lib/Compatibility/tagged-message-waiter.js +42 -0
- package/lib/Compatibility/tagged-message-waiter.js.map +1 -0
- package/lib/Compatibility/usync/adapter.d.ts +13 -0
- package/lib/Compatibility/usync/adapter.d.ts.map +1 -0
- package/lib/Compatibility/usync/adapter.js +291 -0
- package/lib/Compatibility/usync/adapter.js.map +1 -0
- package/lib/Compatibility/websocket-client.d.ts +40 -0
- package/lib/Compatibility/websocket-client.d.ts.map +1 -0
- package/lib/Compatibility/websocket-client.js +120 -0
- package/lib/Compatibility/websocket-client.js.map +1 -0
- package/lib/Defaults/index.d.ts +70 -3
- package/lib/Defaults/index.d.ts.map +1 -1
- package/lib/Defaults/index.js +107 -15
- package/lib/Defaults/index.js.map +1 -1
- package/lib/Platform/crypto.d.ts +6 -0
- package/lib/Platform/crypto.d.ts.map +1 -0
- package/lib/Platform/crypto.js +36 -0
- package/lib/Platform/crypto.js.map +1 -0
- package/lib/Socket/blocking.d.ts +2 -2
- package/lib/Socket/blocking.d.ts.map +1 -1
- package/lib/Socket/blocking.js +2 -1
- package/lib/Socket/blocking.js.map +1 -1
- package/lib/Socket/chat-actions.d.ts +2 -9
- package/lib/Socket/chat-actions.d.ts.map +1 -1
- package/lib/Socket/chat-actions.js +24 -13
- package/lib/Socket/chat-actions.js.map +1 -1
- package/lib/Socket/communities.d.ts +61 -0
- package/lib/Socket/communities.d.ts.map +1 -0
- package/lib/Socket/communities.js +72 -0
- package/lib/Socket/communities.js.map +1 -0
- package/lib/Socket/contacts.d.ts +4 -2
- package/lib/Socket/contacts.d.ts.map +1 -1
- package/lib/Socket/contacts.js +6 -4
- package/lib/Socket/contacts.js.map +1 -1
- package/lib/Socket/events.d.ts +13 -5
- package/lib/Socket/events.d.ts.map +1 -1
- package/lib/Socket/events.js +282 -57
- package/lib/Socket/events.js.map +1 -1
- package/lib/Socket/group-notifications.d.ts +1 -30
- package/lib/Socket/group-notifications.d.ts.map +1 -1
- package/lib/Socket/group-notifications.js +3 -268
- package/lib/Socket/group-notifications.js.map +1 -1
- package/lib/Socket/groups.d.ts +17 -36
- package/lib/Socket/groups.d.ts.map +1 -1
- package/lib/Socket/groups.js +111 -116
- package/lib/Socket/groups.js.map +1 -1
- package/lib/Socket/index.d.ts +140 -201
- package/lib/Socket/index.d.ts.map +1 -1
- package/lib/Socket/index.js +215 -345
- package/lib/Socket/index.js.map +1 -1
- package/lib/Socket/message-capping.d.ts +4 -0
- package/lib/Socket/message-capping.d.ts.map +1 -0
- package/lib/Socket/message-capping.js +22 -0
- package/lib/Socket/message-capping.js.map +1 -0
- package/lib/Socket/messages.d.ts +8 -14
- package/lib/Socket/messages.d.ts.map +1 -1
- package/lib/Socket/messages.js +74 -40
- package/lib/Socket/messages.js.map +1 -1
- package/lib/Socket/newsletter.d.ts +5 -0
- package/lib/Socket/newsletter.d.ts.map +1 -1
- package/lib/Socket/newsletter.js +7 -0
- package/lib/Socket/newsletter.js.map +1 -1
- package/lib/Socket/prekeys.d.ts +10 -0
- package/lib/Socket/prekeys.d.ts.map +1 -0
- package/lib/Socket/prekeys.js +21 -0
- package/lib/Socket/prekeys.js.map +1 -0
- package/lib/Socket/presence.d.ts +3 -3
- package/lib/Socket/presence.d.ts.map +1 -1
- package/lib/Socket/presence.js +2 -2
- package/lib/Socket/presence.js.map +1 -1
- package/lib/Socket/profile.d.ts +6 -8
- package/lib/Socket/profile.d.ts.map +1 -1
- package/lib/Socket/profile.js +18 -17
- package/lib/Socket/profile.js.map +1 -1
- package/lib/Socket/reachout.js +1 -1
- package/lib/Socket/transport.d.ts.map +1 -1
- package/lib/Socket/transport.js +13 -1
- package/lib/Socket/transport.js.map +1 -1
- package/lib/Socket/types.d.ts +4 -2
- package/lib/Socket/types.d.ts.map +1 -1
- package/lib/Socket/types.js.map +1 -1
- package/lib/Socket/usync.d.ts +12 -0
- package/lib/Socket/usync.d.ts.map +1 -0
- package/lib/Socket/usync.js +27 -0
- package/lib/Socket/usync.js.map +1 -0
- package/lib/Types/Auth.d.ts +28 -30
- package/lib/Types/Auth.d.ts.map +1 -1
- package/lib/Types/Auth.js +1 -1
- package/lib/Types/Auth.js.map +1 -1
- package/lib/Types/BinaryNode.d.ts +0 -4
- package/lib/Types/BinaryNode.d.ts.map +1 -1
- package/lib/Types/Bussines.d.ts +1 -1
- package/lib/Types/Bussines.d.ts.map +1 -1
- package/lib/Types/Call.d.ts +3 -1
- package/lib/Types/Call.d.ts.map +1 -1
- package/lib/Types/Chat.d.ts +2 -2
- package/lib/Types/Chat.d.ts.map +1 -1
- package/lib/Types/Events.d.ts +16 -5
- package/lib/Types/Events.d.ts.map +1 -1
- package/lib/Types/Events.js +1 -1
- package/lib/Types/Events.js.map +1 -1
- package/lib/Types/GroupMetadata.d.ts +4 -0
- package/lib/Types/GroupMetadata.d.ts.map +1 -1
- package/lib/Types/Label.d.ts +3 -23
- package/lib/Types/Label.d.ts.map +1 -1
- package/lib/Types/Label.js +24 -23
- package/lib/Types/Label.js.map +1 -1
- package/lib/Types/LabelAssociation.d.ts +5 -6
- package/lib/Types/LabelAssociation.d.ts.map +1 -1
- package/lib/Types/LabelAssociation.js +4 -5
- package/lib/Types/LabelAssociation.js.map +1 -1
- package/lib/Types/Message.d.ts +45 -10
- package/lib/Types/Message.d.ts.map +1 -1
- package/lib/Types/Message.js +5 -7
- package/lib/Types/Message.js.map +1 -1
- package/lib/Types/Newsletter.d.ts +5 -28
- package/lib/Types/Newsletter.d.ts.map +1 -1
- package/lib/Types/Newsletter.js +34 -30
- package/lib/Types/Newsletter.js.map +1 -1
- package/lib/Types/Product.d.ts +75 -0
- package/lib/Types/Product.d.ts.map +1 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/Product.js.map +1 -0
- package/lib/Types/Reachout.d.ts +3 -18
- package/lib/Types/Reachout.d.ts.map +1 -1
- package/lib/Types/Reachout.js +20 -19
- package/lib/Types/Reachout.js.map +1 -1
- package/lib/Types/Signal.d.ts +91 -0
- package/lib/Types/Signal.d.ts.map +1 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Signal.js.map +1 -0
- package/lib/Types/Socket.d.ts +76 -30
- package/lib/Types/Socket.d.ts.map +1 -1
- package/lib/Types/State.d.ts +19 -0
- package/lib/Types/State.d.ts.map +1 -1
- package/lib/Types/State.js +26 -1
- package/lib/Types/State.js.map +1 -1
- package/lib/Types/USync.d.ts +9 -0
- package/lib/Types/USync.d.ts.map +1 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/USync.js.map +1 -0
- package/lib/Types/index.d.ts +9 -12
- package/lib/Types/index.d.ts.map +1 -1
- package/lib/Types/index.js +30 -30
- package/lib/Types/index.js.map +1 -1
- package/lib/Utils/auth-utils.d.ts +2 -0
- package/lib/Utils/auth-utils.d.ts.map +1 -0
- package/lib/Utils/auth-utils.js +3 -0
- package/lib/Utils/auth-utils.js.map +1 -0
- package/lib/Utils/boom.d.ts +8 -32
- package/lib/Utils/boom.d.ts.map +1 -1
- package/lib/Utils/boom.js +7 -62
- package/lib/Utils/boom.js.map +1 -1
- package/lib/Utils/browser-utils.d.ts +1 -0
- package/lib/Utils/browser-utils.d.ts.map +1 -1
- package/lib/Utils/browser-utils.js +6 -0
- package/lib/Utils/browser-utils.js.map +1 -1
- package/lib/Utils/companion-reg-client-utils.d.ts +8 -0
- package/lib/Utils/companion-reg-client-utils.d.ts.map +1 -0
- package/lib/Utils/companion-reg-client-utils.js +32 -0
- package/lib/Utils/companion-reg-client-utils.js.map +1 -0
- package/lib/Utils/crypto.d.ts +31 -0
- package/lib/Utils/crypto.d.ts.map +1 -0
- package/lib/Utils/crypto.js +81 -0
- package/lib/Utils/crypto.js.map +1 -0
- package/lib/Utils/event-buffer.d.ts +15 -4
- package/lib/Utils/event-buffer.d.ts.map +1 -1
- package/lib/Utils/event-buffer.js +471 -34
- package/lib/Utils/event-buffer.js.map +1 -1
- package/lib/Utils/generics.d.ts +52 -15
- package/lib/Utils/generics.d.ts.map +1 -1
- package/lib/Utils/generics.js +269 -25
- package/lib/Utils/generics.js.map +1 -1
- package/lib/Utils/group-stub-params.d.ts +1 -28
- package/lib/Utils/group-stub-params.d.ts.map +1 -1
- package/lib/Utils/group-stub-params.js +2 -44
- package/lib/Utils/group-stub-params.js.map +1 -1
- package/lib/Utils/identity-change-handler.d.ts +2 -0
- package/lib/Utils/identity-change-handler.d.ts.map +1 -0
- package/lib/Utils/identity-change-handler.js +4 -0
- package/lib/Utils/identity-change-handler.js.map +1 -0
- package/lib/Utils/index.d.ts +9 -0
- package/lib/Utils/index.d.ts.map +1 -1
- package/lib/Utils/index.js +19 -10
- package/lib/Utils/index.js.map +1 -1
- package/lib/Utils/logger.d.ts.map +1 -1
- package/lib/Utils/message-retry-manager.d.ts +2 -0
- package/lib/Utils/message-retry-manager.d.ts.map +1 -0
- package/lib/Utils/message-retry-manager.js +4 -0
- package/lib/Utils/message-retry-manager.js.map +1 -0
- package/lib/Utils/messages-media.d.ts +28 -6
- package/lib/Utils/messages-media.d.ts.map +1 -1
- package/lib/Utils/messages-media.js +119 -1
- package/lib/Utils/messages-media.js.map +1 -1
- package/lib/Utils/messages.d.ts +33 -9
- package/lib/Utils/messages.d.ts.map +1 -1
- package/lib/Utils/messages.js +106 -33
- package/lib/Utils/messages.js.map +1 -1
- package/lib/Utils/native-crypto-provider.d.ts +10 -8
- package/lib/Utils/native-crypto-provider.d.ts.map +1 -1
- package/lib/Utils/native-crypto-provider.js +13 -56
- package/lib/Utils/native-crypto-provider.js.map +1 -1
- package/lib/Utils/pre-key-manager.d.ts +2 -0
- package/lib/Utils/pre-key-manager.d.ts.map +1 -0
- package/lib/Utils/pre-key-manager.js +3 -0
- package/lib/Utils/pre-key-manager.js.map +1 -0
- package/lib/Utils/process-history-message.d.ts +15 -4
- package/lib/Utils/process-history-message.d.ts.map +1 -1
- package/lib/Utils/process-history-message.js +162 -95
- package/lib/Utils/process-history-message.js.map +1 -1
- package/lib/Utils/process-message.d.ts +25 -0
- package/lib/Utils/process-message.d.ts.map +1 -0
- package/lib/Utils/process-message.js +79 -0
- package/lib/Utils/process-message.js.map +1 -0
- package/lib/Utils/signal.d.ts +29 -0
- package/lib/Utils/signal.d.ts.map +1 -0
- package/lib/Utils/signal.js +133 -0
- package/lib/Utils/signal.js.map +1 -0
- package/lib/Utils/sparse-array.d.ts +9 -0
- package/lib/Utils/sparse-array.d.ts.map +1 -0
- package/lib/Utils/sparse-array.js +12 -0
- package/lib/Utils/sparse-array.js.map +1 -0
- package/lib/Utils/stanza-ack.d.ts +2 -0
- package/lib/Utils/stanza-ack.d.ts.map +1 -0
- package/lib/Utils/stanza-ack.js +3 -0
- package/lib/Utils/stanza-ack.js.map +1 -0
- package/lib/Utils/use-bridge-store.d.ts.map +1 -1
- package/lib/Utils/use-bridge-store.js +191 -7
- package/lib/Utils/use-bridge-store.js.map +1 -1
- package/lib/Utils/use-memory-store.d.ts +8 -4
- package/lib/Utils/use-memory-store.d.ts.map +1 -1
- package/lib/Utils/use-memory-store.js +87 -10
- package/lib/Utils/use-memory-store.js.map +1 -1
- package/lib/Utils/use-multi-file-auth-state.d.ts +4 -2
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +1 -1
- package/lib/Utils/use-multi-file-auth-state.js +13 -5
- package/lib/Utils/use-multi-file-auth-state.js.map +1 -1
- package/lib/Utils/wrap-legacy-store.d.ts +8 -32
- package/lib/Utils/wrap-legacy-store.d.ts.map +1 -1
- package/lib/Utils/wrap-legacy-store.js +7 -1214
- package/lib/Utils/wrap-legacy-store.js.map +1 -1
- package/lib/WABinary/generic-utils.d.ts +8 -0
- package/lib/WABinary/generic-utils.d.ts.map +1 -1
- package/lib/WABinary/generic-utils.js +63 -1
- package/lib/WABinary/generic-utils.js.map +1 -1
- package/lib/WABinary/index.js +2 -2
- package/lib/WABinary/jid-utils.d.ts +22 -10
- package/lib/WABinary/jid-utils.d.ts.map +1 -1
- package/lib/WABinary/jid-utils.js +40 -9
- package/lib/WABinary/jid-utils.js.map +1 -1
- package/lib/WAProto/compatibility-schema.d.ts +25 -0
- package/lib/WAProto/compatibility-schema.d.ts.map +1 -0
- package/lib/WAProto/compatibility-schema.js +6 -0
- package/lib/WAProto/compatibility-schema.js.map +1 -0
- package/lib/WAProto/runtime.d.ts +14019 -0
- package/lib/WAProto/runtime.js +17 -0
- package/lib/WAProto/runtime.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts +27 -0
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +39 -0
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +33 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +23 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +41 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +13 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +19 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +15 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +13 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +25 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +21 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +1 -0
- package/lib/WAUSync/Protocols/index.d.ts +6 -0
- package/lib/WAUSync/Protocols/index.d.ts.map +1 -0
- package/lib/WAUSync/Protocols/index.js +6 -0
- package/lib/WAUSync/Protocols/index.js.map +1 -0
- package/lib/WAUSync/USyncQuery.d.ts +30 -0
- package/lib/WAUSync/USyncQuery.d.ts.map +1 -0
- package/lib/WAUSync/USyncQuery.js +78 -0
- package/lib/WAUSync/USyncQuery.js.map +1 -0
- package/lib/WAUSync/USyncUser.d.ts +17 -0
- package/lib/WAUSync/USyncUser.d.ts.map +1 -0
- package/lib/WAUSync/USyncUser.js +31 -0
- package/lib/WAUSync/USyncUser.js.map +1 -0
- package/lib/WAUSync/index.d.ts +4 -0
- package/lib/WAUSync/index.d.ts.map +1 -0
- package/lib/WAUSync/index.js +4 -0
- package/lib/WAUSync/index.js.map +1 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +9 -9
- package/lib/index.js.map +1 -1
- package/package.json +33 -15
- package/lib/Bridge/__tests__/adapt.test.d.ts +0 -2
- package/lib/Bridge/__tests__/adapt.test.d.ts.map +0 -1
- package/lib/Bridge/__tests__/adapt.test.js +0 -387
- package/lib/Bridge/__tests__/adapt.test.js.map +0 -1
- package/lib/Bridge/__tests__/dts-drift.test.d.ts +0 -13
- package/lib/Bridge/__tests__/dts-drift.test.d.ts.map +0 -1
- package/lib/Bridge/__tests__/dts-drift.test.js +0 -90
- package/lib/Bridge/__tests__/dts-drift.test.js.map +0 -1
- package/lib/Bridge/__tests__/fixtures.d.ts +0 -192
- package/lib/Bridge/__tests__/fixtures.d.ts.map +0 -1
- package/lib/Bridge/__tests__/fixtures.js +0 -99
- package/lib/Bridge/__tests__/fixtures.js.map +0 -1
- package/lib/Utils/__tests__/_legacy-store-fixtures.d.ts +0 -73
- package/lib/Utils/__tests__/_legacy-store-fixtures.d.ts.map +0 -1
- package/lib/Utils/__tests__/_legacy-store-fixtures.js +0 -113
- package/lib/Utils/__tests__/_legacy-store-fixtures.js.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-coverage.test.d.ts +0 -10
- package/lib/Utils/__tests__/wrap-legacy-store-coverage.test.d.ts.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-coverage.test.js +0 -291
- package/lib/Utils/__tests__/wrap-legacy-store-coverage.test.js.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-lid-mapping.test.d.ts +0 -8
- package/lib/Utils/__tests__/wrap-legacy-store-lid-mapping.test.d.ts.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-lid-mapping.test.js +0 -91
- package/lib/Utils/__tests__/wrap-legacy-store-lid-mapping.test.js.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-sender-key.test.d.ts +0 -10
- package/lib/Utils/__tests__/wrap-legacy-store-sender-key.test.d.ts.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-sender-key.test.js +0 -125
- package/lib/Utils/__tests__/wrap-legacy-store-sender-key.test.js.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-session-ratchet.test.d.ts +0 -2
- package/lib/Utils/__tests__/wrap-legacy-store-session-ratchet.test.d.ts.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-session-ratchet.test.js +0 -214
- package/lib/Utils/__tests__/wrap-legacy-store-session-ratchet.test.js.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-session.test.d.ts +0 -14
- package/lib/Utils/__tests__/wrap-legacy-store-session.test.d.ts.map +0 -1
- package/lib/Utils/__tests__/wrap-legacy-store-session.test.js +0 -305
- package/lib/Utils/__tests__/wrap-legacy-store-session.test.js.map +0 -1
- package/lib/Utils/bridge-call.d.ts +0 -22
- package/lib/Utils/bridge-call.d.ts.map +0 -1
- package/lib/Utils/bridge-call.js +0 -105
- package/lib/Utils/bridge-call.js.map +0 -1
- package/lib/Utils/lid-mapping-store.d.ts +0 -81
- package/lib/Utils/lid-mapping-store.d.ts.map +0 -1
- package/lib/Utils/lid-mapping-store.js +0 -126
- package/lib/Utils/lid-mapping-store.js.map +0 -1
- package/lib/__tests__/expect.d.ts +0 -44
- package/lib/__tests__/expect.d.ts.map +0 -1
- package/lib/__tests__/expect.js +0 -100
- package/lib/__tests__/expect.js.map +0 -1
|
@@ -1,1218 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* MongoDB, Redis, etc.) — zero migration needed.
|
|
2
|
+
* Compatibility facade for callers that still provide Baileys
|
|
3
|
+
* `{ creds, keys }` authentication state.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* auth: { store: await wrapLegacyStore(state, saveCreds) }
|
|
10
|
-
* })
|
|
11
|
-
* ```
|
|
5
|
+
* The implementation lives in `Compatibility/legacy-store/`: the WASM bridge sees only its
|
|
6
|
+
* native byte-store contract, while every Baileys-specific projection remains
|
|
7
|
+
* in this package.
|
|
12
8
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import { mkdir, readFile, stat, unlink, writeFile } from 'node:fs/promises';
|
|
16
|
-
import { join } from 'node:path';
|
|
17
|
-
import { proto } from 'whatsapp-rust-bridge/proto-types';
|
|
18
|
-
import { jidDecode } from "../WABinary/jid-utils.js";
|
|
19
|
-
import { BufferJSON } from "./generics.js";
|
|
20
|
-
const protoLookup = proto;
|
|
21
|
-
const ADVSignedDeviceIdentity = protoLookup.ADVSignedDeviceIdentity ?? protoLookup.AdvSignedDeviceIdentity;
|
|
22
|
-
function warn(msg, err) {
|
|
23
|
-
if (_warnFn)
|
|
24
|
-
_warnFn(msg, err);
|
|
25
|
-
else
|
|
26
|
-
console.warn(`[wrapLegacyStore] ${msg}`, err ?? '');
|
|
27
|
-
}
|
|
28
|
-
let _warnFn;
|
|
29
|
-
// ---- Store routing ----
|
|
30
|
-
// Bridge store name → upstream store type name for keys.get/set.
|
|
31
|
-
// ALL data goes through the user-provided keys interface — no separate files.
|
|
32
|
-
const STORE_MAP = {
|
|
33
|
-
// Signal protocol (binary passthrough with write-through cache)
|
|
34
|
-
identity: 'identity-key',
|
|
35
|
-
session: 'session',
|
|
36
|
-
sender_key: 'sender-key',
|
|
37
|
-
// Upstream Baileys types (with format converters)
|
|
38
|
-
prekey: 'pre-key',
|
|
39
|
-
sync_key: 'app-state-sync-key',
|
|
40
|
-
sync_version: 'app-state-sync-version',
|
|
41
|
-
tc_token: 'tctoken',
|
|
42
|
-
device_list: 'device-list',
|
|
43
|
-
// Bridge-only (stored as raw Buffers with their own type prefix)
|
|
44
|
-
lid_mapping: 'lid-mapping',
|
|
45
|
-
signed_prekey: 'bridge-signed-prekey',
|
|
46
|
-
sender_key_devices: 'bridge-sender-key-devices',
|
|
47
|
-
base_key: 'bridge-base-key',
|
|
48
|
-
sent_message: 'bridge-sent-message',
|
|
49
|
-
mutation_mac: 'bridge-mutation-mac',
|
|
50
|
-
meta: 'bridge-meta'
|
|
51
|
-
};
|
|
52
|
-
// Stores that are byte-compatible between bridge and upstream and so can
|
|
53
|
-
// be persisted unchanged. Currently empty — every Signal record needs
|
|
54
|
-
// either a key rewrite or a value-byte conversion, both handled by
|
|
55
|
-
// `converters` below.
|
|
56
|
-
const BINARY_STORES = new Set();
|
|
57
|
-
// Bridge-only stores — raw binary persisted through the keys interface.
|
|
58
|
-
// Derived from STORE_MAP: anything mapped to a `bridge-*` upstream type
|
|
59
|
-
// has no peer in upstream Baileys' SignalDataTypeMap and must round-trip
|
|
60
|
-
// as raw bytes. `lid_mapping` is mapped to upstream's `lid-mapping` type
|
|
61
|
-
// instead (its converter rewrites the key prefixes), so it's not
|
|
62
|
-
// bridge-only and is naturally excluded by the prefix filter.
|
|
63
|
-
const BRIDGE_ONLY_STORES = new Set(Object.entries(STORE_MAP)
|
|
64
|
-
.filter(([, upstreamType]) => upstreamType.startsWith('bridge-'))
|
|
65
|
-
.map(([bridgeName]) => bridgeName));
|
|
66
|
-
/** Reconstruct a JID string from the bridge's serialized Jid object.
|
|
67
|
-
* Format: `user[_<agent>][:<device>]@<server>`. The agent suffix is
|
|
68
|
-
* required to round-trip hosted Business accounts (`5511_2@hosted`) —
|
|
69
|
-
* `credsToDeviceJson` stores it, so the load path must also emit it.
|
|
70
|
-
* Without this, `creds.me.id` would lose the `_<agent>` half on every
|
|
71
|
-
* reload and the next `credsToDeviceJson` save would zero `agent`. */
|
|
72
|
-
function bridgeJidToString(j) {
|
|
73
|
-
if (!j?.user || !j?.server)
|
|
74
|
-
return null;
|
|
75
|
-
const agent = j.agent ?? 0;
|
|
76
|
-
const device = j.device ?? 0;
|
|
77
|
-
return `${j.user}${agent > 0 ? '_' + agent : ''}${device > 0 ? ':' + device : ''}@${j.server}`;
|
|
78
|
-
}
|
|
79
|
-
// ---- Helpers ----
|
|
80
|
-
const toJson = (v) => new TextEncoder().encode(JSON.stringify(v));
|
|
81
|
-
const fromJson = (b) => JSON.parse(new TextDecoder().decode(b));
|
|
82
|
-
const toBuf = (v) => v instanceof Uint8Array ? v : Buffer.isBuffer(v) ? new Uint8Array(v) : null;
|
|
83
|
-
/** Convert Buffer/Uint8Array to a plain number[] for JSON serialization.
|
|
84
|
-
* Matches Rust's serde_json Vec<u8> format: [byte, byte, ...] */
|
|
85
|
-
const bufToNumArray = (v) => Array.from(Buffer.from(v));
|
|
86
|
-
/**
|
|
87
|
-
* `true` when the key bytes are absent or all zeros. Used at the device-read
|
|
88
|
-
* boundary to detect a partially-hydrated creds object (e.g. migration
|
|
89
|
-
* remnants where only `me.id` survived) and tell the bridge to bootstrap
|
|
90
|
-
* fresh material instead of blowing up the noise handshake with `precondition-required`.
|
|
91
|
-
*/
|
|
92
|
-
const isZeroKey = (b) => {
|
|
93
|
-
if (!b)
|
|
94
|
-
return true;
|
|
95
|
-
// Buffer is a Uint8Array subclass at runtime, so this view is always safe.
|
|
96
|
-
const view = b;
|
|
97
|
-
if (view.length === 0)
|
|
98
|
-
return true;
|
|
99
|
-
for (let i = 0; i < view.length; i++)
|
|
100
|
-
if (view[i] !== 0)
|
|
101
|
-
return false;
|
|
102
|
-
return true;
|
|
103
|
-
};
|
|
104
|
-
/** Bridge uses hex-encoded key IDs for sync_key; upstream uses base64. Convert hex→base64. */
|
|
105
|
-
const hexToBase64 = (hex) => Buffer.from(hex, 'hex').toString('base64');
|
|
106
|
-
const converters = {
|
|
107
|
-
prekey: {
|
|
108
|
-
toBridge(key, value) {
|
|
109
|
-
if (value instanceof Uint8Array || Buffer.isBuffer(value))
|
|
110
|
-
return toBuf(value);
|
|
111
|
-
const kp = value;
|
|
112
|
-
return kp.private && kp.public
|
|
113
|
-
? encodePreKeyRecord(parseInt(key) || 0, Buffer.from(kp.public), Buffer.from(kp.private))
|
|
114
|
-
: null;
|
|
115
|
-
},
|
|
116
|
-
fromBridge(_key, value) {
|
|
117
|
-
return decodePreKeyRecord(value) ?? Buffer.from(value);
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
sync_key: {
|
|
121
|
-
toBridge(_key, value) {
|
|
122
|
-
if (value instanceof Uint8Array || Buffer.isBuffer(value))
|
|
123
|
-
return toBuf(value);
|
|
124
|
-
// Rust AppStateSyncKey: key_data=Vec<u8>, fingerprint=Vec<u8> (protobuf-encoded),
|
|
125
|
-
// timestamp=i64. serde_json serializes Vec<u8> as array of numbers.
|
|
126
|
-
const msg = value;
|
|
127
|
-
const fingerprintBytes = msg.fingerprint
|
|
128
|
-
? proto.Message.AppStateSyncKeyFingerprint.encode(proto.Message.AppStateSyncKeyFingerprint.create(msg.fingerprint)).finish()
|
|
129
|
-
: null;
|
|
130
|
-
return toJson({
|
|
131
|
-
key_data: msg.keyData ? bufToNumArray(Buffer.from(msg.keyData)) : [],
|
|
132
|
-
fingerprint: fingerprintBytes ? bufToNumArray(fingerprintBytes) : [],
|
|
133
|
-
timestamp: Number(msg.timestamp ?? 0)
|
|
134
|
-
});
|
|
135
|
-
},
|
|
136
|
-
fromBridge(_key, value) {
|
|
137
|
-
try {
|
|
138
|
-
const j = fromJson(value);
|
|
139
|
-
const keyData = Array.isArray(j.key_data) ? Buffer.from(j.key_data) : undefined;
|
|
140
|
-
const fingerprint = Array.isArray(j.fingerprint) && j.fingerprint.length > 0
|
|
141
|
-
? proto.Message.AppStateSyncKeyFingerprint.decode(Buffer.from(j.fingerprint))
|
|
142
|
-
: undefined;
|
|
143
|
-
return proto.Message.AppStateSyncKeyData.fromObject({
|
|
144
|
-
keyData,
|
|
145
|
-
fingerprint,
|
|
146
|
-
timestamp: j.timestamp ?? 0
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
return Buffer.from(value);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
},
|
|
154
|
-
sync_version: {
|
|
155
|
-
toBridge(_key, value) {
|
|
156
|
-
if (value instanceof Uint8Array || Buffer.isBuffer(value))
|
|
157
|
-
return toBuf(value);
|
|
158
|
-
// Rust HashState: version=u64, hash=[u8;128] (BigArray → number array),
|
|
159
|
-
// index_value_map=HashMap<String, Vec<u8>> (snake_case, plain byte arrays).
|
|
160
|
-
// Upstream LTHashState: hash=Buffer, indexValueMap={[k]: {valueMac: Buffer}} (camelCase, wrapped).
|
|
161
|
-
const v = value;
|
|
162
|
-
const indexValueMap = {};
|
|
163
|
-
if (v.indexValueMap) {
|
|
164
|
-
for (const [k, entry] of Object.entries(v.indexValueMap)) {
|
|
165
|
-
indexValueMap[k] = bufToNumArray(Buffer.from(entry.valueMac));
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return toJson({
|
|
169
|
-
version: v.version ?? 0,
|
|
170
|
-
hash: v.hash ? bufToNumArray(Buffer.from(v.hash)) : Array(128).fill(0),
|
|
171
|
-
index_value_map: indexValueMap
|
|
172
|
-
});
|
|
173
|
-
},
|
|
174
|
-
fromBridge(_key, value) {
|
|
175
|
-
try {
|
|
176
|
-
const j = fromJson(value);
|
|
177
|
-
const indexValueMap = {};
|
|
178
|
-
if (j.index_value_map) {
|
|
179
|
-
for (const [k, v] of Object.entries(j.index_value_map)) {
|
|
180
|
-
indexValueMap[k] = { valueMac: Buffer.from(v) };
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return {
|
|
184
|
-
version: j.version ?? 0,
|
|
185
|
-
hash: Buffer.from(j.hash ?? []),
|
|
186
|
-
indexValueMap
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
catch {
|
|
190
|
-
return Buffer.from(value);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
tc_token: {
|
|
195
|
-
toBridge(_key, value) {
|
|
196
|
-
// Rust `TcTokenEntry { token: Vec<u8>, token_timestamp: i64,
|
|
197
|
-
// sender_timestamp: Option<i64> }`. serde_json maps Vec<u8> to a
|
|
198
|
-
// numeric array — base64 strings make the deserializer choke
|
|
199
|
-
// with "invalid type: string ... expected a sequence".
|
|
200
|
-
const tc = value;
|
|
201
|
-
return toJson({
|
|
202
|
-
token: tc.token ? bufToNumArray(Buffer.from(tc.token)) : [],
|
|
203
|
-
token_timestamp: tc.timestamp ? parseInt(tc.timestamp) : 0,
|
|
204
|
-
sender_timestamp: tc.senderTimestamp ? parseInt(tc.senderTimestamp) : null
|
|
205
|
-
});
|
|
206
|
-
},
|
|
207
|
-
fromBridge(_key, value) {
|
|
208
|
-
try {
|
|
209
|
-
const j = fromJson(value);
|
|
210
|
-
return {
|
|
211
|
-
token: Array.isArray(j.token) ? Buffer.from(j.token) : Buffer.alloc(0),
|
|
212
|
-
timestamp: j.token_timestamp?.toString(),
|
|
213
|
-
senderTimestamp: j.sender_timestamp != null ? j.sender_timestamp.toString() : undefined
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
catch {
|
|
217
|
-
return { token: Buffer.from(value) };
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
device_list: {
|
|
222
|
-
toBridge(key, value) {
|
|
223
|
-
const list = value;
|
|
224
|
-
return toJson({
|
|
225
|
-
user: key,
|
|
226
|
-
devices: list.map(id => ({ device_id: parseInt(id) || 0 })),
|
|
227
|
-
timestamp: Math.floor(Date.now() / 1000)
|
|
228
|
-
});
|
|
229
|
-
},
|
|
230
|
-
fromBridge(_key, value) {
|
|
231
|
-
try {
|
|
232
|
-
const r = fromJson(value);
|
|
233
|
-
const items = r.devices ?? [];
|
|
234
|
-
return items.map(d => String(d.device_id ?? 0));
|
|
235
|
-
}
|
|
236
|
-
catch {
|
|
237
|
-
return [];
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
|
-
// identity: bridge holds 32-byte raw DJB pubkey, upstream holds 33 bytes
|
|
242
|
-
// (0x05 || 32-byte) — the curve25519-XEdDSA wire form.
|
|
243
|
-
identity: {
|
|
244
|
-
toBridge(_key, value) {
|
|
245
|
-
const buf = toBuf(value);
|
|
246
|
-
if (!buf)
|
|
247
|
-
return null;
|
|
248
|
-
return buf.length === 33 && buf[0] === 0x05 ? new Uint8Array(buf.slice(1)) : buf;
|
|
249
|
-
},
|
|
250
|
-
fromBridge(_key, value) {
|
|
251
|
-
const v = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
252
|
-
return v.length === 32 ? Buffer.concat([Buffer.from([0x05]), v]) : Buffer.from(v);
|
|
253
|
-
}
|
|
254
|
-
},
|
|
255
|
-
// lid_mapping: bridge uses prefixed keys (`lid:{X}` JSON entry,
|
|
256
|
-
// `pn:{X}` raw LID bytes); upstream uses bare keys (`{pnUser}` string LID,
|
|
257
|
-
// `{lidUser}_reverse` string PN). No upstream timestamps; we synthesise.
|
|
258
|
-
lid_mapping: {
|
|
259
|
-
toBridge(key, value) {
|
|
260
|
-
try {
|
|
261
|
-
const asString = typeof value === 'string' ? value : Buffer.from(value).toString('utf-8');
|
|
262
|
-
if (!asString)
|
|
263
|
-
return null;
|
|
264
|
-
if (key.startsWith('pn:'))
|
|
265
|
-
return new TextEncoder().encode(asString);
|
|
266
|
-
if (key.startsWith('lid:')) {
|
|
267
|
-
const now = Math.floor(Date.now() / 1000);
|
|
268
|
-
return toJson({
|
|
269
|
-
lid: key.slice(4),
|
|
270
|
-
phone_number: asString,
|
|
271
|
-
created_at: now,
|
|
272
|
-
updated_at: now,
|
|
273
|
-
learning_source: 'wrap-legacy-store'
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
warn(`lid_mapping.toBridge: unknown key prefix in "${key}"`);
|
|
277
|
-
return null;
|
|
278
|
-
}
|
|
279
|
-
catch (e) {
|
|
280
|
-
warn('lid_mapping.toBridge failed:', e);
|
|
281
|
-
return null;
|
|
282
|
-
}
|
|
283
|
-
},
|
|
284
|
-
fromBridge(key, value) {
|
|
285
|
-
try {
|
|
286
|
-
if (key.startsWith('pn:'))
|
|
287
|
-
return Buffer.from(value).toString('utf-8');
|
|
288
|
-
if (key.startsWith('lid:')) {
|
|
289
|
-
const entry = fromJson(value);
|
|
290
|
-
return entry.phone_number ?? '';
|
|
291
|
-
}
|
|
292
|
-
warn(`lid_mapping.fromBridge: unknown key prefix in "${key}"`);
|
|
293
|
-
return Buffer.from(value);
|
|
294
|
-
}
|
|
295
|
-
catch (e) {
|
|
296
|
-
warn('lid_mapping.fromBridge failed:', e);
|
|
297
|
-
return Buffer.from(value);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
// session: bridge=protobuf RecordStructure, upstream=JS object
|
|
302
|
-
// `{_sessions: {[b64BaseKey]: SessionEntry}, version: 'v1'}` with byte
|
|
303
|
-
// fields stored as base64 strings inside the entry. messageKeys cache
|
|
304
|
-
// is lossy in the Rust→JS direction (HKDF is one-way) — see
|
|
305
|
-
// `bridgeSessionProtoToUpstreamRecord`.
|
|
306
|
-
session: {
|
|
307
|
-
toBridge(_key, value) {
|
|
308
|
-
try {
|
|
309
|
-
if (value == null)
|
|
310
|
-
return null;
|
|
311
|
-
return upstreamSessionRecordToProto(value);
|
|
312
|
-
}
|
|
313
|
-
catch (e) {
|
|
314
|
-
warn('session.toBridge encode failed:', e);
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
},
|
|
318
|
-
fromBridge(_key, value) {
|
|
319
|
-
try {
|
|
320
|
-
return bridgeSessionProtoToUpstreamRecord(value);
|
|
321
|
-
}
|
|
322
|
-
catch (e) {
|
|
323
|
-
warn('session.fromBridge decode failed:', e);
|
|
324
|
-
return Buffer.from(value);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
},
|
|
328
|
-
// sender_key: bridge=protobuf SenderKeyRecordStructure, upstream=
|
|
329
|
-
// `Buffer.from(JSON.stringify(states, BufferJSON.replacer), 'utf-8')`
|
|
330
|
-
// — Buffer fields wrapped as `{type:'Buffer', data:'<base64>'}`.
|
|
331
|
-
sender_key: {
|
|
332
|
-
toBridge(_key, value) {
|
|
333
|
-
try {
|
|
334
|
-
const buf = toBuf(value);
|
|
335
|
-
if (!buf)
|
|
336
|
-
return null;
|
|
337
|
-
return upstreamSenderKeyJsonToProto(buf);
|
|
338
|
-
}
|
|
339
|
-
catch (e) {
|
|
340
|
-
warn('sender_key.toBridge decode failed:', e);
|
|
341
|
-
return null;
|
|
342
|
-
}
|
|
343
|
-
},
|
|
344
|
-
fromBridge(_key, value) {
|
|
345
|
-
try {
|
|
346
|
-
return bridgeSenderKeyProtoToJson(value);
|
|
347
|
-
}
|
|
348
|
-
catch (e) {
|
|
349
|
-
warn('sender_key.fromBridge encode failed:', e);
|
|
350
|
-
return Buffer.from(value);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
const sk_toBytes = (v) => v ? new Uint8Array(Buffer.from(v)) : new Uint8Array();
|
|
356
|
-
const sk_toBuffer = (v) => Buffer.from(v ?? new Uint8Array());
|
|
357
|
-
function bridgeSenderKeyProtoToJson(protoBytes) {
|
|
358
|
-
const struct = proto.SenderKeyRecordStructure.decode(Buffer.from(protoBytes));
|
|
359
|
-
const states = (struct.senderKeyStates ?? []).map(s => ({
|
|
360
|
-
senderKeyId: s.senderKeyId ?? 0,
|
|
361
|
-
senderChainKey: { iteration: s.senderChainKey?.iteration ?? 0, seed: sk_toBuffer(s.senderChainKey?.seed) },
|
|
362
|
-
senderSigningKey: {
|
|
363
|
-
public: sk_toBuffer(s.senderSigningKey?.public),
|
|
364
|
-
private: sk_toBuffer(s.senderSigningKey?.private)
|
|
365
|
-
},
|
|
366
|
-
senderMessageKeys: (s.senderMessageKeys ?? []).map(mk => ({
|
|
367
|
-
iteration: mk.iteration ?? 0,
|
|
368
|
-
seed: sk_toBuffer(mk.seed)
|
|
369
|
-
}))
|
|
370
|
-
}));
|
|
371
|
-
return Buffer.from(JSON.stringify(states, BufferJSON.replacer), 'utf-8');
|
|
372
|
-
}
|
|
373
|
-
function upstreamSenderKeyJsonToProto(jsonBuf) {
|
|
374
|
-
const states = JSON.parse(Buffer.from(jsonBuf).toString('utf-8'), BufferJSON.reviver);
|
|
375
|
-
const senderKeyStates = states.map(s => ({
|
|
376
|
-
senderKeyId: s.senderKeyId ?? 0,
|
|
377
|
-
senderChainKey: { iteration: s.senderChainKey?.iteration ?? 0, seed: sk_toBytes(s.senderChainKey?.seed) },
|
|
378
|
-
senderSigningKey: {
|
|
379
|
-
public: sk_toBytes(s.senderSigningKey?.public),
|
|
380
|
-
private: sk_toBytes(s.senderSigningKey?.private)
|
|
381
|
-
},
|
|
382
|
-
senderMessageKeys: (s.senderMessageKeys ?? []).map(mk => ({
|
|
383
|
-
iteration: mk.iteration ?? 0,
|
|
384
|
-
seed: sk_toBytes(mk.seed)
|
|
385
|
-
}))
|
|
386
|
-
}));
|
|
387
|
-
return proto.SenderKeyRecordStructure.encode(proto.SenderKeyRecordStructure.create({ senderKeyStates })).finish();
|
|
388
|
-
}
|
|
389
|
-
// sender_key key translation: bridge `{group}:{user}[:dev]@{server}.{sig}`
|
|
390
|
-
// → upstream `{group}::{signalUser}::{deviceId}`. Group JIDs never contain
|
|
391
|
-
// `:`, so the first `:` separates group from sender address.
|
|
392
|
-
function bridgeSenderKeyToUpstream(bridgeKey) {
|
|
393
|
-
const sep = bridgeKey.indexOf(':');
|
|
394
|
-
if (sep < 0)
|
|
395
|
-
return null;
|
|
396
|
-
const groupJid = bridgeKey.slice(0, sep);
|
|
397
|
-
const addrStr = bridgeKey.slice(sep + 1);
|
|
398
|
-
const dotIdx = addrStr.lastIndexOf('.');
|
|
399
|
-
if (dotIdx < 0)
|
|
400
|
-
return null;
|
|
401
|
-
const jidPart = addrStr.slice(0, dotIdx);
|
|
402
|
-
const atIdx = jidPart.indexOf('@');
|
|
403
|
-
if (atIdx < 0)
|
|
404
|
-
return null;
|
|
405
|
-
const userPart = jidPart.slice(0, atIdx);
|
|
406
|
-
const server = jidPart.slice(atIdx + 1);
|
|
407
|
-
const [user, jidDev] = userPart.includes(':')
|
|
408
|
-
? [userPart.slice(0, userPart.indexOf(':')), parseInt(userPart.slice(userPart.indexOf(':') + 1), 10) || 0]
|
|
409
|
-
: [userPart, 0];
|
|
410
|
-
const domainType = DOMAIN_TYPE_MAP[server];
|
|
411
|
-
if (domainType === undefined)
|
|
412
|
-
return null;
|
|
413
|
-
return `${groupJid}::${domainType !== 0 ? `${user}_${domainType}` : user}::${jidDev}`;
|
|
414
|
-
}
|
|
415
|
-
const CHAIN_TYPE_SENDING = 1;
|
|
416
|
-
const CHAIN_TYPE_RECEIVING = 2;
|
|
417
|
-
const BASE_KEY_TYPE_OURS = 1;
|
|
418
|
-
const BASE_KEY_TYPE_THEIRS = 2;
|
|
419
|
-
// Non-nullable to keep the empty-vs-missing distinction visible at call sites.
|
|
420
|
-
const b64 = (b) => Buffer.from(b).toString('base64');
|
|
421
|
-
const fromB64 = (s) => Buffer.from(s, 'base64');
|
|
422
|
-
const EMPTY_BYTES = new Uint8Array();
|
|
423
|
-
// Rust `chain_key.index` and JS `chainKey.counter` differ by 1 (fresh = 0 vs -1).
|
|
424
|
-
const rustIndexToJsCounter = (index) => (index ?? 0) - 1;
|
|
425
|
-
const jsCounterToRustIndex = (counter) => counter + 1;
|
|
426
|
-
/**
|
|
427
|
-
* Derive Rust's per-message split (cipher 32 / mac 32 / iv 16) from JS's
|
|
428
|
-
* 32-byte `messageKey` seed. Both impls compute HKDF-SHA256 with
|
|
429
|
-
* salt=[0u8;32] and info="WhisperMessageKeys" — Rust's `None` salt
|
|
430
|
-
* defaults to a zero-byte HashLen string, so the output is byte-identical.
|
|
431
|
-
* Reverse direction (Rust→JS) is impossible: HKDF is one-way.
|
|
432
|
-
*/
|
|
433
|
-
function deriveProtoMessageKey(seed, counter) {
|
|
434
|
-
const prk = createHmac('sha256', Buffer.alloc(32)).update(seed).digest();
|
|
435
|
-
const info = Buffer.from('WhisperMessageKeys');
|
|
436
|
-
const expand = (prev, n) => createHmac('sha256', prk)
|
|
437
|
-
.update(Buffer.concat([prev, info, Buffer.from([n])]))
|
|
438
|
-
.digest();
|
|
439
|
-
const t1 = expand(Buffer.alloc(0), 0x01);
|
|
440
|
-
const t2 = expand(t1, 0x02);
|
|
441
|
-
const t3 = expand(t2, 0x03);
|
|
442
|
-
// Message keys use the same counter/index value in both impls — only the
|
|
443
|
-
// chain key has the off-by-one (see `rustIndexToJsCounter`).
|
|
444
|
-
return {
|
|
445
|
-
index: counter,
|
|
446
|
-
cipherKey: new Uint8Array(t1),
|
|
447
|
-
macKey: new Uint8Array(t2),
|
|
448
|
-
iv: new Uint8Array(t3.subarray(0, 16))
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
function jsChainMessageKeysToProto(messageKeys) {
|
|
452
|
-
if (!messageKeys)
|
|
453
|
-
return [];
|
|
454
|
-
const out = [];
|
|
455
|
-
for (const [counterStr, seedB64] of Object.entries(messageKeys)) {
|
|
456
|
-
const counter = parseInt(counterStr, 10);
|
|
457
|
-
if (!Number.isFinite(counter))
|
|
458
|
-
continue;
|
|
459
|
-
const seed = fromB64(seedB64);
|
|
460
|
-
if (seed.length > 0)
|
|
461
|
-
out.push(deriveProtoMessageKey(seed, counter));
|
|
462
|
-
}
|
|
463
|
-
return out;
|
|
464
|
-
}
|
|
465
|
-
function sessionStructureToEntry(session, closedTs) {
|
|
466
|
-
if (!session.senderChain || !session.rootKey)
|
|
467
|
-
return null;
|
|
468
|
-
// aliceBaseKey is set by Rust on BOTH sides (alice=our ephemeral, bob=
|
|
469
|
-
// peer's ephemeral). pendingPreKey is the side discriminator (alice
|
|
470
|
-
// only, cleared on first reply).
|
|
471
|
-
const baseKeyBytes = session.aliceBaseKey ?? session.senderChain.senderRatchetKey;
|
|
472
|
-
if (!baseKeyBytes)
|
|
473
|
-
return null;
|
|
474
|
-
const weAreAlice = !!session.pendingPreKey?.baseKey;
|
|
475
|
-
const baseKeyType = weAreAlice ? BASE_KEY_TYPE_OURS : BASE_KEY_TYPE_THEIRS;
|
|
476
|
-
// lastRemoteEphemeralKey precedence: tail receiverChain → aliceBaseKey
|
|
477
|
-
// (when bob, matches JS init) → empty. NEVER senderRatchetKey: that
|
|
478
|
-
// collides with the SENDER chain in `_chains`, and upstream's
|
|
479
|
-
// `maybeStepRatchet` would `delete previousRatchet.chainKey.key` on
|
|
480
|
-
// the sender chain when the peer ratchets, corrupting outbound encryption.
|
|
481
|
-
const receiverChains = session.receiverChains ?? [];
|
|
482
|
-
const lastReceiver = receiverChains[receiverChains.length - 1];
|
|
483
|
-
const lastRemoteEph = lastReceiver?.senderRatchetKey && lastReceiver.senderRatchetKey.length > 0
|
|
484
|
-
? lastReceiver.senderRatchetKey
|
|
485
|
-
: !weAreAlice && session.aliceBaseKey && session.aliceBaseKey.length > 0
|
|
486
|
-
? session.aliceBaseKey
|
|
487
|
-
: EMPTY_BYTES;
|
|
488
|
-
const senderRatchetPub = session.senderChain.senderRatchetKey ?? EMPTY_BYTES;
|
|
489
|
-
const senderRatchetPriv = session.senderChain.senderRatchetKeyPrivate ?? EMPTY_BYTES;
|
|
490
|
-
const _chains = {};
|
|
491
|
-
const senderChainKey = session.senderChain.chainKey;
|
|
492
|
-
if (senderChainKey?.key?.length && senderRatchetPub.length > 0) {
|
|
493
|
-
_chains[b64(senderRatchetPub)] = {
|
|
494
|
-
chainKey: { counter: rustIndexToJsCounter(senderChainKey.index), key: b64(senderChainKey.key) },
|
|
495
|
-
chainType: CHAIN_TYPE_SENDING,
|
|
496
|
-
messageKeys: {}
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
for (const rc of receiverChains) {
|
|
500
|
-
if (!rc.chainKey?.key?.length || !rc.senderRatchetKey?.length)
|
|
501
|
-
continue;
|
|
502
|
-
_chains[b64(rc.senderRatchetKey)] = {
|
|
503
|
-
chainKey: { counter: rustIndexToJsCounter(rc.chainKey.index), key: b64(rc.chainKey.key) },
|
|
504
|
-
chainType: CHAIN_TYPE_RECEIVING,
|
|
505
|
-
messageKeys: {}
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
const now = Date.now();
|
|
509
|
-
const entry = {
|
|
510
|
-
registrationId: session.remoteRegistrationId ?? 0,
|
|
511
|
-
currentRatchet: {
|
|
512
|
-
ephemeralKeyPair: { pubKey: b64(senderRatchetPub), privKey: b64(senderRatchetPriv) },
|
|
513
|
-
lastRemoteEphemeralKey: b64(lastRemoteEph),
|
|
514
|
-
previousCounter: session.previousCounter ?? 0,
|
|
515
|
-
rootKey: b64(session.rootKey)
|
|
516
|
-
},
|
|
517
|
-
indexInfo: {
|
|
518
|
-
baseKey: b64(baseKeyBytes),
|
|
519
|
-
baseKeyType,
|
|
520
|
-
closed: closedTs,
|
|
521
|
-
used: now,
|
|
522
|
-
created: now,
|
|
523
|
-
remoteIdentityKey: b64(session.remoteIdentityPublic ?? EMPTY_BYTES)
|
|
524
|
-
},
|
|
525
|
-
_chains
|
|
526
|
-
};
|
|
527
|
-
if (session.pendingPreKey?.baseKey) {
|
|
528
|
-
entry.pendingPreKey = {
|
|
529
|
-
preKeyId: session.pendingPreKey.preKeyId ?? undefined,
|
|
530
|
-
signedKeyId: session.pendingPreKey.signedPreKeyId ?? undefined,
|
|
531
|
-
baseKey: b64(session.pendingPreKey.baseKey)
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
return entry;
|
|
535
|
-
}
|
|
536
|
-
function bridgeSessionProtoToUpstreamRecord(protoBytes) {
|
|
537
|
-
const record = proto.RecordStructure.decode(Buffer.from(protoBytes));
|
|
538
|
-
const _sessions = {};
|
|
539
|
-
const current = record.currentSession ? sessionStructureToEntry(record.currentSession, -1) : null;
|
|
540
|
-
if (current)
|
|
541
|
-
_sessions[current.indexInfo.baseKey] = current;
|
|
542
|
-
// Synthesize descending close timestamps so removeOldSessions can sort:
|
|
543
|
-
// front of Rust `previous_sessions` is the most recently archived.
|
|
544
|
-
const previous = record.previousSessions ?? [];
|
|
545
|
-
for (let i = 0; i < previous.length; i++) {
|
|
546
|
-
const entry = sessionStructureToEntry(previous[i], Math.max(1, Date.now() - i));
|
|
547
|
-
if (entry && !_sessions[entry.indexInfo.baseKey])
|
|
548
|
-
_sessions[entry.indexInfo.baseKey] = entry;
|
|
549
|
-
}
|
|
550
|
-
return { _sessions, version: 'v1' };
|
|
551
|
-
}
|
|
552
|
-
function entryToSessionStructure(entry) {
|
|
553
|
-
const ratchet = entry.currentRatchet;
|
|
554
|
-
const senderRatchetPub = fromB64(ratchet.ephemeralKeyPair.pubKey);
|
|
555
|
-
const senderRatchetPriv = fromB64(ratchet.ephemeralKeyPair.privKey);
|
|
556
|
-
const senderKeyB64 = senderRatchetPub.toString('base64');
|
|
557
|
-
const senderChainEntry = entry._chains[senderKeyB64];
|
|
558
|
-
const senderChain = {
|
|
559
|
-
senderRatchetKey: new Uint8Array(senderRatchetPub),
|
|
560
|
-
senderRatchetKeyPrivate: new Uint8Array(senderRatchetPriv),
|
|
561
|
-
chainKey: senderChainEntry
|
|
562
|
-
? {
|
|
563
|
-
index: jsCounterToRustIndex(senderChainEntry.chainKey.counter),
|
|
564
|
-
key: new Uint8Array(fromB64(senderChainEntry.chainKey.key))
|
|
565
|
-
}
|
|
566
|
-
: { index: 0, key: EMPTY_BYTES },
|
|
567
|
-
messageKeys: [] // sender chain is sequential — no skipped cache either side
|
|
568
|
-
};
|
|
569
|
-
const receiverChains = [];
|
|
570
|
-
for (const [k, ch] of Object.entries(entry._chains)) {
|
|
571
|
-
if (ch.chainType !== CHAIN_TYPE_RECEIVING)
|
|
572
|
-
continue;
|
|
573
|
-
receiverChains.push({
|
|
574
|
-
senderRatchetKey: new Uint8Array(fromB64(k)),
|
|
575
|
-
chainKey: { index: jsCounterToRustIndex(ch.chainKey.counter), key: new Uint8Array(fromB64(ch.chainKey.key)) },
|
|
576
|
-
// JS holds 32-byte HMAC seeds; Rust holds the post-HKDF split.
|
|
577
|
-
// Lossless JS→Rust derivation via deriveProtoMessageKey.
|
|
578
|
-
messageKeys: jsChainMessageKeysToProto(ch.messageKeys)
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
// `indexInfo.baseKey` IS the alice_base_key in either direction
|
|
582
|
-
// (alice=our ephemeral, bob=peer's ephemeral). Rust populates it
|
|
583
|
-
// symmetrically; dropping it would break find_matching_previous_session_index.
|
|
584
|
-
const session = {
|
|
585
|
-
rootKey: new Uint8Array(fromB64(ratchet.rootKey)),
|
|
586
|
-
previousCounter: ratchet.previousCounter,
|
|
587
|
-
senderChain,
|
|
588
|
-
receiverChains,
|
|
589
|
-
remoteIdentityPublic: new Uint8Array(fromB64(entry.indexInfo.remoteIdentityKey)),
|
|
590
|
-
remoteRegistrationId: entry.registrationId ?? 0,
|
|
591
|
-
aliceBaseKey: new Uint8Array(fromB64(entry.indexInfo.baseKey))
|
|
592
|
-
};
|
|
593
|
-
if (entry.pendingPreKey?.baseKey) {
|
|
594
|
-
session.pendingPreKey = {
|
|
595
|
-
preKeyId: entry.pendingPreKey.preKeyId ?? null,
|
|
596
|
-
signedPreKeyId: entry.pendingPreKey.signedKeyId ?? null,
|
|
597
|
-
baseKey: new Uint8Array(fromB64(entry.pendingPreKey.baseKey))
|
|
598
|
-
};
|
|
599
|
-
}
|
|
600
|
-
return session;
|
|
601
|
-
}
|
|
602
|
-
function upstreamSessionRecordToProto(record) {
|
|
603
|
-
const sessions = record?._sessions ?? {};
|
|
604
|
-
let currentSession = null;
|
|
605
|
-
const previousSessions = [];
|
|
606
|
-
for (const entry of Object.values(sessions)) {
|
|
607
|
-
const ss = entryToSessionStructure(entry);
|
|
608
|
-
if (!currentSession && entry.indexInfo.closed === -1)
|
|
609
|
-
currentSession = ss;
|
|
610
|
-
else
|
|
611
|
-
previousSessions.push(ss);
|
|
612
|
-
}
|
|
613
|
-
const recordOut = proto.RecordStructure.create({
|
|
614
|
-
currentSession: currentSession ?? undefined,
|
|
615
|
-
previousSessions
|
|
616
|
-
});
|
|
617
|
-
return proto.RecordStructure.encode(recordOut).finish();
|
|
618
|
-
}
|
|
619
|
-
// session/identity key translation: bridge `{user}[:dev]@{server}.{sig}`
|
|
620
|
-
// → upstream `{signalUser}.{deviceId}` via `bridgeAddrToBaileysAddr`.
|
|
621
|
-
// ---- Device/Creds ----
|
|
622
|
-
/**
|
|
623
|
-
* Extract the literal `_<n>` agent suffix from a raw JID. `jidDecode`
|
|
624
|
-
* folds it into `domainType` only for plain `s.whatsapp.net`; for special
|
|
625
|
-
* servers (`hosted`, `hosted.lid`) it is parsed-then-discarded because
|
|
626
|
-
* `domainType` is taken from the server. The bridge's `Jid.agent`
|
|
627
|
-
* field needs the literal number, so recover it here.
|
|
628
|
-
*/
|
|
629
|
-
function jidAgent(rawJid) {
|
|
630
|
-
if (!rawJid)
|
|
631
|
-
return 0;
|
|
632
|
-
const atIdx = rawJid.indexOf('@');
|
|
633
|
-
if (atIdx < 0)
|
|
634
|
-
return 0;
|
|
635
|
-
const userPart = rawJid.slice(0, atIdx).split(':', 1)[0];
|
|
636
|
-
if (!userPart)
|
|
637
|
-
return 0;
|
|
638
|
-
const sepIdx = userPart.indexOf('_');
|
|
639
|
-
if (sepIdx < 0)
|
|
640
|
-
return 0;
|
|
641
|
-
const n = parseInt(userPart.slice(sepIdx + 1), 10);
|
|
642
|
-
return Number.isFinite(n) ? n : 0;
|
|
643
|
-
}
|
|
644
|
-
function credsToDeviceJson(creds) {
|
|
645
|
-
/** Serialize a key pair as [private(32) + public(32)] matching Rust key_pair_serde */
|
|
646
|
-
const kp = (pair) => {
|
|
647
|
-
if (!pair)
|
|
648
|
-
return Array(64).fill(0);
|
|
649
|
-
return bufToNumArray(Buffer.from(pair.private)).concat(bufToNumArray(Buffer.from(pair.public)));
|
|
650
|
-
};
|
|
651
|
-
const pnJid = jidDecode(creds.me?.id);
|
|
652
|
-
const lidJid = jidDecode(creds.me?.lid);
|
|
653
|
-
const deviceNum = pnJid?.device ?? lidJid?.device ?? 0;
|
|
654
|
-
const pnAgent = jidAgent(creds.me?.id);
|
|
655
|
-
const lidAgent = jidAgent(creds.me?.lid);
|
|
656
|
-
// Preserve `server` and recover the literal `_<n>` agent suffix so
|
|
657
|
-
// hosted / hosted.lid accounts (e.g. `5511_2@hosted`) survive a
|
|
658
|
-
// drop-in migration from upstream Baileys.
|
|
659
|
-
return toJson({
|
|
660
|
-
pn: pnJid ? { user: pnJid.user, server: pnJid.server, device: deviceNum, agent: pnAgent, integrator: 0 } : null,
|
|
661
|
-
lid: lidJid
|
|
662
|
-
? { user: lidJid.user, server: lidJid.server, device: lidJid.device ?? 0, agent: lidAgent, integrator: 0 }
|
|
663
|
-
: null,
|
|
664
|
-
registration_id: creds.registrationId ?? 0,
|
|
665
|
-
noise_key: kp(creds.noiseKey),
|
|
666
|
-
identity_key: kp(creds.signedIdentityKey),
|
|
667
|
-
signed_pre_key: kp(creds.signedPreKey?.keyPair),
|
|
668
|
-
signed_pre_key_id: creds.signedPreKey?.keyId ?? 1,
|
|
669
|
-
signed_pre_key_signature: creds.signedPreKey?.signature
|
|
670
|
-
? bufToNumArray(Buffer.from(creds.signedPreKey.signature))
|
|
671
|
-
: Array(64).fill(0),
|
|
672
|
-
adv_secret_key: creds.advSecretKey
|
|
673
|
-
? bufToNumArray(Buffer.from(creds.advSecretKey, 'base64'))
|
|
674
|
-
: Array(32).fill(0),
|
|
675
|
-
account: null,
|
|
676
|
-
push_name: creds.me?.name ?? '',
|
|
677
|
-
app_version_primary: 2,
|
|
678
|
-
app_version_secondary: 3000,
|
|
679
|
-
app_version_tertiary: 0,
|
|
680
|
-
app_version_last_fetched_ms: 0,
|
|
681
|
-
edge_routing_info: creds.routingInfo ? bufToNumArray(creds.routingInfo) : null,
|
|
682
|
-
props_hash: creds.lastPropHash ?? null,
|
|
683
|
-
next_pre_key_id: creds.nextPreKeyId ?? 1
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Decode a `[priv(32)…pub(32)]` byte array (the bridge's `kp` shape) back into
|
|
688
|
-
* the upstream Baileys `{public, private}` keypair. Returns `undefined` for
|
|
689
|
-
* absent / all-zero arrays so callers can use `??` to keep prior values.
|
|
690
|
-
*/
|
|
691
|
-
function numArrayToKeyPair(arr) {
|
|
692
|
-
if (!Array.isArray(arr) || arr.length < 64)
|
|
693
|
-
return undefined;
|
|
694
|
-
if (arr.every(b => b === 0))
|
|
695
|
-
return undefined;
|
|
696
|
-
return {
|
|
697
|
-
private: new Uint8Array(arr.slice(0, 32)),
|
|
698
|
-
public: new Uint8Array(arr.slice(32, 64))
|
|
699
|
-
};
|
|
700
|
-
}
|
|
701
|
-
function updateCredsFromDevice(bytes, creds) {
|
|
702
|
-
try {
|
|
703
|
-
const d = fromJson(bytes);
|
|
704
|
-
// Reconstruct pn JID: bridge stores Jid as { user, server, device, agent, integrator }
|
|
705
|
-
// bridgeJidToString produces "user:device@server" (device omitted when 0)
|
|
706
|
-
const pnJid = bridgeJidToString(d.pn);
|
|
707
|
-
if (pnJid) {
|
|
708
|
-
if (!creds.me)
|
|
709
|
-
creds.me = { id: pnJid };
|
|
710
|
-
else
|
|
711
|
-
creds.me.id = pnJid;
|
|
712
|
-
}
|
|
713
|
-
// Reconstruct LID JID
|
|
714
|
-
const lidJid = bridgeJidToString(d.lid);
|
|
715
|
-
if (lidJid && creds.me)
|
|
716
|
-
creds.me.lid = lidJid;
|
|
717
|
-
if (d.push_name && creds.me)
|
|
718
|
-
creds.me.name = d.push_name;
|
|
719
|
-
if (d.registration_id)
|
|
720
|
-
creds.registrationId = d.registration_id;
|
|
721
|
-
if (d.next_pre_key_id) {
|
|
722
|
-
creds.nextPreKeyId = d.next_pre_key_id;
|
|
723
|
-
// Keep `firstUnuploadedPreKeyId` pinned to `nextPreKeyId`. Upstream
|
|
724
|
-
// Baileys uses `nextPreKeyId - firstUnuploadedPreKeyId` to decide
|
|
725
|
-
// whether a fresh `getNextPreKeys()` call needs to generate a new
|
|
726
|
-
// keypair or can reuse one already in the store. Bridge consumes
|
|
727
|
-
// prekeys without bumping `firstUnuploadedPreKeyId`, so without
|
|
728
|
-
// this pin upstream sees a non-empty "available" range pointing at
|
|
729
|
-
// IDs that have already been deleted from disk — leading to
|
|
730
|
-
// `preKeys = {}` from `getNextPreKeys`, then
|
|
731
|
-
// `xmppPreKey(undefined)` → TypeError on retry receipt
|
|
732
|
-
// construction, then no retry sent, then upstream never decrypts
|
|
733
|
-
// the first post-handoff message from a bridge peer.
|
|
734
|
-
//
|
|
735
|
-
// Pinning to `nextPreKeyId` forces upstream to always generate a
|
|
736
|
-
// fresh keypair on `getNextPreKeys`, side-stepping the inconsistent
|
|
737
|
-
// "available" range. The cost is one extra Curve keygen on the
|
|
738
|
-
// first retry after handoff — negligible.
|
|
739
|
-
creds.firstUnuploadedPreKeyId = d.next_pre_key_id;
|
|
740
|
-
}
|
|
741
|
-
if (d.props_hash !== undefined)
|
|
742
|
-
creds.lastPropHash = d.props_hash ?? undefined;
|
|
743
|
-
if (d.platform)
|
|
744
|
-
creds.platform = d.platform;
|
|
745
|
-
// adv_secret_key: bridge stores as [u8; 32] (array of 32 numbers),
|
|
746
|
-
// upstream stores as base64 string
|
|
747
|
-
if (Array.isArray(d.adv_secret_key)) {
|
|
748
|
-
const buf = Buffer.from(d.adv_secret_key);
|
|
749
|
-
if (buf.some(b => b !== 0)) {
|
|
750
|
-
creds.advSecretKey = buf.toString('base64');
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
// Hydrate the noise / identity / signed pre-key material so the next
|
|
754
|
-
// `credsToDeviceJson(creds)` round-trip emits real bytes instead of
|
|
755
|
-
// zero-filled placeholders. Without this, a paired session looks
|
|
756
|
-
// half-valid on the next process start (`me.id` set, but key slots
|
|
757
|
-
// all zero) and the bridge's noise handshake gets rejected by the
|
|
758
|
-
// server with stream-error precondition-required.
|
|
759
|
-
const noise = numArrayToKeyPair(d.noise_key);
|
|
760
|
-
if (noise)
|
|
761
|
-
creds.noiseKey = noise;
|
|
762
|
-
const identity = numArrayToKeyPair(d.identity_key);
|
|
763
|
-
if (identity)
|
|
764
|
-
creds.signedIdentityKey = identity;
|
|
765
|
-
const signedPreKeyPair = numArrayToKeyPair(d.signed_pre_key);
|
|
766
|
-
if (signedPreKeyPair &&
|
|
767
|
-
Array.isArray(d.signed_pre_key_signature) &&
|
|
768
|
-
d.signed_pre_key_signature.length === 64 &&
|
|
769
|
-
d.signed_pre_key_signature.some(b => b !== 0)) {
|
|
770
|
-
creds.signedPreKey = {
|
|
771
|
-
keyPair: signedPreKeyPair,
|
|
772
|
-
keyId: d.signed_pre_key_id ?? 1,
|
|
773
|
-
signature: new Uint8Array(d.signed_pre_key_signature)
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
catch (e) {
|
|
778
|
-
warn('updateCredsFromDevice failed:', e);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
// ---- Protobuf helpers (PreKeyRecordStructure) ----
|
|
782
|
-
function encodePreKeyRecord(id, pub, priv) {
|
|
783
|
-
const out = [];
|
|
784
|
-
out.push(0x08);
|
|
785
|
-
encodeVarint(out, id); // field 1: id
|
|
786
|
-
out.push(0x12);
|
|
787
|
-
encodeVarint(out, pub.length); // field 2: public_key
|
|
788
|
-
for (let i = 0; i < pub.length; i++)
|
|
789
|
-
out.push(pub[i]);
|
|
790
|
-
out.push(0x1a);
|
|
791
|
-
encodeVarint(out, priv.length); // field 3: private_key
|
|
792
|
-
for (let i = 0; i < priv.length; i++)
|
|
793
|
-
out.push(priv[i]);
|
|
794
|
-
return new Uint8Array(out);
|
|
795
|
-
}
|
|
796
|
-
function decodePreKeyRecord(data) {
|
|
797
|
-
try {
|
|
798
|
-
let pos = 0, pub = null, priv = null;
|
|
799
|
-
while (pos < data.length) {
|
|
800
|
-
const [tag, p1] = readVarint(data, pos);
|
|
801
|
-
pos = p1;
|
|
802
|
-
const wt = tag & 7, fn = tag >> 3;
|
|
803
|
-
if (wt === 0) {
|
|
804
|
-
const [, p2] = readVarint(data, pos);
|
|
805
|
-
pos = p2;
|
|
806
|
-
}
|
|
807
|
-
else if (wt === 2) {
|
|
808
|
-
const [len, p2] = readVarint(data, pos);
|
|
809
|
-
pos = p2;
|
|
810
|
-
const bytes = Buffer.from(data.slice(pos, pos + len));
|
|
811
|
-
pos += len;
|
|
812
|
-
if (fn === 2)
|
|
813
|
-
pub = bytes;
|
|
814
|
-
else if (fn === 3)
|
|
815
|
-
priv = bytes;
|
|
816
|
-
}
|
|
817
|
-
else
|
|
818
|
-
break;
|
|
819
|
-
}
|
|
820
|
-
return pub && priv ? { public: pub, private: priv } : null;
|
|
821
|
-
}
|
|
822
|
-
catch {
|
|
823
|
-
return null;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
// ---- Protobuf varint helpers ----
|
|
827
|
-
function encodeVarint(out, v) {
|
|
828
|
-
while (v > 0x7f) {
|
|
829
|
-
out.push((v & 0x7f) | 0x80);
|
|
830
|
-
v >>>= 7;
|
|
831
|
-
}
|
|
832
|
-
out.push(v & 0x7f);
|
|
833
|
-
}
|
|
834
|
-
function readVarint(d, p) {
|
|
835
|
-
let r = 0, s = 0;
|
|
836
|
-
while (p < d.length) {
|
|
837
|
-
const b = d[p];
|
|
838
|
-
p++;
|
|
839
|
-
r |= (b & 0x7f) << s;
|
|
840
|
-
if (!(b & 0x80))
|
|
841
|
-
return [r, p];
|
|
842
|
-
s += 7;
|
|
843
|
-
}
|
|
844
|
-
return [r, p];
|
|
845
|
-
}
|
|
846
|
-
// ---- Signal address translation ----
|
|
847
|
-
// Bridge uses JID-based addresses: "236395184570386@lid.0", "559984726662@c.us.0"
|
|
848
|
-
// Baileys uses domain-type addresses: "236395184570386_1.0", "559984726662.0"
|
|
849
|
-
// Domain types: s.whatsapp.net/c.us=0, lid=1, hosted=2, hosted.lid=3
|
|
850
|
-
const DOMAIN_TYPE_MAP = { lid: 1, 'c.us': 0, 's.whatsapp.net': 0, hosted: 2, 'hosted.lid': 3 };
|
|
851
|
-
/** Convert bridge signal address to Baileys signal address */
|
|
852
|
-
function bridgeAddrToBaileysAddr(bridgeAddr) {
|
|
853
|
-
// Format: "user@domain.signalDevice" or "user:jidDevice@domain.signalDevice"
|
|
854
|
-
const dotIdx = bridgeAddr.lastIndexOf('.');
|
|
855
|
-
if (dotIdx < 0)
|
|
856
|
-
return null;
|
|
857
|
-
const signalDevice = bridgeAddr.slice(dotIdx + 1);
|
|
858
|
-
const jidPart = bridgeAddr.slice(0, dotIdx); // "user@domain" or "user:jidDevice@domain"
|
|
859
|
-
const atIdx = jidPart.indexOf('@');
|
|
860
|
-
if (atIdx < 0)
|
|
861
|
-
return null;
|
|
862
|
-
const domain = jidPart.slice(atIdx + 1);
|
|
863
|
-
const userPart = jidPart.slice(0, atIdx); // "user" or "user:jidDevice"
|
|
864
|
-
const domainType = DOMAIN_TYPE_MAP[domain];
|
|
865
|
-
if (domainType === undefined)
|
|
866
|
-
return null;
|
|
867
|
-
// Baileys format: "user_domainType.device" or "user.device" (when domainType=0)
|
|
868
|
-
// For JID device: "user_domainType:jidDevice.device"
|
|
869
|
-
let baileysUser;
|
|
870
|
-
if (userPart.includes(':')) {
|
|
871
|
-
// Has JID device: "user:jidDevice" → for signal address, device is the JID device
|
|
872
|
-
const [user, jidDevice] = userPart.split(':');
|
|
873
|
-
baileysUser = domainType !== 0 ? `${user}_${domainType}` : user;
|
|
874
|
-
return `${baileysUser}.${jidDevice}`;
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
877
|
-
baileysUser = domainType !== 0 ? `${userPart}_${domainType}` : userPart;
|
|
878
|
-
return `${baileysUser}.${signalDevice}`;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
// ---- Account normalization ----
|
|
882
|
-
// Upstream Baileys stores account fields as base64 strings (protobuf.js toJSON),
|
|
883
|
-
// but the bridge's encodeProto expects Uint8Array for bytes fields.
|
|
884
|
-
function normalizeAccountForEncode(account) {
|
|
885
|
-
const toBytes = (v) => {
|
|
886
|
-
if (v instanceof Uint8Array)
|
|
887
|
-
return v;
|
|
888
|
-
if (Buffer.isBuffer(v))
|
|
889
|
-
return new Uint8Array(v);
|
|
890
|
-
if (typeof v === 'string')
|
|
891
|
-
return Buffer.from(v, 'base64');
|
|
892
|
-
return undefined;
|
|
893
|
-
};
|
|
894
|
-
return {
|
|
895
|
-
details: toBytes(account.details),
|
|
896
|
-
accountSignatureKey: toBytes(account.accountSignatureKey),
|
|
897
|
-
accountSignature: toBytes(account.accountSignature),
|
|
898
|
-
deviceSignature: toBytes(account.deviceSignature)
|
|
899
|
-
};
|
|
900
|
-
}
|
|
901
|
-
// ---- Main ----
|
|
902
|
-
export async function wrapLegacyStore(state, saveCreds, logger) {
|
|
903
|
-
if (logger) {
|
|
904
|
-
_warnFn = (msg, err) => logger.warn({ err }, msg);
|
|
905
|
-
}
|
|
906
|
-
if (!state.creds || !state.keys) {
|
|
907
|
-
throw new Error('wrapLegacyStore requires an AuthenticationState with creds and keys');
|
|
908
|
-
}
|
|
909
|
-
const creds = state.creds;
|
|
910
|
-
const keys = state.keys;
|
|
911
|
-
const store = keys;
|
|
912
|
-
const storeGetOne = async (type, id) => {
|
|
913
|
-
const result = await store.get(type, [id]);
|
|
914
|
-
return result[id] ?? null;
|
|
915
|
-
};
|
|
916
|
-
const storeSetOne = (type, id, value) => store.set({ [type]: { [id]: value } });
|
|
917
|
-
let credsTimer = null;
|
|
918
|
-
const debounceSave = () => {
|
|
919
|
-
if (credsTimer)
|
|
920
|
-
clearTimeout(credsTimer);
|
|
921
|
-
credsTimer = setTimeout(() => {
|
|
922
|
-
credsTimer = null;
|
|
923
|
-
saveCreds().catch(err => warn('saveCreds failed', err));
|
|
924
|
-
}, 100);
|
|
925
|
-
};
|
|
926
|
-
/** Route a store to its handler */
|
|
927
|
-
const resolve = (storeName) => {
|
|
928
|
-
if (storeName === 'device')
|
|
929
|
-
return 'device';
|
|
930
|
-
if (BINARY_STORES.has(storeName))
|
|
931
|
-
return 'signal';
|
|
932
|
-
if (BRIDGE_ONLY_STORES.has(storeName))
|
|
933
|
-
return 'bridge-only';
|
|
934
|
-
if (STORE_MAP[storeName])
|
|
935
|
-
return 'converter';
|
|
936
|
-
return 'unknown';
|
|
937
|
-
};
|
|
938
|
-
/** Translate bridge key format to upstream Baileys key format */
|
|
939
|
-
const translateKey = (storeName, key) => {
|
|
940
|
-
// Bridge encodes sync_key IDs as hex; upstream stores use base64
|
|
941
|
-
if (storeName === 'sync_key')
|
|
942
|
-
return hexToBase64(key);
|
|
943
|
-
// Bridge sender_key cache_key uses single-colon separator + signal-
|
|
944
|
-
// device suffix; upstream's `SenderKeyName.serialize()` uses double
|
|
945
|
-
// colons and drops the signal device — see bridgeSenderKeyToUpstream.
|
|
946
|
-
if (storeName === 'sender_key') {
|
|
947
|
-
const translated = bridgeSenderKeyToUpstream(key);
|
|
948
|
-
if (translated == null) {
|
|
949
|
-
warn(`sender_key key translation failed for "${key}", falling back to passthrough`);
|
|
950
|
-
return key;
|
|
951
|
-
}
|
|
952
|
-
return translated;
|
|
953
|
-
}
|
|
954
|
-
// Bridge session/identity keys are the protocol address
|
|
955
|
-
// (`user[:dev]@server.sig`); upstream's libsignal looks under
|
|
956
|
-
// `signalUser.deviceId`. `bridgeAddrToBaileysAddr` does the LID/PN
|
|
957
|
-
// → signalUser rewrite + JID-device extraction.
|
|
958
|
-
if (storeName === 'session' || storeName === 'identity') {
|
|
959
|
-
const translated = bridgeAddrToBaileysAddr(key);
|
|
960
|
-
if (translated == null) {
|
|
961
|
-
warn(`${storeName} key translation failed for "${key}", falling back to passthrough`);
|
|
962
|
-
return key;
|
|
963
|
-
}
|
|
964
|
-
return translated;
|
|
965
|
-
}
|
|
966
|
-
// Bridge lid_mapping uses prefixed keys (`lid:{X}`, `pn:{X}`) that
|
|
967
|
-
// upstream's `Signal/lid-mapping.js` doesn't recognize. Map them to
|
|
968
|
-
// upstream's bare-userpart shape: `pn:{X}` → `{X}`, `lid:{X}` →
|
|
969
|
-
// `{X}_reverse`.
|
|
970
|
-
if (storeName === 'lid_mapping') {
|
|
971
|
-
if (key.startsWith('pn:'))
|
|
972
|
-
return key.slice(3);
|
|
973
|
-
if (key.startsWith('lid:'))
|
|
974
|
-
return `${key.slice(4)}_reverse`;
|
|
975
|
-
return key;
|
|
976
|
-
}
|
|
977
|
-
return key;
|
|
978
|
-
};
|
|
979
|
-
/** Read a binary value from the keys store */
|
|
980
|
-
async function readBinary(type, id) {
|
|
981
|
-
try {
|
|
982
|
-
const val = await storeGetOne(type, id);
|
|
983
|
-
return val != null ? toBuf(val) : null;
|
|
984
|
-
}
|
|
985
|
-
catch (e) {
|
|
986
|
-
warn(`GET ${type}/${id} failed:`, e);
|
|
987
|
-
return null;
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
/** Write a binary value to the keys store */
|
|
991
|
-
async function writeBinary(type, id, value) {
|
|
992
|
-
try {
|
|
993
|
-
await storeSetOne(type, id, Buffer.from(value));
|
|
994
|
-
}
|
|
995
|
-
catch (e) {
|
|
996
|
-
warn(`SET ${type}/${id} failed:`, e);
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
/** Delete a value from the keys store */
|
|
1000
|
-
async function storeDelete(type, id) {
|
|
1001
|
-
try {
|
|
1002
|
-
await storeSetOne(type, id, null);
|
|
1003
|
-
}
|
|
1004
|
-
catch (e) {
|
|
1005
|
-
warn(`DELETE ${type}/${id} failed:`, e);
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
return {
|
|
1009
|
-
async get(bridgeStore, key) {
|
|
1010
|
-
const route = resolve(bridgeStore);
|
|
1011
|
-
const type = STORE_MAP[bridgeStore];
|
|
1012
|
-
if (route === 'device') {
|
|
1013
|
-
if (key === 'device') {
|
|
1014
|
-
// Fresh/stub creds (baileyrs' `initAuthCreds()` shim, or an
|
|
1015
|
-
// upstream flow that hadn't finished its first pair) carry
|
|
1016
|
-
// neither a noise key nor a paired `me.id`. Returning a
|
|
1017
|
-
// zeroed `credsToDeviceJson` in that state poisons the
|
|
1018
|
-
// bridge's noise handshake (server responds 428 Precondition
|
|
1019
|
-
// Required). Signaling `null` instead lets the bridge
|
|
1020
|
-
// bootstrap its own device identity and write it back
|
|
1021
|
-
// through `set('device', 'device', …)` on pair-success.
|
|
1022
|
-
if (!creds.noiseKey && !creds.me?.id)
|
|
1023
|
-
return null;
|
|
1024
|
-
// Even when `noiseKey` is present as an object, the bytes
|
|
1025
|
-
// can still be all-zero — happens after a partial migration
|
|
1026
|
-
// from a legacy creds.json that only persisted `me.id`.
|
|
1027
|
-
// `credsToDeviceJson` would happily emit zero-filled key
|
|
1028
|
-
// slots, which the server rejects with the same 428. Treat
|
|
1029
|
-
// any zero-byte critical key as a bootstrap signal.
|
|
1030
|
-
if (isZeroKey(creds.noiseKey?.private) || isZeroKey(creds.signedIdentityKey?.private)) {
|
|
1031
|
-
warn('device read: noiseKey/signedIdentityKey is zero-valued; signaling bootstrap to bridge');
|
|
1032
|
-
return null;
|
|
1033
|
-
}
|
|
1034
|
-
return credsToDeviceJson(creds);
|
|
1035
|
-
}
|
|
1036
|
-
if (key === 'account') {
|
|
1037
|
-
if (!creds.account)
|
|
1038
|
-
return null;
|
|
1039
|
-
return new Uint8Array(ADVSignedDeviceIdentity.encode(normalizeAccountForEncode(creds.account)).finish());
|
|
1040
|
-
}
|
|
1041
|
-
return readBinary(type, key);
|
|
1042
|
-
}
|
|
1043
|
-
// `signal` route is currently unreachable (BINARY_STORES is empty);
|
|
1044
|
-
// kept for future byte-compatible stores.
|
|
1045
|
-
if (route === 'signal')
|
|
1046
|
-
return readBinary(type, key);
|
|
1047
|
-
if (route === 'bridge-only')
|
|
1048
|
-
return readBinary(type, key);
|
|
1049
|
-
if (route === 'converter') {
|
|
1050
|
-
try {
|
|
1051
|
-
const upstreamKey = translateKey(bridgeStore, key);
|
|
1052
|
-
const value = await storeGetOne(type, upstreamKey);
|
|
1053
|
-
if (value == null)
|
|
1054
|
-
return null;
|
|
1055
|
-
return converters[bridgeStore]?.toBridge(key, value) ?? toBuf(value);
|
|
1056
|
-
}
|
|
1057
|
-
catch (e) {
|
|
1058
|
-
warn(`GET ${bridgeStore}/${key} failed:`, e);
|
|
1059
|
-
return null;
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
warn(`GET unknown store: ${bridgeStore}/${key}`);
|
|
1063
|
-
return null;
|
|
1064
|
-
},
|
|
1065
|
-
async set(bridgeStore, key, value) {
|
|
1066
|
-
const route = resolve(bridgeStore);
|
|
1067
|
-
const type = STORE_MAP[bridgeStore];
|
|
1068
|
-
if (route === 'device') {
|
|
1069
|
-
if (key === 'device') {
|
|
1070
|
-
updateCredsFromDevice(value, creds);
|
|
1071
|
-
debounceSave();
|
|
1072
|
-
return;
|
|
1073
|
-
}
|
|
1074
|
-
if (key === 'account') {
|
|
1075
|
-
try {
|
|
1076
|
-
creds.account = ADVSignedDeviceIdentity.decode(value);
|
|
1077
|
-
debounceSave();
|
|
1078
|
-
}
|
|
1079
|
-
catch (e) {
|
|
1080
|
-
warn('failed to decode account update:', e);
|
|
1081
|
-
}
|
|
1082
|
-
return;
|
|
1083
|
-
}
|
|
1084
|
-
return writeBinary(type, key, value);
|
|
1085
|
-
}
|
|
1086
|
-
if (route === 'signal')
|
|
1087
|
-
return writeBinary(type, key, value);
|
|
1088
|
-
if (route === 'bridge-only')
|
|
1089
|
-
return writeBinary(type, key, value);
|
|
1090
|
-
if (route === 'converter') {
|
|
1091
|
-
try {
|
|
1092
|
-
const upstreamKey = translateKey(bridgeStore, key);
|
|
1093
|
-
const typed = converters[bridgeStore]?.fromBridge(key, value) ?? Buffer.from(value);
|
|
1094
|
-
await storeSetOne(type, upstreamKey, typed);
|
|
1095
|
-
}
|
|
1096
|
-
catch (e) {
|
|
1097
|
-
warn(`SET ${bridgeStore}/${key} failed:`, e);
|
|
1098
|
-
}
|
|
1099
|
-
return;
|
|
1100
|
-
}
|
|
1101
|
-
warn(`SET unknown store: ${bridgeStore}/${key}`);
|
|
1102
|
-
},
|
|
1103
|
-
async delete(bridgeStore, key) {
|
|
1104
|
-
if (bridgeStore === 'device')
|
|
1105
|
-
return;
|
|
1106
|
-
const route = resolve(bridgeStore);
|
|
1107
|
-
const type = STORE_MAP[bridgeStore];
|
|
1108
|
-
if (type) {
|
|
1109
|
-
const storeKey = route === 'converter' ? translateKey(bridgeStore, key) : key;
|
|
1110
|
-
await storeDelete(type, storeKey);
|
|
1111
|
-
}
|
|
1112
|
-
},
|
|
1113
|
-
async flush() {
|
|
1114
|
-
// Drain in a loop because `set('device', ...)` calls landing
|
|
1115
|
-
// during `await saveCreds()` queue a fresh `credsTimer`. A
|
|
1116
|
-
// single-pass flush would leave the latest creds on the timer
|
|
1117
|
-
// — `dispose()` then fires saveCreds() but the orchestrator
|
|
1118
|
-
// has already moved on (`free()`), so the write is racing
|
|
1119
|
-
// against process exit. Looping until the timer is null after
|
|
1120
|
-
// a save closes the window deterministically. Bounded by a
|
|
1121
|
-
// small max-iterations guard so a saveCreds() that re-emits
|
|
1122
|
-
// credentials in a tight loop can't lock us forever.
|
|
1123
|
-
for (let i = 0; i < 32 && credsTimer; i++) {
|
|
1124
|
-
clearTimeout(credsTimer);
|
|
1125
|
-
credsTimer = null;
|
|
1126
|
-
await saveCreds();
|
|
1127
|
-
}
|
|
1128
|
-
if (credsTimer) {
|
|
1129
|
-
warn('flush hit max-iterations cap; pending credsTimer dropped — saveCreds may be re-emitting in a loop');
|
|
1130
|
-
clearTimeout(credsTimer);
|
|
1131
|
-
credsTimer = null;
|
|
1132
|
-
}
|
|
1133
|
-
},
|
|
1134
|
-
dispose() {
|
|
1135
|
-
if (credsTimer) {
|
|
1136
|
-
clearTimeout(credsTimer);
|
|
1137
|
-
saveCreds().catch(err => warn('saveCreds failed during dispose', err));
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
};
|
|
1141
|
-
}
|
|
1142
|
-
// ---- Legacy multi-file auth state loader ----
|
|
1143
|
-
// Reads upstream Baileys' creds.json + per-key .json files via the
|
|
1144
|
-
// shared `BufferJSON` codec (same as @whiskeysockets/baileys
|
|
1145
|
-
// useMultiFileAuthState).
|
|
1146
|
-
const fixFileName = (file) => file?.replace(/\//g, '__')?.replace(/:/g, '-');
|
|
1147
|
-
/**
|
|
1148
|
-
* Loads an upstream Baileys session (creds.json + key .json files) and returns
|
|
1149
|
-
* the standard `{ state, saveCreds }` tuple that `wrapLegacyStore` expects.
|
|
1150
|
-
*
|
|
1151
|
-
* ```typescript
|
|
1152
|
-
* const { state, saveCreds } = await useLegacyMultiFileAuthState('/path/to/baileys_auth_info')
|
|
1153
|
-
* const store = await wrapLegacyStore(state, saveCreds)
|
|
1154
|
-
* const sock = makeWASocket({ auth: { store } })
|
|
1155
|
-
* ```
|
|
1156
|
-
*/
|
|
1157
|
-
export async function useLegacyMultiFileAuthState(folder) {
|
|
1158
|
-
const folderInfo = await stat(folder).catch(() => null);
|
|
1159
|
-
if (folderInfo && !folderInfo.isDirectory()) {
|
|
1160
|
-
throw new Error(`found something that is not a directory at ${folder}`);
|
|
1161
|
-
}
|
|
1162
|
-
if (!folderInfo) {
|
|
1163
|
-
await mkdir(folder, { recursive: true });
|
|
1164
|
-
}
|
|
1165
|
-
const readData = async (file) => {
|
|
1166
|
-
try {
|
|
1167
|
-
const data = await readFile(join(folder, fixFileName(file)), 'utf-8');
|
|
1168
|
-
return JSON.parse(data, BufferJSON.reviver);
|
|
1169
|
-
}
|
|
1170
|
-
catch {
|
|
1171
|
-
return null;
|
|
1172
|
-
}
|
|
1173
|
-
};
|
|
1174
|
-
const writeData = async (data, file) => {
|
|
1175
|
-
await writeFile(join(folder, fixFileName(file)), JSON.stringify(data, BufferJSON.replacer));
|
|
1176
|
-
};
|
|
1177
|
-
const removeData = async (file) => {
|
|
1178
|
-
try {
|
|
1179
|
-
await unlink(join(folder, fixFileName(file)));
|
|
1180
|
-
}
|
|
1181
|
-
catch { }
|
|
1182
|
-
};
|
|
1183
|
-
const creds = await readData('creds.json');
|
|
1184
|
-
if (!creds) {
|
|
1185
|
-
throw new Error(`No creds.json found in ${folder}. This loader requires an existing upstream Baileys session.`);
|
|
1186
|
-
}
|
|
1187
|
-
return {
|
|
1188
|
-
state: {
|
|
1189
|
-
creds,
|
|
1190
|
-
keys: {
|
|
1191
|
-
get: async (type, ids) => {
|
|
1192
|
-
const data = {};
|
|
1193
|
-
await Promise.all(ids.map(async (id) => {
|
|
1194
|
-
let value = await readData(`${type}-${id}.json`);
|
|
1195
|
-
if (type === 'app-state-sync-key' && value) {
|
|
1196
|
-
value = proto.Message.AppStateSyncKeyData.fromObject(value);
|
|
1197
|
-
}
|
|
1198
|
-
data[id] = value;
|
|
1199
|
-
}));
|
|
1200
|
-
return data;
|
|
1201
|
-
},
|
|
1202
|
-
set: async (data) => {
|
|
1203
|
-
const tasks = [];
|
|
1204
|
-
for (const category in data) {
|
|
1205
|
-
for (const id in data[category]) {
|
|
1206
|
-
const value = data[category][id];
|
|
1207
|
-
const file = `${category}-${id}.json`;
|
|
1208
|
-
tasks.push(value ? writeData(value, file) : removeData(file));
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
await Promise.all(tasks);
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
},
|
|
1215
|
-
saveCreds: () => writeData(creds, 'creds.json')
|
|
1216
|
-
};
|
|
1217
|
-
}
|
|
9
|
+
export { wrapLegacyStore } from '../Compatibility/legacy-store/adapter.js';
|
|
10
|
+
export { useLegacyMultiFileAuthState } from '../Compatibility/legacy-store/multi-file.js';
|
|
1218
11
|
//# sourceMappingURL=wrap-legacy-store.js.map
|