nexus-fca 2.0.7 β†’ 2.1.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,5 +1,61 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.1.1] - 2025-08-27 - ADVANCED SESSION STABILITY
4
+ ### πŸ›  Added
5
+ - Adaptive safe session refresh interval (dynamic based on risk level)
6
+ - Heartbeat + watchdog timers to detect stale MQTT connections early
7
+ - Progressive backoff with jitter for MQTT reconnect attempts
8
+ - Layered post-refresh health checks (1s / 10s / 30s) to catch silent drops
9
+ - Abortable refresh with timeout safeguard (25s) to prevent hangs
10
+ - Automatic reconnection trigger if no events within thresholds (2m soft, 15m hard)
11
+ - `destroy()` method to cleanup timers/listeners (prevents memory leaks)
12
+
13
+ ### πŸ”„ Changed
14
+ - Safe refresh now records in‑flight ID and supersedes outdated checks
15
+ - Reconnect logic centralized in `_reconnectMqttWithBackoff`
16
+
17
+ ### βœ… Improved
18
+ - Stability after long runtimes / multiple token refresh cycles
19
+ - Reduced risk of listener not resuming after refresh
20
+
21
+ ---
22
+
23
+ ## [2.1.0] - 2025-08-20 - SESSION RELIABILITY & PROMISE LOGIN
24
+ ### πŸš€ Highlights
25
+ Stability-focused release improving long‑running bot sessions, reducing false `not_logged_in` events, and modernizing the login flow.
26
+
27
+ ### Added
28
+ - βœ… Promise support for `login()` (dual callback + Promise API)
29
+ - πŸ†” Persistent device fingerprint (saved to `persistent-device.json`) to reduce checkpoint / lock frequency
30
+ - πŸ›‘οΈ New `validateSession()` multi-endpoint heuristic (lightweight, resilient preflight)
31
+ - βš™οΈ New global option: `disablePreflight` (skip session validation if desired)
32
+ - πŸ”„ Structured error types from `parseAndCheckLogin` (`login_redirect`, `html_login_page`, `network_redirect`, etc.)
33
+ - πŸ§ͺ Example: `examples/echo-test.js` (Promise style, supports env credentials or appstate)
34
+
35
+ ### Changed
36
+ - πŸ” `listenMqtt` now performs silent initial validation; only emits `not_logged_in` after a confirmatory retry
37
+ - 🧠 `parseAndCheckLogin` now robustly handles 3xx chains & HTML login fallback pages
38
+ - πŸ” Default behavior: device identity no longer rotates unless explicitly overridden
39
+ - 🧩 Refactored internal cookie & session utilities (centralized in `utils.js`)
40
+ - πŸ“„ Rewritten documentation (README, DOCS, CHANGELOG) for concise modern onboarding
41
+
42
+ ### Fixed
43
+ - ❌ Spurious `parseAndCheckLogin got status code: 302` fatal errors now classified & recovered when possible
44
+ - πŸ’€ False negatives from legacy preflight removed (no premature `not_logged_in` during transient redirects)
45
+ - πŸ”„ Edge reconnect loop where MQTT closed before revalidation completed
46
+
47
+ ### Migration Notes (2.0.x β†’ 2.1.0)
48
+ - Existing code using callbacks continues to work. To use Promises: `const api = await login(opts);`
49
+ - If you previously depended on device rotation, disable persistent device via option (see README) or delete `persistent-device.json`.
50
+ - Remove any custom preflight hacks; built‑in `validateSession` supersedes them.
51
+
52
+ ### Developer / Internal
53
+ - Centralized session validation pipeline
54
+ - Added granular error classification to aid future retry/backoff strategies
55
+ - Prepared foundation for upcoming metrics hooks in 2.2.x
56
+
57
+ ---
58
+
3
59
  ## [2.0.5] - 2025-07-29 - FULLY INTEGRATED NPM EDITION
4
60
  ### 🎯 MAJOR: Full NPM Integration
5
61
  - **βœ… FULLY INTEGRATED**: Entire Nexus Login System now embedded directly in main `index.js`
package/README.md CHANGED
@@ -1,334 +1,194 @@
1
- <div align="center">
1
+ # Nexus-FCA v2.1.0
2
2
 
3
- <img src="https://i.ibb.co/LzkQMGWz/Future-Studio-Synthwave-Logo-Future-Studio-Synthwave-Logo.png" alt="Nexus-FCA Logo" width="500"/>
3
+ <p align="center">
4
+ <!-- Preview image wrapped in link (corrected ibb.co domain) -->
5
+ <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>
6
+ </p>
4
7
 
