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.
Files changed (217) hide show
  1. package/README.md +502 -0
  2. package/examples/login-with-cookies.js +102 -0
  3. package/examples/ping.js +1 -0
  4. package/examples/verify.js +70 -0
  5. package/index.js +2 -8
  6. package/package.json +75 -60
  7. package/src/{api/action → apis}/addExternalModule.js +8 -9
  8. package/src/apis/addUserToGroup.js +108 -0
  9. package/src/apis/changeAdminStatus.js +148 -0
  10. package/src/apis/changeArchivedStatus.js +61 -0
  11. package/src/apis/changeAvatar.js +103 -0
  12. package/src/apis/changeBio.js +69 -0
  13. package/src/apis/changeBlockedStatus.js +54 -0
  14. package/src/apis/changeGroupImage.js +136 -0
  15. package/src/apis/changeThreadColor.js +116 -0
  16. package/src/apis/changeThreadEmoji.js +53 -0
  17. package/src/apis/comment.js +207 -0
  18. package/src/apis/createAITheme.js +129 -0
  19. package/src/apis/createNewGroup.js +79 -0
  20. package/src/apis/createPoll.js +73 -0
  21. package/src/apis/deleteMessage.js +44 -0
  22. package/src/apis/deleteThread.js +52 -0
  23. package/src/apis/e2ee.js +17 -0
  24. package/src/apis/editMessage.js +70 -0
  25. package/src/apis/emoji.js +124 -0
  26. package/src/apis/fetchThemeData.js +82 -0
  27. package/src/apis/follow.js +81 -0
  28. package/src/apis/forwardMessage.js +52 -0
  29. package/src/apis/friend.js +243 -0
  30. package/src/apis/gcmember.js +122 -0
  31. package/src/apis/gcname.js +123 -0
  32. package/src/apis/gcrule.js +119 -0
  33. package/src/apis/getAccess.js +111 -0
  34. package/src/apis/getBotInfo.js +88 -0
  35. package/src/apis/getBotInitialData.js +43 -0
  36. package/src/apis/getFriendsList.js +79 -0
  37. package/src/apis/getMessage.js +423 -0
  38. package/src/apis/getTheme.js +95 -0
  39. package/src/apis/getThemeInfo.js +116 -0
  40. package/src/apis/getThreadHistory.js +239 -0
  41. package/src/apis/getThreadInfo.js +267 -0
  42. package/src/apis/getThreadList.js +232 -0
  43. package/src/apis/getThreadPictures.js +58 -0
  44. package/src/apis/getUserID.js +117 -0
  45. package/src/apis/getUserInfo.js +513 -0
  46. package/src/{api/users → apis}/getUserInfoV2.js +26 -14
  47. package/src/apis/handleMessageRequest.js +50 -0
  48. package/src/apis/httpGet.js +63 -0
  49. package/src/apis/httpPost.js +89 -0
  50. package/src/apis/httpPostFormData.js +69 -0
  51. package/src/apis/listenMqtt.js +1184 -0
  52. package/src/apis/listenSpeed.js +179 -0
  53. package/src/apis/logout.js +63 -0
  54. package/src/apis/markAsDelivered.js +47 -0
  55. package/src/{api/messaging → apis}/markAsRead.js +26 -19
  56. package/src/apis/markAsReadAll.js +40 -0
  57. package/src/apis/markAsSeen.js +70 -0
  58. package/src/apis/mqttDeltaValue.js +278 -0
  59. package/src/apis/muteThread.js +45 -0
  60. package/src/apis/nickname.js +132 -0
  61. package/src/apis/notes.js +163 -0
  62. package/src/apis/pinMessage.js +150 -0
  63. package/src/apis/produceMetaTheme.js +180 -0
  64. package/src/apis/realtime.js +182 -0
  65. package/src/apis/removeUserFromGroup.js +117 -0
  66. package/src/apis/resolvePhotoUrl.js +58 -0
  67. package/src/apis/searchForThread.js +154 -0
  68. package/src/apis/sendMessage.js +354 -0
  69. package/src/apis/sendMessageMqtt.js +249 -0
  70. package/src/apis/sendTypingIndicator.js +40 -0
  71. package/src/apis/setMessageReaction.js +27 -0
  72. package/src/apis/setMessageReactionMqtt.js +61 -0
  73. package/src/apis/setThreadTheme.js +260 -0
  74. package/src/apis/setThreadThemeMqtt.js +94 -0
  75. package/src/apis/share.js +107 -0
  76. package/src/apis/shareContact.js +66 -0
  77. package/src/apis/stickers.js +257 -0
  78. package/src/apis/story.js +181 -0
  79. package/src/apis/theme.js +233 -0
  80. package/src/apis/unfriend.js +47 -0
  81. package/src/apis/unsendMessage.js +17 -0
  82. package/src/database/appStateBackup.js +189 -0
  83. package/src/database/models/index.js +44 -76
  84. package/src/database/models/thread.js +3 -22
  85. package/src/database/models/user.js +3 -17
  86. package/src/database/threadData.js +53 -46
  87. package/src/database/userData.js +38 -46
  88. package/src/engine/client.js +92 -0
  89. package/src/engine/models/buildAPI.js +113 -0
  90. package/src/engine/models/loginHelper.js +480 -0
  91. package/src/engine/models/setOptions.js +88 -0
  92. package/src/security/e2ee.js +109 -0
  93. package/src/types/index.d.ts +498 -0
  94. package/src/utils/antiSuspension.js +534 -0
  95. package/src/utils/auth-helpers.js +149 -0
  96. package/src/utils/autoReLogin.js +240 -0
  97. package/src/utils/axios.js +369 -0
  98. package/src/utils/cache.js +54 -0
  99. package/src/utils/clients.js +279 -0
  100. package/src/utils/constants.js +402 -15
  101. package/src/utils/formatters/data/formatAttachment.js +370 -0
  102. package/src/utils/formatters/data/formatDelta.js +109 -0
  103. package/src/utils/formatters/index.js +159 -0
  104. package/src/utils/formatters/value/formatCookie.js +91 -0
  105. package/src/utils/formatters/value/formatDate.js +36 -0
  106. package/src/utils/formatters/value/formatID.js +16 -0
  107. package/src/utils/formatters.js +1369 -0
  108. package/src/utils/headers.js +219 -99
  109. package/src/utils/index.js +153 -0
  110. package/src/utils/monitoring.js +333 -0
  111. package/src/utils/rateLimiter.js +251 -0
  112. package/src/utils/tokenRefresh.js +285 -0
  113. package/src/utils/user-agents.js +238 -0
  114. package/src/utils/validation.js +157 -0
  115. package/func/checkUpdate.js +0 -222
  116. package/func/logAdapter.js +0 -33
  117. package/func/logger.js +0 -48
  118. package/index.d.ts +0 -751
  119. package/module/config.js +0 -40
  120. package/module/login.js +0 -133
  121. package/module/loginHelper.js +0 -1296
  122. package/module/options.js +0 -44
  123. package/src/api/action/changeAvatar.js +0 -137
  124. package/src/api/action/changeBio.js +0 -75
  125. package/src/api/action/enableAutoSaveAppState.js +0 -73
  126. package/src/api/action/getCurrentUserID.js +0 -7
  127. package/src/api/action/handleFriendRequest.js +0 -57
  128. package/src/api/action/logout.js +0 -76
  129. package/src/api/action/refreshFb_dtsg.js +0 -48
  130. package/src/api/action/setPostReaction.js +0 -106
  131. package/src/api/action/unfriend.js +0 -54
  132. package/src/api/http/httpGet.js +0 -46
  133. package/src/api/http/httpPost.js +0 -52
  134. package/src/api/http/postFormData.js +0 -47
  135. package/src/api/messaging/addUserToGroup.js +0 -68
  136. package/src/api/messaging/changeAdminStatus.js +0 -126
  137. package/src/api/messaging/changeArchivedStatus.js +0 -55
  138. package/src/api/messaging/changeBlockedStatus.js +0 -48
  139. package/src/api/messaging/changeGroupImage.js +0 -91
  140. package/src/api/messaging/changeNickname.js +0 -70
  141. package/src/api/messaging/changeThreadColor.js +0 -79
  142. package/src/api/messaging/changeThreadEmoji.js +0 -111
  143. package/src/api/messaging/createNewGroup.js +0 -88
  144. package/src/api/messaging/createPoll.js +0 -46
  145. package/src/api/messaging/createThemeAI.js +0 -98
  146. package/src/api/messaging/deleteMessage.js +0 -136
  147. package/src/api/messaging/deleteThread.js +0 -56
  148. package/src/api/messaging/editMessage.js +0 -68
  149. package/src/api/messaging/forwardAttachment.js +0 -57
  150. package/src/api/messaging/getEmojiUrl.js +0 -29
  151. package/src/api/messaging/getFriendsList.js +0 -82
  152. package/src/api/messaging/getMessage.js +0 -829
  153. package/src/api/messaging/getThemePictures.js +0 -62
  154. package/src/api/messaging/handleMessageRequest.js +0 -65
  155. package/src/api/messaging/markAsDelivered.js +0 -57
  156. package/src/api/messaging/markAsReadAll.js +0 -49
  157. package/src/api/messaging/markAsSeen.js +0 -61
  158. package/src/api/messaging/muteThread.js +0 -50
  159. package/src/api/messaging/removeUserFromGroup.js +0 -62
  160. package/src/api/messaging/resolvePhotoUrl.js +0 -43
  161. package/src/api/messaging/scheduler.js +0 -264
  162. package/src/api/messaging/searchForThread.js +0 -53
  163. package/src/api/messaging/sendMessage.js +0 -270
  164. package/src/api/messaging/sendTypingIndicator.js +0 -74
  165. package/src/api/messaging/setMessageReaction.js +0 -90
  166. package/src/api/messaging/setTitle.js +0 -124
  167. package/src/api/messaging/shareContact.js +0 -49
  168. package/src/api/messaging/threadColors.js +0 -128
  169. package/src/api/messaging/unsendMessage.js +0 -81
  170. package/src/api/messaging/uploadAttachment.js +0 -492
  171. package/src/api/socket/core/connectMqtt.js +0 -258
  172. package/src/api/socket/core/emitAuth.js +0 -103
  173. package/src/api/socket/core/getSeqID.js +0 -320
  174. package/src/api/socket/core/getTaskResponseData.js +0 -25
  175. package/src/api/socket/core/parseDelta.js +0 -377
  176. package/src/api/socket/detail/buildStream.js +0 -215
  177. package/src/api/socket/detail/constants.js +0 -28
  178. package/src/api/socket/listenMqtt.js +0 -377
  179. package/src/api/socket/middleware/index.js +0 -216
  180. package/src/api/threads/getThreadHistory.js +0 -664
  181. package/src/api/threads/getThreadInfo.js +0 -296
  182. package/src/api/threads/getThreadList.js +0 -293
  183. package/src/api/threads/getThreadPictures.js +0 -78
  184. package/src/api/users/getUserID.js +0 -65
  185. package/src/api/users/getUserInfo.js +0 -402
  186. package/src/core/sendReqMqtt.js +0 -96
  187. package/src/database/helpers.js +0 -53
  188. package/src/remote/remoteClient.js +0 -123
  189. package/src/utils/broadcast.js +0 -51
  190. package/src/utils/client.js +0 -10
  191. package/src/utils/cookies.js +0 -68
  192. package/src/utils/format/attachment.js +0 -357
  193. package/src/utils/format/cookie.js +0 -9
  194. package/src/utils/format/date.js +0 -50
  195. package/src/utils/format/decode.js +0 -44
  196. package/src/utils/format/delta.js +0 -194
  197. package/src/utils/format/ids.js +0 -64
  198. package/src/utils/format/index.js +0 -64
  199. package/src/utils/format/message.js +0 -88
  200. package/src/utils/format/presence.js +0 -132
  201. package/src/utils/format/readTyp.js +0 -44
  202. package/src/utils/format/thread.js +0 -42
  203. package/src/utils/format/utils.js +0 -141
  204. package/src/utils/loginParser/autoLogin.js +0 -125
  205. package/src/utils/loginParser/helpers.js +0 -43
  206. package/src/utils/loginParser/index.js +0 -10
  207. package/src/utils/loginParser/parseAndCheckLogin.js +0 -220
  208. package/src/utils/loginParser/textUtils.js +0 -28
  209. package/src/utils/request/client.js +0 -26
  210. package/src/utils/request/config.js +0 -23
  211. package/src/utils/request/defaults.js +0 -46
  212. package/src/utils/request/helpers.js +0 -46
  213. package/src/utils/request/index.js +0 -17
  214. package/src/utils/request/methods.js +0 -163
  215. package/src/utils/request/proxy.js +0 -21
  216. package/src/utils/request/retry.js +0 -77
  217. package/src/utils/request/sanitize.js +0 -49
package/README.md ADDED
@@ -0,0 +1,502 @@
1
+ # sagor-fca
2
+
3
+ [![npm version](https://img.shields.io/npm/v/sagor-fca.svg)](https://www.npmjs.com/package/sagor-fca)
4
+ [![npm downloads](https://img.shields.io/npm/dm/sagor-fca.svg)](https://www.npmjs.com/package/sagor-fca)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node.js Version](https://img.shields.io/node/v/sagor-fca.svg)](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 };
@@ -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
- const login = require("./module/login");
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');