nexus-fca 2.1.10 → 3.0.1

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 CHANGED
@@ -1,235 +1,21 @@
1
1
  # Changelog
2
+ ## [3.0.0] - 2025-09-11 - Advanced Core Release
2
3
 
3
- ## [2.1.10] - 2025-09-08 - Publish Meta Bump
4
- ### Changed
5
- - Fixed Major Problems found in 2.1.9 and Its the last version of 2.1.xxx
6
-
7
- ### Notes
8
- - 2.1.8 And 2.1.10 is the most stable verion!
9
-
10
- ---
11
-
12
- ## [2.1.9] - 2025-09-08 - Advanced Stability Prep
13
- ### Added
14
- - Dynamic risk-tier tuning: heartbeat interval, backoff delay, spacing guard adjust automatically on risk changes.
15
- - Adaptive outbound pacing: micro-delays after heavy maintenance (refresh/reconnect) to reduce burst patterns (2m adaptive window).
16
-
17
- ### Changed
18
- - Reconnect backoff now computed via risk-aware curve (faster recovery in high risk, quieter in low risk).
19
-
20
- ### Notes
21
- - Optional, transparent; no API break. Can expose stats later via planned getSafetyTimingStats.
22
-
23
- ---
24
-
25
- ## [2.1.8] - 2025-09-08 - Safety Consolidation & Collision Guard
26
- ### Added
27
- - Unified safety orchestrator (single module coordinates safe refresh, light poke, periodic recycle) with timer registry and structured teardown.
28
- - Collision spacing guard (45m) preventing clustered token operations (refresh/poke/recycle).
29
- - Recycle suppression logic (defers 20–30m if a refresh/poke occurred inside spacing window).
30
- - Light poke integration moved inside `FacebookSafety.scheduleLightPoke()` (duplicate inline scheduling removed).
31
- - Deprecation warning emitted when legacy `FacebookSafetyManager` is instantiated.
32
-
33
- ### Changed
34
- - Removed duplicate mid-session poke timer from `index.js`.
35
- - Safe refresh participates in collision guard and spacing tracking (`_lastRefreshTs`).
36
- - Periodic recycle respects `_minSpacingMs` and defers if necessary.
37
-
38
- ### Improved
39
- - Lower probability of rapid successive token / connection maintenance clustering.
40
- - Simplified lifecycle cleanup through timer registry.
41
-
42
- ### Deprecated
43
- - `FacebookSafetyManager` (legacy) – retained for backward compatibility only.
4
+ ### Overview
5
+ Version 3.0.0 represents a pivotal milestone in the evolution of the Nexus-fCA platform, transitioning from the iterative stabilization efforts of the 2.1.x series to a unified, production-ready foundation. This release is the culmination of extensive engineering, rigorous validation, and a commitment to delivering enterprise-grade reliability. The legacy diagnostics harness has been formally retired, replaced by a standardized internal instrumentation framework that streamlines monitoring, troubleshooting, and ongoing maintenance. These enhancements collectively reinforce the platform’s robustness, scalability, and operational transparency.
44
6
 
45
- ### Notes
46
- - No public API break; users should remove custom light poke timers.
47
-
48
- ---
49
-
50
- ## [2.1.7] - 2025-09-01 - Session Stability Patch
51
7
  ### Added
52
- - User-Agent continuity (anchored single UA for entire session via safety module; eliminates mid-session UA drift increasing 20–22h expiry risk).
53
- - Exposed `setFixedUserAgent()` in `FacebookSafety` to allow explicit anchoring from credential phase.
54
- - Mid-session lightweight token poke (6h ±40m) to keep session warm without full heavy refresh cycle.
8
+ - **Delivery Receipt Health Metrics:** Introduced a comprehensive suite of metrics for delivery receipts, encompassing attempt counts, success rates, failure rates, timeout tracking, and adaptive disablement flags. These metrics provide granular visibility into delivery performance and facilitate proactive issue resolution.
9
+ - **Advanced Timeout Suppression Logic:** Implemented sophisticated suppression mechanisms for repeated delivery timeouts. This ensures consistent reply performance, mitigates the risk of systemic degradation, and enhances overall service reliability.
10
+ - **Internal Instrumentation Standardization:** All diagnostic and monitoring capabilities have been consolidated under a unified instrumentation framework, simplifying maintenance and enabling more effective root cause analysis.
55
11
 
56
12
  ### Changed
57
- - Removed legacy mobile agent override fallback in `loginHelper` that caused mixed UA fingerprints.
58
- - All safe requests now inherit continuity-aware UA through `applySafeRequestOptions`.
59
-
60
- ### Improved
61
- - Extended resilience against 20–22h cookie invalidation observed with prior dual-phase UA pattern.
62
- - Reduced unnecessary full refresh churn while preserving stealth (`safeRefresh` + light poke coexist).
63
-
64
- ---
65
-
66
- ## [2.1.6] - 2025-08-31 - Memory Guard & Queue Sweeping
67
- ### Added
68
- - Central lightweight memory guard sweeps: group queue pruning (idle >30m, overflow trim) and pendingEdits TTL sweeper (every 4m).
69
- - Health metrics extended: memoryGuardRuns, memoryGuardActions, groupQueueDroppedMessages, groupQueueExpiredQueues, groupQueuePrunedThreads, pendingEditSweeps.
70
- - API: `api.getMemoryMetrics()` returns focused memory-related counters.
71
- - Typings updated (`EditOptions`, new API methods) in `index.d.ts`.
72
-
73
- ### Improved
74
- - Group queue now tracks `lastActive` and enforces idle purge + overflow protection with metrics.
75
- - Pending edits TTL enforcement separated from resend watchdog for deterministic expiry.
13
+ - **Documentation and Package Description:** The package description and README have undergone a comprehensive revision to align with professional standards and accurately reflect the platform’s positioning, capabilities, and intended use cases.
14
+ - **Semantic Versioning:** The major version increment to 3.0.0 signifies the platform’s maturity, stability, and readiness for mission-critical deployments. Importantly, there are no breaking changes to public APIs compared to the 2.1.x series, ensuring continuity for existing integrations.
76
15
 
77
16
  ### Notes
