sagor-fca 0.0.11 → 0.0.12
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/README.md +502 -0
- package/examples/login-with-cookies.js +102 -0
- package/examples/ping.js +1 -0
- package/examples/verify.js +70 -0
- package/index.js +2 -8
- package/package.json +75 -60
- package/src/{api/action → apis}/addExternalModule.js +8 -9
- package/src/apis/addUserToGroup.js +108 -0
- package/src/apis/changeAdminStatus.js +148 -0
- package/src/apis/changeArchivedStatus.js +61 -0
- package/src/apis/changeAvatar.js +103 -0
- package/src/apis/changeBio.js +69 -0
- package/src/apis/changeBlockedStatus.js +54 -0
- package/src/apis/changeGroupImage.js +136 -0
- package/src/apis/changeThreadColor.js +116 -0
- package/src/apis/changeThreadEmoji.js +53 -0
- package/src/apis/comment.js +207 -0
- package/src/apis/createAITheme.js +129 -0
- package/src/apis/createNewGroup.js +79 -0
- package/src/apis/createPoll.js +73 -0
- package/src/apis/deleteMessage.js +44 -0
- package/src/apis/deleteThread.js +52 -0
- package/src/apis/e2ee.js +17 -0
- package/src/apis/editMessage.js +70 -0
- package/src/apis/emoji.js +124 -0
- package/src/apis/fetchThemeData.js +82 -0
- package/src/apis/follow.js +81 -0
- package/src/apis/forwardMessage.js +52 -0
- package/src/apis/friend.js +243 -0
- package/src/apis/gcmember.js +122 -0
- package/src/apis/gcname.js +123 -0
- package/src/apis/gcrule.js +119 -0
- package/src/apis/getAccess.js +111 -0
- package/src/apis/getBotInfo.js +88 -0
- package/src/apis/getBotInitialData.js +43 -0
- package/src/apis/getFriendsList.js +79 -0
- package/src/apis/getMessage.js +423 -0
- package/src/apis/getTheme.js +95 -0
- package/src/apis/getThemeInfo.js +116 -0
- package/src/apis/getThreadHistory.js +239 -0
- package/src/apis/getThreadInfo.js +267 -0
- package/src/apis/getThreadList.js +232 -0
- package/src/apis/getThreadPictures.js +58 -0
- package/src/apis/getUserID.js +117 -0
- package/src/apis/getUserInfo.js +513 -0
- package/src/{api/users → apis}/getUserInfoV2.js +26 -14
- package/src/apis/handleMessageRequest.js +50 -0
- package/src/apis/httpGet.js +63 -0
- package/src/apis/httpPost.js +89 -0
- package/src/apis/httpPostFormData.js +69 -0
- package/src/apis/listenMqtt.js +1184 -0
- package/src/apis/listenSpeed.js +179 -0
- package/src/apis/logout.js +63 -0
- package/src/apis/markAsDelivered.js +47 -0
- package/src/{api/messaging → apis}/markAsRead.js +26 -19
- package/src/apis/markAsReadAll.js +40 -0
- package/src/apis/markAsSeen.js +70 -0
- package/src/apis/mqttDeltaValue.js +278 -0
- package/src/apis/muteThread.js +45 -0
- package/src/apis/nickname.js +132 -0
- package/src/apis/notes.js +163 -0
- package/src/apis/pinMessage.js +150 -0
- package/src/apis/produceMetaTheme.js +180 -0
- package/src/apis/realtime.js +182 -0
- package/src/apis/removeUserFromGroup.js +117 -0
- package/src/apis/resolvePhotoUrl.js +58 -0
- package/src/apis/searchForThread.js +154 -0
- package/src/apis/sendMessage.js +354 -0
- package/src/apis/sendMessageMqtt.js +249 -0
- package/src/apis/sendTypingIndicator.js +40 -0
- package/src/apis/setMessageReaction.js +27 -0
- package/src/apis/setMessageReactionMqtt.js +61 -0
- package/src/apis/setThreadTheme.js +260 -0
- package/src/apis/setThreadThemeMqtt.js +94 -0
- package/src/apis/share.js +107 -0
- package/src/apis/shareContact.js +66 -0
- package/src/apis/stickers.js +257 -0
- package/src/apis/story.js +181 -0
- package/src/apis/theme.js +233 -0
- package/src/apis/unfriend.js +47 -0
- package/src/apis/unsendMessage.js +17 -0
- package/src/database/appStateBackup.js +189 -0
- package/src/database/models/index.js +44 -76
- package/src/database/models/thread.js +3 -22
- package/src/database/models/user.js +3 -17
- package/src/database/threadData.js +53 -46
- package/src/database/userData.js +38 -46
- package/src/engine/client.js +92 -0
- package/src/engine/models/buildAPI.js +113 -0
- package/src/engine/models/loginHelper.js +480 -0
- package/src/engine/models/setOptions.js +88 -0
- package/src/security/e2ee.js +109 -0
- package/src/types/index.d.ts +498 -0
- package/src/utils/antiSuspension.js +534 -0
- package/src/utils/auth-helpers.js +149 -0
- package/src/utils/autoReLogin.js +240 -0
- package/src/utils/axios.js +369 -0
- package/src/utils/cache.js +54 -0
- package/src/utils/clients.js +279 -0
- package/src/utils/constants.js +402 -15
- package/src/utils/formatters/data/formatAttachment.js +370 -0
- package/src/utils/formatters/data/formatDelta.js +109 -0
- package/src/utils/formatters/index.js +159 -0
- package/src/utils/formatters/value/formatCookie.js +91 -0
- package/src/utils/formatters/value/formatDate.js +36 -0
- package/src/utils/formatters/value/formatID.js +16 -0
- package/src/utils/formatters.js +1369 -0
- package/src/utils/headers.js +219 -99
- package/src/utils/index.js +153 -0
- package/src/utils/monitoring.js +333 -0
- package/src/utils/rateLimiter.js +251 -0
- package/src/utils/tokenRefresh.js +285 -0
- package/src/utils/user-agents.js +238 -0
- package/src/utils/validation.js +157 -0
- package/func/checkUpdate.js +0 -222
- package/func/logAdapter.js +0 -33
- package/func/logger.js +0 -48
- package/index.d.ts +0 -751
- package/module/config.js +0 -40
- package/module/login.js +0 -133
- package/module/loginHelper.js +0 -1296
- package/module/options.js +0 -44
- package/src/api/action/changeAvatar.js +0 -137
- package/src/api/action/changeBio.js +0 -75
- package/src/api/action/enableAutoSaveAppState.js +0 -73
- package/src/api/action/getCurrentUserID.js +0 -7
- package/src/api/action/handleFriendRequest.js +0 -57
- package/src/api/action/logout.js +0 -76
- package/src/api/action/refreshFb_dtsg.js +0 -48
- package/src/api/action/setPostReaction.js +0 -106
- package/src/api/action/unfriend.js +0 -54
- package/src/api/http/httpGet.js +0 -46
- package/src/api/http/httpPost.js +0 -52
- package/src/api/http/postFormData.js +0 -47
- package/src/api/messaging/addUserToGroup.js +0 -68
- package/src/api/messaging/changeAdminStatus.js +0 -126
- package/src/api/messaging/changeArchivedStatus.js +0 -55
- package/src/api/messaging/changeBlockedStatus.js +0 -48
- package/src/api/messaging/changeGroupImage.js +0 -91
- package/src/api/messaging/changeNickname.js +0 -70
- package/src/api/messaging/changeThreadColor.js +0 -79
- package/src/api/messaging/changeThreadEmoji.js +0 -111
- package/src/api/messaging/createNewGroup.js +0 -88
- package/src/api/messaging/createPoll.js +0 -46
- package/src/api/messaging/createThemeAI.js +0 -98
- package/src/api/messaging/deleteMessage.js +0 -136
- package/src/api/messaging/deleteThread.js +0 -56
- package/src/api/messaging/editMessage.js +0 -68
- package/src/api/messaging/forwardAttachment.js +0 -57
- package/src/api/messaging/getEmojiUrl.js +0 -29
- package/src/api/messaging/getFriendsList.js +0 -82
- package/src/api/messaging/getMessage.js +0 -829
- package/src/api/messaging/getThemePictures.js +0 -62
- package/src/api/messaging/handleMessageRequest.js +0 -65
- package/src/api/messaging/markAsDelivered.js +0 -57
- package/src/api/messaging/markAsReadAll.js +0 -49
- package/src/api/messaging/markAsSeen.js +0 -61
- package/src/api/messaging/muteThread.js +0 -50
- package/src/api/messaging/removeUserFromGroup.js +0 -62
- package/src/api/messaging/resolvePhotoUrl.js +0 -43
- package/src/api/messaging/scheduler.js +0 -264
- package/src/api/messaging/searchForThread.js +0 -53
- package/src/api/messaging/sendMessage.js +0 -270
- package/src/api/messaging/sendTypingIndicator.js +0 -74
- package/src/api/messaging/setMessageReaction.js +0 -90
- package/src/api/messaging/setTitle.js +0 -124
- package/src/api/messaging/shareContact.js +0 -49
- package/src/api/messaging/threadColors.js +0 -128
- package/src/api/messaging/unsendMessage.js +0 -81
- package/src/api/messaging/uploadAttachment.js +0 -492
- package/src/api/socket/core/connectMqtt.js +0 -258
- package/src/api/socket/core/emitAuth.js +0 -103
- package/src/api/socket/core/getSeqID.js +0 -320
- package/src/api/socket/core/getTaskResponseData.js +0 -25
- package/src/api/socket/core/parseDelta.js +0 -377
- package/src/api/socket/detail/buildStream.js +0 -215
- package/src/api/socket/detail/constants.js +0 -28
- package/src/api/socket/listenMqtt.js +0 -377
- package/src/api/socket/middleware/index.js +0 -216
- package/src/api/threads/getThreadHistory.js +0 -664
- package/src/api/threads/getThreadInfo.js +0 -296
- package/src/api/threads/getThreadList.js +0 -293
- package/src/api/threads/getThreadPictures.js +0 -78
- package/src/api/users/getUserID.js +0 -65
- package/src/api/users/getUserInfo.js +0 -402
- package/src/core/sendReqMqtt.js +0 -96
- package/src/database/helpers.js +0 -53
- package/src/remote/remoteClient.js +0 -123
- package/src/utils/broadcast.js +0 -51
- package/src/utils/client.js +0 -10
- package/src/utils/cookies.js +0 -68
- package/src/utils/format/attachment.js +0 -357
- package/src/utils/format/cookie.js +0 -9
- package/src/utils/format/date.js +0 -50
- package/src/utils/format/decode.js +0 -44
- package/src/utils/format/delta.js +0 -194
- package/src/utils/format/ids.js +0 -64
- package/src/utils/format/index.js +0 -64
- package/src/utils/format/message.js +0 -88
- package/src/utils/format/presence.js +0 -132
- package/src/utils/format/readTyp.js +0 -44
- package/src/utils/format/thread.js +0 -42
- package/src/utils/format/utils.js +0 -141
- package/src/utils/loginParser/autoLogin.js +0 -125
- package/src/utils/loginParser/helpers.js +0 -43
- package/src/utils/loginParser/index.js +0 -10
- package/src/utils/loginParser/parseAndCheckLogin.js +0 -220
- package/src/utils/loginParser/textUtils.js +0 -28
- package/src/utils/request/client.js +0 -26
- package/src/utils/request/config.js +0 -23
- package/src/utils/request/defaults.js +0 -46
- package/src/utils/request/helpers.js +0 -46
- package/src/utils/request/index.js +0 -17
- package/src/utils/request/methods.js +0 -163
- package/src/utils/request/proxy.js +0 -21
- package/src/utils/request/retry.js +0 -77
- package/src/utils/request/sanitize.js +0 -49
package/README.md
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
# sagor-fca
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/sagor-fca)
|
|
4
|
+
[](https://www.npmjs.com/package/sagor-fca)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
|
|
8
|
+
**sagor-fca** is an advanced Facebook Chat API (FCA) client built for **reliable**, **real-time**, and **modular** interaction with Facebook Messenger.
|
|
9
|
+
|
|
10
|
+
Developed and maintained by **[SaGor](https://github.com/SAGOR-KINGx)**.
|
|
11
|
+
Inspired by **ws3-fca** and **@dongdev/fca-unofficial**
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Documentation
|
|
16
|
+
|
|
17
|
+
- **[Cookie Login Guide](COOKIE_LOGIN.md)** — Authenticate using browser cookies
|
|
18
|
+
- **[Theme Features](THEME_FEATURES.md)** — Comprehensive guide to theme management
|
|
19
|
+
- **[Changelog](CHANGELOG.md)** — Version history and updates
|
|
20
|
+
- **[Examples](examples/)** — Code examples and usage patterns
|
|
21
|
+
|
|
22
|
+
### Support & Issues
|
|
23
|
+
|
|
24
|
+
- GitHub: [https://github.com/SAGOR-KINGx](https://github.com/SAGOR-KINGx)
|
|
25
|
+
- Issues: [https://github.com/SAGOR-KINGx/sagor-fca/issues](https://github.com/SAGOR-KINGx/sagor-fca/issues)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
**Authentication**
|
|
32
|
+
- Cookie array login (`appState`) — the safest method for long-running bots
|
|
33
|
+
- Email/password login with TOTP/2FA support
|
|
34
|
+
- Session fingerprint locking — User-Agent, Sec-Ch-Ua, locale, timezone locked per session to prevent detection
|
|
35
|
+
- AppState auto-backup and restore on restart
|
|
36
|
+
|
|
37
|
+
**Real-time Messaging**
|
|
38
|
+
- MQTT and HTTP messaging with automatic protocol fallback
|
|
39
|
+
- Send text, attachments, stickers, emoji, mentions, and location
|
|
40
|
+
- Message editing, unsend, forward, and delete
|
|
41
|
+
- Message reactions via HTTP and MQTT
|
|
42
|
+
- Pin/unpin messages, list pinned messages
|
|
43
|
+
|
|
44
|
+
**Anti-Suspension System**
|
|
45
|
+
- Circuit breaker — halts activity after repeated suspension signals, resumes after cooldown
|
|
46
|
+
- 60+ suspension signal patterns: checkpoints, spam flags, rate limits, identity verification, policy violations, session expiry, and more
|
|
47
|
+
- Adaptive per-thread delay that increases with session volume
|
|
48
|
+
- Hourly and daily message volume limits with automatic warning pauses
|
|
49
|
+
- Warmup mode for fresh sessions — gradually increases allowed message rate
|
|
50
|
+
- Humanized typing simulation before every send
|
|
51
|
+
- Randomized request intervals and jitter to avoid periodicity detection
|
|
52
|
+
- Session fingerprint locking to maintain consistent browser identity
|
|
53
|
+
- PostSafe guard: detects auth failures and checkpoint responses in real-time
|
|
54
|
+
- MQTT watchdog: detects stale connections and forces clean reconnect
|
|
55
|
+
|
|
56
|
+
**Stability & Reliability**
|
|
57
|
+
- MQTT auto-reconnect with exponential backoff and jitter
|
|
58
|
+
- Auto re-login using refreshed AppState when session expires
|
|
59
|
+
- TokenRefreshManager with randomized intervals to keep sessions alive
|
|
60
|
+
- Sliding-window rate limiter with per-endpoint tracking
|
|
61
|
+
- SQLite-backed thread and user data cache for fast lookups
|
|
62
|
+
|
|
63
|
+
**Thread & Group Management**
|
|
64
|
+
- Get thread info, history, pictures, and lists
|
|
65
|
+
- Create groups, add/remove members, change admin status
|
|
66
|
+
- Update group image, name, color, emoji
|
|
67
|
+
- Archive, mute, delete threads
|
|
68
|
+
- Create polls, manage notes and rules
|
|
69
|
+
- Search threads by name, handle message requests
|
|
70
|
+
|
|
71
|
+
**User & Friends**
|
|
72
|
+
- Get user info (basic and extended), resolve user IDs
|
|
73
|
+
- Get full friends list, send/cancel friend requests, unfriend, block/unblock
|
|
74
|
+
|
|
75
|
+
**Social**
|
|
76
|
+
- Comment on posts, share posts, follow/unfollow users
|
|
77
|
+
|
|
78
|
+
**Themes & Stickers**
|
|
79
|
+
- Browse 90+ Messenger themes, apply themes via MQTT
|
|
80
|
+
- Generate AI-powered themes with text prompts
|
|
81
|
+
- Search stickers, browse packs, add packs, get AI stickers
|
|
82
|
+
|
|
83
|
+
**E2EE (Opt-In)**
|
|
84
|
+
- Application-layer end-to-end encryption for DMs using X25519 + HKDF + AES-256-GCM
|
|
85
|
+
|
|
86
|
+
**Monitoring**
|
|
87
|
+
- `api.getHealthStatus()` — MQTT status, token refresh stats, rate limiter metrics
|
|
88
|
+
- Built-in `ProductionMonitor` for request/error/performance telemetry
|
|
89
|
+
|
|
90
|
+
**Proxy Support**
|
|
91
|
+
- Full proxy support via the `proxy` login option
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Installation
|
|
96
|
+
|
|
97
|
+
> **Requirements:** Node.js v18.0.0 or higher
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install sagor-fca
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Quick Start
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
const fs = require("fs");
|
|
109
|
+
const { login } = require("sagor-fca");
|
|
110
|
+
|
|
111
|
+
const appState = JSON.parse(fs.readFileSync("appstate.json", "utf8"));
|
|
112
|
+
|
|
113
|
+
login({ appState }, {
|
|
114
|
+
online: true,
|
|
115
|
+
listenEvents: true,
|
|
116
|
+
autoMarkRead: true,
|
|
117
|
+
autoReconnect: true,
|
|
118
|
+
simulateTyping: true
|
|
119
|
+
}, (err, api) => {
|
|
120
|
+
if (err) return console.error("Login error:", err);
|
|
121
|
+
|
|
122
|
+
console.log("Logged in as:", api.getCurrentUserID());
|
|
123
|
+
|
|
124
|
+
api.listenMqtt((err, event) => {
|
|
125
|
+
if (err || event.type !== "message" || !event.body) return;
|
|
126
|
+
|
|
127
|
+
if (event.body === "/ping") {
|
|
128
|
+
api.sendMessage("pong!", event.threadID);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Anti-Suspension Configuration
|
|
137
|
+
|
|
138
|
+
The anti-suspension system is active by default. You can tune it through login options:
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
login({ appState }, {
|
|
142
|
+
autoReconnect: true,
|
|
143
|
+
listenEvents: true,
|
|
144
|
+
autoMarkRead: true,
|
|
145
|
+
simulateTyping: true, // humanized typing delays before send
|
|
146
|
+
randomUserAgent: true, // rotate user agent on each session
|
|
147
|
+
persona: "desktop", // "desktop" or "android"
|
|
148
|
+
maxConcurrentRequests: 5, // max parallel HTTP requests
|
|
149
|
+
maxRequestsPerMinute: 50, // sliding-window rate cap
|
|
150
|
+
requestCooldownMs: 60000, // per-endpoint cooldown duration
|
|
151
|
+
errorCacheTtlMs: 300000 // how long to suppress repeated errors
|
|
152
|
+
}, (err, api) => {
|
|
153
|
+
if (err) throw err;
|
|
154
|
+
|
|
155
|
+
// Check anti-suspension and rate limiter status
|
|
156
|
+
console.log(api.getHealthStatus());
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Circuit Breaker
|
|
161
|
+
|
|
162
|
+
The circuit breaker trips automatically after detecting 2 or more suspension signals (checkpoints, spam flags, rate limits, etc.). It pauses all activity for 45 minutes by default.
|
|
163
|
+
|
|
164
|
+
You can also trip or reset it manually:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
const { globalAntiSuspension } = require("sagor-fca/src/utils/antiSuspension");
|
|
168
|
+
|
|
169
|
+
// Manually trip (e.g. after you detect a warning in a response)
|
|
170
|
+
globalAntiSuspension.tripCircuitBreaker("manual_pause", 30 * 60 * 1000); // 30 min
|
|
171
|
+
|
|
172
|
+
// Reset after you've resolved the issue
|
|
173
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
174
|
+
|
|
175
|
+
// Check status
|
|
176
|
+
console.log(globalAntiSuspension.getConfig());
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Warmup Mode
|
|
180
|
+
|
|
181
|
+
Use warmup mode when starting a fresh or recovered session:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
const { globalAntiSuspension } = require("sagor-fca/src/utils/antiSuspension");
|
|
185
|
+
globalAntiSuspension.enableWarmup(); // limits to 25 msg/hour for 20 minutes
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## End-to-End Encryption for DMs (Opt-In)
|
|
191
|
+
|
|
192
|
+
Encrypt and decrypt message bodies in direct chats using X25519 + HKDF + AES-256-GCM.
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
api.e2ee.enable();
|
|
196
|
+
|
|
197
|
+
// Share your bot's public key with the peer
|
|
198
|
+
const botPubKey = api.e2ee.getPublicKey();
|
|
199
|
+
|
|
200
|
+
// Register the peer's public key for a DM thread
|
|
201
|
+
api.e2ee.setPeerKey(threadID, peerPublicKeyBase64);
|
|
202
|
+
|
|
203
|
+
// Messages to that thread are now auto-encrypted on send
|
|
204
|
+
// and auto-decrypted on receive
|
|
205
|
+
api.sendMessage("Top secret message", threadID);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Security Warning
|
|
211
|
+
|
|
212
|
+
`appstate.json` contains your Facebook session and must be treated like a password:
|
|
213
|
+
|
|
214
|
+
- **Never commit `appstate.json` to version control**
|
|
215
|
+
- **Never share your `appstate.json` publicly**
|
|
216
|
+
- Add it to `.gitignore`
|
|
217
|
+
- Use environment variables or a secrets manager in production
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Getting Started — Generate `appstate.json`
|
|
222
|
+
|
|
223
|
+
1. Install a cookie export extension:
|
|
224
|
+
- Chrome/Edge: **C3C FbState** or **CookieEditor**
|
|
225
|
+
- Firefox: **Cookie-Editor**
|
|
226
|
+
|
|
227
|
+
2. Log in to Facebook in your browser
|
|
228
|
+
|
|
229
|
+
3. Export cookies as JSON and save as `appstate.json`:
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
[
|
|
233
|
+
{ "key": "c_user", "value": "your-user-id" },
|
|
234
|
+
{ "key": "xs", "value": "your-xs-value" }
|
|
235
|
+
]
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
4. Use in your bot:
|
|
239
|
+
|
|
240
|
+
```js
|
|
241
|
+
const { login } = require("sagor-fca");
|
|
242
|
+
const appState = require("./appstate.json");
|
|
243
|
+
login({ appState }, {}, (err, api) => { ... });
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
See **[COOKIE_LOGIN.md](COOKIE_LOGIN.md)** for more formats and troubleshooting.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Bot Example with Commands
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
const fs = require("fs");
|
|
254
|
+
const path = require("path");
|
|
255
|
+
const { login } = require("sagor-fca");
|
|
256
|
+
|
|
257
|
+
const appState = JSON.parse(fs.readFileSync("appstate.json", "utf8"));
|
|
258
|
+
|
|
259
|
+
login({ appState }, {
|
|
260
|
+
online: true,
|
|
261
|
+
selfListen: false,
|
|
262
|
+
simulateTyping: true,
|
|
263
|
+
autoReconnect: true
|
|
264
|
+
}, async (err, api) => {
|
|
265
|
+
if (err) return console.error("Login error:", err);
|
|
266
|
+
|
|
267
|
+
console.log("Logged in as:", api.getCurrentUserID());
|
|
268
|
+
|
|
269
|
+
const commandsDir = path.join(__dirname, "commands");
|
|
270
|
+
const commands = new Map();
|
|
271
|
+
|
|
272
|
+
if (fs.existsSync(commandsDir)) {
|
|
273
|
+
for (const file of fs.readdirSync(commandsDir).filter(f => f.endsWith(".js"))) {
|
|
274
|
+
const cmd = require(path.join(commandsDir, file));
|
|
275
|
+
if (cmd.name && typeof cmd.execute === "function") {
|
|
276
|
+
commands.set(cmd.name, cmd);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
api.listenMqtt(async (err, event) => {
|
|
282
|
+
if (err || event.type !== "message" || !event.body) return;
|
|
283
|
+
|
|
284
|
+
const prefix = "/";
|
|
285
|
+
if (!event.body.startsWith(prefix)) return;
|
|
286
|
+
|
|
287
|
+
const args = event.body.slice(prefix.length).trim().split(/ +/);
|
|
288
|
+
const name = args.shift().toLowerCase();
|
|
289
|
+
const cmd = commands.get(name);
|
|
290
|
+
if (!cmd) return;
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
await cmd.execute({ api, event, args });
|
|
294
|
+
} catch (e) {
|
|
295
|
+
console.error(`Error in /${name}:`, e.message);
|
|
296
|
+
api.sendMessage("An error occurred.", event.threadID);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## AI Themes
|
|
305
|
+
|
|
306
|
+
```js
|
|
307
|
+
// Generate an AI theme from a text prompt
|
|
308
|
+
const aiThemes = await api.createAITheme("vibrant ocean sunset purple");
|
|
309
|
+
if (aiThemes && aiThemes.length > 0) {
|
|
310
|
+
await api.setThreadThemeMqtt(threadID, aiThemes[0].id);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Browse standard themes
|
|
314
|
+
const themes = await api.getTheme(threadID);
|
|
315
|
+
await api.setThreadThemeMqtt(threadID, themes[0].id);
|
|
316
|
+
|
|
317
|
+
// Check current theme
|
|
318
|
+
const info = await api.getThemeInfo(threadID);
|
|
319
|
+
console.log(info.color, info.emoji);
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## API Reference
|
|
325
|
+
|
|
326
|
+
### Authentication
|
|
327
|
+
| Method | Description |
|
|
328
|
+
|---|---|
|
|
329
|
+
| `login(credentials, options, callback)` | Log in and receive the API object |
|
|
330
|
+
| `api.logout()` | End the session |
|
|
331
|
+
| `api.getAppState()` | Get current session cookies |
|
|
332
|
+
| `api.getCurrentUserID()` | Get logged-in user ID |
|
|
333
|
+
|
|
334
|
+
### Messaging
|
|
335
|
+
| Method | Description |
|
|
336
|
+
|---|---|
|
|
337
|
+
| `api.sendMessage(msg, threadID)` | Send (HTTP + MQTT fallback) |
|
|
338
|
+
| `api.sendMessageMqtt(msg, threadID)` | Send over MQTT |
|
|
339
|
+
| `api.editMessage(text, messageID)` | Edit a message |
|
|
340
|
+
| `api.unsendMessage(messageID, threadID)` | Retract a message |
|
|
341
|
+
| `api.forwardMessage(messageID, threadID)` | Forward a message |
|
|
342
|
+
| `api.deleteMessage(messageIDs)` | Delete locally |
|
|
343
|
+
| `api.shareContact(senderID, threadID)` | Share a contact card |
|
|
344
|
+
|
|
345
|
+
### Reactions & Status
|
|
346
|
+
| Method | Description |
|
|
347
|
+
|---|---|
|
|
348
|
+
| `api.setMessageReaction(reaction, messageID)` | React via HTTP |
|
|
349
|
+
| `api.setMessageReactionMqtt(reaction, messageID, threadID)` | React via MQTT |
|
|
350
|
+
| `api.sendTypingIndicator(isTyping, threadID)` | Show/hide typing |
|
|
351
|
+
| `api.markAsRead(threadID)` | Mark thread as read |
|
|
352
|
+
| `api.markAsReadAll()` | Mark all threads as read |
|
|
353
|
+
| `api.markAsSeen()` | Mark as seen |
|
|
354
|
+
| `api.markAsDelivered(threadID, messageID)` | Mark as delivered |
|
|
355
|
+
|
|
356
|
+
### Threads
|
|
357
|
+
| Method | Description |
|
|
358
|
+
|---|---|
|
|
359
|
+
| `api.getThreadInfo(threadID)` | Thread metadata |
|
|
360
|
+
| `api.getThreadList(limit, timestamp, tags)` | List threads |
|
|
361
|
+
| `api.getThreadHistory(threadID, amount, timestamp)` | Message history |
|
|
362
|
+
| `api.getThreadPictures(threadID, offset, limit)` | Thread images |
|
|
363
|
+
| `api.searchForThread(name)` | Search by name |
|
|
364
|
+
| `api.createNewGroup(participantIDs, name?)` | Create group |
|
|
365
|
+
| `api.deleteThread(threadID)` | Delete thread |
|
|
366
|
+
| `api.muteThread(threadID, muteSeconds)` | Mute thread |
|
|
367
|
+
| `api.changeArchivedStatus(threadID, archive)` | Archive/unarchive |
|
|
368
|
+
| `api.pinMessage(action, threadID, messageID?)` | Pin/unpin/list |
|
|
369
|
+
| `api.createPoll(title, threadID, options?)` | Create poll |
|
|
370
|
+
| `api.handleMessageRequest(threadID, accept)` | Accept/decline |
|
|
371
|
+
|
|
372
|
+
### Group Admin
|
|
373
|
+
| Method | Description |
|
|
374
|
+
|---|---|
|
|
375
|
+
| `api.addUserToGroup(userID, threadID)` | Add member |
|
|
376
|
+
| `api.removeUserFromGroup(userID, threadID)` | Remove member |
|
|
377
|
+
| `api.changeAdminStatus(threadID, userID, isAdmin)` | Promote/demote |
|
|
378
|
+
| `api.changeGroupImage(image, threadID)` | Group photo |
|
|
379
|
+
| `api.gcname(name, threadID)` | Rename group |
|
|
380
|
+
|
|
381
|
+
### Users
|
|
382
|
+
| Method | Description |
|
|
383
|
+
|---|---|
|
|
384
|
+
| `api.getUserInfo(id)` | Basic user info |
|
|
385
|
+
| `api.getUserInfoV2(id)` | Extended user info |
|
|
386
|
+
| `api.getUserID(name)` | Resolve name to ID |
|
|
387
|
+
| `api.getFriendsList()` | Friends list |
|
|
388
|
+
| `api.getBotInfo()` | Bot account info |
|
|
389
|
+
|
|
390
|
+
### Themes & Customization
|
|
391
|
+
| Method | Description |
|
|
392
|
+
|---|---|
|
|
393
|
+
| `api.getTheme(threadID)` | List available themes |
|
|
394
|
+
| `api.getThemeInfo(threadID)` | Current theme |
|
|
395
|
+
| `api.setThreadThemeMqtt(threadID, themeID)` | Apply theme |
|
|
396
|
+
| `api.createAITheme(prompt)` | AI theme |
|
|
397
|
+
| `api.changeThreadColor(color, threadID)` | Thread color |
|
|
398
|
+
| `api.changeThreadEmoji(emoji, threadID)` | Thread emoji |
|
|
399
|
+
| `api.nickname(nickname, threadID, participantID)` | Set nickname |
|
|
400
|
+
| `api.emoji(emoji, threadID)` | Thread emoji shorthand |
|
|
401
|
+
|
|
402
|
+
### Stickers
|
|
403
|
+
| Method | Description |
|
|
404
|
+
|---|---|
|
|
405
|
+
| `api.stickers.search(query)` | Search stickers |
|
|
406
|
+
| `api.stickers.listPacks()` | Installed packs |
|
|
407
|
+
| `api.stickers.getStorePacks()` | Sticker store |
|
|
408
|
+
| `api.stickers.addPack(packID)` | Add pack |
|
|
409
|
+
| `api.stickers.getStickersInPack(packID)` | Stickers in pack |
|
|
410
|
+
| `api.stickers.getAiStickers(options?)` | AI stickers |
|
|
411
|
+
|
|
412
|
+
### E2EE
|
|
413
|
+
| Method | Description |
|
|
414
|
+
|---|---|
|
|
415
|
+
| `api.e2ee.enable()` | Enable E2EE |
|
|
416
|
+
| `api.e2ee.disable()` | Disable E2EE |
|
|
417
|
+
| `api.e2ee.getPublicKey()` | Get public key |
|
|
418
|
+
| `api.e2ee.setPeerKey(threadID, key)` | Set peer key |
|
|
419
|
+
| `api.e2ee.hasPeer(threadID)` | Has peer key |
|
|
420
|
+
| `api.e2ee.clearPeerKey(threadID)` | Remove peer key |
|
|
421
|
+
|
|
422
|
+
### Social
|
|
423
|
+
| Method | Description |
|
|
424
|
+
|---|---|
|
|
425
|
+
| `api.comment(msg, postID)` | Comment on post |
|
|
426
|
+
| `api.share(postID)` | Share post |
|
|
427
|
+
| `api.follow(userID, follow)` | Follow/unfollow |
|
|
428
|
+
| `api.unfriend(userID)` | Unfriend |
|
|
429
|
+
| `api.changeBlockedStatus(userID, block)` | Block/unblock |
|
|
430
|
+
|
|
431
|
+
### Health
|
|
432
|
+
| Method | Description |
|
|
433
|
+
|---|---|
|
|
434
|
+
| `api.getHealthStatus()` | MQTT, token, rate limiter stats |
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Login Options
|
|
439
|
+
|
|
440
|
+
| Option | Type | Default | Description |
|
|
441
|
+
|---|---|---|---|
|
|
442
|
+
| `online` | `boolean` | `true` | Appear online |
|
|
443
|
+
| `selfListen` | `boolean` | `false` | Receive own messages |
|
|
444
|
+
| `listenEvents` | `boolean` | `true` | Receive thread events |
|
|
445
|
+
| `listenTyping` | `boolean` | `false` | Receive typing events |
|
|
446
|
+
| `updatePresence` | `boolean` | `false` | Broadcast presence |
|
|
447
|
+
| `autoMarkDelivery` | `boolean` | `false` | Auto-mark delivered |
|
|
448
|
+
| `autoMarkRead` | `boolean` | `true` | Auto-mark read |
|
|
449
|
+
| `autoReconnect` | `boolean` | `true` | MQTT auto-reconnect |
|
|
450
|
+
| `simulateTyping` | `boolean` | `true` | Humanized typing delays |
|
|
451
|
+
| `randomUserAgent` | `boolean` | `false` | Random User-Agent |
|
|
452
|
+
| `persona` | `"desktop"\|"android"` | `"desktop"` | Browser persona |
|
|
453
|
+
| `proxy` | `string` | — | Proxy URL |
|
|
454
|
+
| `forceLogin` | `boolean` | `false` | Force fresh login |
|
|
455
|
+
| `maxConcurrentRequests` | `number` | `5` | Max parallel requests |
|
|
456
|
+
| `maxRequestsPerMinute` | `number` | `50` | Rate cap per minute |
|
|
457
|
+
| `requestCooldownMs` | `number` | `60000` | Endpoint cooldown |
|
|
458
|
+
| `errorCacheTtlMs` | `number` | `300000` | Error suppression TTL |
|
|
459
|
+
| `stealthMode` | `boolean` | `false` | Extra stealth headers |
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Examples
|
|
464
|
+
|
|
465
|
+
See the **[examples/](examples/)** directory:
|
|
466
|
+
- `simple-bot.js` — Basic bot setup and message handling
|
|
467
|
+
- `theme-usage-example.js` — Theme management
|
|
468
|
+
- `test-bot.js` — Full-featured test bot
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Publishing
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
npm pack --dry-run
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## Credits
|
|
481
|
+
|
|
482
|
+
- **Developed and maintained by [SaGor](https://github.com/SAGOR-KINGx)**
|
|
483
|
+
- **SaGor Team** — development, maintenance, and feature contributions
|
|
484
|
+
- **Inspired by ws3-fca** — by @NethWs3Dev and @CommunityExocore
|
|
485
|
+
|
|
486
|
+
> Copyright (c) 2026 SaGor
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## License
|
|
491
|
+
|
|
492
|
+
**MIT** — Free to use, modify, and distribute. Attribution appreciated.
|
|
493
|
+
|
|
494
|
+
See [LICENSE](LICENSE) for full license text.
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## Links
|
|
499
|
+
|
|
500
|
+
- **npm:** [https://www.npmjs.com/package/sagor-fca](https://www.npmjs.com/package/sagor-fca)
|
|
501
|
+
- **GitHub:** [https://github.com/SAGOR-KINGx](https://github.com/SAGOR-KINGx)
|
|
502
|
+
- **Issues:** [https://github.com/SAGOR-KINGx/sagor-fca/issues](https://github.com/SAGOR-KINGx/sagor-fca/issues)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example: Login with Cookie Array
|
|
6
|
+
*
|
|
7
|
+
* This demonstrates how to login to Facebook Chat API using a cookie array
|
|
8
|
+
* instead of email/password credentials.
|
|
9
|
+
*
|
|
10
|
+
* Cookie Format:
|
|
11
|
+
* - Array of objects with 'name' (or 'key') and 'value' properties
|
|
12
|
+
* - Extracted from browser cookies or previous session
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const login = require('../index.js');
|
|
16
|
+
|
|
17
|
+
// Method 1: Cookie Array with 'name' property
|
|
18
|
+
const cookieArray = [
|
|
19
|
+
{
|
|
20
|
+
name: 'c_user',
|
|
21
|
+
value: 'YOUR_USER_ID_HERE'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'xs',
|
|
25
|
+
value: 'YOUR_XS_TOKEN_HERE'
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'fr',
|
|
29
|
+
value: 'YOUR_FR_TOKEN_HERE'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'datr',
|
|
33
|
+
value: 'YOUR_DATR_TOKEN_HERE'
|
|
34
|
+
}
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
// Method 2: Cookie Array with 'key' property (alternative)
|
|
38
|
+
const cookieArrayAlt = [
|
|
39
|
+
{
|
|
40
|
+
key: 'c_user',
|
|
41
|
+
value: 'YOUR_USER_ID_HERE'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 'xs',
|
|
45
|
+
value: 'YOUR_XS_TOKEN_HERE'
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// Method 3: Cookie String format (semicolon-separated)
|
|
50
|
+
const cookieString = 'c_user=YOUR_USER_ID_HERE; xs=YOUR_XS_TOKEN_HERE; fr=YOUR_FR_TOKEN_HERE; datr=YOUR_DATR_TOKEN_HERE';
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Login using cookie array
|
|
54
|
+
*/
|
|
55
|
+
async function loginWithCookies() {
|
|
56
|
+
try {
|
|
57
|
+
const api = await login.login({
|
|
58
|
+
appState: cookieArray // Pass the cookie array here
|
|
59
|
+
}, {
|
|
60
|
+
logging: true,
|
|
61
|
+
listenEvents: true,
|
|
62
|
+
autoMarkRead: true,
|
|
63
|
+
selfListen: false
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log('✓ Successfully logged in using cookies!');
|
|
67
|
+
console.log('✓ User ID:', api.getCurrentUserID());
|
|
68
|
+
|
|
69
|
+
// Now you can use the API normally
|
|
70
|
+
// Example: Send a message
|
|
71
|
+
// api.sendMessage("Hello World!", threadID);
|
|
72
|
+
|
|
73
|
+
// Clean up
|
|
74
|
+
api.stopListening();
|
|
75
|
+
process.exit(0);
|
|
76
|
+
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('✗ Login failed:', error.message);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* How to extract cookies from your browser:
|
|
85
|
+
*
|
|
86
|
+
* 1. Open Facebook in your browser
|
|
87
|
+
* 2. Open Developer Tools (F12)
|
|
88
|
+
* 3. Go to Application → Cookies → facebook.com
|
|
89
|
+
* 4. Copy the critical cookies:
|
|
90
|
+
* - c_user: Your user ID
|
|
91
|
+
* - xs: Session token
|
|
92
|
+
* - fr: Fraud detection
|
|
93
|
+
* - datr: Device fingerprint
|
|
94
|
+
*
|
|
95
|
+
* 5. Replace the values in cookieArray above
|
|
96
|
+
* 6. Run: node examples/login-with-cookies.js
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
// Uncomment to run:
|
|
100
|
+
// loginWithCookies();
|
|
101
|
+
|
|
102
|
+
module.exports = { loginWithCookies, cookieArray };
|
package/examples/ping.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log('FCA Ping Example');
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Quick sanity check — verifies the library loads correctly and
|
|
6
|
+
* prints the anti-suspension configuration. Run with:
|
|
7
|
+
* node examples/verify.js
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fca = require('../index.js');
|
|
11
|
+
const { globalAntiSuspension } = require('../src/utils/antiSuspension');
|
|
12
|
+
const { globalRateLimiter } = require('../src/utils/rateLimiter');
|
|
13
|
+
|
|
14
|
+
console.log('dhoner-fca Library Verification');
|
|
15
|
+
console.log('================================\n');
|
|
16
|
+
|
|
17
|
+
console.log('Library entry point:', typeof fca.login === 'function' ? 'OK' : 'FAIL');
|
|
18
|
+
|
|
19
|
+
const config = globalAntiSuspension.getConfig();
|
|
20
|
+
console.log('\nAnti-Suspension Configuration:');
|
|
21
|
+
console.log(` Message Delay : ${config.messageDelayMs}ms`);
|
|
22
|
+
console.log(` Thread Delay : ${config.threadDelayMs}ms`);
|
|
23
|
+
console.log(` Max Login Tries : ${config.maxLoginAttempts}`);
|
|
24
|
+
console.log(` Login Cooldown : ${config.loginCooldownMs}ms`);
|
|
25
|
+
console.log(` Daily Msg Limit : ${config.dailyStats.maxDailyMessages}`);
|
|
26
|
+
console.log(` Hourly Msg Limit : ${config.hourlyStats.maxPerHour}`);
|
|
27
|
+
|
|
28
|
+
console.log('\nEnabled Features:');
|
|
29
|
+
Object.entries(config.features).forEach(([feature, enabled]) => {
|
|
30
|
+
console.log(` ${enabled ? '[x]' : '[ ]'} ${feature}`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const activityPattern = globalAntiSuspension.getRealisticActivityPattern();
|
|
34
|
+
console.log('\nActivity Pattern:');
|
|
35
|
+
console.log(` Current activity : ${activityPattern.messageFrequency}`);
|
|
36
|
+
console.log(` Next action delay : ${activityPattern.nextActionDelayMs.toFixed(0)}ms`);
|
|
37
|
+
console.log(` Is active hours : ${activityPattern.isActiveHours}`);
|
|
38
|
+
|
|
39
|
+
console.log('\nCircuit Breaker:');
|
|
40
|
+
console.log(` Tripped : ${globalAntiSuspension.isCircuitBreakerTripped()}`);
|
|
41
|
+
console.log(` Signal count : ${globalAntiSuspension.suspensionCircuitBreaker.signalCount}`);
|
|
42
|
+
|
|
43
|
+
const rateLimiterStats = globalRateLimiter.getStats();
|
|
44
|
+
console.log('\nRate Limiter:');
|
|
45
|
+
console.log(` Max concurrent : ${rateLimiterStats.maxConcurrentRequests}`);
|
|
46
|
+
console.log(` Max per minute : ${rateLimiterStats.maxRequestsPerMinute}`);
|
|
47
|
+
console.log(` Requests (1 min) : ${rateLimiterStats.requestsInLastMinute}`);
|
|
48
|
+
|
|
49
|
+
// Test suspension signal detection
|
|
50
|
+
const testSignals = [
|
|
51
|
+
{ text: 'Everything is fine, message sent', expectSuspicion: false },
|
|
52
|
+
{ text: 'Your account has been suspended due to policy violation', expectSuspicion: true },
|
|
53
|
+
{ text: 'checkpoint required to verify identity', expectSuspicion: true },
|
|
54
|
+
{ text: 'Too many requests - rate limited', expectSuspicion: true },
|
|
55
|
+
{ text: 'Unusual activity detected on your account', expectSuspicion: true },
|
|
56
|
+
];
|
|
57
|
+
console.log('\nSuspension Signal Detection:');
|
|
58
|
+
testSignals.forEach(({ text, expectSuspicion }) => {
|
|
59
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
60
|
+
const detected = globalAntiSuspension.detectSuspensionSignal(text);
|
|
61
|
+
const passed = detected === expectSuspicion;
|
|
62
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
63
|
+
console.log(` ${passed ? '[x]' : '[!]'} "${text.substring(0, 40)}" → ${detected ? 'SUSPICIOUS' : 'CLEAN'}`);
|
|
64
|
+
});
|
|
65
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
66
|
+
|
|
67
|
+
console.log('\nAll checks passed. Library is ready to use.');
|
|
68
|
+
console.log('============================\n');
|
|
69
|
+
|
|
70
|
+
process.exit(0);
|
package/index.js
CHANGED
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// CommonJS default export
|
|
4
|
-
module.exports = login;
|
|
5
|
-
// Support require('{ login }') named import pattern
|
|
6
|
-
module.exports.login = login;
|
|
7
|
-
// Support ESM default import interop
|
|
8
|
-
module.exports.default = login;
|
|
1
|
+
"use strict";
|
|
2
|
+
module.exports = require('./src/engine/client');
|