fb-messenger-e2ee 0.1.0

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.
Files changed (106) hide show
  1. package/DOCS.md +310 -0
  2. package/LICENSE +660 -0
  3. package/README.md +153 -0
  4. package/bun.lock +1014 -0
  5. package/examples/basic-usage.ts +52 -0
  6. package/jest.config.ts +18 -0
  7. package/package.json +56 -0
  8. package/src/config/env.ts +15 -0
  9. package/src/controllers/client.controller.ts +805 -0
  10. package/src/controllers/dgw-handler.ts +171 -0
  11. package/src/controllers/e2ee-handler.ts +832 -0
  12. package/src/controllers/event-mapper.ts +327 -0
  13. package/src/core/client.ts +151 -0
  14. package/src/e2ee/application/e2ee-client.ts +376 -0
  15. package/src/e2ee/application/fanout-planner.ts +79 -0
  16. package/src/e2ee/application/outbound-message-cache.ts +58 -0
  17. package/src/e2ee/application/prekey-maintenance.ts +55 -0
  18. package/src/e2ee/application/retry-manager.ts +156 -0
  19. package/src/e2ee/facebook/facebook-protocol-utils.ts +230 -0
  20. package/src/e2ee/facebook/icdc-payload.ts +31 -0
  21. package/src/e2ee/index.ts +76 -0
  22. package/src/e2ee/internal.ts +27 -0
  23. package/src/e2ee/media/media-crypto.ts +147 -0
  24. package/src/e2ee/media/media-upload.ts +90 -0
  25. package/src/e2ee/message/builders/client-payload.ts +54 -0
  26. package/src/e2ee/message/builders/consumer-application.ts +362 -0
  27. package/src/e2ee/message/builders/message-application.ts +64 -0
  28. package/src/e2ee/message/builders/message-transport.ts +84 -0
  29. package/src/e2ee/message/codecs/protobuf-codecs.ts +101 -0
  30. package/src/e2ee/message/constants.ts +4 -0
  31. package/src/e2ee/message/message-builder.ts +15 -0
  32. package/src/e2ee/message/proto/ArmadilloApplication.proto +281 -0
  33. package/src/e2ee/message/proto/ArmadilloICDC.proto +14 -0
  34. package/src/e2ee/message/proto/ConsumerApplication.proto +232 -0
  35. package/src/e2ee/message/proto/MessageApplication.proto +82 -0
  36. package/src/e2ee/message/proto/MessageTransport.proto +77 -0
  37. package/src/e2ee/message/proto/WACommon.proto +66 -0
  38. package/src/e2ee/message/proto/WAMediaTransport.proto +176 -0
  39. package/src/e2ee/message/proto/proto-writer.ts +76 -0
  40. package/src/e2ee/signal/prekey-manager.ts +140 -0
  41. package/src/e2ee/signal/signal-manager.ts +365 -0
  42. package/src/e2ee/store/device-json.ts +47 -0
  43. package/src/e2ee/store/device-repository.ts +12 -0
  44. package/src/e2ee/store/device-store.ts +538 -0
  45. package/src/e2ee/transport/binary/decoder.ts +180 -0
  46. package/src/e2ee/transport/binary/encoder.ts +143 -0
  47. package/src/e2ee/transport/binary/stanzas.ts +97 -0
  48. package/src/e2ee/transport/binary/tokens.ts +64 -0
  49. package/src/e2ee/transport/binary/wa-binary.ts +8 -0
  50. package/src/e2ee/transport/dgw/dgw-socket.ts +345 -0
  51. package/src/e2ee/transport/noise/noise-handshake.ts +417 -0
  52. package/src/e2ee/transport/noise/noise-socket.ts +230 -0
  53. package/src/index.ts +34 -0
  54. package/src/models/client.ts +26 -0
  55. package/src/models/config.ts +14 -0
  56. package/src/models/domain.ts +299 -0
  57. package/src/models/e2ee.ts +295 -0
  58. package/src/models/media.ts +41 -0
  59. package/src/models/messaging.ts +88 -0
  60. package/src/models/thread.ts +69 -0
  61. package/src/repositories/session.repository.ts +20 -0
  62. package/src/services/auth.service.ts +55 -0
  63. package/src/services/e2ee.service.ts +174 -0
  64. package/src/services/facebook-gateway.service.ts +245 -0
  65. package/src/services/icdc.service.ts +177 -0
  66. package/src/services/media.service.ts +304 -0
  67. package/src/services/messaging.service.ts +28 -0
  68. package/src/services/thread.service.ts +199 -0
  69. package/src/types/advanced-types.ts +61 -0
  70. package/src/types/fca-unofficial.d.ts +212 -0
  71. package/src/types/protocol-types.ts +43 -0
  72. package/src/utils/fca-utils.ts +30 -0
  73. package/src/utils/logger.ts +24 -0
  74. package/src/utils/mime.ts +51 -0
  75. package/tests/.env.example +87 -0
  76. package/tests/data/1x1.png +0 -0
  77. package/tests/data/example.txt +1 -0
  78. package/tests/data/file_example.mp3 +0 -0
  79. package/tests/data/file_example.mp4 +0 -0
  80. package/tests/integration.test.ts +498 -0
  81. package/tests/script/echo-e2ee.ts +174 -0
  82. package/tests/script/send-e2ee-media.ts +227 -0
  83. package/tests/script/send-e2ee-reaction.ts +108 -0
  84. package/tests/script/send-e2ee-unsend.ts +115 -0
  85. package/tests/script/send-typing.ts +107 -0
  86. package/tests/script/test-group-send.ts +105 -0
  87. package/tests/setup.ts +3 -0
  88. package/tests/types.test.ts +57 -0
  89. package/tests/unit/controllers/dgw-handler.test.ts +60 -0
  90. package/tests/unit/controllers/e2ee-handler.test.ts +293 -0
  91. package/tests/unit/controllers/event-mapper.test.ts +252 -0
  92. package/tests/unit/e2ee/application-helpers.test.ts +418 -0
  93. package/tests/unit/e2ee/device-store.test.ts +126 -0
  94. package/tests/unit/e2ee/facebook-protocol-utils.test.ts +134 -0
  95. package/tests/unit/e2ee/media-crypto.test.ts +55 -0
  96. package/tests/unit/e2ee/media-upload.test.ts +60 -0
  97. package/tests/unit/e2ee/message-builder.test.ts +42 -0
  98. package/tests/unit/e2ee/message-builders.test.ts +230 -0
  99. package/tests/unit/e2ee/noise-handshake.test.ts +260 -0
  100. package/tests/unit/e2ee/prekey-manager.test.ts +55 -0
  101. package/tests/unit/e2ee/wa-binary.test.ts +127 -0
  102. package/tests/unit/services/e2ee.service.test.ts +101 -0
  103. package/tests/unit/services/facebook-gateway.service.test.ts +138 -0
  104. package/tests/unit/services/media.service.test.ts +169 -0
  105. package/tests/unit/utils/fca-utils.test.ts +48 -0
  106. package/tsconfig.json +19 -0
