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.
Files changed (110) hide show
  1. package/README.md +27 -2
  2. package/dist/index.cjs +8811 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +885 -0
  5. package/dist/index.d.ts +885 -0
  6. package/dist/index.js +8843 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +19 -4
  9. package/bun.lock +0 -1014
  10. package/examples/basic-usage.ts +0 -52
  11. package/jest.config.ts +0 -18
  12. package/src/config/env.ts +0 -15
  13. package/src/controllers/client.controller.ts +0 -805
  14. package/src/controllers/dgw-handler.ts +0 -171
  15. package/src/controllers/e2ee-handler.ts +0 -832
  16. package/src/controllers/event-mapper.ts +0 -327
  17. package/src/core/client.ts +0 -151
  18. package/src/e2ee/application/e2ee-client.ts +0 -376
  19. package/src/e2ee/application/fanout-planner.ts +0 -79
  20. package/src/e2ee/application/outbound-message-cache.ts +0 -58
  21. package/src/e2ee/application/prekey-maintenance.ts +0 -55
  22. package/src/e2ee/application/retry-manager.ts +0 -156
  23. package/src/e2ee/facebook/facebook-protocol-utils.ts +0 -230
  24. package/src/e2ee/facebook/icdc-payload.ts +0 -31
  25. package/src/e2ee/index.ts +0 -76
  26. package/src/e2ee/internal.ts +0 -27
  27. package/src/e2ee/media/media-crypto.ts +0 -147
  28. package/src/e2ee/media/media-upload.ts +0 -90
  29. package/src/e2ee/message/builders/client-payload.ts +0 -54
  30. package/src/e2ee/message/builders/consumer-application.ts +0 -362
  31. package/src/e2ee/message/builders/message-application.ts +0 -64
  32. package/src/e2ee/message/builders/message-transport.ts +0 -84
  33. package/src/e2ee/message/codecs/protobuf-codecs.ts +0 -101
  34. package/src/e2ee/message/constants.ts +0 -4
  35. package/src/e2ee/message/message-builder.ts +0 -15
  36. package/src/e2ee/signal/prekey-manager.ts +0 -140
  37. package/src/e2ee/signal/signal-manager.ts +0 -365
  38. package/src/e2ee/store/device-json.ts +0 -47
  39. package/src/e2ee/store/device-repository.ts +0 -12
  40. package/src/e2ee/store/device-store.ts +0 -538
  41. package/src/e2ee/transport/binary/decoder.ts +0 -180
  42. package/src/e2ee/transport/binary/encoder.ts +0 -143
  43. package/src/e2ee/transport/binary/stanzas.ts +0 -97
  44. package/src/e2ee/transport/binary/tokens.ts +0 -64
  45. package/src/e2ee/transport/binary/wa-binary.ts +0 -8
  46. package/src/e2ee/transport/dgw/dgw-socket.ts +0 -345
  47. package/src/e2ee/transport/noise/noise-handshake.ts +0 -417
  48. package/src/e2ee/transport/noise/noise-socket.ts +0 -230
  49. package/src/index.ts +0 -34
  50. package/src/models/client.ts +0 -26
  51. package/src/models/config.ts +0 -14
  52. package/src/models/domain.ts +0 -299
  53. package/src/models/e2ee.ts +0 -295
  54. package/src/models/media.ts +0 -41
  55. package/src/models/messaging.ts +0 -88
  56. package/src/models/thread.ts +0 -69
  57. package/src/repositories/session.repository.ts +0 -20
  58. package/src/services/auth.service.ts +0 -55
  59. package/src/services/e2ee.service.ts +0 -174
  60. package/src/services/facebook-gateway.service.ts +0 -245
  61. package/src/services/icdc.service.ts +0 -177
  62. package/src/services/media.service.ts +0 -304
  63. package/src/services/messaging.service.ts +0 -28
  64. package/src/services/thread.service.ts +0 -199
  65. package/src/types/advanced-types.ts +0 -61
  66. package/src/types/fca-unofficial.d.ts +0 -212
  67. package/src/types/protocol-types.ts +0 -43
  68. package/src/utils/fca-utils.ts +0 -30
  69. package/src/utils/logger.ts +0 -24
  70. package/src/utils/mime.ts +0 -51
  71. package/tests/.env.example +0 -87
  72. package/tests/data/1x1.png +0 -0
  73. package/tests/data/example.txt +0 -1
  74. package/tests/data/file_example.mp3 +0 -0
  75. package/tests/data/file_example.mp4 +0 -0
  76. package/tests/integration.test.ts +0 -498
  77. package/tests/script/echo-e2ee.ts +0 -174
  78. package/tests/script/send-e2ee-media.ts +0 -227
  79. package/tests/script/send-e2ee-reaction.ts +0 -108
  80. package/tests/script/send-e2ee-unsend.ts +0 -115
  81. package/tests/script/send-typing.ts +0 -107
  82. package/tests/script/test-group-send.ts +0 -105
  83. package/tests/setup.ts +0 -3
  84. package/tests/types.test.ts +0 -57
  85. package/tests/unit/controllers/dgw-handler.test.ts +0 -60
  86. package/tests/unit/controllers/e2ee-handler.test.ts +0 -293
  87. package/tests/unit/controllers/event-mapper.test.ts +0 -252
  88. package/tests/unit/e2ee/application-helpers.test.ts +0 -418
  89. package/tests/unit/e2ee/device-store.test.ts +0 -126
  90. package/tests/unit/e2ee/facebook-protocol-utils.test.ts +0 -134
  91. package/tests/unit/e2ee/media-crypto.test.ts +0 -55
  92. package/tests/unit/e2ee/media-upload.test.ts +0 -60
  93. package/tests/unit/e2ee/message-builder.test.ts +0 -42
  94. package/tests/unit/e2ee/message-builders.test.ts +0 -230
  95. package/tests/unit/e2ee/noise-handshake.test.ts +0 -260
  96. package/tests/unit/e2ee/prekey-manager.test.ts +0 -55
  97. package/tests/unit/e2ee/wa-binary.test.ts +0 -127
  98. package/tests/unit/services/e2ee.service.test.ts +0 -101
  99. package/tests/unit/services/facebook-gateway.service.test.ts +0 -138
  100. package/tests/unit/services/media.service.test.ts +0 -169
  101. package/tests/unit/utils/fca-utils.test.ts +0 -48
  102. package/tsconfig.json +0 -19
  103. /package/{src/e2ee/message/proto → proto}/ArmadilloApplication.proto +0 -0
  104. /package/{src/e2ee/message/proto → proto}/ArmadilloICDC.proto +0 -0
  105. /package/{src/e2ee/message/proto → proto}/ConsumerApplication.proto +0 -0
  106. /package/{src/e2ee/message/proto → proto}/MessageApplication.proto +0 -0
  107. /package/{src/e2ee/message/proto → proto}/MessageTransport.proto +0 -0
  108. /package/{src/e2ee/message/proto → proto}/WACommon.proto +0 -0
  109. /package/{src/e2ee/message/proto → proto}/WAMediaTransport.proto +0 -0
  110. /package/{src/e2ee/message/proto → proto}/proto-writer.ts +0 -0
