@oxidezap/baileyrs 0.0.27 → 0.0.29
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/history-sync-wire.js +18 -2
- package/lib/Socket/events.js +20 -13
- package/lib/WAProto/runtime.d.ts +1 -1
- package/package.json +9 -8
- package/lib/Bridge/adapt.d.ts.map +0 -1
- package/lib/Bridge/adapt.js.map +0 -1
- package/lib/Bridge/history-sync-wire.d.ts.map +0 -1
- package/lib/Bridge/history-sync-wire.js.map +0 -1
- package/lib/Bridge/index.d.ts.map +0 -1
- package/lib/Bridge/index.js.map +0 -1
- package/lib/Bridge/primitives.d.ts.map +0 -1
- package/lib/Bridge/primitives.js.map +0 -1
- package/lib/Bridge/schema.d.ts.map +0 -1
- package/lib/Bridge/schema.js.map +0 -1
- package/lib/Bridge/types.d.ts.map +0 -1
- package/lib/Bridge/types.js.map +0 -1
- package/lib/Compatibility/group-metadata.d.ts.map +0 -1
- package/lib/Compatibility/group-metadata.js.map +0 -1
- package/lib/Compatibility/group-notifications.d.ts.map +0 -1
- package/lib/Compatibility/group-notifications.js.map +0 -1
- package/lib/Compatibility/group-stub-params.d.ts.map +0 -1
- package/lib/Compatibility/group-stub-params.js.map +0 -1
- package/lib/Compatibility/internal/async-primitives.d.ts.map +0 -1
- package/lib/Compatibility/internal/async-primitives.js.map +0 -1
- package/lib/Compatibility/internal/auth-state.d.ts.map +0 -1
- package/lib/Compatibility/internal/auth-state.js.map +0 -1
- package/lib/Compatibility/internal/cache-store.d.ts.map +0 -1
- package/lib/Compatibility/internal/cache-store.js.map +0 -1
- package/lib/Compatibility/internal/expiring-lru-map.d.ts.map +0 -1
- package/lib/Compatibility/internal/expiring-lru-map.js.map +0 -1
- package/lib/Compatibility/internal/make-mutex.d.ts.map +0 -1
- package/lib/Compatibility/internal/make-mutex.js.map +0 -1
- package/lib/Compatibility/internal/native-memory-store.d.ts.map +0 -1
- package/lib/Compatibility/internal/native-memory-store.js.map +0 -1
- package/lib/Compatibility/internal/numeric-enum.d.ts.map +0 -1
- package/lib/Compatibility/internal/numeric-enum.js.map +0 -1
- package/lib/Compatibility/internal/signal-key-store.d.ts.map +0 -1
- package/lib/Compatibility/internal/signal-key-store.js.map +0 -1
- package/lib/Compatibility/legacy-store/adapter.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/adapter.js.map +0 -1
- package/lib/Compatibility/legacy-store/codecs/basic.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/codecs/basic.js.map +0 -1
- package/lib/Compatibility/legacy-store/codecs/index.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/codecs/index.js.map +0 -1
- package/lib/Compatibility/legacy-store/codecs/signal.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/codecs/signal.js.map +0 -1
- package/lib/Compatibility/legacy-store/common.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/common.js.map +0 -1
- package/lib/Compatibility/legacy-store/constants.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/constants.js.map +0 -1
- package/lib/Compatibility/legacy-store/device.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/device.js.map +0 -1
- package/lib/Compatibility/legacy-store/multi-file.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/multi-file.js.map +0 -1
- package/lib/Compatibility/legacy-store/native-projection.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/native-projection.js.map +0 -1
- package/lib/Compatibility/legacy-store/routing.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/routing.js.map +0 -1
- package/lib/Compatibility/legacy-store/types.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/types.js.map +0 -1
- package/lib/Compatibility/legacy-store/validation.d.ts.map +0 -1
- package/lib/Compatibility/legacy-store/validation.js.map +0 -1
- package/lib/Compatibility/media-type.d.ts.map +0 -1
- package/lib/Compatibility/media-type.js.map +0 -1
- package/lib/Compatibility/message-keys.d.ts.map +0 -1
- package/lib/Compatibility/message-keys.js.map +0 -1
- package/lib/Compatibility/message-relay.d.ts.map +0 -1
- package/lib/Compatibility/message-relay.js.map +0 -1
- package/lib/Compatibility/message-upsert.d.ts.map +0 -1
- package/lib/Compatibility/message-upsert.js.map +0 -1
- package/lib/Compatibility/participating-refresh.d.ts.map +0 -1
- package/lib/Compatibility/participating-refresh.js.map +0 -1
- package/lib/Compatibility/proto-runtime.d.ts.map +0 -1
- package/lib/Compatibility/proto-runtime.js.map +0 -1
- package/lib/Compatibility/public-api/auth-utils.d.ts.map +0 -1
- package/lib/Compatibility/public-api/auth-utils.js.map +0 -1
- package/lib/Compatibility/public-api/enum-types.d.ts.map +0 -1
- package/lib/Compatibility/public-api/enum-types.js.map +0 -1
- package/lib/Compatibility/public-api/identity-change-handler.d.ts.map +0 -1
- package/lib/Compatibility/public-api/identity-change-handler.js.map +0 -1
- package/lib/Compatibility/public-api/message-retry-manager.d.ts.map +0 -1
- package/lib/Compatibility/public-api/message-retry-manager.js.map +0 -1
- package/lib/Compatibility/public-api/pre-key-manager.d.ts.map +0 -1
- package/lib/Compatibility/public-api/pre-key-manager.js.map +0 -1
- package/lib/Compatibility/public-api/stanza-ack.d.ts.map +0 -1
- package/lib/Compatibility/public-api/stanza-ack.js.map +0 -1
- package/lib/Compatibility/signal-repository.d.ts.map +0 -1
- package/lib/Compatibility/signal-repository.js.map +0 -1
- package/lib/Compatibility/socket-results.d.ts.map +0 -1
- package/lib/Compatibility/socket-results.js.map +0 -1
- package/lib/Compatibility/stanza-responses.d.ts.map +0 -1
- package/lib/Compatibility/stanza-responses.js.map +0 -1
- package/lib/Compatibility/tagged-message-waiter.d.ts.map +0 -1
- package/lib/Compatibility/tagged-message-waiter.js.map +0 -1
- package/lib/Compatibility/usync/adapter.d.ts.map +0 -1
- package/lib/Compatibility/usync/adapter.js.map +0 -1
- package/lib/Compatibility/websocket-client.d.ts.map +0 -1
- package/lib/Compatibility/websocket-client.js.map +0 -1
- package/lib/Defaults/index.d.ts.map +0 -1
- package/lib/Defaults/index.js.map +0 -1
- package/lib/Platform/crypto.d.ts.map +0 -1
- package/lib/Platform/crypto.js.map +0 -1
- package/lib/Socket/blocking.d.ts.map +0 -1
- package/lib/Socket/blocking.js.map +0 -1
- package/lib/Socket/chat-actions.d.ts.map +0 -1
- package/lib/Socket/chat-actions.js.map +0 -1
- package/lib/Socket/communities.d.ts.map +0 -1
- package/lib/Socket/communities.js.map +0 -1
- package/lib/Socket/contacts.d.ts.map +0 -1
- package/lib/Socket/contacts.js.map +0 -1
- package/lib/Socket/events.d.ts.map +0 -1
- package/lib/Socket/events.js.map +0 -1
- package/lib/Socket/group-notifications.d.ts.map +0 -1
- package/lib/Socket/group-notifications.js.map +0 -1
- package/lib/Socket/groups.d.ts.map +0 -1
- package/lib/Socket/groups.js.map +0 -1
- package/lib/Socket/index.d.ts.map +0 -1
- package/lib/Socket/index.js.map +0 -1
- package/lib/Socket/message-capping.d.ts.map +0 -1
- package/lib/Socket/message-capping.js.map +0 -1
- package/lib/Socket/messages.d.ts.map +0 -1
- package/lib/Socket/messages.js.map +0 -1
- package/lib/Socket/newsletter.d.ts.map +0 -1
- package/lib/Socket/newsletter.js.map +0 -1
- package/lib/Socket/prekeys.d.ts.map +0 -1
- package/lib/Socket/prekeys.js.map +0 -1
- package/lib/Socket/presence.d.ts.map +0 -1
- package/lib/Socket/presence.js.map +0 -1
- package/lib/Socket/profile.d.ts.map +0 -1
- package/lib/Socket/profile.js.map +0 -1
- package/lib/Socket/reachout.d.ts.map +0 -1
- package/lib/Socket/reachout.js.map +0 -1
- package/lib/Socket/transport.d.ts.map +0 -1
- package/lib/Socket/transport.js.map +0 -1
- package/lib/Socket/types.d.ts.map +0 -1
- package/lib/Socket/types.js.map +0 -1
- package/lib/Socket/usync.d.ts.map +0 -1
- package/lib/Socket/usync.js.map +0 -1
- package/lib/Types/Auth.d.ts.map +0 -1
- package/lib/Types/Auth.js.map +0 -1
- package/lib/Types/BinaryNode.d.ts.map +0 -1
- package/lib/Types/BinaryNode.js.map +0 -1
- package/lib/Types/Bussines.d.ts.map +0 -1
- package/lib/Types/Bussines.js.map +0 -1
- package/lib/Types/Call.d.ts.map +0 -1
- package/lib/Types/Call.js.map +0 -1
- package/lib/Types/Chat.d.ts.map +0 -1
- package/lib/Types/Chat.js.map +0 -1
- package/lib/Types/Contact.d.ts.map +0 -1
- package/lib/Types/Contact.js.map +0 -1
- package/lib/Types/Events.d.ts.map +0 -1
- package/lib/Types/Events.js.map +0 -1
- package/lib/Types/GroupMetadata.d.ts.map +0 -1
- package/lib/Types/GroupMetadata.js.map +0 -1
- package/lib/Types/Label.d.ts.map +0 -1
- package/lib/Types/Label.js.map +0 -1
- package/lib/Types/LabelAssociation.d.ts.map +0 -1
- package/lib/Types/LabelAssociation.js.map +0 -1
- package/lib/Types/Message.d.ts.map +0 -1
- package/lib/Types/Message.js.map +0 -1
- package/lib/Types/Newsletter.d.ts.map +0 -1
- package/lib/Types/Newsletter.js.map +0 -1
- package/lib/Types/Product.d.ts.map +0 -1
- package/lib/Types/Product.js.map +0 -1
- package/lib/Types/Reachout.d.ts.map +0 -1
- package/lib/Types/Reachout.js.map +0 -1
- package/lib/Types/Signal.d.ts.map +0 -1
- package/lib/Types/Signal.js.map +0 -1
- package/lib/Types/Socket.d.ts.map +0 -1
- package/lib/Types/Socket.js.map +0 -1
- package/lib/Types/State.d.ts.map +0 -1
- package/lib/Types/State.js.map +0 -1
- package/lib/Types/USync.d.ts.map +0 -1
- package/lib/Types/USync.js.map +0 -1
- package/lib/Types/index.d.ts.map +0 -1
- package/lib/Types/index.js.map +0 -1
- package/lib/Utils/auth-utils.d.ts.map +0 -1
- package/lib/Utils/auth-utils.js.map +0 -1
- package/lib/Utils/boom.d.ts.map +0 -1
- package/lib/Utils/boom.js.map +0 -1
- package/lib/Utils/browser-utils.d.ts.map +0 -1
- package/lib/Utils/browser-utils.js.map +0 -1
- package/lib/Utils/companion-reg-client-utils.d.ts.map +0 -1
- package/lib/Utils/companion-reg-client-utils.js.map +0 -1
- package/lib/Utils/crypto.d.ts.map +0 -1
- package/lib/Utils/crypto.js.map +0 -1
- package/lib/Utils/event-buffer.d.ts.map +0 -1
- package/lib/Utils/event-buffer.js.map +0 -1
- package/lib/Utils/generics.d.ts.map +0 -1
- package/lib/Utils/generics.js.map +0 -1
- package/lib/Utils/group-stub-params.d.ts.map +0 -1
- package/lib/Utils/group-stub-params.js.map +0 -1
- package/lib/Utils/identity-change-handler.d.ts.map +0 -1
- package/lib/Utils/identity-change-handler.js.map +0 -1
- package/lib/Utils/index.d.ts.map +0 -1
- package/lib/Utils/index.js.map +0 -1
- package/lib/Utils/logger.d.ts.map +0 -1
- package/lib/Utils/logger.js.map +0 -1
- package/lib/Utils/message-retry-manager.d.ts.map +0 -1
- package/lib/Utils/message-retry-manager.js.map +0 -1
- package/lib/Utils/messages-media.d.ts.map +0 -1
- package/lib/Utils/messages-media.js.map +0 -1
- package/lib/Utils/messages.d.ts.map +0 -1
- package/lib/Utils/messages.js.map +0 -1
- package/lib/Utils/native-crypto-provider.d.ts.map +0 -1
- package/lib/Utils/native-crypto-provider.js.map +0 -1
- package/lib/Utils/pre-key-manager.d.ts.map +0 -1
- package/lib/Utils/pre-key-manager.js.map +0 -1
- package/lib/Utils/process-history-message.d.ts.map +0 -1
- package/lib/Utils/process-history-message.js.map +0 -1
- package/lib/Utils/process-message.d.ts.map +0 -1
- package/lib/Utils/process-message.js.map +0 -1
- package/lib/Utils/signal.d.ts.map +0 -1
- package/lib/Utils/signal.js.map +0 -1
- package/lib/Utils/sparse-array.d.ts.map +0 -1
- package/lib/Utils/sparse-array.js.map +0 -1
- package/lib/Utils/stanza-ack.d.ts.map +0 -1
- package/lib/Utils/stanza-ack.js.map +0 -1
- package/lib/Utils/use-bridge-store.d.ts.map +0 -1
- package/lib/Utils/use-bridge-store.js.map +0 -1
- package/lib/Utils/use-memory-store.d.ts.map +0 -1
- package/lib/Utils/use-memory-store.js.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.d.ts.map +0 -1
- package/lib/Utils/use-multi-file-auth-state.js.map +0 -1
- package/lib/Utils/wrap-legacy-store.d.ts.map +0 -1
- package/lib/Utils/wrap-legacy-store.js.map +0 -1
- package/lib/WABinary/generic-utils.d.ts.map +0 -1
- package/lib/WABinary/generic-utils.js.map +0 -1
- package/lib/WABinary/index.d.ts.map +0 -1
- package/lib/WABinary/index.js.map +0 -1
- package/lib/WABinary/jid-utils.d.ts.map +0 -1
- package/lib/WABinary/jid-utils.js.map +0 -1
- package/lib/WAProto/compatibility-schema.d.ts.map +0 -1
- package/lib/WAProto/compatibility-schema.js.map +0 -1
- package/lib/WAProto/runtime.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncLIDProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js.map +0 -1
- package/lib/WAUSync/Protocols/index.d.ts.map +0 -1
- package/lib/WAUSync/Protocols/index.js.map +0 -1
- package/lib/WAUSync/USyncQuery.d.ts.map +0 -1
- package/lib/WAUSync/USyncQuery.js.map +0 -1
- package/lib/WAUSync/USyncUser.d.ts.map +0 -1
- package/lib/WAUSync/USyncUser.js.map +0 -1
- package/lib/WAUSync/index.d.ts.map +0 -1
- package/lib/WAUSync/index.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -27,8 +27,17 @@ so existing integrations can migrate with minimal changes. See
|
|
|
27
27
|
| Key management | JS auth state | Rust `PersistenceManager` |
|
|
28
28
|
| Auto-reconnect | Manual `startSock()` loop | Built-in with fibonacci backoff |
|
|
29
29
|
|
|
30
|
+
## Documentation
|
|
31
|
+
|
|
32
|
+
The full API reference and guides live in the
|
|
33
|
+
**[baileyrs wiki](https://deepwiki.com/oxidezap/baileyrs)** — sending messages and
|
|
34
|
+
media, groups, privacy, newsletters, custom stores, socket configuration,
|
|
35
|
+
error handling, memory monitoring, and more.
|
|
36
|
+
|
|
30
37
|
## Installation
|
|
31
38
|
|
|
39
|
+
Requires Node.js 22 or newer.
|
|
40
|
+
|
|
32
41
|
### New project
|
|
33
42
|
|
|
34
43
|
```sh
|
|
@@ -42,27 +51,26 @@ import makeWASocket from '@oxidezap/baileyrs'
|
|
|
42
51
|
### Drop-in replacement for upstream Baileys
|
|
43
52
|
|
|
44
53
|
baileyrs is API-compatible with [@whiskeysockets/baileys](https://github.com/WhiskeySockets/Baileys).
|
|
45
|
-
Existing projects switch over by aliasing the package — **no source changes needed
|
|
54
|
+
Existing projects switch over by aliasing the package — **no source changes needed**
|
|
55
|
+
(one exception: carrying an existing pairing across takes a one-line import swap,
|
|
56
|
+
see [Migrating from Upstream Baileys](#migrating-from-upstream-baileys)):
|
|
46
57
|
|
|
47
58
|
```sh
|
|
48
59
|
npm install @whiskeysockets/baileys@npm:@oxidezap/baileyrs
|
|
49
60
|
```
|
|
50
61
|
|
|
51
|
-
That writes the alias to your `package.json
|
|
62
|
+
That writes the alias to your `package.json` (with the latest version at install time):
|
|
52
63
|
|
|
53
64
|
```jsonc
|
|
54
65
|
{
|
|
55
66
|
"dependencies": {
|
|
56
|
-
"@whiskeysockets/baileys": "npm:@oxidezap/baileyrs@^
|
|
67
|
+
"@whiskeysockets/baileys": "npm:@oxidezap/baileyrs@^x.x.x"
|
|
57
68
|
}
|
|
58
69
|
}
|
|
59
70
|
```
|
|
60
71
|
|
|
61
72
|
Every `import { makeWASocket } from '@whiskeysockets/baileys'` in your codebase
|
|
62
|
-
now resolves to baileyrs.
|
|
63
|
-
unchanged — see [Migrating from Upstream Baileys](#migrating-from-upstream-baileys)
|
|
64
|
-
for what happens behind the scenes and the (very small) surface where behavior
|
|
65
|
-
differs.
|
|
73
|
+
now resolves to baileyrs.
|
|
66
74
|
|
|
67
75
|
## Quick Start
|
|
68
76
|
|
|
@@ -90,101 +98,11 @@ sock.ev.on('messages.upsert', ({ messages }) => {
|
|
|
90
98
|
console.log('received message', msg.key.id)
|
|
91
99
|
}
|
|
92
100
|
})
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Error Handling
|
|
96
|
-
|
|
97
|
-
baileyrs ships its own `Boom` error class, API-compatible with
|
|
98
|
-
[`@hapi/boom`](https://github.com/hapijs/boom) — no extra dependency needed.
|
|
99
|
-
Methods that fail (including `sendMessage`, media uploads, and connection errors)
|
|
100
|
-
throw a `Boom` with a `statusCode` aligned to WhatsApp disconnect reasons.
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
import { Boom } from '@oxidezap/baileyrs'
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
await sock.sendMessage(jid, { text: 'hi' })
|
|
107
|
-
} catch (err) {
|
|
108
|
-
if (Boom.isBoom(err)) {
|
|
109
|
-
console.log(err.statusCode) // fast path
|
|
110
|
-
console.log(err.output.statusCode) // @hapi/boom-compatible
|
|
111
|
-
console.log(err.data) // optional user payload
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
If you have existing code importing `Boom` from `@hapi/boom`, the
|
|
117
|
-
`(err as Boom)?.output?.statusCode` pattern continues to work via structural
|
|
118
|
-
typing — only the underlying dependency changed.
|
|
119
|
-
|
|
120
|
-
## Connecting
|
|
121
|
-
|
|
122
|
-
### QR Code
|
|
123
|
-
|
|
124
|
-
```ts
|
|
125
|
-
const sock = makeWASocket({
|
|
126
|
-
auth: state,
|
|
127
|
-
browser: Browsers.ubuntu('My App')
|
|
128
|
-
})
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
A QR code will be emitted via `connection.update` events. Scan it with your phone.
|
|
132
|
-
|
|
133
|
-
### Pairing Code
|
|
134
|
-
|
|
135
|
-
```ts
|
|
136
|
-
const sock = makeWASocket({ auth: state })
|
|
137
101
|
|
|
138
|
-
|
|
139
|
-
const code = await sock.requestPairingCode('5511999999999')
|
|
140
|
-
console.log('Pairing code:', code)
|
|
141
|
-
}
|
|
102
|
+
await sock.sendMessage('1234567890@s.whatsapp.net', { text: 'Hello!' })
|
|
142
103
|
```
|
|
143
104
|
|
|
144
|
-
##
|
|
145
|
-
|
|
146
|
-
All state — crypto keys, Signal sessions, device identity, and push name — is managed and persisted by the Rust bridge. No `creds.json`, no `saveCreds` callback.
|
|
147
|
-
|
|
148
|
-
```ts
|
|
149
|
-
import { useMultiFileAuthState } from '@oxidezap/baileyrs'
|
|
150
|
-
|
|
151
|
-
const { state } = await useMultiFileAuthState('auth_folder')
|
|
152
|
-
const sock = makeWASocket({ auth: state })
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Files created in `auth_folder/`:
|
|
156
|
-
- `device-*.bin` — Rust device state (noise keys, identity, push name, etc.)
|
|
157
|
-
- `session-*.bin` — Signal sessions
|
|
158
|
-
- `identity-*.bin` — Signal identity keys
|
|
159
|
-
- `pre-key-*.bin` — Signal pre-keys
|
|
160
|
-
- `sender-key-*.bin` — Group sender keys
|
|
161
|
-
|
|
162
|
-
### Custom Store (Native)
|
|
163
|
-
|
|
164
|
-
For new deployments, implement `JsStoreCallbacks` directly — a flat binary key-value store. The Rust bridge handles all serialization internally.
|
|
165
|
-
|
|
166
|
-
```ts
|
|
167
|
-
import makeWASocket from '@oxidezap/baileyrs'
|
|
168
|
-
|
|
169
|
-
const store = {
|
|
170
|
-
async get(store: string, key: string): Promise<Uint8Array | null> {
|
|
171
|
-
// read from your DB: SELECT value FROM wa_store WHERE store=? AND key=?
|
|
172
|
-
},
|
|
173
|
-
async set(store: string, key: string, value: Uint8Array): Promise<void> {
|
|
174
|
-
// upsert to your DB: INSERT ... ON DUPLICATE KEY UPDATE
|
|
175
|
-
},
|
|
176
|
-
async delete(store: string, key: string): Promise<void> {
|
|
177
|
-
// delete from your DB: DELETE FROM wa_store WHERE store=? AND key=?
|
|
178
|
-
},
|
|
179
|
-
async flush(): Promise<void> { /* flush pending writes if you batch */ }
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const sock = makeWASocket({ auth: { store } })
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
No creds management, no type routing — just `(store, key) → bytes`. Works with any backend (MySQL, Redis, S3, etc.).
|
|
186
|
-
|
|
187
|
-
### Migrating from Upstream Baileys
|
|
105
|
+
## Migrating from Upstream Baileys
|
|
188
106
|
|
|
189
107
|
baileyrs accepts the upstream `auth: { creds, keys }` shape directly — the
|
|
190
108
|
internal `wrapLegacyStore` adapter runs automatically when it sees that
|
|
@@ -217,22 +135,24 @@ Same approach works for any custom upstream auth (`useMySQLAuthState`,
|
|
|
217
135
|
`useRedisAuthState`, mysql-baileys, etc.) — your loader keeps returning
|
|
218
136
|
`{creds, keys, saveCreds}`, baileyrs auto-wraps it on the way in.
|
|
219
137
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
signed pre-keys, and Signal sessions are all preserved. No QR re-scan,
|
|
226
|
-
no logged-out events.
|
|
138
|
+
Existing sessions migrate without re-pairing: `useLegacyMultiFileAuthState`
|
|
139
|
+
reads the existing `creds.json` + `pre-key-*.json` / `session-*.json` files
|
|
140
|
+
from the same folder upstream Baileys was using and hands them to the Rust
|
|
141
|
+
engine. Pair-ID, identity, signed pre-keys, and Signal sessions are all
|
|
142
|
+
preserved. No QR re-scan, no logged-out events.
|
|
227
143
|
|
|
228
144
|
> **Where the new state goes**: baileyrs continues to write the legacy
|
|
229
145
|
> JSON files (via `saveCreds`) so the folder stays compatible with both
|
|
230
146
|
> sides during a rollback window. The Rust engine treats the JSON as the
|
|
231
147
|
> source of truth as long as you keep using `useLegacyMultiFileAuthState`.
|
|
148
|
+
> One edge case: a Signal session imported while it still had pending
|
|
149
|
+
> out-of-order message gaps becomes native-only on its first write-back —
|
|
150
|
+
> after a rollback, that one session re-establishes itself through a fresh
|
|
151
|
+
> Signal handshake (automatic; no re-pairing, other sessions unaffected).
|
|
232
152
|
> If you later want to drop the JSON layer, switch to
|
|
233
153
|
> `useMultiFileAuthState` — but that path requires a fresh QR.
|
|
234
154
|
|
|
235
|
-
|
|
155
|
+
### Gotchas
|
|
236
156
|
|
|
237
157
|
A few behaviors that differ from upstream — almost always to your advantage:
|
|
238
158
|
|
|
@@ -243,359 +163,10 @@ A few behaviors that differ from upstream — almost always to your advantage:
|
|
|
243
163
|
side caches group metadata and message keys natively. You can still pass
|
|
244
164
|
them — they're respected as overrides — but they're optional.
|
|
245
165
|
- **`Boom` ships in the box.** baileyrs exports its own
|
|
246
|
-
`@hapi/boom`-compatible `Boom
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
#### Manual `wrapLegacyStore` (advanced)
|
|
252
|
-
|
|
253
|
-
If you want explicit control over when the adapter runs (testing, custom
|
|
254
|
-
shapes, mixed storage), call it yourself:
|
|
255
|
-
|
|
256
|
-
```ts
|
|
257
|
-
import makeWASocket, { useLegacyMultiFileAuthState, wrapLegacyStore } from '@oxidezap/baileyrs'
|
|
258
|
-
|
|
259
|
-
const { state, saveCreds } = await useLegacyMultiFileAuthState('/path/to/baileys_auth_info')
|
|
260
|
-
const store = await wrapLegacyStore(state, saveCreds)
|
|
261
|
-
const sock = makeWASocket({ auth: { store } })
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
## Sending Messages
|
|
265
|
-
|
|
266
|
-
```ts
|
|
267
|
-
// Text
|
|
268
|
-
await sock.sendMessage(jid, { text: 'Hello!' })
|
|
269
|
-
|
|
270
|
-
// Quote
|
|
271
|
-
await sock.sendMessage(jid, { text: 'Reply' }, { quoted: msg })
|
|
272
|
-
|
|
273
|
-
// Mention
|
|
274
|
-
await sock.sendMessage(jid, {
|
|
275
|
-
text: '@12345678901',
|
|
276
|
-
mentions: ['12345678901@s.whatsapp.net']
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
// Forward
|
|
280
|
-
await sock.sendMessage(jid, { forward: msg })
|
|
281
|
-
|
|
282
|
-
// Location
|
|
283
|
-
await sock.sendMessage(jid, {
|
|
284
|
-
location: { degreesLatitude: 24.12, degreesLongitude: 55.11 }
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
// Contact
|
|
288
|
-
await sock.sendMessage(jid, {
|
|
289
|
-
contacts: {
|
|
290
|
-
displayName: 'Jeff',
|
|
291
|
-
contacts: [{ vcard: 'BEGIN:VCARD\nVERSION:3.0\nFN:Jeff\nEND:VCARD' }]
|
|
292
|
-
}
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
// Reaction
|
|
296
|
-
await sock.sendMessage(jid, { react: { text: '💖', key: msg.key } })
|
|
297
|
-
|
|
298
|
-
// Poll
|
|
299
|
-
await sock.sendMessage(jid, {
|
|
300
|
-
poll: { name: 'My Poll', values: ['Yes', 'No'], selectableCount: 1 }
|
|
301
|
-
})
|
|
302
|
-
|
|
303
|
-
// Delete (for everyone)
|
|
304
|
-
await sock.sendMessage(jid, { delete: msg.key })
|
|
305
|
-
|
|
306
|
-
// Edit
|
|
307
|
-
await sock.sendMessage(jid, { text: 'updated text', edit: msg.key })
|
|
308
|
-
|
|
309
|
-
// Disappearing messages
|
|
310
|
-
await sock.sendMessage(jid, { disappearingMessagesInChat: 604800 }) // 7 days
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
### Media Messages
|
|
314
|
-
|
|
315
|
-
Media encryption, upload, and CDN failover are handled entirely by the Rust bridge.
|
|
316
|
-
|
|
317
|
-
```ts
|
|
318
|
-
// Image
|
|
319
|
-
await sock.sendMessage(jid, { image: readFileSync('photo.jpg'), caption: 'Hello' })
|
|
320
|
-
|
|
321
|
-
// Video
|
|
322
|
-
await sock.sendMessage(jid, { video: { url: './clip.mp4' }, caption: 'Watch this' })
|
|
323
|
-
|
|
324
|
-
// Audio
|
|
325
|
-
await sock.sendMessage(jid, { audio: { url: './audio.ogg' }, mimetype: 'audio/ogg; codecs=opus' })
|
|
326
|
-
|
|
327
|
-
// Document
|
|
328
|
-
await sock.sendMessage(jid, {
|
|
329
|
-
document: { url: './file.pdf' },
|
|
330
|
-
mimetype: 'application/pdf',
|
|
331
|
-
fileName: 'report.pdf'
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
// View once
|
|
335
|
-
await sock.sendMessage(jid, { image: { url: './photo.jpg' }, viewOnce: true })
|
|
336
|
-
|
|
337
|
-
// GIF (mp4 with gifPlayback)
|
|
338
|
-
await sock.sendMessage(jid, { video: readFileSync('anim.mp4'), gifPlayback: true })
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
> Thumbnails are auto-generated for images (requires `jimp` or `sharp`). Video thumbnails need `ffmpeg` on your system, or provide `jpegThumbnail` directly.
|
|
342
|
-
|
|
343
|
-
#### Streaming Upload (Large Files)
|
|
344
|
-
|
|
345
|
-
For files that are too large to buffer in memory, pass a `processMedia` hook to `sendMessage`:
|
|
346
|
-
|
|
347
|
-
```ts
|
|
348
|
-
await sock.sendMessage(jid, { video: readFileSync('large-video.mp4') }, {
|
|
349
|
-
processMedia: async (buffer, mediaType, waClient) => {
|
|
350
|
-
const { Writable } = await import('node:stream')
|
|
351
|
-
const fs = await import('node:fs')
|
|
352
|
-
const os = await import('node:os')
|
|
353
|
-
const path = await import('node:path')
|
|
354
|
-
|
|
355
|
-
const tmpEnc = path.join(os.tmpdir(), `enc-${Date.now()}`)
|
|
356
|
-
|
|
357
|
-
// Streaming encrypt → temp file (constant ~40KB memory)
|
|
358
|
-
const input = new Blob([new Uint8Array(buffer)]).stream()
|
|
359
|
-
const output = Writable.toWeb(fs.createWriteStream(tmpEnc))
|
|
360
|
-
const enc = await waClient.encryptMediaStream(input, output, mediaType)
|
|
361
|
-
|
|
362
|
-
// Upload from temp file
|
|
363
|
-
const encData = await fs.promises.readFile(tmpEnc)
|
|
364
|
-
await fs.promises.unlink(tmpEnc)
|
|
365
|
-
|
|
366
|
-
const upload = await waClient.uploadEncryptedMediaStream(
|
|
367
|
-
() => new Blob([new Uint8Array(encData)]).stream(),
|
|
368
|
-
enc.mediaKey, enc.fileSha256, enc.fileEncSha256, enc.fileLength, mediaType
|
|
369
|
-
)
|
|
370
|
-
|
|
371
|
-
return { upload: { ...upload, ...enc } }
|
|
372
|
-
}
|
|
373
|
-
})
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Downloading Media
|
|
377
|
-
|
|
378
|
-
The recommended way to download media is via the socket method — it handles CDN failover, auth refresh, HMAC verification, and media re-upload automatically:
|
|
379
|
-
|
|
380
|
-
```ts
|
|
381
|
-
// Buffer (recommended)
|
|
382
|
-
const buffer = await sock.downloadMedia(msg, 'buffer')
|
|
383
|
-
await writeFile('photo.jpg', buffer)
|
|
384
|
-
|
|
385
|
-
// Stream
|
|
386
|
-
const stream = await sock.downloadMedia(msg, 'stream')
|
|
387
|
-
for await (const chunk of stream) {
|
|
388
|
-
// process chunk — only ~64KB in memory at a time
|
|
389
|
-
}
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
<details>
|
|
393
|
-
<summary>Advanced: standalone utility (for use without a socket)</summary>
|
|
394
|
-
|
|
395
|
-
If you need to download media outside of a socket context (e.g., custom logger or reupload logic), use the standalone `downloadMediaMessage` utility:
|
|
396
|
-
|
|
397
|
-
```ts
|
|
398
|
-
import { downloadMediaMessage } from '@oxidezap/baileyrs'
|
|
399
|
-
|
|
400
|
-
const buffer = await downloadMediaMessage(msg, 'buffer', {}, {
|
|
401
|
-
logger: sock.logger,
|
|
402
|
-
reuploadRequest: m => sock.updateMediaMessage(m),
|
|
403
|
-
waClient: sock.waClient!
|
|
404
|
-
})
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
</details>
|
|
408
|
-
|
|
409
|
-
### Re-upload Expired Media
|
|
410
|
-
```ts
|
|
411
|
-
await sock.updateMediaMessage(msg)
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
## Read Receipts
|
|
415
|
-
|
|
416
|
-
```ts
|
|
417
|
-
await sock.readMessages([{ remoteJid: msg.key.remoteJid!, id: msg.key.id! }])
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
## Presence
|
|
421
|
-
|
|
422
|
-
```ts
|
|
423
|
-
// Online/offline
|
|
424
|
-
await sock.sendPresenceUpdate('available')
|
|
425
|
-
await sock.sendPresenceUpdate('unavailable')
|
|
426
|
-
|
|
427
|
-
// Subscribe to a contact's presence
|
|
428
|
-
await sock.presenceSubscribe(jid)
|
|
429
|
-
|
|
430
|
-
// Typing indicator
|
|
431
|
-
await sock.sendChatState(jid, 'composing')
|
|
432
|
-
await sock.sendChatState(jid, 'paused')
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
## Chat Actions
|
|
436
|
-
|
|
437
|
-
```ts
|
|
438
|
-
await sock.pinChat(jid, true)
|
|
439
|
-
await sock.muteChat(jid, 8 * 60 * 60 * 1000) // mute 8h
|
|
440
|
-
await sock.muteChat(jid, null) // unmute
|
|
441
|
-
await sock.archiveChat(jid, true)
|
|
442
|
-
await sock.starMessage(jid, msgId, true)
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
## Reject Calls
|
|
446
|
-
|
|
447
|
-
```ts
|
|
448
|
-
await sock.rejectCall(callId, callFrom)
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
## User Queries
|
|
452
|
-
|
|
453
|
-
```ts
|
|
454
|
-
// Check if on WhatsApp
|
|
455
|
-
const [result] = await sock.onWhatsApp('+1234567890')
|
|
456
|
-
if (result.exists) console.log('JID:', result.jid)
|
|
457
|
-
|
|
458
|
-
// Fetch status
|
|
459
|
-
const status = await sock.fetchStatus(jid)
|
|
460
|
-
|
|
461
|
-
// Profile picture
|
|
462
|
-
const url = await sock.profilePictureUrl(jid, 'image')
|
|
463
|
-
|
|
464
|
-
// Business profile
|
|
465
|
-
const profile = await sock.getBusinessProfile(jid)
|
|
466
|
-
|
|
467
|
-
// On-demand history (messages arrive via messaging-history.set event)
|
|
468
|
-
await sock.fetchMessageHistory(50, oldestMsg.key, oldestMsg.messageTimestamp)
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
## Profile
|
|
472
|
-
|
|
473
|
-
```ts
|
|
474
|
-
await sock.setPushName('My Name')
|
|
475
|
-
await sock.updateProfileStatus('Hello World!')
|
|
476
|
-
await sock.updateProfilePicture(jid, imageBytes)
|
|
477
|
-
await sock.removeProfilePicture()
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
## Groups
|
|
481
|
-
|
|
482
|
-
```ts
|
|
483
|
-
// Create
|
|
484
|
-
const group = await sock.groupCreate('Group Name', ['1234@s.whatsapp.net'])
|
|
485
|
-
|
|
486
|
-
// Participants
|
|
487
|
-
await sock.groupParticipantsUpdate(jid, ['1234@s.whatsapp.net'], 'add') // or 'remove', 'promote', 'demote'
|
|
488
|
-
|
|
489
|
-
// Metadata
|
|
490
|
-
const metadata = await sock.groupMetadata(jid)
|
|
491
|
-
const all = await sock.groupFetchAllParticipating()
|
|
492
|
-
|
|
493
|
-
// Settings
|
|
494
|
-
await sock.groupUpdateSubject(jid, 'New Name')
|
|
495
|
-
await sock.groupUpdateDescription(jid, 'New Description')
|
|
496
|
-
await sock.groupSettingUpdate(jid, 'announce', true) // only admins send
|
|
497
|
-
await sock.groupSettingUpdate(jid, 'locked', true) // only admins edit settings
|
|
498
|
-
await sock.groupToggleEphemeral(jid, 604800) // 7 days
|
|
499
|
-
await sock.groupMemberAddMode(jid, 'admin_add') // or 'all_member_add'
|
|
500
|
-
|
|
501
|
-
// Invite
|
|
502
|
-
const code = await sock.groupInviteCode(jid)
|
|
503
|
-
const newCode = await sock.groupRevokeInvite(jid)
|
|
504
|
-
const response = await sock.groupAcceptInvite(code)
|
|
505
|
-
const info = await sock.groupGetInviteInfo(code)
|
|
506
|
-
|
|
507
|
-
// Join requests
|
|
508
|
-
const requests = await sock.groupRequestParticipantsList(jid)
|
|
509
|
-
await sock.groupRequestParticipantsUpdate(jid, ['1234@s.whatsapp.net'], 'approve')
|
|
510
|
-
|
|
511
|
-
// Leave
|
|
512
|
-
await sock.groupLeave(jid)
|
|
513
|
-
```
|
|
514
|
-
|
|
515
|
-
## Privacy
|
|
516
|
-
|
|
517
|
-
```ts
|
|
518
|
-
// Block/unblock
|
|
519
|
-
await sock.updateBlockStatus(jid, 'block')
|
|
520
|
-
await sock.updateBlockStatus(jid, 'unblock')
|
|
521
|
-
|
|
522
|
-
// Fetch
|
|
523
|
-
const settings = await sock.fetchPrivacySettings()
|
|
524
|
-
const blocklist = await sock.fetchBlocklist()
|
|
525
|
-
|
|
526
|
-
// Update privacy settings
|
|
527
|
-
await sock.updateLastSeenPrivacy('contacts') // 'all' | 'contacts' | 'contact_blacklist' | 'none'
|
|
528
|
-
await sock.updateOnlinePrivacy('all') // 'all' | 'match_last_seen'
|
|
529
|
-
await sock.updateProfilePicturePrivacy('contacts')
|
|
530
|
-
await sock.updateStatusPrivacy('contacts')
|
|
531
|
-
await sock.updateReadReceiptsPrivacy('all') // 'all' | 'none'
|
|
532
|
-
await sock.updateGroupsAddPrivacy('contacts')
|
|
533
|
-
await sock.updateDefaultDisappearingMode(604800) // seconds, 0 to disable
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
## Newsletters (Channels)
|
|
537
|
-
|
|
538
|
-
```ts
|
|
539
|
-
const channel = await sock.newsletterCreate('My Channel', 'Description')
|
|
540
|
-
const meta = await sock.newsletterMetadata(jid)
|
|
541
|
-
await sock.newsletterSubscribe(jid)
|
|
542
|
-
await sock.newsletterUnsubscribe(jid)
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
## Memory Monitoring
|
|
546
|
-
|
|
547
|
-
```ts
|
|
548
|
-
import { getWasmMemoryBytes } from 'whatsapp-rust-bridge'
|
|
549
|
-
|
|
550
|
-
// WASM linear memory (total reserved)
|
|
551
|
-
const wasmBytes = getWasmMemoryBytes()
|
|
552
|
-
console.log(`WASM memory: ${(wasmBytes / 1024 / 1024).toFixed(1)} MB`)
|
|
553
|
-
|
|
554
|
-
// Detailed cache/collection diagnostics from the Rust engine
|
|
555
|
-
const diag = await sock.waClient!.getMemoryDiagnostics()
|
|
556
|
-
console.log(diag) // { signalCacheSessions, groupCache, deviceCache, ... }
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
## Socket Config
|
|
560
|
-
|
|
561
|
-
```ts
|
|
562
|
-
const sock = makeWASocket({
|
|
563
|
-
// Required
|
|
564
|
-
auth: state,
|
|
565
|
-
|
|
566
|
-
// Connection
|
|
567
|
-
waWebSocketUrl: 'wss://web.whatsapp.com/ws/chat',
|
|
568
|
-
connectTimeoutMs: 20_000,
|
|
569
|
-
keepAliveIntervalMs: 30_000,
|
|
570
|
-
|
|
571
|
-
// Identity
|
|
572
|
-
version: [2, 3000, 1035194821],
|
|
573
|
-
browser: Browsers.macOS('Chrome'),
|
|
574
|
-
|
|
575
|
-
// Events
|
|
576
|
-
emitOwnEvents: true,
|
|
577
|
-
shouldIgnoreJid: jid => false,
|
|
578
|
-
|
|
579
|
-
// Proxy (for fetch/HTTP requests — uses undici dispatcher)
|
|
580
|
-
options: { dispatcher: undiciAgent },
|
|
581
|
-
|
|
582
|
-
// Cache (Rust-side, see CacheConfig type)
|
|
583
|
-
cache: { group: { ttlSecs: 7200 } },
|
|
584
|
-
|
|
585
|
-
// Optional override for the display identity sent at pairing.
|
|
586
|
-
// Orthogonal to `browser`. Only takes effect on the initial pairing.
|
|
587
|
-
deviceProps: { os: '...', platformType: 'CHROME' }
|
|
588
|
-
})
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
## Relationship to Baileys
|
|
592
|
-
|
|
593
|
-
baileyrs began as a fork of [WhiskeySockets/Baileys](https://github.com/WhiskeySockets/Baileys)
|
|
594
|
-
but the internals have been rewritten from the ground up on top of
|
|
595
|
-
[whatsapp-rust](https://github.com/oxidezap/whatsapp-rust). Only the public API shape
|
|
596
|
-
is preserved, to make migration from Baileys straightforward.
|
|
597
|
-
|
|
598
|
-
See [ATTRIBUTION.md](ATTRIBUTION.md) for the full attribution notice.
|
|
166
|
+
`@hapi/boom`-compatible `Boom`, so the existing
|
|
167
|
+
`(err as Boom).output.statusCode` pattern works unchanged. If your
|
|
168
|
+
`package.json` was pulling `@hapi/boom` only for baileys, you can drop
|
|
169
|
+
the dependency.
|
|
599
170
|
|
|
600
171
|
## Disclaimer
|
|
601
172
|
|
|
@@ -35,8 +35,24 @@ export const decodeHistorySyncWireBatch = (batch, logger) => {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
conversations.length = decodedConversations;
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
// The non-conversation remainder (pushnames, mappings, settings, ...)
|
|
39
|
+
// crosses as one encoded proto.HistorySync payload. The bridge's metadata
|
|
40
|
+
// envelope owns the canonical syncType/chunkOrder/progress values, so those
|
|
41
|
+
// (and the conversations decoded above) are dropped from the remainder
|
|
42
|
+
// instead of merged — that also keeps the proto side's `| null` field types
|
|
43
|
+
// out of the event contract.
|
|
44
|
+
const { conversationData: _wireData, conversationOffsets: _wireOffsets, remainderData, ...metadata } = batch;
|
|
45
|
+
let remainderFields = {};
|
|
46
|
+
if (remainderData && remainderData.length > 0) {
|
|
47
|
+
try {
|
|
48
|
+
const { syncType: _syncType, chunkOrder: _chunkOrder, progress: _progress, conversations: _conversations, ...rest } = WAProto.HistorySync.decode(remainderData);
|
|
49
|
+
remainderFields = rest;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
logger.warn({ err }, 'skipping undecodable history-sync remainder');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const data = { ...remainderFields, ...metadata, conversations };
|
|
40
56
|
return {
|
|
41
57
|
event: { type: HISTORY_SYNC_EVENT_TYPE, data },
|
|
42
58
|
skippedConversations
|
package/lib/Socket/events.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* mapped type so TS forces a handler per variant — a missing handler
|
|
7
7
|
* is a compile error.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { BinaryReader } from 'whatsapp-rust-bridge';
|
|
10
10
|
import { adaptBridgeEvent, adaptBridgeMessageWire } from '../Bridge/index.js';
|
|
11
11
|
import { decodeHistorySyncWireBatch } from '../Bridge/history-sync-wire.js';
|
|
12
12
|
import { bridgeGroupMetadataToBaileys } from '../Compatibility/group-metadata.js';
|
|
@@ -24,7 +24,6 @@ import { mapReachoutTimelock } from './reachout.js';
|
|
|
24
24
|
const CANONICAL_MESSAGE_EVENT = 'message';
|
|
25
25
|
const MESSAGE_UPSERT_APPEND = 'append';
|
|
26
26
|
const MESSAGE_UPSERT_NOTIFY = 'notify';
|
|
27
|
-
const MESSAGE_PROTO_TYPE = 'Message';
|
|
28
27
|
const MESSAGE_WIRE_OFFSET_SENTINEL_COUNT = 1;
|
|
29
28
|
/** Emit CB: pattern events on the ws EventEmitter for retrocompat. */
|
|
30
29
|
const emitCBEvents = (ctx, node) => {
|
|
@@ -779,9 +778,6 @@ export const makeEventHandlers = (ctx, callbacks) => {
|
|
|
779
778
|
if (canonical)
|
|
780
779
|
dispatchCanonicalEvent(canonical, dispatchCtx);
|
|
781
780
|
};
|
|
782
|
-
const onEventBatch = (events) => {
|
|
783
|
-
dispatchCanonicalBatch(ctx, dispatchCtx, events.length, index => adaptBridgeEvent(events[index], ctx.logger));
|
|
784
|
-
};
|
|
785
781
|
const onMessageBatch = (batch) => {
|
|
786
782
|
if (batch.messageOffsets.length < MESSAGE_WIRE_OFFSET_SENTINEL_COUNT) {
|
|
787
783
|
ctx.logger.error('message wire batch is missing its leading offset');
|
|
@@ -792,13 +788,25 @@ export const makeEventHandlers = (ctx, callbacks) => {
|
|
|
792
788
|
ctx.logger.error({ infoCount: batch.infos.length, messageCount }, 'message wire batch metadata count does not match its payload count');
|
|
793
789
|
return;
|
|
794
790
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
791
|
+
// Decode through the runtime facade so each payload materializes as a
|
|
792
|
+
// hydrated runtime instance: `WebMessageInfo.fromObject` then keeps the
|
|
793
|
+
// message subtree via its instanceof short-circuit instead of walking
|
|
794
|
+
// and reallocating the whole tree — the dominant per-message allocation
|
|
795
|
+
// cost on the hot path. Lenient like the history-sync decoder: one
|
|
796
|
+
// malformed payload is skipped, not fatal to the batch.
|
|
797
|
+
const messages = Array.from({ length: messageCount });
|
|
798
|
+
const reader = new BinaryReader(batch.messageData);
|
|
799
|
+
for (let index = 0; index < messageCount; index++) {
|
|
800
|
+
try {
|
|
801
|
+
const start = batch.messageOffsets[index];
|
|
802
|
+
const end = batch.messageOffsets[index + 1];
|
|
803
|
+
reader.pos = start;
|
|
804
|
+
messages[index] = WAProto.Message.decode(reader, end - start);
|
|
805
|
+
}
|
|
806
|
+
catch (err) {
|
|
807
|
+
messages[index] = null;
|
|
808
|
+
ctx.logger.warn({ err, index }, 'skipping malformed wire message');
|
|
809
|
+
}
|
|
802
810
|
}
|
|
803
811
|
dispatchCanonicalBatch(ctx, dispatchCtx, messageCount, index => adaptBridgeMessageWire(messages[index], batch.infos[index], ctx.logger));
|
|
804
812
|
};
|
|
@@ -809,7 +817,6 @@ export const makeEventHandlers = (ctx, callbacks) => {
|
|
|
809
817
|
};
|
|
810
818
|
return {
|
|
811
819
|
onEvent,
|
|
812
|
-
onEventBatch,
|
|
813
820
|
onMessageBatch,
|
|
814
821
|
onHistorySyncBatch,
|
|
815
822
|
historySyncConversationTypes: CONVERSATION_HISTORY_SYNC_TYPES
|
package/lib/WAProto/runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated by scripts/compatibility/waproto-facade.
|
|
1
|
+
// Generated by scripts/compatibility/waproto-facade.ts. Do not edit.
|
|
2
2
|
// Type-only Baileys compatibility facade; runtime codecs remain whatsapp-rust-bridge.
|
|
3
3
|
import * as $protobuf from "protobufjs";
|
|
4
4
|
import Long = require("long");
|