nexus-fca 2.1.1 → 2.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/CHANGELOG.md +11 -0
- package/index.js +20 -0
- package/lib/safety/FacebookSafety.js +35 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.1.2] - Unreleased - CONTINUOUS IDLE RECOVERY
|
|
4
|
+
### Added
|
|
5
|
+
- Soft-stale probing at 2 minutes idle (ping + conditional forced reconnect if no events within 5-8s)
|
|
6
|
+
- Wrapper around `listenMqtt` to automatically feed events into safety heartbeat (`recordEvent`) for precise idle detection
|
|
7
|
+
|
|
8
|
+
### Improved
|
|
9
|
+
- Faster recovery from silent idle states (previously required >5 min or external trigger)
|
|
10
|
+
- Reduced chance of appearing online but unresponsive after short inactivity
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
3
14
|
## [2.1.1] - 2025-08-27 - ADVANCED SESSION STABILITY
|
|
4
15
|
### 🛠 Added
|
|
5
16
|
- Adaptive safe session refresh interval (dynamic based on risk level)
|
package/index.js
CHANGED
|
@@ -239,6 +239,26 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
239
239
|
api[v.replace(".js", "")] = require("./src/" + v)(defaultFuncs, api, ctx);
|
|
240
240
|
});
|
|
241
241
|
api.listen = api.listenMqtt;
|
|
242
|
+
// Safety wrapper: ensure every inbound MQTT event updates safety lastEvent timestamp
|
|
243
|
+
if (!api._safetyWrappedListen) {
|
|
244
|
+
const _origListen = api.listenMqtt;
|
|
245
|
+
api.listenMqtt = function(callback) {
|
|
246
|
+
const wrapped = (err, evt) => {
|
|
247
|
+
if (!err && evt) {
|
|
248
|
+
try { globalSafety.recordEvent(); } catch(_) {}
|
|
249
|
+
}
|
|
250
|
+
if (typeof callback === 'function') callback(err, evt);
|
|
251
|
+
};
|
|
252
|
+
const emitter = _origListen(wrapped);
|
|
253
|
+
// Redundant defensive hooks
|
|
254
|
+
try {
|
|
255
|
+
emitter.on('message', () => globalSafety.recordEvent());
|
|
256
|
+
emitter.on('error', () => globalSafety.recordEvent());
|
|
257
|
+
} catch(_) {}
|
|
258
|
+
return emitter;
|
|
259
|
+
};
|
|
260
|
+
api._safetyWrappedListen = true;
|
|
261
|
+
}
|
|
242
262
|
setInterval(async () => {
|
|
243
263
|
api
|
|
244
264
|
.refreshFb_dtsg()
|
|
@@ -66,6 +66,8 @@ class FacebookSafety {
|
|
|
66
66
|
this._destroyed = false;
|
|
67
67
|
this._postRefreshChecks = [];
|
|
68
68
|
this._inFlightRefreshId = 0;
|
|
69
|
+
// New: probing guard to avoid overlapping soft-stale probes
|
|
70
|
+
this._probing = false;
|
|
69
71
|
|
|
70
72
|
this.initSafety();
|
|
71
73
|
}
|
|
@@ -306,10 +308,41 @@ class FacebookSafety {
|
|
|
306
308
|
async _ensureMqttAlive() {
|
|
307
309
|
if (!this.api || this._destroyed) return;
|
|
308
310
|
try {
|
|
311
|
+
const now = Date.now();
|
|
309
312
|
const disconnected = !this.ctx || !this.ctx.mqttClient || !this.ctx.mqttClient.connected;
|
|
310
|
-
const
|
|
313
|
+
const idle = now - this._lastEventTs;
|
|
314
|
+
const softStale = idle > 2 * 60 * 1000; // >2 min no events
|
|
315
|
+
const hardStale = idle > 5 * 60 * 1000; // >5 min no events (legacy threshold)
|
|
316
|
+
const stale = hardStale; // backwards compat naming
|
|
317
|
+
|
|
318
|
+
// If totally disconnected or hard stale -> reconnect immediately
|
|
311
319
|
if (disconnected || stale) {
|
|
312
|
-
await this._reconnectMqttWithBackoff(disconnected ? 'disconnected' : 'stale');
|
|
320
|
+
await this._reconnectMqttWithBackoff(disconnected ? 'disconnected' : 'hard-stale');
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Soft-stale probing: connection claims to be open but no events for 2-5 minutes.
|
|
325
|
+
// We issue a ping and if still no events after probe window, we force a reconnect.
|
|
326
|
+
if (softStale && !this._probing) {
|
|
327
|
+
this._probing = true;
|
|
328
|
+
const prevTs = this._lastEventTs;
|
|
329
|
+
try {
|
|
330
|
+
if (this.ctx && this.ctx.mqttClient && this.ctx.mqttClient.connected) {
|
|
331
|
+
if (typeof this.ctx.mqttClient.ping === 'function') {
|
|
332
|
+
try { this.ctx.mqttClient.ping(); } catch(_) {}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} catch(_) {}
|
|
336
|
+
setTimeout(() => {
|
|
337
|
+
if (this._destroyed) return;
|
|
338
|
+
// If no new events arrived since probe start, treat as latent-dead connection
|
|
339
|
+
if (this._lastEventTs <= prevTs) {
|
|
340
|
+
// Reset backoff to allow immediate reconnect (latency sensitive)
|
|
341
|
+
this._backoff.attempt = 0;
|
|
342
|
+
this._reconnectMqttWithBackoff('soft-stale');
|
|
343
|
+
}
|
|
344
|
+
this._probing = false;
|
|
345
|
+
}, 5000 + Math.random() * 3000); // 5-8s probe window
|
|
313
346
|
}
|
|
314
347
|
} catch (_) { /* swallow */ }
|
|
315
348
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexus-fca",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"description": "A modern, safe, and advanced Facebook Chat API for Node.js with fully integrated Nexus Login System. NPM-ready with ID/password/2FA support, ultra-low ban rate protection, and zero external dependencies.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|