78
- - All guards are low-frequency, low-impact; no change to delivery reliability or safety only prevention of unbounded growth.
79
-
80
- ---
81
-
82
- ## [2.1.5] - 2025-08-28 - PendingEdits & ACK Metrics
83
- ### Added
84
- - PendingEdits buffer with cap (default 200) + TTL (5m) + resend attempts (2) + ACK timeout (12s).
85
- - Automatic edit resend watchdog with safe limits and metrics (editResends, editFailed, pendingEditsDropped, pendingEditsExpired).
86
- - API: `api.setEditOptions({ maxPendingEdits, editTTLms, ackTimeoutMs, maxResendAttempts })`.
87
- - Edit ACK integration: pending edit removed on ACK receipt.
88
- - Health metrics: p95AckLatencyMs, editResends, editFailed.
89
-
90
- ### Improved
91
- - Safer edit pipeline: prevents uncontrolled retries, bounds memory, tracks expirations.
92
- - Enhanced HealthMetrics with percentile latency sample retention (50-sample window).
93
-
94
- ### Notes
95
- - Durable outbound queue & metrics exporter planned next.
96
-
97
- ---
98
-
99
- ## [2.1.4] - Adaptive Backoff & Core Metrics
100
- ### Added
101
- - Adaptive reconnect backoff with jitter (caps at 5 minutes) for safer, stealthier recovery loops.
102
- - Lazy preflight session validation (skips heavy validation if a recent successful connect occurred) toggle via `api.enableLazyPreflight()`.
103
- - Health metrics collector (uptime, idle time, reconnect counts, failures, message/ack counters, synthetic keepalives) accessible with `api.getHealthMetrics()` and included in `api.healthCheck()`.
104
- - Randomized synthetic keepalive interval (55-75s) to reduce detection patterns.
105
- - Backoff configuration hook: `api.setBackoffOptions()`.
106
-
107
- ### Improved
108
- - Reduced noisy session validation on every `listenMqtt` invocation unless needed.
109
- - More structured error classification feeding metrics (`session_invalid`, `timeout_no_t_ms`, `mqtt_error`, `message_parse`, `not_logged_in`).
110
-
111
- ### Planned (Next)
112
- - ACK tracking refinement & resend logic.
113
- - Pending edits buffer with TTL and cap.
114
- - Durable outbound queue & health exporter.
115
-
116
- ---
117
-
118
- ## [2.1.2] - CONTINUOUS IDLE RECOVERY
119
- ### Added
120
- - Soft-stale probing at 2 minutes idle (ping + conditional forced reconnect if no events within 5-8s)
121
- - Wrapper around `listenMqtt` to automatically feed events into safety heartbeat (`recordEvent`) for precise idle detection
122
- - Ghost connection detection (10m silent but socket connected triggers forced reconnect after probe)
123
- - Periodic connection recycle every ~6h ±30m to prevent long-lived silent degradation
124
- - Force reconnect API: `globalSafety.forceReconnect(tag)`
125
-
126
- ### Improved
127
- - Faster recovery from silent idle states (previously required >5 min or external trigger)
128
- - Reduced chance of appearing online but unresponsive after short inactivity
129
- - Added keepalive foreground_state publishes each heartbeat
130
-
131
- ---
132
-
133
- ## [2.1.1] - 2025-08-27 - ADVANCED SESSION STABILITY
134
- ### 🛠 Added
135
- - Adaptive safe session refresh interval (dynamic based on risk level)
136
- - Heartbeat + watchdog timers to detect stale MQTT connections early
137
- - Progressive backoff with jitter for MQTT reconnect attempts
138
- - Layered post-refresh health checks (1s / 10s / 30s) to catch silent drops
139
- - Abortable refresh with timeout safeguard (25s) to prevent hangs
140
- - Automatic reconnection trigger if no events within thresholds (2m soft, 15m hard)
141
- - `destroy()` method to cleanup timers/listeners (prevents memory leaks)
142
-
143
- ### 🔄 Changed
144
- - Safe refresh now records in‑flight ID and supersedes outdated checks
145
- - Reconnect logic centralized in `_reconnectMqttWithBackoff`
146
-
147
- ### ✅ Improved
148
- - Stability after long runtimes / multiple token refresh cycles
149
- - Reduced risk of listener not resuming after refresh
150
-
151
- ---
152
-
153
- ## [2.1.0] - 2025-08-20 - SESSION RELIABILITY & PROMISE LOGIN
154
- ### 🚀 Highlights
155
- Stability-focused release improving long‑running bot sessions, reducing false `not_logged_in` events, and modernizing the login flow.
156
-
157
- ### Added
158
- - ✅ Promise support for `login()` (dual callback + Promise API)
159
- - 🆔 Persistent device fingerprint (saved to `persistent-device.json`) to reduce checkpoint / lock frequency
160
- - 🛡️ New `validateSession()` multi-endpoint heuristic (lightweight, resilient preflight)
161
- - ⚙️ New global option: `disablePreflight` (skip session validation if desired)
162
- - 🔄 Structured error types from `parseAndCheckLogin` (`login_redirect`, `html_login_page`, `network_redirect`, etc.)
163
- - 🧪 Example: `examples/echo-test.js` (Promise style, supports env credentials or appstate)
164
-
165
- ### Changed
166
- - 🔁 `listenMqtt` now performs silent initial validation; only emits `not_logged_in` after a confirmatory retry
167
- - 🧠 `parseAndCheckLogin` now robustly handles 3xx chains & HTML login fallback pages
168
- - 🧩 Refactored internal cookie & session utilities (centralized in `utils.js`)
169
- - 📄 Rewritten documentation (README, DOCS, CHANGELOG) for concise modern onboarding
170
-
171
- ### Fixed
172
- - ❌ Spurious `parseAndCheckLogin got status code: 302` fatal errors now classified & recovered when possible
173
- - 💤 False negatives from legacy preflight removed (no premature `not_logged_in` during transient redirects)
174
- - 🔄 Edge reconnect loop where MQTT closed before revalidation completed
175
-
176
- ### Migration Notes (2.0.x → 2.1.0)
177
- - Existing code using callbacks continues to work. To use Promises: `const api = await login(opts);`
178
- - If you previously depended on device rotation, disable persistent device via option (see README) or delete `persistent-device.json`.
179
- - Remove any custom preflight hacks; built‑in `validateSession` supersedes them.
180
-
181
- ### Developer / Internal
182
- - Centralized session validation pipeline
183
- - Added granular error classification to aid future retry/backoff strategies
184
- - Prepared foundation for upcoming metrics hooks in 2.2.x
185
-
186
- ---
187
-
188
- ## [2.0.5] - 2025-07-29 - FULLY INTEGRATED NPM EDITION
189
- ### 🎯 MAJOR: Full NPM Integration
190
- - **✅ FULLY INTEGRATED**: Entire Nexus Login System now embedded directly in main `index.js`
191
- - **📦 NPM COMPATIBLE**: Works perfectly when installed via `npm install nexus-fca` - no external folder dependencies
192
- - **⚡ ZERO CONFIG**: Everything works out of the box - no separate folder setup required
193
- - **🔄 SEAMLESS MIGRATION**: Existing code continues to work, new code benefits from integration
194
-
195
- ### Added
196
- - 🎯 **Direct exports**: `nexusLogin` and `IntegratedNexusLoginSystem` available directly from main package
197
- - 🧪 **Updated test files**: All test scripts now use integrated system (`require('nexus-fca')` instead of `./nexloginsystem`)
198
- - 📖 **New documentation**: `npm-integration-guide.md` with complete NPM usage guide
199
- - 🛠️ **NPM scripts**: Added `test:login`, `test:simple`, `test:2fa`, `test:all` for easy testing
200
- - 📦 **Enhanced package.json**: Updated keywords, description, and version for NPM integration
201
-
202
- ### Changed
203
- - 🏗️ **Architecture**: Moved entire Nexus Login System from external folder into main index.js (lines 372-860+)
204
- - 📝 **Documentation**: Updated README.md to reflect NPM installation and integrated usage
205
- - 🔧 **Test files**: Fixed all test imports to use main package instead of external folder
206
- - 📦 **Package info**: Updated to v2.0.5 with new description highlighting NPM integration
207
-
208
- ### Fixed
209
- - ❌ **NPM module errors**: Eliminated "Cannot find module './nexloginsystem'" when using as npm package
210
- - 🔗 **Import paths**: All test files and examples now use correct import paths for npm usage
211
- - 🎯 **Distribution**: Package now works identically whether used locally or installed via npm
212
-
213
- ## [2.0.4] - 2025-07-29
214
- ### Fixed
215
- - 🐛 **Missing nexloginsystem folder**: Added `nexloginsystem/` to npm package files array to fix "Cannot find module './nexloginsystem'" error
216
- - 🔄 **Legacy login fallback**: Added automatic fallback to appstate-only login when Nexus Login System is not available
217
- - 🛡️ **Backward compatibility**: Enhanced compatibility for users using nexus-fca as npm dependency without full login system
218
-
219
- ### Changed
220
- - Updated package.json to include nexloginsystem folder in published package
221
- - Enhanced error handling with graceful fallback mechanisms
222
-
223
- ## [2.0.1] - 2025-07-28
224
- ### Added
225
- - 🚀 **Nexus Login System**: Advanced, safe, and automatic Facebook login system added under `/nexloginsystem`.
226
- - 🔐 **Appstate auto-generation**: Login with username/password/2FA, auto-save appstate, and seamless bot start.
227
- - 🛡️ **Maximum safety**: Human-like device simulation, TOTP/2FA support, and advanced error handling.
228
- - 📦 **Auto-backup & validation**: Appstate backup, validation, and lifecycle management.
229
- - 📚 **Full documentation**: Usage, API, and safety docs in `/nexloginsystem/README.md`.
230
-
231
- ### Changed
232
- - Updated main `README.md` with Nexus Login System quick start and features.
17
+ - **Upgrade Path:** Transitioning from 2.1.x to 3.0.0 is seamless. All documented interfaces remain unchanged, and the upgrade process requires no code modifications for existing consumers. The major version bump reflects strategic lifecycle consolidation and a renewed focus on long-term maintainability, rather than disruptive changes.
18
+ - **Lifecycle Consolidation:** This release unifies prior stabilization efforts, setting a new baseline for future enhancements and support. Users can expect ongoing improvements in reliability, observability, and operational efficiency.
233
19
 
