fb-messenger-e2ee 0.1.5 → 0.1.6
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/DOCS.md +2 -2
- package/README.md +2 -2
- package/dist/index.cjs +33 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +33 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/DOCS.md
CHANGED
|
@@ -18,8 +18,8 @@ new FBClient(options: ClientOptions)
|
|
|
18
18
|
|
|
19
19
|
| Option | Type | Description |
|
|
20
20
|
|---|---|---|
|
|
21
|
-
| `appStatePath` | `string` | Path to Facebook appState/
|
|
22
|
-
| `appState` | `any[] \| string` | Optional in-memory appState alternative. |
|
|
21
|
+
| `appStatePath` | `string` | Path to Facebook appState JSON (contains the active login cookies/session data). |
|
|
22
|
+
| `appState` | `any[] \| string` | Optional in-memory appState/cookies alternative (cookies string or array). |
|
|
23
23
|
| `sessionStorePath` | `string` | Optional path for login/session metadata used by E2EE bootstrap. |
|
|
24
24
|
| `platform` | `"facebook" \| "messenger"` | Login platform hint. Defaults to `"facebook"`. |
|
|
25
25
|
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
- **Language**: [TypeScript](https://www.typescriptlang.org/)
|
|
29
29
|
- **Encryption**: [@signalapp/libsignal-client](https://github.com/signalapp/libsignal-client)
|
|
30
30
|
- **Protocol**: ProtobufJS + manual WA-binary/protobuf encoders
|
|
31
|
-
- **Auth bootstrap bridge**: [fca-unofficial](https://github.com/VangBanLaNhat/fca-unofficial) is used internally only for appState login/CAT bootstrap
|
|
31
|
+
- **Auth bootstrap bridge**: [fca-unofficial](https://github.com/VangBanLaNhat/fca-unofficial) is used internally only for appState login/CAT bootstrap (where appState represents the active Facebook login cookies)
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
@@ -60,7 +60,7 @@ const { FBClient } = require("fb-messenger-e2ee");
|
|
|
60
60
|
import { FBClient } from "fb-messenger-e2ee";
|
|
61
61
|
|
|
62
62
|
const client = new FBClient({
|
|
63
|
-
appStatePath: "./appstate.json",
|
|
63
|
+
appStatePath: "./appstate.json", // Path to Facebook appState JSON (contains active login cookies/session data)
|
|
64
64
|
sessionStorePath: "./session.json",
|
|
65
65
|
platform: "facebook",
|
|
66
66
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -5968,6 +5968,9 @@ var EncryptedFrameSocket = class {
|
|
|
5968
5968
|
const len = header.readUIntBE(0, 3);
|
|
5969
5969
|
logger.debug("FacebookE2EESocket", `RAW frame header: ${header.toString("hex")} (len=${len})`);
|
|
5970
5970
|
const payload = await this.ws.readRaw(len);
|
|
5971
|
+
if (!payload) {
|
|
5972
|
+
throw new Error("Socket closed while reading frame payload");
|
|
5973
|
+
}
|
|
5971
5974
|
try {
|
|
5972
5975
|
const decrypted = this.decryptFrame(payload);
|
|
5973
5976
|
logger.debug("FacebookE2EESocket", `Decrypt successful, result length: ${decrypted.length}`);
|
|
@@ -6107,11 +6110,12 @@ var FacebookE2EESocket = class extends import_node_events2.EventEmitter {
|
|
|
6107
6110
|
url;
|
|
6108
6111
|
heartbeatInterval = null;
|
|
6109
6112
|
isConnected = false;
|
|
6113
|
+
cookieHeader = "";
|
|
6110
6114
|
constructor(endpoint) {
|
|
6111
6115
|
super();
|
|
6112
6116
|
this.url = endpoint;
|
|
6113
6117
|
}
|
|
6114
|
-
async connect(noisePrivKey, authPayload) {
|
|
6118
|
+
async connect(noisePrivKey, authPayload, cookies) {
|
|
6115
6119
|
return new Promise((resolve, reject) => {
|
|
6116
6120
|
try {
|
|
6117
6121
|
let readFromBuffer2 = function(len) {
|
|
@@ -6136,19 +6140,25 @@ var FacebookE2EESocket = class extends import_node_events2.EventEmitter {
|
|
|
6136
6140
|
return res;
|
|
6137
6141
|
};
|
|
6138
6142
|
var readFromBuffer = readFromBuffer2;
|
|
6143
|
+
if (cookies) this.cookieHeader = cookies;
|
|
6139
6144
|
const wsUrl = new URL(this.url);
|
|
6140
6145
|
wsUrl.searchParams.set("cid", "client-" + Date.now());
|
|
6141
6146
|
const UserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36";
|
|
6147
|
+
const wsHeaders = {
|
|
6148
|
+
"Origin": "https://www.facebook.com",
|
|
6149
|
+
"User-Agent": UserAgentStr
|
|
6150
|
+
};
|
|
6151
|
+
if (this.cookieHeader) {
|
|
6152
|
+
wsHeaders["Cookie"] = this.cookieHeader;
|
|
6153
|
+
}
|
|
6142
6154
|
this.ws = new WebSocket(wsUrl.toString(), void 0, {
|
|
6143
|
-
headers:
|
|
6144
|
-
"Origin": "https://www.facebook.com",
|
|
6145
|
-
"User-Agent": UserAgentStr
|
|
6146
|
-
}
|
|
6155
|
+
headers: wsHeaders
|
|
6147
6156
|
});
|
|
6148
6157
|
this.ws.binaryType = "arraybuffer";
|
|
6149
6158
|
let handshakeResolved = false;
|
|
6150
6159
|
let streamBuffer = [];
|
|
6151
6160
|
let streamLen = 0;
|
|
6161
|
+
let waitingRejectFn = null;
|
|
6152
6162
|
let waitingResolver = null;
|
|
6153
6163
|
let waitingLen = 0;
|
|
6154
6164
|
this.ws.addEventListener("message", (ev) => {
|
|
@@ -6173,8 +6183,9 @@ var FacebookE2EESocket = class extends import_node_events2.EventEmitter {
|
|
|
6173
6183
|
const targetLen = len || 0;
|
|
6174
6184
|
if (targetLen === 0) {
|
|
6175
6185
|
if (streamLen > 0) return Promise.resolve(readFromBuffer2(streamLen));
|
|
6176
|
-
return new Promise((resolve2) => {
|
|
6186
|
+
return new Promise((resolve2, reject2) => {
|
|
6177
6187
|
waitingLen = 1;
|
|
6188
|
+
waitingRejectFn = reject2;
|
|
6178
6189
|
waitingResolver = () => resolve2(readFromBuffer2(streamLen));
|
|
6179
6190
|
});
|
|
6180
6191
|
}
|
|
@@ -6184,8 +6195,9 @@ var FacebookE2EESocket = class extends import_node_events2.EventEmitter {
|
|
|
6184
6195
|
if (this.ws?.readyState !== WebSocket.OPEN) {
|
|
6185
6196
|
return Promise.reject(new Error("WebSocket not open"));
|
|
6186
6197
|
}
|
|
6187
|
-
return new Promise((resolve2) => {
|
|
6198
|
+
return new Promise((resolve2, reject2) => {
|
|
6188
6199
|
waitingLen = targetLen;
|
|
6200
|
+
waitingRejectFn = reject2;
|
|
6189
6201
|
waitingResolver = resolve2;
|
|
6190
6202
|
});
|
|
6191
6203
|
},
|
|
@@ -6194,10 +6206,11 @@ var FacebookE2EESocket = class extends import_node_events2.EventEmitter {
|
|
|
6194
6206
|
this.ws.addEventListener("close", () => {
|
|
6195
6207
|
this.isConnected = false;
|
|
6196
6208
|
this.stopHeartbeat();
|
|
6197
|
-
if (
|
|
6198
|
-
|
|
6199
|
-
|
|
6209
|
+
if (waitingRejectFn) {
|
|
6210
|
+
waitingRejectFn(new Error("WebSocket closed while waiting for data"));
|
|
6211
|
+
waitingRejectFn = null;
|
|
6200
6212
|
}
|
|
6213
|
+
waitingResolver = null;
|
|
6201
6214
|
this.emit("disconnected");
|
|
6202
6215
|
});
|
|
6203
6216
|
this.ws.addEventListener("open", async () => {
|
|
@@ -8049,10 +8062,10 @@ var ClientController = class {
|
|
|
8049
8062
|
logger.debug("ClientController", "Fetching CAT...");
|
|
8050
8063
|
const fbCat = await this.gateway.fetchCAT(this.requireApi());
|
|
8051
8064
|
if (!ds.jidDevice) {
|
|
8052
|
-
const
|
|
8053
|
-
const
|
|
8054
|
-
const
|
|
8055
|
-
this.icdcService.setCookies(
|
|
8065
|
+
const api2 = this.requireApi();
|
|
8066
|
+
const appState2 = api2.getAppState?.() || [];
|
|
8067
|
+
const cookieStr2 = appState2.map((c) => `${c.key}=${c.value}`).join("; ");
|
|
8068
|
+
this.icdcService.setCookies(cookieStr2);
|
|
8056
8069
|
logger.info("ClientController", "Registering new device via ICDC...");
|
|
8057
8070
|
const waDeviceId = await this.icdcService.register(userId, fbCat, "2220391788200892", ds);
|
|
8058
8071
|
ds.jidDevice = waDeviceId;
|
|
@@ -8101,7 +8114,12 @@ var ClientController = class {
|
|
|
8101
8114
|
logger.error("E2EE", "Frame error:", err);
|
|
8102
8115
|
}
|
|
8103
8116
|
});
|
|
8104
|
-
|
|
8117
|
+
const api = this.requireApi();
|
|
8118
|
+
const appState = api.getAppState?.() || [];
|
|
8119
|
+
const cookieStr = appState.map((c) => `${c.key}=${c.value}`).join("; ");
|
|
8120
|
+
logger.info("ClientController", "FCA appState length:", appState.length);
|
|
8121
|
+
logger.info("ClientController", "Cookie string snippet:", cookieStr.substring(0, 100));
|
|
8122
|
+
await noiseSocket.connect(ds.noiseKeyPriv, clientPayload, cookieStr || void 0);
|
|
8105
8123
|
this.e2eeSocket = noiseSocket;
|
|
8106
8124
|
await new Promise((resolve, reject) => {
|
|
8107
8125
|
const timeout = setTimeout(() => reject(new Error("Handshake timeout")), 1e4);
|