@@ -0,0 +1,26 @@
1
+ import type { MessengerEvent, Platform } from "./domain.ts";
2
+
3
+ export interface ClientOptions {
4
+ appStatePath?: string;
5
+ appState?: any[] | string;
6
+ sessionStorePath?: string;
7
+ platform?: Platform;
8
+ }
9
+
10
+ export interface SessionData {
11
+ userId: string;
12
+ appState: Array<{ key: string; value: string }>;
13
+ platform: Platform;
14
+ updatedAt: number;
15
+ }
16
+
17
+ export interface SessionRepository {
18
+ read(path: string): Promise<SessionData | null>;
19
+ write(path: string, session: SessionData): Promise<void>;
20
+ }
21
+
22
+ export type MessengerEventMap = {
23
+ [E in MessengerEvent as E["type"]]: E["data"];
24
+ } & {
25
+ event: MessengerEvent;
26
+ };
@@ -0,0 +1,14 @@
1
+ import type { Platform } from "./domain.ts";
2
+
3
+ export interface AppEnv {
4
+ appStatePath?: string;
5
+ appState?: any[] | string;
6
+ sessionStorePath?: string;
7
+ platform: Platform;
8
+ }
9
+
10
+ export interface AuthConfig {
11
+ appStatePath?: string;
12
+ appState?: any[] | string;
13
+ platform: Platform;
14
+ }
@@ -0,0 +1,299 @@
1
+ export type Platform = "facebook" | "messenger";
2
+
3
+ // Auth / Session
4
+
5
+
6
+ // Attachment (mirrors bridge-go Attachment struct)
7
+
8
+ export type AttachmentType = "image" | "video" | "audio" | "voice" | "file" | "sticker" | "gif" | "location" | "link" | "photo";
9
+
10
+ export interface BaseAttachment {
11
+ url?: string;
12
+ fileName?: string;
13
+ mimeType?: string;
14
+ fileSize?: number;
15
+ /** For E2EE media download - base64-encoded */
16
+ mediaKey?: string;
17
+ mediaSha256?: string;
18
+ mediaEncSha256?: string;
19
+ directPath?: string;
20
+ }
21
+
22
+ export interface ImageAttachment extends BaseAttachment {
23
+ type: "image" | "gif" | "photo";
24
+ width?: number;
25
+ height?: number;
26
+ previewUrl?: string;
27
+ }
28
+
29
+ export interface VideoAttachment extends BaseAttachment {
30
+ type: "video";
31
+ width?: number;
32
+ height?: number;
33
+ duration?: number;
34
+ previewUrl?: string;
35
+ }
36
+
37
+ export interface AudioAttachment extends BaseAttachment {
38
+ type: "audio" | "voice";
39
+ duration?: number;
40
+ }
41
+
42
+ export interface FileAttachment extends BaseAttachment {
43
+ type: "file";
44
+ }
45
+
46
+ export interface StickerAttachment extends BaseAttachment {
47
+ type: "sticker";
48
+ stickerID: number;
49
+ }
50
+
51
+ export interface LocationAttachment extends BaseAttachment {
52
+ type: "location";
53
+ latitude: number;
54
+ longitude: number;
55
+ }
56
+
57
+ export interface LinkAttachment extends BaseAttachment {
58
+ type: "link";
59
+ description?: string;
60
+ sourceText?: string;
61
+ previewUrl?: string;
62
+ }
63
+
64
+ export type Attachment =
65
+ | ImageAttachment
66
+ | VideoAttachment
67
+ | AudioAttachment
68
+ | FileAttachment
69
+ | StickerAttachment
70
+ | LocationAttachment
71
+ | LinkAttachment;
72
+
73
+ // Mention / ReplyTo
74
+
75
+ export interface Mention {
76
+ userId: string;
77
+ /** UTF-16 code unit offset in the message text */
78
+ offset: number;
79
+ /** UTF-16 code unit length */
80
+ length: number;
81
+ /** "user" | "thread" | "group" */
82
+ type?: string;
83
+ }
84
+
85
+ export interface ReplyTo {
86
+ messageId: string;
87
+ senderId?: string;
88
+ text?: string;
89
+ }
90
+
91
+ // Thread / UserInfo
92
+
93
+ export interface Thread {
94
+ id: string;
95
+ /** 1 = DM, 2 = group */
96
+ type: number;
97
+ name: string;
98
+ lastActivityTimestampMs: number;
99
+ snippet?: string;
100
+ }
101
+
102
+ export interface UserInfo {
103
+ id: string;
104
+ name: string;
105
+ firstName?: string;
106
+ username?: string;
107
+ profilePictureUrl?: string;
108
+ isMessengerUser?: boolean;
109
+ isVerified?: boolean;
110
+ gender?: number;
111
+ canViewerMessage?: boolean;
112
+ }
113
+
114
+ // Messages
115
+
116
+ export interface MessengerMessage {
117
+ id: string;
118
+ threadId: string;
119
+ senderId: string;
120
+ text: string;
121
+ timestampMs: number;
122
+ replyTo?: ReplyTo;
123
+ attachments?: Attachment[];
124
+ mentions?: Mention[];
125
+ isAdminMsg?: boolean;
126
+ }
127
+
128
+ export type E2EEMessageKind =
129
+ | "text"
130
+ | "image"
131
+ | "video"
132
+ | "audio"
133
+ | "document"
134
+ | "sticker"
135
+ | "reaction"
136
+ | "edit"
137
+ | "revoke"
138
+ | "unknown";
139
+
140
+ export interface BaseE2EEMessage {
141
+ id: string;
142
+ /** Stable conversation ID. For DMs this is the bare Facebook user ID; for groups it is the group JID. */
143
+ threadId: string;
144
+ /** Canonical E2EE chat JID. For DMs this uses the bare .0 Messenger device; senderJid keeps the actual sender device. */
145
+ chatJid: string;
146
+ /** Device-specific sender JID, e.g. user.device@msgr. */
147
+ senderJid: string;
148
+ /** Bare Facebook sender/user ID. */
149
+ senderId: string;
150
+ senderDeviceId?: number;
151
+ isGroup: boolean;
152
+ kind: E2EEMessageKind;
153
+ /** Text body when present; empty string for non-text E2EE events. */
154
+ text: string;
155
+ timestampMs: number;
156
+ attachments?: Attachment[];
157
+ replyTo?: ReplyTo;
158
+ mentions?: Mention[];
159
+ }
160
+
161
+ export interface E2EETextMessage extends BaseE2EEMessage {
162
+ kind: "text";
163
+ text: string;
164
+ }
165
+
166
+ export interface E2EEMediaMessage extends BaseE2EEMessage {
167
+ kind: "image" | "video" | "audio" | "document" | "sticker";
168
+ media?: unknown;
169
+ }
170
+
171
+ export interface E2EEReactionMessage extends BaseE2EEMessage {
172
+ kind: "reaction";
173
+ reaction: string;
174
+ targetId?: string;
175
+ }
176
+
177
+ export interface E2EEEditMessage extends BaseE2EEMessage {
178
+ kind: "edit";
179
+ targetId?: string;
180
+ }
181
+
182
+ export interface E2EERevokeMessage extends BaseE2EEMessage {
183
+ kind: "revoke";
184
+ targetId?: string;
185
+ fromMe?: boolean;
186
+ }
187
+
188
+ export interface E2EEUnknownMessage extends BaseE2EEMessage {
189
+ kind: "unknown";
190
+ raw?: unknown;
191
+ }
192
+
193
+ export type E2EEMessage =
194
+ | E2EETextMessage
195
+ | E2EEMediaMessage
196
+ | E2EEReactionMessage
197
+ | E2EEEditMessage
198
+ | E2EERevokeMessage
199
+ | E2EEUnknownMessage;
200
+
201
+ // Input types - messaging
202
+
203
+
204
+
205
+ // Input types - thread management (mirrors media.go)
206
+
207
+
208
+ // Input types - media download
209
+
210
+
211
+ // Events
212
+
213
+ export type MessengerEvent =
214
+ | { type: "message"; data: MessengerMessage }
215
+ | {
216
+ type: "messageEdit";
217
+ data: {
218
+ messageId: string;
219
+ threadId: string;
220
+ newText: string;
221
+ editCount: number;
222
+ timestampMs: number;
223
+ };
224
+ }
225
+ | {
226
+ type: "reaction";
227
+ data: {
228
+ messageId: string;
229
+ threadId: string;
230
+ actorId: string;
231
+ /** Empty string = reaction removed */
232
+ reaction: string;
233
+ timestampMs: number;
234
+ };
235
+ }
236
+ | {
237
+ type: "typing";
238
+ data: {
239
+ threadId: string;
240
+ senderId: string;
241
+ isTyping: boolean;
242
+ };
243
+ }
244
+ | {
245
+ type: "message_unsend";
246
+ data: {
247
+ messageId: string;
248
+ threadId: string;
249
+ actorId: string;
250
+ timestampMs: number;
251
+ };
252
+ }
253
+ | {
254
+ type: "read_receipt";
255
+ data: {
256
+ threadId: string;
257
+ readerId: string;
258
+ readWatermarkTimestampMs?: number;
259
+ timestampMs: number;
260
+ };
261
+ }
262
+ | {
263
+ type: "presence";
264
+ data: {
265
+ userId: string;
266
+ isOnline: boolean;
267
+ lastActiveTimestampMs?: number;
268
+ };
269
+ }
270
+ | { type: "e2ee_connected"; data: Record<string, never> }
271
+ | { type: "e2ee_message"; data: E2EEMessage }
272
+ | {
273
+ type: "e2ee_reaction";
274
+ data: {
275
+ messageId: string;
276
+ chatJid: string;
277
+ senderJid: string;
278
+ senderId: string;
279
+ /** Empty string = unreaction */
280
+ reaction: string;
281
+ };
282
+ }
283
+ | {
284
+ type: "e2ee_receipt";
285
+ data: {
286
+ type: string;
287
+ chat: string;
288
+ sender: string;
289
+ messageIds: string[];
290
+ };
291
+ }
292
+ | {
293
+ type: "disconnected";
294
+ data: { isE2EE?: boolean };
295
+ }
296
+ | { type: "reconnected"; data: Record<string, never> }
297
+ | { type: "ready"; data: { isNewSession: boolean } }
298
+ | { type: "raw"; data: Record<string, unknown> }
299
+ | { type: "error"; data: { message: string; code?: number } };
@@ -0,0 +1,295 @@
1
+ import type {
2
+ PreKeyRecord,
3
+ SignedPreKeyRecord,
4
+ KyberPreKeyRecord,
5
+ } from "@signalapp/libsignal-client";
6
+ import type { MediaTypeKey } from "../e2ee/media/media-crypto.ts";
7
+ import type { MmsTypeStr } from "./media.ts";
8
+
9
+ // Storage & Keys
10
+
11
+ export type ProtocolAddressStr = `${string}:${number}`;
12
+ export type SenderKeyId = `${ProtocolAddressStr}:${string}`;
13
+
14
+ export interface DeviceJSON {
15
+ /** schema version for local migrations; absent in old stores */
16
+ schema_version?: number;
17
+ /** base64, 32 bytes - Noise handshake key */
18
+ noise_key_priv: string;
19
+ /** base64, 32 bytes - Signal identity key */
20
+ identity_key_priv: string;
21
+ /** base64, 32 bytes - Signal signed prekey */
22
+ signed_pre_key_priv: string;
23
+ signed_pre_key_id: number;
24
+ /** base64, 64 bytes - Ed25519 sig of signed prekey by identity key */
25
+ signed_pre_key_sig: string;
26
+ registration_id: number;
27
+ /** base64, 32 bytes */
28
+ adv_secret_key: string;
29
+ /** uuid v4 */
30
+ facebook_uuid: string;
31
+ jid_user?: string;
32
+ jid_device?: number;
33
+ /** address -> base64(32B identity pub key) */
34
+ identities?: Record<string, string>;
35
+ /** address -> base64(serialized SessionRecord) */
36
+ sessions?: Record<string, string>;
37
+ /** id(number) -> base64(32B priv key) */
38
+ pre_keys?: Record<string, string>;
39
+ /** "groupJID:senderAddress" -> base64(serialized SenderKeyRecord) */
40
+ sender_keys?: Record<string, string>;
41
+ /** id(number) -> base64(serialized SignedPreKeyRecord) */
42
+ signed_pre_keys?: Record<string, string>;
43
+ /** next prekey ID to generate */
44
+ next_pre_key_id: number;
45
+ }
46
+
47
+ export interface NoiseKeyPair {
48
+ priv: Buffer;
49
+ pub: Buffer;
50
+ }
51
+
52
+ // PreKeys
53
+
54
+ export interface GeneratedPreKey {
55
+ id: number;
56
+ record: PreKeyRecord;
57
+ }
58
+
59
+ export interface PreKeyUploadPayload {
60
+ registrationId: number;
61
+ identityKey: Uint8Array; // 32 bytes, X25519 pub
62
+ signedPreKey: {
63
+ keyId: number;
64
+ publicKey: Uint8Array; // 32 bytes
65
+ signature: Uint8Array; // 64 bytes
66
+ };
67
+ preKeys: Array<{
68
+ keyId: number;
69
+ publicKey: Uint8Array; // 32 bytes
70
+ }>;
71
+ }
72
+
73
+ export interface RawPreKeyBundle {
74
+ registrationId: number;
75
+ deviceId: number;
76
+ identityKey: Uint8Array; // 33 bytes (serialize() DER compressed)
77
+ signedPreKey: {
78
+ keyId: number;
79
+ publicKey: Uint8Array;
80
+ signature: Uint8Array;
81
+ };
82
+ /** Optional: one-time prekey (may be absent if server ran out) */
83
+ preKey?: {
84
+ keyId: number;
85
+ publicKey: Uint8Array;
86
+ };
87
+ /**
88
+ * Optional: Kyber (PQ) prekey.
89
+ */
90
+ kyberPreKey?: {
91
+ keyId: number;
92
+ publicKey: Uint8Array;
93
+ signature: Uint8Array;
94
+ };
95
+ }
96
+
97
+ // Handshake & Socket
98
+
99
+ export interface NoiseSocket {
100
+ sendFrame(data: Buffer): Promise<void>;
101
+ readFrame(): Promise<Buffer>;
102
+ close(): void;
103
+ }
104
+
105
+ export interface RawWebSocket {
106
+ send(data: Buffer): void;
107
+ readRaw(len?: number): Promise<Buffer>;
108
+ close(): void;
109
+ }
110
+
111
+ export interface HandshakeResult {
112
+ socket: NoiseSocket;
113
+ }
114
+
115
+ // Client Options & Results
116
+
117
+ export interface E2EESendTextOptions {
118
+ /** Recipient JID (DM) or group JID */
119
+ toJid: string;
120
+ text: string;
121
+ isGroup: boolean;
122
+ /** Own JID - required for all sends (self address in Signal protocol) */
123
+ selfJid: string;
124
+ replyToId?: string;
125
+ replyToSenderJid?: string;
126
+ }
127
+
128
+ export interface E2EESendTextResult {
129
+ /** Encrypted MessageTransport bytes - feed into Signal cipher */
130
+ plaintext: Buffer;
131
+ /** frankingTag for the message node */
132
+ frankingTag: Buffer;
133
+ }
134
+
135
+ export interface E2EEEncryptMediaOptions {
136
+ type: MediaTypeKey;
137
+ data: Buffer;
138
+ mmsType: MmsTypeStr; // From media-upload.ts
139
+ }
140
+
141
+ export interface E2EEEncryptMediaResult {
142
+ mediaKey: Buffer;
143
+ fileSHA256: Buffer;
144
+ fileEncSHA256: Buffer;
145
+ fileLength: number;
146
+ directPath: string;
147
+ /** Upload handle returned by the media CDN. Useful for parity with native clients. */
148
+ handle: string;
149
+ /** CDN object ID returned by upload; encoded into WAMediaTransport ancillary data. */
150
+ objectId: string;
151
+ /** Pre-built MediaFields for encodeImageMessage / encodeVideoMessage / etc. */
152
+ mediaFields: Omit<MediaFields, "caption" | "ptt" | "fileName">;
153
+ }
154
+
155
+ export interface E2EEDecryptMediaOptions {
156
+ data: Buffer;
157
+ mediaKey: Buffer;
158
+ type: MediaTypeKey;
159
+ fileSHA256?: Buffer;
160
+ fileEncSHA256?: Buffer;
161
+ }
162
+
163
+ export type EncryptionResult =
164
+ | { type: "dm"; encrypted: { type: "msg" | "pkmsg"; ciphertext: Buffer }; frankingTag: Buffer; messageApp: Buffer }
165
+ | {
166
+ type: "group";
167
+ messageApp: Buffer;
168
+ groupCiphertext: Buffer;
169
+ devicePayload: Buffer;
170
+ selfDevicePayload: Buffer;
171
+ skdmPayload: Buffer;
172
+ skdm: { groupId: string; skdmBytes: Buffer; distributionId: string };
173
+ frankingTag: Buffer;
174
+ };
175
+
176
+ // Message Builder
177
+
178
+ export interface MediaFields {
179
+ caption?: string;
180
+ mimeType: string;
181
+ fileSHA256: Buffer;
182
+ fileLength: number;
183
+ mediaKey: Buffer;
184
+ fileEncSHA256: Buffer;
185
+ directPath: string;
186
+ /** Optional CDN object ID from media upload response. */
187
+ objectId?: string;
188
+ /** Unix timestamp seconds for the media key. Defaults to current time when encoding. */
189
+ mediaKeyTimestamp?: number;
190
+ width?: number;
191
+ height?: number;
192
+ seconds?: number;
193
+ ptt?: boolean;
194
+ fileName?: string;
195
+ }
196
+
197
+ export interface MessageTransportOptions {
198
+ /** Application payload. Omit for SKDM-only device fanout. */
199
+ messageApp?: Buffer;
200
+ /** Included only when sending a copy to own other devices */
201
+ dsm?: {
202
+ destinationJid: string;
203
+ phash: string;
204
+ };
205
+ /** Included only for group messages */
206
+ skdm?: {
207
+ groupId: string;
208
+ skdmBytes: Buffer;
209
+ };
210
+ /** Included for group sends with backup directive metadata. */
211
+ backupDirective?: {
212
+ messageId: string;
213
+ actionType?: "UPSERT" | "REMOVE";
214
+ };
215
+ padding?: Buffer;
216
+ }
217
+
218
+ // E2EEService types
219
+
220
+ export interface E2EEUploadResult {
221
+ messageId: string;
222
+ timestampMs: number;
223
+ }
224
+
225
+ export interface E2EEDownloadResult {
226
+ data: Buffer;
227
+ mimeType: string;
228
+ fileSize: number;
229
+ }
230
+
231
+ export interface E2EESendImageOptions {
232
+ chatJid: string;
233
+ data: Buffer;
234
+ mimeType?: string;
235
+ caption?: string;
236
+ width?: number;
237
+ height?: number;
238
+ replyToId?: string;
239
+ replyToSenderJid?: string;
240
+ }
241
+
242
+ export interface E2EESendVideoOptions {
243
+ chatJid: string;
244
+ data: Buffer;
245
+ mimeType?: string;
246
+ caption?: string;
247
+ width?: number;
248
+ height?: number;
249
+ duration?: number;
250
+ replyToId?: string;
251
+ replyToSenderJid?: string;
252
+ }
253
+
254
+ export interface E2EESendAudioOptions {
255
+ chatJid: string;
256
+ data: Buffer;
257
+ mimeType?: string;
258
+ duration?: number;
259
+ ptt?: boolean;
260
+ replyToId?: string;
261
+ replyToSenderJid?: string;
262
+ }
263
+
264
+ export interface E2EESendDocumentOptions {
265
+ chatJid: string;
266
+ data: Buffer;
267
+ fileName: string;
268
+ mimeType?: string;
269
+ replyToId?: string;
270
+ replyToSenderJid?: string;
271
+ }
272
+
273
+ export interface E2EESendStickerOptions {
274
+ chatJid: string;
275
+ data: Buffer;
276
+ mimeType?: string;
277
+ width?: number;
278
+ height?: number;
279
+ replyToId?: string;
280
+ replyToSenderJid?: string;
281
+ }
282
+
283
+ export interface E2EEDownloadOptions {
284
+ directPath: string;
285
+ /** Base64-encoded */
286
+ mediaKey: string;
287
+ /** Base64-encoded */
288
+ mediaSha256: string;
289
+ /** Base64-encoded */
290
+ mediaEncSha256?: string;
291
+ /** "image" | "video" | "audio" | "voice" | "document" | "sticker" */
292
+ mediaType: string;
293
+ mimeType?: string;
294
+ fileSize?: number;
295
+ }
@@ -0,0 +1,41 @@
1
+ export interface MediaKeys {
2
+ iv: Buffer;
3
+ cipherKey: Buffer;
4
+ macKey: Buffer;
5
+ refKey: Buffer;
6
+ }
7
+
8
+ export interface EncryptMediaResult {
9
+ dataToUpload: Buffer;
10
+ fileSHA256: Buffer;
11
+ fileEncSHA256: Buffer;
12
+ fileLength: number;
13
+ mediaKey: Buffer;
14
+ }
15
+
16
+ export interface DecryptMediaOptions {
17
+ data: Buffer;
18
+ mediaKey: Buffer;
19
+ type: any; // MediaTypeKey (avoiding circular dep for now)
20
+ fileSHA256?: Buffer;
21
+ fileEncSHA256?: Buffer;
22
+ }
23
+
24
+ export interface MediaUploadConfig {
25
+ /** From server's media connection response */
26
+ auth: string;
27
+ /** Host to upload to - Messenger prefers the last host (rupload.facebook.com) */
28
+ host: string;
29
+ ttl?: number;
30
+ authTtl?: number;
31
+ fetchedAtMs?: number;
32
+ }
33
+
34
+ export interface MediaUploadResult {
35
+ url: string;
36
+ directPath: string;
37
+ handle: string;
38
+ objectId: string;
39
+ }
40
+
41
+ export type MmsTypeStr = "image" | "video" | "ptt" | "document" | "sticker";