234
- ### Removed
235
- - Old test files and legacy appstate generator scripts (now replaced by Nexus Login System).
20
+ ### Historical Logs
21
+ Version logs for the 2.1.x series have been archived and are available upon request for reference and audit purposes.
package/README.md CHANGED
@@ -1,84 +1,30 @@
1
- # Nexus-FCA v2.1.10
2
- <!-- 2.1.10 Safety Consolidation -->
3
- >Fixed Major Problems found in 2.1.9 and Its the last version of 2.1.xxx
4
-
5
- <!-- 2.1.9 Safety Consolidation -->
6
- > New in 2.1.9: Safety Consolidation & Collision Guard – unified safety orchestrator (single scheduler for safe refresh, light poke, periodic recycle) + 45m spacing guard (prevents clustered token actions), timer registry cleanup, recycle suppression after recent refresh, deprecates legacy FacebookSafetyManager.
7
-
8
- <!-- 2.1.7 Session Stability Patch -->
9
- > 2.1.7: Session Stability Patch – anchored User-Agent continuity (eliminates 20–22h silent expiry pattern), lightweight mid‑session token poke (6h ±40m randomized) + existing adaptive safeRefresh, retains ultra‑low ban profile.
10
-
11
- <!-- 2.1.6 Memory Guard -->
12
- > 2.1.6: Memory Guard & Queue Sweeping – bounded group queues, pending edit TTL sweeper, memory metrics exporter.
13
-
14
- <!-- 2.1.5 PendingEdits -->
15
- > 2.1.5: PendingEdits buffer (cap + TTL + safe resend), edit ACK watchdog, p95 ACK latency & edit resend/failure metrics, configurable via `api.setEditOptions()`.
16
-
17
1
  <p align="center">
18
- <!-- Preview image wrapped in link (corrected ibb.co domain) -->
19
- <a href="https://ibb.co/8ymR1tw"><img src="https://i.ibb.co/Sk61FGg/Dragon-Fruit-1.jpg" alt="Nexus-FCA Dragon Fruit" width="520" border="0" /></a>
2
+ <img src="https://i.ibb.co/Sk61FGg/Dragon-Fruit-1.jpg" alt="Nexus-FCA" width="520" />
20
3
  </p>
21
4
 
22
- > Advanced, safe, modern Facebook Chat (Messenger) API with integrated secure login (ID / Password / 2FA), ultra‑low ban rate session management, adaptive MQTT resilience, memory guard, and TypeScript-ready developer experience.
5
+ # Nexus-FCA v3.0.0 Advanced Core Release
23
6
 
24
- ---
25
- ## ✨ Highlights (Core Pillars)
26
- - 🔐 Integrated secure login system (username/password + TOTP 2FA) → auto appstate
27
- - 🛡️ Ultra-low ban rate design (human timing, safety limiter, anchored UA, risk heuristics)
28
- - 🔄 Resilient MQTT listener (adaptive backoff + idle / ghost detection + periodic recycle)
29
- - ♻️ Session continuity: anchored UA + adaptive safe refresh + integrated lightweight mid-session poke
30
- - 🧠 Smart session validation (lazy preflight, multi-endpoint retry, reduced false logouts)
31
- - 📊 Live health & memory metrics (`api.getHealthMetrics()`, `api.getMemoryMetrics()`)
32
- - 🧾 Type definitions (`index.d.ts`) & modern Promise / callback API
33
- - 🧩 Modular architecture (safety, performance, error, mqtt managers)
7
+ Modern, safe, production‑ready Messenger (Facebook Chat) API layer with integrated secure login (credentials + 2FA), adaptive session & connection resilience, delivery reliability safeguards, memory protection, and rich runtime metrics. Promise + callback compatible, TypeScript typed, minimal friction.
34
8
 