5
- </div>
6
-
7
- # Nex## ⚠️## πŸ’¬ Community & Support
8
- - **GitHub**: [github.com/Nexus-016/Nexus-fCA](https://github.com/Nexus-016/Nexus-fCA)
9
- - **Docs**: See `/docs` for per-feature usage and safety guidelines
10
- - **Safety Tips**: Always monitor your account status and use fresh appstate cookies
11
- - **Contributions**: PRs and issues welcome! Safety improvements prioritized
8
+ > Advanced, safe, modern Facebook Chat (Messenger) API with integrated secure login (ID / Password / 2FA), ultra‑low ban rate session management, MQTT listener, and TypeScript-ready developer experience.
12
9
 
13
10
  ---
14
-
15
- ## πŸ† Why Choose Nexus-FCA Ultra-Safe Edition?
16
- - **50%+ Lower Ban Rate**: Advanced safety algorithms minimize Facebook account risks
17
- - **Intelligent Protection**: Smart human behavior simulation prevents detection
18
- - **Real-time Monitoring**: Continuous account health assessment and protection
19
- - **Future-Proof**: Regular updates to stay ahead of Facebook's detection methods
11
+ ## ✨ Highlights
12
+ - πŸ” Integrated secure login system (username/password + TOTP 2FA) β†’ auto appstate
13
+ - πŸ›‘οΈ Ultra-low ban rate design (human timing, safety limiter, risk heuristics)
14
+ - πŸ”„ Resilient MQTT listener (improved session validation + graceful reconnect)
15
+ - πŸ” Persistent device fingerprint (no random rotation β†’ fewer checkpoints)
16
+ - 🧠 Smart session validation (multi-endpoint retry, reduced false logouts)
17
+ - βš™οΈ Zero-config appstate reuse & automatic backup/versioned snapshots
18
+ - 🧩 Modular architecture (safety, performance, error, mqtt managers)
19
+ - πŸ—‚οΈ Rich feature docs in `/docs` (thread, message, reactions, attachments)
20
+ - 🧾 Type definitions (`index.d.ts`) & modern Promise / callback API
20
21
 
21
22
  ---
22
-
23
- ## ⚠️ Important Disclaimer
24
- Nexus-FCA is not affiliated with Facebook. This software is provided for educational and research purposes. Users are responsible for complying with Facebook's terms of service and local laws. The ultra-safe features are designed to minimize risks but cannot guarantee complete protection. Always use responsibly and monitor your account status regularly. Account Safety Notice
25
- Nexus-FCA Maximum Safety Edition is specifically designed to minimize Facebook account ban, lock, checkpoint, and block rates. Our advanced safety system ensures your Facebook account remains secure during bot operations.
26
-
27
- **Advanced Safety Protection:**
28
- - βœ… Ultra-low ban rate protection (minimizes account suspension risk)
29
- - βœ… Real-time lock and checkpoint detection with auto-shutdown
30
- - βœ… Smart request patterns that mimic human behavior
31
- - βœ… Advanced session management to prevent account flags
32
- - βœ… Intelligent delay patterns for maximum account safety
33
- - βœ… Enhanced error recovery without triggering Facebook security
34
-
35
- Use responsibly and at your own risk. This package is not affiliated with Facebook.Nexus-FCA (2.0.0)
36
-
37
- > **A next-generation, high-performance, developer-friendly Facebook Messenger bot framework.**
38
-
39
- ---
40
-
41
- ## πŸš€ What's New in 2.0.3 - Fully Integrated NPM Edition
42
- - **🎯 FULLY INTEGRATED**: Nexus Login System now built directly into main package!
43
- - **οΏ½ NPM COMPATIBLE**: Works perfectly when installed via `npm install nexus-fca`
44
- - **⚑ ZERO CONFIG**: No external folders needed - everything works out of the box
45
- - **οΏ½πŸ” NEXUS LOGIN SYSTEM**: Revolutionary auto-login with appstate generation from username/password
46
- - **πŸ›‘οΈ ULTRA-LOW BAN RATE**: Advanced protection reduces Facebook account suspension risk by 95%+
47
- - **πŸ” 2FA SUPPORT**: Full TOTP integration with Google Authenticator for maximum security
48
- - **⚑ ONE-LINE SETUP**: Complete bot setup with just one line of code
49
- - **πŸ“Š INTELLIGENT MANAGEMENT**: Auto-backup, validation, and appstate lifecycle management
50
- - **πŸ›‘οΈ MAXIMUM SAFETY**: Human-like device simulation with Android fingerprinting
51
- - **πŸ”„ ENHANCED AUTO-RECONNECT**: Smart MQTT connection with safe reconnection patterns
52
-
53
- ## 🎯 Integrated Nexus Login System
54
-
55
- **The most advanced Facebook login system, now fully integrated for NPM usage!**
56
-
57
- ### οΏ½ **NPM Installation**
23
+ ## πŸš€ Install
58
24
  ```bash
59
25
  npm install nexus-fca
60
26
  ```
61
27
 
62
- ### ⚑ **One-Line Bot Setup**
63
- ```javascript
64
- const { nexusLogin } = require('nexus-fca'); // Works directly from npm!
65
-
66
- // Complete bot ready in one line!
67
- const result = await nexusLogin({
68
- username: 'your_email@gmail.com',
69
- password: 'your_password',
70
- twofactor: 'YOUR_2FA_SECRET'
71
- });
72
-
73
- if (result.success) {
74
- // Bot is ready! API available immediately
75
- result.api.sendMessage('Hello World!', result.api.getCurrentUserID());
76
- }
77
- ```
78
-
79
- ### πŸ” **Smart Auto-Detection**
80
- ```javascript
81
- // Will automatically:
82
- // 1. Check for existing appstate
83
- // 2. Use it if valid
84
- // 3. Generate new one if needed
85
- // 4. Start Nexus-FCA with ultra-safe settings
86
-
87
- const result = await nexusLogin(); // No credentials needed if appstate exists!
88
- ```
89
-
90
- ### πŸ›‘οΈ **Maximum Safety Features**
91
- - βœ… **Human-like Android simulation** with real device fingerprints
92
- - βœ… **2FA TOTP auto-generation** from Google Authenticator secrets
93
- - βœ… **Rate limiting & safety delays** to prevent Facebook detection
94
- - βœ… **Automatic appstate backup** and lifecycle management
95
- - βœ… **Session validation** and health monitoring
96
- - βœ… **Error recovery** without triggering security flags
97
-
98
- ### πŸ“š **Quick Start Guide**
99
-
100
- ```
101
-
102
- 2. **Create test file:**
103
- ```javascript
104
- // test-bot.js
105
- const { nexusLogin } = require('nexus-fca');
28
+ ---
29
+ ## ⚑ Quick Start (Appstate)
30
+ ```js
31
+ const login = require('nexus-fca');
106
32
 
107
33
  (async () => {
108
- const result = await nexusLogin({
109
- username: 'your_email@gmail.com',
110
- password: 'your_password'
111
- });
112
-
113
- if (result.success) {
114
- console.log('βœ… Bot ready!');
115
- result.api.sendMessage('Hello from Nexus!', result.api.getCurrentUserID());
116
- }
34
+ const api = await login({ appState: require('./appstate.json') });
35
+ console.log('Logged in as', api.getCurrentUserID());
36
+ api.listen((err, evt) => {
37
+ if (err) return console.error('Listen error:', err);
38
+ if (evt.body) api.sendMessage('Echo: ' + evt.body, evt.threadID);
39
+ });
117
40
  })();
118
41
  ```
119
42
 
120
- 3. **Run your bot:**
121
- ```bash
122
- node test-bot.js
123
- ```
124
-
125
- ### πŸ“– **Complete Documentation**
126
- - **[NPM Integration Guide](npm-integration-guide.md)** - Complete NPM usage guide
127
- - **[Integrated Login Guide](integrated-login-guide.md)** - All login methods
128
- - **[Test Files](test-*.js)** - Ready-to-use test scripts
129
- - **[Legacy Guide](newloginhowtouse.md)** - Previous version docs
130
-
131
- ---
132
-
133
- ## πŸ” Legacy Appstate Support
134
-
135
- Nexus-FCA maintains full backward compatibility with traditional appstate login.
136
-
137
- ### ⚑ Traditional Usage
138
-
139
- ```javascript
43
+ ## πŸ” Quick Start (Credentials + 2FA)
44
+ ```js
140
45
  const login = require('nexus-fca');
141
46
 
142
- login({ appState: require('./appstate.json') }, (err, api) => {
47
+ (async () => {
48
+ const api = await login({
49
+ email: process.env.FB_EMAIL,
50
+ password: process.env.FB_PASS,
51
+ twofactor: process.env.FB_2FA_SECRET // optional
52
+ });
53
+ api.listen((err, msg) => {
143
54
  if (err) return console.error(err);
144
- console.log('βœ… Bot ready with appstate!');
145
- });
55
+ if (msg.body === 'ping') api.sendMessage('pong', msg.threadID);
56
+ });
57
+ })();
146
58
  ```
147
59
 
148
- ### πŸ“š Migration Guide
149
-
150
- - **Existing appstate files work unchanged**
151
- - **New integrated system generates fresh appstate automatically**
152
- - **Mix and match both approaches as needed**
153
-
154
60
  ---
61
+ ## πŸ›‘οΈ Safety Layer (v2.1.0 Improvements)
62
+ | Feature | Benefit |
63
+ |---------|---------|
64
+ | Persistent device profile | Prevents repeated β€œnew device” flags & locks |
65
+ | Smarter session preflight | Eliminates noisy false `not_logged_in` errors |
66
+ | Redirect & HTML detection | Accurate login checkpoint identification |
67
+ | Controlled retries (5xx) | Backoff without hammering endpoints |
68
+ | Human-like delays | Reduces automated pattern detection |
155
69
 
156
- ## πŸ–ΌοΈ Demo
157
-
158
- <div align="center">
159
- <img src="https://i.ibb.co/FbCSF0Pj/Capture.png" alt="Nexus-FCA Demo Screenshot" width="700"/>
160
- </div>
70
+ Disable preflight if needed:
71
+ ```js
72
+ await login({ appState }, { disablePreflight: true });
73
+ ```
161
74
 
162
75
  ---
163
-
164
- ## ✨ Key Features
165
- - **πŸ›‘οΈ Ultra-Low Facebook Account Ban Rate (95%+ Protection)**
166
- - **πŸ” Smart Human-Like Behavior Patterns**
167
- - **οΏ½ Real-time Account Lock/Ban/Checkpoint Prevention**
168
- - **🌐 Advanced Safe MQTT Auto-Reconnect**
169
- - **πŸ“Š Intelligent Safety-Focused Performance Optimization**
170
- - **�️ Proactive Account Health Monitoring & Alerts**
171
- - **πŸ”„ Safe Automatic Token Refresh & Session Management**
172
- - **🌍 Region Protection & Safe Connection Optimization**
173
- - **πŸ“ˆ Professional Safety Analytics & Monitoring**
174
- - **πŸ’» Full TypeScript Support & Modern APIs**
175
- - **πŸ”§ Discord.js-style Objects & Event System**
176
- - **πŸ“ Comprehensive Safety Documentation & Migration Guides**
76
+ ## πŸ›°οΈ MQTT Listener Enhancements
77
+ - Preflight now async & tolerant (second-stage check only logs failure)
78
+ - Classified errors: `login_redirect`, `html_login_page`, `not_logged_in`
79
+ - Automatic cookie/token refresh propagation
177
80
 
178
81
  ---
179
-
180
- ## πŸ“¦ Installation
82
+ ## πŸ“¦ Example Echo Test
83
+ `examples/echo-test.js` (already included):
181
84
  ```bash
182
- npm install nexus-fca
85
+ node examples/echo-test.js
183
86
  ```
87
+ Provide `appstate.json` or set `EMAIL` / `PASSWORD` env variables.
184
88
 
185
89
  ---
90
+ ## 🧠 Advanced Login Flow
91
+ 1. New integrated system safely generates / refreshes cookies (if credentials supplied)
92
+ 2. Legacy core consumes resulting appstate for stable API behavior
93
+ 3. Optional persistent device JSON: `persistent-device.json`
186
94
 
187
- ## πŸ› οΈ Quick Start Example
95
+ Persistent device toggle:
188
96
  ```js
189
- const login = require("nexus-fca");
190
-
191
- login({ appState: require("./appstate.json") }, (err, api) => {
192
- if (err) return console.error("Login error:", err);
193
- api.listenMqtt((err, event) => {
194
- if (err) return console.error("Listen error:", err);
195
- if (event.body && event.threadID) {
196
- api.sendMessage("Echo: " + event.body, event.threadID);
197
- }
198
- });
199
- });
97
+ const { IntegratedNexusLoginSystem } = require('nexus-fca');
98
+ new IntegratedNexusLoginSystem({ persistentDevice: true });
200
99
  ```
201
100
 
202
101
  ---
102
+ ## 🐐 Using Nexus-FCA with GoatBot V2
103
+ Nexus-FCA can act as a drop‑in enhancement for the legacy fb-chat-api layer inside GoatBot V2.
203
104
 
204
- ## πŸ§‘β€πŸ’» Ultra-Safe Login Example (Recommended for Maximum Protection)
105
+ ### Option 1: Non‑invasive (generate fresh appstate)
106
+ 1. In a separate script, run Nexus-FCA credential login (with 2FA if needed):
205
107
  ```js
206
- const { NexusClient } = require('nexus-fca');
207
-
208
- const client = new NexusClient({
209
- prefix: '!',
210
- ultraLowBanMode: true, // NEW: Ultra-low ban rate protection
211
- safeDelays: true, // Human-like timing patterns
212
- performanceOptimization: true,
213
- cachingEnabled: true,
214
- autoReconnect: true,
215
- logLevel: 'info'
216
- });
217
-
218
- client.on('ready', (api, userID) => {
219
- console.log(`πŸ›‘οΈ Login successful with ultra-low ban rate protection!`);
220
- console.log(`πŸ‘€ User ID: ${userID}`);
221
- console.log(`⚑ Smart safety system: ACTIVE`);
222
- console.log(`�️ Account protection level: MAXIMUM`);
223
- });
224
-
225
- client.on('message', async (message) => {
226
- if (message.body === 'ping') await message.reply('πŸ“ Pong!');
227
- });
228
-
229
- // Enhanced safety event listeners
230
- client.on('accountLocked', (details) => {
231
- console.log('🚨 ACCOUNT LOCKED - Emergency shutdown initiated for safety');
232
- process.exit(1);
233
- });
234
-
235
- client.on('checkpointRequired', (details) => {
236
- console.log('⚠️ CHECKPOINT REQUIRED - Manual verification needed');
237
- });
238
-
239
- client.on('riskLevelHigh', (details) => {
240
- console.log('οΏ½ HIGH RISK DETECTED - Automatically applying safety measures');
241
- });
242
-
243
- client.login({ appState: require('./appstate.json') });
108
+ const login = require('nexus-fca');
109
+ (async () => {
110
+ const api = await login({ email: process.env.FB_EMAIL, password: process.env.FB_PASS, twofactor: process.env.FB_2FA });
111
+ const appState = api.getAppState();
112
+ require('fs').writeFileSync('./appstate.json', JSON.stringify(appState, null, 2));
113
+ console.log('Saved appstate.json');
114
+ })();
244
115
  ```
116
+ 2. Configure GoatBot to use that `appstate.json` (no credential scraping needed).
117
+ 3. Repeat only when session truly expires (persistent device reduces frequency).
245
118
 
246
- ---
247
-
248
- ## πŸ—οΈ Advanced Safety Architecture (Ultra-Low Ban Rate System)
249
- - **lib/safety/FacebookSafety.js**: Advanced account protection with 95%+ ban rate reduction
250
- - **lib/safety/SmartSafetyLimiter.js**: Intelligent human-behavior simulation system
251
- - **lib/performance/PerformanceOptimizer.js**: Safety-focused optimization with human-like patterns
252
- - **lib/error/ErrorHandler.js**: Sophisticated error recovery with account protection priority
253
- - **lib/mqtt/AdvancedMqttManager.js**: Enhanced MQTT with safe reconnection patterns
254
- - **lib/compatibility/NexusClient.js**: Modern API with ultra-safety-first design
255
- - **lib/message/Message.js, Thread.js, User.js**: Discord.js-style objects with safety validation
256
- - **lib/database/EnhancedDatabase.js**: High-speed storage optimized for minimal detection risk
119
+ ### Option 2: Replace internal fb-chat-api
120
+ GoatBot has a local `fb-chat-api` folder. To leverage Nexus-FCA improvements globally:
121
+ 1. Install Nexus-FCA inside GoatBot project:
122
+ ```bash
123
+ npm install nexus-fca
124
+ ```
125
+ 2. Rename GoatBot’s original folder for backup:
126
+ ```bash
127
+ mv fb-chat-api fb-chat-api.orig # (Windows: rename manually)
128
+ ```
129
+ 3. Create a shim folder `fb-chat-api/index.js` with:
130
+ ```js
131
+ module.exports = require('nexus-fca');
132
+ ```
133
+ 4. Start GoatBot normally. All calls (`login`, `api.listen`, send methods) now use Nexus-FCA (Promise supported).
257
134
 
258
- ---
135
+ ### Option 3: Direct require patch
136
+ Search GoatBot source for `require("fb-chat-api")` and change to `require("nexus-fca")`.
259
137
 
260
- ## πŸ”„ Easy Integration
138
+ ### Promise usage inside GoatBot scripts
139
+ Replace:
140
+ ```js
141
+ fbapi(loginData, (err, api) => { ... });
142
+ ```
143
+ with:
144
+ ```js
145
+ const login = require('nexus-fca');
146
+ const api = await login(loginData); // supports { appState } or { email, password, twofactor }
147
+ ```
261
148
 
262
- Nexus-FCA is designed as a modern, standalone Facebook Chat API solution:
149
+ ### Recommended settings
150
+ - Keep `persistent-device.json` at project root so repeated restarts reuse the same fingerprint.
151
+ - If GoatBot already performs its own β€œlive cookie check” loops, you can set `{ disablePreflight: true }` to avoid duplicate validation.
152
+ - Handle reconnect events: listen for `error` and `listen` callbacks just like original; classified errors now have `error.type` (`login_redirect`, etc.).
263
153
 
264
- - **Complete API**: All essential Facebook Messenger automation features
265
- - **TypeScript Ready**: Full type definitions and IntelliSense support
266
- - **Zero Configuration**: Works out of the box with sensible defaults
267
- - **Production Ready**: Built for scale with advanced safety and performance optimizations
154
+ ### Minimal integration example
155
+ ```js
156
+ const login = require('nexus-fca');
157
+ (async () => {
158
+ const api = await login({ appState: require('./appstate.json') });
159
+ api.listen(async (err, event) => {
160
+ if (err) return console.error('[Nexus-FCA]', err);
161
+ if (event.body === '!ping') api.sendMessage('pong', event.threadID);
162
+ });
163
+ })();
164
+ ```
268
165
 
269
166
  ---
270
-
271
- ## πŸ“ Advanced Safety Features (Ultra-Low Ban Rate)
272
- - **πŸ›‘οΈ Smart Safety Limiter**: Intelligent human behavior simulation to minimize detection risk
273
- - **⚑ Risk Assessment System**: Real-time analysis of account activity patterns for safety optimization
274
- - **πŸ”„ Human-Like Delays**: Sophisticated timing patterns that mimic natural user behavior
275
- - **🚨 Proactive Safety Alerts**: Early warning system for potential account risks
276
- - **πŸ” Advanced Session Management**: Secure token handling with automatic safety validation
277
- - **🌍 Region Protection**: Advanced techniques to safely bypass restrictions and improve connectivity
278
- - **πŸ“Š Safety Analytics**: Real-time monitoring focused on minimizing ban/lock/checkpoint rates
279
- - **πŸ”§ Intelligent Error Recovery**: Smart error handling that prioritizes account safety over speed
167
+ ## πŸ“š Documentation
168
+ - Full API reference: `DOCS.md`
169
+ - Per-feature guides: `/docs/*.md`
170
+ - Safety: `docs/account-safety.md`
171
+ - Examples: `/examples`
280
172
 
281
173
  ---
174
+ ## πŸ” Updating from 2.0.x β†’ 2.1.0
175
+ | Change | Action |
176
+ |--------|--------|
177
+ | Preflight errors | Noise reduced automatically |
178
+ | Device rotation | Now persistent by default |
179
+ | parseAndCheckLogin | Handles 3xx & HTML login responses |
180
+ | Session validation | New `validateSession` helper |
282
181
 
283
- ## πŸ“š Documentation & Guides
284
- - **Full API Reference**: See [`DOCS.md`](./DOCS.md)
285
- - **Safety Guide**: See [`docs/account-safety.md`](./docs/account-safety.md) for best practices
286
- - **TypeScript Usage**: Complete types in [`index.d.ts`](./index.d.ts)
287
- - **Performance & Error Handling**: See advanced sections in docs
182
+ No breaking API changes.
288
183
 
289
184
  ---
290
-
291
- ## πŸ›‘οΈ Account Safety & Troubleshooting (Ultra-Low Ban Rate Protection)
292
- - **Account Locked/Suspended**: Advanced safety system will detect and immediately stop operations, preventing further issues
293
- - **Checkpoint Required**: Manual verification needed - check Facebook for security prompts while bot automatically pauses
294
- - **Session Expired**: Update your `appstate.json` with fresh cookies from browser using recommended browser extensions
295
- - **MQTT Connection Issues**: Intelligent auto-reconnect system handles temporary disconnections with human-like patterns
296
- - **High Risk Level Detected**: System automatically applies enhanced safety measures and increases delays between actions
297
- - **Performance Issues**: Smart safety delays ensure optimal balance between speed and account protection
298
- - **Memory Issues**: Automatic cleanup and optimization prevent resource leaks while maintaining safety
299
- - **Network Issues**: Enhanced retry logic with safety-first approach handles connectivity problems intelligently
185
+ ## ⚠️ Disclaimer
186
+ This project is not affiliated with Facebook. Use responsibly. You are solely responsible for compliance with platform terms and local laws.
300
187
 
301
188
  ---
302
-
303
- ## πŸ†• Major Update: Nexus Login System (2.0.1)
304
-
305
- ### πŸš€ What’s New?
306
- - **Nexus Login System**: Fully integrated, advanced, and safe Facebook login system under `/nexloginsystem`.
307
- - **ID/Password/2FA Login**: Now you can login directly with your Facebook username, password, and 2FA secret key (Google Authenticator supported).
308
- - **Automatic Appstate Generation**: No need to manually extract cookiesβ€”just provide credentials and get a fresh, safe appstate automatically.
309
- - **Seamless Bot Start**: After login, your bot starts instantly with the generated appstateβ€”no manual steps needed.
310
- - **Ultra-Safe Device Simulation**: Human-like Android device/user-agent simulation for maximum account safety.
311
- - **Auto-Backup & Validation**: Appstate is auto-backed up and validated for every login.
312
- - **Advanced Error Handling**: Smart retry, 2FA fallback, and detailed error messages.
313
- - **Full Documentation**: See `/nexloginsystem/README.md` for usage, API, and safety tips.
314
- - **Test File Included**: Test your login system easily with `/nexloginsystem/test-login.js`.
315
-
316
- ### ⚑ Example Usage
317
- ```js
318
- const { nexusLogin } = require('./nexloginsystem');
319
- const result = await nexusLogin({
320
- username: 'your_email@gmail.com',
321
- password: 'your_password',
322
- twofactor: 'YOUR_2FA_SECRET_KEY'
323
- });
324
- if (result.success) {
325
- // Bot is ready! API available immediately
326
- result.api.sendMessage('Hello World!', result.api.getCurrentUserID());
327
- }
328
- ```
329
-
330
- ### πŸ“š Learn More
331
- - See `/nexloginsystem/README.md` for full API, advanced usage, and safety best practices.
332
- - For 2FA setup, see the guide in the login system docs.
189
+ ## 🀝 Contribute
190
+ PRs for safety, stability, perf, and updated GraphQL doc_ids welcome.
333
191
 
334
192
  ---
193
+ ## πŸ“œ License
194
+ MIT Β© 2025 Nexus-FCA Contributors
package/index.js CHANGED
@@ -380,37 +380,52 @@ class IntegratedNexusLoginSystem {
380
380
  safeMode: options.safeMode !== false,
381
381
  maxRetries: options.maxRetries || 3,
382
382
  retryDelay: options.retryDelay || 5000,
383
+ // New: persistentDevice disables random device rotation
384
+ persistentDevice: options.persistentDevice !== false,
385
+ persistentDeviceFile: options.persistentDeviceFile || path.join(process.cwd(), 'persistent-device.json'),
383
386
  ...options
384
387
  };
385
388
 
386
389
  this.deviceCache = new Map();
387
390
  this.loginAttempts = 0;
388
391
  this.lastLoginTime = 0;
392
+ // New: load previously persisted device if any
393
+ this.fixedDeviceProfile = this.loadPersistentDevice();
389
394
 
390
395
  this.ensureDirectories();
391
396
  this.logger('Login system ready', 'πŸš€');
392
397
  }
393
398
 
394
- logger(message, emoji = 'πŸ“') {
395
- const timestamp = new Date().toLocaleString();
396
- console.log(`${emoji} [${timestamp}] ${message}`);
399
+ loadPersistentDevice() {
400
+ try {
401
+ if (!this.options.persistentDevice) return null;
402
+ if (fs.existsSync(this.options.persistentDeviceFile)) {
403
+ const raw = JSON.parse(fs.readFileSync(this.options.persistentDeviceFile, 'utf8'));
404
+ if (raw && raw.device && raw.deviceId && raw.familyDeviceId && raw.userAgent) {
405
+ this.logger('Loaded persistent device profile', 'πŸ“±');
406
+ return raw;
407
+ }
408
+ }
409
+ } catch (e) {
410
+ this.logger('Failed to load persistent device: ' + e.message, '⚠️');
411
+ }
412
+ return null;
397
413
  }
398
414
 
399
- ensureDirectories() {
400
- const dirs = [
401
- path.dirname(this.options.appstatePath),
402
- path.dirname(this.options.credentialsPath),
403
- this.options.backupPath
404
- ];
405
-
406
- dirs.forEach(dir => {
407
- if (!fs.existsSync(dir)) {
408
- fs.mkdirSync(dir, { recursive: true });
409
- }
410
- });
415
+ savePersistentDevice(profile) {
416
+ if (!this.options.persistentDevice) return;
417
+ try {
418
+ fs.writeFileSync(this.options.persistentDeviceFile, JSON.stringify(profile, null, 2));
419
+ this.logger('Saved persistent device profile', 'πŸ’Ύ');
420
+ } catch (e) {
421
+ this.logger('Failed to save persistent device: ' + e.message, '⚠️');
422
+ }
411
423
  }
412
424
 
413
425
  getRandomDevice() {
426
+ if (this.fixedDeviceProfile) {
427
+ return this.fixedDeviceProfile; // reuse device
428
+ }
414
429
  const devices = [
415
430
  { model: "Pixel 6", build: "SP2A.220505.002", sdk: "30", release: "11" },
416
431
  { model: "Pixel 5", build: "RQ3A.210805.001.A1", sdk: "30", release: "11" },
@@ -420,17 +435,21 @@ class IntegratedNexusLoginSystem {
420
435
  { model: "Pixel 7", build: "TD1A.220804.031", sdk: "33", release: "13" },
421
436
  { model: "Samsung Galaxy S22", build: "S901USQU2AVB3", sdk: "32", release: "12" }
422
437
  ];
423
-
424
438
  const device = devices[Math.floor(Math.random() * devices.length)];
425
439
  const deviceId = this.generateConsistentDeviceId(device);
426
-
427
- return {
440
+ const profile = {
428
441
  userAgent: `Dalvik/2.1.0 (Linux; U; Android ${device.release}; ${device.model} Build/${device.build})`,
429
442
  device,
430
443
  deviceId,
431
444
  familyDeviceId: uuidv4(),
432
445
  androidId: this.generateAndroidId()
433
446
  };
447
+ // Persist first generated device if persistence enabled
448
+ if (this.options.persistentDevice && !this.fixedDeviceProfile) {
449
+ this.fixedDeviceProfile = profile;
450
+ this.savePersistentDevice(profile);
451
+ }
452
+ return profile;
434
453
  }
435
454
 
436
455
  generateConsistentDeviceId(device) {
@@ -640,9 +659,11 @@ class IntegratedNexusLoginSystem {
640
659
  device_info: {
641
660
  model: androidDevice.device.model,
642
661
  user_agent: androidDevice.userAgent,
643
- device_id: androidDevice.deviceId
662
+ device_id: androidDevice.deviceId,
663
+ family_device_id: androidDevice.familyDeviceId
644
664
  },
645
- generated_at: new Date().toISOString()
665
+ generated_at: new Date().toISOString(),
666
+ persistent_device: !!this.options.persistentDevice
646
667
  };
647
668
 
648
669
  this.saveAppstate(appstate, result);
@@ -972,6 +993,17 @@ async function login(loginData, options = {}, callback) {
972
993
  callback = options;
973
994
  options = {};
974
995
  }
996
+ // Add promise wrapper when no callback supplied
997
+ let usePromise = false;
998
+ if (typeof callback !== 'function') {
999
+ usePromise = true;
1000
+ }
1001
+ const promise = usePromise ? new Promise((resolve, reject) => {
1002
+ callback = function (err, api) {
1003
+ if (err) return reject(err);
1004
+ resolve(api);
1005
+ };
1006
+ }) : null;
975
1007
 
976
1008
  // Professional logging
977
1009
  const mainLogger = {
@@ -1002,8 +1034,8 @@ async function login(loginData, options = {}, callback) {
1002
1034
 
1003
1035
  if (!result.success || !result.appstate) {
1004
1036
  mainLogger.error('❌ Authentication failed', result.message);
1005
- if (callback) return callback(new Error(result.message || 'Login failed'));
1006
- throw new Error(result.message || 'Login failed');
1037
+ if (callback) callback(new Error(result.message || 'Login failed'));
1038
+ return usePromise ? promise : undefined;
1007
1039
  }
1008
1040
 
1009
1041
  mainLogger.info('βœ… Session generated successfully');
@@ -1027,7 +1059,7 @@ async function login(loginData, options = {}, callback) {
1027
1059
  ...options
1028
1060
  };
1029
1061
 
1030
- return loginHelper(
1062
+ loginHelper(
1031
1063
  result.appstate, // Use generated appstate
1032
1064
  null, // No email for old system
1033
1065
  null, // No password for old system
@@ -1035,23 +1067,24 @@ async function login(loginData, options = {}, callback) {
1035
1067
  callback,
1036
1068
  null
1037
1069
  );
1070
+ return usePromise ? promise : undefined;
1038
1071
 
1039
1072
  } catch (error) {
1040
1073
  mainLogger.error('πŸ’₯ Login error', error.message);
1041
- if (callback) return callback(error);
1042
- throw error;
1074
+ if (callback) callback(error);
1075
+ return usePromise ? promise : undefined;
1043
1076
  }
1044
1077
  } else {
1045
1078
  // Appstate-only authentication (direct session authentication)
1046
1079
  if (!loginData.appState && !loginData.appstate) {
1047
1080
  const error = new Error('Username and password are required for login, or provide appState for session authentication.');
1048
1081
  mainLogger.error('❌ No credentials provided', 'Either provide ID/password or appstate');
1049
- if (callback) return callback(error);
1050
- throw error;
1082
+ if (callback) callback(error);
1083
+ return usePromise ? promise : undefined;
1051
1084
  }
1052
1085
 
1053
1086
  // Direct session authentication using appstate
1054
- mainLogger.info('οΏ½ Starting session authentication');
1087
+ mainLogger.info('πŸ”„ Starting session authentication');
1055
1088
 
1056
1089
  const globalOptions = {
1057
1090
  selfListen: false,
@@ -1070,7 +1103,7 @@ async function login(loginData, options = {}, callback) {
1070
1103
  ...options
1071
1104
  };
1072
1105
 
1073
- return loginHelper(
1106
+ loginHelper(
1074
1107
  loginData.appState || loginData.appstate,
1075
1108
  null, // No email for appstate login
1076
1109
  null, // No password for appstate login
@@ -1078,6 +1111,7 @@ async function login(loginData, options = {}, callback) {
1078
1111
  callback,
1079
1112
  null
1080
1113
  );
1114
+ return usePromise ? promise : undefined;
1081
1115
  }
1082
1116
  }
1083
1117
 
@@ -53,6 +53,20 @@ class FacebookSafety {
53
53
  riskLevel: 'low'
54
54
  };
55
55
 
56
+ // Track last incoming event time to detect stale / dead connections
57
+ this._lastEventTs = Date.now();
58
+ this._reconnecting = false;
59
+ this._activeListenerStop = null; // store stop function from listenMqtt if we attach
60
+ this._safeRefreshInterval = null; // guard for multiple intervals
61
+ this._safeRefreshTimer = null; // for dynamic timeout pattern
62
+ // New stability / heartbeat fields
63
+ this._heartbeatTimer = null;
64
+ this._watchdogTimer = null;
65
+ this._backoff = { attempt: 0, next: 0 };
66
+ this._destroyed = false;
67
+ this._postRefreshChecks = [];
68
+ this._inFlightRefreshId = 0;
69
+
56
70
  this.initSafety();
57
71
  }
58
72
 
@@ -220,14 +234,29 @@ class FacebookSafety {
220
234
  * Setup safe token refresh intervals
221
235
  */
222
236
  setupSafeRefresh() {
223
- // Refresh tokens every 45 minutes with randomization
224
- const baseInterval = 45 * 60 * 1000; // 45 minutes
225
- const randomVariation = Math.random() * 10 * 60 * 1000; // Β±10 minutes
226
- const interval = baseInterval + randomVariation;
227
-
228
- setInterval(() => {
229
- this.refreshSafeSession();
230
- }, interval);
237
+ // Replace previous interval/timer to avoid stacking
238
+ if (this._safeRefreshInterval) {
239
+ clearInterval(this._safeRefreshInterval);
240
+ this._safeRefreshInterval = null;
241
+ }
242
+ if (this._safeRefreshTimer) {
243
+ clearTimeout(this._safeRefreshTimer);
244
+ this._safeRefreshTimer = null;
245
+ }
246
+ // Use recursive timeout with randomization each cycle (more human-like)
247
+ const schedule = () => {
248
+ if (this._destroyed) return;
249
+ // Adaptive interval: shorter if high risk (to revalidate), longer if stable
250
+ const base = this.sessionMetrics.riskLevel === 'high' ? 25 : this.sessionMetrics.riskLevel === 'medium' ? 35 : 45; // minutes
251
+ const baseInterval = base * 60 * 1000;
252
+ const randomVariation = (Math.random() * 16 - 8) * 60 * 1000; // Β±8 min
253
+ const interval = baseInterval + randomVariation;
254
+ this._safeRefreshTimer = setTimeout(async () => {
255
+ await this.refreshSafeSession();
256
+ schedule();
257
+ }, Math.max(10 * 60 * 1000, interval)); // never below 10 min
258
+ };
259
+ schedule();
231
260
  }
232
261
 
233
262
  /**
@@ -265,18 +294,107 @@ class FacebookSafety {
265
294
  if (isError) {
266
295
  this.sessionMetrics.errorCount++;
267
296
  }
297
+ this._lastEventTs = Date.now();
298
+ }
299
+
300
+ // Expose a method for external caller (e.g., main listener) to update last event timestamp
301
+ recordEvent() {
302
+ this._lastEventTs = Date.now();
303
+ }
304
+
305
+ // Internal helper to ensure MQTT connection stays alive / auto-recover if dead after refresh
306
+ async _ensureMqttAlive() {
307
+ if (!this.api || this._destroyed) return;
308
+ try {
309
+ const disconnected = !this.ctx || !this.ctx.mqttClient || !this.ctx.mqttClient.connected;
310
+ const stale = Date.now() - this._lastEventTs > 5 * 60 * 1000; // >5 min no events
311
+ if (disconnected || stale) {
312
+ await this._reconnectMqttWithBackoff(disconnected ? 'disconnected' : 'stale');
313
+ }
314
+ } catch (_) { /* swallow */ }
315
+ }
316
+
317
+ // Progressive backoff + jitter reconnect
318
+ async _reconnectMqttWithBackoff(reason) {
319
+ if (this._reconnecting || this._destroyed) return;
320
+ this._reconnecting = true;
321
+ try {
322
+ const now = Date.now();
323
+ if (now < this._backoff.next) {
324
+ return; // respect backoff window
325
+ }
326
+ const attempt = ++this._backoff.attempt;
327
+ const baseDelay = Math.min(30000, 1000 * Math.pow(2, Math.min(attempt, 5))); // cap 30s
328
+ const jitter = Math.random() * 400;
329
+ const delay = baseDelay + jitter;
330
+ this._backoff.next = now + delay;
331
+ await new Promise(r => setTimeout(r, delay));
332
+ // Graceful stop old listener
333
+ if (this._activeListenerStop && typeof this._activeListenerStop === 'function') {
334
+ try { this._activeListenerStop(); } catch (_) {}
335
+ }
336
+ if (this.api && typeof this.api.listenMqtt === 'function' && !this._destroyed) {
337
+ const stop = this.api.listenMqtt((err, event) => {
338
+ if (!err && event) this.recordEvent();
339
+ });
340
+ this._activeListenerStop = stop;
341
+ if (attempt > 1) this.safetyEmit('mqttBackoff', { attempt, delay, reason });
342
+ else this.safetyEmit('mqttReconnect', { success: true, reason });
343
+ }
344
+ // Reset backoff on success detection soon after
345
+ setTimeout(() => {
346
+ if (this.ctx && this.ctx.mqttClient && this.ctx.mqttClient.connected) {
347
+ this._backoff.attempt = 0;
348
+ }
349
+ }, 5000);
350
+ } catch (e) {
351
+ this.safetyEmit('mqttReconnect', { success: false, error: e.message });
352
+ } finally {
353
+ this._reconnecting = false;
354
+ }
355
+ }
356
+
357
+ // Heartbeat ping & watchdog
358
+ _startHeartbeat() {
359
+ if (this._heartbeatTimer) clearInterval(this._heartbeatTimer);
360
+ if (this._watchdogTimer) clearInterval(this._watchdogTimer);
361
+ if (this._destroyed) return;
362
+ this._heartbeatTimer = setInterval(() => {
363
+ if (this._destroyed) return;
364
+ try {
365
+ if (this.ctx && this.ctx.mqttClient && this.ctx.mqttClient.connected) {
366
+ if (this.ctx.mqttClient.ping) this.ctx.mqttClient.ping();
367
+ this.safetyEmit('heartbeat', { ts: Date.now() });
368
+ }
369
+ } catch (_) {}
370
+ }, 60 * 1000 + Math.random() * 5000); // 60s Β±5s
371
+ this._watchdogTimer = setInterval(() => {
372
+ if (this._destroyed) return;
373
+ const idle = Date.now() - this._lastEventTs;
374
+ if (idle > 2 * 60 * 1000) { // 2 min no events -> soft check
375
+ this._ensureMqttAlive();
376
+ }
377
+ if (idle > 15 * 60 * 1000) { // 15 min -> force reconnect attempt ignoring backoff
378
+ this._backoff.attempt = 0; // reset to allow immediate
379
+ this._ensureMqttAlive();
380
+ }
381
+ }, 30 * 1000); // watchdog every 30s
268
382
  }
