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,61 @@
1
+ import { EventEmitter } from "node:events";
2
+
3
+ /**
4
+ * A type-safe version of Node.js EventEmitter.
5
+ * T is a record where keys are event names and values are payload types.
6
+ */
7
+ export class TypedEventEmitter<T extends Record<string, any>> extends EventEmitter {
8
+ override on<K extends keyof T>(event: K | (string & symbol) | string | symbol, listener: (data: T[K]) => void): this {
9
+ return super.on(event as string | symbol, listener as any);
10
+ }
11
+
12
+ override once<K extends keyof T>(event: K | (string & symbol) | string | symbol, listener: (data: T[K]) => void): this {
13
+ return super.once(event as string | symbol, listener as any);
14
+ }
15
+
16
+ override off<K extends keyof T>(event: K | (string & symbol) | string | symbol, listener: (data: T[K]) => void): this {
17
+ return super.off(event as string | symbol, listener as any);
18
+ }
19
+
20
+ override emit<K extends keyof T>(event: K | (string & symbol) | string | symbol, data: T[K]): boolean {
21
+ return super.emit(event as string | symbol, data);
22
+ }
23
+
24
+ override removeAllListeners<K extends keyof T>(event?: K | (string & symbol) | string | symbol): this {
25
+ return super.removeAllListeners(event as string | symbol);
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Recursively makes all properties in T readonly.
31
+ */
32
+
33
+ export type DeepReadonly<T> = {
34
+ readonly [P in keyof T]: T[P] extends (infer U)[]
35
+ ? readonly DeepReadonly<U>[]
36
+ : T[P] extends object
37
+ ? DeepReadonly<T[P]>
38
+ : T[P];
39
+ };
40
+
41
+ /**
42
+ * Recursively makes all properties in T optional.
43
+ */
44
+ export type DeepPartial<T> = {
45
+ [P in keyof T]?: T[P] extends (infer U)[]
46
+ ? DeepPartial<U>[]
47
+ : T[P] extends object
48
+ ? DeepPartial<T[P]>
49
+ : T[P];
50
+ };
51
+
52
+ /**
53
+ * Asserts that two types are equal at the type level.
54
+ * Useful for type-level testing.
55
+ */
56
+ export type AssertEqual<T, U> =
57
+ [T] extends [U]
58
+ ? [U] extends [T]
59
+ ? true
60
+ : false
61
+ : false;
@@ -0,0 +1,212 @@
1
+ declare module "fca-unofficial" {
2
+ export interface SendMessagePayload {
3
+ body?: string;
4
+ attachment?: unknown;
5
+ url?: string;
6
+ sticker?: number;
7
+ mentions?: Array<{
8
+ id: string;
9
+ tag: string;
10
+ fromIndex: number;
11
+ }>;
12
+ }
13
+
14
+ export interface AppStateCookie {
15
+ key: string;
16
+ value: string;
17
+ domain?: string;
18
+ path?: string;
19
+ expires?: number;
20
+ }
21
+
22
+ export interface LoginData {
23
+ appState: AppStateCookie[];
24
+ }
25
+
26
+ export interface FriendInfo {
27
+ name: string;
28
+ firstName?: string;
29
+ vanity?: string;
30
+ thumbSrc?: string;
31
+ profileUrl?: string;
32
+ gender?: number;
33
+ type?: string;
34
+ isFriend?: boolean;
35
+ isBirthDay?: boolean;
36
+ }
37
+
38
+ export interface ThreadParticipant {
39
+ accountType: string;
40
+ userID: string;
41
+ name: string;
42
+ url?: string;
43
+ profilePicture?: string;
44
+ username?: string | null;
45
+ gender?: string;
46
+ isViewerFriend?: boolean;
47
+ isMessengerUser?: boolean;
48
+ isVerified?: boolean;
49
+ }
50
+
51
+ export interface ThreadListItem {
52
+ threadID: string;
53
+ name: string | null;
54
+ unreadCount: number;
55
+ messageCount: number;
56
+ imageSrc: string | null;
57
+ emoji: string | null;
58
+ color: string | null;
59
+ nicknames: Array<{ userID: string; nickname: string }>;
60
+ muteUntil: number | null;
61
+ participants: ThreadParticipant[];
62
+ participantIDs: string[];
63
+ adminIDs: string[];
64
+ folder: string;
65
+ isGroup: boolean;
66
+ isArchived: boolean;
67
+ isSubscribed: boolean;
68
+ timestamp: string;
69
+ snippet: string | null;
70
+ snippetSender: string | null;
71
+ lastMessageTimestamp: string | null;
72
+ lastReadTimestamp: string | null;
73
+ approvalMode: boolean;
74
+ threadType: 1 | 2;
75
+ }
76
+
77
+ export interface HistoryMessage {
78
+ type: string;
79
+ senderID: string;
80
+ body: string;
81
+ threadID: string;
82
+ messageID: string;
83
+ attachments: unknown[];
84
+ mentions: Record<string, string>;
85
+ timestamp: string;
86
+ isGroup: boolean;
87
+ isUnread?: boolean;
88
+ messageReactions?: unknown[] | null;
89
+ }
90
+
91
+ export interface FCAApi {
92
+ getCurrentUserID?(): string;
93
+ getAppState?(): AppStateCookie[];
94
+ setOptions?(options: Record<string, unknown>): void;
95
+ listenMqtt(
96
+ callback: (err: unknown, event?: Record<string, unknown>) => void,
97
+ ): Promise<void> | void;
98
+ sendMessage(
99
+ message: string | SendMessagePayload,
100
+ threadID: string,
101
+ callback?: unknown,
102
+ replyToMessage?: string,
103
+ ): Promise<Record<string, unknown>> | void;
104
+ setMessageReaction?(
105
+ reaction: string,
106
+ messageID: string,
107
+ callback?: unknown,
108
+ forceCustomReaction?: boolean,
109
+ ): Promise<void> | void;
110
+ unsendMessage?(messageID: string, callback?: unknown): Promise<void> | void;
111
+ sendTypingIndicator?(
112
+ isTyping: boolean,
113
+ threadID: string,
114
+ callback?: unknown,
115
+ ): Promise<void> | void;
116
+ markAsRead?(threadID: string, read?: boolean, callback?: unknown): Promise<void> | void;
117
+ changeGroupImage?(image: unknown, threadID: string, callback?: unknown): Promise<void> | void;
118
+ setTitle?(newTitle: string, threadID: string, callback?: unknown): Promise<void> | void;
119
+ muteThread?(threadID: string, muteSeconds: number, callback?: unknown): Promise<void> | void;
120
+ deleteThread?(threadOrThreads: string | string[], callback?: unknown): Promise<void> | void;
121
+ stopListenMqtt?(): void;
122
+ /** Download a media URL and return raw buffer */
123
+ getAttachmentStream?(url: string, callback?: unknown): Promise<Buffer> | void;
124
+ /** Search users by query */
125
+ searchUsers?(
126
+ name: string,
127
+ callback?: (err: unknown, users?: Record<string, FriendInfo>[]) => void,
128
+ ): Promise<Record<string, FriendInfo>[]> | void;
129
+ /** Get user info for one or multiple IDs */
130
+ getUserInfo?(
131
+ ids: string | string[],
132
+ callback?: (err: unknown, info?: Record<string, FriendInfo>) => void,
133
+ ): Promise<Record<string, FriendInfo>> | void;
134
+ /** Create a new thread with a user */
135
+ createNewGroup?(
136
+ userIDs: string[],
137
+ groupTitle: string,
138
+ callback?: unknown,
139
+ ): Promise<Record<string, unknown>> | void;
140
+
141
+ /** Get paginated thread list */
142
+ getThreadList?(
143
+ limit: number,
144
+ timestamp: number | null,
145
+ tags: string[],
146
+ callback?: (err: unknown, threads?: ThreadListItem[]) => void,
147
+ ): Promise<ThreadListItem[]> | void;
148
+
149
+ /** Get message history for a thread */
150
+ getThreadHistory?(
151
+ threadID: string,
152
+ amount: number,
153
+ timestamp: number | undefined,
154
+ callback?: (err: unknown, messages?: HistoryMessage[]) => void,
155
+ ): Promise<HistoryMessage[]> | void;
156
+
157
+ /** Forward a media attachment to one or more threads */
158
+ forwardAttachment?(
159
+ attachmentID: string,
160
+ userOrUsers: string | string[],
161
+ callback?: unknown,
162
+ ): Promise<void> | void;
163
+
164
+ /** Create a poll in a thread */
165
+ createPoll?(
166
+ title: string,
167
+ threadID: string,
168
+ options?: Record<string, boolean>,
169
+ callback?: unknown,
170
+ ): Promise<void> | void;
171
+
172
+ /** Edit an already-sent message (requires MQTT) */
173
+ editMessage?(
174
+ text: string,
175
+ messageID: string,
176
+ callback?: unknown,
177
+ ): Promise<Record<string, unknown>> | void;
178
+
179
+ /** Add user(s) to a group thread */
180
+ addUserToGroup?(
181
+ userID: string | string[],
182
+ threadID: string,
183
+ callback?: unknown,
184
+ ): Promise<void> | void;
185
+
186
+ /** Remove a user from a group thread */
187
+ removeUserFromGroup?(
188
+ userID: string,
189
+ threadID: string,
190
+ callback?: unknown,
191
+ ): Promise<void> | void;
192
+
193
+ /** Change admin status of a user in a group */
194
+ changeAdminStatus?(
195
+ threadID: string,
196
+ userID: string,
197
+ adminStatus: boolean,
198
+ callback?: unknown,
199
+ ): Promise<void> | void;
200
+
201
+ /** Get the logged-in user's friends list */
202
+ getFriendsList?(
203
+ callback?: (err: unknown, friends?: Record<string, FriendInfo>) => void,
204
+ ): Promise<Record<string, FriendInfo>> | void;
205
+ }
206
+
207
+ export default function login(
208
+ loginData: LoginData,
209
+ options: Record<string, unknown>,
210
+ callback: (err: unknown, api?: FCAApi) => void,
211
+ ): void;
212
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Protocol-specific Type Definitions
3
+ */
4
+
5
+ export interface E2EEMessagePayload {
6
+ kind?: "text" | "image" | "video" | "audio" | "document" | "sticker" | "reaction" | "edit" | "revoke" | "unknown";
7
+ type?: "text" | "media" | "decryption_failed";
8
+ senderJid: string;
9
+ senderId?: string;
10
+ senderDeviceId?: number;
11
+ chatJid?: string;
12
+ messageId: string;
13
+ timestampMs: number;
14
+ text?: string;
15
+ isArmadillo?: boolean;
16
+ error?: string;
17
+ }
18
+
19
+ export interface DecryptedConsumerApplication {
20
+ payload?: {
21
+ type: string;
22
+ data: number[];
23
+ };
24
+ version?: number;
25
+ }
26
+
27
+ export interface DecryptedArmadillo {
28
+ payload?: {
29
+ type: string;
30
+ data: number[];
31
+ };
32
+ }
33
+
34
+ export interface DecryptedMessageApplication {
35
+ payload?: {
36
+ subProtocol?: {
37
+ consumerMessage?: DecryptedConsumerApplication;
38
+ armadillo?: DecryptedArmadillo;
39
+ futureProof?: string;
40
+ };
41
+ };
42
+ metadata?: any;
43
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * FCA Utilities
3
+ *
4
+ * Re-implementation of basic FCA utility functions to avoid heavy dependencies.
5
+ */
6
+
7
+ export function str(v: unknown): string {
8
+ if (typeof v === "string") return v;
9
+ if (typeof v === "number" || typeof v === "boolean" || typeof v === "bigint") return String(v);
10
+ return "";
11
+ }
12
+
13
+ export function num(v: unknown): number {
14
+ const n = Number(v);
15
+ return Number.isFinite(n) ? n : 0;
16
+ }
17
+
18
+ export function date(v: unknown): number {
19
+ if (v instanceof Date) return v.getTime();
20
+ if (typeof v === "number") return v;
21
+ if (typeof v === "string") {
22
+ const d = new Date(v);
23
+ return isNaN(d.getTime()) ? Date.now() : d.getTime();
24
+ }
25
+ return Date.now();
26
+ }
27
+
28
+ export function now(): number {
29
+ return Date.now();
30
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Centralized logging utility for FME.
3
+ *
4
+ * Controlled by process.env.DEBUG.
5
+ */
6
+
7
+ const isDebug = !!process.env.DEBUG || process.env.NODE_ENV === "development";
8
+
9
+ export const logger = {
10
+ info: (...args: any[]) => {
11
+ console.log(...args);
12
+ },
13
+ debug: (...args: any[]) => {
14
+ if (isDebug) {
15
+ console.log(...args);
16
+ }
17
+ },
18
+ warn: (...args: any[]) => {
19
+ console.warn(...args);
20
+ },
21
+ error: (...args: any[]) => {
22
+ console.error(...args);
23
+ }
24
+ };
@@ -0,0 +1,51 @@
1
+ import { extname } from "node:path";
2
+
3
+ const MIME_BY_EXT: Record<string, string> = {
4
+ ".apng": "image/apng",
5
+ ".avif": "image/avif",
6
+ ".gif": "image/gif",
7
+ ".jpeg": "image/jpeg",
8
+ ".jpg": "image/jpeg",
9
+ ".png": "image/png",
10
+ ".webp": "image/webp",
11
+ ".bmp": "image/bmp",
12
+ ".svg": "image/svg+xml",
13
+ ".mp4": "video/mp4",
14
+ ".m4v": "video/mp4",
15
+ ".mov": "video/quicktime",
16
+ ".webm": "video/webm",
17
+ ".mpeg": "video/mpeg",
18
+ ".mpg": "video/mpeg",
19
+ ".mp3": "audio/mpeg",
20
+ ".m4a": "audio/mp4",
21
+ ".aac": "audio/aac",
22
+ ".ogg": "audio/ogg; codecs=opus",
23
+ ".opus": "audio/ogg; codecs=opus",
24
+ ".wav": "audio/wav",
25
+ ".flac": "audio/flac",
26
+ ".pdf": "application/pdf",
27
+ ".txt": "text/plain",
28
+ ".json": "application/json",
29
+ ".csv": "text/csv",
30
+ ".zip": "application/zip",
31
+ };
32
+
33
+ export type FileMediaKind = "image" | "video" | "audio" | "file";
34
+
35
+ /**
36
+ * Infer a MIME type from a filename/path extension.
37
+ *
38
+ * This intentionally avoids async/content sniffing so public send APIs can make
39
+ * mimeType optional without adding filesystem reads or external dependencies.
40
+ */
41
+ export function inferMimeTypeFromFileName(fileName: string, fallback = "application/octet-stream"): string {
42
+ const ext = extname(fileName).toLowerCase();
43
+ return MIME_BY_EXT[ext] ?? fallback;
44
+ }
45
+
46
+ export function inferFileMediaKindFromMimeType(mimeType: string): FileMediaKind {
47
+ if (mimeType.startsWith("image/")) return "image";
48
+ if (mimeType.startsWith("video/")) return "video";
49
+ if (mimeType.startsWith("audio/")) return "audio";
50
+ return "file";
51
+ }
@@ -0,0 +1,87 @@
1
+ ###############################################
2
+ # Core runtime
3
+ ###############################################
4
+
5
+ # Optional. Defaults shown here.
6
+ FB_APPSTATE_PATH=./tests/appstate.json
7
+ FB_SESSION_STORE_PATH=./tests/session.json
8
+ FB_PLATFORM=facebook
9
+
10
+
11
+ ###############################################
12
+ # DGW integration inside FBClient.connectE2EE
13
+ # Used by src/controllers/client.controller.ts
14
+ ###############################################
15
+
16
+ # Enable DGW bootstrap in connectE2EE
17
+ # 0 = off (default), 1 = on
18
+ FB_DGW_ENABLE=0
19
+
20
+ # Captured WebSocket endpoints from browser session
21
+ FB_DGW_URL_LIGHTSPEED=wss://gateway.facebook.com/ws/lightspeed?x-dgw-appid=2220391788200892&x-dgw-appversion=0&x-dgw-authtype=1:0&x-dgw-version=5&x-dgw-uuid=100050349247667&x-dgw-tier=prod&x-dgw-loggingid=REPLACE_ME&x-dgw-regionhint=HIL&x-dgw-deviceid=REPLACE_ME
22
+ FB_DGW_URL_STREAMCONTROLLER=wss://gateway.facebook.com/ws/streamcontroller?x-dgw-appid=2220391788200892&x-dgw-appversion=0&x-dgw-authtype=1:0&x-dgw-version=5&x-dgw-uuid=100050349247667&x-dgw-tier=prod&x-dgw-deviceid=REPLACE_ME&x-dgw-app-stream-group=group1
23
+ FB_DGW_URL_REALTIME=wss://gateway.facebook.com/ws/realtime?x-dgw-appid=2220391788200892&x-dgw-appversion=0&x-dgw-authtype=1:0&x-dgw-version=5&x-dgw-uuid=100050349247667&x-dgw-tier=prod&x-dgw-deviceid=REPLACE_ME&x-dgw-app-stream-group=group1
24
+
25
+ # Optional override headers
26
+ FB_DGW_UA=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
27
+ FB_DGW_ORIGIN=https://www.facebook.com
28
+ FB_DGW_REFERER=https://www.facebook.com/
29
+ FB_DGW_ACCEPT_LANGUAGE=en-US,en;q=0.9
30
+
31
+ # Optional bootstrap OPEN frame tuning
32
+ FB_DGW_STREAM_ID=1
33
+ FB_DGW_BOOTSTRAP_METHOD=FBGQLS:XDT_DIRECT_REALTIME_EVENT
34
+ FB_DGW_BOOTSTRAP_DOC_ID=9712315318850438
35
+ FB_DGW_BOOTSTRAP_ROUTING_HINT=useIGDTypingIndicatorSubscription
36
+ FB_DGW_BOOTSTRAP_BODY=true
37
+ FB_DGW_BOOTSTRAP_ACCEPT_ACK=RSAck
38
+ FB_DGW_BOOTSTRAP_REFERER=https://www.facebook.com/messages/
39
+
40
+ # Optional DATA bootstrap frame (after OPEN)
41
+ # Option A: provide raw payload hex directly
42
+ FB_DGW_BOOTSTRAP_DATA_PAYLOAD_HEX=
43
+
44
+ # Option B: build payload as prefixHex + JSON + suffixHex
45
+ FB_DGW_BOOTSTRAP_DATA_JSON=
46
+ # Auto build default JSON payload when FB_DGW_BOOTSTRAP_DATA_JSON is empty.
47
+ # Default = 1 (enabled). Set 0 to disable auto payload.
48
+ FB_DGW_BOOTSTRAP_DATA_AUTO=1
49
+ FB_DGW_BOOTSTRAP_DATA_PREFIX_HEX=2c1878
50
+ FB_DGW_BOOTSTRAP_DATA_SUFFIX_HEX=0000
51
+ FB_DGW_BOOTSTRAP_DATA_TARGETS=realtime,streamcontroller
52
+ FB_DGW_BOOTSTRAP_DATA_REQUIRES_ACK=1
53
+ FB_DGW_BOOTSTRAP_DATA_ACK_ID=0
54
+
55
+
56
+ ###############################################
57
+ # Standalone DGW probe script
58
+ # Used by tests/script/probe-dgw.ts
59
+ ###############################################
60
+
61
+ # Full cookie header string from logged-in browser session
62
+ DGW_COOKIE=c_user=...; xs=...; fr=...; datr=...;
63
+
64
+ # Usually same as FB_DGW_UA / FB_DGW_ORIGIN
65
+ DGW_UA=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
66
+ DGW_ORIGIN=https://www.facebook.com
67
+ DGW_TIMEOUT_MS=12000
68
+
69
+ # Reuse same endpoint values if desired
70
+ DGW_URL_LIGHTSPEED=
71
+ DGW_URL_STREAMCONTROLLER=
72
+ DGW_URL_REALTIME=
73
+
74
+ ###############################################
75
+ # E2EE media upload / send-image script
76
+ ###############################################
77
+
78
+ # Optional override for tests/script/send-e2ee-image.ts.
79
+ # Leave FB_E2EE_MEDIA_UPLOAD_AUTH empty to query a fresh media_conn token from the E2EE stream.
80
+ FB_E2EE_MEDIA_UPLOAD_AUTH=
81
+ FB_E2EE_MEDIA_UPLOAD_HOST=rupload.facebook.com
82
+
83
+ # Optional overrides for tests/script/send-e2ee-image.ts
84
+ TEST_E2EE_IMAGE_JID=100042415119261.0@msgr
85
+ TEST_E2EE_IMAGE_PATH=./tests/data/1x1.png
86
+ TEST_E2EE_IMAGE_MIME=image/png
87
+ TEST_E2EE_IMAGE_CAPTION=
Binary file
@@ -0,0 +1 @@
1
+ test
Binary file
Binary file