35
9
  ---
36
- ## 🚀 Recent Stability Enhancements (2.1.8 / 2.1.7 / 2.1.6 / 2.1.5)
37
- | Version | Focus | Key Additions |
38
- |---------|-------|---------------|
39
- | 2.1.8 | Safety Consolidation | Unified orchestrator, collision spacing (45m), timer registry, recycle suppression, legacy manager deprecated |
40
- | 2.1.7 | Session Longevity | UA continuity anchor, lightweight token poke, removal of mid-login UA drift |
41
- | 2.1.6 | Memory Safety | Group queue idle purge + overflow trim, pendingEdits TTL sweeper, memory guard metrics |
42
- | 2.1.5 | Edit Reliability | PendingEdits buffer (cap+TTL), ACK watchdog, resend limits, p95 ACK latency |
43
-
44
- ### Why UA Continuity Matters
45
- Previously, dual-phase login could swap user agents (mobile desktop) causing server-side heuristic expiry near 20–22h. Anchoring a single UA eliminates the inconsistent device fingerprint pattern and extends stable runtime under identical safety posture.
46
-
47
- ### Lightweight Mid-Session Poke (Integrated)
48
- Originally introduced in 2.1.7, now centrally scheduled inside the unified safety orchestrator (no duplicate inline timers). A subtle `fb_dtsg` refresh every ~6h (±40m randomized, alongside adaptive risk-based safe refresh) keeps tokens warm without aggressive churn while avoiding noisy traffic patterns. Collision guard ensures it never triggers too close to a full safe refresh or periodic recycle.
10
+ ## Core Value
11
+ | Pillar | What You Get |
12
+ |--------|--------------|
13
+ | Integrated Secure Login | Username / Password / TOTP 2FA stable appstate generation & reuse |
14
+ | Session Resilience | Anchored User‑Agent continuity, adaptive safe refresh, lightweight token poke, periodic recycle |
15
+ | Connection Stability | Adaptive MQTT backoff, idle & ghost detection, layered post-refresh health probes, synthetic keepalives |
16
+ | Delivery Reliability | Multi-path message send fallback (MQTT HTTP direct) + delivery receipt timeout suppression |
17
+ | Memory Guard | Bounded queues, edit TTL sweeps, controlled resend limits |
18
+ | Observability | Health + memory + delivery metrics (`api.getHealthMetrics()`, `api.getMemoryMetrics()`) |
19
+ | Edit Safety | Pending edit buffer, ACK watchdog, p95 ACK latency tracking |
20
+ | Type Definitions | First-class `index.d.ts` with modern Promise signatures |
49
21
 
50
22
  ---
51
- ## 🧪 Key API Additions
52
- ```js
53
- api.setEditOptions({ maxPendingEdits, editTTLms, ackTimeoutMs, maxResendAttempts });
54
- api.setBackoffOptions({ base, factor, max, jitter });
55
- api.enableLazyPreflight(true); // Skip heavy validation if a recent good connect exists
56
- api.getHealthMetrics(); // uptime, reconnect stats, ack latency, synthetic keepalives
57
- api.getMemoryMetrics(); // queue depths, drops, guard run counters
58
- ```
23
+ ## 🔄 What Changed in 3.0.0
24
+ Major version signals maturity & consolidation. No breaking public API changes versus late 2.1.x – upgrade is drop‑in. Temporary diagnostic harness removed; internal instrumentation formalized. Delivery receipt timeouts now intelligently retried & optionally auto-suppressed to protect outbound responsiveness.
59
25
 
60
26
  ---
61
- ## 🔍 Monitoring Example
62
- ```js
63
- setInterval(() => {
64
- const h = api.getHealthMetrics();
65
- const m = api.getMemoryMetrics();
66
- console.log('[HEALTH]', h?.status, 'acks', h?.ackCount, 'p95Ack', h?.p95AckLatencyMs);
67
- console.log('[MEM]', m);
68
- }, 60000);
69
- ```
70
-
71
- ---
72
- ## 🧷 Long Session Best Practices
73
- 1. Use appstate login when possible (avoid frequent credential logins).
74
- 2. Keep `persistent-device.json` – do not rotate unless forced.
75
- 3. Avoid changing UA manually; continuity is automatic post‑2.1.7.
76
- 4. Inspect health metrics before manually forcing reconnects.
77
- 5. Let adaptive backoff handle transient network instability.
78
- 6. Avoid using deprecated `FacebookSafetyManager`; the consolidated safety layer activates automatically when `login()` resolves.
79
-
80
- ---
81
- ## ⚡ Quick Start (Appstate)
27
+ ## 🚀 Quick Start (Appstate Preferred)
82
28
  ```js
83
29
  const login = require('nexus-fca');
84
30
 
@@ -92,15 +38,14 @@ const login = require('nexus-fca');
92
38
  })();
93
39
  ```
94
40
 
95
- ## 🔐 Quick Start (Credentials + 2FA)
41
+ ### Credentials + 2FA Flow
96
42
  ```js
97
43
  const login = require('nexus-fca');
98
-
99
44
  (async () => {
100
45
  const api = await login({
101
46
  email: process.env.FB_EMAIL,
102
47
  password: process.env.FB_PASS,
103
- twofactor: process.env.FB_2FA_SECRET // optional
48
+ twofactor: process.env.FB_2FA_SECRET // optional TOTP secret
104
49
  });
105
50
  api.listen((err, msg) => {
106
51
  if (err) return console.error(err);
@@ -110,147 +55,132 @@ const login = require('nexus-fca');
110
55
  ```
111
56
 
112
57
  ---