@@ -1,327 +0,0 @@
1
- import { EventEmitter } from "node:events";
2
- import type { MessengerEvent, MessengerMessage, Attachment, E2EEMessage, E2EEMessageKind } from "../models/domain.ts";
3
- import { str, num, now } from "../utils/fca-utils.ts";
4
- import type { MediaService } from "../services/media.service.ts";
5
- import type { E2EEService } from "../services/e2ee.service.ts";
6
-
7
- export class EventMapper {
8
- constructor(
9
- private readonly eventBus: EventEmitter,
10
- private readonly mediaService: MediaService,
11
- private readonly e2eeService: E2EEService
12
- ) {}
13
-
14
- public emitMappedEvent(rawEvent: Record<string, unknown>): void {
15
- const type = str(rawEvent.type);
16
-
17
- // Standard LightSpeed messages
18
- if (type === "message" || type === "message_reply") {
19
- const msg: MessengerMessage = {
20
- id: str(rawEvent.messageID),
21
- threadId: str(rawEvent.threadID),
22
- senderId: str(rawEvent.senderID),
23
- text: str(rawEvent.body),
24
- timestampMs: num(rawEvent.timestamp) || now(),
25
- attachments: this.mapAttachments(rawEvent.attachments),
26
- mentions: this.mapMentions(rawEvent),
27
- };
28
-
29
- const reply = rawEvent.messageReply as Record<string, unknown> | undefined;
30
- if (reply?.messageID) {
31
- msg.replyTo = {
32
- messageId: str(reply.messageID),
33
- senderId: str(reply.senderID),
34
- text: str(reply.body),
35
- };
36
- }
37
-
38
- this.emit({ type: "message", data: msg });
39
- return;
40
- }
41
-
42
- // Message edit
43
- if (type === "message_edit" || type === "messageEdit") {
44
- this.emit({
45
- type: "messageEdit",
46
- data: {
47
- messageId: str(rawEvent.messageID),
48
- threadId: str(rawEvent.threadID),
49
- newText: str(rawEvent.newText ?? rawEvent.text ?? rawEvent.body),
50
- editCount: num(rawEvent.editCount),
51
- timestampMs: num(rawEvent.timestamp) || now(),
52
- },
53
- });
54
- return;
55
- }
56
-
57
- // Reactions
58
- if (type === "message_reaction" || type === "reaction") {
59
- this.emit({
60
- type: "reaction",
61
- data: {
62
- messageId: str(rawEvent.messageID),
63
- threadId: str(rawEvent.threadID),
64
- actorId: str(rawEvent.userID ?? rawEvent.senderID),
65
- reaction: str(rawEvent.reaction),
66
- timestampMs: num(rawEvent.timestamp) || now(),
67
- },
68
- });
69
- return;
70
- }
71
-
72
- // Typing
73
- if (type === "typ") {
74
- this.emit({
75
- type: "typing",
76
- data: {
77
- threadId: str(rawEvent.threadID),
78
- senderId: str(rawEvent.from ?? rawEvent.senderID),
79
- isTyping: Boolean(rawEvent.isTyping),
80
- },
81
- });
82
- return;
83
- }
84
-
85
- // Unsend
86
- if (type === "message_unsend") {
87
- this.emit({
88
- type: "message_unsend",
89
- data: {
90
- messageId: str(rawEvent.messageID),
91
- threadId: str(rawEvent.threadID),
92
- actorId: str(rawEvent.senderID),
93
- timestampMs: num(rawEvent.timestamp) || now(),
94
- },
95
- });
96
- return;
97
- }
98
-
99
- // Read receipt
100
- if (type === "read_receipt") {
101
- this.emit({
102
- type: "read_receipt",
103
- data: {
104
- threadId: str(rawEvent.threadID),
105
- readerId: str(rawEvent.reader ?? rawEvent.readerID),
106
- readWatermarkTimestampMs: num(rawEvent.readWatermarkTimestampMs),
107
- timestampMs: num(rawEvent.time ?? rawEvent.timestamp) || now(),
108
- },
109
- });
110
- return;
111
- }
112
-
113
- // Presence
114
- if (type === "presence") {
115
- this.emit({
116
- type: "presence",
117
- data: {
118
- userId: str(rawEvent.userID),
119
- isOnline: Boolean(rawEvent.userStatus ?? rawEvent.isOnline),
120
- lastActiveTimestampMs: num(rawEvent.timestamp),
121
- },
122
- });
123
- return;
124
- }
125
-
126
- // Handshake events
127
- if (type === "disconnected") {
128
- this.emit({ type: "disconnected", data: { isE2EE: Boolean(rawEvent.isE2EE) } });
129
- return;
130
- }
131
- if (type === "reconnected") {
132
- this.emit({ type: "reconnected", data: {} });
133
- return;
134
- }
135
- if (type === "ready") {
136
- this.emit({ type: "ready", data: { isNewSession: Boolean(rawEvent.isNewSession) } });
137
- return;
138
- }
139
-
140
- // E2EE specific
141
- if (type === "e2ee_connected" || type === "e2eeConnected") {
142
- this.e2eeService.markConnected();
143
- this.emit({ type: "e2ee_connected", data: {} });
144
- return;
145
- }
146
- if (type === "e2ee_message" || type === "e2eeMessage") {
147
- const e2eeData = rawEvent.data as any;
148
- if (!e2eeData) return;
149
-
150
- const rawChatJid = str(e2eeData.chatJid || e2eeData.threadId);
151
- const senderInfo = this.parseMessengerJid(str(e2eeData.senderJid));
152
- const senderId = str(e2eeData.senderId) || senderInfo.user || senderInfo.rawUser || senderInfo.jid;
153
- const senderJid = this.canonicalMessengerDeviceJid(str(e2eeData.senderJid), senderId, senderInfo.device);
154
- const chat = this.normalizeE2EEChat(rawChatJid || senderJid);
155
-
156
- if (e2eeData.type === "decryption_failed") {
157
- this.emit({
158
- type: "error",
159
- data: {
160
- message: `E2EE decrypt failed${chat.chatJid ? ` in ${chat.chatJid}` : ""}${senderJid ? ` from ${senderJid}` : ""}: ${str(e2eeData.error)}`,
161
- },
162
- });
163
- return;
164
- }
165
-
166
- const kind = this.normalizeE2EEKind(e2eeData.kind || e2eeData.type, e2eeData);
167
- const data: Record<string, unknown> = {
168
- id: str(e2eeData.messageId || e2eeData.messageID),
169
- threadId: chat.threadId,
170
- chatJid: chat.chatJid,
171
- senderJid,
172
- senderId,
173
- isGroup: chat.isGroup,
174
- kind,
175
- text: str(e2eeData.text || e2eeData.body || ""),
176
- timestampMs: num(e2eeData.timestampMs || e2eeData.timestamp) || now(),
177
- };
178
-
179
- if (senderInfo.device > 0) data.senderDeviceId = senderInfo.device;
180
- if (Array.isArray(e2eeData.attachments) && e2eeData.attachments.length > 0) data.attachments = e2eeData.attachments;
181
- if (Array.isArray(e2eeData.mentions) && e2eeData.mentions.length > 0) data.mentions = e2eeData.mentions;
182
- if (e2eeData.media) data.media = e2eeData.media;
183
- if (e2eeData.raw) data.raw = e2eeData.raw;
184
- if (e2eeData.emoji || e2eeData.reaction) data.reaction = str(e2eeData.emoji || e2eeData.reaction);
185
- if (e2eeData.targetId) data.targetId = str(e2eeData.targetId);
186
- if (typeof e2eeData.fromMe === "boolean") data.fromMe = e2eeData.fromMe;
187
-
188
- if (e2eeData.replyToId) {
189
- const replySender = this.parseMessengerJid(str(e2eeData.replyToSenderJid));
190
- data.replyTo = {
191
- messageId: str(e2eeData.replyToId),
192
- senderId: replySender.user || str(e2eeData.replyToSenderJid),
193
- };
194
- }
195
-
196
- this.emit({
197
- type: "e2ee_message",
198
- data: data as unknown as E2EEMessage,
199
- });
200
- return;
201
- }
202
- if (type === "e2ee_reaction" || type === "e2eeReaction") {
203
- const d = rawEvent.data as Record<string, unknown> | undefined ?? rawEvent;
204
- this.emit({
205
- type: "e2ee_reaction",
206
- data: {
207
- messageId: str(d.messageId),
208
- chatJid: str(d.chatJid),
209
- senderJid: str(d.senderJid),
210
- senderId: str(d.senderId),
211
- reaction: str(d.reaction),
212
- },
213
- });
214
- return;
215
- }
216
- if (type === "e2ee_receipt" || type === "e2eeReceipt") {
217
- const d = rawEvent.data as Record<string, unknown> | undefined ?? rawEvent;
218
- this.emit({
219
- type: "e2ee_receipt",
220
- data: {
221
- type: str(d.type),
222
- chat: str(d.chat),
223
- sender: str(d.sender),
224
- messageIds: Array.isArray(d.messageIds) ? (d.messageIds as unknown[]).map(str) : [],
225
- },
226
- });
227
- return;
228
- }
229
-
230
- // Raw fallback
231
- this.emit({ type: "raw", data: rawEvent });
232
- }
233
-
234
- private normalizeE2EEKind(value: unknown, data: Record<string, unknown>): E2EEMessageKind {
235
- const kind = str(value);
236
- if (this.isE2EEMessageKind(kind)) return kind;
237
- if (data.media && typeof data.media === "object" && data.media !== null) {
238
- const mediaType = str((data.media as Record<string, unknown>).type);
239
- if (this.isE2EEMessageKind(mediaType)) return mediaType;
240
- }
241
- if (str(data.text || data.body)) return "text";
242
- return "unknown";
243
- }
244
-
245
- private isE2EEMessageKind(value: string): value is E2EEMessageKind {
246
- return ["text", "image", "video", "audio", "document", "sticker", "reaction", "edit", "revoke", "unknown"].includes(value);
247
- }
248
-
249
- private normalizeE2EEChat(jid: string): { threadId: string; chatJid: string; isGroup: boolean } {
250
- if (!jid) return { threadId: "", chatJid: "", isGroup: false };
251
- if (this.isGroupJid(jid)) return { threadId: jid, chatJid: jid, isGroup: true };
252
-
253
- const parsed = this.parseMessengerJid(jid);
254
- if (parsed.server === "msgr" && parsed.user) {
255
- return {
256
- threadId: parsed.user,
257
- chatJid: `${parsed.user}.0@msgr`,
258
- isGroup: false,
259
- };
260
- }
261
-
262
- if (/^\d+$/.test(jid)) {
263
- return { threadId: jid, chatJid: `${jid}.0@msgr`, isGroup: false };
264
- }
265
-
266
- return { threadId: jid, chatJid: jid, isGroup: false };
267
- }
268
-
269
- private isGroupJid(jid: string): boolean {
270
- return jid.endsWith("@g.us") || jid.includes(".g.");
271
- }
272
-
273
- private canonicalMessengerDeviceJid(jid: string, fallbackUser: string, fallbackDevice = 0): string {
274
- const parsed = this.parseMessengerJid(jid);
275
- if (parsed.server === "msgr" && parsed.user) return `${parsed.user}.${parsed.device}@msgr`;
276
- if (!jid && fallbackUser) return `${fallbackUser}.${fallbackDevice}@msgr`;
277
- return jid;
278
- }
279
-
280
- private parseMessengerJid(jid: string): { jid: string; rawUser: string; user: string; device: number; server: string } {
281
- const [userPart = jid, server = ""] = jid.split("@");
282
- const colonIdx = userPart.indexOf(":");
283
- const dotIdx = userPart.indexOf(".");
284
- const userEnd = dotIdx !== -1 ? dotIdx : (colonIdx !== -1 ? colonIdx : userPart.length);
285
- const user = userPart.slice(0, userEnd) || userPart;
286
- const rawDevice = colonIdx !== -1
287
- ? userPart.slice(colonIdx + 1)
288
- : (dotIdx !== -1 ? userPart.slice(dotIdx + 1) : "0");
289
- return { jid, rawUser: userPart, user, device: Number(rawDevice) || 0, server };
290
- }
291
-
292
- public emit(event: MessengerEvent): void {
293
- // Node's EventEmitter treats "error" specially: emitting it without a
294
- // typed error listener throws ERR_UNHANDLED_ERROR and can kill long-running
295
- // listeners such as tests/script/echo-e2ee.ts. We still always emit the
296
- // catch-all "event" below, so client.onEvent(listener) receives the error.
297
- if (event.type !== "error" || this.eventBus.listenerCount("error") > 0) {
298
- this.eventBus.emit(event.type as any, event.data);
299
- }
300
- this.eventBus.emit("event", event);
301
- }
302
-
303
- private mapAttachments(raw: unknown): Attachment[] | undefined {
304
- if (!Array.isArray(raw) || raw.length === 0) return undefined;
305
- const mapped = (raw as unknown[])
306
- .map(item => this.mediaService.normalizeAttachment(item))
307
- .filter((item): item is Attachment => item !== null);
308
- return mapped.length > 0 ? mapped : undefined;
309
- }
310
-
311
- private mapMentions(rawEvent: Record<string, unknown>) {
312
- const mentions = rawEvent.mentions;
313
- if (!Array.isArray(mentions) || mentions.length === 0) return undefined;
314
- return (mentions as unknown[]).flatMap(m => {
315
- if (typeof m !== "object" || m === null) return [];
316
- const item = m as Record<string, unknown>;
317
- return [
318
- {
319
- userId: str(item.id ?? item.userId),
320
- offset: num(item.fromIndex ?? item.offset),
321
- length: num(item.length),
322
- type: str(item.type) || "user",
323
- },
324
- ];
325
- });
326
- }
327
- }
@@ -1,151 +0,0 @@
1
- import type { MessengerEvent } from "../models/domain.ts";
2
- import type {
3
- SendMediaInput,
4
- SendMessageInput,
5
- SendReactionInput,
6
- TypingInput,
7
- } from "../models/messaging.ts";
8
- import type { ClientOptions, MessengerEventMap } from "../models/client.ts";
9
- import { TypedEventEmitter } from "../types/advanced-types.ts";
10
- import { ClientController } from "../controllers/client.controller.ts";
11
- import { FileSessionRepository } from "../repositories/session.repository.ts";
12
- import { AuthService } from "../services/auth.service.ts";
13
- import { E2EEService } from "../services/e2ee.service.ts";
14
- import { FacebookGatewayService } from "../services/facebook-gateway.service.ts";
15
- import { MediaService } from "../services/media.service.ts";
16
- import { ICDCService } from "../services/icdc.service.ts";
17
-
18
- /**
19
- * E2EE-only Messenger client facade.
20
- *
21
- * `fca-unofficial` is still used internally for app-state login and CAT/bootstrap
22
- * material that the E2EE transport currently requires, but plaintext/non-E2EE
23
- * messaging, thread management, polls, stickers, and history APIs are intentionally
24
- * not exposed here. Use `fca-unofficial` directly for those non-E2EE surfaces.
25
- */
26
- export class FBClient {
27
- private readonly eventBus = new TypedEventEmitter<MessengerEventMap>();
28
- private readonly controller: ClientController;
29
-
30
- public constructor(private readonly options: ClientOptions) {
31
- const sessionRepository = new FileSessionRepository();
32
- const authService = new AuthService(sessionRepository);
33
- const gateway = new FacebookGatewayService();
34
- const mediaService = new MediaService(gateway);
35
- const e2eeService = new E2EEService();
36
-
37
- const icdcService = new ICDCService(
38
- "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
39
- );
40
- this.controller = new ClientController(
41
- authService,
42
- gateway,
43
- mediaService,
44
- e2eeService,
45
- icdcService,
46
- this.eventBus as any,
47
- );
48
- }
49
-
50
- // Events
51
-
52
- /** Listen for events. Supports catch-all or specific event types. */
53
- public onEvent(listener: (event: MessengerEvent) => void): void;
54
- public onEvent<K extends keyof MessengerEventMap>(
55
- event: K,
56
- listener: (data: MessengerEventMap[K]) => void,
57
- ): void;
58
- public onEvent(arg1: any, arg2?: any): void {
59
- if (typeof arg1 === "function") {
60
- this.eventBus.on("event", arg1);
61
- } else {
62
- this.eventBus.on(arg1, arg2);
63
- }
64
- }
65
-
66
- /** Stop listening for events. */
67
- public offEvent(listener: (event: MessengerEvent) => void): void;
68
- public offEvent<K extends keyof MessengerEventMap>(
69
- event: K,
70
- listener: (data: MessengerEventMap[K]) => void,
71
- ): void;
72
- public offEvent(arg1: any, arg2?: any): void {
73
- if (typeof arg1 === "function") {
74
- this.eventBus.off("event", arg1);
75
- } else {
76
- this.eventBus.off(arg1, arg2);
77
- }
78
- }
79
-
80
- /** Legacy helper for the catch-all wrapper event. */
81
- public onAnyEvent(listener: (event: MessengerEvent) => void): void {
82
- (this.eventBus as any).on("event", listener);
83
- }
84
-
85
- // Lifecycle
86
-
87
- /**
88
- * Login with appState and prepare auth/CAT bootstrap state.
89
- * This does not start plaintext/non-E2EE MQTT listening.
90
- */
91
- public async connect(): Promise<{ userId: string }> {
92
- return this.controller.connect(
93
- {
94
- appStatePath: this.options.appStatePath,
95
- appState: this.options.appState,
96
- platform: this.options.platform ?? "facebook",
97
- },
98
- this.options.sessionStorePath,
99
- );
100
- }
101
-
102
- public async disconnect(): Promise<void> {
103
- await this.controller.disconnect();
104
- }
105
-
106
- // E2EE lifecycle
107
-
108
- public async connectE2EE(deviceStorePath: string, userId: string): Promise<void> {
109
- await this.controller.connectE2EE(deviceStorePath, userId);
110
- }
111
-
112
- public async sendNoiseKeepAlive(): Promise<void> {
113
- await this.controller.sendNoiseKeepAlive();
114
- }
115
-
116
- // E2EE messaging
117
-
118
- public async sendMessage(input: SendMessageInput): Promise<Record<string, unknown>> {
119
- return this.controller.sendMessage(input);
120
- }
121
-
122
- public async sendReaction(input: SendReactionInput): Promise<void> {
123
- await this.controller.sendReaction(input);
124
- }
125
-
126
- public async unsendMessage(messageId: string, threadId?: string): Promise<void> {
127
- await this.controller.unsendMessage(messageId, threadId);
128
- }
129
-
130
- public async sendTyping(input: TypingInput): Promise<void> {
131
- await this.controller.sendTyping(input);
132
- }
133
-
134
- // E2EE media send
135
-
136
- public async sendImage(input: SendMediaInput): Promise<Record<string, unknown>> {
137
- return this.controller.sendImage(input);
138
- }
139
-
140
- public async sendVideo(input: SendMediaInput): Promise<Record<string, unknown>> {
141
- return this.controller.sendVideo(input);
142
- }
143
-
144
- public async sendAudio(input: SendMediaInput): Promise<Record<string, unknown>> {
145
- return this.controller.sendAudio(input);
146
- }
147
-
148
- public async sendFile(input: SendMediaInput): Promise<Record<string, unknown>> {
149
- return this.controller.sendFile(input);
150
- }
151
- }