fb-messenger-e2ee 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -2
- package/dist/index.cjs +8811 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +885 -0
- package/dist/index.d.ts +885 -0
- package/dist/index.js +8843 -0
- package/dist/index.js.map +1 -0
- package/package.json +19 -4
- package/bun.lock +0 -1014
- package/examples/basic-usage.ts +0 -52
- package/jest.config.ts +0 -18
- package/src/config/env.ts +0 -15
- package/src/controllers/client.controller.ts +0 -805
- package/src/controllers/dgw-handler.ts +0 -171
- package/src/controllers/e2ee-handler.ts +0 -832
- package/src/controllers/event-mapper.ts +0 -327
- package/src/core/client.ts +0 -151
- package/src/e2ee/application/e2ee-client.ts +0 -376
- package/src/e2ee/application/fanout-planner.ts +0 -79
- package/src/e2ee/application/outbound-message-cache.ts +0 -58
- package/src/e2ee/application/prekey-maintenance.ts +0 -55
- package/src/e2ee/application/retry-manager.ts +0 -156
- package/src/e2ee/facebook/facebook-protocol-utils.ts +0 -230
- package/src/e2ee/facebook/icdc-payload.ts +0 -31
- package/src/e2ee/index.ts +0 -76
- package/src/e2ee/internal.ts +0 -27
- package/src/e2ee/media/media-crypto.ts +0 -147
- package/src/e2ee/media/media-upload.ts +0 -90
- package/src/e2ee/message/builders/client-payload.ts +0 -54
- package/src/e2ee/message/builders/consumer-application.ts +0 -362
- package/src/e2ee/message/builders/message-application.ts +0 -64
- package/src/e2ee/message/builders/message-transport.ts +0 -84
- package/src/e2ee/message/codecs/protobuf-codecs.ts +0 -101
- package/src/e2ee/message/constants.ts +0 -4
- package/src/e2ee/message/message-builder.ts +0 -15
- package/src/e2ee/signal/prekey-manager.ts +0 -140
- package/src/e2ee/signal/signal-manager.ts +0 -365
- package/src/e2ee/store/device-json.ts +0 -47
- package/src/e2ee/store/device-repository.ts +0 -12
- package/src/e2ee/store/device-store.ts +0 -538
- package/src/e2ee/transport/binary/decoder.ts +0 -180
- package/src/e2ee/transport/binary/encoder.ts +0 -143
- package/src/e2ee/transport/binary/stanzas.ts +0 -97
- package/src/e2ee/transport/binary/tokens.ts +0 -64
- package/src/e2ee/transport/binary/wa-binary.ts +0 -8
- package/src/e2ee/transport/dgw/dgw-socket.ts +0 -345
- package/src/e2ee/transport/noise/noise-handshake.ts +0 -417
- package/src/e2ee/transport/noise/noise-socket.ts +0 -230
- package/src/index.ts +0 -34
- package/src/models/client.ts +0 -26
- package/src/models/config.ts +0 -14
- package/src/models/domain.ts +0 -299
- package/src/models/e2ee.ts +0 -295
- package/src/models/media.ts +0 -41
- package/src/models/messaging.ts +0 -88
- package/src/models/thread.ts +0 -69
- package/src/repositories/session.repository.ts +0 -20
- package/src/services/auth.service.ts +0 -55
- package/src/services/e2ee.service.ts +0 -174
- package/src/services/facebook-gateway.service.ts +0 -245
- package/src/services/icdc.service.ts +0 -177
- package/src/services/media.service.ts +0 -304
- package/src/services/messaging.service.ts +0 -28
- package/src/services/thread.service.ts +0 -199
- package/src/types/advanced-types.ts +0 -61
- package/src/types/fca-unofficial.d.ts +0 -212
- package/src/types/protocol-types.ts +0 -43
- package/src/utils/fca-utils.ts +0 -30
- package/src/utils/logger.ts +0 -24
- package/src/utils/mime.ts +0 -51
- package/tests/.env.example +0 -87
- package/tests/data/1x1.png +0 -0
- package/tests/data/example.txt +0 -1
- package/tests/data/file_example.mp3 +0 -0
- package/tests/data/file_example.mp4 +0 -0
- package/tests/integration.test.ts +0 -498
- package/tests/script/echo-e2ee.ts +0 -174
- package/tests/script/send-e2ee-media.ts +0 -227
- package/tests/script/send-e2ee-reaction.ts +0 -108
- package/tests/script/send-e2ee-unsend.ts +0 -115
- package/tests/script/send-typing.ts +0 -107
- package/tests/script/test-group-send.ts +0 -105
- package/tests/setup.ts +0 -3
- package/tests/types.test.ts +0 -57
- package/tests/unit/controllers/dgw-handler.test.ts +0 -60
- package/tests/unit/controllers/e2ee-handler.test.ts +0 -293
- package/tests/unit/controllers/event-mapper.test.ts +0 -252
- package/tests/unit/e2ee/application-helpers.test.ts +0 -418
- package/tests/unit/e2ee/device-store.test.ts +0 -126
- package/tests/unit/e2ee/facebook-protocol-utils.test.ts +0 -134
- package/tests/unit/e2ee/media-crypto.test.ts +0 -55
- package/tests/unit/e2ee/media-upload.test.ts +0 -60
- package/tests/unit/e2ee/message-builder.test.ts +0 -42
- package/tests/unit/e2ee/message-builders.test.ts +0 -230
- package/tests/unit/e2ee/noise-handshake.test.ts +0 -260
- package/tests/unit/e2ee/prekey-manager.test.ts +0 -55
- package/tests/unit/e2ee/wa-binary.test.ts +0 -127
- package/tests/unit/services/e2ee.service.test.ts +0 -101
- package/tests/unit/services/facebook-gateway.service.test.ts +0 -138
- package/tests/unit/services/media.service.test.ts +0 -169
- package/tests/unit/utils/fca-utils.test.ts +0 -48
- package/tsconfig.json +0 -19
- /package/{src/e2ee/message/proto → proto}/ArmadilloApplication.proto +0 -0
- /package/{src/e2ee/message/proto → proto}/ArmadilloICDC.proto +0 -0
- /package/{src/e2ee/message/proto → proto}/ConsumerApplication.proto +0 -0
- /package/{src/e2ee/message/proto → proto}/MessageApplication.proto +0 -0
- /package/{src/e2ee/message/proto → proto}/MessageTransport.proto +0 -0
- /package/{src/e2ee/message/proto → proto}/WACommon.proto +0 -0
- /package/{src/e2ee/message/proto → proto}/WAMediaTransport.proto +0 -0
- /package/{src/e2ee/message/proto → proto}/proto-writer.ts +0 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,885 @@
|
|
|
1
|
+
import { IdentityKeyStore, SessionStore, PreKeyStore, SignedPreKeyStore, SenderKeyStore, KyberPreKeyStore, PrivateKey, ProtocolAddress, PublicKey, Direction, SessionRecord, PreKeyRecord, SignedPreKeyRecord, SenderKeyRecord, KyberPreKeyRecord, IdentityKeyPair } from '@signalapp/libsignal-client';
|
|
2
|
+
|
|
3
|
+
type Platform = "facebook" | "messenger";
|
|
4
|
+
interface BaseAttachment {
|
|
5
|
+
url?: string;
|
|
6
|
+
fileName?: string;
|
|
7
|
+
mimeType?: string;
|
|
8
|
+
fileSize?: number;
|
|
9
|
+
/** For E2EE media download - base64-encoded */
|
|
10
|
+
mediaKey?: string;
|
|
11
|
+
mediaSha256?: string;
|
|
12
|
+
mediaEncSha256?: string;
|
|
13
|
+
directPath?: string;
|
|
14
|
+
}
|
|
15
|
+
interface ImageAttachment extends BaseAttachment {
|
|
16
|
+
type: "image" | "gif" | "photo";
|
|
17
|
+
width?: number;
|
|
18
|
+
height?: number;
|
|
19
|
+
previewUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
interface VideoAttachment extends BaseAttachment {
|
|
22
|
+
type: "video";
|
|
23
|
+
width?: number;
|
|
24
|
+
height?: number;
|
|
25
|
+
duration?: number;
|
|
26
|
+
previewUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
interface AudioAttachment extends BaseAttachment {
|
|
29
|
+
type: "audio" | "voice";
|
|
30
|
+
duration?: number;
|
|
31
|
+
}
|
|
32
|
+
interface FileAttachment extends BaseAttachment {
|
|
33
|
+
type: "file";
|
|
34
|
+
}
|
|
35
|
+
interface StickerAttachment extends BaseAttachment {
|
|
36
|
+
type: "sticker";
|
|
37
|
+
stickerID: number;
|
|
38
|
+
}
|
|
39
|
+
interface LocationAttachment extends BaseAttachment {
|
|
40
|
+
type: "location";
|
|
41
|
+
latitude: number;
|
|
42
|
+
longitude: number;
|
|
43
|
+
}
|
|
44
|
+
interface LinkAttachment extends BaseAttachment {
|
|
45
|
+
type: "link";
|
|
46
|
+
description?: string;
|
|
47
|
+
sourceText?: string;
|
|
48
|
+
previewUrl?: string;
|
|
49
|
+
}
|
|
50
|
+
type Attachment = ImageAttachment | VideoAttachment | AudioAttachment | FileAttachment | StickerAttachment | LocationAttachment | LinkAttachment;
|
|
51
|
+
interface Mention {
|
|
52
|
+
userId: string;
|
|
53
|
+
/** UTF-16 code unit offset in the message text */
|
|
54
|
+
offset: number;
|
|
55
|
+
/** UTF-16 code unit length */
|
|
56
|
+
length: number;
|
|
57
|
+
/** "user" | "thread" | "group" */
|
|
58
|
+
type?: string;
|
|
59
|
+
}
|
|
60
|
+
interface ReplyTo {
|
|
61
|
+
messageId: string;
|
|
62
|
+
senderId?: string;
|
|
63
|
+
text?: string;
|
|
64
|
+
}
|
|
65
|
+
interface MessengerMessage {
|
|
66
|
+
id: string;
|
|
67
|
+
threadId: string;
|
|
68
|
+
senderId: string;
|
|
69
|
+
text: string;
|
|
70
|
+
timestampMs: number;
|
|
71
|
+
replyTo?: ReplyTo;
|
|
72
|
+
attachments?: Attachment[];
|
|
73
|
+
mentions?: Mention[];
|
|
74
|
+
isAdminMsg?: boolean;
|
|
75
|
+
}
|
|
76
|
+
type E2EEMessageKind = "text" | "image" | "video" | "audio" | "document" | "sticker" | "reaction" | "edit" | "revoke" | "unknown";
|
|
77
|
+
interface BaseE2EEMessage {
|
|
78
|
+
id: string;
|
|
79
|
+
/** Stable conversation ID. For DMs this is the bare Facebook user ID; for groups it is the group JID. */
|
|
80
|
+
threadId: string;
|
|
81
|
+
/** Canonical E2EE chat JID. For DMs this uses the bare .0 Messenger device; senderJid keeps the actual sender device. */
|
|
82
|
+
chatJid: string;
|
|
83
|
+
/** Device-specific sender JID, e.g. user.device@msgr. */
|
|
84
|
+
senderJid: string;
|
|
85
|
+
/** Bare Facebook sender/user ID. */
|
|
86
|
+
senderId: string;
|
|
87
|
+
senderDeviceId?: number;
|
|
88
|
+
isGroup: boolean;
|
|
89
|
+
kind: E2EEMessageKind;
|
|
90
|
+
/** Text body when present; empty string for non-text E2EE events. */
|
|
91
|
+
text: string;
|
|
92
|
+
timestampMs: number;
|
|
93
|
+
attachments?: Attachment[];
|
|
94
|
+
replyTo?: ReplyTo;
|
|
95
|
+
mentions?: Mention[];
|
|
96
|
+
}
|
|
97
|
+
interface E2EETextMessage extends BaseE2EEMessage {
|
|
98
|
+
kind: "text";
|
|
99
|
+
text: string;
|
|
100
|
+
}
|
|
101
|
+
interface E2EEMediaMessage extends BaseE2EEMessage {
|
|
102
|
+
kind: "image" | "video" | "audio" | "document" | "sticker";
|
|
103
|
+
media?: unknown;
|
|
104
|
+
}
|
|
105
|
+
interface E2EEReactionMessage extends BaseE2EEMessage {
|
|
106
|
+
kind: "reaction";
|
|
107
|
+
reaction: string;
|
|
108
|
+
targetId?: string;
|
|
109
|
+
}
|
|
110
|
+
interface E2EEEditMessage extends BaseE2EEMessage {
|
|
111
|
+
kind: "edit";
|
|
112
|
+
targetId?: string;
|
|
113
|
+
}
|
|
114
|
+
interface E2EERevokeMessage extends BaseE2EEMessage {
|
|
115
|
+
kind: "revoke";
|
|
116
|
+
targetId?: string;
|
|
117
|
+
fromMe?: boolean;
|
|
118
|
+
}
|
|
119
|
+
interface E2EEUnknownMessage extends BaseE2EEMessage {
|
|
120
|
+
kind: "unknown";
|
|
121
|
+
raw?: unknown;
|
|
122
|
+
}
|
|
123
|
+
type E2EEMessage = E2EETextMessage | E2EEMediaMessage | E2EEReactionMessage | E2EEEditMessage | E2EERevokeMessage | E2EEUnknownMessage;
|
|
124
|
+
type MessengerEvent = {
|
|
125
|
+
type: "message";
|
|
126
|
+
data: MessengerMessage;
|
|
127
|
+
} | {
|
|
128
|
+
type: "messageEdit";
|
|
129
|
+
data: {
|
|
130
|
+
messageId: string;
|
|
131
|
+
threadId: string;
|
|
132
|
+
newText: string;
|
|
133
|
+
editCount: number;
|
|
134
|
+
timestampMs: number;
|
|
135
|
+
};
|
|
136
|
+
} | {
|
|
137
|
+
type: "reaction";
|
|
138
|
+
data: {
|
|
139
|
+
messageId: string;
|
|
140
|
+
threadId: string;
|
|
141
|
+
actorId: string;
|
|
142
|
+
/** Empty string = reaction removed */
|
|
143
|
+
reaction: string;
|
|
144
|
+
timestampMs: number;
|
|
145
|
+
};
|
|
146
|
+
} | {
|
|
147
|
+
type: "typing";
|
|
148
|
+
data: {
|
|
149
|
+
threadId: string;
|
|
150
|
+
senderId: string;
|
|
151
|
+
isTyping: boolean;
|
|
152
|
+
};
|
|
153
|
+
} | {
|
|
154
|
+
type: "message_unsend";
|
|
155
|
+
data: {
|
|
156
|
+
messageId: string;
|
|
157
|
+
threadId: string;
|
|
158
|
+
actorId: string;
|
|
159
|
+
timestampMs: number;
|
|
160
|
+
};
|
|
161
|
+
} | {
|
|
162
|
+
type: "read_receipt";
|
|
163
|
+
data: {
|
|
164
|
+
threadId: string;
|
|
165
|
+
readerId: string;
|
|
166
|
+
readWatermarkTimestampMs?: number;
|
|
167
|
+
timestampMs: number;
|
|
168
|
+
};
|
|
169
|
+
} | {
|
|
170
|
+
type: "presence";
|
|
171
|
+
data: {
|
|
172
|
+
userId: string;
|
|
173
|
+
isOnline: boolean;
|
|
174
|
+
lastActiveTimestampMs?: number;
|
|
175
|
+
};
|
|
176
|
+
} | {
|
|
177
|
+
type: "e2ee_connected";
|
|
178
|
+
data: Record<string, never>;
|
|
179
|
+
} | {
|
|
180
|
+
type: "e2ee_message";
|
|
181
|
+
data: E2EEMessage;
|
|
182
|
+
} | {
|
|
183
|
+
type: "e2ee_reaction";
|
|
184
|
+
data: {
|
|
185
|
+
messageId: string;
|
|
186
|
+
chatJid: string;
|
|
187
|
+
senderJid: string;
|
|
188
|
+
senderId: string;
|
|
189
|
+
/** Empty string = unreaction */
|
|
190
|
+
reaction: string;
|
|
191
|
+
};
|
|
192
|
+
} | {
|
|
193
|
+
type: "e2ee_receipt";
|
|
194
|
+
data: {
|
|
195
|
+
type: string;
|
|
196
|
+
chat: string;
|
|
197
|
+
sender: string;
|
|
198
|
+
messageIds: string[];
|
|
199
|
+
};
|
|
200
|
+
} | {
|
|
201
|
+
type: "disconnected";
|
|
202
|
+
data: {
|
|
203
|
+
isE2EE?: boolean;
|
|
204
|
+
};
|
|
205
|
+
} | {
|
|
206
|
+
type: "reconnected";
|
|
207
|
+
data: Record<string, never>;
|
|
208
|
+
} | {
|
|
209
|
+
type: "ready";
|
|
210
|
+
data: {
|
|
211
|
+
isNewSession: boolean;
|
|
212
|
+
};
|
|
213
|
+
} | {
|
|
214
|
+
type: "raw";
|
|
215
|
+
data: Record<string, unknown>;
|
|
216
|
+
} | {
|
|
217
|
+
type: "error";
|
|
218
|
+
data: {
|
|
219
|
+
message: string;
|
|
220
|
+
code?: number;
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
interface SendMessageInput {
|
|
225
|
+
threadId: string;
|
|
226
|
+
text: string;
|
|
227
|
+
replyToMessageId?: string;
|
|
228
|
+
}
|
|
229
|
+
interface SendMediaInput {
|
|
230
|
+
threadId: string;
|
|
231
|
+
data: Buffer;
|
|
232
|
+
fileName: string;
|
|
233
|
+
/** Optional; inferred from fileName extension when omitted. */
|
|
234
|
+
mimeType?: string;
|
|
235
|
+
caption?: string;
|
|
236
|
+
replyToMessageId?: string;
|
|
237
|
+
/** Optional media width in pixels for E2EE image/video/sticker payloads. */
|
|
238
|
+
width?: number;
|
|
239
|
+
/** Optional media height in pixels for E2EE image/video/sticker payloads. */
|
|
240
|
+
height?: number;
|
|
241
|
+
/** Optional media duration in whole seconds for E2EE video/audio payloads. */
|
|
242
|
+
seconds?: number;
|
|
243
|
+
/** Alias for seconds, kept for callers that use media-style naming. */
|
|
244
|
+
duration?: number;
|
|
245
|
+
/** Whether E2EE audio should be sent as push-to-talk/voice. Defaults to true for sendAudio. */
|
|
246
|
+
ptt?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface TypingInput {
|
|
249
|
+
threadId: string;
|
|
250
|
+
isTyping: boolean;
|
|
251
|
+
}
|
|
252
|
+
interface SendReactionInput {
|
|
253
|
+
messageId: string;
|
|
254
|
+
reaction: string;
|
|
255
|
+
/** Thread ID or canonical E2EE chat JID containing the target message. */
|
|
256
|
+
threadId: string;
|
|
257
|
+
/** Sender JID of the target E2EE message; required for reacting to someone else's group message. */
|
|
258
|
+
senderJid?: string;
|
|
259
|
+
/** Alias for senderJid for callers that prefer explicit target naming. */
|
|
260
|
+
targetSenderJid?: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
interface ClientOptions {
|
|
264
|
+
appStatePath?: string;
|
|
265
|
+
appState?: any[] | string;
|
|
266
|
+
sessionStorePath?: string;
|
|
267
|
+
platform?: Platform;
|
|
268
|
+
}
|
|
269
|
+
interface SessionData {
|
|
270
|
+
userId: string;
|
|
271
|
+
appState: Array<{
|
|
272
|
+
key: string;
|
|
273
|
+
value: string;
|
|
274
|
+
}>;
|
|
275
|
+
platform: Platform;
|
|
276
|
+
updatedAt: number;
|
|
277
|
+
}
|
|
278
|
+
type MessengerEventMap = {
|
|
279
|
+
[E in MessengerEvent as E["type"]]: E["data"];
|
|
280
|
+
} & {
|
|
281
|
+
event: MessengerEvent;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* E2EE-only Messenger client facade.
|
|
286
|
+
*
|
|
287
|
+
* `fca-unofficial` is still used internally for app-state login and CAT/bootstrap
|
|
288
|
+
* material that the E2EE transport currently requires, but plaintext/non-E2EE
|
|
289
|
+
* messaging, thread management, polls, stickers, and history APIs are intentionally
|
|
290
|
+
* not exposed here. Use `fca-unofficial` directly for those non-E2EE surfaces.
|
|
291
|
+
*/
|
|
292
|
+
declare class FBClient {
|
|
293
|
+
private readonly options;
|
|
294
|
+
private readonly eventBus;
|
|
295
|
+
private readonly controller;
|
|
296
|
+
constructor(options: ClientOptions);
|
|
297
|
+
/** Listen for events. Supports catch-all or specific event types. */
|
|
298
|
+
onEvent(listener: (event: MessengerEvent) => void): void;
|
|
299
|
+
onEvent<K extends keyof MessengerEventMap>(event: K, listener: (data: MessengerEventMap[K]) => void): void;
|
|
300
|
+
/** Stop listening for events. */
|
|
301
|
+
offEvent(listener: (event: MessengerEvent) => void): void;
|
|
302
|
+
offEvent<K extends keyof MessengerEventMap>(event: K, listener: (data: MessengerEventMap[K]) => void): void;
|
|
303
|
+
/** Legacy helper for the catch-all wrapper event. */
|
|
304
|
+
onAnyEvent(listener: (event: MessengerEvent) => void): void;
|
|
305
|
+
/**
|
|
306
|
+
* Login with appState and prepare auth/CAT bootstrap state.
|
|
307
|
+
* This does not start plaintext/non-E2EE MQTT listening.
|
|
308
|
+
*/
|
|
309
|
+
connect(): Promise<{
|
|
310
|
+
userId: string;
|
|
311
|
+
}>;
|
|
312
|
+
disconnect(): Promise<void>;
|
|
313
|
+
connectE2EE(deviceStorePath: string, userId: string): Promise<void>;
|
|
314
|
+
sendNoiseKeepAlive(): Promise<void>;
|
|
315
|
+
sendMessage(input: SendMessageInput): Promise<Record<string, unknown>>;
|
|
316
|
+
sendReaction(input: SendReactionInput): Promise<void>;
|
|
317
|
+
unsendMessage(messageId: string): Promise<void>;
|
|
318
|
+
sendTyping(input: TypingInput): Promise<void>;
|
|
319
|
+
sendImage(input: SendMediaInput): Promise<Record<string, unknown>>;
|
|
320
|
+
sendVideo(input: SendMediaInput): Promise<Record<string, unknown>>;
|
|
321
|
+
sendAudio(input: SendMediaInput): Promise<Record<string, unknown>>;
|
|
322
|
+
sendFile(input: SendMediaInput): Promise<Record<string, unknown>>;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface EncryptMediaResult {
|
|
326
|
+
dataToUpload: Buffer;
|
|
327
|
+
fileSHA256: Buffer;
|
|
328
|
+
fileEncSHA256: Buffer;
|
|
329
|
+
fileLength: number;
|
|
330
|
+
mediaKey: Buffer;
|
|
331
|
+
}
|
|
332
|
+
interface MediaUploadConfig {
|
|
333
|
+
/** From server's media connection response */
|
|
334
|
+
auth: string;
|
|
335
|
+
/** Host to upload to - Messenger prefers the last host (rupload.facebook.com) */
|
|
336
|
+
host: string;
|
|
337
|
+
ttl?: number;
|
|
338
|
+
authTtl?: number;
|
|
339
|
+
fetchedAtMs?: number;
|
|
340
|
+
}
|
|
341
|
+
interface MediaUploadResult {
|
|
342
|
+
url: string;
|
|
343
|
+
directPath: string;
|
|
344
|
+
handle: string;
|
|
345
|
+
objectId: string;
|
|
346
|
+
}
|
|
347
|
+
type MmsTypeStr = "image" | "video" | "ptt" | "document" | "sticker";
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* E2EE Media Crypto - Layer 4
|
|
351
|
+
*
|
|
352
|
+
* Implements the AES-256-CBC + HMAC-SHA256 + HKDF media scheme.
|
|
353
|
+
*
|
|
354
|
+
* No Signal Protocol needed here - this is pure symmetric crypto.
|
|
355
|
+
*/
|
|
356
|
+
|
|
357
|
+
declare const MediaType: {
|
|
358
|
+
readonly image: "WhatsApp Image Keys";
|
|
359
|
+
readonly video: "WhatsApp Video Keys";
|
|
360
|
+
readonly audio: "WhatsApp Audio Keys";
|
|
361
|
+
readonly document: "WhatsApp Document Keys";
|
|
362
|
+
readonly sticker: "WhatsApp Image Keys";
|
|
363
|
+
readonly history: "WhatsApp History Keys";
|
|
364
|
+
readonly appstate: "WhatsApp App State Keys";
|
|
365
|
+
};
|
|
366
|
+
type MediaTypeKey = keyof typeof MediaType;
|
|
367
|
+
|
|
368
|
+
interface DeviceJSON {
|
|
369
|
+
/** schema version for local migrations; absent in old stores */
|
|
370
|
+
schema_version?: number;
|
|
371
|
+
/** base64, 32 bytes - Noise handshake key */
|
|
372
|
+
noise_key_priv: string;
|
|
373
|
+
/** base64, 32 bytes - Signal identity key */
|
|
374
|
+
identity_key_priv: string;
|
|
375
|
+
/** base64, 32 bytes - Signal signed prekey */
|
|
376
|
+
signed_pre_key_priv: string;
|
|
377
|
+
signed_pre_key_id: number;
|
|
378
|
+
/** base64, 64 bytes - Ed25519 sig of signed prekey by identity key */
|
|
379
|
+
signed_pre_key_sig: string;
|
|
380
|
+
registration_id: number;
|
|
381
|
+
/** base64, 32 bytes */
|
|
382
|
+
adv_secret_key: string;
|
|
383
|
+
/** uuid v4 */
|
|
384
|
+
facebook_uuid: string;
|
|
385
|
+
jid_user?: string;
|
|
386
|
+
jid_device?: number;
|
|
387
|
+
/** address -> base64(32B identity pub key) */
|
|
388
|
+
identities?: Record<string, string>;
|
|
389
|
+
/** address -> base64(serialized SessionRecord) */
|
|
390
|
+
sessions?: Record<string, string>;
|
|
391
|
+
/** id(number) -> base64(32B priv key) */
|
|
392
|
+
pre_keys?: Record<string, string>;
|
|
393
|
+
/** "groupJID:senderAddress" -> base64(serialized SenderKeyRecord) */
|
|
394
|
+
sender_keys?: Record<string, string>;
|
|
395
|
+
/** id(number) -> base64(serialized SignedPreKeyRecord) */
|
|
396
|
+
signed_pre_keys?: Record<string, string>;
|
|
397
|
+
/** next prekey ID to generate */
|
|
398
|
+
next_pre_key_id: number;
|
|
399
|
+
}
|
|
400
|
+
interface RawPreKeyBundle {
|
|
401
|
+
registrationId: number;
|
|
402
|
+
deviceId: number;
|
|
403
|
+
identityKey: Uint8Array;
|
|
404
|
+
signedPreKey: {
|
|
405
|
+
keyId: number;
|
|
406
|
+
publicKey: Uint8Array;
|
|
407
|
+
signature: Uint8Array;
|
|
408
|
+
};
|
|
409
|
+
/** Optional: one-time prekey (may be absent if server ran out) */
|
|
410
|
+
preKey?: {
|
|
411
|
+
keyId: number;
|
|
412
|
+
publicKey: Uint8Array;
|
|
413
|
+
};
|
|
414
|
+
/**
|
|
415
|
+
* Optional: Kyber (PQ) prekey.
|
|
416
|
+
*/
|
|
417
|
+
kyberPreKey?: {
|
|
418
|
+
keyId: number;
|
|
419
|
+
publicKey: Uint8Array;
|
|
420
|
+
signature: Uint8Array;
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
interface E2EESendTextOptions {
|
|
424
|
+
/** Recipient JID (DM) or group JID */
|
|
425
|
+
toJid: string;
|
|
426
|
+
text: string;
|
|
427
|
+
isGroup: boolean;
|
|
428
|
+
/** Own JID - required for all sends (self address in Signal protocol) */
|
|
429
|
+
selfJid: string;
|
|
430
|
+
replyToId?: string;
|
|
431
|
+
replyToSenderJid?: string;
|
|
432
|
+
}
|
|
433
|
+
interface E2EESendTextResult {
|
|
434
|
+
/** Encrypted MessageTransport bytes - feed into Signal cipher */
|
|
435
|
+
plaintext: Buffer;
|
|
436
|
+
/** frankingTag for the message node */
|
|
437
|
+
frankingTag: Buffer;
|
|
438
|
+
}
|
|
439
|
+
interface E2EEEncryptMediaOptions {
|
|
440
|
+
type: MediaTypeKey;
|
|
441
|
+
data: Buffer;
|
|
442
|
+
mmsType: MmsTypeStr;
|
|
443
|
+
}
|
|
444
|
+
interface E2EEEncryptMediaResult {
|
|
445
|
+
mediaKey: Buffer;
|
|
446
|
+
fileSHA256: Buffer;
|
|
447
|
+
fileEncSHA256: Buffer;
|
|
448
|
+
fileLength: number;
|
|
449
|
+
directPath: string;
|
|
450
|
+
/** Upload handle returned by the media CDN. Useful for parity with native clients. */
|
|
451
|
+
handle: string;
|
|
452
|
+
/** CDN object ID returned by upload; encoded into WAMediaTransport ancillary data. */
|
|
453
|
+
objectId: string;
|
|
454
|
+
/** Pre-built MediaFields for encodeImageMessage / encodeVideoMessage / etc. */
|
|
455
|
+
mediaFields: Omit<MediaFields, "caption" | "ptt" | "fileName">;
|
|
456
|
+
}
|
|
457
|
+
interface E2EEDecryptMediaOptions {
|
|
458
|
+
data: Buffer;
|
|
459
|
+
mediaKey: Buffer;
|
|
460
|
+
type: MediaTypeKey;
|
|
461
|
+
fileSHA256?: Buffer;
|
|
462
|
+
fileEncSHA256?: Buffer;
|
|
463
|
+
}
|
|
464
|
+
type EncryptionResult = {
|
|
465
|
+
type: "dm";
|
|
466
|
+
encrypted: {
|
|
467
|
+
type: "msg" | "pkmsg";
|
|
468
|
+
ciphertext: Buffer;
|
|
469
|
+
};
|
|
470
|
+
frankingTag: Buffer;
|
|
471
|
+
messageApp: Buffer;
|
|
472
|
+
} | {
|
|
473
|
+
type: "group";
|
|
474
|
+
messageApp: Buffer;
|
|
475
|
+
groupCiphertext: Buffer;
|
|
476
|
+
devicePayload: Buffer;
|
|
477
|
+
selfDevicePayload: Buffer;
|
|
478
|
+
skdmPayload: Buffer;
|
|
479
|
+
skdm: {
|
|
480
|
+
groupId: string;
|
|
481
|
+
skdmBytes: Buffer;
|
|
482
|
+
distributionId: string;
|
|
483
|
+
};
|
|
484
|
+
frankingTag: Buffer;
|
|
485
|
+
};
|
|
486
|
+
interface MediaFields {
|
|
487
|
+
caption?: string;
|
|
488
|
+
mimeType: string;
|
|
489
|
+
fileSHA256: Buffer;
|
|
490
|
+
fileLength: number;
|
|
491
|
+
mediaKey: Buffer;
|
|
492
|
+
fileEncSHA256: Buffer;
|
|
493
|
+
directPath: string;
|
|
494
|
+
/** Optional CDN object ID from media upload response. */
|
|
495
|
+
objectId?: string;
|
|
496
|
+
/** Unix timestamp seconds for the media key. Defaults to current time when encoding. */
|
|
497
|
+
mediaKeyTimestamp?: number;
|
|
498
|
+
width?: number;
|
|
499
|
+
height?: number;
|
|
500
|
+
seconds?: number;
|
|
501
|
+
ptt?: boolean;
|
|
502
|
+
fileName?: string;
|
|
503
|
+
}
|
|
504
|
+
interface MessageTransportOptions {
|
|
505
|
+
/** Application payload. Omit for SKDM-only device fanout. */
|
|
506
|
+
messageApp?: Buffer;
|
|
507
|
+
/** Included only when sending a copy to own other devices */
|
|
508
|
+
dsm?: {
|
|
509
|
+
destinationJid: string;
|
|
510
|
+
phash: string;
|
|
511
|
+
};
|
|
512
|
+
/** Included only for group messages */
|
|
513
|
+
skdm?: {
|
|
514
|
+
groupId: string;
|
|
515
|
+
skdmBytes: Buffer;
|
|
516
|
+
};
|
|
517
|
+
/** Included for group sends with backup directive metadata. */
|
|
518
|
+
backupDirective?: {
|
|
519
|
+
messageId: string;
|
|
520
|
+
actionType?: "UPSERT" | "REMOVE";
|
|
521
|
+
};
|
|
522
|
+
padding?: Buffer;
|
|
523
|
+
}
|
|
524
|
+
interface E2EEUploadResult {
|
|
525
|
+
messageId: string;
|
|
526
|
+
timestampMs: number;
|
|
527
|
+
}
|
|
528
|
+
interface E2EEDownloadResult {
|
|
529
|
+
data: Buffer;
|
|
530
|
+
mimeType: string;
|
|
531
|
+
fileSize: number;
|
|
532
|
+
}
|
|
533
|
+
interface E2EESendImageOptions {
|
|
534
|
+
chatJid: string;
|
|
535
|
+
data: Buffer;
|
|
536
|
+
mimeType?: string;
|
|
537
|
+
caption?: string;
|
|
538
|
+
width?: number;
|
|
539
|
+
height?: number;
|
|
540
|
+
replyToId?: string;
|
|
541
|
+
replyToSenderJid?: string;
|
|
542
|
+
}
|
|
543
|
+
interface E2EESendVideoOptions {
|
|
544
|
+
chatJid: string;
|
|
545
|
+
data: Buffer;
|
|
546
|
+
mimeType?: string;
|
|
547
|
+
caption?: string;
|
|
548
|
+
width?: number;
|
|
549
|
+
height?: number;
|
|
550
|
+
duration?: number;
|
|
551
|
+
replyToId?: string;
|
|
552
|
+
replyToSenderJid?: string;
|
|
553
|
+
}
|
|
554
|
+
interface E2EESendAudioOptions {
|
|
555
|
+
chatJid: string;
|
|
556
|
+
data: Buffer;
|
|
557
|
+
mimeType?: string;
|
|
558
|
+
duration?: number;
|
|
559
|
+
ptt?: boolean;
|
|
560
|
+
replyToId?: string;
|
|
561
|
+
replyToSenderJid?: string;
|
|
562
|
+
}
|
|
563
|
+
interface E2EESendDocumentOptions {
|
|
564
|
+
chatJid: string;
|
|
565
|
+
data: Buffer;
|
|
566
|
+
fileName: string;
|
|
567
|
+
mimeType?: string;
|
|
568
|
+
replyToId?: string;
|
|
569
|
+
replyToSenderJid?: string;
|
|
570
|
+
}
|
|
571
|
+
interface E2EESendStickerOptions {
|
|
572
|
+
chatJid: string;
|
|
573
|
+
data: Buffer;
|
|
574
|
+
mimeType?: string;
|
|
575
|
+
width?: number;
|
|
576
|
+
height?: number;
|
|
577
|
+
replyToId?: string;
|
|
578
|
+
replyToSenderJid?: string;
|
|
579
|
+
}
|
|
580
|
+
interface E2EEDownloadOptions {
|
|
581
|
+
directPath: string;
|
|
582
|
+
/** Base64-encoded */
|
|
583
|
+
mediaKey: string;
|
|
584
|
+
/** Base64-encoded */
|
|
585
|
+
mediaSha256: string;
|
|
586
|
+
/** Base64-encoded */
|
|
587
|
+
mediaEncSha256?: string;
|
|
588
|
+
/** "image" | "video" | "audio" | "voice" | "document" | "sticker" */
|
|
589
|
+
mediaType: string;
|
|
590
|
+
mimeType?: string;
|
|
591
|
+
fileSize?: number;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* E2EE DeviceStore - Layer 5
|
|
596
|
+
*
|
|
597
|
+
* Persists all Signal Protocol key material to a JSON file.
|
|
598
|
+
* JSON schema is compatible with bridge-go DeviceJSON so existing device
|
|
599
|
+
* files can be imported without re-registration.
|
|
600
|
+
*
|
|
601
|
+
* Implements the @signalapp/libsignal-client store interfaces:
|
|
602
|
+
* IdentityKeyStore, SessionStore, PreKeyStore, SignedPreKeyStore, SenderKeyStore
|
|
603
|
+
*/
|
|
604
|
+
|
|
605
|
+
declare class DeviceStore implements IdentityKeyStore, SessionStore, PreKeyStore, SignedPreKeyStore, SenderKeyStore, KyberPreKeyStore {
|
|
606
|
+
private identities;
|
|
607
|
+
private sessions;
|
|
608
|
+
private preKeys;
|
|
609
|
+
private signedPreKeys;
|
|
610
|
+
private senderKeys;
|
|
611
|
+
private kyberKeys;
|
|
612
|
+
noiseKeyPriv: Buffer;
|
|
613
|
+
private identityKeyPriv;
|
|
614
|
+
signedPreKeyPriv: Buffer;
|
|
615
|
+
signedPreKeyId: number;
|
|
616
|
+
signedPreKeySig: Buffer;
|
|
617
|
+
registrationId: number;
|
|
618
|
+
advSecretKey: Buffer;
|
|
619
|
+
facebookUUID: string;
|
|
620
|
+
jidUser?: string;
|
|
621
|
+
jidDevice?: number;
|
|
622
|
+
nextPreKeyId: number;
|
|
623
|
+
autoTrust: boolean;
|
|
624
|
+
private readonly path;
|
|
625
|
+
private onDataChanged?;
|
|
626
|
+
private constructor();
|
|
627
|
+
/** Create or load from a JSON file path. */
|
|
628
|
+
/** Persist the Messenger JID assigned to this registered E2EE device. */
|
|
629
|
+
setJIDs(id1: string, id2: string): void;
|
|
630
|
+
static fromFile(path: string): Promise<DeviceStore>;
|
|
631
|
+
/** Load from a JSON string (no file I/O). */
|
|
632
|
+
static fromData(json: string, onDataChanged?: (json: string) => void): Promise<DeviceStore>;
|
|
633
|
+
/** Create a fresh in-memory device (nothing persisted). */
|
|
634
|
+
static memoryOnly(): Promise<DeviceStore>;
|
|
635
|
+
private initNew;
|
|
636
|
+
private loadJSON;
|
|
637
|
+
toJSON(): DeviceJSON;
|
|
638
|
+
getData(): string;
|
|
639
|
+
saveToFile(): void;
|
|
640
|
+
getIdentityPublicKey(): Buffer;
|
|
641
|
+
getIdentityPrivateKey(): Buffer;
|
|
642
|
+
getSignedPreKeyPublicKey(): Buffer;
|
|
643
|
+
getIdentityKey(): Promise<PrivateKey>;
|
|
644
|
+
_getIdentityKey(): Promise<any>;
|
|
645
|
+
getLocalRegistrationId(): Promise<number>;
|
|
646
|
+
_getLocalRegistrationId(): Promise<number>;
|
|
647
|
+
_saveIdentity(name: any, key: any): Promise<boolean>;
|
|
648
|
+
saveIdentity(name: ProtocolAddress, key: PublicKey): Promise<boolean>;
|
|
649
|
+
isTrustedIdentity(name: ProtocolAddress, key: PublicKey, _direction: Direction): Promise<boolean>;
|
|
650
|
+
_isTrustedIdentity(name: any, key: any, sending: boolean): Promise<boolean>;
|
|
651
|
+
getIdentity(name: ProtocolAddress): Promise<PublicKey | null>;
|
|
652
|
+
_getIdentity(name: any): Promise<any>;
|
|
653
|
+
saveSession(name: ProtocolAddress, record: SessionRecord): Promise<void>;
|
|
654
|
+
_saveSession(name: any, record: any): Promise<void>;
|
|
655
|
+
getSession(name: ProtocolAddress): Promise<SessionRecord | null>;
|
|
656
|
+
_getSession(name: any): Promise<any>;
|
|
657
|
+
getExistingSessions(addresses: ProtocolAddress[]): Promise<SessionRecord[]>;
|
|
658
|
+
savePreKey(id: number, record: PreKeyRecord): Promise<void>;
|
|
659
|
+
_savePreKey(id: number, record: any): Promise<void>;
|
|
660
|
+
getPreKey(id: number): Promise<PreKeyRecord>;
|
|
661
|
+
_getPreKey(id: number): Promise<any>;
|
|
662
|
+
removePreKey(id: number): Promise<void>;
|
|
663
|
+
_removePreKey(id: number): Promise<void>;
|
|
664
|
+
saveSignedPreKey(id: number, record: SignedPreKeyRecord): Promise<void>;
|
|
665
|
+
_saveSignedPreKey(id: number, record: any): Promise<void>;
|
|
666
|
+
getSignedPreKey(id: number): Promise<SignedPreKeyRecord>;
|
|
667
|
+
_getSignedPreKey(id: number): Promise<any>;
|
|
668
|
+
saveSenderKey(senderAddress: ProtocolAddress, distributionId: string, record: SenderKeyRecord): Promise<void>;
|
|
669
|
+
_saveSenderKey(sender: any, distributionId: any, record: any): Promise<void>;
|
|
670
|
+
getSenderKey(senderAddress: ProtocolAddress, distributionId: string): Promise<SenderKeyRecord>;
|
|
671
|
+
listSenderKeyDistributionIds(senderAddress: ProtocolAddress): string[];
|
|
672
|
+
_getSenderKey(sender: any, distributionId: any): Promise<any>;
|
|
673
|
+
saveKyberPreKey(id: number, record: KyberPreKeyRecord): Promise<void>;
|
|
674
|
+
_saveKyberPreKey(id: number, record: any): Promise<void>;
|
|
675
|
+
getKyberPreKey(id: number): Promise<KyberPreKeyRecord>;
|
|
676
|
+
_getKyberPreKey(id: number): Promise<any>;
|
|
677
|
+
markKyberPreKeyUsed(id: number): Promise<void>;
|
|
678
|
+
_markKyberPreKeyUsed(id: number): Promise<void>;
|
|
679
|
+
getIdentityKeyPair(): Promise<IdentityKeyPair>;
|
|
680
|
+
/** Get a fresh unused prekey ID and bump the counter */
|
|
681
|
+
allocPreKeyId(): number;
|
|
682
|
+
/** True if store has an established session for this address */
|
|
683
|
+
hasSession(address: string): boolean;
|
|
684
|
+
getPreKeyCount(): number;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Encode a ConsumerApplication text message.
|
|
689
|
+
* Field 1 = Payload { field 1 = Content { field 1 = MessageText { field 1 = text } } }
|
|
690
|
+
*/
|
|
691
|
+
declare function encodeTextMessage(text: string): Buffer;
|
|
692
|
+
/** Encode a ConsumerApplication image message. */
|
|
693
|
+
declare function encodeImageMessage(m: MediaFields): Buffer;
|
|
694
|
+
/** Encode a ConsumerApplication video message. */
|
|
695
|
+
declare function encodeVideoMessage(m: MediaFields): Buffer;
|
|
696
|
+
/** Encode a ConsumerApplication audio/voice message. */
|
|
697
|
+
declare function encodeAudioMessage(m: MediaFields): Buffer;
|
|
698
|
+
/** Encode a ConsumerApplication document message. */
|
|
699
|
+
declare function encodeDocumentMessage(m: MediaFields): Buffer;
|
|
700
|
+
/** Encode a ConsumerApplication sticker message. */
|
|
701
|
+
declare function encodeStickerMessage(m: MediaFields): Buffer;
|
|
702
|
+
interface MessageKeyOptions {
|
|
703
|
+
remoteJid?: string;
|
|
704
|
+
fromMe?: boolean;
|
|
705
|
+
participant?: string;
|
|
706
|
+
}
|
|
707
|
+
interface ReactionMessageKeyOptions extends MessageKeyOptions {
|
|
708
|
+
senderTimestampMs?: number;
|
|
709
|
+
}
|
|
710
|
+
/** Encode a reaction message. */
|
|
711
|
+
declare function encodeReactionMessage(targetMessageId: string, emoji: string, keyOpts?: ReactionMessageKeyOptions): Buffer;
|
|
712
|
+
/** Encode a message edit. */
|
|
713
|
+
declare function encodeEditMessage(targetMessageId: string, newText: string): Buffer;
|
|
714
|
+
/** Encode a revoke (unsend) message. */
|
|
715
|
+
declare function encodeRevokeMessage(messageId: string, keyOptsOrFromMe?: MessageKeyOptions | boolean): Buffer;
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Wrap a ConsumerApplication payload into a MessageApplication.
|
|
719
|
+
* Returns (messageApp bytes, frankingKey, frankingTag).
|
|
720
|
+
*/
|
|
721
|
+
declare function encodeMessageApplication(consumerAppBytes: Buffer, replyTo?: {
|
|
722
|
+
id: string;
|
|
723
|
+
senderJid: string;
|
|
724
|
+
}): {
|
|
725
|
+
messageApp: Buffer;
|
|
726
|
+
frankingKey: Buffer;
|
|
727
|
+
frankingTag: Buffer;
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Encode the MessageTransport protobuf that will be fed into Signal cipher.
|
|
732
|
+
*/
|
|
733
|
+
declare function encodeMessageTransport(opts: MessageTransportOptions): Buffer;
|
|
734
|
+
|
|
735
|
+
interface DMTextFanoutPayloads {
|
|
736
|
+
type: "dm";
|
|
737
|
+
messageApp: Buffer;
|
|
738
|
+
devicePayload: Buffer;
|
|
739
|
+
selfDevicePayload: Buffer;
|
|
740
|
+
frankingTag: Buffer;
|
|
741
|
+
}
|
|
742
|
+
declare class E2EEClient {
|
|
743
|
+
private store;
|
|
744
|
+
constructor(store: DeviceStore);
|
|
745
|
+
/** Establish a session with a contact using their prekey bundle (X3DH). */
|
|
746
|
+
establishSession(recipientJid: string, bundle: RawPreKeyBundle): Promise<void>;
|
|
747
|
+
processSenderKeyDistribution(senderJid: string, skdmBytes: Buffer, groupJid?: string): Promise<void>;
|
|
748
|
+
/** Build DM text transports for V3 participant fanout. */
|
|
749
|
+
buildDMTextFanoutPayloads(opts: E2EESendTextOptions): Promise<DMTextFanoutPayloads>;
|
|
750
|
+
/**
|
|
751
|
+
* Build and encrypt a DM text message for Signal transport.
|
|
752
|
+
* Kept for low-level callers; production send should fan out through participants.
|
|
753
|
+
*/
|
|
754
|
+
encryptDMText(opts: E2EESendTextOptions): Promise<Extract<EncryptionResult, {
|
|
755
|
+
type: "dm";
|
|
756
|
+
}>>;
|
|
757
|
+
/** Build and encrypt a group text message. */
|
|
758
|
+
encryptGroupText(groupJid: string, selfJid: string, text: string, messageId: string, replyToId?: string, replyToSenderJid?: string): Promise<Extract<EncryptionResult, {
|
|
759
|
+
type: "group";
|
|
760
|
+
}>>;
|
|
761
|
+
/** Build and encrypt a pre-built MessageApplication for a group send. */
|
|
762
|
+
encryptGroupMessageApplication(groupJid: string, selfJid: string, messageApp: Buffer, messageId: string): Promise<Omit<Extract<EncryptionResult, {
|
|
763
|
+
type: "group";
|
|
764
|
+
}>, "frankingTag">>;
|
|
765
|
+
/** Create a sender-key distribution payload for targeted group retry responses. */
|
|
766
|
+
createSenderKeyDistributionPayload(groupJid: string, selfJid: string): Promise<{
|
|
767
|
+
groupId: string;
|
|
768
|
+
skdmBytes: Buffer;
|
|
769
|
+
distributionId: string;
|
|
770
|
+
}>;
|
|
771
|
+
/** Encrypt a MessageApplication payload directly to one device (used for retry responses). */
|
|
772
|
+
encryptMessageAppForDevice(recipientJid: string, selfJid: string, messageApp: Buffer, opts?: {
|
|
773
|
+
skdm?: {
|
|
774
|
+
groupId: string;
|
|
775
|
+
skdmBytes: Buffer;
|
|
776
|
+
};
|
|
777
|
+
dsm?: {
|
|
778
|
+
destinationJid: string;
|
|
779
|
+
phash: string;
|
|
780
|
+
};
|
|
781
|
+
backupDirective?: {
|
|
782
|
+
messageId: string;
|
|
783
|
+
actionType: "UPSERT" | "REMOVE";
|
|
784
|
+
};
|
|
785
|
+
}): Promise<{
|
|
786
|
+
type: "msg" | "pkmsg";
|
|
787
|
+
ciphertext: Buffer;
|
|
788
|
+
}>;
|
|
789
|
+
/** Check if a session exists for a given device JID. */
|
|
790
|
+
hasSession(jid: string): Promise<boolean>;
|
|
791
|
+
/** Encrypt an SKDM for a specific device DM. */
|
|
792
|
+
encryptSKDM(recipientJid: string, selfJid: string, skdm: {
|
|
793
|
+
groupId: string;
|
|
794
|
+
skdmBytes: Buffer;
|
|
795
|
+
}): Promise<{
|
|
796
|
+
type: "msg" | "pkmsg";
|
|
797
|
+
ciphertext: Buffer;
|
|
798
|
+
}>;
|
|
799
|
+
encryptDevicePayload(recipientJid: string, selfJid: string, payload: Buffer): Promise<{
|
|
800
|
+
type: "msg" | "pkmsg";
|
|
801
|
+
ciphertext: Buffer;
|
|
802
|
+
}>;
|
|
803
|
+
/** Decrypt a DM Signal message (type = "msg"). Returns raw MessageTransport bytes. */
|
|
804
|
+
decryptDMMessage(senderJid: string, ciphertext: Buffer): Promise<Buffer>;
|
|
805
|
+
/** Decrypt a DM PreKeySignalMessage (first message from sender). */
|
|
806
|
+
decryptDMPreKeyMessage(senderJid: string, selfJid: string, ciphertext: Buffer): Promise<Buffer>;
|
|
807
|
+
decryptGroupMessage(senderJid: string, ciphertext: Buffer, groupJid?: string): Promise<Buffer>;
|
|
808
|
+
/** Encrypt media bytes for upload. Returns crypto fields + uploadable buffer. */
|
|
809
|
+
encryptMedia(data: Buffer, type: MediaTypeKey): EncryptMediaResult;
|
|
810
|
+
/** Decrypt downloaded E2EE media. */
|
|
811
|
+
decryptMedia(opts: E2EEDecryptMediaOptions): Buffer;
|
|
812
|
+
/**
|
|
813
|
+
* Encrypt + upload media in one step.
|
|
814
|
+
* Returns all fields needed to build a ConsumerApplication media message.
|
|
815
|
+
* @param refreshConfig Optional callback to refresh upload config on 401.
|
|
816
|
+
*/
|
|
817
|
+
encryptAndUploadMedia(uploadConfig: MediaUploadConfig, data: Buffer, type: MediaTypeKey, mimeType: string, refreshConfig?: () => Promise<MediaUploadConfig>): Promise<E2EEEncryptMediaResult>;
|
|
818
|
+
buildTextMessage: typeof encodeTextMessage;
|
|
819
|
+
buildImageMessage: typeof encodeImageMessage;
|
|
820
|
+
buildVideoMessage: typeof encodeVideoMessage;
|
|
821
|
+
buildAudioMessage: typeof encodeAudioMessage;
|
|
822
|
+
buildDocumentMessage: typeof encodeDocumentMessage;
|
|
823
|
+
buildStickerMessage: typeof encodeStickerMessage;
|
|
824
|
+
buildReactionMessage: typeof encodeReactionMessage;
|
|
825
|
+
buildEditMessage: typeof encodeEditMessage;
|
|
826
|
+
buildRevokeMessage: typeof encodeRevokeMessage;
|
|
827
|
+
buildMessageApplication: typeof encodeMessageApplication;
|
|
828
|
+
buildMessageTransport: typeof encodeMessageTransport;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* E2EEService - extension point for end-to-end encrypted media operations.
|
|
833
|
+
*
|
|
834
|
+
* The JS/TS side of this bridge keeps E2EE media upload/download separate
|
|
835
|
+
* from the non-E2EE Messenger gateway. fca-unofficial speaks to the
|
|
836
|
+
* standard Messenger LightSpeed API (non-E2EE) only.
|
|
837
|
+
*
|
|
838
|
+
* This service therefore acts as a typed facade that:
|
|
839
|
+
* 1. Documents the contract (what operations are expected, their inputs/outputs).
|
|
840
|
+
* 2. Provides an extension point where a future native-addon or WASM layer
|
|
841
|
+
* can be plugged in.
|
|
842
|
+
* 3. Exposes a guard so callers know E2EE is not yet connected.
|
|
843
|
+
*
|
|
844
|
+
* Concrete implementations can extend or replace this class.
|
|
845
|
+
*/
|
|
846
|
+
|
|
847
|
+
declare class E2EEService {
|
|
848
|
+
private _connected;
|
|
849
|
+
private e2eeClient?;
|
|
850
|
+
private uploadConfig?;
|
|
851
|
+
setProvider(client: E2EEClient, uploadConfig: MediaUploadConfig): void;
|
|
852
|
+
get isConnected(): boolean;
|
|
853
|
+
/** Called by an external E2EE provider when it establishes a connection. */
|
|
854
|
+
markConnected(): void;
|
|
855
|
+
/** Called when the E2EE connection drops. */
|
|
856
|
+
markDisconnected(): void;
|
|
857
|
+
ensureEnabled(): void;
|
|
858
|
+
getClient(): E2EEClient;
|
|
859
|
+
/** Send an E2EE image. Requires a concrete provider implementation. */
|
|
860
|
+
sendImage(opts: E2EESendImageOptions): Promise<E2EEUploadResult>;
|
|
861
|
+
/** Send an E2EE video. */
|
|
862
|
+
sendVideo(opts: E2EESendVideoOptions): Promise<E2EEUploadResult>;
|
|
863
|
+
/** Send an E2EE audio/voice message. */
|
|
864
|
+
sendAudio(opts: E2EESendAudioOptions): Promise<E2EEUploadResult>;
|
|
865
|
+
/** Send an E2EE document/file. */
|
|
866
|
+
sendDocument(opts: E2EESendDocumentOptions): Promise<E2EEUploadResult>;
|
|
867
|
+
/** Send an E2EE sticker. */
|
|
868
|
+
sendSticker(opts: E2EESendStickerOptions): Promise<E2EEUploadResult>;
|
|
869
|
+
/** Download E2EE media by decrypting it with the provided keys. */
|
|
870
|
+
downloadMedia(opts: E2EEDownloadOptions): Promise<E2EEDownloadResult>;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
interface AppEnv {
|
|
874
|
+
appStatePath?: string;
|
|
875
|
+
appState?: any[] | string;
|
|
876
|
+
sessionStorePath?: string;
|
|
877
|
+
platform: Platform;
|
|
878
|
+
}
|
|
879
|
+
interface AuthConfig {
|
|
880
|
+
appStatePath?: string;
|
|
881
|
+
appState?: any[] | string;
|
|
882
|
+
platform: Platform;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
export { type AppEnv, type Attachment, type AuthConfig, type ClientOptions, type E2EEDecryptMediaOptions, type E2EEDownloadOptions, type E2EEDownloadResult, type E2EEEncryptMediaOptions, type E2EEEncryptMediaResult, type E2EEMessage, type E2EEMessageKind, type E2EESendTextOptions, type E2EESendTextResult, E2EEService, FBClient, type MediaUploadConfig, type MediaUploadResult, type Mention, type MessengerEvent, type MessengerEventMap, type MmsTypeStr, type Platform, type ReplyTo, type SendMediaInput, type SendMessageInput, type SendReactionInput, type SessionData, type TypingInput };
|