113
- ## 🛡️ Safety Layer (Updated 2.1.8)
114
- | Feature | Benefit |
115
- |---------|---------|
116
- | Anchored User-Agent | Eliminates fingerprint drift (prevents 20–22h expiry) |
117
- | Unified Orchestrator | Single scheduler for refresh, light poke, recycle (no overlap clashes) |
118
- | Adaptive Safe Refresh | Risk‑sensitive token renewal bands (multi‑hour low risk, shorter high risk) |
119
- | Lightweight Token Poke | Quiet longevity without churn (integrated + collision guarded) |
120
- | Idle / Ghost Detection | Auto probe + reconnect on silent stalls |
121
- | Periodic Recycle | ~6h (±30m) randomized connection rejuvenation (suppressed if recent refresh) |
122
- | Persistent Device Profile | Fewer checkpoints / trust continuity |
123
- | Lazy Preflight | Skips heavy validation when recently healthy |
124
- | Human-like Timing | Reduces automation signal surface |
125
-
126
- ### Consolidation / Collision Guard (2.1.8)
127
- The unified safety module keeps a registry of all scheduled timers (safe refresh, light poke, post-refresh health checks, periodic recycle) and enforces a minimum 45 minute spacing window so heavy or light token actions never cluster. Legacy `FacebookSafetyManager` now only emits a deprecation warning and should not be instantiated going forward.
128
-
129
- Disable preflight if needed:
58
+ ## 🧪 Key Runtime APIs
130
59
  ```js
131
- await login({ appState }, { disablePreflight: true });
132
- ```
133
-
134
- ---
135
- ## 🛰️ MQTT Listener Enhancements
136
- - Adaptive exponential backoff with jitter (caps 5m)
137
- - Soft-stale probing (2m30s) + hard watchdog tiers
138
- - Layered post-refresh health checks (1s / 10s / 30s) after token renewal
139
- - Synthetic keepalives (randomized 55–75s) feeding metrics
140
-
141
- ---
142
- ## 📦 Example Echo Test
143
- `examples/echo-test.js`:
144
- ```bash
145
- node examples/echo-test.js
60
+ api.setEditOptions({ maxPendingEdits, editTTLms, ackTimeoutMs, maxResendAttempts });
61
+ api.setBackoffOptions({ base, factor, max, jitter });
62
+ api.enableLazyPreflight(true); // Skip heavy validation if recent success
63
+ api.getHealthMetrics(); // uptime, reconnects, ack latency, delivery stats
64
+ api.getMemoryMetrics(); // queue sizes & guard counters
146
65
  ```
147
- Provide `appstate.json` or set `EMAIL` / `PASSWORD` env variables.
148
66
 
149
- ---
150
- ## 🧠 Advanced Login Flow
151
- 1. Integrated system safely generates / refreshes cookies (if credentials supplied)
152
- 2. Core consumes resulting appstate for stable API behavior
153
- 3. Persistent device JSON: `persistent-device.json`
154
-
155
- Persistent device toggle:
67
+ ### Monitoring Snippet
156
68
  ```js
157
- const { IntegratedNexusLoginSystem } = require('nexus-fca');
158
- new IntegratedNexusLoginSystem({ persistentDevice: true });
69
+ setInterval(() => {
70
+ const h = api.getHealthMetrics();
71
+ const m = api.getMemoryMetrics();
72
+ console.log('[HEALTH]', h?.status, 'acks', h?.ackCount, 'p95Ack', h?.p95AckLatencyMs);
73
+ console.log('[DELIVERY]', {
74
+ attempts: h?.deliveryAttempts,
75
+ success: h?.deliverySuccess,
76
+ failed: h?.deliveryFailed,
77
+ timeouts: h?.deliveryTimeouts,
78
+ disabledSince: h?.deliveryDisabledSince
79
+ });
80
+ console.log('[MEM]', m);
81
+ }, 60000);
159
82
  ```
160
83
 
161
84
  ---
162
- ## 🐐 Using Nexus-FCA with GoatBot V2
163
- Nexus-FCA can act as a drop‑in enhancement for the legacy fb-chat-api layer inside GoatBot V2.
85
+ ## 🛡️ Safety & Stability Architecture
86
+ | Layer | Mechanism | Purpose |
87
+ |-------|-----------|---------|
88
+ | UA Continuity | Single anchored fingerprint | Avoid heuristic expiry & drift |
89
+ | Adaptive Refresh | Risk-aware timing bands | Token longevity without bursts |
90
+ | Lightweight Poke | Subtle `fb_dtsg` renewal | Keeps session warm quietly |
91
+ | Collision Guard | 45m spacing window | Prevent clustered maintenance events |
92
+ | Idle / Ghost Probe | Timed silent detection | Force reconnect on stale sockets |
93
+ | Periodic Recycle | Randomized (~6h ±30m) | Pre-empt silent degradation |
94
+ | Backoff Strategy | Exponential + jitter | Graceful network recovery |
95
+ | Delivery Suppression | Disable after repeated timeouts | Preserve send latency |
164
96
 
165
- ### Option 1: Non‑invasive (generate fresh appstate)
166
- 1. In a separate script, run Nexus-FCA credential login (with 2FA if needed):
97
+ Disable heavy preflight if embedding inside a framework already doing checks:
167
98
  ```js
168
- const login = require('nexus-fca');
169
- (async () => {
170
- const api = await login({ email: process.env.FB_EMAIL, password: process.env.FB_PASS, twofactor: process.env.FB_2FA });
171
- const appState = api.getAppState();
172
- require('fs').writeFileSync('./appstate.json', JSON.stringify(appState, null, 2));
173
- console.log('Saved appstate.json');
174
- })();
99
+ await login({ appState }, { disablePreflight: true });
175
100
  ```
176
- 2. Configure GoatBot to use that `appstate.json` (no credential scraping needed).
177
- 3. Repeat only when session truly expires (persistent device reduces frequency).
178
101
 
179
- ### Option 2: Replace internal fb-chat-api
180
- GoatBot has a local `fb-chat-api` folder. To leverage Nexus-FCA improvements globally:
181
- 1. Install Nexus-FCA inside GoatBot project:
182
- ```bash
183
- npm install nexus-fca
184
- ```
185
- 2. Rename GoatBot’s original folder for backup:
186
- ```bash
187
- mv fb-chat-api fb-chat-api.orig # (Windows: rename manually)
188
- ```
189
- 3. Create a shim folder `fb-chat-api/index.js` with:
190
- ```js
191
- module.exports = require('nexus-fca');
192
- ```
193
- 4. Start GoatBot normally. All calls (`login`, `api.listen`, send methods) now use Nexus-FCA (Promise supported).
102
+ ---
103
+ ## 🛰️ MQTT Enhancements (Since 2.1.x)
104
+ - Adaptive reconnect curve (caps 5m)
105
+ - Layered post-refresh probes (1s / 10s / 30s)
106
+ - Synthetic randomized keepalives (55–75s)
107
+ - Structured error classification feeding metrics
194
108
 
195
- ### Option 3: Direct require patch
196
- Search GoatBot source for `require("fb-chat-api")` and change to `require("nexus-fca")`.
109
+ ---
110
+ ## ✉️ Delivery Reliability
111
+ - Multi-path send fallback (MQTT publish → HTTP send → direct fallback)
112
+ - Per-attempt timeout & retry for message delivery receipts
113
+ - Automatic classification of transient timeouts (ETIMEDOUT / ECONNRESET / EAI_AGAIN)
114
+ - Adaptive suppression of delivery receipt calls when environment unstable (protects primary send throughput)
197
115
 