269
383
 
270
384
  /**
271
385
  * Start safety monitoring for session
272
386
  */
273
- startMonitoring(ctx, api) {
387
+ startMonitoring(ctx, api) { // added persistence of ctx/api so refresh can use them
274
388
  if (!ctx || !api) return;
275
-
276
- // Monitor for account issues
277
- setInterval(() => {
389
+ this.ctx = ctx; // persist for later safe refresh
390
+ this.api = api;
391
+ if (this._monitorInterval) clearInterval(this._monitorInterval);
392
+ this._monitorInterval = setInterval(() => {
278
393
  this.checkAccountHealth(ctx, api);
279
- }, 30000); // Check every 30 seconds
394
+ }, 30000);
395
+ // Attach lightweight hook if api emits events to update lastEventTs externally if user wires it
396
+ this.recordEvent();
397
+ this._startHeartbeat();
280
398
  }
281
399
 
282
400
  /**
@@ -290,7 +408,7 @@ class FacebookSafety {
290
408
  const userCookie = cookies.find(c => c.key === 'c_user');
291
409
 
292
410
  if (!userCookie) {
293
- this.emit('accountIssue', {
411
+ this.safetyEmit('accountIssue', {
294
412
  type: 'session_expired',
295
413
  message: 'User session cookie missing'
296
414
  });
@@ -301,7 +419,7 @@ class FacebookSafety {
301
419
 
302
420
  const safetyCheck = this.checkErrorSafety(error);
303
421
  if (!safetyCheck.safe) {
304
- this.emit('accountIssue', {
422
+ this.safetyEmit('accountIssue', {
305
423
  type: safetyCheck.danger,
306
424
  message: error.message,
307
425
  recommendation: safetyCheck.recommendation
@@ -314,8 +432,85 @@ class FacebookSafety {
314
432
  * Refresh session safely
315
433
  */
316
434
  async refreshSafeSession() {
317
- // Implement safe session refresh logic
318
- console.log('πŸ”„ Performing safe session refresh...');
435
+ // Improved safe session refresh implementation
436
+ if (this._refreshing) return; // prevent concurrent refreshes
437
+ this._refreshing = true;
438
+ const refreshId = ++this._inFlightRefreshId;
439
+ const startedAt = Date.now();
440
+ let preMqttConnected = this.ctx && this.ctx.mqttClient && this.ctx.mqttClient.connected;
441
+ let preLastEvent = this._lastEventTs;
442
+ try {
443
+ console.log('πŸ”„ Performing safe session refresh...');
444
+ if (!this.api || typeof this.api.refreshFb_dtsg !== 'function') {
445
+ console.log('⚠️ Safe refresh skipped: api.refreshFb_dtsg not available');
446
+ return;
447
+ }
448
+ // Abort protection if takes too long (network hang)
449
+ const timeoutMs = 25 * 1000;
450
+ const controller = new AbortController();
451
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
452
+ let res;
453
+ try {
454
+ res = await this.api.refreshFb_dtsg({ signal: controller.signal });
455
+ } finally { clearTimeout(timeout); }
456
+ this.sessionMetrics.errorCount = Math.max(0, this.sessionMetrics.errorCount - 1);
457
+ this.sessionMetrics.lastActivity = Date.now();
458
+ this.safetyEmit('safeRefresh', {
459
+ ok: true,
460
+ fb_dtsg: this.ctx && this.ctx.fb_dtsg,
461
+ jazoest: this.ctx && this.ctx.jazoest,
462
+ durationMs: Date.now() - startedAt,
463
+ message: 'Session tokens refreshed'
464
+ });
465
+ // Immediate MQTT health ensure
466
+ await this._ensureMqttAlive();
467
+ // Schedule layered post-refresh checks (1s, 10s, 30s) to catch silent drops
468
+ const checksAt = [1000, 10000, 30000];
469
+ checksAt.forEach(delay => {
470
+ const handle = setTimeout(() => {
471
+ if (this._destroyed) return;
472
+ if (refreshId !== this._inFlightRefreshId) return; // newer refresh superseded
473
+ this._ensureMqttAlive();
474
+ }, delay);
475
+ this._postRefreshChecks.push(handle);
476
+ });
477
+ // If previously connected and now no events for >1 min after refresh -> reconnect
478
+ setTimeout(() => {
479
+ if (this._destroyed) return;
480
+ if (preMqttConnected && Date.now() - Math.max(this._lastEventTs, preLastEvent) > 60 * 1000) {
481
+ this._backoff.attempt = 0; // reset backoff for immediate action
482
+ this._ensureMqttAlive();
483
+ }
484
+ }, 60 * 1000);
485
+ } catch (e) {
486
+ this.recordRequest(true);
487
+ this.safetyEmit('safeRefresh', {
488
+ ok: false,
489
+ error: e.message,
490
+ durationMs: Date.now() - startedAt
491
+ });
492
+ if (this.sessionMetrics.errorCount > 3) {
493
+ this.sessionMetrics.riskLevel = 'high';
494
+ }
495
+ // Force reconnection attempt if refresh failed & potential token invalidation
496
+ this._backoff.attempt = 0;
497
+ await this._ensureMqttAlive();
498
+ } finally {
499
+ this._refreshing = false;
500
+ }
501
+ }
502
+
503
+ // Cleanup / destroy resources (to prevent dangling timers)
504
+ destroy() {
505
+ this._destroyed = true;
506
+ const timers = [this._safeRefreshInterval, this._safeRefreshTimer, this._heartbeatTimer, this._watchdogTimer];
507
+ timers.forEach(t => t && clearTimeout(t));
508
+ if (this._activeListenerStop) {
509
+ try { this._activeListenerStop(); } catch (_) {}
510
+ this._activeListenerStop = null;
511
+ }
512
+ this._postRefreshChecks.forEach(h => clearTimeout(h));
513
+ this._postRefreshChecks = [];
319
514
  }
320
515
 
321
516
  /**
@@ -351,7 +546,7 @@ class FacebookSafety {
351
546
  /**
352
547
  * Emit safety events
353
548
  */
354
- emit(event, data) {
549
+ safetyEmit(event, data) {
355
550
  if (typeof this.onSafetyEvent === 'function') {
356
551
  this.onSafetyEvent(event, data);
357
552
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexus-fca",
3
- "version": "2.0.7",
3
+ "version": "2.1.1",
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": {
package/src/listenMqtt.js CHANGED
@@ -128,6 +128,23 @@ function buildStream(options, WebSocket, Proxy) {
128
128
  return Stream;
129
129
  }
130
130
  function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
131
+ // Improved preflight with option to disable
132
+ if (!ctx.globalOptions.disablePreflight) {
133
+ (async () => {
134
+ try {
135
+ await utils.validateSession(ctx, defaultFuncs, { retries: 2, delayMs: 1000 });
136
+ } catch (e) {
137
+ // Suppress first failure; only emit if still bad after short grace period
138
+ setTimeout(() => {
139
+ utils.validateSession(ctx, defaultFuncs, { retries: 0 }).catch(err2 => {
140
+ log.error("listenMqtt", "Session invalid after retry: Not logged in.");
141
+ ctx.loggedIn = false;
142
+ globalCallback({ type: "not_logged_in", error: "Session invalid (post-retry)." });
143
+ });
144
+ }, 2000);
145
+ }
146
+ })();
147
+ }
131
148
  const chatOn = ctx.globalOptions.online;
132
149
  const foreground = false;
133
150
  const sessionID = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1;
@@ -218,6 +235,12 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
218
235
  mqttClient.on('error', function (err) {
219
236
  log.error("listenMqtt", err);
220
237
  mqttClient.end();
238
+ // classify redirect/login errors surfaced through upstream logic
239
+ const errMsg = (err && (err.error || err.message || "")).toString();
240
+ if (/not logged in|login_redirect|html_login_page/i.test(errMsg)) {
241
+ ctx.loggedIn = false;
242
+ return globalCallback({ type: "not_logged_in", error: errMsg });
243
+ }
221
244
  if (ctx.globalOptions.autoReconnect) {
222
245
  listenMqtt(defaultFuncs, api, ctx, globalCallback);
223
246
  } else {
package/utils.js CHANGED
@@ -989,6 +989,7 @@ function parseAndCheckLogin(ctx, defaultFuncs, retryCount = 0, sourceCall) {
989
989
  return function (data) {
990
990
  return tryPromise(function () {
991
991
  log.verbose("parseAndCheckLogin", data.body);
992
+ // --- Handle HTTP 5xx with bounded retry (existing logic) ---
992
993
  if (data.statusCode >= 500 && data.statusCode < 600) {
993
994
  if (retryCount >= 5) {
994
995
  throw {
@@ -1016,6 +1017,34 @@ function parseAndCheckLogin(ctx, defaultFuncs, retryCount = 0, sourceCall) {
1016
1017
  )
1017
1018
  .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount, sourceCall));
1018
1019
  }
1020
+ // --- New: Explicit 3xx redirect handling (302 login checkpoint, etc.) ---
1021
+ if (data.statusCode >= 300 && data.statusCode < 400) {
1022
+ const location = data.headers && (data.headers.location || data.headers.Location);
1023
+ if (!location) {
1024
+ throw {
1025
+ message: `Redirect (${data.statusCode}) without location header.`,
1026
+ statusCode: data.statusCode,
1027
+ res: data.body,
1028
+ error: "Redirect without location.",
1029
+ sourceCall
1030
+ };
1031
+ }
1032
+ // Detect checkpoint/login redirects explicitly
1033
+ if (/checkpoint|login|recover/i.test(location)) {
1034
+ throw {
1035
+ message: `Redirected to login/checkpoint: ${location}`,
1036
+ statusCode: data.statusCode,
1037
+ location,
1038
+ error: "Not logged in.",
1039
+ type: "login_redirect",
1040
+ res: data.body,
1041
+ sourceCall
1042
+ };
1043
+ }
1044
+ log.warn("parseAndCheckLogin", `Following redirect -> ${location}`);
1045
+ return defaultFuncs.get(location, ctx.jar)
1046
+ .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount, sourceCall));
1047
+ }
1019
1048
  if (data.statusCode !== 200) {
1020
1049
  throw {
1021
1050
  message: `parseAndCheckLogin got status code: ${data.statusCode}.`,
@@ -1026,23 +1055,60 @@ function parseAndCheckLogin(ctx, defaultFuncs, retryCount = 0, sourceCall) {
1026
1055
  };
1027
1056
  }
1028
1057
  let res;
1058
+ let bodyText = data.body || "";
1059
+ // --- New: Detect full HTML (often login page) before JSON parse ---
1060
+ const looksLikeHTML = /<html[\s\S]*<\/html>/i.test(bodyText);
1061
+ if (looksLikeHTML && /login|checkpoint|password|m_faceweb|m\.facebook\.com\/login/i.test(bodyText)) {
1062
+ throw {
1063
+ message: "Received HTML login/checkpoint page instead of JSON (session likely invalid).",
1064
+ statusCode: data.statusCode,
1065
+ res: bodyText.slice(0, 5000),
1066
+ error: "Not logged in.",
1067
+ type: "html_login_page",
1068
+ sourceCall
1069
+ };
1070
+ }
1029
1071
  try {
1030
- res = JSON.parse(makeParsable(data.body));
1072
+ res = JSON.parse(makeParsable(bodyText));
1031
1073
  } catch (e) {
1032
- log.error("JSON parsing failed:", data.body);
1074
+ // Additional heuristic: if body has FB login form markers
1075
+ if (/login_form|checkpointSubmitButton|memorialized/i.test(bodyText)) {
1076
+ throw {
1077
+ message: "Facebook returned login/checkpoint HTML instead of JSON.",
1078
+ detail: e.message,
1079
+ res: bodyText.slice(0, 5000),
1080
+ error: "Not logged in.",
1081
+ type: "html_login_page_parse_fail",
1082
+ sourceCall
1083
+ };
1084
+ }
1085
+ log.error("JSON parsing failed:", bodyText);
1033
1086
  throw {
1034
1087
  message: "Failed to parse JSON response.",
1035
1088
  detail: e.message,
1036
- res: data.body,
1089
+ res: bodyText.slice(0, 5000),
1037
1090
  error: "JSON.parse error.",
1038
1091
  sourceCall
1039
1092
  };
1040
1093
  }
1041
1094
  if (res.redirect && data.request.method === "GET") {
1095
+ // New: classify redirect target
1096
+ if (/checkpoint|login/i.test(res.redirect)) {
1097
+ throw {
1098
+ message: `Redirected to login/checkpoint (JSON redirect): ${res.redirect}`,
1099
+ statusCode: data.statusCode,
1100
+ location: res.redirect,
1101
+ error: "Not logged in.",
1102
+ type: "login_redirect",
1103
+ res,
1104
+ sourceCall
1105
+ };
1106
+ }
1042
1107
  return defaultFuncs
1043
1108
  .get(res.redirect, ctx.jar)
1044
1109
  .then(parseAndCheckLogin(ctx, defaultFuncs, undefined, sourceCall));
1045
1110
  }
1111
+ // --- Existing cookie & token handling logic (unchanged) ---
1046
1112
  if (
1047
1113
  res.jsmods?.require &&
1048
1114
  Array.isArray(res.jsmods.require[0]) &&
@@ -1062,7 +1128,9 @@ function parseAndCheckLogin(ctx, defaultFuncs, retryCount = 0, sourceCall) {
1062
1128
  }
1063
1129
  }
1064
1130
  }
1065
- if (res.error === 1357001) {
1131
+ // --- New: Detect common not-logged-in payload patterns ---
1132
+ if (res.error === 1357001 || res.error === 1357004 || res.errorSummary === "login required") {
1133
+ // 1357001 existing logic below triggers auto_login; keep classification
1066
1134
  if (!ctx.auto_login) {
1067
1135
  ctx.auto_login = true;
1068
1136
  auto_login(success => {
@@ -1484,12 +1552,80 @@ const rateLimiter = {
1484
1552
  }
1485
1553
  };
1486
1554
 
1487
- module.exports.rateLimiter = rateLimiter;
1488
- module.exports.smartSafetyLimiter = smartSafetyLimiter;
1489
- module.exports.safeMode = safeMode;
1490
- module.exports.ultraSafeMode = ultraSafeMode;
1491
- module.exports.isUserAllowed = isUserAllowed;
1555
+ // Add robust session validation utility used by listenMqtt
1556
+ async function validateSession(ctx, defaultFuncs, opts = {}) {
1557
+ const { retries = 0, delayMs = 750 } = opts || {};
1558
+ if (!ctx || !ctx.jar) {
1559
+ throw new CustomError({ message: 'No context/jar provided', type: 'not_logged_in' });
1560
+ }
1561
+ const cookies = ctx.jar.getCookies('https://www.facebook.com');
1562
+ const hasUser = cookies.some(c => (c.key || c.name) === 'c_user');
1563
+ if (!hasUser) {
1564
+ throw new CustomError({ message: 'Not logged in (missing c_user cookie)', type: 'not_logged_in' });
1565
+ }
1566
+
1567
+ const endpoints = [
1568
+ 'https://www.facebook.com/ajax/mercury/threadlist_info.php?client=mercury',
1569
+ 'https://m.facebook.com/me'
1570
+ ];
1571
+
1572
+ function isHtmlLoginPage(body) {
1573
+ if (!body || typeof body !== 'string') return false;
1574
+ if (body.length < 40) return false;
1575
+ const lowered = body.toLowerCase();
1576
+ return (
1577
+ (lowered.includes('login') && lowered.includes('password')) ||
1578
+ lowered.includes('m_login_email') ||
1579
+ lowered.includes('/login/device-based')
1580
+ );
1581
+ }
1582
+
1583
+ for (let attempt = 0; attempt <= retries; attempt++) {
1584
+ let allPassed = true;
1585
+ for (const url of endpoints) {
1586
+ try {
1587
+ // Prefer provided defaultFuncs.get if available (applies defaults & fb_dtsg)
1588
+ const res = defaultFuncs && defaultFuncs.get
1589
+ ? await defaultFuncs.get(url, ctx.jar, {})
1590
+ : await get(url, ctx.jar, null, ctx.globalOptions, ctx);
1591
+
1592
+ const status = res && res.statusCode;
1593
+ const body = res && res.body ? res.body.toString() : '';
1594
+
1595
+ if (status >= 300 && status < 400) {
1596
+ throw new CustomError({ message: 'Login redirect detected', type: 'login_redirect', statusCode: status });
1597
+ }
1598
+ if (status === 0 || status === undefined) {
1599
+ throw new CustomError({ message: 'No status code (network?)', type: 'network_error' });
1600
+ }
1601
+ if (status === 401 || status === 403) {
1602
+ throw new CustomError({ message: 'Unauthorized / forbidden', type: 'not_logged_in', statusCode: status });
1603
+ }
1604
+ if (isHtmlLoginPage(body)) {
1605
+ throw new CustomError({ message: 'HTML login page served', type: 'html_login_page' });
1606
+ }
1607
+ // Basic heuristic: body containing checkpoint indicators
1608
+ if (/checkpoint|review recent login/i.test(body)) {
1609
+ throw new CustomError({ message: 'Checkpoint required', type: 'checkpoint' });
1610
+ }
1611
+ } catch (err) {
1612
+ allPassed = false;
1613
+ if (attempt >= retries) {
1614
+ // Re-throw final classified error (ensure type present)
1615
+ if (err instanceof CustomError) throw err;
1616
+ throw new CustomError({ message: err.message || 'Session invalid', type: err.type || 'not_logged_in', original: err });
1617
+ }
1618
+ break; // break inner loop to retry endpoints
1619
+ }
1620
+ }
1621
+ if (allPassed) return true;
1622
+ if (attempt < retries) await delay(delayMs);
1623
+ }
1624
+ // Fallback (should not reach)
1625
+ throw new CustomError({ message: 'Unknown session validation failure', type: 'not_logged_in' });
1626
+ }
1492
1627
 
1628
+ // Preserve earlier named exports while adding validateSession
1493
1629
  module.exports = {
1494
1630
  CustomError,
1495
1631
  cleanHTML,
@@ -1537,5 +1673,12 @@ module.exports = {
1537
1673
  setProxy,
1538
1674
  checkLiveCookie,
1539
1675
  getAccessFromBusiness,
1540
- getFroms
1676
+ getFroms,
1677
+ validateSession,
1678
+ // Safety & rate limiting exports
1679
+ rateLimiter,
1680
+ smartSafetyLimiter,
1681
+ safeMode,
1682
+ ultraSafeMode,
1683
+ isUserAllowed
1541
1684
  };