198
- ### Promise usage inside GoatBot scripts
199
- Replace:
200
- ```js
201
- fbapi(loginData, (err, api) => { ... });
202
- ```
203
- with:
204
- ```js
205
- const login = require('nexus-fca');
206
- const api = await login(loginData); // supports { appState } or { email, password, twofactor }
207
- ```
116
+ ---
117
+ ## 🧠 Long Session Best Practices
118
+ 1. Prefer appstate reuse (minimal credential logins).
119
+ 2. Preserve `persistent-device.json` (only delete if forced challenge).
120
+ 3. Don’t manually rotate User-Agent – built-in continuity handles it.
121
+ 4. Inspect metrics before forcing reconnect; let backoff work.
122
+ 5. Keep dependencies updated; review CHANGELOG for operational notes.
208
123
 
209
- ### Recommended settings
210
- - Keep `persistent-device.json` at project root so repeated restarts reuse the same fingerprint.
211
- - If GoatBot already performs its own “live cookie check” loops, you can set `{ disablePreflight: true }` to avoid duplicate validation.
212
- - Handle reconnect events: listen for `error` and `listen` callbacks just like original; classified errors now have `error.type` (`login_redirect`, etc.).
124
+ ---
125
+ ## 🐐 Using with GoatBot V2 (Summary)
126
+ | Goal | Steps |
127
+ |------|-------|
128
+ | Generate appstate | Run credential login script → save `appstate.json` → configure GoatBot |
129
+ | Full replacement | Install `nexus-fca` → shim `fb-chat-api/index.js` exporting module |
130
+ | Direct require swap | Replace `require('fb-chat-api')` with `require('nexus-fca')` |
213
131
 
214
- ### Minimal integration example
132
+ Minimal example:
215
133
  ```js
216
134
  const login = require('nexus-fca');
217
135
  (async () => {
218
136
  const api = await login({ appState: require('./appstate.json') });
219
- api.listen(async (err, event) => {
220
- if (err) return console.error('[Nexus-FCA]', err);
137
+ api.listen((err, event) => {
138
+ if (err) return console.error(err);
221
139
  if (event.body === '!ping') api.sendMessage('pong', event.threadID);
222
140
  });
223
141
  })();
224
142
  ```
225
143
 
226
144
  ---
227
- ## 📚 Documentation
228
- - Full API reference: `DOCS.md`
229
- - Per-feature guides: `/docs/*.md`
230
- - Safety: `docs/account-safety.md` (unified orchestrator & deprecation note)
231
- - Examples: `/examples`
145
+ ## 📚 Documentation Map
146
+ | Resource | Location |
147
+ |----------|----------|
148
+ | Full API Reference | `DOCS.md` |
149
+ | Feature Guides | `docs/*.md` |
150
+ | Safety Details | `docs/account-safety.md` |
151
+ | Examples | `examples/` |
152
+
153
+ ---
154
+ ## � Migrating 2.1.x → 3.0.0
155
+ | Area | Action Needed |
156
+ |------|---------------|
157
+ | Public API | None (fully compatible) |
158
+ | Diagnostics Harness | Removed (no action) |
159
+ | Delivery Metrics | Optionally surface in dashboards |
160
+ | Safety Manager (legacy) | Keep removed / unused |
232
161
 
233
162
  ---
234
- ## 🔁 Updating from 2.0.x 2.1.x
235
- | Change | Action |
236
- |--------|--------|
237
- | UA Continuity (2.1.7) | No action; auto applied |
238
- | Safety Consolidation (2.1.8) | Remove any manual timers/light poke code handled internally |
239
- | Memory Guard (2.1.6) | Inspect `api.getMemoryMetrics()` periodically |
240
- | PendingEdits (2.1.5) | Tune via `api.setEditOptions()` if needed |
241
- | Lazy Preflight | Optionally disable when embedding in other frameworks |
242
- | Persistent Device | Keep file unless forced reset required |
163
+ ## 🗂 Previous 2.1.x Highlights (Condensed)
164
+ | Version | Focus | Key Additions |
165
+ |---------|-------|---------------|
166
+ | 2.1.10 | Stabilization | Final 2.1.x meta adjustments |
167
+ | 2.1.8 | Safety Consolidation | Unified orchestrator, collision spacing, recycle suppression |
168
+ | 2.1.7 | Session Longevity | UA continuity, lightweight poke |
169
+ | 2.1.6 | Memory Guard | Queue pruning, edit TTL sweeps |
170
+ | 2.1.5 | Edit Reliability | PendingEdits buffer, ACK watchdog |
243
171
 
244
- No breaking API changes across 2.1.x line.
172
+ Full details remain in `CHANGELOG.md`.
245
173
 
246
174
  ---
247
175
  ## ⚠️ Disclaimer
248
- This project is not affiliated with Facebook. Use responsibly. You are solely responsible for compliance with platform terms and local laws.
176
+ Not affiliated with Facebook. Use responsibly and comply with platform terms & local laws.
249
177
 
250
178
  ---
251
- ## 🤝 Contribute
252
- PRs for safety, stability, perf, and updated GraphQL doc_ids welcome.
179
+ ## 🤝 Contributing
180
+ Focused PRs improving stability, safety heuristics, protocol coverage, or typings are welcome.
253
181
 
254
182
  ---
255
183
  ## 📜 License
256
- MIT © 2025 Nexus-FCA Contributors
184
+ [Team Nexus](https://www.facebook.com/profile.php?id=61572587854836)
185
+
186
+ MIT © 2025 Nexus (Team Nexus)
package/index.js CHANGED
@@ -271,6 +271,7 @@ function buildAPI(globalOptions, html, jar) {
271
271
  });
272
272
  },
273
273
  getHealthMetrics: function(){ return ctx.health ? ctx.health.snapshot() : null; },
274
+ getMqttDiagnostics: function(){ return ctx.getMqttDiagnostics ? ctx.getMqttDiagnostics() : (ctx._mqttDiag || null); },
274
275
  enableLazyPreflight(enable=true){ ctx.globalOptions.disablePreflight = !enable; },
275
276
  setBackoffOptions(opts={}){ ctx.globalOptions.backoff = Object.assign(ctx.globalOptions.backoff||{}, opts); },
276
277
  setEditOptions(opts={}){ Object.assign(ctx.globalOptions.editSettings, opts); },
@@ -34,6 +34,12 @@ class HealthMetrics {
34
34
  this.groupQueueExpiredQueues = 0;
35
35
  this.groupQueueDroppedMessages = 0;
36
36
  this.pendingEditSweeps = 0;
37
+ // Delivery receipt metrics
38
+ this.deliveryAttempts = 0;
39
+ this.deliverySuccess = 0;
40
+ this.deliveryFailed = 0;
41
+ this.deliveryTimeouts = 0;
42
+ this.deliveryDisabledSince = 0; // timestamp if adaptive disable engaged
37
43
  }
38
44
  onConnect() { this.lastConnectTs = Date.now(); this.consecutiveFailures = 0; }
39
45
  onDisconnect() { this.lastDisconnectTs = Date.now(); }
@@ -57,6 +63,7 @@ class HealthMetrics {
57
63
  this.p95AckLatencyMs = sorted[idx];
58
64
  }
59
65
  onError(type){ this.lastErrorTs = Date.now(); this.lastErrorType = type || 'unknown'; }
66
+ incFailure(){ this.consecutiveFailures++; }
60
67
  onReconnectScheduled(delay){ this.reconnects++; this.currentBackoffDelay = delay; if(delay > (this.maxObservedBackoff||0)) this.maxObservedBackoff = delay; }
61
68
  trackOutbound(depth){ this.outboundQueueDepth = depth; }
62
69
  incOutboundDropped(){ this.outboundQueueDropped++; }
@@ -114,6 +121,11 @@ class HealthMetrics {
114
121
  groupQueueExpiredQueues: this.groupQueueExpiredQueues,
115
122
  groupQueueDroppedMessages: this.groupQueueDroppedMessages,
116
123
  pendingEditSweeps: this.pendingEditSweeps,
124
+ deliveryAttempts: this.deliveryAttempts,
125
+ deliverySuccess: this.deliverySuccess,
126
+ deliveryFailed: this.deliveryFailed,
127
+ deliveryTimeouts: this.deliveryTimeouts,
128
+ deliveryDisabled: !!this.deliveryDisabledSince,
117
129
  healthy: this.isHealthy(idleMs)
118
130
  };
119
131
  }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ // Lightweight diagnostics helper for MQTT/WebSocket connection lifecycle.
3
+ // Captures low-level events so we can understand repeated reconnect loops.
4
+ module.exports = function attachMqttDiagnostics(ws, ctx, log){
5
+ if(!ws || typeof ws.on !== 'function') return;
6
+ const diag = ctx._mqttDiag = ctx._mqttDiag || { attempts:0, events:[] };
7
+ function push(evt){
8
+ try {
9
+ diag.events.push({ t: Date.now(), ...evt });
10
+ if(diag.events.length > 50) diag.events.shift();
11
+ } catch(_) {}
12
+ }
13
+ ws.on('upgrade', (res)=>{ push({ type:'upgrade', status: res.statusCode, headers: safeHeaders(res.headers) }); });
14
+ ws.on('unexpected-response', (req, res)=>{ push({ type:'unexpected_response', status: res && res.statusCode, headers: res && safeHeaders(res.headers) }); });
15
+ ws.on('close', (code, reason)=>{ push({ type:'close', code, reason: reason && reason.toString() }); });
16
+ ws.on('error', (err)=>{ push({ type:'error', message: err && (err.message||err.code||'').toString(), code: err && err.code }); });
17
+ function safeHeaders(h){ if(!h) return {}; const out={}; for(const k of Object.keys(h)){ if(k.startsWith('cookie')) continue; out[k]=h[k]; } return out; }
18
+ // expose a snapshot method
19
+ ctx.getMqttDiagnostics = () => ({ attempts: diag.attempts, recent: [...diag.events] });
20
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nexus-fca",
3
- "version": "2.1.10",
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.",
3
+ "version": "3.0.1",
4
+ "description": "Nexus-FCA 3.0 – stable, low-risk Facebook Messenger automation API with integrated secure login (ID / Password / 2FA), adaptive MQTT core, safety orchestration, metrics, and TypeScript support.",
5
5
  "main": "index.js",
6
6
  "repository": {
7
7
  "type": "git",
package/src/listenMqtt.js CHANGED
@@ -166,9 +166,18 @@ function buildStream(options, WebSocket, Proxy) {
166
166
  return Stream;
167
167
  }
168
168
  function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
169
+ const attemptStartTs = Date.now();
169
170
  // Attach health metrics container lazily
170
171
  if(!ctx.health) ctx.health = new (require('../lib/health/HealthMetrics').HealthMetrics)();
172
+ // Ensure tasks map exists to track ls_req -> ls_resp correlations (avoid TypeError on undefined)
173
+ if(!ctx.tasks) ctx.tasks = new Map();
171
174
  const backoff = getBackoffState(ctx);
175
+ if(!ctx._mqttDiag) ctx._mqttDiag = { attempts:0, events:[] };
176
+ ctx._mqttDiag.attempts++;
177
+ // Suppress previously noisy test info log (kept only if verbose flag enabled)
178
+ if (ctx.globalOptions && ctx.globalOptions.verboseMqtt) {
179
+ log.info('listenMqtt', `Starting Nexus MQTT bridge (attempt=${ctx._mqttDiag.attempts}, backoff=${backoff.current||0}ms)`);
180
+ }
172
181
  const runPreflight = shouldRunPreflight(ctx);
173
182
  if (runPreflight) {
174
183
  (async () => {
@@ -263,20 +272,29 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
263
272
  log.error("listenMqtt", `Failed to create proxy agent: ${error.message}`);
264
273
  }
265
274
  }
275
+ // Create raw WebSocket first so we can attach diagnostics hooks.
276
+ const rawWs = new WebSocket(host, options.wsOptions);
277
+ try { require('../lib/mqtt/MqttDiagnostics')(rawWs, ctx, log); } catch(_) {}
266
278
  ctx.mqttClient = new mqtt.Client(
267
- () =>
268
- buildStream(
269
- options,
270
- new WebSocket(host, options.wsOptions),
271
- buildProxy()
272
- ),
279
+ () => buildStream(options, rawWs, buildProxy()),
273
280
  options
274
281
  );
282
+ if (ctx.globalOptions && ctx.globalOptions.verboseMqtt) {
283
+ log.info('listenMqtt', `MQTT bridge dialing ${host}`);
284
+ }
275
285
  const mqttClient = ctx.mqttClient;
276
286
  global.mqttClient = mqttClient;
277
287
  mqttClient.on('error', function (err) {
278
288
  const errMsg = (err && (err.error || err.message || "")).toString();
279
289
  ctx.health.onError(errMsg.includes('not logged in') ? 'not_logged_in' : 'mqtt_error');
290
+ // Increment failure counter for health tracking
291
+ if(ctx.health && typeof ctx.health.incFailure === 'function') ctx.health.incFailure();
292
+ if(!errMsg){
293
+ log.error('listenMqtt', 'Empty error message (mqtt error event). Raw err object: ' + JSON.stringify(Object.getOwnPropertyNames(err || {}).reduce((a,k)=>{a[k]=err[k];return a;},{})));
294
+ }
295
+ else {
296
+ log.error('listenMqtt', `MQTT error after ${(Date.now()-attemptStartTs)}ms: ${errMsg}`);
297
+ }
280
298
  log.error("listenMqtt", errMsg);
281
299
  try { mqttClient.end(true); } catch(_){ }
282
300
  if (/not logged in|login_redirect|html_login_page/i.test(errMsg)) {
@@ -294,6 +312,8 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
294
312
  // Ensure reconnection also triggers on unexpected close without prior error
295
313
  mqttClient.on('close', function () {
296
314
  ctx.health.onDisconnect();
315
+ if(ctx.health && typeof ctx.health.incFailure === 'function'){ ctx.health.incFailure(); }
316
+ log.warn('listenMqtt', `MQTT bridge socket closed after ${(Date.now()-attemptStartTs)}ms (attempt=${ctx._mqttDiag.attempts}).`);
297
317
  if (!ctx.loggedIn) return; // avoid loops if logged out
298
318
  if (ctx.globalOptions.autoReconnect) {
299
319
  scheduleAdaptiveReconnect(defaultFuncs, api, ctx, globalCallback);
@@ -301,6 +321,8 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
301
321
  });
302
322
  mqttClient.on('disconnect', function(){
303
323
  ctx.health.onDisconnect();
324
+ if(ctx.health && typeof ctx.health.incFailure === 'function'){ ctx.health.incFailure(); }
325
+ log.warn('listenMqtt', `MQTT bridge disconnect event after ${(Date.now()-attemptStartTs)}ms (attempt=${ctx._mqttDiag.attempts}).`);
304
326
  if (!ctx.loggedIn) return;
305
327
  if (ctx.globalOptions.autoReconnect) {
306
328
  scheduleAdaptiveReconnect(defaultFuncs, api, ctx, globalCallback);
@@ -309,11 +331,11 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
309
331
  mqttClient.on("connect", function () {
310
332
  resetBackoff(backoff);
311
333
  ctx.health.onConnect();
334
+ if (ctx.globalOptions && ctx.globalOptions.verboseMqtt) {
335
+ log.info('listenMqtt', `Nexus MQTT bridge established in ${(Date.now()-attemptStartTs)}ms (attempt=${ctx._mqttDiag.attempts}).`);
336
+ }
312
337
  if (ctx.globalSafety) { try { ctx.globalSafety.recordEvent(); } catch(_) {} }
313
- if (process.env.OnStatus === undefined) {
314
- logger("Nexus-FCA premium features works only with Nexus-Bot framework(Kidding)", "info");
315
- process.env.OnStatus = true;
316
- }
338
+ // Removed test-only premium features banner
317
339
  topics.forEach((topicsub) => mqttClient.subscribe(topicsub));
318
340
  var topic;
319
341
  const queue = {
@@ -418,7 +440,8 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
418
440
  } else if (topic == "/ls_resp") {
419
441
  const parsedPayload = JSON.parse(jsonMessage.payload);
420
442
  const reqID = jsonMessage.request_id;
421
- if (ctx["tasks"].has(reqID)) {
443
+ // Guard: ctx.tasks may be empty; only proceed if it's a Map and contains the reqID
444
+ if (ctx.tasks && typeof ctx.tasks.has === 'function' && ctx.tasks.has(reqID)) {
422
445
  const taskData = ctx["tasks"].get(reqID);
423
446
  const { type: taskType, callback: taskCallback } = taskData;
424
447
  const taskRespData = getTaskResponseData(taskType, parsedPayload);
@@ -30,28 +30,61 @@ module.exports = function (defaultFuncs, api, ctx) {
30
30
  form["message_ids[0]"] = messageID;
31
31
  form["thread_ids[" + threadID + "][0]"] = messageID;
32
32
 
33
- defaultFuncs
34
- .post(
35
- "https://www.facebook.com/ajax/mercury/delivery_receipts.php",
36
- ctx.jar,
37
- form
38
- )
39
- .then(utils.saveCookies(ctx.jar))
40
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
41
- .then(function (resData) {
42
- if (resData.error) {
43
- throw resData;
44
- }
45
-
33
+ // Lightweight retry with exponential backoff for transient network timeouts.
34
+ const maxAttempts = 3;
35
+ let attempt = 0;
36
+ const baseDelay = 500; // ms
37
+ const transientCodes = ['ETIMEDOUT','ECONNRESET','EAI_AGAIN'];
38
+ if(ctx.health){
39
+ ctx.health.deliveryAttempts++;
40
+ // If we previously disabled delivery receipts due to repeated timeouts, short-circuit success.
41
+ if(ctx.health.deliveryDisabledSince){
46
42
  return callback();
47
- })
48
- .catch(function (err) {
49
- log.error("markAsDelivered", err);
50
- if (utils.getType(err) == "Object" && err.error === "Not logged in.") {
51
- ctx.loggedIn = false;
52
- }
53
- return callback(err);
54
- });
43
+ }
44
+ }
45
+ function doPost(){
46
+ attempt++;
47
+ defaultFuncs
48
+ .post(
49
+ "https://www.facebook.com/ajax/mercury/delivery_receipts.php",
50
+ ctx.jar,
51
+ form
52
+ )
53
+ .then(utils.saveCookies(ctx.jar))
54
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
55
+ .then(function (resData) {
56
+ if (resData.error) { throw resData; }
57
+ if(ctx.health){ ctx.health.deliverySuccess++; }
58
+ return callback();
59
+ })
60
+ .catch(function (err) {
61
+ const code = err && (err.code || err.errno || (err.error && err.error.code));
62
+ const isTransient = code && transientCodes.includes(code);
63
+ if(code === 'ETIMEDOUT' && ctx.health){ ctx.health.deliveryTimeouts++; }
64
+ if(isTransient && attempt < maxAttempts){
65
+ const delay = Math.round(baseDelay * Math.pow(2, attempt-1) * (1 + Math.random()*0.2));
66
+ log.warn('markAsDelivered', `Transient ${code} attempt ${attempt}/${maxAttempts} -> retrying in ${delay}ms`);
67
+ return setTimeout(doPost, delay);
68
+ }
69
+ // Suppress noisy timeout logs after final retry unless verbose
70
+ if(!(isTransient && attempt >= maxAttempts)){
71
+ log.error("markAsDelivered", err);
72
+ }else{
73
+ log.warn('markAsDelivered', `Giving up after ${attempt} attempts (${code})`);
74
+ // Adaptive disable: if too many timeouts overall, stop calling delivery receipts for this run
75
+ if(code === 'ETIMEDOUT' && ctx.health && ctx.health.deliveryTimeouts >= 5){
76
+ ctx.health.deliveryDisabledSince = Date.now();
77
+ log.warn('markAsDelivered', 'Adaptive disable engaged after repeated ETIMEDOUT. Further receipts suppressed.');
78
+ }
79
+ }
80
+ if (utils.getType(err) == "Object" && err.error === "Not logged in.") {
81
+ ctx.loggedIn = false;
82
+ }
83
+ if(ctx.health){ ctx.health.deliveryFailed++; }
84
+ return callback(err);
85
+ });
86
+ }
87
+ doPost();
55
88
 
56
89
  return returnPromise;
57
90
  };